From 094b96ca1df4a035b5f93c351f773306c0241f3f Mon Sep 17 00:00:00 2001 From: Ash Wolf Date: Thu, 26 Jan 2023 11:30:47 +0000 Subject: move lots of source files around to match their actual placement in the original tree --- compiler_and_linker/BackEnd/PowerPC/CMachine.c | 1488 +++++ .../BackEnd/PowerPC/CodeGenerator/CodeGen.c | 2437 +++++++++ .../BackEnd/PowerPC/CodeGenerator/Exceptions.c | 857 +++ .../BackEnd/PowerPC/CodeGenerator/FunctionCalls.c | 642 +++ .../BackEnd/PowerPC/CodeGenerator/InstrSelection.c | 5348 ++++++++++++++++++ .../BackEnd/PowerPC/CodeGenerator/Intrinsics.c | 4894 +++++++++++++++++ .../BackEnd/PowerPC/CodeGenerator/Operands.c | 1040 ++++ .../BackEnd/PowerPC/CodeGenerator/PCodeAssembly.c | 1613 ++++++ .../BackEnd/PowerPC/CodeGenerator/PCodeListing.c | 536 ++ .../BackEnd/PowerPC/CodeGenerator/PCodeUtilities.c | 345 ++ .../BackEnd/PowerPC/CodeGenerator/Peephole.c | 2753 ++++++++++ .../BackEnd/PowerPC/CodeGenerator/StackFrame.c | 1252 +++++ .../BackEnd/PowerPC/CodeGenerator/StructMoves.c | 792 +++ .../BackEnd/PowerPC/CodeGenerator/Switch.c | 518 ++ .../BackEnd/PowerPC/CodeGenerator/TOC.c | 2272 ++++++++ .../BackEnd/PowerPC/GlobalOptimizer/Alias.c | 747 +++ .../BackEnd/PowerPC/GlobalOptimizer/CodeMotion.c | 906 ++++ .../PowerPC/GlobalOptimizer/ConstantPropagation.c | 643 +++ .../PowerPC/GlobalOptimizer/LoopDetection.c | 885 +++ .../PowerPC/GlobalOptimizer/LoopOptimization.c | 1553 ++++++ .../PowerPC/GlobalOptimizer/StrengthReduction.c | 751 +++ .../PowerPC/GlobalOptimizer/ValueNumbering.c | 661 +++ .../PowerPC/GlobalOptimizer/VectorArraysToRegs.c | 548 ++ .../PowerPC/InlineAssembler/FuncLevelAsmPPC.c | 393 ++ .../BackEnd/PowerPC/InlineAssembler/GCCInlineAsm.c | 230 + .../BackEnd/PowerPC/InlineAssembler/InlineAsm.c | 680 +++ .../BackEnd/PowerPC/InlineAssembler/InlineAsmPPC.c | 2586 +++++++++ .../BackEnd/PowerPC/PCode/PCodeInfo.c | 1354 +++++ compiler_and_linker/BackEnd/PowerPC/PPCError.c | 70 + .../BackEnd/PowerPC/RegisterAllocator/Coloring.c | 268 + .../PowerPC/RegisterAllocator/InterferenceGraph.c | 364 ++ .../PowerPC/RegisterAllocator/RegisterInfo.c | 381 ++ .../BackEnd/PowerPC/RegisterAllocator/SpillCode.c | 452 ++ .../PowerPC/Scheduler/MachineSimulation601.c | 552 ++ .../PowerPC/Scheduler/MachineSimulation603.c | 626 +++ .../PowerPC/Scheduler/MachineSimulation603e.c | 650 +++ .../PowerPC/Scheduler/MachineSimulation604.c | 670 +++ .../PowerPC/Scheduler/MachineSimulation7400.c | 744 +++ .../PowerPC/Scheduler/MachineSimulation750.c | 678 +++ .../PowerPC/Scheduler/MachineSimulation821.c | 615 +++ .../PowerPC/Scheduler/MachineSimulationAltiVec.c | 752 +++ .../BackEnd/PowerPC/Scheduler/Scheduler.c | 547 ++ .../Src/Options/Glue/ParserGlue-mach-ppc-cc.c | 24 +- .../Tools_PPC/Src/Plugin/libimp-mach-ppc.c | 2 +- compiler_and_linker/FrontEnd/C/CABI.c | 2033 +++++++ compiler_and_linker/FrontEnd/C/CBrowse.c | 737 +++ compiler_and_linker/FrontEnd/C/CClass.c | 2312 ++++++++ compiler_and_linker/FrontEnd/C/CDecl.c | 4845 +++++++++++++++++ compiler_and_linker/FrontEnd/C/CError.c | 1098 ++++ compiler_and_linker/FrontEnd/C/CException.c | 2183 ++++++++ compiler_and_linker/FrontEnd/C/CExpr.c | 4971 +++++++++++++++++ compiler_and_linker/FrontEnd/C/CExpr2.c | 4206 ++++++++++++++ compiler_and_linker/FrontEnd/C/CExprConvMatch.c | 2518 +++++++++ compiler_and_linker/FrontEnd/C/CFunc.c | 3224 +++++++++++ compiler_and_linker/FrontEnd/C/CInit.c | 3082 +++++++++++ compiler_and_linker/FrontEnd/C/CInline.c | 4206 ++++++++++++++ compiler_and_linker/FrontEnd/C/CMangler.c | 713 +++ compiler_and_linker/FrontEnd/C/CParser.c | 3477 ++++++++++++ compiler_and_linker/FrontEnd/C/CPrec.c | 3482 ++++++++++++ compiler_and_linker/FrontEnd/C/CPrep.c | 2 +- compiler_and_linker/FrontEnd/C/CPreprocess.c | 676 +++ compiler_and_linker/FrontEnd/C/CRTTI.c | 940 ++++ compiler_and_linker/FrontEnd/C/CSOM.c | 2068 +++++++ compiler_and_linker/FrontEnd/C/CTemplateClass.c | 1632 ++++++ compiler_and_linker/FrontEnd/C/CTemplateFunc.c | 1383 +++++ compiler_and_linker/FrontEnd/C/CTemplateNew.c | 1880 +++++++ compiler_and_linker/FrontEnd/C/CTemplateTools.c | 1962 +++++++ compiler_and_linker/FrontEnd/Common/CIRTransform.c | 534 ++ compiler_and_linker/FrontEnd/Common/COptimizer.c | 1831 +++++++ compiler_and_linker/FrontEnd/Optimizer/BitVector.h | 36 + compiler_and_linker/FrontEnd/Optimizer/IROUseDef.c | 1432 +++++ compiler_and_linker/FrontEnd/Optimizer/IROUseDef.h | 48 + .../FrontEnd/Optimizer/IrOptimizer.c | 400 ++ .../FrontEnd/Optimizer/IrOptimizer.h | 30 + .../FrontEnd/Optimizer/IroBitVect.c | 112 + compiler_and_linker/FrontEnd/Optimizer/IroCSE.c | 1038 ++++ compiler_and_linker/FrontEnd/Optimizer/IroCSE.h | 45 + compiler_and_linker/FrontEnd/Optimizer/IroDump.c | 660 +++ compiler_and_linker/FrontEnd/Optimizer/IroDump.h | 27 + .../FrontEnd/Optimizer/IroEmptyLoop.c | 560 ++ .../FrontEnd/Optimizer/IroEmptyLoop.h | 8 + compiler_and_linker/FrontEnd/Optimizer/IroEval.c | 914 ++++ compiler_and_linker/FrontEnd/Optimizer/IroEval.h | 14 + .../FrontEnd/Optimizer/IroExprRegeneration.c | 1531 ++++++ .../FrontEnd/Optimizer/IroExprRegeneration.h | 8 + .../FrontEnd/Optimizer/IroFlowgraph.c | 439 ++ .../FrontEnd/Optimizer/IroFlowgraph.h | 97 + compiler_and_linker/FrontEnd/Optimizer/IroJump.c | 267 + compiler_and_linker/FrontEnd/Optimizer/IroJump.h | 12 + .../FrontEnd/Optimizer/IroLinearForm.c | 1797 ++++++ .../FrontEnd/Optimizer/IroLinearForm.h | 165 + compiler_and_linker/FrontEnd/Optimizer/IroLoop.c | 2324 ++++++++ compiler_and_linker/FrontEnd/Optimizer/IroLoop.h | 111 + compiler_and_linker/FrontEnd/Optimizer/IroMalloc.c | 564 ++ compiler_and_linker/FrontEnd/Optimizer/IroMalloc.h | 15 + .../FrontEnd/Optimizer/IroPointerAnalysis.c | 5734 ++++++++++++++++++++ .../FrontEnd/Optimizer/IroPointerAnalysis.h | 25 + .../FrontEnd/Optimizer/IroPointerAnalysisADTs.c | 2736 ++++++++++ .../FrontEnd/Optimizer/IroPropagate.c | 593 ++ .../FrontEnd/Optimizer/IroPropagate.h | 35 + .../FrontEnd/Optimizer/IroRangePropagation.c | 774 +++ .../FrontEnd/Optimizer/IroRangePropagation.h | 8 + .../FrontEnd/Optimizer/IroSubable.c | 160 + .../FrontEnd/Optimizer/IroSubable.h | 10 + .../FrontEnd/Optimizer/IroTransform.c | 2794 ++++++++++ .../FrontEnd/Optimizer/IroTransform.h | 13 + .../FrontEnd/Optimizer/IroUnrollLoop.c | 2305 ++++++++ .../FrontEnd/Optimizer/IroUnrollLoop.h | 23 + compiler_and_linker/FrontEnd/Optimizer/IroUtil.c | 1262 +++++ compiler_and_linker/FrontEnd/Optimizer/IroUtil.h | 127 + compiler_and_linker/FrontEnd/Optimizer/IroVars.c | 1430 +++++ compiler_and_linker/FrontEnd/Optimizer/IroVars.h | 51 + compiler_and_linker/unsorted/Alias.c | 747 --- compiler_and_linker/unsorted/CABI.c | 2033 ------- compiler_and_linker/unsorted/CBrowse.c | 737 --- compiler_and_linker/unsorted/CClass.c | 2312 -------- compiler_and_linker/unsorted/CCompiler.c | 2 +- compiler_and_linker/unsorted/CDecl.c | 4845 ----------------- compiler_and_linker/unsorted/CError.c | 1098 ---- compiler_and_linker/unsorted/CException.c | 2183 -------- compiler_and_linker/unsorted/CExpr.c | 4971 ----------------- compiler_and_linker/unsorted/CExpr2.c | 4206 -------------- compiler_and_linker/unsorted/CExprConvMatch.c | 2518 --------- compiler_and_linker/unsorted/CFunc.c | 3224 ----------- compiler_and_linker/unsorted/CIRTransform.c | 534 -- compiler_and_linker/unsorted/CInit.c | 3082 ----------- compiler_and_linker/unsorted/CInline.c | 4206 -------------- compiler_and_linker/unsorted/CMachine.c | 1488 ----- compiler_and_linker/unsorted/CMangler.c | 713 --- compiler_and_linker/unsorted/COptimizer.c | 1831 ------- compiler_and_linker/unsorted/CParser.c | 3477 ------------ compiler_and_linker/unsorted/CPrec.c | 3482 ------------ compiler_and_linker/unsorted/CPreprocess.c | 676 --- compiler_and_linker/unsorted/CRTTI.c | 940 ---- compiler_and_linker/unsorted/CSOM.c | 2069 ------- compiler_and_linker/unsorted/CTemplateClass.c | 1632 ------ compiler_and_linker/unsorted/CTemplateFunc.c | 1383 ----- compiler_and_linker/unsorted/CTemplateNew.c | 1880 ------- compiler_and_linker/unsorted/CTemplateTools.c | 1962 ------- compiler_and_linker/unsorted/CodeGen.c | 2437 --------- compiler_and_linker/unsorted/CodeMotion.c | 906 ---- compiler_and_linker/unsorted/Coloring.c | 268 - compiler_and_linker/unsorted/ConstantPropagation.c | 643 --- compiler_and_linker/unsorted/DumpIR.c | 729 +++ compiler_and_linker/unsorted/Exceptions.c | 857 --- compiler_and_linker/unsorted/FuncLevelAsmPPC.c | 393 -- compiler_and_linker/unsorted/FunctionCalls.c | 642 --- compiler_and_linker/unsorted/GCCInlineAsm.c | 230 - compiler_and_linker/unsorted/IROUseDef.c | 1432 ----- compiler_and_linker/unsorted/InlineAsm.c | 680 --- compiler_and_linker/unsorted/InlineAsmPPC.c | 2586 --------- compiler_and_linker/unsorted/InstrSelection.c | 5348 ------------------ compiler_and_linker/unsorted/InterferenceGraph.c | 364 -- compiler_and_linker/unsorted/Intrinsics.c | 4894 ----------------- compiler_and_linker/unsorted/IrOptimizer.c | 400 -- compiler_and_linker/unsorted/IroBitVect.c | 112 - compiler_and_linker/unsorted/IroCSE.c | 1038 ---- compiler_and_linker/unsorted/IroDump.c | 660 --- compiler_and_linker/unsorted/IroEmptyLoop.c | 560 -- compiler_and_linker/unsorted/IroEval.c | 914 ---- compiler_and_linker/unsorted/IroExprRegeneration.c | 1531 ------ compiler_and_linker/unsorted/IroFlowgraph.c | 439 -- compiler_and_linker/unsorted/IroJump.c | 267 - compiler_and_linker/unsorted/IroLinearForm.c | 1797 ------ compiler_and_linker/unsorted/IroLoop.c | 2324 -------- compiler_and_linker/unsorted/IroMalloc.c | 564 -- compiler_and_linker/unsorted/IroPointerAnalysis.c | 5734 -------------------- .../unsorted/IroPointerAnalysisADTs.c | 2736 ---------- compiler_and_linker/unsorted/IroPropagate.c | 593 -- compiler_and_linker/unsorted/IroRangePropagation.c | 774 --- compiler_and_linker/unsorted/IroSubable.c | 160 - compiler_and_linker/unsorted/IroTransform.c | 2794 ---------- compiler_and_linker/unsorted/IroUnrollLoop.c | 2305 -------- compiler_and_linker/unsorted/IroUtil.c | 1262 ----- compiler_and_linker/unsorted/IroVars.c | 1430 ----- compiler_and_linker/unsorted/LoopDetection.c | 885 --- compiler_and_linker/unsorted/LoopOptimization.c | 1553 ------ .../unsorted/MachineSimulation601.c | 552 -- .../unsorted/MachineSimulation603.c | 626 --- .../unsorted/MachineSimulation603e.c | 650 --- .../unsorted/MachineSimulation604.c | 670 --- .../unsorted/MachineSimulation7400.c | 744 --- .../unsorted/MachineSimulation750.c | 678 --- .../unsorted/MachineSimulation821.c | 615 --- .../unsorted/MachineSimulationAltiVec.c | 752 --- compiler_and_linker/unsorted/ObjGenMachO.c | 4 +- compiler_and_linker/unsorted/Operands.c | 1040 ---- compiler_and_linker/unsorted/PCodeAssembly.c | 1613 ------ compiler_and_linker/unsorted/PCodeInfo.c | 1354 ----- compiler_and_linker/unsorted/PCodeListing.c | 536 -- compiler_and_linker/unsorted/PCodeUtilities.c | 345 -- compiler_and_linker/unsorted/PPCError.c | 70 - compiler_and_linker/unsorted/Peephole.c | 2753 ---------- compiler_and_linker/unsorted/RegisterInfo.c | 381 -- compiler_and_linker/unsorted/Scheduler.c | 547 -- compiler_and_linker/unsorted/SpillCode.c | 452 -- compiler_and_linker/unsorted/StackFrame.c | 1252 ----- compiler_and_linker/unsorted/StrengthReduction.c | 751 --- compiler_and_linker/unsorted/StructMoves.c | 792 --- compiler_and_linker/unsorted/Switch.c | 518 -- compiler_and_linker/unsorted/TOC.c | 2272 -------- compiler_and_linker/unsorted/ValueNumbering.c | 661 --- compiler_and_linker/unsorted/VectorArraysToRegs.c | 548 -- compiler_and_linker/unsorted/uDump.c | 729 --- 204 files changed, 133566 insertions(+), 132659 deletions(-) create mode 100644 compiler_and_linker/BackEnd/PowerPC/CMachine.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/CodeGenerator/CodeGen.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Exceptions.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/CodeGenerator/FunctionCalls.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/CodeGenerator/InstrSelection.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Intrinsics.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Operands.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeAssembly.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeListing.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeUtilities.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Peephole.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/CodeGenerator/StackFrame.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/CodeGenerator/StructMoves.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Switch.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/CodeGenerator/TOC.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/Alias.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/CodeMotion.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/ConstantPropagation.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/LoopDetection.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/LoopOptimization.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/StrengthReduction.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/ValueNumbering.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/VectorArraysToRegs.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/InlineAssembler/FuncLevelAsmPPC.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/InlineAssembler/GCCInlineAsm.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/InlineAssembler/InlineAsm.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/InlineAssembler/InlineAsmPPC.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/PCode/PCodeInfo.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/PPCError.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/Coloring.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/InterferenceGraph.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/RegisterInfo.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/SpillCode.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation601.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation603.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation603e.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation604.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation7400.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation750.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation821.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulationAltiVec.c create mode 100644 compiler_and_linker/BackEnd/PowerPC/Scheduler/Scheduler.c create mode 100644 compiler_and_linker/FrontEnd/C/CABI.c create mode 100644 compiler_and_linker/FrontEnd/C/CBrowse.c create mode 100644 compiler_and_linker/FrontEnd/C/CClass.c create mode 100644 compiler_and_linker/FrontEnd/C/CDecl.c create mode 100644 compiler_and_linker/FrontEnd/C/CError.c create mode 100644 compiler_and_linker/FrontEnd/C/CException.c create mode 100644 compiler_and_linker/FrontEnd/C/CExpr.c create mode 100644 compiler_and_linker/FrontEnd/C/CExpr2.c create mode 100644 compiler_and_linker/FrontEnd/C/CExprConvMatch.c create mode 100644 compiler_and_linker/FrontEnd/C/CFunc.c create mode 100644 compiler_and_linker/FrontEnd/C/CInit.c create mode 100644 compiler_and_linker/FrontEnd/C/CInline.c create mode 100644 compiler_and_linker/FrontEnd/C/CMangler.c create mode 100644 compiler_and_linker/FrontEnd/C/CParser.c create mode 100644 compiler_and_linker/FrontEnd/C/CPrec.c create mode 100644 compiler_and_linker/FrontEnd/C/CPreprocess.c create mode 100644 compiler_and_linker/FrontEnd/C/CRTTI.c create mode 100644 compiler_and_linker/FrontEnd/C/CSOM.c create mode 100644 compiler_and_linker/FrontEnd/C/CTemplateClass.c create mode 100644 compiler_and_linker/FrontEnd/C/CTemplateFunc.c create mode 100644 compiler_and_linker/FrontEnd/C/CTemplateNew.c create mode 100644 compiler_and_linker/FrontEnd/C/CTemplateTools.c create mode 100644 compiler_and_linker/FrontEnd/Common/CIRTransform.c create mode 100644 compiler_and_linker/FrontEnd/Common/COptimizer.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/BitVector.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IROUseDef.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IROUseDef.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroBitVect.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroCSE.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroCSE.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroDump.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroDump.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroEmptyLoop.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroEmptyLoop.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroEval.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroEval.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroExprRegeneration.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroExprRegeneration.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroFlowgraph.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroFlowgraph.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroJump.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroJump.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroLoop.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroLoop.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroMalloc.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroMalloc.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysisADTs.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroPropagate.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroPropagate.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroRangePropagation.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroRangePropagation.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroSubable.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroSubable.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroTransform.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroTransform.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroUnrollLoop.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroUnrollLoop.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroUtil.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroUtil.h create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroVars.c create mode 100644 compiler_and_linker/FrontEnd/Optimizer/IroVars.h delete mode 100644 compiler_and_linker/unsorted/Alias.c delete mode 100644 compiler_and_linker/unsorted/CABI.c delete mode 100644 compiler_and_linker/unsorted/CBrowse.c delete mode 100644 compiler_and_linker/unsorted/CClass.c delete mode 100644 compiler_and_linker/unsorted/CDecl.c delete mode 100644 compiler_and_linker/unsorted/CError.c delete mode 100644 compiler_and_linker/unsorted/CException.c delete mode 100644 compiler_and_linker/unsorted/CExpr.c delete mode 100644 compiler_and_linker/unsorted/CExpr2.c delete mode 100644 compiler_and_linker/unsorted/CExprConvMatch.c delete mode 100644 compiler_and_linker/unsorted/CFunc.c delete mode 100644 compiler_and_linker/unsorted/CIRTransform.c delete mode 100644 compiler_and_linker/unsorted/CInit.c delete mode 100644 compiler_and_linker/unsorted/CInline.c delete mode 100644 compiler_and_linker/unsorted/CMachine.c delete mode 100644 compiler_and_linker/unsorted/CMangler.c delete mode 100644 compiler_and_linker/unsorted/COptimizer.c delete mode 100644 compiler_and_linker/unsorted/CParser.c delete mode 100644 compiler_and_linker/unsorted/CPrec.c delete mode 100644 compiler_and_linker/unsorted/CPreprocess.c delete mode 100644 compiler_and_linker/unsorted/CRTTI.c delete mode 100644 compiler_and_linker/unsorted/CSOM.c delete mode 100644 compiler_and_linker/unsorted/CTemplateClass.c delete mode 100644 compiler_and_linker/unsorted/CTemplateFunc.c delete mode 100644 compiler_and_linker/unsorted/CTemplateNew.c delete mode 100644 compiler_and_linker/unsorted/CTemplateTools.c delete mode 100644 compiler_and_linker/unsorted/CodeGen.c delete mode 100644 compiler_and_linker/unsorted/CodeMotion.c delete mode 100644 compiler_and_linker/unsorted/Coloring.c delete mode 100644 compiler_and_linker/unsorted/ConstantPropagation.c create mode 100644 compiler_and_linker/unsorted/DumpIR.c delete mode 100644 compiler_and_linker/unsorted/Exceptions.c delete mode 100644 compiler_and_linker/unsorted/FuncLevelAsmPPC.c delete mode 100644 compiler_and_linker/unsorted/FunctionCalls.c delete mode 100644 compiler_and_linker/unsorted/GCCInlineAsm.c delete mode 100644 compiler_and_linker/unsorted/IROUseDef.c delete mode 100644 compiler_and_linker/unsorted/InlineAsm.c delete mode 100644 compiler_and_linker/unsorted/InlineAsmPPC.c delete mode 100644 compiler_and_linker/unsorted/InstrSelection.c delete mode 100644 compiler_and_linker/unsorted/InterferenceGraph.c delete mode 100644 compiler_and_linker/unsorted/Intrinsics.c delete mode 100644 compiler_and_linker/unsorted/IrOptimizer.c delete mode 100644 compiler_and_linker/unsorted/IroBitVect.c delete mode 100644 compiler_and_linker/unsorted/IroCSE.c delete mode 100644 compiler_and_linker/unsorted/IroDump.c delete mode 100644 compiler_and_linker/unsorted/IroEmptyLoop.c delete mode 100644 compiler_and_linker/unsorted/IroEval.c delete mode 100644 compiler_and_linker/unsorted/IroExprRegeneration.c delete mode 100644 compiler_and_linker/unsorted/IroFlowgraph.c delete mode 100644 compiler_and_linker/unsorted/IroJump.c delete mode 100644 compiler_and_linker/unsorted/IroLinearForm.c delete mode 100644 compiler_and_linker/unsorted/IroLoop.c delete mode 100644 compiler_and_linker/unsorted/IroMalloc.c delete mode 100644 compiler_and_linker/unsorted/IroPointerAnalysis.c delete mode 100644 compiler_and_linker/unsorted/IroPointerAnalysisADTs.c delete mode 100644 compiler_and_linker/unsorted/IroPropagate.c delete mode 100644 compiler_and_linker/unsorted/IroRangePropagation.c delete mode 100644 compiler_and_linker/unsorted/IroSubable.c delete mode 100644 compiler_and_linker/unsorted/IroTransform.c delete mode 100644 compiler_and_linker/unsorted/IroUnrollLoop.c delete mode 100644 compiler_and_linker/unsorted/IroUtil.c delete mode 100644 compiler_and_linker/unsorted/IroVars.c delete mode 100644 compiler_and_linker/unsorted/LoopDetection.c delete mode 100644 compiler_and_linker/unsorted/LoopOptimization.c delete mode 100644 compiler_and_linker/unsorted/MachineSimulation601.c delete mode 100644 compiler_and_linker/unsorted/MachineSimulation603.c delete mode 100644 compiler_and_linker/unsorted/MachineSimulation603e.c delete mode 100644 compiler_and_linker/unsorted/MachineSimulation604.c delete mode 100644 compiler_and_linker/unsorted/MachineSimulation7400.c delete mode 100644 compiler_and_linker/unsorted/MachineSimulation750.c delete mode 100644 compiler_and_linker/unsorted/MachineSimulation821.c delete mode 100644 compiler_and_linker/unsorted/MachineSimulationAltiVec.c delete mode 100644 compiler_and_linker/unsorted/Operands.c delete mode 100644 compiler_and_linker/unsorted/PCodeAssembly.c delete mode 100644 compiler_and_linker/unsorted/PCodeInfo.c delete mode 100644 compiler_and_linker/unsorted/PCodeListing.c delete mode 100644 compiler_and_linker/unsorted/PCodeUtilities.c delete mode 100644 compiler_and_linker/unsorted/PPCError.c delete mode 100644 compiler_and_linker/unsorted/Peephole.c delete mode 100644 compiler_and_linker/unsorted/RegisterInfo.c delete mode 100644 compiler_and_linker/unsorted/Scheduler.c delete mode 100644 compiler_and_linker/unsorted/SpillCode.c delete mode 100644 compiler_and_linker/unsorted/StackFrame.c delete mode 100644 compiler_and_linker/unsorted/StrengthReduction.c delete mode 100644 compiler_and_linker/unsorted/StructMoves.c delete mode 100644 compiler_and_linker/unsorted/Switch.c delete mode 100644 compiler_and_linker/unsorted/TOC.c delete mode 100644 compiler_and_linker/unsorted/ValueNumbering.c delete mode 100644 compiler_and_linker/unsorted/VectorArraysToRegs.c delete mode 100644 compiler_and_linker/unsorted/uDump.c (limited to 'compiler_and_linker') diff --git a/compiler_and_linker/BackEnd/PowerPC/CMachine.c b/compiler_and_linker/BackEnd/PowerPC/CMachine.c new file mode 100644 index 0000000..bfa7023 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/CMachine.c @@ -0,0 +1,1488 @@ +#include "compiler/CMachine.h" +#include "compiler/CClass.h" +#include "compiler/CError.h" +#include "compiler/CInt64.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CompilerTools.h" +#include "compiler/ScanFloat.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +TypeIntegral stbool = {TYPEINT, 1, IT_BOOL}; +TypeIntegral stchar = {TYPEINT, 1, IT_CHAR}; +TypeIntegral stsignedchar = {TYPEINT, 1, IT_SCHAR}; +TypeIntegral stunsignedchar = {TYPEINT, 1, IT_UCHAR}; +TypeIntegral stwchar = {TYPEINT, 4, IT_WCHAR_T}; +TypeIntegral stsignedshort = {TYPEINT, 2, IT_SHORT}; +TypeIntegral stunsignedshort = {TYPEINT, 2, IT_USHORT}; +TypeIntegral stsignedint = {TYPEINT, 4, IT_INT}; +TypeIntegral stunsignedint = {TYPEINT, 4, IT_UINT}; +TypeIntegral stsignedlong = {TYPEINT, 4, IT_LONG}; +TypeIntegral stunsignedlong = {TYPEINT, 4, IT_ULONG}; +TypeIntegral stsignedlonglong = {TYPEINT, 8, IT_LONGLONG}; +TypeIntegral stunsignedlonglong = {TYPEINT, 8, IT_ULONGLONG}; +TypeIntegral stfloat = {TYPEFLOAT, 4, IT_FLOAT}; +TypeIntegral stshortdouble = {TYPEFLOAT, 8, IT_SHORTDOUBLE}; +TypeIntegral stdouble = {TYPEFLOAT, 8, IT_DOUBLE}; +TypeIntegral stlongdouble = {TYPEFLOAT, 8, IT_LONGDOUBLE}; + +static StructMember stVUC_unsignedchar15 = {NULL, (Type *) &stunsignedchar, NULL, 15, 0}; +static StructMember stVUC_unsignedchar14 = {&stVUC_unsignedchar15, (Type *) &stunsignedchar, NULL, 14, 0}; +static StructMember stVUC_unsignedchar13 = {&stVUC_unsignedchar14, (Type *) &stunsignedchar, NULL, 13, 0}; +static StructMember stVUC_unsignedchar12 = {&stVUC_unsignedchar13, (Type *) &stunsignedchar, NULL, 12, 0}; +static StructMember stVUC_unsignedchar11 = {&stVUC_unsignedchar12, (Type *) &stunsignedchar, NULL, 11, 0}; +static StructMember stVUC_unsignedchar10 = {&stVUC_unsignedchar11, (Type *) &stunsignedchar, NULL, 10, 0}; +static StructMember stVUC_unsignedchar9 = {&stVUC_unsignedchar10, (Type *) &stunsignedchar, NULL, 9, 0}; +static StructMember stVUC_unsignedchar8 = {&stVUC_unsignedchar9, (Type *) &stunsignedchar, NULL, 8, 0}; +static StructMember stVUC_unsignedchar7 = {&stVUC_unsignedchar7, (Type *) &stunsignedchar, NULL, 7, 0}; +static StructMember stVUC_unsignedchar6 = {&stVUC_unsignedchar7, (Type *) &stunsignedchar, NULL, 6, 0}; +static StructMember stVUC_unsignedchar5 = {&stVUC_unsignedchar6, (Type *) &stunsignedchar, NULL, 5, 0}; +static StructMember stVUC_unsignedchar4 = {&stVUC_unsignedchar5, (Type *) &stunsignedchar, NULL, 4, 0}; +static StructMember stVUC_unsignedchar3 = {&stVUC_unsignedchar4, (Type *) &stunsignedchar, NULL, 3, 0}; +static StructMember stVUC_unsignedchar2 = {&stVUC_unsignedchar3, (Type *) &stunsignedchar, NULL, 2, 0}; +static StructMember stVUC_unsignedchar1 = {&stVUC_unsignedchar2, (Type *) &stunsignedchar, NULL, 1, 0}; +static StructMember stVUC_unsignedchar0 = {&stVUC_unsignedchar1, (Type *) &stunsignedchar, NULL, 0, 0}; + +static StructMember stVSC_signedchar15 = {NULL, (Type *) &stsignedchar, NULL, 15, 0}; +static StructMember stVSC_signedchar14 = {&stVSC_signedchar15, (Type *) &stsignedchar, NULL, 14, 0}; +static StructMember stVSC_signedchar13 = {&stVSC_signedchar14, (Type *) &stsignedchar, NULL, 13, 0}; +static StructMember stVSC_signedchar12 = {&stVSC_signedchar13, (Type *) &stsignedchar, NULL, 12, 0}; +static StructMember stVSC_signedchar11 = {&stVSC_signedchar12, (Type *) &stsignedchar, NULL, 11, 0}; +static StructMember stVSC_signedchar10 = {&stVSC_signedchar11, (Type *) &stsignedchar, NULL, 10, 0}; +static StructMember stVSC_signedchar9 = {&stVSC_signedchar10, (Type *) &stsignedchar, NULL, 9, 0}; +static StructMember stVSC_signedchar8 = {&stVSC_signedchar9, (Type *) &stsignedchar, NULL, 8, 0}; +static StructMember stVSC_signedchar7 = {&stVSC_signedchar7, (Type *) &stsignedchar, NULL, 7, 0}; +static StructMember stVSC_signedchar6 = {&stVSC_signedchar7, (Type *) &stsignedchar, NULL, 6, 0}; +static StructMember stVSC_signedchar5 = {&stVSC_signedchar6, (Type *) &stsignedchar, NULL, 5, 0}; +static StructMember stVSC_signedchar4 = {&stVSC_signedchar5, (Type *) &stsignedchar, NULL, 4, 0}; +static StructMember stVSC_signedchar3 = {&stVSC_signedchar4, (Type *) &stsignedchar, NULL, 3, 0}; +static StructMember stVSC_signedchar2 = {&stVSC_signedchar3, (Type *) &stsignedchar, NULL, 2, 0}; +static StructMember stVSC_signedchar1 = {&stVSC_signedchar2, (Type *) &stsignedchar, NULL, 1, 0}; +static StructMember stVSC_signedchar0 = {&stVSC_signedchar1, (Type *) &stsignedchar, NULL, 0, 0}; + +static StructMember stVUS_unsignedshort7 = {NULL, (Type *) &stunsignedshort, NULL, 14, 0}; +static StructMember stVUS_unsignedshort6 = {&stVUS_unsignedshort7, (Type *) &stunsignedshort, NULL, 12, 0}; +static StructMember stVUS_unsignedshort5 = {&stVUS_unsignedshort7, (Type *) &stunsignedshort, NULL, 10, 0}; +static StructMember stVUS_unsignedshort4 = {&stVUS_unsignedshort5, (Type *) &stunsignedshort, NULL, 8, 0}; +static StructMember stVUS_unsignedshort3 = {&stVUS_unsignedshort4, (Type *) &stunsignedshort, NULL, 6, 0}; +static StructMember stVUS_unsignedshort2 = {&stVUS_unsignedshort3, (Type *) &stunsignedshort, NULL, 4, 0}; +static StructMember stVUS_unsignedshort1 = {&stVUS_unsignedshort2, (Type *) &stunsignedshort, NULL, 2, 0}; +static StructMember stVUS_unsignedshort0 = {&stVUS_unsignedshort1, (Type *) &stunsignedshort, NULL, 0, 0}; + +static StructMember stVSS_signedshort7 = {NULL, (Type *) &stsignedshort, NULL, 14, 0}; +static StructMember stVSS_signedshort6 = {&stVSS_signedshort7, (Type *) &stsignedshort, NULL, 12, 0}; +static StructMember stVSS_signedshort5 = {&stVSS_signedshort7, (Type *) &stsignedshort, NULL, 10, 0}; +static StructMember stVSS_signedshort4 = {&stVSS_signedshort5, (Type *) &stsignedshort, NULL, 8, 0}; +static StructMember stVSS_signedshort3 = {&stVSS_signedshort4, (Type *) &stsignedshort, NULL, 6, 0}; +static StructMember stVSS_signedshort2 = {&stVSS_signedshort3, (Type *) &stsignedshort, NULL, 4, 0}; +static StructMember stVSS_signedshort1 = {&stVSS_signedshort2, (Type *) &stsignedshort, NULL, 2, 0}; +static StructMember stVSS_signedshort0 = {&stVSS_signedshort1, (Type *) &stsignedshort, NULL, 0, 0}; + +static StructMember stVUL_unsignedlong3 = {NULL, (Type *) &stunsignedlong, NULL, 12, 0}; +static StructMember stVUL_unsignedlong2 = {&stVUL_unsignedlong3, (Type *) &stunsignedlong, NULL, 8, 0}; +static StructMember stVUL_unsignedlong1 = {&stVUL_unsignedlong2, (Type *) &stunsignedlong, NULL, 4, 0}; +static StructMember stVUL_unsignedlong0 = {&stVUL_unsignedlong1, (Type *) &stunsignedlong, NULL, 0, 0}; + +static StructMember stVSL_signedlong3 = {NULL, (Type *) &stsignedlong, NULL, 12, 0}; +static StructMember stVSL_signedlong2 = {&stVSL_signedlong3, (Type *) &stsignedlong, NULL, 8, 0}; +static StructMember stVSL_signedlong1 = {&stVSL_signedlong2, (Type *) &stsignedlong, NULL, 4, 0}; +static StructMember stVSL_signedlong0 = {&stVSL_signedlong1, (Type *) &stsignedlong, NULL, 0, 0}; + +static StructMember stVF_float3 = {NULL, (Type *) &stfloat, NULL, 12, 0}; +static StructMember stVF_float2 = {&stVF_float3, (Type *) &stfloat, NULL, 8, 0}; +static StructMember stVF_float1 = {&stVF_float2, (Type *) &stfloat, NULL, 4, 0}; +static StructMember stVF_float0 = {&stVF_float1, (Type *) &stfloat, NULL, 0, 0}; + +TypeStruct stvectorunsignedchar = {TYPESTRUCT, 16, NULL, &stVUC_unsignedchar0, STRUCT_VECTOR_UCHAR, 16}; +TypeStruct stvectorsignedchar = {TYPESTRUCT, 16, NULL, &stVSC_signedchar0, STRUCT_VECTOR_SCHAR, 16}; +TypeStruct stvectorboolchar = {TYPESTRUCT, 16, NULL, &stVSC_signedchar0, STRUCT_VECTOR_BCHAR, 16}; + +TypeStruct stvectorunsignedshort = {TYPESTRUCT, 16, NULL, &stVUS_unsignedshort0, STRUCT_VECTOR_USHORT, 16}; +TypeStruct stvectorsignedshort = {TYPESTRUCT, 16, NULL, &stVSS_signedshort0, STRUCT_VECTOR_SSHORT, 16}; +TypeStruct stvectorboolshort = {TYPESTRUCT, 16, NULL, &stVSS_signedshort0, STRUCT_VECTOR_BSHORT, 16}; + +TypeStruct stvectorunsignedlong = {TYPESTRUCT, 16, NULL, &stVUL_unsignedlong0, STRUCT_VECTOR_UINT, 16}; +TypeStruct stvectorsignedlong = {TYPESTRUCT, 16, NULL, &stVSL_signedlong0, STRUCT_VECTOR_SINT, 16}; +TypeStruct stvectorboollong = {TYPESTRUCT, 16, NULL, &stVSL_signedlong0, STRUCT_VECTOR_BINT, 16}; + +TypeStruct stvectorfloat = {TYPESTRUCT, 16, NULL, &stVF_float0, STRUCT_VECTOR_FLOAT, 16}; + +TypeStruct stvectorpixel = {TYPESTRUCT, 16, NULL, &stVUS_unsignedshort0, STRUCT_VECTOR_PIXEL, 16}; + +TypeStruct stvector = {TYPESTRUCT, 16, NULL, NULL, STRUCT_VECTOR_UINT, 16}; + +static SInt32 cmach_structoffset; +static UInt8 cmach_structalign; +static short cmach_curbfsize; +static short cmach_curbfbasesize; +static int cmach_curbfoffset; + +static short cmach_packsize[] = { + 1, 2, 4, 8, 16 +}; + +// forward declarations +static SInt16 CMach_GetQualifiedTypeAlign(Type *type, Boolean flag); +static SInt16 CMach_GetMemberAlignment(Type *type, SInt32 align, Boolean flag); + +void CMach_Configure(void) { +} + +SInt32 CMach_GetQUALalign(UInt32 qual) { + SInt32 result = 0; + UInt32 chk; + + if ((chk = (qual & Q_ALIGNED_MASK))) { + if (chk == Q_ALIGNED_1) + result = 1; + else if (chk == Q_ALIGNED_2) + result = 2; + else if (chk == Q_ALIGNED_4) + result = 4; + else if (chk == Q_ALIGNED_8) + result = 8; + else if (chk == Q_ALIGNED_16) + result = 16; + else if (chk == Q_ALIGNED_32) + result = 32; + else if (chk == Q_ALIGNED_64) + result = 64; + else if (chk == Q_ALIGNED_128) + result = 128; + else if (chk == Q_ALIGNED_256) + result = 256; + else if (chk == Q_ALIGNED_512) + result = 512; + else if (chk == Q_ALIGNED_1024) + result = 1024; + else if (chk == Q_ALIGNED_2048) + result = 2048; + else if (chk == Q_ALIGNED_4096) + result = 4096; + else if (chk == Q_ALIGNED_8192) + result = 8192; + else + CError_FATAL(226); + } + + return result; +} + +SInt32 CMach_ArgumentAlignment(Type *type) { + char save_align_mode; + UInt8 save_oldalignment; + SInt32 align; + + save_align_mode = copts.structalignment; + save_oldalignment = copts.oldalignment; + copts.structalignment = AlignMode2_PPC; + copts.oldalignment = 0; + align = CMach_GetQualifiedTypeAlign(type, 0); + copts.structalignment = save_align_mode; + copts.oldalignment = save_oldalignment; + + if (type->type == TYPESTRUCT && !TYPE_STRUCT(type)->members) { + if (TYPE_STRUCT(type)->align > align) + return TYPE_STRUCT(type)->align; + else + return align; + } else { + return align; + } +} + +// TODO: investigate if this returns SInt16 actually +SInt32 CMach_AllocationAlignment(Type *type, UInt32 qual) { + SInt32 align; + SInt32 qualalign; + SInt32 argalign; + SInt32 anotheralign; + + qualalign = CMach_GetQUALalign(qual); + align = CMach_GetQualifiedTypeAlign(type, 1); + if (qualalign > align) + align = qualalign; + argalign = CMach_ArgumentAlignment(type); + if (argalign > align) + align = argalign; + + switch (type->type) { + case TYPEVOID: + case TYPEMEMBERPOINTER: + case TYPEPOINTER: + anotheralign = 4; + break; + default: + anotheralign = 1; + } + if (anotheralign > align) + align = anotheralign; + + if (copts.optimizationlevel > 0) { + if (type->type == TYPEARRAY || (type->type == TYPESTRUCT && (TYPE_STRUCT(type)->stype < STRUCT_VECTOR_UCHAR || TYPE_STRUCT(type)->stype > STRUCT_VECTOR_PIXEL)) || type->type == TYPECLASS || (type->type == TYPEMEMBERPOINTER && (UInt32) type->size == 12)) { + return (copts.min_struct_alignment > align) ? copts.min_struct_alignment : align; + } + } + + return align; +} + +CInt64 CMach_CalcIntDiadic(Type *type, CInt64 left, short op, CInt64 right) { + if (is_unsigned(type)) { + switch (type->size) { + case 1: + CInt64_ConvertUInt8(&left); + CInt64_ConvertUInt8(&right); + break; + case 2: + CInt64_ConvertUInt16(&left); + CInt64_ConvertUInt16(&right); + break; + case 4: + CInt64_ConvertUInt32(&left); + CInt64_ConvertUInt32(&right); + break; + case 8: + break; + default: + CError_FATAL(327); + } + + switch (op) { + case '*': + left = CInt64_MulU(left, right); + break; + case '/': + if (CInt64_IsZero(&right)) + CError_Warning(CErrorStr139); + else + left = CInt64_DivU(left, right); + break; + case '%': + if (CInt64_IsZero(&right)) + CError_Warning(CErrorStr139); + else + left = CInt64_ModU(left, right); + break; + case '+': + left = CInt64_Add(left, right); + break; + case '-': + left = CInt64_Sub(left, right); + break; + case TK_SHL: + left = CInt64_Shl(left, right); + break; + case TK_SHR: + left = CInt64_ShrU(left, right); + break; + case '<': + CInt64_SetLong(&left, CInt64_LessU(left, right)); + break; + case '>': + CInt64_SetLong(&left, CInt64_GreaterU(left, right)); + break; + case TK_LESS_EQUAL: + CInt64_SetLong(&left, CInt64_LessEqualU(left, right)); + break; + case TK_GREATER_EQUAL: + CInt64_SetLong(&left, CInt64_GreaterEqualU(left, right)); + break; + case TK_LOGICAL_EQ: + CInt64_SetLong(&left, CInt64_Equal(left, right)); + break; + case TK_LOGICAL_NE: + CInt64_SetLong(&left, CInt64_NotEqual(left, right)); + break; + case '&': + left = CInt64_And(left, right); + break; + case '^': + left = CInt64_Xor(left, right); + break; + case '|': + left = CInt64_Or(left, right); + break; + case TK_LOGICAL_AND: + CInt64_SetLong(&left, (!CInt64_IsZero(&left) && !CInt64_IsZero(&right))); + break; + case TK_LOGICAL_OR: + CInt64_SetLong(&left, (!CInt64_IsZero(&left) || !CInt64_IsZero(&right))); + break; + default: + CError_Error(CErrorStr120); + } + + switch (type->size) { + case 1: + CInt64_ConvertUInt8(&left); + break; + case 2: + CInt64_ConvertUInt16(&left); + break; + case 4: + CInt64_ConvertUInt32(&left); + break; + case 8: + break; + } + } else { + switch (type->size) { + case 1: + CInt64_ConvertInt8(&left); + CInt64_ConvertInt8(&right); + break; + case 2: + CInt64_ConvertInt16(&left); + CInt64_ConvertInt16(&right); + break; + case 4: + CInt64_ConvertInt32(&left); + CInt64_ConvertInt32(&right); + break; + case 8: + break; + default: + CError_FATAL(389); + } + + switch (op) { + case '*': + left = CInt64_Mul(left, right); + break; + case '/': + if (CInt64_IsZero(&right)) + CError_Warning(CErrorStr139); + else + left = CInt64_Div(left, right); + break; + case '%': + if (CInt64_IsZero(&right)) + CError_Warning(CErrorStr139); + else + left = CInt64_Mod(left, right); + break; + case '+': + left = CInt64_Add(left, right); + break; + case '-': + left = CInt64_Sub(left, right); + break; + case TK_SHL: + left = CInt64_Shl(left, right); + break; + case TK_SHR: + left = CInt64_Shr(left, right); + break; + case '<': + CInt64_SetLong(&left, CInt64_Less(left, right)); + break; + case '>': + CInt64_SetLong(&left, CInt64_Greater(left, right)); + break; + case TK_LESS_EQUAL: + CInt64_SetLong(&left, CInt64_LessEqual(left, right)); + break; + case TK_GREATER_EQUAL: + CInt64_SetLong(&left, CInt64_GreaterEqual(left, right)); + break; + case TK_LOGICAL_EQ: + CInt64_SetLong(&left, CInt64_Equal(left, right)); + break; + case TK_LOGICAL_NE: + CInt64_SetLong(&left, CInt64_NotEqual(left, right)); + break; + case '&': + left = CInt64_And(left, right); + break; + case '^': + left = CInt64_Xor(left, right); + break; + case '|': + left = CInt64_Or(left, right); + break; + case TK_LOGICAL_AND: + CInt64_SetLong(&left, (!CInt64_IsZero(&left) && !CInt64_IsZero(&right))); + break; + case TK_LOGICAL_OR: + CInt64_SetLong(&left, (!CInt64_IsZero(&left) || !CInt64_IsZero(&right))); + break; + default: + CError_Error(CErrorStr120); + } + + switch (type->size) { + case 1: + CInt64_ConvertInt8(&left); + break; + case 2: + CInt64_ConvertInt16(&left); + break; + case 4: + CInt64_ConvertInt32(&left); + break; + case 8: + break; + } + } + + return left; +} + +CInt64 CMach_CalcIntMonadic(Type *type, short op, CInt64 val) { + if (is_unsigned(type)) { + switch (type->size) { + case 1: + CInt64_ConvertUInt8(&val); + break; + case 2: + CInt64_ConvertUInt16(&val); + break; + case 4: + CInt64_ConvertUInt32(&val); + break; + case 8: + break; + default: + CError_FATAL(448); + } + + switch (op) { + case '-': + val = CInt64_Neg(val); + break; + case '~': + val = CInt64_Inv(val); + break; + case '!': + val = CInt64_Not(val); + break; + default: + CError_Error(CErrorStr120); + } + + switch (type->size) { + case 1: + CInt64_ConvertUInt8(&val); + break; + case 2: + CInt64_ConvertUInt16(&val); + break; + case 4: + CInt64_ConvertUInt32(&val); + break; + case 8: + break; + } + } else { + switch (type->size) { + case 1: + CInt64_ConvertInt8(&val); + break; + case 2: + CInt64_ConvertInt16(&val); + break; + case 4: + CInt64_ConvertInt32(&val); + break; + case 8: + break; + default: + CError_FATAL(478); + } + + switch (op) { + case '-': + val = CInt64_Neg(val); + break; + case '~': + val = CInt64_Inv(val); + break; + case '!': + val = CInt64_Not(val); + break; + default: + CError_Error(CErrorStr120); + } + + switch (type->size) { + case 1: + CInt64_ConvertInt8(&val); + break; + case 2: + CInt64_ConvertInt16(&val); + break; + case 4: + CInt64_ConvertInt32(&val); + break; + case 8: + break; + } + } + + return val; +} + +CInt64 CMach_CalcIntConvertFromFloat(Type *type, Float fval) { + CInt64 result; + + if ((type->type == TYPEINT || type->type == TYPEENUM) && (type->size == 8)) { + if (is_unsigned(type)) + CInt64_ConvertUFromLongDouble(&result, fval.value); + else + CInt64_ConvertFromLongDouble(&result, fval.value); + } else { + if (is_unsigned(type)) + CInt64_SetULong(&result, fval.value); + else + CInt64_SetLong(&result, fval.value); + } + + return result; +} + +void CMach_InitIntMem(Type *type, CInt64 val, void *mem) { + SInt32 lg; + SInt16 sh; + SInt8 ch; + + switch (type->type) { + case TYPEINT: + switch (type->size) { + case 1: + ch = CInt64_GetULong(&val); + memcpy(mem, &ch, 1); + break; + case 2: + sh = CTool_EndianConvertWord16(CInt64_GetULong(&val)); + memcpy(mem, &sh, 2); + break; + case 4: + lg = CTool_EndianConvertWord32(CInt64_GetULong(&val)); + memcpy(mem, &lg, 4); + break; + case 8: + CTool_EndianConvertWord64(val, mem); + break; + default: + CError_FATAL(566); + } + break; + default: + CError_FATAL(570); + } +} + +void CMach_InitVectorMem(Type *type, MWVector128 val, void *mem, Boolean flag) { + unsigned char uc[16]; + unsigned short us[8]; + unsigned int ul[4]; + float f[4]; + int i; + + switch (type->type) { + case TYPESTRUCT: + switch (TYPE_STRUCT(type)->stype) { + case STRUCT_VECTOR_UCHAR: + case STRUCT_VECTOR_SCHAR: + case STRUCT_VECTOR_BCHAR: + for (i = 0; i < 16; i++) + uc[i] = val.uc[i]; + memcpy(mem, uc, 16); + break; + case STRUCT_VECTOR_USHORT: + case STRUCT_VECTOR_SSHORT: + case STRUCT_VECTOR_BSHORT: + case STRUCT_VECTOR_PIXEL: + for (i = 0; i < 8; i++) + us[i] = val.us[i]; + memcpy(mem, us, 16); + break; + case STRUCT_VECTOR_UINT: + case STRUCT_VECTOR_SINT: + case STRUCT_VECTOR_BINT: + for (i = 0; i < 4; i++) + ul[i] = val.ul[i]; + memcpy(mem, ul, 16); + break; + case STRUCT_VECTOR_FLOAT: + for (i = 0; i < 4; i++) + f[i] = val.f[i]; + memcpy(mem, f, 16); + break; + default: + CError_FATAL(655); + } + break; + default: + CError_FATAL(659); + } +} + +Float CMach_CalcFloatDiadic(Type *type, Float left, short op, Float right) { + switch (op) { + case '+': + left.value += right.value; + break; + case '-': + left.value -= right.value; + break; + case '*': + left.value *= right.value; + break; + case '/': + left.value /= right.value; + break; + default: + CError_FATAL(679); + } + + return CMach_CalcFloatConvert(type, left); +} + +Float CMach_CalcFloatMonadic(Type *type, short op, Float fval) { + if (op != '-') + CError_FATAL(692); + + fval.value = -fval.value; + return CMach_CalcFloatConvert(type, fval); +} + +Boolean CMach_CalcFloatDiadicBool(Type *type, Float left, short op, Float right) { + switch (op) { + case TK_LOGICAL_EQ: + return left.value == right.value; + case TK_LOGICAL_NE: + return left.value != right.value; + case TK_LESS_EQUAL: + return left.value <= right.value; + case TK_GREATER_EQUAL: + return left.value >= right.value; + case '>': + return left.value > right.value; + case '<': + return left.value < right.value; + default: + CError_FATAL(714); + return 0; + } +} + +Boolean CMach_CalcVectorDiadicBool(Type *type, MWVector128 *left, short op, MWVector128 *right) { + switch (op) { + case TK_LOGICAL_EQ: + return (left->ul[0] == right->ul[0]) && (left->ul[1] == right->ul[1]) && (left->ul[2] == right->ul[2]) && (left->ul[3] == right->ul[3]); + case TK_LOGICAL_NE: + return (left->ul[0] != right->ul[0]) && (left->ul[1] != right->ul[1]) && (left->ul[2] != right->ul[2]) && (left->ul[3] != right->ul[3]); + default: + CError_FATAL(740); + return 0; + } +} + +char *CMach_FloatScan(char *input, Float *result, Boolean *fail) { + double resultval; + char *outpos; + + if (!(outpos = ScanFloat(input, &resultval, fail))) + CError_ErrorTerm(CErrorStr154); + + if (*fail) + result->value = 0.0; + else + result->value = resultval; + + return outpos; +} + +Float CMach_CalcFloatConvertFromInt(Type *type, CInt64 val) { + Float result; + + if ((type->type == TYPEINT || type->type == TYPEENUM) && (type->size == 8)) { + if (is_unsigned(type)) + result.value = CInt64_ConvertUToLongDouble(&val); + else + result.value = CInt64_ConvertToLongDouble(&val); + } else { + if (is_unsigned(type)) + result.value = val.lo; + else + result.value = (SInt32) val.lo; + } + + return result; +} + +Float CMach_CalcFloatConvert(Type *type, Float fval) { + switch (type->size) { + case 4: + fval.value = (float) fval.value; + break; + case 8: + fval.value = (double) fval.value; + break; + case 10: + case 12: + break; + default: + CError_FATAL(801); + } + return fval; +} + +Boolean CMach_FloatIsZero(Float fval) { + return fval.value == 0.0; +} + +Boolean CMach_FloatIsOne(Float fval) { + return fval.value == 1.0; +} + +Boolean CMach_FloatIsNegOne(Float fval) { + return fval.value == -1.0; +} + +void CMach_InitFloatMem(Type *type, Float val, void *mem) { + float f; + double d; + + if (type->type == TYPEFLOAT) { + switch (type->size) { + case 4: + f = val.value; + memcpy(mem, &f, 4); + CTool_EndianConvertMem(mem, 4); + return; + case 8: + d = val.value; + memcpy(mem, &d, 8); + CTool_EndianConvertMem(mem, 8); + return; + } + } + + CError_FATAL(866); +} + +void CMach_PrintFloat(char *buf, Float val) { + double f; + CMach_InitFloatMem((Type *) &stshortdouble, val, &f); + sprintf(buf, "%g", f); +} + +void CMach_PragmaParams(void) { + if (copts.warn_illpragma) + CError_Warning(CErrorStr186, 0); + + while (notendofline()) + lex(); +} + +void CMach_AdjustFuntionArgs() { + // not called so we will never know what the args should have been :( +} + +static SInt32 CMach_GetPPCTypeAlign(Type *type, Boolean flag1, Boolean flag2) { + ClassList *base; + ObjMemberVar *ivar; + StructMember *member; + SInt32 best; + SInt32 ivarAlign; + SInt32 qualAlign; + + SInt32 align = CMach_GetQualifiedTypeAlign(type, flag2); + if (align <= 8) { + while (type->type == TYPEARRAY) + type = TYPE_POINTER(type)->target; + + if (flag1) { + if (type->type == TYPEFLOAT && type->size > 4 && align < 8) + return 8; + } else if (align == 8) { + if (type->type == TYPECLASS) { + best = 4; + for (base = TYPE_CLASS(type)->bases; base; base = base->next) { + if (base->base->align > best) + best = base->base->align; + } + for (ivar = TYPE_CLASS(type)->ivars; ivar; ivar = ivar->next) { + ivarAlign = CMach_GetPPCTypeAlign(ivar->type, 0, flag2); + if (ivarAlign > best) + best = ivarAlign; + if (flag2) { + qualAlign = CMach_GetQUALalign(ivar->qual); + if (qualAlign > best) + best = qualAlign; + } + } + return best; + } + if (type->type == TYPESTRUCT) { + best = 4; + for (member = TYPE_STRUCT(type)->members; member; member = member->next) { + ivarAlign = CMach_GetPPCTypeAlign(member->type, 0, flag2); + if (ivarAlign > best) + best = ivarAlign; + if (flag2) { + qualAlign = CMach_GetQUALalign(member->qual); + if (qualAlign > best) + best = qualAlign; + } + } + return best; + } + } + } + + return align; +} + +static SInt16 CMach_GetQualifiedStructAlign(const TypeStruct *tstruct, Boolean flag) { + StructMember *member; + SInt32 best; + SInt32 align; + Boolean isFirst; + + if (tstruct->stype >= STRUCT_VECTOR_UCHAR && tstruct->stype <= STRUCT_VECTOR_PIXEL) + return 16; + + switch (copts.structalignment) { + case AlignMode3_1Byte: + case AlignMode8_Packed: + return 1; + case AlignMode0_Mac68k: + return 2; + case AlignMode1_Mac68k4byte: + return (tstruct->size <= 2) ? 2 : 4; + } + + if (tstruct->size <= 1) + return 1; + + best = 1; + switch (copts.structalignment) { + default: + CError_FATAL(1026); + case AlignMode4_2Byte: + case AlignMode5_4Byte: + case AlignMode6_8Byte: + case AlignMode7_16Byte: + for (member = tstruct->members; member; member = member->next) { + align = CMach_GetQualifiedTypeAlign(member->type, flag); + if (align > best) + best = align; + if (flag) { + align = CMach_GetQUALalign(member->qual); + if (align > best) + best = align; + } + } + return best; + case AlignMode2_PPC: + if (copts.oldalignment) { + for (member = tstruct->members; member; member = member->next) { + align = CMach_GetQualifiedTypeAlign(member->type, flag); + if (align > best) + best = align; + if (flag) { + align = CMach_GetQUALalign(member->qual); + if (align > best) + best = align; + } + } + } else if (TYPE_STRUCT(tstruct)->stype == STRUCT_TYPE_UNION) { + for (member = tstruct->members; member; member = member->next) { + align = CMach_GetPPCTypeAlign(member->type, 1, flag); + if (align > best) + best = align; + if (flag) { + align = CMach_GetQUALalign(member->qual); + if (align > best) + best = align; + } + } + } else { + isFirst = 1; + for (member = tstruct->members; member; member = member->next) { + align = CMach_GetPPCTypeAlign(member->type, isFirst || (best >= 8), flag); + if (align > best) + best = align; + if (flag) { + align = CMach_GetQUALalign(member->qual); + if (align > best) + best = align; + } + isFirst = 0; + } + } + return best; + } +} + +SInt16 CMach_GetStructAlign(TypeStruct *tstruct) { + return CMach_GetQualifiedStructAlign(tstruct, 1); +} + +static SInt16 CMach_GetQualifiedClassAlign(TypeClass *tclass, Boolean flag) { + ClassList *base; + ObjMemberVar *ivar; + SInt32 best; + SInt32 align; + Boolean isFirst; + + switch (copts.structalignment) { + case AlignMode3_1Byte: + case AlignMode8_Packed: + return 1; + case AlignMode0_Mac68k: + return 2; + case AlignMode1_Mac68k4byte: + return (tclass->size <= 2) ? 2 : 4; + } + if (tclass->size <= 1) + return 1; + best = 1; + switch (copts.structalignment) { + default: + CError_FATAL(1149); + case AlignMode4_2Byte: + case AlignMode5_4Byte: + case AlignMode6_8Byte: + case AlignMode7_16Byte: + for (base = tclass->bases; base; base = base->next) { + if ((align = base->base->align) > best) + best = align; + } + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + align = CMach_GetMemberAlignment(ivar->type, flag ? CMach_GetQUALalign(ivar->qual) : 0, flag); + if (align > best) + best = align; + } + return best; + case AlignMode2_PPC: + best = 1; + if (copts.oldalignment) { + for (base = tclass->bases; base; base = base->next) { + if ((align = base->base->align) > best) + best = align; + } + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + align = CMach_GetMemberAlignment(ivar->type, flag ? CMach_GetQUALalign(ivar->qual) : 0, flag); + if (align > best) + best = align; + } + } else { + isFirst = 1; + for (base = tclass->bases; base; base = base->next) { + if ((align = base->base->align) > best) + best = align; + isFirst = 0; + } + if (tclass->mode == 1) { + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + align = CMach_GetPPCTypeAlign(ivar->type, 1, flag); + if (align > best) + best = align; + if (flag) { + align = CMach_GetQUALalign(ivar->qual); + if (align > best) + best = align; + } + } + } else { + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + if (ivar->offset && align != 8) + isFirst = 0; + align = CMach_GetPPCTypeAlign(ivar->type, isFirst || (best >= 8), flag); + if (align > best) + best = align; + if (flag) { + align = CMach_GetQUALalign(ivar->qual); + if (align > best) + best = align; + } + } + } + } + return best; + } +} + +SInt16 CMach_GetClassAlign(TypeClass *tclass) { + return CMach_GetQualifiedClassAlign(tclass, 1); +} + +static SInt16 CMach_GetWinTypeAlign(Type *type) { + int packoffs = copts.structalignment - 3; + SInt32 align = cmach_packsize[packoffs]; + if (type->size < align) + align = type->size; + return align; +} + +static SInt16 CMach_GetWinMinimizeAlign(SInt16 align) { + int packoffs = copts.structalignment - 3; + SInt16 minimum = cmach_packsize[packoffs]; + if (minimum < align) + align = minimum; + return align; +} + +static SInt16 CMach_GetQualifiedTypeAlign(Type *type, Boolean flag) { + Boolean isWin; + SInt16 align; + + if (type->type == TYPESTRUCT && TYPE_STRUCT(type)->stype >= STRUCT_VECTOR_UCHAR && TYPE_STRUCT(type)->stype <= STRUCT_VECTOR_PIXEL) + return 16; + + switch (copts.structalignment) { + case AlignMode3_1Byte: + case AlignMode8_Packed: + return 1; + case AlignMode4_2Byte: + case AlignMode5_4Byte: + case AlignMode6_8Byte: + case AlignMode7_16Byte: + isWin = 1; + break; + default: + isWin = 0; + break; + } + +restart: + switch (type->type) { + case TYPEVOID: + return 0; + case TYPEFUNC: + return 0; + case TYPEENUM: + type = TYPE_ENUM(type)->enumtype; + case TYPEINT: + if (isWin) + return CMach_GetWinTypeAlign(type); + if (type->size == 1) + return 1; + if (copts.oldalignment && type->size == 8) + return 8; + if (copts.structalignment != AlignMode0_Mac68k && type->size >= 4) + return 4; + return 2; + case TYPEFLOAT: + if (isWin) + return CMach_GetWinTypeAlign(type); + switch (copts.structalignment) { + case AlignMode0_Mac68k: + return 2; + case AlignMode1_Mac68k4byte: + return 4; + case AlignMode2_PPC: + if (copts.oldalignment && type->size > 4) + return 8; + return 4; + default: + CError_FATAL(1346); + } + case TYPEMEMBERPOINTER: + case TYPEPOINTER: + if (isWin) + return CMach_GetWinTypeAlign(type); + if (copts.structalignment == AlignMode0_Mac68k) + return 2; + else + return 4; + case TYPEARRAY: + if (copts.alignarraymembers) { + if (isWin) + return CMach_GetWinTypeAlign(type); + if (type->size == 1) + return 1; + if (copts.structalignment == AlignMode0_Mac68k || type->size <= 2) + return 2; + if (copts.structalignment == AlignMode1_Mac68k4byte || type->size < 8) + return 4; + align = CMach_GetQualifiedTypeAlign(TYPE_POINTER(type)->target, flag); + if (align > 4) + return align; + else + return 4; + } else { + type = TYPE_POINTER(type)->target; + goto restart; + } + case TYPESTRUCT: + if (flag) + align = TYPE_STRUCT(type)->align; + else + align = CMach_GetQualifiedStructAlign(TYPE_STRUCT(type), flag); + if (isWin) + return CMach_GetWinMinimizeAlign(align); + else + return align; + case TYPECLASS: + if (flag) + align = TYPE_CLASS(type)->align; + else + align = CMach_GetQualifiedClassAlign(TYPE_CLASS(type), flag); + if (isWin) + return CMach_GetWinMinimizeAlign(align); + else + return align; + case TYPEBITFIELD: + type = TYPE_BITFIELD(type)->bitfieldtype; + goto restart; + case TYPETEMPLATE: + return 1; + default: + CError_FATAL(1392); + return 0; + } +} + +SInt16 CMach_GetTypeAlign(Type *type) { + return CMach_GetQualifiedTypeAlign(type, 1); +} + +static SInt16 CMach_GetMemberAlignment(Type *type, SInt32 var, Boolean flag) { + SInt32 align; + + align = CMach_GetQualifiedTypeAlign(type, flag); + if (align < 1) + align = 1; + + if (IS_TYPE_VECTOR(type) && align < 16) + align = 16; + + switch (copts.structalignment) { + case AlignMode8_Packed: + align = 1; + break; + case AlignMode0_Mac68k: + if (align > 2) + align = 2; + break; + case AlignMode1_Mac68k4byte: + if (align > 4) + align = 4; + break; + case AlignMode2_PPC: + if (!copts.oldalignment) + align = CMach_GetPPCTypeAlign(type, !cmach_structoffset || (cmach_structalign >= 8), flag); + if (var > align) + align = var; + break; + } + + if (align > cmach_structalign) + cmach_structalign = align; + return align; +} + +SInt16 CMach_MemberAlignValue(Type *type, SInt32 var) { + SInt16 align = CMach_GetMemberAlignment(type, 0, 1); + if (align <= 1) + return 0; + + return (align - 1) & (align - (var & (align - 1))); +} + +static SInt16 MemberAlignValue(Type *type, SInt32 var1, SInt32 var2) { + SInt16 align = CMach_GetMemberAlignment(type, var2, 1); + return (align - 1) & (align - (var1 & (align - 1))); +} + +void CMach_StructLayoutInitOffset(SInt32 offset) { + cmach_structoffset = offset; + cmach_structalign = 4; + cmach_curbfsize = 0; +} + +SInt32 CMach_StructLayoutGetCurSize(void) { + return cmach_structoffset; +} + +SInt32 CMach_StructLayoutGetOffset(Type *type, UInt32 qual) { + SInt32 align; + SInt32 offset; + + qual = CParser_GetTypeQualifiers(type, qual); + + cmach_curbfsize = 0; + align = MemberAlignValue(type, cmach_structoffset, CMach_GetQUALalign(qual)); + offset = cmach_structoffset + align; + cmach_structoffset = offset + type->size; + return offset; +} + +SInt32 CMach_StructLayoutBitfield(TypeBitfield *tbitfield, UInt32 qual) { + SInt16 align; + SInt16 padding_at_start; + SInt16 basesize; + SInt16 basesize_bits; + SInt16 required_alignment; + SInt16 r4; + + padding_at_start = 0; + required_alignment = 0; + align = CMach_GetQUALalign(qual); + if (align <= tbitfield->bitfieldtype->size) + align = 0; + + switch (tbitfield->bitfieldtype->size) { + case 1: + basesize = 1; + basesize_bits = 8; + required_alignment = 0; + break; + case 2: + basesize = 2; + basesize_bits = 16; + required_alignment = 2; + break; + case 4: + if (copts.structalignment != AlignMode0_Mac68k && copts.structalignment != AlignMode4_2Byte) + required_alignment = 4; + else + required_alignment = 2; + basesize = 4; + basesize_bits = 32; + break; + default: + CError_FATAL(1620); + } + + switch (copts.structalignment) { + case AlignMode3_1Byte: + case AlignMode8_Packed: + required_alignment = 0; + break; + } + + r4 = required_alignment; + if (align > required_alignment) + r4 = align; + if (r4 && (cmach_structoffset & (r4 - 1))) + padding_at_start = r4 - (cmach_structoffset & (r4 - 1)); + + if (!cmach_curbfsize) { + cmach_structoffset += padding_at_start; + if (!tbitfield->bitlength) + return cmach_structoffset; + cmach_curbfsize = tbitfield->bitlength; + cmach_curbfbasesize = basesize; + cmach_curbfoffset = cmach_structoffset; + cmach_structoffset += basesize; + tbitfield->offset = 0; + return cmach_curbfoffset; + } else { + if (!tbitfield->bitlength || (cmach_curbfsize + tbitfield->bitlength) > basesize_bits || cmach_curbfbasesize != basesize) { + cmach_structoffset += padding_at_start; + cmach_curbfsize = 0; + cmach_curbfbasesize = basesize; + if (!tbitfield->bitlength) + return cmach_structoffset; + cmach_curbfoffset = cmach_structoffset; + cmach_structoffset += basesize; + } + tbitfield->offset = cmach_curbfsize; + cmach_curbfsize += tbitfield->bitlength; + return cmach_curbfoffset; + } +} + +static Boolean CMach_IsTrivialClass(TypeClass *tclass) { + return !CClass_Constructor(tclass); +} + +UInt8 CMach_GetFunctionResultClass(TypeFunc *tfunc) { + switch (tfunc->functype->type) { + case TYPESTRUCT: + if (tfunc->functype->type == TYPESTRUCT && TYPE_STRUCT(tfunc->functype)->stype >= STRUCT_VECTOR_UCHAR && TYPE_STRUCT(tfunc->functype)->stype <= STRUCT_VECTOR_PIXEL) + return 0; + case TYPECLASS: + case TYPEMEMBERPOINTER: + return CMach_PassResultInHiddenArg(tfunc->functype) != 0; + default: + return 0; + } +} + +Boolean CMach_PassResultInHiddenArg(Type *type) { + switch (type->type) { + case TYPESTRUCT: + if (TYPE_STRUCT(type)->stype >= STRUCT_VECTOR_UCHAR && TYPE_STRUCT(type)->stype <= STRUCT_VECTOR_PIXEL) + return 0; + else + return 1; + case TYPECLASS: + return 1; + case TYPEMEMBERPOINTER: + return (type->size != 4); + default: + return 0; + } +} + +char *CMach_GetCPU(void) { + switch (copts.processor) { + case CPU_PPC401: return "__PPC401__"; + case CPU_PPC403: return "__PPC403__"; + case CPU_PPC505: return "__PPC505__"; + case CPU_PPC509: return "__PPC509__"; + case CPU_PPC555: return "__PPC555__"; + case CPU_PPC556: return "__PPC556__"; + case CPU_PPC565: return "__PPC565__"; + case CPU_PPC601: return "__PPC601__"; + case CPU_PPC602: return "__PPC602__"; + case CPU_PPC603: return "__PPC603__"; + case CPU_PPC603e: return "__PPC603e__"; + case CPU_PPC604: return "__PPC604__"; + case CPU_PPC604e: return "__PPC604e__"; + case CPU_PPC740: return "__PPC740__"; + case CPU_PPC750: return "__PPC750__"; + case CPU_PPC801: return "__PPC801__"; + case CPU_PPC821: return "__PPC821__"; + case CPU_PPC823: return "__PPC823__"; + case CPU_PPC850: return "__PPC850__"; + case CPU_PPC860: return "__PPC860__"; + case CPU_PPC7400: return "__PPC7400__"; + case CPU_PPC7450: return "__PPC7450__"; + case CPU_PPC8240: return "__PPC8240__"; + case CPU_PPC8260: return "__PPC8260__"; + case CPU_PPCGEKKO: return "__PPCGEKKO__"; + case CPU_PPCELF: return "__PPCELF__"; + default: return NULL; + } +} + +Boolean CMach_FloatIsPowerOf2(Float flt) { + return (flt.value == 2.0) || + (flt.value == 4.0) || + (flt.value == 8.0) || + (flt.value == 16.0) || + (flt.value == 32.0) || + (flt.value == 64.0) || + (flt.value == 128.0) || + (flt.value == 256.0) || + (flt.value == 512.0) || + (flt.value == 1024.0); +} + +Float CMach_FloatReciprocal(Float flt) { + flt.value = 1.0 / flt.value; + return flt; +} + +SInt32 CMach_RoundedSizeOf(Object *object) { + SInt32 size = object->type->size; + SInt32 align = CMach_GetTypeAlign(object->type) - 1; + return (size + align) & ~align; +} + +void CMach_ReInitRuntimeObjects(void) { + HashNameNode *e0 = GetHashNameNodeExport("[0]"); + HashNameNode *e1 = GetHashNameNodeExport("[1]"); + HashNameNode *e2 = GetHashNameNodeExport("[2]"); + HashNameNode *e3 = GetHashNameNodeExport("[3]"); + HashNameNode *e4 = GetHashNameNodeExport("[4]"); + HashNameNode *e5 = GetHashNameNodeExport("[5]"); + HashNameNode *e6 = GetHashNameNodeExport("[6]"); + HashNameNode *e7 = GetHashNameNodeExport("[7]"); + HashNameNode *e8 = GetHashNameNodeExport("[8]"); + HashNameNode *e9 = GetHashNameNodeExport("[9]"); + HashNameNode *e10 = GetHashNameNodeExport("[10]"); + HashNameNode *e11 = GetHashNameNodeExport("[11]"); + HashNameNode *e12 = GetHashNameNodeExport("[12]"); + HashNameNode *e13 = GetHashNameNodeExport("[13]"); + HashNameNode *e14 = GetHashNameNodeExport("[14]"); + HashNameNode *e15 = GetHashNameNodeExport("[15]"); + HashNameNode *vuc = GetHashNameNodeExport("vector unsigned char"); + HashNameNode *vus = GetHashNameNodeExport("vector unsigned short"); + HashNameNode *vui = GetHashNameNodeExport("vector unsigned int"); + HashNameNode *vsc = GetHashNameNodeExport("vector signed char"); + HashNameNode *vss = GetHashNameNodeExport("vector signed short"); + HashNameNode *vsi = GetHashNameNodeExport("vector signed int"); + HashNameNode *vbc = GetHashNameNodeExport("vector bool char"); + HashNameNode *vbs = GetHashNameNodeExport("vector bool short"); + HashNameNode *vbi = GetHashNameNodeExport("vector bool int"); + HashNameNode *vf = GetHashNameNodeExport("vector float"); + HashNameNode *vp = GetHashNameNodeExport("vector pixel"); + + stvectorunsignedchar.name = vuc; + stvectorunsignedshort.name = vus; + stvectorunsignedlong.name = vui; + stvectorsignedchar.name = vsc; + stvectorsignedshort.name = vss; + stvectorsignedlong.name = vsi; + stvectorboolchar.name = vbc; + stvectorboolshort.name = vbs; + stvectorboollong.name = vbi; + stvectorfloat.name = vf; + stvectorpixel.name = vp; + + stVUC_unsignedchar0.name = e0; + stVUC_unsignedchar1.name = e1; + stVUC_unsignedchar2.name = e2; + stVUC_unsignedchar3.name = e3; + stVUC_unsignedchar4.name = e4; + stVUC_unsignedchar5.name = e5; + stVUC_unsignedchar6.name = e6; + stVUC_unsignedchar7.name = e7; + stVUC_unsignedchar8.name = e8; + stVUC_unsignedchar9.name = e9; + stVUC_unsignedchar10.name = e10; + stVUC_unsignedchar11.name = e11; + stVUC_unsignedchar12.name = e12; + stVUC_unsignedchar13.name = e13; + stVUC_unsignedchar14.name = e14; + stVUC_unsignedchar15.name = e15; + stVSC_signedchar0.name = e0; + stVSC_signedchar1.name = e1; + stVSC_signedchar2.name = e2; + stVSC_signedchar3.name = e3; + stVSC_signedchar4.name = e4; + stVSC_signedchar5.name = e5; + stVSC_signedchar6.name = e6; + stVSC_signedchar7.name = e7; + stVSC_signedchar8.name = e8; + stVSC_signedchar9.name = e9; + stVSC_signedchar10.name = e10; + stVSC_signedchar11.name = e11; + stVSC_signedchar12.name = e12; + stVSC_signedchar13.name = e13; + stVSC_signedchar14.name = e14; + stVSC_signedchar15.name = e15; + + stVUS_unsignedshort0.name = e0; + stVUS_unsignedshort1.name = e1; + stVUS_unsignedshort2.name = e2; + stVUS_unsignedshort3.name = e3; + stVUS_unsignedshort4.name = e4; + stVUS_unsignedshort5.name = e5; + stVUS_unsignedshort6.name = e6; + stVUS_unsignedshort7.name = e7; + stVSS_signedshort0.name = e0; + stVSS_signedshort1.name = e1; + stVSS_signedshort2.name = e2; + stVSS_signedshort3.name = e3; + stVSS_signedshort4.name = e4; + stVSS_signedshort5.name = e5; + stVSS_signedshort6.name = e6; + stVSS_signedshort7.name = e7; + + stVUL_unsignedlong0.name = e0; + stVUL_unsignedlong1.name = e1; + stVUL_unsignedlong2.name = e2; + stVUL_unsignedlong3.name = e3; + stVSL_signedlong0.name = e0; + stVSL_signedlong1.name = e1; + stVSL_signedlong2.name = e2; + stVSL_signedlong3.name = e3; + + stVF_float0.name = e0; + stVF_float1.name = e1; + stVF_float2.name = e2; + stVF_float3.name = e3; +} diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/CodeGen.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/CodeGen.c new file mode 100644 index 0000000..d3bac77 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/CodeGen.c @@ -0,0 +1,2437 @@ +#include "compiler/CodeGen.h" +#include "compiler/CCompiler.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/COptimizer.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/Coloring.h" +#include "compiler/CompilerTools.h" +#include "compiler/DumpIR.h" +#include "compiler/Exceptions.h" +#include "compiler/InlineAsmPPC.h" +#include "compiler/Intrinsics.h" +#include "compiler/InstrSelection.h" +#include "compiler/GlobalOptimizer.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/Operands.h" +#include "compiler/PCode.h" +#include "compiler/PCodeAssembly.h" +#include "compiler/PCodeInfo.h" +#include "compiler/PCodeListing.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/Peephole.h" +#include "compiler/PPCError.h" +#include "compiler/RegisterInfo.h" +#include "compiler/Scheduler.h" +#include "compiler/StackFrame.h" +#include "compiler/Switch.h" +#include "compiler/TOC.h" +#include "compiler/ValueNumbering.h" +#include "compiler/enode.h" +#include "compiler/objc.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/tokens.h" +#include "compiler/types.h" + +static Macro powcM; +static Macro __powcM; +static Macro ppc_cpu; +static Macro profM; +static Macro hostM; +static Macro bendM; +static Macro _ppc_M; +static Macro longI; +static Macro IEEED; +Macro vecM; +Macro altivecM; +static Macro macM2; +static Macro appleM; +static Macro optM; +static Macro alignM; +static Macro _machM; +static Macro archM; +static Macro dynM; +static Macro ppcM; +Object *gFunction; +static ObjectList *temps; +CLabel *returnlabel; +CLabel *cleanreturnlabel; +Boolean needs_cleanup; +Statement *current_statement; +int has_catch_blocks; +int disable_optimizer; +SInt32 current_linenumber; +Boolean has_altivec_arrays; +short high_reg; +short low_reg; +short high_offset; +short low_offset; +short low_reg2; +short high_reg2; +PCodeLabel *pic_base_pcodelabel; +Object *dyld_stub_binding_helper; +Object *rt_cvt_fp2unsigned; +Object *rt_profile_entry; +Object *rt_profile_exit; +Object *rt_div2i; +Object *rt_div2u; +Object *rt_mod2i; +Object *rt_mod2u; +Object *rt_shr2i; +Object *rt_shr2u; +Object *rt_shl2i; +Object *rt_cvt_ull_dbl; +Object *rt_cvt_sll_dbl; +Object *rt_cvt_ull_flt; +Object *rt_cvt_sll_flt; +Object *rt_cvt_dbl_usll; +static heaperror_t saveheaperror; + +enum { + GPRLimit = 10, + FPRLimit = 13, + VRLimit = 13 +}; + +// forward decls +static void CodeGen_heaperror(void); + +VarInfo *CodeGen_GetNewVarInfo(void) { + VarInfo *vi; + + vi = lalloc(sizeof(VarInfo)); + memclrw(vi, sizeof(VarInfo)); + + vi->deftoken = *CPrep_CurStreamElement(); + vi->varnumber = localcount++; + + return vi; +} + +Object *maketemporary(Type *type) { + ObjectList *list; + Object *obj; + + for (list = temps; list; list = list->next) { + obj = list->object; + if (obj->u.var.uid == 0 && obj->type == type) { + obj->u.var.uid = 1; + return obj; + } + } + + obj = lalloc(sizeof(Object)); + memclrw(obj, sizeof(Object)); + obj->otype = OT_OBJECT; + obj->access = ACCESSPUBLIC; + obj->datatype = DLOCAL; + obj->type = type; + obj->name = CParser_GetUniqueName(); + obj->u.var.info = CodeGen_GetNewVarInfo(); + obj->u.var.uid = 1; + + list = lalloc(sizeof(ObjectList)); + memclrw(list, sizeof(ObjectList)); + list->next = temps; + list->object = obj; + temps = list; + + return obj; +} + +static void free_temporaries(void) { + ObjectList *list; + + for (list = temps; list; list = list->next) + list->object->u.var.uid = 0; +} + +static void allocate_temporaries(void) { + ObjectList *list; + + for (list = temps; list; list = list->next) + assign_local_memory(list->object); +} + +void process_arguments(ArgumentProcessor func, Boolean flag) { + short gpr = 3; + short fpr = 1; + short vr = 2; + Type *type; + ObjectList *list; + + for (list = arguments; list; list = list->next) { + type = list->object->type; + if (IS_TYPE_FLOAT(type)) { + func(list->object, (fpr <= FPRLimit) ? fpr : 0); + fpr++; + if (type->size == 4) + gpr++; + else + gpr += 2; + } else if (IS_TYPE_VECTOR(type)) { + func(list->object, (vr <= VRLimit) ? vr : 0); + vr++; + if (flag) { + if ((vr - 1) == 2) + gpr = 9; + else if ((vr - 1) > 2) + gpr = 11; + } + } else { + func(list->object, (gpr <= GPRLimit) ? gpr : 0); + if (TYPE_FITS_IN_REGISTER(type)) { + if (type->size <= 4) + gpr += 1; + else + gpr += 2; + } else { + gpr += (type->size >> 2); + if (type->size & 3) + gpr++; + } + } + } + + last_argument_register[RegClass_GPR] = gpr - 1; + last_argument_register[RegClass_FPR] = fpr - 1; + last_argument_register[RegClass_VR] = vr - 1; + if (flag) + move_varargs_to_memory(); +} + +static void retain_argument_register(Object *obj, short reg) { + VarInfo *vi = Registers_GetVarInfo(obj); + Type *type = obj->type; + + if (reg && !vi->noregister && vi->used) { + if (TYPE_FITS_IN_REGISTER(type)) { + if (type->size <= 4) { + retain_register(obj, RegClass_GPR, reg); + } else if (reg < GPRLimit) { + if (copts.littleendian) + retain_GPR_pair(obj, reg, reg + 1); + else + retain_GPR_pair(obj, reg + 1, reg); + } + } else if (IS_TYPE_FLOAT(type)) { + retain_register(obj, RegClass_FPR, reg); + } else if (IS_TYPE_VECTOR(type)) { + retain_register(obj, RegClass_VR, reg); + } + } +} + +static void allocate_local_vregs(void) { + ObjectList *list; + Object *obj; + VarInfo *vi; + + if (copts.codegen_pic && uses_globals && assignable_registers[RegClass_GPR]) { + if (assignable_registers[RegClass_GPR]) { + vi = pic_base.u.var.info; + vi->reg = 0; + assign_register_by_type(&pic_base); + pic_base_reg = vi->reg; + CError_ASSERT(497, pic_base_reg); + } else { + CError_FATAL(500); + } + } else { + pic_base_reg = 0; + } + + for (list = exceptionlist; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + + if (vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg) + assign_register_by_type(obj); + } + } + + set_last_exception_registers(); + + for (list = arguments; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + + if (vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg) + assign_register_by_type(obj); + } + } + + for (list = locals; list; list = list->next) { + obj = list->object; + if (!IsTempName(obj->name)) { + vi = Registers_GetVarInfo(obj); + + if (vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg) + assign_register_by_type(obj); + } + } + } + + open_fe_temp_registers(); + + for (list = locals; list; list = list->next) { + obj = list->object; + if (IsTempName(obj->name)) { + vi = Registers_GetVarInfo(obj); + + if (vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg) + assign_register_by_type(obj); + } + } + } + + for (list = toclist; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + + if (!vi->reg && vi->used && vi->usage > 1) + assign_register_by_type(obj); + } +} + +static void allocate_local_GPRs(void) { + ObjectList *list; + Object *obj; + Object *winning_obj; + SInt32 winning_usage; + VarInfo *vi; + Type *type; + + if (copts.codegen_pic && uses_globals && assignable_registers[RegClass_GPR]) { + vi = pic_base.u.var.info; + vi->reg = 0; + assign_register_by_type(&pic_base); + pic_base_reg = vi->reg; + CError_ASSERT(605, pic_base_reg); + } else { + pic_base_reg = 0; + } + + while (assignable_registers[RegClass_GPR]) { + winning_obj = NULL; + winning_usage = -1; + if (!(disable_optimizer & 2)) { + for (list = arguments; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + type = obj->type; + if (vi->flags & VarInfoFlag40) + vi->usage = 100000; + if (!vi->reg && vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { + if (TYPE_FITS_IN_REGISTER(type) && (!TYPE_IS_8BYTES(type) || assignable_registers[RegClass_GPR] >= 2)) { + winning_obj = obj; + winning_usage = vi->usage; + } + } + } + } + } + if (!(disable_optimizer & 2)) { + for (list = locals; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + type = obj->type; + if (vi->flags & VarInfoFlag40) + vi->usage = 100000; + if (!vi->reg && vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { + if (TYPE_FITS_IN_REGISTER(type) && (!TYPE_IS_8BYTES(type) || assignable_registers[RegClass_GPR] >= 2)) { + winning_obj = obj; + winning_usage = vi->usage; + } + } + } + } + } + for (list = toclist; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + if (vi->flags & VarInfoFlag40) + vi->usage = 100000; + if (!vi->reg && vi->used) { + if (vi->usage >= winning_usage && vi->usage >= 3) { + winning_obj = obj; + winning_usage = vi->usage; + } + } + } + + if (!winning_obj) + break; + + assign_register_by_type(winning_obj); + CError_ASSERT(698, Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2); + } +} + +static void allocate_local_FPRs(void) { + ObjectList *list; + Object *obj; + Object *winning_obj; + SInt32 winning_usage; + VarInfo *vi; + Type *type; + + while (assignable_registers[RegClass_FPR]) { + winning_obj = NULL; + winning_usage = -1; + if (!(disable_optimizer & 2)) { + for (list = arguments; list; list = list->next) { + obj = list->object; + type = obj->type; + vi = Registers_GetVarInfo(obj); + if (vi->flags & VarInfoFlag40) + vi->usage = 100000; + if (!vi->reg && vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { + if (IS_TYPE_FLOAT(type)) { + winning_obj = obj; + winning_usage = vi->usage; + } + } + } + } + } + if (!(disable_optimizer & 2)) { + for (list = locals; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + if (vi->flags & VarInfoFlag40) + vi->usage = 100000; + if (!vi->reg && vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { + if (IS_TYPE_FLOAT(obj->type)) { + winning_obj = obj; + winning_usage = vi->usage; + } + } + } + } + } + + if (!winning_obj) + break; + + assign_register_by_type(winning_obj); + CError_ASSERT(782, Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2); + } +} + +static void allocate_local_VRs(void) { + ObjectList *list; + Object *obj; + Object *winning_obj; + SInt32 winning_usage; + VarInfo *vi; + + while (assignable_registers[RegClass_VR]) { + winning_obj = NULL; + winning_usage = -1; + if (!(disable_optimizer & 2)) { + for (list = arguments; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + if (vi->flags & VarInfoFlag40) + vi->usage = 100000; + if (!vi->reg && vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { + if (IS_TYPE_VECTOR(obj->type)) { + winning_obj = obj; + winning_usage = vi->usage; + } + } + } + } + } + if (!(disable_optimizer & 2)) { + for (list = locals; list; list = list->next) { + obj = list->object; + vi = Registers_GetVarInfo(obj); + if (vi->flags & VarInfoFlag40) + vi->usage = 100000; + if (!vi->reg && vi->used && !vi->noregister) { + if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { + if (IS_TYPE_VECTOR(obj->type)) { + winning_obj = obj; + winning_usage = vi->usage; + } + } + } + } + } + + if (!winning_obj) + break; + + assign_register_by_type(winning_obj); + CError_ASSERT(846, Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2); + } +} + +static void allocate_locals(void) { + has_altivec_arrays = 0; + + if (!requires_frame && !optimizing) + process_arguments(retain_argument_register, 0); + + if (optimizing) { + allocate_local_vregs(); + } else { + allocate_local_GPRs(); + allocate_local_FPRs(); + allocate_local_VRs(); + } + + assign_locals_to_memory(locals); +} + +void move_assigned_argument(Object *obj, short reg) { + VarInfo *vi; + Type *type; + SInt32 bytesLeft; + SInt32 offset; + + vi = Registers_GetVarInfo(obj); + type = obj->type; + CError_ASSERT(901, obj->datatype == DLOCAL); + + if (!vi->used) + return; + + if (reg) { + if (vi->reg) { + if (TYPE_IS_8BYTES(type)) { + if (copts.littleendian) { + if (vi->reg != reg) + emitpcode(PC_MR, vi->reg, reg); + if (reg < GPRLimit) { + CError_FAIL(916, (vi->regHi == reg) || (vi->reg == (reg + 1))); + if (vi->regHi != (reg + 1)) + emitpcode(PC_MR, vi->regHi, reg + 1); + } else { + load_store_register(PC_LWZ, vi->regHi, local_base_register(obj), obj, high_offset); + } + } else { + if (vi->regHi != reg) + emitpcode(PC_MR, vi->regHi, reg); + if (reg < GPRLimit) { + CError_FAIL(931, (vi->reg == reg) || (vi->regHi == (reg + 1))); + if (vi->reg != (reg + 1)) + emitpcode(PC_MR, vi->reg, reg + 1); + } else { + load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, low_offset); + } + } + } else if (vi->reg != reg) { + if (IS_TYPE_FLOAT(type)) { + emitpcode(PC_FMR, vi->reg, reg); + } else if (IS_TYPE_VECTOR(type)) { + emitpcode(PC_VMR, vi->reg, reg); + } else { + emitpcode(PC_MR, vi->reg, reg); + } + } + } else { + if (IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)) { + load_store_register(PC_STW, reg, local_base_register(obj), obj, 0); + } else if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) { + switch (type->size) { + case 1: + load_store_register(PC_STB, reg, local_base_register(obj), obj, 0); + break; + case 2: + load_store_register(PC_STH, reg, local_base_register(obj), obj, 0); + break; + case 4: + load_store_register(PC_STW, reg, local_base_register(obj), obj, 0); + break; + case 8: + load_store_register(PC_STW, reg, local_base_register(obj), obj, 0); + if (reg < GPRLimit) + load_store_register(PC_STW, reg + 1, local_base_register(obj), obj, 4); + break; + default: + CError_FATAL(993); + } + } else if (IS_TYPE_FLOAT(type)) { + load_store_register((type->size == 4) ? PC_STFS : PC_STFD, reg, local_base_register(obj), obj, 0); + } else if (IS_TYPE_VECTOR(type)) { + load_store_register(PC_STVX, reg, local_base_register(obj), obj, 0); + } else { + bytesLeft = (11 - reg) * 4; + if (bytesLeft > obj->type->size) + bytesLeft = obj->type->size; + offset = 0; + while (bytesLeft > 0) { + load_store_register(PC_STW, reg, local_base_register(obj), obj, offset); + reg++; + offset += 4; + bytesLeft -= 4; + } + } + } + } else { + if (vi->reg) { + if (IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)) { + load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, 0); + } else if (IS_TYPE_FLOAT(type)) { + load_store_register((type->size == 4) ? PC_LFS : PC_LFD, vi->reg, local_base_register(obj), obj, 0); + } else if (IS_TYPE_VECTOR(type)) { + load_store_register(PC_LVX, vi->reg, local_base_register(obj), obj, 0); + } else { + switch (type->size) { + case 1: + load_store_register(PC_LBZ, vi->reg, local_base_register(obj), obj, 0); + break; + case 2: + load_store_register(is_unsigned(type) ? PC_LHZ : PC_LHA, vi->reg, local_base_register(obj), obj, 0); + break; + case 4: + load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, 0); + break; + case 8: + load_store_register(PC_LWZ, vi->regHi, local_base_register(obj), obj, high_offset); + load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, low_offset); + break; + default: + CError_FATAL(1095); + } + } + } else if (!optimizing) { + local_base_register(obj); + } + } +} + +static void load_TOC_pointers(void) { + VarInfo *vi; + Object *obj; + ObjectList *list; + PCode *pc; + Operand opnd; + + if (uses_globals && pic_base_reg) { + pic_base_pcodelabel = makepclabel(); + pc = makepcode(PC_BC, 20, 7, 3, pic_base_pcodelabel); + pcsetlinkbit(pc); + pcsetsideeffects(pc); + appendpcode(pclastblock, pc); + pcbranch(pclastblock, pic_base_pcodelabel); + makepcblock(); + pclabel(pclastblock, pic_base_pcodelabel); + emitpcode(PC_MFLR, pic_base_reg); + } + + memclrw(&opnd, sizeof(Operand)); + for (list = toclist; list; list = list->next) { + obj = list->object; + if ((vi = Registers_GetVarInfo(obj)) && (vi->flags & VarInfoFlag2)) { + switch (obj->datatype) { + case DNONLAZYPTR: + symbol_operand(&opnd, obj); + opnd.optype = OpndType_IndirectSymbol; + if (opnd.optype) + Coerce_to_register(&opnd, TYPE(&void_ptr), vi->reg); + if (opnd.reg != vi->reg) + emitpcode(PC_MR, vi->reg, opnd.reg); + break; + default: + CError_FATAL(1206); + } + } + } +} + +static int has_vararglist(Object *funcobj) { + FuncArg *arg; + + arg = TYPE_FUNC(funcobj->type)->args; + while (arg && arg != &elipsis) + arg = arg->next; + + return (arg == &elipsis); +} + +void assign_labels(Statement *stmt) { + Statement *last; + + last = NULL; + while (stmt) { + if (stmt->type == ST_LABEL && !stmt->label->pclabel) { + if (last && last->type == ST_LABEL) + stmt->label->pclabel = last->label->pclabel; + else + stmt->label->pclabel = makepclabel(); + } + + last = stmt; + stmt = stmt->next; + } +} + +static Boolean islaststatement(Statement *stmt) { + for (stmt = stmt->next; stmt; stmt = stmt->next) { + if (stmt->type > ST_LABEL) + return 0; + } + return 1; +} + +static void newstatement(SInt32 sourceoffset, SInt32 value, int flag) { + PCodeBlock *block = pclastblock; + + pcloopweight = value; + if (!block->pcodeCount) + block->loopWeight = value; + + if (block->pcodeCount > 100) + branch_label(makepclabel()); + + if (flag) + block->flags |= fPCBlockFlag4000; +} + +static void expressionstatement(ENode *expr) { + Operand opnd; + + memclrw(&opnd, sizeof(Operand)); + cgdispatch[expr->type](expr, 0, 0, &opnd); + + if (ENODE_IS(expr, EINDIRECT) && (opnd.flags & OpndFlags_Volatile)) { + if (TYPE_FITS_IN_REGISTER_2(expr->rtype)) { + if (opnd.optype != OpndType_GPR) + Coerce_to_register(&opnd, expr->rtype, 0); + } else if (IS_TYPE_FLOAT(expr->rtype)) { + if (opnd.optype != OpndType_FPR) + Coerce_to_fp_register(&opnd, expr->rtype, 0); + } else if (IS_TYPE_VECTOR(expr->rtype)) { + if (opnd.optype != OpndType_VR) + Coerce_to_v_register(&opnd, expr->rtype, 0); + } + } +} + +static void labelstatement(CLabel *label) { + if (!label->pclabel) + label->pclabel = makepclabel(); + if (!label->pclabel->resolved) + branch_label(label->pclabel); + free_temporaries(); +} + +static void gotostatement(CLabel *label) { + if (!label->pclabel) + label->pclabel = makepclabel(); + branch_always(label->pclabel); + free_temporaries(); +} + +static void gotoexpression(ENode *expr) { + Operand opnd; + CodeLabelList *list; + + memclrw(&opnd, sizeof(Operand)); + cgdispatch[expr->type](expr, 0, 0, &opnd); + + if (opnd.optype != OpndType_GPR) + Coerce_to_register(&opnd, TYPE(&void_ptr), 0); + CError_ASSERT(1397, opnd.optype == OpndType_GPR); + + for (list = codelabellist; list; list = list->next) + pcbranch(pclastblock, list->label->pclabel); + + emitpcode(PC_MTCTR, opnd.reg); + branch_indirect(NULL); +} + +static void conditionalstatement(ENode *cond, CLabel *label, short truthy) { + Operand opnd; + memclrw(&opnd, sizeof(Operand)); + + cond = evaluate_and_skip_comma(cond); + if (!label->pclabel) + label->pclabel = makepclabel(); + + if (TYPE_IS_8BYTES(cond->data.diadic.right->rtype) || TYPE_IS_8BYTES(cond->data.diadic.left->rtype)) + I8_gen_condition(cond, &opnd, 0); + else + gen_condition(cond, &opnd); + + branch_conditional(opnd.reg, opnd.regOffset, truthy, label->pclabel); + free_temporaries(); +} + +static void returnstatement(ENode *expr, Boolean dont_branch) { + Operand opnd; + Type *type; + memclrw(&opnd, sizeof(Operand)); + + if (expr) { + type = expr->rtype; + if (TYPE_FITS_IN_REGISTER(type)) { + if (TYPE_IS_8BYTES(type)) { + cgdispatch[expr->type](expr, low_reg, high_reg, &opnd); + coerce_to_register_pair(&opnd, type, low_reg, high_reg); + } else { + cgdispatch[expr->type](expr, 3, 0, &opnd); + if (opnd.optype != OpndType_GPR) + Coerce_to_register(&opnd, type, 3); + if (opnd.reg != 3) + emitpcode(PC_MR, 3, opnd.reg); + } + } else if (IS_TYPE_FLOAT(type)) { + cgdispatch[expr->type](expr, 1, 0, &opnd); + if (opnd.optype != OpndType_FPR) + Coerce_to_fp_register(&opnd, type, 1); + if (opnd.reg != 1) + emitpcode(PC_FMR, 1, opnd.reg); + } else if (IS_TYPE_VECTOR(type)) { + cgdispatch[expr->type](expr, 2, 0, &opnd); + if (opnd.optype != OpndType_VR) + Coerce_to_v_register(&opnd, type, 2); + if (opnd.reg != 2) + emitpcode(PC_VMR, 2, opnd.reg); + } else { + cgdispatch[expr->type](expr, 0, 0, &opnd); + } + } + + if (!dont_branch) { + if (!returnlabel->pclabel) + returnlabel->pclabel = makepclabel(); + branch_always(returnlabel->pclabel); + free_temporaries(); + } +} + +static void capturestackpointer(Object *obj) { + branch_label(makepclabel()); + CError_ASSERT(1568, obj->datatype == DLOCAL); + + load_store_register(PC_STW, 1, local_base_register(obj), obj, 20); + branch_label(makepclabel()); +} + +static void resetstackpointer(Object *obj) { + PCode *pc; + + CError_ASSERT(1595, obj->datatype == DLOCAL); + + branch_label(makepclabel()); + + load_store_register(PC_LWZ, 0, 1, NULL, 0); + + pc = makepcode(PC_LWZ, 1, local_base_register(obj), obj, 20); + pcsetsideeffects(pc); + appendpcode(pclastblock, pc); + + load_store_register(PC_STW, 0, 1, NULL, 0); + + branch_label(makepclabel()); +} + +static void callprofiler(char *name) { + UInt32 masks[RegClassMax] = {0, 0, 0, 0, 0}; + load_store_register(PC_LWZ, 3, 1, NULL, 0); + load_store_register(PC_LWZ, 3, 3, NULL, 8); + masks[RegClass_GPR] |= (1 << 3); + branch_subroutine(rt_profile_entry, 1, masks); +} + +static void exitprofiler(void) { +} + +void CodeGen_Generator(Statement *statements, Object *func, UInt8 mysteryFlag, Boolean callOnModuleBind) { + Statement *stmt; + Boolean has_varargs; + PCodeBlock *tmp; + SInt32 size; + + CodeGen_InitialSanityCheck(); + if (!saveheaperror) { + saveheaperror = getheaperror(); + setheaperror(CodeGen_heaperror); + } + + if (cparamblkptr->precompile == 1) + CError_Error(CErrorStr180); + + if (!func) { + func = createstaticinitobject(); + } else { +#ifdef CW_CLT + if (func && func->name) + PrintProgressFunction(func->name->name); +#endif + } + + gFunction = func; + has_varargs = has_vararglist(func); + init_endian(); + init_stack_globals(func); + assign_arguments_to_memory(func, mysteryFlag, has_varargs); + + needs_cleanup = 0; + disable_optimizer = 0; + has_catch_blocks = 0; + current_statement = NULL; + current_linenumber = 0; + precomputedoperands = NULL; + switchtables = NULL; + temps = NULL; + initializeexceptiontables(); + returnlabel = cleanreturnlabel = newlabel(); + + if (copts.debuglisting) + DumpIR(statements, func); + + statements = COpt_Optimizer(func, statements); + if (copts.debuglisting) + DumpIR(statements, func); + + resetTOCvarinfo(); + init_registers(); + expandTOCreferences(&statements->next); + if (copts.debuglisting) + DumpIR(statements, func); + + if (copts.profile) { + makes_call = 1; + requires_frame = 1; + } + + initpcode(); + + pclabel(prologue = makepcblock(), makepclabel()); + prologue->flags |= fIsProlog; + + pclabel(tmp = makepcblock(), makepclabel()); + pcbranch(prologue, tmp->labels); + + init_frame_sizes(has_varargs); + allocate_locals(); + process_arguments(move_assigned_argument, has_varargs); + + if (copts.schedule_factor || copts.altivec_model) + branch_label(makepclabel()); + + load_TOC_pointers(); + + if (copts.profile) + callprofiler(CMangler_GetLinkName(func)->name); + + assign_labels(statements->next); + open_temp_registers(); + + for (stmt = statements->next; stmt; stmt = stmt->next) { + current_statement = stmt; + current_linenumber = stmt->sourceoffset; + switch (stmt->type) { + case ST_NOP: + break; + case ST_EXPRESSION: + newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0); + expressionstatement(stmt->expr); + break; + case ST_LABEL: + labelstatement(stmt->label); + break; + case ST_IFGOTO: + newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0); + conditionalstatement(stmt->expr, stmt->label, 1); + break; + case ST_IFNGOTO: + newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0); + conditionalstatement(stmt->expr, stmt->label, 0); + break; + case ST_GOTOEXPR: + newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0); + gotoexpression(stmt->expr); + break; + case ST_GOTO: + newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0); + gotostatement(stmt->label); + break; + case ST_RETURN: + newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0); + returnstatement(stmt->expr, islaststatement(stmt)); + break; + case ST_SWITCH: + newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0); + switchstatement(stmt->expr, (SwitchInfo *) stmt->label); + break; + case ST_BEGINCATCH: + capturestackpointer(stmt->expr->data.objref); + break; + case ST_ENDCATCHDTOR: + CError_ASSERT(2056, stmt->expr->data.objref->datatype == DLOCAL); + add_immediate(3, local_base_register(stmt->expr->data.objref), stmt->expr->data.objref, 0); + { + UInt32 masks[RegClassMax] = {0, 0, 0, 0, 0}; + masks[RegClass_GPR] |= 1 << 3; + branch_subroutine(Xecth_func, 1, masks); + } + case ST_ENDCATCH: + resetstackpointer(stmt->expr->data.objref); + break; + case ST_ASM: + if (stmt->expr) { + if (((InlineAsm *) stmt->expr)->flags & IAFlag1) { + CError_FATAL(2076); + } else { + branch_label(makepclabel()); + InlineAsm_TranslateIRtoPCode(stmt); + } + } + break; + case ST_BEGINLOOP: + CError_FATAL(2086); + break; + case ST_ENDLOOP: + CError_FATAL(2090); + break; + default: + CError_FATAL(2094); + } + check_temp_registers(); + } + + close_temp_registers(); + labelstatement(returnlabel); + + current_statement = NULL; + + epilogue = pclastblock; + pclastblock->flags |= fIsEpilogue; + + pccomputepredecessors(); + deleteunreachableblocks(); + + if (copts.report_heap_info > 0) + CodeGen_reportheapinfo(0, CMangler_GetLinkName(func)->name, "before optimization"); + + if (copts.optimizationlevel > 0 && !disable_optimizer) + globallyoptimizepcode(func); + else + pclistblocks(CMangler_GetLinkName(func)->name, "INITIAL CODE"); + + if (copts.schedule_factor == 2) { + if (copts.peephole) + peepholemergeblocks(func, 0); + if (copts.debuglisting) + pclistblocks_start_scheduler(CMangler_GetLinkName(func)->name, "BEFORE SCHEDULING"); + scheduleinstructions(0); + if (copts.debuglisting) + pclistblocks_end_scheduler(); + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER INSTRUCTION SCHEDULING"); + } + + if (copts.peephole) { + if (copts.schedule_factor == 0 && copts.optimizationlevel > 1) + peepholemergeblocks(func, 0); + peepholeoptimizeforward(func); + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER PEEPHOLE FORWARD"); + } + + allocate_temporaries(); + colorinstructions(func); + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER REGISTER COLORING"); + + if (copts.optimizationlevel > 1 && !disable_optimizer) { + removecommonsubexpressions(func, 1); + if (removedcommonsubexpressions && copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER VALUE NUMBERING (POST COLORING)"); + } + + compute_frame_sizes(); + generate_prologue(prologue, has_varargs); + if (copts.profile) + exitprofiler(); + generate_epilogue(epilogue, 1); + + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER GENERATING EPILOGUE, PROLOGUE"); + + if (copts.peephole) { + if (copts.schedule_factor) { + peepholemergeblocks(func, 1); + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER MERGING EPILOGUE, PROLOGUE"); + } + peepholeoptimizepcode(func); + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER PEEPHOLE OPTIMIZATION"); + } + + if (copts.schedule_factor) { + if (copts.debuglisting) + pclistblocks_start_scheduler(CMangler_GetLinkName(func)->name, "BEFORE SCHEDULING"); + scheduleinstructions(1); + if (copts.debuglisting) + pclistblocks_end_scheduler(); + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "FINAL CODE AFTER INSTRUCTION SCHEDULING"); + } else { + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "FINAL CODE"); + } + + size = assemblefunction(func, NULL); + dumpswitchtables(func); + dumpcodelabels(func); + if (callOnModuleBind) + ObjGen_DeclareInitFunction(func); + + pic_base_pcodelabel = NULL; + pic_base_reg = 0; + if (copts.exceptions && requires_frame) + dumpexceptiontables(func, size); + + if (copts.report_heap_info > 0) + CodeGen_reportheapinfo(0, CMangler_GetLinkName(func)->name, "finished"); + + if (saveheaperror) + setheaperror(saveheaperror); +} + +enum { + reg3 = 3, + reg4 = 4 +}; + +void CodeGen_GenVDispatchThunk(Object *thunkobj, Object *obj, SInt32 a, SInt32 b, SInt32 c) { + Boolean save_debug; + Boolean save_peephole; + Boolean save_traceback; + char reg; + + save_debug = copts.filesyminfo; + save_peephole = copts.peephole; + save_traceback = copts.traceback; + + CodeGen_InitialSanityCheck(); + CError_ASSERT(2270, b == 0); + + initpcode(); + makepcblock(); + + if (a) { + reg = CMach_PassResultInHiddenArg(TYPE_FUNC(obj->type)->functype) ? reg4 : reg3; + + if (c >= 0) { + if (!FITS_IN_SHORT(c)) { + emitpcode(PC_ADDIS, 11, 0, 0, HIGH_PART(c)); + if (c) + emitpcode(PC_ADDI, 11, 11, 0, LOW_PART(c)); + } else { + emitpcode(PC_ADDI, 11, 0, 0, c); + } + emitpcode(PC_LWZX, 11, reg, 11); + emitpcode(PC_ADD, reg, reg, 11); + } + + if (!FITS_IN_SHORT(a)) { + emitpcode(PC_ADDIS, reg, reg, 0, HIGH_PART(a)); + if (a) + emitpcode(PC_ADDI, reg, reg, 0, LOW_PART(a)); + } else { + emitpcode(PC_ADDI, reg, reg, 0, a); + } + } + + emitpcode(PC_B, 0, obj); + + copts.filesyminfo = 0; + copts.peephole = 0; + copts.traceback = 0; + assemblefunction(thunkobj, NULL); + copts.filesyminfo = save_debug; + copts.peephole = save_peephole; + copts.traceback = save_traceback; +} + +void CodeGen_SetupRuntimeObjects(void) { + setupaddressing(); + dyld_stub_binding_helper = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + rt_cvt_fp2unsigned = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + rt_profile_entry = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + rt_profile_exit = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + rt_div2i = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + rt_div2u = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + rt_mod2i = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + rt_mod2u = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + rt_shr2i = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + rt_shr2u = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + rt_shl2i = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + rt_cvt_ull_dbl = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + rt_cvt_sll_dbl = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + rt_cvt_ull_flt = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + rt_cvt_sll_flt = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + rt_cvt_dbl_usll = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + Intrinsics_SetupRuntimeObjects(); +} + +Boolean CodeGen_ReInitRuntimeObjects(Boolean is_precompiler) { + dyld_stub_binding_helper->name = GetHashNameNodeExport("dyld_stub_binding_helper"); + dyld_stub_binding_helper->u.func.linkname = dyld_stub_binding_helper->name; + + rt_cvt_fp2unsigned->name = GetHashNameNodeExport("__cvt_fp2unsigned"); + + rt_profile_entry->name = GetHashNameNodeExport("mcount"); + rt_profile_entry->u.func.linkname = rt_profile_entry->name; + + rt_profile_exit->name = GetHashNameNodeExport("profile_exit"); + + rt_div2i->name = GetHashNameNodeExport("__div2i"); + rt_div2u->name = GetHashNameNodeExport("__div2u"); + rt_mod2i->name = GetHashNameNodeExport("__mod2i"); + rt_mod2u->name = GetHashNameNodeExport("__mod2u"); + rt_shr2i->name = GetHashNameNodeExport("__shr2i"); + rt_shr2u->name = GetHashNameNodeExport("__shr2u"); + rt_shl2i->name = GetHashNameNodeExport("__shl2i"); + + rt_cvt_ull_dbl->name = GetHashNameNodeExport("__cvt_ull_dbl"); + rt_cvt_sll_dbl->name = GetHashNameNodeExport("__cvt_sll_dbl"); + rt_cvt_ull_flt->name = GetHashNameNodeExport("__cvt_ull_flt"); + rt_cvt_sll_flt->name = GetHashNameNodeExport("__cvt_sll_flt"); + rt_cvt_dbl_usll->name = GetHashNameNodeExport("__cvt_dbl_usll"); + + CMach_ReInitRuntimeObjects(); + return Intrinsics_ReInitRuntimeObjects(is_precompiler); +} + +Boolean CodeGen_IsPublicRuntimeObject(Object *obj) { + return Intrinsics_IsPublicRuntimeObject(obj); +} + +void CodeGen_SOMStub(Object *a, Object *b, Object *c, SInt32 offset) { + Boolean save_debug; + Boolean save_peephole; + Boolean save_traceback; + Object *tmp; + Operand opnd; + + save_debug = copts.filesyminfo; + save_peephole = copts.peephole; + save_traceback = copts.traceback; + + CodeGen_InitialSanityCheck(); + memclrw(&opnd, sizeof(Operand)); + CError_ASSERT(2528, offset <= 0x7FFF); + + initpcode(); + makepcblock(); + + tmp = createIndirect(c, 1, 1); + if (tmp) { + opnd.optype = OpndType_Symbol; + opnd.object = tmp; + indirect(&opnd, NULL); + } else { + opnd.optype = OpndType_Symbol; + opnd.object = c; + } + + if (opnd.optype != OpndType_GPR) + Coerce_to_register(&opnd, TYPE(&void_ptr), 12); + + if (opnd.optype != OpndType_GPR) { + CError_FATAL(2562); + } else if (opnd.reg != 12) { + emitpcode(PC_MR, 12, opnd.reg); + } + + load_store_register(PC_LWZ, 12, 12, NULL, (short) offset); + emitpcode(PC_B, 0, b); + + copts.filesyminfo = 0; + copts.peephole = 0; + copts.traceback = 0; + assemblefunction(a, NULL); + copts.filesyminfo = save_debug; + copts.peephole = save_peephole; + copts.traceback = save_traceback; +} + +void CodeGen_ParseDeclSpec(HashNameNode *identifier, DeclInfo *declinfo) { + if (!strcmp(identifier->name, "private_extern")) { + declinfo->storageclass = TK_EXTERN; + declinfo->exportflags = EXPORT_FLAGS_INTERNAL; + } else { + CError_Error(CErrorStr176); + } +} + +static void CodeGen_EOLCheck(void) { + short t; + + if (plex() != TK_EOL) { + CPrep_Error(CErrorStr113); + do { + t = plex(); + } while (t != TK_EOL && t != 0); + } +} + +static void schedule_for(int what) { + CPrep_PushOption(OPT_OFFSET(scheduling), what); + if (copts.schedule_factor == 0) + CPrep_PushOption(OPT_OFFSET(schedule_factor), 2); +} + +static void pragma_scheduling(void) { + Boolean *flag; + int cpu; + + tk = plex(); + if (tk == TK_IDENTIFIER) { + flag = &copts.altivec_model; + if (!strcmp(tkidentifier->name, "vger")) { + schedule_for(10); + return; + } else if (!strcmp(tkidentifier->name, "altivec")) { + schedule_for(7); + return; + } else if (!strcmp(tkidentifier->name, "reset")) { + CPrep_PopOption(OPT_OFFSET(scheduling)); + CPrep_PopOption(OPT_OFFSET(schedule_factor)); + return; + } else if (!strcmp(tkidentifier->name, "off")) { + CPrep_PushOption(OPT_OFFSET(schedule_factor), 0); + return; + } else if (!strcmp(tkidentifier->name, "once")) { + CPrep_PushOption(OPT_OFFSET(schedule_factor), 1); + return; + } else if (!strcmp(tkidentifier->name, "twice")) { + CPrep_PushOption(OPT_OFFSET(schedule_factor), 2); + return; + } else if (!strcmp(tkidentifier->name, "on")) { + CPrep_PushOption(OPT_OFFSET(schedule_factor), 2); + return; + } else if (!*flag) { + if (!strcmp(tkidentifier->name, "603e")) { + schedule_for(5); + return; + } else if (!strcmp(tkidentifier->name, "604e")) { + schedule_for(6); + return; + } else if (!strcmp(tkidentifier->name, "PPC603e")) { + schedule_for(5); + return; + } else if (!strcmp(tkidentifier->name, "PPC604e")) { + schedule_for(6); + return; + } + } else { + PPCError_Error(PPCErrorStr115); + return; + } + CPrep_Error(CErrorStr186); + return; + } + + if (tk == TK_INTCONST) { + switch (CInt64_GetULong(&tkintconst)) { + case 601: + cpu = 1; + break; + case 603: + cpu = 2; + break; + case 604: + cpu = 3; + break; + case 750: + cpu = 4; + break; + case 7400: + cpu = 7; + break; + case 7450: + cpu = 10; + break; + case 8240: + case 8260: + cpu = 5; + break; + case 801: + case 821: + case 823: + case 850: + case 860: + cpu = 9; + break; + default: + CPrep_Error(CErrorStr186); + return; + } + schedule_for(cpu); + return; + } + + if (copts.warn_illpragma) + CPrep_Warning(CErrorStr186); +} + +static SInt32 CodeGen_ParseLongIntegerORonORoff(void) { + SInt32 result; + short t; + + result = 0; + t = plex(); + if (t == TK_INTCONST) { + if (!tkintconst.hi) + result = CInt64_GetULong(&tkintconst); + else + CPrep_Error(CErrorStr154); + CodeGen_EOLCheck(); + } else if (t == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "on")) { + CodeGen_EOLCheck(); + return 1; + } + if (!strcmp(tkidentifier->name, "off")) { + CodeGen_EOLCheck(); + return 0; + } + if (copts.warn_illpragma) + CPrep_Warning(CErrorStr186); + return 0; + } else { + if (copts.warn_illpragma) + CPrep_Warning(CErrorStr186); + } + + return result; +} + +void CodeGen_ParsePragma(HashNameNode *name) { + short t; + SInt32 value; + char *str; + NameSpace *nspace; + NameSpaceObjectList *list; + + if (!strcmp(name->name, "debuglisting")) { + copts.debuglisting = CodeGen_ParseLongIntegerORonORoff(); + return; + } + + if (!strcmp(name->name, "report_heap_info")) { + t = plex(); + if (t == TK_INTCONST) { + copts.report_heap_info = CInt64_GetULong(&tkintconst); + if (copts.report_heap_info < 0) { + copts.report_heap_info = 0; + CError_Error(CErrorStr186); + } + } else if (t == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "off")) { + copts.report_heap_info = 0; + } else if (!strcmp(tkidentifier->name, "on")) { + copts.report_heap_info = 1; + } else { + CError_Error(CErrorStr186); + return; + } + } else { + CError_Error(CErrorStr186); + } + CodeGen_EOLCheck(); + return; + } + + if (!strcmp(name->name, "scheduling")) { + pragma_scheduling(); + CodeGen_EOLCheck(); + return; + } + + if (!strcmp(name->name, "ppc_unroll_speculative")) { + if (plex() == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "off")) { + copts.unroll_speculative = 0; + } else if (!strcmp(tkidentifier->name, "on")) { + copts.unroll_speculative = 1; + } else { + CError_Error(CErrorStr186); + return; + } + } else { + CError_Error(CErrorStr186); + } + CodeGen_EOLCheck(); + return; + } + + if (!strcmp(name->name, "ppc_unroll_instructions_limit")) { + t = plex(); + if (t == TK_INTCONST) { + copts.unroll_instr_limit = CInt64_GetULong(&tkintconst); + if (copts.unroll_instr_limit < 0) { + copts.unroll_instr_limit = 0; + CError_Error(CErrorStr186); + } + } else if (t == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "off")) { + copts.unroll_instr_limit = 0; + } else if (!strcmp(tkidentifier->name, "on")) { + copts.unroll_instr_limit = 70; + } else { + CError_Error(CErrorStr186); + return; + } + } else { + CError_Error(CErrorStr186); + } + CodeGen_EOLCheck(); + return; + } + + if (!strcmp(name->name, "gen_fsel")) { + t = plex(); + if (t == TK_INTCONST) { + value = CInt64_GetULong(&tkintconst); + if (value < 0) { + copts.gen_fsel = 0; + CError_Error(CErrorStr186); + } else if (value > 255) { + copts.gen_fsel = 255; + CError_Error(CErrorStr186); + } else { + copts.gen_fsel = value; + } + } else if (t == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "off")) { + copts.gen_fsel = 0; + } else if (!strcmp(tkidentifier->name, "on")) { + copts.gen_fsel = 10; + } else if (!strcmp(tkidentifier->name, "always")) { + copts.gen_fsel = 255; + } else { + CError_Error(CErrorStr186); + return; + } + } else { + CError_Error(CErrorStr186); + } + CodeGen_EOLCheck(); + return; + } + + if (!strcmp(name->name, "ppc_unroll_factor_limit")) { + t = plex(); + if (t == TK_INTCONST) { + copts.unroll_factor_limit = CInt64_GetULong(&tkintconst); + if (copts.unroll_factor_limit < 0) { + copts.unroll_factor_limit = 0; + CError_Error(CErrorStr186); + } + } else if (t == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "off")) { + copts.unroll_factor_limit = 0; + } else if (!strcmp(tkidentifier->name, "on")) { + copts.unroll_factor_limit = 10; + } else { + CError_Error(CErrorStr186); + return; + } + } else { + CError_Error(CErrorStr186); + } + CodeGen_EOLCheck(); + return; + } + + if (!strcmp(name->name, "altivec_model")) { + if (plex() == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "off")) { + copts.altivec_model = 0; + } else if (!strcmp(tkidentifier->name, "on")) { + copts.altivec_model = 1; + } else { + CError_Error(CErrorStr186); + return; + } + } else { + CError_Error(CErrorStr186); + } + CodeGen_EOLCheck(); + return; + } + + if (!strcmp(name->name, "altivec_vrsave")) { + if (plex() == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "off")) { + CPrep_PushOption(OPT_OFFSET(altivec_vrsave), 0); + } else if (!strcmp(tkidentifier->name, "on")) { + CPrep_PushOption(OPT_OFFSET(altivec_vrsave), 1); + } else if (!strcmp(tkidentifier->name, "allon")) { + CPrep_PushOption(OPT_OFFSET(altivec_vrsave), 2); + } else if (!strcmp(tkidentifier->name, "reset")) { + CPrep_PopOption(OPT_OFFSET(altivec_vrsave)); + } else { + CError_Error(CErrorStr186); + return; + } + } else { + CError_Error(CErrorStr186); + } + CodeGen_EOLCheck(); + return; + } + + if (!strcmp(name->name, "function_align")) { + t = plex(); + if (t == TK_INTCONST) { + value = CInt64_GetULong(&tkintconst); + switch (value) { + case 4: + case 8: + case 16: + case 32: + case 64: + case 128: + CPrep_PushOption(OPT_OFFSET(function_align), value); + break; + default: + PPCError_Warning(PPCErrorStr161); + CodeGen_EOLCheck(); + return; + } + } else if (t == TK_IDENTIFIER && !strcmp(tkidentifier->name, "reset")) { + CPrep_PopOption(OPT_OFFSET(function_align)); + } else { + PPCError_Warning(PPCErrorStr161); + } + CodeGen_EOLCheck(); + return; + } + + if (!strcmp(name->name, "processor")) { + if (cscope_currentfunc) { + PPCError_Warning(PPCErrorStr156, "pragma processor"); + return; + } + t = plex(); + if (t == TK_INTCONST) { + switch (CInt64_GetULong(&tkintconst)) { + case 401: + copts.processor = 0; + break; + case 403: + copts.processor = 1; + break; + case 505: + copts.processor = 2; + break; + case 509: + copts.processor = 3; + break; + case 555: + copts.processor = 4; + break; + case 556: + copts.processor = 25; + break; + case 565: + copts.processor = 26; + break; + case 601: + copts.processor = 5; + break; + case 602: + copts.processor = 6; + break; + case 8240: + copts.processor = 18; + break; + case 8260: + copts.processor = 19; + break; + case 603: + copts.processor = 7; + break; + case 604: + copts.processor = 9; + break; + case 740: + copts.processor = 11; + break; + case 750: + copts.processor = 12; + break; + case 801: + copts.processor = 13; + break; + case 821: + copts.processor = 14; + break; + case 823: + copts.processor = 15; + break; + case 850: + copts.processor = 16; + break; + case 860: + copts.processor = 17; + break; + case 7400: + copts.processor = 21; + break; + default: + PPCError_Warning(PPCErrorStr208); + CodeGen_EOLCheck(); + return; + } + } else if (t == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "generic")) + copts.processor = 20; + else if (!strcmp(tkidentifier->name, "603e")) + copts.processor = 8; + else if (!strcmp(tkidentifier->name, "604e")) + copts.processor = 10; + else if (!strcmp(tkidentifier->name, "PPC603e")) + copts.processor = 8; + else if (!strcmp(tkidentifier->name, "PPC604e")) + copts.processor = 10; + else + PPCError_Warning(PPCErrorStr208); + } else { + PPCError_Warning(PPCErrorStr208); + } + + if ((str = CMach_GetCPU())) + CPrep_InsertSpecialMacro(&ppc_cpu, str); + + CodeGen_EOLCheck(); + return; + } + + if (!strcmp(name->name, "min_struct_alignment")) { + t = plex(); + if (t == TK_INTCONST) { + value = CInt64_GetULong(&tkintconst); + switch (value) { + case 4: + case 8: + case 16: + case 32: + case 64: + case 128: + CPrep_PushOption(OPT_OFFSET(min_struct_alignment), value); + break; + default: + PPCError_Warning(PPCErrorStr191); + CodeGen_EOLCheck(); + return; + } + } else if (t == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "reset")) + CPrep_PopOption(OPT_OFFSET(min_struct_alignment)); + else if (!strcmp(tkidentifier->name, "on")) + CPrep_PushOption(OPT_OFFSET(min_struct_alignment), 4); + else if (!strcmp(tkidentifier->name, "off")) + CPrep_PushOption(OPT_OFFSET(min_struct_alignment), 1); + } else { + PPCError_Warning(PPCErrorStr161); + } + + CodeGen_EOLCheck(); + return; + } + + if (!strcmp(name->name, "tvectors")) { + if (plex() == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "off")) { + no_descriptors = 1; + } else if (!strcmp(tkidentifier->name, "on")) { + no_descriptors = 0; + } else { + CError_Error(CErrorStr186); + return; + } + } else { + CError_Error(CErrorStr186); + } + + CodeGen_EOLCheck(); + return; + } + + if (!strcmp(name->name, "dynamic")) { + if (plex() == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "off")) { + copts.codegen_dynamic = 0; + copts.codegen_pic = 0; + } else if (!strcmp(tkidentifier->name, "on")) { + copts.codegen_dynamic = 1; + } else { + CError_Error(CErrorStr186); + return; + } + } else { + CError_Error(CErrorStr186); + } + + CodeGen_EOLCheck(); + return; + } + + if (!strcmp(name->name, "pic")) { + if (plex() == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "off")) { + copts.codegen_pic = 0; + } else if (!strcmp(tkidentifier->name, "on")) { + copts.codegen_pic = 1; + if (!copts.codegen_dynamic) { + PPCError_Error(PPCErrorStr189); + copts.codegen_pic = 0; + } + } else { + CError_Error(CErrorStr186); + return; + } + } else { + CError_Error(CErrorStr186); + } + + CodeGen_EOLCheck(); + return; + } + + if (!strcmp(name->name, "implicit_templates")) { + if (plex() == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "off")) { + copts.no_implicit_templates = 1; + } else if (!strcmp(tkidentifier->name, "on")) { + copts.no_implicit_templates = 0; + } else { + CError_Error(CErrorStr186); + return; + } + } else { + CError_Error(CErrorStr186); + } + + CodeGen_EOLCheck(); + return; + } + + if (!strcmp(name->name, "common")) { + if (plex() == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "off")) { + copts.no_common = 1; + } else if (!strcmp(tkidentifier->name, "on")) { + copts.no_common = 0; + } else { + CError_Error(CErrorStr186); + return; + } + } else { + CError_Error(CErrorStr186); + } + + CodeGen_EOLCheck(); + return; + } + + if (!strcmp(name->name, "CALL_ON_MODULE_BIND")) { + if (plex() == TK_IDENTIFIER) { + for (nspace = cscope_current; nspace; nspace = nspace->parent) { + list = CScope_GetLocalObject(nspace, tkidentifier); + if (list && list->object->otype == OT_OBJECT && OBJECT(list->object)->datatype == DFUNC) { + ObjGen_DeclareInitFunction(OBJECT(list->object)); + break; + } + } + } else { + CError_Error(CErrorStr186); + } + + CodeGen_EOLCheck(); + return; + } + + if (copts.warn_illpragma) + CPrep_Warning(CErrorStr186); + + if (plex() != TK_EOL) { + do { + t = plex(); + } while (t != TK_EOL && t != 0); + } +} + +void CodeGen_UpdateObject(Object *object) { + if (object->datatype == DDATA && object->section == SECT_DEFAULT && object == rt_ptmf_null) + object->sclass = TK_EXTERN; +} + +void CodeGen_UpdateBackEndOptions(void) { + copts.globaloptimizer = 1; +} + +SInt32 CodeGen_objc_method_self_offset(ObjCMethod *meth) { + SInt32 size; + + if (!meth->return_type) { + size = 4; + } else if ( + IS_TYPE_ARRAY(meth->return_type) || + IS_TYPE_NONVECTOR_STRUCT(meth->return_type) || + IS_TYPE_CLASS(meth->return_type) || + IS_TYPE_12BYTES_MEMBERPOINTER(meth->return_type) + ) + { + size = 8; + } else { + size = meth->return_type->size; + } + + if (size == 0) + size = 1; + + return (size + 3) & ~3; +} + +SInt32 CodeGen_objc_method_sel_offset(ObjCMethod *meth) { + return (CodeGen_objc_method_self_offset(meth) + 7) & ~3; +} + +SInt32 CodeGen_objc_method_arg_offset(ObjCMethod *meth, ObjCMethodArg *arg) { + SInt32 pos; + ObjCMethodArg *scan; + + pos = CodeGen_objc_method_sel_offset(meth) + 4; + for (scan = meth->selector_args; scan; scan = scan->next) { + if (scan == arg) + return pos; + + if (scan->type == NULL) + pos += 4; + else + pos += scan->type->size; + + pos = (pos + 3) & ~3; + } + + return 0; +} + +SInt32 CodeGen_objc_method_args_size(ObjCMethod *meth) { + SInt32 size; + ObjCMethodArg *scan; + + size = CodeGen_objc_method_self_offset(meth); + for (scan = meth->selector_args; scan; scan = scan->next) { + if (scan->next == NULL && scan->type == NULL) + return size; + + size = (size + 3) & ~3; + if (scan->type == NULL) + size += 4; + else + size += scan->type->size; + } + + return size; +} + +ENode *CodeGen_HandleIntrinsicCall(Object *func, ENodeList *arg_exprs) { + return Intrinsics_HandleIntrinsicCall(func, arg_exprs); +} + +ENode *CodeGen_HandleTypeCast(ENode *expr, Type *type, UInt32 qual) { + short flags; + + if (copts.altivec_model) { + flags = qual & ENODE_FLAG_QUALS; + if (IS_TYPE_STRUCT(type) && IS_TYPE_STRUCT(expr->rtype) && expr->flags == flags) { + switch (TYPE_STRUCT(type)->stype) { + case STRUCT_VECTOR_UCHAR: + case STRUCT_VECTOR_SCHAR: + case STRUCT_VECTOR_BCHAR: + case STRUCT_VECTOR_USHORT: + case STRUCT_VECTOR_SSHORT: + case STRUCT_VECTOR_BSHORT: + case STRUCT_VECTOR_UINT: + case STRUCT_VECTOR_SINT: + case STRUCT_VECTOR_BINT: + case STRUCT_VECTOR_FLOAT: + case STRUCT_VECTOR_PIXEL: + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = type; + expr->flags = flags; + return expr; + } + } + } + + return NULL; +} + +short CodeGen_AssignCheck(const ENode *expr, const Type *type, Boolean flag1, Boolean flag2) { + short result; + const Type *exprtype = expr->rtype; + + if ( + copts.altivec_model && + IS_TYPE_VECTOR(type) && + IS_TYPE_VECTOR(exprtype) && + TYPE_STRUCT(type)->stype == TYPE_STRUCT(exprtype)->stype + ) + result = CheckResult3; + else + result = CheckResult0; + return result; +} + +Boolean CodeGen_CollapseVectorExpression(ENode *expr, MWVector128 *vec, Type *type) { + // this function is a mess and needs lots of fixing + Boolean result; + //int count; + int i; + ENode *escan; + + result = 0; + for (i = 0; i < 4; i++) + vec->ul[i] = 0; + + if (ENODE_IS(expr, ECOMMA)) { + i = 0; + escan = expr; + while (ENODE_IS(escan, ECOMMA)) { + i++; + escan = escan->data.diadic.left; + } + switch (TYPE_STRUCT(type)->stype) { + case STRUCT_VECTOR_UCHAR: + case STRUCT_VECTOR_SCHAR: + case STRUCT_VECTOR_BCHAR: + if (i < 15) { + PPCError_Error(PPCErrorStr110, type, 0); + } else if (i > 15) { + PPCError_Error(PPCErrorStr111, type, 0); + } else { + escan = expr; + i = 15; + while (ENODE_IS(escan, ECOMMA)) { + CInt64 v; + expr = escan->data.diadic.right; + v = expr->data.intval; + if (!ENODE_IS(expr, EINTCONST)) { + PPCError_Error(PPCErrorStr112); + break; + } + + if (copts.pedantic) { + if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UCHAR) { + if (!CInt64_IsInURange(v, 1)) + PPCError_Warning(PPCErrorStr113, type, 0); + } else { + if (!CInt64_IsInRange(v, 1)) + PPCError_Warning(PPCErrorStr113, type, 0); + } + } + + vec->uc[i--] = (UInt8) v.lo; + escan = escan->data.diadic.left; + } + + if (ENODE_IS(escan, EINTCONST)) { + CInt64 v = escan->data.intval; + if (copts.pedantic) { + if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UCHAR) { + if (!CInt64_IsInURange(v, 1)) + PPCError_Warning(PPCErrorStr113, type, 0); + } else { + if (!CInt64_IsInRange(v, 1)) + PPCError_Warning(PPCErrorStr113, type, 0); + } + } + vec->uc[0] = (UInt8) v.lo; + } else { + PPCError_Error(PPCErrorStr112); + break; + } + result = 1; + } + break; + + case STRUCT_VECTOR_USHORT: + case STRUCT_VECTOR_SSHORT: + case STRUCT_VECTOR_BSHORT: + case STRUCT_VECTOR_PIXEL: + if (i < 7) { + PPCError_Error(PPCErrorStr110, type, 0); + } else if (i > 7) { + PPCError_Error(PPCErrorStr111, type, 0); + } else { + escan = expr; + i = 7; + while (ENODE_IS(escan, ECOMMA)) { + ENode *e = escan->data.diadic.right; + CInt64 v = e->data.intval; + if (!ENODE_IS(e, EINTCONST)) { + PPCError_Error(PPCErrorStr112); + break; + } + + if (copts.pedantic) { + if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_USHORT || TYPE_STRUCT(type)->stype == STRUCT_VECTOR_PIXEL) { + if (!CInt64_IsInURange(v, 2)) + PPCError_Warning(PPCErrorStr113, type, 0); + } else { + if (!CInt64_IsInRange(v, 2)) + PPCError_Warning(PPCErrorStr113, type, 0); + } + } + + vec->us[i--] = (UInt16) e->data.intval.lo; + escan = escan->data.diadic.left; + } + + if (ENODE_IS(escan, EINTCONST)) { + CInt64 v = escan->data.intval; + if (copts.pedantic) { + if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_USHORT || TYPE_STRUCT(type)->stype == STRUCT_VECTOR_PIXEL) { + if (!CInt64_IsInURange(v, 2)) + PPCError_Warning(PPCErrorStr113, type, 0); + } else { + if (!CInt64_IsInRange(v, 2)) + PPCError_Warning(PPCErrorStr113, type, 0); + } + } + vec->us[0] = (UInt16) v.lo; + } else { + PPCError_Error(PPCErrorStr112); + break; + } + result = 1; + } + break; + + case STRUCT_VECTOR_UINT: + case STRUCT_VECTOR_SINT: + case STRUCT_VECTOR_BINT: + if (i < 3) { + PPCError_Error(PPCErrorStr110, type, 0); + } else if (i > 3) { + PPCError_Error(PPCErrorStr111, type, 0); + } else { + escan = expr; + i = 3; + while (ENODE_IS(escan, ECOMMA)) { + CInt64 v; + expr = escan->data.diadic.right; + v = expr->data.intval; + if (!ENODE_IS(expr, EINTCONST)) { + PPCError_Error(PPCErrorStr112); + break; + } + + if (copts.pedantic) { + if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UINT) { + if (!CInt64_IsInURange(v, 4)) + PPCError_Warning(PPCErrorStr113, type, 0); + } else { + if (!CInt64_IsInRange(v, 4)) + PPCError_Warning(PPCErrorStr113, type, 0); + } + } + + vec->ul[i--] = expr->data.intval.lo; + escan = escan->data.diadic.left; + } + + if (ENODE_IS(escan, EINTCONST)) { + CInt64 v = escan->data.intval; + if (copts.pedantic) { + if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UINT) { + if (!CInt64_IsInURange(v, 4)) + PPCError_Warning(PPCErrorStr113, type, 0); + } else { + if (!CInt64_IsInRange(v, 4)) + PPCError_Warning(PPCErrorStr113, type, 0); + } + } + vec->ul[0] = v.lo; + } else { + PPCError_Error(PPCErrorStr112); + break; + } + result = 1; + } + break; + + case STRUCT_VECTOR_FLOAT: + if (i < 3) { + PPCError_Error(PPCErrorStr110, type, 0); + } else if (i > 3) { + PPCError_Error(PPCErrorStr111, type, 0); + } else { + Float fv; + escan = expr; + i = 3; + while (ENODE_IS(escan, ECOMMA)) { + expr = escan->data.diadic.right; + if (ENODE_IS(expr, EFLOATCONST)) { + fv = expr->data.floatval; + } else if (ENODE_IS(escan->data.diadic.right, EINTCONST)) { + fv = CMach_CalcFloatConvertFromInt(expr->rtype, + expr->data.intval); + } else { + PPCError_Error(PPCErrorStr112); + break; + } + + CMach_InitFloatMem(TYPE(&stfloat), fv, &vec->f[i]); + i--; + escan = escan->data.diadic.left; + } + + if (ENODE_IS(escan, EFLOATCONST)) { + fv = escan->data.floatval; + } else if (ENODE_IS(escan, EINTCONST)) { + fv = CMach_CalcFloatConvertFromInt(escan->rtype, escan->data.intval); + } else { + PPCError_Error(PPCErrorStr112); + break; + } + + CMach_InitFloatMem(TYPE(&stfloat), fv, &vec->f[0]); + result = 1; + } + break; + } + } else if (ENODE_IS(expr, EINTCONST)) { + int i = 0; + switch (TYPE_STRUCT(type)->stype) { + case STRUCT_VECTOR_UCHAR: + case STRUCT_VECTOR_SCHAR: + case STRUCT_VECTOR_BCHAR: + { + CInt64 v = expr->data.intval; + if (copts.pedantic) { + if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UCHAR) { + if (!CInt64_IsInURange(v, 1)) + PPCError_Warning(PPCErrorStr113, type, 0); + } else { + if (!CInt64_IsInRange(v, 1)) + PPCError_Warning(PPCErrorStr113, type, 0); + } + } + while (i < 16) + vec->uc[i++] = (UInt8) v.lo; + result = 1; + break; + } + case STRUCT_VECTOR_USHORT: + case STRUCT_VECTOR_SSHORT: + case STRUCT_VECTOR_BSHORT: + case STRUCT_VECTOR_PIXEL: + { + CInt64 v = expr->data.intval; + if (copts.pedantic) { + if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_USHORT || TYPE_STRUCT(type)->stype == STRUCT_VECTOR_PIXEL) { + if (!CInt64_IsInURange(v, 2)) + PPCError_Warning(PPCErrorStr113, type, 0); + } else { + if (!CInt64_IsInRange(v, 2)) + PPCError_Warning(PPCErrorStr113, type, 0); + } + } + while (i < 8) + vec->us[i++] = (UInt16) v.lo; + result = 1; + break; + } + case STRUCT_VECTOR_UINT: + case STRUCT_VECTOR_SINT: + case STRUCT_VECTOR_BINT: + { + CInt64 v = expr->data.intval; + if (copts.pedantic) { + if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UINT) { + if (!CInt64_IsInURange(v, 4)) + PPCError_Warning(PPCErrorStr113, type, 0); + } else { + if (!CInt64_IsInRange(v, 4)) + PPCError_Warning(PPCErrorStr113, type, 0); + } + } + while (i < 4) + vec->ul[i++] = v.lo; + result = 1; + break; + } + case STRUCT_VECTOR_FLOAT: + { + Float fv; + if (!CInt64_IsInRange(expr->data.intval, 4)) { + PPCError_Error(PPCErrorStr112); + break; + } + fv = CMach_CalcFloatConvertFromInt(expr->rtype, expr->data.intval); + for (; i < 4; i++) + CMach_InitFloatMem(TYPE(&stfloat), fv, &vec->f[i]); + result = 1; + break; + } + default: + PPCError_Error(PPCErrorStr112); + } + } else if (ENODE_IS(expr, EFLOATCONST)) { + switch (TYPE_STRUCT(type)->stype) { + default: + PPCError_Error(PPCErrorStr112); + break; + case STRUCT_VECTOR_FLOAT: + { + Float fv; + i = 0; + fv = expr->data.floatval; + CMach_InitFloatMem(TYPE(&stfloat), fv, &vec->f[0]); + while (i < 4) + CMach_InitFloatMem(TYPE(&stfloat), fv, &vec->f[i++]); + result = 1; + break; + } + } + } else if (ENODE_IS2(expr, EINDIRECT, EFUNCCALL)) { + if (!IS_TYPE_STRUCT(expr->rtype)) + PPCError_Error(PPCErrorStr112); + } else if (!ENODE_IS(expr, EVECTOR128CONST)) { + PPCError_Error(PPCErrorStr112); + } + + return result; +} + +void CodeGen_InsertSpecialMacros(void) { + char *str; + + CPrep_InsertSpecialMacro(&vecM, "__VEC__"); + CPrep_InsertSpecialMacro(&altivecM, "__ALTIVEC__"); + CPrep_InsertSpecialMacro(&powcM, "powerc"); + CPrep_InsertSpecialMacro(&__powcM, "__powerc"); + CPrep_InsertSpecialMacro(&hostM, "__POWERPC__"); + CPrep_InsertSpecialMacro(&_ppc_M, "__ppc__"); + + CPrep_InsertSpecialMacro(&bendM, "__BIG_ENDIAN__"); + + if ((str = CMach_GetCPU())) + CPrep_InsertSpecialMacro(&ppc_cpu, str); + + CPrep_InsertSpecialMacro(&profM, "__profile__"); + CPrep_InsertSpecialMacro(&longI, "__fourbyteints__"); + CPrep_InsertSpecialMacro(&IEEED, "__IEEEdoubles__"); + CPrep_InsertSpecialMacro(&macM2, "__MACOS__"); + CPrep_InsertSpecialMacro(&appleM, "__APPLE__"); + CPrep_InsertSpecialMacro(&_machM, "__MACH__"); + CPrep_InsertSpecialMacro(&archM, "__ARCHITECTURE__"); + + if (copts.optimizationlevel > 0) + CPrep_InsertSpecialMacro(&optM, "__OPTIMIZE__"); + + if (copts.codegen_dynamic) + CPrep_InsertSpecialMacro(&dynM, "__DYNAMIC__"); + if (!copts.codegen_dynamic) + CPrep_InsertSpecialMacro(&dynM, "__STATIC__"); + + if (copts.oldalignment && copts.structalignment == AlignMode2_PPC) + CPrep_InsertSpecialMacro(&alignM, "__NATURAL_ALIGNMENT__"); + + if (!copts.ANSIstrict) + CPrep_InsertSpecialMacro(&ppcM, "ppc"); +} + +char *CodeGen_ExpandSpecialMacro(Macro *macro) { + if (macro == &vecM) return "10205"; + if (macro == &altivecM) return "100000000"; + if (macro == &powcM) return "1"; + if (macro == &__powcM) return "1"; + if (macro == &hostM) return "1"; + if (macro == &bendM) return "1"; + if (macro == &_ppc_M) return "1"; + if (CMach_GetCPU() && macro == &ppc_cpu) return "1"; + if (macro == &profM) return copts.profile ? "1" : "0"; + if (macro == &longI) return "1"; + if (macro == &IEEED) return "1"; + if (macro == &macM2) return "1"; + if (macro == &appleM) return "1"; + if (macro == &alignM) return "1"; + + if (macro == &optM) { + switch (copts.optimizationlevel) { + case 1: return "1"; + case 2: return "2"; + case 3: return "3"; + case 4: return "4"; + case 0: return "0"; + default: return "9"; + } + } + + if (macro == &_machM) return "1"; + if (macro == &archM) return "ppc"; + if (macro == &dynM) return "1"; + if (!copts.ANSIstrict && macro == &ppcM) return "1"; + if (macro == &_ppc_M) return "1"; + + CError_FATAL(4801); + return "0"; +} + +void CodeGen_reportheapinfo(Boolean release_flag, char *name, char *text) { + HeapInfo o; + HeapInfo all; + + CTool_GetHeapInfo(&o, 3); + CTool_GetHeapInfo(&all, 5); + + if (release_flag) + releaseoheap(); + + PPCError_Message( + "%n:%u HEAP STATUS\n" + " optimizer: %i blocks, used: %i, free: %i, total: %i, largest free: %i\n" + " all: %i blocks, used: %i, free: %i, total: %i, largest free: %i", + name, text, + o.blocks, o.total_size - o.total_free, o.total_free, o.total_size, o.largest_free_block, + all.blocks, all.total_size - all.total_free, all.total_free, all.total_size, all.largest_free_block + ); +} + +static void CodeGen_heaperror(void) { + CodeGen_reportheapinfo(1, "?", "out of memory"); + if (saveheaperror) { + setheaperror(saveheaperror); + saveheaperror(); + } +} + +void CodeGen_InitialSanityCheck(void) { +} diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Exceptions.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Exceptions.c new file mode 100644 index 0000000..14627cf --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Exceptions.c @@ -0,0 +1,857 @@ +#include "compiler/Exceptions.h" +#include "compiler/CError.h" +#include "compiler/CException.h" +#include "compiler/CInit.h" +#include "compiler/CFunc.h" +#include "compiler/CParser.h" +#include "compiler/CompilerTools.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/PCode.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/objects.h" + +static PCAction *pc_actions; +static PCAction *last_pc_action; +EANode *DAG[EAT_NACTIONS]; +static GList exceptmodule; +static OLinkList *except_refs; +static OLinkList *last_except_ref; + +static EANode *makeEAnode(ExceptionAction *ea) { + EANode *prev; + EANode *node; + + for (node = DAG[ea->type]; node; node = node->dagListNext) { + if (node->action == ea) + return node; + } + + if (ea->prev) + prev = makeEAnode(ea->prev); + else + prev = NULL; + + for (node = DAG[ea->type]; node; node = node->dagListNext) { + if (node->prev == prev && CExcept_ActionCompare(node->action, ea)) + return node; + } + + node = lalloc(sizeof(EANode)); + node->prev = prev; + node->action = ea; + node->count = 0; + node->xE = 0; + + node->dagListNext = DAG[ea->type]; + DAG[ea->type] = node; + + if (prev) + prev->count++; + return node; +} + +static void addrelocation(Object *obj, SInt32 offset) { + OLinkList *ref; + + ref = lalloc(sizeof(OLinkList)); + ref->next = NULL; + ref->obj = obj; + ref->offset = offset; + ref->somevalue = 0; + if (except_refs) + last_except_ref->next = ref; + else + except_refs = ref; + last_except_ref = ref; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct AABC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt32 d; +} AABC; + +typedef struct AACC { + UInt8 a; + UInt8 b; + UInt32 c; + UInt32 d; +} AACC; + +typedef struct AABBC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt16 d; + UInt32 e; +} AABBC; + +typedef struct AABCC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt32 d; + UInt32 e; +} AABCC; + +typedef struct AACCC { + UInt8 a; + UInt8 b; + UInt32 c; + UInt32 d; + UInt32 e; +} AACCC; + +typedef struct AABBBC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt16 d; + UInt16 e; + UInt32 f; +} AABBBC; + +typedef struct AABBCC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt16 d; + UInt32 e; + UInt32 f; +} AABBCC; + +typedef struct AACCCC { + UInt8 a; + UInt8 b; + UInt32 c; + UInt32 d; + UInt32 e; + UInt32 f; +} AACCCC; + +typedef struct AABCCCC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt32 d; + UInt32 e; + UInt32 f; + UInt32 g; +} AABCCCC; + +typedef struct AACCCCC { + UInt8 a; + UInt8 b; + UInt32 c; + UInt32 d; + UInt32 e; + UInt32 f; + UInt32 g; +} AACCCCC; + +typedef struct AAB { + UInt8 a; + UInt8 b; + UInt16 c; +} AAB; + +typedef struct AAC { + UInt8 a; + UInt8 b; + UInt32 c; +} AAC; + +typedef struct AA { + UInt8 a; + UInt8 b; +} AA; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void allocateactioninfo(EANode *node) { + ExceptionAction *ea; + SInt32 offset; + UInt32 flag26; + int reg; + int reg2; + + while (node && (node->xE == 0 || node->prev == NULL)) { + offset = exceptmodule.size; + if (node->xE == 0) + node->xE = offset; + + flag26 = node->prev ? 0 : 0x80; + + ea = node->action; + + switch (ea->type) { + case EAT_NOP: + CError_FATAL(146); + break; + case EAT_DESTROYLOCAL: { + if (local_is_16bit_offset(ea->data.destroy_local.local)) { + AABC e; + e.a = flag26 | 2; + e.b = 0; + e.c = CTool_EndianConvertWord16(local_offset_16(ea->data.destroy_local.local)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local.dtor, offset + 4); + } else { + AACC e; + e.a = flag26 | 0x11; + e.b = 0; + e.c = CTool_EndianConvertWord32(local_offset_32(ea->data.destroy_local.local)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local.dtor, offset + 6); + } + break; + } + case EAT_DESTROYLOCALCOND: { + reg = OBJECT_REG(ea->data.destroy_local_cond.cond); + if ( + (reg || local_is_16bit_offset(ea->data.destroy_local_cond.cond)) && + local_is_16bit_offset(ea->data.destroy_local_cond.local) + ) + { + AABBC e; + e.a = flag26 | 3; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_local_cond.cond)); + e.d = CTool_EndianConvertWord16(local_offset_16(ea->data.destroy_local_cond.local)); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_cond.dtor, offset + 6); + } else { + AACCC e; + e.a = flag26 | 0x12; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_local_cond.cond)); + e.d = CTool_EndianConvertWord32(local_offset_32(ea->data.destroy_local_cond.local)); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_cond.dtor, offset + 10); + } + break; + } + case EAT_DESTROYLOCALOFFSET: { + if (local_is_16bit_offset(ea->data.destroy_local_offset.local)) { + AABC e; + e.a = flag26 | 2; + e.b = 0; + e.c = CTool_EndianConvertWord16(ea->data.destroy_local_offset.offset + local_offset_16(ea->data.destroy_local_offset.local)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_offset.dtor, offset + 4); + } else { + AACC e; + e.a = flag26 | 0x11; + e.b = 0; + e.c = CTool_EndianConvertWord32(ea->data.destroy_local_offset.offset + local_offset_32(ea->data.destroy_local_offset.local)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_offset.dtor, offset + 6); + } + break; + } + case EAT_DESTROYLOCALPOINTER: { + reg = OBJECT_REG(ea->data.destroy_local_pointer.pointer); + if (reg || local_is_16bit_offset(ea->data.destroy_local_pointer.pointer)) { + AABC e; + e.a = flag26 | 4; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_local_pointer.pointer)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_pointer.dtor, offset + 4); + } else { + AACC e; + e.a = flag26 | 0x13; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_local_pointer.pointer)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_pointer.dtor, offset + 6); + } + break; + } + case EAT_DESTROYLOCALARRAY: { + if (local_is_16bit_offset(ea->data.destroy_local_array.localarray)) { + AABBBC e; + e.a = flag26 | 5; + e.b = 0; + e.c = CTool_EndianConvertWord16(local_offset_16(ea->data.destroy_local_array.localarray)); + e.d = CTool_EndianConvertWord16(ea->data.destroy_local_array.elements); + e.e = CTool_EndianConvertWord16(ea->data.destroy_local_array.element_size); + e.f = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_array.dtor, offset + 8); + } else { + AACCCC e; + e.a = flag26 | 0x14; + e.b = 0; + e.c = CTool_EndianConvertWord32(local_offset_32(ea->data.destroy_local_array.localarray)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_local_array.elements); + e.e = CTool_EndianConvertWord32(ea->data.destroy_local_array.element_size); + e.f = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_array.dtor, offset + 14); + } + break; + } + case EAT_DESTROYMEMBER: { + reg = OBJECT_REG(ea->data.destroy_member.objectptr); + if (reg || local_is_16bit_offset(ea->data.destroy_member.objectptr)) { + AABCC e; + e.a = flag26 | 7; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member.dtor, offset + 8); + } else { + AACCC e; + e.a = flag26 | 0x16; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member.dtor, offset + 10); + } + break; + } + case EAT_DESTROYBASE: { + reg = OBJECT_REG(ea->data.destroy_member.objectptr); + if (reg || local_is_16bit_offset(ea->data.destroy_member.objectptr)) { + AABCC e; + e.a = flag26 | 6; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member.dtor, offset + 8); + } else { + AACCC e; + e.a = flag26 | 0x15; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member.dtor, offset + 10); + } + break; + } + case EAT_DESTROYMEMBERCOND: { + reg = OBJECT_REG(ea->data.destroy_member_cond.cond); + reg2 = OBJECT_REG(ea->data.destroy_member_cond.objectptr); + if ( + (reg || local_is_16bit_offset(ea->data.destroy_member_cond.cond)) && + (reg2 || local_is_16bit_offset(ea->data.destroy_member_cond.objectptr)) + ) + { + AABBCC e; + e.a = flag26 | 8; + e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6); + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member_cond.cond)); + e.d = CTool_EndianConvertWord16(reg2 ? reg2 : local_offset_16(ea->data.destroy_member_cond.objectptr)); + e.e = CTool_EndianConvertWord32(ea->data.destroy_member_cond.offset); + e.f = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member_cond.dtor, offset + 10); + } else { + AACCCC e; + e.a = flag26 | 0x17; + e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6); + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member_cond.cond)); + e.d = CTool_EndianConvertWord32(reg2 ? reg2 : local_offset_32(ea->data.destroy_member_cond.objectptr)); + e.e = CTool_EndianConvertWord32(ea->data.destroy_member_cond.offset); + e.f = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member_cond.dtor, offset + 14); + } + break; + } + case EAT_DESTROYMEMBERARRAY: { + reg = OBJECT_REG(ea->data.destroy_member_array.objectptr); + if (reg || local_is_16bit_offset(ea->data.destroy_member_array.objectptr)) { + AABCCCC e; + e.a = flag26 | 9; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member_array.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member_array.offset); + e.e = CTool_EndianConvertWord32(ea->data.destroy_member_array.elements); + e.f = CTool_EndianConvertWord32(ea->data.destroy_member_array.element_size); + e.g = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member_array.dtor, offset + 16); + } else { + AACCCCC e; + e.a = flag26 | 0x18; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member_array.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member_array.offset); + e.e = CTool_EndianConvertWord32(ea->data.destroy_member_array.elements); + e.f = CTool_EndianConvertWord32(ea->data.destroy_member_array.element_size); + e.g = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member_array.dtor, offset + 18); + } + break; + } + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: { + reg = OBJECT_REG(ea->data.delete_pointer.pointerobject); + if (reg || local_is_16bit_offset(ea->data.delete_pointer.pointerobject)) { + AABC e; + e.a = flag26 | 0xA; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.delete_pointer.pointerobject)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.delete_pointer.deletefunc, offset + 4); + } else { + AACC e; + e.a = flag26 | 0x19; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.delete_pointer.pointerobject)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.delete_pointer.deletefunc, offset + 6); + } + break; + } + case EAT_DELETEPOINTERCOND: { + reg = OBJECT_REG(ea->data.delete_pointer_cond.cond); + reg2 = OBJECT_REG(ea->data.delete_pointer_cond.pointerobject); + if ( + (reg || local_is_16bit_offset(ea->data.delete_pointer_cond.cond)) && + (reg2 || local_is_16bit_offset(ea->data.delete_pointer_cond.pointerobject)) + ) + { + AABBC e; + e.a = flag26 | 0xB; + e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6); + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.delete_pointer_cond.cond)); + e.d = CTool_EndianConvertWord16(reg2 ? reg2 : local_offset_16(ea->data.delete_pointer_cond.pointerobject)); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.delete_pointer_cond.deletefunc, offset + 6); + } else { + AACCC e; + e.a = flag26 | 0x1A; + e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6); + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.delete_pointer_cond.cond)); + e.d = CTool_EndianConvertWord32(reg2 ? reg2 : local_offset_32(ea->data.delete_pointer_cond.pointerobject)); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.delete_pointer_cond.deletefunc, offset + 10); + } + break; + } + case EAT_CATCHBLOCK: { + AACCC e; + e.a = flag26 | 0x10; + e.b = 0; + e.c = 0; + if (ea->data.catch_block.catch_label->pclabel) + e.d = CTool_EndianConvertWord32(ea->data.catch_block.catch_label->pclabel->block->codeOffset); + else + e.d = 0; + e.e = CTool_EndianConvertWord32(local_offset_16(ea->data.catch_block.catch_info_object)); + AppendGListData(&exceptmodule, &e, sizeof(e)); + if (ea->data.catch_block.catch_typeid) + addrelocation(ea->data.catch_block.catch_typeid, offset + 2); + break; + } + case EAT_ACTIVECATCHBLOCK: { + if (local_is_16bit_offset(ea->data.active_catch_block.catch_info_object)) { + AAB e; + e.a = flag26 | 0xD; + e.b = 0; + e.c = CTool_EndianConvertWord16(local_offset_16(ea->data.active_catch_block.catch_info_object)); + AppendGListData(&exceptmodule, &e, sizeof(e)); + } else { + AAC e; + e.a = flag26 | 0x1B; + e.b = 0; + e.c = CTool_EndianConvertWord32(local_offset_32(ea->data.active_catch_block.catch_info_object)); + AppendGListData(&exceptmodule, &e, sizeof(e)); + } + break; + } + case EAT_SPECIFICATION: { + AABCC e; + int i; + + e.a = flag26 | 0xF; + e.b = 0; + e.c = CTool_EndianConvertWord16(ea->data.specification.unexp_ids); + if (ea->data.specification.unexp_label->pclabel) + e.d = CTool_EndianConvertWord32(ea->data.specification.unexp_label->pclabel->block->codeOffset); + e.e = CTool_EndianConvertWord32(local_offset_16(ea->data.specification.unexp_info_object)); + AppendGListData(&exceptmodule, &e, sizeof(e)); + + for (i = 0; i < ea->data.specification.unexp_ids; i++) { + addrelocation(ea->data.specification.unexp_id[i], 12 + i * 4 + offset); + AppendGListLong(&exceptmodule, 0); + } + break; + } + case EAT_TERMINATE: { + AA e; + e.a = flag26 | 0xE; + e.b = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + break; + } + default: + CError_FATAL(671); + } + + node = node->prev; + } + + if (node) { + AAB e; + e.a = 1; + e.b = 0; + e.c = CTool_EndianConvertWord16(node->xE); + AppendGListData(&exceptmodule, &e, sizeof(e)); + } +} + +static UInt32 findPC(PCode *instr) { + UInt32 pc = instr->block->codeOffset; + instr = instr->prevPCode; + while (instr) { + instr = instr->prevPCode; + pc += 4; + } + CError_ASSERT(704, FITS_IN_USHORT(pc)); + return pc; +} + +static UInt32 findPC_long(PCode *instr) { + UInt32 pc = instr->block->codeOffset; + instr = instr->prevPCode; + while (instr) { + instr = instr->prevPCode; + pc += 4; + } + return pc; +} + +void initializeexceptiontables(void) { + int i; + + for (i = 0; i < EAT_NACTIONS; i++) + DAG[i] = NULL; + + pc_actions = last_pc_action = NULL; + except_refs = last_except_ref = NULL; +} + +int countexceptionactionregisters(ExceptionAction *actions) { + int count = 0; + + while (actions) { + switch (actions->type) { + case EAT_DESTROYLOCALCOND: + if (OBJECT_REG(actions->data.destroy_local_cond.cond)) + count++; + break; + case EAT_DESTROYLOCALPOINTER: + if (OBJECT_REG(actions->data.destroy_local_pointer.pointer)) + count++; + break; + case EAT_DESTROYMEMBER: + if (OBJECT_REG(actions->data.destroy_member.objectptr)) + count++; + break; + case EAT_DESTROYBASE: + if (OBJECT_REG(actions->data.destroy_base.objectptr)) + count++; + break; + case EAT_DESTROYMEMBERCOND: + if (OBJECT_REG(actions->data.destroy_member_cond.cond)) + count++; + if (OBJECT_REG(actions->data.destroy_member_cond.objectptr)) + count++; + break; + case EAT_DESTROYMEMBERARRAY: + if (OBJECT_REG(actions->data.destroy_member_array.objectptr)) + count++; + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + if (OBJECT_REG(actions->data.delete_pointer.pointerobject)) + count++; + break; + case EAT_DELETEPOINTERCOND: + if (OBJECT_REG(actions->data.delete_pointer_cond.cond)) + count++; + if (OBJECT_REG(actions->data.delete_pointer_cond.pointerobject)) + count++; + break; + } + actions = actions->prev; + } + + return count; +} + +void noteexceptionactionregisters(ExceptionAction *actions, PCodeArg *ops) { + Object *obj; + int reg; + + while (actions) { + switch (actions->type) { + case EAT_DESTROYLOCALCOND: + if ((reg = OBJECT_REG(obj = actions->data.destroy_local_cond.cond))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DESTROYLOCALPOINTER: + if ((reg = OBJECT_REG(obj = actions->data.destroy_local_pointer.pointer))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DESTROYMEMBER: + if ((reg = OBJECT_REG(obj = actions->data.destroy_member.objectptr))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DESTROYBASE: + if ((reg = OBJECT_REG(obj = actions->data.destroy_base.objectptr))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DESTROYMEMBERCOND: + if ((reg = OBJECT_REG(obj = actions->data.destroy_member_cond.cond))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + if ((reg = OBJECT_REG(obj = actions->data.destroy_member_cond.objectptr))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DESTROYMEMBERARRAY: + if ((reg = OBJECT_REG(obj = actions->data.destroy_member_array.objectptr))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + if ((reg = OBJECT_REG(obj = actions->data.delete_pointer.pointerobject))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DELETEPOINTERCOND: + if ((reg = OBJECT_REG(obj = actions->data.delete_pointer_cond.cond))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + if ((reg = OBJECT_REG(obj = actions->data.delete_pointer_cond.pointerobject))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + } + actions = actions->prev; + } +} + +void recordexceptionactions(PCode *instr, ExceptionAction *actions) { + PCAction *pca; + + if (!actions && (!last_pc_action || !last_pc_action->actions)) + return; + + pca = lalloc(sizeof(PCAction)); + pca->next = NULL; + pca->firstInstr = pca->lastInstr = instr; + pca->actions = actions; + pca->prev = last_pc_action; + if (last_pc_action) + last_pc_action->next = pca; + else + pc_actions = pca; + last_pc_action = pca; + + branch_label(makepclabel()); + while (actions) { + if (actions->type == EAT_CATCHBLOCK && actions->data.catch_block.catch_label->pclabel) + pcbranch(instr->block, actions->data.catch_block.catch_label->pclabel); + else if (actions->type == EAT_SPECIFICATION && actions->data.specification.unexp_label->pclabel) + pcbranch(instr->block, actions->data.specification.unexp_label->pclabel); + actions = actions->prev; + } +} + +static void deleteexceptionaction(PCAction *pca) { + if (pca->prev) + pca->prev->next = pca->next; + else + pc_actions = pca->next; + + if (pca->next) + pca->next->prev = pca->prev; +} + +static int mergeexceptionactions(void) { + int count; + PCAction *pca; + PCAction *prev; + + if (!pc_actions) + return 0; + + for (pca = pc_actions; pca; pca = pca->next) { + if (pca->firstInstr->block->flags & fDeleted) + deleteexceptionaction(pca); + } + + if (!(pca = pc_actions)) + return 0; + + while (pca) { + pca->node = pca->actions ? makeEAnode(pca->actions) : NULL; + pca = pca->next; + } + + prev = pc_actions; + for (pca = pc_actions->next; pca; pca = pca->next) { + if (pca->node == prev->node) { + prev->lastInstr = pca->lastInstr; + deleteexceptionaction(pca); + } else { + prev = pca; + } + } + + count = 0; + for (pca = pc_actions; pca; pca = pca->next) { + if (!pca->actions) + deleteexceptionaction(pca); + else + count++; + } + + return count; +} + +typedef struct ExceptionThing { + UInt32 x0; + UInt16 x4; + UInt16 x6; +} ExceptionThing; + +void dumpexceptiontables(Object *function, SInt32 codesize) { + PCAction *pca; + UInt32 insn_start; + UInt32 insn_count; + UInt16 *sh; + ExceptionThing *thing; + int count; + + count = mergeexceptionactions(); + InitGList(&exceptmodule, 256); + AppendGListNoData(&exceptmodule, 8 * count + 4); + AppendGListLong(&exceptmodule, 0); + + for (pca = pc_actions; pca; pca = pca->next) { + if (pca->node->count == 0 && pca->node->xE == 0) + allocateactioninfo(pca->node); + } + + sh = (UInt16 *) *exceptmodule.data; + if (copts.altivec_model && used_nonvolatile_registers[RegClass_VR]) { + sh[0] = + CTool_EndianConvertWord16( + (used_nonvolatile_registers[RegClass_GPR] << 11) | + ((used_nonvolatile_registers[RegClass_FPR] & 0x1F) << 6) | + (((used_nonvolatile_registers[RegClass_CRFIELD] != 0) & 1) << 5) | + ((dynamic_stack & 1) << 4) | + 8); + sh[0] |= 4; + if (copts.altivec_vrsave) + sh[1] = CTool_EndianConvertWord16((used_nonvolatile_registers[RegClass_VR] << 11) | 0x400); + else + sh[1] = CTool_EndianConvertWord16((used_nonvolatile_registers[RegClass_VR] & 0x1F) << 11); + } else { + sh[0] = + CTool_EndianConvertWord16( + (used_nonvolatile_registers[RegClass_GPR] << 11) | + ((used_nonvolatile_registers[RegClass_FPR] & 0x1F) << 6) | + (((used_nonvolatile_registers[RegClass_CRFIELD] != 0) & 1) << 5) | + ((dynamic_stack & 1) << 4) | + 8); + sh[1] = 0; + } + + thing = (ExceptionThing *) (sh + 2); + pca = pc_actions; + while (pca) { + insn_start = findPC_long(pca->firstInstr); + insn_count = (findPC_long(pca->lastInstr) - insn_start) / 4; + CError_ASSERT(1203, (insn_count & 0xFFFF0000) == 0); + thing->x0 = CTool_EndianConvertWord32(insn_start + 4); + thing->x4 = CTool_EndianConvertWord16(insn_count); + thing->x6 = CTool_EndianConvertWord16(pca->node->xE); + pca = pca->next; + thing++; + } + + LockGList(&exceptmodule); + ObjGen_DeclareExceptionTables(function, codesize, *exceptmodule.data, exceptmodule.size, except_refs); + FreeGList(&exceptmodule); +} diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/FunctionCalls.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/FunctionCalls.c new file mode 100644 index 0000000..67d7443 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/FunctionCalls.c @@ -0,0 +1,642 @@ +#include "compiler/FunctionCalls.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/InstrSelection.h" +#include "compiler/Operands.h" +#include "compiler/PCode.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/Registers.h" +#include "compiler/StackFrame.h" +#include "compiler/StructMoves.h" +#include "compiler/types.h" + +enum { + AIF_PassInGPR = 1, + AIF_PassInFPR = 2, + AIF_PassOnStack = 4, + AIF_ExtendTo32Bits = 8, + AIF_ForceDoublePrecision = 0x10, + AIF_PassInVR = 0x20, + AIF_PassMask = AIF_PassInGPR | AIF_PassInFPR | AIF_PassOnStack | AIF_PassInVR +}; + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct ArgInfo { + struct ArgInfo *next; + ENode *expr; + Operand opnd; + SInt32 offset; + short gpr; + short gprHi; + short fpr; + short vr; + short evaluated; + short flags; +} ArgInfo; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +// forward decls +static void branch_subroutine_indirect_ctr(Operand *addrOpnd, UInt32 *used_regs); + +static ArgInfo *make_arginfo(ENode *expr) { + ArgInfo *info = lalloc(sizeof(ArgInfo)); + memclrw(info, sizeof(ArgInfo)); + + info->next = NULL; + info->expr = expr; + info->offset = -1; + info->gpr = -1; + info->gprHi = -1; + info->fpr = -1; + info->vr = -1; + info->evaluated = 0; + info->flags = 0; + + return info; +} + +static ArgInfo *analyze_arguments(ENode *funcref, ENodeList *arg_expr, FuncArg *arg, UInt32 *used_regs, Boolean *resultHasFloats, char has_varargs) { + ArgInfo *infos; + ArgInfo *info; + SInt32 displ; + SInt32 arg_size; + int gpr_counter; + int fpr_counter; + int vr_counter; + Type *type; + RegClass rclass; + Boolean spilledVectorFlag; + + infos = NULL; + displ = 0; + gpr_counter = 3; + fpr_counter = 1; + vr_counter = 2; + + for (rclass = 0; rclass < RegClassMax; rclass++) + used_regs[rclass] = 0; + *resultHasFloats = 0; + + while (arg_expr) { + if (arg_expr->node == funcref) { + arg_expr = arg_expr->next; + arg = arg->next; + continue; + } + + type = arg_expr->node->rtype; + if (infos) { + info->next = make_arginfo(arg_expr->node); + info = info->next; + } else { + infos = info = make_arginfo(arg_expr->node); + } + + arg_size = 0; + if (IS_TYPE_VECTOR(type)) { + if (arg == &elipsis) { + spilledVectorFlag = 1; + info->flags |= AIF_PassOnStack; + } else { + spilledVectorFlag = 0; + if (vr_counter <= 13) { + info->flags |= AIF_PassInVR; + info->vr = vr_counter; + used_regs[RegClass_VR] |= 1 << vr_counter; + } else { + spilledVectorFlag = 1; + info->flags |= AIF_PassOnStack; + } + } + + if (has_varargs) { + if (gpr_counter < 10) { + gpr_counter = ((gpr_counter - 2) & ~3) + 5; + if (arg == &elipsis && gpr_counter < 10) { + info->flags |= AIF_PassInGPR; + info->gpr = gpr_counter; + used_regs[RegClass_GPR] |= (15 << gpr_counter) & 0x7E0; + } + gpr_counter += 4; + } + spilledVectorFlag = 1; + } + + if (spilledVectorFlag) + arg_size = 16; + vr_counter++; + } else if (IS_TYPE_FLOAT(type)) { + *resultHasFloats = 1; + if (!arg || arg == &oldstyle) { + if (fpr_counter <= 13) { + info->flags |= AIF_PassInFPR; + info->fpr = fpr_counter; + used_regs[RegClass_FPR] |= 1 << fpr_counter; + } else { + info->flags |= AIF_PassOnStack | AIF_ForceDoublePrecision; + } + arg_size = 8; + fpr_counter++; + gpr_counter += 2; + } else if (arg == &elipsis) { + if (gpr_counter < 10) { + info->flags |= AIF_PassInGPR; + info->gpr = gpr_counter; + used_regs[RegClass_GPR] |= 3 << gpr_counter; + } else if (gpr_counter == 10) { + info->flags |= AIF_PassInGPR | AIF_PassOnStack | AIF_ForceDoublePrecision; + info->gpr = gpr_counter; + used_regs[RegClass_GPR] |= 3 << gpr_counter; + } else { + info->flags |= AIF_PassOnStack | AIF_ForceDoublePrecision; + } + arg_size = 8; + fpr_counter++; + gpr_counter += 2; + } else { + if (fpr_counter <= 13) { + info->flags |= AIF_PassInFPR; + info->fpr = fpr_counter; + used_regs[RegClass_FPR] |= 1 << fpr_counter; + } else { + info->flags |= AIF_PassOnStack; + } + + if (type->size == 4) { + arg_size = 4; + gpr_counter++; + } else { + arg_size = 8; + gpr_counter += 2; + } + + fpr_counter++; + } + } else if (TYPE_IS_8BYTES(type)) { + if (gpr_counter <= 10) { + info->flags |= AIF_PassInGPR; + if (copts.littleendian) { + info->gpr = gpr_counter; + info->gprHi = gpr_counter + 1; + } else { + info->gpr = gpr_counter + 1; + info->gprHi = gpr_counter; + } + used_regs[RegClass_GPR] |= 1 << gpr_counter; + if ((gpr_counter + 1) <= 10) + used_regs[RegClass_GPR] |= 1 << (gpr_counter + 1); + } else { + info->flags |= AIF_PassOnStack; + } + + arg_size = 8; + gpr_counter += 2; + } else if (TYPE_FITS_IN_REGISTER(type)) { + if ((!arg || arg == &elipsis || arg == &oldstyle) && type->size < 4) + info->flags |= AIF_ExtendTo32Bits; + + if (gpr_counter <= 10) { + info->flags |= AIF_PassInGPR; + info->gpr = gpr_counter; + used_regs[RegClass_GPR] |= 1 << gpr_counter; + } else { + info->flags |= AIF_PassOnStack; + } + + arg_size = 4; + gpr_counter++; + } else if (IS_TYPE_ARRAY(type) || IS_TYPE_NONVECTOR_STRUCT(type) || IS_TYPE_CLASS(type) || + IS_TYPE_12BYTES_MEMBERPOINTER(type)) { + SInt32 gprs_needed = (type->size >> 2) + ((type->size & 3) != 0); + if (gpr_counter <= 10) { + if ((gpr_counter + gprs_needed - 1) <= 10) { + info->flags |= AIF_PassInGPR; + info->gpr = gpr_counter; + used_regs[RegClass_GPR] |= ((1 << gprs_needed) - 1) << gpr_counter; + } else { + info->flags |= AIF_PassInGPR | AIF_PassOnStack; + info->gpr = gpr_counter; + used_regs[RegClass_GPR] |= ((1 << (11 - gpr_counter)) - 1) << gpr_counter; + } + } else { + info->flags |= AIF_PassOnStack; + } + + gpr_counter += gprs_needed; + arg_size = type->size; + } else { + CError_FATAL(421); + } + + displ = set_out_param_displ(displ, type, info->flags & AIF_PassOnStack, &info->offset, arg_size); + + arg_expr = arg_expr->next; + if (arg && arg != &elipsis && arg != &oldstyle) + arg = arg->next; + } + + update_out_param_size(displ); + + return infos; +} + +static void pass_in_memory(ArgInfo *info) { + Type *type; + Operand opnd; + + type = info->expr->rtype; + memclrw(&opnd, sizeof(Operand)); + + if (TYPE_FITS_IN_REGISTER(type)) { + if (TYPE_IS_8BYTES(type)) { + if (!info->evaluated) + GEN_NODE(info->expr, &info->opnd); + coerce_to_register_pair(&info->opnd, type, 0, 0); + + load_store_register( + PC_STW, info->opnd.reg, 1, + NULL, low_offset + out_param_displ_to_offset(info->offset)); + load_store_register( + PC_STW, info->opnd.regHi, 1, + NULL, high_offset + out_param_displ_to_offset(info->offset)); + } else { + if (!info->evaluated) + GEN_NODE(info->expr, &info->opnd); + if (info->flags & AIF_ExtendTo32Bits) + extend32(&info->opnd, type, 0); + ENSURE_GPR(&info->opnd, type, 0); + + load_store_register( + PC_STW, info->opnd.reg, 1, + NULL, out_param_displ_to_offset(info->offset)); + } + } else if (IS_TYPE_FLOAT(type)) { + if (!info->evaluated) + GEN_NODE(info->expr, &info->opnd); + ENSURE_FPR(&info->opnd, type, 0); + + if (type->size == 4 && !(info->flags & AIF_ForceDoublePrecision)) { + load_store_register( + PC_STFS, info->opnd.reg, 1, + NULL, out_param_displ_to_offset(info->offset)); + } else { + load_store_register( + PC_STFD, info->opnd.reg, 1, + NULL, out_param_displ_to_offset(info->offset)); + } + } else if (IS_TYPE_VECTOR(type)) { + if (!info->evaluated) + GEN_NODE(info->expr, &info->opnd); + ENSURE_VR(&info->opnd, type, 0); + + load_store_register( + PC_STVX, info->opnd.reg, 1, + NULL, out_param_displ_to_offset(info->offset)); + } else { + opnd.optype = OpndType_IndirectGPR_ImmOffset; + opnd.reg = 1; + opnd.object = NULL; + opnd.immOffset = out_param_displ_to_offset(info->offset); + + if (!info->evaluated) + GEN_NODE(info->expr, &info->opnd); + + move_block(&opnd, &info->opnd, type->size, CMach_ArgumentAlignment(type)); + } +} + +static void pass_in_register(ArgInfo *info) { + Type *type; + + type = info->expr->rtype; + + if ((info->flags & AIF_PassMask) == AIF_PassInFPR) { + if (!info->evaluated) + GEN_NODE_TO_REG(info->expr, info->fpr, 0, &info->opnd); + ENSURE_FPR(&info->opnd, type, info->fpr); + if (info->opnd.reg != info->fpr) + emitpcode(PC_FMR, info->fpr, info->opnd.reg); + } else if ((info->flags & AIF_PassMask) == AIF_PassInVR) { + if (!info->evaluated) + GEN_NODE_TO_REG(info->expr, info->vr, 0, &info->opnd); + ENSURE_VR(&info->opnd, type, info->vr); + if (info->opnd.reg != info->vr) + emitpcode(PC_VMR, info->vr, info->opnd.reg); + } else if (TYPE_FITS_IN_REGISTER(type)) { + if (TYPE_IS_8BYTES(type)) { + if (!info->evaluated) + GEN_NODE_TO_REG(info->expr, info->gpr, info->gprHi, &info->opnd); + coerce_to_register_pair(&info->opnd, type, info->gpr, info->gprHi); + if (copts.littleendian) { + if (info->gprHi > 10) { + load_store_register( + PC_STW, info->opnd.regHi, 1, + NULL, high_offset + out_param_displ_to_offset(info->offset)); + } + } else { + if (info->gpr > 10) { + load_store_register( + PC_STW, info->opnd.reg, 1, + NULL, low_offset + out_param_displ_to_offset(info->offset)); + } + } + } else { + if (!info->evaluated) + GEN_NODE_TO_REG(info->expr, info->gpr, 0, &info->opnd); + if (info->flags & AIF_ExtendTo32Bits) + extend32(&info->opnd, type, info->gpr); + ENSURE_GPR(&info->opnd, type, info->gpr); + if (info->opnd.reg != info->gpr) + emitpcode(PC_MR, info->gpr, info->opnd.reg); + } + } else if (IS_TYPE_FLOAT(type)) { + if (!info->evaluated) + GEN_NODE(info->expr, &info->opnd); + + if (type->size != 4 && info->opnd.optype == OpndType_IndirectGPR_ImmOffset) { + load_store_register( + PC_LWZ, info->gpr, info->opnd.reg, + info->opnd.object, info->opnd.immOffset); + load_store_register( + PC_LWZ, info->gpr + 1, info->opnd.reg, + info->opnd.object, info->opnd.immOffset + 4); + } else { + ENSURE_FPR(&info->opnd, type, 0); + load_store_register( + PC_STFD, info->opnd.reg, 1, + NULL, out_param_displ_to_offset(info->offset)); + load_store_register( + PC_LWZ, info->gpr, 1, + NULL, out_param_displ_to_offset(info->offset)); + load_store_register( + PC_LWZ, info->gpr + 1, 1, + NULL, out_param_displ_to_offset(info->offset) + 4); + } + } else if (IS_TYPE_VECTOR(type)) { + if (!info->evaluated) + GEN_NODE(info->expr, &info->opnd); + + if (info->opnd.optype == OpndType_IndirectGPR_ImmOffset) { + load_store_register( + PC_LWZ, info->gpr, info->opnd.reg, + info->opnd.object, info->opnd.immOffset); + load_store_register( + PC_LWZ, info->gpr + 1, info->opnd.reg, + info->opnd.object, info->opnd.immOffset + 4); + if ((info->gpr + 2) < 10) { + load_store_register( + PC_LWZ, info->gpr + 2, info->opnd.reg, + info->opnd.object, info->opnd.immOffset + 8); + load_store_register( + PC_LWZ, info->gpr + 3, info->opnd.reg, + info->opnd.object, info->opnd.immOffset + 12); + } + } else { + ENSURE_VR(&info->opnd, type, 0); + load_store_register( + PC_STVX, info->opnd.reg, 1, + NULL, out_param_displ_to_offset(info->offset)); + load_store_register( + PC_LWZ, info->gpr, 1, + NULL, out_param_displ_to_offset(info->offset)); + load_store_register( + PC_LWZ, info->gpr + 1, 1, + NULL, out_param_displ_to_offset(info->offset) + 4); + if ((info->gpr + 2) < 10) { + load_store_register( + PC_LWZ, info->gpr + 2, 1, + NULL, out_param_displ_to_offset(info->offset) + 8); + load_store_register( + PC_LWZ, info->gpr + 3, 1, + NULL, out_param_displ_to_offset(info->offset) + 12); + } + } + } else { + if (!info->evaluated) + GEN_NODE(info->expr, &info->opnd); + + if (type->size <= 4) { + if (info->opnd.optype == OpndType_IndirectSymbol) + coerce_to_addressable(&info->opnd); + + if (info->opnd.optype == OpndType_IndirectGPR_ImmOffset) { + load_store_register( + PC_LWZ, info->gpr, info->opnd.reg, + info->opnd.object, info->opnd.immOffset); + } else if (info->opnd.optype == OpndType_IndirectGPR_Indexed) { + emitpcode( + PC_LWZX, info->gpr, info->opnd.reg, + info->opnd.regOffset); + } + } else { + SInt32 gprs_needed = (type->size >> 2) + ((type->size & 3) != 0); + SInt32 i; + + make_addressable(&info->opnd, gprs_needed * 4, 12); + for (i = 0; i < gprs_needed; i++) { + if (info->opnd.reg != (info->gpr + i)) { + load_store_register( + PC_LWZ, info->gpr + i, info->opnd.reg, + info->opnd.object, info->opnd.immOffset + i * 4); + } + } + + if (info->opnd.reg >= info->gpr && info->opnd.reg < (info->gpr + gprs_needed)) { + load_store_register( + PC_LWZ, info->opnd.reg, info->opnd.reg, + info->opnd.object, info->opnd.immOffset + (info->opnd.reg - info->gpr) * 4); + } + } + } +} + +static void pass_in_register_and_memory(ArgInfo *info) { + Type *type; + int gpr; + SInt32 offset; + + type = info->expr->rtype; + gpr = info->gpr; + offset = 0; + while (offset < type->size && gpr <= 10) { + load_store_register( + PC_LWZ, gpr, 1, + NULL, offset + out_param_displ_to_offset(info->offset)); + gpr++; + offset += 4; + } +} + +static Boolean needs_TOC_reload(Object *func) { + return 0; +} + +static void load_virtual_function(TypeClass *tclass, SInt32 offset, int reg, Operand *opnd) { + if (tclass->flags & CLASS_HANDLEOBJECT) { + load_store_register(PC_LWZ, 12, reg, NULL, 0); + load_store_register(PC_LWZ, 12, 12, NULL, tclass->vtable->offset); + } else { + load_store_register(PC_LWZ, 12, reg, NULL, tclass->vtable->offset); + } + load_store_register(PC_LWZ, 12, 12, NULL, offset); + opnd->optype = OpndType_GPR; + opnd->reg = 12; +} + +static void branch_subroutine_indirect(Object *func, Operand *addrOpnd, UInt32 *used_regs) { + if (addrOpnd->reg != 12) + emitpcode(PC_MR, 12, addrOpnd->reg); + + used_regs[RegClass_GPR] |= 1 << 12; + branch_subroutine(func, 1, used_regs); +} + +static void evaluate_nested_function_calls(ArgInfo *info) { + ArgInfo *scan; + + scan = info->next; + while (scan && !scan->expr->hascall) + scan = scan->next; + + if (scan) + evaluate_nested_function_calls(scan); + + if (info->expr->hascall) { + GEN_NODE(info->expr, &info->opnd); + info->evaluated = 1; + } +} + +void call_function(ENode *expr, Operand *output) { + ArgInfo *infos; // r31 + ENode *funcref = expr->data.funccall.funcref; // r27 + Type *resultType = expr->data.funccall.functype->functype; // r26 + ENode *node = NULL; // r25 + char has_varargs; // r24 + ArgInfo *info; // r22 + Operand opnd; + UInt32 used_regs[RegClassMax] = {0}; + Boolean has_floats; + FuncArg *arg; + + memclrw(&opnd, sizeof(Operand)); + + has_varargs = 0; + for (arg = expr->data.funccall.functype->args; arg; arg = arg->next) { + if (arg == &elipsis) { + has_varargs = 1; + break; + } + } + + if (expr->data.funccall.functype->flags & FUNC_FLAGS_80) { + if (CMach_PassResultInHiddenArg(resultType)) + node = expr->data.funccall.args->next->node; + else + node = expr->data.funccall.args->node; + } + + infos = analyze_arguments( + node, + expr->data.funccall.args, + expr->data.funccall.functype->args, + used_regs, + &has_floats, + has_varargs); + + if (infos) + evaluate_nested_function_calls(infos); + + if (funcref->hascall) { + GEN_NODE_TO_GPR(funcref, &opnd, TYPE(&void_ptr), 0); + } else if (node && node->hascall) { + GEN_NODE_TO_GPR(node, &opnd, TYPE(&void_ptr), 0); + } + + for (info = infos; info; info = info->next) { + if (info->flags & AIF_PassOnStack) + pass_in_memory(info); + } + for (info = infos; info; info = info->next) { + if ((info->flags & AIF_PassMask) == (AIF_PassInGPR | AIF_PassOnStack)) + pass_in_register_and_memory(info); + } + for (info = infos; info; info = info->next) { + int flag = info->flags & AIF_PassMask; + if ( + flag == AIF_PassInGPR || + flag == AIF_PassInFPR || + flag == AIF_PassInVR + ) + pass_in_register(info); + } + + if (funcref->type == EOBJREF) { + TypeClass *tclass; + SInt32 vfOffset; + if (CParser_IsVirtualFunction(funcref->data.objref, &tclass, &vfOffset)) { + load_virtual_function( + tclass, + vfOffset, + CMach_PassResultInHiddenArg(resultType) ? Register4 : Register3, + &opnd + ); + branch_subroutine_indirect_ctr(&opnd, used_regs); + } else if (node) { + if (!node->hascall) { + GEN_NODE_TO_REG(node, 12, 0, &opnd); + ENSURE_GPR(&opnd, TYPE(&void_ptr), 12); + } + branch_subroutine_indirect(funcref->data.objref, &opnd, used_regs); + } else { + branch_subroutine(funcref->data.objref, needs_TOC_reload(funcref->data.objref), used_regs); + } + } else { + if (!funcref->hascall) + GEN_NODE_TO_REG(funcref, 12, 0, &opnd); + ENSURE_GPR(&opnd, TYPE(&void_ptr), 12); + branch_subroutine_indirect_ctr(&opnd, used_regs); + } + + if (IS_TYPE_FLOAT(resultType)) { + output->optype = OpndType_FPR; + output->reg = used_virtual_registers[RegClass_FPR]++; + emitpcode(PC_FMR, output->reg, 1); + } else if (IS_TYPE_VECTOR(resultType)) { + output->optype = OpndType_VR; + output->reg = used_virtual_registers[RegClass_VR]++; + emitpcode(PC_VMR, output->reg, 2); + } else if (TYPE_FITS_IN_REGISTER(resultType)) { + if (resultType->size > 4) { + output->optype = OpndType_GPRPair; + output->reg = used_virtual_registers[RegClass_GPR]++; + output->regHi = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_MR, output->reg, low_reg); + emitpcode(PC_MR, output->regHi, high_reg); + } else { + output->optype = OpndType_GPR; + output->reg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_MR, output->reg, 3); + } + } else { + output->optype = OpndType_Absolute; + output->immediate = 0; + } +} + +static void branch_subroutine_indirect_ctr(Operand *addrOpnd, UInt32 *used_regs) { + if (addrOpnd->reg != 12) + emitpcode(PC_MR, 12, addrOpnd->reg); + + emitpcode(PC_MTCTR, 12); + used_regs[RegClass_GPR] |= 1 << 12; + branch_subroutine_ctr(used_regs); +} diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/InstrSelection.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/InstrSelection.c new file mode 100644 index 0000000..359c980 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/InstrSelection.c @@ -0,0 +1,5348 @@ +#include "compiler/InstrSelection.h" +#include "compiler/CError.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/FunctionCalls.h" +#include "compiler/Intrinsics.h" +#include "compiler/Operands.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StructMoves.h" +#include "compiler/TOC.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +PrecomputedOperand *precomputedoperands; +void (*cgdispatch[MAXEXPR + 1])(ENode *, short, short, Operand *); + +// forward decls +static int ispowerof2(SInt32 val); +static void binary_immediate(Opcode opcode, ENode *left, SInt32 value, short outputReg, Operand *output); +static void shift_left_immediate(ENode *expr, short shift, short negate, short outputReg, Operand *output); +static void shift_right_immediate(ENode *expr, Type *type, short shift, short outputReg, Operand *output); +static void or_xor_immediate(Opcode opcode, ENode *expr, SInt32 value, short outputReg, Operand *output); +static void signed_divide_by_power_of_2(ENode *expr, int shift, int negate, short outputReg, Operand *output); +static void signed_mod_by_power_of_2(ENode *expr, int shift, int negate, short outputReg, Operand *output); +static void fp_binary_operator(Opcode opcode, ENode *left, ENode *right, short outputReg, Operand *output); +static void logical_expression_nobranch(ENode *cond, Boolean invert, Operand *output); +static void shift_and_mask(ENode *expr, short a, short b, short c, short outputReg, Operand *output); +static ENodeType invert_relop(ENodeType nt); + +#define IS_INT_CONST(node) ( ENODE_IS((node), EINTCONST) && IS_TYPE_INT((node)->rtype) && (node)->rtype->size <= 4 ) +#define IS_INT_CONST_ZERO(node) ( IS_INT_CONST(node) && (node)->data.intval.lo == 0 ) + +void init_cgdispatch(void) { + ENodeType t; + + for (t = 0; t <= MAXEXPR; t++) + cgdispatch[t] = gen_UNEXPECTED; + + cgdispatch[EPOSTINC] = gen_POSTINCDEC; + cgdispatch[EPOSTDEC] = gen_POSTINCDEC; + cgdispatch[EINDIRECT] = gen_INDIRECT; + cgdispatch[EMONMIN] = gen_MONMIN; + cgdispatch[EBINNOT] = gen_BINNOT; + cgdispatch[ELOGNOT] = gen_LOGICAL; + cgdispatch[EFORCELOAD] = gen_FORCELOAD; + cgdispatch[EMUL] = gen_MUL; + cgdispatch[EDIV] = gen_DIV; + cgdispatch[EMODULO] = gen_MODULO; + cgdispatch[EADD] = gen_ADD; + cgdispatch[ESUB] = gen_SUB; + cgdispatch[ESHL] = gen_SHL; + cgdispatch[ESHR] = gen_SHR; + cgdispatch[ELESS] = gen_COMPARE; + cgdispatch[EGREATER] = gen_COMPARE; + cgdispatch[ELESSEQU] = gen_COMPARE; + cgdispatch[EGREATEREQU] = gen_COMPARE; + cgdispatch[EEQU] = gen_COMPARE; + cgdispatch[ENOTEQU] = gen_COMPARE; + cgdispatch[EAND] = gen_AND; + cgdispatch[EXOR] = gen_XOR; + cgdispatch[EOR] = gen_OR; + cgdispatch[ELAND] = gen_LOGICAL; + cgdispatch[ELOR] = gen_LOGICAL; + cgdispatch[EASS] = gen_ASS; + cgdispatch[ECOMMA] = gen_COMMA; + cgdispatch[ETYPCON] = gen_TYPCON; + cgdispatch[EBITFIELD] = gen_BITFIELD; + cgdispatch[EINTCONST] = gen_INTCONST; + cgdispatch[EFLOATCONST] = gen_FLOATCONST; + cgdispatch[ESTRINGCONST] = gen_STRINGCONST; + cgdispatch[ECOND] = gen_COND; + cgdispatch[EFUNCCALL] = gen_FUNCCALL; + cgdispatch[EFUNCCALLP] = gen_FUNCCALL; + cgdispatch[EOBJREF] = gen_OBJREF; + cgdispatch[ENULLCHECK] = gen_NULLCHECK; + cgdispatch[EPRECOMP] = gen_PRECOMP; + cgdispatch[EDEFINE] = gen_DEFINE; + cgdispatch[EREUSE] = gen_REUSE; + cgdispatch[EVECTOR128CONST] = gen_VECTOR128CONST; + cgdispatch[ECONDASS] = gen_CONDASS; +} + +void gen_DEFINE(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + Operand *op; + + if (!expr->data.diadic.right) { + op = lalloc(sizeof(Operand)); + memclrw(op, sizeof(Operand)); + expr->data.diadic.right = (ENode *) op; + GEN_NODE(expr->data.diadic.left, op); + } + + op = (Operand *) expr->data.diadic.right; + *output = *op; +} + +void gen_REUSE(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *inner = expr->data.monadic; + CError_ASSERT(250, ENODE_IS(inner, EDEFINE)); + gen_DEFINE(inner, outputReg, outputRegHi, output); +} + +void gen_POSTINCDEC(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + TypeBitfield *tbitfield; + ENode *inner; + Type *type; + Operand a; + Operand b; + Operand c; + Float fval; + int objReg; + int constReg; + int finalReg; + SInt32 incval; + + inner = expr->data.monadic->data.monadic; + type = expr->rtype; + tbitfield = NULL; + + memclrw(&a, sizeof(Operand)); + memclrw(&b, sizeof(Operand)); + memclrw(&c, sizeof(Operand)); + + if (TYPE_IS_8BYTES(type)) { + I8_gen_POSTINCDEC(expr, outputReg, outputRegHi, output); + return; + } + + if (IS_TYPE_FLOAT(type)) { + if (ENODE_IS(inner, EOBJREF) && (objReg = OBJECT_REG(inner->data.objref))) { + output->optype = OpndType_FPR; + output->reg = (outputReg && outputReg != objReg) ? outputReg : ALLOC_FPR(); + emitpcode(PC_FMR, output->reg, objReg); + fval = one_point_zero; + load_floating_constant(constReg = ALLOC_FPR(), type, &fval); + + if (ENODE_IS(expr, EPOSTINC)) { + emitpcode((type->size == 4) ? PC_FADDS : PC_FADD, objReg, objReg, constReg); + } else { + emitpcode((type->size == 4) ? PC_FSUBS : PC_FSUB, objReg, objReg, constReg); + } + } else { + GEN_NODE(inner, &a); + indirect(&a, inner); + b = a; + ENSURE_FPR(&b, type, 0); + + output->optype = OpndType_FPR; + output->reg = ALLOC_FPR(); + emitpcode(PC_FMR, output->reg, b.reg); + + fval = one_point_zero; + load_floating_constant(constReg = ALLOC_FPR(), type, &fval); + + finalReg = ALLOC_FPR(); + if (ENODE_IS(expr, EPOSTINC)) + emitpcode((type->size == 4) ? PC_FADDS : PC_FADD, finalReg, b.reg, constReg); + else + emitpcode((type->size == 4) ? PC_FSUBS : PC_FSUB, finalReg, b.reg, constReg); + + store_fp(finalReg, &a, type); + } + } else { + if (IS_TYPE_POINTER(type)) { + if (ENODE_IS(expr, EPOSTINC)) + incval = TPTR_TARGET(type)->size; + else + incval = -TPTR_TARGET(type)->size; + } else { + if (ENODE_IS(expr, EPOSTINC)) + incval = 1; + else + incval = -1; + } + + if (ENODE_IS(inner, EOBJREF) && (objReg = OBJECT_REG(inner->data.objref))) { + output->optype = OpndType_GPR; + output->reg = (outputReg && outputReg != objReg) ? outputReg : ALLOC_GPR(); + emitpcode(PC_MR, output->reg, objReg); + add_register_immediate(objReg, objReg, incval); + } else { + if (ENODE_IS(inner, EBITFIELD)) { + tbitfield = TYPE_BITFIELD(TPTR_TARGET(inner)); + inner = inner->data.monadic; + } + GEN_NODE(inner, &a); + indirect(&a, inner); + b = a; + ENSURE_GPR(&b, type, 0); + + if (tbitfield) { + c = b; + extract_bitfield(&c, tbitfield, 0, &b); + } + output->optype = OpndType_GPR; + + output->reg = ALLOC_GPR(); + emitpcode(PC_MR, output->reg, b.reg); + + finalReg = ALLOC_GPR(); + add_register_immediate(finalReg, b.reg, incval); + + if (tbitfield) { + insert_bitfield(finalReg, &c, tbitfield); + finalReg = c.reg; + } + + store(finalReg, &a, type); + } + } +} + +void gen_INDIRECT(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + Type *type; + ENode *inner; + VarInfo *vi; + SInt32 postincvalue; + Operand op; + + type = expr->rtype; + inner = expr->data.monadic; + + if (TYPE_IS_8BYTES(type)) { + I8_gen_INDIRECT(expr, outputReg, outputRegHi, output); + return; + } + + memclrw(&op, sizeof(Operand)); + if (ENODE_IS(inner, EOBJREF) && OBJECT_REG(inner->data.objref)) { + vi = Registers_GetVarInfo(inner->data.objref); + switch (vi->rclass) { + case RegClass_GPR: + output->optype = OpndType_GPR; + break; + case RegClass_FPR: + output->optype = OpndType_FPR; + break; + case RegClass_VR: + output->optype = OpndType_VR; + break; + case RegClass_CRFIELD: + output->optype = OpndType_CRField; + break; + default: + CError_FATAL(456); + } + output->reg = vi->reg; + output->object = NULL; + return; + } + + if (ENODE_IS(inner, EBITFIELD)) { + GEN_NODE(inner->data.monadic, &op); + indirect(&op, expr); + ENSURE_GPR(&op, type, 0); + extract_bitfield(&op, TYPE_BITFIELD(inner->rtype), outputReg, output); + return; + } + + if (ispostincrementopportunity(inner, &op, &postincvalue) && (TYPE_FITS_IN_REGISTER(type) || IS_TYPE_FLOAT(type) || IS_TYPE_VECTOR(type))) { + indirect(&op, expr); + *output = op; + if (TYPE_FITS_IN_REGISTER(type)) { + ENSURE_GPR(output, type, outputReg); + } else if (IS_TYPE_FLOAT(type)) { + ENSURE_FPR(output, type, outputReg); + } else { + ENSURE_VR(output, type, outputReg); + } + + add_register_immediate(op.reg, op.reg, postincvalue); + return; + } + + GEN_NODE(inner, output); + indirect(output, expr); +} + +void gen_MONMIN(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *inner; + Type *type; + ENode *scan; + + inner = expr->data.monadic; + type = expr->rtype; + + if (TYPE_IS_8BYTES(type)) { + I8_gen_MONMIN(expr, outputReg, outputRegHi, output); + return; + } + + if (IS_TYPE_FLOAT(type)) { + if (ENODE_IS(inner, EADD) && ENODE_IS(inner->data.diadic.left, EMUL) && copts.fp_contract) { + fp_multiply_add( + (type->size == 4) ? PC_FNMADDS : PC_FNMADD, + inner->data.diadic.left->data.diadic.left, + inner->data.diadic.left->data.diadic.right, + inner->data.diadic.right, + outputReg, + output); + } else if (ENODE_IS(inner, EADD) && ENODE_IS(inner->data.diadic.right, EMUL) && copts.fp_contract) { + fp_multiply_add( + (type->size == 4) ? PC_FNMADDS : PC_FNMADD, + inner->data.diadic.right->data.diadic.left, + inner->data.diadic.right->data.diadic.right, + inner->data.diadic.left, + outputReg, + output); + } else if (ENODE_IS(inner, ESUB) && ENODE_IS(inner->data.diadic.left, EMUL) && copts.fp_contract) { + fp_multiply_add( + (type->size == 4) ? PC_FNMSUBS : PC_FNMSUB, + inner->data.diadic.left->data.diadic.left, + inner->data.diadic.left->data.diadic.right, + inner->data.diadic.right, + outputReg, + output); + } else { + fp_unary_operator(PC_FNEG, inner, outputReg, output); + } + return; + } + + scan = inner; + while (ENODE_IS(scan, ETYPCON) && IS_TYPE_INT_OR_ENUM(type) && !is_unsigned(type)) + scan = scan->data.monadic; + + switch (scan->type) { + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + if (TYPE_FITS_IN_REGISTER(scan->data.diadic.left->rtype) && TYPE_FITS_IN_REGISTER(scan->data.diadic.right->rtype)) { + gen_negated_condition_gpr(scan, output, outputReg); + return; + } + } + unary_operator(PC_NEG, inner, outputReg, output); +} + +void gen_BINNOT(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *inner; + Type *type; + + inner = expr->data.monadic; + type = expr->rtype; + + if (TYPE_IS_8BYTES(type)) { + I8_gen_BINNOT(expr, outputReg, outputRegHi, output); + return; + } + + if (ENODE_IS(inner, EAND)) + binary_operator(PC_NAND, inner->data.diadic.left, inner->data.diadic.right, outputReg, output); + else if (ENODE_IS(inner, EOR)) + binary_operator(PC_NOR, inner->data.diadic.left, inner->data.diadic.right, outputReg, output); + else if (ENODE_IS(inner, EXOR)) + binary_operator(PC_EQV, inner->data.diadic.left, inner->data.diadic.right, outputReg, output); + else + unary_operator(PC_NOT, inner, outputReg, output); +} + +void gen_FORCELOAD(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *inner; + + inner = expr->data.monadic; + GEN_NODE(inner, output); + + if (IS_TYPE_FLOAT(inner->rtype)) { + ENSURE_FPR(output, inner->rtype, outputReg); + } else if (IS_TYPE_VECTOR(inner->rtype)) { + ENSURE_VR(output, inner->rtype, outputReg); + } else if (TYPE_FITS_IN_REGISTER(inner->rtype)) { + if (TYPE_IS_8BYTES(inner->rtype)) + coerce_to_register_pair(output, inner->rtype, outputReg, outputRegHi); + else + ENSURE_GPR(output, inner->rtype, outputReg); + } else if (!IS_TYPE_VOID(inner->rtype)) { + CError_FATAL(681); + } +} + +void gen_MUL(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *left; + ENode *right; + Type *type; + int tmp; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + type = expr->rtype; + + if (TYPE_IS_8BYTES(type)) { + I8_gen_MUL(expr, outputReg, outputRegHi, output); + return; + } + + if (IS_TYPE_FLOAT(type)) { + fp_binary_operator((type->size == 4) ? PC_FMULS : PC_FMUL, left, right, outputReg, output); + return; + } + + if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(right->data.intval.lo))) { + shift_left_immediate(left, tmp, 0, outputReg, output); + } else if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(-right->data.intval.lo))) { + shift_left_immediate(left, tmp, 1, outputReg, output); + } else if (ENODE_IS(left, EINTCONST) && (tmp = ispowerof2(left->data.intval.lo))) { + shift_left_immediate(right, tmp, 0, outputReg, output); + } else if (ENODE_IS(left, EINTCONST) && (tmp = ispowerof2(-left->data.intval.lo))) { + shift_left_immediate(right, tmp, 1, outputReg, output); + } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT(right->data.intval.lo)) { + binary_immediate(PC_MULLI, left, right->data.intval.lo, outputReg, output); + } else if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT(left->data.intval.lo)) { + binary_immediate(PC_MULLI, right, left->data.intval.lo, outputReg, output); + } else { + binary_operator(PC_MULLW, left, right, outputReg, output); + } +} + +struct ms { + SInt32 m; + int s; +}; +static void create_signed_magic(SInt32 val, struct ms *output) { + // PowerPC CWG page 57-58 + int p; + UInt32 ad, anc, delta, q1, r1, q2, r2, t; + + ad = abs(val); + t = 0x80000000U + ((UInt32) val >> 31); + anc = t - 1 - t % ad; + p = 31; + q1 = 0x80000000U / anc; + r1 = 0x80000000U - q1 * anc; + q2 = 0x80000000U / ad; + r2 = 0x80000000U - q2 * ad; + + do { + p = p + 1; + q1 = 2 * q1; + r1 = 2 * r1; + if (r1 >= anc) { + q1 = q1 + 1; + r1 = r1 - anc; + } + q2 = 2 * q2; + r2 = 2 * r2; + if (r2 >= ad) { + q2 = q2 + 1; + r2 = r2 - ad; + } + delta = ad - r2; + } while (q1 < delta || (q1 == delta && r1 == 0)); + + // after loop + output->m = q2 + 1; + if (val < 0) + output->m = -output->m; + output->s = p - 32; +} + +struct mu { + UInt32 m; + int a; + int s; +}; +static void create_unsigned_magic(UInt32 val, struct mu *output) { + // PowerPC CWG page 58-59 + int p; + UInt32 nc, delta, q1, r1, q2, r2; + + output->a = 0; + nc = - 1 - (-val) % val; + p = 31; + q1 = 0x80000000U / nc; + r1 = 0x80000000U - q1 * nc; + q2 = 0x7FFFFFFFU / val; + r2 = 0x7FFFFFFFU - q2 * val; + do { + p = p + 1; + if (r1 >= nc - r1) { + q1 = 2 * q1 + 1; + r1 = 2 * r1 - nc; + } else { + q1 = 2 * q1; + r1 = 2 * r1; + } + if (r2 + 1 >= val - r2) { + if (q2 >= 0x7FFFFFFFU) + output->a = 1; + q2 = 2 * q2 + 1; + r2 = 2 * r2 + 1 - val; + } else { + if (q2 >= 0x80000000U) + output->a = 1; + q2 = 2 * q2; + r2 = 2 * r2 + 1; + } + delta = val - 1 - r2; + } while (p < 64 && (q1 < delta || (q1 == delta && r1 == 0))); + + output->m = q2 + 1; + output->s = p - 32; +} + +void gen_DIV(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *left; + ENode *right; + Type *type; + int tmp; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + type = expr->rtype; + + if (TYPE_IS_8BYTES(type)) { + I8_gen_DIV_MOD(expr, outputReg, outputRegHi, output); + return; + } + + if (IS_TYPE_FLOAT(type)) { + fp_binary_operator((type->size == 4) ? PC_FDIVS : PC_FDIV, left, right, outputReg, output); + return; + } + + if (is_unsigned(type)) { + if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(right->data.intval.lo))) { + shift_right_immediate(left, type, tmp, outputReg, output); + } else if (!copts.optimizesize && ENODE_IS(right, EINTCONST) && right->data.intval.lo != 1) { + SInt32 value; + int tmpreg1; + int tmpreg2; + int tmpreg3; + int tmpreg4; + int tmpreg5; + int tmpreg6; + int finalReg; + struct mu u_magicoutput; + Operand op1; + value = right->data.intval.lo; + tmpreg1 = ALLOC_GPR(); + tmpreg2 = ALLOC_GPR(); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + + memclrw(&op1, sizeof(Operand)); + GEN_NODE(left, &op1); + ENSURE_GPR(&op1, left->rtype, 0); + + tmpreg3 = op1.reg; + create_unsigned_magic(value, &u_magicoutput); + load_immediate(tmpreg2, u_magicoutput.m); + emitpcode(PC_MULHWU, tmpreg1, tmpreg2, tmpreg3); + if (u_magicoutput.a == 0) { + if (u_magicoutput.s) + emitpcode(PC_RLWINM, finalReg, tmpreg1, (32 - u_magicoutput.s) & 31, u_magicoutput.s, 31); + else + emitpcode(PC_MR, finalReg, tmpreg1); + } else if (u_magicoutput.a == 1) { + tmpreg4 = ALLOC_GPR(); + if (copts.optimizationlevel > 1) { + tmpreg5 = ALLOC_GPR(); + tmpreg6 = ALLOC_GPR(); + } else { + tmpreg5 = tmpreg4; + tmpreg6 = tmpreg4; + } + + emitpcode(PC_SUBF, tmpreg4, tmpreg1, tmpreg3); + emitpcode(PC_RLWINM, tmpreg5, tmpreg4, 31, 1, 31); + emitpcode(PC_ADD, tmpreg6, tmpreg5, tmpreg1); + emitpcode(PC_RLWINM, finalReg, tmpreg6, (32 - (u_magicoutput.s - 1)) & 31, u_magicoutput.s - 1, 31); + } + + output->optype = OpndType_GPR; + output->reg = finalReg; + } else { + binary_operator(PC_DIVWU, left, right, outputReg, output); + } + } else { + SInt32 value; + if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(right->data.intval.lo))) { + signed_divide_by_power_of_2(left, tmp, 0, outputReg, output); + } else if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(-right->data.intval.lo))) { + signed_divide_by_power_of_2(left, tmp, 1, outputReg, output); + } else if (!copts.optimizesize && ENODE_IS(right, EINTCONST) && (value = right->data.intval.lo) != 1u && value != -1) { + int tmpreg2; + int tmpreg3; + int tmpreg1; + int tmpreg4; + int finalReg; + struct ms s_magicoutput; + Operand op2; + value = right->data.intval.lo; + tmpreg1 = ALLOC_GPR(); + tmpreg2 = ALLOC_GPR(); + tmpreg3 = ALLOC_GPR(); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + + memclrw(&op2, sizeof(Operand)); + GEN_NODE(left, &op2); + ENSURE_GPR(&op2, left->rtype, 0); + + tmpreg4 = op2.reg; + create_signed_magic(value, &s_magicoutput); + load_immediate(tmpreg2, s_magicoutput.m); + emitpcode(PC_MULHW, tmpreg1, tmpreg2, tmpreg4); + if (value > 0 && s_magicoutput.m < 0) { + int t = ALLOC_GPR(); + emitpcode(PC_ADD, t, tmpreg1, tmpreg4); + tmpreg1 = t; + } else if (value < 0 && s_magicoutput.m > 0) { + int t = ALLOC_GPR(); + emitpcode(PC_SUBF, t, tmpreg4, tmpreg1); + tmpreg1 = t; + } + + if (s_magicoutput.s) { + int t = ALLOC_GPR(); + emitpcode(PC_SRAWI, t, tmpreg1, s_magicoutput.s); + tmpreg1 = t; + } + + emitpcode(PC_RLWINM, tmpreg3, tmpreg1, 1, 31, 31); + emitpcode(PC_ADD, finalReg, tmpreg1, tmpreg3); + + output->optype = OpndType_GPR; + output->reg = finalReg; + } else { + binary_operator(PC_DIVW, left, right, outputReg, output); + } + } +} + +void gen_MODULO(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *left; + ENode *right; + int tmp; + struct mu u_magicoutput; + struct ms s_magicoutput; + Operand op1; + Operand op2; + SInt32 value; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + memclrw(&op1, sizeof(Operand)); + memclrw(&op2, sizeof(Operand)); + + if (TYPE_IS_8BYTES(expr->rtype)) { + I8_gen_DIV_MOD(expr, outputReg, outputRegHi, output); + return; + } + + if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(right->data.intval.lo))) { + if (is_unsigned(expr->rtype)) + shift_and_mask(left, 0, 32 - tmp, 31, outputReg, output); + else + signed_mod_by_power_of_2(left, tmp, 0, outputReg, output); + } else if (!copts.optimizesize && ENODE_IS(right, EINTCONST) && (value = right->data.intval.lo) != 1u && value != -1) { + GEN_NODE(left, &op1); + ENSURE_GPR(&op1, left->rtype, 0); + + if (is_unsigned(expr->rtype)) { + int tmpreg1; + int tmpreg2; + int tmpreg3; + int tmpreg4; + int tmpreg5; + int tmpreg6; + int tmpreg7; + int tmpreg8; + int finalReg; + + tmpreg1 = op1.reg; + tmpreg2 = ALLOC_GPR(); + tmpreg3 = ALLOC_GPR(); + tmpreg4 = ALLOC_GPR(); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + + create_unsigned_magic(right->data.intval.lo, &u_magicoutput); + load_immediate(tmpreg3, u_magicoutput.m); + emitpcode(PC_MULHWU, tmpreg2, tmpreg3, tmpreg1); + + if (u_magicoutput.a == 0 && u_magicoutput.s != 0) + emitpcode(PC_RLWINM, tmpreg2, tmpreg2, (32 - u_magicoutput.s) & 31, u_magicoutput.s, 31); + + if (u_magicoutput.a == 1) { + tmpreg5 = ALLOC_GPR(); + if (copts.optimizationlevel > 1) { + tmpreg6 = ALLOC_GPR(); + tmpreg7 = ALLOC_GPR(); + tmpreg8 = ALLOC_GPR(); + } else { + tmpreg6 = tmpreg5; + tmpreg7 = tmpreg5; + tmpreg8 = tmpreg5; + } + emitpcode(PC_SUBF, tmpreg5, tmpreg2, tmpreg1); + emitpcode(PC_RLWINM, tmpreg6, tmpreg5, 31, 1, 31); + emitpcode(PC_ADD, tmpreg7, tmpreg6, tmpreg2); + emitpcode(PC_RLWINM, tmpreg8, tmpreg7, (32 - (u_magicoutput.s - 1)) & 31, u_magicoutput.s - 1, 31); + tmpreg2 = tmpreg8; + } + + if (value > 0 && value < 0x7FFF) { + emitpcode(PC_MULLI, tmpreg4, tmpreg2, value); + } else { + GEN_NODE(right, &op2); + ENSURE_GPR(&op2, right->rtype, 0); + emitpcode(PC_MULLW, tmpreg4, tmpreg2, op2.reg); + } + + emitpcode(PC_SUBF, finalReg, tmpreg4, tmpreg1); + output->optype = OpndType_GPR; + output->reg = finalReg; + } else { + int tmpreg1; + int tmpreg2; + int tmpreg3; + int tmpreg4; + int tmpreg5; + int tmpreg6; + int finalReg; + + tmpreg1 = op1.reg; + tmpreg2 = ALLOC_GPR(); + tmpreg3 = ALLOC_GPR(); + tmpreg4 = ALLOC_GPR(); + tmpreg5 = ALLOC_GPR(); + tmpreg6 = ALLOC_GPR(); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + + create_signed_magic(right->data.intval.lo, &s_magicoutput); + load_immediate(tmpreg3, s_magicoutput.m); + emitpcode(PC_MULHW, tmpreg2, tmpreg3, tmpreg1); + + if (value > 0 && s_magicoutput.m < 0) { + int tmp = ALLOC_GPR(); + emitpcode(PC_ADD, tmp, tmpreg2, tmpreg1); + tmpreg2 = tmp; + } else if (value < 0 && s_magicoutput.m > 0) { + int tmp = ALLOC_GPR(); + emitpcode(PC_SUBF, tmp, tmpreg1, tmpreg2); + tmpreg2 = tmp; + } + + if (s_magicoutput.s != 0) { + int tmp = ALLOC_GPR(); + emitpcode(PC_SRAWI, tmp, tmpreg2, s_magicoutput.s); + tmpreg2 = tmp; + } + + emitpcode(PC_RLWINM, tmpreg4, tmpreg2, 1, 31, 31); + emitpcode(PC_ADD, tmpreg5, tmpreg2, tmpreg4); + + if (value < 0x7FFF && value > -0x4000) { + emitpcode(PC_MULLI, tmpreg6, tmpreg5, value); + } else { + GEN_NODE(right, &op2); + ENSURE_GPR(&op2, right->rtype, 0); + + emitpcode(PC_MULLW, tmpreg6, tmpreg5, op2.reg); + } + + emitpcode(PC_SUBF, finalReg, tmpreg6, tmpreg1); + output->optype = OpndType_GPR; + output->reg = finalReg; + } + } else { + int tmpreg1; + int tmpreg2; + int finalReg; + + if (right->hascall) { + GEN_NODE(right, &op2); + ENSURE_GPR(&op2, right->rtype, 0); + GEN_NODE(left, &op1); + ENSURE_GPR(&op1, left->rtype, 0); + } else { + GEN_NODE(left, &op1); + ENSURE_GPR(&op1, left->rtype, 0); + GEN_NODE(right, &op2); + ENSURE_GPR(&op2, right->rtype, 0); + } + + tmpreg1 = ALLOC_GPR(); + tmpreg2 = ALLOC_GPR(); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + + emitpcode(is_unsigned(expr->rtype) ? PC_DIVWU : PC_DIVW, tmpreg1, op1.reg, op2.reg); + emitpcode(PC_MULLW, tmpreg2, tmpreg1, op2.reg); + emitpcode(PC_SUBF, finalReg, tmpreg2, op1.reg); + + output->optype = OpndType_GPR; + output->reg = finalReg; + } +} + +void gen_ADD(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *left; + ENode *right; + Type *type; + Operand opleft; + Operand opright; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + type = expr->rtype; + + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + + if (TYPE_IS_8BYTES(type)) { + I8_gen_ADD(expr, outputReg, outputRegHi, output); + return; + } + + if (IS_TYPE_FLOAT(type)) { + if (ENODE_IS(left, EMUL) && copts.fp_contract) { + fp_multiply_add( + (type->size == 4) ? PC_FMADDS : PC_FMADD, + left->data.diadic.left, + left->data.diadic.right, + right, + outputReg, output); + } else if (ENODE_IS(right, EMUL) && copts.fp_contract) { + fp_multiply_add( + (type->size == 4) ? PC_FMADDS : PC_FMADD, + right->data.diadic.left, + right->data.diadic.right, + left, + outputReg, output); + } else { + fp_binary_operator( + (type->size == 4) ? PC_FADDS : PC_FADD, + left, right, + outputReg, output); + } + return; + } + + if (right->hascall) { + GEN_NODE(right, &opright); + if (opright.optype >= OpndType_IndirectGPR_ImmOffset) + ENSURE_GPR(&opright, right->rtype, 0); + + GEN_NODE(left, &opleft); + if (opleft.optype >= OpndType_IndirectGPR_ImmOffset) + ENSURE_GPR(&opleft, left->rtype, 0); + } else { + GEN_NODE(left, &opleft); + if (opleft.optype >= OpndType_IndirectGPR_ImmOffset) + ENSURE_GPR(&opleft, left->rtype, 0); + + GEN_NODE(right, &opright); + if (opright.optype >= OpndType_IndirectGPR_ImmOffset) + ENSURE_GPR(&opright, right->rtype, 0); + } + + if (IS_TYPE_POINTER(expr->rtype)) { + if (TYPE_IS_8BYTES(expr->data.diadic.left->rtype)) { + opleft.optype = OpndType_GPR; + opleft.regHi = 0; + } + if (TYPE_IS_8BYTES(expr->data.diadic.right->rtype)) { + opright.optype = OpndType_GPR; + opright.regHi = 0; + } + } + + combine(&opleft, &opright, outputReg, output); +} + +void gen_SUB(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *left; + ENode *right; + Type *type; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + type = expr->rtype; + + if (TYPE_IS_8BYTES(type)) { + I8_gen_SUB(expr, outputReg, outputRegHi, output); + return; + } + + if (IS_TYPE_FLOAT(type)) { + if (ENODE_IS(left, EMUL) && copts.fp_contract) { + fp_multiply_add( + (type->size == 4) ? PC_FMSUBS : PC_FMSUB, + left->data.diadic.left, + left->data.diadic.right, + right, + outputReg, output); + } else if (ENODE_IS(right, EMUL) && copts.fp_contract) { + fp_multiply_add( + (type->size == 4) ? PC_FNMSUBS : PC_FNMSUB, + right->data.diadic.left, + right->data.diadic.right, + left, + outputReg, output); + } else { + fp_binary_operator( + (type->size == 4) ? PC_FSUBS : PC_FSUB, + left, right, + outputReg, output); + } + return; + } + + if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT(left->data.intval.lo)) + binary_immediate(PC_SUBFIC, right, left->data.intval.lo, outputReg, output); + else + binary_operator(PC_SUBF, right, left, outputReg, output); +} + +void gen_SHL(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + Type *type; + ENode *left; + ENode *right; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + type = expr->rtype; + + if (TYPE_IS_8BYTES(type)) { + I8_gen_SHL_SHR(expr, outputReg, outputRegHi, output); + return; + } + + if (ENODE_IS(right, EINTCONST)) + shift_left_immediate(left, right->data.intval.lo, 0, outputReg, output); + else + binary_operator(PC_SLW, left, right, outputReg, output); +} + +void gen_SHR(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + Type *type; + ENode *left; + ENode *right; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + type = expr->rtype; + + if (TYPE_IS_8BYTES(type)) { + I8_gen_SHL_SHR(expr, outputReg, outputRegHi, output); + return; + } + + if (ENODE_IS(right, EINTCONST)) + shift_right_immediate(left, type, right->data.intval.lo, outputReg, output); + else + binary_operator(is_unsigned(type) ? PC_SRW : PC_SRAW, left, right, outputReg, output); +} + +void gen_AND(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + Type *type; + ENode *left; + ENode *right; + short first; + short last; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + type = expr->rtype; + + if (TYPE_IS_8BYTES(type)) { + I8_gen_AND(expr, outputReg, outputRegHi, output); + return; + } + + if (ENODE_IS(right, EINTCONST) && ismaskconstant(right->data.intval.lo, &first, &last)) { + if (ENODE_IS(left, ESHL) && ENODE_IS(left->data.diadic.right, EINTCONST) && (int)(left->data.diadic.right->data.intval.lo + last) < 32) { + shift_and_mask( + left->data.diadic.left, + left->data.diadic.right->data.intval.lo, + first, last, + outputReg, output); + } else if (ENODE_IS(left, ESHR) && ENODE_IS(left->data.diadic.right, EINTCONST) && (int)left->data.diadic.right->data.intval.lo <= first && last >= first) { + if (left->data.diadic.right->data.intval.lo == 0) + shift_and_mask(left->data.diadic.left, 0, first, last, outputReg, output); + else + shift_and_mask(left->data.diadic.left, 32 - left->data.diadic.right->data.intval.lo, first, last, outputReg, output); + } else { + shift_and_mask(left, 0, first, last, outputReg, output); + } + return; + } + + if (ENODE_IS(right, EINTCONST) && FITS_IN_USHORT(right->data.intval.lo)) { + binary_immediate(PC_ANDI, left, right->data.intval.lo, outputReg, output); + return; + } + if (ENODE_IS(right, EINTCONST) && FITS_IN_HI_SHORT(right->data.intval.lo)) { + binary_immediate(PC_ANDIS, left, right->data.intval.lo >> 16, outputReg, output); + return; + } + + if (ENODE_IS(left, EINTCONST) && ismaskconstant(left->data.intval.lo, &first, &last)) { + if (ENODE_IS(right, ESHL) && ENODE_IS(right->data.diadic.right, EINTCONST) && (int)(right->data.diadic.right->data.intval.lo + last) < 32) { + shift_and_mask( + right->data.diadic.left, + right->data.diadic.right->data.intval.lo, + first, last, + outputReg, output); + } else if (ENODE_IS(right, ESHR) && ENODE_IS(right->data.diadic.right, EINTCONST) && (int)right->data.diadic.right->data.intval.lo <= first) { + if (right->data.diadic.right->data.intval.lo == 0) + shift_and_mask(right->data.diadic.left, 0, first, last, outputReg, output); + else + shift_and_mask(right->data.diadic.left, 32 - right->data.diadic.right->data.intval.lo, first, last, outputReg, output); + } else { + shift_and_mask(right, 0, first, last, outputReg, output); + } + return; + } + + if (ENODE_IS(left, EINTCONST) && FITS_IN_USHORT(left->data.intval.lo)) { + binary_immediate(PC_ANDI, right, left->data.intval.lo, outputReg, output); + return; + } + if (ENODE_IS(left, EINTCONST) && FITS_IN_HI_SHORT(left->data.intval.lo)) { + binary_immediate(PC_ANDIS, right, left->data.intval.lo >> 16, outputReg, output); + return; + } + + if (ENODE_IS(right, EBINNOT)) + binary_operator(PC_ANDC, left, right->data.monadic, outputReg, output); + else if (ENODE_IS(left, EBINNOT)) + binary_operator(PC_ANDC, right, left->data.monadic, outputReg, output); + else + binary_operator(PC_AND, left, right, outputReg, output); +} + +void gen_XOR(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + Type *type; + ENode *left; + ENode *right; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + type = expr->rtype; + + if (TYPE_IS_8BYTES(type)) { + I8_gen_XOR(expr, outputReg, outputRegHi, output); + return; + } + + if (ENODE_IS(left, EINTCONST)) + or_xor_immediate(PC_XORI, right, left->data.intval.lo, outputReg, output); + else if (ENODE_IS(right, EINTCONST)) + or_xor_immediate(PC_XORI, left, right->data.intval.lo, outputReg, output); + else if (ENODE_IS(right, EBINNOT)) + binary_operator(PC_EQV, left, right->data.monadic, outputReg, output); + else if (ENODE_IS(left, EBINNOT)) + binary_operator(PC_EQV, left->data.monadic, right, outputReg, output); + else + binary_operator(PC_XOR, left, right, outputReg, output); +} + +void gen_OR(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + Type *type; + ENode *left; + ENode *right; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + type = expr->rtype; + + if (TYPE_IS_8BYTES(type)) { + I8_gen_OR(expr, outputReg, outputRegHi, output); + return; + } + + if (ENODE_IS(left, EINTCONST)) + or_xor_immediate(PC_ORI, right, left->data.intval.lo, outputReg, output); + else if (ENODE_IS(right, EINTCONST)) + or_xor_immediate(PC_ORI, left, right->data.intval.lo, outputReg, output); + else if (ENODE_IS(right, EBINNOT)) + binary_operator(PC_ORC, left, right->data.monadic, outputReg, output); + else if (ENODE_IS(left, EBINNOT)) + binary_operator(PC_ORC, right, left->data.monadic, outputReg, output); + else + binary_operator(PC_OR, left, right, outputReg, output); +} + +void gen_ASS(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + Type *type; + ENode *left; + ENode *right; + Operand opleft; + Operand opright; + Operand op2; + VarInfo *vi; + SInt32 incval; + short align; + short align2; + + type = expr->rtype; + if (ENODE_IS(expr, ECONDASS)) { + left = expr->data.cond.expr1; + if (ENODE_IS(left, EINDIRECT)) { + left = left->data.monadic; + } else { + CError_FATAL(1759); + } + right = expr->data.cond.expr2; + } else { + left = expr->data.diadic.left; + right = expr->data.diadic.right; + } + + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + memclrw(&op2, sizeof(Operand)); + + if (TYPE_IS_8BYTES(type)) { + I8_gen_ASS(expr, outputReg, outputRegHi, output); + return; + } + + if (ENODE_IS(left, EOBJREF) && OBJECT_REG(left->data.objref)) { + vi = Registers_GetVarInfo(left->data.objref); + GEN_NODE_TO_REG(right, vi->reg, 0, &opright); + switch (vi->rclass) { + case RegClass_GPR: + ENSURE_GPR(&opright, type, vi->reg); + output->optype = OpndType_GPR; + break; + case RegClass_FPR: + ENSURE_FPR(&opright, type, vi->reg); + output->optype = OpndType_FPR; + break; + case RegClass_VR: + ENSURE_VR(&opright, type, vi->reg); + output->optype = OpndType_VR; + break; + default: + CError_FATAL(1810); + } + if (opright.reg != vi->reg) { + PCodeArg a, b; + a.kind = PCOp_REGISTER; + a.arg = vi->rclass; + a.data.reg.reg = vi->reg; + a.data.reg.effect = EffectWrite; + b.kind = PCOp_REGISTER; + b.arg = vi->rclass; + b.data.reg.reg = opright.reg; + b.data.reg.effect = EffectRead; + appendpcode(pclastblock, makecopyinstruction(&b, &a)); + } + output->reg = vi->reg; + return; + } + + if (IS_TYPE_FLOAT(type)) { + GEN_NODE_TO_FPR(right, &opright, right->rtype, 0); + if (ispostincrementopportunity(left, &opleft, &incval)) { + indirect(&opleft, expr); + store_fp(opright.reg, &opleft, type); + add_register_immediate(opleft.reg, opleft.reg, incval); + } else { + GEN_NODE(left, &opleft); + indirect(&opleft, expr); + store_fp(opright.reg, &opleft, type); + } + output->optype = OpndType_FPR; + output->reg = opright.reg; + return; + } + + if (IS_TYPE_VECTOR(type)) { + GEN_NODE(right, &opright); + if (opright.optype == OpndType_Absolute) + ENSURE_VR(&opright, type, 0); + else + ENSURE_VR(&opright, right->rtype, 0); + + if (ispostincrementopportunity(left, &opleft, &incval)) { + indirect(&opleft, expr); + store_v(opright.reg, &opleft, type); + add_register_immediate(opleft.reg, opleft.reg, incval); + } else { + GEN_NODE(left, &opleft); + indirect(&opleft, expr); + store_v(opright.reg, &opleft, type); + } + output->optype = OpndType_VR; + output->reg = opright.reg; + return; + } + + if (TYPE_FITS_IN_REGISTER(type)) { + GEN_NODE_TO_GPR(right, &opright, right->rtype, 0); + + if (ENODE_IS(left, EBITFIELD)) { + GEN_NODE(left->data.monadic, &opleft); + indirect(&opleft, expr); + + op2 = opleft; + ENSURE_GPR(&op2, type, 0); + insert_bitfield(opright.reg, &op2, TYPE_BITFIELD(left->rtype)); + store(op2.reg, &opleft, type); + + if (!expr->ignored) + extract_bitfield(&op2, TYPE_BITFIELD(left->rtype), opright.reg, &opleft); + } else if (ispostincrementopportunity(left, &opleft, &incval)) { + indirect(&opleft, expr); + store(opright.reg, &opleft, type); + add_register_immediate(opleft.reg, opleft.reg, incval); + } else { + GEN_NODE(left, &opleft); + indirect(&opleft, expr); + store(opright.reg, &opleft, type); + } + + output->optype = OpndType_GPR; + output->reg = opright.reg; + return; + } + + GEN_NODE(right, &opright); + GEN_NODE(left, output); + + indirect(output, expr); + if (output->object) { + if (output->object->datatype == DLOCAL && (output->object->u.var.info->flags & VarInfoFlag1)) + align = CMach_ArgumentAlignment(type); + else + align = CMach_AllocationAlignment(type, output->object->qual); + } else { + align = CMach_AllocationAlignment(type, 0); + } + if (opright.object) { + if (opright.object->datatype == DLOCAL && (opright.object->u.var.info->flags & VarInfoFlag1)) + align2 = CMach_ArgumentAlignment(type); + else + align2 = CMach_AllocationAlignment(type, opright.object->qual); + } else { + align2 = CMach_AllocationAlignment(type, 0); + } + + if (align2 < align) + align = align2; + + move_block(output, &opright, type->size, align); +} + +ENode *evaluate_and_skip_comma(ENode *expr) { + Operand op; + ENode *inner; + + memclrw(&op, sizeof(Operand)); + while (ENODE_IS(expr, ECOMMA)) { + inner = expr->data.diadic.left; + GEN_NODE(inner, &op); + if (ENODE_IS(inner, EINDIRECT) && (op.flags & OpndFlags_Volatile)) { + if (TYPE_FITS_IN_REGISTER_2(inner->rtype)) { + ENSURE_GPR(&op, inner->rtype, 0); + } else if (IS_TYPE_FLOAT(inner->rtype)) { + ENSURE_FPR(&op, inner->rtype, 0); + } + } + expr = expr->data.diadic.right; + } + return expr; +} + +void gen_COMMA(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *left; + ENode *right; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + GEN_NODE(left, output); + + if (ENODE_IS(left, EINDIRECT) && (output->flags & OpndFlags_Volatile)) { + if (TYPE_FITS_IN_REGISTER_2(left->rtype)) { + ENSURE_GPR(output, left->rtype, 0); + } else if (IS_TYPE_FLOAT(left->rtype)) { + ENSURE_FPR(output, left->rtype, 0); + } + } + + GEN_NODE_TO_REG(right, outputReg, 0, output); +} + +void gen_TYPCON(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *inner; + Type *srctype; + Type *dsttype; + + inner = expr->data.monadic; + srctype = inner->rtype; + dsttype = expr->rtype; + + if (TYPE_IS_8BYTES(srctype) || TYPE_IS_8BYTES(dsttype)) { + I8_gen_TYPCON(expr, outputReg, outputRegHi, output); + return; + } + + if (IS_TYPE_VOID(dsttype)) { + GEN_NODE(inner, output); + if (ENODE_IS(inner, EINDIRECT) && (output->flags & OpndFlags_Volatile)) { + if (TYPE_FITS_IN_REGISTER_2(srctype)) { + ENSURE_GPR(output, srctype, 0); + } else if (IS_TYPE_FLOAT(srctype)) { + ENSURE_FPR(output, srctype, 0); + } + } + } else if (IS_TYPE_INT_OR_ENUM(srctype)) { + if (IS_TYPE_FLOAT(dsttype)) { + GEN_NODE(inner, output); + if (srctype->size < 4) + extend32(output, srctype, 0); + ENSURE_GPR(output, srctype, 0); + + if (is_unsigned(srctype)) + convert_unsigned_to_floating(output, dsttype->size == 4, outputReg); + else + convert_integer_to_floating(output, dsttype->size == 4, outputReg); + } else if (IS_TYPE_VECTOR(dsttype)) { + GEN_NODE_TO_REG(inner, outputReg, 0, output); + ENSURE_VR(output, dsttype, outputReg); + } else if ( + srctype->size < dsttype->size && + !ENODE_IS_INDIRECT_TO(inner, EBITFIELD) && + !ENODE_IS_ASSIGN_TO(inner, EBITFIELD) && + !(ENODE_IS_RANGE(inner, EPOSTINC, EPREDEC) && ENODE_IS(inner->data.monadic->data.monadic, EBITFIELD)) + ) { + GEN_NODE(inner, output); + extend32(output, srctype, outputReg); + } else if (dsttype->size < srctype->size || dsttype->size < 4) { + GEN_NODE(inner, output); + ENSURE_GPR(output, srctype, 0); + extend32(output, dsttype, outputReg); + } else { + GEN_NODE_TO_REG(inner, outputReg, 0, output); + } + } else if (IS_TYPE_POINTER(srctype)) { + GEN_NODE_TO_REG(inner, outputReg, 0, output); + if (dsttype->size < srctype->size) + ENSURE_GPR(output, srctype, outputReg); + } else if (IS_TYPE_FLOAT(srctype)) { + if (IS_TYPE_FLOAT(dsttype)) { + GEN_NODE_TO_REG(inner, outputReg, 0, output); + ENSURE_FPR(output, srctype, outputReg); + + if (dsttype->size == 4 && srctype->size != 4) { + int tmp = outputReg ? outputReg : ALLOC_FPR(); + emitpcode(PC_FRSP, tmp, output->reg); + output->optype = OpndType_FPR; + output->reg = tmp; + } + } else if (is_unsigned(dsttype) && dsttype->size == 4) { + GEN_NODE_TO_REG(inner, 1, 0, output); + ENSURE_FPR(output, srctype, 1); + convert_floating_to_unsigned(output, outputReg); + } else { + GEN_NODE_TO_REG(inner, 0, 0, output); + ENSURE_FPR(output, srctype, 0); + convert_floating_to_integer(output, outputReg); + } + } else if (IS_TYPE_VECTOR(srctype) && IS_TYPE_VECTOR(dsttype)) { + GEN_NODE_TO_REG(inner, outputReg, 0, output); + ENSURE_VR(output, srctype, outputReg); + } else if (srctype->size == dsttype->size) { + GEN_NODE_TO_REG(inner, outputReg, 0, output); + } else { + CError_FATAL(2224); + } +} + +void gen_BITFIELD(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + CError_FATAL(2238); +} + +void gen_INTCONST(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + if (TYPE_IS_8BYTES(expr->rtype)) { + I8_gen_INTCONST(expr, outputReg, outputRegHi, output); + return; + } + + output->optype = OpndType_Absolute; + output->immediate = CInt64_GetULong(&expr->data.intval); +} + +void gen_FLOATCONST(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + CError_FATAL(2294); +} + +void gen_STRINGCONST(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + CError_FATAL(2308); +} + +static Boolean COND_is_ABS_MatchNodes(ENode *cond, ENode *expr1, ENode *expr2) { + if (cond->type != expr1->type || cond->type != expr2->type) + return 0; + + if (!(TYPE_FITS_IN_REGISTER(cond->rtype) && TYPE_FITS_IN_REGISTER(expr1->rtype) && TYPE_FITS_IN_REGISTER(expr2->rtype))) + return 0; + + if (cond->rtype->size != expr1->rtype->size || cond->rtype->size != expr2->rtype->size) + return 0; + + switch (cond->type) { + case EOBJREF: + if (cond->data.objref != expr1->data.objref || cond->data.objref != expr2->data.objref) + return 0; + return 1; + case EINDIRECT: + case ETYPCON: + return COND_is_ABS_MatchNodes(cond->data.monadic, expr1->data.monadic, expr2->data.monadic); + default: + return 0; + } +} + +static ENode *COND_is_ABS(ENode *cond, ENode *expr1, ENode *expr2) { + ENode *tmp; + + int parity = 0; + while (ENODE_IS(cond, ELOGNOT)) { + parity = (parity + 1) & 1; + cond = cond->data.monadic; + } + + if (parity) { + tmp = expr1; + expr1 = expr2; + expr2 = tmp; + } + + switch (cond->type) { + case ELESS: + case ELESSEQU: + tmp = expr1; + expr1 = expr2; + expr2 = tmp; + break; + case EGREATER: + case EGREATEREQU: + break; + default: + return NULL; + } + + if (IS_INT_CONST_ZERO(cond->data.diadic.right)) { + cond = cond->data.diadic.left; + } else if (IS_INT_CONST_ZERO(cond->data.diadic.left)) { + cond = cond->data.diadic.left; + tmp = expr1; + expr1 = expr2; + expr2 = tmp; + } else { + return NULL; + } + + if (ENODE_IS(expr1, EADD) && ENODE_IS(expr2, ESUB)) { + if (COND_is_ABS_MatchNodes(cond, expr1->data.diadic.right, expr2->data.diadic.right)) + return expr1; + else + return NULL; + } + + if (!ENODE_IS(expr2, EMONMIN)) + return NULL; + + expr2 = expr2->data.monadic; + if (COND_is_ABS_MatchNodes(cond, expr1, expr2)) + return expr1; + + return NULL; +} + +static int COND_has_const(ENode *expr1, ENode *expr2) { + SInt32 diff; + int result = 0; + + if (IS_INT_CONST(expr1)) + result += 1; + if (IS_INT_CONST(expr2)) + result += 2; + + if (result & 1) { + if (IS_INT_CONST_ZERO(expr1)) + return 5; + } + if (result & 2) { + if (IS_INT_CONST_ZERO(expr2)) + return 6; + } + + if (result == 3) { + diff = expr1->data.intval.lo - expr2->data.intval.lo; + if (diff == 1 || diff == -1) + return 4; + } + + return result; +} + +static Boolean COND_is_COMPARE(ENode *cond, ENode *expr1, ENode *expr2, short outputReg, Operand *output) { + SInt32 left; + SInt32 right; + int parity; + int negate; + ENodeType nt; + + while (ENODE_IS(expr1, ETYPCON) && TYPE_FITS_IN_REGISTER(expr1->rtype)) + expr1 = expr1->data.monadic; + while (ENODE_IS(expr2, ETYPCON) && TYPE_FITS_IN_REGISTER(expr2->rtype)) + expr2 = expr2->data.monadic; + + if (!(ENODE_IS(expr1, EINTCONST) && TYPE_FITS_IN_REGISTER(expr1->rtype) && CInt64_IsInRange(expr1->data.intval, 4))) + return 0; + if (!(ENODE_IS(expr2, EINTCONST) && TYPE_FITS_IN_REGISTER(expr2->rtype) && CInt64_IsInRange(expr2->data.intval, 4))) + return 0; + + left = CInt64_GetULong(&expr1->data.intval); + right = CInt64_GetULong(&expr2->data.intval); + parity = 0; + negate = 0; + switch (left) { + case 1: + if (right != 0) + return 0; + break; + case 0: + parity = 1; + if (right == -1) + negate = 1; + else if (right != 1) + return 0; + break; + case -1: + if (right != 0) + return 0; + negate = 1; + break; + default: + return 0; + } + + while (ENODE_IS(cond, ELOGNOT)) { + parity = (parity + 1) & 1; + cond = cond->data.monadic; + } + + if (parity) { + nt = invert_relop(cond->type); + if (nt == cond->type) + return 0; + cond->type = nt; + } + + if (negate) + gen_negated_condition_gpr(cond, output, outputReg); + else + gen_condition_gpr(cond, output, outputReg); + + return 1; +} + +void gen_COND(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *cond; + ENode *expr1; + ENode *expr2; + Type *type; + PCodeLabel *label1; + PCodeLabel *label2; + PCodeLabel *label3; + Operand op1; + Operand op2; + int has_const; + int reg1; + int reg2; + int reg3; + short align; + short max_align; + + expr1 = expr->data.cond.expr1; + expr2 = expr->data.cond.expr2; + type = expr->rtype; + + label1 = makepclabel(); + label2 = makepclabel(); + label3 = makepclabel(); + + memclrw(&op1, sizeof(Operand)); + memclrw(&op2, sizeof(Operand)); + + cond = evaluate_and_skip_comma(expr->data.cond.cond); + + if (TOC_use_fsel(expr)) { + ENode *left; + ENode *right; + ENode *tmp; + ENodeType nt; + Boolean flag; + Operand op; + int fneg_reg; + int fneg_reg2; + int fneg_reg3; + int fsel_reg; + int final_reg; + + left = cond->data.diadic.left; + right = cond->data.diadic.right; + nt = cond->type; + flag = 0; + memclrw(&op, sizeof(Operand)); + + switch (nt) { + case EGREATEREQU: + case EEQU: + break; + case EGREATER: + tmp = left; + left = right; + right = tmp; + case ELESS: + case ENOTEQU: + tmp = expr1; + expr1 = expr2; + expr2 = tmp; + break; + case ELESSEQU: + tmp = left; + left = right; + right = tmp; + break; + default: + CError_FATAL(2780); + } + + if (ENODE_IS(left, EFLOATCONST) && CMach_FloatIsZero(left->data.floatval)) { + GEN_NODE(right, &op); + ENSURE_FPR(&op, right->rtype, 0); + flag = 1; + } else if (ENODE_IS(right, EFLOATCONST) && CMach_FloatIsZero(right->data.floatval)) { + GEN_NODE(left, &op); + ENSURE_FPR(&op, left->rtype, 0); + } else { + fp_binary_operator((type->size == 4) ? PC_FSUBS : PC_FSUB, left, right, 0, &op); + } + + switch (cond->type) { + case EEQU: + case ENOTEQU: + if (flag) { + GEN_NODE_TO_FPR(expr1, &op1, expr1->rtype, 0); + GEN_NODE_TO_FPR(expr2, &op2, expr2->rtype, 0); + + fneg_reg = ALLOC_FPR(); + emitpcode(PC_FNEG, fneg_reg, op.reg); + fsel_reg = ALLOC_FPR(); + emitpcode(PC_FSEL, fsel_reg, op.reg, op1.reg, op2.reg); + final_reg = outputReg ? outputReg : ALLOC_FPR(); + emitpcode(PC_FSEL, final_reg, fneg_reg, fsel_reg, op2.reg); + } else { + GEN_NODE_TO_FPR(expr1, &op1, expr1->rtype, 0); + GEN_NODE_TO_FPR(expr2, &op2, expr2->rtype, 0); + + fneg_reg2 = ALLOC_FPR(); + emitpcode(PC_FNEG, fneg_reg2, op.reg); + fsel_reg = ALLOC_FPR(); + emitpcode(PC_FSEL, fsel_reg, op.reg, op1.reg, op2.reg); + final_reg = outputReg ? outputReg : ALLOC_FPR(); + emitpcode(PC_FSEL, final_reg, fneg_reg2, fsel_reg, op2.reg); + } + break; + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + GEN_NODE_TO_FPR(expr1, &op1, expr1->rtype, 0); + GEN_NODE_TO_FPR(expr2, &op2, expr2->rtype, 0); + + fneg_reg3 = op.reg; + if (flag) { + fneg_reg3 = ALLOC_FPR(); + emitpcode(PC_FNEG, fneg_reg3, op.reg); + } + + final_reg = outputReg ? outputReg : ALLOC_FPR(); + emitpcode(PC_FSEL, final_reg, fneg_reg3, op1.reg, op2.reg); + break; + default: + CError_FATAL(2862); + } + + output->optype = OpndType_FPR; + output->reg = final_reg; + return; + } + + if (TOC_use_isel(expr, 1)) { + Operand isel_op1; + Operand isel_op2; + ENode *x; + ENode *y; + ENode *abs_expr; + + memclrw(&isel_op1, sizeof(Operand)); + memclrw(&isel_op2, sizeof(Operand)); + + if (COND_is_COMPARE(cond, expr1, expr2, outputReg, output)) + return; + + if ((abs_expr = COND_is_ABS(cond, expr1, expr2))) { + if (ENODE_IS(expr1, EADD) && ENODE_IS(expr2, ESUB)) { + x = expr1->data.diadic.left; + y = expr2->data.diadic.right; + if (y->hascall) { + GEN_NODE(y, &op2); + ENSURE_GPR(&op2, y->rtype, 0); + + GEN_NODE(x, &op1); + if (op1.optype >= OpndType_IndirectGPR_ImmOffset) + ENSURE_GPR(&op1, x->rtype, 0); + } else { + GEN_NODE(x, &op1); + if (op1.optype >= OpndType_IndirectGPR_ImmOffset) + ENSURE_GPR(&op1, x->rtype, 0); + + GEN_NODE(y, &op2); + ENSURE_GPR(&op2, y->rtype, 0); + } + + reg1 = ALLOC_GPR(); + emitpcode(PC_SRAWI, reg1, op2.reg, 31); + reg2 = ALLOC_GPR(); + emitpcode(PC_XOR, reg2, reg1, op2.reg); + reg3 = ALLOC_GPR(); + emitpcode(PC_SUBF, reg3, reg1, reg2); + op2.optype = OpndType_GPR; + op2.reg = reg3; + combine(&op1, &op2, outputReg, output); + } else { + GEN_NODE(abs_expr, output); + ENSURE_GPR(output, abs_expr->rtype, 0); + + reg1 = ALLOC_GPR(); + emitpcode(PC_SRAWI, reg1, output->reg, 31); + reg2 = ALLOC_GPR(); + emitpcode(PC_XOR, reg2, reg1, output->reg); + reg3 = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SUBF, reg3, reg1, reg2); + output->optype = OpndType_GPR; + output->reg = reg3; + } + return; + } + + if ((has_const = COND_has_const(expr1, expr2))) { + switch (COND_has_const(expr1, expr2)) { + case 0: + case 2: + break; + case 3: + case 4: + if (has_const == 4) { + if (expr1->data.intval.lo < expr2->data.intval.lo) + gen_negated_condition_gpr(cond, &isel_op1, 0); + else + gen_condition_gpr(cond, &isel_op1, 0); + + GEN_NODE(expr1, &op1); + GEN_NODE(expr2, &op2); + reg1 = ALLOC_GPR(); + ENSURE_GPR(&op2, expr2->rtype, reg1); + emitpcode(PC_ADD, reg1, isel_op1.reg, op2.reg); + if (outputReg) { + emitpcode(PC_MR, reg2 = outputReg, reg1); + reg1 = reg2; + } + output->optype = OpndType_GPR; + output->reg = reg1; + return; + } + break; + case 5: + case 6: + gen_negated_condition_gpr(cond, &isel_op1, 0); + ENSURE_GPR(&isel_op1, TYPE(&stunsignedint), 0); + GEN_NODE(expr1, &op1); + GEN_NODE(expr2, &op2); + + reg1 = outputReg ? outputReg : ALLOC_GPR(); + if (op1.optype == OpndType_Absolute && op1.immediate == 0) { + ENSURE_GPR(&op2, expr2->rtype, 0); + emitpcode(PC_ANDC, reg1, op2.reg, isel_op1.reg); + } else if (op2.optype == OpndType_Absolute && op2.immediate == 0) { + ENSURE_GPR(&op1, expr1->rtype, 0); + emitpcode(PC_AND, reg1, op1.reg, isel_op1.reg); + } else { + CError_FATAL(3119); + } + + output->optype = OpndType_GPR; + output->reg = reg1; + return; + case 1: + reg2 = ALLOC_GPR(); + reg1 = reg2; + logical_expression_nobranch(cond, 0, &isel_op2); + + GEN_NODE_TO_REG(expr1, reg1, 0, &op1); + ENSURE_GPR(&op1, expr1->rtype, reg1); + if (op1.reg != reg1) + emitpcode(PC_MR, reg1, op1.reg); + + branch_conditional(isel_op2.reg, isel_op2.regOffset, 1, label2); + branch_label(label1); + + GEN_NODE_TO_REG(expr2, reg1, 0, &op2); + ENSURE_GPR(&op2, expr2->rtype, reg1); + if (op2.reg != reg1) + emitpcode(PC_MR, reg1, op2.reg); + + branch_label(label2); + + if (outputReg) { + emitpcode(PC_MR, reg2 = outputReg, reg1); + reg1 = reg2; + } + + output->optype = OpndType_GPR; + output->reg = reg1; + return; + + default: + CError_FATAL(3168); + } + } + + reg1 = ALLOC_GPR(); + logical_expression_nobranch(cond, 0, &isel_op2); + + GEN_NODE_TO_REG(expr2, reg1, 0, &op2); + ENSURE_GPR(&op2, expr2->rtype, reg1); + if (op2.reg != reg1) + emitpcode(PC_MR, reg1, op2.reg); + + branch_conditional(isel_op2.reg, isel_op2.regOffset, 0, label2); + branch_label(label1); + + GEN_NODE_TO_REG(expr1, reg1, 0, &op1); + ENSURE_GPR(&op1, expr1->rtype, reg1); + if (op1.reg != reg1) + emitpcode(PC_MR, reg1, op1.reg); + + branch_label(label2); + + if (outputReg) { + emitpcode(PC_MR, reg2 = outputReg, reg1); + reg1 = reg2; + } + + output->optype = OpndType_GPR; + output->reg = reg1; + return; + } + + logical_expression(cond, label1, label2, label1); + branch_label(label1); + + if (IS_TYPE_VOID(type) || expr->ignored) { + GEN_NODE(expr1, &op1); + branch_always(label3); + branch_label(label2); + GEN_NODE(expr2, &op2); + } else if (IS_TYPE_FLOAT(type)) { + if (expr1->hascall || expr2->hascall) + reg1 = ALLOC_FPR(); + else + reg1 = outputReg ? outputReg : ALLOC_FPR(); + + GEN_NODE_TO_REG(expr1, reg1, 0, &op1); + ENSURE_FPR(&op1, expr1->rtype, reg1); + if (op1.reg != reg1) + emitpcode(PC_FMR, reg1, op1.reg); + + branch_always(label3); + branch_label(label2); + + GEN_NODE_TO_REG(expr2, reg1, 0, &op2); + ENSURE_FPR(&op2, expr2->rtype, reg1); + if (op2.reg != reg1) + emitpcode(PC_FMR, reg1, op2.reg); + + output->optype = OpndType_FPR; + output->reg = reg1; + } else if (TYPE_IS_8BYTES(type)) { + if (expr1->hascall || expr2->hascall) { + reg1 = ALLOC_GPR(); + reg3 = ALLOC_GPR(); + reg2 = reg3; + } else { + reg1 = outputReg ? outputReg : ALLOC_GPR(); + reg3 = outputRegHi ? outputRegHi : ALLOC_GPR(); + reg2 = reg3; + } + + GEN_NODE_TO_REG(expr1, reg1, reg2, &op1); + coerce_to_register_pair(&op1, expr1->rtype, reg1, reg2); + + branch_always(label3); + branch_label(label2); + + GEN_NODE_TO_REG(expr2, reg1, reg2, &op2); + coerce_to_register_pair(&op2, expr2->rtype, reg1, reg2); + + output->optype = OpndType_GPRPair; + output->reg = reg1; + output->regHi = reg2; + } else if (TYPE_FITS_IN_REGISTER(type)) { + if (expr1->hascall || expr2->hascall) + reg1 = ALLOC_GPR(); + else + reg1 = outputReg ? outputReg : ALLOC_GPR(); + + GEN_NODE_TO_REG(expr1, reg1, 0, &op1); + ENSURE_GPR(&op1, expr1->rtype, reg1); + if (op1.reg != reg1) + emitpcode(PC_MR, reg1, op1.reg); + + branch_always(label3); + branch_label(label2); + + GEN_NODE_TO_REG(expr2, reg1, 0, &op2); + ENSURE_GPR(&op2, expr2->rtype, reg1); + if (op2.reg != reg1) + emitpcode(PC_MR, reg1, op2.reg); + + output->optype = OpndType_GPR; + output->reg = reg1; + } else if (IS_TYPE_VECTOR(type)) { + if (expr1->hascall || expr2->hascall) + reg1 = ALLOC_VR(); + else + reg1 = outputReg ? outputReg : ALLOC_VR(); + + GEN_NODE_TO_REG(expr1, reg1, 0, &op1); + ENSURE_VR(&op1, expr1->rtype, reg1); + if (op1.reg != reg1) + emitpcode(PC_VMR, reg1, op1.reg); + + branch_always(label3); + branch_label(label2); + + GEN_NODE_TO_REG(expr2, reg1, 0, &op2); + ENSURE_VR(&op2, expr2->rtype, reg1); + if (op2.reg != reg1) + emitpcode(PC_VMR, reg1, op2.reg); + + output->optype = OpndType_VR; + output->reg = reg1; + } else { + symbol_operand(output, maketemporary(type)); + indirect(output, NULL); + coerce_to_addressable(output); + + GEN_NODE(expr1, &op1); + + if (op1.object) { + if (op1.object->datatype == DLOCAL && (op1.object->u.var.info->flags & VarInfoFlag1)) + align = CMach_ArgumentAlignment(type); + else + align = CMach_AllocationAlignment(type, op1.object->qual); + } else { + align = CMach_AllocationAlignment(type, 0); + } + + max_align = CMach_AllocationAlignment(type, 0); + if (align > max_align) + align = max_align; + + move_block(output, &op1, type->size, align); + + branch_always(label3); + branch_label(label2); + + GEN_NODE(expr2, &op2); + + if (op2.object) { + if (op2.object->datatype == DLOCAL && (op2.object->u.var.info->flags & VarInfoFlag1)) + align = CMach_ArgumentAlignment(type); + else + align = CMach_AllocationAlignment(type, op2.object->qual); + } else { + align = CMach_AllocationAlignment(type, 0); + } + + if (align > max_align) + align = max_align; + + move_block(output, &op2, type->size, align); + } + + branch_label(label3); +} + +static Boolean CONDASS_is_ABS(ENode *cond, ENode *expr1, ENode *expr2) { + ENode *inner; + + int parity = 0; + while (ENODE_IS(cond, ELOGNOT)) { + parity = (parity + 1) & 1; + cond = cond->data.monadic; + } + + if (IS_INT_CONST_ZERO(cond->data.diadic.right)) { + inner = cond->data.diadic.left; + } else if (IS_INT_CONST_ZERO(cond->data.diadic.left)) { + inner = cond->data.diadic.left; + parity = (parity + 1) & 1; + } else { + return 0; + } + + switch (cond->type) { + case EGREATER: + case EGREATEREQU: + if (!parity) + return 0; + break; + case ELESS: + case ELESSEQU: + if (parity) + return 0; + break; + default: + return 0; + } + + if (!ENODE_IS(expr2, EMONMIN)) + return 0; + + expr2 = expr2->data.monadic; + if (ENODE_IS(inner, EASS)) { + inner = inner->data.diadic.left; + if (!ENODE_IS(expr2, EINDIRECT)) + return 0; + expr2 = expr2->data.monadic; + if (!ENODE_IS(expr1, EINDIRECT)) + return 0; + expr1 = expr1->data.monadic; + } + + return COND_is_ABS_MatchNodes(inner, expr1, expr2); +} + +static int CONDASS_is_OPASS_One(ENode *a, ENode *b, SInt32 *value, ENodeType *nodetype) { + Type *type; + + type = a->rtype; + if (!ENODE_IS(a, EINDIRECT)) + return 0; + a = a->data.monadic; + if (!ENODE_IS(a, EOBJREF)) + return 0; + + if (ENODE_IS(b, ETYPCON) && b->rtype == type) + b = b->data.monadic; + + if (b->type != EOR && b->type != EADD && b->type != ESUB) + return 0; + + *nodetype = b->type; + if (!IS_INT_CONST(b->data.diadic.right)) + return 0; + *value = b->data.diadic.right->data.intval.lo; + + if (*value != 1 && *value != -1) + return 0; + + b = b->data.diadic.left; + if (ENODE_IS(b, ETYPCON) && TYPE_FITS_IN_REGISTER(b->rtype)) + b = b->data.monadic; + + if (!ENODE_IS(b, EINDIRECT)) + return 0; + b = b->data.monadic; + if (!ENODE_IS(b, EOBJREF)) + return 0; + + if (a->data.objref == b->data.objref) + return 1; + return 0; +} + +void gen_CONDASS(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *cond; + ENode *expr1; + ENode *expr2; + Type *type; + PCodeLabel *label1; + PCodeLabel *label2; + Operand op1; + Operand op2; + Operand op3; + int reg1; + int reg2; + + expr1 = expr->data.cond.expr1; + expr2 = expr->data.cond.expr2; + type = expr->rtype; + + label1 = makepclabel(); + label2 = makepclabel(); + + memclrw(&op1, sizeof(Operand)); + memclrw(&op2, sizeof(Operand)); + memclrw(&op3, sizeof(Operand)); + + cond = evaluate_and_skip_comma(expr->data.cond.cond); + + if (TOC_use_fsel(expr)) { + ENode *left; + ENode *right; + ENode *tmp; + ENodeType nt; + Boolean flag; + Boolean flag2; + Operand op; + int tmpreg; + int fneg_reg; + int fsel_reg; + int final_reg; + + left = cond->data.diadic.left; + right = cond->data.diadic.right; + nt = cond->type; + flag = 0; + memclrw(&op, sizeof(Operand)); + + CError_ASSERT(3704, ENODE_IS(expr1, EINDIRECT)); + CError_ASSERT(3705, ENODE_IS(expr1->data.monadic, EOBJREF)); + + tmpreg = OBJECT_REG(expr1->data.monadic->data.objref); + final_reg = outputReg ? tmpreg : ALLOC_FPR(); + + switch (nt) { + case EGREATER: + tmp = left; + left = right; + right = tmp; + case ELESS: + case ENOTEQU: + tmp = expr1; + expr1 = expr2; + expr2 = tmp; + flag2 = 1; + break; + case ELESSEQU: + tmp = left; + left = right; + right = tmp; + flag2 = 0; + break; + case EGREATEREQU: + case EEQU: + flag2 = 0; + break; + default: + CError_FATAL(3744); + } + + if (ENODE_IS(left, EFLOATCONST) && CMach_FloatIsZero(left->data.floatval)) { + GEN_NODE(right, &op); + ENSURE_FPR(&op, right->rtype, 0); + flag = 1; + } else if (ENODE_IS(right, EFLOATCONST) && CMach_FloatIsZero(right->data.floatval)) { + GEN_NODE(left, &op); + ENSURE_FPR(&op, left->rtype, 0); + } else { + fp_binary_operator((type->size == 4) ? PC_FSUBS : PC_FSUB, left, right, 0, &op); + } + + switch (cond->type) { + case EEQU: + case ENOTEQU: + if (flag) { + GEN_NODE(expr1, &op1); + op3 = op1; + ENSURE_FPR(&op1, expr1->rtype, 0); + + GEN_NODE_TO_FPR(expr2, &op2, expr2->rtype, 0); + + fneg_reg = ALLOC_FPR(); + emitpcode(PC_FNEG, fneg_reg, op.reg); + fsel_reg = ALLOC_FPR(); + emitpcode(PC_FSEL, fsel_reg, op.reg, op2.reg, op1.reg); + emitpcode(PC_FSEL, final_reg, fneg_reg, op2.reg, fsel_reg); + } else { + GEN_NODE(expr1, &op1); + op3 = op1; + ENSURE_FPR(&op1, expr1->rtype, 0); + + GEN_NODE_TO_FPR(expr2, &op2, expr2->rtype, 0); + + fneg_reg = ALLOC_FPR(); + emitpcode(PC_FNEG, fneg_reg, op.reg); + fsel_reg = ALLOC_FPR(); + emitpcode(PC_FSEL, fsel_reg, op.reg, op2.reg, op1.reg); + emitpcode(PC_FSEL, final_reg, fneg_reg, op2.reg, fsel_reg); + } + break; + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + GEN_NODE(expr1, &op1); + GEN_NODE(expr2, &op2); + op3 = flag2 ? op2 : op1; + + ENSURE_FPR(&op1, expr1->rtype, 0); + ENSURE_FPR(&op2, expr2->rtype, 0); + + fneg_reg = op.reg; + if (flag) { + fneg_reg = ALLOC_FPR(); + emitpcode(PC_FNEG, fneg_reg, op.reg); + } + + emitpcode(PC_FSEL, final_reg, fneg_reg, op2.reg, op1.reg); + break; + default: + CError_FATAL(2862); + } + + if (op3.optype != OpndType_FPR) + store_fp(final_reg, &op3, type); + + output->optype = OpndType_FPR; + output->reg = final_reg; + return; + } + + if (TOC_use_isel(expr, 1)) { + Operand isel_op; + ENode *x; + ENode *y; + ENode *abs_expr; + + memclrw(&isel_op, sizeof(Operand)); + CError_ASSERT(3966, ENODE_IS(expr1, EINDIRECT)); + CError_ASSERT(3968, ENODE_IS(expr1->data.monadic, EOBJREF)); + + if (CONDASS_is_ABS(cond, expr1, expr2)) { + if (ENODE_IS(cond->data.diadic.left, EASS)) + GEN_NODE(cond->data.diadic.left, &isel_op); + else if (ENODE_IS(cond->data.diadic.right, EASS)) + GEN_NODE(cond->data.diadic.right, &isel_op); + + outputReg = OBJECT_REG(expr1->data.monadic->data.objref); + CError_ASSERT(3979, outputReg); + + GEN_NODE(expr1, &op1); + op3 = op1; + + CError_ASSERT(3986, op3.optype == OpndType_GPR && op3.reg == outputReg); + + ENSURE_GPR(&op1, expr1->rtype, 0); + if (expr1->rtype->size < 4) + extend32(output, expr1->rtype, op3.reg); + + reg1 = ALLOC_GPR(); + reg2 = ALLOC_GPR(); + emitpcode(PC_SRAWI, reg1, op1.reg, 31); + emitpcode(PC_XOR, reg2, reg1, op1.reg); + emitpcode(PC_SUBF, outputReg, reg1, reg2); + output->optype = OpndType_GPR; + output->reg = op3.reg; + + if (expr1->rtype->size < 4) + extend32(output, expr1->rtype, op3.reg); + + return; + } + } + + logical_expression(cond, label1, label2, label1); + branch_label(label1); + gen_ASS(expr, outputReg, outputRegHi, output); + branch_label(label2); +} + +void gen_FUNCCALL(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + if (is_intrinsic_function_call(expr)) + call_intrinsic_function(expr, outputReg, output); + else + call_function(expr, output); +} + +void gen_OBJREF(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + symbol_operand(output, expr->data.objref); +} + +void gen_UNEXPECTED(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + CError_FATAL(4160); +} + +static int small(ENode *expr) { + Type *type; + + type = expr->rtype; + if (!ENODE_IS(expr, ETYPCON)) + return 0; + + do { + expr = expr->data.monadic; + } while (ENODE_IS(expr, ETYPCON) && (type = expr->rtype)->size == 4); + + return IS_TYPE_INT_OR_ENUM(type) && ((type->size < 2) || (type->size == 2 && !is_unsigned(type))); +} + +void binary_operator(Opcode opcode, ENode *left, ENode *right, short outputReg, Operand *output) { + Operand opleft; + Operand opright; + int reg; + + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + + if (right->hascall) { + GEN_NODE_TO_GPR(right, &opright, right->rtype, 0); + GEN_NODE_TO_GPR(left, &opleft, left->rtype, 0); + } else { + GEN_NODE_TO_GPR(left, &opleft, left->rtype, 0); + GEN_NODE_TO_GPR(right, &opright, right->rtype, 0); + } + + reg = outputReg ? outputReg : ALLOC_GPR(); + + if (opcode == PC_MULLW && small(left)) + emitpcode(opcode, reg, opright.reg, opleft.reg); + else + emitpcode(opcode, reg, opleft.reg, opright.reg); + + output->optype = OpndType_GPR; + output->reg = reg; +} + +static void binary_immediate(Opcode opcode, ENode *left, SInt32 value, short outputReg, Operand *output) { + Operand opleft; + int reg; + + memclrw(&opleft, sizeof(Operand)); + GEN_NODE_TO_GPR(left, &opleft, left->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_GPR(); + + if (opcode == PC_MULLI && value == 0) + emitpcode(PC_LI, reg, 0); + else if (opcode == PC_MULLI && value == 1) + emitpcode(PC_MR, reg, opleft.reg); + else + emitpcode(opcode, reg, opleft.reg, value); + + output->optype = OpndType_GPR; + output->reg = reg; +} + +void unary_operator(Opcode opcode, ENode *expr, short outputReg, Operand *output) { + Operand op; + int reg; + + memclrw(&op, sizeof(Operand)); + GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(opcode, reg, op.reg); + + output->optype = OpndType_GPR; + output->reg = reg; +} + +static void or_xor_immediate(Opcode opcode, ENode *expr, SInt32 value, short outputReg, Operand *output) { + Operand op; + int reg; + + memclrw(&op, sizeof(Operand)); + GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_GPR(); + + if (expr->rtype->size > 2 && value != (value & 0xFFFF)) { + if (value & 0xFFFF) { + emitpcode((opcode == PC_ORI) ? PC_ORIS : PC_XORIS, reg, op.reg, value >> 16); + emitpcode(opcode, reg, reg, value & 0xFFFF); + } else { + emitpcode((opcode == PC_ORI) ? PC_ORIS : PC_XORIS, reg, op.reg, value >> 16); + } + } else { + emitpcode(opcode, reg, op.reg, value & 0xFFFF); + } + + output->optype = OpndType_GPR; + output->reg = reg; +} + +static void shift_left_immediate(ENode *expr, short shift, short negate, short outputReg, Operand *output) { + Operand op; + int reg; + + memclrw(&op, sizeof(Operand)); + GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); + + if (negate) + reg = ALLOC_GPR(); + else + reg = outputReg ? outputReg : ALLOC_GPR(); + + emitpcode(PC_RLWINM, reg, op.reg, shift & 31, 0, 31 - (shift & 31)); + + if (negate) { + int tmp = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_NEG, tmp, reg); + reg = tmp; + } + + output->optype = OpndType_GPR; + output->reg = reg; +} + +static void shift_right_immediate(ENode *expr, Type *type, short shift, short outputReg, Operand *output) { + Operand op; + int reg; + + memclrw(&op, sizeof(Operand)); + GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_GPR(); + + if (is_unsigned(type)) + emitpcode(PC_RLWINM, reg, op.reg, (32 - (shift & 31)) & 31, (shift & 31) + (32 - (type->size * 8)), 31); + else + emitpcode(PC_SRAWI, reg, op.reg, shift & 31); + + output->optype = OpndType_GPR; + output->reg = reg; +} + +static void signed_divide_by_power_of_2(ENode *expr, int shift, int negate, short outputReg, Operand *output) { + Operand op; + int reg; + int tmpreg1; + int tmpreg2; + + memclrw(&op, sizeof(Operand)); + GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); + + if (!copts.optimizesize && shift == 1) { + tmpreg1 = ALLOC_GPR(); + emitpcode(PC_RLWINM, tmpreg1, op.reg, 1, 31, 31); + tmpreg2 = ALLOC_GPR(); + emitpcode(PC_ADD, tmpreg2, tmpreg1, op.reg); + reg = (outputReg && !negate) ? outputReg : ALLOC_GPR(); + emitpcode(PC_SRAWI, reg, tmpreg2, 1); + } else { + tmpreg1 = ALLOC_GPR(); + emitpcode(PC_SRAWI, tmpreg1, op.reg, shift); + reg = (outputReg && !negate) ? outputReg : ALLOC_GPR(); + emitpcode(PC_ADDZE, reg, tmpreg1); + } + + if (negate) { + int prevreg = reg; + reg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_NEG, reg, prevreg); + } + + output->optype = OpndType_GPR; + output->reg = reg; +} + +static void signed_mod_by_power_of_2(ENode *expr, int shift, int negate, short outputReg, Operand *output) { + Operand op; + int reg; + int tmpreg1; + int tmpreg2; + int tmpreg3; + int tmpreg4; + + memclrw(&op, sizeof(Operand)); + GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_GPR(); + tmpreg1 = ALLOC_GPR(); + tmpreg2 = ALLOC_GPR(); + tmpreg3 = ALLOC_GPR(); + + if (shift == 1) { + emitpcode(PC_RLWINM, tmpreg1, op.reg, 1, 31, 31); + emitpcode(PC_RLWINM, tmpreg2, op.reg, 0, 31, 31); + emitpcode(PC_XOR, tmpreg3, tmpreg2, tmpreg1); + emitpcode(PC_SUBF, reg, tmpreg1, tmpreg3); + } else { + tmpreg4 = ALLOC_GPR(); + emitpcode(PC_RLWINM, tmpreg1, op.reg, 32 - shift, 0, 31 - (32 - shift)); + emitpcode(PC_RLWINM, tmpreg2, op.reg, 1, 31, 31); + emitpcode(PC_SUBF, tmpreg3, tmpreg2, tmpreg1); + emitpcode(PC_RLWINM, tmpreg4, tmpreg3, shift, 0, 31); + emitpcode(PC_ADD, reg, tmpreg4, tmpreg2); + } + + output->optype = OpndType_GPR; + output->reg = reg; +} + +static void fp_binary_operator(Opcode opcode, ENode *left, ENode *right, short outputReg, Operand *output) { + Operand opleft; + Operand opright; + int reg; + + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + + if (right->hascall) { + GEN_NODE_TO_FPR(right, &opright, right->rtype, 0); + GEN_NODE_TO_FPR(left, &opleft, left->rtype, 0); + } else { + GEN_NODE_TO_FPR(left, &opleft, left->rtype, 0); + GEN_NODE_TO_FPR(right, &opright, right->rtype, 0); + } + + reg = outputReg ? outputReg : ALLOC_FPR(); + emitpcode(opcode, reg, opleft.reg, opright.reg); + + output->optype = OpndType_FPR; + output->reg = reg; +} + +void fp_unary_operator(Opcode opcode, ENode *expr, short outputReg, Operand *output) { + Operand op; + int reg; + + memclrw(&op, sizeof(Operand)); + GEN_NODE_TO_FPR(expr, &op, expr->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_FPR(); + emitpcode(opcode, reg, op.reg); + + output->optype = OpndType_FPR; + output->reg = reg; +} + +void fp_multiply_add(Opcode opcode, ENode *a, ENode *b, ENode *c, short outputReg, Operand *output) { + Operand opA; + Operand opB; + Operand opC; + int reg; + + memclrw(&opA, sizeof(Operand)); + memclrw(&opB, sizeof(Operand)); + memclrw(&opC, sizeof(Operand)); + + if (c->hascall) { + GEN_NODE_TO_FPR(c, &opC, c->rtype, 0); + if (b->hascall) { + GEN_NODE_TO_FPR(b, &opB, b->rtype, 0); + GEN_NODE_TO_FPR(a, &opA, a->rtype, 0); + } else { + GEN_NODE_TO_FPR(a, &opA, a->rtype, 0); + GEN_NODE_TO_FPR(b, &opB, b->rtype, 0); + } + } else { + if (b->hascall) { + GEN_NODE_TO_FPR(b, &opB, b->rtype, 0); + GEN_NODE_TO_FPR(a, &opA, a->rtype, 0); + GEN_NODE_TO_FPR(c, &opC, c->rtype, 0); + } else { + GEN_NODE_TO_FPR(a, &opA, a->rtype, 0); + GEN_NODE_TO_FPR(b, &opB, b->rtype, 0); + GEN_NODE_TO_FPR(c, &opC, c->rtype, 0); + } + } + + reg = outputReg ? outputReg : ALLOC_FPR(); + emitpcode(opcode, reg, opA.reg, opB.reg, opC.reg); + + output->optype = OpndType_FPR; + output->reg = reg; +} + +void gen_COMPARE(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + expr = evaluate_and_skip_comma(expr); + if (TYPE_IS_8BYTES(expr->data.diadic.right->rtype) || TYPE_IS_8BYTES(expr->data.diadic.left->rtype)) + I8_gen_condition(expr, output, 1); + else + gen_condition_gpr(expr, output, outputReg); +} + +void gen_LOGICAL(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *inner; + ENodeType op; + + expr = evaluate_and_skip_comma(expr); + inner = evaluate_and_skip_comma(expr->data.monadic); + expr->data.monadic = inner; + + if (ENODE_IS(expr, ELOGNOT) && !ENODE_IS2(inner, ELAND, ELOR)) { + op = inner->type; + if (ENODE_IS(inner, ELOGNOT)) { + switch (inner->data.monadic->type) { + case ELOGNOT: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case ELAND: + case ELOR: + GEN_NODE(inner->data.monadic, output); + if (expr->data.monadic->rtype->size < 4) + extend32(output, expr->data.monadic->rtype, 0); + ENSURE_GPR(output, expr->data.monadic->rtype, 0); + return; + } + } + + if (ENODE_IS(inner, ENOTEQU) && !TYPE_IS_8BYTES(inner->data.diadic.left->rtype) && ENODE_IS(inner->data.diadic.right, EINTCONST) && inner->data.diadic.right->data.intval.lo == 0) { + int tmpreg1; + int tmpreg2; + GEN_NODE(inner->data.diadic.left, output); + if (inner->data.diadic.left->rtype->size < 4) + extend32(output, inner->data.diadic.left->rtype, 0); + ENSURE_GPR(output, inner->data.diadic.left->rtype, 0); + + tmpreg1 = ALLOC_GPR(); + tmpreg2 = ALLOC_GPR(); + CError_ASSERT(4853, output->optype == OpndType_GPR); + + emitpcode(PC_CNTLZW, tmpreg2, output->reg); + emitpcode(PC_RLWINM, tmpreg1, tmpreg2, 27, 5, 31); + output->optype = OpndType_GPR; + output->reg = tmpreg1; + } else { + int tmpreg1; + int tmpreg2; + ENodeType inverted; + + inverted = invert_relop(op); + if (op != inverted && !IS_TYPE_FLOAT(inner->data.diadic.left->rtype)) { + inner->type = inverted; + gen_COMPARE(inner, 0, 0, output); + inner->type = inverted; + return; + } + + GEN_NODE(inner, output); + if (inner->rtype->size < 4) + extend32(output, inner->rtype, 0); + ENSURE_GPR(output, inner->rtype, 0); + + tmpreg1 = ALLOC_GPR(); + tmpreg2 = ALLOC_GPR(); + CError_ASSERT(4883, output->optype == OpndType_GPR); + + emitpcode(PC_CNTLZW, tmpreg2, output->reg); + emitpcode(PC_RLWINM, tmpreg1, tmpreg2, 27, 5, 31); + output->optype = OpndType_GPR; + output->reg = tmpreg1; + } + } else { + PCodeLabel *label1; + PCodeLabel *label2; + int tmpreg; + + label1 = makepclabel(); + label2 = makepclabel(); + + tmpreg = ALLOC_GPR(); + emitpcode(PC_LI, tmpreg, 0); + logical_expression(expr, label1, label2, label1); + branch_label(label1); + emitpcode(PC_LI, tmpreg, 1); + branch_label(label2); + output->optype = OpndType_GPR; + output->reg = tmpreg; + } +} + +void gen_NULLCHECK(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *left; + ENode *right; + Operand opleft; + Operand opright; + PrecomputedOperand *precomp; + int flag; + int reg; + PCodeLabel *label; + + left = expr->data.nullcheck.nullcheckexpr; + right = expr->data.nullcheck.condexpr; + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + flag = !IS_TYPE_VOID(expr->rtype) && !expr->ignored; + + GEN_NODE(left, &opleft); + if (left->rtype->size < 4) + extend32(&opleft, left->rtype, 0); + ENSURE_GPR(&opleft, left->rtype, 0); + + precomp = lalloc(sizeof(PrecomputedOperand)); + precomp->precompid = expr->data.nullcheck.precompid; + precomp->operand = opleft; + precomp->next = precomputedoperands; + precomputedoperands = precomp; + + emitpcode(PC_CMPI, 0, opleft.reg, 0); + if (flag) { + emitpcode(PC_MR, reg = ALLOC_GPR(), opleft.reg); + } + + label = makepclabel(); + branch_conditional(0, EEQU, 1, label); + GEN_NODE(right, &opright); + precomputedoperands = precomputedoperands->next; + + if (flag) { + ENSURE_GPR(&opright, right->rtype, reg); + if (opright.reg != reg) + emitpcode(PC_MR, reg, opright.reg); + output->optype = OpndType_GPR; + output->reg = reg; + } + + branch_label(label); +} + +void gen_PRECOMP(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + PrecomputedOperand *precomp; + + for (precomp = precomputedoperands; precomp; precomp = precomp->next) { + if (precomp->precompid == expr->data.precompid) + break; + } + + *output = precomp->operand; +} + +void logical_expression(ENode *cond, PCodeLabel *if_true, PCodeLabel *if_false, PCodeLabel *end) { + PCodeLabel *label; + Operand op; + memclrw(&op, sizeof(Operand)); + + cond = evaluate_and_skip_comma(cond); + switch (cond->type) { + case ELAND: + label = makepclabel(); + logical_expression(cond->data.diadic.left, label, if_false, label); + branch_label(label); + logical_expression(cond->data.diadic.right, if_true, if_false, end); + break; + case ELOR: + label = makepclabel(); + logical_expression(cond->data.diadic.left, if_true, label, label); + branch_label(label); + logical_expression(cond->data.diadic.right, if_true, if_false, end); + break; + case ELOGNOT: + logical_expression(cond->data.monadic, if_false, if_true, end); + break; + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + if (TYPE_IS_8BYTES(cond->data.diadic.right->rtype) || TYPE_IS_8BYTES(cond->data.diadic.left->rtype)) + I8_gen_condition(cond, &op, 0); + else + gen_condition(cond, &op); + + if (end == if_true) + branch_conditional(op.reg, op.regOffset, 0, if_false); + else + branch_conditional(op.reg, op.regOffset, 1, if_true); + break; + default: + CError_FATAL(5160); + } +} + +static void logical_expression_nobranch(ENode *cond, Boolean invert, Operand *output) { + cond = evaluate_and_skip_comma(cond); + switch (cond->type) { + case ELOGNOT: + logical_expression_nobranch(cond->data.monadic, 1, output); + break; + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + if (invert) { + ENodeType nt = invert_relop(cond->type); + CError_ASSERT(5190, nt != cond->type); + cond->type = nt; + } + + if (TYPE_IS_8BYTES(cond->data.diadic.right->rtype) || TYPE_IS_8BYTES(cond->data.diadic.left->rtype)) + I8_gen_condition(cond, output, 0); + else + gen_condition(cond, output); + + break; + default: + CError_FATAL(5206); + } +} + +static ENodeType invert_relop(ENodeType nt) { + switch (nt) { + case ELESS: return EGREATEREQU; + case EGREATER: return ELESSEQU; + case ELESSEQU: return EGREATER; + case EGREATEREQU: return ELESS; + case EEQU: return ENOTEQU; + case ENOTEQU: return EEQU; + default: return nt; + } +} + +static int reverse_relop(int nt) { + switch (nt) { + case ELESS: return EGREATER; + case EGREATER: return ELESS; + case ELESSEQU: return EGREATEREQU; + case EGREATEREQU: return ELESSEQU; + default: return nt; + } +} + +void gen_condition(ENode *cond, Operand *output) { + ENode *left; + ENode *right; + + left = cond->data.diadic.left; + right = cond->data.diadic.right; + if (IS_TYPE_FLOAT(left->rtype)) { + compare_floating(cond->type, left, right, output); + return; + } + + if (ENODE_IS(right, EINTCONST)) { + if (is_unsigned(left->rtype)) { + UInt32 val = right->data.intval.lo; + if (FITS_IN_USHORT(val)) { + compare_immediate(cond->type, left, val, output); + return; + } else if (ENODE_IS2(cond, EEQU, ENOTEQU)) { + compare_immediate_long(cond->type, left, val, output); + return; + } + } else { + UInt32 val = right->data.intval.lo; + if (FITS_IN_SHORT(val)) { + compare_immediate(cond->type, left, val, output); + return; + } else if (ENODE_IS2(cond, EEQU, ENOTEQU)) { + compare_immediate_long(cond->type, left, val, output); + return; + } + } + } else if (ENODE_IS(left, EINTCONST)) { + if (is_unsigned(right->rtype)) { + UInt32 val = left->data.intval.lo; + if (FITS_IN_USHORT(val)) { + compare_immediate(reverse_relop(cond->type), right, val, output); + return; + } else if (ENODE_IS2(cond, EEQU, ENOTEQU)) { + compare_immediate_long(reverse_relop(cond->type), right, val, output); + return; + } + } else { + UInt32 val = left->data.intval.lo; + if (FITS_IN_SHORT(val)) { + compare_immediate(reverse_relop(cond->type), right, val, output); + return; + } else if (ENODE_IS2(cond, EEQU, ENOTEQU)) { + compare_immediate_long(reverse_relop(cond->type), right, val, output); + return; + } + } + } + + compare_integer(cond->type, left, right, output); +} + +void gen_condition_gpr(ENode *cond, Operand *output, short outputReg) { + ENode *left; + ENode *right; + Operand condOp; + int finalReg; + int tmpReg; + int tmpReg2; + int tmpReg3; + int tmpReg4; + int a; + int b; + + left = cond->data.diadic.left; + right = cond->data.diadic.right; + memclrw(&condOp, sizeof(Operand)); + + if (!IS_TYPE_FLOAT(left->rtype)) { + Operand op1; + Operand op2; + Operand opTmp; + memclrw(&op1, sizeof(Operand)); + memclrw(&op2, sizeof(Operand)); + memclrw(&opTmp, sizeof(Operand)); + + if (right->hascall) { + GEN_NODE(right, &op2); + if (!IS_INT_CONST_ZERO(right)) { + if (right->rtype->size < 4) + extend32(&op2, right->rtype, 0); + ENSURE_GPR(&op2, right->rtype, 0); + } + + GEN_NODE(left, &op1); + if (left->rtype->size < 4) + extend32(&op1, left->rtype, 0); + ENSURE_GPR(&op1, left->rtype, 0); + } else { + GEN_NODE(left, &op1); + ENSURE_GPR(&op1, left->rtype, 0); + if (left->rtype->size < 4) + extend32(&op1, left->rtype, 0); + + GEN_NODE(right, &op2); + if (!IS_INT_CONST_ZERO(right)) { + if (right->rtype->size < 4) + extend32(&op2, right->rtype, 0); + ENSURE_GPR(&op2, right->rtype, 0); + } + } + + switch (cond->type) { + case EEQU: + if ( + copts.peephole && + IS_INT_CONST(right) && + pclastblock->pcodeCount > 0 && + pclastblock->lastPCode->op == PC_RLWINM && + pclastblock->lastPCode->args[0].data.reg.reg == op1.reg + ) + { + PCode *pc = pclastblock->lastPCode; + SInt32 a = pc->args[2].data.imm.value; + SInt32 b = pc->args[3].data.imm.value; + SInt32 value = right->data.intval.lo; + if (b == pc->args[4].data.imm.value) { + finalReg = outputReg ? outputReg : ALLOC_GPR(); + + if (value != (value & 1)) { + emitpcode(PC_LI, finalReg, 0); + } else if (value == 0) { + tmpReg = ALLOC_GPR(); + emitpcode( + PC_RLWINM, tmpReg, + pc->args[1].data.reg.reg, + (a + b + 1) & 31, 31, 31); + emitpcode(PC_XORI, finalReg, tmpReg, 1); + } else if (value == 1) { + emitpcode( + PC_RLWINM, finalReg, + pc->args[1].data.reg.reg, + (a + b + 1) & 31, 31, 31); + } else { + CError_FATAL(5434); + } + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + } + + if (IS_INT_CONST_ZERO(right)) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_CNTLZW, tmpReg, op1.reg, 0); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_RLWINM, finalReg, tmpReg, 27, 5, 31); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } else { + tmpReg = ALLOC_GPR(); + emitpcode(PC_SUBF, tmpReg, op1.reg, op2.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_CNTLZW, tmpReg2, tmpReg); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_RLWINM, finalReg, tmpReg2, 27, 5, 31); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + case ENOTEQU: + if ( + copts.peephole && + IS_INT_CONST(right) && + pclastblock->pcodeCount > 0 && + pclastblock->lastPCode->op == PC_RLWINM && + pclastblock->lastPCode->args[0].data.reg.reg == op1.reg + ) + { + PCode *pc = pclastblock->lastPCode; + SInt32 a = pc->args[2].data.imm.value; + SInt32 b = pc->args[3].data.imm.value; + SInt32 value = right->data.intval.lo; + if (b == pc->args[4].data.imm.value) { + finalReg = outputReg ? outputReg : ALLOC_GPR(); + + if (value != (value & 1)) { + emitpcode(PC_LI, finalReg, 1); + } else if (value == 0) { + emitpcode( + PC_RLWINM, finalReg, + pc->args[1].data.reg.reg, + (a + b + 1) & 31, 31, 31); + } else if (value == 1) { + tmpReg = ALLOC_GPR(); + emitpcode( + PC_RLWINM, tmpReg, + pc->args[1].data.reg.reg, + (a + b + 1) & 31, 31, 31); + emitpcode(PC_XORI, finalReg, tmpReg, 1); + } else { + CError_FATAL(5503); + } + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + } + + if (IS_INT_CONST_ZERO(right)) { + if (copts.optimizesize) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_ADDIC, tmpReg, op1.reg, -1); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SUBFE, finalReg, tmpReg, op1.reg); + } else { + tmpReg = ALLOC_GPR(); + emitpcode(PC_NEG, tmpReg, op1.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_OR, tmpReg2, tmpReg, op1.reg); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_RLWINM, finalReg, tmpReg2, 1, 31, 31); + } + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + if (copts.optimizesize) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_SUBF, tmpReg, op1.reg, op2.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_ADDIC, tmpReg2, tmpReg, -1); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SUBFE, finalReg, tmpReg2, tmpReg); + } else { + tmpReg = ALLOC_GPR(); + emitpcode(PC_SUBF, tmpReg, op1.reg, op2.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_SUBF, tmpReg2, op2.reg, op1.reg); + tmpReg3 = ALLOC_GPR(); + emitpcode(PC_OR, tmpReg3, tmpReg, tmpReg2); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_RLWINM, finalReg, tmpReg3, 1, 31, 31); + } + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + + case EGREATEREQU: + if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_RLWINM, tmpReg, op1.reg, 1, 31, 31); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_XORI, finalReg, tmpReg, 1); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + opTmp = op2; + op2 = op1; + op1 = opTmp; + + case ELESSEQU: + if (is_unsigned(left->rtype)) { + if (copts.optimizesize) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_LI, tmpReg, -1); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_SUBFC, tmpReg2, op1.reg, op2.reg); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SUBFZE, finalReg, tmpReg); + } else { + tmpReg = ALLOC_GPR(); + emitpcode(PC_SUBF, tmpReg, op1.reg, op2.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_ORC, tmpReg2, op2.reg, op1.reg); + tmpReg3 = ALLOC_GPR(); + emitpcode(PC_RLWINM, tmpReg3, tmpReg, 31, 1, 31); + tmpReg4 = ALLOC_GPR(); + emitpcode(PC_SUBF, tmpReg4, tmpReg3, tmpReg2); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_RLWINM, finalReg, tmpReg4, 1, 31, 31); + } + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + if (IS_INT_CONST_ZERO(right)) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_LI, tmpReg, 1); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_CNTLZW, tmpReg2, op1.reg); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_RLWNM, finalReg, tmpReg, tmpReg2, 31, 31); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_SRAWI, tmpReg2, op2.reg, 31); + tmpReg = ALLOC_GPR(); + emitpcode(PC_RLWINM, tmpReg, op1.reg, 1, 31, 31); + tmpReg3 = ALLOC_GPR(); + emitpcode(PC_SUBFC, tmpReg3, op1.reg, op2.reg); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_ADDE, finalReg, tmpReg2, tmpReg); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + + case EGREATER: + if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_NEG, tmpReg, op1.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_ANDC, tmpReg2, tmpReg, op1.reg); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_RLWINM, finalReg, tmpReg2, 1, 31, 31); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + opTmp = op2; + op2 = op1; + op1 = opTmp; + + case ELESS: + if (is_unsigned(left->rtype)) { + if (left->rtype->size <= 2) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_RLWINM, finalReg, tmpReg, 1, 31, 31); + output->optype = OpndType_GPR; + output->reg = finalReg; + } else { + if (copts.optimizesize) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_SUBFC, tmpReg, op2.reg, op1.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_SUBFE, tmpReg2, tmpReg, tmpReg); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_NEG, finalReg, tmpReg2); + } else { + tmpReg = ALLOC_GPR(); + emitpcode(PC_XOR, tmpReg, op2.reg, op1.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_CNTLZW, tmpReg2, tmpReg); + tmpReg3 = ALLOC_GPR(); + emitpcode(PC_SLW, tmpReg3, op2.reg, tmpReg2); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_RLWINM, finalReg, tmpReg3, 1, 31, 31); + } + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + return; + } + + if (IS_INT_CONST_ZERO(right)) { + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_RLWINM, finalReg, op1.reg, 1, 31, 31); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + tmpReg = ALLOC_GPR(); + emitpcode(PC_XOR, tmpReg, op2.reg, op1.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_SRAWI, tmpReg2, tmpReg, 1); + tmpReg3 = ALLOC_GPR(); + emitpcode(PC_AND, tmpReg3, tmpReg, op2.reg); + tmpReg4 = ALLOC_GPR(); + emitpcode(PC_SUBF, tmpReg4, tmpReg3, tmpReg2); + + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_RLWINM, finalReg, tmpReg4, 1, 31, 31); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + + default: + CError_FATAL(5777); + } + } + + gen_condition(cond, &condOp); + emitpcode(PC_MFCR, tmpReg = used_virtual_registers[RegClass_GPR]++); + a = 0; + b = condOp.reg * 4; + switch (condOp.regOffset) { + case ENOTEQU: + a = 1; + case EEQU: + b += 2; + break; + case EGREATEREQU: + a = 1; + break; + case ELESSEQU: + a = 1; + case EGREATER: + b += 1; + break; + } + + finalReg = outputReg ? outputReg : ALLOC_GPR(); + if (a) { + emitpcode(PC_RLWINM, tmpReg, tmpReg, b + 1, 31, 31); + emitpcode(PC_XORI, finalReg, tmpReg, 1); + } else { + emitpcode(PC_RLWINM, finalReg, tmpReg, b + 1, 31, 31); + } + output->optype = OpndType_GPR; + output->reg = finalReg; +} + +void gen_negated_condition_gpr(ENode *cond, Operand *output, short outputReg) { + ENode *left; + ENode *right; + Operand op1; + Operand op2; + Operand opTmp; + int finalReg; + int tmpReg; + int tmpReg2; + int tmpReg3; + + left = cond->data.diadic.left; + right = cond->data.diadic.right; + CError_ASSERT(5843, TYPE_FITS_IN_REGISTER(left->rtype) && TYPE_FITS_IN_REGISTER(right->rtype)); + + memclrw(&op1, sizeof(Operand)); + memclrw(&op2, sizeof(Operand)); + memclrw(&opTmp, sizeof(Operand)); + + if (right->hascall) { + GEN_NODE(right, &op2); + if (!IS_INT_CONST_ZERO(right)) { + if (right->rtype->size < 4) + extend32(&op2, right->rtype, 0); + ENSURE_GPR(&op2, right->rtype, 0); + } + + GEN_NODE(left, &op1); + if (left->rtype->size < 4) + extend32(&op1, left->rtype, 0); + ENSURE_GPR(&op1, left->rtype, 0); + } else { + GEN_NODE(left, &op1); + ENSURE_GPR(&op1, left->rtype, 0); + if (left->rtype->size < 4) + extend32(&op1, left->rtype, 0); + + GEN_NODE(right, &op2); + if (!IS_INT_CONST_ZERO(right)) { + if (right->rtype->size < 4) + extend32(&op2, right->rtype, 0); + ENSURE_GPR(&op2, right->rtype, 0); + } + } + + switch (cond->type) { + case EEQU: + if ( + copts.peephole && + IS_INT_CONST(right) && + pclastblock->pcodeCount > 0 && + pclastblock->lastPCode->op == PC_RLWINM && + pclastblock->lastPCode->args[0].data.reg.reg == op1.reg + ) + { + PCode *pc = pclastblock->lastPCode; + SInt32 a = pc->args[2].data.imm.value; + SInt32 b = pc->args[3].data.imm.value; + SInt32 value = right->data.intval.lo; + if (b == pc->args[4].data.imm.value) { + finalReg = outputReg ? outputReg : ALLOC_GPR(); + + if (value != (value & 1)) { + emitpcode(PC_LI, finalReg, 0); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + if (value == 0) { + tmpReg = ALLOC_GPR(); + emitpcode( + PC_RLWINM, tmpReg, + pc->args[1].data.reg.reg, + (a + b + 1) & 31, 31, 31); + emitpcode(PC_ADDI, finalReg, tmpReg, 0, -1); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + if (value == 1) { + tmpReg = ALLOC_GPR(); + emitpcode( + PC_RLWINM, + tmpReg, + pc->args[1].data.reg.reg, + (a + b + 1) & 31, + 31, + 31); + emitpcode(PC_NEG, finalReg, tmpReg); + output->optype = OpndType_GPR; + output->reg = tmpReg; // bug??? + return; + } + + CError_FATAL(5923); + } + } + + if (IS_INT_CONST_ZERO(right)) { + if (copts.optimizesize) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_ADDIC, tmpReg, op1.reg, -1); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SUBFE, finalReg, tmpReg, tmpReg); + } else { + tmpReg = ALLOC_GPR(); + emitpcode(PC_CNTLZW, tmpReg, op1.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_RLWINM, tmpReg2, tmpReg, 27, 31, 31); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_NEG, finalReg, tmpReg2); + } + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + if (copts.optimizesize) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_ADDIC, tmpReg2, tmpReg, -1); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SUBFE, finalReg, tmpReg2, tmpReg2); + } else { + tmpReg = ALLOC_GPR(); + emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_SUBF, tmpReg2, op1.reg, op2.reg); + tmpReg3 = ALLOC_GPR(); + emitpcode(PC_NOR, tmpReg3, tmpReg, tmpReg2); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SRAWI, finalReg, tmpReg3, 31); + } + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + + case ENOTEQU: + if ( + copts.peephole && + IS_INT_CONST(right) && + pclastblock->pcodeCount > 0 && + pclastblock->lastPCode->op == PC_RLWINM && + pclastblock->lastPCode->args[0].data.reg.reg == op1.reg + ) + { + PCode *pc = pclastblock->lastPCode; + SInt32 a = pc->args[2].data.imm.value; + SInt32 b = pc->args[3].data.imm.value; + SInt32 value = right->data.intval.lo; + if (b == pc->args[4].data.imm.value) { + finalReg = outputReg ? outputReg : ALLOC_GPR(); + + if (value != (value & 1)) { + emitpcode(PC_LI, finalReg, -1); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + if (value == 0) { + tmpReg = ALLOC_GPR(); + emitpcode( + PC_RLWINM, tmpReg, + pc->args[1].data.reg.reg, + (a + b + 1) & 31, 31, 31); + emitpcode(PC_NEG, finalReg, tmpReg); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + if (value == 1) { + tmpReg = ALLOC_GPR(); + emitpcode( + PC_RLWINM, tmpReg, + pc->args[1].data.reg.reg, + (a + b + 1) & 31, 31, 31); + emitpcode(PC_ADDI, finalReg, tmpReg, 0, -1); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + CError_FATAL(6031); + } + } + + if (IS_INT_CONST_ZERO(right)) { + if (copts.optimizesize) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_SUBFIC, tmpReg, op1.reg, 0); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SUBFE, finalReg, tmpReg, tmpReg); + } else { + tmpReg = ALLOC_GPR(); + emitpcode(PC_NEG, tmpReg, op1.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_OR, tmpReg2, tmpReg, op1.reg); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SRAWI, finalReg, tmpReg2, 31); + } + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + if (copts.optimizesize) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_SUBFIC, tmpReg2, tmpReg, 0); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SUBFE, finalReg, tmpReg2, tmpReg2); + } else { + tmpReg = ALLOC_GPR(); + emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_SUBF, tmpReg2, op1.reg, op2.reg); + tmpReg3 = ALLOC_GPR(); + emitpcode(PC_OR, tmpReg3, tmpReg, tmpReg2); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SRAWI, finalReg, tmpReg3, 31); + } + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + + case EGREATEREQU: + if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_RLWINM, tmpReg, op1.reg, 1, 31, 31); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_ADDI, finalReg, tmpReg, 0, -1); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + opTmp = op2; + op2 = op1; + op1 = opTmp; + + case ELESSEQU: + if (is_unsigned(left->rtype)) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_SUBFC, tmpReg, op1.reg, op2.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_ADDZE, tmpReg2, op1.reg); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SUBF, finalReg, tmpReg2, op1.reg); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + if (IS_INT_CONST_ZERO(right)) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_NEG, tmpReg, op1.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_ORC, tmpReg2, op1.reg, tmpReg); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SRAWI, finalReg, tmpReg2, 31); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + tmpReg = ALLOC_GPR(); + emitpcode(PC_XORIS, tmpReg, op1.reg, 0x8000); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_SUBF, tmpReg2, op1.reg, op2.reg); + tmpReg3 = ALLOC_GPR(); + emitpcode(PC_ADDC, tmpReg3, tmpReg2, tmpReg); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SUBFE, finalReg, tmpReg3, tmpReg3); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + + case EGREATER: + if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_NEG, tmpReg, op1.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_ANDC, tmpReg2, tmpReg, op1.reg); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SRAWI, finalReg, tmpReg2, 31); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + opTmp = op2; + op2 = op1; + op1 = opTmp; + + case ELESS: + if (is_unsigned(left->rtype)) { + tmpReg = ALLOC_GPR(); + emitpcode(PC_SUBFC, tmpReg, op2.reg, op1.reg); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SUBFE, finalReg, tmpReg, tmpReg); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + if (IS_INT_CONST_ZERO(right)) { + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SRAWI, finalReg, op1.reg, 31); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + } + + tmpReg = ALLOC_GPR(); + emitpcode(PC_SUBFC, tmpReg, op2.reg, op1.reg); + tmpReg2 = ALLOC_GPR(); + emitpcode(PC_RLWINM, tmpReg2, op2.reg, 1, 31, 31); + tmpReg3 = ALLOC_GPR(); + emitpcode(PC_RLWINM, tmpReg3, op1.reg, 1, 31, 31); + finalReg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_SUBFE, finalReg, tmpReg3, tmpReg2); + output->optype = OpndType_GPR; + output->reg = finalReg; + return; + + default: + CError_FATAL(6240); + } +} + +void compare_floating(short nt, ENode *left, ENode *right, Operand *output) { + Operand opleft; + Operand opright; + + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + + if (right->hascall) { + GEN_NODE_TO_FPR(right, &opright, right->rtype, 0); + GEN_NODE_TO_FPR(left, &opleft, left->rtype, 0); + } else { + GEN_NODE_TO_FPR(left, &opleft, left->rtype, 0); + GEN_NODE_TO_FPR(right, &opright, right->rtype, 0); + } + + emitpcode((nt == EEQU || nt == ENOTEQU) ? PC_FCMPU : PC_FCMPO, 0, opleft.reg, opright.reg); + if (nt == ELESSEQU) { + emitpcode(PC_CROR, 0, 2, 0, 0, 0, 2); + nt = EEQU; + } else if (nt == EGREATEREQU) { + emitpcode(PC_CROR, 0, 2, 0, 1, 0, 2); + nt = EEQU; + } + + output->optype = OpndType_CRField; + output->reg = 0; + output->regOffset = nt; +} + +void compare_integer(short nt, ENode *left, ENode *right, Operand *output) { + Operand opleft; + Operand opright; + + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + + if (right->hascall) { + GEN_NODE(right, &opright); + if (right->rtype->size < 4) + extend32(&opright, right->rtype, 0); + ENSURE_GPR(&opright, right->rtype, 0); + + GEN_NODE(left, &opleft); + if (left->rtype->size < 4) + extend32(&opleft, left->rtype, 0); + ENSURE_GPR(&opleft, left->rtype, 0); + } else { + GEN_NODE(left, &opleft); + ENSURE_GPR(&opleft, left->rtype, 0); + if (left->rtype->size < 4) + extend32(&opleft, left->rtype, 0); + + GEN_NODE(right, &opright); + if (right->rtype->size < 4) + extend32(&opright, right->rtype, 0); + ENSURE_GPR(&opright, right->rtype, 0); + } + + emitpcode(is_unsigned(left->rtype) ? PC_CMPL : PC_CMP, 0, opleft.reg, opright.reg); + + output->optype = OpndType_CRField; + output->reg = 0; + output->regOffset = nt; +} + +void compare_immediate(short nt, ENode *left, SInt32 value, Operand *output) { + int postIncFlag; + short postIncReg; + Operand op; + SInt32 postIncValue; + + memclrw(&op, sizeof(Operand)); + + postIncFlag = ispostincrementopportunity(left, &op, &postIncValue); + if (!postIncFlag) { + GEN_NODE(left, &op); + if (op.optype != OpndType_CRField) { + if (left->rtype->size < 4) + extend32(&op, left->rtype, 0); + else + ENSURE_GPR(&op, left->rtype, 0); + } + } else { + postIncReg = op.reg; + if (left->rtype->size < 4) + extend32(&op, left->rtype, 0); + ENSURE_GPR(&op, left->rtype, 0); + } + + if (op.optype == OpndType_CRField) { + if ( + (nt == EEQU && value == 1) || + (nt == ENOTEQU && value == 0) || + (nt == EGREATER && value == 0) || + (nt == EGREATEREQU && value == 1) + ) + { + *output = op; + return; + } + + if ( + (nt == EEQU && value == 0) || + (nt == ENOTEQU && value == 1) || + (nt == ELESS && value == 1) || + (nt == ELESSEQU && value == 0) + ) + { + *output = op; + switch (op.regOffset) { + case EEQU: + output->regOffset = ENOTEQU; + return; + case ENOTEQU: + output->regOffset = EEQU; + return; + case ELESS: + output->regOffset = EGREATEREQU; + return; + case EGREATER: + output->regOffset = ELESSEQU; + return; + case ELESSEQU: + output->regOffset = EGREATER; + return; + case EGREATEREQU: + output->regOffset = ELESS; + return; + } + } + + ENSURE_GPR(&op, left->rtype, 0); + } + + if ( + copts.peephole && + value == 0 && + pclastblock->pcodeCount > 0 && + pclastblock->lastPCode->op != PC_RLWINM && + (PCODE_FLAG_SET_F(pclastblock->lastPCode) & (fIsMove | fSideEffects | fCanSetRecordBit | fOpTypeGPR)) == (fCanSetRecordBit | fOpTypeGPR) && + pclastblock->lastPCode->args[0].data.reg.reg == op.reg && + (!is_unsigned(left->rtype) || nt == EEQU || nt == ENOTEQU) + ) + { + pcsetrecordbit(pclastblock->lastPCode); + } else { + emitpcode(is_unsigned(left->rtype) ? PC_CMPLI : PC_CMPI, 0, op.reg, value); + } + + if (postIncFlag) + add_register_immediate(postIncReg, postIncReg, postIncValue); + + output->optype = OpndType_CRField; + output->reg = 0; + output->regOffset = nt; +} + +void compare_immediate_long(short nt, ENode *left, SInt32 value, Operand *output) { + int postIncFlag; + short postIncReg; + int outputReg; + Operand op; + SInt32 postIncValue; + + memclrw(&op, sizeof(Operand)); + + postIncFlag = ispostincrementopportunity(left, &op, &postIncValue); + if (!postIncFlag) { + GEN_NODE(left, &op); + } else { + postIncReg = op.reg; + } + + if (left->rtype->size < 4) + extend32(&op, left->rtype, 0); + ENSURE_GPR(&op, left->rtype, 0); + + outputReg = ALLOC_GPR(); + emitpcode(PC_ADDIS, outputReg, op.reg, 0, (SInt16) (~(value >> 16) + 1)); + emitpcode(PC_CMPLI, 0, outputReg, value & 0xFFFF); + + if (postIncFlag) + add_register_immediate(postIncReg, postIncReg, postIncValue); + + output->optype = OpndType_CRField; + output->reg = 0; + output->regOffset = nt; +} + +static int ismask(SInt32 value, short *first, short *last) { + int start, end, bit; + start = end = -1; + for (bit = 31; bit >= 0; bit--) { + if (value & 1) { + if (start != -1) + return 0; + if (end == -1) + end = bit; + } else { + if (end != -1 && start == -1) + start = bit + 1; + } + value >>= 1; + } + + if (end == -1) + return 0; + if (start == -1) + start = 0; + *first = start; + *last = end; + return 1; +} + +int ismaskconstant(SInt32 value, short *first, short *last) { + short my_first; + short my_last; + if (ismask(value, first, last)) + return 1; + + if (value && ismask(~value, &my_first, &my_last)) { + *first = my_last + 1; + *last = my_first - 1; + return 1; + } else { + return 0; + } +} + +static void shift_and_mask(ENode *expr, short a, short b, short c, short outputReg, Operand *output) { + Operand op; + int reg; + + memclrw(&op, sizeof(Operand)); + GEN_NODE(expr, &op); + ENSURE_GPR(&op, expr->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_RLWINM, reg, op.reg, a, b, c); + + output->optype = OpndType_GPR; + output->reg = reg; +} + +int ispostincrementopportunity(ENode *expr, Operand *op, SInt32 *value) { + Type *type; + int reg; + + type = expr->rtype; + if (!ENODE_IS2(expr, EPOSTINC, EPOSTDEC)) + return 0; + if (!ENODE_IS(expr->data.monadic, EINDIRECT)) + return 0; + if (!ENODE_IS(expr->data.monadic->data.monadic, EOBJREF)) + return 0; + + reg = OBJECT_REG(expr->data.monadic->data.monadic->data.objref); + if (!reg) + return 0; + + if (IS_TYPE_POINTER(type)) { + if (ENODE_IS(expr, EPOSTINC)) + *value = TPTR_TARGET(type)->size; + else + *value = -TPTR_TARGET(type)->size; + } else { + if (ENODE_IS(expr, EPOSTINC)) + *value = 1; + else + *value = -1; + } + + op->optype = OpndType_GPR; + op->reg = reg; + return 1; +} + +void add_register_immediate(short regA, short regB, SInt32 value) { + if (!FITS_IN_SHORT(value)) { + emitpcode(PC_ADDIS, regA, regB, 0, HIGH_PART(value)); + if (LOW_PART(value)) + emitpcode(PC_ADDI, regA, regA, 0, LOW_PART(value)); + } else { + emitpcode(PC_ADDI, regA, regB, 0, value); + } +} + +static int ispowerof2(SInt32 val) { + int bit = getbit(val); + return (bit > 0 && bit < 31) ? bit : 0; +} + +void I8_gen_ADD(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + int is_uns; + ENode *left; + ENode *right; + short reg; + short regHi; + short tmpreg1; + short tmpreg2; + SInt32 skipleft; + SInt32 skipright; + Operand opleft; + Operand opright; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + + if (right->hascall) { + GEN_NODE(right, &opright); + if (TYPE_IS_8BYTES(right->rtype)) + coerce_to_register_pair(&opright, right->rtype, 0, 0); + else + ENSURE_GPR(&opright, right->rtype, 0); + + GEN_NODE(left, &opleft); + if (TYPE_IS_8BYTES(left->rtype)) + coerce_to_register_pair(&opleft, left->rtype, 0, 0); + else + ENSURE_GPR(&opleft, left->rtype, 0); + } else { + GEN_NODE(left, &opleft); + if (TYPE_IS_8BYTES(left->rtype)) + coerce_to_register_pair(&opleft, left->rtype, 0, 0); + else + ENSURE_GPR(&opleft, left->rtype, 0); + + GEN_NODE(right, &opright); + if (TYPE_IS_8BYTES(right->rtype)) + coerce_to_register_pair(&opright, right->rtype, 0, 0); + else + ENSURE_GPR(&opright, right->rtype, 0); + } + + reg = ALLOC_GPR(); + regHi = ALLOC_GPR(); + is_uns = is_unsigned(expr->rtype) != 0; + skipleft = GetSizeSkip(left); + skipright = GetSizeSkip(right); + + if (skipleft < skipright) { + Operand tmpop; + SInt32 tmp; + + expr->data.diadic.left = right; + expr->data.diadic.right = left; + left = expr->data.diadic.left; + right = expr->data.diadic.right; + + tmpop = opright; + opright = opleft; + opleft = tmpop; + + tmp = skipleft; + skipleft = skipright; + skipright = tmp; + } + + switch (skipleft + skipright) { + case 1 + 1: + case 1 + 2: + case 2 + 2: + if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) { + emitpcode(PC_ADDIC, reg, opright.reg, LOW_PART(left->data.intval.lo)); + } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo)) { + emitpcode(PC_ADDIC, reg, opleft.reg, LOW_PART(right->data.intval.lo)); + } else { + emitpcode(PC_ADDC, reg, opleft.reg, opright.reg); + } + if (is_uns) + emitpcode(PC_LI, regHi, 0); + else + emitpcode(PC_SRAWI, regHi, reg, 31); + break; + case 1 + 4: + case 2 + 4: + case 4 + 4: + if (!is_uns) { + tmpreg1 = ALLOC_GPR(); + tmpreg2 = ALLOC_GPR(); + emitpcode(PC_SRAWI, tmpreg2, opleft.reg, 31); + emitpcode(PC_SRAWI, tmpreg1, opright.reg, 31); + } + if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) { + emitpcode(PC_ADDIC, reg, opright.reg, LOW_PART(left->data.intval.lo)); + } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo)) { + emitpcode(PC_ADDIC, reg, opleft.reg, LOW_PART(right->data.intval.lo)); + } else { + emitpcode(PC_ADDC, reg, opleft.reg, opright.reg); + } + if (is_uns) { + tmpreg1 = ALLOC_GPR(); + emitpcode(PC_LI, tmpreg1, 0); + emitpcode(PC_ADDZE, regHi, tmpreg1); + } else { + emitpcode(PC_ADDE, regHi, tmpreg1, tmpreg2); + } + break; + case 1 + 8: + case 2 + 8: + case 4 + 8: + CError_ASSERT(6933, skipleft == 8); + if (!is_uns) { + tmpreg2 = ALLOC_GPR(); + emitpcode(PC_SRAWI, tmpreg2, opright.reg, 31); + } + if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo) && left->data.intval.hi == 0) { + emitpcode(PC_ADDIC, reg, opright.reg, LOW_PART(left->data.intval.lo)); + } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo) && right->data.intval.hi == 0) { + emitpcode(PC_ADDIC, reg, opleft.reg, LOW_PART(right->data.intval.lo)); + } else { + emitpcode(PC_ADDC, reg, opleft.reg, opright.reg); + } + if (is_uns) + emitpcode(PC_ADDZE, regHi, opleft.regHi); + else + emitpcode(PC_ADDE, regHi, opleft.regHi, tmpreg2); + break; + case 8 + 8: + emitpcode(PC_ADDC, reg, opleft.reg, opright.reg); + emitpcode(PC_ADDE, regHi, opleft.regHi, opright.regHi); + break; + default: + CError_FATAL(6979); + } + + output->optype = OpndType_GPRPair; + output->reg = reg; + output->regHi = regHi; +} + +void I8_gen_INTCONST(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + short reg; + short regHi; + + reg = outputReg ? outputReg : ALLOC_GPR(); + regHi = outputRegHi ? outputRegHi : ALLOC_GPR(); + + load_immediate(reg, expr->data.intval.lo); + load_immediate(regHi, expr->data.intval.hi); + + output->optype = OpndType_GPRPair; + output->reg = reg; + output->regHi = regHi; +} + +void I8_gen_SUB(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + int is_uns; + ENode *left; + ENode *right; + short reg; + short regHi; + short tmpreg1; + short tmpreg2; + short tmpreg3; + SInt32 skipleft; + SInt32 skipright; + Operand opleft; + Operand opright; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + + if (right->hascall) { + GEN_NODE(right, &opright); + if (TYPE_IS_8BYTES(right->rtype)) + coerce_to_register_pair(&opright, right->rtype, 0, 0); + else + ENSURE_GPR(&opright, right->rtype, 0); + + GEN_NODE(left, &opleft); + if (TYPE_IS_8BYTES(left->rtype)) + coerce_to_register_pair(&opleft, left->rtype, 0, 0); + else + ENSURE_GPR(&opleft, left->rtype, 0); + } else { + GEN_NODE(left, &opleft); + if (TYPE_IS_8BYTES(left->rtype)) + coerce_to_register_pair(&opleft, left->rtype, 0, 0); + else + ENSURE_GPR(&opleft, left->rtype, 0); + + GEN_NODE(right, &opright); + if (TYPE_IS_8BYTES(right->rtype)) + coerce_to_register_pair(&opright, right->rtype, 0, 0); + else + ENSURE_GPR(&opright, right->rtype, 0); + } + + reg = ALLOC_GPR(); + regHi = ALLOC_GPR(); + is_uns = is_unsigned(expr->rtype) != 0; + skipleft = GetSizeSkip(left); + skipright = GetSizeSkip(right); + + switch (skipleft + skipright) { + case 1 + 1: + case 1 + 2: + case 2 + 2: + if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) { + emitpcode(PC_SUBFIC, reg, opright.reg, LOW_PART(left->data.intval.lo)); + } else { + emitpcode(PC_SUBFC, reg, opright.reg, opleft.reg); + } + if (is_uns) + emitpcode(PC_LI, regHi, 0); + else + emitpcode(PC_SRAWI, regHi, reg, 31); + break; + case 1 + 4: + case 2 + 4: + case 4 + 4: + if (!is_uns) { + tmpreg1 = ALLOC_GPR(); + tmpreg2 = ALLOC_GPR(); + emitpcode(PC_SRAWI, tmpreg2, opleft.reg, 31); + emitpcode(PC_SRAWI, tmpreg1, opright.reg, 31); + } + if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) { + emitpcode(PC_SUBFIC, reg, opright.reg, LOW_PART(left->data.intval.lo)); + } else { + emitpcode(PC_SUBFC, reg, opright.reg, opleft.reg); + } + if (is_uns) { + tmpreg1 = ALLOC_GPR(); + emitpcode(PC_LI, tmpreg1, 0); + emitpcode(PC_SUBFZE, regHi, tmpreg1); + } else { + emitpcode(PC_SUBFE, regHi, tmpreg1, tmpreg2); + } + break; + case 1 + 8: + case 2 + 8: + case 4 + 8: + if (skipleft < skipright) { + emitpcode(PC_SUBFC, reg, opright.reg, opleft.reg); + emitpcode(PC_SUBFE, regHi, opright.regHi, opleft.regHi); + } else { + if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo) && left->data.intval.hi == 0) { + emitpcode(PC_SUBFIC, reg, opright.reg, LOW_PART(left->data.intval.lo)); + } else { + emitpcode(PC_SUBFC, reg, opright.reg, opleft.reg); + } + tmpreg1 = ALLOC_GPR(); + emitpcode(PC_LI, tmpreg1, 0); + emitpcode(PC_SUBFE, regHi, tmpreg1, opleft.regHi); + } + break; + case 8 + 8: + emitpcode(PC_SUBFC, reg, opright.reg, opleft.reg); + emitpcode(PC_SUBFE, regHi, opright.regHi, opleft.regHi); + break; + default: + CError_FATAL(7211); + } + + output->optype = OpndType_GPRPair; + output->reg = reg; + output->regHi = regHi; +} + +void I8_gen_XOR(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *left; + ENode *right; + short reg; + short regHi; + Operand opleft; + Operand opright; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + + if (right->hascall) { + GEN_NODE(right, &opright); + coerce_to_register_pair(&opright, right->rtype, 0, 0); + + GEN_NODE(left, &opleft); + coerce_to_register_pair(&opleft, left->rtype, 0, 0); + } else { + GEN_NODE(left, &opleft); + coerce_to_register_pair(&opleft, left->rtype, 0, 0); + + GEN_NODE(right, &opright); + coerce_to_register_pair(&opright, right->rtype, 0, 0); + } + + CError_ASSERT(7254, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair); + + reg = outputReg ? outputReg : ALLOC_GPR(); + regHi = outputRegHi ? outputRegHi : ALLOC_GPR(); + + emitpcode(PC_XOR, reg, opleft.reg, opright.reg); + emitpcode(PC_XOR, regHi, opleft.regHi, opright.regHi); + + output->optype = OpndType_GPRPair; + output->reg = reg; + output->regHi = regHi; +} + +void I8_gen_OR(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *left; + ENode *right; + short reg; + short regHi; + Operand opleft; + Operand opright; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + + if (right->hascall) { + GEN_NODE(right, &opright); + coerce_to_register_pair(&opright, right->rtype, 0, 0); + + GEN_NODE(left, &opleft); + coerce_to_register_pair(&opleft, left->rtype, 0, 0); + } else { + GEN_NODE(left, &opleft); + coerce_to_register_pair(&opleft, left->rtype, 0, 0); + + GEN_NODE(right, &opright); + coerce_to_register_pair(&opright, right->rtype, 0, 0); + } + + CError_ASSERT(7304, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair); + + reg = outputReg ? outputReg : ALLOC_GPR(); + regHi = outputRegHi ? outputRegHi : ALLOC_GPR(); + + emitpcode(PC_OR, reg, opleft.reg, opright.reg); + emitpcode(PC_OR, regHi, opleft.regHi, opright.regHi); + + output->optype = OpndType_GPRPair; + output->reg = reg; + output->regHi = regHi; +} + +void I8_gen_AND(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *left; + ENode *right; + short reg; + short regHi; + Operand opleft; + Operand opright; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + + if (right->hascall) { + GEN_NODE(right, &opright); + coerce_to_register_pair(&opright, right->rtype, 0, 0); + + GEN_NODE(left, &opleft); + coerce_to_register_pair(&opleft, left->rtype, 0, 0); + } else { + GEN_NODE(left, &opleft); + coerce_to_register_pair(&opleft, left->rtype, 0, 0); + + GEN_NODE(right, &opright); + coerce_to_register_pair(&opright, right->rtype, 0, 0); + } + + CError_ASSERT(7354, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair); + + reg = outputReg ? outputReg : ALLOC_GPR(); + regHi = outputRegHi ? outputRegHi : ALLOC_GPR(); + + emitpcode(PC_AND, reg, opleft.reg, opright.reg); + emitpcode(PC_AND, regHi, opleft.regHi, opright.regHi); + + output->optype = OpndType_GPRPair; + output->reg = reg; + output->regHi = regHi; +} + +int I8_getbit(UInt64 val) { + switch (val) { + case 0: return -1; + case 1ULL << 0: return 0; + case 1ULL << 1: return 1; + case 1ULL << 2: return 2; + case 1ULL << 3: return 3; + case 1ULL << 4: return 4; + case 1ULL << 5: return 5; + case 1ULL << 6: return 6; + case 1ULL << 7: return 7; + case 1ULL << 8: return 8; + case 1ULL << 9: return 9; + case 1ULL << 10: return 10; + case 1ULL << 11: return 11; + case 1ULL << 12: return 12; + case 1ULL << 13: return 13; + case 1ULL << 14: return 14; + case 1ULL << 15: return 15; + case 1ULL << 16: return 16; + case 1ULL << 17: return 17; + case 1ULL << 18: return 18; + case 1ULL << 19: return 19; + case 1ULL << 20: return 20; + case 1ULL << 21: return 21; + case 1ULL << 22: return 22; + case 1ULL << 23: return 23; + case 1ULL << 24: return 24; + case 1ULL << 25: return 25; + case 1ULL << 26: return 26; + case 1ULL << 27: return 27; + case 1ULL << 28: return 28; + case 1ULL << 29: return 29; + case 1ULL << 30: return 30; + case 1ULL << 31: return 31; + case 1ULL << 32: return 32; + case 1ULL << 33: return 33; + case 1ULL << 34: return 34; + case 1ULL << 35: return 35; + case 1ULL << 36: return 36; + case 1ULL << 37: return 37; + case 1ULL << 38: return 38; + case 1ULL << 39: return 39; + case 1ULL << 40: return 40; + case 1ULL << 41: return 41; + case 1ULL << 42: return 42; + case 1ULL << 43: return 43; + case 1ULL << 44: return 44; + case 1ULL << 45: return 45; + case 1ULL << 46: return 46; + case 1ULL << 47: return 47; + case 1ULL << 48: return 48; + case 1ULL << 49: return 49; + case 1ULL << 50: return 50; + case 1ULL << 51: return 51; + case 1ULL << 52: return 52; + case 1ULL << 53: return 53; + case 1ULL << 54: return 54; + case 1ULL << 55: return 55; + case 1ULL << 56: return 56; + case 1ULL << 57: return 57; + case 1ULL << 58: return 58; + case 1ULL << 59: return 59; + case 1ULL << 60: return 60; + case 1ULL << 61: return 61; + case 1ULL << 62: return 62; + case 1ULL << 63: return 63; + default: return -2; + } +} + +int I8_log2n(UInt64 val) { + int bit = I8_getbit(val); + return (bit > 0 && bit < 63) ? bit : 0; +} + +void I8_ShiftLeftImmediate(Operand opnd, SInt32 value, int is_unsigned, SInt32 size, short reg, short regHi) { + if (opnd.reg == reg || opnd.regHi == regHi || opnd.reg == regHi || opnd.regHi == reg) + CError_FATAL(7703); + + if (value < 32) { + emitpcode(PC_RLWINM, reg, opnd.reg, value, 0, 31 - value); + if (size > 4) { + emitpcode(PC_RLWINM, regHi, opnd.regHi, value, 0, 31 - value); + emitpcode(PC_RLWIMI, regHi, opnd.reg, value, 32 - value, 31); + } else { + emitpcode(PC_RLWINM, regHi, opnd.reg, value, 32 - value, 31); + } + } else if (value <= 63) { + if (value == 32) + emitpcode(PC_MR, regHi, opnd.reg); + else + emitpcode(PC_RLWINM, regHi, opnd.reg, value - 32, 0, 63 - value); + emitpcode(PC_LI, reg, 0); + } else { + CError_FATAL(7732); + } +} + +void I8_ShiftRightImmediate(Operand opnd, SInt32 value, int is_unsigned, short reg, short regHi, int unk) { + short tmpreg1; + short tmpreg2; + short tmpreg3; + short tmpreg4; + + if (opnd.reg == reg || opnd.regHi == regHi || opnd.reg == regHi || opnd.regHi == reg) + CError_FATAL(7756); + + if (value < 32) { + emitpcode(PC_RLWINM, reg, opnd.reg, 32 - value, 0, 31); + emitpcode(PC_RLWIMI, reg, opnd.regHi, 32 - value, 0, value - 1); + if (is_unsigned) { + emitpcode(PC_RLWINM, regHi, opnd.regHi, 32 - value, value, 31); + } else if (unk) { + tmpreg1 = ALLOC_GPR(); + emitpcode(PC_MR, tmpreg1, opnd.regHi); + emitpcode(PC_RLWIMI, tmpreg1, opnd.reg, 0, 31 - (value - 1), 31); + emitpcode(PC_SRAWI, regHi, tmpreg1, value); + } else { + emitpcode(PC_SRAWI, regHi, opnd.regHi, value); + } + } else if (value == 32) { + if (is_unsigned) { + emitpcode(PC_MR, reg, opnd.regHi); + emitpcode(PC_LI, regHi, 0); + } else if (unk) { + tmpreg1 = ALLOC_GPR(); + tmpreg2 = ALLOC_GPR(); + tmpreg3 = ALLOC_GPR(); + emitpcode(PC_NEG, tmpreg1, opnd.reg); + emitpcode(PC_OR, tmpreg2, tmpreg1, opnd.reg); + emitpcode(PC_RLWINM, tmpreg3, tmpreg2, 1, 31, 31); + emitpcode(PC_RLWIMI, tmpreg3, opnd.regHi, 0, 0, 0); + emitpcode(PC_MR, reg, opnd.regHi); + emitpcode(PC_SRAWI, regHi, value, 31); + } else { + emitpcode(PC_MR, reg, opnd.regHi); + emitpcode(PC_SRAWI, regHi, opnd.regHi, 31); + } + } else if (value <= 63) { + if (is_unsigned) { + emitpcode(PC_RLWINM, reg, opnd.regHi, 64 - value, value - 32, 31); + emitpcode(PC_LI, regHi, 0); + } else if (unk) { + tmpreg1 = ALLOC_GPR(); + tmpreg2 = ALLOC_GPR(); + tmpreg3 = ALLOC_GPR(); + tmpreg4 = ALLOC_GPR(); + emitpcode(PC_NEG, tmpreg1, opnd.reg); + emitpcode(PC_OR, tmpreg2, tmpreg1, opnd.reg); + emitpcode(PC_RLWINM, tmpreg3, tmpreg2, 1, 31, 31); + emitpcode(PC_OR, tmpreg4, opnd.regHi, tmpreg3); + emitpcode(PC_SRAWI, regHi, opnd.regHi, 31); + emitpcode(PC_SRAWI, reg, tmpreg4, value - 32); + } else { + emitpcode(PC_SRAWI, reg, opnd.regHi, value - 32); + emitpcode(PC_SRAWI, regHi, opnd.regHi, 31); + } + } else { + CError_FATAL(7866); + } +} + +void I8_gen_MUL(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + int is_uns; + ENode *left; + ENode *right; + short reg; + short regHi; + short tmpreg1; + short tmpreg2; + short tmpreg3; + short tmpreg4; + SInt32 skipleft; + SInt32 skipright; + Operand opleft; + Operand opright; + SInt64 leftval; + SInt64 rightval; + int shift; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + skipleft = GetSizeSkip(left); + skipright = GetSizeSkip(right); + + if (ENODE_IS(right, EINTCONST) && ENODE_IS(left, EINTCONST)) + CError_FATAL(7900); + + if (ENODE_IS(left, EINTCONST)) + leftval = left->data.intval.lo + (((SInt64) ((skipleft < 8) ? 0 : left->data.intval.hi)) << 32); + if (ENODE_IS(right, EINTCONST)) + rightval = right->data.intval.lo + (((SInt64) ((skipright < 8) ? 0 : right->data.intval.hi)) << 32); + + if (right->hascall) { + GEN_NODE(right, &opright); + if (TYPE_IS_8BYTES(right->rtype)) + coerce_to_register_pair(&opright, right->rtype, 0, 0); + else + ENSURE_GPR(&opright, right->rtype, 0); + + if (!(ENODE_IS(left, EINTCONST) && I8_log2n(leftval) > 0)) { + GEN_NODE(left, &opleft); + if (TYPE_IS_8BYTES(left->rtype)) + coerce_to_register_pair(&opleft, left->rtype, 0, 0); + else + ENSURE_GPR(&opleft, left->rtype, 0); + } + } else { + if (!(ENODE_IS(left, EINTCONST) && I8_log2n(leftval) > 0)) { + GEN_NODE(left, &opleft); + if (TYPE_IS_8BYTES(left->rtype)) + coerce_to_register_pair(&opleft, left->rtype, 0, 0); + else + ENSURE_GPR(&opleft, left->rtype, 0); + } + + if (!(ENODE_IS(right, EINTCONST) && I8_log2n(rightval) > 0)) { + GEN_NODE(right, &opright); + if (TYPE_IS_8BYTES(right->rtype)) + coerce_to_register_pair(&opright, right->rtype, 0, 0); + else + ENSURE_GPR(&opright, right->rtype, 0); + } + } + + is_uns = is_unsigned(expr->rtype) != 0; + + if (skipleft < skipright) { + Operand tmpop; + SInt64 tmp64; + SInt32 tmp; + + expr->data.diadic.left = right; + expr->data.diadic.right = left; + left = expr->data.diadic.left; + right = expr->data.diadic.right; + + tmpop = opright; + opright = opleft; + opleft = tmpop; + + tmp64 = leftval; + leftval = rightval; + rightval = tmp64; + + tmp = skipleft; + skipleft = skipright; + skipright = tmp; + } + + reg = ALLOC_GPR(); + regHi = ALLOC_GPR(); + + if (ENODE_IS(left, EINTCONST) && (shift = I8_log2n(leftval)) > 0) { + I8_ShiftLeftImmediate(opright, shift, is_uns, skipright, reg, regHi); + } else if (ENODE_IS(right, EINTCONST) && (shift = I8_log2n(rightval)) > 0) { + I8_ShiftLeftImmediate(opleft, shift, is_uns, skipleft, reg, regHi); + } else { + switch (skipleft + skipright) { + case 1 + 1: + case 1 + 2: + case 2 + 2: + if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) { + emitpcode(PC_MULLI, reg, opright.reg, LOW_PART(left->data.intval.lo)); + } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo)) { + emitpcode(PC_MULLI, reg, opleft.reg, LOW_PART(right->data.intval.lo)); + } else { + emitpcode(PC_MULLW, reg, opleft.reg, opright.reg); + } + if (is_uns) + emitpcode(PC_LI, regHi, 0); + else + emitpcode(PC_SRAWI, regHi, reg, 31); + break; + case 1 + 4: + case 2 + 4: + case 4 + 4: + if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) { + emitpcode(PC_MULLI, reg, opright.reg, LOW_PART(left->data.intval.lo)); + } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo)) { + emitpcode(PC_MULLI, reg, opleft.reg, LOW_PART(right->data.intval.lo)); + } else { + emitpcode(PC_MULLW, reg, opleft.reg, opright.reg); + } + if (is_uns) + emitpcode(PC_MULHWU, regHi, opleft.reg, opright.reg); + else + emitpcode(PC_MULHW, regHi, opleft.reg, opright.reg); + break; + case 1 + 8: + case 2 + 8: + case 4 + 8: + CError_ASSERT(8097, skipleft == 8); + if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo) && left->data.intval.hi == 0) { + emitpcode(PC_MULLI, reg, opright.reg, LOW_PART(left->data.intval.lo)); + if (is_uns) + emitpcode(PC_MULHWU, regHi, opright.reg, opleft.reg); + else + emitpcode(PC_MULHW, regHi, opright.reg, opleft.reg); + } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo) && right->data.intval.hi == 0) { + tmpreg1 = ALLOC_GPR(); + tmpreg2 = ALLOC_GPR(); + if (is_uns) { + emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg); + emitpcode(PC_MULLI, tmpreg1, opleft.regHi, LOW_PART(right->data.intval.lo)); + emitpcode(PC_MULLI, reg, opleft.reg, LOW_PART(right->data.intval.lo)); + emitpcode(PC_ADD, regHi, tmpreg2, tmpreg1); + } else { + tmpreg3 = ALLOC_GPR(); + tmpreg4 = ALLOC_GPR(); + emitpcode(PC_SRAWI, tmpreg4, opright.reg, 31); + emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg); + emitpcode(PC_MULLI, tmpreg1, opleft.regHi, LOW_PART(right->data.intval.lo)); + emitpcode(PC_MULLI, reg, opleft.reg, LOW_PART(right->data.intval.lo)); + emitpcode(PC_MULLW, tmpreg3, opleft.reg, tmpreg4); + emitpcode(PC_ADD, regHi, tmpreg2, tmpreg1); + emitpcode(PC_ADD, regHi, regHi, tmpreg3); + } + } else { + tmpreg1 = ALLOC_GPR(); + tmpreg2 = ALLOC_GPR(); + if (is_uns) { + emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg); + emitpcode(PC_MULLW, tmpreg1, opleft.regHi, opright.reg); + emitpcode(PC_MULLW, reg, opleft.reg, opright.reg); + emitpcode(PC_ADD, regHi, tmpreg2, tmpreg1); + } else { + tmpreg3 = ALLOC_GPR(); + tmpreg4 = ALLOC_GPR(); + emitpcode(PC_SRAWI, tmpreg4, opright.reg, 31); + emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg); + emitpcode(PC_MULLW, tmpreg1, opleft.regHi, opright.reg); + emitpcode(PC_MULLW, reg, opleft.reg, opright.reg); + emitpcode(PC_MULLW, tmpreg3, opleft.reg, tmpreg4); + emitpcode(PC_ADD, regHi, tmpreg2, tmpreg1); + emitpcode(PC_ADD, regHi, regHi, tmpreg3); + } + } + break; + case 8 + 8: + if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo) && left->data.intval.hi == 0) { + tmpreg1 = ALLOC_GPR(); + tmpreg2 = ALLOC_GPR(); + emitpcode(PC_MULHWU, tmpreg1, opright.reg, opleft.reg); + emitpcode(PC_MULLW, tmpreg2, opright.reg, opleft.regHi); + emitpcode(PC_MULLI, reg, opright.reg, LOW_PART(left->data.intval.lo)); + emitpcode(PC_ADD, regHi, tmpreg1, tmpreg2); + } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo) && right->data.intval.hi == 0) { + tmpreg1 = ALLOC_GPR(); + tmpreg2 = ALLOC_GPR(); + emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg); + emitpcode(PC_MULLW, tmpreg1, opleft.regHi, opright.reg); + emitpcode(PC_MULLI, reg, opleft.reg, LOW_PART(right->data.intval.lo)); + emitpcode(PC_ADD, regHi, tmpreg2, tmpreg1); + } else { + tmpreg1 = ALLOC_GPR(); + tmpreg2 = ALLOC_GPR(); + tmpreg3 = ALLOC_GPR(); + tmpreg4 = ALLOC_GPR(); + emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg); + emitpcode(PC_MULLW, tmpreg1, opleft.regHi, opright.reg); + emitpcode(PC_ADD, tmpreg3, tmpreg2, tmpreg1); + emitpcode(PC_MULLW, tmpreg4, opleft.reg, opright.regHi); + emitpcode(PC_MULLW, reg, opleft.reg, opright.reg); + emitpcode(PC_ADD, regHi, tmpreg3, tmpreg4); + } + break; + default: + CError_FATAL(8218); + } + } + + output->optype = OpndType_GPRPair; + output->reg = reg; + output->regHi = regHi; +} + +void I8_gen_BINNOT(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *inner; + Operand op; + int reg; + int regHi; + + inner = expr->data.monadic; + memclrw(&op, sizeof(Operand)); + GEN_NODE(inner, &op); + coerce_to_register_pair(&op, inner->rtype, 0, 0); + + reg = outputReg ? outputReg : ALLOC_GPR(); + regHi = outputRegHi ? outputRegHi : ALLOC_GPR(); + emitpcode(PC_NOR, reg, op.reg, op.reg); + emitpcode(PC_NOR, regHi, op.regHi, op.regHi); + + output->optype = OpndType_GPRPair; + output->reg = reg; + output->regHi = regHi; +} + +void I8_gen_MONMIN(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *inner; + Operand op; + int reg; + int regHi; + + inner = expr->data.monadic; + memclrw(&op, sizeof(Operand)); + GEN_NODE(inner, &op); + coerce_to_register_pair(&op, inner->rtype, 0, 0); + + reg = outputReg ? outputReg : ALLOC_GPR(); + regHi = outputRegHi ? outputRegHi : ALLOC_GPR(); + emitpcode(PC_SUBFIC, reg, op.reg, 0); + emitpcode(PC_SUBFZE, regHi, op.regHi); + + output->optype = OpndType_GPRPair; + output->reg = reg; + output->regHi = regHi; +} + +void I8_gen_ASS(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + Type *type; + ENode *left; + ENode *right; + Operand opleft; + Operand opright; + VarInfo *vi; + + type = expr->rtype; + if (ENODE_IS(expr, ECONDASS)) { + left = expr->data.cond.expr1; + if (ENODE_IS(left, EINDIRECT)) + left = left->data.monadic; + else + CError_FATAL(8328); + right = expr->data.cond.expr2; + } else { + left = expr->data.diadic.left; + right = expr->data.diadic.right; + } + + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + + if (ENODE_IS(left, EOBJREF) && OBJECT_REG(left->data.objref)) { + vi = Registers_GetVarInfo(left->data.objref); + GEN_NODE_TO_REG(right, vi->reg, vi->regHi, &opright); + if (vi->rclass != RegClass_GPR) { + CError_FATAL(8348); + } else { + coerce_to_register_pair(&opright, type, vi->reg, vi->regHi); + *output = opright; + } + return; + } + + if (TYPE_FITS_IN_REGISTER(type)) { + GEN_NODE(right, &opright); + coerce_to_register_pair(&opright, right->rtype, 0, 0); + + if (ENODE_IS(left, EBITFIELD)) { + CError_FATAL(8376); + } else { + GEN_NODE(left, &opleft); + indirect(&opleft, left); + store_pair(opright.reg, opright.regHi, &opleft, type); + } + + output->optype = OpndType_GPRPair; + output->reg = opright.reg; + output->regHi = opright.regHi; + } +} + +void I8_gen_POSTINCDEC(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *inner; + Type *type; + int flag; + int reg; + int regHi; + Operand op1; + Operand op2; + Operand op3; + + inner = expr->data.monadic->data.monadic; + type = expr->rtype; + flag = 0; + memclrw(&op1, sizeof(Operand)); + memclrw(&op2, sizeof(Operand)); + + if (ENODE_IS(inner, EOBJREF) && (reg = OBJECT_REG(inner->data.objref))) { + regHi = Registers_GetVarInfo(inner->data.objref)->regHi; + output->optype = OpndType_GPRPair; + output->reg = (outputReg && outputReg != reg && outputReg != regHi) ? outputReg : ALLOC_GPR(); + output->regHi = (outputRegHi && outputRegHi != regHi && outputRegHi != reg) ? outputRegHi : ALLOC_GPR(); + emitpcode(PC_MR, output->reg, reg); + emitpcode(PC_MR, output->regHi, regHi); + if (ENODE_IS(expr, EPOSTINC)) { + emitpcode(PC_ADDIC, reg, reg, 1); + emitpcode(PC_ADDME, regHi, regHi); + } else { + emitpcode(PC_ADDIC, reg, reg, -1); + emitpcode(PC_ADDZE, regHi, regHi); + } + return; + } + + CError_ASSERT(8446, !ENODE_IS(inner, EBITFIELD)); + + GEN_NODE(inner, &op1); + indirect(&op1, inner); + op2 = op1; + coerce_to_register_pair(&op2, type, 0, 0); + + output->optype = OpndType_GPRPair; + output->reg = ALLOC_GPR(); + output->regHi = ALLOC_GPR(); + + emitpcode(PC_MR, output->reg, op2.reg); + emitpcode(PC_MR, output->regHi, op2.regHi); + + reg = ALLOC_GPR(); + regHi = ALLOC_GPR(); + + if (ENODE_IS(expr, EPOSTINC)) { + emitpcode(PC_ADDIC, reg, op2.reg, 1); + emitpcode(PC_ADDZE, regHi, op2.regHi); + } else { + emitpcode(PC_ADDIC, reg, op2.reg, -1); + emitpcode(PC_ADDME, regHi, op2.regHi); + } + store_pair(reg, regHi, &op1, type); +} + +void I8_gen_INDIRECT(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + ENode *inner; + VarInfo *vi; + + inner = expr->data.monadic; + if (ENODE_IS(inner, EOBJREF) && OBJECT_REG(inner->data.objref)) { + vi = Registers_GetVarInfo(inner->data.objref); + switch (vi->rclass) { + case RegClass_GPR: + output->optype = OpndType_GPRPair; + break; + case RegClass_FPR: + output->optype = OpndType_FPR; + break; + default: + CError_FATAL(8511); + } + + output->reg = vi->reg; + output->regHi = vi->regHi; + output->object = NULL; + return; + } + + if (ENODE_IS(inner, EBITFIELD)) { + CError_FATAL(8529); + return; + } + + GEN_NODE(inner, output); + indirect(output, inner); +} + +void I8_gen_condition(ENode *cond, Operand *output, int write_to_gpr) { + ENode *left; + ENode *right; + Operand opleft; + Operand opright; + Operand tmpop; + int reg1; + int reg2; + int reg3; + int reg4; + int reg5; + + left = cond->data.diadic.left; + right = cond->data.diadic.right; + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + memclrw(&tmpop, sizeof(Operand)); + + if (right->hascall) { + GEN_NODE(right, &opright); + if (right->rtype->size < 4) + extend32(&opright, right->rtype, 0); + ENSURE_GPR(&opright, right->rtype, 0); + + if (right->rtype->size < 8) { + short tmp = ALLOC_GPR(); + if (is_unsigned(right->rtype)) + load_immediate(tmp, 0); + else + emitpcode(PC_SRAWI, tmp, opright.reg, 31); + opright.optype = OpndType_GPRPair; + opright.regHi = tmp; + } + + GEN_NODE(left, &opleft); + if (left->rtype->size < 4) + extend32(&opleft, left->rtype, 0); + ENSURE_GPR(&opleft, left->rtype, 0); + + if (left->rtype->size < 8) { + short tmp = ALLOC_GPR(); + // this looks like a bug??? surely this should check left->rtype + if (is_unsigned(right->rtype)) + load_immediate(tmp, 0); + else + emitpcode(PC_SRAWI, tmp, opleft.reg, 31); + opleft.optype = OpndType_GPRPair; + opleft.regHi = tmp; + } + } else { + GEN_NODE(left, &opleft); + ENSURE_GPR(&opleft, left->rtype, 0); + if (left->rtype->size < 4) + extend32(&opleft, left->rtype, 0); + + if (left->rtype->size < 8) { + short tmp = ALLOC_GPR(); + if (is_unsigned(right->rtype)) + load_immediate(tmp, 0); + else + emitpcode(PC_SRAWI, tmp, opleft.reg, 31); + opleft.optype = OpndType_GPRPair; + opleft.regHi = tmp; + } + + GEN_NODE(right, &opright); + if (right->rtype->size < 4) + extend32(&opright, right->rtype, 0); + ENSURE_GPR(&opright, right->rtype, 0); + + if (right->rtype->size < 8) { + short tmp = ALLOC_GPR(); + if (is_unsigned(right->rtype)) + load_immediate(tmp, 0); + else + emitpcode(PC_SRAWI, tmp, opright.reg, 31); + opright.optype = OpndType_GPRPair; + opright.regHi = tmp; + } + } + + CError_ASSERT(8704, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair); + + switch (cond->type) { + case EEQU: + case ENOTEQU: + reg1 = ALLOC_GPR(); + reg2 = ALLOC_GPR(); + emitpcode(PC_XOR, reg1, opleft.reg, opright.reg); + emitpcode(PC_XOR, reg2, opleft.regHi, opright.regHi); + emitpcode(PC_OR, reg2, reg1, reg2); + if (write_to_gpr) { + if (ENODE_IS(cond, EEQU)) { + emitpcode(PC_CNTLZW, reg2, reg2); + emitpcode(PC_RLWINM, reg2, reg2, 27, 5, 31); + } else { + emitpcode(PC_ADDIC, reg1, reg2, -1); + emitpcode(PC_SUBFE, reg2, reg1, reg2); + } + output->optype = OpndType_GPR; + output->reg = reg2; + output->regHi = 0; + } else { + emitpcode(PC_CMPI, 0, reg2, 0); + output->optype = OpndType_CRField; + output->reg = 0; + output->regOffset = cond->type; + } + break; + case EGREATER: + tmpop = opleft; + opleft = opright; + opright = tmpop; + case ELESS: + reg1 = ALLOC_GPR(); + reg2 = ALLOC_GPR(); + reg3 = ALLOC_GPR(); + if (left->rtype != TYPE(&stunsignedlonglong) && right->rtype != TYPE(&stunsignedlonglong)) { + emitpcode(PC_XORIS, reg1, opleft.regHi, 0x8000); + emitpcode(PC_XORIS, reg2, opright.regHi, 0x8000); + reg4 = reg1; + reg5 = reg2; + } else { + reg4 = opleft.regHi; + reg5 = opright.regHi; + } + emitpcode(PC_SUBFC, reg3, opright.reg, opleft.reg); + emitpcode(PC_SUBFE, reg2, reg5, reg4); + emitpcode(PC_SUBFE, reg2, reg1, reg1); + emitpcode(PC_NEG, reg2, reg2); + if (write_to_gpr) { + output->optype = OpndType_GPR; + output->reg = reg2; + output->regHi = 0; + } else { + emitpcode(PC_CMPI, 0, reg2, 0); + output->optype = OpndType_CRField; + output->reg = 0; + output->regOffset = ENOTEQU; + } + break; + case ELESSEQU: + tmpop = opleft; + opleft = opright; + opright = tmpop; + case EGREATEREQU: + reg1 = ALLOC_GPR(); + reg2 = ALLOC_GPR(); + reg3 = ALLOC_GPR(); + if (left->rtype != TYPE(&stunsignedlonglong) && right->rtype != TYPE(&stunsignedlonglong)) { + emitpcode(PC_XORIS, reg1, opleft.regHi, 0x8000); + emitpcode(PC_XORIS, reg2, opright.regHi, 0x8000); + reg4 = reg1; + reg5 = reg2; + } else { + reg4 = opleft.regHi; + reg5 = opright.regHi; + } + emitpcode(PC_SUBFC, reg3, opright.reg, opleft.reg); + emitpcode(PC_SUBFE, reg2, reg5, reg4); + emitpcode(PC_SUBFE, reg2, reg1, reg1); + emitpcode(PC_NEG, reg2, reg2); + if (write_to_gpr) { + emitpcode(PC_SUBFIC, reg2, reg2, 1); + output->optype = OpndType_GPR; + output->reg = reg2; + output->regHi = 0; + } else { + emitpcode(PC_CMPI, 0, reg2, 0); + output->optype = OpndType_CRField; + output->reg = 0; + output->regOffset = EEQU; + } + break; + default: + CError_FATAL(8814); + } +} + +void I8_gen_SHL_SHR(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + static UInt32 used_regs[RegClassMax] = {0, 0, 0, 0, (1 << 3) | (1 << 4) | (1 << 5)}; + + ENode *left; + ENode *right; + Operand opleft; + Operand opright; + int is_uns; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + + GEN_NODE(left, &opleft); + coerce_to_register_pair(&opleft, left->rtype, 0, 0); + + output->optype = OpndType_GPRPair; + output->reg = ALLOC_GPR(); + output->regHi = ALLOC_GPR(); + + is_uns = is_unsigned(expr->rtype) != 0; + + if (ENODE_IS(right, EINTCONST)) { + if (ENODE_IS(expr, ESHL)) { + I8_ShiftLeftImmediate(opleft, right->data.intval.lo, is_uns, expr->rtype->size, output->reg, output->regHi); + } else { + I8_ShiftRightImmediate(opleft, right->data.intval.lo, is_uns, output->reg, output->regHi, 0); + } + return; + } + + GEN_NODE(right, &opright); + ENSURE_GPR(&opright, right->rtype, 0); + if (opright.optype == OpndType_GPRPair) { + opright.regHi = 0; + opright.optype = OpndType_GPR; + } + + CError_ASSERT(8890, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPR); + + if (opleft.regHi != high_reg) + emitpcode(PC_MR, high_reg, opleft.regHi); + if (opleft.reg != low_reg) + emitpcode(PC_MR, low_reg, opleft.reg); + if (opright.reg != 5) + emitpcode(PC_MR, 5, opright.reg); + + if (ENODE_IS(expr, ESHR)) { + if (is_unsigned(left->rtype)) + branch_subroutine(rt_shr2u, 0, used_regs); + else + branch_subroutine(rt_shr2i, 0, used_regs); + } else if (ENODE_IS(expr, ESHL)) { + branch_subroutine(rt_shl2i, 0, used_regs); + } else { + CError_FATAL(8909); + } + + emitpcode(PC_MR, output->reg, low_reg); + emitpcode(PC_MR, output->regHi, high_reg); +} + +void I8_gen_DIV_MOD(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + static UInt32 used_regs[RegClassMax] = {0, 0, 0, 0, (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6)}; + + int is_uns; + ENode *left; + ENode *right; + Operand opleft; + Operand opright; + SInt64 constval; + int shift; + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + memclrw(&opleft, sizeof(Operand)); + memclrw(&opright, sizeof(Operand)); + + GEN_NODE(left, &opleft); + coerce_to_register_pair(&opleft, left->rtype, 0, 0); + + output->optype = OpndType_GPRPair; + output->reg = ALLOC_GPR(); + output->regHi = ALLOC_GPR(); + + is_uns = is_unsigned(expr->rtype) != 0; + + if (ENODE_IS(right, EINTCONST)) + constval = (((SInt64) right->data.intval.hi) << 32) + right->data.intval.lo; + if (ENODE_IS(right, EINTCONST) && ((shift = I8_log2n(constval)) > 0)) { + CError_ASSERT(8976, opleft.optype == OpndType_GPRPair); + if (ENODE_IS(expr, EDIV)) { + I8_ShiftRightImmediate(opleft, shift, is_uns, output->reg, output->regHi, 1); + if (!is_uns) { + emitpcode(PC_ADDZE, output->reg, output->reg); + emitpcode(PC_ADDZE, output->regHi, output->regHi); + } + } else { + if (is_uns) { + if (shift < 32) { + emitpcode(PC_LI, output->regHi, 0); + emitpcode(PC_RLWINM, output->reg, opleft.reg, 0, 32 - shift, 31); + } else if (shift == 32) { + emitpcode(PC_LI, output->regHi, 0); + emitpcode(PC_MR, output->reg, opleft.reg); + } else if (shift <= 63) { + emitpcode(PC_RLWINM, output->regHi, opleft.regHi, 0, 32 - (shift - 32), 31); + emitpcode(PC_MR, output->reg, opleft.reg); + } else { + CError_FATAL(9018); + } + } else { + short tmpreg1 = ALLOC_GPR(); + short tmpreg2 = ALLOC_GPR(); + I8_ShiftRightImmediate(opleft, shift, is_uns, output->reg, output->regHi, 1); + emitpcode(PC_ADDZE, output->reg, output->reg); + emitpcode(PC_ADDZE, output->regHi, output->regHi); + I8_ShiftLeftImmediate(*output, shift, is_uns, expr->rtype->size, tmpreg1, tmpreg2); + emitpcode(PC_SUBFC, output->reg, tmpreg1, opleft.reg); + emitpcode(PC_SUBFE, output->regHi, tmpreg2, opleft.regHi); + } + } + return; + } + + GEN_NODE(right, &opright); + coerce_to_register_pair(&opright, right->rtype, 0, 0); + + CError_ASSERT(9048, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair); + + if (opleft.regHi != high_reg) + emitpcode(PC_MR, high_reg, opleft.regHi); + if (opleft.reg != low_reg) + emitpcode(PC_MR, low_reg, opleft.reg); + if (opright.regHi != high_reg2) + emitpcode(PC_MR, high_reg2, opright.regHi); + if (opright.reg != low_reg2) + emitpcode(PC_MR, low_reg2, opright.reg); + + if (ENODE_IS(expr, EDIV)) { + if (is_unsigned(left->rtype) || is_unsigned(right->rtype)) + branch_subroutine(rt_div2u, 0, used_regs); + else + branch_subroutine(rt_div2i, 0, used_regs); + } else if (ENODE_IS(expr, EMODULO)) { + if (is_unsigned(left->rtype) || is_unsigned(right->rtype)) + branch_subroutine(rt_mod2u, 0, used_regs); + else + branch_subroutine(rt_mod2i, 0, used_regs); + } else { + CError_FATAL(9074); + } + + emitpcode(PC_MR, output->reg, low_reg); + emitpcode(PC_MR, output->regHi, high_reg); +} + +void I8_gen_TYPCON(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + Type *dsttype; + ENode *inner; + Type *srctype; + short regHi; + short reg; + + static UInt32 used_regs[RegClassMax] = {0, 0, 0, 0, (1 << 3) | (1 << 4)}; + static UInt32 used_regs_f1[RegClassMax] = {0, 0, 0, (1 << 1), 0}; + + inner = expr->data.monadic; + srctype = inner->rtype; + dsttype = expr->rtype; + + if (IS_TYPE_VOID(dsttype)) { + GEN_NODE(inner, output); + if (ENODE_IS(inner, EINDIRECT) && (output->flags & OpndFlags_Volatile)) + coerce_to_register_pair(output, inner->rtype, 0, 0); + output->optype = OpndType_Absolute; + output->immediate = 0; + return; + } + + if (IS_TYPE_INT_OR_ENUM(srctype)) { + if (IS_TYPE_FLOAT(dsttype)) { + GEN_NODE(inner, output); + coerce_to_register_pair(output, srctype, 0, 0); + if (output->regHi != high_reg) + emitpcode(PC_MR, high_reg, output->regHi); + if (output->reg != low_reg) + emitpcode(PC_MR, low_reg, output->reg); + + if (is_unsigned(srctype)) { + branch_subroutine( + (dsttype->size == 4) ? rt_cvt_ull_flt : rt_cvt_ull_dbl, + 0, + used_regs); + } else { + branch_subroutine( + (dsttype->size == 4) ? rt_cvt_sll_flt : rt_cvt_sll_dbl, + 0, + used_regs); + } + + output->optype = OpndType_FPR; + output->reg = ALLOC_FPR(); + emitpcode(PC_FMR, output->reg, 1); + return; + } + + if (srctype->size < dsttype->size) { + CError_ASSERT(9171, TYPE_IS_8BYTES(dsttype)); + + GEN_NODE(inner, output); + if (srctype->size < 4 && + !ENODE_IS_INDIRECT_TO(inner, EBITFIELD) && + !((ENODE_IS_ASSIGN(inner) || ENODE_IS_RANGE(inner, EPOSTINC, EPREDEC)) && ENODE_IS(inner->data.monadic->data.monadic, EBITFIELD)) + ) { + extend32(output, srctype, outputReg); + } + extend64(output, srctype, outputReg, outputRegHi); + } else { + GEN_NODE_TO_REG(inner, outputReg, 0, output); + if (dsttype->size < srctype->size) { + coerce_to_register_pair(output, srctype, outputReg, outputRegHi); + output->optype = OpndType_GPR; + output->regHi = 0; + } + } + return; + } + + if (IS_TYPE_POINTER(srctype)) { + GEN_NODE_TO_REG(inner, outputReg, 0, output); + CError_ASSERT(9200, TYPE_IS_8BYTES(expr->rtype)); + GEN_NODE_TO_REG(inner, outputReg, 0, output); + + regHi = outputRegHi ? outputRegHi : ALLOC_GPR(); + if (regHi == output->reg) { + reg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_MR, reg, output->reg); + output->reg = reg; + } + if (is_unsigned(inner->rtype)) + load_immediate(regHi, 0); + else + emitpcode(PC_SRAWI, regHi, output->reg, 31); + output->optype = OpndType_GPRPair; + output->regHi = regHi; + return; + } + + if (IS_TYPE_FLOAT(srctype)) { + if (IS_TYPE_FLOAT(dsttype)) { + CError_FATAL(9222); + return; + } + + GEN_NODE(inner, output); + ENSURE_FPR(output, srctype, 0); + if (output->reg != 1) + emitpcode(PC_FMR, 1, output->reg); + + branch_subroutine(rt_cvt_dbl_usll, 0, used_regs_f1); + + output->optype = OpndType_GPRPair; + output->reg = ALLOC_GPR(); + output->regHi = ALLOC_GPR(); + emitpcode(PC_MR, output->reg, low_reg); + emitpcode(PC_MR, output->regHi, high_reg); + return; + } + + if (IS_TYPE_STRUCT(srctype)) { + GEN_NODE_TO_REG(inner, outputReg, 0, output); + + if (TYPE_IS_8BYTES(expr->rtype) && dsttype->size == srctype->size) { + coerce_to_register_pair(output, srctype, outputReg, outputRegHi); + } else { + CError_FATAL(9256); + } + return; + } + + CError_FATAL(9261); +} + +void gen_VECTOR128CONST(ENode *expr, short outputReg, short outputRegHi, Operand *output) { + int gpr; + int vr; + COVCResult result; + + vr = outputReg ? outputReg : ALLOC_VR(); + if (!canoptimizevectorconst(&expr->data.vector128val, expr->rtype, &result)) + CError_FATAL(9282); + + if (result.op1 != -1) { + emitpcode(result.op1, vr, result.arg); + output->optype = OpndType_VR; + output->reg = vr; + return; + } + + if (result.op2 != -1) { + gpr = ALLOC_GPR(); + emitpcode(PC_LI, gpr, result.arg); + emitpcode(result.op2, vr, 0, gpr); + output->optype = OpndType_VR; + output->reg = vr; + return; + } + + CError_FATAL(9298); +} diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Intrinsics.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Intrinsics.c new file mode 100644 index 0000000..49334b8 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Intrinsics.c @@ -0,0 +1,4894 @@ +#include "compiler/Intrinsics.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CScope.h" +#include "compiler/CompilerTools.h" +#include "compiler/FunctionCalls.h" +#include "compiler/InstrSelection.h" +#include "compiler/PCode.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/PPCError.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/StructMoves.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/types.h" + +Object *__memcpy_object; +static Object *intrinsics[311]; +int VectorConditions; // unused? +static Object *cur_intrinsic_object; + +static TypePointer stvectorunsignedchar_ptr = {TYPEPOINTER, 4, TYPE(&stvectorunsignedchar), 0}; +static TypePointer stvectorsignedchar_ptr = {TYPEPOINTER, 4, TYPE(&stvectorsignedchar), 0}; +static TypePointer stvectorboolchar_ptr = {TYPEPOINTER, 4, TYPE(&stvectorboolchar), 0}; +static TypePointer stvectorunsignedshort_ptr = {TYPEPOINTER, 4, TYPE(&stvectorunsignedshort), 0}; +static TypePointer stvectorsignedshort_ptr = {TYPEPOINTER, 4, TYPE(&stvectorsignedshort), 0}; +static TypePointer stvectorboolshort_ptr = {TYPEPOINTER, 4, TYPE(&stvectorboolshort), 0}; +static TypePointer stvectorunsignedlong_ptr = {TYPEPOINTER, 4, TYPE(&stvectorunsignedlong), 0}; +static TypePointer stvectorsignedlong_ptr = {TYPEPOINTER, 4, TYPE(&stvectorsignedlong), 0}; +static TypePointer stvectorboollong_ptr = {TYPEPOINTER, 4, TYPE(&stvectorboollong), 0}; +static TypePointer stvectorfloat_ptr = {TYPEPOINTER, 4, TYPE(&stvectorfloat), 0}; +static TypePointer stvectorpixel_ptr = {TYPEPOINTER, 4, TYPE(&stvectorpixel), 0}; +static TypePointer stunsignedchar_ptr = {TYPEPOINTER, 4, TYPE(&stunsignedchar), 0}; +static TypePointer stsignedchar_ptr = {TYPEPOINTER, 4, TYPE(&stsignedchar), 0}; +static TypePointer stunsignedshort_ptr = {TYPEPOINTER, 4, TYPE(&stunsignedshort), 0}; +static TypePointer stsignedshort_ptr = {TYPEPOINTER, 4, TYPE(&stsignedshort), 0}; +static TypePointer stunsignedlong_ptr = {TYPEPOINTER, 4, TYPE(&stunsignedlong), 0}; +static TypePointer stsignedlong_ptr = {TYPEPOINTER, 4, TYPE(&stsignedlong), 0}; +static TypePointer stunsignedint_ptr = {TYPEPOINTER, 4, TYPE(&stunsignedint), 0}; +static TypePointer stsignedint_ptr = {TYPEPOINTER, 4, TYPE(&stsignedint), 0}; +static TypePointer stfloat_ptr = {TYPEPOINTER, 4, TYPE(&stfloat), 0}; + +// Verify1VectorArg2Ops +typedef struct TypeTable22 { + Type *rtype; + Type *arg1; + int opcode1; + int opcode2; +} TypeTable22; + +// VerifyNoVectorArgs +typedef struct TypeTable11 { + Type *rtype; + int opcode; +} TypeTable11; + +// Verify1VectorArg +typedef struct TypeTable21 { + Type *rtype; + Type *arg1; + int opcode; +} TypeTable21; + +// Verify2VectorArgs +typedef struct TypeTable31 { + Type *rtype; + Type *arg1; + Type *arg2; + int opcode; +} TypeTable31; + +// Verify3VectorArgs +typedef struct TypeTable41 { + Type *rtype; + Type *arg1; + Type *arg2; + Type *arg3; + int opcode; +} TypeTable41; + +static TypeTable31 vector_add_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VADDUBM, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VADDUBM, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VADDUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VADDUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VADDUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VADDUBM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VADDUHM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VADDUHM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VADDUHM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDUWM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VADDUWM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VADDUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VADDUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VADDUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VADDUWM, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VADDFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_addc_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDCUW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_adds_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VADDUBS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VADDUBS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VADDUBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VADDSBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VADDSBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VADDSBS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VADDUHS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VADDUHS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VADDUHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VADDSHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VADDSHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VADDSHS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDUWS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VADDUWS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VADDUWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VADDSWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VADDSWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VADDSWS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_and_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VAND, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VAND, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VAND, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VAND, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VAND, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VAND, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VAND, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VAND, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VAND, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VAND, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VAND, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VAND, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VAND, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VAND, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VAND, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VAND, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VAND, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VAND, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VAND, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VAND, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VAND, + TYPE(&stvectorfloat), TYPE(&stvectorboollong), TYPE(&stvectorfloat), PC_VAND, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VAND, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VAND, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_andc_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VANDC, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VANDC, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VANDC, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VANDC, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VANDC, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VANDC, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VANDC, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VANDC, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VANDC, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VANDC, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VANDC, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VANDC, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VANDC, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VANDC, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VANDC, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VANDC, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VANDC, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VANDC, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VANDC, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VANDC, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VANDC, + TYPE(&stvectorfloat), TYPE(&stvectorboollong), TYPE(&stvectorfloat), PC_VANDC, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VANDC, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VANDC, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_avg_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VAVGUB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VAVGSB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VAVGUH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VAVGSH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VAVGUW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VAVGSW, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_ceil_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRFIP, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_cmpb_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPBFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_cmpeq_type_table[] = { + TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_cmpge_type_table[] = { + TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_cmpgt_type_table[] = { + TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_ctf_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VCFUX, + TYPE(&stvectorfloat), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VCFSX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_cts_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VCTSXS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_ctu_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VCTUXS, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_dss_type_table[] = { + TYPE(&stvoid), TYPE(&stsignedint), PC_DSS, PC_B, + NULL, NULL, 0 +}; +static TypeTable11 vector_dssall_type_table[] = { + TYPE(&stvoid), PC_DSSALL, + NULL, 0 +}; +static TypeTable41 vector_datastream_type_table[] = { + TYPE(&stvoid), TYPE(&stvectorunsignedchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorsignedchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorboolchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorunsignedshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorsignedshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorboolshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorpixel_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorunsignedlong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorsignedlong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorboollong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stvectorfloat_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stunsignedchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stsignedchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stunsignedshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stsignedshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stunsignedint_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stsignedint_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stunsignedlong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stsignedlong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + TYPE(&stvoid), TYPE(&stfloat_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_expte_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VEXPTEFP, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_floor_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRFIM, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_load_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stvectorunsignedchar_ptr), PC_LVX, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVX, + TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stvectorsignedchar_ptr), PC_LVX, + TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVX, + TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stvectorboolchar_ptr), PC_LVX, + TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stvectorunsignedshort_ptr), PC_LVX, + TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVX, + TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stvectorsignedshort_ptr), PC_LVX, + TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVX, + TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stvectorboolshort_ptr), PC_LVX, + TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stvectorpixel_ptr), PC_LVX, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stvectorunsignedlong_ptr), PC_LVX, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVX, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVX, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stvectorsignedlong_ptr), PC_LVX, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVX, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVX, + TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stvectorboollong_ptr), PC_LVX, + TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stvectorfloat_ptr), PC_LVX, + TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_loade_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVEBX, + TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVEBX, + TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVEHX, + TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVEHX, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVEWX, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVEWX, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVEWX, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVEWX, + TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVEWX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_loadl_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stvectorunsignedchar_ptr), PC_LVXL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVXL, + TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stvectorsignedchar_ptr), PC_LVXL, + TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVXL, + TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stvectorboolchar_ptr), PC_LVXL, + TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stvectorunsignedshort_ptr), PC_LVXL, + TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVXL, + TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stvectorsignedshort_ptr), PC_LVXL, + TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVXL, + TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stvectorboolshort_ptr), PC_LVXL, + TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stvectorpixel_ptr), PC_LVXL, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stvectorunsignedlong_ptr), PC_LVXL, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVXL, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVXL, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stvectorsignedlong_ptr), PC_LVXL, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVXL, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVXL, + TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stvectorboollong_ptr), PC_LVXL, + TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stvectorfloat_ptr), PC_LVXL, + TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVXL, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_loge_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VLOGEFP, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_lvsl_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVSL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVSL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVSL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVSL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVSL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVSL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVSL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVSL, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVSL, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_lvsr_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVSR, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVSR, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVSR, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVSR, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVSR, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVSR, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVSR, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVSR, + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVSR, + NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_madd_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMADDFP, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_madds_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMHADDSHS, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_max_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMAXUB, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VMAXUB, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VMAXUB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMAXSB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VMAXSB, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VMAXSB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMAXUH, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VMAXUH, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VMAXUH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMAXSH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VMAXSH, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VMAXSH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMAXUW, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VMAXUW, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VMAXUW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMAXSW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VMAXSW, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VMAXSW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMAXFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_mergeh_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGHB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMRGHB, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VMRGHB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGHH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMRGHH, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VMRGHH, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VMRGHH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMRGHW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMRGHW, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VMRGHW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMRGHW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_mergel_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGLB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMRGLB, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VMRGLB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGLH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMRGLH, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VMRGLH, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VMRGLH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMRGLW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMRGLW, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VMRGLW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMRGLW, + NULL, NULL, NULL, 0 +}; +static TypeTable11 vector_mfvscr_type_table[] = { + TYPE(&stvectorunsignedshort), PC_MFVSCR, + NULL, 0 +}; +static TypeTable31 vector_min_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMINUB, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VMINUB, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VMINUB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMINSB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VMINSB, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VMINSB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMINUH, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VMINUH, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VMINUH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMINSH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VMINSH, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VMINSH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMINUW, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VMINUW, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VMINUW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMINSW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VMINSW, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VMINSW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMINFP, + NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_mladd_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMLADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMLADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMLADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMLADDUHM, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_mradds_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMHRADDSHS, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_msum_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VMSUMUBM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VMSUMUHM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedlong), PC_VMSUMMBM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VMSUMSHM, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_msums_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VMSUMUHS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VMSUMSHS, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable21 vector_mtvscr_type_table[] = { + TYPE(&stvoid), TYPE(&stvectorunsignedchar), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorsignedchar), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorboolchar), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorunsignedshort), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorsignedshort), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorboolshort), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorpixel), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorsignedlong), PC_MTVSCR, + TYPE(&stvoid), TYPE(&stvectorboollong), PC_MTVSCR, + NULL, NULL, 0 +}; +static TypeTable31 vector_mule_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMULEUB, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMULESB, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMULEUH, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMULESH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_mulo_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMULOUB, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMULOSB, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMULOUH, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMULOSH, + NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_nmsub_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VNMSUBFP, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_nor_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VNOR, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VNOR, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VNOR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VNOR, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VNOR, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VNOR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VNOR, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VNOR, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VNOR, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VNOR, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_or_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VOR, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VOR, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VOR, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VOR, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VOR, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VOR, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VOR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VOR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VOR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VOR, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VOR, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VOR, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VOR, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VOR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VOR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VOR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VOR, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VOR, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VOR, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VOR, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VOR, + TYPE(&stvectorfloat), TYPE(&stvectorboollong), TYPE(&stvectorfloat), PC_VOR, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VOR, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VOR, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_pack_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKUHUM, + TYPE(&stvectorboolchar), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VPKUHUM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKUWUM, + TYPE(&stvectorboolshort), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VPKUWUM, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_packpx_type_table[] = { + TYPE(&stvectorpixel), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKPX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_packs_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUS, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKSHSS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUS, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKSWSS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_packsu_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKSHUS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKSWUS, + NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_perm_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedchar), PC_VPERM, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorunsignedchar), PC_VPERM, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_re_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VREFP, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_rl_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VRLB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VRLB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VRLH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VRLH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VRLW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VRLW, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_round_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRFIN, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_rsqrte_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRSQRTEFP, PC_B, + NULL, NULL, 0 +}; +static TypeTable41 vector_sel_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSEL, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSEL, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSEL, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSEL, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSEL, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VSEL, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSEL, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSEL, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSEL, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSEL, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSEL, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VSEL, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSEL, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSEL, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSEL, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSEL, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSEL, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VSEL, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorunsignedlong), PC_VSEL, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VSEL, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_sl_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSLB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSLB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSLH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSLH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSLW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSLW, + NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_sld_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), PC_VSLDOI, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSLDOI, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), PC_VSLDOI, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSLDOI, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stsignedint), PC_VSLDOI, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VSLDOI, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSLDOI, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VSLDOI, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_sll_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSL, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedchar), PC_VSL, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedshort), PC_VSL, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSL, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_slo_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSLO, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedchar), PC_VSLO, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSLO, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSLO, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VSLO, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedchar), PC_VSLO, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VSLO, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VSLO, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VSLO, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorsignedchar), PC_VSLO, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VSLO, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorsignedchar), PC_VSLO, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VSLO, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), PC_VSLO, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorunsignedchar), PC_VSLO, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorsignedchar), PC_VSLO, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_splat_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), PC_VSPLTB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSPLTB, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stsignedint), PC_VSPLTB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), PC_VSPLTH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSPLTH, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stsignedint), PC_VSPLTH, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stsignedint), PC_VSPLTH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VSPLTW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSPLTW, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stsignedint), PC_VSPLTW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VSPLTW, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_splat_s8_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSPLTISB, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_splat_s16_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSPLTISH, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_splat_s32_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSPLTISW, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_splat_u8_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), PC_VSPLTISB, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_splat_u16_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stsignedint), PC_VSPLTISH, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_splat_u32_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VSPLTISW, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_sr_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSRH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSRH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSRW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSRW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_sra_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRAB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRAB, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSRAH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSRAH, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSRAW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSRAW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_srl_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSR, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedchar), PC_VSR, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedshort), PC_VSR, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSR, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_sro_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRO, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedchar), PC_VSRO, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRO, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSRO, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VSRO, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedchar), PC_VSRO, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VSRO, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VSRO, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VSRO, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorsignedchar), PC_VSRO, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VSRO, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorsignedchar), PC_VSRO, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VSRO, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), PC_VSRO, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorunsignedchar), PC_VSRO, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorsignedchar), PC_VSRO, + NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_st_type_table[] = { + TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stvectorunsignedchar_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stvectorsignedchar_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stvectorunsignedshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stvectorsignedshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stvectorunsignedlong_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stvectorsignedlong_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stvectorfloat_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stvectorpixel_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stvectorboolchar_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stvectorboolshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stvectorboollong_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVX, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_ste_type_table[] = { + TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVEBX, + TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVEBX, + TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVEBX, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVEBX, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVEWX, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_stl_type_table[] = { + TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stvectorunsignedchar_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stvectorsignedchar_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stvectorunsignedshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stvectorsignedshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stvectorunsignedlong_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stvectorsignedlong_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stvectorfloat_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stvectorpixel_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stvectorboolchar_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stvectorboolshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stvectorboollong_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVXL, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVXL, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_sub_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSUBUBM, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBM, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSUBUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VSUBUBM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSUBUHM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSUBUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VSUBUHM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBUWM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSUBUWM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSUBUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSUBUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VSUBUWM, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VSUBFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_subc_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBCUW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_subs_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSUBUBS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSUBUBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBSBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSUBSBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VSUBSBS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSUBUHS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSUBUHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBSHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSUBSHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VSUBSHS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBUWS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSUBUWS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSUBUWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBSWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSUBSWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VSUBSWS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_sum4s_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VSUM4UBS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedlong), PC_VSUM4SBS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VSUM4SHS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_sum2s_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUM2SWS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_sums_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUMSWS, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_trunc_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRFIZ, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_unpack2sh_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGHB, + TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGHH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_unpack2sl_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGLB, + TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGLH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_unpack2uh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGHB, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGHH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_unpack2ul_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGLB, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGLH, + NULL, NULL, NULL, 0 +}; +static TypeTable21 vector_unpackh_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VUPKHSB, + TYPE(&stvectorboolshort), TYPE(&stvectorboolchar), PC_VUPKHSB, + TYPE(&stvectorunsignedlong), TYPE(&stvectorpixel), PC_VUPKHPX, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), PC_VUPKHSH, + TYPE(&stvectorboollong), TYPE(&stvectorboolshort), PC_VUPKHSH, + NULL, NULL, 0 +}; +static TypeTable21 vector_unpackl_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VUPKLSB, + TYPE(&stvectorboolshort), TYPE(&stvectorboolchar), PC_VUPKLSB, + TYPE(&stvectorunsignedlong), TYPE(&stvectorpixel), PC_VUPKLPX, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), PC_VUPKLSH, + TYPE(&stvectorboollong), TYPE(&stvectorboolshort), PC_VUPKLSH, + NULL, NULL, 0 +}; +static TypeTable31 vector_xor_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VXOR, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VXOR, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VXOR, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VXOR, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VXOR, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VXOR, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VXOR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VXOR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VXOR, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VXOR, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VXOR, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VXOR, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VXOR, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VXOR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VXOR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VXOR, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VXOR, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VXOR, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VXOR, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VXOR, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VXOR, + TYPE(&stvectorfloat), TYPE(&stvectorboollong), TYPE(&stvectorfloat), PC_VXOR, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VXOR, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VXOR, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_eq_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_ge_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_gt_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_in_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPBFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_le_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_lt_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP +}; +static TypeTable22 vector_all_nan_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), PC_VCMPEQFP, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_all_ne_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_nge_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_ngt_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_nle_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_all_nlt_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_all_numeric_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), PC_VCMPEQFP, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_any_eq_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_any_ge_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_any_gt_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_any_le_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_any_lt_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_any_nan_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), PC_VCMPEQFP, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_any_ne_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VCMPEQUH, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VCMPEQUW, + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_any_nge_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_any_ngt_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_any_nle_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_any_nlt_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_any_numeric_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), PC_VCMPEQFP, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_any_out_type_table[] = { + TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPBFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vaddubm_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VADDUBM, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VADDUBM, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VADDUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VADDUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VADDUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VADDUBM, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vadduhm_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VADDUHM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VADDUHM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VADDUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VADDUHM, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vadduwm_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDUWM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VADDUWM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VADDUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VADDUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VADDUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VADDUWM, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vaddfp_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VADDFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vaddubs_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VADDUBS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VADDUBS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VADDUBS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vaddsbs_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VADDSBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VADDSBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VADDSBS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vadduhs_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VADDUHS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VADDUHS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VADDUHS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vaddshs_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VADDSHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VADDSHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VADDSHS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vadduws_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDUWS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VADDUWS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VADDUWS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vaddsws_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VADDSWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VADDSWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VADDSWS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vavgub_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VAVGUB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vavgsb_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VAVGSB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vavguh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VAVGUH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vavgsh_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VAVGSH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vavguw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VAVGUW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vavgsw_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VAVGSW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpequb_type_table[] = { + TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, + TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpequh_type_table[] = { + TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, + TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpequw_type_table[] = { + TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, + TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpeqfp_type_table[] = { + TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpgtub_type_table[] = { + TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpgtsb_type_table[] = { + TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpgtuh_type_table[] = { + TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpgtsh_type_table[] = { + TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpgtuw_type_table[] = { + TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpgtsw_type_table[] = { + TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcmpgtfp_type_table[] = { + TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcfux_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VCFUX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vcfsx_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VCFSX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_lvebx_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVEBX, + TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVEBX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_lvehx_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVEHX, + TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVEHX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_lvewx_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVEWX, + TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVEWX, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVEWX, + TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVEWX, + TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVEWX, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmaxub_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMAXUB, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VMAXUB, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VMAXUB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmaxsb_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMAXSB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VMAXSB, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VMAXSB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmaxuh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMAXUH, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VMAXUH, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VMAXUH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmaxsh_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMAXSH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VMAXSH, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VMAXSH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmaxuw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMAXUW, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VMAXUW, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VMAXUW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmaxsw_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMAXSW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VMAXSW, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VMAXSW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmaxfp_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMAXFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmrghb_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGHB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMRGHB, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VMRGHB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmrghh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGHH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMRGHH, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VMRGHH, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VMRGHH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmrghw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMRGHW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMRGHW, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VMRGHW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMRGHW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmrglb_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGLB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMRGLB, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VMRGLB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmrglh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGLH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMRGLH, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VMRGLH, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VMRGLH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmrglw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMRGLW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMRGLW, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VMRGLW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMRGLW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vminub_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMINUB, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VMINUB, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VMINUB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vminsb_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMINSB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VMINSB, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VMINSB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vminuh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMINUH, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VMINUH, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VMINUH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vminsh_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMINSH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VMINSH, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VMINSH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vminuw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMINUW, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VMINUW, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VMINUW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vminsw_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMINSW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VMINSW, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VMINSW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vminfp_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMINFP, + NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_vmsumubm_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VMSUMUBM, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_vmsumuhm_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VMSUMUHM, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_vmsummbm_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedlong), PC_VMSUMMBM, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_vmsumshm_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VMSUMSHM, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_vmsumuhs_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VMSUMUHS, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_vmsumshs_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VMSUMSHS, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmuleub_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMULEUB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmulesb_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMULESB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmuleuh_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMULEUH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmulesh_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMULESH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmuloub_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMULOUB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmulosb_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMULOSB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmulouh_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMULOUH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vmulosh_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMULOSH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vpkuhum_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKUHUM, + TYPE(&stvectorboolchar), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VPKUHUM, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vpkuwum_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKUWUM, + TYPE(&stvectorboolshort), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VPKUWUM, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vpkuhus_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vpkshss_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKSHSS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vpkuwus_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vpkswss_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKSWSS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vpkshus_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKSHUS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vpkswus_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKSWUS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vrlb_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VRLB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VRLB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vrlh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VRLH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VRLH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vrlw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VRLW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VRLW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vslb_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSLB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSLB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vslh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSLH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSLH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vslw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSLW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSLW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vspltb_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), PC_VSPLTB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSPLTB, + TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stsignedint), PC_VSPLTB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsplth_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), PC_VSPLTH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSPLTH, + TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stsignedint), PC_VSPLTH, + TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stsignedint), PC_VSPLTH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vspltw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VSPLTW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSPLTW, + TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stsignedint), PC_VSPLTW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VSPLTW, + NULL, NULL, NULL, 0 +}; +static TypeTable22 vector_vspltisb_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSPLTISB, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_vspltish_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSPLTISH, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_vspltisw_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSPLTISW, PC_B, + NULL, NULL, 0 +}; +static TypeTable31 vector_vsrb_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsrh_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSRH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSRH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsrw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSRW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSRW, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsrab_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRAB, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRAB, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsrah_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSRAH, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSRAH, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsraw_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSRAW, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSRAW, + NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_stvebx_type_table[] = { + TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVEBX, + TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVEBX, + TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVEBX, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_stvehx_type_table[] = { + TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, + TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable41 vector_stvewx_type_table[] = { + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVEWX, + TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVEWX, + NULL, NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsububm_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSUBUBM, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBM, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSUBUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBM, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VSUBUBM, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsubuhm_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSUBUHM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHM, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSUBUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHM, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VSUBUHM, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsubuwm_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBUWM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSUBUWM, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSUBUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSUBUWM, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VSUBUWM, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VSUBFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsubfp_type_table[] = { + TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VSUBFP, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsububs_type_table[] = { + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSUBUBS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBS, + TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSUBUBS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsubsbs_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBSBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSUBSBS, + TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VSUBSBS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsubuhs_type_table[] = { + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSUBUHS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHS, + TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSUBUHS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsubshs_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBSHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSUBSHS, + TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VSUBSHS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsubuws_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBUWS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSUBUWS, + TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSUBUWS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsubsws_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBSWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSUBSWS, + TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VSUBSWS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsum4ubs_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VSUM4UBS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsum4sbs_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedlong), PC_VSUM4SBS, + NULL, NULL, NULL, 0 +}; +static TypeTable31 vector_vsum4shs_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VSUM4SHS, + NULL, NULL, NULL, 0 +}; +static TypeTable21 vector_vupkhsb_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VUPKHSB, + TYPE(&stvectorboolshort), TYPE(&stvectorboolchar), PC_VUPKHSB, + NULL, NULL, 0 +}; +static TypeTable21 vector_vupklsb_type_table[] = { + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VUPKLSB, + TYPE(&stvectorboolshort), TYPE(&stvectorboolchar), PC_VUPKLSB, + NULL, NULL, 0 +}; +static TypeTable22 vector_vupkhpx_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorpixel), PC_VUPKHPX, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_vupklpx_type_table[] = { + TYPE(&stvectorunsignedlong), TYPE(&stvectorpixel), PC_VUPKLPX, PC_B, + NULL, NULL, 0 +}; +static TypeTable21 vector_vupkhsh_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), PC_VUPKHSH, + TYPE(&stvectorboollong), TYPE(&stvectorboolshort), PC_VUPKHSH, + NULL, NULL, 0 +}; +static TypeTable21 vector_vupklsh_type_table[] = { + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), PC_VUPKLSH, + TYPE(&stvectorboollong), TYPE(&stvectorboolshort), PC_VUPKLSH, + NULL, NULL, 0 +}; +static TypeTable22 vector_abs_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBUBM, PC_VMAXSB, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBUHM, PC_VMAXSH, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBUWM, PC_VMAXSW, + TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VANDC, PC_B, + NULL, NULL, 0 +}; +static TypeTable22 vector_abss_type_table[] = { + TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBSBS, PC_VMAXSB, + TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBSHS, PC_VMAXSH, + TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBSWS, PC_VMAXSW, + NULL, NULL, 0 +}; +static void *typeTable[] = { + vector_add_type_table, + vector_addc_type_table, + vector_adds_type_table, + vector_and_type_table, + vector_andc_type_table, + vector_avg_type_table, + vector_ceil_type_table, + vector_cmpb_type_table, + vector_cmpeq_type_table, + vector_cmpge_type_table, + vector_cmpge_type_table, + vector_cmpgt_type_table, + vector_cmpgt_type_table, + vector_ctf_type_table, + vector_cts_type_table, + vector_ctu_type_table, + vector_dss_type_table, + vector_dssall_type_table, + vector_datastream_type_table, + vector_datastream_type_table, + vector_datastream_type_table, + vector_datastream_type_table, + vector_expte_type_table, + vector_floor_type_table, + vector_load_type_table, + vector_loade_type_table, + vector_loadl_type_table, + vector_loge_type_table, + vector_lvsl_type_table, + vector_lvsr_type_table, + vector_madd_type_table, + vector_madds_type_table, + vector_max_type_table, + vector_mergeh_type_table, + vector_mergel_type_table, + vector_mfvscr_type_table, + vector_min_type_table, + vector_mladd_type_table, + vector_mradds_type_table, + vector_msum_type_table, + vector_msums_type_table, + vector_mtvscr_type_table, + vector_mule_type_table, + vector_mulo_type_table, + vector_nmsub_type_table, + vector_nor_type_table, + vector_or_type_table, + vector_pack_type_table, + vector_packpx_type_table, + vector_packs_type_table, + vector_packsu_type_table, + vector_perm_type_table, + vector_re_type_table, + vector_rl_type_table, + vector_round_type_table, + vector_rsqrte_type_table, + vector_sel_type_table, + vector_sl_type_table, + vector_sld_type_table, + vector_sll_type_table, + vector_slo_type_table, + vector_splat_type_table, + vector_splat_s8_type_table, + vector_splat_s16_type_table, + vector_splat_s32_type_table, + vector_splat_u8_type_table, + vector_splat_u16_type_table, + vector_splat_u32_type_table, + vector_sr_type_table, + vector_sra_type_table, + vector_srl_type_table, + vector_sro_type_table, + vector_st_type_table, + vector_ste_type_table, + vector_stl_type_table, + vector_sub_type_table, + vector_subc_type_table, + vector_subs_type_table, + vector_sum4s_type_table, + vector_sum2s_type_table, + vector_sums_type_table, + vector_trunc_type_table, + vector_unpack2sh_type_table, + vector_unpack2sl_type_table, + vector_unpack2uh_type_table, + vector_unpack2ul_type_table, + vector_unpackh_type_table, + vector_unpackl_type_table, + vector_xor_type_table, + vector_all_eq_type_table, + vector_all_ge_type_table, + vector_all_gt_type_table, + vector_all_in_type_table, + vector_all_le_type_table, + vector_all_lt_type_table, + vector_all_nan_type_table, + vector_all_ne_type_table, + vector_all_nge_type_table, + vector_all_ngt_type_table, + vector_all_nle_type_table, + vector_all_nlt_type_table, + vector_all_numeric_type_table, + vector_any_eq_type_table, + vector_any_ge_type_table, + vector_any_gt_type_table, + vector_any_le_type_table, + vector_any_lt_type_table, + vector_any_nan_type_table, + vector_any_ne_type_table, + vector_any_nge_type_table, + vector_any_ngt_type_table, + vector_any_nle_type_table, + vector_any_nlt_type_table, + vector_any_numeric_type_table, + vector_any_out_type_table, + vector_vaddubm_type_table, + vector_vadduhm_type_table, + vector_vadduwm_type_table, + vector_vaddfp_type_table, + vector_addc_type_table, + vector_vaddubs_type_table, + vector_vaddsbs_type_table, + vector_vadduhs_type_table, + vector_vaddshs_type_table, + vector_vadduws_type_table, + vector_vaddsws_type_table, + vector_and_type_table, + vector_andc_type_table, + vector_vavgub_type_table, + vector_vavgsb_type_table, + vector_vavguh_type_table, + vector_vavgsh_type_table, + vector_vavguw_type_table, + vector_vavgsw_type_table, + vector_ceil_type_table, + vector_cmpb_type_table, + vector_vcmpequb_type_table, + vector_vcmpequh_type_table, + vector_vcmpequw_type_table, + vector_vcmpeqfp_type_table, + vector_cmpge_type_table, + vector_vcmpgtub_type_table, + vector_vcmpgtsb_type_table, + vector_vcmpgtuh_type_table, + vector_vcmpgtsh_type_table, + vector_vcmpgtuw_type_table, + vector_vcmpgtsw_type_table, + vector_vcmpgtfp_type_table, + vector_vcfux_type_table, + vector_vcfsx_type_table, + vector_cts_type_table, + vector_ctu_type_table, + vector_expte_type_table, + vector_floor_type_table, + vector_load_type_table, + vector_lvebx_type_table, + vector_lvehx_type_table, + vector_lvewx_type_table, + vector_loadl_type_table, + vector_loge_type_table, + vector_madd_type_table, + vector_madds_type_table, + vector_vmaxub_type_table, + vector_vmaxsb_type_table, + vector_vmaxuh_type_table, + vector_vmaxsh_type_table, + vector_vmaxuw_type_table, + vector_vmaxsw_type_table, + vector_vmaxfp_type_table, + vector_vmrghb_type_table, + vector_vmrghh_type_table, + vector_vmrghw_type_table, + vector_vmrglb_type_table, + vector_vmrglh_type_table, + vector_vmrglw_type_table, + vector_vminub_type_table, + vector_vminsb_type_table, + vector_vminuh_type_table, + vector_vminsh_type_table, + vector_vminuw_type_table, + vector_vminsw_type_table, + vector_vminfp_type_table, + vector_mladd_type_table, + vector_mradds_type_table, + vector_vmsumubm_type_table, + vector_vmsumuhm_type_table, + vector_vmsummbm_type_table, + vector_vmsumshm_type_table, + vector_vmsumuhs_type_table, + vector_vmsumshs_type_table, + vector_vmuleub_type_table, + vector_vmulesb_type_table, + vector_vmuleuh_type_table, + vector_vmulesh_type_table, + vector_vmuloub_type_table, + vector_vmulosb_type_table, + vector_vmulouh_type_table, + vector_vmulosh_type_table, + vector_nmsub_type_table, + vector_nor_type_table, + vector_or_type_table, + vector_vpkuhum_type_table, + vector_vpkuwum_type_table, + vector_packpx_type_table, + vector_vpkuhus_type_table, + vector_vpkshss_type_table, + vector_vpkuwus_type_table, + vector_vpkswss_type_table, + vector_vpkshus_type_table, + vector_vpkswus_type_table, + vector_perm_type_table, + vector_re_type_table, + vector_vrlb_type_table, + vector_vrlh_type_table, + vector_vrlw_type_table, + vector_round_type_table, + vector_rsqrte_type_table, + vector_sel_type_table, + vector_vslb_type_table, + vector_vslh_type_table, + vector_vslw_type_table, + vector_sld_type_table, + vector_sll_type_table, + vector_slo_type_table, + vector_vspltb_type_table, + vector_vsplth_type_table, + vector_vspltw_type_table, + vector_vspltisb_type_table, + vector_vspltish_type_table, + vector_vspltisw_type_table, + vector_vsrb_type_table, + vector_vsrh_type_table, + vector_vsrw_type_table, + vector_vsrab_type_table, + vector_vsrah_type_table, + vector_vsraw_type_table, + vector_srl_type_table, + vector_sro_type_table, + vector_st_type_table, + vector_stvebx_type_table, + vector_stvehx_type_table, + vector_stvewx_type_table, + vector_stl_type_table, + vector_vsububm_type_table, + vector_vsubuhm_type_table, + vector_vsubuwm_type_table, + vector_vsubfp_type_table, + vector_subc_type_table, + vector_vsububs_type_table, + vector_vsubsbs_type_table, + vector_vsubuhs_type_table, + vector_vsubshs_type_table, + vector_vsubuws_type_table, + vector_vsubsws_type_table, + vector_vsum4ubs_type_table, + vector_vsum4sbs_type_table, + vector_vsum4shs_type_table, + vector_sum2s_type_table, + vector_sums_type_table, + vector_trunc_type_table, + vector_vupkhsb_type_table, + vector_vupklsb_type_table, + vector_vupkhpx_type_table, + vector_vupklpx_type_table, + vector_vupkhsh_type_table, + vector_vupklsh_type_table, + vector_xor_type_table, + vector_abs_type_table, + vector_abss_type_table, + NULL +}; + +int is_intrinsic_function_call(ENode *funccall) { + ENode *funcref = funccall->data.funccall.funcref; + return + ENODE_IS(funcref, EOBJREF) && + funcref->data.objref->datatype == DFUNC && + (TYPE_FUNC(funcref->data.objref->type)->flags & FUNC_INTRINSIC); +} + +static void abs_intrinsic(ENode *expr, short outputReg, Operand *output) { + int reg1; + int reg2; + Operand op; + + memclrw(&op, sizeof(op)); + GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); + + reg1 = ALLOC_GPR(); + emitpcode(PC_SRAWI, reg1, op.reg, 31); + + reg2 = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_XOR, reg2, reg1, op.reg); + emitpcode(PC_SUBF, reg2, reg1, reg2); + + output->optype = OpndType_GPR; + output->reg = reg2; +} + +static void setflm_intrinsic(ENode *expr, short outputReg, Operand *output, int flag) { + int reg; + Operand op; + + memclrw(&op, sizeof(op)); + GEN_NODE_TO_FPR(expr, &op, expr->rtype, 0); + + if (!flag) { + output->optype = OpndType_FPR; + reg = (outputReg && outputReg != op.reg) ? outputReg : ALLOC_FPR(); + emitpcode(PC_MFFS, output->reg = reg); + } + + emitpcode(PC_MTFSF, 255, op.reg); +} + +static void alloca_intrinsic(ENode *expr, short outputReg, Operand *output) { + int reg; + Operand op; + + memclrw(&op, sizeof(op)); + + if (ENODE_IS(expr, EINTCONST)) { + reg = outputReg ? outputReg : ALLOC_GPR(); + allocate_dynamic_stack_space( + 1, reg, ALLOC_GPR(), CInt64_GetULong(&expr->data.intval)); + } else { + GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); + reg = outputReg ? outputReg : ALLOC_GPR(); + + emitpcode(PC_NEG, reg, op.reg); + emitpcode(PC_RLWINM, reg, reg, 0, 0, get_alloca_alignment()); + allocate_dynamic_stack_space(0, reg, ALLOC_GPR(), 0); + } + + output->optype = OpndType_GPR; + output->reg = reg; +} + +static void load_bytereversed_intrinsic(Opcode opcode, ENode *expr1, ENode *expr2, short outputReg, Operand *output) { + int reg; + Operand op1; + Operand op2; + + reg = outputReg ? outputReg : ALLOC_GPR(); + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + + if (ENODE_IS(expr2, EINTCONST) && expr2->data.intval.lo == 0) { + GEN_NODE(expr1, &op1); + if (op1.optype == OpndType_GPR_Indexed) { + emitpcode(opcode, reg, op1.reg, op1.regOffset); + } else { + ENSURE_GPR(&op1, expr1->rtype, 0); + emitpcode(opcode, reg, 0, op1.reg); + } + } else { + GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); + GEN_NODE_TO_GPR(expr2, &op2, expr2->rtype, 0); + emitpcode(opcode, reg, op1.reg, op2.reg); + } + + setpcodeflags(fSideEffects | ((expr1->flags | expr2->flags | output->flags) & (fIsConst | fIsVolatile))); + output->optype = OpndType_GPR; + output->reg = reg; +} + +static void store_bytereversed_intrinsic(Opcode opcode, ENode *expr1, ENode *expr2, ENode *expr3) { + Operand op1; + Operand op2; + Operand op3; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + memclrw(&op3, sizeof(op3)); + + if (ENODE_IS(expr3, EINTCONST) && expr3->data.intval.lo == 0) { + GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); + GEN_NODE(expr2, &op2); + if (op2.optype == OpndType_GPR_Indexed) { + emitpcode(opcode, op1.reg, op2.reg, op2.regOffset); + } else { + ENSURE_GPR(&op2, expr2->rtype, 0); + emitpcode(opcode, op1.reg, 0, op2.reg); + } + } else { + GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); + GEN_NODE_TO_GPR(expr2, &op2, expr2->rtype, 0); + GEN_NODE_TO_GPR(expr3, &op3, expr3->rtype, 0); + emitpcode(opcode, op1.reg, op2.reg, op3.reg); + } + + setpcodeflags(fSideEffects | ((op1.flags | op2.flags | op3.flags) & (fIsConst | fIsVolatile))); +} + +static void data_cache_block_intrinsic(Opcode opcode, ENode *expr1, ENode *expr2) { + Operand op1; + Operand op2; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + + if (ENODE_IS(expr2, EINTCONST) && expr2->data.intval.lo == 0) { + GEN_NODE(expr1, &op1); + if (op1.optype == OpndType_GPR_Indexed) { + emitpcode(opcode, op1.reg, op1.regOffset); + } else { + ENSURE_GPR(&op1, expr1->rtype, 0); + emitpcode(opcode, 0, op1.reg); + } + } else { + GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); + GEN_NODE_TO_GPR(expr2, &op2, expr2->rtype, 0); + emitpcode(opcode, op1.reg, op2.reg); + } +} + +static void memcpy_intrinsic(ENode *destexpr, ENode *srcexpr, SInt32 size, Boolean ignored, Operand *output) { + UInt32 qual; + Operand destOp; + Operand srcOp; + + qual = 0; + + memclrw(&destOp, sizeof(destOp)); + memclrw(&srcOp, sizeof(srcOp)); + + GEN_NODE(srcexpr, &srcOp); + indirect(&srcOp, srcexpr); + + GEN_NODE(destexpr, output); + destOp = *output; + indirect(&destOp, destexpr); + + if (destOp.object) + qual = destOp.object->qual; + + move_block(&destOp, &srcOp, size, destexpr->rtype ? CMach_AllocationAlignment(destexpr->rtype, qual) : 1); +} + +static SInt32 checkconstintarg(ENode *expr, char *name, SInt32 min, SInt32 max, int argnum) { + SInt32 value; + + if (!ENODE_IS(expr, EINTCONST)) + PPCError_ErrorTerm(PPCErrorStr210, name, 3, max, argnum); + + value = CInt64_GetULong(&expr->data.intval); + + if (value < min) { + PPCError_Warning(PPCErrorStr211, name, argnum, value, min, max, min); + return min; + } + + if (value > max) { + PPCError_Warning(PPCErrorStr211, name, argnum, value, min, max, value & max); + value = value & max; + } + + return value; +} + +static void rlwimi_intrinsic(ENode *expr1, ENode *expr2, ENode *expr3, ENode *expr4, ENode *expr5, short outputReg, Operand *output) { + SInt32 arg3; + SInt32 arg4; + SInt32 arg5; + Operand op1; + Operand op2; + int reg; + char *name = "__rlwimi"; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + + arg3 = checkconstintarg(expr3, name, 0, 31, 3); + arg4 = checkconstintarg(expr4, name, 0, 31, 4); + arg5 = checkconstintarg(expr5, name, 0, 31, 5); + + GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); + + GEN_NODE(expr2, &op2); + if (copts.optimizationlevel > 1) { + reg = ALLOC_GPR(); + emitpcode(PC_MR, reg, op1.reg); + op1.reg = reg; + } + ENSURE_GPR(&op2, expr2->rtype, 0); + + emitpcode(PC_RLWIMI, op1.reg, op2.reg, arg3, arg4, arg5); + + output->optype = OpndType_GPR; + output->reg = op1.reg; +} + +static void rlwinm_intrinsic(ENode *expr1, ENode *expr2, ENode *expr3, ENode *expr4, short outputReg, Operand *output) { + char *name = "__rlwinm"; + short reg; + short arg2; + short arg3; + short arg4; + Operand op1; + + memclrw(&op1, sizeof(op1)); + arg2 = checkconstintarg(expr2, name, 0, 31, 2); + arg3 = checkconstintarg(expr3, name, 0, 31, 3); + arg4 = checkconstintarg(expr4, name, 0, 31, 4); + + GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_RLWINM, reg, op1.reg, arg2, arg3, arg4); + + output->optype = OpndType_GPR; + output->reg = reg; +} + +static void rlwnm_intrinsic(ENode *expr1, ENode *expr2, ENode *expr3, ENode *expr4, short outputReg, Operand *output) { + short reg; + short arg3; + short arg4; + char *name = "__rlwnm"; + Operand op1; + Operand op2; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + arg3 = checkconstintarg(expr3, name, 0, 31, 3); + arg4 = checkconstintarg(expr4, name, 0, 31, 4); + + GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); + GEN_NODE_TO_GPR(expr2, &op2, expr2->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_GPR(); + emitpcode(PC_RLWNM, reg, op1.reg, op2.reg, arg3, arg4); + + output->optype = OpndType_GPR; + output->reg = reg; +} + +static Boolean promotable_types_are_equal(Type *a, Type *b) { + if (a == b) + return 1; + + if (a == TYPE(&stsignedint)) { + if ( + b == TYPE(&stunsignedint) || + b == TYPE(&stsignedchar) || + b == TYPE(&stunsignedchar) || + b == TYPE(&stsignedshort) || + b == TYPE(&stunsignedshort) || + b == TYPE(&stsignedlong) || + b == TYPE(&stunsignedlong) || + b == TYPE(&stbool) + ) + return 1; + } + + return 0; +} + +static int Intrinsics_VerifyParameterCount(int wantedCount, ENodeList *args, HashNameNode *name) { + ENodeList *scan; + int count; + + for (scan = args, count = 0; scan; scan = scan->next) + count++; + + if (count != wantedCount) { + PPCError_Error(PPCErrorStr103, name->name, count, wantedCount); + return 0; + } + + return 1; +} + +static ENode *Intrinsics_CreateIntrinsicFunc(Object *func, ENodeList *args, Type *rtype) { + TypeFunc *tfunc; + ENodeList *scan; + ENode *expr; + + tfunc = TYPE_FUNC(func->type); + CError_ASSERT(3741, IS_TYPE_FUNC(tfunc)); + + for (scan = args; scan; scan = scan->next) { + if (IS_TYPE_ARRAY(scan->node->rtype)) + scan->node = CExpr_PointerGeneration(scan->node); + } + + expr = lalloc(sizeof(ENode)); + expr->type = EFUNCCALL; + expr->cost = 4; + expr->rtype = rtype; + expr->ignored = 0; + expr->flags = tfunc->qual & ENODE_FLAG_QUALS; + expr->data.funccall.funcref = create_objectrefnode(func); + expr->data.funccall.args = args; + expr->data.funccall.functype = tfunc; + return CExpr_AdjustFunctionCall(expr); +} + +static Type *Intrinsics_Verify1VectorArg2Ops(Intrinsics id, ENodeList *args, HashNameNode *name) { + ENode *arg1; + TypeTable22 *table; + Type *typeA; + Type *typeB; + Type *rtype; + + arg1 = args->node; + + for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { + typeB = arg1->rtype; + typeA = table->arg1; + if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) { + typeA = TPTR_TARGET(typeA); + typeB = TPTR_TARGET(typeB); + } + if (promotable_types_are_equal(typeA, typeB)) + break; + } + + rtype = table->rtype; + if (!rtype) { + PPCError_Error(PPCErrorStr104, name->name, name->name, arg1->rtype, 0); + rtype = NULL; + } + return rtype; +} + +static Type *Intrinsics_VerifyNoVectorArgs(Intrinsics id, HashNameNode *name) { + TypeTable11 *table = typeTable[id - Intrinsic_042]; + return table->rtype; +} + +static Type *Intrinsics_Verify1VectorArg(Intrinsics id, ENodeList *args, HashNameNode *name) { + ENode *arg1; + TypeTable21 *table; + Type *typeA; + Type *typeB; + Type *rtype; + + arg1 = args->node; + + for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { + typeB = arg1->rtype; + typeA = table->arg1; + if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) { + typeA = TPTR_TARGET(typeA); + typeB = TPTR_TARGET(typeB); + } + if (promotable_types_are_equal(typeA, typeB)) + break; + } + + switch (id) { + case Intrinsic_104: + case Intrinsic_105: + case Intrinsic_106: + case Intrinsic_107: + case Intrinsic_108: + case Intrinsic_109: + case Intrinsic_269: + case Intrinsic_270: + case Intrinsic_271: + if (ENODE_IS(arg1, EINTCONST)) { + SInt32 val = arg1->data.intval.lo; + if (val > 15 || val < -16) { + PPCError_Error(PPCErrorStr108, name->name, name->name, 5); + return NULL; + } + } else { + PPCError_Error(PPCErrorStr108, name->name, name->name, 5); + return NULL; + } + break; + case Intrinsic_058: + if (ENODE_IS(arg1, EINTCONST)) { + SInt32 val = arg1->data.intval.lo; + if (val > 3 || val < 0) { + PPCError_Error(PPCErrorStr108, name->name, name->name, 2); + return NULL; + } + } else { + PPCError_Error(PPCErrorStr108, name->name, name->name, 2); + return NULL; + } + break; + } + + rtype = table->rtype; + if (!rtype) { + PPCError_Error(PPCErrorStr104, name->name, name->name, arg1->rtype, 0); + rtype = NULL; + } + return rtype; +} + +static Type *Intrinsics_Verify2VectorArgs(Intrinsics id, ENodeList *args, HashNameNode *name) { + ENode *arg1; + ENode *arg2; + TypeTable31 *table; + Type *typeB1; + Type *typeB2; + Type *typeA1; + Type *typeA2; + + arg1 = args->node; + arg2 = args->next->node; + table = typeTable[id - Intrinsic_042]; + + switch (id) { + case Intrinsic_055: + case Intrinsic_056: + case Intrinsic_057: + case Intrinsic_103: + case Intrinsic_190: + case Intrinsic_191: + case Intrinsic_192: + case Intrinsic_193: + case Intrinsic_266: + case Intrinsic_267: + case Intrinsic_268: + if (ENODE_IS(arg2, EINTCONST)) { + if (arg2->data.intval.lo > 31 || arg2->data.intval.hi < 0) { + PPCError_Error(PPCErrorStr108, name->name, name->name, 5); + return NULL; + } + } else { + PPCError_Error(PPCErrorStr108, name->name, name->name, 5); + return NULL; + } + break; + } + + for (; table->rtype; table++) { + typeB1 = arg1->rtype; + typeB2 = arg2->rtype; + typeA1 = table->arg1; + typeA2 = table->arg2; + if (IS_TYPE_POINTER(typeA1) && IS_TYPE_POINTER(typeB1)) { + typeA1 = TPTR_TARGET(typeA1); + typeB1 = TPTR_TARGET(typeB1); + } + if (IS_TYPE_POINTER(typeA2) && IS_TYPE_POINTER(typeB2)) { + typeA2 = TPTR_TARGET(typeA2); + typeB2 = TPTR_TARGET(typeB2); + } + if (promotable_types_are_equal(typeA1, typeB1) && + promotable_types_are_equal(typeA2, typeB2)) + break; + } + + if (!table->rtype) { + PPCError_Error(PPCErrorStr105, name->name, name->name, arg1->rtype, 0, arg2->rtype, 0); + return NULL; + } + + switch (id) { + case Intrinsic_066: + case Intrinsic_067: + case Intrinsic_068: + if (arg2->flags & ENODE_FLAG_VOLATILE) + PPCError_Warning(PPCErrorStr178, name->name); + } + + return table->rtype; +} + +static Type *Intrinsics_Verify3VectorArgs(Intrinsics id, ENodeList *args, HashNameNode *name) { + ENode *arg1; + ENode *arg2; + ENode *arg3; + TypeTable41 *table; + Type *typeB1; + Type *typeB2; + Type *typeB3; + Type *typeA1; + Type *typeA2; + Type *typeA3; + + arg1 = args->node; + arg2 = args->next->node; + arg3 = args->next->next->node; + + for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { + typeB1 = arg1->rtype; + typeB2 = arg2->rtype; + typeB3 = arg3->rtype; + typeA1 = table->arg1; + typeA2 = table->arg2; + typeA3 = table->arg3; + if (IS_TYPE_POINTER(typeA1) && IS_TYPE_POINTER(typeB1)) { + typeA1 = TPTR_TARGET(typeA1); + typeB1 = TPTR_TARGET(typeB1); + } + if (IS_TYPE_POINTER(typeA2) && IS_TYPE_POINTER(typeB2)) { + typeA2 = TPTR_TARGET(typeA2); + typeB2 = TPTR_TARGET(typeB2); + } + if (IS_TYPE_POINTER(typeA3) && IS_TYPE_POINTER(typeB3)) { + typeA3 = TPTR_TARGET(typeA3); + typeB3 = TPTR_TARGET(typeB3); + } + if (promotable_types_are_equal(typeA1, typeB1) && + promotable_types_are_equal(typeA2, typeB2) && + promotable_types_are_equal(typeA3, typeB3)) + break; + } + + switch (id) { + case Intrinsic_060: + case Intrinsic_061: + case Intrinsic_062: + case Intrinsic_063: + if (ENODE_IS(arg3, EINTCONST)) { + SInt32 val = arg3->data.intval.lo; + if (val > 3 || val < 0) { + PPCError_Error(PPCErrorStr108, name->name, name->name, 2); + return NULL; + } + } else { + PPCError_Error(PPCErrorStr108, name->name, name->name, 2); + return NULL; + } + break; + case Intrinsic_100: + case Intrinsic_263: + if (ENODE_IS(arg3, EINTCONST)) { + if (arg3->data.intval.lo > 15 || arg3->data.intval.hi < 0) { + PPCError_Error(PPCErrorStr108, name->name, name->name, 4); + return NULL; + } + } else { + PPCError_Error(PPCErrorStr108, name->name, name->name, 4); + return NULL; + } + break; + } + + if (!table->rtype) { + PPCError_Error(PPCErrorStr106, name->name, name->name, arg1->rtype, 0, arg2->rtype, 0, arg3->rtype, 0); + return NULL; + } + + switch (id) { + case Intrinsic_114: + case Intrinsic_115: + case Intrinsic_116: + if (arg3->flags & ENODE_FLAG_VOLATILE) + PPCError_Warning(PPCErrorStr178, name->name); + } + + return table->rtype; +} + +static Opcode Intrinsics_FindOpcodeNoArgs(Intrinsics id, ENode *funccall) { + TypeTable11 *table = typeTable[id - Intrinsic_042]; + return table->opcode; +} + +static Opcode Intrinsics_FindOpcode1Arg(Intrinsics id, ENode *funccall, ENode *arg1) { + TypeTable21 *table; + Type *typeA; + Type *typeB; + + for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { + typeB = arg1->rtype; + typeA = table->arg1; + if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) { + typeA = TPTR_TARGET(typeA); + typeB = TPTR_TARGET(typeB); + } + if (promotable_types_are_equal(typeA, typeB)) + break; + } + + CError_ASSERT(4105, table->rtype); + return table->opcode; +} + +static Opcode Intrinsics_FindOpcode2Args(Intrinsics id, ENode *funccall, ENode *arg1, ENode *arg2) { + TypeTable31 *table; + Type *typeB1; + Type *typeB2; + Type *typeA1; + Type *typeA2; + + for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { + typeB1 = arg1->rtype; + typeB2 = arg2->rtype; + typeA1 = table->arg1; + typeA2 = table->arg2; + if (IS_TYPE_POINTER(typeA1) && IS_TYPE_POINTER(typeB1)) { + typeA1 = TPTR_TARGET(typeA1); + typeB1 = TPTR_TARGET(typeB1); + } + if (IS_TYPE_POINTER(typeA2) && IS_TYPE_POINTER(typeB2)) { + typeA2 = TPTR_TARGET(typeA2); + typeB2 = TPTR_TARGET(typeB2); + } + if (promotable_types_are_equal(typeA1, typeB1) && + promotable_types_are_equal(typeA2, typeB2)) + break; + } + + CError_ASSERT(4144, table->rtype); + return table->opcode; +} + +static Opcode Intrinsics_FindOpcode3Args(Intrinsics id, ENode *funccall, ENode *arg1, ENode *arg2, ENode *arg3) { + TypeTable41 *table; + Type *typeB1; + Type *typeB2; + Type *typeB3; + Type *typeA1; + Type *typeA2; + Type *typeA3; + + for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { + typeB1 = arg1->rtype; + typeB2 = arg2->rtype; + typeB3 = arg3->rtype; + typeA1 = table->arg1; + typeA2 = table->arg2; + typeA3 = table->arg3; + if (IS_TYPE_POINTER(typeA1) && IS_TYPE_POINTER(typeB1)) { + typeA1 = TPTR_TARGET(typeA1); + typeB1 = TPTR_TARGET(typeB1); + } + if (IS_TYPE_POINTER(typeA2) && IS_TYPE_POINTER(typeB2)) { + typeA2 = TPTR_TARGET(typeA2); + typeB2 = TPTR_TARGET(typeB2); + } + if (IS_TYPE_POINTER(typeA3) && IS_TYPE_POINTER(typeB3)) { + typeA3 = TPTR_TARGET(typeA3); + typeB3 = TPTR_TARGET(typeB3); + } + if (promotable_types_are_equal(typeA1, typeB1) && + promotable_types_are_equal(typeA2, typeB2) && + promotable_types_are_equal(typeA3, typeB3)) + break; + } + + CError_ASSERT(4191, table->rtype); + return table->opcode; +} + +static void vector_intrinsic_no_args(Opcode opcode) { + emitpcode(opcode); +} + +static void vector_intrinsic_mfvscr(short outputReg, Opcode opcode, Operand *output) { + short reg; + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_1arg(ENode *arg1, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + short reg; + + memclrw(&op1, sizeof(op1)); + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.reg); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_splats(ENode *arg1, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + short reg; + + memclrw(&op1, sizeof(op1)); + CError_ASSERT(4253, ENODE_IS(arg1, EINTCONST)); + GEN_NODE(arg1, &op1); + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.immediate); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_splatu8(ENode *arg1, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + short reg; + + memclrw(&op1, sizeof(op1)); + CError_ASSERT(4277, ENODE_IS(arg1, EINTCONST)); + GEN_NODE(arg1, &op1); + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.immediate); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_splatu16(ENode *arg1, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + short reg; + + memclrw(&op1, sizeof(op1)); + CError_ASSERT(4301, ENODE_IS(arg1, EINTCONST)); + GEN_NODE(arg1, &op1); + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.immediate); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_splatu32(ENode *arg1, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + short reg; + + memclrw(&op1, sizeof(op1)); + CError_ASSERT(4325, ENODE_IS(arg1, EINTCONST)); + GEN_NODE(arg1, &op1); + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.immediate); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_dss(ENode *arg1) { + Operand op1; + + memclrw(&op1, sizeof(op1)); + CError_ASSERT(4348, ENODE_IS(arg1, EINTCONST)); + GEN_NODE(arg1, &op1); + + emitpcode(PC_DSS, op1.immediate, 0); +} + +static void vector_intrinsic_2args(ENode *arg1, ENode *arg2, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + Operand op2; + short reg; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + GEN_NODE_TO_VR(arg2, &op2, arg2->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.reg, op2.reg); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_2args1const(ENode *arg1, ENode *arg2, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + Operand op2; + short reg; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + CError_ASSERT(4393, ENODE_IS(arg2, EINTCONST)); + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + GEN_NODE(arg2, &op2); + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.reg, op2.immediate); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_3args(ENode *arg1, ENode *arg2, ENode *arg3, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + Operand op2; + Operand op3; + short reg; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + memclrw(&op3, sizeof(op3)); + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + GEN_NODE_TO_VR(arg2, &op2, arg2->rtype, 0); + GEN_NODE_TO_VR(arg3, &op3, arg3->rtype, 0); + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.reg, op2.reg, op3.reg); + + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_datastream(ENode *arg1, ENode *arg2, ENode *arg3, Opcode opcode) { + Operand op1; + Operand op2; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + CError_ASSERT(4445, ENODE_IS(arg3, EINTCONST)); + GEN_NODE_TO_GPR(arg1, &op1, arg1->rtype, 0); + GEN_NODE_TO_GPR(arg2, &op2, arg2->rtype, 0); + + switch (opcode) { + case PC_DST: + case PC_DSTST: + emitpcode(opcode, op1.reg, op2.reg, arg3->data.intval.lo, 0); + break; + case PC_DSTT: + case PC_DSTSTT: + emitpcode(opcode, op1.reg, op2.reg, arg3->data.intval.lo); + break; + default: + CError_FATAL(4463); + } +} + +static void vector_intrinsic_sld(ENode *arg1, ENode *arg2, ENode *arg3, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + Operand op2; + short reg; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + CError_ASSERT(4479, ENODE_IS(arg3, EINTCONST)); + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + GEN_NODE_TO_VR(arg2, &op2, arg2->rtype, 0); + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.reg, op2.reg, arg3->data.intval.lo); + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_load(ENode *arg1, ENode *arg2, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + Operand op2; + short reg; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + + GEN_NODE(arg1, &op1); + if (op1.optype == OpndType_Absolute && op1.immediate == 0) { + op1.optype = OpndType_GPR; + op1.reg = 0; + } else { + ENSURE_GPR(&op1, arg1->rtype, 0); + } + + GEN_NODE(arg2, &op2); + if (op2.optype == OpndType_Absolute && op2.immediate == 0 && op1.reg != 0) { + op2 = op1; + op1.optype = OpndType_GPR; + op1.reg = 0; + } else { + ENSURE_GPR(&op2, arg2->rtype, 0); + } + + reg = outputReg ? outputReg : ALLOC_VR(); + + emitpcode(opcode, reg, op1.reg, op2.reg); + output->optype = OpndType_VR; + output->reg = reg; +} + +static void vector_intrinsic_store(ENode *arg1, ENode *arg2, ENode *arg3, short outputReg, Operand *output, Opcode opcode) { + Operand op1; + Operand op2; + Operand op3; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + memclrw(&op3, sizeof(op3)); + + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + + GEN_NODE(arg2, &op2); + if (op2.optype == OpndType_Absolute && op2.immediate == 0) { + op2.optype = OpndType_GPR; + op2.reg = 0; + } else { + ENSURE_GPR(&op2, arg2->rtype, 0); + } + + GEN_NODE(arg3, &op3); + if (op3.optype == OpndType_Absolute && op3.immediate == 0 && op2.reg != 0) { + op3 = op2; + op2.optype = OpndType_GPR; + op2.reg = 0; + } else { + ENSURE_GPR(&op3, arg3->rtype, 0); + } + + emitpcode(opcode, op1.reg, op2.reg, op3.reg); + output->optype = OpndType_VR; + output->reg = op1.reg; +} + +static void vector_intrinsic_abs(Intrinsics id, ENode *funccall, ENode *arg1, short outputReg, Operand *output) { + TypeTable22 *table; + Type *typeA; + Type *typeB; + short reg1; + short reg2; + short reg3; + Operand op1; + + for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { + typeB = arg1->rtype; + typeA = table->arg1; + if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) { + typeA = TPTR_TARGET(typeA); + typeB = TPTR_TARGET(typeB); + } + if (promotable_types_are_equal(typeA, typeB)) + break; + } + + CError_ASSERT(4617, table->rtype); + + reg1 = ALLOC_VR(); + reg2 = ALLOC_VR(); + reg3 = outputReg ? outputReg : ALLOC_VR(); + + memclrw(&op1, sizeof(op1)); + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + + if (arg1->rtype == TYPE(&stvectorfloat)) { + emitpcode(PC_VSPLTISW, reg1, -1); + emitpcode(PC_VSLW, reg2, reg1, reg1); + emitpcode(table->opcode1, reg3, op1.reg, reg2); + } else { + emitpcode(PC_VSPLTISB, reg1, 0); + emitpcode(table->opcode1, reg2, reg1, op1.reg); + emitpcode(table->opcode2, reg3, op1.reg, reg2); + } + + output->optype = OpndType_VR; + output->reg = reg3; +} + +static void vector_intrinsic_abss(Intrinsics id, ENode *funccall, ENode *arg1, short outputReg, Operand *output) { + TypeTable22 *table; + Type *typeA; + Type *typeB; + short reg1; + short reg2; + short reg3; + Operand op1; + + for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { + typeB = arg1->rtype; + typeA = table->arg1; + if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) { + typeA = TPTR_TARGET(typeA); + typeB = TPTR_TARGET(typeB); + } + if (promotable_types_are_equal(typeA, typeB)) + break; + } + + CError_ASSERT(4683, table->rtype); + + reg1 = ALLOC_VR(); + reg2 = ALLOC_VR(); + reg3 = outputReg ? outputReg : ALLOC_VR(); + + memclrw(&op1, sizeof(op1)); + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + + emitpcode(PC_VSPLTISB, reg1, 0); + emitpcode(table->opcode1, reg2, reg1, op1.reg); + emitpcode(table->opcode2, reg3, op1.reg, reg2); + + output->optype = OpndType_VR; + output->reg = reg3; +} + +static void vector_intrinsic_mtvscr(ENode *arg1, Operand *output, Opcode opcode) { + Operand op1; + + memclrw(&op1, sizeof(op1)); + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + emitpcode(opcode, op1.reg); +} + +static void vector_predicate_2args(ENode *arg1, ENode *arg2, short outputReg, Operand *output, Opcode opcode, Intrinsics id) { + Operand op1; + Operand op2; + short reg1; + short reg2; + short reg3; + Opcode cond; + + memclrw(&op1, sizeof(op1)); + memclrw(&op2, sizeof(op2)); + + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + GEN_NODE_TO_VR(arg2, &op2, arg2->rtype, 0); + + reg1 = ALLOC_VR(); + reg2 = op1.reg; + reg3 = op2.reg; + if ( + ((id == Intrinsic_132 || id == Intrinsic_145) && arg1->rtype != TYPE(&stvectorfloat)) || + ((id == Intrinsic_135 || id == Intrinsic_147) && arg1->rtype == TYPE(&stvectorfloat)) || + id == Intrinsic_136 || + id == Intrinsic_148 || + id == Intrinsic_153 || + id == Intrinsic_141 || + id == Intrinsic_142 || + id == Intrinsic_154 + ) + { + reg3 = op1.reg; + reg2 = op2.reg; + } + emitpcode(opcode, reg1, reg2, reg3); + pcsetrecordbit(pclastblock->lastPCode); + + if (arg1->rtype == TYPE(&stvectorfloat)) { + switch (id) { + case Intrinsic_131: + case Intrinsic_132: + case Intrinsic_133: + case Intrinsic_135: + case Intrinsic_136: + cond = ELESS; + break; + case Intrinsic_150: + case Intrinsic_151: + case Intrinsic_152: + case Intrinsic_153: + case Intrinsic_154: + cond = EGREATEREQU; + break; + case Intrinsic_134: + case Intrinsic_138: + case Intrinsic_139: + case Intrinsic_140: + case Intrinsic_141: + case Intrinsic_142: + cond = EEQU; + break; + case Intrinsic_144: + case Intrinsic_145: + case Intrinsic_146: + case Intrinsic_147: + case Intrinsic_148: + case Intrinsic_156: + cond = ENOTEQU; + break; + default: + CError_FATAL(4805); + } + } else { + switch (id) { + case Intrinsic_131: + case Intrinsic_133: + case Intrinsic_136: + cond = ELESS; + break; + case Intrinsic_144: + case Intrinsic_146: + case Intrinsic_148: + cond = ENOTEQU; + break; + case Intrinsic_132: + case Intrinsic_135: + case Intrinsic_138: + cond = EEQU; + break; + case Intrinsic_145: + case Intrinsic_147: + case Intrinsic_150: + cond = EGREATEREQU; + break; + default: + CError_FATAL(4834); + } + } + + output->optype = OpndType_CRField; + output->reg = 6; + output->regOffset = cond; +} + +static void vector_predicate_1arg(ENode *arg1, short outputReg, Operand *output, Opcode opcode, Intrinsics id) { + Operand op1; + short reg; + Opcode cond; + + memclrw(&op1, sizeof(op1)); + + GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); + + reg = ALLOC_VR(); + emitpcode(opcode, reg, op1.reg, op1.reg); + pcsetrecordbit(pclastblock->lastPCode); + + switch (id) { + case Intrinsic_143: + cond = ELESS; + break; + case Intrinsic_149: + cond = EGREATEREQU; + break; + case Intrinsic_137: + cond = EEQU; + break; + case Intrinsic_155: + cond = ENOTEQU; + break; + default: + CError_FATAL(4878); + } + + output->optype = OpndType_CRField; + output->reg = 6; + output->regOffset = cond; +} + +ENode *Intrinsics_HandleIntrinsicCall(Object *func, ENodeList *args) { + ENode *callexpr; + Type *rtype; + Intrinsics id; + + callexpr = NULL; + + if (copts.altivec_model) { + id = func->u.func.u.intrinsicid; + switch (id) { + case Intrinsic_060: + case Intrinsic_061: + case Intrinsic_062: + case Intrinsic_063: + case Intrinsic_072: + case Intrinsic_073: + case Intrinsic_079: + case Intrinsic_080: + case Intrinsic_081: + case Intrinsic_082: + case Intrinsic_086: + case Intrinsic_093: + case Intrinsic_098: + case Intrinsic_100: + case Intrinsic_114: + case Intrinsic_115: + case Intrinsic_116: + case Intrinsic_202: + case Intrinsic_203: + case Intrinsic_224: + case Intrinsic_225: + case Intrinsic_226: + case Intrinsic_227: + case Intrinsic_228: + case Intrinsic_229: + case Intrinsic_230: + case Intrinsic_231: + case Intrinsic_240: + case Intrinsic_252: + case Intrinsic_259: + case Intrinsic_263: + case Intrinsic_280: + case Intrinsic_281: + case Intrinsic_282: + case Intrinsic_283: + case Intrinsic_284: + if (Intrinsics_VerifyParameterCount(3, args, func->name)) { + if ((rtype = Intrinsics_Verify3VectorArgs(id, args, func->name))) + callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype); + } + break; + case Intrinsic_042: + case Intrinsic_043: + case Intrinsic_044: + case Intrinsic_045: + case Intrinsic_046: + case Intrinsic_047: + case Intrinsic_049: + case Intrinsic_050: + case Intrinsic_051: + case Intrinsic_052: + case Intrinsic_053: + case Intrinsic_054: + case Intrinsic_055: + case Intrinsic_056: + case Intrinsic_057: + case Intrinsic_066: + case Intrinsic_067: + case Intrinsic_068: + case Intrinsic_070: + case Intrinsic_071: + case Intrinsic_074: + case Intrinsic_075: + case Intrinsic_076: + case Intrinsic_078: + case Intrinsic_084: + case Intrinsic_085: + case Intrinsic_087: + case Intrinsic_088: + case Intrinsic_089: + case Intrinsic_090: + case Intrinsic_091: + case Intrinsic_092: + case Intrinsic_095: + case Intrinsic_099: + case Intrinsic_101: + case Intrinsic_102: + case Intrinsic_103: + case Intrinsic_110: + case Intrinsic_111: + case Intrinsic_112: + case Intrinsic_113: + case Intrinsic_117: + case Intrinsic_118: + case Intrinsic_119: + case Intrinsic_120: + case Intrinsic_121: + case Intrinsic_122: + case Intrinsic_124: + case Intrinsic_125: + case Intrinsic_126: + case Intrinsic_127: + case Intrinsic_130: + case Intrinsic_131: + case Intrinsic_132: + case Intrinsic_133: + case Intrinsic_134: + case Intrinsic_135: + case Intrinsic_136: + case Intrinsic_138: + case Intrinsic_139: + case Intrinsic_140: + case Intrinsic_141: + case Intrinsic_142: + case Intrinsic_144: + case Intrinsic_145: + case Intrinsic_146: + case Intrinsic_147: + case Intrinsic_148: + case Intrinsic_150: + case Intrinsic_151: + case Intrinsic_152: + case Intrinsic_153: + case Intrinsic_154: + case Intrinsic_156: + case Intrinsic_157: + case Intrinsic_158: + case Intrinsic_159: + case Intrinsic_160: + case Intrinsic_161: + case Intrinsic_162: + case Intrinsic_163: + case Intrinsic_164: + case Intrinsic_165: + case Intrinsic_166: + case Intrinsic_167: + case Intrinsic_168: + case Intrinsic_169: + case Intrinsic_170: + case Intrinsic_171: + case Intrinsic_172: + case Intrinsic_173: + case Intrinsic_174: + case Intrinsic_175: + case Intrinsic_177: + case Intrinsic_178: + case Intrinsic_179: + case Intrinsic_180: + case Intrinsic_181: + case Intrinsic_182: + case Intrinsic_183: + case Intrinsic_184: + case Intrinsic_185: + case Intrinsic_186: + case Intrinsic_187: + case Intrinsic_188: + case Intrinsic_189: + case Intrinsic_190: + case Intrinsic_191: + case Intrinsic_192: + case Intrinsic_193: + case Intrinsic_196: + case Intrinsic_197: + case Intrinsic_198: + case Intrinsic_199: + case Intrinsic_200: + case Intrinsic_204: + case Intrinsic_205: + case Intrinsic_206: + case Intrinsic_207: + case Intrinsic_208: + case Intrinsic_209: + case Intrinsic_210: + case Intrinsic_211: + case Intrinsic_212: + case Intrinsic_213: + case Intrinsic_214: + case Intrinsic_215: + case Intrinsic_216: + case Intrinsic_217: + case Intrinsic_218: + case Intrinsic_219: + case Intrinsic_220: + case Intrinsic_221: + case Intrinsic_222: + case Intrinsic_223: + case Intrinsic_232: + case Intrinsic_233: + case Intrinsic_234: + case Intrinsic_235: + case Intrinsic_236: + case Intrinsic_237: + case Intrinsic_238: + case Intrinsic_239: + case Intrinsic_241: + case Intrinsic_242: + case Intrinsic_243: + case Intrinsic_244: + case Intrinsic_245: + case Intrinsic_246: + case Intrinsic_247: + case Intrinsic_248: + case Intrinsic_249: + case Intrinsic_250: + case Intrinsic_251: + case Intrinsic_254: + case Intrinsic_255: + case Intrinsic_256: + case Intrinsic_260: + case Intrinsic_261: + case Intrinsic_262: + case Intrinsic_264: + case Intrinsic_265: + case Intrinsic_266: + case Intrinsic_267: + case Intrinsic_268: + case Intrinsic_272: + case Intrinsic_273: + case Intrinsic_274: + case Intrinsic_275: + case Intrinsic_276: + case Intrinsic_277: + case Intrinsic_278: + case Intrinsic_279: + case Intrinsic_285: + case Intrinsic_286: + case Intrinsic_287: + case Intrinsic_288: + case Intrinsic_289: + case Intrinsic_290: + case Intrinsic_291: + case Intrinsic_292: + case Intrinsic_293: + case Intrinsic_294: + case Intrinsic_295: + case Intrinsic_296: + case Intrinsic_297: + case Intrinsic_298: + case Intrinsic_299: + case Intrinsic_300: + case Intrinsic_308: + if (Intrinsics_VerifyParameterCount(2, args, func->name)) { + if ((rtype = Intrinsics_Verify2VectorArgs(id, args, func->name))) + callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype); + } + break; + case Intrinsic_048: + case Intrinsic_058: + case Intrinsic_064: + case Intrinsic_065: + case Intrinsic_069: + case Intrinsic_083: + case Intrinsic_094: + case Intrinsic_096: + case Intrinsic_097: + case Intrinsic_104: + case Intrinsic_105: + case Intrinsic_106: + case Intrinsic_107: + case Intrinsic_108: + case Intrinsic_109: + case Intrinsic_123: + case Intrinsic_128: + case Intrinsic_129: + case Intrinsic_137: + case Intrinsic_143: + case Intrinsic_149: + case Intrinsic_155: + case Intrinsic_176: + case Intrinsic_194: + case Intrinsic_195: + case Intrinsic_201: + case Intrinsic_253: + case Intrinsic_257: + case Intrinsic_258: + case Intrinsic_269: + case Intrinsic_270: + case Intrinsic_271: + case Intrinsic_301: + case Intrinsic_302: + case Intrinsic_303: + case Intrinsic_304: + case Intrinsic_305: + case Intrinsic_306: + case Intrinsic_307: + if (Intrinsics_VerifyParameterCount(1, args, func->name)) { + if ((rtype = Intrinsics_Verify1VectorArg(id, args, func->name))) + callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype); + } + break; + case Intrinsic_059: + case Intrinsic_077: + if (Intrinsics_VerifyParameterCount(0, args, func->name)) { + if ((rtype = Intrinsics_VerifyNoVectorArgs(id, func->name))) + callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype); + } + break; + case Intrinsic_309: + case Intrinsic_310: + if (Intrinsics_VerifyParameterCount(1, args, func->name)) { + if ((rtype = Intrinsics_Verify1VectorArg2Ops(id, args, func->name))) + callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype); + } + break; + } + } + + return callexpr; +} + +void call_intrinsic_function(ENode *funccall, short outputReg, Operand *output) { + ENodeList *args; + Object *object; + Intrinsics id; + Opcode op; + short reg; + + static Opcode opcode[MaxIntrinsics] = { + /* Intrinsic_000 */ PC_EIEIO, + /* Intrinsic_001 */ PC_SYNC, + /* Intrinsic_002 */ PC_ISYNC, + 0, + 0, + /* Intrinsic_005 */ PC_FABS, + /* Intrinsic_006 */ PC_FNABS, + 0, + 0, + /* Intrinsic_009 */ PC_CNTLZW, + /* Intrinsic_010 */ PC_LHBRX, + /* Intrinsic_011 */ PC_LWBRX, + /* Intrinsic_012 */ PC_STHBRX, + /* Intrinsic_013 */ PC_STWBRX, + /* Intrinsic_014 */ PC_DCBF, + /* Intrinsic_015 */ PC_DCBT, + /* Intrinsic_016 */ PC_DCBST, + /* Intrinsic_017 */ PC_DCBTST, + /* Intrinsic_018 */ PC_DCBZ, + /* Intrinsic_019 */ PC_MULHW, + /* Intrinsic_020 */ PC_MULHWU, + /* Intrinsic_021 */ PC_DIVW, + /* Intrinsic_022 */ PC_DIVWU, + /* Intrinsic_023 */ PC_FMADD, + /* Intrinsic_024 */ PC_FMSUB, + /* Intrinsic_025 */ PC_FNMADD, + /* Intrinsic_026 */ PC_FNMSUB, + /* Intrinsic_027 */ PC_FMADDS, + /* Intrinsic_028 */ PC_FMSUBS, + /* Intrinsic_029 */ PC_FNMADDS, + /* Intrinsic_030 */ PC_FNMSUBS, + /* Intrinsic_031 */ PC_MFFS, + /* Intrinsic_032 */ PC_FRES, + /* Intrinsic_033 */ PC_FRSQRTE, + /* Intrinsic_004 */ PC_FSEL, + 0, + 0, + /* Intrinsic_037 */ PC_RLWIMI, + /* Intrinsic_038 */ PC_RLWINM, + /* Intrinsic_039 */ PC_RLWNM, + /* Intrinsic_040 */ PC_FABS, + /* Intrinsic_041 */ PC_FNABS + }; + + args = funccall->data.funccall.args; + object = funccall->data.funccall.funcref->data.objref; + id = object->u.func.u.intrinsicid; + cur_intrinsic_object = object; + + switch (id) { + case Intrinsic_000: + case Intrinsic_001: + case Intrinsic_002: + appendpcode(pclastblock, makepcode(opcode[id])); + output->optype = OpndType_Absolute; + break; + case Intrinsic_003: + case Intrinsic_004: + abs_intrinsic(args->node, outputReg, output); + break; + case Intrinsic_005: + case Intrinsic_006: + case Intrinsic_032: + case Intrinsic_033: + case Intrinsic_040: + case Intrinsic_041: + fp_unary_operator(opcode[id], args->node, outputReg, output); + break; + case Intrinsic_007: + setflm_intrinsic(args->node, outputReg, output, funccall->ignored); + break; + case Intrinsic_008: + alloca_intrinsic(args->node, outputReg, output); + break; + case Intrinsic_009: + unary_operator(PC_CNTLZW, args->node, outputReg, output); + break; + case Intrinsic_010: + case Intrinsic_011: + load_bytereversed_intrinsic(opcode[id], args->node, args->next->node, outputReg, output); + break; + case Intrinsic_012: + case Intrinsic_013: + store_bytereversed_intrinsic(opcode[id], args->node, args->next->node, args->next->next->node); + output->optype = OpndType_Absolute; + break; + case Intrinsic_014: + case Intrinsic_015: + case Intrinsic_016: + case Intrinsic_017: + case Intrinsic_018: + data_cache_block_intrinsic(opcode[id], args->node, args->next->node); + output->optype = OpndType_Absolute; + break; + case Intrinsic_019: + case Intrinsic_020: + case Intrinsic_021: + case Intrinsic_022: + binary_operator(opcode[id], args->node, args->next->node, outputReg, output); + break; + case Intrinsic_023: + case Intrinsic_024: + case Intrinsic_025: + case Intrinsic_026: + case Intrinsic_027: + case Intrinsic_028: + case Intrinsic_029: + case Intrinsic_030: + case Intrinsic_034: + fp_multiply_add(opcode[id], + args->node, args->next->node, args->next->next->node, + outputReg, output); + break; + case Intrinsic_031: + reg = outputReg ? outputReg : ALLOC_FPR(); + emitpcode(PC_MFFS, output->reg = reg); + output->optype = OpndType_FPR; + break; + case Intrinsic_035: + call_function(funccall, output); + break; + case Intrinsic_036: + if (ENODE_IS(args->next->next->node, EINTCONST)) + memcpy_intrinsic( + args->node, args->next->node, args->next->next->node->data.intval.lo, + funccall->ignored, output); + else + call_function(funccall, output); + break; + case Intrinsic_037: + rlwimi_intrinsic( + args->node, + args->next->node, + args->next->next->node, + args->next->next->next->node, + args->next->next->next->next->node, + outputReg, output); + break; + case Intrinsic_038: + rlwinm_intrinsic( + args->node, + args->next->node, + args->next->next->node, + args->next->next->next->node, + outputReg, output); + break; + case Intrinsic_039: + rlwnm_intrinsic( + args->node, + args->next->node, + args->next->next->node, + args->next->next->next->node, + outputReg, output); + break; + case Intrinsic_072: + case Intrinsic_073: + case Intrinsic_079: + case Intrinsic_080: + case Intrinsic_081: + case Intrinsic_082: + case Intrinsic_086: + case Intrinsic_093: + case Intrinsic_098: + case Intrinsic_202: + case Intrinsic_203: + case Intrinsic_224: + case Intrinsic_225: + case Intrinsic_226: + case Intrinsic_227: + case Intrinsic_228: + case Intrinsic_229: + case Intrinsic_230: + case Intrinsic_231: + case Intrinsic_240: + case Intrinsic_252: + case Intrinsic_259: + op = Intrinsics_FindOpcode3Args(id, funccall, args->node, args->next->node, args->next->next->node); + vector_intrinsic_3args(args->node, args->next->node, args->next->next->node, outputReg, output, op); + break; + case Intrinsic_100: + case Intrinsic_263: + op = Intrinsics_FindOpcode3Args(id, funccall, args->node, args->next->node, args->next->next->node); + vector_intrinsic_sld(args->node, args->next->node, args->next->next->node, outputReg, output, op); + break; + case Intrinsic_042: + case Intrinsic_043: + case Intrinsic_044: + case Intrinsic_045: + case Intrinsic_046: + case Intrinsic_047: + case Intrinsic_049: + case Intrinsic_050: + case Intrinsic_051: + case Intrinsic_053: + case Intrinsic_074: + case Intrinsic_075: + case Intrinsic_076: + case Intrinsic_078: + case Intrinsic_084: + case Intrinsic_085: + case Intrinsic_087: + case Intrinsic_088: + case Intrinsic_089: + case Intrinsic_090: + case Intrinsic_091: + case Intrinsic_092: + case Intrinsic_095: + case Intrinsic_099: + case Intrinsic_101: + case Intrinsic_102: + case Intrinsic_110: + case Intrinsic_111: + case Intrinsic_112: + case Intrinsic_113: + case Intrinsic_117: + case Intrinsic_118: + case Intrinsic_119: + case Intrinsic_120: + case Intrinsic_121: + case Intrinsic_122: + case Intrinsic_124: + case Intrinsic_125: + case Intrinsic_126: + case Intrinsic_127: + case Intrinsic_130: + case Intrinsic_157: + case Intrinsic_158: + case Intrinsic_159: + case Intrinsic_160: + case Intrinsic_161: + case Intrinsic_162: + case Intrinsic_163: + case Intrinsic_164: + case Intrinsic_165: + case Intrinsic_166: + case Intrinsic_167: + case Intrinsic_168: + case Intrinsic_169: + case Intrinsic_170: + case Intrinsic_171: + case Intrinsic_172: + case Intrinsic_173: + case Intrinsic_174: + case Intrinsic_175: + case Intrinsic_177: + case Intrinsic_178: + case Intrinsic_179: + case Intrinsic_180: + case Intrinsic_181: + case Intrinsic_182: + case Intrinsic_183: + case Intrinsic_184: + case Intrinsic_185: + case Intrinsic_186: + case Intrinsic_187: + case Intrinsic_188: + case Intrinsic_189: + case Intrinsic_204: + case Intrinsic_205: + case Intrinsic_206: + case Intrinsic_207: + case Intrinsic_208: + case Intrinsic_209: + case Intrinsic_210: + case Intrinsic_211: + case Intrinsic_212: + case Intrinsic_213: + case Intrinsic_214: + case Intrinsic_215: + case Intrinsic_216: + case Intrinsic_217: + case Intrinsic_218: + case Intrinsic_219: + case Intrinsic_220: + case Intrinsic_221: + case Intrinsic_222: + case Intrinsic_223: + case Intrinsic_232: + case Intrinsic_233: + case Intrinsic_234: + case Intrinsic_235: + case Intrinsic_236: + case Intrinsic_237: + case Intrinsic_238: + case Intrinsic_239: + case Intrinsic_241: + case Intrinsic_242: + case Intrinsic_243: + case Intrinsic_244: + case Intrinsic_245: + case Intrinsic_246: + case Intrinsic_247: + case Intrinsic_248: + case Intrinsic_249: + case Intrinsic_250: + case Intrinsic_251: + case Intrinsic_254: + case Intrinsic_255: + case Intrinsic_256: + case Intrinsic_260: + case Intrinsic_261: + case Intrinsic_262: + case Intrinsic_264: + case Intrinsic_265: + case Intrinsic_272: + case Intrinsic_273: + case Intrinsic_274: + case Intrinsic_275: + case Intrinsic_276: + case Intrinsic_277: + case Intrinsic_278: + case Intrinsic_279: + case Intrinsic_285: + case Intrinsic_286: + case Intrinsic_287: + case Intrinsic_288: + case Intrinsic_289: + case Intrinsic_290: + case Intrinsic_291: + case Intrinsic_292: + case Intrinsic_293: + case Intrinsic_294: + case Intrinsic_295: + case Intrinsic_296: + case Intrinsic_297: + case Intrinsic_298: + case Intrinsic_299: + case Intrinsic_300: + case Intrinsic_308: + op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node); + vector_intrinsic_2args(args->node, args->next->node, outputReg, output, op); + break; + case Intrinsic_048: + case Intrinsic_064: + case Intrinsic_065: + case Intrinsic_069: + case Intrinsic_094: + case Intrinsic_096: + case Intrinsic_097: + case Intrinsic_123: + case Intrinsic_128: + case Intrinsic_129: + case Intrinsic_176: + case Intrinsic_194: + case Intrinsic_195: + case Intrinsic_201: + case Intrinsic_253: + case Intrinsic_257: + case Intrinsic_258: + case Intrinsic_301: + case Intrinsic_302: + case Intrinsic_303: + case Intrinsic_304: + case Intrinsic_305: + case Intrinsic_306: + case Intrinsic_307: + op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); + vector_intrinsic_1arg(args->node, outputReg, output, op); + break; + case Intrinsic_055: + case Intrinsic_056: + case Intrinsic_057: + case Intrinsic_103: + case Intrinsic_190: + case Intrinsic_191: + case Intrinsic_192: + case Intrinsic_193: + case Intrinsic_266: + case Intrinsic_267: + case Intrinsic_268: + op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node); + vector_intrinsic_2args1const(args->node, args->next->node, outputReg, output, op); + break; + case Intrinsic_104: + case Intrinsic_105: + case Intrinsic_106: + case Intrinsic_269: + case Intrinsic_270: + case Intrinsic_271: + op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); + vector_intrinsic_splats(args->node, outputReg, output, op); + break; + case Intrinsic_107: + op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); + vector_intrinsic_splatu8(args->node, outputReg, output, op); + break; + case Intrinsic_108: + op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); + vector_intrinsic_splatu16(args->node, outputReg, output, op); + break; + case Intrinsic_109: + op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); + vector_intrinsic_splatu32(args->node, outputReg, output, op); + break; + case Intrinsic_083: + vector_intrinsic_mtvscr(args->node, output, PC_MTVSCR); + break; + case Intrinsic_077: + op = Intrinsics_FindOpcodeNoArgs(id, funccall); + vector_intrinsic_mfvscr(outputReg, op, output); + break; + case Intrinsic_058: + vector_intrinsic_dss(args->node); + break; + case Intrinsic_059: + op = Intrinsics_FindOpcodeNoArgs(id, funccall); + vector_intrinsic_no_args(op); + break; + case Intrinsic_060: + case Intrinsic_061: + case Intrinsic_062: + case Intrinsic_063: + switch (id) { + case Intrinsic_060: + op = PC_DST; + break; + case Intrinsic_061: + op = PC_DSTST; + break; + case Intrinsic_062: + op = PC_DSTSTT; + break; + case Intrinsic_063: + op = PC_DSTT; + break; + } + vector_intrinsic_datastream(args->node, args->next->node, args->next->next->node, op); + break; + case Intrinsic_066: + case Intrinsic_067: + case Intrinsic_068: + case Intrinsic_070: + case Intrinsic_071: + case Intrinsic_196: + case Intrinsic_197: + case Intrinsic_198: + case Intrinsic_199: + case Intrinsic_200: + op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node); + vector_intrinsic_load(args->node, args->next->node, outputReg, output, op); + break; + case Intrinsic_114: + case Intrinsic_115: + case Intrinsic_116: + case Intrinsic_280: + case Intrinsic_281: + case Intrinsic_282: + case Intrinsic_283: + case Intrinsic_284: + op = Intrinsics_FindOpcode3Args(id, funccall, args->node, args->next->node, args->next->next->node); + vector_intrinsic_store(args->node, args->next->node, args->next->next->node, outputReg, output, op); + break; + case Intrinsic_131: + case Intrinsic_132: + case Intrinsic_133: + case Intrinsic_134: + case Intrinsic_135: + case Intrinsic_136: + case Intrinsic_138: + case Intrinsic_139: + case Intrinsic_140: + case Intrinsic_141: + case Intrinsic_142: + case Intrinsic_144: + case Intrinsic_145: + case Intrinsic_146: + case Intrinsic_147: + case Intrinsic_148: + case Intrinsic_150: + case Intrinsic_151: + case Intrinsic_152: + case Intrinsic_153: + case Intrinsic_154: + case Intrinsic_156: + op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node); + vector_predicate_2args(args->node, args->next->node, outputReg, output, op, id); + break; + case Intrinsic_137: + case Intrinsic_143: + case Intrinsic_149: + case Intrinsic_155: + op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); + vector_predicate_1arg(args->node, outputReg, output, op, id); + break; + case Intrinsic_309: + vector_intrinsic_abs(id, funccall, args->node, outputReg, output); + break; + case Intrinsic_310: + vector_intrinsic_abss(id, funccall, args->node, outputReg, output); + break; + case Intrinsic_052: + case Intrinsic_054: + op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node); + vector_intrinsic_2args(args->node, args->next->node, outputReg, output, op); + break; + default: + CError_FATAL(6152); + } +} + +void Intrinsics_SetupRuntimeObjects(void) { + static TypePointer char_ptr = {TYPEPOINTER, 4, TYPE(&stchar), 0}; + Boolean savecpp; + int i; + + savecpp = copts.cplusplus; + copts.cplusplus = 0; + + for (i = 0; i < MaxIntrinsics; i++) + intrinsics[i] = NULL; + + intrinsics[Intrinsic_000] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__eieio"), 0, 0); + intrinsics[Intrinsic_001] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__sync"), 0, 0); + intrinsics[Intrinsic_002] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__isync"), 0, 0); + intrinsics[Intrinsic_003] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__abs"), 0, 1, &stsignedint); + intrinsics[Intrinsic_004] = CParser_NewRTFunc(TYPE(&stsignedlong), GetHashNameNodeExport("__labs"), 0, 1, &stsignedlong); + intrinsics[Intrinsic_005] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fabs"), 0, 1, &stdouble); + intrinsics[Intrinsic_006] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fnabs"), 0, 1, &stdouble); + intrinsics[Intrinsic_007] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__setflm"), 0, 1, &stdouble); + intrinsics[Intrinsic_033] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__frsqrte"), 0, 1, &stdouble); + intrinsics[Intrinsic_008] = CParser_NewRTFunc(TYPE(&void_ptr), GetHashNameNodeExport("__alloca"), 0, 1, &stunsignedint); + intrinsics[Intrinsic_009] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__cntlzw"), 0, 1, &stunsignedint); + intrinsics[Intrinsic_010] = CParser_NewRTFunc(TYPE(&stunsignedint), GetHashNameNodeExport("__lhbrx"), 0, 2, &void_ptr, &stsignedint); + intrinsics[Intrinsic_011] = CParser_NewRTFunc(TYPE(&stunsignedint), GetHashNameNodeExport("__lwbrx"), 0, 2, &void_ptr, &stsignedint); + intrinsics[Intrinsic_012] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__sthbrx"), 0, 3, &stunsignedshort, &void_ptr, &stsignedint); + intrinsics[Intrinsic_013] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__stwbrx"), 0, 3, &stunsignedint, &void_ptr, &stsignedint); + intrinsics[Intrinsic_014] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbf"), 0, 2, &void_ptr, &stsignedint); + intrinsics[Intrinsic_015] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbt"), 0, 2, &void_ptr, &stsignedint); + intrinsics[Intrinsic_016] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbst"), 0, 2, &void_ptr, &stsignedint); + intrinsics[Intrinsic_017] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbtst"), 0, 2, &void_ptr, &stsignedint); + intrinsics[Intrinsic_018] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbz"), 0, 2, &void_ptr, &stsignedint); + intrinsics[Intrinsic_019] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__mulhw"), 0, 2, &stsignedint, &stsignedint); + intrinsics[Intrinsic_020] = CParser_NewRTFunc(TYPE(&stunsignedint), GetHashNameNodeExport("__mulhwu"), 0, 2, &stunsignedint, &stunsignedint); + intrinsics[Intrinsic_021] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__divw"), 0, 2, &stsignedint, &stsignedint); + intrinsics[Intrinsic_022] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__divwu"), 0, 2, &stsignedint, &stsignedint); + intrinsics[Intrinsic_023] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fmadd"), 0, 3, &stdouble, &stdouble, &stdouble); + intrinsics[Intrinsic_024] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fmsub"), 0, 3, &stdouble, &stdouble, &stdouble); + intrinsics[Intrinsic_025] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fnmadd"), 0, 3, &stdouble, &stdouble, &stdouble); + intrinsics[Intrinsic_026] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fnmsub"), 0, 3, &stdouble, &stdouble, &stdouble); + intrinsics[Intrinsic_034] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fsel"), 0, 3, &stdouble, &stdouble, &stdouble); + intrinsics[Intrinsic_027] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fmadds"), 0, 3, &stfloat, &stfloat, &stfloat); + intrinsics[Intrinsic_028] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fmsubs"), 0, 3, &stfloat, &stfloat, &stfloat); + intrinsics[Intrinsic_029] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fnmadds"), 0, 3, &stfloat, &stfloat, &stfloat); + intrinsics[Intrinsic_030] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fnmsubs"), 0, 3, &stfloat, &stfloat, &stfloat); + intrinsics[Intrinsic_031] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__mffs"), 0, 0); + intrinsics[Intrinsic_032] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fres"), 0, 1, &stfloat); + intrinsics[Intrinsic_040] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fabsf"), 0, 1, &stfloat); + intrinsics[Intrinsic_041] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fnabsf"), 0, 1, &stfloat); + intrinsics[Intrinsic_035] = CParser_NewRTFunc(TYPE(&char_ptr), GetHashNameNodeExport("__strcpy"), 0, 2, &char_ptr, &char_ptr); + TYPE_FUNC(intrinsics[Intrinsic_035]->type)->args->next->qual |= Q_CONST; + intrinsics[Intrinsic_036] = CParser_NewRTFunc(TYPE(&void_ptr), GetHashNameNodeExport("__memcpy"), 0, 3, &void_ptr, &void_ptr, &stunsignedlong); + __memcpy_object = intrinsics[Intrinsic_036]; + TYPE_FUNC(intrinsics[Intrinsic_036]->type)->args->next->qual |= Q_CONST; + intrinsics[Intrinsic_037] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__rlwimi"), 0, 5, &stsignedint, &stsignedint, &stsignedint, &stsignedint, &stsignedint); + intrinsics[Intrinsic_038] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__rlwinm"), 0, 4, &stsignedint, &stsignedint, &stsignedint, &stsignedint); + intrinsics[Intrinsic_039] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__rlwnm"), 0, 4, &stsignedint, &stsignedint, &stsignedint, &stsignedint); + intrinsics[Intrinsic_042] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_add"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_043] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_addc"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_044] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_adds"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_045] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_and"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_046] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_andc"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_047] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_avg"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_048] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ceil"), 0, 1, &stvector); + intrinsics[Intrinsic_049] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmpb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_050] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmpeq"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_051] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmpge"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_052] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmple"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_053] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmpgt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_054] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmplt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_055] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ctf"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_056] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cts"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_057] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ctu"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_058] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dss"), 0, 1, &stsignedint); + intrinsics[Intrinsic_059] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dssall"), 0, 0); + intrinsics[Intrinsic_060] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dst"), 0, 3, &stvector, &stsignedint, &stsignedint); + intrinsics[Intrinsic_061] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dstst"), 0, 3, &stvector, &stsignedint, &stsignedint); + intrinsics[Intrinsic_062] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dststt"), 0, 3, &stvector, &stsignedint, &stsignedint); + intrinsics[Intrinsic_063] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dstt"), 0, 3, &stvector, &stsignedint, &stsignedint); + intrinsics[Intrinsic_064] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_expte"), 0, 1, &stvector); + intrinsics[Intrinsic_065] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_floor"), 0, 1, &stvector); + intrinsics[Intrinsic_066] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ld"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_067] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lde"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_068] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ldl"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_069] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_loge"), 0, 1, &stvector); + intrinsics[Intrinsic_070] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvsl"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_071] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvsr"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_072] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_madd"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_073] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_madds"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_074] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_max"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_075] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mergeh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_076] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mergel"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_077] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mfvscr"), 0, 0); + intrinsics[Intrinsic_078] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_min"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_079] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mladd"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_080] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mradds"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_081] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_msum"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_082] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_msums"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_083] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mtvscr"), 0, 1, &stvector); + intrinsics[Intrinsic_084] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mule"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_085] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mulo"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_086] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_nmsub"), 0, 2, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_087] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_nor"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_088] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_or"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_089] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_pack"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_090] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_packpx"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_091] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_packs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_092] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_packsu"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_093] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_perm"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_094] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_re"), 0, 1, &stvector); + intrinsics[Intrinsic_095] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_rl"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_096] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_round"), 0, 1, &stvector); + intrinsics[Intrinsic_097] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_rsqrte"), 0, 1, &stvector); + intrinsics[Intrinsic_098] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sel"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_099] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sl"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_100] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sld"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_101] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sll"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_102] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_slo"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_103] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_104] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_s8"), 0, 1, &stvector); + intrinsics[Intrinsic_105] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_s16"), 0, 1, &stvector); + intrinsics[Intrinsic_106] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_s32"), 0, 1, &stvector); + intrinsics[Intrinsic_107] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_u8"), 0, 1, &stvector); + intrinsics[Intrinsic_108] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_u16"), 0, 1, &stvector); + intrinsics[Intrinsic_109] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_u32"), 0, 1, &stvector); + intrinsics[Intrinsic_110] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sr"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_111] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sra"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_112] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_srl"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_113] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sro"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_114] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_st"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_115] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ste"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_116] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stl"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_117] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sub"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_118] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_subc"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_119] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_subs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_120] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sum4s"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_121] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sum2s"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_122] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sums"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_123] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_trunc"), 0, 1, &stvector); + intrinsics[Intrinsic_124] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpack2sh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_125] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpack2sl"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_126] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpack2uh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_127] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpack2ul"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_128] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpackh"), 0, 1, &stvector); + intrinsics[Intrinsic_129] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpackl"), 0, 1, &stvector); + intrinsics[Intrinsic_130] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_xor"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_131] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_eq"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_132] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_ge"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_133] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_gt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_134] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_in"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_135] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_le"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_136] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_lt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_137] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_nan"), 0, 1, &stvector); + intrinsics[Intrinsic_138] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_ne"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_139] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_nge"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_140] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_ngt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_141] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_nle"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_142] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_nlt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_143] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_numeric"), 0, 1, &stvector); + intrinsics[Intrinsic_144] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_eq"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_145] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_ge"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_146] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_gt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_147] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_le"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_148] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_lt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_149] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_nan"), 0, 1, &stvector); + intrinsics[Intrinsic_150] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_ne"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_151] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_nge"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_152] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_ngt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_153] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_nle"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_154] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_nlt"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_155] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_numeric"), 0, 1, &stvector); + intrinsics[Intrinsic_156] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_out"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_157] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddubm"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_158] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vadduhm"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_159] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vadduwm"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_160] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddfp"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_161] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddcuw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_162] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddubs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_163] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddsbs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_164] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vadduhs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_165] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddshs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_166] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vadduws"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_167] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddsws"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_168] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vand"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_169] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vandc"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_170] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavgub"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_171] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavgsb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_172] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavguh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_173] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavgsh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_174] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavguw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_175] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavgsw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_176] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrfip"), 0, 1, &stvector); + intrinsics[Intrinsic_177] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpbfp"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_178] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpequb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_179] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpequh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_180] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpequw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_181] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpeqfp"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_182] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgefp"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_183] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtub"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_184] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtsb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_185] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtuh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_186] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtsh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_187] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtuw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_188] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtsw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_189] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtfp"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_190] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcfux"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_191] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcfsx"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_192] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vctsxs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_193] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vctuxs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_194] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vexptefp"), 0, 1, &stvector); + intrinsics[Intrinsic_195] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrfim"), 0, 1, &stvector); + intrinsics[Intrinsic_196] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvx"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_197] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvebx"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_198] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvehx"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_199] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvewx"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_200] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvxl"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_201] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vlogefp"), 0, 1, &stvector); + intrinsics[Intrinsic_202] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaddfp"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_203] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmhaddshs"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_204] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxub"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_205] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxsb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_206] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxuh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_207] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxsh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_208] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxuw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_209] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxsw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_210] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxfp"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_211] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrghb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_212] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrghh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_213] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrghw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_214] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrglb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_215] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrglh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_216] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrglw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_217] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminub"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_218] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminsb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_219] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminuh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_220] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminsh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_221] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminuw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_222] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminsw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_223] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminfp"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_224] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmladduhm"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_225] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmhraddshs"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_226] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumubm"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_227] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumuhm"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_228] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsummbm"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_229] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumshm"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_230] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumuhs"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_231] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumshs"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_232] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmuleub"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_233] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulesb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_234] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmuleuh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_235] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulesh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_236] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmuloub"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_237] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulosb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_238] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulouh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_239] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulosh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_240] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vnmsubfp"), 0, 2, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_241] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vnor"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_242] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vor"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_243] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkuhum"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_244] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkuwum"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_245] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkpx"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_246] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkuhus"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_247] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkshss"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_248] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkuwus"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_249] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkswss"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_250] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkshus"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_251] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkswus"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_252] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vperm"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_253] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrefp"), 0, 1, &stvector); + intrinsics[Intrinsic_254] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrlb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_255] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrlh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_256] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrlw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_257] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrfin"), 0, 1, &stvector); + intrinsics[Intrinsic_258] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrsqrtefp"), 0, 1, &stvector); + intrinsics[Intrinsic_259] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsel"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_260] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vslb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_261] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vslh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_262] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vslw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_263] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsldoi"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_264] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsl"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_265] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vslo"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_266] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_267] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsplth"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_268] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_269] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltisb"), 0, 1, &stvector); + intrinsics[Intrinsic_270] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltish"), 0, 1, &stvector); + intrinsics[Intrinsic_271] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltisw"), 0, 1, &stvector); + intrinsics[Intrinsic_272] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrb"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_273] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrh"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_274] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_275] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrab"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_276] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrah"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_277] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsraw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_278] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsr"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_279] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsro"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_280] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvx"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_281] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvebx"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_282] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvehx"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_283] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvewx"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_284] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvxl"), 0, 3, &stvector, &stvector, &stvector); + intrinsics[Intrinsic_285] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsububm"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_286] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubuhm"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_287] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubuwm"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_288] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubfp"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_289] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubcuw"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_290] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsububs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_291] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubsbs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_292] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubuhs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_293] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubshs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_294] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubuws"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_295] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubsws"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_296] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsum4ubs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_297] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsum4sbs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_298] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsum4shs"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_299] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsum2sws"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_300] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsumsws"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_301] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrfiz"), 0, 1, &stvector); + intrinsics[Intrinsic_302] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupkhsb"), 0, 1, &stvector); + intrinsics[Intrinsic_303] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupklsb"), 0, 1, &stvector); + intrinsics[Intrinsic_304] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupkhpx"), 0, 1, &stvector); + intrinsics[Intrinsic_305] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupklpx"), 0, 1, &stvector); + intrinsics[Intrinsic_306] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupkhsh"), 0, 1, &stvector); + intrinsics[Intrinsic_307] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupklsh"), 0, 1, &stvector); + intrinsics[Intrinsic_308] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vxor"), 0, 2, &stvector, &stvector); + intrinsics[Intrinsic_309] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_abs"), 0, 1, &stvector); + intrinsics[Intrinsic_310] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_abss"), 0, 1, &stvector); + + for (i = 0; i < MaxIntrinsics; i++) { + CError_ASSERT(6600, intrinsics[i]); + intrinsics[i]->u.func.u.intrinsicid = i; + TYPE_FUNC(intrinsics[i]->type)->flags |= FUNC_INTRINSIC; + CScope_AddGlobalObject(intrinsics[i]); + } + + copts.cplusplus = savecpp; +} + +static Object *CheckRuntimeObject(char *name) { + NameSpaceName *nsname = CScope_FindNameSpaceName(cscope_root, GetHashNameNodeExport(name)); + + if (!nsname) + return NULL; + + if (nsname->first.object && nsname->first.next == NULL) + return OBJECT(nsname->first.object); + + return NULL; +} + +Boolean Intrinsics_ReInitRuntimeObjects(Boolean flag) { + if (flag) { + if (!(intrinsics[Intrinsic_000] = CheckRuntimeObject("__eieio"))) return 0; + if (!(intrinsics[Intrinsic_001] = CheckRuntimeObject("__sync"))) return 0; + if (!(intrinsics[Intrinsic_002] = CheckRuntimeObject("__isync"))) return 0; + if (!(intrinsics[Intrinsic_003] = CheckRuntimeObject("__abs"))) return 0; + if (!(intrinsics[Intrinsic_004] = CheckRuntimeObject("__labs"))) return 0; + if (!(intrinsics[Intrinsic_005] = CheckRuntimeObject("__fabs"))) return 0; + if (!(intrinsics[Intrinsic_006] = CheckRuntimeObject("__fnabs"))) return 0; + if (!(intrinsics[Intrinsic_007] = CheckRuntimeObject("__setflm"))) return 0; + if (!(intrinsics[Intrinsic_033] = CheckRuntimeObject("__frsqrte"))) return 0; + if (!(intrinsics[Intrinsic_008] = CheckRuntimeObject("__alloca"))) return 0; + if (!(intrinsics[Intrinsic_009] = CheckRuntimeObject("__cntlzw"))) return 0; + if (!(intrinsics[Intrinsic_010] = CheckRuntimeObject("__lhbrx"))) return 0; + if (!(intrinsics[Intrinsic_011] = CheckRuntimeObject("__lwbrx"))) return 0; + if (!(intrinsics[Intrinsic_012] = CheckRuntimeObject("__sthbrx"))) return 0; + if (!(intrinsics[Intrinsic_013] = CheckRuntimeObject("__stwbrx"))) return 0; + if (!(intrinsics[Intrinsic_014] = CheckRuntimeObject("__dcbf"))) return 0; + if (!(intrinsics[Intrinsic_015] = CheckRuntimeObject("__dcbt"))) return 0; + if (!(intrinsics[Intrinsic_016] = CheckRuntimeObject("__dcbst"))) return 0; + if (!(intrinsics[Intrinsic_017] = CheckRuntimeObject("__dcbtst"))) return 0; + if (!(intrinsics[Intrinsic_018] = CheckRuntimeObject("__dcbz"))) return 0; + if (!(intrinsics[Intrinsic_019] = CheckRuntimeObject("__mulhw"))) return 0; + if (!(intrinsics[Intrinsic_020] = CheckRuntimeObject("__mulhwu"))) return 0; + if (!(intrinsics[Intrinsic_021] = CheckRuntimeObject("__divw"))) return 0; + if (!(intrinsics[Intrinsic_022] = CheckRuntimeObject("__divwu"))) return 0; + if (!(intrinsics[Intrinsic_023] = CheckRuntimeObject("__fmadd"))) return 0; + if (!(intrinsics[Intrinsic_024] = CheckRuntimeObject("__fmsub"))) return 0; + if (!(intrinsics[Intrinsic_025] = CheckRuntimeObject("__fnmadd"))) return 0; + if (!(intrinsics[Intrinsic_026] = CheckRuntimeObject("__fnmsub"))) return 0; + if (!(intrinsics[Intrinsic_034] = CheckRuntimeObject("__fsel"))) return 0; + if (!(intrinsics[Intrinsic_027] = CheckRuntimeObject("__fmadds"))) return 0; + if (!(intrinsics[Intrinsic_028] = CheckRuntimeObject("__fmsubs"))) return 0; + if (!(intrinsics[Intrinsic_029] = CheckRuntimeObject("__fnmadds"))) return 0; + if (!(intrinsics[Intrinsic_030] = CheckRuntimeObject("__fnmsubs"))) return 0; + if (!(intrinsics[Intrinsic_031] = CheckRuntimeObject("__mffs"))) return 0; + if (!(intrinsics[Intrinsic_032] = CheckRuntimeObject("__fres"))) return 0; + if (!(intrinsics[Intrinsic_040] = CheckRuntimeObject("__fabsf"))) return 0; + if (!(intrinsics[Intrinsic_041] = CheckRuntimeObject("__fnabsf"))) return 0; + if (!(intrinsics[Intrinsic_035] = CheckRuntimeObject("__strcpy"))) return 0; + if (!(intrinsics[Intrinsic_037] = CheckRuntimeObject("__rlwimi"))) return 0; + if (!(intrinsics[Intrinsic_038] = CheckRuntimeObject("__rlwinm"))) return 0; + if (!(intrinsics[Intrinsic_039] = CheckRuntimeObject("__rlwnm"))) return 0; + if (!(intrinsics[Intrinsic_042] = CheckRuntimeObject("vec_add"))) return 0; + if (!(intrinsics[Intrinsic_043] = CheckRuntimeObject("vec_addc"))) return 0; + if (!(intrinsics[Intrinsic_044] = CheckRuntimeObject("vec_adds"))) return 0; + if (!(intrinsics[Intrinsic_045] = CheckRuntimeObject("vec_and"))) return 0; + if (!(intrinsics[Intrinsic_046] = CheckRuntimeObject("vec_andc"))) return 0; + if (!(intrinsics[Intrinsic_047] = CheckRuntimeObject("vec_avg"))) return 0; + if (!(intrinsics[Intrinsic_048] = CheckRuntimeObject("vec_ceil"))) return 0; + if (!(intrinsics[Intrinsic_049] = CheckRuntimeObject("vec_cmpb"))) return 0; + if (!(intrinsics[Intrinsic_050] = CheckRuntimeObject("vec_cmpeq"))) return 0; + if (!(intrinsics[Intrinsic_051] = CheckRuntimeObject("vec_cmpge"))) return 0; + if (!(intrinsics[Intrinsic_052] = CheckRuntimeObject("vec_cmple"))) return 0; + if (!(intrinsics[Intrinsic_053] = CheckRuntimeObject("vec_cmpgt"))) return 0; + if (!(intrinsics[Intrinsic_054] = CheckRuntimeObject("vec_cmplt"))) return 0; + if (!(intrinsics[Intrinsic_055] = CheckRuntimeObject("vec_ctf"))) return 0; + if (!(intrinsics[Intrinsic_056] = CheckRuntimeObject("vec_cts"))) return 0; + if (!(intrinsics[Intrinsic_057] = CheckRuntimeObject("vec_ctu"))) return 0; + if (!(intrinsics[Intrinsic_064] = CheckRuntimeObject("vec_expte"))) return 0; + if (!(intrinsics[Intrinsic_065] = CheckRuntimeObject("vec_floor"))) return 0; + if (!(intrinsics[Intrinsic_066] = CheckRuntimeObject("vec_ld"))) return 0; + if (!(intrinsics[Intrinsic_067] = CheckRuntimeObject("vec_lde"))) return 0; + if (!(intrinsics[Intrinsic_068] = CheckRuntimeObject("vec_ldl"))) return 0; + if (!(intrinsics[Intrinsic_069] = CheckRuntimeObject("vec_loge"))) return 0; + if (!(intrinsics[Intrinsic_070] = CheckRuntimeObject("vec_lvsl"))) return 0; + if (!(intrinsics[Intrinsic_071] = CheckRuntimeObject("vec_lvsr"))) return 0; + if (!(intrinsics[Intrinsic_072] = CheckRuntimeObject("vec_madd"))) return 0; + if (!(intrinsics[Intrinsic_073] = CheckRuntimeObject("vec_madds"))) return 0; + if (!(intrinsics[Intrinsic_074] = CheckRuntimeObject("vec_max"))) return 0; + if (!(intrinsics[Intrinsic_075] = CheckRuntimeObject("vec_mergeh"))) return 0; + if (!(intrinsics[Intrinsic_076] = CheckRuntimeObject("vec_mergel"))) return 0; + if (!(intrinsics[Intrinsic_077] = CheckRuntimeObject("vec_mfvscr"))) return 0; + if (!(intrinsics[Intrinsic_078] = CheckRuntimeObject("vec_min"))) return 0; + if (!(intrinsics[Intrinsic_079] = CheckRuntimeObject("vec_mladd"))) return 0; + if (!(intrinsics[Intrinsic_080] = CheckRuntimeObject("vec_mradds"))) return 0; + if (!(intrinsics[Intrinsic_081] = CheckRuntimeObject("vec_msum"))) return 0; + if (!(intrinsics[Intrinsic_082] = CheckRuntimeObject("vec_msums"))) return 0; + if (!(intrinsics[Intrinsic_083] = CheckRuntimeObject("vec_mtvscr"))) return 0; + if (!(intrinsics[Intrinsic_084] = CheckRuntimeObject("vec_mule"))) return 0; + if (!(intrinsics[Intrinsic_085] = CheckRuntimeObject("vec_mulo"))) return 0; + if (!(intrinsics[Intrinsic_086] = CheckRuntimeObject("vec_nmsub"))) return 0; + if (!(intrinsics[Intrinsic_087] = CheckRuntimeObject("vec_nor"))) return 0; + if (!(intrinsics[Intrinsic_088] = CheckRuntimeObject("vec_or"))) return 0; + if (!(intrinsics[Intrinsic_089] = CheckRuntimeObject("vec_pack"))) return 0; + if (!(intrinsics[Intrinsic_090] = CheckRuntimeObject("vec_packpx"))) return 0; + if (!(intrinsics[Intrinsic_091] = CheckRuntimeObject("vec_packs"))) return 0; + if (!(intrinsics[Intrinsic_092] = CheckRuntimeObject("vec_packsu"))) return 0; + if (!(intrinsics[Intrinsic_093] = CheckRuntimeObject("vec_perm"))) return 0; + if (!(intrinsics[Intrinsic_094] = CheckRuntimeObject("vec_re"))) return 0; + if (!(intrinsics[Intrinsic_095] = CheckRuntimeObject("vec_rl"))) return 0; + if (!(intrinsics[Intrinsic_096] = CheckRuntimeObject("vec_round"))) return 0; + if (!(intrinsics[Intrinsic_097] = CheckRuntimeObject("vec_rsqrte"))) return 0; + if (!(intrinsics[Intrinsic_098] = CheckRuntimeObject("vec_sel"))) return 0; + if (!(intrinsics[Intrinsic_099] = CheckRuntimeObject("vec_sl"))) return 0; + if (!(intrinsics[Intrinsic_100] = CheckRuntimeObject("vec_sld"))) return 0; + if (!(intrinsics[Intrinsic_101] = CheckRuntimeObject("vec_sll"))) return 0; + if (!(intrinsics[Intrinsic_102] = CheckRuntimeObject("vec_slo"))) return 0; + if (!(intrinsics[Intrinsic_103] = CheckRuntimeObject("vec_splat"))) return 0; + if (!(intrinsics[Intrinsic_104] = CheckRuntimeObject("vec_splat_s8"))) return 0; + if (!(intrinsics[Intrinsic_105] = CheckRuntimeObject("vec_splat_s16"))) return 0; + if (!(intrinsics[Intrinsic_106] = CheckRuntimeObject("vec_splat_s32"))) return 0; + if (!(intrinsics[Intrinsic_107] = CheckRuntimeObject("vec_splat_u8"))) return 0; + if (!(intrinsics[Intrinsic_108] = CheckRuntimeObject("vec_splat_u16"))) return 0; + if (!(intrinsics[Intrinsic_109] = CheckRuntimeObject("vec_splat_u32"))) return 0; + if (!(intrinsics[Intrinsic_110] = CheckRuntimeObject("vec_sr"))) return 0; + if (!(intrinsics[Intrinsic_111] = CheckRuntimeObject("vec_sra"))) return 0; + if (!(intrinsics[Intrinsic_112] = CheckRuntimeObject("vec_srl"))) return 0; + if (!(intrinsics[Intrinsic_113] = CheckRuntimeObject("vec_sro"))) return 0; + if (!(intrinsics[Intrinsic_114] = CheckRuntimeObject("vec_st"))) return 0; + if (!(intrinsics[Intrinsic_115] = CheckRuntimeObject("vec_ste"))) return 0; + if (!(intrinsics[Intrinsic_116] = CheckRuntimeObject("vec_stl"))) return 0; + if (!(intrinsics[Intrinsic_117] = CheckRuntimeObject("vec_sub"))) return 0; + if (!(intrinsics[Intrinsic_118] = CheckRuntimeObject("vec_subc"))) return 0; + if (!(intrinsics[Intrinsic_119] = CheckRuntimeObject("vec_subs"))) return 0; + if (!(intrinsics[Intrinsic_120] = CheckRuntimeObject("vec_sum4s"))) return 0; + if (!(intrinsics[Intrinsic_121] = CheckRuntimeObject("vec_sum2s"))) return 0; + if (!(intrinsics[Intrinsic_122] = CheckRuntimeObject("vec_sums"))) return 0; + if (!(intrinsics[Intrinsic_123] = CheckRuntimeObject("vec_trunc"))) return 0; + if (!(intrinsics[Intrinsic_124] = CheckRuntimeObject("vec_unpack2sh"))) return 0; + if (!(intrinsics[Intrinsic_125] = CheckRuntimeObject("vec_unpack2sl"))) return 0; + if (!(intrinsics[Intrinsic_126] = CheckRuntimeObject("vec_unpack2uh"))) return 0; + if (!(intrinsics[Intrinsic_127] = CheckRuntimeObject("vec_unpack2ul"))) return 0; + if (!(intrinsics[Intrinsic_128] = CheckRuntimeObject("vec_unpackh"))) return 0; + if (!(intrinsics[Intrinsic_129] = CheckRuntimeObject("vec_unpackl"))) return 0; + if (!(intrinsics[Intrinsic_130] = CheckRuntimeObject("vec_xor"))) return 0; + if (!(intrinsics[Intrinsic_131] = CheckRuntimeObject("vec_all_eq"))) return 0; + if (!(intrinsics[Intrinsic_132] = CheckRuntimeObject("vec_all_ge"))) return 0; + if (!(intrinsics[Intrinsic_133] = CheckRuntimeObject("vec_all_gt"))) return 0; + if (!(intrinsics[Intrinsic_134] = CheckRuntimeObject("vec_all_in"))) return 0; + if (!(intrinsics[Intrinsic_135] = CheckRuntimeObject("vec_all_le"))) return 0; + if (!(intrinsics[Intrinsic_136] = CheckRuntimeObject("vec_all_lt"))) return 0; + if (!(intrinsics[Intrinsic_137] = CheckRuntimeObject("vec_all_nan"))) return 0; + if (!(intrinsics[Intrinsic_138] = CheckRuntimeObject("vec_all_ne"))) return 0; + if (!(intrinsics[Intrinsic_139] = CheckRuntimeObject("vec_all_nge"))) return 0; + if (!(intrinsics[Intrinsic_140] = CheckRuntimeObject("vec_all_ngt"))) return 0; + if (!(intrinsics[Intrinsic_141] = CheckRuntimeObject("vec_all_nle"))) return 0; + if (!(intrinsics[Intrinsic_142] = CheckRuntimeObject("vec_all_nlt"))) return 0; + if (!(intrinsics[Intrinsic_143] = CheckRuntimeObject("vec_all_numeric"))) return 0; + if (!(intrinsics[Intrinsic_144] = CheckRuntimeObject("vec_any_eq"))) return 0; + if (!(intrinsics[Intrinsic_145] = CheckRuntimeObject("vec_any_ge"))) return 0; + if (!(intrinsics[Intrinsic_146] = CheckRuntimeObject("vec_any_gt"))) return 0; + if (!(intrinsics[Intrinsic_147] = CheckRuntimeObject("vec_any_le"))) return 0; + if (!(intrinsics[Intrinsic_148] = CheckRuntimeObject("vec_any_lt"))) return 0; + if (!(intrinsics[Intrinsic_149] = CheckRuntimeObject("vec_any_nan"))) return 0; + if (!(intrinsics[Intrinsic_150] = CheckRuntimeObject("vec_any_ne"))) return 0; + if (!(intrinsics[Intrinsic_151] = CheckRuntimeObject("vec_any_nge"))) return 0; + if (!(intrinsics[Intrinsic_152] = CheckRuntimeObject("vec_any_ngt"))) return 0; + if (!(intrinsics[Intrinsic_153] = CheckRuntimeObject("vec_any_nle"))) return 0; + if (!(intrinsics[Intrinsic_154] = CheckRuntimeObject("vec_any_nlt"))) return 0; + if (!(intrinsics[Intrinsic_155] = CheckRuntimeObject("vec_any_numeric"))) return 0; + if (!(intrinsics[Intrinsic_156] = CheckRuntimeObject("vec_any_out"))) return 0; + if (!(intrinsics[Intrinsic_157] = CheckRuntimeObject("vec_vaddubm"))) return 0; + if (!(intrinsics[Intrinsic_158] = CheckRuntimeObject("vec_vadduhm"))) return 0; + if (!(intrinsics[Intrinsic_159] = CheckRuntimeObject("vec_vadduwm"))) return 0; + if (!(intrinsics[Intrinsic_160] = CheckRuntimeObject("vec_vaddfp"))) return 0; + if (!(intrinsics[Intrinsic_161] = CheckRuntimeObject("vec_vaddcuw"))) return 0; + if (!(intrinsics[Intrinsic_162] = CheckRuntimeObject("vec_vaddubs"))) return 0; + if (!(intrinsics[Intrinsic_163] = CheckRuntimeObject("vec_vaddubs"))) return 0; + if (!(intrinsics[Intrinsic_164] = CheckRuntimeObject("vec_vadduhs"))) return 0; + if (!(intrinsics[Intrinsic_165] = CheckRuntimeObject("vec_vadduhs"))) return 0; + if (!(intrinsics[Intrinsic_166] = CheckRuntimeObject("vec_vadduws"))) return 0; + if (!(intrinsics[Intrinsic_167] = CheckRuntimeObject("vec_vadduws"))) return 0; + if (!(intrinsics[Intrinsic_168] = CheckRuntimeObject("vec_vand"))) return 0; + if (!(intrinsics[Intrinsic_169] = CheckRuntimeObject("vec_vandc"))) return 0; + if (!(intrinsics[Intrinsic_170] = CheckRuntimeObject("vec_vavgub"))) return 0; + if (!(intrinsics[Intrinsic_171] = CheckRuntimeObject("vec_vavgsb"))) return 0; + if (!(intrinsics[Intrinsic_172] = CheckRuntimeObject("vec_vavguh"))) return 0; + if (!(intrinsics[Intrinsic_173] = CheckRuntimeObject("vec_vavgsh"))) return 0; + if (!(intrinsics[Intrinsic_174] = CheckRuntimeObject("vec_vavguw"))) return 0; + if (!(intrinsics[Intrinsic_175] = CheckRuntimeObject("vec_vavgsw"))) return 0; + if (!(intrinsics[Intrinsic_176] = CheckRuntimeObject("vec_vrfip"))) return 0; + if (!(intrinsics[Intrinsic_177] = CheckRuntimeObject("vec_vcmpbfp"))) return 0; + if (!(intrinsics[Intrinsic_178] = CheckRuntimeObject("vec_vcmpequb"))) return 0; + if (!(intrinsics[Intrinsic_179] = CheckRuntimeObject("vec_vcmpequh"))) return 0; + if (!(intrinsics[Intrinsic_180] = CheckRuntimeObject("vec_vcmpequw"))) return 0; + if (!(intrinsics[Intrinsic_181] = CheckRuntimeObject("vec_vcmpeqfp"))) return 0; + if (!(intrinsics[Intrinsic_182] = CheckRuntimeObject("vec_vcmpgefp"))) return 0; + if (!(intrinsics[Intrinsic_183] = CheckRuntimeObject("vec_vcmpgtub"))) return 0; + if (!(intrinsics[Intrinsic_184] = CheckRuntimeObject("vec_vcmpgtsb"))) return 0; + if (!(intrinsics[Intrinsic_185] = CheckRuntimeObject("vec_vcmpgtuh"))) return 0; + if (!(intrinsics[Intrinsic_186] = CheckRuntimeObject("vec_vcmpgtsh"))) return 0; + if (!(intrinsics[Intrinsic_187] = CheckRuntimeObject("vec_vcmpgtuw"))) return 0; + if (!(intrinsics[Intrinsic_188] = CheckRuntimeObject("vec_vcmpgtsw"))) return 0; + if (!(intrinsics[Intrinsic_189] = CheckRuntimeObject("vec_vcmpgtfp"))) return 0; + if (!(intrinsics[Intrinsic_190] = CheckRuntimeObject("vec_vcfux"))) return 0; + if (!(intrinsics[Intrinsic_191] = CheckRuntimeObject("vec_vcfsx"))) return 0; + if (!(intrinsics[Intrinsic_192] = CheckRuntimeObject("vec_vctsxs"))) return 0; + if (!(intrinsics[Intrinsic_193] = CheckRuntimeObject("vec_vctuxs"))) return 0; + if (!(intrinsics[Intrinsic_194] = CheckRuntimeObject("vec_vexptefp"))) return 0; + if (!(intrinsics[Intrinsic_195] = CheckRuntimeObject("vec_vrfim"))) return 0; + if (!(intrinsics[Intrinsic_196] = CheckRuntimeObject("vec_lvx"))) return 0; + if (!(intrinsics[Intrinsic_197] = CheckRuntimeObject("vec_lvebx"))) return 0; + if (!(intrinsics[Intrinsic_198] = CheckRuntimeObject("vec_lvehx"))) return 0; + if (!(intrinsics[Intrinsic_199] = CheckRuntimeObject("vec_lvewx"))) return 0; + if (!(intrinsics[Intrinsic_200] = CheckRuntimeObject("vec_lvxl"))) return 0; + if (!(intrinsics[Intrinsic_201] = CheckRuntimeObject("vec_vlogefp"))) return 0; + if (!(intrinsics[Intrinsic_202] = CheckRuntimeObject("vec_vmaddfp"))) return 0; + if (!(intrinsics[Intrinsic_203] = CheckRuntimeObject("vec_vmhaddshs"))) return 0; + if (!(intrinsics[Intrinsic_204] = CheckRuntimeObject("vec_vmaxub"))) return 0; + if (!(intrinsics[Intrinsic_205] = CheckRuntimeObject("vec_vmaxsb"))) return 0; + if (!(intrinsics[Intrinsic_206] = CheckRuntimeObject("vec_vmaxuh"))) return 0; + if (!(intrinsics[Intrinsic_207] = CheckRuntimeObject("vec_vmaxsh"))) return 0; + if (!(intrinsics[Intrinsic_208] = CheckRuntimeObject("vec_vmaxuw"))) return 0; + if (!(intrinsics[Intrinsic_209] = CheckRuntimeObject("vec_vmaxsw"))) return 0; + if (!(intrinsics[Intrinsic_210] = CheckRuntimeObject("vec_vmaxfp"))) return 0; + if (!(intrinsics[Intrinsic_211] = CheckRuntimeObject("vec_vmrghb"))) return 0; + if (!(intrinsics[Intrinsic_212] = CheckRuntimeObject("vec_vmrghh"))) return 0; + if (!(intrinsics[Intrinsic_213] = CheckRuntimeObject("vec_vmrghw"))) return 0; + if (!(intrinsics[Intrinsic_214] = CheckRuntimeObject("vec_vmrglb"))) return 0; + if (!(intrinsics[Intrinsic_215] = CheckRuntimeObject("vec_vmrglh"))) return 0; + if (!(intrinsics[Intrinsic_216] = CheckRuntimeObject("vec_vmrglw"))) return 0; + if (!(intrinsics[Intrinsic_204] = CheckRuntimeObject("vec_vminub"))) return 0; + if (!(intrinsics[Intrinsic_205] = CheckRuntimeObject("vec_vminsb"))) return 0; + if (!(intrinsics[Intrinsic_206] = CheckRuntimeObject("vec_vminuh"))) return 0; + if (!(intrinsics[Intrinsic_207] = CheckRuntimeObject("vec_vminsh"))) return 0; + if (!(intrinsics[Intrinsic_208] = CheckRuntimeObject("vec_vminuw"))) return 0; + if (!(intrinsics[Intrinsic_209] = CheckRuntimeObject("vec_vminsw"))) return 0; + if (!(intrinsics[Intrinsic_210] = CheckRuntimeObject("vec_vminfp"))) return 0; + if (!(intrinsics[Intrinsic_224] = CheckRuntimeObject("vec_vmladduhm"))) return 0; + if (!(intrinsics[Intrinsic_225] = CheckRuntimeObject("vec_vmhraddshs"))) return 0; + if (!(intrinsics[Intrinsic_226] = CheckRuntimeObject("vec_vmsumubm"))) return 0; + if (!(intrinsics[Intrinsic_227] = CheckRuntimeObject("vec_vmsumuhm"))) return 0; + if (!(intrinsics[Intrinsic_228] = CheckRuntimeObject("vec_vmsummbm"))) return 0; + if (!(intrinsics[Intrinsic_229] = CheckRuntimeObject("vec_vmsumshm"))) return 0; + if (!(intrinsics[Intrinsic_230] = CheckRuntimeObject("vec_vmsumuhs"))) return 0; + if (!(intrinsics[Intrinsic_231] = CheckRuntimeObject("vec_vmsumshs"))) return 0; + if (!(intrinsics[Intrinsic_232] = CheckRuntimeObject("vec_vmuleub"))) return 0; + if (!(intrinsics[Intrinsic_233] = CheckRuntimeObject("vec_vmulesb"))) return 0; + if (!(intrinsics[Intrinsic_234] = CheckRuntimeObject("vec_vmuleuh"))) return 0; + if (!(intrinsics[Intrinsic_235] = CheckRuntimeObject("vec_vmulesh"))) return 0; + if (!(intrinsics[Intrinsic_236] = CheckRuntimeObject("vec_vmuloub"))) return 0; + if (!(intrinsics[Intrinsic_237] = CheckRuntimeObject("vec_vmulosb"))) return 0; + if (!(intrinsics[Intrinsic_238] = CheckRuntimeObject("vec_vmulouh"))) return 0; + if (!(intrinsics[Intrinsic_239] = CheckRuntimeObject("vec_vmulosh"))) return 0; + if (!(intrinsics[Intrinsic_240] = CheckRuntimeObject("vec_vnmsubfp"))) return 0; + if (!(intrinsics[Intrinsic_241] = CheckRuntimeObject("vec_vnor"))) return 0; + if (!(intrinsics[Intrinsic_242] = CheckRuntimeObject("vec_vor"))) return 0; + if (!(intrinsics[Intrinsic_243] = CheckRuntimeObject("vec_vpkuhum"))) return 0; + if (!(intrinsics[Intrinsic_244] = CheckRuntimeObject("vec_vpkuwum"))) return 0; + if (!(intrinsics[Intrinsic_245] = CheckRuntimeObject("vec_vpkpx"))) return 0; + if (!(intrinsics[Intrinsic_246] = CheckRuntimeObject("vec_vpkuhus"))) return 0; + if (!(intrinsics[Intrinsic_247] = CheckRuntimeObject("vec_vpkshss"))) return 0; + if (!(intrinsics[Intrinsic_248] = CheckRuntimeObject("vec_vpkuwus"))) return 0; + if (!(intrinsics[Intrinsic_249] = CheckRuntimeObject("vec_vpkswss"))) return 0; + if (!(intrinsics[Intrinsic_250] = CheckRuntimeObject("vec_vpkshus"))) return 0; + if (!(intrinsics[Intrinsic_251] = CheckRuntimeObject("vec_vpkswus"))) return 0; + if (!(intrinsics[Intrinsic_252] = CheckRuntimeObject("vec_vperm"))) return 0; + if (!(intrinsics[Intrinsic_253] = CheckRuntimeObject("vec_vrefp"))) return 0; + if (!(intrinsics[Intrinsic_254] = CheckRuntimeObject("vec_vrlb"))) return 0; + if (!(intrinsics[Intrinsic_255] = CheckRuntimeObject("vec_vrlh"))) return 0; + if (!(intrinsics[Intrinsic_256] = CheckRuntimeObject("vec_vrlw"))) return 0; + if (!(intrinsics[Intrinsic_257] = CheckRuntimeObject("vec_vrfin"))) return 0; + if (!(intrinsics[Intrinsic_258] = CheckRuntimeObject("vec_vrsqrtefp"))) return 0; + if (!(intrinsics[Intrinsic_259] = CheckRuntimeObject("vec_vsel"))) return 0; + if (!(intrinsics[Intrinsic_260] = CheckRuntimeObject("vec_vslb"))) return 0; + if (!(intrinsics[Intrinsic_261] = CheckRuntimeObject("vec_vslh"))) return 0; + if (!(intrinsics[Intrinsic_262] = CheckRuntimeObject("vec_vslw"))) return 0; + if (!(intrinsics[Intrinsic_263] = CheckRuntimeObject("vec_vsldoi"))) return 0; + if (!(intrinsics[Intrinsic_264] = CheckRuntimeObject("vec_vsl"))) return 0; + if (!(intrinsics[Intrinsic_265] = CheckRuntimeObject("vec_vslo"))) return 0; + if (!(intrinsics[Intrinsic_266] = CheckRuntimeObject("vec_vspltb"))) return 0; + if (!(intrinsics[Intrinsic_267] = CheckRuntimeObject("vec_vsplth"))) return 0; + if (!(intrinsics[Intrinsic_268] = CheckRuntimeObject("vec_vspltw"))) return 0; + if (!(intrinsics[Intrinsic_269] = CheckRuntimeObject("vec_vspltisb"))) return 0; + if (!(intrinsics[Intrinsic_270] = CheckRuntimeObject("vec_vspltish"))) return 0; + if (!(intrinsics[Intrinsic_271] = CheckRuntimeObject("vec_vspltisw"))) return 0; + if (!(intrinsics[Intrinsic_272] = CheckRuntimeObject("vec_vsrb"))) return 0; + if (!(intrinsics[Intrinsic_273] = CheckRuntimeObject("vec_vsrh"))) return 0; + if (!(intrinsics[Intrinsic_274] = CheckRuntimeObject("vec_vsrw"))) return 0; + if (!(intrinsics[Intrinsic_275] = CheckRuntimeObject("vec_vsrab"))) return 0; + if (!(intrinsics[Intrinsic_276] = CheckRuntimeObject("vec_vsrah"))) return 0; + if (!(intrinsics[Intrinsic_277] = CheckRuntimeObject("vec_vsraw"))) return 0; + if (!(intrinsics[Intrinsic_278] = CheckRuntimeObject("vec_vsr"))) return 0; + if (!(intrinsics[Intrinsic_279] = CheckRuntimeObject("vec_vsro"))) return 0; + if (!(intrinsics[Intrinsic_280] = CheckRuntimeObject("vec_stvx"))) return 0; + if (!(intrinsics[Intrinsic_281] = CheckRuntimeObject("vec_stvebx"))) return 0; + if (!(intrinsics[Intrinsic_282] = CheckRuntimeObject("vec_stvehx"))) return 0; + if (!(intrinsics[Intrinsic_283] = CheckRuntimeObject("vec_stvewx"))) return 0; + if (!(intrinsics[Intrinsic_284] = CheckRuntimeObject("vec_stvxl"))) return 0; + if (!(intrinsics[Intrinsic_285] = CheckRuntimeObject("vec_vsububm"))) return 0; + if (!(intrinsics[Intrinsic_286] = CheckRuntimeObject("vec_vsubuhm"))) return 0; + if (!(intrinsics[Intrinsic_287] = CheckRuntimeObject("vec_vsubuwm"))) return 0; + if (!(intrinsics[Intrinsic_288] = CheckRuntimeObject("vec_vsubfp"))) return 0; + if (!(intrinsics[Intrinsic_289] = CheckRuntimeObject("vec_vsubcuw"))) return 0; + if (!(intrinsics[Intrinsic_290] = CheckRuntimeObject("vec_vsububs"))) return 0; + if (!(intrinsics[Intrinsic_291] = CheckRuntimeObject("vec_vsubsbs"))) return 0; + if (!(intrinsics[Intrinsic_292] = CheckRuntimeObject("vec_vsubuhs"))) return 0; + if (!(intrinsics[Intrinsic_293] = CheckRuntimeObject("vec_vsubshs"))) return 0; + if (!(intrinsics[Intrinsic_294] = CheckRuntimeObject("vec_vsubuws"))) return 0; + if (!(intrinsics[Intrinsic_295] = CheckRuntimeObject("vec_vsubsws"))) return 0; + if (!(intrinsics[Intrinsic_296] = CheckRuntimeObject("vec_vsum4ubs"))) return 0; + if (!(intrinsics[Intrinsic_297] = CheckRuntimeObject("vec_vsum4sbs"))) return 0; + if (!(intrinsics[Intrinsic_298] = CheckRuntimeObject("vec_vsum4shs"))) return 0; + if (!(intrinsics[Intrinsic_299] = CheckRuntimeObject("vec_vsum2sws"))) return 0; + if (!(intrinsics[Intrinsic_300] = CheckRuntimeObject("vec_vsumsws"))) return 0; + if (!(intrinsics[Intrinsic_301] = CheckRuntimeObject("vec_vrfiz"))) return 0; + if (!(intrinsics[Intrinsic_302] = CheckRuntimeObject("vec_vupkhsb"))) return 0; + if (!(intrinsics[Intrinsic_303] = CheckRuntimeObject("vec_vupklsb"))) return 0; + if (!(intrinsics[Intrinsic_304] = CheckRuntimeObject("vec_vupkhpx"))) return 0; + if (!(intrinsics[Intrinsic_305] = CheckRuntimeObject("vec_vupklpx"))) return 0; + if (!(intrinsics[Intrinsic_306] = CheckRuntimeObject("vec_vupkhsh"))) return 0; + if (!(intrinsics[Intrinsic_307] = CheckRuntimeObject("vec_vupklsh"))) return 0; + if (!(intrinsics[Intrinsic_308] = CheckRuntimeObject("vec_vxor"))) return 0; + if (!(intrinsics[Intrinsic_309] = CheckRuntimeObject("vec_abs"))) return 0; + if (!(intrinsics[Intrinsic_310] = CheckRuntimeObject("vec_abss"))) return 0; + } + + return 1; +} + +Boolean Intrinsics_IsPublicRuntimeObject(Object *object) { + int i; + + for (i = 0; i < MaxIntrinsics; i++) { + if (object == intrinsics[i]) + return 1; + } + + return 0; +} diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Operands.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Operands.c new file mode 100644 index 0000000..c5da285 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Operands.c @@ -0,0 +1,1040 @@ +#include "compiler/Operands.h" +#include "compiler/CError.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/RegisterInfo.h" +#include "compiler/Registers.h" +#include "compiler/StackFrame.h" +#include "compiler/TOC.h" +#include "compiler/enode.h" +#include "compiler/objects.h" + +unsigned long long uns_to_float_cc = 0x4330000000000000; +unsigned long long int_to_float_cc = 0x4330000080000000; +Float one_point_zero = {1.0}; + +void load_immediate(short reg, SInt32 value) { + short tmpreg = reg; + short tmpreg2; + + if (!FITS_IN_SHORT(value)) { + if (copts.optimizationlevel > 1 && LOW_PART_BUGGY(value)) + tmpreg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_LIS, tmpreg2 = tmpreg, 0, (short) HIGH_PART(value)); + if (LOW_PART_BUGGY(value)) + emitpcode(PC_ADDI, reg, tmpreg2, 0, LOW_PART(value)); + } else { + emitpcode(PC_LI, reg, value); + } +} + +static void set_op_flags(Operand *op, ENode *expr) { + CError_ASSERT(118, op); + + if (expr) { + if (expr->type == EINTCONST) { + op->flags = 0; + if (expr->flags & ENODE_FLAG_VOLATILE) + op->flags |= OpndFlags_Volatile; + if (expr->flags & ENODE_FLAG_CONST) + op->flags |= OpndFlags_Const; + } else { + op->flags = CParserIsVolatileExpr(expr) ? OpndFlags_Volatile : 0; + op->flags |= CParserIsConstExpr(expr) ? OpndFlags_Const : 0; + } + } else { + op->flags = 0; + } +} + +void symbol_operand(Operand *op, Object *obj) { + memclrw(op, sizeof(Operand)); + op->optype = OpndType_Symbol; + op->object = obj; +} + +void indirect(Operand *op, ENode *expr) { + switch (op->optype) { + case OpndType_GPRPair: + CError_FATAL(163); + case OpndType_CRField: + case OpndType_IndirectGPR_ImmOffset: + case OpndType_IndirectGPR_Indexed: + case OpndType_IndirectSymbol: + if (op->optype) + Coerce_to_register(op, TYPE(&void_ptr), 0); + case OpndType_GPR: + op->immOffset = 0; + op->object = NULL; + case OpndType_GPR_ImmOffset: + op->optype = OpndType_IndirectGPR_ImmOffset; + set_op_flags(op, expr); + break; + case OpndType_GPR_Indexed: + op->optype = OpndType_IndirectGPR_Indexed; + set_op_flags(op, expr); + break; + case OpndType_Absolute: + if (FITS_IN_SHORT(op->immediate)) { + op->reg = 0; + op->immOffset = op->immediate; + } else { + emitpcode(PC_LIS, op->reg = used_virtual_registers[RegClass_GPR]++, 0, (short) HIGH_PART(op->immediate)); + op->immOffset = LOW_PART(op->immediate); + } + op->object = NULL; + op->optype = OpndType_IndirectGPR_ImmOffset; + set_op_flags(op, expr); + break; + case OpndType_Symbol: + op->optype = OpndType_IndirectSymbol; + set_op_flags(op, expr); + break; + default: + CError_FATAL(215); + } +} + +#define COMBO_OP(a, b) (b + (a * 11)) + +void combine(Operand *opA, Operand *opB, short output_reg, Operand *opOut) { + Operand *tmp_op; + int tmp; + + if (opA->optype == OpndType_Symbol || opA->optype == OpndType_IndirectSymbol) + coerce_to_addressable(opA); + if (opB->optype == OpndType_Symbol || opB->optype == OpndType_IndirectSymbol) + coerce_to_addressable(opB); + + switch (COMBO_OP(opA->optype, opB->optype)) { + case COMBO_OP(OpndType_GPR, OpndType_GPR): + opOut->optype = OpndType_GPR_Indexed; + opOut->reg = opA->reg; + opOut->regOffset = opB->reg; + break; + case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR_ImmOffset): + if (FITS_IN_SHORT(opA->immOffset + opB->immOffset) && (!opA->object || !opB->object)) { + opB->immOffset += opA->immOffset; + if (!opB->object) + opB->object = opA->object; + } else { + tmp = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; + add_immediate(tmp, opA->reg, opA->object, opA->immOffset); + opA->reg = tmp; + } + case COMBO_OP(OpndType_GPR, OpndType_GPR_ImmOffset): + tmp_op = opA; + opA = opB; + opB = tmp_op; + case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR): + if (opA->reg == _FP_ || opA->reg == _CALLER_SP_) { + opOut->optype = OpndType_GPR_Indexed; + opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; + opOut->regOffset = opB->reg; + add_immediate(opOut->reg, opA->reg, opA->object, LOW_PART(opA->immOffset)); + } else if (opB->reg == _FP_ || opB->reg == _CALLER_SP_) { + opOut->optype = OpndType_GPR_Indexed; + opOut->reg = (output_reg && (output_reg != opA->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; + opOut->regOffset = opA->reg; + add_immediate(opOut->reg, opB->reg, opA->object, LOW_PART(opA->immOffset)); + } else if (opA->object) { + opOut->optype = OpndType_GPR_Indexed; + opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; + opOut->regOffset = opB->reg; + add_immediate(opOut->reg, opA->reg, opA->object, LOW_PART(opA->immOffset)); + } else { + opOut->optype = OpndType_GPR_ImmOffset; + opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + opOut->immOffset = opA->immOffset; + opOut->object = opA->object; + emitpcode(PC_ADD, opOut->reg, opA->reg, opB->reg); + } + break; + case COMBO_OP(OpndType_GPR, OpndType_GPR_Indexed): + tmp_op = opA; + opA = opB; + opB = tmp_op; + case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR): + opOut->optype = OpndType_GPR_Indexed; + opOut->reg = opA->reg; + opOut->regOffset = (output_reg && (output_reg != opA->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADD, opOut->regOffset, opA->regOffset, opB->reg); + break; + case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR_Indexed): + tmp_op = opA; + opA = opB; + opB = tmp_op; + case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR_ImmOffset): + if (opB->object) { + opOut->optype = OpndType_GPR_Indexed; + opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg + : used_virtual_registers[RegClass_GPR]++; + opOut->regOffset = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADD, opOut->reg, opA->reg, opA->regOffset); + add_immediate(opOut->regOffset, opB->reg, opB->object, opB->immOffset); + } else { + opOut->optype = OpndType_GPR_ImmOffset; + opOut->immOffset = opB->immOffset; + opOut->object = opB->object; + opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg + : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADD, opOut->reg, opA->reg, opA->regOffset); + emitpcode(PC_ADD, opOut->reg, opOut->reg, opB->reg); + } + break; + case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR_Indexed): + opOut->optype = OpndType_GPR_Indexed; + opOut->reg = opA->reg; + opOut->regOffset = (output_reg && (output_reg != opA->regOffset)) ? output_reg + : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADD, opOut->regOffset, opB->reg, opB->regOffset); + emitpcode(PC_ADD, opOut->regOffset, opOut->regOffset, opA->regOffset); + break; + case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_Absolute): + tmp_op = opA; + opA = opB; + opB = tmp_op; + case COMBO_OP(OpndType_Absolute, OpndType_GPR_ImmOffset): + if (!opB->object) { + opOut->optype = OpndType_GPR_ImmOffset; + opOut->reg = opB->reg; + opOut->immOffset = opB->immOffset; + opOut->object = opB->object; + if (FITS_IN_SHORT(opOut->immOffset + opA->immediate)) { + opOut->immOffset += opA->immediate; + } else { + opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + if (!HIGH_PART(opA->immediate)) { + emitpcode(PC_ADDI, opOut->reg, opB->reg, 0, LOW_PART(opA->immediate)); + } else { + emitpcode(PC_ADDIS, opOut->reg, opB->reg, 0, (short) HIGH_PART(opA->immediate)); + if (FITS_IN_SHORT(opOut->immOffset + LOW_PART(opA->immediate))) { + opOut->immOffset += LOW_PART(opA->immediate); + } else { + emitpcode(PC_ADDI, opOut->reg, opOut->reg, 0, LOW_PART(opA->immediate)); + } + } + } + break; + } else if (opB->object->datatype == DLOCAL && can_add_displ_to_local(opB->object, opB->immOffset + opA->immediate)) { + opOut->optype = OpndType_GPR_ImmOffset; + opOut->object = opB->object; + opOut->reg = opB->reg; + opOut->immOffset = LOW_PART(opB->immOffset + opA->immediate); + break; + } else { + opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + add_immediate(opOut->reg, opB->reg, opB->object, opB->immOffset); + opB->optype = OpndType_GPR; + opB->reg = opOut->reg; + tmp_op = opA; + opA = opB; + opB = tmp_op; + } + case COMBO_OP(OpndType_GPR, OpndType_Absolute): + tmp_op = opA; + opA = opB; + opB = tmp_op; + case COMBO_OP(OpndType_Absolute, OpndType_GPR): + opOut->optype = (opA->immediate != 0) ? OpndType_GPR_ImmOffset : OpndType_GPR; + opOut->immOffset = LOW_PART(opA->immediate); + opOut->object = NULL; + if (FITS_IN_SHORT(opA->immediate)) { + opOut->reg = opB->reg; + } else { + opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADDIS, opOut->reg, opB->reg, 0, (short) HIGH_PART(opA->immediate)); + } + break; + case COMBO_OP(OpndType_GPR_Indexed, OpndType_Absolute): + tmp_op = opA; + opA = opB; + opB = tmp_op; + case COMBO_OP(OpndType_Absolute, OpndType_GPR_Indexed): + opOut->optype = OpndType_GPR_Indexed; + opOut->reg = opB->reg; + opOut->regOffset = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; + if (!HIGH_PART(opA->immediate)) { + emitpcode(PC_ADDI, opOut->regOffset, opB->regOffset, 0, LOW_PART(opA->immediate)); + } else { + emitpcode(PC_ADDIS, opOut->regOffset, opB->regOffset, 0, (short) HIGH_PART(opA->immediate)); + if (LOW_PART_BUGGY(opA->immediate)) + emitpcode(PC_ADDI, opOut->regOffset, opOut->regOffset, 0, LOW_PART(opA->immediate)); + } + break; + case COMBO_OP(OpndType_Absolute, OpndType_Absolute): + opOut->optype = OpndType_Absolute; + opOut->immediate = opA->immediate + opB->immediate; + break; + default: + CError_FATAL(415); + } +} + +void coerce_to_addressable(Operand *op) { + UInt32 offset; + short reg; + short flag; + short tmp; + Object *obj; + + flag = 0; + obj = op->object; + tmp = 0; + + switch (op->optype) { + case OpndType_GPR: + case OpndType_GPR_ImmOffset: + case OpndType_GPR_Indexed: + case OpndType_GPRPair: + case OpndType_Absolute: + case OpndType_VR: + case OpndType_CRField: + case OpndType_IndirectGPR_ImmOffset: + case OpndType_IndirectGPR_Indexed: + break; + case OpndType_IndirectSymbol: + flag = 1; + case OpndType_Symbol: + if (obj->datatype == DLOCAL) { + if (!local_is_16bit_offset(obj)) { + reg = used_virtual_registers[RegClass_GPR]++; + op_absolute_ha(reg, local_base_register(obj), obj, 0, 1); + op->optype = OpndType_GPR_ImmOffset; + op->reg = reg; + op->object = obj; + } else { + op->optype = OpndType_GPR_ImmOffset; + op->reg = local_base_register(obj); + op->object = obj; + } + } else if (obj->datatype == DABSOLUTE) { + offset = obj->u.address; + if (FITS_IN_SHORT(offset)) { + op->reg = 0; + op->immOffset = obj->u.address; + } else { + emitpcode(PC_LIS, op->reg = used_virtual_registers[RegClass_GPR]++, 0, (short) HIGH_PART(offset)); + op->immOffset = LOW_PART(obj->u.address); + } + op->object = obj; + op->optype = OpndType_GPR_ImmOffset; + } else { + if (copts.codegen_pic) + tmp = pic_base_reg; + reg = used_virtual_registers[RegClass_GPR]++; + op_absolute_ha(reg, tmp, obj, 0, 1); + op->optype = OpndType_GPR_ImmOffset; + op->reg = reg; + } + if (flag) { + if (op->optype == OpndType_GPR_ImmOffset) { + op->optype = OpndType_IndirectGPR_ImmOffset; + } else { + CError_FATAL(563); + } + } + break; + default: + CError_FATAL(581); + } +} + +void Coerce_to_register(Operand *op, Type *type, short output_reg) { + SInt32 offset; + Opcode opcode; + short reg; + short tmp; + short cond_neg; + short cond; + short bit_offset; + short bit_size; + + if (TYPE_IS_8BYTES(type)) { + coerce_to_register_pair(op, type, output_reg, 0); + return; + } + + coerce_to_addressable(op); + switch (op->optype) { + case OpndType_GPRPair: + return; + case OpndType_GPR: + return; + case OpndType_GPR_ImmOffset: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + add_immediate(reg, op->reg, op->object, op->immOffset); + break; + case OpndType_GPR_Indexed: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADD, reg, op->reg, op->regOffset); + break; + case OpndType_Absolute: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + offset = op->immediate; + if (FITS_IN_SHORT(offset)) { + emitpcode(PC_LI, reg, offset); + } else { + tmp = reg; + if (copts.optimizationlevel > 1 && LOW_PART_BUGGY(offset)) + tmp = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_LIS, tmp, 0, (short) HIGH_PART(offset)); + if (LOW_PART_BUGGY(offset)) + emitpcode(PC_ADDI, reg, tmp, 0, LOW_PART(offset)); + } + break; + case OpndType_IndirectGPR_ImmOffset: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + opcode = PC_LWZ; + if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) { + switch (type->size) { + case 1: + opcode = PC_LBZ; + break; + case 2: + if (is_unsigned(type)) + opcode = PC_LHZ; + else + opcode = PC_LHA; + break; + } + } else { + CError_ASSERT(680, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); + } + load_store_register(opcode, reg, op->reg, op->object, op->immOffset); + setpcodeflags(op->flags); + break; + case OpndType_IndirectGPR_Indexed: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + opcode = PC_LWZX; + if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) { + switch (type->size) { + case 1: + opcode = PC_LBZX; + break; + case 2: + if (is_unsigned(type)) + opcode = PC_LHZX; + else + opcode = PC_LHAX; + break; + } + } else { + CError_ASSERT(724, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); + } + emitpcode(opcode, reg, op->reg, op->regOffset); + setpcodeflags(op->flags); + break; + case OpndType_CRField: + cond_neg = 0; + cond = 0; + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_MFCR, tmp = reg); + switch (op->regOffset) { + case ENOTEQU: + cond_neg = 1; + case EEQU: + cond = 2; + break; + case EGREATEREQU: + cond_neg = 1; + case ELESS: + cond = 0; + break; + case ELESSEQU: + cond_neg = 1; + case EGREATER: + cond = 1; + break; + default: + CError_FATAL(758); + } + bit_offset = cond + (op->reg << 2); + bit_size = 1; + emitpcode(PC_RLWINM, tmp, tmp, (bit_size + bit_offset) & 31, 32 - bit_size, 31); + if (cond_neg) + emitpcode(PC_XORI, tmp, tmp, 1); + break; + default: + CError_FATAL(769); + } + + op->optype = OpndType_GPR; + op->reg = reg; +} + +void coerce_to_register_pair(Operand *op, Type *type, short output_reg, short output_regHi) { + SInt32 offset; + short reg; + short regHi; + short tmp1; + short tmp2; + + regHi = -1; + + CError_ASSERT(794, TYPE_IS_8BYTES(type) || (IS_TYPE_STRUCT(type) && type->size == 8)); + + coerce_to_addressable(op); + switch (op->optype) { + case OpndType_GPRPair: + if (output_reg && !output_regHi) + output_regHi = used_virtual_registers[RegClass_GPR]++; + if (output_regHi && !output_reg) + output_reg = used_virtual_registers[RegClass_GPR]++; + if (op->reg != output_reg || op->regHi != output_regHi) { + tmp1 = output_reg ? output_reg : op->reg; + tmp2 = output_regHi ? output_regHi : op->regHi; + if (tmp1 != op->reg) { + if (tmp1 == op->regHi) { + CError_ASSERT(818, tmp1 != tmp2); + emitpcode(PC_MR, tmp2, op->regHi); + emitpcode(PC_MR, tmp1, op->reg); + } else { + emitpcode(PC_MR, tmp1, op->reg); + if (op->regHi != tmp2) + emitpcode(PC_MR, tmp2, op->regHi); + } + } else if (tmp2 != op->regHi) { + if (tmp2 == op->reg) { + CError_ASSERT(832, tmp1 != tmp2); + emitpcode(PC_MR, tmp1, op->reg); + emitpcode(PC_MR, tmp2, op->regHi); + } else { + emitpcode(PC_MR, tmp2, op->regHi); + if (op->reg != tmp1) + emitpcode(PC_MR, tmp1, op->reg); + } + } + } + reg = op->reg; + regHi = op->regHi; + break; + case OpndType_GPR: + CError_FATAL(849); + break; + case OpndType_GPR_ImmOffset: + CError_FATAL(852); + break; + case OpndType_GPR_Indexed: + CError_FATAL(855); + break; + case OpndType_Absolute: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + offset = op->immediate; + if (FITS_IN_SHORT(offset)) { + emitpcode(PC_LI, reg, offset); + } else { + tmp1 = reg; + if (copts.optimizationlevel > 1 && LOW_PART_BUGGY(offset)) + tmp1 = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_LIS, tmp1, 0, (short) HIGH_PART(offset)); + if (LOW_PART_BUGGY(offset)) + emitpcode(PC_ADDI, reg, tmp1, 0, LOW_PART(offset)); + } + regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++; + if (is_unsigned(type) || offset >= 0) + load_immediate(regHi, 0); + else + load_immediate(regHi, -1); + break; + case OpndType_IndirectGPR_ImmOffset: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++; + if (op->reg == regHi) { + if (op->reg == reg) { + CError_FATAL(887); + } else { + load_store_register(PC_LWZ, reg, op->reg, op->object, op->immOffset + low_offset); + setpcodeflags(op->flags); + load_store_register(PC_LWZ, regHi, op->reg, op->object, op->immOffset + high_offset); + setpcodeflags(op->flags); + } + } else { + load_store_register(PC_LWZ, regHi, op->reg, op->object, op->immOffset + high_offset); + setpcodeflags(op->flags); + load_store_register(PC_LWZ, reg, op->reg, op->object, op->immOffset + low_offset); + setpcodeflags(op->flags); + } + break; + case OpndType_IndirectGPR_Indexed: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADD, reg, op->reg, op->regOffset); + load_store_register(PC_LWZ, regHi, reg, NULL, high_offset); + setpcodeflags(op->flags); + load_store_register(PC_LWZ, reg, reg, NULL, low_offset); + setpcodeflags(op->flags); + break; + default: + CError_FATAL(912); + } + + if (regHi == -1) { + CError_FATAL(916); + } else { + op->optype = OpndType_GPRPair; + op->reg = reg; + op->regHi = regHi; + } +} + +void Coerce_to_fp_register(Operand *op, Type *type, short output_reg) { + short reg; + + coerce_to_addressable(op); + + switch (op->optype) { + case OpndType_FPR: + reg = op->reg; + break; + case OpndType_IndirectGPR_ImmOffset: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++; + load_store_register((type->size == 4) ? PC_LFS : PC_LFD, reg, op->reg, op->object, op->immOffset); + setpcodeflags(op->flags); + break; + case OpndType_IndirectGPR_Indexed: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++; + emitpcode((type->size == 4) ? PC_LFSX : PC_LFDX, reg, op->reg, op->regOffset, 0, 0x390); + setpcodeflags(op->flags); + break; + default: + CError_FATAL(986); + } + + op->optype = OpndType_FPR; + op->reg = reg; +} + +void Coerce_to_v_register(Operand *op, Type *type, short output_reg) { + short reg; + + coerce_to_addressable(op); + + switch (op->optype) { + case OpndType_VR: + reg = op->reg; + break; + case OpndType_IndirectGPR_ImmOffset: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++; + load_store_register(PC_LVX, reg, op->reg, op->object, op->immOffset); + setpcodeflags(op->flags); + break; + case OpndType_IndirectGPR_Indexed: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++; + emitpcode(PC_LVX, reg, op->reg, op->regOffset); + setpcodeflags(op->flags); + break; + case OpndType_Absolute: + reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++; + switch (TYPE_STRUCT(type)->stype) { + case STRUCT_VECTOR_UCHAR: + case STRUCT_VECTOR_SCHAR: + case STRUCT_VECTOR_BCHAR: + emitpcode(PC_VSPLTISB, reg, op->immediate); + break; + case STRUCT_VECTOR_USHORT: + case STRUCT_VECTOR_SSHORT: + case STRUCT_VECTOR_BSHORT: + case STRUCT_VECTOR_PIXEL: + emitpcode(PC_VSPLTISH, reg, op->immediate); + break; + case STRUCT_VECTOR_UINT: + case STRUCT_VECTOR_SINT: + case STRUCT_VECTOR_BINT: + case STRUCT_VECTOR_FLOAT: + emitpcode(PC_VSPLTISW, reg, op->immediate); + break; + default: + CError_FATAL(1049); + } + op->optype = OpndType_VR; + op->reg = reg; + setpcodeflags(op->flags); + break; + default: + CError_FATAL(1059); + } + + op->optype = OpndType_VR; + op->reg = reg; +} + +void store(short reg, Operand *op, Type *type) { + Opcode opcode; + + coerce_to_addressable(op); + switch (op->optype) { + case OpndType_IndirectGPR_ImmOffset: + opcode = PC_STW; + if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) { + switch (type->size) { + case 1: + opcode = PC_STB; + break; + case 2: + opcode = PC_STH; + break; + } + } else { + CError_ASSERT(1171, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); + } + load_store_register(opcode, reg, op->reg, op->object, op->immOffset); + setpcodeflags(op->flags); + break; + case OpndType_IndirectGPR_Indexed: + opcode = PC_STWX; + if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) { + switch (type->size) { + case 1: + opcode = PC_STBX; + break; + case 2: + opcode = PC_STHX; + break; + } + } else { + CError_ASSERT(1188, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); + } + emitpcode(opcode, reg, op->reg, op->regOffset); + setpcodeflags(op->flags); + break; + default: + CError_FATAL(1193); + } +} + +void store_pair(short reg, short regHi, Operand *op, Type *type) { + short tmp; + + CError_ASSERT(1208, TYPE_IS_8BYTES(type)); + + coerce_to_addressable(op); + switch (op->optype) { + case OpndType_IndirectGPR_ImmOffset: + load_store_register(PC_STW, reg, op->reg, op->object, op->immOffset + low_offset); + setpcodeflags(op->flags); + load_store_register(PC_STW, regHi, op->reg, op->object, op->immOffset + high_offset); + setpcodeflags(op->flags); + break; + case OpndType_IndirectGPR_Indexed: + tmp = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADD, tmp, op->reg, op->regOffset); + load_store_register(PC_STW, reg, tmp, NULL, low_offset); + setpcodeflags(op->flags); + load_store_register(PC_STW, regHi, tmp, NULL, high_offset); + setpcodeflags(op->flags); + break; + default: + CError_FATAL(1228); + } +} + +void store_fp(short reg, Operand *op, Type *type) { + coerce_to_addressable(op); + switch (op->optype) { + case OpndType_IndirectGPR_ImmOffset: + load_store_register((type->size == 4) ? PC_STFS : PC_STFD, reg, op->reg, op->object, op->immOffset); + setpcodeflags(op->flags); + break; + case OpndType_IndirectGPR_Indexed: + emitpcode((type->size == 4) ? PC_STFSX : PC_STFDX, reg, op->reg, op->regOffset); + setpcodeflags(op->flags); + break; + default: + CError_FATAL(1259); + } +} + +void store_v(short reg, Operand *op, Type *tstruct) { + coerce_to_addressable(op); + switch (op->optype) { + case OpndType_IndirectGPR_ImmOffset: + load_store_register(PC_STVX, reg, op->reg, op->object, op->immOffset); + setpcodeflags(op->flags); + break; + case OpndType_IndirectGPR_Indexed: + emitpcode(PC_STVX, reg, op->reg, op->regOffset); + setpcodeflags(op->flags); + break; + default: + CError_FATAL(1283); + } +} + +static Boolean last_matches_rlwinm_or_exts(Operand *op, short opcode, short b, short c) { + PCode *pc; + + if (pclastblock->pcodeCount <= 0) + return 0; + + pc = pclastblock->lastPCode; + if (pc->args[0].kind != PCOp_REGISTER || pc->args[0].arg != RegClass_GPR || pc->args[0].data.reg.reg != op->reg) + return 0; + + if (pc->op != opcode && (opcode != PC_EXTSH || pc->op != PC_EXTSB)) + return 0; + + if (opcode == PC_RLWINM) { + if (pc->args[2].data.imm.value != 0 || pc->args[3].data.imm.value != b || pc->args[4].data.imm.value != c) + return 0; + } + + return 1; +} + +void extend32(Operand *op, Type *type, short output_reg) { + int r28; + int reg; + + r28 = op->optype >= OpndType_IndirectGPR_ImmOffset; + if (op->optype != OpndType_GPR) + Coerce_to_register(op, type, output_reg); + + switch (type->size) { + case 1: + if (is_unsigned(type)) { + if (r28) + return; + if (last_matches_rlwinm_or_exts(op, PC_RLWINM, 24, 31)) + return; + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_RLWINM, reg, op->reg, 0, 24, 31); + } else { + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + if (last_matches_rlwinm_or_exts(op, PC_EXTSB, 0, 0)) + return; + emitpcode(PC_EXTSB, reg, op->reg); + } + break; + case 2: + if (r28) + return; + if (is_unsigned(type)) { + if (last_matches_rlwinm_or_exts(op, PC_RLWINM, 16, 31)) + return; + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_RLWINM, reg, op->reg, 0, 16, 31); + } else { + if (last_matches_rlwinm_or_exts(op, PC_EXTSH, 0, 0)) + return; + reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_EXTSH, reg, op->reg); + } + break; + default: + CError_FATAL(1389); + } + + op->optype = OpndType_GPR; + op->reg = reg; +} + +void extend64(Operand *op, Type *type, short output_reg, short output_regHi) { + short tmp; + short regHi; + + if (op->optype != OpndType_GPR) + Coerce_to_register(op, type, output_reg); + + regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++; + if (regHi == op->reg) { + tmp = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_MR, tmp, op->reg); + op->reg = tmp; + } + + if (is_unsigned(type)) + load_immediate(regHi, 0); + else + emitpcode(PC_SRAWI, regHi, op->reg, 31); + + op->optype = OpndType_GPRPair; + op->regHi = regHi; +} + +void load_floating_constant(short reg, Type *type, Float *data) { + Object *object; + Object *indObject; + Operand op1; + Operand op2; + Operand op3; + SInt32 offset = 0; + + memclrw(&op1, sizeof(Operand)); + + object = CreateFloatConst(type, data, &offset); + indObject = createIndirect(object, 0, 1); + + if (indObject) { + symbol_operand(&op1, indObject); + indirect(&op1, NULL); + } else { + symbol_operand(&op1, object); + } + + if (offset) { + op2 = op1; + memclrw(&op3, sizeof(Operand)); + op3.optype = OpndType_Absolute; + op3.immediate = offset; + if (op2.optype != OpndType_GPR) + Coerce_to_register(&op2, TYPE(&void_ptr), 0); + combine(&op2, &op3, 0, &op1); + } + + indirect(&op1, NULL); + if (op1.optype != OpndType_FPR) + Coerce_to_fp_register(&op1, type, reg); +} + +void convert_integer_to_floating(Operand *op, Boolean is_single, short output_reg) { + Operand temp_op; + Float d; + int const_reg; + int tmp_reg; + int work_reg; + int result_reg; + Opcode opcode; + + symbol_operand(&temp_op, maketemporary(TYPE(&stdouble))); + coerce_to_addressable(&temp_op); + d.value = *((double *) &int_to_float_cc); + + const_reg = used_virtual_registers[RegClass_FPR]++; + load_floating_constant(const_reg, TYPE(&stdouble), &d); + + tmp_reg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_XORIS, tmp_reg, op->reg, 0x8000); + load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, low_offset); + + emitpcode(PC_LIS, tmp_reg = used_virtual_registers[RegClass_GPR]++, 0, 0x4330); + load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, high_offset); + + load_store_register(PC_LFD, work_reg = used_virtual_registers[RegClass_FPR]++, temp_op.reg, temp_op.object, 0); + + result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++; + if (is_single != 0) + opcode = PC_FSUBS; + else + opcode = PC_FSUB; + emitpcode(opcode, result_reg, work_reg, const_reg); + + op->optype = OpndType_FPR; + op->reg = result_reg; +} + +void convert_unsigned_to_floating(Operand *op, Boolean is_single, short output_reg) { + Operand temp_op; + Float d; + int const_reg; + int tmp_reg; + int work_reg; + int result_reg; + Opcode opcode; + + symbol_operand(&temp_op, maketemporary(TYPE(&stdouble))); + coerce_to_addressable(&temp_op); + d.value = *((double *) &uns_to_float_cc); + + const_reg = used_virtual_registers[RegClass_FPR]++; + load_floating_constant(const_reg, TYPE(&stdouble), &d); + + load_store_register(PC_STW, op->reg, temp_op.reg, temp_op.object, low_offset); + + emitpcode(PC_LIS, tmp_reg = used_virtual_registers[RegClass_GPR]++, 0, 0x4330); + load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, high_offset); + + load_store_register(PC_LFD, work_reg = used_virtual_registers[RegClass_FPR]++, temp_op.reg, temp_op.object, 0); + + result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++; + if (is_single != 0) + opcode = PC_FSUBS; + else + opcode = PC_FSUB; + emitpcode(opcode, result_reg, work_reg, const_reg); + + op->optype = OpndType_FPR; + op->reg = result_reg; +} + +void convert_floating_to_integer(Operand *op, short output_reg) { + Operand temp_op; + int tmp_reg; + int result_reg; + + symbol_operand(&temp_op, maketemporary(TYPE(&stdouble))); + coerce_to_addressable(&temp_op); + + tmp_reg = used_virtual_registers[RegClass_FPR]++; + emitpcode(PC_FCTIWZ, tmp_reg, op->reg); + load_store_register(PC_STFD, tmp_reg, temp_op.reg, temp_op.object, 0); + + result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + load_store_register(PC_LWZ, result_reg, temp_op.reg, temp_op.object, low_offset); + + op->optype = OpndType_GPR; + op->reg = result_reg; +} + +void convert_floating_to_unsigned(Operand *op, short output_reg) { + static UInt32 used_regs[RegClassMax] = {0, 0, 0, 2, 0}; + + if (op->reg != 1) + emitpcode(PC_FMR, 1, op->reg); + + branch_subroutine(rt_cvt_fp2unsigned, 0, used_regs); + + op->optype = OpndType_GPR; + op->reg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_MR, op->reg, 3); +} + +void extract_bitfield(Operand *input_op, TypeBitfield *tbitfield, short output_reg, Operand *output_op) { + int r27; + int offset; + int tmp_reg; + int output; + + offset = tbitfield->bitlength; + output = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; + r27 = tbitfield->offset + (32 - (tbitfield->bitfieldtype->size * 8)); + if (is_unsigned(tbitfield->bitfieldtype)) { + emitpcode(PC_RLWINM, output, input_op->reg, (r27 + offset) & 31, 32 - offset, 31); + } else if (r27 == 0) { + emitpcode(PC_SRAWI, output, input_op->reg, 32 - offset); + } else { + tmp_reg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_RLWINM, tmp_reg, input_op->reg, r27 & 31, 0, offset); + emitpcode(PC_SRAWI, output, tmp_reg, 32 - offset); + } + + output_op->optype = OpndType_GPR; + output_op->reg = output; +} + +void insert_bitfield(short reg, Operand *op, TypeBitfield *tbitfield) { + int offset = tbitfield->bitlength; + int r7 = tbitfield->offset + (32 - (tbitfield->bitfieldtype->size * 8)); + emitpcode(PC_RLWIMI, op->reg, reg, 32 - (r7 + offset), r7, r7 + offset - 1); +} + +void load_address(short dest_reg, Operand *op) { + coerce_to_addressable(op); + if (op->optype == OpndType_IndirectGPR_ImmOffset) { + if (!op->immOffset && !op->object) { + if (op->reg != dest_reg) + emitpcode(PC_MR, dest_reg, op->reg); + } else { + add_immediate(dest_reg, op->reg, op->object, (SInt16) op->immOffset); + } + } else if (op->optype == OpndType_IndirectGPR_Indexed) { + emitpcode(PC_ADD, dest_reg, op->reg, op->regOffset); + } else { + CError_FATAL(1849); + } +} diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeAssembly.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeAssembly.c new file mode 100644 index 0000000..368f8c5 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeAssembly.c @@ -0,0 +1,1613 @@ +#include "compiler/PCodeAssembly.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CodeGen.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/PCodeListing.h" +#include "compiler/PPCError.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/TOC.h" +#include "compiler/objects.h" + +static UInt32 codebase; + +static SInt32 pcode_update_mem_labeldiff_imm(PCode *instr, const PCodeArg *op, WeirdOperand *wop) { + SInt32 offset; + Object *object; + UInt8 arg; + + if (op->kind == PCOp_MEMORY) { + object = op->data.mem.obj; + offset = op->data.mem.offset; + switch (object->datatype) { + case DLOCAL: + switch ((UInt8) op->arg) { + case RefType_1: + offset += local_offset_16(object); + break; + case RefType_D: + offset = local_offset_lo(object, offset); + break; + case RefType_C: + offset = local_offset_ha(object, offset); + break; + default: + CError_FATAL(83); + } + break; + case DDATA: + case DFUNC: + case DVFUNC: + case DNONLAZYPTR: + switch ((UInt8) op->arg) { + case RefType_6: + wop->type = MW_RELOC_5_LO16; + break; + case RefType_2: + wop->type = MW_RELOC_3; + break; + case RefType_3: + wop->type = MW_RELOC_4; + break; + case RefType_8: + wop->type = MW_RELOC_7_HA16; + break; + case RefType_7: + wop->type = MW_RELOC_6_HI16; + break; + default: + CError_FATAL(135); + } + + wop->x2 = object; + CError_ASSERT(144, offset == 0); + break; + default: + CError_FATAL(164); + } + } else if (op->kind == PCOp_LABELDIFF) { + arg = op->arg; + + offset = op->data.labeldiff.labelA->block->codeOffset - op->data.labeldiff.labelB->block->codeOffset; + offset += op->data.labeldiff.offset; + if (arg == 1) + offset = -offset; + + if (offset > 0x7FFF) + PPCError_Error(PPCErrorStr109); + else if (offset < -0x8000) + PPCError_Error(PPCErrorStr109); + } else if (op->kind == PCOp_IMMEDIATE) { + offset = op->data.imm.value; + } else { + CError_FATAL(193); + } + + return offset; +} + +UInt32 assemblepcode(PCode *instr, UInt32 offset, WeirdOperand *wop) { + UInt32 bits; + + bits = opcodeinfo[instr->op].insn; + wop->type = -1; + wop->x6 = 0; + + switch (instr->op) { + case PC_BL: { + int flag = PCODE_FLAG_SET_T(instr) & fAbsolute; + if (instr->args[0].kind == PCOp_MEMORY) { + bits |= instr->args[0].data.mem.offset & 0x3FFFFFC; + wop->type = MW_RELOC_2_BR24; + wop->x2 = instr->args[0].data.mem.obj; + if (flag == 0) + wop->type = MW_RELOC_2_BR24; + else + CError_FATAL(246); + } else if (instr->args[0].kind == PCOp_IMMEDIATE) { + bits |= instr->args[0].data.imm.value & 0x3FFFFFC; + if (flag) + bits |= 2; + } else { + bits |= (instr->args[0].data.label.label->block->codeOffset - offset) & 0x3FFFFFC; + if (flag) + CError_FATAL(261); + } + break; + } + + case PC_B: { + int flag = PCODE_FLAG_SET_T(instr) & fAbsolute; + if (instr->args[0].kind == PCOp_MEMORY) { + bits |= instr->args[0].data.mem.offset & 0x3FFFFFC; + wop->x2 = instr->args[0].data.mem.obj; + if (flag == 0) + wop->type = MW_RELOC_2_BR24; + else + CError_FATAL(288); + } else if (instr->args[0].kind == PCOp_IMMEDIATE) { + bits |= instr->args[0].data.imm.value & 0x3FFFFFC; + if (flag) + bits |= 2; + } else { + bits |= (instr->args[0].data.label.label->block->codeOffset - offset) & 0x3FFFFFC; + if (flag) + CError_FATAL(302); + } + if (PCODE_FLAG_SET_T(instr) & fLink) + bits |= 1; + break; + } + + case PC_BDNZ: + case PC_BDZ: { + int flag = PCODE_FLAG_SET_T(instr) & fAbsolute; + if (instr->args[0].kind == PCOp_MEMORY) { + bits |= instr->args[0].data.mem.offset & 0xFFFC; + wop->x2 = instr->args[0].data.mem.obj; + if (flag == 0) + wop->type = MW_RELOC_8; + else + CError_FATAL(333); + } else { + SInt32 value; + if (instr->args[0].kind == PCOp_IMMEDIATE) + value = instr->args[0].data.imm.value; + else + value = instr->args[0].data.label.label->block->codeOffset - offset; + + bits |= value & 0xFFFF; + if (value < 0) { + if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken) + bits |= 0x200000u; + } else { + if (PCODE_FLAG_SET_T(instr) & fBranchTaken) + bits |= 0x200000u; + } + } + if (PCODE_FLAG_SET_T(instr) & fLink) + bits |= 1; + break; + } + + case PC_BC: { + int flag = PCODE_FLAG_SET_T(instr) & fAbsolute; + bits |= (instr->args[0].data.imm.value & 31) << 21; + bits |= ((instr->args[1].data.reg.reg * 4 + instr->args[2].data.imm.value) & 31) << 16; + + if (instr->args[3].kind == PCOp_MEMORY) { + bits |= instr->args[3].data.mem.offset & 0xFFFC; + wop->x2 = instr->args[3].data.mem.obj; + if (flag == 0) + wop->type = MW_RELOC_8; + else + CError_FATAL(387); + } else { + SInt32 value; + if (instr->args[3].kind == PCOp_IMMEDIATE) + value = instr->args[3].data.imm.value; + else + value = instr->args[3].data.label.label->block->codeOffset - offset; + + bits |= value & 0xFFFF; + if (value < 0) { + if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken) + bits |= 0x200000u; + } else { + if (PCODE_FLAG_SET_T(instr) & fBranchTaken) + bits |= 0x200000u; + } + } + if (PCODE_FLAG_SET_T(instr) & fLink) + bits |= 1; + break; + } + + case PC_BT: + case PC_BF: + case PC_BDNZT: + case PC_BDNZF: + case PC_BDZT: + case PC_BDZF: { + int flag = PCODE_FLAG_SET_T(instr) & fAbsolute; + bits |= ((instr->args[0].data.reg.reg * 4 + instr->args[1].data.imm.value) & 31) << 16; + + if (instr->args[2].kind == PCOp_MEMORY) { + bits |= instr->args[2].data.mem.offset & 0xFFFC; + wop->x2 = instr->args[2].data.mem.obj; + if (flag == 0) + wop->type = MW_RELOC_8; + else + CError_FATAL(446); + } else { + SInt32 value; + if (instr->args[2].kind == PCOp_IMMEDIATE) { + value = instr->args[2].data.imm.value; + if (flag) + bits |= 2; + } else { + value = instr->args[2].data.label.label->block->codeOffset - offset; + CError_ASSERT(458, !flag); + } + + bits |= value & 0xFFFF; + + if (value < 0) { + if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken) + bits |= 0x200000u; + } else { + if (PCODE_FLAG_SET_T(instr) & fBranchTaken) + bits |= 0x200000u; + } + } + + if (PCODE_FLAG_SET_T(instr) & fLink) + bits |= 1; + break; + } + + case PC_BTLR: + case PC_BTCTR: + case PC_BFLR: + case PC_BFCTR: + bits |= ((instr->args[0].data.reg.reg * 4 + instr->args[1].data.imm.value) & 31) << 16; + if (PCODE_FLAG_SET_T(instr) & fLink) + bits |= 1; + if (PCODE_FLAG_SET_T(instr) & fBranchTaken) + bits |= 0x200000u; + break; + + case PC_BCLR: + case PC_BCCTR: + bits |= instr->args[0].data.imm.value << 21; + bits |= ((instr->args[1].data.reg.reg * 4 + instr->args[2].data.imm.value) & 31) << 16; + case PC_BLR: + case PC_BCTR: + case PC_BCTRL: + case PC_BLRL: + if (PCODE_FLAG_SET_T(instr) & fLink) + bits |= 1; + if (PCODE_FLAG_SET_T(instr) & fBranchTaken) + bits |= 0x200000u; + break; + + case PC_CRAND: + case PC_CRANDC: + case PC_CREQV: + case PC_CRNAND: + case PC_CRNOR: + case PC_CROR: + case PC_CRORC: + case PC_CRXOR: + bits |= ((instr->args[0].data.reg.reg * 4 + instr->args[1].data.imm.value) & 31) << 21; + bits |= ((instr->args[2].data.reg.reg * 4 + instr->args[3].data.imm.value) & 31) << 16; + bits |= ((instr->args[4].data.reg.reg * 4 + instr->args[5].data.imm.value) & 31) << 11; + break; + + case PC_MCRF: + bits |= instr->args[0].data.reg.reg << 23; + bits |= instr->args[1].data.reg.reg << 18; + break; + + case PC_LBZ: + case PC_LBZU: + case PC_LHZ: + case PC_LHZU: + case PC_LHA: + case PC_LHAU: + case PC_LWZ: + case PC_LWZU: + case PC_LMW: + case PC_STB: + case PC_STBU: + case PC_STH: + case PC_STHU: + case PC_STW: + case PC_STWU: + case PC_STMW: + case PC_LFS: + case PC_LFSU: + case PC_LFD: + case PC_LFDU: + case PC_STFS: + case PC_STFSU: + case PC_STFD: + case PC_STFDU: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF; + break; + + case PC_LBZX: + case PC_LBZUX: + case PC_LHZX: + case PC_LHZUX: + case PC_LHAX: + case PC_LHAUX: + case PC_LHBRX: + case PC_LWZX: + case PC_LWZUX: + case PC_LWBRX: + case PC_STBX: + case PC_STBUX: + case PC_STHX: + case PC_STHUX: + case PC_STHBRX: + case PC_STWX: + case PC_STWUX: + case PC_STWBRX: + case PC_LFSX: + case PC_LFSUX: + case PC_LFDX: + case PC_LFDUX: + case PC_STFSX: + case PC_STFSUX: + case PC_STFDX: + case PC_STFDUX: + case PC_LWARX: + case PC_LSWX: + case PC_STFIWX: + case PC_STSWX: + case PC_STWCX: + case PC_ECIWX: + case PC_ECOWX: + case PC_DCREAD: + case PC_TLBSX: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_DCBF: + case PC_DCBST: + case PC_DCBT: + case PC_DCBTST: + case PC_DCBZ: + case PC_DCBI: + case PC_ICBI: + case PC_DCCCI: + case PC_ICBT: + case PC_ICCCI: + case PC_ICREAD: + case PC_DCBA: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 11; + break; + + case PC_ADD: + case PC_ADDC: + case PC_ADDE: + case PC_DIVW: + case PC_DIVWU: + case PC_MULHW: + case PC_MULHWU: + case PC_MULLW: + case PC_SUBF: + case PC_SUBFC: + case PC_SUBFE: + bits |= instr->args[2].data.reg.reg << 11; + case PC_ADDME: + case PC_ADDZE: + case PC_NEG: + case PC_SUBFME: + case PC_SUBFZE: + case PC_MFROM: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + if (PCODE_FLAG_SET_F(instr) & fOverflow) + bits |= 0x400; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_ADDI: + case PC_ADDIC: + case PC_ADDICR: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF; + break; + + case PC_ADDIS: + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[0].data.reg.reg << 21; + bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF; + break; + + case PC_MULLI: + case PC_SUBFIC: + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[2].data.imm.value & 0xFFFF; + break; + + case PC_LI: + case PC_LIS: + bits |= instr->args[0].data.reg.reg << 21; + bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[1], wop) & 0xFFFF; + break; + + case PC_ANDI: + case PC_ANDIS: + case PC_ORI: + case PC_ORIS: + case PC_XORI: + case PC_XORIS: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 21; + bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF; + break; + + case PC_AND: + case PC_OR: + case PC_XOR: + case PC_NAND: + case PC_NOR: + case PC_EQV: + case PC_ANDC: + case PC_ORC: + case PC_SLW: + case PC_SRW: + case PC_SRAW: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 21; + bits |= instr->args[2].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_EXTSH: + case PC_EXTSB: + case PC_CNTLZW: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 21; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_MR: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_NOT: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_SRAWI: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 21; + bits |= (instr->args[2].data.imm.value & 31) << 11; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_RLWINM: + case PC_RLWIMI: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 21; + bits |= (instr->args[2].data.imm.value & 31) << 11; + bits |= (instr->args[3].data.imm.value & 31) << 6; + bits |= (instr->args[4].data.imm.value & 31) << 1; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_RLWNM: + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 21; + bits |= instr->args[2].data.reg.reg << 11; + bits |= (instr->args[3].data.imm.value & 31) << 6; + bits |= (instr->args[4].data.imm.value & 31) << 1; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_CMP: + case PC_CMPL: + bits |= instr->args[0].data.reg.reg << 23; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + break; + + case PC_CMPI: + case PC_CMPLI: + bits |= instr->args[0].data.reg.reg << 23; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.imm.value & 0xFFFF; + break; + + case PC_MTXER: + case PC_MTCTR: + case PC_MTLR: + case PC_MTMSR: + case PC_MFMSR: + case PC_MFXER: + case PC_MFCTR: + case PC_MFLR: + case PC_MFCR: + bits |= instr->args[0].data.reg.reg << 21; + break; + + case PC_MFFS: + bits |= instr->args[0].data.reg.reg << 21; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_MTCRF: + bits |= instr->args[0].data.imm.value << 12; + bits |= instr->args[1].data.reg.reg << 21; + break; + + case PC_MTFSF: + bits |= (instr->args[0].data.imm.value & 0xFF) << 17; + bits |= instr->args[1].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_FMR: + case PC_FABS: + case PC_FNEG: + case PC_FNABS: + case PC_FRES: + case PC_FRSQRTE: + case PC_FRSP: + case PC_FCTIW: + case PC_FCTIWZ: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_FADD: + case PC_FADDS: + case PC_FSUB: + case PC_FSUBS: + case PC_FDIV: + case PC_FDIVS: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_FMADD: + case PC_FMADDS: + case PC_FMSUB: + case PC_FMSUBS: + case PC_FNMADD: + case PC_FNMADDS: + case PC_FNMSUB: + case PC_FNMSUBS: + case PC_FSEL: + bits |= instr->args[3].data.reg.reg << 11; + case PC_FMUL: + case PC_FMULS: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 6; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_FCMPU: + case PC_FCMPO: + bits |= instr->args[0].data.reg.reg << 23; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + break; + + case PC_MTSPR: + if (instr->args[0].kind == PCOp_REGISTER) { + CError_ASSERT(1027, instr->args[0].arg == RegClass_SPR); + CError_ASSERT(1028, instr->args[0].data.reg.reg < 4); + bits |= ((spr_to_sysreg[instr->args[0].data.reg.reg] & 0x1F) << 16) + + ((spr_to_sysreg[instr->args[0].data.reg.reg] & 0x3E0) << 6); + } else if (instr->args[0].kind == PCOp_SYSREG && instr->args[0].arg == 0) { + bits |= ((instr->args[0].data.reg.reg & 0x1F) << 16) + + ((instr->args[0].data.reg.reg & 0x3E0) << 6); + } else { + CError_FATAL(1033); + } + + bits |= instr->args[1].data.reg.reg << 21; + break; + + case PC_MTDCR: + if (instr->args[0].kind == PCOp_IMMEDIATE) { + bits |= ((instr->args[0].data.imm.value & 0x1F) << 16) + + ((instr->args[0].data.imm.value & 0x3E0) << 6); + } else { + CError_FATAL(1042); + } + + bits |= instr->args[1].data.reg.reg << 21; + break; + + case PC_MFSPR: + bits |= instr->args[0].data.reg.reg << 21; + + if (instr->args[1].kind == PCOp_REGISTER && instr->args[1].arg == RegClass_SPR) { + CError_ASSERT(1055, instr->args[1].data.reg.reg < 4); + bits |= ((spr_to_sysreg[instr->args[1].data.reg.reg] & 0x1F) << 16) + + ((spr_to_sysreg[instr->args[1].data.reg.reg] & 0x3E0) << 6); + } else if (instr->args[1].kind == PCOp_SYSREG && instr->args[1].arg == 0) { + bits |= ((instr->args[1].data.reg.reg & 0x1F) << 16) + + ((instr->args[1].data.reg.reg & 0x3E0) << 6); + } else { + CError_FATAL(1060); + } + break; + + case PC_MFDCR: + bits |= instr->args[0].data.reg.reg << 21; + + if (instr->args[1].kind == PCOp_IMMEDIATE) { + bits |= ((instr->args[1].data.imm.value & 0x1F) << 16) + + ((instr->args[1].data.imm.value & 0x3E0) << 6); + } else { + CError_FATAL(1069); + } + break; + + case PC_LSWI: + case PC_STSWI: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= (instr->args[2].data.imm.value & 31) << 11; + break; + + case PC_MCRFS: + bits |= (instr->args[1].data.imm.value & 7) << 18; + case PC_MCRXR: + bits |= instr->args[0].data.reg.reg << 23; + break; + + case PC_MFTB: + bits |= instr->args[0].data.reg.reg << 21; + if (instr->args[1].kind == PCOp_SYSREG && instr->args[1].arg == 0) { + if (instr->args[1].data.reg.reg == 284) + bits |= 0xC4000u; + else if (instr->args[1].data.reg.reg == 285) + bits |= 0xD4000u; + else + CError_FATAL(1100); + } else { + CError_FATAL(1103); + } + break; + + case PC_MTSR: + bits |= instr->args[1].data.reg.reg << 21; + bits |= (instr->args[0].data.imm.value & 15) << 16; + break; + + case PC_MFSR: + bits |= instr->args[0].data.reg.reg << 21; + bits |= (instr->args[1].data.imm.value & 15) << 16; + break; + + case PC_MFSRIN: + case PC_MTSRIN: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 11; + break; + + case PC_MTFSB0: + case PC_MTFSB1: + bits |= (instr->args[0].data.imm.value & 31) << 21; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_MTFSFI: + bits |= instr->args[0].data.reg.reg << 23; + bits |= (instr->args[1].data.imm.value & 15) << 12; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_FSQRT: + case PC_FSQRTS: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_TLBIE: + case PC_TLBLD: + case PC_TLBLI: + bits |= instr->args[0].data.reg.reg << 11; + break; + + case PC_TW: + bits |= (instr->args[0].data.imm.value & 31) << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + break; + + case PC_TWI: + bits |= (instr->args[0].data.imm.value & 31) << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.imm.value & 0xFFFF; + break; + + case PC_OPWORD: + CError_ASSERT(1176, instr->args[0].kind != PCOp_MEMORY); + bits = pcode_update_mem_labeldiff_imm(instr, &instr->args[0], wop); + break; + + case PC_MASKG: + case PC_MASKIR: + bits |= instr->args[1].data.reg.reg << 21; + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_LSCBX: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_DIV: + case PC_DIVS: + case PC_DOZ: + case PC_MUL: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fOverflow) + bits |= 0x400; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_NABS: + case PC_ABS: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + if (PCODE_FLAG_SET_F(instr) & fOverflow) + bits |= 0x400; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_CLCS: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_DOZI: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.imm.value & 0xFFFF; + break; + + case PC_RLMI: + bits |= instr->args[1].data.reg.reg << 21; + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + bits |= (instr->args[3].data.imm.value & 31) << 6; + bits |= (instr->args[4].data.imm.value & 31) << 1; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_SLE: + case PC_SLEQ: + case PC_SLLQ: + case PC_SLQ: + case PC_SRAQ: + case PC_SRE: + case PC_SREA: + case PC_SREQ: + case PC_SRLQ: + case PC_SRQ: + case PC_RRIB: + bits |= instr->args[1].data.reg.reg << 21; + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_SLIQ: + case PC_SLLIQ: + case PC_SRAIQ: + case PC_SRIQ: + case PC_SRLIQ: + bits |= instr->args[1].data.reg.reg << 21; + bits |= instr->args[0].data.reg.reg << 16; + bits |= (instr->args[2].data.imm.value & 31) << 11; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 1; + break; + + case PC_TLBRE: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= (instr->args[2].data.imm.value & 1) << 11; + break; + + case PC_TLBWE: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= (instr->args[2].data.imm.value & 1) << 11; + break; + + case PC_WRTEE: + bits |= instr->args[0].data.reg.reg << 21; + break; + + case PC_WRTEEI: + bits |= instr->args[0].data.imm.value << 15; + break; + + case PC_DSTT: + case PC_DSTSTT: + bits |= 0x2000000u; + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 11; + bits |= (instr->args[2].data.imm.value & 3) << 21; + break; + + case PC_DST: + case PC_DSTST: + bits |= (instr->args[3].data.imm.value & 1) << 25; + bits |= instr->args[0].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 11; + bits |= (instr->args[2].data.imm.value & 3) << 21; + break; + + case PC_DSSALL: + bits |= 0x2000000u; + break; + + case PC_DSS: + bits |= (instr->args[1].data.imm.value & 1) << 25; + bits |= (instr->args[0].data.imm.value & 3) << 21; + break; + + case PC_LVEBX: + case PC_LVEHX: + case PC_LVEWX: + case PC_LVSL: + case PC_LVSR: + case PC_LVX: + case PC_LVXL: + case PC_STVEBX: + case PC_STVEHX: + case PC_STVEWX: + case PC_STVX: + case PC_STVXL: + case PC_VADDCUW: + case PC_VADDFP: + case PC_VADDSBS: + case PC_VADDSHS: + case PC_VADDSWS: + case PC_VADDUBM: + case PC_VADDUBS: + case PC_VADDUHM: + case PC_VADDUHS: + case PC_VADDUWM: + case PC_VADDUWS: + case PC_VAND: + case PC_VANDC: + case PC_VAVGSB: + case PC_VAVGSH: + case PC_VAVGSW: + case PC_VAVGUB: + case PC_VAVGUH: + case PC_VAVGUW: + case PC_VMAXFP: + case PC_VMAXSB: + case PC_VMAXSH: + case PC_VMAXSW: + case PC_VMAXUB: + case PC_VMAXUH: + case PC_VMAXUW: + case PC_VMINFP: + case PC_VMINSB: + case PC_VMINSH: + case PC_VMINSW: + case PC_VMINUB: + case PC_VMINUH: + case PC_VMINUW: + case PC_VMRGHB: + case PC_VMRGHH: + case PC_VMRGHW: + case PC_VMRGLB: + case PC_VMRGLH: + case PC_VMRGLW: + case PC_VMULESB: + case PC_VMULESH: + case PC_VMULEUB: + case PC_VMULEUH: + case PC_VMULOSB: + case PC_VMULOSH: + case PC_VMULOUB: + case PC_VMULOUH: + case PC_VNOR: + case PC_VOR: + case PC_VPKPX: + case PC_VPKSHSS: + case PC_VPKSHUS: + case PC_VPKSWSS: + case PC_VPKSWUS: + case PC_VPKUHUM: + case PC_VPKUHUS: + case PC_VPKUWUM: + case PC_VPKUWUS: + case PC_VRLB: + case PC_VRLH: + case PC_VRLW: + case PC_VSL: + case PC_VSLB: + case PC_VSLH: + case PC_VSLO: + case PC_VSLW: + case PC_VSR: + case PC_VSRAB: + case PC_VSRAH: + case PC_VSRAW: + case PC_VSRB: + case PC_VSRH: + case PC_VSRO: + case PC_VSRW: + case PC_VSUBCUW: + case PC_VSUBFP: + case PC_VSUBSBS: + case PC_VSUBSHS: + case PC_VSUBSWS: + case PC_VSUBUBM: + case PC_VSUBUBS: + case PC_VSUBUHM: + case PC_VSUBUHS: + case PC_VSUBUWM: + case PC_VSUBUWS: + case PC_VSUMSWS: + case PC_VSUM2SWS: + case PC_VSUM4SBS: + case PC_VSUM4SHS: + case PC_VSUM4UBS: + case PC_VXOR: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + break; + + case PC_VCFSX: + case PC_VCFUX: + case PC_VCTSXS: + case PC_VCTUXS: + case PC_VSPLTB: + case PC_VSPLTH: + case PC_VSPLTW: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 11; + bits |= (instr->args[2].data.imm.value & 31) << 16; + break; + + case PC_VEXPTEFP: + case PC_VLOGEFP: + case PC_VREFP: + case PC_VRFIM: + case PC_VRFIN: + case PC_VRFIP: + case PC_VRFIZ: + case PC_VRSQRTEFP: + case PC_VUPKHPX: + case PC_VUPKHSB: + case PC_VUPKHSH: + case PC_VUPKLPX: + case PC_VUPKLSB: + case PC_VUPKLSH: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 11; + break; + + case PC_VCMPBFP: + case PC_VCMPEQFP: + case PC_VCMPEQUB: + case PC_VCMPEQUH: + case PC_VCMPEQUW: + case PC_VCMPGEFP: + case PC_VCMPGTFP: + case PC_VCMPGTSB: + case PC_VCMPGTSH: + case PC_VCMPGTSW: + case PC_VCMPGTUB: + case PC_VCMPGTUH: + case PC_VCMPGTUW: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + bits |= 0x400; + break; + + case PC_VSPLTISB: + case PC_VSPLTISH: + case PC_VSPLTISW: + bits |= instr->args[0].data.reg.reg << 21; + bits |= (instr->args[1].data.imm.value & 31) << 16; + break; + + case PC_VMHADDSHS: + case PC_VMHRADDSHS: + case PC_VMLADDUHM: + case PC_VMSUMMBM: + case PC_VMSUMSHM: + case PC_VMSUMSHS: + case PC_VMSUMUBM: + case PC_VMSUMUHM: + case PC_VMSUMUHS: + case PC_VPERM: + case PC_VSEL: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + bits |= instr->args[3].data.reg.reg << 6; + break; + + case PC_VMADDFP: + case PC_VNMSUBFP: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 6; + bits |= instr->args[3].data.reg.reg << 11; + break; + + case PC_VSLDOI: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[2].data.reg.reg << 11; + bits |= (instr->args[3].data.imm.value & 15) << 6; + break; + + case PC_VMR: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 11; + break; + + case PC_VMRP: + bits |= instr->args[0].data.reg.reg << 21; + bits |= instr->args[1].data.reg.reg << 16; + bits |= instr->args[1].data.reg.reg << 11; + break; + + case PC_MFVSCR: + bits |= instr->args[0].data.reg.reg << 21; + break; + + case PC_MTVSCR: + bits |= instr->args[0].data.reg.reg << 11; + break; + + case PC_EIEIO: + case PC_ISYNC: + case PC_SYNC: + case PC_RFI: + case PC_NOP: + case PC_SC: + case PC_TLBIA: + case PC_TLBSYNC: + case PC_TRAP: + case PC_DSA: + case PC_ESA: + case PC_RFCI: + break; + + default: + CError_FATAL(2203); + } + + return CTool_EndianConvertWord32(bits); +} + +static PCode *targetinstruction(PCodeLabel *label) { + PCodeBlock *block = label->block; + while (block->pcodeCount == 0) + block = block->nextBlock; + return block->firstPCode; +} + +static void invertybit(PCode *instr, SInt32 value) { + if (instr->op == PC_BC) { + if (instr->args[0].data.imm.value & 1) { + if (value < 0) + instr->flags |= fBranchNotTaken; + else + instr->flags |= fBranchTaken; + } + } else if (instr->op == PC_BCCTR || instr->op == PC_BCLR) { + if (instr->args[0].data.imm.value & 1) + instr->flags |= fBranchTaken; + } + + if (PCODE_FLAG_SET_T(instr) & fBranchTaken) + instr->flags = (instr->flags & ~fBranchTaken) | fBranchNotTaken; + else if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken) + instr->flags = (instr->flags & ~fBranchNotTaken) | fBranchTaken; + else if (value < 0) + instr->flags = (instr->flags & ~fBranchTaken) | fBranchNotTaken; + else + instr->flags = (instr->flags & ~fBranchNotTaken) | fBranchTaken; +} + +static void insertlongbranches(SInt32 mask) { + PCodeBlock *block; + PCodeLabel *label; + SInt32 i; + + i = 0; + for (block = pcbasicblocks; block; block = block->nextBlock) { + block->codeOffset = i; + if (block->pcodeCount) { + i += block->pcodeCount * 4; + if (block->pcodeCount && (block->lastPCode->flags & fIsBranch)) + i += 4; + } + } + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (block->pcodeCount && (block->lastPCode->flags & fIsBranch)) { + switch (block->lastPCode->op) { + case PC_BT: + case PC_BF: + i = block->codeOffset + ((block->pcodeCount - 1) * 4); + if (block->lastPCode->args[2].kind == PCOp_LABEL) { + label = block->lastPCode->args[2].data.label.label; + i = label->block->codeOffset - i; + if (i != ((SInt16) (i & mask))) { + block->lastPCode->op = (block->lastPCode->op == PC_BT) ? PC_BF : PC_BT; + block->lastPCode->args[2].data.label.label = block->nextBlock->labels; + invertybit(block->lastPCode, i); + appendpcode(block, makepcode(PC_B, label)); + } + } + break; + + case PC_BC: + i = block->codeOffset + ((block->pcodeCount - 1) * 4); + if (block->lastPCode->args[3].kind == PCOp_LABEL) { + label = block->lastPCode->args[3].data.label.label; + i = label->block->codeOffset - i; + invertybit(block->lastPCode, i); + if (i != ((SInt16) (i & mask))) { + switch (block->lastPCode->args[0].data.imm.value & 30) { + case 0: + case 2: + case 8: + case 10: + block->lastPCode->args[0].data.imm.value ^= 11; + block->lastPCode->args[3].data.label.label = block->nextBlock->labels; + break; + case 16: + case 18: + block->lastPCode->args[0].data.imm.value ^= 3; + block->lastPCode->args[3].data.label.label = block->nextBlock->labels; + break; + case 4: + case 12: + block->lastPCode->args[0].data.imm.value ^= 9; + block->lastPCode->args[3].data.label.label = block->nextBlock->labels; + break; + case 20: + deletepcode(block->lastPCode); + break; + default: + CError_FATAL(2368); + } + + appendpcode(block, makepcode(PC_B, label)); + } + } + break; + + case PC_BDNZ: + case PC_BDZ: + i = block->codeOffset + ((block->pcodeCount - 1) * 4); + if (block->lastPCode->args[0].kind == PCOp_LABEL) { + label = block->lastPCode->args[0].data.label.label; + i = label->block->codeOffset - i; + if (i != ((SInt16) (i & mask))) { + switch (block->lastPCode->op) { + case PC_BDZ: + block->lastPCode->op = PC_BDNZ; + break; + case PC_BDNZ: + block->lastPCode->op = PC_BDZ; + break; + default: + CError_FATAL(2389); + } + + block->lastPCode->args[0].data.label.label = block->nextBlock->labels; + invertybit(block->lastPCode, i); + appendpcode(block, makepcode(PC_B, label)); + } + } + break; + + case PC_BDNZT: + case PC_BDNZF: + case PC_BDZT: + case PC_BDZF: + i = block->codeOffset + ((block->pcodeCount - 1) * 4); + if (block->lastPCode->args[2].kind == PCOp_LABEL) { + label = block->lastPCode->args[2].data.label.label; + i = label->block->codeOffset - i; + if (i != ((SInt16) (i & mask))) { + switch (block->lastPCode->op) { + case PC_BDNZT: + block->lastPCode->op = PC_BDZF; + break; + case PC_BDNZF: + block->lastPCode->op = PC_BDZT; + break; + case PC_BDZT: + block->lastPCode->op = PC_BDNZF; + break; + case PC_BDZF: + block->lastPCode->op = PC_BDNZT; + break; + default: + CError_FATAL(2420); + } + + block->lastPCode->args[2].data.label.label = block->nextBlock->labels; + invertybit(block->lastPCode, i); + appendpcode(block, makepcode(PC_B, label)); + } + } + break; + + } + } + } +} + +SInt32 optimizefinalbranches(SInt32 codesize) { + PCodeBlock *block; + PCode *instr; + SInt32 offset; + int changed; + int deleted; + PCodeLabel *label; + PCode *target; + + do { + changed = deleted = 0; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (block->pcodeCount == 0) + continue; + + instr = block->lastPCode; + if (!(instr->flags & fIsBranch)) + continue; + + offset = block->codeOffset + (block->pcodeCount - 1) * 4; + + if (instr->op == PC_B && instr->args[0].kind == PCOp_LABEL) { + label = instr->args[0].data.label.label; + target = targetinstruction(label); + + if (label->block->codeOffset == (offset + 4)) { + deletepcode(instr); + changed = deleted = 1; + } else if (target->op == PC_B) { + if (target->args[0].kind == PCOp_LABEL && target->args[0].data.label.label != instr->args[0].data.label.label) { + instr->args[0].data.label.label = target->args[0].data.label.label; + changed = 1; + } + } else if (target->op == PC_BLR) { + instr->op = PC_BLR; + changed = 1; + } + continue; + } + + if ((instr->op == PC_BT || instr->op == PC_BF) && instr->args[2].kind == PCOp_LABEL) { + PCodeBlock *block2 = instr->block; + label = instr->args[2].data.label.label; + target = targetinstruction(label); + + if (label->block->codeOffset == (offset + 4)) { + deletepcode(instr); + changed = deleted = 1; + } else if (target->op == PC_B) { + if (target->args[0].kind == PCOp_LABEL && target->args[0].data.label.label != instr->args[2].data.label.label) { + instr->args[2].data.label.label = target->args[0].data.label.label; + changed = 1; + } + } else if (copts.opt_bcc_lr_ctr) { + if (target->op == PC_BLR) { + if (instr->op == PC_BT) + instr->op = PC_BTLR; + else + instr->op = PC_BFLR; + instr->argCount = 2; + changed = 1; + } else if (target->op == PC_BCTR) { + if (instr->op == PC_BT) + instr->op = PC_BTCTR; + else + instr->op = PC_BFCTR; + instr->argCount = 2; + changed = 1; + } else if ( + block2->nextBlock && + block2->nextBlock->firstPCode && + block2->nextBlock->firstPCode->op == PC_BLR && + label->block->codeOffset == (offset + 8) + ) { + if ( + block2->nextBlock->predecessors && + block2->nextBlock->predecessors->block == block2 && + !block2->nextBlock->predecessors->nextLink + ) { + if (instr->op == PC_BT) + instr->op = PC_BFLR; + else + instr->op = PC_BTLR; + change_num_operands(instr, 2); + deletepcode(block2->nextBlock->firstPCode); + changed = deleted = 1; + } + } else if ( + block2->nextBlock && + block2->nextBlock->firstPCode && + block2->nextBlock->firstPCode->op == PC_BCTR && + label->block->codeOffset == (offset + 8) + ) { + if ( + block2->nextBlock->predecessors && + block2->nextBlock->predecessors->block == block2 && + !block2->nextBlock->predecessors->nextLink + ) { + if (instr->op == PC_BT) + instr->op = PC_BFCTR; + else + instr->op = PC_BTCTR; + change_num_operands(instr, 2); + deletepcode(block2->nextBlock->firstPCode); + changed = deleted = 1; + } + } + } + continue; + } + + if ( + instr->op == PC_BC && + instr->args[3].kind == PCOp_LABEL && + !(PCODE_FLAG_SET_T(instr) & (fSideEffects | fLink)) + ) + { + PCodeBlock *block2 = instr->block; + label = instr->args[3].data.label.label; + target = targetinstruction(label); + + if (label->block->codeOffset == (offset + 4)) { + deletepcode(instr); + changed = deleted = 1; + } else if (target->op == PC_B) { + if (target->args[0].kind == PCOp_LABEL && target->args[0].data.label.label != instr->args[3].data.label.label) { + instr->args[3].data.label.label = target->args[0].data.label.label; + changed = 1; + } + } else if (copts.opt_bcc_lr_ctr) { + if (target->op == PC_BLR) { + instr->op = PC_BCLR; + instr->argCount = 3; + changed = 1; + } else if (target->op == PC_BCTR) { + instr->op = PC_BCCTR; + instr->argCount = 3; + changed = 1; + } else if ( + block2->nextBlock && + block2->nextBlock->firstPCode && + block2->nextBlock->firstPCode->op == PC_BLR && + label->block->codeOffset == (offset + 8) + ) { + SInt32 val = instr->args[0].data.imm.value & 30; + if ( + block2->nextBlock->predecessors && + block2->nextBlock->predecessors->block == block2 && + !block2->nextBlock->predecessors->nextLink + ) { + if ((val & 30) == 4) + instr->args[0].data.imm.value = val | 12; + else if ((val & 30) == 12) + instr->args[0].data.imm.value = val & 23; + instr->op = PC_BCLR; + instr->argCount = 3; + deletepcode(block2->nextBlock->firstPCode); + changed = deleted = 1; + } + } else if ( + block2->nextBlock && + block2->nextBlock->firstPCode && + block2->nextBlock->firstPCode->op == PC_BCTR && + label->block->codeOffset == (offset + 8) + ) { + SInt32 val = instr->args[0].data.imm.value & 30; + if ( + block2->nextBlock->predecessors && + block2->nextBlock->predecessors->block == block2 && + !block2->nextBlock->predecessors->nextLink + ) { + if ((val & 30) == 4) + instr->args[0].data.imm.value = val | 12; + else if ((val & 30) == 12) + instr->args[0].data.imm.value = val & 23; + instr->op = PC_BCCTR; + instr->argCount = 3; + deletepcode(block2->nextBlock->firstPCode); + changed = deleted = 1; + } + } + } + } + } + + if (deleted) + codesize = pccomputeoffsets(); + } while (changed); + + return codesize; +} + +static SInt32 insert_align_nops(Object *func, SInt32 codesize) { + PCodeBlock *block; + int changed; + PCodeBlock *prev; + + do { + changed = 0; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if ( + (block->flags & fPCBlockFlag6000) == fPCBlockFlag2000 && + (block->codeOffset & 7) && + block->pcodeCount < 8 && + (prev = block->prevBlock) && + !(prev->flags & fPCBlockFlag2000) + ) + { + if (prev->lastPCode && prev->lastPCode->op == PC_NOP && !(prev->lastPCode->flags & fSideEffects)) { + deletepcode(prev->lastPCode); + } else { + PCode *nop = makepcode(PC_NOP); + nop->flags &= ~fSideEffects; + appendpcode(prev, nop); + } + + codesize = pccomputeoffsets(); + changed = 1; + } + } + + if (changed) { + pclistblocks(CMangler_GetLinkName(func)->name, "AFTER INSERT ALIGN NOPs"); + if (codesize > 32766) { + insertlongbranches(32766); + codesize = pccomputeoffsets(); + } + } + + } while (changed); + + return codesize; +} + +SInt32 assemblefunction(Object *func, EntryPoint *entrypoints) { + void *tbdata; + GList *gl; + PCodeBlock *block; + PCode *instr; + SInt32 offset2; + SInt32 codesize; + SInt32 tbsize; + SInt32 offset; + SectionHandle section; + EntryPoint *ep; + WeirdOperand wop; + + codesize = pccomputeoffsets(); + if (codesize <= 0) + PPCError_Error(PPCErrorStr190, func->name->name); + + if (copts.peephole || copts.optimizationlevel >= 3) + codesize = optimizefinalbranches(codesize); + + if (codesize > 32766) { + insertlongbranches(32766); + codesize = pccomputeoffsets(); + } + + if (copts.function_align > 4) + codesize = insert_align_nops(func, codesize); + + tbsize = 0; + if (copts.traceback) + tbdata = generate_traceback(codesize, CMangler_GetLinkName(func)->name, &tbsize, func); + + if (func->section == SECT_DEFAULT) + func->section = SECT_TEXT; + + offset = tbsize; + section = ObjGen_DeclareCode(func, codesize + tbsize); + gl = ObjGen_GetSectionGList(section); + + codebase = gl->size; + AppendGListNoData(gl, codesize + tbsize); + + if (copts.filesyminfo) { + ObjGen_SymFunc(func); + ObjGen_Line(functionbodyoffset, 0); + ObjGen_DeclareSymInfo(); + } + + if (uses_globals && pic_base_reg) + ObjGen_DeclarePICBase(func, pic_base_pcodelabel->block->codeOffset); + + if (entrypoints) { + for (ep = entrypoints; ep; ep = ep->next) { + ObjGen_DeclareEntry(ep->object, ep->block->codeOffset); + } + } + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (offset2 = block->codeOffset, instr = block->firstPCode; instr; instr = instr->nextPCode, offset2 += 4) { + if (copts.filesyminfo && instr->sourceoffset != -1) + ObjGen_Line(instr->sourceoffset, offset2); + + *((UInt32 *) (*gl->data + codebase + offset2)) = assemblepcode(instr, offset2, &wop); + + if (wop.type != -1) + ObjGen_RelocateObj(section, offset2, wop.x2, wop.type); + } + } + + if (copts.filesyminfo) + ObjGenMach_SymFuncEnd(func, codesize); + + if (copts.traceback) + memcpy(*gl->data + codebase + codesize, tbdata, offset); + + if (copts.traceback) + return codesize + tbsize; + else + return codesize; +} diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeListing.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeListing.c new file mode 100644 index 0000000..7a9fa13 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeListing.c @@ -0,0 +1,536 @@ +#include "compiler/PCodeListing.h" +#include "compiler/CError.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/Alias.h" +#include "compiler/BitVectors.h" +#include "compiler/CompilerTools.h" +#include "compiler/InterferenceGraph.h" +#include "compiler/LiveInfo.h" +#include "compiler/PCode.h" +#include "compiler/PCodeAssembly.h" +#include "compiler/Registers.h" +#include "compiler/Scheduler.h" +#include "compiler/objects.h" + +static FILE *pcfile; +static int ptime; +static int sourcetext; +static int sourcetext_is_main; +static int sourcelength; +int pclist_bad_operand; + +static void formatdataflowset(char *name, UInt32 *vec, UInt32 size, char *format) { + UInt32 i; + UInt32 counter; + char *separator; + + separator = ""; + fprintf(pcfile, "%s = {", name); + + for (i = 0, counter = 0; i < size; i++) { + if (bitvectorgetbit(i, vec)) { + if (i) + fprintf(pcfile, separator); + if (counter++ == 10) { + fprintf(pcfile, "\n\t\t"); + counter = 0; + } + fprintf(pcfile, format, i); + separator = ","; + } + } + + fprintf(pcfile, "}\n"); +} + +static void pclistblock(PCodeBlock *block, char *format, UInt32 vecSize) { + PCLink *link; + PCodeLabel *label; + int cpu; + int chr; + PCode *instr; + int offset; + int latency; + UInt32 opcode; + MachineInfo *mi; + char buf[500]; + WeirdOperand dummyArg; + + fprintf(pcfile, ":{%4.4x}::::::::::::::::::::::::::::::::::::::::LOOPWEIGHT=%" PRId32 "\n", block->flags, block->loopWeight); + fprintf(pcfile, "B%" PRId32 ": ", block->blockIndex); + + fprintf(pcfile, "Successors = { "); + for (link = block->successors; link; link = link->nextLink) { + if (link->block) + fprintf(pcfile, "B%" PRId32 " ", link->block->blockIndex); + } + fprintf(pcfile, "} "); + + fprintf(pcfile, "Predecessors = { "); + for (link = block->predecessors; link; link = link->nextLink) { + if (link->block) + fprintf(pcfile, "B%" PRId32 " ", link->block->blockIndex); + } + + if (block->labels) { + fprintf(pcfile, "} Labels = { "); + for (label = block->labels; label; label = label->nextLabel) + fprintf(pcfile, "L%" PRId32 " ", label->index); + } + + fprintf(pcfile, "}\n\n"); + + cpu = copts.scheduling; + if (cpu == 10) { + mi = &machine7450; + } else if (copts.altivec_model != 0 || cpu == 7) { + mi = &machine7400; + } else if (cpu == 2) { + mi = &machine603; + } else if (cpu == 5) { + mi = &machine603e; + } else if (cpu == 3) { + mi = &machine604; + } else if (cpu == 6) { + mi = &machine604; + } else if (cpu == 4) { + mi = &machine750; + } else if (cpu == 1) { + mi = &machine601; + } else if (cpu == 9) { + mi = &machine821; + } else { + mi = &machine603; + } + + for (offset = block->codeOffset, instr = block->firstPCode; instr; instr = instr->nextPCode, offset += 4) { + latency = mi->latency(instr); + formatoperands(instr, buf, 1); + chr = (PCODE_FLAG_SET_F(instr) & fRecordBit) ? '.' : ' '; + if (coloring) + opcode = 0; + else + opcode = assemblepcode(instr, offset, &dummyArg); + + fprintf( + pcfile, + " %.8" PRIX32 " %.8" PRIX32 " %4" PRId32 " %-7s%c %s\n", + offset, CTool_EndianConvertWord32(opcode), latency, + opcodeinfo[instr->op].name, chr, buf + ); + + if (instr->alias) + dumpalias(instr->alias, 0, 1, 0); + } + + if (vecSize) { + fprintf(pcfile, "............................................................\n"); + formatdataflowset("use", liveinfo[block->blockIndex].use, vecSize, format); + formatdataflowset("def", liveinfo[block->blockIndex].def, vecSize, format); + formatdataflowset("in ", liveinfo[block->blockIndex].in, vecSize, format); + formatdataflowset("out", liveinfo[block->blockIndex].out, vecSize, format); + } + + fflush(pcfile); + + if (pclist_bad_operand) + CError_FATAL(252); +} + +static void pclistonoff(int flag) { + if (flag) + fprintf(pcfile, "On\n"); + else + fprintf(pcfile, "Off\n"); +} + +void pcinitlisting() { + // unknown args, etc +} + +void pccleanuplisting(void) { +#ifdef CW_ENABLE_PCODE_DEBUG + // this code is not based on the original as we don't have it + if (pcfile) { + fclose(pcfile); + pcfile = NULL; + } +#endif +} + +void pclistblocks(char *name1, char *name2) { +#ifdef CW_ENABLE_PCODE_DEBUG + // this code is not based on the original as we don't have it + PCodeBlock *block; + if (copts.debuglisting) { + if (!pcfile) + pcfile = fopen("pcdump.txt", "a"); + + fprintf(pcfile, "\n%s\n%s\n", name1, name2); + for (block = pcbasicblocks; block; block = block->nextBlock) + pclistblock(block, NULL, 0); + } +#endif +} + +void pclistdataflow() { + // unknown args +} + +void pclistinterferences(char *class_format, int regcount) { +} + +void pclistspill() { + // unknown args +} + +void pclistcopypropitem() { + // unknown args +} + +void pclistcoalesce() { + // unknown args +} + +void pclistusedefs() { + // unknown args +} + +void pclistpropinfo() { + // unknown args +} + +static void listloop() { + // unknown args +} + +static void listloops() { + // unknown args +} + +void pclistloops() { + // unknown args +} + +static void listswitchtables() { + // unknown args +} + +void pclistswitchtables() { + // unknown args +} + +void pclistdominators() { + // unknown args +} + +void pclistbackedge() { + // unknown args +} + +static char *GetInterferenceFlags(IGNode *node) { + char *buf; + Boolean first; + + first = 1; + buf = oalloc(512); + buf[0] = 0; + + if (node->flags & fSpilled) { + strcat(buf, "fSpilled"); + first = 0; + } + + if (node->flags & fPushed) { + if (!first) + strcat(buf, "|"); + strcat(buf, "fPushed"); + first = 0; + } + + if (node->flags & fCoalesced) { + if (!first) + strcat(buf, "|"); + strcat(buf, "fCoalesced"); + first = 0; + } + + if (node->flags & fCoalescedInto) { + if (!first) + strcat(buf, "|"); + strcat(buf, "fCoalescedInto"); + first = 0; + } + + if (node->flags & fPairHigh) { + if (!first) + strcat(buf, "|"); + strcat(buf, "fPairHigh"); + first = 0; + } + + if (node->flags & fPairLow) { + if (!first) + strcat(buf, "|"); + strcat(buf, "fPairLow"); + first = 0; + } + + if (!*buf) + strcat(buf, "no_flags"); + + return buf; +} + +void pclistinterferencegraphnode() { + // unknown args +} + +void pclistinterferencegraph() { + // unknown args +} + +void pclistblock_scheduler() { + // unknown args +} + +void pclistblocks_start_scheduler(char *str1, char *str2) { +} + +void pclistblocks_end_scheduler(void) { + if (pclist_bad_operand) + CError_FATAL(1318); +} + +static void printheapsize() { + // unknown args +} + +void pctotalheap() { + // unknown args +} + +void pctotalmemory() { + // unknown args +} + +void pcmessage(char *probably_a_string, ...) { +} + +int formatalias(Alias *alias, char *buf, int bufSize) { + char *name; + char *typestr; + int len; + int len2; + + if (bufSize < 16) + return sprintf(buf, "..."); + + switch (alias->type) { + case AliasType0: + case AliasType1: + name = CMangler_GetLinkName(alias->object)->name; + if (!strlen(name) || name[0] < 0) + CError_FATAL(1458); + + if (strlen(name) + 16 > bufSize) + return sprintf(buf, "..."); + + switch (alias->object->datatype) { + case DNONLAZYPTR: + typestr = "{NL}"; + break; + case DDATA: + typestr = "{RW}"; + break; + case DLOCAL: + typestr = "{SP}"; + break; + default: + typestr = ""; + } + + len = sprintf(buf, "%0.*s%s", bufSize - 20, name, typestr, alias->size); + buf += len; + if (alias->type == AliasType0) + return len; + + if (alias->offset == 0) + len2 = sprintf(buf, ":%d", alias->size); + else if (alias->offset > 0) + len2 = sprintf(buf, "+%d:%d", alias->offset, alias->size); + else + len2 = sprintf(buf, "-%d:%d", -alias->offset, alias->size); + + return len + len2; + + case AliasType2: + len = 0; + + len2 = sprintf(buf, "{"); + buf += len2; + len += len2; + + len2 = sprintf(buf, "*"); + buf += len2; + len += len2; + + len2 = sprintf(buf, "}"); + buf += len2; + len += len2; + return len; + + default: + CError_FATAL(1543); + return 0; + } +} + +int dumpalias(Alias *alias, int len, Boolean flag1, Boolean flag2) { + char *name; + char *typestr; + AliasMember *member; + Boolean notFirst; + + if (!flag2 && alias == worst_case) { + fprintf(pcfile, " ALIAS = {worst_case}"); + if (flag1) + fprintf(pcfile, "\n"); + return 0; + } + + if (flag1) { + if (alias == worst_case) + fprintf(pcfile, "ALIAS worst_case = "); + else + fprintf(pcfile, " ALIAS = "); + } + + switch (alias->type) { + case AliasType0: + case AliasType1: + name = CMangler_GetLinkName(alias->object)->name; + if (!strlen(name) || name[0] < 0) + CError_FATAL(1581); + + switch (alias->object->datatype) { + case DNONLAZYPTR: + typestr = "{NL}"; + break; + case DDATA: + typestr = "{RW}"; + break; + case DLOCAL: + typestr = "{SP}"; + break; + default: + typestr = ""; + } + + len += fprintf(pcfile, "%0.80s%s", name, typestr); + + if (alias->type == AliasType0) { + if (flag1) + fprintf(pcfile, "\n"); + return len; + } + + if (alias->offset == 0) + len += fprintf(pcfile, ":%d", alias->size); + else if (alias->offset > 0) + len += fprintf(pcfile, "+%d:%d", alias->offset, alias->size); + else + len += fprintf(pcfile, "-%d:%d", -alias->offset, alias->size); + + if (flag1) + fprintf(pcfile, "\n"); + + return len; + + case AliasType2: + len += fprintf(pcfile, "{"); + notFirst = 0; + for (member = alias->parents; member; member = member->nextParent) { + if (member->child->type == AliasType0) { + if (notFirst) + len += fprintf(pcfile, ","); + if (len > 60) { + fprintf(pcfile, "\n "); + len = 0; + } + len = dumpalias(member->child, len, 0, 0); + notFirst = 1; + } + } + for (member = alias->parents; member; member = member->nextParent) { + if (member->child->type != AliasType0) { + if (notFirst) + len += fprintf(pcfile, ","); + if (len > 60) { + fprintf(pcfile, "\n "); + len = 0; + } + len = dumpalias(member->child, len, 0, 0); + notFirst = 1; + } + } + + len += fprintf(pcfile, "}"); + if (flag1) + fprintf(pcfile, "\n"); + return len; + + default: + CError_FATAL(1661); + return 0; + } +} + +void pcformatset() { + // unknown args +} + +int GetLineEndOffset(char *str, int lineNum, int len) { + int offset; + char *work; + + offset = GetLineOffset(str, lineNum, len); + if (offset < 0) + return offset; + + work = str + offset; + while (*work) { + if (*work == '\n') + return work - str - 1; + work++; + } + return -1; +} + +int GetLineOffset(char *str, int lineNum, int len) { + char *work = str; + char *end; + + if (lineNum < 0) + return -1; + + end = str + len; + while (work < end) { + if (*work == '\n' && --lineNum <= 0) + return work - str; + work++; + } + + return 0; +} + +void DumpSourceCode() { + // unknown args +} + +int DumpIR_SrcBreak() { + // unknown args + return 0; +} + diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeUtilities.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeUtilities.c new file mode 100644 index 0000000..b1f8ffb --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeUtilities.c @@ -0,0 +1,345 @@ +#include "compiler/PCodeUtilities.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CParser.h" +#include "compiler/CodeGen.h" +#include "compiler/Exceptions.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/Registers.h" +#include "compiler/enode.h" +#include "compiler/objects.h" + +void pcsetrecordbit(PCode *pc) { + int reg; + PCodeArg *arg; + short argCount; + int argIdx; + + pc->flags &= ~(fIsMove | fCommutative | fIsCSE); + if ((pc->flags & fOpTypeMask) == fOpTypeFPR) { + reg = 1; + } else if ((pc->flags & fOpTypeMask) == fOpTypeVR) { + reg = 6; + } else { + reg = 0; + } + + if (pc->op == PC_ANDI || pc->op == PC_ANDIS) { + pc->flags |= fRecordBit; + } else if (pc->op == PC_ADDI || pc->op == PC_ADDIC) { + pc->flags |= fSetsCarry; + pc->flags |= fRecordBit; + change_num_operands(pc, 5); + pc->op = PC_ADDICR; + + CError_ASSERT(76, pc->args[3].kind == PCOp_PLACEHOLDEROPERAND); + pc->args[3].kind = PCOp_REGISTER; + pc->args[3].arg = RegClass_SPR; + pc->args[3].data.reg.reg = 0; + pc->args[3].data.reg.effect = EffectWrite; + CError_ASSERT(80, pc->args[4].kind == PCOp_PLACEHOLDEROPERAND); + pc->args[4].kind = PCOp_REGISTER; + pc->args[4].arg = RegClass_CRFIELD; + pc->args[4].data.reg.reg = reg; + pc->args[4].data.reg.effect = EffectWrite; + } else { + arg = pc->args; + argIdx = argCount = pc->argCount; + while (arg->kind != PCOp_PLACEHOLDEROPERAND && argIdx) { + if (arg->kind == PCOp_REGISTER && arg->arg == RegClass_CRFIELD && arg->data.reg.reg == reg) { + arg->data.reg.effect |= EffectWrite; + pc->flags |= fRecordBit; + return; + } + arg++; + argIdx--; + } + + if (argIdx <= 0) { + arg = &pc->args[argCount]; + pc->argCount++; + } + + CError_ASSERT(105, arg->kind == PCOp_PLACEHOLDEROPERAND); + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_CRFIELD; + arg->data.reg.reg = reg; + arg->data.reg.effect = EffectWrite; + if (pc->op != PC_ADDICR) + pc->flags |= fRecordBit; + } +} + +void pcsetsideeffects(PCode *pc) { + pc->flags &= ~(fIsMove | fCommutative | fIsCSE); + pc->flags |= fSideEffects; +} + +void pcsetlinkbit(PCode *pc) { + PCodeArg *arg; + int argIdx; + + switch (pc->op) { + case PC_B: + pc->op = PC_BL; + break; + case PC_BCTR: + pc->op = PC_BCTRL; + break; + case PC_BLR: + pc->op = PC_BLRL; + break; + } + + arg = pc->args; + argIdx = pc->argCount; + while (arg->kind != PCOp_PLACEHOLDEROPERAND && argIdx) { + if (arg->kind == PCOp_REGISTER && arg->arg == RegClass_SPR && arg->data.reg.reg == 1) { + arg->data.reg.effect |= EffectWrite; + pc->flags |= fLink; + return; + } + arg++; + argIdx--; + } + + CError_ASSERT(169, arg->kind == PCOp_PLACEHOLDEROPERAND); + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_SPR; + arg->data.reg.reg = 1; + arg->data.reg.effect = EffectWrite; + + if (opcodeinfo[pc->op].flags & fIsCall) { + pc->flags &= ~fIsBranch; + pc->flags |= fIsCall; + } + pc->flags |= fLink; +} + +void branch_label(PCodeLabel *label) { + if (pclastblock->pcodeCount) { + pcbranch(pclastblock, label); + makepcblock(); + } + pclabel(pclastblock, label); +} + +void branch_conditional(short a, short compareop, short c, PCodeLabel *label) { + PCodeBlock *tmpblock; + PCodeLabel *tmplabel; + int r28; + + tmpblock = pclastblock; + tmplabel = makepclabel(); + + switch (compareop) { + case ENOTEQU: + c = !c; + case EEQU: + r28 = 2; + break; + case EGREATEREQU: + c = !c; + case ELESS: + r28 = 0; + break; + case ELESSEQU: + c = !c; + case EGREATER: + r28 = 1; + break; + } + + emitpcode(c ? PC_BT : PC_BF, a, r28, label); + pcbranch(pclastblock, label); + pcbranch(pclastblock, tmplabel); + makepcblock(); + pclabel(pclastblock, tmplabel); +} + +void branch_always(PCodeLabel *label) { + emitpcode(PC_B, label); + pcbranch(pclastblock, label); + makepcblock(); +} + +void branch_decrement_always(Opcode opcode, PCodeLabel *label) { + PCodeLabel *tmplabel = makepclabel(); + emitpcode(opcode, label); + pcbranch(pclastblock, label); + pcbranch(pclastblock, tmplabel); + makepcblock(); + pclabel(pclastblock, tmplabel); +} + +void branch_indirect(Object *obj) { + emitpcode(PC_BCTR, obj, 0); + makepcblock(); +} + +int branch_count_volatiles(void) { + int count = 0; + int i; + RegClass rclass; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + for (i = 0; i < n_scratch_registers[rclass]; i++) { + count++; + } + } + + return count; +} + +PCodeArg *branch_record_volatiles(PCodeArg *arglist, UInt32 *masks) { + int i; + RegClass rclass; + + for (rclass = RegClassMax - 1; rclass >= 0; rclass--) { + for (i = 0; i < n_scratch_registers[rclass]; i++) { + arglist->kind = PCOp_REGISTER; + arglist->arg = rclass; + arglist->data.reg.reg = scratch_registers[rclass][i]; + arglist->data.reg.effect = EffectWrite; + if (masks[rclass] & (1 << scratch_registers[rclass][i])) + arglist->data.reg.effect |= EffectRead; + arglist++; + } + } + + return arglist; +} + +void branch_subroutine(Object *obj, short add_nop, UInt32 *masks) { + int count; + PCode *pc; + PCodeArg *arg; + + count = branch_count_volatiles(); + if (copts.exceptions && current_statement) + count += countexceptionactionregisters(current_statement->dobjstack); + + pc = makepcode(PC_BL, count, obj, 0); + arg = branch_record_volatiles(pc->args + 1, masks); + if (copts.exceptions && current_statement) + noteexceptionactionregisters(current_statement->dobjstack, arg); + appendpcode(pclastblock, pc); + + if (add_nop) + emitpcode(PC_NOP); + + branch_label(makepclabel()); + if (copts.exceptions && current_statement) + recordexceptionactions(pc, current_statement->dobjstack); +} + +void branch_subroutine_ctr(UInt32 *masks) { + int count; + PCode *pc; + PCodeArg *arg; + + count = branch_count_volatiles(); + if (copts.exceptions && current_statement) + count += countexceptionactionregisters(current_statement->dobjstack); + + pc = makepcode(PC_BCTRL, count); + arg = branch_record_volatiles(pc->args + 1, masks); + if (copts.exceptions && current_statement) + noteexceptionactionregisters(current_statement->dobjstack, arg); + appendpcode(pclastblock, pc); + + branch_label(makepclabel()); + if (copts.exceptions && current_statement) + recordexceptionactions(pc, current_statement->dobjstack); +} + +void add_immediate(short dest_reg, short base_reg, Object *obj, SInt16 offset) { + short tmp_reg = base_reg; + + if (obj && offset && obj->datatype != DLOCAL) { + tmp_reg = used_virtual_registers[RegClass_GPR]++; + add_immediate_lo(tmp_reg, base_reg, obj, 0, 1); + obj = NULL; + } + + if (!obj && !offset) + emitpcode(PC_MR, dest_reg, tmp_reg); + else + emitpcode(PC_ADDI, dest_reg, tmp_reg, obj, offset); +} + +PCode *add_immediate_lo(short dest_reg, short base_reg, Object *obj, SInt16 offset, char add_to_block) { + PCode *pc; + + CError_ASSERT(577, obj); + + pc = makepcode(PC_ADDI, dest_reg, base_reg, obj, offset); + if (add_to_block) + appendpcode(pclastblock, pc); + return pc; +} + +PCode *op_absolute_ha(short dest_reg, short base_reg, Object *obj, short offset, char add_to_block) { + PCode *pc; + int tmp_reg; + + if (obj->datatype == DLOCAL) { + pc = makepcode(PC_ADDIS, dest_reg, base_reg, obj, offset); + } else if (copts.codegen_pic) { + tmp_reg = base_reg; + CError_ASSERT(601, tmp_reg); + pc = makepcode(PC_ADDIS, dest_reg, tmp_reg, obj, offset); + } else { + CError_ASSERT(606, base_reg == 0); + pc = makepcode(PC_LIS, dest_reg, obj, offset); + } + + if (add_to_block) + appendpcode(pclastblock, pc); + return pc; +} + +void load_store_register(Opcode opcode, short dest_reg, short base_reg, Object *obj, SInt32 offset) { + short addi_tmp; + short offset_reg1; + short offset_reg2; + + offset_reg1 = base_reg; + if (obj && offset && obj->datatype != DLOCAL) { + offset_reg1 = used_virtual_registers[RegClass_GPR]++; + add_immediate_lo(offset_reg1, base_reg, obj, 0, 1); + obj = NULL; + } + + if (offset != (short)offset) { + if (opcode == PC_LWZ && dest_reg == 12) + offset_reg2 = 12; + else if (opcode == PC_LWZ && dest_reg == 11) + offset_reg2 = 11; + else + offset_reg2 = used_virtual_registers[RegClass_GPR]++; + + emitpcode(PC_ADDIS, offset_reg2, offset_reg1, 0, (short) ((offset >> 16) + ((offset & 0x8000) >> 15))); + offset = (short) offset; + offset_reg1 = offset_reg2; + } + + if (opcode == PC_STVX || opcode == PC_LVX) { + offset_reg2 = 0; + if (obj) { + addi_tmp = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADDI, addi_tmp, offset_reg1, obj, offset); + offset_reg1 = addi_tmp; + } else if (offset) { + offset_reg2 = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_LI, offset_reg2, offset); + } + if (!offset_reg2) + emitpcode(opcode, dest_reg, 0, offset_reg1); + else + emitpcode(opcode, dest_reg, offset_reg1, offset_reg2); + } else { + emitpcode(opcode, dest_reg, offset_reg1, obj, offset); + } +} diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Peephole.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Peephole.c new file mode 100644 index 0000000..151e448 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Peephole.c @@ -0,0 +1,2753 @@ +#include "compiler/Peephole.h" +#include "compiler/CompilerTools.h" +#include "compiler/InstrSelection.h" +#include "compiler/PCode.h" +#include "compiler/objects.h" +#include "compiler/types.h" +#include "compiler/Scheduler.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/Alias.h" +#include "compiler/CParser.h" + +typedef int (*PeepholeFunc)(PCode *instr, UInt32 *masks); + +typedef struct Pattern { + struct Pattern *next; + PeepholeFunc func; +} Pattern; + +typedef struct LiveRegs { + UInt32 x0; + UInt32 x4; + UInt32 x8; + UInt32 xC; +} LiveRegs; + +static LiveRegs *liveregs[RegClassMax]; +static Pattern *peepholepatterns[OPCODE_MAX]; +static PCode **defininginstruction; + +static void computeregisterusedefs(void) { + PCodeBlock *block; + PCode *instr; + PCodeArg *op; + int i; + RegClass rclass; + LiveRegs *lr; + UInt32 array1[RegClassMax]; + UInt32 array2[RegClassMax]; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (rclass = 0; rclass < RegClassMax; rclass++) { + array1[rclass] = 0; + array2[rclass] = 0; + } + + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + for (op = instr->args, i = instr->argCount; i--; op++) { + if ( + op->kind == PCOp_REGISTER && + (op->data.reg.effect & EffectRead) && + !((1 << op->data.reg.reg) & array2[op->arg]) + ) + array1[op->arg] |= 1 << op->data.reg.reg; + } + + for (op = instr->args, i = instr->argCount; i--; op++) { + if ( + op->kind == PCOp_REGISTER && + (op->data.reg.effect & EffectWrite) && + !((1 << op->data.reg.reg) & array1[op->arg]) + ) + array2[op->arg] |= 1 << op->data.reg.reg; + } + } + + for (rclass = 0; rclass < RegClassMax; rclass++) { + lr = liveregs[rclass] + block->blockIndex; + lr->x0 = array1[rclass]; + lr->x4 = array2[rclass]; + if (rclass == RegClass_GPR) { + lr->x8 = 1 << 1; + lr->xC = 1 << 1; + } else { + lr->x8 = 0; + lr->xC = 0; + } + } + } +} + +static void computeliveness(LiveRegs *lrarray, UInt32 x) { + PCodeBlock *block; + LiveRegs *lr; + PCLink *link; + UInt32 newC; + UInt32 new8; + int i; + int flag; + + flag = 1; + while (flag) { + flag = 0; + i = pcblockcount; + while (i) { + if ((block = depthfirstordering[--i])) { + lr = lrarray + block->blockIndex; + newC = x; + for (link = block->successors; link; link = link->nextLink) + newC |= lrarray[link->block->blockIndex].x8; + lr->xC = newC; + + new8 = lr->x0 | (lr->xC & ~lr->x4); + if (new8 != lr->x8) { + lr->x8 = new8; + flag = 1; + } + } + } + } +} + +static void computeliveregisters(Object *func) { + Type *returntype; + RegClass rclass; + + returntype = TYPE_FUNC(func->type)->functype; + + for (rclass = 0; rclass < RegClassMax; rclass++) + liveregs[rclass] = lalloc(sizeof(LiveRegs) * pcblockcount); + + computedepthfirstordering(); + computeregisterusedefs(); + + if (TYPE_FITS_IN_REGISTER(returntype)) { + liveregs[RegClass_GPR][epilogue->blockIndex].x0 |= 1 << 3; + if (TYPE_IS_8BYTES(returntype)) + liveregs[RegClass_GPR][epilogue->blockIndex].x0 |= 1 << 4; + } else if (IS_TYPE_FLOAT(returntype)) { + liveregs[RegClass_FPR][epilogue->blockIndex].x0 |= 1 << 1; + } else if (IS_TYPE_VECTOR(returntype)) { + liveregs[RegClass_VR][epilogue->blockIndex].x0 |= 1 << 2; + } + + for (rclass = 0; rclass < RegClassMax; rclass++) { + if (rclass == RegClass_GPR) + computeliveness(liveregs[rclass], 2); + else + computeliveness(liveregs[rclass], 0); + } +} + +static void computeinstructionpredecessors(PCodeBlock *block) { + PCode *nop; + RegClass rclass; + SInt32 i; + SInt32 defID; + SInt32 totalOps; + PCode *instr; + PCodeArg *op; + PCode *array[RegClassMax][32]; + + nop = makepcode(PC_NOP); + for (rclass = 0; rclass < RegClassMax; rclass++) { + for (i = 0; i < 32; i++) { + array[rclass][i] = nop; + } + } + + totalOps = 0; + for (instr = block->firstPCode; instr; instr = instr->nextPCode) + totalOps += instr->argCount; + + if (totalOps) { + defininginstruction = oalloc(sizeof(PCode *) * totalOps); + for (i = 0; i < totalOps; i++) + defininginstruction[i] = nop; + + defID = 0; + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + instr->defID = defID; + + for (i = 0, op = instr->args; i < instr->argCount; i++, op++) { + if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectRead)) + defininginstruction[defID + i] = array[op->arg][op->data.reg.reg]; + } + + for (i = 0, op = instr->args; i < instr->argCount; i++, op++) { + if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite)) + array[op->arg][op->data.reg.reg] = instr; + } + + defID += instr->argCount; + } + } +} + +static int dead(PCode *instr, UInt32 *masks) { + int i; + PCodeArg *op; + + if (instr->block->flags & (fIsProlog | fIsEpilogue)) + return 0; + if (instr->flags & (fIsBranch | fIsWrite | fIsCall | fIsVolatile | fSideEffects)) + return 0; + if (!instr->block->predecessors) + return 1; + + for (op = instr->args, i = instr->argCount; i--; op++) { + if ( + op->kind == PCOp_REGISTER && + (op->data.reg.effect & EffectWrite) && + ((1 << op->data.reg.reg) & masks[op->arg]) + ) + return 0; + } + + return 1; +} + +static int definedbetween(PCode *start, PCode *end, PCodeArg *checkOp) { + PCode *instr; + PCodeArg *op; + int i; + + for (instr = start->prevPCode; instr != end; instr = instr->prevPCode) { + for (op = instr->args, i = instr->argCount; i--; op++) { + if (PC_OP_IS_WRITE_REGISTER(op, checkOp->arg, checkOp->data.reg.reg)) + return 1; + } + } + + return 0; +} + +static int usedbetween(PCode *start, PCode *end, PCodeArg *checkOp) { + PCode *instr; + PCodeArg *op; + int i; + + for (instr = start->prevPCode; instr != end; instr = instr->prevPCode) { + for (op = instr->args, i = instr->argCount; i--; op++) { + if (PC_OP_IS_READ_REGISTER(op, checkOp->arg, checkOp->data.reg.reg)) + return 1; + } + } + + return 0; +} + +static int isSPRlive(PCode *instr, int reg) { + PCode *scan; + PCodeArg *op; + int i; + + for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { + for (op = scan->args, i = scan->argCount; i--; op++) { + if (PC_OP_IS_READ_REGISTER(op, RegClass_SPR, reg)) + return 1; + + if (PC_OP_IS_WRITE_REGISTER(op, RegClass_SPR, reg)) + return 0; + } + } + + return 0; +} + +static SInt32 extractedbits(PCode *instr) { + SInt32 a = instr->args[2].data.imm.value; + SInt32 b = instr->args[3].data.imm.value; + SInt32 c = instr->args[4].data.imm.value; + SInt32 val; + + if (b <= c) + val = ((b > 31) ? 0 : (0xFFFFFFFFu >> b)) & ~(((c + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c + 1))); + else + val = ((b > 31) ? 0 : (0xFFFFFFFFu >> b)) | ~(((c + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c + 1))); + + return ((UInt32) val >> a) | (val << (32 - a)); +} + +static int canmergemasks(SInt32 b1, SInt32 c1, SInt32 a, SInt32 b2, SInt32 c2, short *first, short *last) { + SInt32 val1; + SInt32 val2; + + if (b1 <= c1) + val1 = ((b1 > 31) ? 0 : (0xFFFFFFFFu >> b1)) & ~(((c1 + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c1 + 1))); + else + val1 = ((b1 > 31) ? 0 : (0xFFFFFFFFu >> b1)) | ~(((c1 + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c1 + 1))); + + if (b2 <= c2) + val2 = ((b2 > 31) ? 0 : (0xFFFFFFFFu >> b2)) & ~(((c2 + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c2 + 1))); + else + val2 = ((b2 > 31) ? 0 : (0xFFFFFFFFu >> b2)) | ~(((c2 + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c2 + 1))); + + return ismaskconstant(val2 & ((val1 << a) | ((UInt32) val1 >> (32 - a))), first, last); +} + +static int canuseupdatetest(PCodeBlock *block, PCode *instr, int count1, int count2, int count3, int count4, int count5) { + int i; + PCLink *link; + + while (instr) { + if (++count1 > 17) + return 1; + + switch (instr->op) { + case PC_DIVW: + case PC_DIVWU: + case PC_MULHW: + case PC_MULHWU: + case PC_MULLI: + case PC_MULLW: + return count3 == 0; + case PC_MTXER: + case PC_MTCTR: + case PC_MTLR: + case PC_MTCRF: + case PC_MTMSR: + case PC_MTSPR: + case PC_MFMSR: + case PC_MFSPR: + case PC_MFXER: + case PC_MFCTR: + case PC_MFLR: + case PC_MFCR: + case PC_ECIWX: + case PC_ECOWX: + case PC_DCBI: + case PC_ICBI: + case PC_MCRFS: + case PC_MCRXR: + case PC_MFTB: + case PC_MFSR: + case PC_MTSR: + case PC_MFSRIN: + case PC_MTSRIN: + case PC_MTFSB0: + case PC_MTFSB1: + case PC_MTFSFI: + case PC_SC: + case PC_TLBIA: + case PC_TLBIE: + case PC_TLBLD: + case PC_TLBLI: + case PC_TLBSYNC: + case PC_TW: + case PC_TRAP: + case PC_TWI: + case PC_MFROM: + case PC_DSA: + case PC_ESA: + return 1; + case PC_CRAND: + case PC_CRANDC: + case PC_CREQV: + case PC_CRNAND: + case PC_CRNOR: + case PC_CROR: + case PC_CRORC: + case PC_CRXOR: + case PC_MCRF: + if (++count5 > 1) + return 1; + } + + if (instr->flags & (fIsRead | fIsWrite)) { + if (++count4 > 1) + return 1; + } else if (instr->flags & fIsBranch) { + if (++count2 > 2) + return 1; + + for (i = 0; i < instr->argCount; i++) { + if (PC_OP_IS_ANY_REGISTER(&instr->args[i], RegClass_CRFIELD)) { + ++count3; + break; + } + } + } + + instr = instr->nextPCode; + } + + if (block && block->successors) { + for (link = block->successors; link; link = link->nextLink) { + if (link->block && !canuseupdatetest(link->block, link->block->firstPCode, count1, count2, count3, count4, count5)) + return 0; + } + } + + return 1; +} + +static int canuseupdate(PCode *instr) { + return canuseupdatetest(instr->block, instr->nextPCode, 0, 0, 0, 0, 0); +} + +static int MR_Rx_Rx(PCode *instr, UInt32 *masks) { + if ( + instr->args[0].data.reg.reg == instr->args[1].data.reg.reg && + !(PCODE_FLAG_SET_F(instr) & fRecordBit) + ) + { + deletepcode(instr); + return 1; + } + + return 0; +} + +static int FMR_Fx_Fx(PCode *instr, UInt32 *masks) { + if ( + instr->args[0].data.reg.reg == instr->args[1].data.reg.reg && + !(PCODE_FLAG_SET_F(instr) & fRecordBit) + ) + { + deletepcode(instr); + return 1; + } + + return 0; +} + +static int VMR_Vx_Vx(PCode *instr, UInt32 *masks) { + if ( + instr->args[0].data.reg.reg == instr->args[1].data.reg.reg && + !(PCODE_FLAG_SET_F(instr) & fRecordBit) + ) + { + deletepcode(instr); + return 1; + } + + return 0; +} + +static int MR_MR(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_MR && + instr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && + !definedbetween(instr, defInstr, &instr->args[0]) && + !(PCODE_FLAG_SET_F(instr) & fRecordBit) + ) + { + deletepcode(instr); + return 1; + } + + return 0; +} + +static int FMR_FMR(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_FMR && + instr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && + !(PCODE_FLAG_SET_F(instr) & fRecordBit) && + !definedbetween(instr, defInstr, &instr->args[0]) + ) + { + deletepcode(instr); + return 1; + } + + return 0; +} + +static int VMR_VMR(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_VMR && + instr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && + !(PCODE_FLAG_SET_F(instr) & fRecordBit) && + !definedbetween(instr, defInstr, &instr->args[0]) + ) + { + deletepcode(instr); + return 1; + } + + return 0; +} + +static int VMR_VMRP(PCode *instr, UInt32 *masks) { + PCode *prev = instr->prevPCode; + PCode *next = instr->nextPCode; + int prevFlag = 0; + int prevPermute = 0; + int nextFlag = 0; + int nextPermute = 0; + + if (prev) { + prevFlag = (prev->flags & fOpTypeMask) == fOpTypeVR; + prevPermute = uses_vpermute_unit(prev); + } + if (next) { + nextFlag = (next->flags & fOpTypeMask) == fOpTypeVR; + nextPermute = uses_vpermute_unit(next); + } + + if (prev) { + if (next) { + if (prevFlag && !prevPermute) { + if (nextFlag) { + if (!nextPermute) { + change_opcode(instr, PC_VMRP); + return 1; + } + } else { + change_opcode(instr, PC_VMRP); + return 1; + } + } + } else { + if (prevFlag && !prevPermute) { + change_opcode(instr, PC_VMRP); + return 1; + } + } + } else { + if (next && nextFlag && !nextPermute) { + change_opcode(instr, PC_VMRP); + return 1; + } + } + + return 0; +} + +static int MR_CMPI(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + PCodeArg op; + + if ( + instr->args[0].data.reg.reg == 0 && + instr->args[2].data.imm.value == 0 && + (PCODE_FLAG_SET_F(defInstr) & (fSideEffects | fCanSetRecordBit | fOpTypeGPR)) == (fCanSetRecordBit | fOpTypeGPR) && + !usedbetween(instr, defInstr, &instr->args[0]) && + !definedbetween(instr, defInstr, &instr->args[0]) + ) + { + if (defInstr->op == PC_ADDI) { + op.kind = PCOp_REGISTER; + op.arg = RegClass_SPR; + op.data.reg.reg = 0; + op.data.reg.effect = EffectRead | EffectWrite; + if (usedbetween(instr, defInstr, &op)) + return 0; + } + + pcsetrecordbit(defInstr); + deletepcode(instr); + return 1; + } + + return 0; +} + +static int EXTSB_RLWINM(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_EXTSB && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && + !definedbetween(instr, defInstr, &defInstr->args[1]) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + (extractedbits(instr) & 0xFFFFFF00) == 0 + ) + { + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int EXTSH_RLWINM(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_EXTSH && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && + !definedbetween(instr, defInstr, &defInstr->args[1]) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + (extractedbits(instr) & 0xFFFF0000) == 0 + ) + { + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int LBZ_RLWINM(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + (defInstr->op == PC_LBZ || defInstr->op == PC_LBZX) && + instr->args[2].data.imm.value == 0 && + instr->args[3].data.imm.value <= 24 && + instr->args[4].data.imm.value == 31 && + !(PCODE_FLAG_SET_F(instr) & fRecordBit) && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + !definedbetween(instr, defInstr, &instr->args[0]) && + !usedbetween(instr, defInstr, &instr->args[0]) + ) + { + defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg; + deletepcode(instr); + return 1; + } + + return 0; +} + +static int LHZ_RLWINM(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + (defInstr->op == PC_LHZ || defInstr->op == PC_LHZX) && + instr->args[2].data.imm.value == 0 && + instr->args[3].data.imm.value <= 16 && + instr->args[4].data.imm.value == 31 && + !(PCODE_FLAG_SET_F(instr) & fRecordBit) && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + !definedbetween(instr, defInstr, &instr->args[0]) && + !usedbetween(instr, defInstr, &instr->args[0]) + ) + { + defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg; + deletepcode(instr); + return 1; + } + + return 0; +} + +static int LHA_EXTSH(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_LHA && + !(PCODE_FLAG_SET_F(instr) & fRecordBit) && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + !definedbetween(instr, defInstr, &instr->args[0]) && + !usedbetween(instr, defInstr, &instr->args[0]) + ) + { + defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg; + deletepcode(instr); + return 1; + } + + if ( + defInstr->op == PC_EXTSB && + !(PCODE_FLAG_SET_F(instr) & fRecordBit) + ) + { + if (defInstr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg) { + if ( + !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg)) && + !usedbetween(instr, defInstr, &defInstr->args[0]) + ) + { + change_opcode(instr, PC_EXTSB); + deletepcode(defInstr); + return 1; + } + } else { + if (!definedbetween(instr, defInstr, &defInstr->args[1])) { + change_opcode(instr, PC_EXTSB); + instr->args[1] = defInstr->args[1]; + } else { + change_opcode(instr, PC_MR); + } + return 1; + } + } + + return 0; +} + +static int ADDI_L_S(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + SInt32 addleft; + SInt32 addright; + + if (defInstr->op == PC_ADDI && instr->args[2].kind == PCOp_IMMEDIATE) { + if (!PC_OP_IS_REGISTER(&instr->args[0], RegClass_GPR, instr->args[1].data.reg.reg)) { + if ( + instr->args[2].data.imm.value == 0 && + defInstr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + (!(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg)) || canuseupdate(instr)) + ) + { + if (!(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) { + instr->args[2] = defInstr->args[2]; + } else { + instr->op++; + instr->args[1].data.reg.effect |= EffectWrite; + instr->args[2] = defInstr->args[2]; + } + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + deletepcode(defInstr); + return 1; + } + + addleft = 0x1FFFF; + addright = instr->args[2].data.imm.value; + if (defInstr->args[2].kind == PCOp_IMMEDIATE) { + addleft = defInstr->args[2].data.imm.value; + } else if (defInstr->args[2].kind == PCOp_MEMORY) { + if (defInstr->args[2].data.mem.obj->datatype == DLOCAL) + addleft = defInstr->args[2].data.mem.offset + defInstr->args[2].data.mem.obj->u.var.uid; + else if (addright == 0) + addleft = 0; + else + return 0; + } + + if (!FITS_IN_SHORT(addleft + addright)) + return 0; + + if ( + !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg)) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + !definedbetween(instr, defInstr, &defInstr->args[1]) + ) + { + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + + if (defInstr->args[2].kind == PCOp_MEMORY) { + instr->args[2] = defInstr->args[2]; + instr->args[2].data.mem.offset += addright; + if (instr->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) { + instr->alias = make_alias( + instr->args[2].data.mem.obj, + instr->args[2].data.mem.offset, + nbytes_loaded_or_stored_by(instr) + ); + } + } else { + instr->args[2].data.imm.value = addleft + addright; + } + + deletepcode(defInstr); + return 1; + } + + if ( + instr->args[1].data.reg.reg != defInstr->args[1].data.reg.reg && + !definedbetween(instr, defInstr, &defInstr->args[1]) + ) + { + if (defInstr->args[2].kind == PCOp_MEMORY && defInstr->args[2].data.mem.obj->datatype != DLOCAL) + return 0; + + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + + if (defInstr->args[2].kind == PCOp_MEMORY) { + instr->args[2] = defInstr->args[2]; + instr->args[2].data.mem.offset += addright; + if (instr->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) { + instr->alias = make_alias( + instr->args[2].data.mem.obj, + instr->args[2].data.mem.offset, + nbytes_loaded_or_stored_by(instr) + ); + } + } else { + instr->args[2].data.imm.value = addleft + addright; + } + + return 1; + } + } + } else { + if ( + defInstr->op == PC_MR && + PC_OP_IS_ANY_REGISTER(&defInstr->args[1], RegClass_GPR) && + defInstr->args[1].data.reg.reg != 0 && + !definedbetween(instr, defInstr, &defInstr->args[1]) + ) + { + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + } + } + + return 0; +} + +static int ADDI_LU_SU(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + instr->args[2].kind == PCOp_IMMEDIATE && + defInstr->args[2].kind == PCOp_IMMEDIATE && + defInstr->op == PC_ADDI && + defInstr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && + !(instr->args[0].arg == instr->args[1].arg && instr->args[0].data.reg.reg == instr->args[1].data.reg.reg) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + FITS_IN_SHORT(instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) + ) + { + if ((instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) == 0) { + instr->op--; + instr->args[1].data.reg.effect &= ~EffectWrite; + instr->args[2].data.imm.value = 0; + } else { + instr->args[2].data.imm.value += defInstr->args[2].data.imm.value; + } + + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int L_S_ADDI(PCode *instr, UInt32 *masks) { + PCode *scan; + PCodeArg *op; + int i; + short reg; + + if (instr->args[2].kind != PCOp_IMMEDIATE) + return 0; + + reg = instr->args[1].data.reg.reg; + if (!canuseupdate(instr)) + return 0; + + for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { + for (op = scan->args, i = scan->argCount; i--; op++) { + if (PC_OP_IS_READ_REGISTER(op, RegClass_GPR, reg)) + return 0; + + if (PC_OP_IS_WRITE_REGISTER(op, RegClass_GPR, reg)) { + if (scan->op != PC_ADDI) + return 0; + if (scan->args[2].kind != PCOp_IMMEDIATE) + return 0; + + if ( + instr->args[2].data.imm.value == scan->args[2].data.imm.value && + scan->args[0].data.reg.reg == scan->args[1].data.reg.reg && + !(instr->args[0].arg == instr->args[1].arg && instr->args[0].data.reg.reg == instr->args[1].data.reg.reg) + ) + { + if (!(masks[RegClass_GPR] & (1 << scan->args[0].data.reg.reg))) { + instr->args[2] = scan->args[2]; + } else { + instr->op++; + instr->args[1].data.reg.effect |= EffectWrite; + instr->args[2] = scan->args[2]; + } + + change_opcode(scan, PC_NOP); + change_num_operands(scan, 0); + deletepcode(scan); + return 1; + } + + return 0; + } + } + } + + return 0; +} + +static int LI_CMP_BC(PCode *instr, UInt32 *masks) { + PCode *defInstr; + PCode *defInstr2; + PCLink *link; + PCLink **ptr; + + if (instr->args[1].data.imm.value == 2) { + defInstr = defininginstruction[instr->defID]; + if ((defInstr->op == PC_CMPLI || defInstr->op == PC_CMPI) && defInstr->args[0].data.reg.reg == 0) { + defInstr2 = defininginstruction[defInstr->defID + 1]; + if ( + defInstr2->op == PC_LI && + defInstr2->args[1].kind == PCOp_IMMEDIATE && + (instr->op == PC_BT) == (defInstr2->args[1].data.imm.value == defInstr->args[2].data.imm.value) + ) + { + change_opcode(instr, PC_B); + instr->args[0] = instr->args[2]; + change_num_operands(instr, 1); + + defininginstruction[instr->defID] = defininginstruction[instr->defID + 1]; + + for (ptr = &instr->block->successors; (link = *ptr); ptr = &link->nextLink) { + if (link->block == instr->block->nextBlock) { + *ptr = link->nextLink; + break; + } + } + + for (ptr = &instr->block->nextBlock->predecessors; (link = *ptr); ptr = &link->nextLink) { + if (link->block == instr->block) { + *ptr = link->nextLink; + break; + } + } + } + } + } + + return 0; +} + +static int RLWINM_CMPLI_BC(PCode *instr, UInt32 *masks) { + PCode *defInstr; + PCode *defInstr2; + + if (instr->args[1].data.imm.value == 2) { + defInstr = defininginstruction[instr->defID]; + if (defInstr->op == PC_CMPLI && defInstr->args[0].data.reg.reg == 0 && defInstr->args[2].data.imm.value == 0) { + defInstr2 = defininginstruction[defInstr->defID + 1]; + if ( + (PCODE_FLAG_SET_F(defInstr2) & (fSideEffects | fCanSetRecordBit | fOpTypeGPR)) == (fCanSetRecordBit | fOpTypeGPR) && + !usedbetween(defInstr, defInstr2, &defInstr->args[0]) && + !definedbetween(defInstr, defInstr2, &defInstr->args[0]) + ) + { + pcsetrecordbit(defInstr2); + defininginstruction[instr->defID] = defininginstruction[defInstr->defID + 1]; + deletepcode(defInstr); + return 1; + } + } + } + + return 0; +} + +static int LBZ_EXTSB_CMPI_BC(PCode *instr, UInt32 *masks) { + PCode *defInstr; + PCode *defInstr2; + + if (instr->args[1].data.imm.value == 2) { + defInstr = defininginstruction[instr->defID]; + if ( + ( + (defInstr->op == PC_CMPI || defInstr->op == PC_CMPLI) && + defInstr->args[2].data.imm.value >= 0 && + defInstr->args[2].data.imm.value <= 127 + ) + || + ( + (defInstr->op == PC_EXTSB || defInstr->op == PC_EXTSH) && + (PCODE_FLAG_SET_F(defInstr) & fRecordBit) + ) + ) + { + defInstr2 = defininginstruction[defInstr->defID + 1]; + if ( + defInstr2->op == PC_EXTSB && + defininginstruction[defInstr2->defID + 1]->op == PC_LBZ && + !(masks[RegClass_GPR] & (1 << defInstr2->args[0].data.reg.reg)) && + !usedbetween(instr, defInstr, &defInstr2->args[0]) && + !usedbetween(defInstr, defInstr2, &defInstr2->args[0]) && + !definedbetween(defInstr, defInstr2, &defInstr2->args[1]) + ) + { + defInstr->args[1].data.reg.reg = defInstr2->args[1].data.reg.reg; + defininginstruction[defInstr->defID + 1] = defininginstruction[defInstr2->defID + 1]; + deletepcode(defInstr2); + return 1; + } + } + } + + return 0; +} + +static int FRSP_STFS(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID]; + + if ( + defInstr->op == PC_FRSP && + !(masks[RegClass_FPR] & (1 << defInstr->args[0].data.reg.reg)) && + !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && + !definedbetween(instr, defInstr, &defInstr->args[1]) && + !usedbetween(instr, defInstr, &defInstr->args[0]) + ) + { + instr->args[0].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID] = defininginstruction[defInstr->defID + 1]; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int NOT_AND(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 2]; + + if ( + defInstr->op == PC_NOT && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && + !definedbetween(instr, defInstr, &defInstr->args[1]) && + !usedbetween(instr, defInstr, &defInstr->args[0]) + ) + { + instr->args[2].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 2] = defininginstruction[defInstr->defID + 1]; + change_opcode(instr, PC_ANDC); + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int LI_MR(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_LI && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(instr) & fRecordBit) && + !usedbetween(instr, defInstr, &defInstr->args[0]) + ) + { + change_opcode(instr, PC_LI); + instr->args[1] = defInstr->args[1]; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int VSPLTIS_VMR(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + short opcode = defInstr->op; + + if ( + (opcode == PC_VSPLTISB || opcode == PC_VSPLTISH || opcode == PC_VSPLTISW) && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_VR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(instr) & fRecordBit) && + !usedbetween(instr, defInstr, &defInstr->args[0]) + ) + { + change_opcode(instr, opcode); + instr->args[1] = defInstr->args[1]; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int L_MR(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + (defInstr->flags & fIsRead) && + !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg)) && + !(PCODE_FLAG_SET_F(instr) & fRecordBit) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + !usedbetween(instr, defInstr, &instr->args[0]) && + !definedbetween(instr, defInstr, &instr->args[0]) + ) + { + defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg; + deletepcode(instr); + return 1; + } + + return 0; +} + +static int L_FMR(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + (defInstr->flags & fIsRead) && + !(masks[RegClass_FPR] & (1 << defInstr->args[0].data.reg.reg)) && + !(PCODE_FLAG_SET_F(instr) & fRecordBit) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + !usedbetween(instr, defInstr, &instr->args[0]) && + !definedbetween(instr, defInstr, &instr->args[0]) + ) + { + defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg; + deletepcode(instr); + return 1; + } + + return 0; +} + +static int L_S(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID]; + SInt32 isIndexed; + SInt32 isFloat; + SInt32 isVector; + PCode *scan; + SInt32 loadSize; + SInt32 defInstrOffset; + SInt32 scanOffset; + SInt32 storeSize; + + if (PCODE_FLAG_SET_F(instr) & (fIsVolatile | fSideEffects | fUpdatesPtr)) + return 0; + if (PCODE_FLAG_SET_F(defInstr) & (fIsVolatile | fSideEffects | fUpdatesPtr)) + return 0; + + if ( + (defInstr->flags & fIsRead) && + PC_OP_IS_REGISTER(&defInstr->args[1], RegClass_GPR, instr->args[1].data.reg.reg) && + defInstr->args[2].kind == instr->args[2].kind && + !definedbetween(instr, defInstr, &instr->args[1]) + ) + { + if (instr->args[2].kind == PCOp_IMMEDIATE) { + if (instr->args[2].data.imm.value != defInstr->args[2].data.imm.value) + return 0; + } else if (instr->args[2].kind == PCOp_MEMORY) { + if (instr->args[2].data.mem.offset != defInstr->args[2].data.mem.offset || + instr->args[2].data.mem.obj != defInstr->args[2].data.mem.obj) + return 0; + } else if (instr->args[2].kind == PCOp_REGISTER && instr->args[2].arg == RegClass_GPR) { + if (instr->args[2].data.reg.reg != defInstr->args[2].data.reg.reg || + definedbetween(instr, defInstr, &instr->args[2])) + return 0; + } else { + return 0; + } + + isIndexed = 0; + isFloat = 0; + isVector = 0; + switch (defInstr->op) { + case PC_LBZX: + isIndexed = 1; + case PC_LBZ: + loadSize = 1; + break; + case PC_LHZX: + case PC_LHAX: + isIndexed = 1; + case PC_LHZ: + case PC_LHA: + loadSize = 2; + break; + case PC_LWZX: + isIndexed = 1; + case PC_LWZ: + loadSize = 4; + break; + case PC_LFSX: + isIndexed = 1; + case PC_LFS: + isFloat = 1; + loadSize = 4; + break; + case PC_LFDX: + isIndexed = 1; + case PC_LFD: + isFloat = 1; + loadSize = 8; + break; + case PC_LVX: + case PC_LVXL: + isIndexed = 1; + isVector = 1; + loadSize = 16; + break; + default: + return 0; + } + + switch (instr->op) { + case PC_STBX: + if (!isIndexed) return 0; + case PC_STB: + if (isFloat) return 0; + if (loadSize != 1) return 0; + break; + case PC_STHX: + if (!isIndexed) return 0; + case PC_STH: + if (isFloat) return 0; + if (loadSize != 2) return 0; + break; + case PC_STWX: + if (!isIndexed) return 0; + case PC_STW: + if (isFloat) return 0; + if (loadSize != 4) return 0; + break; + case PC_STFSX: + if (!isIndexed) return 0; + case PC_STFS: + if (!isFloat) return 0; + if (loadSize != 4) return 0; + break; + case PC_STFDX: + if (!isIndexed) return 0; + case PC_STFD: + if (!isFloat) return 0; + if (loadSize != 8) return 0; + break; + case PC_STVX: + case PC_STVXL: + if (!isIndexed) return 0; + if (!isVector) return 0; + if (loadSize != 16) return 0; + break; + default: + return 0; + } + + for (scan = instr->prevPCode; scan && scan != defInstr; scan = scan->prevPCode) { + if (scan->flags & fIsWrite) { + if (scan->args[1].data.reg.reg != instr->args[1].data.reg.reg) + return 0; + if (scan->args[2].kind != defInstr->args[2].kind) + return 0; + + if (scan->args[2].kind == PCOp_MEMORY) { + if (instr->args[2].data.mem.obj == scan->args[2].data.mem.obj) { + if (instr->args[2].data.mem.offset == defInstr->args[2].data.mem.offset) + return 0; + defInstrOffset = defInstr->args[2].data.mem.offset; + scanOffset = scan->args[2].data.mem.offset; + } + } else if (scan->args[2].kind == PCOp_IMMEDIATE) { + if (instr->args[1].data.reg.reg != scan->args[1].data.reg.reg) + return 0; + if (instr->args[2].data.imm.value == scan->args[2].data.imm.value) + return 0; + defInstrOffset = defInstr->args[2].data.imm.value; + scanOffset = scan->args[2].data.imm.value; + } else { + return 0; + } + + switch (scan->op) { + case PC_STB: + case PC_STBX: + storeSize = 1; + break; + case PC_STH: + case PC_STHX: + storeSize = 2; + break; + case PC_STW: + case PC_STWX: + case PC_STFS: + case PC_STFSX: + storeSize = 4; + break; + case PC_STFD: + case PC_STFDX: + storeSize = 8; + break; + case PC_STVX: + case PC_STVXL: + storeSize = 16; + break; + default: + return 0; + } + + if (defInstrOffset > scanOffset) { + if ((scanOffset + storeSize) > defInstrOffset) + return 0; + } else { + if ((defInstrOffset + loadSize) > scanOffset) + return 0; + } + } + } + + deletepcode(instr); + return 1; + } + + return 0; +} + +static int RLWINM_RLWINM(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + short start; + short end; + + if ( + defInstr->op == PC_RLWINM && + !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && + !definedbetween(instr, defInstr, &defInstr->args[1]) && + !( + defInstr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && + ( + (defInstr->args[0].data.reg.reg != instr->args[0].data.reg.reg && (masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) || + usedbetween(instr, defInstr, &defInstr->args[0]) + ) + ) && + canmergemasks( + defInstr->args[3].data.imm.value, + defInstr->args[4].data.imm.value, + instr->args[2].data.imm.value, + instr->args[3].data.imm.value, + instr->args[4].data.imm.value, + &start, &end) + ) + { + if (instr->op == PC_RLWIMI) { + if (instr->args[0].data.reg.reg == defInstr->args[0].data.reg.reg) + return 0; + if (start != instr->args[3].data.imm.value || end != instr->args[4].data.imm.value) + return 0; + } + + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + + instr->args[2].data.imm.value = (instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) & 31; + instr->args[3].data.imm.value = start; + instr->args[4].data.imm.value = end; + + if ( + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !usedbetween(instr, defInstr, &defInstr->args[0]) + ) + deletepcode(defInstr); + + return 1; + } + + if ( + defInstr->op == PC_MR && + instr->op == PC_RLWINM && + !definedbetween(instr, defInstr, &defInstr->args[1]) + ) + { + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + + if ( + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && + !usedbetween(instr, defInstr, &defInstr->args[0]) + ) + deletepcode(defInstr); + + return 1; + } + + return 0; +} + +static int MULLI_MULLI(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_MULLI && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && + !definedbetween(instr, defInstr, &defInstr->args[1]) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + FITS_IN_SHORT(instr->args[2].data.imm.value * defInstr->args[2].data.imm.value) + ) + { + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + + instr->args[2].data.imm.value *= defInstr->args[2].data.imm.value; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int ADDI_ADDI(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_ADDI && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && + !definedbetween(instr, defInstr, &defInstr->args[1]) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + instr->args[2].kind == PCOp_IMMEDIATE && + defInstr->args[2].kind == PCOp_IMMEDIATE && + FITS_IN_SHORT(instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) + ) + { + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + + instr->args[2].data.imm.value += defInstr->args[2].data.imm.value; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int SRAWI_SRAWI(PCode *instr, UInt32 *masks) { + PCode *defInstr = defininginstruction[instr->defID + 1]; + + if ( + defInstr->op == PC_SRAWI && + (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && + !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && + !definedbetween(instr, defInstr, &defInstr->args[1]) && + !usedbetween(instr, defInstr, &defInstr->args[0]) && + instr->args[2].kind == PCOp_IMMEDIATE && + defInstr->args[2].kind == PCOp_IMMEDIATE && + (instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) < 32 && + (instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) > 0 + ) + { + instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; + + instr->args[2].data.imm.value += defInstr->args[2].data.imm.value; + deletepcode(defInstr); + return 1; + } + + return 0; +} + +static int MR_ADDI(PCode *instr, UInt32 *masks) { + PCode *prev = instr->prevPCode; + PCode *next = instr->nextPCode; + int prevFlag = 0; + int nextFlag = 0; + + if (copts.processor == CPU_PPC603e) { + if (prev) + prevFlag = (prev->flags & fOpTypeMask) == fOpTypeGPR; + if (next) + nextFlag = (next->flags & fOpTypeMask) == fOpTypeGPR; + + if ( + !(PCODE_FLAG_SET_F(instr) & fRecordBit) && + instr->argCount >= 2 && + instr->args[1].data.reg.reg != 0 && + (prevFlag || nextFlag) + ) + { + change_opcode(instr, PC_ADDI); + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = 0; + instr->args[2].data.imm.obj = NULL; + change_num_operands(instr, 3); + } + } + + return 0; +} + +static int rotatedefinedusedtest(UInt32 *masks, PCode *instr, PCode *a, PCode *b, PCode *subfic) { + PCode *scan; + PCodeArg *op; + int i; + int reg1; + int reg2; + + if ( + (masks[RegClass_GPR] & (1 << subfic->args[0].data.reg.reg)) && + subfic->args[0].data.reg.reg != instr->args[0].data.reg.reg && + subfic->args[0].data.reg.reg != a->args[2].data.reg.reg + ) + return 1; + + for (scan = instr->block->firstPCode; scan != instr->block->lastPCode; scan = scan->nextPCode) { + if (scan == a) break; + if (scan == b) break; + if (scan == subfic) break; + } + + reg1 = a->args[1].data.reg.reg; + reg2 = subfic->args[1].data.reg.reg; + while (scan != instr) { + for (op = instr->args, i = instr->argCount; i--; op++) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + ( + ( + (op->data.reg.reg == reg1 || op->data.reg.reg == reg2) && + (op->data.reg.effect & EffectWrite) + ) + || + ( + op->data.reg.reg == subfic->args[0].data.reg.reg && (op->data.reg.effect & EffectRead) + ) + ) && + scan != a && + scan != b && + scan != subfic + ) + return 1; + } + + scan = scan->nextPCode; + } + + return 0; +} + +static int SRW_SUBFIC_RLW_OR(PCode *instr, UInt32 *masks) { + PCode *subfic; + PCode *defInstr1 = defininginstruction[instr->defID + 1]; + PCode *defInstr2 = defininginstruction[instr->defID + 2]; + + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + return 0; + + if ( + (masks[RegClass_GPR] & (1 << instr->args[1].data.reg.reg)) && + instr->args[1].data.reg.reg != instr->args[0].data.reg.reg + ) + return 0; + + if ( + (masks[RegClass_GPR] & (1 << instr->args[2].data.reg.reg)) && + instr->args[1].data.reg.reg != instr->args[0].data.reg.reg + ) + return 0; + + if (defInstr1->op != PC_SRW && defInstr1->op != PC_SLW) + return 0; + if (defInstr2->op != PC_SRW && defInstr2->op != PC_SLW) + return 0; + + if (usedbetween(instr, defInstr1, &defInstr1->args[0])) + return 0; + if (usedbetween(instr, defInstr2, &defInstr2->args[0])) + return 0; + + if ( + defInstr1->op == PC_SRW && defInstr2->op == PC_SLW && + defInstr1->args[1].data.reg.reg == defInstr2->args[1].data.reg.reg + ) + { + subfic = defininginstruction[defInstr1->defID + 2]; + if ( + subfic->op == PC_SUBFIC && + subfic->args[1].data.reg.reg == defInstr2->args[2].data.reg.reg && + subfic->args[2].data.imm.value == 32 + ) + { + if (rotatedefinedusedtest(masks, instr, defInstr2, defInstr1, subfic)) + return 0; + + change_opcode(instr, PC_RLWNM); + + instr->args[1] = defInstr1->args[1]; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr1->defID + 1]; + + instr->args[2] = defInstr2->args[2]; + defininginstruction[instr->defID + 2] = defininginstruction[defInstr2->defID + 2]; + + instr->args[3].kind = PCOp_IMMEDIATE; + instr->args[3].data.imm.value = 0; + instr->args[3].data.imm.obj = NULL; + + instr->args[4].kind = PCOp_IMMEDIATE; + instr->args[4].data.imm.value = 31; + instr->args[4].data.imm.obj = NULL; + + deletepcode(defInstr1); + deletepcode(defInstr2); + deletepcode(subfic); + return 1; + } + + subfic = defininginstruction[defInstr2->defID + 2]; + if ( + subfic->op == PC_SUBFIC && + subfic->args[1].data.reg.reg == defInstr1->args[2].data.reg.reg && + subfic->args[2].data.imm.value == 32 + ) + { + if (rotatedefinedusedtest(masks, instr, defInstr2, defInstr1, subfic)) + return 0; + + change_opcode(instr, PC_RLWNM); + + instr->args[1] = defInstr1->args[1]; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr1->defID + 1]; + + instr->args[2] = defInstr2->args[2]; + defininginstruction[instr->defID + 2] = defininginstruction[defInstr2->defID + 2]; + + instr->args[3].kind = PCOp_IMMEDIATE; + instr->args[3].data.imm.value = 0; + instr->args[3].data.imm.obj = NULL; + + instr->args[4].kind = PCOp_IMMEDIATE; + instr->args[4].data.imm.value = 31; + instr->args[4].data.imm.obj = NULL; + + deletepcode(defInstr1); + deletepcode(defInstr2); + return 1; + } + } else if ( + defInstr1->op == PC_SLW && defInstr2->op == PC_SRW && + defInstr1->args[1].data.reg.reg == defInstr2->args[1].data.reg.reg + ) + { + subfic = defininginstruction[defInstr1->defID + 2]; + if ( + subfic->op == PC_SUBFIC && + subfic->args[1].data.reg.reg == defInstr2->args[2].data.reg.reg && + subfic->args[2].data.imm.value == 32 + ) + { + if (rotatedefinedusedtest(masks, instr, defInstr1, defInstr2, subfic)) + return 0; + + change_opcode(instr, PC_RLWNM); + + instr->args[1] = defInstr1->args[1]; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr1->defID + 1]; + + instr->args[2] = defInstr1->args[2]; + defininginstruction[instr->defID + 2] = defininginstruction[defInstr1->defID + 2]; + + instr->args[3].kind = PCOp_IMMEDIATE; + instr->args[3].data.imm.value = 0; + instr->args[3].data.imm.obj = NULL; + + instr->args[4].kind = PCOp_IMMEDIATE; + instr->args[4].data.imm.value = 31; + instr->args[4].data.imm.obj = NULL; + + deletepcode(defInstr1); + deletepcode(defInstr2); + return 1; + } + + subfic = defininginstruction[defInstr2->defID + 2]; + if ( + subfic->op == PC_SUBFIC && + subfic->args[1].data.reg.reg == defInstr1->args[2].data.reg.reg && + subfic->args[2].data.imm.value == 32 + ) + { + if (rotatedefinedusedtest(masks, instr, defInstr1, defInstr2, subfic)) + return 0; + + change_opcode(instr, PC_RLWNM); + + instr->args[1] = defInstr1->args[1]; + defininginstruction[instr->defID + 1] = defininginstruction[defInstr1->defID + 1]; + + instr->args[2] = defInstr1->args[2]; + defininginstruction[instr->defID + 2] = defininginstruction[defInstr1->defID + 2]; + + instr->args[3].kind = PCOp_IMMEDIATE; + instr->args[3].data.imm.value = 0; + instr->args[3].data.imm.obj = NULL; + + instr->args[4].kind = PCOp_IMMEDIATE; + instr->args[4].data.imm.value = 31; + instr->args[4].data.imm.obj = NULL; + + deletepcode(defInstr1); + deletepcode(defInstr2); + deletepcode(subfic); + return 1; + } + } + + return 0; +} + +static int RLWINM_RLWIMI_STW(PCode *instr, UInt32 *masks) { + PCode *newInstr; + Boolean isZeroOffset; + int flags; + PCode *scan; + int i; + PCode *array[4]; + + flags = 0; + isZeroOffset = 0; + if (instr->op == PC_STW && instr->args[2].kind == PCOp_IMMEDIATE && instr->args[2].data.imm.value == 0) + isZeroOffset = 1; + + scan = instr; + for (i = 0; i < 4; i++) { + if (scan->op == PC_RLWINM) + array[i] = defininginstruction[scan->defID + 1]; + else + array[i] = defininginstruction[scan->defID]; + + scan = array[i]; + if (array[0]->args[1].data.reg.reg != scan->args[1].data.reg.reg) + return 0; + + if (i < 3) { + if (scan->op != PC_RLWIMI) + return 0; + } else { + if (scan->op != PC_RLWINM) + return 0; + } + + if (scan->args[2].data.imm.value == 8) { + if (scan->args[3].data.imm.value == 24 && scan->args[4].data.imm.value == 31) { + if (flags & 1) + return 0; + flags |= 1; + } else if (scan->args[3].data.imm.value == 8 && scan->args[4].data.imm.value == 15) { + if (flags & 4) + return 0; + flags |= 4; + } else { + return 0; + } + } else if (scan->args[2].data.imm.value == 24) { + if (scan->args[3].data.imm.value == 0 && scan->args[4].data.imm.value == 7) { + if (flags & 8) + return 0; + flags |= 8; + } else if (scan->args[3].data.imm.value == 16 && scan->args[4].data.imm.value == 23) { + if (flags & 2) + return 0; + flags |= 2; + } else { + return 0; + } + } else { + return 0; + } + } + + if (definedbetween(instr, array[3], &array[0]->args[1])) + return 0; + + if (instr->op == PC_STWX) { + change_opcode(instr, PC_STWBRX); + instr->args[0] = array[0]->args[1]; + defininginstruction[instr->defID] = defininginstruction[array[3]->defID + 1]; + return 1; + } + + if (instr->op == PC_STW) { + if (!isZeroOffset) { + if (masks[RegClass_GPR] & (1 << array[0]->args[0].data.reg.reg)) + return 0; + + if (usedbetween(array[2], array[3], &array[0]->args[0])) + return 0; + if (usedbetween(array[1], array[2], &array[0]->args[0])) + return 0; + if (usedbetween(array[0], array[1], &array[0]->args[0])) + return 0; + if (usedbetween(instr, array[0], &array[0]->args[0])) + return 0; + } + + defininginstruction[instr->defID] = defininginstruction[array[3]->defID + 1]; + + if (!isZeroOffset) { + newInstr = makepcode(PC_STWBRX, array[3]->args[1].data.reg.reg, 0, instr->args[0].data.reg.reg); + newInstr->alias = instr->alias; + change_opcode(instr, PC_ADDI); + insertpcodeafter(instr, newInstr); + + masks[RegClass_GPR] |= 1 << newInstr->args[0].data.reg.reg; + masks[RegClass_GPR] |= 1 << newInstr->args[2].data.reg.reg; + instr->args[0].data.reg.effect &= ~EffectRead; + instr->args[0].data.reg.effect |= EffectWrite; + defininginstruction[instr->defID] = instr; + + deletepcode(array[0]); + deletepcode(array[1]); + deletepcode(array[2]); + deletepcode(array[3]); + } else { + change_opcode(instr, PC_STWBRX); + instr->args[0] = array[0]->args[1]; + instr->args[2] = instr->args[1]; + defininginstruction[instr->defID + 2] = defininginstruction[instr->defID + 1]; + + instr->args[1].kind = PCOp_REGISTER; + instr->args[1].arg = RegClass_GPR; + instr->args[1].data.reg.reg = 0; + instr->args[1].data.reg.effect = 0; + } + + return 1; + } + + return 0; +} + +static int RLWINM_RLWIMI_STH(PCode *instr, UInt32 *masks) { + PCode *newInstr; + Boolean isZeroOffset; + int flags; + PCode *scan; + int i; + PCode *array[2]; + + flags = 0; + isZeroOffset = 0; + if (instr->op == PC_STH && instr->args[2].kind == PCOp_IMMEDIATE && instr->args[2].data.imm.value == 0) + isZeroOffset = 1; + + scan = instr; + for (i = 0; i < 2; i++) { + if (scan->op == PC_RLWINM) + array[i] = defininginstruction[scan->defID + 1]; + else + array[i] = defininginstruction[scan->defID]; + + scan = array[i]; + if (array[0]->args[1].data.reg.reg != scan->args[1].data.reg.reg) + return 0; + + if (i < 1) { + if (scan->op != PC_RLWIMI) + return 0; + } else { + if (scan->op != PC_RLWINM) + return 0; + } + + if (scan->args[2].data.imm.value == 8) { + if (scan->args[3].data.imm.value == 16 && scan->args[4].data.imm.value == 23) { + if (flags & 2) + return 0; + flags |= 2; + } else { + return 0; + } + } else if (scan->args[2].data.imm.value == 24) { + if (scan->args[3].data.imm.value == 24 && scan->args[4].data.imm.value == 31) { + if (flags & 1) + return 0; + flags |= 1; + } else { + return 0; + } + } else { + return 0; + } + } + + if (definedbetween(instr, array[1], &array[0]->args[1])) + return 0; + + if (instr->op == PC_STHX) { + change_opcode(instr, PC_STHBRX); + instr->args[0] = array[0]->args[1]; + defininginstruction[instr->defID] = defininginstruction[array[1]->defID + 1]; + return 1; + } + + if (instr->op == PC_STH) { + if (!isZeroOffset) { + if (masks[RegClass_GPR] & (1 << array[0]->args[0].data.reg.reg)) + return 0; + + if (usedbetween(array[0], array[1], &array[0]->args[0])) + return 0; + if (usedbetween(instr, array[0], &array[0]->args[0])) + return 0; + } + + defininginstruction[instr->defID] = defininginstruction[array[1]->defID + 1]; + + if (!isZeroOffset) { + newInstr = makepcode(PC_STHBRX, array[1]->args[1].data.reg.reg, 0, instr->args[0].data.reg.reg); + newInstr->alias = instr->alias; + change_opcode(instr, PC_ADDI); + + instr->args[0].data.reg.effect &= ~EffectRead; + instr->args[0].data.reg.effect |= EffectWrite; + defininginstruction[instr->defID] = instr; + + insertpcodeafter(instr, newInstr); + + masks[RegClass_GPR] |= 1 << newInstr->args[0].data.reg.reg; + masks[RegClass_GPR] |= 1 << newInstr->args[2].data.reg.reg; + + deletepcode(array[0]); + deletepcode(array[1]); + } else { + change_opcode(instr, PC_STHBRX); + instr->args[0] = array[0]->args[1]; + instr->args[2] = instr->args[1]; + defininginstruction[instr->defID + 2] = defininginstruction[instr->defID + 1]; + + instr->args[1].kind = PCOp_REGISTER; + instr->args[1].arg = RegClass_GPR; + instr->args[1].data.reg.reg = 0; + instr->args[1].data.reg.effect = 0; + } + + return 1; + } + + return 0; +} + +static void peepholeoptimizeblock(PCodeBlock *block) { + RegClass rclass; + PCode *instr; + PCodeArg *op; + int i; + Pattern *pattern; + UInt32 masks[RegClassMax]; + + for (rclass = 0; rclass < RegClassMax; rclass++) + masks[rclass] = liveregs[rclass][block->blockIndex].xC; + + for (instr = block->lastPCode; instr; instr = instr->prevPCode) { + if (dead(instr, masks)) { + deletepcode(instr); + } else { + pattern = peepholepatterns[instr->op]; + + while (pattern) { + if (pattern->func(instr, masks)) { + if (!instr->block) + break; + pattern = peepholepatterns[instr->op]; + } else { + pattern = pattern->next; + } + } + + if (instr->block) { + for (op = instr->args, i = instr->argCount; i--; op++) { + if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite)) + masks[op->arg] &= ~(1 << op->data.reg.reg); + } + + for (op = instr->args, i = instr->argCount; i--; op++) { + if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectRead)) + masks[op->arg] |= 1 << op->data.reg.reg; + } + } + } + } +} + +static SInt32 computepossiblemask(PCode *instr, short reg) { + SInt32 mask; + SInt32 val; + PCodeArg *op; + int i; + + mask = 0xFFFFFFFF; + while (instr) { + for (op = instr->args, i = instr->argCount; i--; op++) { + if (PC_OP_IS_WRITE_REGISTER(op, RegClass_GPR, reg)) { + switch (instr->op) { + case PC_LBZ: + case PC_LBZU: + case PC_LBZX: + case PC_LBZUX: + mask = 0xFF; + break; + + case PC_LHZ: + case PC_LHZU: + case PC_LHZX: + case PC_LHZUX: + mask = 0xFFFF; + break; + + case PC_LI: + mask = instr->args[1].data.imm.value; + break; + + case PC_SRAWI: + mask = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg) >> instr->args[2].data.imm.value; + break; + + case PC_RLWINM: + val = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg); + mask = (val << instr->args[2].data.imm.value) | ((UInt32) val >> (32 - instr->args[2].data.imm.value)); + + if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) + val = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) & ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); + else + val = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) | ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); + + mask &= val; + break; + + case PC_RLWIMI: + val = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg); + mask = (val << instr->args[2].data.imm.value) | ((UInt32) val >> (32 - instr->args[2].data.imm.value)); + + if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) + val = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) & ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); + else + val = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) | ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); + + mask &= val; + mask |= computepossiblemask(instr->prevPCode, instr->args[0].data.reg.reg); + break; + + case PC_OR: + mask = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg) | + computepossiblemask(instr->prevPCode, instr->args[2].data.reg.reg); + break; + + case PC_ORI: + mask = instr->args[2].data.imm.value | + computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg); + break; + + case PC_AND: + mask = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg) & + computepossiblemask(instr->prevPCode, instr->args[2].data.reg.reg); + break; + + case PC_ANDI: + mask = instr->args[2].data.imm.value & + computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg); + break; + + case PC_MR: + mask = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg); + break; + } + + return mask; + } + } + instr = instr->prevPCode; + } + + return mask; +} + +static UInt32 fillmaskholes(UInt32 mask) { + UInt32 oneBit; + UInt32 allBits; + UInt32 result; + + oneBit = 1; + allBits = 0xFFFFFFFF; + result = 0; + + if ((mask & 1) && (mask & 0x80000000)) { + result = 0xFFFFFFFF; + while ((mask & oneBit) == 1) { + oneBit <<= 1; + } + + while ((mask & oneBit) == 0) { + result &= ~oneBit; + oneBit <<= 1; + } + + return result; + } else { + while ((mask & oneBit) == 0 && (mask & allBits) != 0) { + oneBit <<= 1; + allBits <<= 1; + } + while ((mask & allBits) != 0) { + result |= oneBit; + oneBit <<= 1; + allBits <<= 1; + } + return result; + } +} + +static int canuseinsert(PCode *instr1, PCode *instr2, short reg) { + if (computepossiblemask(instr2, reg) & fillmaskholes(computepossiblemask(instr1, instr1->args[0].data.reg.reg))) + return 0; + return 1; +} + +static PCode *find_def_backwords(PCode *instr, short reg) { + int i; + + while (instr) { + for (i = 0; i < instr->argCount; i++) { + if (PC_OP_IS_WRITE_REGISTER(&instr->args[i], RegClass_GPR, reg)) + return instr; + } + instr = instr->prevPCode; + } + + return NULL; +} + +static void adjustforward(PCodeBlock *block) { + PCode *instr; + PCode *scan; + PCode *tmp; + PCodeArg *op; + int i; + short opcode; + short reg0; + short reg1; + SInt32 valA; + SInt32 valB; + + instr = block->firstPCode; + while (instr) { + if (instr->op == PC_RLWINM) { + SInt32 val2; + SInt32 val3; + SInt32 val4; + short start; + short end; + + short flag1 = 0; + short flag2 = 0; + reg0 = instr->args[0].data.reg.reg; + reg1 = instr->args[1].data.reg.reg; + val2 = instr->args[2].data.imm.value; + val3 = instr->args[3].data.imm.value; + val4 = instr->args[4].data.imm.value; + + for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { + opcode = scan->op; + if (opcode == PC_RLWINM && scan->args[1].data.reg.reg == reg0) { + if ( + scan->args[3].data.imm.value == val3 && + scan->args[4].data.imm.value == val4 && + scan->args[2].data.imm.value == 0 + ) + { + if (PCODE_FLAG_SET_F(scan) & fRecordBit) { + if (!flag1) { + pcsetrecordbit(instr); + change_opcode(scan, PC_MR); + scan->flags &= ~fRecordBit; + scan->flags |= fIsMove; + change_num_operands(scan, 2); + } else { + change_opcode(scan, PC_MR); + scan->args[2] = scan->args[5]; + change_num_operands(scan, 3); + } + } else { + change_opcode(scan, PC_MR); + change_num_operands(scan, 2); + } + } + else if ( + reg0 != reg1 && + !flag2 && + canmergemasks( + val3, + val4, + scan->args[2].data.imm.value, + scan->args[3].data.imm.value, + scan->args[4].data.imm.value, + &start, &end) + ) + { + scan->args[1].data.reg.reg = reg1; + scan->args[2].data.imm.value = (scan->args[2].data.imm.value + instr->args[2].data.imm.value) & 31; + scan->args[3].data.imm.value = start; + scan->args[4].data.imm.value = end; + } + } + else if ( + opcode == PC_SRAWI && + scan->args[1].data.reg.reg == reg0 && + reg0 != reg1 && + instr->args[2].data.imm.value == 0 && + !(computepossiblemask(instr, reg0) & 0x80000000) && + !flag2 && + canmergemasks(val3, val4, 32 - scan->args[2].data.imm.value, scan->args[2].data.imm.value, 31, &start, &end) && + !isSPRlive(scan, 0) + ) + { + insertpcodeafter(scan, makepcode( + PC_RLWINM, scan->args[0].data.reg.reg, reg1, + 32 - scan->args[2].data.imm.value, start, end + )); + if (PCODE_FLAG_SET_F(scan) & fRecordBit) + pcsetrecordbit(scan->nextPCode); + deletepcode(scan); + } + else if ( + opcode == PC_OR && + !flag2 && + reg0 != reg1 && + !(PCODE_FLAG_SET_F(scan) & fRecordBit) && + !(PCODE_FLAG_SET_F(instr) & fRecordBit) && + scan->args[0].data.reg.reg != instr->args[1].data.reg.reg + ) + { + if (scan->args[1].data.reg.reg == reg0 && canuseinsert(instr, scan, scan->args[2].data.reg.reg)) { + op = &scan->args[2]; + tmp = find_def_backwords(scan->prevPCode, scan->args[2].data.reg.reg); + if (tmp->op == PC_RLWINM && tmp->args[2].data.imm.value == 0) { + if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) + valA = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) & ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); + else + valA = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) | ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); + + if (tmp->args[3].data.imm.value <= tmp->args[4].data.imm.value) + valB = ((tmp->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> tmp->args[3].data.imm.value)) & ~(((tmp->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (tmp->args[4].data.imm.value + 1))); + else + valB = ((tmp->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> tmp->args[3].data.imm.value)) | ~(((tmp->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (tmp->args[4].data.imm.value + 1))); + + if (valA == ~valB) + op = &tmp->args[1]; + } + + change_opcode(scan, PC_MR); + scan->args[1] = *op; + change_num_operands(scan, 2); + + tmp = copypcode(instr); + change_opcode(tmp, PC_RLWIMI); + tmp->args[0] = scan->args[0]; + tmp->args[0].data.reg.effect |= EffectRead; + + if (ismaskconstant(fillmaskholes(computepossiblemask(instr, instr->args[0].data.reg.reg)), &start, &end)) { + tmp->args[3].data.imm.value = start; + tmp->args[4].data.imm.value = end; + } + + insertpcodeafter(scan, tmp); + break; + } + + if ( + scan->args[2].data.reg.reg == reg0 && + canuseinsert(instr, scan, scan->args[1].data.reg.reg) + ) + { + op = &scan->args[1]; + tmp = find_def_backwords(scan->prevPCode, scan->args[1].data.reg.reg); + if (tmp->op == PC_RLWINM && tmp->args[2].data.imm.value == 0) { + if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) + valA = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) & ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); + else + valA = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) | ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); + + if (tmp->args[3].data.imm.value <= tmp->args[4].data.imm.value) + valB = ((tmp->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> tmp->args[3].data.imm.value)) & ~(((tmp->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (tmp->args[4].data.imm.value + 1))); + else + valB = ((tmp->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> tmp->args[3].data.imm.value)) | ~(((tmp->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (tmp->args[4].data.imm.value + 1))); + + if (valA == ~valB) + op = &tmp->args[1]; + } + + change_opcode(scan, PC_MR); + scan->args[1] = *op; + change_num_operands(scan, 2); + + tmp = copypcode(instr); + change_opcode(tmp, PC_RLWIMI); + tmp->args[0] = scan->args[0]; + tmp->args[0].data.reg.effect |= EffectRead; + + if (ismaskconstant(fillmaskholes(computepossiblemask(instr, instr->args[0].data.reg.reg)), &start, &end)) { + tmp->args[3].data.imm.value = start; + tmp->args[4].data.imm.value = end; + } + + insertpcodeafter(scan, tmp); + break; + } + } + else if ( + !flag2 && + reg0 != reg1 && + val4 == 31 && + instr->args[2].data.imm.value == 0 && + ( + ((opcode == PC_STB || opcode == PC_STBX) && val3 <= 24) || + ((opcode == PC_STH || opcode == PC_STHX) && val3 <= 16) + ) && + scan->args[0].data.reg.reg == reg0 + ) + { + scan->args[0].data.reg.reg = reg1; + } + else if ( + opcode == PC_EXTSH && + scan->args[1].data.reg.reg == reg0 && + val2 == 0 && + val3 > 16 && + val3 < val4 + ) + { + change_opcode(scan, PC_MR); + if ((PCODE_FLAG_SET_F(scan) & fRecordBit) && !flag1) { + pcsetrecordbit(instr); + scan->flags &= ~fRecordBit; + scan->flags |= fIsMove; + change_num_operands(scan, 2); + } + } + else if ( + opcode == PC_EXTSB && + scan->args[1].data.reg.reg == reg0 && + val2 == 0 && + val3 > 24 && + val3 < val4 + ) + { + change_opcode(scan, PC_MR); + if ((PCODE_FLAG_SET_F(scan) & fRecordBit) && !flag1) { + pcsetrecordbit(instr); + scan->flags &= ~fRecordBit; + scan->flags |= fIsMove; + change_num_operands(scan, 2); + } + } + + for (op = scan->args, i = scan->argCount; i--; op++) { + if (PC_OP_IS_WRITE_REGISTER(op, RegClass_GPR, reg0)) { + scan = block->lastPCode; + break; + } + + if (PC_OP_IS_WRITE_REGISTER(op, RegClass_GPR, reg1)) + flag2 = 1; + + if (PC_OP_IS_REGISTER(op, RegClass_CRFIELD, 0)) + flag1 = 1; + } + } + + } else if ( + instr->op == PC_EXTSB && + (reg0 = instr->args[0].data.reg.reg) != (reg1 = instr->args[1].data.reg.reg) + ) + { + short flag = 0; + for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { + if ( + (scan->op >= PC_STB && scan->op <= PC_STBUX) && + scan->args[0].data.reg.reg == reg0 + ) + { + scan->args[0].data.reg.reg = reg1; + } + else if ( + (scan->op == PC_EXTSH || scan->op == PC_EXTSB) && + scan->args[1].data.reg.reg == reg0 + ) + { + change_opcode(scan, PC_MR); + if ((PCODE_FLAG_SET_F(scan) & fRecordBit) && !flag) { + pcsetrecordbit(instr); + scan->flags &= ~fRecordBit; + scan->flags |= fIsMove; + change_num_operands(scan, 2); + } + } + + for (op = scan->args, i = scan->argCount; i--; op++) { + if ( + PC_OP_IS_WRITE_ANY_REGISTER(op, RegClass_GPR) && + (op->data.reg.reg == reg0 || op->data.reg.reg == reg1) + ) + { + scan = block->lastPCode; + break; + } + + if (PC_OP_IS_REGISTER(op, RegClass_CRFIELD, 0)) + flag = 1; + } + } + } else if ( + instr->op == PC_EXTSH && + (reg0 = instr->args[0].data.reg.reg) != (reg1 = instr->args[1].data.reg.reg) + ) + { + short flag = 0; + for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { + if ( + ((scan->op >= PC_STB && scan->op <= PC_STBUX) || (scan->op >= PC_STH && scan->op <= PC_STHUX)) && + scan->args[0].data.reg.reg == reg0 + ) + { + scan->args[0].data.reg.reg = reg1; + } + else if (scan->op == PC_EXTSH && scan->args[1].data.reg.reg == reg0) + { + change_opcode(scan, PC_MR); + if ((PCODE_FLAG_SET_F(scan) & fRecordBit) && !flag) { + pcsetrecordbit(instr); + scan->flags &= ~fRecordBit; + scan->flags |= fIsMove; + change_num_operands(scan, 2); + } + } + + for (op = scan->args, i = scan->argCount; i--; op++) { + if ( + PC_OP_IS_WRITE_ANY_REGISTER(op, RegClass_GPR) && + (op->data.reg.reg == reg0 || op->data.reg.reg == reg1) + ) + { + scan = block->lastPCode; + break; + } + + if (PC_OP_IS_REGISTER(op, RegClass_CRFIELD, 0)) + flag = 1; + } + } + } else if ( + instr->op == PC_ADDI && + (reg0 = instr->args[0].data.reg.reg) == (reg1 = instr->args[1].data.reg.reg) && + instr->args[2].kind == PCOp_IMMEDIATE + ) + { + Boolean flag1 = 0; + Boolean flag2 = 0; + SInt32 val2 = instr->args[2].data.imm.value; + + for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { + if ((scan->flags & fIsWrite) && scan->args[0].data.reg.reg == reg0) + break; + + if ( + (scan->flags & (fIsRead | fIsWrite)) && + scan->args[1].data.reg.reg == reg0 && + scan->args[2].kind == PCOp_IMMEDIATE && + FITS_IN_SHORT(val2 + scan->args[2].data.imm.value) + ) + { + scan->args[2].data.imm.value += val2; + tmp = instr->prevPCode; + if ( + (scan->flags & fIsRead) && + scan->args[0].data.reg.reg == reg0 && + scan->args[0].kind == PCOp_REGISTER && + scan->args[0].arg == RegClass_GPR + ) + { + deletepcode(instr); + } else { + deletepcode(instr); + insertpcodeafter(scan, instr); + } + instr = tmp; + break; + } + + if ( + scan->op == PC_ADDI && + scan->args[1].data.reg.reg == reg0 && + scan->args[2].kind == PCOp_IMMEDIATE && + FITS_IN_SHORT(val2 + scan->args[2].data.imm.value) + ) + { + scan->args[2].data.imm.value += val2; + tmp = instr->prevPCode; + if (scan->args[0].data.reg.reg == reg0) { + deletepcode(instr); + } else { + deletepcode(instr); + insertpcodeafter(scan, instr); + } + instr = tmp; + break; + } + + if (scan->flags & (fIsBranch | fIsCall)) { + if (flag1 && scan->prevPCode != instr) { + tmp = instr->prevPCode; + deletepcode(instr); + insertpcodebefore(scan, instr); + instr = tmp; + } + break; + } + + for (op = scan->args, i = scan->argCount; i--; op++) { + if (PC_OP_IS_R_OR_W_REGISTER(op, RegClass_GPR, reg0)) { + if (flag1 && scan->prevPCode != instr) { + tmp = instr->prevPCode; + deletepcode(instr); + insertpcodebefore(scan, instr); + instr = tmp; + } + flag2 = 1; + break; + } + } + + if (flag2) + break; + + if (scan->op != PC_ADDI) + flag1 = 1; + + if (flag1 && !scan->nextPCode) { + tmp = instr->prevPCode; + deletepcode(instr); + appendpcode(block, instr); + instr = tmp; + break; + } + } + } + + if (instr) + instr = instr->nextPCode; + else + instr = block->firstPCode; + } +} + +static void installpattern(Opcode opcode, PeepholeFunc func) { + Pattern *pattern = lalloc(sizeof(Pattern)); + pattern->func = func; + pattern->next = peepholepatterns[opcode]; + peepholepatterns[opcode] = pattern; +} + +static void installpeepholepatterns(void) { + int i; + + for (i = 0; i < OPCODE_MAX; i++) + peepholepatterns[i] = NULL; + + installpattern(PC_AND, NOT_AND); + installpattern(PC_MR, LI_MR); + installpattern(PC_MR, L_MR); + installpattern(PC_FMR, L_FMR); + installpattern(PC_MR, MR_MR); + installpattern(PC_MR, MR_Rx_Rx); + installpattern(PC_FMR, FMR_FMR); + installpattern(PC_FMR, FMR_Fx_Fx); + installpattern(PC_VMR, VMR_VMRP); + installpattern(PC_VMR, VMR_VMR); + installpattern(PC_VMR, VMR_Vx_Vx); + installpattern(PC_VMR, VSPLTIS_VMR); + installpattern(PC_CMPI, MR_CMPI); + installpattern(PC_RLWIMI, RLWINM_RLWINM); + installpattern(PC_RLWINM, RLWINM_RLWINM); + installpattern(PC_RLWINM, EXTSB_RLWINM); + installpattern(PC_RLWINM, EXTSH_RLWINM); + installpattern(PC_RLWINM, LBZ_RLWINM); + installpattern(PC_RLWINM, LHZ_RLWINM); + installpattern(PC_EXTSH, LHA_EXTSH); + installpattern(PC_STW, RLWINM_RLWIMI_STW); + installpattern(PC_STWX, RLWINM_RLWIMI_STW); + installpattern(PC_STH, RLWINM_RLWIMI_STH); + installpattern(PC_STHX, RLWINM_RLWIMI_STH); + installpattern(PC_LBZ, ADDI_L_S); + installpattern(PC_LHZ, ADDI_L_S); + installpattern(PC_LHA, ADDI_L_S); + installpattern(PC_LWZ, ADDI_L_S); + installpattern(PC_STB, ADDI_L_S); + installpattern(PC_STH, ADDI_L_S); + installpattern(PC_STW, ADDI_L_S); + installpattern(PC_LFS, ADDI_L_S); + installpattern(PC_LFD, ADDI_L_S); + installpattern(PC_STFS, ADDI_L_S); + installpattern(PC_STFD, ADDI_L_S); + installpattern(PC_LBZU, ADDI_LU_SU); + installpattern(PC_LHZU, ADDI_LU_SU); + installpattern(PC_LHAU, ADDI_LU_SU); + installpattern(PC_LWZU, ADDI_LU_SU); + installpattern(PC_STBU, ADDI_LU_SU); + installpattern(PC_STHU, ADDI_LU_SU); + installpattern(PC_STWU, ADDI_LU_SU); + installpattern(PC_LFSU, ADDI_LU_SU); + installpattern(PC_LFDU, ADDI_LU_SU); + installpattern(PC_STFSU, ADDI_LU_SU); + installpattern(PC_STFDU, ADDI_LU_SU); + installpattern(PC_LBZ, L_S_ADDI); + installpattern(PC_LHZ, L_S_ADDI); + installpattern(PC_LHA, L_S_ADDI); + installpattern(PC_LWZ, L_S_ADDI); + installpattern(PC_STB, L_S_ADDI); + installpattern(PC_STH, L_S_ADDI); + installpattern(PC_STW, L_S_ADDI); + installpattern(PC_LFS, L_S_ADDI); + installpattern(PC_LFD, L_S_ADDI); + installpattern(PC_STFS, L_S_ADDI); + installpattern(PC_STFD, L_S_ADDI); + installpattern(PC_STB, L_S); + installpattern(PC_STH, L_S); + installpattern(PC_STW, L_S); + installpattern(PC_STFS, L_S); + installpattern(PC_STFD, L_S); + installpattern(PC_STBX, L_S); + installpattern(PC_STHX, L_S); + installpattern(PC_STWX, L_S); + installpattern(PC_STFSX, L_S); + installpattern(PC_STFDX, L_S); + installpattern(PC_BT, LBZ_EXTSB_CMPI_BC); + installpattern(PC_BF, LBZ_EXTSB_CMPI_BC); + installpattern(PC_BT, RLWINM_CMPLI_BC); + installpattern(PC_BF, RLWINM_CMPLI_BC); + installpattern(PC_BT, LI_CMP_BC); + installpattern(PC_BF, LI_CMP_BC); + installpattern(PC_RLWINM, RLWINM_RLWINM); + installpattern(PC_MULLI, MULLI_MULLI); + installpattern(PC_ADDI, ADDI_ADDI); + installpattern(PC_SRAWI, SRAWI_SRAWI); + installpattern(PC_MR, MR_ADDI); + installpattern(PC_OR, SRW_SUBFIC_RLW_OR); +} + +void peepholeoptimizeforward(Object *func) { + PCodeBlock *block; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (block->pcodeCount >= 2) + adjustforward(block); + } +} + +void peepholemergeblocks(Object *func, Boolean flag) { + PCodeBlock *block; + PCodeBlock *next; + Boolean flag2; + PCode *instr; + PCode *nextinstr; + PCLink *link; + PCLink *link2; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + flag2 = 0; + next = block->nextBlock; + + if (!flag) { + flag2 = next && (next->flags & fIsEpilogue); + if (block->flags & fIsProlog) + continue; + } + + if (block->pcodeCount > 0) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if (instr->flags & (fIsCall | fSideEffects)) + break; + } + + if (instr) + continue; + + instr = block->lastPCode; + if (instr && instr->op == PC_B) { + if (instr->args[0].kind == PCOp_LABEL && instr->args[0].data.label.label->block == next) + deletepcode(instr); + else + continue; + } + + instr = block->lastPCode; + if (instr && (instr->flags & fIsBranch) && instr->op != PC_B) + continue; + + while ( + block->successors->block == next && + block->successors->nextLink == NULL && + next->predecessors->block == block && + next->predecessors->nextLink == NULL && + !flag2 && + !(next->flags & fPCBlockFlag8000) && + (block->pcodeCount + next->pcodeCount) <= 100 + ) + { + if (next->pcodeCount > 0) { + for (instr = next->firstPCode; instr; instr = nextinstr) { + nextinstr = instr->nextPCode; + if (instr->flags & (fIsCall | fSideEffects)) + break; + + deletepcode(instr); + if (instr->op != PC_B) { + appendpcode(block, instr); + } else if (instr->args[0].kind == PCOp_LABEL) { + if (instr->args[0].data.label.label->block != next->nextBlock) + appendpcode(block, instr); + } else { + appendpcode(block, instr); + } + } + } + + if (next->pcodeCount != 0) + break; + if (next == epilogue) + break; + + block->successors = next->successors; + + for (link = block->successors; link; link = link->nextLink) { + for (link2 = link->block->predecessors; link2; link2 = link2->nextLink) { + if (link2->block == next) { + link2->block = block; + break; + } + } + } + + block->nextBlock = next->nextBlock; + if (block->nextBlock) + block->nextBlock->prevBlock = block; + + next->flags |= fDeleted; + next = block->nextBlock; + + if (!flag) + flag2 = next && (next->flags & fIsEpilogue); + } + } + } +} + +void peepholeoptimizepcode(Object *func) { + PCodeBlock *block; + + installpeepholepatterns(); + computeliveregisters(func); + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (block->pcodeCount >= 1) { + computeinstructionpredecessors(block); + peepholeoptimizeblock(block); + freeoheap(); + } + } +} diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/StackFrame.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/StackFrame.c new file mode 100644 index 0000000..6fa4524 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/StackFrame.c @@ -0,0 +1,1252 @@ +#include "compiler/StackFrame.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/RegisterInfo.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +#define ALIGN(thing, alignment) ( ~((alignment) - 1) & ((thing) + (alignment) - 1) ) +#define ALIGN_REMAINDER(thing, alignment) ( ALIGN(thing, alignment) - (thing) ) + +Boolean requires_frame; +Boolean makes_call; +Boolean uses_globals; +Boolean dynamic_stack; +Boolean large_stack; +static SInt32 out_param_alignment; +static SInt32 in_parameter_size; +static SInt32 in_param_alignment; +static SInt32 frame_alignment; +static SInt32 alloca_alignment; +static SInt32 linkage_area_size; +static SInt32 parameter_area_size; +static SInt32 parameter_area_size_estimate; +static SInt32 local_data_size; +static SInt32 local_data_limit; +static SInt32 large_data_near_size; +static SInt32 large_data_far_size; +static ObjectList *local_objects[ObjClassMax]; +static ObjectList *local_objects_tail[ObjClassMax]; +static SInt32 non_volatile_save_offset[RegClassMax]; +static SInt32 VRSAVE_save_offset; +static SInt32 LR_save_offset; +static SInt32 nonvolatile_save_size; +static UInt32 vrsave_mask; +static SInt32 frame_size; +static SInt32 frame_size_estimate; +static SInt32 genuine_frame_size; +static Object *dummylocal; +static Boolean dynamic_align_stack; +static Boolean has_varargs; +static Boolean compressing_data_area; +static PCode *setup_caller_sp; +static PCode *align_instr1; +static PCode *align_instr2; +static short vrsave_register; +static PCode *loadvrsave; +static PCode *storevrsave; +Object *dummyvaparam; +void *dummyprofiler; + +// forward declarations +static void insert_local_object(UInt8 oclass, Object *obj); +static void compress_data_area(void); +static UInt32 align_bits(UInt32 value, UInt8 bitcount); +static Boolean use_helper_function(char rclass); +static Boolean need_link_register(void); +static void call_helper_function(char *name, char rclass, short effect); +static void save_nonvolatile_FPRs(int reg, SInt32 offset); +static void save_nonvolatile_VRs(int reg, SInt32 offset); +static void restore_nonvolatile_FPRs(int reg, SInt32 offset); +static void restore_nonvolatile_VRs(int reg, SInt32 offset); +static void save_nonvolatile_GPRs(int reg, SInt32 offset); +static void restore_nonvolatile_GPRs(int reg, SInt32 offset); +static void do_allocate_dynamic_stack_space(Boolean isConstantSize, int reg1, int reg2, SInt32 size); + +void init_stack_globals(Object *funcobj) { + RegClass rclass; + ObjClass oclass; + + requires_frame = 0; + makes_call = 0; + uses_globals = 0; + dynamic_stack = 0; + large_stack = 0; + vrsave_register = -1; + dynamic_align_stack = 0; + compressing_data_area = 0; + align_instr1 = NULL; + align_instr2 = NULL; + setup_caller_sp = NULL; + dummyvaparam = NULL; + loadvrsave = NULL; + storevrsave = NULL; + local_data_size = 0; + local_data_limit = 0x2000; + large_data_near_size = 0; + large_data_far_size = 0; + frame_size_estimate = 0; + in_parameter_size = 0; + parameter_area_size = 0; + parameter_area_size_estimate = 0; + frame_alignment = 8; + out_param_alignment = 8; + in_param_alignment = 8; + alloca_alignment = 0; + has_varargs = 0; + linkage_area_size = 0; + frame_size = 0; + genuine_frame_size = 0; + nonvolatile_save_size = -1; + VRSAVE_save_offset = -1; + LR_save_offset = -1; + + for (rclass = 0; rclass < RegClassMax; rclass++) + non_volatile_save_offset[rclass] = -1; + + dummyprofiler = NULL; + dummyvaparam = NULL; + dummylocal = NULL; + + for (oclass = 0; oclass < ObjClassMax; oclass++) { + local_objects[oclass] = NULL; + local_objects_tail[oclass] = NULL; + } +} + +void init_frame_sizes(Boolean has_varargs) { + ObjectList *scan; + Object *obj; + SInt32 r30; + SInt32 align; + SInt32 mask; + + r30 = in_parameter_size + parameter_area_size_estimate; + frame_size_estimate = r30 + 2484; + for (scan = locals; scan; scan = scan->next) { + obj = scan->object; + { + align = CMach_AllocationAlignment(obj->type, obj->qual) - 1; + mask = ~align; + } + frame_size_estimate = (frame_size_estimate + align) & mask; + frame_size_estimate += obj->type->size; + } + + if (frame_size_estimate > 0x8000) { + dynamic_stack = 1; + large_stack = 1; + requires_frame = 1; + } + + local_data_limit = 0x8000 - (r30 + 2484); + + if (dynamic_stack) { + requires_frame = 1; + dummylocal = galloc(sizeof(Object)); + memclrw(dummylocal, sizeof(Object)); + dummylocal->type = (Type *) &stvoid; + dummylocal->otype = OT_OBJECT; + dummylocal->name = GetHashNameNode(""); + dummylocal->datatype = DLOCAL; + dummylocal->u.var.info = CodeGen_GetNewVarInfo(); + dummylocal->u.var.info->flags |= VarInfoFlag80; + dummylocal->u.var.info->noregister = 1; + } + + if (dynamic_stack) { + retain_register(NULL, RegClass_GPR, 31); + _FP_ = 31; + } else { + _FP_ = 1; + } +} + +void assign_local_memory(Object *obj) { + // some misassigned registers x.x + short align; + VarInfo *vi; + + align = CMach_AllocationAlignment(obj->type, obj->qual); + if (!compressing_data_area && (obj->u.var.info->flags & VarInfoFlag80)) + return; + + update_frame_align(align); + if (local_data_size + (ALIGN_REMAINDER(local_data_size, align) + ALIGN(obj->type->size, align)) < local_data_limit) { + local_data_size = ALIGN(local_data_size, align); + vi = Registers_GetVarInfo(obj); + vi->flags &= ~VarInfoFlag2; + vi->flags |= VarInfoFlag80; + obj->u.var.uid = local_data_size; + local_data_size += ALIGN(obj->type->size, align); + insert_local_object(ObjClass0, obj); + return; + } + if (compressing_data_area || obj->type->size <= 32) { + large_data_near_size = ALIGN(large_data_near_size, align); + vi = Registers_GetVarInfo(obj); + vi->flags &= ~VarInfoFlag2; + vi->flags |= VarInfoFlag80; + obj->u.var.uid = 0x8000 + large_data_near_size; + large_data_near_size += ALIGN(obj->type->size, align); + insert_local_object(ObjClass1, obj); + } else { + large_data_far_size = ALIGN(large_data_far_size, align); + vi = Registers_GetVarInfo(obj); + vi->flags &= ~VarInfoFlag2; + vi->flags |= VarInfoFlag80; + obj->u.var.uid = 0x10000 + large_data_far_size; + large_data_far_size += ALIGN(obj->type->size, align); + insert_local_object(ObjClass2, obj); + } +} + +void assign_locals_to_memory(ObjectList *first) { + ObjectList *list; + Object *obj; + SInt32 i; + + for (i = 1; i < 1024; i <<= 1) { + for (list = first; list; list = list->next) { + obj = list->object; + if (Registers_GetVarInfo(obj)->used) { + if ((Registers_GetVarInfo(obj) ? Registers_GetVarInfo(obj)->reg : 0) == 0) { + if (obj->type->size <= i) + assign_local_memory(obj); + } + } + } + } + + for (list = first; list; list = list->next) { + obj = list->object; + if (Registers_GetVarInfo(obj)->used) { + if ((Registers_GetVarInfo(obj) ? Registers_GetVarInfo(obj)->reg : 0) == 0) { + assign_local_memory(list->object); + } + } + + if (obj->type && IS_TYPE_ARRAY(obj->type) && IS_TYPE_VECTOR(TYPE_POINTER(obj->type)->target)) + has_altivec_arrays = 1; + } +} + +void compute_frame_sizes(void) { + SInt32 altivec_size; + SInt32 altivec_offset; + + CError_ASSERT(897, alloca_alignment == 0 || alloca_alignment == frame_alignment); + + update_asm_nonvolatile_registers(); + LR_save_offset = 8; + non_volatile_save_offset[RegClass_FPR] = -(used_nonvolatile_registers[RegClass_FPR] * 8); + non_volatile_save_offset[RegClass_GPR] = -(((15 - non_volatile_save_offset[RegClass_FPR]) & ~15) + used_nonvolatile_registers[RegClass_GPR] * 4); + nonvolatile_save_size = -non_volatile_save_offset[RegClass_GPR]; + non_volatile_save_offset[RegClass_CRFIELD] = 4; + VRSAVE_save_offset = -1; + non_volatile_save_offset[RegClass_VR] = -1; + + if (copts.altivec_model) { + if (vrsave_mask) { + VRSAVE_save_offset = non_volatile_save_offset[RegClass_GPR] - 4; + nonvolatile_save_size = nonvolatile_save_size + 4; + } + altivec_size = used_nonvolatile_registers[RegClass_VR] * 16; + if (altivec_size > 0) + nonvolatile_save_size = ALIGN(nonvolatile_save_size + altivec_size, frame_alignment); + } + + if (parameter_area_size) + requires_frame = 1; + + compress_data_area(); + local_data_size = ALIGN(local_data_size, frame_alignment); + nonvolatile_save_size = ALIGN(nonvolatile_save_size, frame_alignment); + if (!requires_frame && (local_data_size + nonvolatile_save_size) <= 224) { + CError_ASSERT(1005, !dynamic_align_stack); + linkage_area_size = 0; + frame_size = 0; + genuine_frame_size = local_data_size + nonvolatile_save_size; + } else { + requires_frame = 1; + if (parameter_area_size < 32) + parameter_area_size = 32; + parameter_area_size = ALIGN(parameter_area_size + 24, frame_alignment) - 24; + if (large_stack) { + CError_ASSERT(1019, !large_data_far_size); + large_data_near_size += parameter_area_size; + parameter_area_size = 0; + } + linkage_area_size = 24; + frame_size = nonvolatile_save_size + (altivec_offset = parameter_area_size + 24 + local_data_size); + if (copts.altivec_model && used_nonvolatile_registers[RegClass_VR]) + non_volatile_save_offset[RegClass_VR] = altivec_offset; + frame_size += ALIGN_REMAINDER(frame_size, 16); + frame_size = ALIGN(frame_size, frame_alignment); + genuine_frame_size = frame_size; + } + if (!large_stack && frame_size > 0x7FFF) + CError_ErrorTerm(CErrorStr210); +} + +static void allocate_new_frame(int reg1, int reg2) { + if (dynamic_align_stack) { + CError_ASSERT(1116, reg1 != _CALLER_SP_); + emitpcode(PC_RLWINM, reg1, 1, 0, align_bits(frame_alignment, 1), 31); + if (frame_size > 0x7FFF) { + CError_FATAL(1122); + return; + } + + if (frame_size) + emitpcode(PC_SUBFIC, reg1, reg1, -frame_size); + else + emitpcode(PC_SUBFIC, reg1, reg1, -genuine_frame_size); + + if (reg2) + emitpcode(PC_MR, reg2, 1); + + emitpcode(PC_STWUX, 1, 1, reg1); + } else { + if (frame_size > 0x7FFF) + CError_FATAL(1153); + else + emitpcode(PC_STWU, 1, 1, 0, -frame_size); + + if (reg2) + emitpcode(PC_MR, reg2, 1); + } +} + +void generate_prologue(PCodeBlock *block, Boolean has_varargs) { + PCodeBlock *save_block; + Boolean needs_lr; + Statement *save_statement; + Statement stmt; + UInt32 vrsave_low; + UInt32 vrsave_high; + + save_block = pclastblock; + needs_lr = need_link_register(); + save_statement = current_statement; + stmt.sourceoffset = functionbodyoffset; + current_statement = &stmt; + pclastblock = block; + + if (setup_caller_sp && setup_caller_sp->block) { + if ( + setup_caller_sp->op == PC_MR && + setup_caller_sp->args[1].kind == PCOp_REGISTER && + setup_caller_sp->args[1].arg == RegClass_GPR && + setup_caller_sp->args[1].data.reg.reg == _FP_ + ) + CError_FATAL(1197); + + _CALLER_SP_ = setup_caller_sp->args[0].data.reg.reg; + deletepcode(setup_caller_sp); + setup_caller_sp = NULL; + } else if (_CALLER_SP_ != _FP_) { + _CALLER_SP_ = -1; + } + + if (align_instr1 && align_instr1->block) { + deletepcode(align_instr1); + align_instr1 = NULL; + } + + if (align_instr2 && align_instr2->block) { + deletepcode(align_instr2); + align_instr2 = NULL; + } + + if (loadvrsave && loadvrsave->block) { + deletepcode(loadvrsave); + loadvrsave = NULL; + } + + if (storevrsave && storevrsave->block) { + deletepcode(storevrsave); + storevrsave = NULL; + } + + if (needs_lr) + emitpcode(PC_MFLR, 0); + + if (used_nonvolatile_registers[RegClass_CRFIELD]) { + emitpcode(PC_MFCR, 12); + emitpcode(PC_STW, 12, 1, 0, non_volatile_save_offset[RegClass_CRFIELD]); + } + + if (used_nonvolatile_registers[RegClass_FPR]) + save_nonvolatile_FPRs(1, 0); + if (used_nonvolatile_registers[RegClass_GPR]) + save_nonvolatile_GPRs(1, 0); + if (needs_lr) + emitpcode(PC_STW, 0, 1, 0, 8); + + if (frame_size) { + if (vrsave_mask) { + emitpcode(PC_MFSPR, 0, 256); + emitpcode(PC_STW, 0, 1, 0, VRSAVE_save_offset); + vrsave_register = 0; + } + allocate_new_frame(12, (_CALLER_SP_ > 0 && _CALLER_SP_ != _FP_) ? _CALLER_SP_ : 0); + } else { + CError_ASSERT(1326, !dynamic_align_stack); + if (vrsave_mask) + emitpcode(PC_MFSPR, vrsave_register, 256); + } + + if (vrsave_mask) { + vrsave_high = vrsave_mask >> 16; + vrsave_low = vrsave_mask & 0xFFFF; + if (vrsave_mask == 0xFFFFFFFF) { + emitpcode(PC_LI, 0, -1); + } else { + if (vrsave_high) + emitpcode(PC_ORIS, 0, vrsave_register, vrsave_high); + if (vrsave_low) + emitpcode(PC_ORI, 0, 0, vrsave_low); + } + emitpcode(PC_MTSPR, 256, 0); + } + + if (used_nonvolatile_registers[RegClass_VR]) + save_nonvolatile_VRs(1, 0); + + if (dynamic_stack) + emitpcode(PC_MR, 31, 1); + + if (large_stack) + do_allocate_dynamic_stack_space(1, 11, 0, large_data_near_size); + + block->flags |= fIsProlog; + pclastblock = save_block; + current_statement = save_statement; +} + +void generate_epilogue(PCodeBlock *block, Boolean add_blr) { + PCodeBlock *save_block; + Boolean needs_lr; + Statement *save_statement; + Statement stmt; + + save_block = pclastblock; + needs_lr = need_link_register(); + save_statement = current_statement; + if (!save_statement) { + stmt.sourceoffset = current_linenumber; + current_statement = &stmt; + } + pclastblock = block; + + if (used_nonvolatile_registers[RegClass_VR]) + restore_nonvolatile_VRs(_FP_, 0); + + if (dynamic_align_stack) { + load_store_register(PC_LWZ, 1, 1, NULL, 0); + setpcodeflags(fSideEffects); + if (needs_lr) + load_store_register(PC_LWZ, 0, 1, 0, 8); + } else { + if (needs_lr) + load_store_register(PC_LWZ, 0, _FP_, 0, frame_size + 8); + if (frame_size > 0) { + if (dynamic_stack) { + load_store_register(PC_LWZ, 1, 1, 0, 0); + setpcodeflags(fSideEffects); + } else { + emitpcode(PC_ADDI, 1, 1, 0, frame_size); + setpcodeflags(fSideEffects); + } + } + } + + if (used_nonvolatile_registers[RegClass_CRFIELD]) { + load_store_register(PC_LWZ, 12, 1, NULL, non_volatile_save_offset[RegClass_CRFIELD]); + emitpcode(PC_MTCRF, 255, 12); + } + + if (vrsave_mask) { + if (!requires_frame) { + emitpcode(PC_MTSPR, 256, vrsave_register); + } else { + emitpcode(PC_LWZ, 11, 1, 0, VRSAVE_save_offset); + emitpcode(PC_MTSPR, 256, 11); + } + } + + if (used_nonvolatile_registers[RegClass_FPR]) + restore_nonvolatile_FPRs(1, 0); + if (needs_lr && !use_helper_function(RegClass_GPR)) + emitpcode(PC_MTLR, 0); + + if (used_nonvolatile_registers[RegClass_GPR]) + restore_nonvolatile_GPRs(1, 0); + if (needs_lr && use_helper_function(RegClass_GPR)) + emitpcode(PC_MTLR, 0); + + if (add_blr) { + emitpcode(PC_BLR); + setpcodeflags(fIsVolatile); + } + + block->flags |= fIsEpilogue; + pclastblock = save_block; + current_statement = save_statement; +} + +static void load_base_offset(int dest_reg, int base_reg, SInt32 offset) { + if (offset) + emitpcode(PC_ADDI, dest_reg, base_reg, 0, offset); + else + emitpcode(PC_MR, dest_reg, base_reg); +} + +static void save_nonvolatile_FPRs(int reg, SInt32 offset) { + short i; + SInt32 o; + + o = offset + non_volatile_save_offset[RegClass_FPR]; + + if (!use_helper_function(RegClass_FPR)) { + for (i = 1; i <= used_nonvolatile_registers[RegClass_FPR]; i++) { + emitpcode(PC_STFD, 32 - i, reg, NULL, o + (used_nonvolatile_registers[RegClass_FPR] - i) * 8); + setpcodeflags(fIsVolatile); + } + } else { + load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_FPR] * 8); + call_helper_function("__save_fpr_%d", RegClass_FPR, EffectRead); + } +} + +static void save_nonvolatile_VRs(int reg, SInt32 offset) { + short i; + SInt32 o; + + o = offset + non_volatile_save_offset[RegClass_VR]; + + if (!use_helper_function(RegClass_VR)) { + for (i = 1; i <= used_nonvolatile_registers[RegClass_VR]; i++) { + emitpcode(PC_LI, 0, o + (used_nonvolatile_registers[RegClass_VR] - i) * 16); + emitpcode(PC_STVX, 32 - i, reg, 0); + setpcodeflags(fIsVolatile); + } + } else { + load_base_offset(0, reg, o + used_nonvolatile_registers[RegClass_VR] * 16); + call_helper_function("__savev%d", RegClass_VR, EffectRead); + } +} + +static void restore_nonvolatile_FPRs(int reg, SInt32 offset) { + short i; + SInt32 o; + + o = offset + non_volatile_save_offset[RegClass_FPR]; + + if (!use_helper_function(RegClass_FPR)) { + for (i = 1; i <= used_nonvolatile_registers[RegClass_FPR]; i++) { + load_store_register(PC_LFD, 32 - i, reg, NULL, o + (used_nonvolatile_registers[RegClass_FPR] - i) * 8); + setpcodeflags(fIsVolatile); + } + } else { + load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_FPR] * 8); + call_helper_function("__restore_fpr_%d", RegClass_FPR, EffectWrite); + } +} + +static void restore_nonvolatile_VRs(int reg, SInt32 offset) { + short i; + SInt32 o; + + o = offset + non_volatile_save_offset[RegClass_VR]; + + if (!use_helper_function(RegClass_VR)) { + for (i = 1; i <= used_nonvolatile_registers[RegClass_VR]; i++) { + emitpcode(PC_LI, 0, o + (used_nonvolatile_registers[RegClass_VR] - i) * 16); + setpcodeflags(fIsVolatile); + emitpcode(PC_LVX, 32 - i, reg, 0); + setpcodeflags(fIsVolatile); + } + } else { + load_base_offset(0, reg, o + used_nonvolatile_registers[RegClass_VR] * 16); + call_helper_function("__restv%d", RegClass_VR, EffectWrite); + } +} + +static void save_nonvolatile_GPRs(int reg, SInt32 offset) { + int i; + SInt32 o; + + o = offset + non_volatile_save_offset[RegClass_GPR]; + + if (!use_helper_function(RegClass_GPR)) { + if (copts.use_lmw_stmw && ((used_nonvolatile_registers[RegClass_GPR] > 4) || (copts.optimizesize && (used_nonvolatile_registers[RegClass_GPR] > 1)))) { + emitpcode(PC_STMW, used_nonvolatile_registers[RegClass_GPR] - 1, 32 - used_nonvolatile_registers[RegClass_GPR], reg, 0, o); + } else { + for (i = 1; i <= used_nonvolatile_registers[RegClass_GPR]; i++) { + emitpcode(PC_STW, 32 - i, reg, 0, o + (used_nonvolatile_registers[RegClass_GPR] - i) * 4); + } + } + } else { + load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_GPR] * 4); + call_helper_function("__savegpr_%d", RegClass_GPR, EffectRead); + } +} + +static void restore_nonvolatile_GPRs(int reg, SInt32 offset) { + int i; + SInt32 o; + + o = offset + non_volatile_save_offset[RegClass_GPR]; + + if (!use_helper_function(RegClass_GPR)) { + if (copts.use_lmw_stmw && ((used_nonvolatile_registers[RegClass_GPR] > 4) || (copts.optimizesize && (used_nonvolatile_registers[RegClass_GPR] > 1)))) { + emitpcode(PC_LMW, used_nonvolatile_registers[RegClass_GPR] - 1, 32 - used_nonvolatile_registers[RegClass_GPR], reg, 0, o); + setpcodeflags(fIsVolatile); + } else { + for (i = 1; i <= used_nonvolatile_registers[RegClass_GPR]; i++) { + emitpcode(PC_LWZ, 32 - i, reg, 0, o + (used_nonvolatile_registers[RegClass_GPR] - i) * 4); + setpcodeflags(fIsVolatile); + } + } + } else { + load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_GPR] * 4); + call_helper_function("__restgpr_%d", RegClass_GPR, EffectWrite); + } +} + +static void do_allocate_dynamic_stack_space(Boolean isConstantSize, int reg1, int reg2, SInt32 size) { + load_store_register(PC_LWZ, reg2, 1, NULL, 0); + if (isConstantSize) { + size = ALIGN(size, frame_alignment); + if (size < 0x8000) { + emitpcode(PC_STWU, reg2, 1, 0, -size); + } else { + emitpcode(PC_LIS, reg1, 0, (short) HIGH_PART(-size)); + if (-size) + emitpcode(PC_ADDI, reg1, reg1, 0, LOW_PART(-size)); + emitpcode(PC_STWUX, reg2, 1, reg1); + setpcodeflags(fIsVolatile | fSideEffects); + } + } else { + emitpcode(PC_STWUX, reg2, 1, reg1); + setpcodeflags(fIsVolatile | fSideEffects); + } +} + +void allocate_dynamic_stack_space(Boolean isConstantSize, int reg1, int reg2, SInt32 size) { + if (copts.altivec_model) + update_frame_align(16); + do_allocate_dynamic_stack_space(isConstantSize, reg1, reg2, size); + add_immediate(reg1, 1, dummylocal, 0); +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct Traceback { + UInt8 x0; + UInt8 x1; + UInt8 x2; + UInt8 x3; + UInt8 x4; + UInt8 x5; + + UInt8 x6_0 : 2; + UInt8 x6_1 : 1; // set to 1 + UInt8 x6_2 : 5; + + UInt8 x7_0 : 1; + UInt8 x7_1 : 1; // set to 1 + UInt8 has_dynamic_stack : 1; // set to 1 if dynamic_stack + UInt8 x7_3 : 3; + UInt8 uses_CRs : 1; // set to 1 if CRs used + UInt8 needs_link_register : 1; // set to 1 if link register used + + UInt8 has_frame_size : 1; // set to 1 if frame_size is nonzero + UInt8 x8_1 : 1; // set to 0 + UInt8 used_FPRs : 6; // stores non-volatile FPRs used + + UInt8 x9_0 : 1; // set to 0 + UInt8 x9_1 : 1; // set to 1 if VRs or vrsave used + UInt8 used_GPRs : 6; // stores non-volatile GPRs used + + UInt8 xA; + UInt8 xB; + + SInt32 funcsize; + SInt16 namelen; + char name[0]; +} Traceback; + +typedef struct TracebackExtra { + UInt8 used_VRs : 6; + UInt8 has_vrsave_mask : 1; + UInt8 is_varargs : 1; + UInt8 vec_arg_count : 7; + UInt8 has_vrsave_mask_or_used_VRs : 1; +} TracebackExtra; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +char *generate_traceback(SInt32 funcsize, char *funcname, SInt32 *tbsize, Object *func) { + char *work; + short namelen; + Traceback *buf; + SInt32 bufsize; + + namelen = strlen(funcname); + bufsize = ALIGN(sizeof(Traceback) + namelen + (dynamic_stack ? 1 : 0) + ((used_nonvolatile_registers[RegClass_VR] || vrsave_mask) ? sizeof(TracebackExtra) : 0), 4); + buf = lalloc(bufsize); + memclrw(buf, bufsize); + + buf->x4 = 0; + buf->x5 = copts.cplusplus ? 9 : 0; + buf->x6_1 = 1; + buf->x7_1 = 1; + if (dynamic_stack) + buf->has_dynamic_stack = 1; + if (used_nonvolatile_registers[RegClass_CRFIELD]) + buf->uses_CRs = 1; + if (need_link_register()) + buf->needs_link_register = 1; + if (frame_size) + buf->has_frame_size = 1; + buf->used_FPRs = used_nonvolatile_registers[RegClass_FPR]; + buf->used_GPRs = used_nonvolatile_registers[RegClass_GPR]; + buf->x8_1 = 0; + buf->x9_0 = 0; + buf->x9_1 = (used_nonvolatile_registers[RegClass_VR] || vrsave_mask) != 0; + buf->funcsize = funcsize; + buf->namelen = namelen; + + work = buf->name; + strcpy(work, funcname); + work += namelen; + if (dynamic_stack) { + *(work++) = 31; + } + + if (vrsave_mask || used_nonvolatile_registers[RegClass_VR]) { + TracebackExtra *extra; + Boolean is_varargs; + int vec_count; + FuncArg *args, *scan; + Type *type; + + extra = (TracebackExtra *) work; + vec_count = 0; + args = TYPE_FUNC(func->type)->args; + scan = args; + while (scan && scan != &elipsis) + scan = scan->next; + is_varargs = scan == &elipsis; + while (args) { + if ((type = args->type) && IS_TYPE_VECTOR(type)) + vec_count++; + args = args->next; + } + extra->used_VRs = used_nonvolatile_registers[RegClass_VR]; + extra->has_vrsave_mask = vrsave_mask != 0; + extra->is_varargs = is_varargs; + extra->vec_arg_count = vec_count; + extra->has_vrsave_mask_or_used_VRs = vrsave_mask || used_nonvolatile_registers[RegClass_VR]; + } + + *tbsize = bufsize; + return (char *) buf; +} + +static SInt32 localsbase(void) { + SInt32 size = parameter_area_size; + if (frame_size || dynamic_align_stack) + size += linkage_area_size; + else + size -= genuine_frame_size; + return size; +} + +static SInt32 parametersbase(int flag) { + if (flag) + return 24; + + return frame_size ? (genuine_frame_size + 24) : 24; +} + +void check_dynamic_aligned_frame(void) { + PCode *pc; + + if (used_nonvolatile_registers[RegClass_VR]) { + update_frame_align(16); + requires_frame = 1; + } + + if (frame_alignment > in_param_alignment) { + dynamic_align_stack = 1; + requires_frame = 1; + CError_ASSERT(2091, !has_varargs || _CALLER_SP_ != -1); + CError_ASSERT(2096, _CALLER_SP_ != _FP_); + if (setup_caller_sp && setup_caller_sp->block) { + align_instr1 = makepcode(PC_RLWINM, 12, 1, 0, 5, 31); + insertpcodebefore(setup_caller_sp, align_instr1); + align_instr2 = makepcode(PC_STWUX, 1, 1, 12); + insertpcodeafter(setup_caller_sp, align_instr2); + } + } else { + dynamic_align_stack = 0; + if (setup_caller_sp && setup_caller_sp->block) { + pc = makepcode(PC_MR, _CALLER_SP_, _FP_); + insertpcodebefore(setup_caller_sp, pc); + deletepcode(setup_caller_sp); + setup_caller_sp = pc; + } + _CALLER_SP_ = _FP_; + } + + vrsave_mask = 0; + if (copts.altivec_model) { + vrsave_mask = colored_vrs_as_vrsave(pcbasicblocks); + if (!requires_frame && vrsave_mask) { + vrsave_register = 11; + loadvrsave = makepcode(PC_LWZ, 11, 1, 0, -4); + appendpcode(prologue, loadvrsave); + storevrsave = makepcode(PC_STW, 11, 1, 0, -4); + appendpcode(epilogue, storevrsave); + } + } +} + +void move_varargs_to_memory(void) { + short reg; + + has_varargs = 1; + dummyvaparam = galloc(sizeof(Object)); + memclrw(dummyvaparam, sizeof(Object)); + + dummyvaparam->type = TYPE(&stvoid); + dummyvaparam->otype = OT_OBJECT; + dummyvaparam->name = GetHashNameNode(""); + dummyvaparam->datatype = DLOCAL; + dummyvaparam->u.var.info = CodeGen_GetNewVarInfo(); + dummyvaparam->u.var.uid = 0; + dummyvaparam->u.var.info->noregister = 1; + Registers_GetVarInfo(dummyvaparam)->flags = (Registers_GetVarInfo(dummyvaparam)->flags & ~VarInfoFlag1) | VarInfoFlag1; + + for (reg = last_argument_register[RegClass_GPR] + 1; (int)reg <= 10; reg++) { + emitpcode(PC_STW, reg, local_base_register(dummyvaparam), dummyvaparam, (reg - 3) * 4); + setpcodeflags(fIsPtrOp | fIsArgInit); + } +} + +void assign_arguments_to_memory(Object *func, UInt8 mysteryFlag, Boolean hasVarargs) { + // almost matches except for the not/andc issue + SInt32 pos; + ObjectList *list; + Object *obj; + Type *type; + short reg; + SInt32 chk; + Boolean flag; + + pos = 0; + reg = 2; + + for (list = arguments; list; list = list->next) { + obj = list->object; + type = obj->type; + if (!IS_TYPE_VECTOR(type)) { + obj->datatype = DLOCAL; + obj->u.var.info = CodeGen_GetNewVarInfo(); + if (IS_TYPE_ARRAY(type) || IS_TYPE_NONVECTOR_STRUCT(type) || IS_TYPE_CLASS(type) || + IS_TYPE_12BYTES_MEMBERPOINTER(type)) { + chk = CMach_ArgumentAlignment(type); + if (chk > 4) { + pos = ALIGN(pos, chk); + update_in_param_align(chk); + } + } + obj->u.var.uid = pos; + Registers_GetVarInfo(obj)->flags = (Registers_GetVarInfo(obj)->flags & ~VarInfoFlag1) | VarInfoFlag1; + if (!copts.littleendian && (IS_TYPE_INT(obj->type) || IS_TYPE_ENUM(obj->type)) && obj->type->size < 4) + obj->u.var.uid += 4 - obj->type->size; + pos += type->size; + pos = ALIGN(pos, 4); + } else { + obj->u.var.info = CodeGen_GetNewVarInfo(); + obj->u.var.uid = 0; + obj->datatype = DLOCAL; + flag = 1; + if (reg <= 13) + flag = hasVarargs; + if (flag) { + pos = ALIGN(pos + 24, 16) - 24; + obj->u.var.uid = pos; + pos += 16; + update_in_param_align(16); + Registers_GetVarInfo(obj)->flags = (Registers_GetVarInfo(obj)->flags & ~VarInfoFlag1) | VarInfoFlag1; + } else { + assign_local_memory(obj); + Registers_GetVarInfo(obj)->flags = Registers_GetVarInfo(obj)->flags & ~VarInfoFlag1; + } + reg++; + } + } + + in_parameter_size = (in_parameter_size < pos) ? pos : in_parameter_size; + CError_ASSERT(2408, !dummyvaparam); +} + +SInt32 set_out_param_displ(SInt32 a, Type *type, Boolean flag, SInt32 *outvar, SInt32 b) { + // does not match due to errant andc + SInt32 argAlign; + + if (!flag && !b) { + *outvar = 0; + return a; + } + + if (IS_TYPE_VECTOR(type)) { + update_out_param_align(16); + a = ALIGN(a + 16 + 24, 16) - 24; + } else if (IS_TYPE_ARRAY(type) || IS_TYPE_NONVECTOR_STRUCT(type) || IS_TYPE_CLASS(type) || IS_TYPE_12BYTES_MEMBERPOINTER(type)) { + argAlign = CMach_ArgumentAlignment(type); + if (argAlign > 4) { + a = ALIGN(a + 24, argAlign) - 24; + update_in_param_align(argAlign); + } + } + + *outvar = a; + a = ALIGN(a + b, 4); + return a; +} + +SInt32 out_param_displ_to_offset(SInt32 displ) { + return displ + 24; +} + +Boolean needs_frame(void) { + return (frame_size > 224) || requires_frame; +} + +void update_out_param_size(SInt32 size) { + if (size < 32) + size = 32; + if (parameter_area_size < size) + parameter_area_size = size; +} + +void estimate_out_param_size(SInt32 size) { + if (parameter_area_size_estimate < size) + parameter_area_size_estimate = size; +} + +void update_out_param_align(SInt32 align) { + if (out_param_alignment < align) + out_param_alignment = align; + update_frame_align(align); +} + +void update_in_param_align(SInt32 align) { + if (in_param_alignment < align) + in_param_alignment = align; +} + +void update_frame_align(SInt32 align) { + if (frame_alignment < align) + frame_alignment = align; +} + +SInt32 local_offset_32(Object *obj) { + short align; + SInt32 offset; + + if (obj->u.var.info->flags & VarInfoFlag1) + align = CMach_ArgumentAlignment(obj->type); + else + align = CMach_AllocationAlignment(obj->type, obj->qual); + + offset = obj->u.var.uid; + if (offset > 0x7FFF) + offset = 0x8000 - offset - ALIGN(obj->type->size, align); + + if (obj->u.var.info->flags & VarInfoFlag1) + return offset + parametersbase(local_base_register(obj) != _FP_); + else + return offset + localsbase(); +} + +SInt32 local_offset_lo(Object *obj, SInt32 offset) { + SInt32 combo = offset + local_offset_32(obj); + return LOW_PART(combo); + //return (SInt16) (offset + local_offset_32(obj)); +} + +SInt32 local_offset_ha(Object *obj, SInt32 offset) { + SInt32 combo = offset + local_offset_32(obj); + return HIGH_PART(combo); + //return (SInt16) ((combo >> 16) + ((combo & 0x8000) >> 15)); +} + +SInt32 local_offset_16(Object *obj) { + SInt32 offset32 = local_offset_32(obj); + SInt16 offset16 = (SInt16) offset32; + CError_ASSERT(2662, offset32 == offset16); + return offset16; +} + +Boolean local_is_16bit_offset(Object *obj) { + SInt32 offset32 = local_offset_32(obj); + SInt16 offset16 = (SInt16) offset32; + return offset32 == offset16; +} + +int local_base_register(Object *obj) { + PCode *pc; + + if (obj->u.var.info->flags & VarInfoFlag1) { + if (coloring && _CALLER_SP_ == -1) { + _CALLER_SP_ = used_virtual_registers[RegClass_GPR]++; + pc = makepcode(PC_LWZ, _CALLER_SP_, 1, 0, 0); + setup_caller_sp = pc; + appendpcode(prologue, pc); + } + return _CALLER_SP_; + } else { + return _FP_; + } +} + +static UInt32 align_bits(UInt32 value, UInt8 bitcount) { + UInt32 base = bitcount != 0; + switch (value) { + case 0x0002: return base + 30; + case 0x0004: return base + 29; + case 0x0008: return base + 28; + case 0x0010: return base + 27; + case 0x0020: return base + 26; + case 0x0040: return base + 25; + case 0x0080: return base + 24; + case 0x0100: return base + 23; + case 0x0200: return base + 22; + case 0x0400: return base + 21; + case 0x0800: return base + 20; + case 0x1000: return base + 19; + case 0x2000: return base + 18; + default: + CError_FATAL(2754); + return base + 27; + } +} + +Boolean is_large_frame(void) { + CError_ASSERT(2769, frame_size != -1); + return large_stack; +} + +void no_frame_for_asm(void) { + frame_size = 0; +} + +Boolean can_add_displ_to_local(Object *obj, SInt32 displ) { + if (obj->datatype != DLOCAL) + return 0; + + if (local_offset_32(obj) == (short) local_offset_32(obj)) + if ((displ + local_offset_32(obj)) == (short) (displ + local_offset_32(obj))) + return 1; + + return 0; +} + +SInt32 get_alloca_alignment(void) { + SInt32 align = frame_alignment; + if (copts.altivec_model) + align = ALIGN(align, 16); + + if (!alloca_alignment) + alloca_alignment = align; + else + CError_ASSERT(2825, alloca_alignment == align); + + return align_bits(align, 0); +} + +static Boolean use_helper_function(char rclass) { + if (copts.no_register_save_helpers) + return 0; + + switch (rclass) { + case RegClass_GPR: + if (copts.use_lmw_stmw) + return 0; + return (used_nonvolatile_registers[RegClass_GPR] > 4) || (copts.optimizesize && used_nonvolatile_registers[RegClass_GPR] > 2); + case RegClass_FPR: + return (used_nonvolatile_registers[RegClass_FPR] > 3) || (copts.optimizesize && used_nonvolatile_registers[RegClass_FPR] > 2); + case RegClass_VR: + return (used_nonvolatile_registers[RegClass_VR] > 3) || (copts.optimizesize && used_nonvolatile_registers[RegClass_VR] > 2); + default: + CError_FATAL(2862); + return 0; + } +} + +static Boolean need_link_register(void) { + if (copts.codegen_pic && uses_globals) + return 1; + + if (makes_call) + return 1; + + return use_helper_function(RegClass_FPR) || use_helper_function(RegClass_GPR) || use_helper_function(RegClass_VR); +} + +static void call_helper_function(char *name, char rclass, short effect) { + char str[32]; + Object *func; + NameSpace *save_scope; + PCode *pc; + int extra_args; + PCodeArg *arg; + short i; + + extra_args = 1; + if (rclass == RegClass_VR) + extra_args = 2; + + sprintf(str, name, 32 - used_nonvolatile_registers[rclass]); + + save_scope = cscope_current; + cscope_current = cscope_root; + func = CParser_NewRTFunc(&stvoid, NULL, 2, 0); + cscope_current = save_scope; + + func->name = GetHashNameNodeExport(str); + + pc = makepcode(PC_BL, extra_args + used_nonvolatile_registers[rclass], func, 0); + for (i = 1, arg = &pc->args[1]; i <= used_nonvolatile_registers[rclass]; i++, arg++) { + arg->kind = PCOp_REGISTER; + arg->arg = rclass; + arg->data.reg.reg = n_real_registers[rclass] - i; + arg->data.reg.effect = effect; + } + + if (rclass == RegClass_VR) { + arg[1].kind = PCOp_REGISTER; + arg[1].arg = RegClass_GPR; + arg[1].data.reg.reg = 12; + arg[1].data.reg.effect = EffectWrite; + arg[2].kind = PCOp_REGISTER; + arg[2].arg = RegClass_GPR; + arg[2].data.reg.reg = 0; + arg[2].data.reg.effect = EffectRead; + } else { + arg[1].kind = PCOp_REGISTER; + arg[1].arg = RegClass_GPR; + arg[1].data.reg.reg = 11; + arg[1].data.reg.effect = EffectRead; + } + + appendpcode(pclastblock, pc); + setpcodeflags(fSideEffects); +} + +static SInt32 nearest_power_of_two(SInt32 n) { + SInt32 power = 1; + do { + power <<= 1; + } while (power && power < n); + + CError_ASSERT(2933, power != 0); + return power; +} + +static void compress_data_area(void) { + // doesn't quite match + SInt32 r0; + SInt32 r7; + ObjectList *list; + Object *obj; + PCodeBlock *block; + PCode *pc; + int i; + + compressing_data_area = 1; + + if (large_stack) { + r0 = 0; + } else { + r0 = parameter_area_size; + if (r0 < 32) + r0 = 32; + } + r7 = ALIGN(r0 + 24, frame_alignment) - 24; + local_data_limit = 0x8000 - ALIGN(24 + in_parameter_size + nonvolatile_save_size + r7, frame_alignment); + + if (local_objects_tail[ObjClass0]) { + if (local_objects[ObjClass1]) { + local_objects_tail[ObjClass0]->next = local_objects[ObjClass1]; + local_objects_tail[ObjClass0] = local_objects_tail[ObjClass1]; + } + if (local_objects[ObjClass2]) { + local_objects_tail[ObjClass0]->next = local_objects[ObjClass2]; + local_objects_tail[ObjClass0] = local_objects_tail[ObjClass2]; + } + } else if (local_objects_tail[ObjClass1]) { + local_objects[ObjClass0] = local_objects[ObjClass1]; + local_objects_tail[ObjClass0] = local_objects_tail[ObjClass1]; + if (local_objects[ObjClass2]) { + local_objects_tail[ObjClass0]->next = local_objects[ObjClass2]; + local_objects_tail[ObjClass0] = local_objects_tail[ObjClass2]; + } + } else { + local_objects[ObjClass0] = local_objects[ObjClass2]; + local_objects_tail[ObjClass0] = local_objects_tail[ObjClass2]; + } + + for (list = local_objects[ObjClass0]; list; list = list->next) + Registers_GetVarInfo(list->object)->used = 0; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (pc = block->firstPCode; pc; pc = pc->nextPCode) { + for (i = 0; i < pc->argCount; i++) { + if (pc->args[i].kind == PCOp_MEMORY && pc->args[i].data.mem.obj && pc->args[i].data.mem.obj->datatype == DLOCAL) + Registers_GetVarInfo(pc->args[i].data.mem.obj)->used = 1; + } + } + } + + local_data_size = 0; + large_data_near_size = 0; + large_data_far_size = 0; + + for (list = local_objects[ObjClass0]; list; list = list->next) { + obj = list->object; + if (Registers_GetVarInfo(obj)->used) + assign_local_memory(obj); + } +} + +static void insert_local_object(UInt8 oclass, Object *obj) { + ObjectList *list; + + if (!compressing_data_area) { + list = lalloc(sizeof(ObjectList)); + memclrw(list, sizeof(ObjectList)); + list->object = obj; + if (!local_objects[oclass]) + local_objects[oclass] = list; + if (local_objects_tail[oclass]) + local_objects_tail[oclass]->next = list; + local_objects_tail[oclass] = list; + } +} diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/StructMoves.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/StructMoves.c new file mode 100644 index 0000000..7c28b88 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/StructMoves.c @@ -0,0 +1,792 @@ +#include "compiler/StructMoves.h" +#include "compiler/CError.h" +#include "compiler/CParser.h" +#include "compiler/CodeGen.h" +#include "compiler/Operands.h" +#include "compiler/PCode.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/Registers.h" + +void make_addressable(Operand *opnd, SInt32 offset, int unusedArg) { + int reg; + + if (opnd->optype == OpndType_IndirectSymbol) + coerce_to_addressable(opnd); + + if (opnd->optype != OpndType_IndirectGPR_ImmOffset || (opnd->immOffset + offset) > 0x7FFF) { + reg = used_virtual_registers[RegClass_GPR]++; + load_address(reg, opnd); + opnd->optype = OpndType_IndirectGPR_ImmOffset; + opnd->reg = reg; + opnd->object = NULL; + opnd->immOffset = 0; + } +} + +static void load_displaced_address(Operand *opnd, SInt32 offset) { + int reg; + + reg = used_virtual_registers[RegClass_GPR]++; + if (opnd->optype == OpndType_IndirectSymbol) + coerce_to_addressable(opnd); + + if (opnd->optype == OpndType_IndirectGPR_ImmOffset) { + offset += opnd->immOffset; + if (!FITS_IN_SHORT(offset)) { + add_immediate(reg, opnd->reg, opnd->object, opnd->immOffset); + emitpcode(PC_ADDI, reg, reg, 0, offset - opnd->immOffset); + } else { + add_immediate(reg, opnd->reg, opnd->object, offset); + } + } else if (opnd->optype == OpndType_IndirectGPR_Indexed) { + emitpcode(PC_ADD, reg, opnd->reg, opnd->regOffset); + emitpcode(PC_ADDI, reg, reg, 0, offset); + } else { + CError_FATAL(80); + } + + opnd->optype = OpndType_IndirectGPR_ImmOffset; + opnd->reg = reg; + opnd->object = NULL; + opnd->immOffset = 0; +} + +static void move_block_via_load_store(Operand *dst, Operand *src, SInt32 len, SInt32 align) { + SInt32 step; + SInt32 pos; + int floatReg; + int reg; + + if (src->optype == OpndType_IndirectSymbol) + coerce_to_addressable(src); + if (dst->optype == OpndType_IndirectSymbol) + coerce_to_addressable(dst); + + if (len == 8) { + floatReg = used_virtual_registers[RegClass_FPR]++; + if (src->optype == OpndType_IndirectGPR_ImmOffset) { + load_store_register(PC_LFD, floatReg, src->reg, src->object, src->immOffset); + setpcodeflags(src->flags); + } else if (src->optype == OpndType_IndirectGPR_Indexed) { + emitpcode(PC_LFDX, floatReg, src->reg, src->regOffset); + setpcodeflags(src->flags); + } else { + CError_FATAL(145); + } + + if (dst->optype == OpndType_IndirectGPR_ImmOffset) { + load_store_register(PC_STFD, floatReg, dst->reg, dst->object, dst->immOffset); + setpcodeflags(dst->flags); + } else if (dst->optype == OpndType_IndirectGPR_Indexed) { + emitpcode(PC_STFDX, floatReg, dst->reg, dst->regOffset); + setpcodeflags(dst->flags); + } else { + CError_FATAL(157); + } + + return; + } + + if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { + SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align; + step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2; + } else { + step = ((UInt32) len > 4) ? 4 : ((UInt32) len <= 2) ? len : 2; + } + + if (step != len) { + if (dst->optype == OpndType_IndirectGPR_Indexed) + make_addressable(dst, len, 0); + if (src->optype == OpndType_IndirectGPR_Indexed) + make_addressable(src, len, 0); + } + + for (pos = 0; len != 0; len -= step, pos += step) { + reg = used_virtual_registers[RegClass_GPR]++; + if (src->optype == OpndType_IndirectGPR_ImmOffset) { + load_store_register( + (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, + reg, + src->reg, + src->object, + src->immOffset + pos + ); + setpcodeflags(src->flags); + } else if (src->optype == OpndType_IndirectGPR_Indexed) { + emitpcode( + (step == 1) ? PC_LBZX : (step == 2) ? PC_LHZX : PC_LWZX, + reg, + src->reg, + src->regOffset + ); + setpcodeflags(src->flags); + } else { + CError_FATAL(183); + } + + if (dst->optype == OpndType_IndirectGPR_ImmOffset) { + load_store_register( + (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, + reg, + dst->reg, + dst->object, + dst->immOffset + pos + ); + setpcodeflags(dst->flags); + } else if (dst->optype == OpndType_IndirectGPR_Indexed) { + emitpcode( + (step == 1) ? PC_STBX : (step == 2) ? PC_STHX : PC_STWX, + reg, + dst->reg, + dst->regOffset + ); + setpcodeflags(dst->flags); + } else { + CError_FATAL(195); + } + } +} + +static void move_block_via_load_store_sequence(Operand *dst, Operand *src, SInt32 len, SInt32 align) { + SInt32 pos; + int i; + SInt32 step; + + pos = 0; + make_addressable(dst, len, 0); + make_addressable(src, len, 0); + + if ((align % 8) == 0) { + while (len >= 16) { + int reg1 = used_virtual_registers[RegClass_FPR]++; + int reg2 = used_virtual_registers[RegClass_FPR]++; + load_store_register(PC_LFD, reg1, src->reg, src->object, src->immOffset + pos); + setpcodeflags(src->flags); + load_store_register(PC_LFD, reg2, src->reg, src->object, src->immOffset + pos + 8); + setpcodeflags(src->flags); + + load_store_register(PC_STFD, reg1, dst->reg, dst->object, dst->immOffset + pos); + setpcodeflags(dst->flags); + load_store_register(PC_STFD, reg2, dst->reg, dst->object, dst->immOffset + pos + 8); + setpcodeflags(dst->flags); + + pos += 16; + len -= 16; + } + } + + while (len >= 8) { + if ((align % 8) == 0) { + int reg = used_virtual_registers[RegClass_FPR]++; + + load_store_register(PC_LFD, reg, src->reg, src->object, src->immOffset + pos); + setpcodeflags(src->flags); + + load_store_register(PC_STFD, reg, dst->reg, dst->object, dst->immOffset + pos); + setpcodeflags(dst->flags); + + pos += 8; + len -= 8; + } else { + if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { + SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align; + step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp > 2) ? 2 : 1; + } else { + step = 4; + } + + for (i = 0; i < 8; i += (step * 2)) { + int reg1 = used_virtual_registers[RegClass_GPR]++; + int reg2 = used_virtual_registers[RegClass_GPR]++; + + load_store_register( + (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, + reg1, + src->reg, + src->object, + src->immOffset + pos + ); + setpcodeflags(src->flags); + + load_store_register( + (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, + reg2, + src->reg, + src->object, + src->immOffset + pos + step + ); + setpcodeflags(src->flags); + + load_store_register( + (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, + reg1, + dst->reg, + dst->object, + dst->immOffset + pos + ); + setpcodeflags(dst->flags); + + load_store_register( + (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, + reg2, + dst->reg, + dst->object, + dst->immOffset + pos + step + ); + setpcodeflags(dst->flags); + + pos += (step * 2); + len -= (step * 2); + } + } + } + + while (len) { + int reg; + + if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { + SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align; + step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2; + } else { + step = ((UInt32) len > 4) ? 4 : ((UInt32) len <= 2) ? len : 2; + } + + reg = used_virtual_registers[RegClass_GPR]++; + + load_store_register( + (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, + reg, + src->reg, + src->object, + src->immOffset + pos + ); + setpcodeflags(src->flags); + + load_store_register( + (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, + reg, + dst->reg, + dst->object, + dst->immOffset + pos + ); + setpcodeflags(dst->flags); + + len -= step; + pos += step; + } +} + +static void move_block_via_inline_loop(Operand *dst, Operand *src, SInt32 len, SInt32 align) { + PCodeLabel *label; // r25 + SInt32 pos; // r25 + SInt32 step; // r24 + int reg1; // r22 + int reg2; // r23 + SInt32 remainder; // r23 + + label = makepclabel(); + + if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { + SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align; + step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2; + } else { + step = 4; + } + + load_displaced_address(dst, -step); + load_displaced_address(src, -step); + + CError_ASSERT(377, (len / step) != 0); + + reg1 = used_virtual_registers[RegClass_GPR]++; + load_immediate(reg1, len / (step * 2)); + emitpcode(PC_MTCTR, reg1); + branch_label(label); + + reg1 = used_virtual_registers[RegClass_GPR]++; + reg2 = used_virtual_registers[RegClass_GPR]++; + + load_store_register( + (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, + reg1, + src->reg, + NULL, + step + ); + setpcodeflags(src->flags); + + load_store_register( + (step == 1) ? PC_LBZU : (step == 2) ? PC_LHZU : PC_LWZU, + reg2, + src->reg, + NULL, + step * 2 + ); + setpcodeflags(src->flags); + + load_store_register( + (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, + reg1, + dst->reg, + NULL, + step + ); + setpcodeflags(dst->flags); + + load_store_register( + (step == 1) ? PC_STBU : (step == 2) ? PC_STHU : PC_STWU, + reg2, + dst->reg, + NULL, + step * 2 + ); + setpcodeflags(dst->flags); + + branch_decrement_always(PC_BDNZ, label); + + for (remainder = len & 7, pos = step; remainder != 0; remainder -= step, pos += step) { + int reg; + + if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { + SInt32 tmp = (align == 0) ? 1 : (align > remainder) ? remainder : align; + step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2; + } else { + step = ((UInt32) remainder > 4) ? 4 : ((UInt32) remainder <= 2) ? remainder : 2; + } + + reg = used_virtual_registers[RegClass_GPR]++; + + load_store_register( + (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, + reg, + src->reg, + NULL, + pos + ); + setpcodeflags(src->flags); + + load_store_register( + (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, + reg, + dst->reg, + NULL, + pos + ); + setpcodeflags(dst->flags); + } +} + +void move_block(Operand *dst, Operand *src, SInt32 len, SInt32 align) { + Operand myDst; + + myDst = *dst; + + CError_ASSERT(447, myDst.optype >= OpndType_IndirectGPR_ImmOffset); + CError_ASSERT(449, src->optype >= OpndType_IndirectGPR_ImmOffset); + + if (len == 1 || len == 2 || len == 4) + move_block_via_load_store(&myDst, src, len, align); + else if (len == 8 && align == 8) + move_block_via_load_store(&myDst, src, len, align); + else if (len <= 16 || (copts.optimizesize == 0 && len <= 64)) + move_block_via_load_store_sequence(&myDst, src, len, align); + else + move_block_via_inline_loop(&myDst, src, len, align); +} + +static void load_word_of_small_struct(short dstReg, short srcReg, Operand *opnd, SInt32 offset, SInt32 len, SInt32 align) { + short tmpReg; + short extra = 0; + + switch (len) { + case 1: + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWINM, dstReg, tmpReg, 24, 0, 7); + setpcodeflags(opnd->flags); + break; + case 2: + case 3: + if (align > 1) { + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_store_register(PC_LHZ, tmpReg, srcReg, opnd->object, offset); + extra += 2; + setpcodeflags(opnd->flags); + emitpcode(PC_RLWINM, dstReg, tmpReg, 16, 0, 15); + setpcodeflags(opnd->flags); + } else { + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWINM, dstReg, tmpReg, 24, 0, 7); + setpcodeflags(opnd->flags); + + load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 1); + extra += 2; + setpcodeflags(opnd->flags); + emitpcode(PC_RLWIMI, dstReg, tmpReg, 16, 8, 15); + setpcodeflags(opnd->flags); + } + if (len == 3) { + load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + extra); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWIMI, dstReg, tmpReg, 8, 16, 23); + setpcodeflags(opnd->flags); + } + break; + case 4: + if (align > 2) { + load_store_register(PC_LWZ, dstReg, srcReg, opnd->object, offset); + setpcodeflags(opnd->flags); + } else if (align > 1) { + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_store_register(PC_LHZ, tmpReg, srcReg, opnd->object, offset); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWINM, dstReg, tmpReg, 16, 0, 15); + setpcodeflags(opnd->flags); + + load_store_register(PC_LHZ, tmpReg, srcReg, opnd->object, offset + 2); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWIMI, dstReg, tmpReg, 0, 16, 31); + setpcodeflags(opnd->flags); + } else { + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWINM, dstReg, tmpReg, 24, 0, 7); + setpcodeflags(opnd->flags); + + load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 1); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWIMI, dstReg, tmpReg, 16, 8, 15); + setpcodeflags(opnd->flags); + + load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 2); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWIMI, dstReg, tmpReg, 8, 16, 23); + setpcodeflags(opnd->flags); + + load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 3); + setpcodeflags(opnd->flags); + emitpcode(PC_RLWIMI, dstReg, tmpReg, 0, 24, 31); + setpcodeflags(opnd->flags); + } + break; + } +} + +void load_small_block_into_reg(short dstReg, Operand *srcOpnd, Type *type, SInt32 align) { + short finalReg; + short tmpReg; + SInt32 absAddress; + + coerce_to_addressable(srcOpnd); + + if (srcOpnd->optype == OpndType_IndirectGPR_Indexed) { + CError_FATAL(557); + + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_address(tmpReg, srcOpnd); + srcOpnd->optype = OpndType_IndirectGPR_ImmOffset; + srcOpnd->reg = tmpReg; + srcOpnd->object = NULL; + srcOpnd->immOffset = 0; + } + + if (copts.misaligned_mem_access) + align = 4; + + switch (srcOpnd->optype) { + case OpndType_GPRPair: + return; + case OpndType_GPR: + return; + case OpndType_GPR_ImmOffset: + finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++; + add_immediate(finalReg, srcOpnd->reg, srcOpnd->object, srcOpnd->immOffset); + break; + case OpndType_GPR_Indexed: + finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_ADD, finalReg, srcOpnd->reg, srcOpnd->regOffset); + break; + case OpndType_Absolute: + finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++; + absAddress = srcOpnd->immediate; + if (FITS_IN_SHORT(absAddress)) { + emitpcode(PC_LI, finalReg, absAddress); + } else { + tmpReg = finalReg; + if (copts.optimizationlevel > 1 && absAddress) + tmpReg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_LIS, tmpReg, 0, HIGH_PART(absAddress)); + if (absAddress) + emitpcode(PC_ADDI, finalReg, tmpReg, 0, LOW_PART(absAddress)); + } + break; + case OpndType_IndirectGPR_ImmOffset: + finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++; + load_word_of_small_struct(finalReg, srcOpnd->reg, srcOpnd, srcOpnd->immOffset, type->size, align); + break; + default: + CError_FATAL(606); + } + + srcOpnd->optype = OpndType_GPR; + srcOpnd->reg = finalReg; +} + +void load_small_block_into_reg_pair(short dstRegLo, short dstRegHi, Operand *srcOpnd, Type *type, SInt32 align) { + short finalRegLo; + short finalRegHi; + short tmpRegLo; + short tmpRegHi; + short tmpReg; + SInt32 absAddress; + + finalRegHi = -1; + coerce_to_addressable(srcOpnd); + + if (srcOpnd->optype == OpndType_IndirectGPR_Indexed) { + CError_FATAL(624); + + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_address(tmpReg, srcOpnd); + srcOpnd->optype = OpndType_IndirectGPR_ImmOffset; + srcOpnd->reg = tmpReg; + srcOpnd->object = NULL; + srcOpnd->immOffset = 0; + } + + if (copts.misaligned_mem_access) + align = 4; + + switch (srcOpnd->optype) { + case OpndType_GPRPair: + if (dstRegLo != 0 && dstRegHi == 0) + dstRegHi = used_virtual_registers[RegClass_GPR]++; + if (dstRegHi != 0 && dstRegLo == 0) + dstRegLo = used_virtual_registers[RegClass_GPR]++; + + if (srcOpnd->reg != dstRegLo || srcOpnd->regHi != dstRegHi) { + tmpRegLo = dstRegLo ? dstRegLo : srcOpnd->reg; + tmpRegHi = dstRegHi ? dstRegHi : srcOpnd->regHi; + + if (tmpRegLo != srcOpnd->reg) { + if (tmpRegLo == srcOpnd->regHi) { + CError_ASSERT(657, tmpRegLo != tmpRegHi); + emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi); + emitpcode(PC_MR, tmpRegLo, srcOpnd->reg); + } else { + emitpcode(PC_MR, tmpRegLo, srcOpnd->reg); + if (srcOpnd->regHi != tmpRegHi) + emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi); + } + } else if (tmpRegHi != srcOpnd->regHi) { + if (tmpRegHi == srcOpnd->reg) { + CError_ASSERT(671, tmpRegLo != tmpRegHi); + emitpcode(PC_MR, tmpRegLo, srcOpnd->reg); + emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi); + } else { + emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi); + if (srcOpnd->reg != tmpRegLo) + emitpcode(PC_MR, tmpRegLo, srcOpnd->reg); + } + } + } + + finalRegLo = srcOpnd->reg; + finalRegHi = srcOpnd->regHi; + break; + case OpndType_GPR: + CError_FATAL(688); + break; + case OpndType_GPR_ImmOffset: + CError_FATAL(691); + break; + case OpndType_GPR_Indexed: + CError_FATAL(694); + break; + case OpndType_Absolute: + finalRegLo = dstRegLo ? dstRegLo : used_virtual_registers[RegClass_GPR]++; + absAddress = srcOpnd->immediate; + if (FITS_IN_SHORT(absAddress)) { + emitpcode(PC_LI, finalRegLo, absAddress); + } else { + tmpReg = finalRegLo; + if (copts.optimizationlevel > 1 && absAddress) + tmpReg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_LIS, tmpReg, 0, HIGH_PART(absAddress)); + if (absAddress) + emitpcode(PC_ADDI, finalRegLo, tmpReg, 0, LOW_PART(absAddress)); + } + + finalRegHi = dstRegHi ? dstRegHi : used_virtual_registers[RegClass_GPR]++; + if (is_unsigned(type) || absAddress >= 0) + load_immediate(finalRegHi, 0); + else + load_immediate(finalRegHi, -1); + + break; + case OpndType_IndirectGPR_ImmOffset: + finalRegLo = dstRegLo ? dstRegLo : used_virtual_registers[RegClass_GPR]++; + finalRegHi = dstRegHi ? dstRegHi : used_virtual_registers[RegClass_GPR]++; + if (srcOpnd->reg == finalRegHi) { + if (srcOpnd->reg == finalRegLo) { + CError_FATAL(726); + } else { + load_word_of_small_struct( + finalRegLo, srcOpnd->reg, srcOpnd, + srcOpnd->immOffset + low_offset, type->size - 4, align); + load_word_of_small_struct( + finalRegHi, srcOpnd->reg, srcOpnd, + srcOpnd->immOffset + high_offset, 4, align); + } + } else { + load_word_of_small_struct( + finalRegHi, srcOpnd->reg, srcOpnd, + srcOpnd->immOffset + high_offset, 4, align); + load_word_of_small_struct( + finalRegLo, srcOpnd->reg, srcOpnd, + srcOpnd->immOffset + low_offset, type->size - 4, align); + } + break; + default: + CError_FATAL(737); + } + + if (finalRegHi == -1) { + CError_FATAL(741); + } else { + srcOpnd->optype = OpndType_GPRPair; + srcOpnd->reg = finalRegLo; + srcOpnd->regHi = finalRegHi; + } +} + +static void store_word_of_small_struct(short srcReg, short dstReg, Operand *opnd, SInt32 offset, SInt32 len, SInt32 align) { + short tmpReg; + short extra = 0; + + switch (len) { + case 1: + tmpReg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_RLWINM, tmpReg, srcReg, 8, 24, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset); + setpcodeflags(opnd->flags); + break; + case 2: + case 3: + if (align > 1) { + tmpReg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 16, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STH, tmpReg, dstReg, opnd->object, offset); + extra += 2; + setpcodeflags(opnd->flags); + } else { + tmpReg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_RLWINM, tmpReg, srcReg, 8, 24, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset); + setpcodeflags(opnd->flags); + + emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 24, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + 1); + extra += 2; + setpcodeflags(opnd->flags); + } + if (len == 3) { + emitpcode(PC_RLWINM, tmpReg, srcReg, 24, 24, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + extra); + setpcodeflags(opnd->flags); + } + break; + case 4: + if (align > 2) { + load_store_register(PC_STW, srcReg, dstReg, opnd->object, offset); + setpcodeflags(opnd->flags); + } else if (align > 1) { + tmpReg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 16, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STH, tmpReg, dstReg, opnd->object, offset); + setpcodeflags(opnd->flags); + + load_store_register(PC_STH, srcReg, dstReg, opnd->object, offset + 2); + setpcodeflags(opnd->flags); + } else { + tmpReg = used_virtual_registers[RegClass_GPR]++; + emitpcode(PC_RLWINM, tmpReg, srcReg, 8, 24, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset); + setpcodeflags(opnd->flags); + + emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 24, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + 1); + setpcodeflags(opnd->flags); + + emitpcode(PC_RLWINM, tmpReg, srcReg, 24, 24, 31); + setpcodeflags(opnd->flags); + load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + 2); + setpcodeflags(opnd->flags); + + load_store_register(PC_STB, srcReg, dstReg, opnd->object, offset + 3); + setpcodeflags(opnd->flags); + } + break; + } +} + +void store_small_block_from_reg(short srcReg, Operand *dstOpnd, Type *type, SInt32 align) { + short tmpReg; + + coerce_to_addressable(dstOpnd); + + if (dstOpnd->optype == OpndType_IndirectGPR_Indexed) { + CError_FATAL(839); + + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_address(tmpReg, dstOpnd); + dstOpnd->optype = OpndType_IndirectGPR_ImmOffset; + dstOpnd->reg = tmpReg; + dstOpnd->object = NULL; + dstOpnd->immOffset = 0; + } + + if (copts.misaligned_mem_access) + align = 4; + + store_word_of_small_struct(srcReg, dstOpnd->reg, dstOpnd, dstOpnd->immOffset, type->size, align); +} + +void store_small_block_from_reg_pair(short srcRegLo, short srcRegHi, Operand *dstOpnd, Type *type, SInt32 align) { + short tmpReg; + + coerce_to_addressable(dstOpnd); + + if (dstOpnd->optype == OpndType_IndirectGPR_Indexed) { + CError_FATAL(860); + + tmpReg = used_virtual_registers[RegClass_GPR]++; + load_address(tmpReg, dstOpnd); + dstOpnd->optype = OpndType_IndirectGPR_ImmOffset; + dstOpnd->reg = tmpReg; + dstOpnd->object = NULL; + dstOpnd->immOffset = 0; + } + + if (copts.misaligned_mem_access) + align = 4; + + store_word_of_small_struct( + srcRegLo, dstOpnd->reg, dstOpnd, + dstOpnd->immOffset + low_offset, type->size - 4, align); + store_word_of_small_struct( + srcRegHi, dstOpnd->reg, dstOpnd, + dstOpnd->immOffset + high_offset, 4, align); +} diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Switch.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Switch.c new file mode 100644 index 0000000..4bbd82e --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Switch.c @@ -0,0 +1,518 @@ +#include "compiler/Switch.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CParser.h" +#include "compiler/InstrSelection.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/Operands.h" +#include "compiler/PCode.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/RegisterInfo.h" +#include "compiler/TOC.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" + +ObjectList *switchtables; +static SwitchCase **caselabels; +static CaseRange *caseranges; +static SInt32 ncases; +static SInt32 nranges_minus1; +static CInt64 min; +static CInt64 max; +static CInt64 first; +static short selector_gpr; +static short selector_gprHi; +static Type *selector_type; +static PCodeLabel *defaultlabel; +static CInt64 range; + +static int compare_cases(const void *a, const void *b) { + const SwitchCase **casea = (const SwitchCase **) a; + const SwitchCase **caseb = (const SwitchCase **) b; + + if (CInt64_Less((*casea)->min, (*caseb)->min)) + return -1; + if (CInt64_Greater((*casea)->min, (*caseb)->min)) + return 1; + return 0; +} + +static void build_case_ranges(Type *type, SwitchCase *cases, CLabel *label) { + SwitchCase **caseptr; + SInt32 i; + SwitchCase *curcase; + CaseRange *currange; + + if (type->size == 8) { + min.lo = 0; + min.hi = 0x80000000; + max.lo = 0xFFFFFFFF; + max.hi = 0x7FFFFFFF; + } else if (type->size == 4) { + CInt64_SetLong(&min, 0x80000000); + CInt64_SetLong(&max, 0x7FFFFFFF); + } else if (is_unsigned(type)) { + min.hi = 0; + min.lo = 0; + max.hi = 0; + max.lo = 0xFFFF; + } else { + CInt64_SetLong(&min, -0x8000); + CInt64_SetLong(&max, 0x7FFF); + } + + caselabels = lalloc(sizeof(SwitchCase *) * ncases); + caseptr = caselabels; + while (cases) { + *caseptr = cases; + cases = cases->next; + ++caseptr; + } + + caseranges = lalloc(((ncases * 2) + 2) * sizeof(CaseRange)); + if (type->size < 8) { + for (i = 0; i < ncases; i++) + CInt64_SetLong(&caselabels[i]->min, caselabels[i]->min.lo); + } + + qsort(caselabels, ncases, sizeof(SwitchCase *), &compare_cases); + + currange = caseranges; + currange->min = min; + currange->range = CInt64_Sub(max, min); + currange->label = label->pclabel; + + for (i = 0; i < ncases; i++) { + curcase = caselabels[i]; + if (CInt64_GreaterEqual(curcase->min, min) && CInt64_LessEqual(curcase->min, max)) { + if (CInt64_Equal(currange->min, min)) + first = curcase->min; + range = CInt64_Sub(curcase->min, first); + + if (CInt64_Greater(curcase->min, currange->min)) { + currange->range = CInt64_Sub(CInt64_Sub(curcase->min, currange->min), cint64_one); + (++currange)->min = curcase->min; + } else if (CInt64_Greater(currange->min, min) && curcase->label->pclabel == currange[-1].label) { + currange[-1].range = CInt64_Add(currange[-1].range, cint64_one); + if (CInt64_Equal(currange->range, cint64_zero)) { + currange--; + } else { + currange->min = CInt64_Add(currange->min, cint64_one); + currange->range = CInt64_Sub(currange->range, cint64_one); + } + continue; + } + + currange->range = cint64_zero; + currange->label = curcase->label->pclabel; + + if (CInt64_Less(curcase->min, max)) { + currange++; + currange->min = CInt64_Add(curcase->min, cint64_one); + currange->range = CInt64_Sub(max, currange->min); + currange->label = label->pclabel; + } + } + } + + nranges_minus1 = currange - caseranges; +} + +static void treecompare(SInt32 start, SInt32 end) { + SInt32 r30; + SInt32 r29; + CaseRange *currange; + int count; + + count = end - start; + CError_ASSERT(175, selector_type->size <= 4); + + r29 = start + (count >> 1) + 1; + currange = caseranges + r29; + + if (CInt64_Equal(currange[-1].range, cint64_zero) && (!(count & 1) || (CInt64_NotEqual(currange->range, cint64_zero) && count > 1))) { + currange--; + r29--; + } + + r30 = r29 - 1; + + if (selector_type->size < 4 && is_unsigned(selector_type)) { + emitpcode(PC_CMPLI, 0, selector_gpr, CInt64_GetULong(&currange->min)); + } else if (FITS_IN_SHORT((SInt32) CInt64_GetULong(&currange->min))) { + emitpcode(PC_CMPI, 0, selector_gpr, CInt64_GetULong(&currange->min)); + } else { + SInt32 value = CInt64_GetULong(&currange->min); + int reg = ALLOC_GPR(); + load_immediate(reg, value); + emitpcode(PC_CMP, 0, selector_gpr, reg); + } + + if (CInt64_Equal(currange->range, cint64_zero) && r29 < end) { + branch_conditional(0, EEQU, 1, currange->label); + r29++; + } + + if (r29 == end) { + if (start == r30) { + if (caseranges[start].label == caseranges[end].label) { + branch_always(caseranges[start].label); + } else { + branch_conditional(0, EGREATEREQU, 1, caseranges[end].label); + branch_always(caseranges[start].label); + } + } else { + branch_conditional(0, EGREATEREQU, 1, caseranges[end].label); + treecompare(start, r30); + } + } else { + if (start == r30) { + branch_conditional(0, ELESS, 1, caseranges[start].label); + treecompare(r29, end); + } else { + PCodeLabel *label = makepclabel(); + branch_conditional(0, EGREATEREQU, 1, label); + treecompare(start, r30); + branch_label(label); + treecompare(r29, end); + } + } +} + +static void I8_treecompare(SInt32 start, SInt32 end) { + SInt32 r30; + SInt32 r29; + CaseRange *currange; + int count; + + count = end - start; + + r29 = start + (count >> 1) + 1; + currange = caseranges + r29; + + if (CInt64_Equal(currange[-1].range, cint64_zero) && (!(count & 1) || (CInt64_NotEqual(currange->range, cint64_zero) && count > 1))) { + currange--; + r29--; + } + + r30 = r29 - 1; + + if (CInt64_Equal(currange->range, cint64_zero) && r29 < end) { + short a = ALLOC_GPR(); + short b = ALLOC_GPR(); + load_immediate(a, currange->min.lo); + load_immediate(b, currange->min.hi); + emitpcode(PC_XOR, a, selector_gpr, a); + emitpcode(PC_XOR, b, selector_gprHi, b); + emitpcode(PC_OR, b, a, b); + emitpcode(PC_CMPI, 0, b, 0); + branch_conditional(0, EEQU, 1, currange->label); + r29++; + } + + if (r29 == end) { + if (start == r30) { + if (caseranges[start].label == caseranges[end].label) { + branch_always(caseranges[start].label); + } else { + short a = ALLOC_GPR(); + short b = ALLOC_GPR(); + short c = ALLOC_GPR(); + short d = ALLOC_GPR(); + load_immediate(a, currange->min.lo); + load_immediate(b, currange->min.hi); + if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) { + emitpcode(PC_XORIS, c, selector_gprHi, 0x8000); + emitpcode(PC_XORIS, d, b, 0x8000); + } else { + c = selector_gprHi; + d = b; + } + emitpcode(PC_SUBFC, a, a, selector_gpr); + emitpcode(PC_SUBFE, b, d, c); + emitpcode(PC_SUBFE, b, a, a); + emitpcode(PC_NEG, b, b); + emitpcode(PC_CMPI, 0, b, 0); + branch_conditional(0, EEQU, 1, caseranges[end].label); + branch_always(caseranges[start].label); + } + } else { + short a = ALLOC_GPR(); + short b = ALLOC_GPR(); + short c = ALLOC_GPR(); + short d = ALLOC_GPR(); + load_immediate(a, currange->min.lo); + load_immediate(b, currange->min.hi); + if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) { + emitpcode(PC_XORIS, c, selector_gprHi, 0x8000); + emitpcode(PC_XORIS, d, b, 0x8000); + } else { + c = selector_gprHi; + d = b; + } + emitpcode(PC_SUBFC, a, a, selector_gpr); + emitpcode(PC_SUBFE, b, d, c); + emitpcode(PC_SUBFE, b, a, a); + emitpcode(PC_NEG, b, b); + emitpcode(PC_CMPI, 0, b, 0); + branch_conditional(0, EEQU, 1, caseranges[end].label); + I8_treecompare(start, r30); + } + } else { + if (start == r30) { + short a = ALLOC_GPR(); + short b = ALLOC_GPR(); + short c = ALLOC_GPR(); + short d = ALLOC_GPR(); + load_immediate(a, currange->min.lo); + load_immediate(b, currange->min.hi); + if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) { + emitpcode(PC_XORIS, c, selector_gprHi, 0x8000); + emitpcode(PC_XORIS, d, b, 0x8000); + } else { + c = selector_gprHi; + d = b; + } + emitpcode(PC_SUBFC, a, selector_gpr, a); + emitpcode(PC_SUBFE, b, c, d); + emitpcode(PC_SUBFE, b, a, a); + emitpcode(PC_NEG, b, b); + emitpcode(PC_CMPI, 0, b, 0); + branch_conditional(0, ENOTEQU, 1, caseranges[end].label); + I8_treecompare(r29, end); + } else { + PCodeLabel *label; + short a = ALLOC_GPR(); + short b = ALLOC_GPR(); + short c = ALLOC_GPR(); + short d = ALLOC_GPR(); + load_immediate(a, currange->min.lo); + load_immediate(b, currange->min.hi); + if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) { + emitpcode(PC_XORIS, c, selector_gprHi, 0x8000); + emitpcode(PC_XORIS, d, b, 0x8000); + } else { + c = selector_gprHi; + d = b; + } + emitpcode(PC_SUBFC, a, a, selector_gpr); + emitpcode(PC_SUBFE, b, d, c); + emitpcode(PC_SUBFE, b, a, a); + emitpcode(PC_NEG, b, b); + emitpcode(PC_CMPI, 0, b, 0); + label = makepclabel(); + branch_conditional(0, EEQU, 1, label); + I8_treecompare(start, r30); + branch_label(label); + I8_treecompare(r29, end); + } + } +} + +static void generate_tree(ENode *expr) { + Operand op; + + memclrw(&op, sizeof(Operand)); + if (TYPE_IS_8BYTES(expr->rtype)) { + GEN_NODE(expr, &op); + coerce_to_register_pair(&op, expr->rtype, 0, 0); + selector_type = expr->rtype; + selector_gpr = op.reg; + selector_gprHi = op.regHi; + I8_treecompare(0, nranges_minus1); + } else { + GEN_NODE(expr, &op); + if (expr->rtype->size < 4) + extend32(&op, expr->rtype, 0); + ENSURE_GPR(&op, expr->rtype, 0); + selector_type = expr->rtype; + selector_gpr = op.reg; + treecompare(0, nranges_minus1); + } +} + +static Object *create_switch_table(void) { + Object *obj; + ObjectList *list; + UInt32 *outptr; + CaseRange *currange; + SInt32 size; + CInt64 value; + + obj = galloc(sizeof(Object)); + list = galloc(sizeof(ObjectList)); + memclrw(obj, sizeof(Object)); + memclrw(list, sizeof(ObjectList)); + + obj->otype = OT_OBJECT; + obj->access = ACCESSPUBLIC; + obj->datatype = DDATA; + obj->name = CParser_GetUniqueName(); + obj->toc = NULL; + obj->sclass = TK_STATIC; + obj->qual = Q_CONST; + obj->flags |= OBJECT_FLAGS_2 | OBJECT_DEFINED; + obj->u.data.linkname = obj->name; + obj->type = NULL; + createIndirect(obj, 0, 0); + obj->type = TYPE(&void_ptr); + + size = CInt64_GetULong(&range) + 1; + obj->u.data.u.switchtable.size = size; + obj->u.data.u.switchtable.data = lalloc(4 * size); + + currange = caseranges; + outptr = (UInt32 *) obj->u.data.u.switchtable.data; + value = cint64_zero; + while (CInt64_LessEqual(value, range)) { + while (CInt64_Greater(CInt64_Add(first, value), CInt64_Add(currange->min, currange->range))) + currange++; + *outptr = CTool_CreateIndexFromPointer(currange->label); + value = CInt64_Add(value, cint64_one); + outptr++; + } + + list->object = obj; + list->next = switchtables; + switchtables = list; + return list->object; +} + +static void generate_table(ENode *expr, SwitchInfo *info) { + Object *table; + SwitchCase *curcase; + short reg; + short reg2; + short reg3; + Operand op1; + Operand op2; + + CInt64 val3 = {0, 3}; + memclrw(&op1, sizeof(Operand)); + memclrw(&op2, sizeof(Operand)); + + if (CInt64_Greater(first, cint64_zero) && CInt64_Less(first, val3)) { + range = CInt64_Add(range, first); + first = cint64_zero; + } + + table = create_switch_table(); + CError_ASSERT(553, !TYPE_IS_8BYTES(expr->rtype)); + + GEN_NODE(expr, &op1); + if (expr->rtype->size < 4) + extend32(&op1, expr->rtype, 0); + ENSURE_GPR(&op1, expr->rtype, 0); + + reg = op1.reg; + if (CInt64_NotEqual(first, cint64_zero)) { + SInt32 value; + reg = ALLOC_GPR(); + value = -CInt64_GetULong(&first); + if (!FITS_IN_SHORT(value)) { + emitpcode(PC_ADDIS, reg, op1.reg, 0, HIGH_PART(value)); + if (value) + emitpcode(PC_ADDI, reg, reg, 0, LOW_PART(value)); + } else { + emitpcode(PC_ADDI, reg, op1.reg, 0, value); + } + } + + if (!FITS_IN_SHORT(CInt64_GetULong(&range))) { + short tmp = ALLOC_GPR(); + load_immediate(tmp, CInt64_GetULong(&range)); + emitpcode(PC_CMPL, 0, reg, tmp); + } else { + emitpcode(PC_CMPLI, 0, reg, CInt64_GetULong(&range)); + } + + branch_conditional(0, EGREATER, 1, defaultlabel); + if (table->toc) { + op2.optype = OpndType_Symbol; + op2.object = table->toc; + indirect(&op2, NULL); + } else { + op2.optype = OpndType_Symbol; + op2.object = table; + } + + if (op2.optype != OpndType_GPR) { + Coerce_to_register(&op2, TYPE(&void_ptr), reg2 = ALLOC_GPR()); + } + + if (op2.optype != OpndType_GPR) { + CError_FATAL(599); + } else { + if (op2.reg != reg2) + emitpcode(PC_MR, reg2, op2.reg); + } + + if (CInt64_Equal(first, cint64_zero)) { + reg = ALLOC_GPR(); + emitpcode(PC_RLWINM, reg, op1.reg, 2, 0, 29); + } else { + emitpcode(PC_RLWINM, reg, reg, 2, 0, 29); + } + + reg3 = reg2; + emitpcode(PC_LWZX, reg3, reg3, reg); + for (curcase = info->cases; curcase; curcase = curcase->next) + pcbranch(pclastblock, curcase->label->pclabel); + pcbranch(pclastblock, info->defaultlabel->pclabel); + emitpcode(PC_MTCTR, reg3); + branch_indirect(table); +} + +void switchstatement(ENode *expr, SwitchInfo *info) { + Boolean use_table; + SwitchCase *swcase; + + use_table = copts.switch_tables; + + ncases = 0; + for (swcase = info->cases; swcase; swcase = swcase->next) { + if (!swcase->label->pclabel) + swcase->label->pclabel = makepclabel(); + ncases++; + } + + CError_ASSERT(656, ncases >= 0 && ncases <= 0x3333332U); + + if (!info->defaultlabel->pclabel) + info->defaultlabel->pclabel = makepclabel(); + defaultlabel = info->defaultlabel->pclabel; + + build_case_ranges(expr->rtype, info->cases, info->defaultlabel); + + if (TYPE_IS_8BYTES(expr->rtype)) { + generate_tree(expr); + return; + } + + if (!use_table || nranges_minus1 < 8 || (nranges_minus1 * 2) < ((range.lo / 2) + 4)) + generate_tree(expr); + else + generate_table(expr, info); +} + +void dumpswitchtables(Object *funcobj) { + Object *table; + ObjectList *list; + SInt32 size; + UInt32 *array; + + for (list = switchtables; list; list = list->next) { + table = list->object; + CError_ASSERT(694, table->otype == OT_OBJECT && table->access == ACCESSPUBLIC && table->datatype == DDATA); + + size = table->u.data.u.switchtable.size; + array = (UInt32 *) table->u.data.u.switchtable.data; + while (size--) { + *array = CTool_EndianConvertWord32(((PCodeLabel *) CTool_ResolveIndexToPointer(*array))->block->codeOffset); + array++; + } + + ObjGen_DeclareSwitchTable(table, funcobj); + } +} diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/TOC.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/TOC.c new file mode 100644 index 0000000..7af09e3 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/TOC.c @@ -0,0 +1,2272 @@ +#include "cos.h" +#include "compiler/TOC.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CInit.h" +#include "compiler/CInt64.h" +#include "compiler/CFunc.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/Exceptions.h" +#include "compiler/InlineAsm.h" +#include "compiler/InlineAsmPPC.h" +#include "compiler/InstrSelection.h" +#include "compiler/Intrinsics.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/Operands.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/PPCError.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +ObjectList *toclist; +ObjectList *exceptionlist; +void *descriptorlist; +PoolEntry *floatconstpool; +PoolEntry *doubleconstpool; +ObjectList *floatconstlist; +PoolEntry *vectorconstpool; +ObjectList *vectorconstlist; +Object toc0; +Boolean no_descriptors; +Object pic_base; +VarInfo pic_base_varinfo; +short pic_base_reg; +CodeLabelList *codelabellist; + +UInt8 lvslBytes[16][16] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, + 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, + 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, + 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E +}; + +UInt8 lvsrBytes[16][16] = { + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, + 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 +}; + +// forward decls +static void estimate_func_param_size(ENode *node); + +static int disables_optimizer(ENode *node) { + ENode *funcref = node->data.funccall.funcref; + if (ENODE_IS(funcref, EOBJREF)) { + if (!strcmp(CMangler_GetLinkName(funcref->data.objref)->name, "___setjmp")) + return 1; + if (!strcmp(CMangler_GetLinkName(funcref->data.objref)->name, "___vec_setjmp")) + return 1; + } + return 0; +} + +void setupaddressing(void) { + floatconstlist = NULL; + descriptorlist = NULL; + toclist = NULL; + exceptionlist = NULL; + vectorconstlist = NULL; + vectorconstpool = NULL; + floatconstpool = NULL; + doubleconstpool = NULL; + + no_descriptors = 1; + memclrw(&toc0, sizeof(toc0)); + + pic_base_reg = 0; + memclrw(&pic_base, sizeof(pic_base)); + memclrw(&pic_base_varinfo, sizeof(pic_base_varinfo)); + pic_base.otype = OT_OBJECT; + pic_base.type = (Type *) &void_ptr; + pic_base.datatype = DNONLAZYPTR; + pic_base.u.toc.info = &pic_base_varinfo; +} + +void createNonLazyPointer(Object *obj) { + Object *toc; + ObjectList *list; + + toc = galloc(sizeof(Object)); + obj->toc = toc; + memclrw(toc, sizeof(Object)); + + toc->otype = OT_OBJECT; + toc->name = CParser_GetUniqueName(); + toc->toc = NULL; + toc->section = SECT_NONLAZY_PTRS; + toc->u.toc.info = CodeGen_GetNewVarInfo(); + toc->sclass = TK_STATIC; + toc->qual = Q_CONST; + toc->datatype = DNONLAZYPTR; + toc->flags |= OBJECT_FLAGS_2; + toc->type = CDecl_NewPointerType(obj->type); + toc->u.toc.over_load = obj; + toc->u.toc.linkname = CMangler_GetLinkName(obj); + + list = galloc(sizeof(ObjectList)); + memclrw(list, sizeof(ObjectList)); + list->object = toc; + list->next = toclist; + toclist = list; +} + +void referenceIndirectPointer(Object *obj) { + VarInfo *vi = obj->toc->u.toc.info; + vi->used = 1; + vi->usage += copts.optimizesize ? 1 : curstmtvalue; +} + +Object *createIndirect(Object *obj, Boolean flag1, Boolean flag2) { + CError_ASSERT(622, !copts.no_common || (obj->section != SECT_COMMON_VARS) || (obj->qual & Q_20000)); + + if (CParser_HasInternalLinkage(obj)) + return NULL; + if (ObjGen_IsExported(obj)) + return NULL; + + if (!copts.no_common && obj->datatype == DDATA && obj->section == SECT_DEFAULT && (obj->qual & Q_1000000)) + obj->section = SECT_COMMON_VARS; + + if (copts.codegen_dynamic && (!copts.no_common || !(obj->qual & Q_1000000))) { + if (!obj->toc) + createNonLazyPointer(obj); + else if (flag1) + obj->toc->u.toc.info = CodeGen_GetNewVarInfo(); + + if (flag2) + referenceIndirectPointer(obj); + + return obj->toc; + } else { + return NULL; + } +} + +Object *createfloatconstant(Type *type, Float *data) { + ObjectList *list; + Object *obj; + UInt32 *check; + + for (list = floatconstlist; list; list = list->next) { + obj = list->object; + check = (UInt32 *) obj->u.data.u.floatconst; + if (obj->type == type && check[0] == ((UInt32 *) data)[0] && check[1] == ((UInt32 *) data)[1]) + return obj; + } + + obj = galloc(sizeof(Object)); + memclrw(obj, sizeof(Object)); + obj->otype = OT_OBJECT; + obj->type = type; + obj->name = CParser_GetUniqueName(); + obj->toc = NULL; + obj->u.data.info = NULL; + obj->u.data.linkname = obj->name; + obj->sclass = TK_STATIC; + obj->qual = Q_CONST | Q_INLINE_DATA; + obj->datatype = DDATA; + if (type->size == 8) + obj->section = SECT_8BYTE_LITERALS; + else if (type->size == 4) + obj->section = SECT_4BYTE_LITERALS; + else + CError_FATAL(807); + + obj->flags |= OBJECT_FLAGS_2; + + obj->u.data.u.floatconst = galloc(sizeof(Float)); + *obj->u.data.u.floatconst = *data; + + list = galloc(sizeof(ObjectList)); + memclrw(list, sizeof(ObjectList)); + list->object = obj; + list->next = floatconstlist; + floatconstlist = list; + + ObjGen_DeclareFloatConst(obj); + return obj; +} + +Object *createvectorconstant(Type *type, MWVector128 *data) { + ObjectList *list; + Object *obj; + MWVector128 *check; + + for (list = vectorconstlist; list; list = list->next) { + obj = list->object; + check = obj->u.data.u.vector128const; + if (check->ul[0] == data->ul[0] && check->ul[1] == data->ul[1] && check->ul[2] == data->ul[2] && check->ul[3] == data->ul[3]) + return obj; + } + + obj = galloc(sizeof(Object)); + memclrw(obj, sizeof(Object)); + obj->otype = OT_OBJECT; + obj->type = type; + obj->name = CParser_GetUniqueName(); + obj->toc = NULL; + obj->u.data.info = NULL; + obj->u.data.linkname = obj->name; + obj->sclass = TK_STATIC; + obj->qual = Q_CONST | Q_INLINE_DATA; + obj->datatype = DDATA; + if (type->size == 16) + obj->section = SECT_16BYTE_LITERALS; + else + CError_FATAL(900); + + obj->flags |= OBJECT_FLAGS_2; + + obj->u.data.u.vector128const = galloc(sizeof(MWVector128)); + *obj->u.data.u.vector128const = *data; + + list = galloc(sizeof(ObjectList)); + memclrw(list, sizeof(ObjectList)); + list->object = obj; + list->next = vectorconstlist; + vectorconstlist = list; + + ObjGen_DeclareVectorConst(obj); + return obj; +} + +void DeclarePooledConstants(void) { + PoolEntry *entry; + char *buffer; + SInt32 fsize; + SInt32 dsize; + SInt32 vsize; + + fsize = 0; + for (entry = floatconstpool; entry; entry = entry->next) + fsize += 4; + + if (fsize) { + floatconstpool->object->type = CDecl_NewArrayType(TYPE(&stfloat), fsize); + buffer = galloc(fsize); + for (entry = floatconstpool; entry; entry = entry->next) + memcpy(buffer + entry->offset, entry->buffer, 4); + CInit_DeclareReadOnlyData(floatconstpool->object, buffer, NULL, fsize); + } + + dsize = 0; + for (entry = doubleconstpool; entry; entry = entry->next) + dsize += 8; + + if (dsize) { + doubleconstpool->object->type = CDecl_NewArrayType(TYPE(&stdouble), dsize); + buffer = galloc(dsize); + for (entry = doubleconstpool; entry; entry = entry->next) + memcpy(buffer + entry->offset, entry->buffer, 8); + CInit_DeclareReadOnlyData(doubleconstpool->object, buffer, NULL, dsize); + } + + vsize = 0; + for (entry = vectorconstpool; entry; entry = entry->next) + vsize += 16; + + if (vsize) { + vectorconstpool->object->type = CDecl_NewArrayType(TYPE(&stvectorsignedlong), vsize); + buffer = galloc(vsize); + for (entry = vectorconstpool; entry; entry = entry->next) + memcpy(buffer + entry->offset, entry->buffer, 16); + CInit_DeclareReadOnlyData(vectorconstpool->object, buffer, NULL, vsize); + } +} + +static Object *CreatePooledFloatConst(Type *type, Float *data, SInt32 *pOffset) { + if (type->size == 8u) { + PoolEntry *entry; + void *buffer; + Object *object; + SInt32 offset; + + buffer = galloc(8u); + CMach_InitFloatMem(type, *data, buffer); + if (cparamblkptr->precompile == 1) + CError_Error(CErrorStr180); + + for (entry = doubleconstpool; entry; entry = entry->next) { + if (!memcmp(entry->buffer, buffer, 8u)) + break; + } + + if (!entry) { + if (doubleconstpool) { + object = doubleconstpool->object; + offset = doubleconstpool->offset + 8u; + doubleconstpool->object->type->size += 8u; + } else { + DeclInfo di; + memclrw(&di, sizeof(di)); + di.thetype = CDecl_NewArrayType(TYPE(&stdouble), 8u); + di.name = GetHashNameNodeExport("@doubleBase0"); + di.qual = Q_CONST; + di.storageclass = TK_STATIC; + di.is_extern_c = 1; + di.section = SECT_CONST; + object = CParser_NewGlobalDataObject(&di); + object->nspace = cscope_root; + offset = 0; + } + + entry = galloc(sizeof(PoolEntry)); + entry->next = doubleconstpool; + doubleconstpool = entry; + entry->object = object; + entry->offset = offset; + entry->buffer = galloc(8u); + memcpy(entry->buffer, buffer, 8u); + } + + *pOffset = entry->offset; + return entry->object; + } + + if (type->size == 4u) { + PoolEntry *entry; + void *buffer; + Object *object; + SInt32 offset; + + buffer = galloc(4u); + CMach_InitFloatMem(type, *data, buffer); + if (cparamblkptr->precompile == 1) + CError_Error(CErrorStr180); + + for (entry = floatconstpool; entry; entry = entry->next) { + if (!memcmp(entry->buffer, buffer, 4u)) + break; + } + + if (!entry) { + if (floatconstpool) { + object = floatconstpool->object; + offset = floatconstpool->offset + 4u; + object->type->size += 4u; + } else { + DeclInfo di; + memclrw(&di, sizeof(di)); + di.thetype = CDecl_NewArrayType(TYPE(&stfloat), 4u); + di.name = GetHashNameNodeExport("@floatBase0"); + di.qual = Q_CONST; + di.storageclass = TK_STATIC; + di.is_extern_c = 1; + di.section = SECT_CONST; + object = CParser_NewGlobalDataObject(&di); + object->nspace = cscope_root; + offset = 0; + } + + entry = galloc(sizeof(PoolEntry)); + entry->next = floatconstpool; + floatconstpool = entry; + entry->object = object; + entry->offset = offset; + entry->buffer = galloc(4u); + memcpy(entry->buffer, buffer, 4u); + } + + *pOffset = entry->offset; + return entry->object; + } + + CError_FATAL(1183); + return NULL; +} + +Object *CreateFloatConst(Type *type, Float *data, SInt32 *pOffset) { + *pOffset = 0; + return createfloatconstant(type, data); +} + +static void RewriteFloatConst(ENode *expr) { + Object *obj; + SInt32 n; + ENode *subexpr; + + obj = CreateFloatConst(expr->rtype, &expr->data.floatval, &n); + if (n) { + subexpr = makediadicnode(create_objectrefnode(obj), intconstnode(TYPE(&stunsignedlong), n), EADD); + } else { + subexpr = create_objectrefnode(obj); + } + + expr->type = EINDIRECT; + expr->cost = 1; + expr->flags |= Q_CONST; + expr->data.monadic = subexpr; +} + +static void RewriteVectorConst(ENode *expr) { + PoolEntry *entry; + Object *object; + SInt32 offset; + ENode *inner; + UInt8 data[16]; + + CMach_InitVectorMem(expr->rtype, expr->data.vector128val, data, 1); + + if (cparamblkptr->precompile == 1) + CError_Error(CErrorStr180); + + for (entry = vectorconstpool; entry; entry = entry->next) { + if (!memcmp(entry->buffer, data, 16)) + break; + } + + if (!entry) { + if (vectorconstpool) { + object = vectorconstpool->object; + offset = vectorconstpool->offset + 16; + vectorconstpool->object->type->size += 16; + } else { + DeclInfo di; + memclrw(&di, sizeof(di)); + di.thetype = CDecl_NewArrayType(TYPE(&stvectorsignedlong), 16); + di.name = GetHashNameNodeExport("@vectorBase0"); + di.qual = Q_CONST; + di.storageclass = TK_STATIC; + di.is_extern_c = 1; + di.section = SECT_CONST; + object = CParser_NewGlobalDataObject(&di); + object->nspace = cscope_root; + offset = 0; + } + + entry = galloc(sizeof(PoolEntry)); + entry->next = vectorconstpool; + vectorconstpool = entry; + entry->object = object; + entry->offset = offset; + entry->buffer = galloc(16); + memcpy(entry->buffer, data, 16); + } + + if (entry->offset) { + inner = makediadicnode( + create_objectrefnode(entry->object), + intconstnode(TYPE(&stunsignedlong), entry->offset), + EADD); + } else { + inner = create_objectrefnode(entry->object); + } + + expr->type = EINDIRECT; + expr->cost = 1; + expr->flags |= ENODE_FLAG_CONST; + expr->data.monadic = inner; +} + +static Object *createcodelabel(CLabel *label) { + CodeLabelList *list; + Object *obj; + + for (list = codelabellist; list; list = list->next) { + if (list->label == label) + return list->object; + } + + obj = galloc(sizeof(Object)); + memclrw(obj, sizeof(Object)); + obj->otype = OT_OBJECT; + obj->type = (Type *) &void_ptr; + obj->name = label->uniquename; + obj->toc = NULL; + obj->u.data.info = NULL; // not sure if this is the right union! + obj->sclass = TK_STATIC; + obj->qual = Q_CONST; + obj->datatype = DDATA; + obj->flags |= OBJECT_FLAGS_2 | OBJECT_DEFINED; + + list = galloc(sizeof(CodeLabelList)); + memclrw(list, sizeof(CodeLabelList)); + list->object = obj; + list->label = label; + list->next = codelabellist; + codelabellist = list; + + return obj; +} + +void dumpcodelabels(Object *func) { + CodeLabelList *list; + + for (list = codelabellist; list; list = list->next) + ObjGen_DeclareCodeLabel(list->object, list->label->pclabel->block->codeOffset, func); +} + +static void referenceexception(Object *obj) { + ObjectList *list; + + if (obj && obj->otype == OT_OBJECT && obj->datatype == DLOCAL) { + for (list = exceptionlist; list; list = list->next) { + if (list->object == obj) + return; + } + + list = lalloc(sizeof(ObjectList)); + memclrw(list, sizeof(ObjectList)); + list->object = obj; + list->next = exceptionlist; + exceptionlist = list; + } +} + +static ENodeType invert_relop(ENodeType nodetype) { + switch (nodetype) { + case ELESS: return EGREATEREQU; + case EGREATER: return ELESSEQU; + case ELESSEQU: return EGREATER; + case EGREATEREQU: return ELESS; + case EEQU: return ENOTEQU; + case ENOTEQU: return EEQU; + default: return nodetype; + } +} + +static ENode *COND_to_COMPARE(ENode *cond, ENode *expr1, ENode *expr2) { + SInt32 val1; + SInt32 val2; + SInt32 condval; + ENodeType invop; + + while (expr1->type == ETYPCON && TYPE_FITS_IN_REGISTER(expr1->rtype)) + expr1 = expr1->data.monadic; + while (expr2->type == ETYPCON && TYPE_FITS_IN_REGISTER(expr2->rtype)) + expr2 = expr2->data.monadic; + + if (expr1->type != EINTCONST || !TYPE_FITS_IN_REGISTER(expr1->rtype) || !CInt64_IsInRange(expr1->data.intval, 4)) + return NULL; + if (expr2->type != EINTCONST || !TYPE_FITS_IN_REGISTER(expr2->rtype) || !CInt64_IsInRange(expr2->data.intval, 4)) + return NULL; + + val1 = expr1->data.intval.lo; + val2 = expr2->data.intval.lo; + condval = 0; + switch (val1) { + case 1: + if (val2 != 0) + return NULL; + break; + case 0: + condval = 1; + if (val2 != 1) + return NULL; + break; + default: + return NULL; + } + + while (cond->type == ELOGNOT) { + condval = (condval + 1) & 1; + cond = cond->data.monadic; + } + + if (condval) { + invop = invert_relop(cond->type); + if (invop == cond->type) + return NULL; + cond->type = invop; + } + + return cond; +} + +static ENode *comparewithzero(ENode *expr) { + ENode *expr1; + ENode *expr2; + ENode *tmp; + + expr1 = lalloc(sizeof(ENode)); + memclrw(expr1, sizeof(ENode)); + expr2 = lalloc(sizeof(ENode)); + memclrw(expr2, sizeof(ENode)); + + while (expr->type == EFORCELOAD || expr->type == ETYPCON || expr->type == ECOMMA) { + if (!TYPE_FITS_IN_REGISTER(expr->rtype)) + break; + if (expr->type == ECOMMA) { + expr->data.diadic.right = comparewithzero(expr->data.diadic.right); + return expr; + } + expr = expr->data.monadic; + } + + if (expr->type == ECOND && TYPE_FITS_IN_REGISTER(expr->rtype)) { + tmp = COND_to_COMPARE(expr->data.cond.cond, expr->data.cond.expr1, expr->data.cond.expr2); + if (tmp) + expr = tmp; + } + + if (expr->type >= ELESS && expr->type <= ENOTEQU) + return expr; + + if (IS_TYPE_FLOAT(expr->rtype)) { + static Float float0 = {0.0}; + + expr2->type = EFLOATCONST; + expr2->cost = 0; + expr2->rtype = (expr->rtype->size == 4) ? (Type *) &stfloat : (Type *) &stdouble; + expr2->data.floatval = float0; + } else { + expr2->type = EINTCONST; + expr2->cost = 0; + if (TYPE_IS_8BYTES(expr->rtype)) + expr2->rtype = (Type *) &stsignedlonglong; + else + expr2->rtype = (Type *) &stsignedint; + expr2->data.intval.lo = 0; + expr2->data.intval.hi = 0; + } + + expr1->type = ENOTEQU; + expr1->cost = expr->cost; + expr1->rtype = (Type *) &stsignedint; + expr1->data.diadic.left = expr; + expr1->data.diadic.right = expr2; + return expr1; +} + +static void rewritefunctioncallreturningstruct(ENode *expr) { + ENode *ret_expr; + ENode *copy; + + ret_expr = expr->data.funccall.args->node; + + copy = lalloc(sizeof(ENode)); + memclrw(copy, sizeof(ENode)); + + *copy = *expr; + expr->type = ECOMMA; + expr->data.diadic.left = copy; + expr->data.diadic.right = ret_expr; +} + +static void rewritestrcpy(ENode *expr) { + ENode *int_expr; + ENodeList *list; + + int_expr = lalloc(sizeof(ENode)); + memclrw(int_expr, sizeof(ENode)); + int_expr->type = EINTCONST; + int_expr->cost = 0; + int_expr->flags = 0; + int_expr->rtype = (Type *) &stunsignedlong; + CInt64_SetLong(&int_expr->data.intval, expr->data.funccall.args->next->node->data.string.size); + + list = lalloc(sizeof(ENodeList)); + memclrw(list, sizeof(ENodeList)); + list->next = NULL; + list->node = int_expr; + expr->data.funccall.args->next->next = list; + expr->data.funccall.funcref->data.objref = __memcpy_object; +} + +static SInt32 magnitude(Type *type) { + if (IS_TYPE_FLOAT(type)) + return type->size * 4; + else if (is_unsigned(type)) + return (type->size * 2) + 1; + else + return type->size * 2; +} + +static Type *promote_type(Type *type) { + if (IS_TYPE_ENUM(type)) + type = TYPE_ENUM(type)->enumtype; + if (TYPE_INTEGRAL(type)->integral > stsignedint.integral) + return type; + else + return (Type *) &stsignedint; +} + +static Type *common_type(Type *type1, Type *type2) { + Type *tmp; + + if (IS_TYPE_FLOAT(type1) || IS_TYPE_FLOAT(type2)) { + if (TYPE_INTEGRAL(type1)->integral > TYPE_INTEGRAL(type2)->integral) + return type1; + else + return type2; + } + + type1 = promote_type(type1); + type2 = promote_type(type2); + if (type1 != type2) { + if (TYPE_INTEGRAL(type1)->integral < TYPE_INTEGRAL(type2)->integral) { + tmp = type1; + type1 = type2; + type2 = tmp; + } + + if (type1->size == type2->size && !is_unsigned(type1) && is_unsigned(type2)) { + if (type1 == (Type *) &stsignedlong) { + type1 = (Type *) &stunsignedlong; + } else { + CError_ASSERT(1789, type1 == (Type *) &stsignedlonglong); + type1 = (Type *) &stunsignedlonglong; + } + } + } + + return type1; +} + +static void rewrite_opassign(ENode *expr, ENodeType exprtype) { + ENode *left_sub; + ENode *right; + Type *left_type; + Type *right_type; + ENode *new_expr; + ENode *tmp; + Type *commontype; + Type *promo_left; + Type *promo_right; + + left_sub = expr->data.diadic.left->data.monadic; + right = expr->data.diadic.right; + left_type = expr->data.diadic.left->rtype; + right_type = expr->data.diadic.right->rtype; + + new_expr = lalloc(sizeof(ENode)); + memclrw(new_expr, sizeof(ENode)); + new_expr->type = exprtype; + new_expr->rtype = left_type; + new_expr->data.diadic.left = expr->data.diadic.left; + new_expr->data.diadic.right = right; + + expr->type = EASS; + expr->data.diadic.left = left_sub; + expr->data.diadic.right = new_expr; + + if (left_sub->type != EOBJREF) { + ENode *define; + ENode *reuse; + + define = lalloc(sizeof(ENode)); + memclrw(define, sizeof(ENode)); + define->type = EDEFINE; + define->rtype = left_type; + + reuse = lalloc(sizeof(ENode)); + memclrw(reuse, sizeof(ENode)); + reuse->type = EREUSE; + reuse->rtype = left_type; + reuse->data.monadic = define; + + if (left_sub->type != EBITFIELD) { + define->data.monadic = expr->data.diadic.left; + expr->data.diadic.left = define; + new_expr->data.diadic.left->data.diadic.left = reuse; + } else { + ENode *copy; + define->data.monadic = left_sub->data.diadic.left; + left_sub->data.diadic.left = define; + + copy = lalloc(sizeof(ENode)); + *copy = *left_sub; + copy->data.diadic.left = reuse; + new_expr->data.diadic.left->data.diadic.left = copy; + } + } + + switch (exprtype) { + case EADD: + case ESUB: + if (IS_TYPE_POINTER(left_type)) + break; + if (right->type == EINTCONST && TYPE_FITS_IN_REGISTER(left_type)) + break; + case EAND: + case EXOR: + case EOR: + if (left_type == right_type) + break; + case EMUL: + case EDIV: + case EMODULO: + commontype = common_type(left_type, right_type); + if (left_type != commontype) { + tmp = lalloc(sizeof(ENode)); + memclrw(tmp, sizeof(ENode)); + tmp->type = ETYPCON; + tmp->rtype = left_type; + tmp->data.monadic = expr->data.diadic.right; + expr->data.diadic.right = tmp; + + tmp = lalloc(sizeof(ENode)); + memclrw(tmp, sizeof(ENode)); + tmp->type = ETYPCON; + tmp->rtype = commontype; + tmp->data.monadic = new_expr->data.diadic.left; + new_expr->data.diadic.left = tmp; + } + if (right_type != commontype) { + tmp = lalloc(sizeof(ENode)); + memclrw(tmp, sizeof(ENode)); + tmp->type = ETYPCON; + tmp->rtype = commontype; + tmp->data.monadic = new_expr->data.diadic.right; + new_expr->data.diadic.right = tmp; + } + new_expr->rtype = commontype; + break; + + case ESHL: + case ESHR: + promo_left = promote_type(left_type); + promo_right = promote_type(right_type); + if (left_type != promo_left) { + tmp = lalloc(sizeof(ENode)); + memclrw(tmp, sizeof(ENode)); + tmp->type = ETYPCON; + tmp->rtype = left_type; + tmp->data.monadic = expr->data.diadic.right; + expr->data.diadic.right = tmp; + + tmp = lalloc(sizeof(ENode)); + memclrw(tmp, sizeof(ENode)); + tmp->type = ETYPCON; + tmp->rtype = promo_left; + tmp->data.monadic = new_expr->data.diadic.left; + new_expr->data.diadic.left = tmp; + } + if (right_type != promo_right) { + if (new_expr->data.diadic.right->type == EINTCONST && promo_right == (Type *) &stsignedint) { + new_expr->data.diadic.right->rtype = (Type *) &stsignedint; + } else { + tmp = lalloc(sizeof(ENode)); + memclrw(tmp, sizeof(ENode)); + tmp->type = ETYPCON; + tmp->rtype = promo_right; + tmp->data.monadic = new_expr->data.diadic.right; + new_expr->data.diadic.right = tmp; + } + } + new_expr->rtype = promo_left; + break; + } +} + +static void rewrite_preincdec(ENode *expr) { + ENode *subexpr; // r31 + Type *type; // r28 + ENode *new_expr; // r29 + + subexpr = expr->data.monadic; + type = expr->rtype; + + new_expr = lalloc(sizeof(ENode)); + memclrw(new_expr, sizeof(ENode)); + + if (IS_TYPE_FLOAT(type)) { + new_expr->type = EFLOATCONST; + new_expr->cost = 0; + new_expr->rtype = type; + new_expr->data.floatval = one_point_zero; + } else if (IS_TYPE_POINTER(type)) { + new_expr->type = EINTCONST; + new_expr->cost = 0; + new_expr->rtype = (Type *) &stunsignedlong; + new_expr->data.intval.hi = 0; + new_expr->data.intval.lo = TYPE_POINTER(type)->target->size; + } else { + new_expr->type = EINTCONST; + new_expr->cost = 0; + new_expr->rtype = type; + new_expr->data.intval.hi = 0; + new_expr->data.intval.lo = 1; + } + + expr->type = (expr->type == EPREDEC) ? ESUBASS : EADDASS; + expr->data.diadic.left = subexpr; + expr->data.diadic.right = new_expr; +} + +// Don't know what this would be called in the original, but weh +typedef union signed_vec { + SInt8 sc[16]; + SInt16 ss[8]; + SInt32 sl[4]; +} signed_vec; + +Boolean canoptimizevectorconst(MWVector128 *vecp, Type *type, COVCResult *result) { + // this function is very broken + signed_vec vec; + union { SInt32 lg; SInt8 ch[4]; } conv32; + union { SInt16 sh; SInt8 ch[2]; } conv16; + char flag; + SInt8 first8; + SInt16 first16; + SInt32 first32; + int i; + char ci; + UInt32 l0, l1, l2, l3; + + if (IS_TYPE_VECTOR(type)) { + vec = *((signed_vec *) vecp); + + first8 = vec.sc[0]; + flag = 1; + i = 1; + while (flag && i < 16) + flag = first8 == vec.sc[i++]; + /*flag = 1; + for (i = 1; flag && i < 16; i++) { + flag = first8 == vec.sc[i]; + }*/ + + if (flag && first8 < 16 && first8 > -17) { + if (result) { + result->op1 = PC_VSPLTISB; + result->op2 = -1; + result->arg = first8; + } + return 1; + } + + first16 = vec.ss[0]; + flag = 1; + for (i = 1; flag && i < 8; i++) { + flag = vec.ss[i] == first16; + } + + conv16.sh = first16; + if (flag && conv16.ch[0] == 0 && conv16.ch[1] < 16 && conv16.ch[1] >= 0) { + if (result) { + result->op1 = PC_VSPLTISH; + result->op2 = -1; + result->arg = conv16.ch[1]; + } + return 1; + } + + if (flag && conv16.ch[0] == -1 && (conv16.ch[1] & 0xF0) == 0xF0) { + if (result) { + result->op1 = PC_VSPLTISH; + result->op2 = -1; + result->arg = conv16.ch[1]; + } + return 1; + } + + first32 = vec.sl[0]; + flag = 1; + for (i = 1; flag && i < 4; i++) { + flag = vec.sl[i] == first32; + } + + conv32.lg = first32; + if (flag && conv32.ch[0] == 0 && conv32.ch[1] == 0 && conv32.ch[2] == 0 && conv32.ch[3] < 16 && conv32.ch[3] >= 0) { + if (result) { + result->op1 = PC_VSPLTISW; + result->op2 = -1; + result->arg = conv32.ch[3]; + } + return 1; + } + + if (flag && conv32.ch[0] == -1 && conv32.ch[1] == -1 && conv32.ch[2] == -1 && (conv32.ch[3] & 0xF0) == 0xF0) { + if (result) { + result->op1 = PC_VSPLTISW; + result->op2 = -1; + result->arg = conv32.ch[3]; + } + return 1; + } + + l0 = vec.sl[0]; + l1 = vec.sl[1]; + l2 = vec.sl[2]; + l3 = vec.sl[3]; + for (ci = 0; ci < 16; ci++) { + UInt32 *l; + UInt32 *r; + + l = (UInt32 *) lvslBytes[(char) ci]; + r = (UInt32 *) lvsrBytes[(char) ci]; + if (l0 == l[0] && l1 == l[1] && l2 == l[2] && l3 == l[3]) { + if (result) { + result->op1 = -1; + result->op2 = PC_LVSL; + result->arg = ci; + } + return 1; + } + if (l0 == r[0] && l1 == r[1] && l2 == r[2] && l3 == r[3]) { + if (result) { + result->op1 = -1; + result->op2 = PC_LVSR; + result->arg = ci; + } + return 1; + } + } + } + + return 0; +} + +static SInt32 countindirects(ENode *expr) { + SInt32 tmp1; + SInt32 tmp2; + + switch (expr->type) { + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EVECTOR128CONST: + return 0; + case ECOND: + if (expr->data.cond.cond->hascall || expr->data.cond.expr1->hascall || expr->data.cond.expr2->hascall) + return 2; + + if ((tmp1 = countindirects(expr->data.cond.cond)) >= 2) + return 2; + if ((tmp2 = countindirects(expr->data.cond.expr1)) >= 2) + return 2; + if (tmp2 > tmp1) + tmp1 = tmp2; + if ((tmp2 = countindirects(expr->data.cond.expr2)) >= 2) + return 2; + if (tmp2 > tmp1) + tmp1 = tmp2; + return tmp1; + case EFUNCCALL: + case EFUNCCALLP: + return 2; + case EMUL: + case EMULV: + case EDIV: + case EMODULO: + case EADDV: + case ESUBV: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBCLR: + case EBTST: + case EBSET: + if ((tmp1 = countindirects(expr->data.diadic.left)) >= 2) + return 2; + if ((tmp2 = countindirects(expr->data.diadic.right)) >= 2) + return 2; + if (tmp2 > tmp1) + tmp1 = tmp2; + return tmp1; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + if (expr->type == EINDIRECT) + return countindirects(expr->data.monadic) + 1; + else + return countindirects(expr->data.monadic); + default: + return 2; + } +} + +static Boolean DetectCondSideAffect(ENode *expr) { + switch (expr->type) { + case EMUL: + case EMULV: + case EDIV: + case EMODULO: + case EADDV: + case ESUBV: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case EAND: + case EXOR: + case EOR: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBCLR: + case EBTST: + case EBSET: + if (DetectCondSideAffect(expr->data.diadic.left)) + return 1; + return DetectCondSideAffect(expr->data.diadic.right); + case EINDIRECT: + if (expr->data.monadic->type == EINDIRECT) + return 1; + if (expr->data.monadic->type == EOBJREF) { + if (expr->data.monadic->data.objref->datatype != DLOCAL && expr->data.monadic->data.objref->datatype != DDATA) + return 1; + if (IS_TYPE_POINTER(expr->data.monadic->data.objref->type)) + return 1; + return Registers_GetVarInfo(expr->data.monadic->data.objref)->noregister != 0; + } + return 1; + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + return DetectCondSideAffect(expr->data.monadic); + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EVECTOR128CONST: + return 0; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case ELAND: + case ELOR: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOND: + case EFUNCCALL: + case EFUNCCALLP: + case EMFPOINTER: + case ENULLCHECK: + case EPRECOMP: + case EDEFINE: + case EREUSE: + case EASSBLK: + case ECONDASS: + return 1; + default: + CError_FATAL(2523); + return 1; + } +} + +static UInt8 WeightandSumOps(ENode *expr) { + UInt32 score; + + switch (expr->type) { + case ECOND: + case ECONDASS: + score = WeightandSumOps(expr->data.cond.cond); + score += WeightandSumOps(expr->data.cond.expr1); + score += WeightandSumOps(expr->data.cond.expr2); + break; + case EMUL: + case EMULV: + case EMULASS: + score = WeightandSumOps(expr->data.diadic.left) + 10; + score += WeightandSumOps(expr->data.diadic.right); + break; + case EDIV: + case EMODULO: + case EDIVASS: + case EMODASS: + score = WeightandSumOps(expr->data.diadic.left) + 20; + score += WeightandSumOps(expr->data.diadic.right); + break; + case EADDV: + case ESUBV: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case EASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBCLR: + case EBTST: + case EBSET: + score = WeightandSumOps(expr->data.diadic.left) + 1; + score += WeightandSumOps(expr->data.diadic.right); + break; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + score = WeightandSumOps(expr->data.monadic) + 1; + break; + case EINDIRECT: + if (expr->data.monadic->type == EOBJREF && expr->data.monadic->data.objref->datatype == DLOCAL) + if (!Registers_GetVarInfo(expr->data.monadic->data.objref)->noregister) + return 0; + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + score = WeightandSumOps(expr->data.monadic); + break; + case EOBJREF: + score = 0; + break; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EVECTOR128CONST: + score = 0; + break; + case EFUNCCALL: + case EFUNCCALLP: + score = 5; + break; + default: + score = 255; + } + + if (score >= 255) + score = 255; + return (UInt8) score; +} + +Boolean TOC_use_fsel(ENode *expr) { + ENode *left; + ENode *right; + Type *rtype; + int score1; + int score2; + + left = expr->data.cond.expr1; + right = expr->data.cond.expr2; + rtype = expr->rtype; + + if (!copts.peephole) return 0; + if (!copts.gen_fsel) return 0; + if (left->hascall) return 0; + if (right->hascall) return 0; + if (!IS_TYPE_FLOAT(rtype)) return 0; + if (!IS_TYPE_FLOAT(left->rtype)) return 0; + if (!IS_TYPE_FLOAT(right->rtype)) return 0; + + if (expr->data.cond.cond->type < ELESS || expr->data.cond.cond->type > ENOTEQU) + return 0; + if (!IS_TYPE_FLOAT(expr->data.cond.cond->data.diadic.right->rtype)) + return 0; + if (expr->data.cond.cond->type == ELOGNOT || expr->data.cond.cond->type == ELAND || expr->data.cond.cond->type == ELOR) + return 0; + + if (expr->type == ECONDASS) { + if (left->type != EINDIRECT) + return 0; + if (left->data.monadic->type != EOBJREF) + return 0; + } + + if (DetectCondSideAffect(left)) + return 0; + if (DetectCondSideAffect(right)) + return 0; + + if (expr->type == ECONDASS) + score1 = 1; + else + score1 = WeightandSumOps(left); + score2 = WeightandSumOps(right); + + if (score1 > copts.gen_fsel) + return 0; + else if (score2 > copts.gen_fsel) + return 0; + else + return 1; +} + +Boolean TOC_use_isel(ENode *expr, Boolean flag) { + int opt; + ENode *left; + ENode *right; + Type *rtype; + Object *obj; + int score1; + int score2; + + left = expr->data.cond.expr1; + right = expr->data.cond.expr2; + rtype = expr->rtype; + if (flag) + opt = 10; + else + opt = copts.gen_isel; + + if (!opt) return 0; + if (!copts.peephole) return 0; + if (left->hascall) return 0; + if (right->hascall) return 0; + if (!TYPE_FITS_IN_REGISTER(rtype)) return 0; + if (!TYPE_FITS_IN_REGISTER(left->rtype)) return 0; + if (!TYPE_FITS_IN_REGISTER(right->rtype)) return 0; + + if (expr->data.cond.cond->type < ELESS || expr->data.cond.cond->type > ENOTEQU) + return 0; + if (TYPE_IS_8BYTES(rtype)) + return 0; + + if (flag) { + if (!TYPE_FITS_IN_REGISTER(expr->data.cond.cond->data.diadic.right->rtype)) + return 0; + if (TYPE_IS_8BYTES(expr->data.cond.cond->data.diadic.right->rtype)) + return 0; + } + + if (expr->type == ECONDASS) { + if (left->type != EINDIRECT) + return 0; + if (left->data.monadic->type != EOBJREF) + return 0; + if (flag) { + obj = left->data.monadic->data.objref; + if (obj->datatype != DLOCAL) + return 0; + if ((Registers_GetVarInfo(obj) ? Registers_GetVarInfo(obj)->reg : 0) == 0) + return 0; + if (obj->u.var.info->rclass != RegClass_GPR) + return 0; + } + } + + if (DetectCondSideAffect(left)) + return 0; + if (DetectCondSideAffect(right)) + return 0; + + if (expr->type == ECONDASS) + score1 = 1; + else + score1 = WeightandSumOps(left); + score2 = WeightandSumOps(right); + + if (score1 > opt) + return 0; + else if (score2 > opt) + return 0; + else + return 1; +} + +SInt32 GetSizeSkip(ENode *expr) { + if (expr->type == EASS) + expr = expr->data.diadic.right; + if (expr->type == ETYPCON && expr->data.monadic->rtype->size < expr->rtype->size) + return expr->data.monadic->rtype->size; + else + return expr->rtype->size; +} + +void Optimize64bitMath(ENode *expr) { + ENode *left; // r23 + ENode *right; // r28 + SInt32 leftsize; // r24 + SInt32 rightsize; // r25 + SInt32 totalsize; // r22 + int unsignedflag; // r4 + + CError_ASSERT(2886, TYPE_IS_8BYTES(expr->rtype)); + + left = expr->data.diadic.left; + right = expr->data.diadic.right; + leftsize = GetSizeSkip(left); + totalsize = (leftsize + (rightsize = GetSizeSkip(right))); + unsignedflag = is_unsigned(expr->rtype) != 0; + + switch (totalsize) { + case 2: + case 3: + case 4: + if (unsignedflag) { + left->rtype = (Type *) &stunsignedint; + right->rtype = (Type *) &stunsignedint; + } else { + left->rtype = (Type *) &stsignedint; + right->rtype = (Type *) &stsignedint; + } + break; + case 5: + case 6: + case 8: + case 9: + case 10: + case 12: + if (expr->type != ESUB || leftsize >= rightsize) { + if (leftsize < 4) { + if (unsignedflag) + left->rtype = (Type *) &stunsignedint; + else + left->rtype = (Type *) &stsignedint; + } else { + if (left->type == ETYPCON && left->data.monadic->rtype != (Type *) &stfloat) + expr->data.diadic.left = left->data.monadic; + } + if (rightsize < 4) { + if (unsignedflag) + right->rtype = (Type *) &stunsignedint; + else + right->rtype = (Type *) &stsignedint; + } else { + if (right->type == ETYPCON && right->data.monadic->rtype != (Type *) &stfloat) + expr->data.diadic.right = right->data.monadic; + } + } + break; + case 16: + break; + default: + CError_FATAL(2975); + } +} + +static Boolean OptimizeNestedAssginments(ENode **pexpr, Object *check) { + ENode *expr; + Boolean success1; + Boolean success2; + + expr = *pexpr; + switch (expr->type) { + case EOBJREF: + return check != expr->data.objref; + case EMUL: + case EMULV: + case EDIV: + case EMODULO: + case EADDV: + case ESUBV: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBCLR: + case EBTST: + case EBSET: + switch (expr->type) { + case EASS: + if (ENODE_IS(expr->data.diadic.left, EOBJREF) && expr->data.diadic.left->data.objref == check) { + *pexpr = expr->data.diadic.right; + return OptimizeNestedAssginments(pexpr, check); + } + break; + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + CError_FATAL(3033); + return 0; + } + if (OptimizeNestedAssginments(&expr->data.diadic.right, check)) + return OptimizeNestedAssginments(&expr->data.diadic.left, check); + else + return 0; + break; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + return OptimizeNestedAssginments(&expr->data.monadic, check); + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EVECTOR128CONST: + return 1; + case ECOND: + success2 = OptimizeNestedAssginments(&expr->data.cond.expr2, check); + success1 = OptimizeNestedAssginments(&expr->data.cond.expr1, check); + if (!success2 || !success1) + return 0; + return OptimizeNestedAssginments(&expr->data.cond.cond, check) == 0; + case ECONDASS: + if (!OptimizeNestedAssginments(&expr->data.cond.expr2, check)) + return 0; + if (OptimizeNestedAssginments(&expr->data.cond.cond, check)) + return OptimizeNestedAssginments(&expr->data.cond.expr1, check) == 0; + else + return 0; + case EFUNCCALL: + case EFUNCCALLP: + case EMFPOINTER: + case ENULLCHECK: + case EPRECOMP: + case EDEFINE: + case EREUSE: + case EASSBLK: + return 0; + default: + CError_FATAL(3083); + return 0; + } +} + +static void expandTOCexpression(ENode *expr, Type *type, int ignored) { + Object *obj; + Object *tmpobj; + ENode *cond; + ENode *tmpexpr; + ENode *newexpr; + ENodeList *list; + + expr->ignored = ignored; + switch (expr->type) { + case EINTCONST: + expr->hascall = 0; + break; + case EFLOATCONST: + uses_globals = 1; + RewriteFloatConst(expr); + expandTOCexpression(expr, NULL, 0); + break; + case EVECTOR128CONST: + if (!canoptimizevectorconst(&expr->data.vector128val, expr->rtype, NULL)) { + uses_globals = 1; + RewriteVectorConst(expr); + expandTOCexpression(expr, NULL, 0); + } + break; + case ESTRINGCONST: + uses_globals = 1; + CInit_RewriteString(expr, 1); + expandTOCexpression(expr, NULL, 0); + break; + case EOBJREF: + obj = expr->data.objref; + CError_ASSERT(3203, obj->datatype != DALIAS); + if (obj->datatype == DFUNC || obj->datatype == DVFUNC) + uses_globals = 1; + if (obj->datatype == DDATA) { + uses_globals = 1; + if (createIndirect(obj, 0, 1)) { + tmpexpr = lalloc(sizeof(ENode)); + memclrw(tmpexpr, sizeof(ENode)); + tmpexpr->type = EOBJREF; + tmpexpr->cost = 0; + tmpexpr->data.objref = obj->toc; + tmpexpr->rtype = CDecl_NewPointerType(expr->rtype); + + expr->type = EINDIRECT; + expr->cost = 1; + expr->data.monadic = tmpexpr; + } + } + expr->hascall = 0; + break; + case ECONDASS: + expr->ignored = 0; + case ECOND: + if (!ENODE_IS_RANGE(expr->data.cond.cond, ELESS, ENOTEQU)) + expr->data.cond.cond = comparewithzero(expr->data.cond.cond); + expandTOCexpression(expr->data.cond.expr1, NULL, ignored); + expandTOCexpression(expr->data.cond.expr2, NULL, ignored); + if (TOC_use_fsel(expr)) { + cond = expr->data.cond.cond; + if (ENODE_IS(cond->data.diadic.right, EFLOATCONST) && CMach_FloatIsZero(cond->data.diadic.right->data.floatval)) { + expandTOCexpression(cond->data.diadic.left, NULL, 0); + } else if (ENODE_IS(cond->data.diadic.left, EFLOATCONST) && CMach_FloatIsZero(cond->data.diadic.left->data.floatval)) { + expandTOCexpression(cond->data.diadic.right, NULL, 0); + } else { + expandTOCexpression(expr->data.cond.cond, NULL, 0); + } + } else { + expandTOCexpression(expr->data.cond.cond, NULL, 0); + } + expr->hascall = expr->data.cond.cond->hascall | expr->data.cond.expr1->hascall | expr->data.cond.expr2->hascall; + break; + case EFUNCCALL: + case EFUNCCALLP: + if (is_intrinsic_function_call(expr)) { + expr->hascall = 0; + if ((expr->data.funccall.funcref->data.objref->u.func.u.intrinsicid & 0xFFFFu) == Intrinsic_008) { + if (copts.altivec_model) + update_frame_align(16); + dynamic_stack = 1; + requires_frame = 1; + } else if ((expr->data.funccall.funcref->data.objref->u.func.u.intrinsicid & 0xFFFFu) == Intrinsic_035) { + if (expr->data.funccall.args->next->node->type == ESTRINGCONST) { + rewritestrcpy(expr); + } else { + requires_frame = 1; + makes_call = 1; + expr->hascall = 1; + } + } else if ((expr->data.funccall.funcref->data.objref->u.func.u.intrinsicid & 0xFFFFu) == Intrinsic_036) { + if (expr->data.funccall.args->next->next->node->type != EINTCONST) { + requires_frame = 1; + makes_call = 1; + expr->hascall = 1; + } + } + } else { + requires_frame = 1; + makes_call = 1; + expr->hascall = 1; + } + + if (disables_optimizer(expr)) { + disable_optimizer |= 1; + if (copts.disable_registers) + disable_optimizer |= 2; + } + + if (ENODE_IS(expr->data.funccall.funcref, EINDIRECT) && IS_TYPE_FUNC(expr->data.funccall.funcref->rtype)) + *expr->data.funccall.funcref = *expr->data.funccall.funcref->data.monadic; + + if (ENODE_IS(expr->data.funccall.funcref, EOBJREF)) { + expr->data.funccall.funcref->hascall = 0; + if (expr->data.funccall.funcref->data.objref->datatype == DVFUNC && (expr->data.funccall.funcref->flags & ENODE_FLAG_80)) { + tmpobj = galloc(sizeof(Object)); + *tmpobj = *expr->data.funccall.funcref->data.objref; + tmpobj->datatype = DFUNC; + expr->data.funccall.funcref->data.objref = tmpobj; + } + } else { + expandTOCexpression(expr->data.funccall.funcref, NULL, 0); + } + + for (list = expr->data.funccall.args; list; list = list->next) + expandTOCexpression(list->node, NULL, 0); + + if (expr->hascall) + estimate_func_param_size(expr); + + if (is_intrinsic_function_call(expr)) { + for (list = expr->data.funccall.args; list; list = list->next) + expr->hascall |= list->node->hascall; + } + + if (CMach_PassResultInHiddenArg(TYPE_FUNC(expr->data.funccall.functype)->functype)) + rewritefunctioncallreturningstruct(expr); + + break; + case ECOMMA: + expandTOCexpression(expr->data.diadic.left, NULL, 1); + expandTOCexpression(expr->data.diadic.right, NULL, ignored); + expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; + break; + case ELAND: + case ELOR: + if (!ENODE_IS(expr->data.diadic.left, ELOGNOT) && !ENODE_IS2(expr->data.diadic.left, ELAND, ELOR) && !ENODE_IS_RANGE(expr->data.diadic.left, ELESS, ENOTEQU)) + expr->data.diadic.left = comparewithzero(expr->data.diadic.left); + if (!ENODE_IS(expr->data.diadic.right, ELOGNOT) && !ENODE_IS2(expr->data.diadic.right, ELAND, ELOR) && !ENODE_IS_RANGE(expr->data.diadic.right, ELESS, ENOTEQU)) + expr->data.diadic.right = comparewithzero(expr->data.diadic.right); + expandTOCexpression(expr->data.diadic.left, NULL, 0); + expandTOCexpression(expr->data.diadic.right, NULL, 0); + expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; + break; + case EDIVASS: + if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype)) + uses_globals = 1; + rewrite_opassign(expr, EDIV); + goto opassign_common; + case EMULASS: + if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype)) + uses_globals = 1; + rewrite_opassign(expr, EMUL); + goto opassign_common; + case EADDASS: + if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype)) + uses_globals = 1; + rewrite_opassign(expr, EADD); + goto opassign_common; + case ESUBASS: + if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype)) + uses_globals = 1; + rewrite_opassign(expr, ESUB); + goto opassign_common; + case EMODASS: + if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype)) + uses_globals = 1; + rewrite_opassign(expr, EMODULO); + goto opassign_common; + case ESHLASS: + rewrite_opassign(expr, ESHL); + goto opassign_common; + case ESHRASS: + rewrite_opassign(expr, ESHR); + goto opassign_common; + case EANDASS: + rewrite_opassign(expr, EAND); + goto opassign_common; + case EXORASS: + rewrite_opassign(expr, EXOR); + goto opassign_common; + case EORASS: + rewrite_opassign(expr, EOR); + goto opassign_common; + case EASS: + if (ENODE_IS(expr->data.diadic.left, EINDIRECT)) + expr->data.diadic.left = expr->data.diadic.left->data.monadic; + opassign_common: + expandTOCexpression(expr->data.diadic.left, NULL, 0); + expandTOCexpression(expr->data.diadic.right, NULL, 0); + expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; + break; + case EEQU: + case ENOTEQU: + if (ENODE_IS(expr->data.diadic.right, EINTCONST) && expr->data.diadic.right->data.intval.lo == 0 && expr->data.diadic.right->data.intval.hi == 0) { + for (tmpexpr = expr->data.diadic.left; ENODE_IS2(tmpexpr, EFORCELOAD, ETYPCON); tmpexpr = tmpexpr->data.monadic) { + if (!TYPE_FITS_IN_REGISTER(tmpexpr->rtype)) + break; + } + if (ENODE_IS(tmpexpr, ELOGNOT) && TYPE_FITS_IN_REGISTER(tmpexpr->data.monadic->rtype)) { + if (ENODE_IS(expr, EEQU)) + expr->type = ENOTEQU; + else + expr->type = EEQU; + expr->data.diadic.left = tmpexpr->data.monadic; + expandTOCexpression(expr, NULL, 0); + break; + } + if (ENODE_IS(tmpexpr, EEQU)) { + if (ENODE_IS(expr, EEQU)) + tmpexpr->type = ENOTEQU; + *expr = *tmpexpr; + expandTOCexpression(expr, NULL, 0); + break; + } + if (ENODE_IS(tmpexpr, ENOTEQU)) { + if (ENODE_IS(expr, EEQU)) + tmpexpr->type = EEQU; + *expr = *tmpexpr; + expandTOCexpression(expr, NULL, 0); + break; + } + if (ENODE_IS(tmpexpr, ECOND)) { + newexpr = COND_to_COMPARE(tmpexpr->data.cond.cond, tmpexpr->data.cond.expr1, tmpexpr->data.cond.expr2); + if (newexpr) { + *tmpexpr = *newexpr; + expandTOCexpression(expr, NULL, 0); + break; + } + } + } + case EDIV: + if (ENODE_IS(expr, EDIV) && ENODE_IS(expr->data.diadic.right, EFLOATCONST) && CMach_FloatIsPowerOf2(expr->data.diadic.right->data.floatval)) { + expr->type = EMUL; + expr->data.diadic.right->data.floatval = CMach_FloatReciprocal(expr->data.diadic.right->data.floatval); + } + case EMODULO: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + expandTOCexpression(expr->data.diadic.left, NULL, 0); + expandTOCexpression(expr->data.diadic.right, NULL, 0); + expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; + if (TYPE_IS_8BYTES(expr->rtype)) { + if (ENODE_IS2(expr, ESHL, ESHR) && !ENODE_IS(expr->data.diadic.right, EINTCONST)) { + expr->hascall = 1; + requires_frame = 1; + makes_call = 1; + } + if (ENODE_IS2(expr, EDIV, EMODULO)) { + if (ENODE_IS(expr->data.diadic.right, EINTCONST)) { + if (I8_log2n(((SInt64) expr->data.diadic.right->data.intval.hi << 32) + expr->data.diadic.right->data.intval.lo) <= 0) { + expr->hascall = 1; + requires_frame = 1; + makes_call = 1; + } + } else { + expr->hascall = 1; + requires_frame = 1; + makes_call = 1; + } + } + } + break; + case ESUB: + if (ENODE_IS(expr->data.diadic.right, EINTCONST)) { + expr->type = EADD; + expr->data.diadic.right->data.intval = CInt64_Neg(expr->data.diadic.right->data.intval); + } + case EMUL: + case EADD: + case EAND: + case EXOR: + case EOR: + expandTOCexpression(expr->data.diadic.left, type, 0); + expandTOCexpression(expr->data.diadic.right, type, 0); + expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; + if (ENODE_IS3(expr, EMUL, EADD, ESUB) && TYPE_IS_8BYTES(expr->rtype)) + Optimize64bitMath(expr); + if (type) { + if ( + ENODE_IS(expr->data.diadic.left, ETYPCON) && + IS_TYPE_INT_OR_ENUM(expr->data.diadic.left->rtype) && + IS_TYPE_INT_OR_ENUM(expr->data.diadic.left->data.monadic->rtype) && + expr->data.diadic.left->data.monadic->rtype->size >= type->size && + !TYPE_IS_8BYTES(expr->data.diadic.left->data.monadic->rtype) + ) + expr->data.diadic.left = expr->data.diadic.left->data.monadic; + + if ( + ENODE_IS(expr->data.diadic.right, ETYPCON) && + IS_TYPE_INT_OR_ENUM(expr->data.diadic.right->rtype) && + IS_TYPE_INT_OR_ENUM(expr->data.diadic.right->data.monadic->rtype) && + expr->data.diadic.right->data.monadic->rtype->size >= type->size && + !TYPE_IS_8BYTES(expr->data.diadic.right->data.monadic->rtype) + ) + expr->data.diadic.right = expr->data.diadic.right->data.monadic; + + expr->rtype = type; + } + break; + + case ETYPCON: + tmpexpr = expr->data.monadic; + if ((IS_TYPE_INT_OR_ENUM(expr->rtype) && expr->rtype->size < 4) && IS_TYPE_INT_OR_ENUM(tmpexpr->rtype) && !TYPE_IS_8BYTES(tmpexpr->rtype)) { + expandTOCexpression(tmpexpr, expr->rtype, 0); + } else { + expandTOCexpression(tmpexpr, NULL, expr->rtype->type == TYPEVOID); + } + + expr->hascall = tmpexpr->hascall; + if (IS_TYPE_INT_OR_ENUM(tmpexpr->rtype) && IS_TYPE_FLOAT(expr->rtype)) + uses_globals = 1; + + if ((TYPE_IS_8BYTES(tmpexpr->rtype) && IS_TYPE_FLOAT(expr->rtype)) || (TYPE_IS_8BYTES(expr->rtype) && IS_TYPE_FLOAT(tmpexpr->rtype))) { + uses_globals = 1; + expr->hascall = 1; + requires_frame = 1; + makes_call = 1; + } + + if (IS_TYPE_FLOAT(tmpexpr->rtype)) { + if (is_unsigned(expr->rtype) && expr->rtype->size == 4) { + expr->hascall = 1; + requires_frame = 1; + makes_call = 1; + } else { + uses_globals = 1; + } + } + + if (IS_TYPE_VECTOR(expr->rtype) && !IS_TYPE_VECTOR(tmpexpr->rtype)) + PPCError_Error(PPCErrorStr114); + break; + + case EPOSTINC: + if (!expr->ignored) { + if (IS_TYPE_FLOAT(expr->data.monadic->rtype) && is_unsigned(expr->rtype)) + uses_globals = 1; + expandTOCexpression(expr->data.monadic, NULL, 0); + expr->hascall = expr->data.monadic->hascall; + break; + } + expr->type = EPREINC; + case EPREINC: + rewrite_preincdec(expr); + rewrite_opassign(expr, EADD); + goto opassign_common; + + case EPOSTDEC: + if (!expr->ignored) { + if (IS_TYPE_FLOAT(expr->data.monadic->rtype) && is_unsigned(expr->rtype)) + uses_globals = 1; + expandTOCexpression(expr->data.monadic, NULL, 0); + expr->hascall = expr->data.monadic->hascall; + break; + } + expr->type = EPREDEC; + case EPREDEC: + rewrite_preincdec(expr); + rewrite_opassign(expr, ESUB); + goto opassign_common; + + case ELOGNOT: + if (!ENODE_IS(expr->data.monadic, ELOGNOT) && !ENODE_IS2(expr->data.monadic, ELAND, ELOR) && !ENODE_IS_RANGE(expr->data.monadic, ELESS, ENOTEQU)) + expr->data.monadic = comparewithzero(expr->data.monadic); + case EMONMIN: + case EBINNOT: + tmpexpr = expr->data.monadic; + expandTOCexpression(tmpexpr, type, 0); + expr->hascall = tmpexpr->hascall; + if (type && ENODE_IS(expr->data.monadic, ETYPCON)) { + if (IS_TYPE_INT_OR_ENUM(expr->data.monadic->rtype) && IS_TYPE_INT_OR_ENUM(expr->data.monadic->data.monadic->rtype)) { + if (expr->data.monadic->data.monadic->rtype->size >= type->size) { + expr->data.monadic = expr->data.monadic->data.monadic; + expr->rtype = type; + } + } + } + break; + + case EINDIRECT: + case EFORCELOAD: + case EBITFIELD: + tmpexpr = expr->data.monadic; + expandTOCexpression(tmpexpr, NULL, 0); + expr->hascall = tmpexpr->hascall; + break; + + case EDEFINE: + tmpexpr = expr->data.monadic; + expandTOCexpression(tmpexpr, NULL, 0); + expr->hascall = tmpexpr->hascall; + break; + + case EREUSE: + expr->hascall = expr->data.monadic->hascall; + break; + + case ENULLCHECK: + expandTOCexpression(expr->data.diadic.left, NULL, 0); + expandTOCexpression(expr->data.diadic.right, NULL, 0); + expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; + break; + + case EPRECOMP: + expr->hascall = 0; + break; + + case ELABEL: + obj = createcodelabel(expr->data.label); + newexpr = lalloc(sizeof(ENode)); + memclrw(newexpr, sizeof(ENode)); + newexpr->type = EOBJREF; + newexpr->cost = 0; + newexpr->data.objref = obj; + newexpr->rtype = CDecl_NewPointerType(obj->type); + + expr->type = EINDIRECT; + expr->cost = 1; + expr->data.monadic = newexpr; + expr->hascall = 0; + break; + } +} + +static void checkexceptionreferences(ExceptionAction *action) { + for (; action; action = action->prev) { + switch (action->type) { + case EAT_DESTROYLOCAL: + referenceexception(action->data.destroy_local.local); + break; + case EAT_DESTROYLOCALCOND: + referenceexception(action->data.destroy_local_cond.local); + referenceexception(action->data.destroy_local_cond.cond); + break; + case EAT_DESTROYLOCALOFFSET: + referenceexception(action->data.destroy_local_offset.local); + break; + case EAT_DESTROYLOCALPOINTER: + referenceexception(action->data.destroy_local_pointer.pointer); + break; + case EAT_DESTROYLOCALARRAY: + referenceexception(action->data.destroy_local_array.localarray); + break; + case EAT_DESTROYBASE: + referenceexception(action->data.destroy_member.objectptr); // wrong union? + break; + case EAT_DESTROYPARTIALARRAY: + referenceexception(action->data.destroy_partial_array.arraypointer); + referenceexception(action->data.destroy_partial_array.arraycounter); + referenceexception(action->data.destroy_partial_array.element_size); + break; + case EAT_DESTROYMEMBER: + referenceexception(action->data.destroy_member.objectptr); + break; + case EAT_DESTROYMEMBERCOND: + referenceexception(action->data.destroy_member_cond.objectptr); + referenceexception(action->data.destroy_member_cond.cond); + break; + case EAT_DESTROYMEMBERARRAY: + referenceexception(action->data.destroy_member_array.objectptr); + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + referenceexception(action->data.delete_pointer.pointerobject); + break; + case EAT_DELETEPOINTERCOND: + referenceexception(action->data.delete_pointer_cond.pointerobject); + referenceexception(action->data.delete_pointer_cond.cond); + break; + case EAT_CATCHBLOCK: + referenceexception(action->data.catch_block.catch_object); + referenceexception(action->data.catch_block.catch_info_object); + break; + case EAT_ACTIVECATCHBLOCK: + referenceexception(action->data.active_catch_block.catch_info_object); + break; + } + } +} + +void expandTOCreferences(Statement **stmts) { + Statement *stmt; + IAOperand *op; + int i; + InlineAsm *ia; + VarInfo *vi; + + codelabellist = NULL; + exceptionlist = NULL; + + for (stmt = *stmts; stmt; stmt = stmt->next) { + curstmtvalue = stmt->value; + if (stmt->flags & StmtFlag_1) { + has_catch_blocks = 1; + dynamic_stack = 1; + requires_frame = 1; + } + + switch (stmt->type) { + case ST_EXPRESSION: + expandTOCexpression(stmt->expr, NULL, 1); + if (stmt->expr->type == ETYPCON && IS_TYPE_VOID(stmt->expr->rtype)) + stmt->expr = stmt->expr->data.monadic; + break; + case ST_GOTOEXPR: + expandTOCexpression(stmt->expr, NULL, 0); + break; + case ST_IFGOTO: + case ST_IFNGOTO: + if (stmt->expr->type < ELESS || stmt->expr->type > ENOTEQU) + stmt->expr = comparewithzero(stmt->expr); + expandTOCexpression(stmt->expr, NULL, 0); + break; + case ST_RETURN: + if (!stmt->expr) + continue; + expandTOCexpression( + stmt->expr, NULL, + IS_TYPE_ARRAY(stmt->expr->rtype) || IS_TYPE_NONVECTOR_STRUCT(stmt->expr->rtype) || IS_TYPE_CLASS(stmt->expr->rtype) || + IS_TYPE_12BYTES_MEMBERPOINTER(stmt->expr->rtype)); + break; + case ST_SWITCH: + uses_globals = 1; + expandTOCexpression(stmt->expr, NULL, 0); + break; + case ST_ENDCATCHDTOR: + requires_frame = 1; + makes_call = 1; + break; + case ST_ASM: + if ((ia = (InlineAsm *) stmt->expr)) { + if (ia->flags & IAFlag1) { + if (ia->opcode == IADirective_FrFree) + requires_frame = 1; + } else { + for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { + if (op->type == IAOpnd_Reg) { + if (!op->u.reg.object) { + if (op->u.reg.num == INVALID_PIC_REG) + uses_globals = 1; + else if (op->u.reg.effect & EffectWrite) + asm_used_register(op->u.reg.rclass, op->u.reg.num); + } else if ((vi = Registers_GetVarInfo(op->u.reg.object))) { + vi->flags |= VarInfoFlag40; + } + } else if (op->type == IAOpnd_3) { + uses_globals = 1; + } + } + + if (ia->flags & IAFlag2) + makes_call = 1; + } + } + break; + } + + checkexceptionreferences(stmt->dobjstack); + } +} + +void resetTOCvarinfo(void) { + ObjectList *list; + + for (list = toclist; list; list = list->next) + list->object->u.toc.info = CodeGen_GetNewVarInfo(); +} + +Boolean needdescriptor(void) { + // completely unused, dunno what args this might take + return 0; +} + +Object *createstaticinitobject(void) { + char buf[100]; + char *p; + Str255 fname; + TypeFunc *tfunc; + Object *obj; + + COS_FileGetFSSpecInfo(&cparamblkptr->sourcefile, NULL, NULL, fname); + sprintf(buf, "__sinit_%*.*s", -fname[0], fname[0], &fname[1]); + for (p = &buf[1]; *p; p++) { + if (*p == '.') + *p = '_'; + } + + tfunc = galloc(sizeof(TypeFunc)); + memclrw(tfunc, sizeof(TypeFunc)); + tfunc->type = TYPEFUNC; + tfunc->functype = &stvoid; + tfunc->args = NULL; + tfunc->flags = FUNC_DEFINED; + + obj = galloc(sizeof(Object)); + memclrw(obj, sizeof(Object)); + obj->otype = OT_OBJECT; + obj->type = (Type *) tfunc; + obj->name = GetHashNameNodeExport(buf); + obj->sclass = TK_STATIC; + obj->datatype = DFUNC; + + return obj; +} + +static void estimate_func_param_size(ENode *node) { + SInt32 work; + ENodeList *list; + SInt32 align; + + work = 0; + for (list = node->data.funccall.args; list; list = list->next) { + align = ~7 & (CMach_ArgumentAlignment(list->node->rtype) + 7); + work += ~(align - 1) & (list->node->rtype->size + align - 1); + } + + estimate_out_param_size(work); +} diff --git a/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/Alias.c b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/Alias.c new file mode 100644 index 0000000..8223bf4 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/Alias.c @@ -0,0 +1,747 @@ +#include "compiler/Alias.h" +#include "compiler/CClass.h" +#include "compiler/CError.h" +#include "compiler/CParser.h" +#include "compiler/CMachine.h" +#include "compiler/CodeGen.h" +#include "compiler/CopyPropagation.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/RegisterInfo.h" +#include "compiler/UseDefChains.h" +#include "compiler/ValueNumbering.h" +#include "compiler/BitVectors.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +static Alias *aliases; +static int n_aliases; +static int n_gathered_aliases; +static Alias *alias_hash[997]; +Alias *worst_case; +Object worst_case_obj; + +static TypePointer worst_case_memory_type = { + TYPEARRAY, + 0xFFFFFF, + TYPE(&stchar) +}; + +static Boolean is_safe_const(Object *obj) { + Type *type; + + type = obj->type; + while (IS_TYPE_ARRAY(type)) + type = TPTR_TARGET(type); + + if (TYPE_FITS_IN_REGISTER(type) || IS_TYPE_VECTOR(type) || IS_TYPE_FLOAT(type) || IS_TYPE_STRUCT(type)) + return is_const_object(obj); + + if (IS_TYPE_CLASS(type)) + return is_const_object(obj) && CClass_IsPODClass(TYPE_CLASS(type)); + + return 0; +} + +void initialize_aliases(void) { + int i; + + memclrw(&worst_case_obj, sizeof(Object)); + worst_case_obj.otype = OT_OBJECT; + worst_case_obj.type = TYPE(&worst_case_memory_type); + worst_case_obj.datatype = DDATA; + worst_case_obj.name = GetHashNameNodeExport("@worst_case@"); + + aliases = NULL; + n_aliases = 0; + n_gathered_aliases = 0; + for (i = 0; i < 997; i++) + alias_hash[i] = NULL; + + worst_case = make_alias_set(); + add_alias_member(worst_case, make_alias(&worst_case_obj, 0, 0)); +} + +static UInt32 hash_alias(Object *object, SInt32 offset, SInt32 size) { + return (UInt32) (object->name->hashval * offset * size) % 997; +} + +static Alias *create_alias(AliasType type, Object *object, SInt32 offset, SInt32 size, Boolean addToHash) { + Alias *alias; + UInt32 hash; + + alias = lalloc(sizeof(Alias)); + memclrw(alias, sizeof(Alias)); + alias->type = type; + alias->index = n_aliases++; + alias->next = aliases; + aliases = alias; + alias->object = object; + alias->offset = offset; + alias->size = size; + + if (addToHash) { + hash = hash_alias(object, offset, size); + alias->hashNext = alias_hash[hash]; + alias_hash[hash] = alias; + } + + return alias; +} + +static Alias *lookup_alias(Object *object, SInt32 offset, SInt32 size) { + Alias *scan; + + for (scan = alias_hash[hash_alias(object, offset, size)]; scan; scan = scan->hashNext) { + if (scan->object == object && scan->offset == offset && scan->size == size) + return scan; + } + + return NULL; +} + +Alias *make_alias(Object *object, SInt32 offset, SInt32 size) { + Alias *alias; + Alias *alias2; + + if (!offset && !size) + size = object->type->size; + + alias = lookup_alias(object, offset, size); + if (!alias) { + if (offset > 0 || size != object->type->size) { + alias2 = make_alias(object, 0, object->type->size); + alias = create_alias(AliasType1, object, offset, size, 1); + add_alias_member(alias2, alias); + } else { + alias = create_alias(AliasType0, object, offset, size, 1); + } + + switch (object->datatype) { + case DLOCAL: + case DNONLAZYPTR: + break; + default: + if (!is_safe_const(object)) + add_alias_member(worst_case, make_alias(object, 0, 0)); + } + } + + if (offset > object->type->size) + return NULL; + else + return alias; +} + +Alias *make_alias_set(void) { + return create_alias(AliasType2, NULL, 0, 0, 0); +} + +void add_alias_member(Alias *parent, Alias *child) { + AliasMember *member; + + if (child->type == AliasType2) { + for (member = child->parents; member; member = member->nextParent) + add_alias_member(parent, member->child); + } else { + if (parent == worst_case && child->type == AliasType1) + child = make_alias(child->object, 0, 0); + + for (member = parent->parents; member; member = member->nextParent) { + if (member->child == child) + return; + } + + member = lalloc(sizeof(AliasMember)); + member->parent = parent; + member->child = child; + member->nextParent = parent->parents; + parent->parents = member; + member->nextChild = child->children; + child->children = member; + } +} + +Alias *make_alias_set_from_IR(void) { + CError_FATAL(333); + return NULL; +} + +static Boolean aliases_overlap(Alias *a, Alias *b) { + return ( + a->offset == b->offset || + (a->offset > b->offset && a->offset < (b->offset + b->size)) || + (b->offset > a->offset && b->offset < (a->offset + a->size)) + ); +} + +static int is_address_load(PCode *pcode) { + Object *obj; + + switch (pcode->op) { + case PC_LWZ: + if (pcode->args[2].kind == PCOp_MEMORY && pcode->args[2].data.mem.obj->datatype == DNONLAZYPTR) + return 1; + break; + case PC_LBZU: + case PC_LBZUX: + case PC_LHZU: + case PC_LHZUX: + case PC_LHAU: + case PC_LHAUX: + case PC_LWZU: + case PC_LWZUX: + case PC_STBU: + case PC_STBUX: + case PC_STHU: + case PC_STHUX: + case PC_STWU: + case PC_STWUX: + return 1; + case PC_ADDI: + case PC_ADDIS: + if (pcode->args[0].data.reg.reg < n_real_registers[RegClass_GPR]) { + if (pcode->args[2].kind == PCOp_MEMORY) { + obj = pcode->args[2].data.mem.obj; + if (obj->datatype == DLOCAL && !is_safe_const(obj)) + add_alias_member(worst_case, make_alias(obj, 0, 0)); + return 0; + } + } else { + return 1; + } + break; + case PC_ADD: + return 1; + } + + return 0; +} + +static int addresspropagatestouse(int candidateID, int useID) { + PCode *candidate_pcode; // r30 + PCode *use_pcode; // r29 + int reg; // r28 + short reg2; + Object *object; // r27 + SInt32 offset; // r26 + Alias *alias; // r25 + Boolean flag24; // r24 + SInt32 size; // r23 + Alias *aliasSet; // r22 + int i; + PCode *scan; + PCodeArg *op; + + candidate_pcode = Candidates[candidateID].pcode; + use_pcode = Uses[useID].pcode; + flag24 = 0; + size = 1; + reg = candidate_pcode->args[0].data.reg.reg; + + if (candidate_pcode->alias && (candidate_pcode->alias->type == AliasType0 || candidate_pcode->alias->type == AliasType1)) { + object = candidate_pcode->alias->object; + offset = candidate_pcode->alias->offset; + if (offset == 0 && candidate_pcode->alias->size == object->type->size) + flag24 = 1; + } else if (candidate_pcode->args[2].kind == PCOp_MEMORY) { + object = candidate_pcode->args[2].data.mem.obj; + if (candidate_pcode->op == PC_ADDIS) + offset = candidate_pcode->args[2].data.mem.offset << 16; + else + offset = candidate_pcode->args[2].data.mem.offset; + } else { + return 0; + } + + CError_ASSERT(478, object->otype == OT_OBJECT); + + if ((candidate_pcode->flags & (fIsRead | fIsWrite)) && (candidate_pcode->flags & fUpdatesPtr)) { + reg = candidate_pcode->args[1].data.reg.reg; + offset = 0; + flag24 = 1; + } else if (candidate_pcode->op == PC_LWZ) { + if (object->datatype != DNONLAZYPTR) + return 0; + + object = object->u.var.realObj; + CError_ASSERT(495, object->otype == OT_OBJECT); + offset = 0; + } else if (candidate_pcode->op == PC_ADDI) { + if (!candidate_pcode->alias && object) + candidate_pcode->alias = make_alias(object, offset, 1); + } else if (candidate_pcode->op == PC_ADDIS) { + if (!candidate_pcode->alias && object) + candidate_pcode->alias = make_alias(object, offset, 1); + } else if (candidate_pcode->op == PC_ADD) { + offset = 0; + flag24 = 1; + } else { + CError_FATAL(509); + } + + if ( + !(use_pcode->flags & (fIsRead | fIsWrite)) && + use_pcode->op != PC_ADDI && + use_pcode->op != PC_ADD && + use_pcode->op != PC_ADDIS + ) { + if (object->datatype == DLOCAL && !is_safe_const(object)) + add_alias_member(worst_case, make_alias(object, 0, 0)); + return 1; + } + + if ( + (use_pcode->flags & (fIsWrite | fPCodeFlag40000)) && + use_pcode->args[0].kind == PCOp_REGISTER && + use_pcode->args[0].arg == RegClass_GPR && + use_pcode->args[0].data.reg.reg == reg && + object->datatype == DLOCAL && + !is_safe_const(object) + ) + add_alias_member(worst_case, make_alias(object, 0, 0)); + + if (use_pcode->argCount < 3) + return 1; + + CError_ASSERT(543, use_pcode->args[1].kind == PCOp_REGISTER); + + if (candidate_pcode->block == use_pcode->block && precedes(candidate_pcode, use_pcode)) { + for (scan = candidate_pcode->nextPCode; scan && scan != use_pcode; scan = scan->nextPCode) { + for (op = scan->args, i = scan->argCount; i--; op++) { + if (op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + (op->data.reg.effect & EffectWrite) && + op->data.reg.reg == reg) + return 1; + } + } + } else { + if (!bitvectorgetbit(candidateID, propinfo[use_pcode->block->blockIndex].vec8)) { + if (bitvectorgetbit(candidate_pcode->defID, usedefinfo[use_pcode->block->blockIndex].defvec8)) { + for (scan = use_pcode->block->firstPCode; scan && scan != use_pcode; scan = scan->nextPCode) { + for (op = scan->args, i = scan->argCount; i--; op++) { + if (op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + (op->data.reg.effect & EffectWrite) && + op->data.reg.reg == reg) + return 1; + } + } + } else { + return 1; + } + } + + for (scan = use_pcode->block->firstPCode; scan; scan = scan->nextPCode) { + if (scan == use_pcode) + break; + for (op = scan->args, i = scan->argCount; i--; op++) { + if (op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + (op->data.reg.effect & EffectWrite) && + op->data.reg.reg == reg) + return 1; + } + } + } + + CError_ASSERT(598, object != NULL); + + if (use_pcode->op == PC_ADDI || use_pcode->op == PC_ADD || use_pcode->op == PC_ADDIS) { + if (use_pcode->args[0].data.reg.reg < n_real_registers[RegClass_GPR] && !is_safe_const(object)) + add_alias_member(worst_case, make_alias(object, 0, 0)); + } + + if (use_pcode->flags & (fIsRead | fIsWrite)) + size = nbytes_loaded_or_stored_by(use_pcode); + + if (use_pcode->args[2].kind == PCOp_REGISTER) { + if (use_pcode->args[1].data.reg.reg == 0) { + if (use_pcode->args[2].data.reg.reg == reg) + alias = make_alias(object, offset, size); + } else { + if (use_pcode->args[1].data.reg.reg == reg) + reg2 = use_pcode->args[2].data.reg.reg; + else if (use_pcode->args[2].data.reg.reg == reg) + reg2 = use_pcode->args[1].data.reg.reg; + else + return 1; + + for (scan = use_pcode->prevPCode; scan; scan = scan->prevPCode) { + if (scan->op == PC_LI && scan->args[0].data.reg.reg == reg2) + break; + + for (i = 0; i < scan->argCount; i++) { + if (scan->args[i].kind == PCOp_REGISTER && + scan->args[i].arg == RegClass_GPR && + scan->args[i].data.reg.reg == reg2 && + (scan->args[i].data.reg.effect & EffectWrite)) { + scan = NULL; + break; + } + } + + if (!scan) + break; + } + + if (scan) { + offset += scan->args[1].data.mem.offset; + alias = make_alias(object, offset, size); + } else { + alias = make_alias(object, 0, 0); + } + } + } else { + if (use_pcode->args[1].kind != PCOp_REGISTER || + use_pcode->args[1].arg != RegClass_GPR || + use_pcode->args[1].data.reg.reg != reg) + return 1; + + if (use_pcode->args[1].data.reg.effect & EffectWrite) { + alias = make_alias(object, 0, 0); + } else if (use_pcode->args[2].kind == PCOp_IMMEDIATE) { + if (use_pcode->op == PC_ADDIS) { + offset += use_pcode->args[2].data.imm.value << 16; + alias = make_alias(object, offset, 1); + } else { + offset += use_pcode->args[2].data.imm.value; + alias = make_alias(object, offset, size); + } + } else { + return 1; + } + } + + if (flag24) + alias = make_alias(object, 0, 0); + + if (!alias) + return 1; + + if (!use_pcode->alias) { + if ( + use_pcode->op == PC_ADDI || + use_pcode->op == PC_ADD || + use_pcode->op == PC_ADDIS || + ((candidate_pcode->flags & (fIsRead | fIsWrite)) && (candidate_pcode->flags & fUpdatesPtr)) + ) + recursive_propagation = 1; + } + + if (use_pcode->alias) { + if (use_pcode->alias == worst_case) { + add_alias_member(worst_case, make_alias(object, 0, 0)); + } else if (use_pcode->alias == alias) { + return 1; + } else if (use_pcode->alias->type == AliasType0 || use_pcode->alias->type == AliasType1) { + if (object == use_pcode->alias->object) { + use_pcode->alias = make_alias(object, 0, 0); + } else { + aliasSet = make_alias_set(); + if ( + use_pcode->op == PC_ADDI || + use_pcode->op == PC_ADD || + use_pcode->op == PC_ADDIS || + ((use_pcode->flags & (fIsRead | fIsWrite)) && (use_pcode->flags & fUpdatesPtr)) + ) { + if (alias->type == AliasType2) + add_alias_member(worst_case, alias); + else + add_alias_member(worst_case, make_alias(use_pcode->alias->object, 0, 0)); + } + add_alias_member(aliasSet, use_pcode->alias); + add_alias_member(aliasSet, alias); + use_pcode->alias = aliasSet; + } + } else { + add_alias_member(use_pcode->alias, alias); + } + } else { + use_pcode->alias = alias; + } + + propagated_instructions = 1; + return 1; +} + +static void finishpropagatealiases(int id) { + propagated_instructions = 1; +} + +static Propagation alias_prop = { + &is_address_load, + &addresspropagatestouse, + &finishpropagatealiases, + "ALIAS", + "ALIASES", + "A%" PRId32, + 1 +}; + +static void propagatealiasinfo(Object *proc) { + propagateinstructions(proc, &alias_prop, (copts.optimizationlevel >= 4) ? 4 : 1, 1); +} + +void gather_alias_info(void) { + UInt32 *myvec; // r31 + Alias *alias; // r22 + AliasMember *member; + AliasMember *member2; + PCodeBlock *block; // r21 + PCode *pcode; // r20 + PCodeArg *op; // r19 + RegUseOrDef *list; // r18 + int i; // r17 + Alias *alias_choice; // r16 + int aliases_idx; // r15 (helper in r23) + PCode *defpcode; // r14 + Alias *alias_array[3]; + UseOrDef *def; + int defID; + + if (coloring) { + propagatealiasinfo(gFunction); + myvec = oalloc(4 * ((number_of_Defs + 31) >> 5)); + + for (block = pcbasicblocks; block; block = block->nextBlock) { + bitvectorcopy(myvec, usedefinfo[block->blockIndex].defvec8, number_of_Defs); + + for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { + if (pcode->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) { + if (!pcode->alias) { + pcode->alias = worst_case; + } else { + if ((pcode->alias->type == AliasType0 || pcode->alias->type == AliasType1) && + pcode->alias->size == nbytes_loaded_or_stored_by(pcode)) { + pcode->flags &= ~fIsPtrOp; + } else { + pcode->flags |= fIsPtrOp; + } + + if (pcode->alias != worst_case) { + aliases_idx = 0; + alias_choice = NULL; + op = pcode->args; + for (i = 0; i < pcode->argCount; i++, op++) { + if ( + (!(pcode->flags & (fIsWrite | fPCodeFlag40000)) || op != pcode->args) && + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + (op->data.reg.effect & EffectRead) + ) { + alias_array[aliases_idx] = NULL; + if (aliases_idx >= 2) { + alias_choice = worst_case; + break; + } + alias_array[aliases_idx] = pcode->alias; + + for (list = reg_Defs[RegClass_GPR][op->data.reg.reg]; list; list = list->next) { + if (bitvectorgetbit(list->id, myvec)) { + defpcode = Defs[list->id].pcode; + if (!defpcode->alias || !is_address_load(defpcode) || defpcode->alias == worst_case) { + alias_array[aliases_idx] = worst_case; + break; + } + } + } + + aliases_idx++; + } + } + + if (!alias_choice) { + if (aliases_idx > 0) { + alias_choice = alias_array[0]; + if (aliases_idx == 2) { + if (alias_array[0] != worst_case) { + if (alias_array[1] != worst_case) + alias_choice = worst_case; + } else if (alias_array[1] != worst_case) { + alias_choice = alias_array[1]; + } + } + } + + if (alias_choice == worst_case) { + pcode->flags |= fIsPtrOp; + if (pcode->alias->type == AliasType2) + add_alias_member(worst_case, pcode->alias); + else + add_alias_member(worst_case, make_alias(pcode->alias->object, 0, 0)); + } + + if (alias_choice) + pcode->alias = alias_choice; + } + } + } + } else { + if ((pcode->flags & fIsCall) && !pcode->alias) + pcode->alias = worst_case; + } + + for (def = &Defs[defID = pcode->defID]; defID < number_of_Defs && def->pcode == pcode; defID++, def++) { + if (def->v.kind == PCOp_REGISTER && def->v.arg == RegClass_GPR) { + for (list = reg_Defs[RegClass_GPR][def->v.u.reg]; list; list = list->next) + bitvectorclearbit(list->id, myvec); + } + bitvectorsetbit(defID, myvec); + } + } + } + + freeoheap(); + } else { + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { + if ((pcode->flags & (fIsRead | fIsWrite | fIsCall | fPCodeFlag20000 | fPCodeFlag40000)) && !pcode->alias) + pcode->alias = worst_case; + } + } + } + + if (n_gathered_aliases != n_aliases) { + for (alias = aliases; alias; alias = alias->next) { + if (alias->type == AliasType2) { + alias->vec24 = lalloc(4 * ((n_aliases + 31) >> 5)); + bitvectorinitialize(alias->vec24, n_aliases, 0); + for (member = alias->parents; member; member = member->nextParent) { + bitvectorsetbit(member->child->index, alias->vec24); + for (member2 = member->child->parents; member2; member2 = member2->nextParent) + bitvectorsetbit(member2->child->index, alias->vec24); + } + } + } + n_gathered_aliases = n_aliases; + } +} + +static Boolean may_alias_alias(Alias *a, Alias *b) { + switch ((a->type * 3) + b->type) { + case (AliasType0 * 3) + AliasType0: + return a == b; + case (AliasType0 * 3) + AliasType1: + case (AliasType1 * 3) + AliasType0: + return a->object == b->object; + case (AliasType1 * 3) + AliasType1: + return (a->object == b->object) && aliases_overlap(a, b); + case (AliasType0 * 3) + AliasType2: + case (AliasType1 * 3) + AliasType2: + return bitvectorgetbit(a->index, b->vec24) != 0; + case (AliasType2 * 3) + AliasType0: + case (AliasType2 * 3) + AliasType1: + return bitvectorgetbit(b->index, a->vec24) != 0; + case (AliasType2 * 3) + AliasType2: + return (a == b) || !bitvectorintersectionisempty(a->vec24, b->vec24, n_aliases); + default: + CError_FATAL(1054); + return 1; + } +} + +Boolean may_alias(PCode *a, PCode *b) { + return may_alias_alias(a->alias, b->alias); +} + +Boolean uniquely_aliases(PCode *a, PCode *b) { + if (may_alias_alias(a->alias, b->alias)) { + if ( + a->alias->type != AliasType2 && + b->alias->type != AliasType2 && + a->alias && + b->alias && + a->alias->size == nbytes_loaded_or_stored_by(a) && + b->alias->size == nbytes_loaded_or_stored_by(b) + ) + return 1; + } + + return 0; +} + +Boolean may_alias_worst_case(PCode *pcode) { + return may_alias_alias(pcode->alias, worst_case); +} + +Boolean may_alias_object(PCode *pcode, Object *object) { + return may_alias_alias(pcode->alias, make_alias(object, 0, 0)); +} + +void initialize_alias_values(void) { + Alias *alias; + + for (alias = aliases; alias; alias = alias->next) { + alias->valuenumber = nextvaluenumber++; + alias->valuepcode = NULL; + } +} + +void update_alias_value(Alias *alias, PCode *pcode) { + AliasMember *member; + AliasMember *member2; + AliasMember *member3; + + switch (alias->type) { + case AliasType0: + killmemory(alias, pcode); + for (member = alias->children; member; member = member->nextChild) { + CError_ASSERT(1152, member->parent->type == AliasType2); + killmemory(member->parent, NULL); + } + for (member = alias->parents; member; member = member->nextParent) { + CError_ASSERT(1157, member->child->type == AliasType1); + killmemory(member->child, NULL); + for (member2 = member->child->children; member2; member2 = member2->nextChild) { + if (member2->parent != alias) { + CError_ASSERT(1163, member2->parent->type == AliasType2); + killmemory(member2->parent, NULL); + } + } + } + break; + + case AliasType1: + killmemory(alias, pcode); + for (member = alias->children; member; member = member->nextChild) { + killmemory(member->parent, NULL); + if (member->parent->type == AliasType0) { + for (member2 = member->parent->parents; member2; member2 = member2->nextParent) { + if (member2->child != alias && aliases_overlap(alias, member2->child)) { + killmemory(member2->child, NULL); + } + } + } + } + break; + + case AliasType2: + killmemory(alias, NULL); + for (member = alias->parents; member; member = member->nextParent) { + killmemory(member->child, NULL); + for (member2 = member->child->children; member2; member2 = member2->nextChild) { + if (member2->parent != alias) + killmemory(member2->parent, NULL); + } + for (member3 = member->child->parents; member3; member3 = member3->nextParent) { + killmemory(member3->child, NULL); + for (member2 = member3->child->children; member2; member2 = member2->nextChild) { + if (member2->parent != member->child) + killmemory(member2->parent, NULL); + } + } + } + break; + } +} + +void update_all_alias_values(void) { + Alias *alias; + + for (alias = aliases; alias; alias = alias->next) + killmemory(alias, NULL); +} + diff --git a/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/CodeMotion.c b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/CodeMotion.c new file mode 100644 index 0000000..8ce2962 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/CodeMotion.c @@ -0,0 +1,906 @@ +#include "compiler/CodeMotion.h" +#include "compiler/Alias.h" +#include "compiler/BitVectors.h" +#include "compiler/LoopDetection.h" +#include "compiler/LoopOptimization.h" +#include "compiler/CompilerTools.h" +#include "compiler/PCode.h" +#include "compiler/UseDefChains.h" +#include "compiler/RegisterInfo.h" + +int movedloopinvariantcode; +int unswitchedinvariantcode; + +static int isloopinvariant(PCode *pcode, Loop *loop, UInt32 *vec, int flag1, int flag2) { + PCodeArg *op; + RegUseOrDef *list; + int i; + + if (pcode->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) { + if (pcode->alias) { + if (pcode->alias->type == AliasType2 || (pcode->flags & (fIsVolatile | fSideEffects))) + return 0; + + if (pcode->flags & fIsRead) { + for (list = findobjectusedef(pcode->alias->object)->defs; list; list = list->next) { + if ( + may_alias(pcode, Defs[list->id].pcode) && + bitvectorgetbit(list->id, vec) && + bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) + ) + return 0; + } + } + + if (pcode->flags & fIsWrite) { + for (list = findobjectusedef(pcode->alias->object)->uses; list; list = list->next) { + if ( + may_alias(pcode, Uses[list->id].pcode) && + bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) + ) + return 0; + } + } + } else { + return 0; + } + } + + if ((pcode->flags & fIsWrite) && !bitvectorgetbit(pcode->block->blockIndex, loop->vec2C)) + return 0; + + op = pcode->args; + i = pcode->argCount; + while (i--) { + switch (op->kind) { + case PCOp_MEMORY: + if ((pcode->flags & fIsRead) && ((pcode->flags == 0) & 0x40)) { + for (list = findobjectusedef(op->data.mem.obj)->defs; list; list = list->next) { + if ( + may_alias(pcode, Defs[list->id].pcode) && + bitvectorgetbit(list->id, vec) && + bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) + ) + return 0; + } + } + if (pcode->flags & fIsWrite) { + for (list = findobjectusedef(op->data.mem.obj)->uses; list; list = list->next) { + if ( + may_alias(pcode, Uses[list->id].pcode) && + bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) + ) + return 0; + } + } + break; + case PCOp_REGISTER: + if (op->data.reg.effect & (EffectRead | EffectWrite)) { + if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) { + if (op->data.reg.reg == _FP_) + break; + if (op->data.reg.reg == _CALLER_SP_) + break; + if (op->data.reg.reg == 2) + break; + } + if (op->data.reg.reg < n_real_registers[op->arg]) { + if (op->arg == RegClass_CRFIELD) { + if (!flag2 || (op->data.reg.effect & EffectRead)) + return 0; + } else if (op->arg == RegClass_SPR) { + if (!flag1) + return 0; + } else { + return 0; + } + } else if (op->data.reg.effect & EffectRead) { + if (flag1 && op->kind == PCOp_REGISTER && op->arg == RegClass_SPR) + break; + if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) { + if (op->data.reg.reg == _FP_) + break; + if (op->data.reg.reg == _CALLER_SP_) + break; + if (op->data.reg.reg == 2) + break; + } + + for (list = reg_Defs[op->arg][op->data.reg.reg]; list; list = list->next) { + if ( + bitvectorgetbit(list->id, vec) && + bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) + ) + return 0; + } + } + } + break; + } + op++; + } + + return 1; +} + +static int isuniquedefinition(PCode *pcode, Loop *loop) { + RegUseOrDef *list; + int defID; + UseOrDef *def; + + defID = pcode->defID; + def = &Defs[defID]; + if (defID >= number_of_Defs) + return 0; + if (def->pcode != pcode) + return 0; + if ((defID + 1) < number_of_Defs && def[1].pcode == pcode) + return 0; + + if (def->v.kind == PCOp_REGISTER) { + for (list = reg_Defs[def->v.arg][def->v.u.reg]; list; list = list->next) { + if ( + bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) && + list->id != defID + ) + return 0; + } + } else if (def->v.kind == PCOp_MEMORY) { + for (list = findobjectusedef(def->v.u.object)->defs; list; list = list->next) { + if ( + may_alias(pcode, Defs[list->id].pcode) && + bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) && + list->id != defID + ) + return 0; + } + } else { + CError_FATAL(292); + } + + return 1; +} + +static int uniquelyreachesuse(int defID, int useID) { + UseOrDef *def; + UseOrDef *use; + RegUseOrDef *list; + PCode *pcode; + + def = &Defs[defID]; + use = &Uses[useID]; + if (def->v.kind == PCOp_REGISTER) { + for (list = reg_Defs[def->v.arg][def->v.u.reg]; list; list = list->next) { + if ( + list->id != defID && + bitvectorgetbit(list->id, usedefinfo[use->pcode->block->blockIndex].defvec8) + ) + break; + } + } else if (def->v.kind == PCOp_MEMORY) { + for (list = findobjectusedef(def->v.u.object)->defs; list; list = list->next) { + if ( + may_alias(def->pcode, Defs[list->id].pcode) && + list->id != defID && + bitvectorgetbit(list->id, usedefinfo[use->pcode->block->blockIndex].defvec8) + ) + break; + } + } + + if (!list) + return 1; + + if (def->pcode->block == use->pcode->block) { + for (pcode = use->pcode->prevPCode; pcode; pcode = pcode->prevPCode) { + if (pcode == def->pcode) + return 1; + } + } + + return 0; +} + +static int uniquelyreachesalluses(int defID, Loop *loop) { + UseOrDef *def; + RegUseOrDef *list; + + def = &Defs[defID]; + + if (def->v.kind == PCOp_REGISTER) { + for (list = reg_Uses[def->v.arg][def->v.u.reg]; list; list = list->next) { + if ( + bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].usevec1C) || + (bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) && !uniquelyreachesuse(defID, list->id)) + ) + return 0; + } + } else if (def->v.kind == PCOp_MEMORY) { + for (list = findobjectusedef(def->v.u.object)->uses; list; list = list->next) { + if (may_alias(def->pcode, Uses[list->id].pcode)) { + if ( + bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].usevec1C) || + (bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) && !uniquelyreachesuse(defID, list->id)) + ) + return 0; + } + } + } else { + CError_FATAL(382); + } + + return 1; +} + +static int isliveonexit(TinyValue *v, Loop *loop) { + RegUseOrDef *list; + UInt32 *vec; + + vec = usedefinfo[loop->preheader->blockIndex].usevec1C; + + if (v->kind == PCOp_REGISTER) { + for (list = reg_Uses[v->arg][v->u.reg]; list; list = list->next) { + if ( + bitvectorgetbit(list->id, vec) && + !bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) + ) + return 1; + } + } else if (v->kind == PCOp_MEMORY) { + for (list = findobjectusedef(v->u.object)->uses; list; list = list->next) { + if ( + bitvectorgetbit(list->id, vec) && + !bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) + ) + return 1; + } + } + + return 0; +} + +static int dominatesallexits(PCode *pcode, Loop *loop) { + return bitvectorgetbit(pcode->block->blockIndex, loop->vec28) != 0; +} + +static int maymove(PCode *pcode, Loop *loop) { + short reg; + + if (!isuniquedefinition(pcode, loop)) + return 0; + if (!uniquelyreachesalluses(pcode->defID, loop)) + return 0; + if (!dominatesallexits(pcode, loop) && isliveonexit(&Defs[pcode->defID].v, loop)) + return 0; + + if (loop->bodySize > 25) { + switch (pcode->op) { + case PC_LI: + if ( + pcode->nextPCode && + pcode->nextPCode->op == PC_LVX && + (pcode->nextPCode->flags & fIsConst) + ) { + reg = pcode->args[0].data.reg.reg; + if (pcode->nextPCode->args[1].data.reg.reg == reg || + pcode->nextPCode->args[2].data.reg.reg == reg) + return 1; + } + case PC_VSPLTISB: + case PC_VSPLTISH: + case PC_VSPLTISW: + return 0; + default: + if (!bitvectorgetbit(pcode->block->blockIndex, loop->vec2C)) + return 0; + } + } + + return 1; +} + +static void moveinvariantcomputation(PCode *pcode, Loop *loop) { + ObjectUseDef *oud; + BlockList *blocklist; + RegUseOrDef *list; + UseOrDef *def; + int defID; + + defID = pcode->defID; + def = &Defs[defID]; + deletepcode(pcode); + insertpcodebefore(loop->preheader->lastPCode, pcode); + loop->bodySize--; + movedloopinvariantcode = 1; + + if (def->v.kind == PCOp_REGISTER) { + for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { + for (list = reg_Defs[def->v.arg][def->v.u.reg]; list; list = list->next) + bitvectorclearbit(list->id, usedefinfo[blocklist->block->blockIndex].defvec8); + bitvectorsetbit(defID, usedefinfo[blocklist->block->blockIndex].defvec8); + } + } else if (def->v.kind == PCOp_MEMORY) { + oud = findobjectusedef(def->v.u.object); + for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { + for (list = oud->defs; list; list = list->next) { + if (uniquely_aliases(pcode, Defs[list->id].pcode)) + bitvectorclearbit(list->id, usedefinfo[blocklist->block->blockIndex].defvec8); + } + bitvectorsetbit(defID, usedefinfo[blocklist->block->blockIndex].defvec8); + } + } else { + CError_FATAL(545); + } +} + +static int srawi_addze_maymove(PCode *pcode, Loop *loop) { + RegUseOrDef *list; + UseOrDef *def; + int defID; + int nextDefID; + + defID = pcode->defID; + nextDefID = pcode->nextPCode->defID; + + def = &Defs[defID]; + if (defID >= number_of_Defs) + return 0; + if (def->pcode != pcode) + return 0; + if ((defID + 1) < number_of_Defs && def[1].pcode == pcode) + return 0; + + if (def->v.kind == PCOp_REGISTER && def->v.arg == RegClass_GPR) { + for (list = reg_Defs[RegClass_GPR][def->v.u.reg]; list; list = list->next) { + if ( + bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) && + list->id != defID && + list->id != nextDefID + ) + return 0; + } + } else { + CError_FATAL(582); + } + + if (!uniquelyreachesalluses(pcode->defID, loop)) + return 0; + if (!dominatesallexits(pcode, loop) && isliveonexit(&Defs[pcode->defID].v, loop)) + return 0; + if (!dominatesallexits(pcode->nextPCode, loop) && isliveonexit(&Defs[pcode->nextPCode->defID].v, loop)) + return 0; + + return 1; +} + +static int srawi_addze_isloopinvariant(PCode *pcode, Loop *loop, UInt32 *vec) { + static PCode *oldNextInstr; + PCode *nextInstr; + + nextInstr = pcode->nextPCode; + if ( + pcode->op == PC_ADDZE && + oldNextInstr == pcode + ) { + oldNextInstr = NULL; + return 1; + } else if ( + pcode->op == PC_SRAWI && + nextInstr && + nextInstr->op == PC_ADDZE && + pcode->args[0].data.reg.reg == nextInstr->args[0].data.reg.reg && + nextInstr->args[0].data.reg.reg == nextInstr->args[1].data.reg.reg && + !(pcode->flags & (fIsCall | fIsPtrOp | fIsVolatile | fSideEffects)) && + !(nextInstr->flags & (fIsCall | fIsPtrOp | fIsVolatile | fSideEffects)) && + isloopinvariant(pcode, loop, vec, 1, 0) && + srawi_addze_maymove(pcode, loop) + ) { + oldNextInstr = nextInstr; + return 1; + } else { + oldNextInstr = NULL; + return 0; + } +} + +static void removeblockfromloop(Loop *loop, PCodeBlock *block) { + BlockList *list; + BlockList **ptr; + + bitvectorclearbit(block->blockIndex, loop->memberblocks); + bitvectorclearbit(block->blockIndex, loop->vec24); + bitvectorclearbit(block->blockIndex, loop->vec28); + bitvectorclearbit(block->blockIndex, loop->vec2C); + loop->bodySize -= block->pcodeCount; + + ptr = &loop->blocks; + while ((list = *ptr)) { + if (list->block == block) + *ptr = list->next; + else + ptr = &list->next; + } +} + +static void changesuccessor(PCodeBlock *block, PCodeBlock *from, PCodeBlock *to) { + PCLink **ptr; + PCLink *link; + + for (link = block->successors; link; link = link->nextLink) { + if (link->block == from) + link->block = to; + } + + ptr = &from->predecessors; + while ((link = *ptr)) { + if (link->block == block) { + *ptr = link->nextLink; + link->nextLink = to->predecessors; + to->predecessors = link; + } else { + ptr = &link->nextLink; + } + } +} + +static void movesuccessor(PCodeBlock *to, PCodeBlock *from, PCodeBlock *block) { + PCLink **ptr; + PCLink *link; + + for (link = block->predecessors; link; link = link->nextLink) { + if (link->block == from) + link->block = to; + } + + ptr = &from->successors; + while ((link = *ptr)) { + if (link->block == block) { + *ptr = link->nextLink; + link->nextLink = to->successors; + to->successors = link; + } else { + ptr = &link->nextLink; + } + } +} + +static void movecmptopreheader(Loop *loop, PCodeBlock *block, PCode *pc1, PCode *pc2, PCodeArg *op) { + PCodeBlock *preheader; + PCode *pc3; + + preheader = loop->preheader; + if (PCODE_FLAG_SET_F(pc1) & fRecordBit) { + moveinvariantcomputation(pc1, loop); + } else { + deletepcode(pc1); + insertpcodebefore(loop->preheader->lastPCode, pc1); + loop->bodySize--; + movedloopinvariantcode = 1; + } + loop->preheader = NULL; + + insertpreheaderblock(loop); + + pc3 = preheader->lastPCode; + CError_ASSERT(775, pc3->op == PC_B); + deletepcode(pc3); + deletepcode(pc2); + appendpcode(preheader, pc2); + movesuccessor(preheader, block, op->data.label.label->block); +} + +static PCodeBlock *appendheadercopy(Loop *loop, PCodeBlock *block1, PCodeBlock *block2, PCodeBlock *block3) { + PCodeBlock *newblock1; + PCodeBlock *newblock2; + PCLink *link; + PCode *scan; + + newblock1 = lalloc(sizeof(PCodeBlock)); + newblock2 = lalloc(sizeof(PCodeBlock)); + + newblock1->labels = NULL; + newblock1->predecessors = newblock1->successors = NULL; + newblock1->firstPCode = newblock1->lastPCode = NULL; + newblock1->pcodeCount = 0; + newblock1->loopWeight = loop->body->loopWeight; + newblock1->flags = 0; + newblock1->blockIndex = pcblockcount++; + + newblock2->labels = NULL; + newblock2->predecessors = newblock2->successors = NULL; + newblock2->firstPCode = newblock2->lastPCode = NULL; + newblock2->pcodeCount = 0; + newblock2->loopWeight = loop->body->loopWeight; + newblock2->flags = 0; + newblock2->blockIndex = pcblockcount++; + + newblock1->nextBlock = newblock2; + newblock2->prevBlock = newblock1; + newblock1->prevBlock = block1; + newblock2->nextBlock = block1->nextBlock; + block1->nextBlock = newblock1; + newblock2->nextBlock->prevBlock = newblock2; + + pclabel(newblock1, makepclabel()); + pclabel(newblock2, makepclabel()); + + changesuccessor(block1, block1->successors->block, newblock1); + + link = lalloc(sizeof(PCLink)); + link->block = newblock2; + link->nextLink = newblock1->successors; + newblock1->successors = link; + + link = lalloc(sizeof(PCLink)); + link->block = newblock1; + link->nextLink = newblock2->predecessors; + newblock2->predecessors = link; + + appendpcode(newblock2, makepcode(PC_B, block2->nextBlock->labels)); + pcbranch(newblock2, block2->nextBlock->labels); + pccomputepredecessors1(newblock2); + + for (scan = block2->firstPCode; scan; scan = scan->nextPCode) + appendpcode(newblock1, copypcode(scan)); + + pcbranch(newblock1, block3->labels); + + link = lalloc(sizeof(PCLink)); + link->block = newblock1; + link->nextLink = block3->predecessors; + block3->predecessors = link; + + addblocktoloop(loop, newblock1); + if (bitvectorgetbit(block2->blockIndex, loop->vec28)) + bitvectorsetbit(newblock1->blockIndex, loop->vec28); + if (bitvectorgetbit(block2->blockIndex, loop->vec2C)) + bitvectorsetbit(newblock1->blockIndex, loop->vec2C); + + for (loop = loop->parent; loop; loop = loop->parent) { + addblocktoloop(loop, newblock1); + if (bitvectorgetbit(block2->blockIndex, loop->vec28)) + bitvectorsetbit(newblock1->blockIndex, loop->vec28); + if (bitvectorgetbit(block2->blockIndex, loop->vec2C)) + bitvectorsetbit(newblock1->blockIndex, loop->vec2C); + + addblocktoloop(loop, newblock2); + if (bitvectorgetbit(block2->blockIndex, loop->vec28)) + bitvectorsetbit(newblock2->blockIndex, loop->vec28); + if (bitvectorgetbit(block2->blockIndex, loop->vec2C)) + bitvectorsetbit(newblock2->blockIndex, loop->vec2C); + } + + return newblock1; +} + +static BlockList *findswitchpath(Loop *loop, PCodeBlock *block) { + BlockList *head; + BlockList *tail; + BlockList *node; + PCodeBlock *scan; + + head = NULL; + tail = NULL; + + for (scan = block; scan && scan != loop->body; scan = scan->successors->block) { + if (!bitvectorgetbit(scan->blockIndex, loop->memberblocks)) + return NULL; + if (scan->successors && scan->successors->nextLink) + return NULL; + + node = oalloc(sizeof(BlockList)); + node->block = scan; + node->next = NULL; + if (head) { + tail->next = node; + tail = node; + } else { + head = node; + tail = node; + } + } + + return head; +} + +static void simpleunswitchloop(Loop *loop) { + PCode *pc29; + PCodeArg *op27; + UInt32 *myvec; + PCodeBlock *block26; + PCode *pc25; // r25 + BlockList *path2_24; + PCodeArg *op23; + PCode *pc23; // r23 + BlockList *scanlist; // r23 + BlockList *bestpath1; // r23 + BlockList *bestpath2; // r22 + PCodeBlock *headercopy; // r22 + Loop *newloop; // r21 + PCodeBlock *preheader21; + BlockList *path20; + PCode *scan20; + PCode *lastpcode; + int i; + BlockList *pathiter1; + BlockList *pathiter2; + + if (!(lastpcode = loop->body->lastPCode)) + return; + if (lastpcode->op != PC_BT && lastpcode->op != PC_BF) + return; + if (lastpcode->args[2].kind != PCOp_LABEL) + return; + if (!bitvectorgetbit(lastpcode->args[2].data.label.label->block->blockIndex, loop->memberblocks)) + return; + if (loop->x57) + return; + if (loop->x4D) + return; + if (bitvectorgetbit(loop->body->nextBlock->blockIndex, loop->memberblocks)) + return; + + for (block26 = pcbasicblocks; block26; block26 = block26->nextBlock) { + if (bitvectorgetbit(block26->blockIndex, loop->memberblocks)) + break; + } + + if (!block26) + return; + + myvec = oalloc(4 * ((number_of_Defs + 31) >> 5)); + bitvectorcopy(myvec, usedefinfo[block26->blockIndex].defvec8, number_of_Defs); + for (pc25 = loop->preheader->nextBlock->firstPCode; pc25; pc25 = pc25->nextPCode) { + if (!(PCODE_FLAG_SET_F(pc25) & (fIsCall | fIsPtrOp | fIsVolatile | fSideEffects | fRecordBit))) { + if (isloopinvariant(pc25, loop, myvec, 0, 1)) + break; + } + } + + if (!pc25 || pc25->argCount < 1) + return; + + if ( + pc25->argCount < 1 || + pc25->args[0].kind != PCOp_REGISTER || + pc25->args[0].arg != RegClass_CRFIELD + ) + return; + + pc29 = pc25->block->lastPCode; + if ( + !pc29 || + !(pc29->flags & fIsBranch) || + pc29->args[0].kind != PCOp_REGISTER || + pc29->args[0].arg != RegClass_CRFIELD + ) + return; + + if (pc29->args[0].data.reg.reg != pc25->args[0].data.reg.reg) + return; + + op27 = NULL; + for (i = 0; i < pc29->argCount; i++) { + if (pc29->args[i].kind == PCOp_LABEL) + op27 = &pc29->args[i]; + } + + if (op27) { + preheader21 = loop->preheader; + + path20 = findswitchpath(loop, block26->nextBlock); + if (!path20) + return; + + path2_24 = findswitchpath(loop, op27->data.label.label->block); + if (!path2_24) + return; + + bestpath1 = NULL; + bestpath2 = NULL; + for (pathiter1 = path20; pathiter1; pathiter1 = pathiter1->next) { + for (pathiter2 = path2_24; pathiter2; pathiter2 = pathiter2->next) { + if (pathiter1->block == pathiter2->block) { + bestpath1 = pathiter1; + break; + } + } + if (bestpath1) + break; + bestpath2 = pathiter1; + } + + CError_ASSERT(1192, bestpath2->block); + + if (bestpath2->block->lastPCode && bestpath2->block->lastPCode->op == PC_B) + deletepcode(bestpath2->block->lastPCode); + + while (bestpath1) { + for (scan20 = bestpath1->block->firstPCode; scan20; scan20 = scan20->nextPCode) { + if (scan20->op != PC_B) + appendpcode(bestpath2->block, copypcode(scan20)); + } + bestpath1 = bestpath1->next; + } + + headercopy = appendheadercopy(loop, bestpath2->block, loop->body, block26); + movecmptopreheader(loop, block26, pc25, pc29, op27); + + if (block26->pcodeCount) { + if (path2_24->block->firstPCode) { + pc23 = path2_24->block->firstPCode; + for (scan20 = block26->firstPCode; scan20; scan20 = scan20->nextPCode) { + if (scan20->op != PC_B) + insertpcodebefore(pc23, copypcode(scan20)); + } + } else { + for (scan20 = block26->firstPCode; scan20; scan20 = scan20->nextPCode) { + if (scan20->op != PC_B) + appendpcode(path2_24->block, copypcode(scan20)); + } + } + } + + op23 = NULL; + for (i = 0; i < loop->body->lastPCode->argCount; i++) { + if (loop->body->lastPCode->args[i].kind == PCOp_LABEL) + op23 = &loop->body->lastPCode->args[i]; + } + + CError_ASSERT(1250, op23 != NULL); + + changesuccessor(loop->body, op23->data.label.label->block, path2_24->block); + op23->data.label.label = path2_24->block->labels; + + op23 = NULL; + for (i = 0; i < preheader21->lastPCode->argCount; i++) { + if (preheader21->lastPCode->args[i].kind == PCOp_LABEL) + op23 = &preheader21->lastPCode->args[i]; + } + + CError_ASSERT(1267, op23 != NULL); + + changesuccessor(preheader21, op23->data.label.label->block, loop->body); + op23->data.label.label = loop->body->labels; + + op23 = NULL; + for (i = 0; i < loop->preheader->lastPCode->argCount; i++) { + if (loop->preheader->lastPCode->args[i].kind == PCOp_LABEL) + op23 = &loop->preheader->lastPCode->args[i]; + } + + CError_ASSERT(1284, op23 != NULL); + + changesuccessor(loop->preheader, op23->data.label.label->block, headercopy); + op23->data.label.label = headercopy->labels; + + newloop = lalloc(sizeof(Loop)); + newloop->parent = loop->parent; + newloop->children = NULL; + newloop->nextSibling = loop->nextSibling; + loop->nextSibling = newloop; + newloop->body = loop->body; + newloop->preheader = NULL; + newloop->blocks = NULL; + newloop->basicInductionVars = NULL; + newloop->footer = NULL; + newloop->pc18 = NULL; + newloop->loopWeight = loop->loopWeight; + + bitvectorinitialize(newloop->memberblocks = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); + bitvectorinitialize(newloop->vec24 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); + bitvectorinitialize(newloop->vec28 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); + bitvectorinitialize(newloop->vec2C = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); + + removeblockfromloop(loop, newloop->body); + addblocktoloop(newloop, newloop->body); + + bitvectorsetbit(newloop->body->blockIndex, newloop->vec24); + bitvectorsetbit(newloop->body->blockIndex, newloop->vec2C); + bitvectorsetbit(newloop->body->blockIndex, newloop->vec28); + + for (scanlist = path2_24; scanlist; scanlist = scanlist->next) { + removeblockfromloop(loop, scanlist->block); + addblocktoloop(newloop, scanlist->block); + bitvectorsetbit(scanlist->block->blockIndex, newloop->vec2C); + } + + newloop->preheader = NULL; + insertpreheaderblock(newloop); + analyzeloop(newloop); + + loop->body = headercopy; + + for (scanlist = loop->blocks; scanlist; scanlist = scanlist->next) + bitvectorsetbit(scanlist->block->blockIndex, loop->vec2C); + + bitvectorsetbit(headercopy->blockIndex, loop->vec24); + analyzeloop(loop); + + unswitchedinvariantcode = 1; + } +} + +static void simpleunswitchloops(Loop *loop) { + while (loop) { + if (loop->children) + simpleunswitchloops(loop->children); + else if (!loop->x4F) + simpleunswitchloop(loop); + loop = loop->nextSibling; + } +} + +static void moveinvariantsfromloop(Loop *loop) { + RegUseOrDef *list; + BlockList *blocklist; + PCode *instr; + PCode *nextInstr; + UInt32 *myvec; + UseOrDef *def; + int defID; + int flag; + PCodeBlock *block; + + myvec = oalloc(4 * ((number_of_Defs + 31) >> 5)); + do { + flag = 0; + for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { + block = blocklist->block; + bitvectorcopy(myvec, usedefinfo[block->blockIndex].defvec8, number_of_Defs); + for (instr = block->firstPCode; instr; instr = nextInstr) { + nextInstr = instr->nextPCode; + if (!(instr->flags & fIsBranch) && instr->argCount) { + if ( + !(instr->flags & (fIsCall | fIsPtrOp | fIsVolatile | fSideEffects)) && + isloopinvariant(instr, loop, myvec, 0, 0) && + maymove(instr, loop) + ) { + moveinvariantcomputation(instr, loop); + flag = 1; + } else if (srawi_addze_isloopinvariant(instr, loop, myvec)) { + moveinvariantcomputation(instr, loop); + flag = 1; + } + + for (def = &Defs[defID = instr->defID]; defID < number_of_Defs && def->pcode == instr; def++, defID++) { + if (def->v.kind == PCOp_REGISTER) { + for (list = reg_Defs[def->v.arg][def->v.u.reg]; list; list = list->next) + bitvectorclearbit(list->id, myvec); + } else if (def->v.kind == PCOp_MEMORY) { + if (def->v.arg == PCOpMemory0) { + for (list = findobjectusedef(def->v.u.object)->defs; list; list = list->next) { + if (uniquely_aliases(instr, Defs[list->id].pcode)) + bitvectorclearbit(list->id, myvec); + } + } + } else { + CError_FATAL(1434); + } + + bitvectorsetbit(defID, myvec); + } + } + } + } + } while (flag); +} + +static void moveinvariantsfromloops(Loop *loop) { + while (loop) { + if (loop->children) + moveinvariantsfromloops(loop->children); + moveinvariantsfromloop(loop); + loop = loop->nextSibling; + } +} + +void moveloopinvariantcode(void) { + unswitchedinvariantcode = 0; + movedloopinvariantcode = 0; + if (loopsinflowgraph) { + moveinvariantsfromloops(loopsinflowgraph); + simpleunswitchloops(loopsinflowgraph); + } + freeoheap(); +} diff --git a/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/ConstantPropagation.c b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/ConstantPropagation.c new file mode 100644 index 0000000..2b40453 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/ConstantPropagation.c @@ -0,0 +1,643 @@ +#include "compiler/ConstantPropagation.h" +#include "compiler/Alias.h" +#include "compiler/BitVectors.h" +#include "compiler/CompilerTools.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/UseDefChains.h" +#include "compiler/objects.h" + +int propagatedconstants; +static int changed; +static PCode **defininginstruction; +static PCode **vrdefininginstruction; + +static void computedefininginstructions(PCodeBlock *block) { + RegUseOrDef *list; + PCode *instr; + int i; + + for (i = 0; i < used_virtual_registers[RegClass_GPR]; i++) { + instr = NULL; + for (list = reg_Defs[RegClass_GPR][i]; list; list = list->next) { + if (bitvectorgetbit(list->id, usedefinfo[block->blockIndex].defvec8)) { + if (instr == NULL) { + instr = Defs[list->id].pcode; + } else { + instr = NULL; + break; + } + } + } + defininginstruction[i] = instr; + } + + for (i = 0; i < used_virtual_registers[RegClass_VR]; i++) { + instr = NULL; + for (list = reg_Defs[RegClass_VR][i]; list; list = list->next) { + if (bitvectorgetbit(list->id, usedefinfo[block->blockIndex].defvec8)) { + if (instr == NULL) { + instr = Defs[list->id].pcode; + } else { + instr = NULL; + break; + } + } + } + vrdefininginstruction[i] = instr; + } +} + +static PCode *isstackoperand(PCodeArg *op, SInt16 *resultValue, SInt16 addend) { + PCode *instr; + + if ((instr = defininginstruction[op->data.reg.reg]) && instr->op == PC_ADDI) { + if ( + instr->args[2].kind == PCOp_MEMORY && + (instr->args[1].data.reg.reg == _FP_ || instr->args[1].data.reg.reg == _CALLER_SP_) && + instr->args[2].data.mem.obj->datatype == DLOCAL + ) + { + if (can_add_displ_to_local(instr->args[2].data.mem.obj, addend)) { + *resultValue = instr->args[2].data.mem.offset; + return instr; + } else { + return NULL; + } + } else { + return NULL; + } + } else { + return NULL; + } +} + +static int isconstantoperand(PCodeArg *op, SInt16 *resultValue) { + PCode *instr; + + if ( + (instr = defininginstruction[op->data.reg.reg]) && + instr->op == PC_LI && + instr->args[1].kind == PCOp_IMMEDIATE + ) + { + *resultValue = instr->args[1].data.imm.value; + return 1; + } else { + return 0; + } +} + +static int isuint16constantoperand(PCodeArg *op, SInt16 *resultValue) { + PCode *instr; + + if ( + (instr = defininginstruction[op->data.reg.reg]) && + instr->op == PC_LI && + instr->args[1].kind == PCOp_IMMEDIATE && + FITS_IN_USHORT(instr->args[1].data.imm.value) + ) + { + *resultValue = instr->args[1].data.imm.value; + return 1; + } else { + return 0; + } +} + +static int isvectorconstantoperand(PCodeArg *op, SInt16 *resultValue, Opcode *resultNewOp) { + PCode *instr; + + if ( + (instr = vrdefininginstruction[op->data.reg.reg]) && + (instr->op == PC_VSPLTISB || instr->op == PC_VSPLTISH || instr->op == PC_VSPLTISW) && + instr->args[1].kind == PCOp_IMMEDIATE + ) + { + *resultValue = instr->args[1].data.imm.value; + *resultNewOp = instr->op; + return 1; + } else { + return 0; + } +} + +static int isunsignedloadoperand(PCodeArg *op) { + PCode *instr; + + if ((instr = defininginstruction[op->data.reg.reg])) { + if (instr->flags & fIsRead) { + if (instr->op >= PC_LHZ && instr->op <= PC_LHZUX) + return 2; + if (instr->op >= PC_LBZ && instr->op <= PC_LBZUX) + return 1; + } else if (instr->op == PC_RLWINM) { + int var3 = instr->args[3].data.imm.value; + int var4 = instr->args[4].data.imm.value; + if (var4 == 31) { + if (var3 == 24) + return 1; + if (var3 == 16) + return 2; + } + } + } + + return 0; +} + +static int ismaskedoperand(PCodeArg *op, UInt32 *resultMask) { + PCode *instr; + UInt32 mask; + + if ((instr = defininginstruction[op->data.reg.reg]) && instr->op == PC_RLWINM) { + if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) { + mask = + ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFU >> instr->args[3].data.imm.value)) & + ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFU >> (instr->args[4].data.imm.value + 1))); + } else { + mask = + ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFU >> instr->args[3].data.imm.value)) | + ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFU >> (instr->args[4].data.imm.value + 1))); + } + *resultMask = mask; + return 1; + } + + return 0; +} + +static int issignedloadoperand(PCodeArg *op) { + PCode *instr; + + if ((instr = defininginstruction[op->data.reg.reg])) { + if (instr->flags & fIsRead) { + if (instr->op >= PC_LHA && instr->op <= PC_LHAUX) + return 2; + } else if (instr->op == PC_EXTSB) { + return 1; + } else if (instr->op == PC_EXTSH) { + return 2; + } + } + + return 0; +} + +static void propagateconstantstoblock(PCodeBlock *block) { + PCode *instr; + SInt16 immAddend; + SInt16 value1; + SInt16 valueU16; + Opcode newOpcode; + SInt16 value2; + UInt32 mask; + UInt32 mask2; + int loadSize; + PCodeArg *op; + int i; + + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + switch (instr->op) { + case PC_MR: + if (isconstantoperand(&instr->args[1], &value1)) { + change_opcode(instr, PC_LI); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = value1; + instr->args[1].data.imm.obj = NULL; + propagatedconstants = 1; + changed = 1; + } + break; + case PC_VMR: + if (isvectorconstantoperand(&instr->args[1], &value1, &newOpcode)) { + change_opcode(instr, newOpcode); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = value1; + instr->args[1].data.imm.obj = NULL; + propagatedconstants = 1; + changed = 1; + } + break; + case PC_RLWINM: + if ( + !(PCODE_FLAG_SET_F(instr) & fRecordBit) && + instr->args[2].data.imm.value == 0 && + instr->args[4].data.imm.value == 31 + ) + { + if (isconstantoperand(&instr->args[1], &value1)) { + if ( + (instr->args[3].data.imm.value == 16 && value1 == (value1 & 0x7FFF)) || + (instr->args[3].data.imm.value == 24 && value1 == (value1 & 0xFF)) + ) + { + change_opcode(instr, PC_LI); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = value1; + instr->args[1].data.imm.obj = NULL; + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + break; + } + } + + loadSize = isunsignedloadoperand(&instr->args[1]); + if ( + (loadSize == 2 && instr->args[3].data.imm.value <= 16) || + (loadSize == 1 && instr->args[3].data.imm.value <= 24) + ) + { + change_opcode(instr, PC_MR); + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + break; + } + + if (ismaskedoperand(&instr->args[1], &mask)) { + if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) { + mask2 = + ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFU >> instr->args[3].data.imm.value)) & + ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFU >> (instr->args[4].data.imm.value + 1))); + } else { + mask2 = + ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFU >> instr->args[3].data.imm.value)) | + ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFU >> (instr->args[4].data.imm.value + 1))); + } + if (mask == (mask & mask2)) { + change_opcode(instr, PC_MR); + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + } + } + break; + + case PC_EXTSH: + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + break; + + if (isconstantoperand(&instr->args[1], &value1)) { + change_opcode(instr, PC_LI); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = value1; + instr->args[1].data.imm.obj = NULL; + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + break; + } + + loadSize = issignedloadoperand(&instr->args[1]); + if (loadSize == 1 || loadSize == 2) { + change_opcode(instr, PC_MR); + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + break; + + case PC_EXTSB: + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + break; + + if ( + isconstantoperand(&instr->args[1], &value1) && + value1 >= -128 && + value1 <= 127 + ) + { + change_opcode(instr, PC_LI); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = value1; + instr->args[1].data.imm.obj = NULL; + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + break; + } + + loadSize = issignedloadoperand(&instr->args[1]); + if (loadSize == 1) { + change_opcode(instr, PC_MR); + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + break; + + case PC_ADDI: + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + break; + + immAddend = instr->args[2].data.imm.value; + if ( + isconstantoperand(&instr->args[1], &value1) && + FITS_IN_SHORT(immAddend + value1) + ) + { + change_opcode(instr, PC_LI); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = immAddend + value1; + instr->args[1].data.imm.obj = NULL; + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + break; + + case PC_ADD: + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + break; + + if (isconstantoperand(&instr->args[2], &value1)) { + if (value1 == 0) { + change_opcode(instr, PC_MR); + change_num_operands(instr, 2); + } else { + change_opcode(instr, PC_ADDI); + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = value1; + instr->args[2].data.imm.obj = NULL; + } + propagatedconstants = 1; + changed = 1; + immAddend = value1; + } + + if (isconstantoperand(&instr->args[1], &value1)) { + if (instr->op == PC_ADDI || instr->op == PC_MR) { + if (FITS_IN_SHORT(immAddend + value1)) { + change_opcode(instr, PC_LI); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = immAddend + value1; + instr->args[1].data.imm.obj = NULL; + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + } else { + instr->args[1] = instr->args[2]; + if (value1 == 0) { + change_opcode(instr, PC_MR); + change_num_operands(instr, 2); + } else { + change_opcode(instr, PC_ADDI); + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = value1; + instr->args[2].data.imm.obj = NULL; + } + propagatedconstants = 1; + changed = 1; + } + } + + if (changed) { + if (instr->op == PC_MR) { + PCode *stackInstr; + if ((stackInstr = isstackoperand(&instr->args[1], &value1, 0))) { + change_opcode(instr, PC_ADDI); + instr->flags = stackInstr->flags; + instr->args[1] = stackInstr->args[1]; + instr->args[2] = stackInstr->args[2]; + change_num_operands(instr, 3); + propagatedconstants = 1; + changed = 1; + } + } else if (instr->op == PC_ADDI && instr->args[2].kind == PCOp_IMMEDIATE) { + PCode *stackInstr; + SInt16 addend = instr->args[2].data.imm.value; + if ((stackInstr = isstackoperand(&instr->args[1], &value1, addend))) { + change_opcode(instr, PC_ADDI); + instr->flags = stackInstr->flags; + instr->args[1] = stackInstr->args[1]; + instr->args[2] = stackInstr->args[2]; + instr->args[2].data.imm.value = value1 + addend; + if (instr->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) + instr->alias = make_alias(instr->args[2].data.imm.obj, instr->args[2].data.imm.value, 1); + propagatedconstants = 1; + changed = 1; + } + } + } + break; + + case PC_OR: + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + break; + + value1 = 0; + immAddend = 0; + if (isconstantoperand(&instr->args[2], &value1)) { + if (isuint16constantoperand(&instr->args[2], &valueU16)) { + if (valueU16 != 0) { + change_opcode(instr, PC_ORI); + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = valueU16; + instr->args[2].data.imm.obj = NULL; + propagatedconstants = 1; + changed = 1; + } else { + change_opcode(instr, PC_MR); + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + value1 = valueU16; + } else if (value1 == 0) { + change_opcode(instr, PC_MR); + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + immAddend = value1; + } + + if (isconstantoperand(&instr->args[1], &value1)) { + if (instr->op == PC_ORI || instr->op == PC_MR) { + change_opcode(instr, PC_LI); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = immAddend | value1; + instr->args[1].data.imm.obj = NULL; + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } else if (isuint16constantoperand(&instr->args[1], &valueU16)) { + if (valueU16 != 0) { + change_opcode(instr, PC_ORI); + instr->args[1] = instr->args[2]; + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = valueU16; + instr->args[2].data.imm.obj = NULL; + propagatedconstants = 1; + changed = 1; + } else { + change_opcode(instr, PC_MR); + instr->args[1] = instr->args[2]; + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + } else if (value1 == 0) { + change_opcode(instr, PC_MR); + instr->args[1] = instr->args[2]; + change_num_operands(instr, 2); + propagatedconstants = 1; + changed = 1; + } + } + break; + + case PC_SUBF: + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + break; + + if (isconstantoperand(&instr->args[1], &value1) && FITS_IN_SHORT(-value1)) { + if (isconstantoperand(&instr->args[2], &value2) && FITS_IN_SHORT(value2 - value1)) { + change_opcode(instr, PC_LI); + instr->args[1].kind = PCOp_IMMEDIATE; + instr->args[1].data.imm.value = value2 - value1; + instr->args[1].data.imm.obj = NULL; + change_num_operands(instr, 2); + } else if (value1 == 0) { + change_opcode(instr, PC_MR); + instr->args[1] = instr->args[2]; + change_num_operands(instr, 2); + } else { + change_opcode(instr, PC_ADDI); + instr->args[1] = instr->args[2]; + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = -value1; + instr->args[2].data.imm.obj = NULL; + } + propagatedconstants = 1; + changed = 1; + value2 = value1; + } else if (isconstantoperand(&instr->args[2], &value1) && FITS_IN_SHORT(-value1)) { + if (value1 == 0) { + change_opcode(instr, PC_NEG); + change_num_operands(instr, 2); + } else { + instr->flags = opcodeinfo[PC_SUBFIC].flags | (instr->flags & ~opcodeinfo[PC_SUBF].flags); + change_opcode(instr, PC_SUBFIC); + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = value1; + instr->args[2].data.imm.obj = NULL; + instr->args[3].kind = PCOp_REGISTER; + instr->args[3].arg = RegClass_SPR; + instr->args[3].data.reg.reg = 0; + instr->args[3].data.reg.effect = EffectWrite; + change_num_operands(instr, 4); + } + propagatedconstants = 1; + changed = 1; + } + + break; + + case PC_LBZ: + case PC_LHZ: + case PC_LHA: + case PC_LWZ: + case PC_STB: + case PC_STH: + case PC_STW: + case PC_LFS: + case PC_LFD: + case PC_STFS: + case PC_STFD: + if (instr->args[2].kind == PCOp_IMMEDIATE) { + PCode *stackInstr; + SInt16 addend = instr->args[2].data.imm.value; + + if ((stackInstr = isstackoperand(&instr->args[1], &value1, addend))) { + instr->args[1] = stackInstr->args[1]; + instr->args[2] = stackInstr->args[2]; + instr->args[2].data.imm.value = value1 + addend; + if (instr->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) + instr->alias = make_alias(instr->args[2].data.imm.obj, instr->args[2].data.imm.value, + nbytes_loaded_or_stored_by(instr)); + propagatedconstants = 1; + changed = 1; + } + } + break; + + case PC_LBZX: + case PC_LHZX: + case PC_LHAX: + case PC_LWZX: + case PC_STBX: + case PC_STHX: + case PC_STWX: + case PC_LFSX: + case PC_LFDX: + case PC_STFSX: + case PC_STFDX: + if (isconstantoperand(&instr->args[2], &value1)) { + instr->op -= 2; + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = value1; + instr->args[2].data.imm.obj = NULL; + propagatedconstants = 1; + changed = 1; + } else if (isconstantoperand(&instr->args[1], &value1)) { + instr->op -= 2; + instr->args[1] = instr->args[2]; + instr->args[2].kind = PCOp_IMMEDIATE; + instr->args[2].data.imm.value = value1; + instr->args[2].data.imm.obj = NULL; + propagatedconstants = 1; + changed = 1; + } + + break; + } + + for (i = 0, op = instr->args; i < instr->argCount; i++, op++) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + (op->data.reg.effect & EffectWrite) + ) + { + defininginstruction[op->data.reg.reg] = instr; + } + else if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_VR && + (op->data.reg.effect & EffectWrite) + ) + { + vrdefininginstruction[op->data.reg.reg] = instr; + } + } + } +} + +void propagateconstants(void) { + PCodeBlock *block; + int i; + + propagatedconstants = 0; + computeusedefchains(0); + defininginstruction = galloc(sizeof(PCode *) * used_virtual_registers[RegClass_GPR]); + vrdefininginstruction = galloc(sizeof(PCode *) * used_virtual_registers[RegClass_VR]); + + do { + changed = 0; + for (i = 0; i < pcblockcount; i++) { + if ((block = depthfirstordering[i])) { + computedefininginstructions(block); + propagateconstantstoblock(block); + } + } + } while (changed); + + freeoheap(); +} diff --git a/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/LoopDetection.c b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/LoopDetection.c new file mode 100644 index 0000000..6bb2d51 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/LoopDetection.c @@ -0,0 +1,885 @@ +#include "compiler/LoopDetection.h" +#include "compiler/CFunc.h" +#include "compiler/PCode.h" +#include "compiler/TOC.h" +#include "compiler/UseDefChains.h" +#include "compiler/CompilerTools.h" +#include "compiler/BitVectors.h" +#include "compiler/enode.h" +#include "compiler/objects.h" + +Loop *loopsinflowgraph; +int loopdetection_nblocks; +static UInt32 **dominators; +static BlockList *loopheaders; +static int nloopheaders; +static PCodeBlock **loopstack; +BitVector *LoopTemp; +struct LoopList *LoopList_First; + +static void computedominators(void) { + int i; + PCodeBlock *block; + int blockCount; + int flag; + UInt32 *myvec; + PCLink *link; + + blockCount = pcblockcount; + flag = 1; + + dominators = oalloc(sizeof(UInt32 *) * pcblockcount); + for (i = 0; i < pcblockcount; i++) + dominators[i] = oalloc(4 * ((blockCount + 31) >> 5)); + + myvec = oalloc(4 * ((blockCount + 31) >> 5)); + + bitvectorinitialize(dominators[pcbasicblocks->blockIndex], blockCount, 0); + //dominators[pcbasicblocks->blockIndex][0] |= 1; + bitvectorsetbit(0, dominators[pcbasicblocks->blockIndex]); + + for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) + bitvectorinitialize(dominators[block->blockIndex], blockCount, 0xFFFFFFFF); + + computedepthfirstordering(); + + while (flag) { + flag = 0; + for (i = 0; i < pcblockcount; i++) { + block = depthfirstordering[i]; + if (block && block->blockIndex != pcbasicblocks->blockIndex) { + bitvectorcopy(myvec, dominators[block->predecessors->block->blockIndex], blockCount); + for (link = block->predecessors->nextLink; link; link = link->nextLink) + bitvectorintersect(myvec, dominators[link->block->blockIndex], blockCount); + //myvec[block->blockIndex >> 5] |= 1 << (block->blockIndex & 31); + bitvectorsetbit(block->blockIndex, myvec); + + if (bitvectorchanged(dominators[block->blockIndex], myvec, blockCount)) + flag = 1; + } + } + } +} + +static BlockList *findloopheaders(void) { + PCodeBlock *block; + PCLink *link; + BlockList *list; + + loopheaders = NULL; + nloopheaders = 0; + + for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) { + for (link = block->predecessors; link; link = link->nextLink) { + //if ((1 << (block->blockIndex & 31)) & dominators[link->block->blockIndex][block->blockIndex >> 5]) + if (bitvectorgetbit(block->blockIndex, dominators[link->block->blockIndex])) + break; + } + + if (link) { + list = oalloc(sizeof(BlockList)); + list->block = block; + list->next = loopheaders; + loopheaders = list; + nloopheaders++; + } + } + + return loopheaders; +} + +void addblocktoloop(Loop *loop, PCodeBlock *block) { + BlockList *list = lalloc(sizeof(BlockList)); + + //loop->memberblocks[block->blockIndex >> 5] |= 1 << (block->blockIndex & 31); + bitvectorsetbit(block->blockIndex, loop->memberblocks); + + list->block = block; + list->next = loop->blocks; + loop->blocks = list; +} + +static void findnaturalloop(Loop *loop) { + BlockList *list; + BlockList *list2; + PCLink *link; + PCodeBlock *block; + int i; + + i = 0; + addblocktoloop(loop, loop->body); + for (link = loop->body->predecessors; link; link = link->nextLink) { + if (bitvectorgetbit(loop->body->blockIndex, dominators[link->block->blockIndex]) && link->block != loop->body) { + addblocktoloop(loop, link->block); + loopstack[i++] = link->block; + } + } + + while (i) { + link = loopstack[--i]->predecessors; + while (link) { + if (!bitvectorgetbit(link->block->blockIndex, loop->memberblocks)) { + addblocktoloop(loop, link->block); + loopstack[i++] = link->block; + } + link = link->nextLink; + } + } + + for (list = loop->blocks; list; list = list->next) { + block = list->block; + for (link = block->successors; link; link = link->nextLink) { + if (!bitvectorgetbit(link->block->blockIndex, loop->memberblocks)) { + bitvectorsetbit(block->blockIndex, loop->vec24); + break; + } + } + } + + for (list = loop->blocks; list; list = list->next) { + for (list2 = loop->blocks; list2; list2 = list2->next) { + if (bitvectorgetbit(list2->block->blockIndex, loop->vec24) && + !bitvectorgetbit(list->block->blockIndex, dominators[list2->block->blockIndex])) + break; + } + + if (!list2) + bitvectorsetbit(list->block->blockIndex, loop->vec28); + } + + for (list = loop->blocks; list; list = list->next) { + for (link = loop->body->predecessors; link; link = link->nextLink) { + if (bitvectorgetbit(link->block->blockIndex, loop->memberblocks) && + !bitvectorgetbit(list->block->blockIndex, dominators[link->block->blockIndex])) + break; + } + + if (!link) + bitvectorsetbit(list->block->blockIndex, loop->vec2C); + } +} + +static void addlooptolist(Loop *loop, Loop **list) { + Loop **scan; + Loop *scanloop; + + scan = list; + while ((scanloop = *scan)) { + if (bitvectorgetbit(loop->body->blockIndex, scanloop->memberblocks)) { + loop->parent = scanloop; + addlooptolist(loop, &scanloop->children); + return; + } + + if (bitvectorgetbit(scanloop->body->blockIndex, loop->memberblocks)) { + *scan = scanloop->nextSibling; + scanloop->parent = loop; + scanloop->nextSibling = loop->children; + loop->children = scanloop; + } else { + scan = &scanloop->nextSibling; + } + } + + loop->nextSibling = *list; + *list = loop; +} + +static void findnaturalloops(void) { + Loop *loop; + int size; + + loopdetection_nblocks = pcblockcount + 5 * nloopheaders; + loopstack = oalloc(sizeof(PCodeBlock *) * pcblockcount); + while (loopheaders) { + loop = lalloc(sizeof(Loop)); + loop->parent = loop->nextSibling = loop->children = NULL; + loop->body = loopheaders->block; + loop->preheader = NULL; + loop->blocks = NULL; + loop->basicInductionVars = NULL; + loop->footer = NULL; + loop->pc18 = NULL; + loop->loopWeight = loop->body->loopWeight; + + bitvectorinitialize(loop->memberblocks = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); + bitvectorinitialize(loop->vec24 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); + bitvectorinitialize(loop->vec28 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); + bitvectorinitialize(loop->vec2C = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); + + findnaturalloop(loop); + addlooptolist(loop, &loopsinflowgraph); + + loopheaders = loopheaders->next; + } +} + +static PCodeBlock *makepreheaderblock(void) { + PCodeLabel *label; + PCodeBlock *block; + + label = makepclabel(); + block = lalloc(sizeof(PCodeBlock)); + block->nextBlock = NULL; + block->prevBlock = NULL; + block->labels = NULL; + block->successors = NULL; + block->predecessors = NULL; + block->firstPCode = block->lastPCode = NULL; + block->pcodeCount = 0; + block->flags = 0; + block->blockIndex = pcblockcount++; + pclabel(block, label); + return block; +} + +static void insertpreheaderbefore(PCodeBlock *a, PCodeBlock *b) { + a->nextBlock = b; + a->prevBlock = b->prevBlock; + b->prevBlock->nextBlock = a; + b->prevBlock = a; +} + +void insertpreheaderblock(Loop *loop) { + PCodeBlock *preheader; + PCodeBlock *block29; + PCodeBlock *block28; + PCode *pcode27; + PCLink *link; // r26 + PCLink **linkptr; // r25 + PCodeLabel *newlabel; // r23 + PCLink *innerlink; + PCodeBlock *block; + PCodeArg *arg; + int i; + + preheader = loop->preheader = makepreheaderblock(); + block29 = NULL; + block28 = loop->body; + + if (!block28->labels) + pclabel(block28, makepclabel()); + + appendpcode(preheader, makepcode(PC_B, block28->labels)); + preheader->loopWeight = loop->parent ? loop->parent->loopWeight : 1; + + linkptr = &block28->predecessors; + while ((link = *linkptr)) { + if (bitvectorgetbit(link->block->blockIndex, loop->memberblocks)) { + linkptr = &link->nextLink; + } else { + if (link->block->pcodeCount) { + pcode27 = link->block->lastPCode; + if (pcode27->op == PC_B) { + CError_ASSERT(462, pcode27->args[0].kind == PCOp_LABEL); + if (pcode27->args[0].data.label.label->block == block28) + pcode27->args[0].data.label.label = preheader->labels; + } else if (pcode27->op == PC_BT || pcode27->op == PC_BF) { + CError_ASSERT(474, pcode27->args[2].kind == PCOp_LABEL); + if (pcode27->args[2].data.label.label->block == block28) + pcode27->args[2].data.label.label = preheader->labels; + } else if (pcode27->op == PC_BCTR) { + if (pcode27->argCount > 1 && pcode27->args[1].kind == PCOp_MEMORY) { + Object *obj = pcode27->args[1].data.mem.obj; + UInt32 *array = (UInt32 *) obj->u.data.u.switchtable.data; + int i; + for (i = 0; i < obj->u.data.u.switchtable.size; i++) { + if (((PCodeLabel *) CTool_ResolveIndexToPointer(array[i]))->block == block28) + array[i] = CTool_CreateIndexFromPointer(preheader->labels); + } + } else { + CodeLabelList *cll; + for (cll = codelabellist; cll; cll = cll->next) { + if (cll->label->pclabel->block == block28) + cll->label->pclabel = preheader->labels; + } + } + } else { + CError_ASSERT(505, link->block->nextBlock == block28); + } + } + + for (innerlink = link->block->successors; innerlink; innerlink = innerlink->nextLink) { + if (innerlink->block == block28) + innerlink->block = preheader; + } + + *linkptr = link->nextLink;; + link->nextLink = preheader->predecessors; + preheader->predecessors = link; + } + } + + if (!bitvectorgetbit(block28->prevBlock->blockIndex, loop->memberblocks)) { + insertpreheaderbefore(preheader, block28); + + if ( + (!block28->nextBlock || !bitvectorgetbit(block28->nextBlock->blockIndex, loop->memberblocks)) && + block28->lastPCode && + (block28->lastPCode->flags & fIsBranch) && + block28->lastPCode->op != PC_BDNZ + ) { + i = block28->lastPCode->argCount; + arg = block28->lastPCode->args; + while (i && arg->kind != PCOp_LABEL) { + arg++; + i--; + } + + if (i && arg->kind == PCOp_LABEL && arg->data.label.label->block == block28) { + block29 = makepreheaderblock(); + insertpreheaderbefore(block29, block28); + newlabel = makepclabel(); + pclabel(block29, newlabel); + arg->data.label.label = newlabel; + + link = lalloc(sizeof(PCLink)); + link->block = block28; + link->nextLink = block29->predecessors; + block29->predecessors = link; + + link = lalloc(sizeof(PCLink)); + link->block = block28; + link->nextLink = block29->successors; + block29->successors = link; + + for (link = block28->successors; link; link = link->nextLink) { + if (link->block == block28) + link->block = block29; + } + for (link = block28->predecessors; link; link = link->nextLink) { + if (link->block == block28) + link->block = block29; + } + + bitvectorsetbit(block29->blockIndex, loop->vec2C); + addblocktoloop(loop, block29); + } + } + } else { + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (bitvectorgetbit(block->blockIndex, loop->memberblocks)) + break; + } + insertpreheaderbefore(preheader, block); + } + + link = lalloc(sizeof(PCLink)); + link->block = preheader; + link->nextLink = block28->predecessors; + block28->predecessors = link; + + link = lalloc(sizeof(PCLink)); + link->block = block28; + link->nextLink = preheader->successors; + preheader->successors = link; + + for (loop = loop->parent; loop; loop = loop->parent) { + addblocktoloop(loop, preheader); + if (bitvectorgetbit(block28->blockIndex, loop->vec28)) { + bitvectorsetbit(preheader->blockIndex, loop->vec28); + if (block29) + bitvectorsetbit(block29->blockIndex, loop->vec28); + } + if (bitvectorgetbit(block28->blockIndex, loop->vec2C)) { + bitvectorsetbit(preheader->blockIndex, loop->vec2C); + if (block29) + bitvectorsetbit(block29->blockIndex, loop->vec2C); + } + } +} + +static void insertpreheaderblocks(Loop *loop) { + while (loop) { + if (loop->children) + insertpreheaderblocks(loop->children); + insertpreheaderblock(loop); + loop = loop->nextSibling; + } +} + +void findloopsinflowgraph(void) { + loopsinflowgraph = NULL; + computedominators(); + if (findloopheaders()) { + findnaturalloops(); + insertpreheaderblocks(loopsinflowgraph); + } + freeoheap(); +} + +static int checklooplimits(SInt32 opcode, SInt32 condition, SInt32 c, SInt32 d, SInt32 addend, SInt32 *result) { + if (opcode == PC_BT) { + if (condition == 0) { + if (addend <= 0) + return 0; + if (c < d) + *result = (d - c + addend - 1) / addend; + else + *result = 0; + } else if (condition == 1) { + if (addend >= 0) + return 0; + if (c > d) + *result = (c - d - addend - 1) / -addend; + else + *result = 0; + } else { + return 0; + } + } else { + if (condition == 0) { + if (addend >= 0) + return 0; + if (c >= d) + *result = (c - d - addend) / -addend; + else + *result = 0; + } else if (condition == 1) { + if (addend <= 0) + return 0; + if (c <= d) + *result = (d - c + addend) / addend; + else + *result = 0; + } else if (c < d) { + if (addend <= 0) + return 0; + if ((d - c) % addend) + return 0; + *result = (d - c) / addend; + } else if (c > d) { + if (addend >= 0) + return 0; + if ((c - d) % -addend) + return 0; + *result = (c - d) / -addend; + } else { + *result = 0; + } + } + + return 1; +} + +static int checkunsignedlooplimits(SInt32 opcode, SInt32 condition, UInt32 c, UInt32 d, SInt32 addend, UInt32 *result) { + if (opcode == PC_BT) { + if (condition == 0) { + if (addend <= 0) + return 0; + if (c < d) + *result = (d - c + addend - 1) / addend; + else + *result = 0; + } else if (condition == 1) { + if (addend >= 0) + return 0; + if (c > d) + *result = (c - d - addend - 1) / -addend; + else + *result = 0; + } else { + return 0; + } + } else { + if (condition == 0) { + if (addend >= 0) + return 0; + if (c >= d) + *result = (c - d - addend) / -addend; + else + *result = 0; + } else if (condition == 1) { + if (addend <= 0) + return 0; + if (c <= d) + *result = (d - c + addend) / addend; + else + *result = 0; + } else if (c < d) { + if (addend <= 0) + return 0; + if ((d - c) % addend) + return 0; + *result = (d - c) / addend; + } else if (c > d) { + if (addend >= 0) + return 0; + if ((c - d) % -addend) + return 0; + *result = (c - d) / -addend; + } else { + *result = 0; + } + } + + return (*result & 0x80000000) == 0; +} + +static int checkunknownloop(int a, int b, int c, unsigned char *op) { + if (a == PC_BT) { + if (b == 0) { + if (c <= 0) + return 0; + *op = ELESS; + } else if (b == 1) { + if (c >= 0) + return 0; + *op = EGREATER; + } else { + return 0; + } + } else { + if (b == 0) { + if (c >= 0) + return 0; + *op = EGREATEREQU; + } else if (b == 1) { + if (c <= 0) + return 0; + *op = ELESSEQU; + } else if (c == 1) { + *op = ENOTEQU; + } else if (c == -1) { + *op = ENOTEQU; + } else { + return 0; + } + } + + return 1; +} + +static void checkcountingloop(Loop *loop) { + RegUseOrDef *list; + PCode *lastpcode; + PCode *prevpcode; + PCode *pc8; + PCode *check; + short op12; + short reg11; + SInt16 reg4; + short reg11b; + Loop *child; + + if (!(lastpcode = loop->body->lastPCode)) + return; + if (lastpcode->op != PC_BT && lastpcode->op != PC_BF) + return; + if (lastpcode->args[2].kind != PCOp_LABEL) + return; + + if (!bitvectorgetbit(lastpcode->args[2].data.label.label->block->blockIndex, loop->memberblocks)) + return; + if (bitvectorgetbit(loop->body->nextBlock->blockIndex, loop->memberblocks)) + return; + + reg11 = lastpcode->args[0].data.reg.reg; + reg4 = lastpcode->args[1].data.imm.value; + prevpcode = lastpcode->prevPCode; + if (!prevpcode) + return; + + op12 = prevpcode->op; + if (op12 == PC_ADDI && prevpcode->args[2].kind == PCOp_IMMEDIATE) { + pc8 = prevpcode; + prevpcode = prevpcode->prevPCode; + if (!prevpcode) + return; + + op12 = prevpcode->op; + if (pc8->args[0].data.reg.reg != pc8->args[1].data.reg.reg) + return; + if (op12 != PC_CMP && op12 != PC_CMPL && op12 != PC_CMPI && op12 != PC_CMPLI) + return; + if (prevpcode->args[1].data.reg.reg != pc8->args[0].data.reg.reg) + return; + if ((loop->step = pc8->args[2].data.imm.value) == 0) + return; + } + + if (op12 != PC_CMP && op12 != PC_CMPL && op12 != PC_CMPI && op12 != PC_CMPLI) + return; + + if (prevpcode->args[0].data.reg.reg != reg11) + return; + + reg11b = prevpcode->args[1].data.reg.reg; + if (reg11b < 32) + return; + + if (loop->preheader->nextBlock != lastpcode->args[2].data.label.label->block) + return; + + if (op12 == PC_CMPI) { + if (prevpcode->prevPCode) + return; + loop->upper = prevpcode->args[2].data.imm.value; + loop->upperType = LOOP_BOUND_CONSTANT; + } else if (op12 == PC_CMPLI) { + if (prevpcode->prevPCode) + return; + loop->upper = prevpcode->args[2].data.imm.value & 0xFFFF; + loop->upperType = LOOP_BOUND_CONSTANT; + } else if (op12 == PC_CMP || op12 == PC_CMPL) { + if (prevpcode->prevPCode) { + if ( + prevpcode->prevPCode->op == PC_LI && + prevpcode->prevPCode->args[1].kind == PCOp_IMMEDIATE && + prevpcode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg && + !prevpcode->prevPCode->prevPCode + ) { + loop->upper = prevpcode->prevPCode->args[1].data.imm.value; + loop->upperType = LOOP_BOUND_CONSTANT; + } else if ( + prevpcode->prevPCode->op == PC_LIS && + prevpcode->prevPCode->args[1].kind == PCOp_IMMEDIATE && + prevpcode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg && + !prevpcode->prevPCode->prevPCode + ) { + loop->upper = prevpcode->prevPCode->args[1].data.imm.value << 16; + loop->upperType = LOOP_BOUND_CONSTANT; + } else if ( + prevpcode->prevPCode->op == PC_ADDI && + prevpcode->prevPCode->args[2].kind == PCOp_IMMEDIATE && + prevpcode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg && + prevpcode->prevPCode->args[1].data.reg.reg == prevpcode->args[2].data.reg.reg && + prevpcode->prevPCode->prevPCode && + prevpcode->prevPCode->prevPCode->op == PC_LIS && + prevpcode->prevPCode->prevPCode->args[1].kind == PCOp_IMMEDIATE && + prevpcode->prevPCode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg && + !prevpcode->prevPCode->prevPCode->prevPCode + ) { + loop->upper = prevpcode->prevPCode->args[2].data.imm.value + + (prevpcode->prevPCode->prevPCode->args[1].data.imm.value << 16); + loop->upperType = LOOP_BOUND_CONSTANT; + } else { + return; + } + } else { + pc8 = NULL; + for (list = reg_Defs[RegClass_GPR][prevpcode->args[2].data.reg.reg]; list; list = list->next) { + if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks)) + return; + } + for (list = reg_Defs[RegClass_GPR][prevpcode->args[2].data.reg.reg]; list; list = list->next) { + if (bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].defvec8)) { + if (!pc8) { + pc8 = Defs[list->id].pcode; + if ( + pc8->op == PC_LI && + pc8->args[1].kind == PCOp_IMMEDIATE + ) { + loop->upper = pc8->args[1].data.imm.value; + loop->upperType = LOOP_BOUND_CONSTANT; + } else if ( + pc8->op == PC_LIS && + pc8->args[1].kind == PCOp_IMMEDIATE + ) { + loop->upper = pc8->args[1].data.imm.value << 16; + loop->upperType = LOOP_BOUND_CONSTANT; + } else if ( + pc8->op == PC_ADDI && + pc8->args[2].kind == PCOp_IMMEDIATE && + pc8->args[1].data.reg.reg == prevpcode->args[2].data.reg.reg && + pc8->prevPCode && + pc8->prevPCode->op == PC_LIS && + pc8->prevPCode->args[1].kind == PCOp_IMMEDIATE && + pc8->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg + ) { + loop->upper = pc8->args[2].data.imm.value + + (pc8->prevPCode->args[1].data.imm.value << 16); + loop->upperType = LOOP_BOUND_CONSTANT; + } else { + loop->upperType = LOOP_BOUND_VARIABLE; + break; + } + } else { + loop->upperType = LOOP_BOUND_VARIABLE; + break; + } + } + } + + if (loop->upperType == LOOP_BOUND_INDETERMINATE) + loop->upperType = LOOP_BOUND_VARIABLE; + } + } + + pc8 = NULL; + + for (list = reg_Defs[RegClass_GPR][reg11b]; list; list = list->next) { + check = Defs[list->id].pcode; + if (bitvectorgetbit(check->block->blockIndex, loop->memberblocks)) { + if (!pc8) { + pc8 = check; + if (check->op != PC_ADDI) + return; + if (check->args[1].data.reg.reg != reg11b) + return; + if (check->args[2].kind != PCOp_IMMEDIATE) + return; + if ((loop->step = check->args[2].data.imm.value) == 0) + return; + } else { + return; + } + } + } + + if (!pc8) + return; + + if (pc8->block != prevpcode->block && !bitvectorgetbit(prevpcode->block->blockIndex, loop->vec2C)) + return; + + if (loop->children) { + for (child = loop->children; child; child = child->nextSibling) { + if (bitvectorgetbit(pc8->block->blockIndex, child->memberblocks)) + return; + } + } + + loop->pc18 = pc8; + + pc8 = NULL; + + for (list = reg_Defs[RegClass_GPR][reg11b]; list; list = list->next) { + if (bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].defvec8)) { + if (!pc8) { + pc8 = Defs[list->id].pcode; + if ( + pc8->op == PC_LI && + pc8->args[1].kind == PCOp_IMMEDIATE + ) { + loop->lower = pc8->args[1].data.imm.value; + loop->lowerType = LOOP_BOUND_CONSTANT; + } else if ( + pc8->op == PC_LIS && + pc8->args[1].kind == PCOp_IMMEDIATE + ) { + loop->lower = pc8->args[1].data.imm.value << 16; + loop->lowerType = LOOP_BOUND_CONSTANT; + } else if ( + pc8->op == PC_ADDI && + pc8->args[2].kind == PCOp_IMMEDIATE && + pc8->args[1].data.reg.reg == reg11b && + pc8->prevPCode && + pc8->prevPCode->op == PC_LIS && + pc8->prevPCode->args[1].kind == PCOp_IMMEDIATE && + pc8->prevPCode->args[0].data.reg.reg == reg11b + ) { + loop->lower = pc8->args[2].data.imm.value + + (pc8->prevPCode->args[1].data.imm.value << 16); + loop->lowerType = LOOP_BOUND_CONSTANT; + } else { + loop->lowerType = LOOP_BOUND_VARIABLE; + break; + } + } else { + loop->lowerType = LOOP_BOUND_INDETERMINATE; + break; + } + } + } + + if (loop->lowerType == LOOP_BOUND_INDETERMINATE) + loop->lowerType = LOOP_BOUND_VARIABLE; + + if (loop->lowerType == LOOP_BOUND_CONSTANT && loop->upperType == LOOP_BOUND_CONSTANT) { + if (op12 == PC_CMP || op12 == PC_CMPI) { + if (!checklooplimits(lastpcode->op, reg4, loop->lower, loop->upper, loop->step, &loop->iterationCount)) + return; + } else { + if (!checkunsignedlooplimits(lastpcode->op, reg4, loop->lower, loop->upper, loop->step, (UInt32 *) &loop->iterationCount)) + return; + } + loop->isKnownCountingLoop = 1; + } else if (loop->lowerType != LOOP_BOUND_INDETERMINATE || loop->upperType != LOOP_BOUND_INDETERMINATE) { + if (!checkunknownloop(lastpcode->op, reg4, loop->step, &loop->unknownCondition)) + return; + loop->isUnknownCountingLoop = 1; + } +} + +void analyzeForCountableLoops(Loop *loop) { + if (!loop) + return; + + while (loop) { + if (loop->children) + analyzeForCountableLoops(loop->children); + checkcountingloop(loop); + loop = loop->nextSibling; + } +} + +void analyzeloop(Loop *loop) { + BlockList *list; + PCodeBlock *block; + PCode *pcode; + + loop->bodySize = 0; + loop->x4D = 0; + loop->x4E = 0; + loop->x4F = 1; + loop->isKnownCountingLoop = 0; + loop->isUnknownCountingLoop = 0; + loop->lowerType = LOOP_BOUND_INDETERMINATE; + loop->upperType = LOOP_BOUND_INDETERMINATE; + loop->iterationCount = -1; + loop->x57 = 0; + loop->x52 = 0; + + for (list = loop->blocks; list; list = list->next) { + block = list->block; + if (!loop->children) + block->flags |= fPCBlockFlag2000; + loop->bodySize += block->pcodeCount; + + if (block != loop->body) { + if (!block->successors || !block->predecessors || block->successors->nextLink || block->predecessors->nextLink) + loop->x4F = 0; + } + + if ((block->flags & fPCBlockFlag4000) == fPCBlockFlag4000) + loop->x52 = 1; + + for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { + if (PCODE_FLAG_SET_T(pcode) & fLink) + loop->x4D = 1; + + if (pcode->op == PC_BCTRL || pcode->op == PC_BCTR || pcode->op == PC_BCCTR || pcode->op == PC_MTCTR || pcode->op == PC_MFCTR) { + loop->x4E = 1; + } else if (pcode->flags & fIsRead) { + if (pcode->op == PC_LBZX || pcode->op == PC_LHZX || pcode->op == PC_LHAX || pcode->op == PC_LWZX || pcode->op == PC_LFSX || pcode->op == PC_LFDX) + loop->x53 = 1; + } else if (pcode->flags & fIsWrite) { + if (pcode->op == PC_STBX || pcode->op == PC_STHX || pcode->op == PC_STWX || pcode->op == PC_STFSX || pcode->op == PC_STFDX) + loop->x54 = 1; + } else { + if (pcode->op == PC_EIEIO || pcode->op == PC_SYNC || pcode->op == PC_ISYNC) + loop->x57 = 1; + } + } + } + + if (!loop->children && !loop->x4D && loop->bodySize < 32) { + for (list = loop->blocks; list; list = list->next) + list->block->flags |= fPCBlockFlag2000; + } +} + +static void analyzeloops(Loop *loop) { + while (loop) { + if (loop->children) + analyzeloops(loop->children); + analyzeloop(loop); + loop = loop->nextSibling; + } +} + +void analyzeloopsinflowgraph(void) { + if (loopsinflowgraph) + analyzeloops(loopsinflowgraph); +} diff --git a/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/LoopOptimization.c b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/LoopOptimization.c new file mode 100644 index 0000000..b2aef1e --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/LoopOptimization.c @@ -0,0 +1,1553 @@ +#include "compiler/LoopOptimization.h" +#include "compiler/CFunc.h" +#include "compiler/CParser.h" +#include "compiler/BitVectors.h" +#include "compiler/CompilerTools.h" +#include "compiler/LoopDetection.h" +#include "compiler/PCode.h" +#include "compiler/Registers.h" +#include "compiler/UseDefChains.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +int optimizedloops; +int optimizedloop_full_unroll; +int optimizedloop_trans_regs; +static UInt32 *liveonexit; +static UInt32 *inductionvariables; +static int last_virtual_GPR; + +static int ispowerof2(SInt32 value) { + int bit = getbit(value); + return (bit > 0 && bit < 31) ? bit : 0; +} + +static void insertupdateinstructions(Loop *loop) { + // nothing +} + +static void computeliveonexit(Loop *loop) { + UInt32 *usevec; + UInt32 *defvec; + BlockList *blocklist; + RegUseOrDef *list; + int gpr; + + bitvectorinitialize(usevec = oalloc(4 * ((number_of_Uses + 31) >> 5)), number_of_Uses, 0); + for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { + if (bitvectorgetbit(blocklist->block->blockIndex, loop->vec24)) + bitvectorunion(usevec, usedefinfo[blocklist->block->blockIndex].usevec1C, number_of_Uses); + } + + bitvectorinitialize(defvec = oalloc(4 * ((number_of_Defs + 31) >> 5)), number_of_Defs, 0); + if (loop->preheader) + bitvectorunion(defvec, usedefinfo[loop->preheader->blockIndex].defvec8, number_of_Defs); + + bitvectorinitialize(liveonexit, last_virtual_GPR, 0); + + for (gpr = 32; gpr < last_virtual_GPR; gpr++) { + for (list = reg_Defs[RegClass_GPR][gpr]; list; list = list->next) { + if (bitvectorgetbit(list->id, defvec)) { + if (!Defs[list->id].pcode->block || bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks)) { + bitvectorsetbit(gpr, liveonexit); + break; + } + } + } + + for (list = reg_Uses[RegClass_GPR][gpr]; list; list = list->next) { + if (bitvectorgetbit(list->id, usevec)) { + if (!Uses[list->id].pcode->block || !bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks)) { + bitvectorsetbit(gpr, liveonexit); + break; + } + } + } + } +} + +static void eliminateinductionvariables(Loop *loop) { + BlockList *blocklist; + PCode *instr; + PCode *nextInstr; + PCodeArg *op; + int i; + + bitvectorinitialize(inductionvariables, last_virtual_GPR, 0xFFFFFFFF); + + for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { + for (instr = blocklist->block->firstPCode; instr; instr = instr->nextPCode) { + if ( + instr->op != PC_ADDI || + instr->args[0].data.reg.reg < 32 || + instr->args[0].data.reg.reg >= last_virtual_GPR || + instr->args[1].data.reg.reg != instr->args[0].data.reg.reg + ) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + op->data.reg.reg >= n_real_registers[RegClass_GPR] && + op->data.reg.reg < last_virtual_GPR + ) + bitvectorclearbit(op->data.reg.reg, inductionvariables); + op++; + } + } + } + } + + if (loop->parent) { + for (instr = loop->preheader->firstPCode; instr; instr = nextInstr) { + nextInstr = instr->nextPCode; + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + op->data.reg.reg >= n_real_registers[RegClass_GPR] && + op->data.reg.reg < last_virtual_GPR + ) + bitvectorsetbit(op->data.reg.reg, liveonexit); + op++; + } + } + } + + for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { + for (instr = blocklist->block->firstPCode; instr; instr = nextInstr) { + nextInstr = instr->nextPCode; + if ( + instr->op == PC_ADDI && + instr->args[0].data.reg.reg >= 32 && + instr->args[0].data.reg.reg < last_virtual_GPR && + instr->args[1].data.reg.reg == instr->args[0].data.reg.reg && + bitvectorgetbit(instr->args[0].data.reg.reg, inductionvariables) && + !bitvectorgetbit(instr->args[0].data.reg.reg, liveonexit) + ) { + deletepcode(instr); + optimizedloops = 1; + } + } + } +} + +static void skiplooptest(Loop *loop) { + PCodeBlock *preheader; + PCodeLabel *label; + PCLink **ptr; + PCLink *link; + PCode *lastInstr; + PCode *instr; + + preheader = loop->preheader; + lastInstr = loop->body->lastPCode; + CError_ASSERT(340, lastInstr->args[2].kind == PCOp_LABEL); + + label = lastInstr->args[2].data.label.label; + preheader->lastPCode->args[0].data.label.label = label; + preheader->successors->block = label->block; + + ptr = &loop->body->predecessors; + while ((link = *ptr)) { + if (link->block == preheader) { + *ptr = link->nextLink; + break; + } + ptr = &link->nextLink; + } + + link->nextLink = label->block->predecessors; + label->block->predecessors = link; + + while (1) { + instr = loop->body->firstPCode; + CError_ASSERT(369, instr); + + if (instr->op == PC_CMP || instr->op == PC_CMPI || instr->op == PC_CMPLI || instr->op == PC_CMPL) + break; + + deletepcode(instr); + insertpcodebefore(loop->preheader->lastPCode, instr); + loop->bodySize--; + } + + for (instr = instr->nextPCode; instr && !(instr->flags & fIsBranch); instr = instr->nextPCode) + insertpcodebefore(loop->preheader->lastPCode, copypcode(instr)); +} + +static void unrollloop(Loop *loop) { + PCodeBlock *newBlock; + int i; + int factor; + PCode *instr; + PCodeBlock *block; + PCode *firstInstr; + PCode *nextInstr; + + for (factor = copts.unroll_factor_limit; factor > 1; factor--) { + if ((loop->iterationCount % factor) == 0 && (loop->bodySize - 2) * factor <= copts.unroll_instr_limit) + break; + } + + if (factor == 1) + return; + if ((loop->iterationCount / factor) != 1 && loop->bodySize < 4) + return; + + newBlock = oalloc(sizeof(PCodeBlock)); + newBlock->firstPCode = newBlock->lastPCode = NULL; + for (i = 0; i < factor - 1; i++) { + firstInstr = loop->body->firstPCode; + CError_ASSERT(448, firstInstr); + if (firstInstr->op != PC_CMP && firstInstr->op != PC_CMPL && firstInstr->op != PC_CMPI && firstInstr->op != PC_CMPLI) + CError_FATAL(450); + + for (instr = firstInstr->nextPCode; instr && !(instr->flags & fIsBranch); instr = instr->nextPCode) + appendpcode(newBlock, copypcode(instr)); + + for (block = loop->preheader->successors->block; block != loop->body; block = block->successors->block) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if (instr->op != PC_B) + appendpcode(newBlock, copypcode(instr)); + } + } + } + + block = loop->body->predecessors->block; + for (instr = newBlock->firstPCode; instr; instr = nextInstr) { + nextInstr = instr->nextPCode; + appendpcode(block, instr); + } + loop->iterationCount /= factor; +} + +void pccomputepredecessors1(PCodeBlock *block) { + PCLink *succ; + PCLink *pred; + + for (succ = block->successors; succ; succ = succ->nextLink) { + if (!succ->block) { + CError_FATAL(496); + } else { + for (pred = succ->block->predecessors; pred; pred = pred->nextLink) { + if (pred->block == block) + break; + } + + if (!pred) { + pred = lalloc(sizeof(PCLink)); + pred->block = block; + pred->nextLink = succ->block->predecessors; + succ->block->predecessors = pred; + } + } + } +} + +static PCodeBlock *insertnewpcblock(PCodeBlock *block, int loopWeight) { + PCodeBlock *newBlock; + PCodeBlock *nextBlock; + PCodeLabel *label; + PCLink *prev; + PCLink *link; + + label = makepclabel(); + newBlock = lalloc(sizeof(PCodeBlock)); + + nextBlock = block->nextBlock; + newBlock->nextBlock = nextBlock; + block->nextBlock = newBlock; + + newBlock->prevBlock = block; + nextBlock->prevBlock = newBlock; + + newBlock->labels = NULL; + newBlock->predecessors = newBlock->successors = NULL; + newBlock->firstPCode = newBlock->lastPCode = NULL; + newBlock->pcodeCount = 0; + newBlock->loopWeight = loopWeight; + newBlock->flags = 0; + newBlock->blockIndex = pcblockcount++; + pclabel(newBlock, label); + + prev = NULL; + for (link = block->successors; link; link = link->nextLink) { + if (link->block == nextBlock) { + if (!prev) + block->successors = link->nextLink; + else + prev->nextLink = link->nextLink; + link->nextLink = NULL; + newBlock->successors = link; + break; + } + prev = link; + } + + prev = NULL; + for (link = nextBlock->predecessors; link; link = link->nextLink) { + if (link->block == block) { + if (!prev) + nextBlock->predecessors = link->nextLink; + else + prev->nextLink = link->nextLink; + link->nextLink = NULL; + newBlock->predecessors = link; + break; + } + prev = link; + } + + link = lalloc(sizeof(PCLink)); + link->block = newBlock; + link->nextLink = block->successors; + block->successors = link; + + link = lalloc(sizeof(PCLink)); + link->block = newBlock; + link->nextLink = nextBlock->predecessors; + nextBlock->predecessors = link; + + return newBlock; +} + +static void unrollloopconditional(Loop *loop) { + PCodeBlock *lastBlock; + PCodeLabel *label24; + PCode *instr; + PCode *instrCopy; + int outputBlockCount; + int inputBlockCount; + PCodeBlock **blocks; + PCodeBlock **blocks2; + PCodeBlock **blocks3; + PCode *firstInstr; + int factor; + PCodeBlock *block; + PCLink *link; + PCLink *prev; + int i; + int j; + int k; + int instructionCount; + + label24 = NULL; + outputBlockCount = 0; + instructionCount = 0; + + for (factor = copts.unroll_factor_limit; factor > 1; factor--) { + if ((loop->iterationCount % factor) == 0 && (loop->bodySize - 2) * factor <= copts.unroll_instr_limit) + break; + } + + if (factor == 1) + return; + + inputBlockCount = 0; + for (block = loop->preheader->successors->block; block != loop->body; block = block->nextBlock) { + inputBlockCount++; + if (!bitvectorgetbit(block->blockIndex, loop->memberblocks)) + instructionCount += block->pcodeCount; + } + + if ((loop->bodySize - instructionCount - 2) < instructionCount || instructionCount > 8) + return; + + blocks = oalloc(inputBlockCount * sizeof(PCodeBlock *)); + blocks2 = oalloc(inputBlockCount * sizeof(PCodeBlock *)); + blocks3 = oalloc(factor * (inputBlockCount * sizeof(PCodeBlock *))); + memclrw(blocks, inputBlockCount * sizeof(PCodeBlock *)); + memclrw(blocks2, inputBlockCount * sizeof(PCodeBlock *)); + memclrw(blocks3, factor * (inputBlockCount * sizeof(PCodeBlock *))); + + block = loop->preheader->nextBlock; + for (i = 0; i < inputBlockCount; i++) { + blocks[i] = block; + block = block->nextBlock; + } + + lastBlock = blocks[inputBlockCount - 1]; + for (i = 0; i < factor - 1; i++) { + for (j = 0; j < inputBlockCount; j++) { + blocks2[j] = insertnewpcblock(lastBlock, loop->loopWeight); + blocks3[outputBlockCount++] = blocks2[j]; + lastBlock = blocks2[j]; + } + if (label24) { + pclabel(blocks2[0], label24); + label24 = NULL; + } + + for (j = 0; j < inputBlockCount; j++) { + for (instr = blocks[j]->firstPCode; instr; instr = instr->nextPCode) { + if (instr->flags & fIsBranch) { + PCodeArg *op; + int opID; + instrCopy = copypcode(instr); + op = NULL; + for (opID = 0; opID < instr->argCount; opID++) { + if (instr->args[opID].kind == PCOp_LABEL) { + op = &instr->args[opID]; + break; + } + } + + if (op) { + if (op->data.label.label->block == loop->body) { + if (!label24) + label24 = makepclabel(); + instrCopy->args[opID].data.label.label = label24; + } else { + for (k = 0; k < inputBlockCount; k++) { + if (op->data.label.label->block == blocks[k]) { + instrCopy->args[opID].data.label.label = blocks2[k]->labels; + break; + } + } + } + } + + appendpcode(blocks2[j], instrCopy); + if (op) + pcbranch(blocks2[j], instrCopy->args[opID].data.label.label); + } else { + appendpcode(blocks2[j], copypcode(instr)); + } + } + } + + firstInstr = loop->body->firstPCode; + CError_ASSERT(762, firstInstr != NULL); + if (firstInstr->op != PC_CMP && firstInstr->op != PC_CMPL && firstInstr->op != PC_CMPI && firstInstr->op != PC_CMPLI) + CError_FATAL(764); + + for (instr = firstInstr->nextPCode; instr && !(instr->flags & fIsBranch); instr = instr->nextPCode) + appendpcode(blocks2[inputBlockCount - 1], copypcode(instr)); + + for (j = 0; j < inputBlockCount; j++) { + for (link = blocks[j]->successors; link; link = link->nextLink) { + if (link->block == blocks[j]->nextBlock) + break; + } + + if (!link) { + for (link = blocks2[j]->successors, prev = NULL; link; link = link->nextLink) { + if (link->block == blocks2[j]->nextBlock) { + if (prev) + prev->nextLink = link->nextLink; + else + blocks2[j]->successors = link->nextLink; + } else { + prev = link; + } + } + + for (link = blocks2[j]->nextBlock->predecessors, prev = NULL; link; link = link->nextLink) { + if (link->block == blocks2[j]) { + if (prev) + prev->nextLink = link->nextLink; + else + blocks2[j]->nextBlock->predecessors = link->nextLink; + } else { + prev = link; + } + } + } + } + } + + if (label24) + pclabel(loop->body, label24); + + for (i = 0; i < inputBlockCount; i++) { + for (instr = blocks[i]->firstPCode; instr; instr = instr->nextPCode) { + if (instr->flags & fIsBranch) { + PCodeArg *op; + int opID; + op = NULL; + for (opID = 0; opID < instr->argCount; opID++) { + if (instr->args[opID].kind == PCOp_LABEL) { + op = &instr->args[opID]; + break; + } + } + + if (op && op->data.label.label->block == loop->body) { + instr->args[opID].data.label.label = blocks3[0]->labels; + + for (link = blocks[i]->successors, prev = NULL; link; link = link->nextLink) { + if (link->block == loop->body) { + if (prev) + prev->nextLink = link->nextLink; + else + blocks[i]->successors = link->nextLink; + } else { + prev = link; + } + } + + for (link = loop->body->predecessors, prev = NULL; link; link = link->nextLink) { + if (link->block == blocks[i]) { + if (prev) + prev->nextLink = link->nextLink; + else + loop->body->predecessors = link->nextLink; + } else { + prev = link; + } + } + + link = blocks[i]->successors; + while (link && link->block != blocks3[0]) + link = link->nextLink; + + if (!link) { + pcbranch(blocks[i], op->data.label.label); + pccomputepredecessors1(blocks[i]); + } + } + } + } + } + + for (i = 0; i < outputBlockCount; i++) + pccomputepredecessors1(blocks3[i]); + + loop->iterationCount /= factor; +} + +static void unrollunknownBDNZ(Loop *loop) { + int factor; // r29 + PCodeBlock *preheader; // r17 + PCodeBlock *blockA; // r23 + PCodeBlock *postheader; // r22 + PCodeBlock *newblock1; // r26 + PCodeBlock *newblock2; // r31 + PCodeBlock *newblock3; // r19 + PCodeBlock *newblock4; // r20 + PCodeBlock *newblock5; // r24 + PCode *mtctr; // r21 + int mtctr_reg; // r27 + PCode *instr28; // r28 + PCode *instr6; // r6 + PCodeBlock *block; + PCode *instr; + PCodeArg *op; + int i; + int val; + short mtctr_shifted_reg; // r16 + short reg25; // r25 + PCLink *link; + + if (loop->bodySize < 4) + return; + + factor = 128; + while (factor > copts.unroll_factor_limit) + factor >>= 1; + while (factor > 1 && (loop->bodySize - 2) * factor > copts.unroll_instr_limit) + factor >>= 1; + + if (factor < 2) + return; + + preheader = loop->preheader; + blockA = loop->body->nextBlock; + postheader = preheader->nextBlock; + + newblock1 = insertnewpcblock(preheader, loop->loopWeight); + newblock2 = insertnewpcblock(newblock1, loop->loopWeight); + newblock3 = insertnewpcblock(newblock2, loop->loopWeight); + newblock4 = insertnewpcblock(newblock3, loop->loopWeight); + newblock5 = insertnewpcblock(newblock4, loop->loopWeight); + addblocktoloop(loop, newblock1); + addblocktoloop(loop, newblock2); + addblocktoloop(loop, newblock3); + addblocktoloop(loop, newblock4); + addblocktoloop(loop, newblock5); + + for (instr = preheader->lastPCode; instr; instr = instr->prevPCode) { + if (instr->op == PC_MTCTR) { + mtctr = instr; + mtctr_reg = instr->args[0].data.reg.reg; + } + } + + if (!mtctr) + return; + + instr28 = NULL; + for (block = postheader; block != loop->body; block = block->successors->block) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if (instr->op != PC_B) { + appendpcode(newblock2, copypcode(instr)); + if (instr == loop->pc18) + instr28 = newblock2->lastPCode; + } + } + } + + if (!instr28) { + appendpcode(newblock2, copypcode(loop->pc18)); + instr28 = newblock2->lastPCode; + } + + instr6 = NULL; + for (instr = newblock2->firstPCode; instr; instr = instr->nextPCode) { + if (instr != instr28) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + op->data.reg.reg == loop->pc18->args[0].data.reg.reg && + (op->data.reg.effect & (EffectRead | EffectWrite)) + ) { + instr6 = instr; + break; + } + op++; + } + } + if (instr6) + break; + } + + if (!instr6) { + deletepcode(instr28); + deletepcode(loop->pc18); + if (loop->footer) + blockA = loop->footer; + else + blockA = insertnewpcblock(loop->body, loop->loopWeight); + } else { + instr28 = NULL; + } + + for (i = 1; i < factor; i++) { + for (block = postheader; block != loop->body; block = block->successors->block) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if (instr->op != PC_B) + appendpcode(newblock2, copypcode(instr)); + } + } + } + + mtctr_shifted_reg = used_virtual_registers[RegClass_GPR]++; + appendpcode(newblock1, makepcode( + PC_RLWINM, + mtctr_shifted_reg, + mtctr_reg, + 32 - ispowerof2(factor), + ispowerof2(factor), + 31)); + + appendpcode(newblock1, makepcode(PC_CMPLI, 0, mtctr_shifted_reg, 0)); + + if (instr28) { + reg25 = used_virtual_registers[RegClass_GPR]++; + if (loop->step == 1) { + instr = makepcode(PC_MR, reg25, mtctr_reg); + } else if (loop->step == -1) { + instr = makepcode(PC_NEG, reg25, mtctr_reg); + } else { + val = ispowerof2(abs(loop->step)); + if (val > 0) { + instr = makepcode(PC_RLWINM, reg25, mtctr_reg, val, 0, 31 - val); + if (loop->step < 0) { + appendpcode(newblock1, instr); + instr = makepcode(PC_NEG, reg25, reg25); + } + } else { + instr = makepcode(PC_MULLI, reg25, mtctr_reg, loop->step); + } + } + appendpcode(newblock1, instr); + } + + appendpcode(newblock1, makepcode(PC_MTCTR, mtctr_shifted_reg)); + appendpcode(newblock1, makepcode(PC_BT, 0, 2, newblock5->labels)); + pcbranch(newblock1, newblock5->labels); + + link = lalloc(sizeof(PCLink)); + link->block = newblock1; + link->nextLink = newblock5->predecessors; + newblock5->predecessors = link; + + appendpcode(newblock3, makepcode(PC_BDNZ, newblock2->labels)); + pcbranch(newblock3, newblock2->labels); + + link = lalloc(sizeof(PCLink)); + link->block = newblock3; + link->nextLink = newblock2->predecessors; + newblock2->predecessors = link; + + appendpcode(newblock4, makepcode(PC_ANDI, mtctr_reg, mtctr_reg, factor - 1)); + appendpcode(newblock4, makepcode(PC_BT, 0, 2, blockA->labels)); + pcbranch(newblock4, blockA->labels); + + link = lalloc(sizeof(PCLink)); + link->block = newblock4; + link->nextLink = blockA->predecessors; + blockA->predecessors = link; + + deletepcode(mtctr); + appendpcode(newblock5, mtctr); + + if (instr28 && bitvectorgetbit(instr28->args[0].data.reg.reg, liveonexit)) { + instr = makepcode(PC_ADD, instr28->args[0].data.reg.reg, instr28->args[0].data.reg.reg, reg25); + if (blockA->firstPCode) + insertpcodebefore(blockA->firstPCode, instr); + else + appendpcode(blockA, instr); + } +} + +static void deleteloop(Loop *loop) { + PCodeBlock *body; + PCodeBlock *preheader; + PCodeBlock *nextblock; + PCodeLabel *label; + PCode *instr; + PCLink **ptr; + PCLink *link; + PCodeBlock *block; + + body = loop->body; + preheader = loop->preheader; + nextblock = body->nextBlock; + label = makepclabel(); + + while (1) { + instr = body->firstPCode; + CError_ASSERT(1294, instr != NULL); + + if (instr->op == PC_CMP || instr->op == PC_CMPI || instr->op == PC_CMPLI || instr->op == PC_CMPL) + break; + + deletepcode(instr); + insertpcodebefore(loop->preheader->lastPCode, instr); + loop->bodySize--; + } + + pclabel(nextblock, label); + preheader->lastPCode->args[0].data.label.label = label; + preheader->successors->block = nextblock; + + ptr = &nextblock->predecessors; + while ((link = *ptr)) { + if (link->block == body) { + link->block = preheader; + break; + } + ptr = &link->nextLink; + } + + block = pcbasicblocks; + while ((nextblock = block->nextBlock)) { + if (bitvectorgetbit(nextblock->blockIndex, loop->memberblocks)) + block->nextBlock = nextblock->nextBlock; + else + block = nextblock; + } +} + +static void deleteloopheader(Loop *loop) { + PCLink *link; + PCLink **ptr; + + ptr = &loop->body->successors; + while ((link = *ptr)) { + if (link->block == loop->body->lastPCode->args[2].data.label.label->block) { + *ptr = link->nextLink; + break; + } + ptr = &link->nextLink; + } + + ptr = &loop->body->lastPCode->args[2].data.label.label->block->predecessors; + while ((link = *ptr)) { + if (link->block == loop->body) { + *ptr = link->nextLink; + break; + } + ptr = &link->nextLink; + } + + deletepcode(loop->body->firstPCode); + deletepcode(loop->body->lastPCode); + optimizedloop_full_unroll = 1; +} + +static void rewriteloopwithBDNZ(Loop *loop) { + PCode *instr; + + if (!FITS_IN_SHORT(loop->iterationCount)) { + instr = makepcode(PC_LIS, used_virtual_registers[RegClass_GPR]++, 0, HIGH_PART(loop->iterationCount)); + insertpcodebefore(loop->preheader->lastPCode, instr); + + if (loop->iterationCount != 0) + insertpcodeafter(instr, makepcode(PC_ADDI, instr->args[0].data.reg.reg, instr->args[0].data.reg.reg, 0, LOW_PART(loop->iterationCount))); + } else { + instr = makepcode(PC_LI, used_virtual_registers[RegClass_GPR]++, loop->iterationCount); + insertpcodebefore(loop->preheader->lastPCode, instr); + } + + insertpcodebefore(loop->preheader->lastPCode, makepcode(PC_MTCTR, instr->args[0].data.reg.reg)); + + instr = makepcode(PC_BDNZ, loop->body->lastPCode->args[2].data.label.label); + deletepcode(loop->body->firstPCode); + deletepcode(loop->body->lastPCode); + appendpcode(loop->body, instr); + + for (loop = loop->parent; loop; loop = loop->parent) + loop->x4E = 1; +} + +static void rewriteunknownloopwithBDNZ(Loop *loop) { + SInt32 value1; // r24 + SInt32 value2; // r30 + Opcode branchOpcode; // r19 + SInt32 absStep; // r28 + int branchCondition; // r20 + int counterReg; // r27 + int reg1; // r26 + int reg2; // r22 + unsigned char mode; // r23 + PCodeBlock *afterLoop; // r25 + PCode *addiInstr; + PCode *instr; + PCLink *link; + PCLink **ptr; + + absStep = abs(loop->step); + afterLoop = NULL; + + for (addiInstr = loop->body->lastPCode->prevPCode; addiInstr->op == PC_ADDI; addiInstr = loop->body->lastPCode->prevPCode) { + deletepcode(addiInstr); + if (loop->body->lastPCode->args[2].data.label.label->block->firstPCode) + insertpcodebefore(loop->body->lastPCode->args[2].data.label.label->block->firstPCode, addiInstr); + else + appendpcode(loop->body->lastPCode->args[2].data.label.label->block, addiInstr); + + afterLoop = insertnewpcblock(loop->body, loop->loopWeight); + appendpcode(afterLoop, copypcode(addiInstr)); + loop->footer = afterLoop; + } + + if (loop->unknownCondition == ELESS) { + branchOpcode = PC_BF; + if (loop->lowerType == LOOP_BOUND_CONSTANT) { + branchCondition = 1; // GT + value1 = loop->lower; + reg1 = addiInstr->args[2].data.reg.reg; + value2 = absStep - 1 - loop->lower; + mode = 0; + } else if (loop->upperType == LOOP_BOUND_CONSTANT) { + branchCondition = 0; // LT + value1 = loop->upper; + reg1 = addiInstr->args[1].data.reg.reg; + value2 = absStep - 1 + loop->upper; + mode = 1; + } else { + branchCondition = 0; // LT + reg1 = addiInstr->args[1].data.reg.reg; + reg2 = addiInstr->args[2].data.reg.reg; + value2 = absStep - 1; + mode = 2; + } + } else if (loop->unknownCondition == ELESSEQU) { + branchOpcode = PC_BT; + if (loop->lowerType == LOOP_BOUND_CONSTANT) { + branchCondition = 0; // LT + value1 = loop->lower; + reg1 = addiInstr->args[2].data.reg.reg; + value2 = absStep - loop->lower; + mode = 0; + } else if (loop->upperType == LOOP_BOUND_CONSTANT) { + branchCondition = 1; // GT + value1 = loop->upper; + reg1 = addiInstr->args[1].data.reg.reg; + value2 = absStep + loop->upper; + mode = 1; + } else { + branchCondition = 1; // GT + value1 = 0; + reg1 = addiInstr->args[1].data.reg.reg; + reg2 = addiInstr->args[2].data.reg.reg; + value2 = absStep; + mode = 2; + } + } else if (loop->unknownCondition == EGREATER) { + branchOpcode = PC_BF; + if (loop->lowerType == LOOP_BOUND_CONSTANT) { + branchCondition = 0; // LT + value1 = loop->lower; + reg1 = addiInstr->args[2].data.reg.reg; + value2 = absStep - 1 + loop->lower; + mode = 1; + } else if (loop->upperType == LOOP_BOUND_CONSTANT) { + branchCondition = 1; // GT + value1 = loop->upper; + reg1 = addiInstr->args[1].data.reg.reg; + value2 = absStep - 1 - loop->upper; + mode = 0; + } else { + branchCondition = 1; // GT + value1 = 0; + reg1 = addiInstr->args[1].data.reg.reg; + reg2 = addiInstr->args[2].data.reg.reg; + value2 = absStep - 1; + mode = 3; + } + } else if (loop->unknownCondition == EGREATEREQU) { + branchOpcode = PC_BT; + if (loop->lowerType == LOOP_BOUND_CONSTANT) { + branchCondition = 1; // GT + value1 = loop->lower; + reg1 = addiInstr->args[2].data.reg.reg; + value2 = absStep + loop->lower; + mode = 1; + } else if (loop->upperType == LOOP_BOUND_CONSTANT) { + branchCondition = 0; // LT + value1 = loop->upper; + reg1 = addiInstr->args[1].data.reg.reg; + value2 = absStep - loop->upper; + mode = 0; + } else { + branchCondition = 0; // LT + reg1 = addiInstr->args[1].data.reg.reg; + reg2 = addiInstr->args[2].data.reg.reg; + value2 = absStep; + mode = 3; + } + } else if (loop->unknownCondition == ENOTEQU) { + branchOpcode = PC_BT; + branchCondition = 2; // EQ + if (loop->step > 0) { + if (loop->lowerType == LOOP_BOUND_CONSTANT) { + value1 = loop->lower; + reg1 = addiInstr->args[2].data.reg.reg; + value2 = absStep - 1 - loop->lower; + mode = 0; + } else if (loop->upperType == LOOP_BOUND_CONSTANT) { + value1 = loop->upper; + reg1 = addiInstr->args[1].data.reg.reg; + value2 = absStep - 1 + loop->upper; + mode = 1; + } else { + reg1 = addiInstr->args[1].data.reg.reg; + reg2 = addiInstr->args[2].data.reg.reg; + value2 = absStep - 1; + mode = 2; + } + } else { + if (loop->lowerType == LOOP_BOUND_CONSTANT) { + value1 = loop->lower; + reg1 = addiInstr->args[2].data.reg.reg; + value2 = absStep - 1 + loop->lower; + mode = 1; + } else if (loop->upperType == LOOP_BOUND_CONSTANT) { + value1 = loop->upper; + reg1 = addiInstr->args[1].data.reg.reg; + value2 = absStep - 1 - loop->upper; + mode = 0; + } else { + reg1 = addiInstr->args[1].data.reg.reg; + reg2 = addiInstr->args[2].data.reg.reg; + value2 = absStep - 1; + mode = 3; + } + } + } + + while (1) { + instr = loop->body->firstPCode; + CError_ASSERT(1857, instr); + + if (instr->op == PC_CMP || instr->op == PC_CMPI || instr->op == PC_CMPLI || instr->op == PC_CMPL) + break; + + deletepcode(instr); + insertpcodebefore(loop->preheader->lastPCode, instr); + loop->bodySize--; + } + + // build a value for mtctr + counterReg = used_virtual_registers[RegClass_GPR]++; + + if (mode == 1) { + if (value2 == 0) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_NEG, counterReg, reg1)); + } else if (FITS_IN_SHORT(value2)) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_SUBFIC, counterReg, reg1, value2)); + } else { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_LIS, counterReg, 0, HIGH_PART(value2))); + if (value2 != 0) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDI, counterReg, counterReg, 0, LOW_PART(value2))); + } + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_SUBF, counterReg, reg1, counterReg)); + } + } else if (mode == 0) { + if (value2 == 0) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_MR, counterReg, reg1)); + } else if (FITS_IN_SHORT(value2)) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDI, counterReg, reg1, 0, value2)); + } else { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDIS, counterReg, reg1, 0, HIGH_PART(value2))); + if (value2 != 0) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDI, counterReg, counterReg, 0, LOW_PART(value2))); + } + } + } else if (mode == 2) { + if (value2 == 0) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_SUBF, counterReg, reg1, reg2)); + } else if (FITS_IN_SHORT(value2)) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDI, counterReg, reg2, 0, value2)); + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_SUBF, counterReg, reg1, counterReg)); + } else { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDIS, counterReg, reg2, 0, HIGH_PART(value2))); + if (value2 != 0) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDI, counterReg, counterReg, 0, LOW_PART(value2))); + } + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_SUBF, counterReg, reg1, counterReg)); + } + } else { + if (value2 == 0) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_SUBF, counterReg, reg2, reg1)); + } else { + if (FITS_IN_SHORT(value2)) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDI, counterReg, reg1, 0, value2)); + } else { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDIS, counterReg, reg1, 0, HIGH_PART(value2))); + if (value2 != 0) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_ADDI, counterReg, counterReg, 0, LOW_PART(value2))); + } + } + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_SUBF, counterReg, reg2, counterReg)); + } + } + + if (absStep > 1) { + unsigned char bits; + if ((bits = ispowerof2(absStep))) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_RLWINM, counterReg, counterReg, 32 - bits, bits, 31)); + } else { + int reg = used_virtual_registers[RegClass_GPR]++; + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_LI, reg, absStep)); + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_DIVWU, counterReg, counterReg, reg)); + } + } + + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_MTCTR, counterReg)); + + if (mode < 2) { + if (addiInstr->op == PC_CMPL || addiInstr->op == PC_CMPLI) { + if (FITS_IN_USHORT(value1)) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_CMPLI, 0, reg1, value1)); + } else { + PCode *tmp; + tmp = makepcode(PC_LIS, used_virtual_registers[RegClass_GPR]++, 0, HIGH_PART(value1)); + insertpcodebefore(loop->preheader->lastPCode, tmp); + + if (loop->iterationCount != 0) + insertpcodeafter(tmp, + makepcode(PC_ADDI, + tmp->args[0].data.reg.reg, + tmp->args[0].data.reg.reg, + 0, LOW_PART(value1))); + + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_CMPL, 0, reg1, tmp->args[0].data.reg.reg)); + } + } else { + if (FITS_IN_SHORT(value1)) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_CMPI, 0, reg1, value1)); + } else { + PCode *tmp; + tmp = makepcode(PC_LIS, used_virtual_registers[RegClass_GPR]++, 0, HIGH_PART(value1)); + insertpcodebefore(loop->preheader->lastPCode, tmp); + + if (loop->iterationCount != 0) + insertpcodeafter(tmp, + makepcode(PC_ADDI, + tmp->args[0].data.reg.reg, + tmp->args[0].data.reg.reg, + 0, LOW_PART(value1))); + + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_CMP, 0, reg1, tmp->args[0].data.reg.reg)); + } + } + } else { + if (addiInstr->op == PC_CMPL || addiInstr->op == PC_CMPLI) { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_CMPL, 0, reg1, reg2)); + } else { + insertpcodebefore(loop->preheader->lastPCode, + makepcode(PC_CMP, 0, reg1, reg2)); + } + } + + if (!afterLoop) + afterLoop = loop->body->nextBlock; + + instr = makepcode(branchOpcode, 0, branchCondition, afterLoop->labels); + deletepcode(loop->preheader->lastPCode); + appendpcode(loop->preheader, instr); + + instr = makepcode(PC_BDNZ, loop->body->lastPCode->args[2].data.label.label); + deletepcode(loop->body->firstPCode); + deletepcode(loop->body->lastPCode); + appendpcode(loop->body, instr); + + loop->preheader->successors = NULL; + ptr = &loop->body->predecessors; + while ((link = *ptr)) { + if (link->block == loop->preheader) { + *ptr = link->nextLink; + break; + } + ptr = &link->nextLink; + } + + link = lalloc(sizeof(PCLink)); + link->block = loop->preheader->nextBlock; + link->nextLink = loop->preheader->successors; + loop->preheader->successors = link; + + link = lalloc(sizeof(PCLink)); + link->block = loop->preheader; + link->nextLink = loop->preheader->nextBlock->predecessors; + loop->preheader->nextBlock->predecessors = link; + + link = lalloc(sizeof(PCLink)); + link->block = afterLoop; + link->nextLink = loop->preheader->successors; + loop->preheader->successors = link; + + link = lalloc(sizeof(PCLink)); + link->block = loop->preheader; + link->nextLink = afterLoop->predecessors; + afterLoop->predecessors = link; + + for (loop = loop->parent; loop; loop = loop->parent) + loop->x4E = 1; +} + +static void optimizeloop(Loop *loop) { + computeliveonexit(loop); + + if (loop->x53 || loop->x54) + insertupdateinstructions(loop); + + if (loop->isKnownCountingLoop) { + if (loop->iterationCount > 0) { + skiplooptest(loop); + if (!copts.optimizesize && !loop->x4D && !loop->x57) { + if (loop->x4F) + unrollloop(loop); + else if (!loop->x4E) + unrollloopconditional(loop); + } + } + + if (loop->iterationCount != 0) { + if (loop->iterationCount == 1) + deleteloopheader(loop); + else if (!loop->x4E && !loop->x4D) + rewriteloopwithBDNZ(loop); + } + + optimizedloops = 1; + } else if (loop->isUnknownCountingLoop && !loop->x4E && !loop->x4D) { + rewriteunknownloopwithBDNZ(loop); + if (copts.unroll_speculative && !copts.optimizesize) { + if (loop->x4F && !loop->x57 && !loop->x52) + unrollunknownBDNZ(loop); + } + optimizedloops = 1; + } + + eliminateinductionvariables(loop); +} + +typedef struct LocalArray { + struct LocalArray *next; + Object *object; + unsigned int invalid:1; + unsigned int isFloat:1; + unsigned int isSigned:1; + SInt32 elementSize; + SInt32 arraySize; + SInt32 elementCount; + int totalUses; + int elements[1]; +} LocalArray; + +static LocalArray *scanforlocalarrays(void) { + SInt32 elementCount; + LocalArray *head; + LocalArray *array; + ObjectList *list; + int i; + SInt32 arraySize; + SInt32 elementSize; + + head = NULL; + + for (list = locals; list; list = list->next) { + if ( + list->object && + !(IS_TYPE_POINTER(list->object->type) ? (TPTR_QUAL(list->object->type) & Q_VOLATILE) : (list->object->qual & Q_VOLATILE)) && + list->object->type && + IS_TYPE_ARRAY(list->object->type) && + TPTR_TARGET(list->object->type) && + TPTR_TARGET(list->object->type)->type < TYPESTRUCT + ) { + arraySize = list->object->type->size; + elementSize = TPTR_TARGET(list->object->type)->size; + elementCount = arraySize / elementSize; + if (elementCount > 0 && elementCount <= 8) { + array = oalloc(sizeof(int) * (elementCount - 1) + sizeof(LocalArray)); + array->next = head; + head = array; + + array->object = list->object; + array->elementSize = elementSize; + array->arraySize = arraySize; + array->elementCount = elementCount; + array->totalUses = 0; + array->isSigned = 1; + array->isFloat = IS_TYPE_FLOAT(TPTR_TARGET(list->object->type)); + array->invalid = 0; + array->isSigned = 1; + if (!array->isFloat && is_unsigned(TPTR_TARGET(list->object->type))) + array->isSigned = 0; + + for (i = 0; i < elementCount; i++) { + array->elements[i] = 0; + } + } + } + } + + return head; +} + +static LocalArray *lookup_array_object(LocalArray *arrays, Object *object) { + while (arrays) { + if (arrays->object == object) + return arrays; + arrays = arrays->next; + } + return NULL; +} + +void changearraytoregisters(void) { + LocalArray *arrays; + PCodeBlock *block; + PCode *instr; + int i; + PCodeArg *op; + LocalArray **ptr; + LocalArray *array; + int intCounter; + int floatCounter; + int reg; + int reg2; + PCode *newInstr; + + arrays = NULL; + if ((arrays = scanforlocalarrays())) { + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if (!(instr->flags & fIsBranch) && instr->argCount) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_MEMORY && + (PCOpMemoryArg) op->arg == PCOpMemory1 && + (array = lookup_array_object(arrays, op->data.mem.obj)) && + !array->invalid + ) { + if ( + (instr->flags & (fIsRead | fIsWrite)) && + (op->data.mem.offset % array->elementSize) == 0 && + op->data.mem.offset < array->arraySize + ) { + switch (instr->op) { + case PC_LBZ: + case PC_STB: + if (array->elementSize != 1) + array->invalid = 1; + break; + case PC_LHZ: + case PC_LHA: + case PC_STH: + if (array->elementSize != 2) + array->invalid = 1; + break; + case PC_LWZ: + case PC_STW: + if (array->elementSize != 4) + array->invalid = 1; + break; + case PC_LFD: + case PC_STFD: + if (array->elementSize != 8) + array->invalid = 1; + break; + default: + array->invalid = 1; + break; + } + + if (!array->invalid) + array->elements[op->data.mem.offset / array->elementSize]++; + } else { + array->invalid = 1; + } + } + op++; + } + } + } + } + + intCounter = 0; + floatCounter = 0; + ptr = &arrays; + array = *ptr; + while (array) { + if (array->invalid) { + *ptr = array = array->next; + continue; + } + + if (array->isFloat) + floatCounter += array->elementCount; + if (!array->isFloat) + intCounter += array->elementCount; + + for (i = 0; i < array->elementCount; i++) + array->totalUses += array->elements[i]; + + array = array->next; + } + + if (arrays) { + while (intCounter > 8) { + LocalArray *best; + int score; + score = 0; + best = NULL; + for (array = arrays; array; array = array->next) { + if (!array->isFloat) { + if (best) { + if (array->totalUses < score) { + score = array->totalUses; + best = array; + } + } else { + best = array; + score = array->totalUses; + } + } + } + + if (!best) + break; + + if (best == arrays) { + arrays = best->next; + } else { + for (array = arrays; array; array = array->next) { + if (array->next == best) { + array->next = best->next; + break; + } + } + } + + intCounter -= best->elementCount; + } + + while (floatCounter > 8) { + LocalArray *best; + int score; + score = 0; + best = NULL; + for (array = arrays; array; array = array->next) { + if (array->isFloat) { + if (best) { + if (array->totalUses < score) { + score = array->totalUses; + best = array; + } + } else { + best = array; + score = array->totalUses; + } + } + } + + if (!best) + break; + + if (best == arrays) { + arrays = best->next; + } else { + for (array = arrays; array; array = array->next) { + if (array->next == best) { + array->next = best->next; + break; + } + } + } + + floatCounter -= best->elementCount; + } + + CError_ASSERT(2394, intCounter <= 8 && floatCounter <= 8); + + if (!arrays) + return; + + optimizedloop_trans_regs = 1; + + for (array = arrays; array; array = array->next) { + for (i = 0; i < array->elementCount; i++) { + if (array->isFloat) + array->elements[i] = used_virtual_registers[RegClass_FPR]++; + else + array->elements[i] = used_virtual_registers[RegClass_GPR]++; + } + } + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if ( + !(instr->flags & fIsBranch) && + instr->argCount && + (instr->flags & (fIsRead | fIsWrite)) && + instr->args[2].kind == PCOp_MEMORY && + (PCOpMemoryArg) instr->args[2].arg == PCOpMemory1 && + (array = lookup_array_object(arrays, instr->args[2].data.mem.obj)) && + !(array->invalid) + ) + { + reg2 = instr->args[0].data.reg.reg; + reg = array->elements[instr->args[2].data.mem.offset / array->elementSize]; + newInstr = NULL; + switch (instr->op) { + case PC_LBZ: + if (array->isSigned) + newInstr = makepcode(PC_MR, reg2, reg); + else + newInstr = makepcode(PC_RLWINM, reg2, reg, 0, 24, 31); + break; + case PC_STB: + if (array->isSigned) + newInstr = makepcode(PC_EXTSB, reg, reg2); + else + newInstr = makepcode(PC_RLWINM, reg, reg2, 0, 24, 31); + break; + case PC_LHZ: + newInstr = makepcode(PC_RLWINM, reg2, reg, 0, 16, 31); + break; + case PC_LHA: + newInstr = makepcode(PC_EXTSH, reg2, reg); + break; + case PC_STH: + if (array->isSigned) + newInstr = makepcode(PC_EXTSH, reg, reg2); + else + newInstr = makepcode(PC_RLWINM, reg, reg2, 0, 16, 31); + break; + case PC_LWZ: + newInstr = makepcode(PC_MR, reg2, reg); + break; + case PC_STW: + newInstr = makepcode(PC_MR, reg, reg2); + break; + case PC_LFD: + newInstr = makepcode(PC_FMR, reg2, reg); + break; + case PC_STFD: + newInstr = makepcode(PC_FMR, reg, reg2); + break; + default: + CError_FATAL(2494); + break; + } + + if (newInstr) { + insertpcodebefore(instr, newInstr); + deletepcode(instr); + instr = newInstr; + } + } + } + } + } + } + + freeoheap(); +} + +static void optimizenestedloops(Loop *loop) { + while (loop) { + if (loop->children) + optimizenestedloops(loop->children); + optimizeloop(loop); + loop = loop->nextSibling; + } +} + +void optimizeloops(void) { + optimizedloops = 0; + optimizedloop_full_unroll = 0; + optimizedloop_trans_regs = 0; + if (loopsinflowgraph) { + computeusedefchains(0); + last_virtual_GPR = used_virtual_registers[RegClass_GPR]; + liveonexit = oalloc(4 * ((used_virtual_registers[RegClass_GPR] + 31) >> 5)); + inductionvariables = oalloc(4 * ((last_virtual_GPR + 31) >> 5)); + optimizenestedloops(loopsinflowgraph); + freeoheap(); + } +} + diff --git a/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/StrengthReduction.c b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/StrengthReduction.c new file mode 100644 index 0000000..2b68dca --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/StrengthReduction.c @@ -0,0 +1,751 @@ +#include "compiler/StrengthReduction.h" +#include "compiler/BitVectors.h" +#include "compiler/CompilerTools.h" +#include "compiler/LoopDetection.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/Registers.h" +#include "compiler/UseDefChains.h" + +int strengthreducedloops; + +static PCode *findinitializer(Loop *loop, short reg) { + UInt32 *vec; + PCode *best; + RegUseOrDef *list; + + vec = usedefinfo[loop->body->blockIndex].defvec8; + best = NULL; + + for (list = reg_Defs[RegClass_GPR][reg]; list; list = list->next) { + if ( + !(bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks)) && + bitvectorgetbit(list->id, vec) + ) + { + if (best) + return NULL; + best = Defs[list->id].pcode; + } + } + + if (best) { + if (best->op == PC_LI || best->op == PC_ADDI || best->op == PC_ADD) + return best; + } + + return NULL; +} + +static int isbasicinductionvariable(Loop *loop, short reg, SInt32 step) { + RegUseOrDef *list; + PCode *instr; + + for (list = reg_Defs[RegClass_GPR][reg]; list; list = list->next) { + instr = Defs[list->id].pcode; + if (bitvectorgetbit(instr->block->blockIndex, loop->memberblocks)) { + if (instr->op != PC_ADDI) + return 0; + if (instr->args[1].data.reg.reg != reg) + return 0; + if (instr->args[2].data.imm.value != step) + return 0; + } + } + + return 1; +} + +static void addbasicinductionvariable(Loop *loop, short reg, SInt32 step) { + BasicInductionVar *biv; + RegUseOrDef *list; + PCode *instr; + InstrList *instrList; + + for (biv = loop->basicInductionVars; biv; biv = biv->next) { + if (biv->reg == reg) + return; + } + + biv = oalloc(sizeof(BasicInductionVar)); + biv->next = loop->basicInductionVars; + loop->basicInductionVars = biv; + + biv->loop = loop; + biv->inductionVars = NULL; + biv->instrsC = NULL; + biv->step = step; + biv->reg = reg; + + for (list = reg_Defs[RegClass_GPR][reg]; list; list = list->next) { + instr = Defs[list->id].pcode; + if (bitvectorgetbit(instr->block->blockIndex, loop->memberblocks)) { + instrList = oalloc(sizeof(InstrList)); + instrList->next = biv->instrsC; + biv->instrsC = instrList; + instrList->instr = instr; + } + } + + biv->initializer = findinitializer(loop, reg); +} + +static void findbasicinductionvariables(Loop *loop) { + SInt16 step; + BlockList *block; + PCode *instr; + short reg; + + for (block = loop->blocks; block; block = block->next) { + for (instr = block->block->firstPCode; instr; instr = instr->nextPCode) { + if (instr->op == PC_ADDI) { + if ( + (reg = instr->args[0].data.reg.reg) >= 32 && + instr->args[1].data.reg.reg == reg && + isbasicinductionvariable(loop, reg, step = instr->args[2].data.imm.value) + ) + addbasicinductionvariable(loop, reg, step); + } + } + } +} + +static void findallbasicinductionvariables(Loop *loop) { + while (loop) { + if (loop->children) + findallbasicinductionvariables(loop->children); + findbasicinductionvariables(loop); + loop = loop->nextSibling; + } +} + +static int isinductionvariable(BasicInductionVar *biv, int useID, SInt32 *result1, short *result2, short *result3, Loop **result4) { + RegUseOrDef *list; + int counter; + Loop *loop; + Loop *scanloop; + PCode *instr; + + instr = Uses[useID].pcode; + *result2 = 0; + *result3 = 0; + *result4 = NULL; + + switch (instr->op) { + case PC_MULLI: + *result1 = instr->args[2].data.imm.value; + break; + + case PC_RLWINM: + if (instr->args[3].data.imm.value) + return 0; + if (instr->args[2].data.imm.value > 15) + return 0; + if (instr->args[4].data.imm.value != (31 - instr->args[2].data.imm.value)) + return 0; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + return 0; + *result1 = 1 << instr->args[2].data.imm.value; + break; + + case PC_LBZX: + case PC_LHZX: + case PC_LHAX: + case PC_LWZX: + case PC_STBX: + case PC_STHX: + case PC_STWX: + case PC_LFSX: + case PC_LFDX: + case PC_STFSX: + case PC_STFDX: + *result2 = 0; + *result3 = 0; + if (instr->args[1].data.reg.reg == biv->reg) { + *result2 = 1; + *result3 = 2; + } else if (instr->args[2].data.reg.reg == biv->reg) { + *result2 = 2; + *result3 = 1; + } + + counter = 0; + for (list = reg_Defs[RegClass_GPR][instr->args[*result3].data.reg.reg]; list; list = list->next) { + if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, biv->loop->memberblocks)) + counter++; + } + if (counter) + return 0; + + loop = biv->loop; + for (scanloop = loop->parent; scanloop; scanloop = scanloop->parent) { + counter = 0; + for (list = reg_Defs[RegClass_GPR][instr->args[*result3].data.reg.reg]; list; list = list->next) { + if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, scanloop->memberblocks)) + counter++; + } + if (!biv->initializer || bitvectorgetbit(biv->initializer->block->blockIndex, scanloop->memberblocks)) + counter++; + if (counter) + break; + loop = scanloop; + } + + *result4 = loop; + *result1 = 1; + return 1; + + default: + return 0; + } + + counter = 0; + for (list = reg_Defs[RegClass_GPR][instr->args[0].data.reg.reg]; list; list = list->next) { + if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, biv->loop->memberblocks)) + counter++; + } + + return counter == 1; +} + +static void addinductionvariable(BasicInductionVar *biv, PCode *instr, SInt32 val1, short val2, short val3, Loop *val4) { + InductionVar *iv; + + iv = oalloc(sizeof(InductionVar)); + iv->next = biv->inductionVars; + biv->inductionVars = iv; + + iv->basicVar = biv; + iv->instr = instr; + iv->instrC = NULL; + iv->step = val1; + iv->x18 = val2; + iv->x1A = val3; + iv->someloop = val4; + if (instr->flags & (fIsRead | fIsWrite)) + iv->x1C = -1; + else + iv->x1C = instr->args[0].data.reg.reg; + iv->x1E = -1; +} + +static void findnonbasicinductionvariables(Loop *loop) { + BasicInductionVar *biv; + RegUseOrDef *list; + SInt32 result1; + short result2; + short result3; + Loop *result4; + + for (biv = loop->basicInductionVars; biv; biv = biv->next) { + for (list = reg_Uses[RegClass_GPR][biv->reg]; list; list = list->next) { + if (bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks)) { + if (isinductionvariable(biv, list->id, &result1, &result2, &result3, &result4)) + addinductionvariable(biv, Uses[list->id].pcode, result1, result2, result3, result4); + } + } + } +} + +static void findallnonbasicinductionvariables(Loop *loop) { + while (loop) { + if (loop->children) + findallnonbasicinductionvariables(loop->children); + if (loop->basicInductionVars) + findnonbasicinductionvariables(loop); + loop = loop->nextSibling; + } +} + +static void initializeinductionvariable(InductionVar *iv) { + BasicInductionVar *biv; // r31 + PCode *instr; // r27 + PCodeBlock *preheader; // r30 + SInt32 value30; // r30 + short reg29; // r29 + short reg26; // r26 + + biv = iv->basicVar; + preheader = biv->loop->preheader; + + if (iv->x1A) { + reg29 = iv->instr->args[iv->x1A].data.reg.reg; + reg26 = iv->instr->args[iv->x18].data.reg.reg; + instr = NULL; + + if ( + biv->initializer && + biv->initializer->op == PC_LI && + biv->initializer->block == preheader + ) + { + if (biv->initializer->args[1].data.imm.value == 0) + instr = makepcode(PC_MR, iv->x1E, reg29); + else if (FITS_IN_SHORT(biv->initializer->args[1].data.imm.value)) + instr = makepcode(PC_ADDI, iv->x1E, reg29, 0, biv->initializer->args[1].data.imm.value); + } + + if (!instr) + instr = makepcode(PC_ADD, iv->x1E, reg29, reg26); + + if (biv->initializer && instr->op != PC_ADD) + insertpcodeafter(biv->initializer, instr); + else if (iv->someloop && iv->someloop->preheader->lastPCode) + insertpcodebefore(iv->someloop->preheader->lastPCode, instr); + else + insertpcodebefore(preheader->lastPCode, instr); + + iv->instrC = instr; + iv->x1C = reg29; + return; + } + + if (!biv->initializer || biv->initializer->op != PC_LI) { + instr = copypcode(iv->instr); + instr->args[0].data.reg.reg = iv->x1E; + insertpcodebefore(preheader->lastPCode, instr); + } else { + value30 = biv->initializer->args[1].data.imm.value * iv->step; + if (!FITS_IN_SHORT(value30)) { + instr = makepcode(PC_LIS, iv->x1E, 0, HIGH_PART(value30)); + insertpcodeafter(biv->initializer, instr); + if (value30 != 0) + insertpcodeafter(instr, makepcode(PC_ADDI, iv->x1E, iv->x1E, 0, LOW_PART(value30))); + } else { + instr = makepcode(PC_LI, iv->x1E, value30); + insertpcodeafter(biv->initializer, instr); + } + } +} + +static void incrementinductionvariable(InductionVar *iv) { + SInt32 value; + BasicInductionVar *biv; + PCode *instr; + InstrList *list; + + biv = iv->basicVar; + value = iv->step * biv->step; + for (list = biv->instrsC; list; list = list->next) { + if (!FITS_IN_SHORT(value)) { + instr = makepcode(PC_ADDIS, iv->x1E, iv->x1E, 0, HIGH_PART(value)); + insertpcodeafter(list->instr, instr); + + if (value != 0) { + instr = makepcode(PC_ADDI, iv->x1E, iv->x1E, 0, LOW_PART(value)); + insertpcodeafter(list->instr->nextPCode, instr); + } + } else { + instr = makepcode(PC_ADDI, iv->x1E, iv->x1E, 0, value); + insertpcodeafter(list->instr, instr); + } + } +} + +static void copyinductionvariable(InductionVar *iv) { + if (iv->instr->flags & (fIsRead | fIsWrite)) { + iv->instr->op -= 2; + iv->instr->args[1].data.reg.reg = iv->x1E; + iv->instr->args[2].kind = PCOp_IMMEDIATE; + iv->instr->args[2].data.imm.value = 0; + iv->instr->args[2].data.imm.obj = NULL; + } else { + insertpcodeafter(iv->instr, makepcode(PC_MR, iv->x1C, iv->x1E)); + deletepcode(iv->instr); + } +} + +static int testnestediv(InductionVar *iv, SInt32 step1, int reg, SInt32 step2, Loop *loop1, Loop *loop2) { + SInt32 addend; + BlockList *list; + PCode *instr; + PCodeArg *op; + int i; + + if (iv->instrC && iv->x1C == reg) { + if (iv->instrC->op == PC_MR) + addend = 0; + else if (iv->instrC->op == PC_ADDI) + addend = iv->instrC->args[2].data.imm.value; + else + return 0; + + if (step2 == (addend + (step1 * iv->step * loop2->iterationCount))) { + for (list = loop1->blocks; list && list->block != loop2->blocks->block; list = list->next) { + for (instr = list->block->firstPCode; instr; instr = instr->nextPCode) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + op->data.reg.reg == reg + ) + return 0; + op++; + } + } + } + return 1; + } + } + + return 0; +} + +static void strengthreducenestediv(short reg, SInt32 step, PCode *initializer, Loop *loop) { + Loop *scanloop; + BasicInductionVar *biv; + InductionVar *iv; + PCode *instr; + PCodeArg *op; + int i; + + for (scanloop = loop->children; scanloop; scanloop = scanloop->nextSibling) { + if ( + scanloop->isKnownCountingLoop && + scanloop->x4F && + bitvectorgetbit(scanloop->body->blockIndex, loop->vec2C) + ) + { + for (biv = scanloop->basicInductionVars; biv; biv = biv->next) { + for (iv = biv->inductionVars; iv; iv = iv->next) { + if (testnestediv(iv, biv->step, reg, step, loop, scanloop)) { + deletepcode(iv->instrC); + if (initializer) { + insertpcodeafter(initializer, iv->instrC); + } else if (loop->body->lastPCode) { + for (instr = loop->body->lastPCode; instr; instr = instr->prevPCode) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + (op->data.reg.effect & EffectWrite) && + op->data.reg.reg == reg + ) + break; + op++; + } + } + + if (instr) + insertpcodeafter(instr, iv->instrC); + else + insertpcodebefore(loop->body->firstPCode, iv->instrC); + } else { + appendpcode(loop->body, iv->instrC); + } + } + } + } + } + } +} + +static void strengthreducenestedbiv(BasicInductionVar *biv) { + Loop *loop; + InductionVar *iv; + + loop = biv->loop; + for (iv = biv->inductionVars; iv; iv = iv->next) + strengthreducenestediv(iv->x1E, iv->step * biv->step, iv->instrC, loop); + + strengthreducenestediv(biv->reg, biv->step, biv->initializer, loop); +} + +static void strengthreduceinductionvariable(BasicInductionVar *biv) { + int counter; + InductionVar *iv; + InductionVar *otherIv; + short reg; + + counter = 0; + for (iv = biv->inductionVars; iv; iv = iv->next) { + if (iv->step == 1) + counter++; + } + + for (iv = biv->inductionVars; iv; iv = iv->next) { + if ( + (counter <= 4 || iv->step != 1) && + iv->instr->block && + (iv->x1A == 0 || iv->instr->args[2].kind != PCOp_IMMEDIATE) + ) + { + if (iv->x1E == -1) { + iv->x1E = used_virtual_registers[RegClass_GPR]++; + initializeinductionvariable(iv); + incrementinductionvariable(iv); + if (iv->step == 1) { + reg = iv->instr->args[iv->x1A].data.reg.reg; + for (otherIv = iv->next; otherIv; otherIv = otherIv->next) { + if (otherIv->x1A != 0 && otherIv->instr->args[otherIv->x1A].data.reg.reg == reg) + otherIv->x1E = iv->x1E; + } + } else { + for (otherIv = iv->next; otherIv; otherIv = otherIv->next) { + if (otherIv->step == iv->step) + otherIv->x1E = iv->x1E; + } + } + } + + copyinductionvariable(iv); + strengthreducedloops = 1; + } + } +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct BivInit { + SInt32 x0; + short x4; + short x6; + short x8; + Object *xA; +} BivInit; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void calc_biv_init(BasicInductionVar *biv, BivInit *init) { + PCode *instr; + PCode *scan; + PCodeArg *op; + int i; + + instr = biv->initializer; + init->x0 = 0; + init->x4 = -1; + init->x6 = -1; + init->x8 = 0; + init->xA = NULL; + + if (!biv->initializer || (biv->initializer->op != PC_ADDI && biv->initializer->op != PC_ADD)) + return; + + if (instr->op == PC_ADDI) { + if (instr->args[1].data.reg.reg == biv->reg) { + init->x0 = instr->args[2].data.imm.value; + for (scan = instr->prevPCode; scan; scan = scan->prevPCode) { + op = scan->args; + i = scan->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + op->data.reg.reg == biv->reg && + (op->data.reg.effect & EffectWrite) + ) + { + if (scan->op == PC_ADD) { + init->x4 = scan->args[1].data.reg.reg; + init->x6 = scan->args[2].data.reg.reg; + } else if (scan->op == PC_ADDI) { + if (scan->args[2].kind == PCOp_IMMEDIATE) { + init->x4 = scan->args[1].data.reg.reg; + init->x8 = scan->args[2].data.imm.value; + } else if (scan->args[2].kind == PCOp_MEMORY) { + init->x4 = scan->args[1].data.reg.reg; + init->x8 = scan->args[2].data.mem.offset; + init->xA = scan->args[2].data.mem.obj; + } + } + return; + } + op++; + } + } + } else { + if (instr->args[2].kind == PCOp_IMMEDIATE) { + init->x4 = instr->args[1].data.reg.reg; + init->x8 = instr->args[2].data.imm.value; + } else if (instr->args[2].kind == PCOp_MEMORY) { + init->x4 = instr->args[1].data.reg.reg; + init->x8 = instr->args[2].data.mem.offset; + init->xA = instr->args[2].data.mem.obj; + } + } + } else if (instr->op == PC_ADD) { + if (instr->args[1].data.reg.reg == biv->reg) { + init->x6 = instr->args[2].data.reg.reg; + for (scan = instr->prevPCode; scan; scan = scan->prevPCode) { + op = scan->args; + i = scan->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + op->data.reg.reg == biv->reg && + (op->data.reg.effect & EffectWrite) && + scan->op == PC_ADDI + ) + { + if (scan->args[2].kind == PCOp_IMMEDIATE) { + init->x4 = scan->args[1].data.reg.reg; + init->x8 = scan->args[2].data.imm.value; + } else if (scan->args[2].kind == PCOp_MEMORY) { + init->x4 = scan->args[1].data.reg.reg; + init->x8 = scan->args[2].data.mem.offset; + init->xA = scan->args[2].data.mem.obj; + } + return; + } + op++; + } + } + } else { + init->x4 = instr->args[1].data.reg.reg; + init->x6 = instr->args[2].data.reg.reg; + } + } +} + +static void combineinductionvariables(Loop *loop, BasicInductionVar *biv1, BasicInductionVar *biv2, SInt32 difference) { + PCode *instr1; // r31 + int reg1; // r30 + int reg2; // r29 + PCode *instr2; // r24 + PCodeBlock *nextBlock; // r24 + BlockList *list; + PCodeArg *op; + int i; + PCode *instr; + + instr1 = NULL; + instr2 = NULL; + + reg1 = biv1->reg; + CError_ASSERT(930, reg1 >= 0); + + reg2 = biv2->reg; + CError_ASSERT(934, reg2 >= 0); + + if (!FITS_IN_SHORT(difference)) + return; + + for (list = loop->blocks; list; list = list->next) { + for (instr = list->block->firstPCode; instr; instr = instr->nextPCode) { + if (instr1) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_REGISTER && + op->arg == RegClass_GPR && + op->data.reg.reg == reg1 + ) + return; + op++; + } + } + + if (instr->op == PC_ADDI) { + if (instr->args[0].data.reg.reg == reg1) { + if (instr1) + return; + instr1 = instr; + } else if (instr->args[0].data.reg.reg == reg2) { + if (instr2) + return; + instr2 = instr; + } + } + } + } + + if (loop->body->lastPCode->flags & fIsBranch) { + nextBlock = NULL; + + for (i = 0; i < loop->body->lastPCode->argCount; i++) { + if (loop->body->lastPCode->args[i].kind == PCOp_LABEL) { + nextBlock = loop->body->lastPCode->args[i].data.label.label->block; + break; + } + } + + if (!nextBlock) + return; + } else { + nextBlock = loop->body->nextBlock; + } + + deletepcode(instr1); + instr1->args[1].data.reg.reg = reg2; + instr1->args[2].data.imm.value = difference; + + if (nextBlock->firstPCode) + insertpcodebefore(nextBlock->firstPCode, instr1); + else + appendpcode(nextBlock, instr1); + + biv1->reg = -1; + strengthreducedloops = 1; +} + +static void strengthreduceinductionvariables(Loop *loop) { + BasicInductionVar *biv1; + BasicInductionVar *biv2; + BivInit init1; + BivInit init2; + + for (biv1 = loop->basicInductionVars; biv1; biv1 = biv1->next) { + if (biv1->inductionVars) + strengthreduceinductionvariable(biv1); + strengthreducenestedbiv(biv1); + } + + for (biv1 = loop->basicInductionVars; biv1; biv1 = biv1->next) { + if (biv1->reg != -1) { + calc_biv_init(biv1, &init1); + if (init1.x4 != -1) { + for (biv2 = loop->basicInductionVars; biv2; biv2 = biv2->next) { + if (biv2->reg != -1 && biv2 != biv1) { + calc_biv_init(biv2, &init2); + if ( + init2.x4 != -1 && + init1.x4 == init2.x4 && + init1.x6 == init2.x6 && + init1.x8 == init2.x8 && + init1.xA == init2.xA && + biv1->step == biv2->step + ) + { + if (init1.x0 < init2.x0) { + combineinductionvariables(loop, biv2, biv1, init2.x0 - init1.x0); + } else { + combineinductionvariables(loop, biv1, biv2, init1.x0 - init2.x0); + break; + } + } + } + } + } + } + } +} + +static void strengthreduceallinductionvariables(Loop *loop) { + while (loop) { + if (loop->children) + strengthreduceallinductionvariables(loop->children); + if (loop->basicInductionVars) + strengthreduceinductionvariables(loop); + loop = loop->nextSibling; + } +} + +void strengthreduceloops(void) { + strengthreducedloops = 0; + if (loopsinflowgraph) { + computeusedefchains(0); + findallbasicinductionvariables(loopsinflowgraph); + findallnonbasicinductionvariables(loopsinflowgraph); + strengthreduceallinductionvariables(loopsinflowgraph); + freeoheap(); + } +} diff --git a/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/ValueNumbering.c b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/ValueNumbering.c new file mode 100644 index 0000000..0907fa1 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/ValueNumbering.c @@ -0,0 +1,661 @@ +#include "compiler/ValueNumbering.h" +#include "compiler/Alias.h" +#include "compiler/PCode.h" +#include "compiler/Registers.h" +#include "compiler/RegisterInfo.h" +#include "compiler/CompilerTools.h" +#include "compiler/CError.h" + +typedef struct ValueLabel { + struct ValueLabel *next; + PCodeArg op; +} ValueLabel; + +typedef struct AvailableValue { + struct AvailableValue *next; + ValueLabel *labelled; + PCode *pcode; + int killedregister; + int aliasnumber; + int opnumbers[0]; +} AvailableValue; + +typedef struct RegValue { + int number; + int x4; + AvailableValue *available; +} RegValue; + +typedef struct State { + void *stackedvalues; + int valueceiling; +} State; + +typedef struct StackedValue { + struct StackedValue *next; + PCodeArg op; + RegValue value; + Alias *alias; + PCode *valuepcode; +} StackedValue; + +int removedcommonsubexpressions; +int nextvaluenumber; +static AvailableValue *opvalue[428]; +static RegValue *regvalue[RegClassMax]; +static StackedValue *stackedvalues; +static int valueceiling; +static int moreaggressiveoptimization; + +static void allocatecsedatastructures(void) { + char rclass; + + for (rclass = 0; rclass < RegClassMax; rclass++) + regvalue[(char) rclass] = oalloc(sizeof(RegValue) * used_virtual_registers[(char) rclass]); +} + +static void initializecsedatastructures(void) { + RegValue *rv; + char rclass; + int i; + + nextvaluenumber = 0; + + for (i = 0; i < 428; i++) + opvalue[i] = NULL; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + rv = regvalue[(char) rclass]; + for (i = 0; i < used_virtual_registers[(char) rclass]; i++, rv++) { + rv->number = nextvaluenumber++; + rv->x4 = 0; + rv->available = NULL; + } + } + + initialize_alias_values(); + stackedvalues = NULL; + valueceiling = 0x7FFFFFFF; +} + +static void labelvalue(AvailableValue *av, PCodeArg *op) { + ValueLabel *label = oalloc(sizeof(ValueLabel)); + label->op = *op; + label->next = av->labelled; + av->labelled = label; +} + +static void unlabelvalue(AvailableValue *av, PCodeArg *op) { + ValueLabel *labelled; + ValueLabel **ptr; + + ptr = &av->labelled; + while ((labelled = *ptr)) { + if (labelled->op.data.reg.reg == op->data.reg.reg) + *ptr = labelled->next; + else + ptr = &labelled->next; + } +} + +static void stackregistervalue(PCodeArg *op, RegValue *value) { + StackedValue *stacked = oalloc(sizeof(StackedValue)); + stacked->next = stackedvalues; + stackedvalues = stacked; + + stacked->op = *op; + stacked->value = *value; +} + +static void stackmemoryvalue(Alias *alias) { + StackedValue *stacked = oalloc(sizeof(StackedValue)); + stacked->next = stackedvalues; + stackedvalues = stacked; + + stacked->op.kind = PCOp_MEMORY; + stacked->alias = alias; + stacked->value.number = alias->valuenumber; + stacked->valuepcode = alias->valuepcode; +} + +static void unstackvalue(StackedValue *stacked) { + PCodeArg *op = &stacked->op; + RegValue *value; + + if (stacked->op.kind == PCOp_MEMORY) { + stacked->alias->valuenumber = stacked->value.number; + stacked->alias->valuepcode = stacked->valuepcode; + } else { + value = ®value[op->arg][op->data.reg.reg]; + if (value->available) + unlabelvalue(value->available, op); + value->number = stacked->value.number; + value->x4 = stacked->value.x4; + value->available = stacked->value.available; + if (value->available) + labelvalue(value->available, op); + } +} + +static int samevalue(PCodeArg *op1, PCodeArg *op2) { + return regvalue[op1->arg][op1->data.reg.reg].number == regvalue[op2->arg][op2->data.reg.reg].number; +} + +static int killregister(PCodeArg *op) { + RegValue *value; + + value = ®value[op->arg][op->data.reg.reg]; + if (value->number < valueceiling && nextvaluenumber >= valueceiling) + stackregistervalue(op, value); + + if (value->available) + unlabelvalue(value->available, op); + value->available = NULL; + value->x4 = 0; + return value->number = nextvaluenumber++; +} + +void killmemory(Alias *alias, PCode *newValue) { + if (alias->valuenumber < valueceiling && nextvaluenumber >= valueceiling) + stackmemoryvalue(alias); + + if (newValue) { + alias->valuenumber = regvalue[newValue->args[0].arg][newValue->args[0].data.reg.reg].number; + alias->valuepcode = newValue; + } else { + alias->valuenumber = nextvaluenumber++; + alias->valuepcode = NULL; + } +} + +static void killspecificCSEs(short op) { + AvailableValue *av; + ValueLabel *labelled; + + for (av = opvalue[op]; av; av = av->next) { + for (labelled = av->labelled; labelled; labelled = labelled->next) + killregister(&labelled->op); + } +} + +static void killallCSEs(void) { + AvailableValue *av; + ValueLabel *labelled; + int i; + + for (i = 0; i < 428; i++) { + for (av = opvalue[i]; av; av = av->next) { + for (labelled = av->labelled; labelled; labelled = labelled->next) + killregister(&labelled->op); + } + } +} + +static void killregisters(PCode *pcode) { + PCodeArg *op; + int i; + + for (i = 0, op = pcode->args; i < pcode->argCount; i++, op++) { + if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite)) + killregister(op); + } +} + +static void copyregister(PCodeArg *src, PCodeArg *dest) { + RegValue *srcvalue; + RegValue *destvalue; + + srcvalue = ®value[src->arg][src->data.reg.reg]; + destvalue = ®value[dest->arg][dest->data.reg.reg]; + + if (destvalue->number < valueceiling && nextvaluenumber >= valueceiling) + stackregistervalue(dest, destvalue); + + if (destvalue->available) + unlabelvalue(destvalue->available, dest); + destvalue->available = srcvalue->available; + if (destvalue->available) + labelvalue(destvalue->available, dest); + + destvalue->number = srcvalue->number; + + if (srcvalue->x4 && srcvalue->number == regvalue[src->arg][srcvalue->x4].number) + destvalue->x4 = srcvalue->x4; + else + destvalue->x4 = src->data.reg.reg; +} + +static int matchvalues(AvailableValue *av, PCode *match) { + PCodeArg *avOp; + PCodeArg *matchOp; + int i; + + for (avOp = &av->pcode->args[0], matchOp = &match->args[0], i = 0; i < match->argCount; i++, avOp++, matchOp++) { + if (i != 0) { + switch (avOp->kind) { + case PCOp_REGISTER: + if (av->opnumbers[i] != regvalue[matchOp->arg][matchOp->data.reg.reg].number) + return 0; + break; + case PCOp_MEMORY: + if (matchOp->kind != PCOp_MEMORY) + return 0; + if (matchOp->data.mem.obj != avOp->data.mem.obj) + return 0; + if (matchOp->data.mem.offset != avOp->data.mem.offset) + return 0; + if ((unsigned char) matchOp->arg != (unsigned char) avOp->arg) + return 0; + break; + case PCOp_IMMEDIATE: + if (matchOp->kind != PCOp_IMMEDIATE) + return 0; + if (matchOp->data.imm.value != avOp->data.imm.value) + return 0; + break; + case PCOp_LABEL: + if (matchOp->kind != PCOp_LABEL) + return 0; + if (matchOp->data.label.label != avOp->data.label.label) + return 0; + break; + case PCOp_SYSREG: + CError_FATAL(572); + } + } + } + + if ((match->flags & (fIsRead | fPCodeFlag20000)) && match->alias->valuenumber != av->aliasnumber) + return 0; + + return 1; +} + +static void chooselocation(AvailableValue *av, PCodeArg *op) { + ValueLabel *labelled; + PCodeArg *baseop; + + baseop = &av->pcode->args[0]; + labelled = av->labelled; + while (labelled) { + if (labelled->op.data.reg.reg == baseop->data.reg.reg) { + *op = labelled->op; + return; + } + labelled = labelled->next; + } + + *op = av->labelled[0].op; +} + +static int findavailablevalue(PCode *pcode, PCodeArg *op) { + AvailableValue *av; + PCodeArg tmp1; + PCodeArg tmp2; + + for (av = opvalue[pcode->op]; av; av = av->next) { + if (av->labelled && av->pcode->flags == pcode->flags && av->pcode->argCount == pcode->argCount) { + if (!matchvalues(av, pcode)) { + if (!(pcode->flags & fCommutative)) + continue; + + tmp1 = pcode->args[1]; + pcode->args[1] = pcode->args[2]; + pcode->args[2] = tmp1; + + if (!matchvalues(av, pcode)) { + tmp2 = pcode->args[1]; + pcode->args[1] = pcode->args[2]; + pcode->args[2] = tmp2; + continue; + } + } + chooselocation(av, op); + return 1; + } + } + + return 0; +} + +static void addavailablevalue(PCode *pcode) { + AvailableValue *av; + PCodeArg *op; + int i; + + av = oalloc(sizeof(AvailableValue) + sizeof(int) * pcode->argCount); + av->labelled = NULL; + av->pcode = pcode; + for (i = 0, op = &pcode->args[0]; i < pcode->argCount; i++, op++) { + if (op->kind == PCOp_REGISTER) + av->opnumbers[i] = regvalue[op->arg][op->data.reg.reg].number; + } + + if (pcode->flags & (fIsRead | fPCodeFlag20000)) + av->aliasnumber = pcode->alias->valuenumber; + + op = &pcode->args[0]; + av->killedregister = killregister(op); + labelvalue(av, op); + regvalue[op->arg][op->data.reg.reg].available = av; + av->next = opvalue[pcode->op]; + opvalue[pcode->op] = av; +} + +static int isCSEop(PCode *pcode) { + PCodeArg *baseOp; + PCodeArg *op; + int i; + + baseOp = &pcode->args[0]; + + switch (pcode->op) { + case PC_CMPI: + case PC_CMP: + case PC_CMPLI: + case PC_CMPL: + case PC_FCMPU: + case PC_FCMPO: + if (!moreaggressiveoptimization) + return 0; + break; + case PC_LI: + case PC_LIS: + if (!moreaggressiveoptimization) + return 0; + if (pcode->args[0].data.reg.reg < first_fe_temporary_register[RegClass_GPR] || pcode->args[0].data.reg.reg > last_temporary_register[RegClass_GPR]) + return 0; + break; + } + + if (PCODE_FLAG_SET_F(pcode) & (fIsVolatile | fSideEffects | fOverflow | fSetsCarry | fRecordBit)) + return 0; + + for (i = 0, op = &pcode->args[0]; i < pcode->argCount; i++, op++) { + if (op != baseOp && + op->kind == baseOp->kind && + op->arg == baseOp->arg && + op->data.reg.reg == baseOp->data.reg.reg) + return 0; + } + + return 1; +} + +static int isCSEload(PCode *pcode) { + PCodeArg *op; + int i; + int count; + + count = 0; + for (i = 0, op = &pcode->args[0]; i < pcode->argCount; i++, op++) { + if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite)) + count++; + } + + return count == 1; +} + +static void registercopy(PCode *pcode) { + PCodeArg *op1; + PCodeArg *op2; + + op1 = &pcode->args[0]; + op2 = &pcode->args[1]; + if (samevalue(op2, op1)) + deletepcode(pcode); + else + copyregister(op2, op1); +} + +static PCode *recentlystored(Alias *alias, PCodeArg *op) { + PCode *pc; + if ((pc = alias->valuepcode) && alias->valuenumber == regvalue[pc->args[0].arg][pc->args[0].data.reg.reg].number) { + *op = pc->args[0]; + return pc; + } else { + return NULL; + } +} + +static void simpleload(PCode *pcode) { + PCodeArg *origOp; + PCodeArg op; + PCode *rs; + + origOp = &pcode->args[0]; + if ((pcode->flags & fIsVolatile) || !isCSEload(pcode)) { + killregisters(pcode); + return; + } + + if (findavailablevalue(pcode, &op)) { + if (!samevalue(origOp, &op)) { + insertpcodebefore(pcode, makecopyinstruction(&op, origOp)); + copyregister(&op, origOp); + } + deletepcode(pcode); + removedcommonsubexpressions = 1; + } else if ((rs = recentlystored(pcode->alias, &op)) && can_reuse_stored_value(rs, pcode)) { + if (!samevalue(origOp, &op)) { + insertpcodebefore(pcode, makecopyinstruction(&op, origOp)); + copyregister(&op, origOp); + } + deletepcode(pcode); + removedcommonsubexpressions = 1; + } else { + addavailablevalue(pcode); + } +} + +static void simplestore(PCode *pcode) { + update_alias_value(pcode->alias, pcode); + killregisters(pcode); +} + +static void pointerload(PCode *pcode) { + PCodeArg *op; + PCodeArg buf; + + op = &pcode->args[0]; + + if ((pcode->flags & fIsVolatile) || !isCSEload(pcode)) { + killregisters(pcode); + return; + } + + if (findavailablevalue(pcode, &buf)) { + if (!samevalue(op, &buf)) { + insertpcodebefore(pcode, makecopyinstruction(&buf, op)); + copyregister(&buf, op); + } + deletepcode(pcode); + removedcommonsubexpressions = 1; + } else { + addavailablevalue(pcode); + } +} + +static void pointerstore(PCode *pcode) { + update_alias_value(pcode->alias, NULL); + killregisters(pcode); +} + +static void arithmeticop(PCode *pcode) { + PCodeArg *op; + PCodeArg buf; + + op = &pcode->args[0]; + + if (findavailablevalue(pcode, &buf)) { + if (!samevalue(op, &buf)) { + insertpcodebefore(pcode, makecopyinstruction(&buf, op)); + copyregister(&buf, op); + } + deletepcode(pcode); + removedcommonsubexpressions = 1; + } else { + addavailablevalue(pcode); + } +} + +static void functioncall(PCode *pcode) { + killregisters(pcode); + if (coloring) { + update_all_alias_values(); + killallCSEs(); + } else { + update_alias_value(pcode->alias, NULL); + } +} + +static void operatefrommemory(PCode *pcode) { + CError_FATAL(980); +} + +static void operatetomemory(PCode *pcode) { + CError_FATAL(1011); +} + +static void propagatecopiesto(PCode *pcode) { + PCodeArg *op; + int i; + + for (i = 0, op = &pcode->args[0]; i < pcode->argCount; i++, op++) { + if ( + op->kind == PCOp_REGISTER && + (op->data.reg.effect & (EffectRead | EffectWrite | Effect8)) == EffectRead && + op->data.reg.reg >= n_real_registers[op->arg] && + regvalue[op->arg][op->data.reg.reg].x4 && + regvalue[op->arg][op->data.reg.reg].x4 >= n_real_registers[op->arg] && + regvalue[op->arg][op->data.reg.reg].number == regvalue[op->arg][regvalue[op->arg][op->data.reg.reg].x4].number + ) { + op->data.reg.reg = regvalue[op->arg][op->data.reg.reg].x4; + } + } +} + +static void removecsesfrombasicblock(PCodeBlock *block) { + PCode *pcode; + PCode *next; + + for (pcode = block->firstPCode; pcode; pcode = next) { + next = pcode->nextPCode; + propagatecopiesto(pcode); + if (pcode->flags & fIsMove) { + registercopy(pcode); + } else if ((pcode->flags & fIsCall) && (pcode->flags & (fLink | fSideEffects))) { + functioncall(pcode); + } else if (pcode->flags & fIsRead) { + if (pcode->flags & fIsPtrOp) + pointerload(pcode); + else + simpleload(pcode); + } else if (pcode->flags & fIsWrite) { + if (pcode->flags & fIsPtrOp) + pointerstore(pcode); + else + simplestore(pcode); + } else if (pcode->flags & fPCodeFlag20000) { + operatefrommemory(pcode); + } else if (pcode->flags & fPCodeFlag40000) { + operatetomemory(pcode); + } else if ((pcode->flags & fIsCSE) && isCSEop(pcode)) { + arithmeticop(pcode); + } else { + killregisters(pcode); + } + } + + block->flags |= fVisited; +} + +static void getvaluestate(State *state) { + state->stackedvalues = stackedvalues; + state->valueceiling = valueceiling; +} + +static void setvaluestate(State *state) { + stackedvalues = state->stackedvalues; + valueceiling = state->valueceiling; +} + +static void forkvaluestate(int number) { + stackedvalues = NULL; + valueceiling = number; +} + +static void regressvaluestate(void) { + AvailableValue *av; + AvailableValue **ptr; + int i; + StackedValue *stacked; + + for (i = 0; i < 428; i++) { + ptr = &opvalue[i]; + while ((av = *ptr)) { + if (av->killedregister >= valueceiling) + *ptr = av->next; + else + ptr = &av->next; + } + } + + for (stacked = stackedvalues; stacked; stacked = stacked->next) + unstackvalue(stacked); +} + +static void removecsesfromextendedbasicblock(PCodeBlock *block) { + PCLink *succ; + int counter; + State state; + + removecsesfrombasicblock(block); + while (block->successors && + !block->successors->nextLink && + block->successors->block->predecessors && + !block->successors->block->predecessors->nextLink) { + block = block->successors->block; + removecsesfrombasicblock(block); + } + + counter = 0; + for (succ = block->successors; succ; succ = succ->nextLink) { + if (!(succ->block->flags & fVisited) && succ->block->predecessors && !succ->block->predecessors->nextLink) + counter++; + } + + if (counter) { + getvaluestate(&state); + forkvaluestate(nextvaluenumber); + for (succ = block->successors; succ; succ = succ->nextLink) { + if (!(succ->block->flags & fVisited) && succ->block->predecessors && !succ->block->predecessors->nextLink) { + removecsesfromextendedbasicblock(succ->block); + regressvaluestate(); + } + } + setvaluestate(&state); + } +} + +void removecommonsubexpressions(Object *proc, int flag) { + PCodeBlock *block; + + moreaggressiveoptimization = flag; + removedcommonsubexpressions = 0; + gather_alias_info(); + allocatecsedatastructures(); + + for (block = pcbasicblocks; block; block = block->nextBlock) + block->flags &= ~fVisited; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (!(block->flags & fVisited)) { + initializecsedatastructures(); + removecsesfromextendedbasicblock(block); + } + } + + freeoheap(); +} + diff --git a/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/VectorArraysToRegs.c b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/VectorArraysToRegs.c new file mode 100644 index 0000000..fde27f1 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/GlobalOptimizer/VectorArraysToRegs.c @@ -0,0 +1,548 @@ +#include "compiler/VectorArraysToRegs.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/BitVectors.h" +#include "compiler/CompilerTools.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" +#include "compiler/Registers.h" +#include "compiler/UseDefChains.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +typedef struct LocalVectorArray { + struct LocalVectorArray *next; + Object *object; + unsigned int invalid:1; + SInt32 arraySize; + SInt32 elementCount; + int totalUses; + int elements[1]; +} LocalVectorArray; + +typedef struct VectorPropInfo { + UInt32 *use; + UInt32 *def; + UInt32 *in; + UInt32 *out; +} VectorPropInfo; + +typedef struct ADDI { + PCode *instr; + RegUseOrDef *list; +} ADDI; + +static int number_of_ADDIs; +static ADDI *ADDIs; +static VectorPropInfo *vectorpropinfo; +static int *naddsinblock; +static int *firstaddinblock; +static Boolean converted_arrays; + +static LocalVectorArray *scanforlocalvectorarrays(void) { + SInt32 elementCount; + LocalVectorArray *head; + LocalVectorArray *array; + ObjectList *list; + int i; + SInt32 arraySize; + + head = NULL; + + for (list = locals; list; list = list->next) { + if ( + list->object && + !(IS_TYPE_POINTER(list->object->type) ? (TPTR_QUAL(list->object->type) & Q_VOLATILE) : (list->object->qual & Q_VOLATILE)) && + list->object->type && + IS_TYPE_ARRAY(list->object->type) && + IS_TYPE_VECTOR(TPTR_TARGET(list->object->type)) + ) { + arraySize = list->object->type->size; + elementCount = arraySize / 16; + if (elementCount > 0 && elementCount <= 8) { + array = oalloc(sizeof(int) * (elementCount - 1) + sizeof(LocalVectorArray)); + array->next = head; + head = array; + + array->object = list->object; + array->arraySize = arraySize; + array->elementCount = elementCount; + array->totalUses = 0; + array->invalid = 0; + + for (i = 0; i < elementCount; i++) { + array->elements[i] = 0; + } + } + } + } + + return head; +} + +static LocalVectorArray *lookup_vector_array_object(LocalVectorArray *arrays, Object *object) { + while (arrays) { + if (arrays->object == object) + return arrays; + arrays = arrays->next; + } + return NULL; +} + +static void scaninstructions(LocalVectorArray *arrays) { + PCodeBlock *block; + PCode *instr; + int counter; + int i; + PCodeArg *op; + LocalVectorArray *array; + int element; + + naddsinblock = oalloc(sizeof(int) * pcblockcount); + memclrw(naddsinblock, sizeof(int) * pcblockcount); + + firstaddinblock = oalloc(sizeof(int) * pcblockcount); + memclrw(firstaddinblock, sizeof(int) * pcblockcount); + + number_of_ADDIs = 0; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + firstaddinblock[block->blockIndex] = number_of_ADDIs; + counter = 0; + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if (!(instr->flags & fIsBranch) && instr->argCount) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + op->kind == PCOp_MEMORY && + (PCOpMemoryArg) op->arg == PCOpMemory1 && + (array = lookup_vector_array_object(arrays, op->data.mem.obj)) && + !array->invalid + ) + { + if (instr->op != PC_ADDI) { + array->invalid = 1; + } else if (instr->args[0].data.reg.reg < n_real_registers[RegClass_GPR]) { + array->invalid = 1; + } else { + number_of_ADDIs++; + counter++; + } + + if (!array->invalid) { + element = op->data.mem.offset / 16; + if (element < array->elementCount) + array->elements[element]++; + else + array->invalid = 1; + } + } + op++; + } + } + } + naddsinblock[block->blockIndex] = counter; + } +} + +static void computeaddilist(LocalVectorArray *arrays) { + PCodeBlock *block; + PCode *instr; + RegUseOrDef *list; + ADDI *addi; + UInt32 *vec; + LocalVectorArray *array; + UseOrDef *def; + int defID; + UseOrDef *use; + int useID; + + ADDIs = oalloc(sizeof(ADDI) * number_of_ADDIs); + memclrw(ADDIs, sizeof(ADDI) * number_of_ADDIs); + + vec = oalloc(4 * ((number_of_Uses + 31) >> 5)); + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (naddsinblock[block->blockIndex]) { + bitvectorcopy(vec, usedefinfo[block->blockIndex].usevec1C, number_of_Uses); + addi = &ADDIs[firstaddinblock[block->blockIndex] + naddsinblock[block->blockIndex] - 1]; + for (instr = block->lastPCode; instr; instr = instr->prevPCode) { + if (!(instr->flags & fIsBranch) && instr->argCount) { + int reg; // r18 + if ( + instr->op == PC_ADDI && + (reg = instr->args[0].data.reg.reg) >= n_real_registers[RegClass_GPR] && + instr->args[2].kind == PCOp_MEMORY && + (PCOpMemoryArg) instr->args[2].arg == PCOpMemory1 && + (array = lookup_vector_array_object(arrays, instr->args[2].data.mem.obj)) && + !array->invalid + ) + { + addi->instr = instr; + addi->list = NULL; + for (list = reg_Uses[RegClass_GPR][reg]; list; list = list->next) { + if (bitvectorgetbit(list->id, vec)) { + RegUseOrDef *node = oalloc(sizeof(RegUseOrDef)); + node->id = list->id; + node->next = addi->list; + addi->list = node; + } + } + addi--; + } + + for (def = &Defs[defID = instr->defID]; defID < number_of_Defs && def->pcode == instr; def++, defID++) { + if (def->v.kind == PCOp_REGISTER) { + RegUseOrDef *l; + for (l = reg_Uses[def->v.arg][def->v.u.reg]; l; l = l->next) + bitvectorclearbit(l->id, vec); + } + } + + for (use = &Uses[useID = instr->useID]; useID < number_of_Uses && use->pcode == instr; use++, useID++) { + if (use->v.kind == PCOp_REGISTER) + bitvectorsetbit(useID, vec); + } + } + } + } + } +} + +static void allocatevectorpropinfo(void) { + VectorPropInfo *info; + int i; + + vectorpropinfo = oalloc(sizeof(VectorPropInfo) * pcblockcount); + for (i = 0, info = vectorpropinfo; i < pcblockcount; i++, info++) { + info->use = oalloc(4 * ((number_of_ADDIs + 31) >> 5)); + info->def = oalloc(4 * ((number_of_ADDIs + 31) >> 5)); + info->in = oalloc(4 * ((number_of_ADDIs + 31) >> 5)); + info->out = oalloc(4 * ((number_of_ADDIs + 31) >> 5)); + } +} + +static void computelocalvectorpropinfo(LocalVectorArray *arrays) { + VectorPropInfo *info; + PCodeBlock *block; + PCode *instr; + UInt32 *vec0; + UInt32 *vec4; + int index; + PCodeArg *op; + int i; + int addi_i; + ADDI *addi; + LocalVectorArray *array; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + info = &vectorpropinfo[block->blockIndex]; + vec0 = info->use; + vec4 = info->def; + bitvectorinitialize(vec0, number_of_ADDIs, 0); + bitvectorinitialize(vec4, number_of_ADDIs, 0); + index = firstaddinblock[block->blockIndex]; + + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if (!(instr->flags & fIsBranch) && instr->argCount) { + i = instr->argCount; + op = instr->args; + while (i--) { + if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR && (op->data.reg.effect & EffectWrite)) { + for (addi_i = 0, addi = ADDIs; addi_i < number_of_ADDIs; addi_i++, addi++) { + if ( + addi->instr && + addi->instr->args[0].arg == op->arg && + addi->instr->args[0].data.reg.reg == op->data.reg.reg + ) + { + if (addi->instr->block == block) + bitvectorclearbit(addi_i, vec0); + else + bitvectorsetbit(addi_i, vec4); + } + } + } + op++; + } + + if ( + instr->op == PC_ADDI && + instr->args[2].kind == PCOp_MEMORY && + (PCOpMemoryArg) instr->args[2].arg == PCOpMemory1 && + (array = lookup_vector_array_object(arrays, instr->args[2].data.mem.obj)) && + !array->invalid + ) + { + bitvectorsetbit(index, vec0); + index++; + } + } + } + } +} + +static void computeglobalvectorpropinfo(void) { + VectorPropInfo *info; + PCodeBlock *block; + UInt32 *vec0; + UInt32 *vec4; + UInt32 *vec8; + UInt32 *vecC; + int bitvecsize; + int blockIndex; + int i; + int j; + int flag; + PCLink *preds; + UInt32 val; + + bitvecsize = (number_of_ADDIs + 31) >> 5; + flag = 1; + info = &vectorpropinfo[pcbasicblocks->blockIndex]; + bitvectorinitialize(info->in, number_of_ADDIs, 0); + bitvectorcopy(info->out, info->use, number_of_ADDIs); + + for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) { + info = &vectorpropinfo[block->blockIndex]; + vecC = info->out; + vec4 = info->def; + for (i = 0; i < bitvecsize; vecC++, vec4++, i++) + *vecC = ~*vec4; + } + + while (flag) { + flag = 0; + for (blockIndex = 0; blockIndex < pcblockcount; blockIndex++) { + if (depthfirstordering[blockIndex]) { + info = &vectorpropinfo[depthfirstordering[blockIndex]->blockIndex]; + if ((preds = depthfirstordering[blockIndex]->predecessors)) { + vec8 = info->in; + bitvectorcopy(vec8, vectorpropinfo[preds->block->blockIndex].out, number_of_ADDIs); + for (preds = preds->nextLink; preds; preds = preds->nextLink) + bitvectorintersect(vec8, vectorpropinfo[preds->block->blockIndex].out, number_of_ADDIs); + } + + vecC = info->out; + vec8 = info->in; + vec0 = info->use; + vec4 = info->def; + for (j = 0; j < bitvecsize; j++) { + val = *vec0 | (*vec8 & ~*vec4); + if (val != *vecC) { + *vecC = val; + flag = 1; + } + vec8++; + vecC++; + vec4++; + vec0++; + } + } + } + } +} + +static int precedes(PCode *a, PCode *b) { + PCode *scan; + + for (scan = a->nextPCode; scan; scan = scan->nextPCode) { + if (scan == b) + return 1; + } + + return 0; +} + +static int checkvectorstoreorload(int addiID, int useID) { + PCode *addiInstr; + UseOrDef *use; + + addiInstr = ADDIs[addiID].instr; + use = Uses + useID; + if (!addiInstr) + return 0; + + if (addiInstr->args[0].data.reg.reg < n_real_registers[RegClass_GPR]) + return 0; + + if (use->pcode->op != PC_LVX && use->pcode->op != PC_STVX) + return 0; + + if ( + use->pcode->args[1].kind != PCOp_REGISTER || + use->pcode->args[1].arg != RegClass_GPR || + use->pcode->args[1].data.reg.reg != 0 + ) + return 0; + + return use->pcode->args[2].data.reg.reg == addiInstr->args[0].data.reg.reg; +} + +static int checkalluses(LocalVectorArray *arrays, int addiID) { + RegUseOrDef *list; + PCode *instr; + LocalVectorArray *array; + + instr = ADDIs[addiID].instr; + for (list = ADDIs[addiID].list; list; list = list->next) { + if (list && !checkvectorstoreorload(addiID, list->id)) { + array = lookup_vector_array_object(arrays, instr->args[2].data.mem.obj); + array->invalid = 1; + return 0; + } + } + + return 1; +} + +static void convert_array_to_register(LocalVectorArray *arrays, int addiID) { + ADDI *addi; + int newReg; + RegUseOrDef *list; + PCode *instr; + PCode *useInstr; + LocalVectorArray *array; + int element; + + addi = ADDIs + addiID; + + if (!(instr = addi->instr)) + return; + + if ( + !(array = lookup_vector_array_object(arrays, instr->args[2].data.mem.obj)) || + array->invalid + ) + return; + + element = instr->args[2].data.mem.offset / 16; + if (element > array->elementCount) + return; + + newReg = array->elements[element]; + for (list = addi->list; list; list = list->next) { + useInstr = Uses[list->id].pcode; + if (useInstr->op == PC_LVX) { + converted_arrays = 1; + change_opcode(useInstr, PC_VMR); + change_num_operands(useInstr, 2); + useInstr->args[1].kind = PCOp_REGISTER; + useInstr->args[1].arg = RegClass_VR; + useInstr->args[1].data.reg.reg = newReg; + useInstr->args[1].data.reg.effect = EffectRead; + } else if (useInstr->op == PC_STVX) { + converted_arrays = 1; + change_opcode(useInstr, PC_VMR); + change_num_operands(useInstr, 2); + useInstr->args[1] = useInstr->args[0]; + useInstr->args[0].kind = PCOp_REGISTER; + useInstr->args[0].arg = RegClass_VR; + useInstr->args[0].data.reg.reg = newReg; + useInstr->args[0].data.reg.effect = EffectWrite; + } else { + CError_FATAL(661); + } + } + deletepcode(addi->instr); +} + +static void convert_arrays_to_registers(LocalVectorArray *arrays) { + int i; + int counter; + LocalVectorArray **ptr; + LocalVectorArray *array; + + for (i = 0; i < number_of_ADDIs; i++) + checkalluses(arrays, i); + + counter = 0; + ptr = &arrays; + array = *ptr; + while (array) { + if (array->invalid) { + *ptr = array->next; + array = *ptr; + continue; + } + + counter += array->elementCount; + + for (i = 0; i < array->elementCount; i++) + array->totalUses += array->elements[i]; + + array = array->next; + } + + if (arrays) { + while (counter > 32) { + LocalVectorArray *best; + int score; + score = 0; + best = NULL; + for (array = arrays; array; array = array->next) { + if (best) { + if (array->totalUses < score) { + score = array->totalUses; + best = array; + } + } else { + best = array; + score = array->totalUses; + } + } + + if (!best) + break; + + if (best == arrays) { + arrays = best->next; + } else { + for (array = arrays; array; array = array->next) { + if (array->next == best) { + array->next = best->next; + break; + } + } + } + + counter -= best->elementCount; + } + + if (!(array = arrays)) + return; + + while (array) { + for (i = 0; i < array->elementCount; i++) + array->elements[i] = used_virtual_registers[RegClass_VR]++; + array = array->next; + } + + if (arrays) { + for (i = 0; i < number_of_ADDIs; i++) + convert_array_to_register(arrays, i); + } + } +} + +int vectorarraystoregs(void) { + LocalVectorArray *arrays; + + converted_arrays = 0; + if ((arrays = scanforlocalvectorarrays())) { + scaninstructions(arrays); + if (number_of_ADDIs > 0) { + computeusedefchains(0); + computeaddilist(arrays); + allocatevectorpropinfo(); + computelocalvectorpropinfo(arrays); + computedepthfirstordering(); + computeglobalvectorpropinfo(); + convert_arrays_to_registers(arrays); + } + } + + freeoheap(); + return converted_arrays; +} diff --git a/compiler_and_linker/BackEnd/PowerPC/InlineAssembler/FuncLevelAsmPPC.c b/compiler_and_linker/BackEnd/PowerPC/InlineAssembler/FuncLevelAsmPPC.c new file mode 100644 index 0000000..340a54b --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/InlineAssembler/FuncLevelAsmPPC.c @@ -0,0 +1,393 @@ +#include "compiler/FuncLevelAsmPPC.h" +#include "compiler/CCompiler.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CodeGen.h" +#include "compiler/Coloring.h" +#include "compiler/CompilerTools.h" +#include "compiler/DumpIR.h" +#include "compiler/InlineAsmPPC.h" +#include "compiler/InlineAsmRegisters.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/PCode.h" +#include "compiler/PCodeAssembly.h" +#include "compiler/PCodeListing.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/PPCError.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/TOC.h" +#include "compiler/objects.h" + +static EntryPoint *entrypoints_head; +static EntryPoint **entrypoints_tail; + +void setup_assembly_argument(Object *obj, short reg) { + VarInfo *vi; + Type *type; + + vi = Registers_GetVarInfo(obj); + type = obj->type; + vi->used = 1; + + if (!requires_frame) { + if (is_register_object(obj)) { + if (!reg) + CError_Error(CErrorStr263, obj->name->name); + + if (TYPE_IS_8BYTES(type)) { + short regLo; + short regHi; + if (reg < 10) { + if (copts.littleendian) { + regLo = reg; + regHi = reg + 1; + } else { + regLo = reg + 1; + regHi = reg; + } + retain_GPR_pair(obj, regLo, regHi); + InlineAsm_InsertRegister(obj->name->name, RegClass_GPR, regLo, obj); + } + } else if (IS_TYPE_FLOAT(type)) { + retain_register(obj, RegClass_FPR, reg); + InlineAsm_InsertRegister(obj->name->name, RegClass_FPR, reg, obj); + } else if (IS_TYPE_VECTOR(type)) { + retain_register(obj, RegClass_VR, reg); + InlineAsm_InsertRegister(obj->name->name, RegClass_VR, reg, obj); + } else { + retain_register(obj, RegClass_GPR, reg); + InlineAsm_InsertRegister(obj->name->name, RegClass_GPR, reg, obj); + } + } + } else { + if (is_register_object(obj)) { + vi = Registers_GetVarInfo(obj); + if (!vi->reg) { + assign_register_by_type(obj); + if (!(vi->flags & VarInfoFlag2)) + CError_Error(CErrorStr263, obj->name->name); + else + InlineAsm_InsertRegister(obj->name->name, vi->rclass, vi->reg, obj); + } + } + } +} + +void assign_local_addresses(void) { + VarInfo *vi; + ObjectList *list; + Object *object; + + for (list = locals; list; list = list->next) { + vi = CodeGen_GetNewVarInfo(); + list->object->u.var.info = vi; + list->object->flags |= OBJECT_USED; + vi->used = 1; + } + + for (list = locals; list; list = list->next) { + object = list->object; + if (is_register_object(object)) { + vi = Registers_GetVarInfo(object); + if (!vi->reg) { + assign_register_by_type(object); + if (!(vi->flags & VarInfoFlag2)) + CError_Error(CErrorStr263, object->name->name); + else + InlineAsm_InsertRegister(object->name->name, vi->rclass, vi->reg, object); + } + } + } + + for (list = locals; list; list = list->next) { + object = list->object; + if (OBJECT_REG(object) == 0) + assign_local_memory(object); + } +} + +static void FuncAsm_PreScanDirectives(void) { + SInt32 directive; + Boolean save_eoltokens; + + in_assembler = 1; + save_eoltokens = cprep_eoltokens; + cprep_eoltokens = 1; + + if (setjmp(InlineAsm_assemblererror) == 0) { + while (tk == TK_IDENTIFIER && (directive = InlineAsm_IsDirective(AssemblerType_1))) { + InlineAsm_ProcessDirective(directive); + + if (tk == ';' || tk == TK_EOL) { + CPrep_TokenStreamFlush(); + tk = lex(); + } else { + InlineAsm_SyntaxError(CErrorStr113); + } + + if (directive == IADirective_FrAlloc) { + requires_frame = 1; + break; + } else if (directive == IADirective_NoFrAlloc) { + user_responsible_for_frame = 1; + break; + } + } + } + + in_assembler = 0; + cprep_eoltokens = save_eoltokens; +} + +static void FuncAsm_AddEntryPoint(Statement *stmt, PCodeBlock *block) { + EntryPoint *ep; + IAEntryPoint *ia_ep; + + ia_ep = (IAEntryPoint *) stmt->expr; + ep = lalloc(sizeof(EntryPoint)); + memclrw(ep, sizeof(EntryPoint)); + + ep->object = ia_ep->x8; + ep->block = block; + + *entrypoints_tail = ep; + entrypoints_tail = &ep->next; + + block->flags |= fPCBlockFlag8000; +} + +void Assembler(Object *func) { + PCodeBlock *block; + Statement *stmt; + Boolean flag17; + Boolean flag16; + char *name; + InlineAsm *ia; + Boolean save_unusedvar; + Boolean save_unusedarg; + + flag17 = 0; + flag16 = 0; + + init_endian(); + init_stack_globals(func); + memclrw(asm_alloc_flags, sizeof(asm_alloc_flags)); + fralloc_parameter_area_size = 0; + user_responsible_for_frame = 0; + assembledinstructions = 0; + + entrypoints_head = NULL; + entrypoints_tail = &entrypoints_head; + + stmt = curstmt; + + if (func && func->name) + PrintProgressFunction(func->name->name); + + CodeGen_InitialSanityCheck(); + + if (func->qual & Q_INLINE) + PPCError_Warning(PPCErrorStr173); + + CheckCLabels(); + + if (fatalerrors) + return; + + if (copts.filesyminfo) + CPrep_SetSourceFile(&cparser_fileoffset); + + sm_section = SECT_TEXT; + + initpcode(); + + pclabel(prologue = makepcblock(), makepclabel()); + pclabel(block = makepcblock(), makepclabel()); + pcbranch(prologue, block->labels); + + resetTOCvarinfo(); + InlineAsm_InitializePPC(); + FuncAsm_PreScanDirectives(); + + disable_optimizer = 1; + + init_registers(); + assign_arguments_to_memory(func, 0, 0); + init_frame_sizes(0); + + if (copts.debuglisting) + DumpIR(stmt, func); + + cprep_eoltokens = 1; + in_assembler = 1; + + save_unusedvar = copts.warn_unusedvar; + save_unusedarg = copts.warn_unusedarg; + copts.warn_unusedvar = 0; + copts.warn_unusedarg = 0; + + InlineAsm_ScanFunction('}'); + + expandTOCreferences(&stmt->next); + + if (!anyerrors && copts.debuglisting) + DumpIR(stmt, func); + + in_assembler = 0; + cprep_eoltokens = 0; + + name = CMangler_GetLinkName(func)->name; + func->flags |= OBJECT_DEFINED; + + if (fralloc_parameter_area_size) + update_out_param_size(fralloc_parameter_area_size); + if (!user_responsible_for_frame) + process_arguments(move_assigned_argument, 0); + + branch_label(makepclabel()); + assign_labels(stmt->next); + + copts.warn_unusedvar = save_unusedvar; + copts.warn_unusedarg = save_unusedarg; + + for (stmt = stmt->next; stmt; stmt = stmt->next) { + current_statement = stmt; + switch (stmt->type) { + case ST_ASM: + if ((ia = (InlineAsm *) stmt->expr)) { + if (ia->flags & IAFlag1) { + if (ia->opcode == IADirective_Entry) { + branch_label(makepclabel()); + FuncAsm_AddEntryPoint(stmt, pclastblock); + } else if (ia->opcode == IADirective_FrFree) { + if (flag16) + PPCError_Error(PPCErrorStr188); + else + flag16 = 1; + + asm_alloc_flags[3] = 1; + asm_alloc_flags[4] = 1; + branch_label(makepclabel()); + + epilogue = pclastblock; + pclastblock->flags |= fIsEpilogue; + + CheckCLabels(); + if (fatalerrors) + return; + + pccomputepredecessors(); + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] INITIAL CODE"); + colorinstructions(func); + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER REGISTER COLORING"); + compute_frame_sizes(); + generate_prologue(prologue, 0); + epilogue = pclastblock; + generate_epilogue(epilogue, 0); + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER PROLOGUE/EPILOGUE CREATION"); + + flag17 = 1; + } + } else { + branch_label(makepclabel()); + asm_alloc_flags[6] = 0; + asm_alloc_flags[7] = 0; + InlineAsm_TranslateIRtoPCode(stmt); + asm_alloc_flags[4] = 0; + } + } + break; + case ST_LABEL: + if (!stmt->label->pclabel->resolved) + branch_label(stmt->label->pclabel); + break; + default: + CError_FATAL(525); + } + } + + current_statement = NULL; + + if (fatalerrors) + return; + CheckCLabels(); + if (fatalerrors) + return; + + if (!flag17) { + branch_label(makepclabel()); + + epilogue = pclastblock; + pclastblock->flags |= fIsEpilogue; + + pccomputepredecessors(); + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] INITIAL CODE"); + + if (!asm_alloc_flags[1]) { + colorinstructions(func); + if (fatalerrors) + return; + + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER REGISTER COLORING"); + } + + compute_frame_sizes(); + if (asm_alloc_flags[1]) + no_frame_for_asm(); + + if (fatalerrors) + return; + + if (!asm_alloc_flags[1]) { + generate_prologue(prologue, 0); + generate_epilogue(epilogue, !asm_alloc_flags[6] && !asm_alloc_flags[7]); + } + + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER PROLOGUE/EPILOGUE CREATION"); + } + + if (fatalerrors) + return; + + if (!asm_alloc_flags[1] && needs_frame()) { + if (asm_alloc_flags[3]) { + if (!asm_alloc_flags[5] || !asm_alloc_flags[6]) + PPCError_Warning(PPCErrorStr187, "blr"); + if (asm_alloc_flags[8]) + PPCError_Warning(PPCErrorStr186); + } else { + PPCError_Warning(PPCErrorStr185, "blr"); + } + } + + func->section = sm_section; + + if (copts.filesyminfo) + symdeclend = CPrep_GetFileOffsetInfo(&cparser_fileoffset); + + copts.peephole = 0; + if (pic_base_label) + pic_base_pcodelabel = pic_base_label->pclabel; + assemblefunction(func, entrypoints_head); + + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "[FUNCTION-LEVEL ASM] FINAL CODE"); + + CFunc_WarnUnused(); +} + +void SetupAssembler(void) { +} + +void CleanupAssembler(void) { +} diff --git a/compiler_and_linker/BackEnd/PowerPC/InlineAssembler/GCCInlineAsm.c b/compiler_and_linker/BackEnd/PowerPC/InlineAssembler/GCCInlineAsm.c new file mode 100644 index 0000000..897df9b --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/InlineAssembler/GCCInlineAsm.c @@ -0,0 +1,230 @@ +#include "compiler/GCCInlineAsm.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/InlineAsm.h" +#include "compiler/objects.h" + +Statement *first_ST_ASM; +IALookupResult gcc_name_list[20]; +int gcc_name_list_index; + +void InlineAsm_SkipComment(void) { + while (1) { + if (tk != '/') + break; + if (lookahead() != '*') + break; + + tk = lex(); + while (!((tk = lex()) == '*' && (tk = lex()) == '/')) { + // nothing + } + tk = lex(); + } +} + +static char gcc_parse_attribute(void) { + char ch; + + while (tk == TK_EOL) + tk = lex(); + + if (tk != '"') + CError_Error(CErrorStr105); + + while ((tk = lex()) != TK_IDENTIFIER) { + // nothing + } + + ch = tkidentifier->name[0]; + + if ((tk = lex()) != '"') + CError_Error(CErrorStr105); + tk = lex(); + + return ch; +} + +static void gcc_parse_name(Boolean flag, char attribute) { + IALookupResult *nameentry; + ENode *expr; + Object *tempobj; + ENode *tempexpr; + Statement *stmt; + + while (tk == TK_EOL) + tk = lex(); + + if (tk != '(') + CError_Error(CErrorStr114); + + tk = lex(); + + if (flag) { + if (tk != TK_IDENTIFIER) + CError_Error(CErrorStr105); + + InlineAsm_LookupSymbol(tkidentifier, &gcc_name_list[++gcc_name_list_index]); + if (gcc_name_list[gcc_name_list_index].object && gcc_name_list[gcc_name_list_index].object->u.var.info) + gcc_name_list[gcc_name_list_index].object->u.var.info->used = 1; + + tk = lex(); + } else { + in_assembler = 0; + cprep_nostring = 0; + nameentry = &gcc_name_list[++gcc_name_list_index]; + + expr = expression(); + if (attribute == 'i' || attribute == 'I') { + if (!ENODE_IS(expr, EINTCONST)) + CError_Error(CErrorStr144); + nameentry->value = CInt64_GetULong(&expr->data.intval); + nameentry->has_value = 1; + } else { + tempobj = create_temp_object(expr->rtype); + tempexpr = create_objectnode(tempobj); + if (tempobj->u.var.info) + tempobj->u.var.info->used = 1; + expr = makediadicnode(tempexpr, expr, EASS); + + stmt = CFunc_InsertBeforeStatement(ST_EXPRESSION, first_ST_ASM); + first_ST_ASM = stmt->next; + if (!first_ST_ASM->next) + curstmt = first_ST_ASM; + stmt->expr = expr; + + nameentry->name = tempobj->name; + nameentry->object = tempobj; + nameentry->label = NULL; + nameentry->type = NULL; + nameentry->has_value = 0; + } + } + + cprep_nostring = 1; + in_assembler = 1; + + if (tk != ')') + CError_Error(CErrorStr115); + tk = lex(); +} + +static void gcc_parse_expression(Boolean flag) { + while (1) { + gcc_parse_name(flag, gcc_parse_attribute()); + if (tk != ',') + break; + tk = lex(); + } +} + +static void gcc_parse_input(void) { + if (tk == ':') { + if ((tk = lex()) == ':' || tk == ')' || tk == '}') + return; + gcc_parse_expression(0); + } +} + +static void gcc_parse_output(void) { + if (tk == ':') { + if ((tk = lex()) == ':' || tk == ')' || tk == '}') + return; + gcc_parse_expression(1); + } +} + +static void gcc_parse_killed(void) { + if (tk == ':') { + while (1) { + if ((tk = lex()) != '"') + return; + + tk = lex(); + while (1) { + if (tk == '"') { + if (lookahead() == ',') { + tk = lex(); + break; + } + tk = lex(); + return; + } + tk = lex(); + } + } + } +} + +static void gcc_replace_arg_st_asm(Statement *stmt) { + InlineAsm *ia; + int i; + IAOperand *op; + short effect; + short rclass; + SInt32 num; + + if ((ia = (InlineAsm *) stmt->expr)) { + for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { + switch (op->type) { + case IAOpnd_Imm: + case IAOpnd_Reg: + case IAOpnd_3: + case IAOpnd_4: + case IAOpnd_Lab: + break; + + case IAOpnd_6: + if (op->u.unk6.unk4 == 2) { + effect = op->u.unk6.effect; + rclass = op->u.unk6.rclass; + num = op->u.unk6.num; + op->type = IAOpnd_Reg; + op->u.reg.effect = effect; + op->u.reg.rclass = rclass; + op->u.reg.object = NULL; + if (num <= gcc_name_list_index) + op->u.reg.object = gcc_name_list[num].object; + else + CError_Error(CErrorStr144); + op->u.reg.num = 0; + } else { + CError_FATAL(365); + } + break; + + case IAOpnd_7: + op->type = IAOpnd_Imm; + op->u.imm.value = gcc_name_list[op->u.unk7.value].value; + break; + } + } + } +} + +static void gcc_replace_arg(void) { + Statement *stmt; + + for (stmt = first_ST_ASM; stmt; stmt = stmt->next) { + if (stmt->type == ST_ASM) + gcc_replace_arg_st_asm(stmt); + } +} + +void InlineAsm_gcc_parse(void) { + gcc_name_list_index = -1; + cprep_eoltokens = 0; + + if (tk == TK_EOL) + tk = lex(); + + gcc_parse_output(); + gcc_parse_input(); + gcc_parse_killed(); + gcc_replace_arg(); +} diff --git a/compiler_and_linker/BackEnd/PowerPC/InlineAssembler/InlineAsm.c b/compiler_and_linker/BackEnd/PowerPC/InlineAssembler/InlineAsm.c new file mode 100644 index 0000000..46a95d2 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/InlineAssembler/InlineAsm.c @@ -0,0 +1,680 @@ +#include "compiler/InlineAsm.h" +#include "compiler/InlineAsmPPC.h" +#include "compiler/GCCInlineAsm.h" +#include "compiler/CompilerTools.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInit.h" +#include "compiler/CInline.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/COptimizer.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/PCode.h" +#include "compiler/Registers.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/types.h" + +int allow_array_expressions = 1; + +int backtracking; +jmp_buf backtrack; +jmp_buf InlineAsm_assemblererror; +static int ASMstmtnb; + +void AssemblerError(void) { + longjmp(InlineAsm_assemblererror, 1); +} + +void InlineAsm_SyntaxError(short code) { + if (backtracking) + longjmp(backtrack, 1); + + if (tk == TK_EOL || tk == ';') + code = CErrorStr112; + CError_Error(code); +} + +CLabel *InlineAsm_LookupLabel(HashNameNode *name) { + CLabel *label; + + for (label = Labels; label; label = label->next) { + if (name == label->name) + break; + } + + return label; +} + +CLabel *InlineAsm_DeclareLabel(HashNameNode *name) { + CLabel *label = newlabel(); + label->name = name; + label->next = Labels; + Labels = label; + return label; +} + +static void InlineAsm_DefineLabel(HashNameNode *name) { + CLabel *label; + Statement *stmt; + + label = InlineAsm_LookupLabel(name); + if (!label) { + label = InlineAsm_DeclareLabel(name); + } else { + if (label->stmt) + CError_Error(CErrorStr171, name->name); + } + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = label; + label->stmt = stmt; +} + +Boolean InlineAsm_LookupSymbolOrTag(HashNameNode *name, IALookupResult *result, Boolean allow_tag) { + ObjBase *obj; + NameSpace *nspace; + NameSpaceObjectList *list; + + result->name = name; + result->object = NULL; + result->label = NULL; + result->type = NULL; + result->has_value = 0; + + if ((result->label = InlineAsm_LookupLabel(name))) + return 1; + + for (nspace = cscope_current; nspace; nspace = nspace->parent) { + if ((list = CScope_FindName(nspace, name))) { + obj = list->object; + switch (obj->otype) { + case OT_ENUMCONST: + result->has_value = 1; + result->value = OBJ_ENUM_CONST(list->object)->val.lo; + return 1; + case OT_OBJECT: + if (OBJECT(obj)->datatype == DABSOLUTE) { + result->has_value = 1; + result->value = OBJECT(obj)->u.address; + } else { + if (OBJECT(obj)->datatype == DDATA && (OBJECT(obj)->qual & Q_INLINE_DATA)) + CInit_ExportConst(OBJECT(obj)); + result->object = OBJECT(obj); + } + return 1; + case OT_TYPE: + result->type = OBJ_TYPE(obj)->type; + return 1; + case OT_TYPETAG: + if (allow_tag) { + result->type = OBJ_TYPE_TAG(obj)->type; + return 1; + } + case OT_NAMESPACE: + case OT_MEMBERVAR: + return 0; + default: + CError_FATAL(245); + } + } + } + + return 0; +} + +Boolean InlineAsm_LookupSymbol(HashNameNode *name, IALookupResult *result) { + return InlineAsm_LookupSymbolOrTag(name, result, 0); +} + +static ObjMemberVar *isclassmember(TypeClass *tclass, HashNameNode *name) { + NameSpaceObjectList *list; + + list = CScope_FindName(tclass->nspace, name); + return (list && list->object->otype == OT_MEMBERVAR) ? OBJ_MEMBER_VAR(list->object) : NULL; +} + +SInt32 InlineAsm_StructMemberOffset(Type *type) { + StructMember *member; + ObjMemberVar *ivar; + SInt32 offset = 0; + + do { + if (IS_TYPE_STRUCT(type)) { + tk = lex(); + if (tk != TK_IDENTIFIER) + InlineAsm_SyntaxError(CErrorStr107); + member = ismember(TYPE_STRUCT(type), tkidentifier); + if (!member) + CError_Error(CErrorStr150, tkidentifier->name); + offset += member->offset; + type = member->type; + tk = lex(); + } else if (IS_TYPE_CLASS(type)) { + tk = lex(); + if (tk != TK_IDENTIFIER) + InlineAsm_SyntaxError(CErrorStr107); + ivar = isclassmember(TYPE_CLASS(type), tkidentifier); + if (!ivar) + CError_Error(CErrorStr150, tkidentifier->name); + offset += ivar->offset; + type = ivar->type; + tk = lex(); + } else { + CError_Error(CErrorStr149); + } + } while (tk == '.'); + + return offset; +} + +SInt32 InlineAsm_StructArrayMemberOffset(Type *type) { + StructMember *member; + ObjMemberVar *ivar; + SInt32 offset = 0; + + do { + if (tk == '.') { + if (IS_TYPE_STRUCT(type)) { + tk = lex(); + if (tk != TK_IDENTIFIER) + InlineAsm_SyntaxError(CErrorStr107); + member = ismember(TYPE_STRUCT(type), tkidentifier); + if (!member) + CError_Error(CErrorStr150, tkidentifier->name); + offset += member->offset; + type = member->type; + tk = lex(); + } else if (IS_TYPE_CLASS(type)) { + tk = lex(); + if (tk != TK_IDENTIFIER) + InlineAsm_SyntaxError(CErrorStr107); + ivar = isclassmember(TYPE_CLASS(type), tkidentifier); + if (!ivar) + CError_Error(CErrorStr150, tkidentifier->name); + offset += ivar->offset; + type = ivar->type; + tk = lex(); + } else { + CError_Error(CErrorStr149); + } + } else { + if (IS_TYPE_ARRAY(type)) { + type = TPTR_TARGET(type); + tk = lex(); + offset += type->size * InlineAsm_ConstantExpression(); + if (tk != ']') + InlineAsm_SyntaxError(125); + tk = lex(); + } else { + CError_Error(CErrorStr148); + } + } + } while (tk == '.' || tk == '['); + + return offset; +} + +SInt32 InlineAsm_StructPointerMemberOffset(Type *type) { + StructMember *member; + ObjMemberVar *ivar; + SInt32 offset; + + tk = lex(); + if (tk != TK_IDENTIFIER) + InlineAsm_SyntaxError(107); + + if (IS_TYPE_STRUCT(type)) { + member = ismember(TYPE_STRUCT(type), tkidentifier); + if (!member) + CError_Error(CErrorStr150, tkidentifier->name); + offset = member->offset; + type = member->type; + } else { + ivar = isclassmember(TYPE_CLASS(type), tkidentifier); + if (!ivar) + CError_Error(CErrorStr150, tkidentifier->name); + offset = ivar->offset; + type = ivar->type; + } + + tk = lex(); + if (tk == '.' || tk == '[') + offset += InlineAsm_StructArrayMemberOffset(type); + + return offset; +} + +static SInt32 DiadicOperator(SInt32 left, short op, SInt32 right) { + CInt64 left64; + CInt64 right64; + CInt64_SetLong(&left64, left); + CInt64_SetLong(&right64, right); + right64 = CMach_CalcIntDiadic(TYPE(&stsignedint), left64, op, right64); + return CInt64_GetULong(&right64); +} + +static SInt32 PrimaryExpression(void) { + IALookupResult result; + SInt32 value; + + switch (tk) { + case TK_IDENTIFIER: + if (InlineAsm_LookupSymbol(tkidentifier, &result)) { + if (result.has_value) { + tk = lex(); + return result.value; + } + + if (result.type && (IS_TYPE_STRUCT(result.type) || IS_TYPE_CLASS(result.type))) { + tk = lex(); + if (tk != '.') + InlineAsm_SyntaxError(120); + if (allow_array_expressions) + return InlineAsm_StructArrayMemberOffset(result.type); + else + return InlineAsm_StructMemberOffset(result.type); + } else { + InlineAsm_SyntaxError(124); + } + } else { + InlineAsm_SyntaxError(124); + } + break; + case TK_INTCONST: + value = tkintconst.lo; + tk = lex(); + return value; + case TK_SIZEOF: + return scansizeof(); + case '+': + tk = lex(); + return PrimaryExpression(); + case '-': + tk = lex(); + return -PrimaryExpression(); + case '!': + tk = lex(); + return PrimaryExpression() == 0; + case '~': + tk = lex(); + return ~PrimaryExpression(); + case '(': + tk = lex(); + value = InlineAsm_ConstantExpression(); + if (tk != ')') + InlineAsm_SyntaxError(115); + tk = lex(); + return value; + default: + InlineAsm_SyntaxError(120); + } + + return 0; +} + +static SInt32 ConstantExpressionTail(SInt32 value) { + SInt32 right; + short left_token; + short right_prec; + + while (1) { + left_token = tk; + tk = lex(); + right = PrimaryExpression(); + + right_prec = GetPrec(tk); + if (right_prec == 0) + return DiadicOperator(value, left_token, right); + + if (GetPrec(left_token) >= right_prec) { + value = DiadicOperator(value, left_token, right); + } else { + value = DiadicOperator(value, left_token, ConstantExpressionTail(right)); + if (GetPrec(tk) == 0) + return value; + } + } +} + +SInt32 InlineAsm_ConstantExpression(void) { + SInt32 value = PrimaryExpression(); + + if (GetPrec(tk) == 0) + return value; + else + return ConstantExpressionTail(value); +} + +HashNameNode *MakeLocalLabel(CInt64 num) { + char buf[80]; + sprintf(buf, "@%i_%i", ASMstmtnb, CInt64_GetULong(&num)); + return GetHashNameNodeExport(buf); +} + +static void ScanOptionalLabel(void) { + if (tk == TK_INTCONST) { + if (lookahead() == ':') { + InlineAsm_DefineLabel(MakeLocalLabel(tkintconst)); + tk = lex(); + tk = lex(); + } + } else { + if (tkidentifier->name[0] == '@') { + InlineAsm_DefineLabel(tkidentifier); + tk = lex(); + if (tk == ':') + tk = lex(); + } else { + HashNameNode *name = tkidentifier; + short t = lookahead(); + tkidentifier = name; + if (t == ':') { + InlineAsm_DefineLabel(name); + tk = lex(); + tk = lex(); + } + } + } +} + +static void ScanStatements(volatile short endToken, AssemblerType mode) { + if (setjmp(InlineAsm_assemblererror)) { + while (tk != TK_EOL && tk != endToken && tk != '}' && tk) + tk = lex(); + if (tk == ';' || tk == TK_EOL) + tk = lex(); + } else { + InlineAsm_Initialize(mode); + InlineAsm_gccmode = 0; + if (setjmp(InlineAsm_assemblererror)) { + while (tk != ';' && tk != TK_EOL && tk != endToken && tk != '}' && tk) + tk = lex(); + if (tk == ';' || tk == TK_EOL) + tk = lex(); + } + + while (tk && tk != endToken) { + backtracking = 0; + sourceoffset = CPrep_GetFileOffsetInfo(&cparser_fileoffset); + if (tk == '"') { + if (InlineAsm_gccmode) { + tk = lex(); + InlineAsm_gcc_parse(); + } else { + InlineAsm_gccmode = 1; + copts.cplusplus = 0; + copts.asmpoundcomment = 1; + tk = lex(); + } + } + + if (tk == '.') { + InlineAsm_ScanAssemblyDirective(); + } else if (tk == TK_IDENTIFIER) { + ScanOptionalLabel(); + if (tk == TK_IDENTIFIER) + InlineAsm_ScanAssemblyInstruction(); + } else if (tk == TK_INTCONST) { + ScanOptionalLabel(); + if (tk == TK_IDENTIFIER) + InlineAsm_ScanAssemblyInstruction(); + } + + if (InlineAsm_gccmode && tk == '"') { + tk = lex(); + InlineAsm_gcc_parse(); + } + + if (tk == ';' || tk == TK_EOL) { + CPrep_TokenStreamFlush(); + tk = lex(); + } else if (tk != endToken) { + if (endToken == ')') + CError_Error(CErrorStr115); + else + CError_Error(CErrorStr113); + } + } + } +} + +void InlineAsm_ScanStatements(volatile short endToken) { + ScanStatements(endToken, AssemblerType_0); +} + +void InlineAsm_ScanFunction(volatile short endToken) { + ScanStatements(endToken, AssemblerType_1); +} + +void InlineAsm_Assemble(void) { + short token = (tk == '(') ? ')' : '}'; + char save_pc = copts.asmpoundcomment; + char save_cpp = copts.cplusplus; + + cprep_nostring = 1; + CFunc_AppendStatement(ST_NOP); + first_ST_ASM = curstmt; + ASMstmtnb++; + + cprep_eoltokens = 1; + in_assembler = 1; + tk = lex(); + InlineAsm_ScanStatements(token); + in_assembler = 0; + cprep_eoltokens = 0; + cprep_nostring = 0; + + copts.asmpoundcomment = save_pc; + copts.cplusplus = save_cpp; +} + +void InlineAsm_PackAsmStatement(Statement *stmt, Statement *first, void **output, SInt32 *outsize) { + InlineAsm *src; + InlineAsm *dest; + IAOperand *op; + SInt32 i; + SInt32 size; + + src = (InlineAsm *) stmt->expr; + size = sizeof(InlineAsm) + sizeof(IAOperand) * src->argcount; + dest = galloc(size); + memcpy(dest, src, size); + + for (i = 0, op = dest->args; i < dest->argcount; i++, op++) { + switch (op->type) { + case IAOpnd_0: + break; + case IAOpnd_Reg: + case IAOpnd_4: + op->u.reg.object = (Object *) CInline_GetLocalID(op->u.reg.object); + break; + case IAOpnd_Lab: + op->u.lab.label = (CLabel *) CInline_GetStatementNumber(first, op->u.lab.label->stmt); + break; + case IAOpnd_LabDiff: + op->u.labdiff.label1 = (CLabel *) CInline_GetStatementNumber(first, op->u.labdiff.label1->stmt); + op->u.labdiff.label2 = (CLabel *) CInline_GetStatementNumber(first, op->u.labdiff.label2->stmt); + break; + } + } + + *output = dest; + *outsize = size; +} + +void InlineAsm_UnpackAsmStatement(Statement *stmt, CLabel **labelArray, Boolean flag, void *data, SInt32 size) { + InlineAsm *ia; + IAOperand *op; + SInt32 i; + + ia = galloc(size); + memcpy(ia, data, size); + + for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { + switch (op->type) { + case IAOpnd_0: + break; + case IAOpnd_Reg: + case IAOpnd_4: + op->u.reg.object = CInline_GetLocalObj((SInt32) op->u.reg.object, flag); + break; + case IAOpnd_Lab: + op->u.lab.label = labelArray[(SInt16) op->u.lab.label]; + break; + case IAOpnd_LabDiff: + op->u.labdiff.label1 = labelArray[(SInt16) op->u.labdiff.label1]; + op->u.labdiff.label2 = labelArray[(SInt16) op->u.labdiff.label2]; + break; + } + } + + stmt->expr = (ENode *) ia; +} + +void InlineAsm_CheckLocalUsage(Statement *stmt) { + InlineAsm *ia = (InlineAsm *) stmt->expr; + IAOperand *op; + SInt32 i; + + for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { + switch (op->type) { + case IAOpnd_Reg: + if (op->u.reg.object) + SetVarUsage(op->u.reg.object, 0); + break; + case IAOpnd_4: + SetVarUsage(op->u.obj.obj, 1); + break; + } + } +} + +CLabel *InlineAsm_GetReferencedLabel(Statement *stmt) { + InlineAsm *ia = (InlineAsm *) stmt->expr; + IAOperand *op; + SInt32 i; + + for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { + if (op->type == IAOpnd_Lab) + return op->u.lab.label; + if (op->type == IAOpnd_LabDiff) + return op->u.labdiff.label1; + } + + return NULL; +} + +CLabel *InlineAsm_GetReferencedLabel2(Statement *stmt) { + InlineAsm *ia = (InlineAsm *) stmt->expr; + IAOperand *op; + SInt32 i; + + for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { + if (op->type == IAOpnd_LabDiff) + return op->u.labdiff.label2; + } + + return NULL; +} + +Object *InlineAsm_GetObjectOffset(InlineAsm *ia, SInt32 index, SInt32 *offset) { + IAOperand *op; + SInt32 i; + SInt32 counter; + + for (i = 0, counter = 0, op = ia->args; i < ia->argcount; i++, op++) { + if (op->type == IAOpnd_3) { + if (counter++ == index) { + *offset = ((intptr_t) &op->u.obj.obj) - ((intptr_t) ia); + return op->u.obj.obj; + } + } + } + + return NULL; +} + +char *InlineAsm_DumpStatement(Statement *stmt) { + static char buffer[1024]; + InlineAsm *ia; + IAOperand *arg; + int i; + char ch; + SInt32 offset; + + ia = (InlineAsm *) stmt->expr; + + strcpy(buffer, "\""); + strcat(buffer, InlineAsm_GetMnemonic(ia)); + strcat(buffer, "\""); + + for (i = 0, arg = ia->args; i < ia->argcount; i++, arg++) { + char argbuf[1024]; + + switch (arg->type) { + case IAOpnd_Imm: + sprintf(argbuf, " imm(%ld)", arg->u.imm.value); + break; + case IAOpnd_Reg: + ch = ' '; + if (arg->u.reg.effect & EffectWrite) { + if (arg->u.reg.effect & EffectRead) + ch = '+'; + else + ch = '='; + } else { + if (!(arg->u.reg.effect & EffectRead)) + ch = '0'; + } + + if (arg->u.reg.object) { + sprintf(argbuf, + "%creg(%s)", + ch, + arg->u.reg.object->name->name); + } else { + sprintf(argbuf, + "%creg(%s%d)", + ch, + register_class_name[arg->u.reg.rclass], + arg->u.reg.num); + } + break; + + case IAOpnd_3: + case IAOpnd_4: + if (arg->u.obj.offset > 0) + sprintf(argbuf, " obj(%s+%ld)", arg->u.obj.obj->name->name, arg->u.obj.offset); + else if (arg->u.obj.offset < 0) + sprintf(argbuf, " obj(%s-%ld)", arg->u.obj.obj->name->name, -arg->u.obj.offset); + else + sprintf(argbuf, " obj(%s)", arg->u.obj.obj->name->name); + break; + + case IAOpnd_Lab: + sprintf(argbuf, " lab(%s)", arg->u.lab.label->uniquename->name); + break; + + case IAOpnd_LabDiff: + offset = !arg->negated ? 0 : arg->u.labdiff.offset; + sprintf(argbuf, + " labdiff(%s-%s%c%d)", + arg->u.labdiff.label1->uniquename->name, + arg->u.labdiff.label2->uniquename->name, + (arg->negated == 1) ? '-' : '+', + offset + ); + break; + } + + strcat(buffer, argbuf); + } + + return buffer; +} diff --git a/compiler_and_linker/BackEnd/PowerPC/InlineAssembler/InlineAsmPPC.c b/compiler_and_linker/BackEnd/PowerPC/InlineAssembler/InlineAsmPPC.c new file mode 100644 index 0000000..464f9f9 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/InlineAssembler/InlineAsmPPC.c @@ -0,0 +1,2586 @@ +#include "compiler/InlineAsmPPC.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CInt64.h" +#include "compiler/CFunc.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/Alias.h" +#include "compiler/CodeGen.h" +#include "compiler/CodeGenOptPPC.h" +#include "compiler/CompilerTools.h" +#include "compiler/Exceptions.h" +#include "compiler/FuncLevelAsmPPC.h" +#include "compiler/InlineAsm.h" +#include "compiler/InlineAsmMnemonicsPPC.h" +#include "compiler/InlineAsmRegisters.h" +#include "compiler/InlineAsmRegistersPPC.h" +#include "compiler/PCode.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/PPCError.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/TOC.h" +#include "compiler/objects.h" + +char asm_alloc_flags[10]; +Section sm_section; +UInt32 cpu; +SInt32 fralloc_parameter_area_size; +Boolean user_responsible_for_frame; +Boolean supports_hardware_fpu; +UInt32 assembledinstructions; +AssemblerType assembler_type; +char volatileasm; +Boolean InlineAsm_gccmode; +Boolean InlineAsm_labelref; +CLabel *pic_base_label; + +// forward decls +static SInt32 InlineAsm_ConstantExpressionPPC(SInt32 value); +static Object *isvariableoperand(void); +static Object *isregisterstructpointeroperand(void); +static void registeroperand(IAOperand *op, char rclass, short effect); +static void DiadicOperatorPPC(IAExpr *left, short token, IAExpr *right); +static void InlineAsm_ExpressionPPC(IAExpr *expr, SInt32 value); +static void savepicbase(short reg, HashNameNode *name); + +CW_INLINE SInt32 ExtractValue(CInt64 value) { + return (SInt32) CInt64_GetULong(&value); +} + +static void IllegalObjectOperator(HashNameNode *name1, HashNameNode *name2, short token) { + char *opstr; + switch (token) { + case '*': opstr = "*"; break; + case '/': opstr = "/"; break; + case '%': opstr = "%"; break; + case '+': opstr = "+"; break; + case '-': opstr = "-"; break; + case TK_SHL: opstr = "<<"; break; + case TK_SHR: opstr = ">>"; break; + case '<': opstr = "<"; break; + case '>': opstr = ">"; break; + // bug? these two seem swapped + case TK_LESS_EQUAL: opstr = ">="; break; + case TK_GREATER_EQUAL: opstr = "<="; break; + case TK_LOGICAL_EQ: opstr = "=="; break; + case TK_LOGICAL_NE: opstr = "!="; break; + case '&': opstr = "&"; break; + case '^': opstr = "^"; break; + case '|': opstr = "|"; break; + case TK_LOGICAL_AND: opstr = "&&"; break; + case TK_LOGICAL_OR: opstr = "||"; break; + default: opstr = "???"; + } + + if (!name2) { + PPCError_Error(PPCErrorStr119, opstr, name1->name); + } else if (!name1) { + PPCError_Error(PPCErrorStr120, opstr, name2->name); + } else { + PPCError_Error(PPCErrorStr118, name1->name, opstr, name2->name); + } +} + +static void IllegalObjectInConst(IAExpr *expr) { + if (expr->xC) { + PPCError_Error(PPCErrorStr122, expr->xC->name->name); + } else if (expr->object) { + PPCError_Error(PPCErrorStr122, expr->object->name->name); + } else if (expr->label) { + PPCError_Error(PPCErrorStr166, expr->label->name->name); + } +} + +static void NotInRegisterError(char *name, char rclass) { + PPCError_Error(PPCErrorStr167, name, register_class_name[rclass]); +} + +static int isregisteroperand(char rclass) { + IARegister *reg; + + return (tk == TK_IDENTIFIER && (reg = InlineAsm_LookupRegisterPPCName(tkidentifier)) && reg->rclass == rclass); +} + +static SInt32 getcroperand(char rclass) { + SInt32 value; + IARegister *reg; + + value = 0; + if (tk == TK_IDENTIFIER && (reg = InlineAsm_LookupRegisterPPCName(tkidentifier)) && reg->rclass == rclass) { + value = reg->num; + } else { + PPCError_Error(PPCErrorStr167, tkidentifier->name); + } + + tk = lex(); + return value; +} + +static SInt32 getimmediateoperand(SInt32 minimum, SInt32 maximum) { + SInt32 value = InlineAsm_ConstantExpressionPPC(0); + if (value < minimum || value > maximum) + CError_Error(CErrorStr154); + return value; +} + +static void PrimaryExpressionPPC(IAExpr *expr, SInt32 value) { + Object *obj; + IALookupResult result; + IAExpr subexpr; + IAExprType type = IAExpr_0; + SInt32 v; + + switch (tk) { + case TK_IDENTIFIER: + if ((obj = isregisterstructpointeroperand())) { + tk = lex(); + InlineAsm_InitExpr5(expr, InlineAsm_StructPointerMemberOffset(TPTR_TARGET(obj->type))); + expr->object = obj; + return; + } + + if ((obj = isvariableoperand())) { + short reg; + InlineAsm_InitExpr5(expr, 0); + expr->xC = obj; + + if (obj->datatype == DLOCAL) + reg = 1; + else + reg = pic_base_reg; + + tk = lex(); + if (tk == '.' || tk == '[') { + InlineAsm_InitExpr5(&subexpr, InlineAsm_StructArrayMemberOffset(obj->type)); + DiadicOperatorPPC(expr, '+', &subexpr); + } + + if (tk == '+') { + tk = lex(); + InlineAsm_ExpressionPPC(&subexpr, value); + DiadicOperatorPPC(expr, '+', &subexpr); + } else if (tk == '-') { + tk = lex(); + InlineAsm_ExpressionPPC(&subexpr, value); + DiadicOperatorPPC(expr, '-', &subexpr); + } else if (!strcmp(tkidentifier->name, "@loword")) { + tk = lex(); + if (low_offset) { + InlineAsm_InitExpr5(&subexpr, low_offset); + DiadicOperatorPPC(expr, '+', &subexpr); + } + } else if (!strcmp(tkidentifier->name, "@hiword")) { + tk = lex(); + if (high_offset) { + InlineAsm_InitExpr5(&subexpr, high_offset); + DiadicOperatorPPC(expr, '+', &subexpr); + } + } + expr->reg = reg; + return; + } + + if (InlineAsm_LookupSymbolOrTag(tkidentifier, &result, 1)) { + if (result.has_value) { + tk = lex(); + InlineAsm_InitExpr5(expr, result.value); + return; + } + + if (result.type && (IS_TYPE_STRUCT(result.type) || IS_TYPE_CLASS(result.type))) { + tk = lex(); + if (tk != '.') + CError_Error(CErrorStr120); + + if (allow_array_expressions) { + InlineAsm_InitExpr5(expr, InlineAsm_StructArrayMemberOffset(result.type)); + return; + } + + InlineAsm_InitExpr5(expr, InlineAsm_StructMemberOffset(result.type)); + return; + } + + if (result.object && result.object->datatype == DABSOLUTE) { + tk = lex(); + InlineAsm_InitExpr5(expr, result.object->u.address); + return; + } + } else if (value) { + if (isregisteroperand(RegClass_CRFIELD)) { + InlineAsm_InitExpr5(expr, getcroperand(RegClass_CRFIELD)); + return; + } + if (isregisteroperand(RegClass_6)) { + InlineAsm_InitExpr5(expr, getcroperand(RegClass_6)); + return; + } + if (strlen(tkidentifier->name) == 6 && !strncmp(tkidentifier->name, "cr", 2) && tkidentifier->name[3] == '_') { + IARegister *reg; + char regname[4]; + regname[0] = tkidentifier->name[0]; + regname[1] = tkidentifier->name[1]; + regname[2] = tkidentifier->name[2]; + regname[3] = 0; + if ((reg = InlineAsm_LookupRegisterPPC(regname)) && reg->rclass == RegClass_CRFIELD) { + SInt32 v = reg->num * 4; + regname[0] = tkidentifier->name[4]; + regname[1] = tkidentifier->name[5]; + regname[2] = 0; + if ((reg = InlineAsm_LookupRegisterPPC(regname)) && reg->rclass == RegClass_6) { + tk = lex(); + InlineAsm_InitExpr5(expr, v + reg->num); + return; + } + } + } + } + + if (!strcmp("ha16", tkidentifier->name)) + type = IAExpr_8; + else if (!strcmp("hi16", tkidentifier->name)) + type = IAExpr_7; + else if (!strcmp("lo16", tkidentifier->name)) + type = IAExpr_6; + + if (type != IAExpr_0) { + tk = lex(); + if (tk == '(') { + SInt32 v; + tk = lex(); + PrimaryExpressionPPC(expr, value); + expr->type = type; + if (tk != ')') + CError_Error(CErrorStr115); + + tk = lex(); + if (InlineAsm_CheckExpr(expr)) { + expr->value = InlineAsm_GetExprValue(expr); + expr->type = IAExpr_5; + } + return; + } + + CError_Error(CErrorStr114); + } else { + if (!result.label) + result.label = InlineAsm_DeclareLabel(tkidentifier); + + InlineAsm_InitExpr5(expr, 0); + expr->flags |= IAFlag1; + expr->label = result.label; + tk = lex(); + return; + } + break; + + case TK_INTCONST: + v = CInt64_GetULong(&tkintconst); + tk = lex(); + InlineAsm_InitExpr5(expr, v); + return; + + case TK_SIZEOF: + InlineAsm_InitExpr5(expr, scansizeof()); + return; + + case '+': + tk = lex(); + PrimaryExpressionPPC(expr, value); + return; + + case '-': + tk = lex(); + PrimaryExpressionPPC(expr, value); + if (InlineAsm_CheckExpr(expr)) + expr->value = -expr->value; + else + CError_Error(CErrorStr124); + return; + + case '!': + tk = lex(); + PrimaryExpressionPPC(expr, value); + if (InlineAsm_CheckExpr(expr)) + expr->value = !expr->value; + else + CError_Error(CErrorStr124); + return; + + case '~': + tk = lex(); + PrimaryExpressionPPC(expr, value); + if (InlineAsm_CheckExpr(expr)) + expr->value = ~expr->value; + else + CError_Error(CErrorStr124); + return; + + case '(': + tk = lex(); + InlineAsm_ExpressionPPC(expr, value); + if (tk != ')') + CError_Error(CErrorStr115); + tk = lex(); + return; + + default: + CError_Error(CErrorStr120); + } + + InlineAsm_InitExpr5(expr, 0); +} + +static void DiadicOperatorPPC(IAExpr *left, short token, IAExpr *right) { + CInt64 leftval; + CInt64 rightval; + + CInt64_SetLong(&leftval, left->value); + CInt64_SetLong(&rightval, right->value); + rightval = CMach_CalcIntDiadic(TYPE(&stsignedint), leftval, token, rightval); + + if (left->xC) { + if (right->label) + PPCError_Error(PPCErrorStr124, left->xC->name->name, right->label->name->name); + + if (right->xC) { + if (left->x10) { + PPCError_Error(PPCErrorStr121, left->xC->name->name, left->x10->name->name, right->xC->name->name); + } else if (right->x10) { + PPCError_Error(PPCErrorStr121, left->xC->name->name, right->xC->name->name, right->x10->name->name); + } else if (token == '-') { + left->value = CInt64_GetULong(&rightval); + left->x10 = right->xC; + } else { + IllegalObjectOperator(left->xC->name, right->xC->name, token); + } + } else if (token == '-' || token == '+') { + left->value = CInt64_GetULong(&rightval); + } else { + IllegalObjectOperator(left->xC->name, NULL, token); + } + } else if (right->xC) { + if (right->label) + PPCError_Error(PPCErrorStr124, right->xC->name->name, right->label->name->name); + + if (token == '+') { + left->xC = right->xC; + left->x10 = right->x10; + left->value = CInt64_GetULong(&rightval); + } else { + IllegalObjectOperator(NULL, right->xC->name, token); + } + } else if (left->label) { + if (left->xC) + PPCError_Error(PPCErrorStr124, left->label->name->name, left->xC->name->name); + + if (right->label) { + if (left->x18) { + PPCError_Error(PPCErrorStr121, left->label->name->name, left->x18->name->name, right->label->name->name); + } else if (right->x18) { + PPCError_Error(PPCErrorStr121, left->label->name->name, right->label->name->name, right->x18->name->name); + } else if (token == '-') { + left->value = CInt64_GetULong(&rightval); + left->x18 = right->label; + } else { + IllegalObjectOperator(left->label->name, right->label->name, token); + } + } else if (token == '+' || token == '-') { + left->value = CInt64_GetULong(&rightval); + } else { + IllegalObjectOperator(NULL, left->label->name, token); + } + } else if (right->label) { + if (token == '+') { + left->label = right->label; + left->x18 = right->x18; + left->value = CInt64_GetULong(&rightval); + } else { + IllegalObjectOperator(NULL, right->label->name, token); + } + } else { + left->value = CInt64_GetULong(&rightval); + } + + left->flags |= right->flags; + if (left->type == IAOpnd_Lab) { + if (right->type != IAOpnd_Lab) + left->type = right->type; + } else { + if (right->type != IAOpnd_Lab && right->type != left->type) + PPCError_Error(PPCErrorStr126); + } +} + +static void ExpressionTailPPC(IAExpr *left, SInt32 value) { + IAExpr right; + short left_tk; + short right_prec; + + while (1) { + left_tk = tk; + tk = lex(); + + PrimaryExpressionPPC(&right, value); + right_prec = GetPrec(tk); + if (right_prec == 0) { + DiadicOperatorPPC(left, left_tk, &right); + break; + } + + if (GetPrec(left_tk) >= right_prec) { + DiadicOperatorPPC(left, left_tk, &right); + } else { + ExpressionTailPPC(&right, value); + DiadicOperatorPPC(left, left_tk, &right); + if (GetPrec(tk) == 0) + break; + } + } +} + +static void immediateoperand(IAOperand *op, SInt32 minval, SInt32 maxval) { + SInt32 value; + if (InlineAsm_gccmode && tk == '%') { + tk = lex(); + if (tk != TK_INTCONST) { + CError_Error(CErrorStr144); + } else { + CInt64 c = tkintconst; + value = CInt64_GetULong(&c); + if (value < 0) + CError_Error(CErrorStr144); + } + op->type = IAOpnd_7; + op->u.unk7.value = value; + op->u.unk7.unk1 = 1; + op->u.unk7.unk2 = 0; + op->u.unk7.unk3 = 0; + tk = lex(); + } else { + value = InlineAsm_ConstantExpressionPPC(0); + if (value < minval || value > maxval) + CError_Error(CErrorStr154); + op->type = IAOpnd_Imm; + op->u.imm.value = value; + } +} + +static SInt32 immediatevalue(IAOperand *op, SInt32 minval, SInt32 maxval) { + SInt32 value; + if (InlineAsm_gccmode && tk == '%') { + CError_Error(CErrorStr144); + return 0; + } else { + value = InlineAsm_ConstantExpressionPPC(0); + if (value < minval || value > maxval) + CError_Error(CErrorStr154); + op->type = IAOpnd_Imm; + op->u.imm.value = value; + return value; + } +} + +static void InlineAsm_ExpressionPPC(IAExpr *expr, SInt32 value) { + PrimaryExpressionPPC(expr, value); + if (GetPrec(tk)) + ExpressionTailPPC(expr, value); + if (GetPrec(tk)) + ExpressionTailPPC(expr, value); + + if (expr->type == IAExpr_5 && tk == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "@l")) { + expr->type = IAExpr_6; + tk = lex(); + } else if (!strcmp(tkidentifier->name, "@ha")) { + expr->type = IAExpr_8; + tk = lex(); + } else if (!strcmp(tkidentifier->name, "@h")) { + expr->type = IAExpr_7; + tk = lex(); + } + } +} + +static SInt32 InlineAsm_ConstantExpressionPPC(SInt32 value) { + IAExpr expr; + + InlineAsm_ExpressionPPC(&expr, value); + if (!InlineAsm_CheckExpr(&expr)) { + IllegalObjectInConst(&expr); + return 0; + } else { + return InlineAsm_GetExprValue(&expr); + } +} + +static SInt32 crbitoperand(void) { + SInt32 value = InlineAsm_ConstantExpressionPPC(1); + if (value < 0 || value > 31) + CError_Error(CErrorStr154); + return value; +} + +static void floatoperand(IAOperand *op, InlineAsm *ia, Type *type) { + Object *obj; + + obj = createfloatconstant(type, &tkfloatconst); + op[0].type = IAOpnd_Reg; + op[0].u.reg.rclass = RegClass_GPR; + op[0].u.reg.object = NULL; + op[0].u.reg.effect = EffectRead; + op[0].u.reg.num = pic_base_reg; + + ia->argcount++; + op[1].type = IAOpnd_4; + op[1].u.obj.obj = obj; + PPCError_Error(PPCErrorStr179); + op[1].u.obj.unk = IAExpr_2; + op[1].u.obj.offset = 0; + tk = lex(); +} + +static Object *isvariableoperand(void) { + IALookupResult result; + Object *obj; + + if (tk == TK_IDENTIFIER) { + InlineAsm_LookupSymbol(tkidentifier, &result); + if ((obj = result.object)) { + if (obj->datatype == DLOCAL) { + if (OBJECT_REG(obj)) + return NULL; + return obj; + } + + if (obj->datatype == DFUNC || obj->datatype == DVFUNC) + return obj; + + if (obj->datatype == DDATA) { + createIndirect(obj, 0, 0); + return obj; + } + } + } + + return NULL; +} + +static Object *isregisterstructpointeroperand(void) { + IALookupResult result; + Object *obj; + + if (tk != TK_IDENTIFIER) + return NULL; + + InlineAsm_LookupSymbol(tkidentifier, &result); + if ((obj = result.object)) { + if (obj->datatype != DLOCAL) + return NULL; + if (!OBJECT_REG(obj) && !is_register_object(obj)) + return NULL; + if (!IS_TYPE_POINTER(obj->type)) + return NULL; + if (!IS_TYPE_STRUCT(TPTR_TARGET(obj->type)) && !IS_TYPE_CLASS(TPTR_TARGET(obj->type))) + return NULL; + return obj; + } + + return NULL; +} + +static void memoryoperand(IAOperand *op, InlineAsm *ia, Boolean flag, short effect) { + IAExpr expr; + + InlineAsm_ExpressionPPC(&expr, 0); + if (expr.object) { + if (!flag) + CError_Error(CErrorStr155); + if (expr.xC) + PPCError_Error(PPCErrorStr122, expr.xC); + + op[0].type = IAOpnd_Reg; + op[0].u.reg.rclass = RegClass_GPR; + op[0].u.reg.object = expr.object; + op[0].u.reg.num = 0; + op[0].u.reg.effect = effect; + if (expr.object || expr.reg) + op[0].u.reg.effect = effect; + else + op[0].u.reg.effect = 0; + + ia->argcount++; + op[1].type = IAOpnd_Imm; + switch (expr.type) { + case IAExpr_5: + expr.type = IAExpr_6; + if (expr.object->datatype != DLOCAL || !OBJECT_REG(expr.object)) + PPCError_Error(PPCErrorStr180); + case IAExpr_2: + case IAExpr_6: + case IAExpr_7: + case IAExpr_8: + op[1].u.imm.value = InlineAsm_GetExprValue(&expr); + break; + default: + CError_Error(CErrorStr155); + } + + expr.object->flags |= OBJECT_USED; + return; + } + + if (expr.xC) { + if (expr.x10) + PPCError_Error(PPCErrorStr123, expr.xC->name->name, expr.x10->name->name); + + if (flag) { + if (tk == '(') { + if (flag) { + tk = lex(); + registeroperand(op, RegClass_GPR, effect); + if ((expr.type == IAExpr_8 || expr.type == IAExpr_7) && copts.codegen_pic && pic_base_reg) + CError_Error(CErrorStr155); + if (tk != ')') + CError_Error(CErrorStr115); + tk = lex(); + } + } else { + op[0].type = IAOpnd_Reg; + op[0].u.reg.rclass = RegClass_GPR; + op[0].u.reg.object = expr.object; + op[0].u.reg.num = expr.reg; + } + + if (expr.object || expr.reg) + op[0].u.reg.effect = effect; + else + op[0].u.reg.effect = 0; + + ia->argcount++; + op++; + } + + if (expr.xC->datatype == DLOCAL) { + op[0].type = IAOpnd_4; + op[0].u.obj.unk = IAExpr_1; + } else { + op[0].type = IAOpnd_3; + if (expr.type == IAExpr_5) { + expr.type = IAExpr_6; + PPCError_Error(PPCErrorStr180); + } + op[0].u.obj.unk = expr.type; + } + + op[0].u.obj.obj = expr.xC; + op[0].u.obj.offset = expr.value; + expr.xC->flags |= OBJECT_USED; + return; + } + + if (flag) { + if (tk == '(') { + tk = lex(); + registeroperand(op, RegClass_GPR, effect); + ia->argcount++; + op++; + if (tk != ')') + CError_Error(CErrorStr115); + tk = lex(); + } else { + op->type = IAOpnd_Reg; + op->u.reg.rclass = RegClass_GPR; + op->u.reg.object = expr.object; + op->u.reg.num = expr.reg; + ia->argcount++; + op++; + } + } + + if (expr.label) { + if (expr.x18) { + op->type = IAOpnd_LabDiff; + op->negated = 0; + op->u.labdiff.label1 = expr.label; + op->u.labdiff.label2 = expr.x18; + op->u.labdiff.offset = expr.value; + } else { + PPCError_Error(PPCErrorStr125, expr.label->name->name); + } + } else { + op->type = IAOpnd_Imm; + op->u.imm.value = InlineAsm_GetExprValue(&expr); + } +} + +static void registeroperand(IAOperand *op, char rclass, short effect) { + IARegister *reg; + Object *obj; + + if (tk == TK_IDENTIFIER && (reg = InlineAsm_LookupRegisterPPCName(tkidentifier)) && reg->rclass == rclass) { + SInt32 num; + obj = reg->object; + num = reg->num; + op->type = IAOpnd_Reg; + op->u.reg.rclass = rclass; + op->u.reg.object = obj; + op->u.reg.num = num; + op->u.reg.effect = effect; + if (obj) { + reg->object->flags |= OBJECT_USED; + Registers_GetVarInfo(obj)->flags |= VarInfoFlag40; + } + } else if (rclass == RegClass_CRFIELD) { + op->type = IAOpnd_Reg; + op->u.reg.rclass = RegClass_CRFIELD; + op->u.reg.object = NULL; + op->u.reg.num = getimmediateoperand(0, 7); + op->u.reg.effect = effect; + return; + } else if (rclass == RegClass_SPR) { + op->type = IAOpnd_Reg; + op->u.reg.rclass = RegClass_SPR; + op->u.reg.object = NULL; + op->u.reg.num = getimmediateoperand(0, 1024); + op->u.reg.effect = effect; + return; + } else if (tk == '%' && InlineAsm_gccmode) { + SInt32 num; + tk = lex(); + if (tk != TK_INTCONST) { + CError_Error(CErrorStr144); + } else { + num = ExtractValue(tkintconst); + if (num < 0) + CError_Error(CErrorStr144); + } + + op->type = IAOpnd_6; + op->u.unk6.num = num; + op->u.unk6.unk4 = 2; + op->u.unk6.effect = effect; + op->u.unk6.rclass = rclass; + tk = lex(); + return; + } else if (tk == TK_IDENTIFIER) { + NotInRegisterError(tkidentifier->name, rclass); + } else { + PPCError_Error(PPCErrorStr171); + } + + tk = lex(); + if (!strcmp(tkidentifier->name, "@loword")) { + tk = lex(); + } else if (!strcmp(tkidentifier->name, "@hiword")) { + if (reg->object) + op->u.reg.num = 1; + else + PPCError_Error(PPCErrorStr168); + tk = lex(); + } else if (rclass == RegClass_GPR) { + if (reg->object && reg->object->type->size == 8) { + HashNameNode *name = reg->object->name; + PPCError_Error(PPCErrorStr127, name->name, name->name, name->name); + } + } +} + +static void cr0_operand(IAOperand *op, short effect) { + IARegister *reg; + + if ((reg = InlineAsm_LookupRegisterPPC("cr0"))) { + op->type = IAOpnd_Reg; + op->u.reg.rclass = RegClass_CRFIELD; + op->u.reg.object = reg->object; + op->u.reg.num = reg->num; + op->u.reg.effect = effect; + } else { + NotInRegisterError("cr0", RegClass_CRFIELD); + } +} + +static void r0_operand(IAOperand *op) { + IARegister *reg; + + if ((reg = InlineAsm_LookupRegisterPPC("r0"))) { + op->type = IAOpnd_Reg; + op->u.reg.rclass = RegClass_GPR; + op->u.reg.object = reg->object; + op->u.reg.num = reg->num; + op->u.reg.effect = 0; + tk = lex(); + } else { + NotInRegisterError("r0", RegClass_GPR); + } +} + +static void labeloperand(InlineAsm *ia, IAOperand *op, Boolean flag1, Boolean flag2, Boolean flag3) { + IALookupResult result; + + if (tk == TK_IDENTIFIER) { + if (!InlineAsm_LookupSymbol(tkidentifier, &result)) + result.label = InlineAsm_DeclareLabel(tkidentifier); + + if (result.label) { + op->type = IAOpnd_Lab; + op->u.lab.label = result.label; + } else if (result.object && result.object->datatype == DFUNC) { + if (flag3) + ia->flags |= IAFlag2; + op->type = IAOpnd_3; + op->u.obj.obj = result.object; + op->u.obj.offset = 0; + + if (flag1) { + op->u.obj.unk = IAExpr_4; + if (flag2) + CError_Error(CErrorStr261); + } else { + op->u.obj.unk = IAExpr_2; + if (flag2) + op->u.obj.unk = IAExpr_10; + op->u.obj.unk = IAExpr_6; + PPCError_Error(PPCErrorStr180); + } + } else { + CError_Error(CErrorStr144); + } + + tk = lex(); + } else if (tk == '*') { + if (!flag2) { + tk = lex(); + if (tk == '+') { + tk = lex(); + if (flag1) + immediateoperand(op, -0x2000000, 0x1FFFFFF); + else + immediateoperand(op, -0x8000, 0xFFFF); + } else if (tk == '-') { + tk = lex(); + op->u.imm.value = flag1 ? -immediatevalue(op, -0x1FFFFFF, 0x2000000) : -immediatevalue(op, -0x7FFF, 0x10000); + } else { + CError_Error(CErrorStr144); + } + } else { + CError_Error(CErrorStr144); + } + } else { + if (flag2) { + if (flag1) + immediateoperand(op, -0x2000000, 0x1FFFFFF); + else + immediateoperand(op, -0x8000, 0xFFFF); + } else { + CError_Error(CErrorStr144); + } + } +} + +static void imm_or_labeldiff_operand(InlineAsm *ia, IAOperand *op, SInt32 minimum, SInt32 maximum, Boolean negate) { + IAExpr expr; + Object *obj; + SInt32 value; + + InlineAsm_ExpressionPPC(&expr, 0); + + if ((obj = expr.xC) && !expr.x10 && expr.type == IAExpr_5 && obj->datatype == DDATA && IS_TYPE_INT_OR_ENUM(obj->type) && (obj->qual & Q_INLINE_DATA)) { + switch (ia->opcode) { + case PC_ADDI: + case PC_ADDIC: + case PC_ADDICR: + case PC_ADDIS: + case PC_ORI: + case PC_ORIS: + if (ia->args[1].u.imm.value) { + SInt32 cmp; + if (obj->datatype != DLOCAL) { + cmp = copts.codegen_pic ? INVALID_PIC_REG : NO_REG; + } else { + cmp = local_base_register(obj); + } + if (ia->args[1].u.imm.value == cmp) + break; + } + case PC_LI: + case PC_LIS: + case PC_TWI: + case PC_OPWORD: + InlineAsm_InitExpr5(&expr, expr.value + CInt64_GetULong(&obj->u.data.u.intconst)); + break; + } + } + + if (expr.label) { + if (expr.x18) { + op->type = IAOpnd_LabDiff; + if (negate) + op->negated = 1; + else + op->negated = 0; + op->u.labdiff.label1 = expr.label; + op->u.labdiff.label2 = expr.x18; + op->u.labdiff.offset = expr.value; + } else { + PPCError_Error(PPCErrorStr125, expr.label->name->name); + } + return; + } + + if (expr.xC) { + if (!expr.x10) { + if (ia->opcode != PC_OPWORD && expr.type == IAExpr_5) { + IllegalObjectInConst(&expr); + return; + } + + if (expr.xC->datatype == DLOCAL) { + op->type = IAOpnd_4; + op->u.obj.unk = IAExpr_1; + } else { + op->type = IAOpnd_3; + if (expr.type == IAExpr_5) { + expr.type = IAExpr_6; + PPCError_Error(PPCErrorStr180); + } + op->u.obj.unk = expr.type; + } + op->u.obj.obj = expr.xC; + op->u.obj.offset = expr.value; + } else { + PPCError_Error(PPCErrorStr123, expr.xC->name->name, expr.x10->name->name); + } + return; + } + + value = InlineAsm_GetExprValue(&expr); + if (value < minimum || value > maximum) + CError_Error(CErrorStr154); + + op->type = IAOpnd_Imm; + if (negate) + op->u.imm.value = -value; + else + op->u.imm.value = value; +} + +static void eatcommatoken(void) { + if (tk == ',') + tk = lex(); + else + CError_Error(CErrorStr116); +} + +static InlineAsm *InlineAsm_ScanAssemblyOperands(IAMnemonic *mnemonic) { + OpcodeInfo *info; + InlineAsm *ia; + SInt32 buffersize; + IAOperand *op; + int argcount; + char *format; + IARegister *reg; + + char code; + short effect; + Boolean has_excl; + Boolean has_question; + Boolean negate; + UInt32 t; + + info = &opcodeinfo[mnemonic->x4]; + argcount = info->x8; + if (PCODE_FLAG_SET_F(info) & fCanSetRecordBit) + argcount++; + if (!(PCODE_FLAG_SET_F(info) & fSetsCarry) && (PCODE_FLAG_SET_F(info) & fCanSetCarry)) + argcount++; + if (PCODE_FLAG_SET_T(info) & fCanLink) + argcount++; + + buffersize = sizeof(InlineAsm) + sizeof(IAOperand) * argcount; + ia = galloc(buffersize); + memset(ia, 0, buffersize); + + ia->opcode = mnemonic->x4; + ia->flags = 0; + ia->argcount = 0; + + op = ia->args; + for (format = mnemonic->format; *format; format++) { + CError_ASSERT(1664, ia->argcount < argcount); + + if (*format == ',') { + eatcommatoken(); + format++; + } else if (*format == ';') { + format++; + } + + if (*format == '[' || *format == '(') + format++; + + effect = EffectRead; + has_excl = 0; + has_question = 0; + negate = 0; + if (*format == '=') { + effect = EffectWrite; + format++; + } else if (*format == '+') { + effect = EffectRead | EffectWrite; + format++; + } + + if (*format == '-') { + negate = 1; + format++; + } + + if (*format == '?') { + has_question = 1; + format++; + } + + if (*format == '!') { + has_excl = 1; + format++; + } + + switch (*format) { + case 'p': + continue; + case '&': + if (format[1] == '2') { + op[0] = op[-2]; + format++; + if (op->type == IAOpnd_Reg) + op->u.reg.effect = effect; + ia->argcount++; + + op[1] = op[-1]; + op++; + if (op->type == IAOpnd_Reg) + op->u.reg.effect = effect; + } else { + op[0] = op[-1]; + if (op->type == IAOpnd_Reg) + op->u.reg.effect = effect; + } + break; + + case '%': { + SInt32 value; + format += pcode_const_from_format(format + 1, &value); + op->type = IAOpnd_Imm; + op->u.imm.value = value; + break; + } + + case 'b': + if (!isregisteroperand(RegClass_GPR)) { + if (tk == TK_INTCONST && tkintconst.lo == 0) + r0_operand(op); + } else { + registeroperand(op, RegClass_GPR, effect); + if (op->u.reg.object == NULL && op->u.reg.num == 0) + op->u.reg.effect = 0; + } + break; + + case 'r': + registeroperand(op, RegClass_GPR, effect); + break; + + case 'B': + case 'a': + case 'i': + case 't': + case 'u': + case 'x': + { + SInt32 value, hi, lo; + code = *format; + value = 16; + if (code == 'a') { + if (isdigit(format[1])) + code = *(++format); + else + CError_FATAL(1804); + } + + if (isdigit(format[1])) { + format += pcode_const_from_format(format + 1, &value); + } else if (code == 't' || code == 'B') { + code = 'u'; + value = 5; + } + + pcode_get_hi_lo(value, code, &hi, &lo); + if (!has_question || tk == ',') { + if (has_question) + tk = lex(); + if (has_excl) + getimmediateoperand(lo, hi); + else + immediateoperand(op, lo, hi); + } else { + op->type = IAOpnd_Imm; + op->u.imm.value = 0; + } + + if (code == 'i' && value == 16) + op->u.imm.value = (short) op->u.imm.value; + if (negate) + op->u.imm.value = -op->u.imm.value; + + if (pcode_check_imm_bits(op->u.imm.value, value, code)) + CError_FATAL(1838); + + break; + } + + case 'O': + if (tk == TK_INTCONST && tkintconst.lo == 0) { + getimmediateoperand(0, 0); + eatcommatoken(); + } + continue; + + case 'f': + registeroperand(op, RegClass_FPR, effect); + break; + + case 'v': + registeroperand(op, RegClass_VR, effect); + break; + + case 'T': + if (!has_question || tk == ',') { + if (has_question) + tk = lex(); + + immediateoperand(op, 268, 269); + if (op->u.reg.num == 268) + op->u.reg.num = 284; + else + op->u.reg.num = 285; + } else { + op->u.reg.num = 284; + } + + op->type = IAOpnd_Reg; + op->u.reg.rclass = RegClass_SPR; + op->u.reg.effect = effect; + break; + + case 'S': + { + SInt32 value; + format += pcode_const_from_format(format + 1, &value); + op->type = IAOpnd_Reg; + op->u.reg.rclass = RegClass_SPR; + op->u.reg.num = value; + op->u.reg.effect = effect; + break; + } + + case 'c': + if (has_question) { + if (isregisteroperand(RegClass_CRFIELD) || tk == TK_INTCONST) { + registeroperand(op, RegClass_CRFIELD, effect); + } else { + cr0_operand(op, effect); + if (format[1] == ',') + format++; + } + } else { + registeroperand(op, RegClass_CRFIELD, effect); + } + break; + + case 'l': + switch (ia->opcode) { + case PC_B: + case PC_BL: + labeloperand(ia, op, 1, mnemonic->x10 & 2, mnemonic->x10 & 1); + break; + default: + labeloperand(ia, op, 0, mnemonic->x10 & 2, mnemonic->x10 & 1); + break; + } + break; + + case 'w': + imm_or_labeldiff_operand(ia, op, -0x80000000, 0x7FFFFFFF, negate); + break; + + case 'M': + case 'm': + case 'n': + imm_or_labeldiff_operand(ia, op, -0x8000, 0xFFFF, negate); + break; + + case 'Q': + { + SInt32 cr = crbitoperand(); + op->type = IAOpnd_Reg; + op->u.reg.num = cr >> 2; + op->u.reg.rclass = RegClass_CRFIELD; + op->u.reg.effect = effect; + + ia->argcount++; + op[1].type = IAOpnd_Imm; + op[1].u.imm.value = cr % 4; + op++; + break; + } + + case 'd': { + short effect2; + CError_ASSERT(1971, format[1] == '('); + format++; + effect2 = EffectRead; + if (format[1] == '=') { + effect2 = EffectWrite; + format++; + } else if (format[1] == '+') { + effect2 = EffectRead | EffectWrite; + format++; + } + + CError_ASSERT(1983, format[1] == 'b'); + CError_ASSERT(1985, format[2] == ')'); + format += 2; + + switch (ia->opcode) { + case PC_LFS: + if (tk == TK_FLOATCONST) + floatoperand(op, ia, TYPE(&stfloat)); + else + memoryoperand(op, ia, 1, effect2); + break; + case PC_LFD: + if (tk == TK_FLOATCONST) + floatoperand(op, ia, TYPE(&stdouble)); + else + memoryoperand(op, ia, 1, effect2); + break; + default: + memoryoperand(op, ia, 1, effect2); + } + + break; + } + + case 'N': + immediateoperand(op, 1, 32); + break; + + case 's': + registeroperand(op, RegClass_SPR, effect); + break; + + case 'D': + if (tk == TK_IDENTIFIER && (reg = InlineAsm_LookupDCRRegister(tkidentifier->name))) { + op->type = IAOpnd_Imm; + op->u.imm.value = reg->num; + } else { + immediateoperand(op, 0, 1023); + } + break; + + case 'Y': + { + SInt32 mask = 255; + SInt32 i; + if (ia->opcode == PC_MTCRF) { + if (ia->args[0].type != IAOpnd_Imm) + CError_Error(CErrorStr144); + mask = ia->args[0].u.imm.value; + } + for (i = 0; i < 8; i++) { + if ((0x80 >> i) & mask) { + op->type = IAOpnd_Reg; + op->u.reg.num = i; + op->u.reg.rclass = RegClass_CRFIELD; + op->u.reg.effect = effect; + ia->argcount++; + op++; + } + } + ia->argcount--; + op--; + break; + } + + case 'P': + op->type = IAOpnd_Reg; + op->u.reg.rclass = RegClass_SPR; + op->u.reg.object = NULL; + if (format[1] == '3') { + format++; + op->u.reg.num = getimmediateoperand(0, 7); + } else { + op->u.reg.num = getimmediateoperand(0, 3); + } + op->u.reg.effect = effect; + break; + + case 'C': + op->type = IAOpnd_Reg; + op->u.reg.rclass = RegClass_SPR; + op->u.reg.object = NULL; + op->u.reg.num = 9; + op->u.reg.effect = effect; + break; + + case 'L': + op->type = IAOpnd_Reg; + op->u.reg.rclass = RegClass_SPR; + op->u.reg.object = NULL; + op->u.reg.num = 8; + op->u.reg.effect = effect; + break; + + case 'X': + op->type = IAOpnd_Reg; + op->u.reg.rclass = RegClass_SPR; + op->u.reg.object = NULL; + op->u.reg.num = 1; + op->u.reg.effect = effect; + break; + + case 'Z': + op->type = IAOpnd_Reg; + op->u.reg.rclass = RegClass_CRFIELD; + op->u.reg.object = NULL; + t = info->flags & 0xC0000000; + if (t == 0x40000000) { + op->u.reg.num = 1; + } else if (t == 0xC0000000) { + op->u.reg.num = 6; + } else { + op->u.reg.num = 0; + } + op->u.reg.effect = effect; + break; + + default: + CError_FATAL(2266); + } + + while (format[1] && strchr("/<>|*", format[1])) { + int index; + SInt32 value; + SInt32 value2; + IAOperand tmp; + switch ((code = *(++format))) { + case '/': + index = -1; + if (format[1] == '2') { + index = -2; + format++; + } + + tmp = op[index]; + op[index] = op[0]; + op[0] = tmp; + break; + case '*': + case '<': + case '>': + case '|': + if (op->type == IAOpnd_Imm) + value = op->u.imm.value; + else if (op->type == IAOpnd_Reg) + value = op->u.reg.num; + else + CError_FATAL(2312); + + if (format[1] == 'p') { + format++; + if (op[-1].type == IAOpnd_Imm) + value2 = op[-1].u.imm.value; + else if (op[-1].type == IAOpnd_Reg) + value2 = op[-1].u.reg.num; + else + CError_FATAL(2322); + } else if (isdigit(format[1])) { + format += pcode_const_from_format(format + 1, &value2); + } else { + CError_FATAL(2327); + } + + switch (code) { + case '<': + value = value2 - value; + break; + case '>': + value = value - value2; + break; + case '|': + value = value + value2; + break; + case '*': + value = value * value2; + break; + default: + CError_FATAL(2348); + } + + if (op->type == IAOpnd_Imm) + op->u.imm.value = value; + else if (op->type == IAOpnd_Reg) + op->u.reg.num = value; + else + CError_FATAL(2355); + break; + } + } + + ia->argcount++; + op++; + if (format[1] == ']' || format[1] == ')') + format++; + } + + return ia; +} + +static int mnemonic_has_overflow(char *buf) { + int result = 0; + + if (buf[strlen(buf) - 1] == 'o') { + if (!strcmp(buf, "bso")) + return 0; + if (!strcmp(buf, "fcmpo")) + return 0; + if (!strcmp(buf, "eieio")) + return 0; + if (!strcmp(buf, "vslo")) + return 0; + if (!strcmp(buf, "vsro")) + return 0; + result = 1; + } + + return result; +} + +static int mnemonic_has_absolute(const char *buf) { + int result = 0; + char last = buf[strlen(buf) - 1]; + + if (buf[0] == 'b' && last == 'a') + result = 1; + + return result; +} + +static int mnemonic_has_linkregister(const char *buf) { + int result = 0; + char last = buf[strlen(buf) - 1]; + + if (buf[0] == 'b' && last == 'l') + result = 1; + + return result; +} + +static int mnemonic_has_record(char *buf) { + int result = 0; + + if (lookahead() == '.') { + tk = lex(); + result = 1; + strcat(buf, "."); + } + + return result; +} + +static void installregistervariables(void) { +} + +void InlineAsm_InitializePPC(void) { + Test_Version_Numbers(); + allow_array_expressions = 1; + supports_hardware_fpu = 1; + assembledinstructions = 0; + + switch (copts.processor) { + case CPU_PPC401: cpu = CPUMask_401; break; + case CPU_PPC403: cpu = CPUMask_403; break; + case CPU_PPC505: cpu = CPUMask_50x; break; + case CPU_PPC509: cpu = CPUMask_50x; break; + case CPU_PPC555: cpu = CPUMask_55x_56x; break; + case CPU_PPC556: cpu = CPUMask_55x_56x; break; + case CPU_PPC565: cpu = CPUMask_55x_56x; break; + case CPU_PPC601: cpu = CPUMask_601; break; + case CPU_PPC602: cpu = CPUMask_602; break; + case CPU_PPC8240: cpu = CPUMask_8240; break; + case CPU_PPC8260: cpu = CPUMask_8260; break; + case CPU_PPC603: cpu = CPUMask_603; break; + case CPU_PPC603e: cpu = CPUMask_603; break; + case CPU_PPC604: cpu = CPUMask_604; break; + case CPU_PPC604e: cpu = CPUMask_604; break; + case CPU_PPC740: cpu = CPUMask_740_750; break; + case CPU_PPC750: cpu = CPUMask_740_750; break; + case CPU_PPC801: cpu = CPUMask_801_821_860; break; + case CPU_PPC821: cpu = CPUMask_801_821_860; break; + case CPU_PPC823: cpu = CPUMask_823_850; break; + case CPU_PPC850: cpu = CPUMask_823_850; break; + case CPU_PPC860: cpu = CPUMask_801_821_860; break; + case CPU_PPC7400: case CPU_PPC7450: cpu = CPUMask_74xx; break; + case CPU_Generic: cpu = CPUMask_Generic; break; + default: + CError_FATAL(2613); + } + + if (copts.altivec_model) + cpu |= 0x40000000; +} + +void InlineAsm_Initialize(AssemblerType assemblertype) { + assembler_type = assemblertype; + + if (assembler_type == 0) { + InlineAsm_InitializePPC(); + pic_base_reg = INVALID_PIC_REG; + } else { + pic_base_reg = 0; + pic_base_label = NULL; + } + + InlineAsm_InitializeMnemonicsPPC(); + InlineAsm_InitializeRegisters(); + InlineAsm_InitializeRegistersPPC(); + + if (assembler_type == 0) { + installregistervariables(); + } else { + process_arguments(setup_assembly_argument, 0); + assign_local_addresses(); + } +} + +static IAEntryPoint *InlineAsm_CreateEntryPoint(HashNameNode *name, Boolean flag) { + Object *obj; + IAEntryPoint *ep; + IALookupResult result; + + if (InlineAsm_LookupSymbol(name, &result) && (obj = result.object)) { + if (!(obj->datatype == DFUNC && !(obj->flags & OBJECT_DEFINED))) + CError_Error(CErrorStr122, name->name); + + obj->flags |= OBJECT_DEFINED; + obj->sclass = flag ? TK_STATIC : TK_EXTERN; + + ep = lalloc(sizeof(IAEntryPoint)); + memclrw(ep, sizeof(IAEntryPoint)); + ep->x0 = IADirective_Entry; + ep->x2 = 1; + ep->x8 = obj; + ep->size = assembledinstructions * 4; + } else { + CError_Error(CErrorStr140, name->name); + } + + return ep; +} + +static InlineAsm *InlineAsm_CreateFrFree(void) { + InlineAsm *ia = lalloc(sizeof(InlineAsm)); + memclrw(ia, sizeof(InlineAsm)); + ia->opcode = IADirective_FrFree; + ia->flags = IAFlag1; + return ia; +} + +SInt32 InlineAsm_IsDirective(AssemblerType assemblertype) { + char *name; + SInt32 directive = IADirective_Null; + + if (tk == '.') + tk = lex(); + + if (tk == TK_IDENTIFIER) { + name = tkidentifier->name; + if (!strcmp(name, "machine")) { + directive = IADirective_Machine; + } else if (assemblertype == AssemblerType_1) { + if (!strcmp(name, "entry")) { + directive = IADirective_Entry; + } else if (!strcmp(name, "fralloc")) { + directive = IADirective_FrAlloc; + } else if (!strcmp(name, "nofralloc")) { + directive = IADirective_NoFrAlloc; + } else if (!strcmp(name, "frfree")) { + directive = IADirective_FrFree; + } else if (!strcmp(name, "smclass")) { + directive = IADirective_SmClass; + } else if (!strcmp(name, "picbase")) { + directive = IADirective_PicBase; + } else { + directive = IADirective_Null; + } + } + } + + return directive; +} + +void InlineAsm_ProcessDirective(SInt32 directive) { + Boolean flag; + Statement *stmt; + IAOperand op; + + switch (directive) { + case IADirective_Entry: + flag = 0; + tk = lex(); + if (tk == TK_STATIC) { + flag = 1; + tk = lex(); + } else if (tk == TK_EXTERN) { + tk = lex(); + } + + if (tk != TK_IDENTIFIER) + CError_Error(CErrorStr107); + + stmt = CFunc_AppendStatement(ST_ASM); + stmt->expr = NULL; + stmt->expr = (ENode *) InlineAsm_CreateEntryPoint(tkidentifier, flag); + stmt->sourceoffset = -1; + tk = lex(); + break; + + case IADirective_FrAlloc: + if (assembledinstructions) + CError_Error(CErrorStr166); + if (asm_alloc_flags[0]) + CError_Error(CErrorStr165); + if (asm_alloc_flags[1] || asm_alloc_flags[2]) + CError_Error(CErrorStr166); + + tk = lex(); + if (tk != TK_EOL && tk != ';') + fralloc_parameter_area_size = getimmediateoperand(0x20, 0x7FFE); + + requires_frame = 1; + asm_alloc_flags[0] = 1; + break; + + case IADirective_NoFrAlloc: + if (asm_alloc_flags[0] || asm_alloc_flags[1]) + CError_Error(CErrorStr165); + if (asm_alloc_flags[2]) + CError_Error(CErrorStr166); + if (assembledinstructions) + CError_Error(CErrorStr166); + tk = lex(); + + asm_alloc_flags[1] = 1; + user_responsible_for_frame = 1; + break; + + case IADirective_FrFree: + if (asm_alloc_flags[1] || asm_alloc_flags[2]) + CError_Error(CErrorStr166); + + asm_alloc_flags[2] = 1; + stmt = CFunc_AppendStatement(ST_ASM); + stmt->expr = NULL; + stmt->expr = (ENode *) InlineAsm_CreateFrFree(); + if (copts.filesyminfo) + stmt->sourceoffset = CPrep_GetFileOffsetInfo(&cparser_fileoffset); + else + stmt->sourceoffset = -1; + tk = lex(); + break; + + case IADirective_Machine: + tk = lex(); + if (tk == TK_INTCONST) { + switch (tkintconst.lo) { + case 401: cpu = CPUMask_401; break; + case 403: cpu = CPUMask_403; break; + case 505: cpu = CPUMask_50x; break; + case 509: cpu = CPUMask_50x; break; + case 555: cpu = CPUMask_55x_56x; break; + case 556: cpu = CPUMask_55x_56x; break; + case 565: cpu = CPUMask_55x_56x; break; + case 601: cpu = CPUMask_601; break; + case 602: cpu = CPUMask_602; break; + case 8240: cpu = CPUMask_8240; break; + case 8260: cpu = CPUMask_8260; break; + case 603: cpu = CPUMask_603; break; + case 604: cpu = CPUMask_604; break; + case 740: cpu = CPUMask_740_750; break; + case 750: cpu = CPUMask_740_750; break; + case 801: cpu = CPUMask_801_821_860; break; + case 821: cpu = CPUMask_801_821_860; break; + case 823: cpu = CPUMask_823_850; break; + case 850: cpu = CPUMask_823_850; break; + case 860: cpu = CPUMask_801_821_860; break; + case 7400: cpu = CPUMask_74xx; break; + default: + CError_Error(CErrorStr144); + } + } else if (tk == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "all")) { + cpu = CPUMask_All; + } else if (!strcmp(tkidentifier->name, "generic")) { + cpu = CPUMask_Generic; + } else if (!strcmp(tkidentifier->name, "603e")) { + cpu = CPUMask_603; + } else if (!strcmp(tkidentifier->name, "604e")) { + cpu = CPUMask_604; + } else if (!strcmp(tkidentifier->name, "PPC603e")) { + cpu = CPUMask_603; + } else if (!strcmp(tkidentifier->name, "PPC604e")) { + cpu = CPUMask_604; + } else if (!strcmp(tkidentifier->name, "altivec")) { + cpu = CPUMask_74xx; + } else { + CError_Error(CErrorStr144); + } + } else { + CError_Error(CErrorStr144); + } + tk = lex(); + break; + + case IADirective_SmClass: + tk = lex(); + if (tk == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "PR")) + sm_section = SECT_TEXT; + else + CError_Error(CErrorStr144); + } else { + CError_Error(CErrorStr144); + } + tk = lex(); + break; + + case IADirective_PicBase: + tk = lex(); + registeroperand(&op, RegClass_GPR, EffectRead); + + if (!(op.type == IAOpnd_Reg && op.u.reg.object == NULL)) + CError_Error(CErrorStr144); + + tk = lex(); + if (tk == TK_IDENTIFIER) { + savepicbase(op.u.reg.num, tkidentifier); + tk = lex(); + } else { + CError_Error(CErrorStr144); + } + break; + + default: + CError_Error(CErrorStr261); + } +} + +void InlineAsm_ScanAssemblyDirective(void) { + SInt32 directive; + + if ((directive = InlineAsm_IsDirective(assembler_type)) != IADirective_Null) + InlineAsm_ProcessDirective(directive); +} + +void InlineAsm_ScanAssemblyInstruction(void) { + Statement *stmt; + InlineAsm *ia; + IAMnemonic *mnemonic; + Boolean record_flag; + Boolean flag3; + Boolean flag4; + Boolean flag5; + Boolean flag1; + Boolean flag2; + SInt32 directive; + OpcodeInfo *info; + char buf[20]; + + flag1 = 0; + flag2 = 0; + if ((directive = InlineAsm_IsDirective(assembler_type)) != IADirective_Null) { + InlineAsm_ProcessDirective(directive); + return; + } + + stmt = CFunc_AppendStatement(ST_ASM); + stmt->expr = NULL; + if (copts.filesyminfo) + stmt->sourceoffset = CPrep_GetFileOffsetInfo(&cparser_fileoffset); + else + stmt->sourceoffset = -1; + + strncpy(buf, tkidentifier->name, sizeof(buf)); + record_flag = mnemonic_has_record(buf); + mnemonic = InlineAsm_LookupMnemonicPPC(buf); + if (!mnemonic) + CError_Error(CErrorStr261); + + info = &opcodeinfo[mnemonic->x4]; + flag3 = (FLAG_SET_F(info->flags) & fCanSetCarry) && (mnemonic->x10 & 0x400); + flag4 = (FLAG_SET_T(info->flags) & fCanBeAbsolute) && (mnemonic->x10 & 2); + flag5 = (FLAG_SET_T(info->flags) & fCanLink) && (mnemonic->x10 & 1); + + if ((cpu == CPUMask_Generic) && (cpu & CPUFLAG_LOW_MASK) != ((cpu & mnemonic->cpu) & CPUFLAG_LOW_MASK)) { + CError_Error(CErrorStr152); + } else if (((cpu & mnemonic->cpu) & CPUFLAG_LOW_MASK) == 0) { + CError_Error(CErrorStr152); + } else if ((mnemonic->cpu & CPUFLAG_10000000) && !(cpu & CPUFLAG_10000000)) { + CError_Error(CErrorStr152); + } else if ((mnemonic->cpu & CPUFLAG_8000000) && !(cpu & CPUFLAG_8000000)) { + CError_Error(CErrorStr152); + } else if ((mnemonic->cpu & CPUFLAG_2000000) && !(cpu & CPUFLAG_2000000)) { + CError_Error(CErrorStr152); + } else if ((mnemonic->cpu & CPUFLAG_4000000) && !(cpu & CPUFLAG_4000000)) { + CError_Error(CErrorStr152); + } else if ((mnemonic->cpu & CPUFLAG_1000000) && !(cpu & CPUFLAG_1000000)) { + CError_Error(CErrorStr152); + } else if ((mnemonic->cpu & CPUFLAG_40000000) && !(cpu & CPUFLAG_40000000)) { + CError_Error(CErrorStr152); + } else if ((mnemonic->cpu & CPUFLAG_20000000) && !(cpu & CPUFLAG_20000000)) { + CError_Error(CErrorStr152); + } else if ((mnemonic->cpu & CPUFLAG_800000) && !(cpu & CPUFLAG_800000)) { + CError_Error(CErrorStr152); + } + + tk = lex(); + if (tk == '+' || tk == '-') { + if ( + ((OPCODE_PART_1(mnemonic->x10) == 16) && (OPCODE_PART_2(mnemonic->x10) != 20)) || + ((OPCODE_PART_1(mnemonic->x10) == 19) && (OPCODE_PART_3(mnemonic->x10) == 528) && (OPCODE_PART_2(mnemonic->x10) != 20)) || + ((OPCODE_PART_1(mnemonic->x10) == 19) && (OPCODE_PART_3(mnemonic->x10) == 16) && (OPCODE_PART_2(mnemonic->x10) != 20)) + ) { + if (tk == '+') + flag1 = 1; + else if (tk == '-') + flag2 = 1; + tk = lex(); + } else { + CError_Error(CErrorStr120); + } + } + + stmt->expr = (ENode *) InlineAsm_ScanAssemblyOperands(mnemonic); + + ia = (InlineAsm *) stmt->expr; + if (record_flag) + ia->flags2 |= IAFlagsB_1; + if (flag3) + ia->flags2 |= IAFlagsB_2; + if (flag4) + ia->flags2 |= IAFlagsB_4; + if (flag5) + ia->flags2 |= IAFlagsB_8; + if (flag1) + ia->flags2 |= IAFlagsB_10; + if (flag2) + ia->flags2 |= IAFlagsB_20; + if (volatileasm) + ia->flags2 |= IAFlagsB_40; + + ++assembledinstructions; +} + +static PCode *InlineAsm_TranslateIRtoPCodePPC(InlineAsm *ia, int argcount, AssemblerType assemblertype) { + PCode *pc; + int index; + int extra_args; + int reg; + int newargcount; + SInt32 buffersize; + IAOperand *src; + PCodeArg *dest; + OpcodeInfo *info; + + info = &opcodeinfo[ia->opcode]; + index = 0; + extra_args = 0; + reg = 0; + + if ((PCODE_FLAG_SET_F(info) & fCanSetRecordBit) && !(PCODE_FLAG_SET_F(info) & fRecordBit)) + extra_args++; + + if (!(PCODE_FLAG_SET_F(info) & fSetsCarry) && (PCODE_FLAG_SET_F(info) & fCanSetCarry)) + extra_args++; + + if (argcount < ia->argcount) { + if ((argcount + extra_args) >= ia->argcount) { + extra_args -= (ia->argcount - argcount); + argcount = ia->argcount; + } else { + CError_FATAL(3317); + } + } + + if (ia->opcode == PC_B && ia->args[0].type == IAOpnd_Imm) + ia->flags2 |= IAFlagsB_40; + + if (ia->opcode == PC_TWI || ia->opcode == PC_TW || ia->opcode == PC_TRAP || ia->opcode == PC_SC) + ia->flags |= IAFlag2; + + if (ia->flags & IAFlag2) { + newargcount = argcount + branch_count_volatiles(); + if (copts.exceptions && current_statement && assembler_type == 0) + newargcount += countexceptionactionregisters(current_statement->dobjstack); + + buffersize = sizeof(PCode) + sizeof(PCodeArg) * (newargcount + extra_args); + pc = lalloc(buffersize); + memset(pc, 0, buffersize); + pc->argCount = newargcount; + } else if (ia->opcode == PC_STMW || ia->opcode == PC_LMW) { + reg = ia->args[0].u.reg.object ? OBJECT_REG(ia->args[0].u.reg.object) : ia->args[0].u.reg.num; + newargcount = argcount + (32 - reg); + + buffersize = sizeof(PCode) + sizeof(PCodeArg) * newargcount; + pc = lalloc(buffersize); + memset(pc, 0, buffersize); + pc->argCount = newargcount; + } else { + buffersize = sizeof(PCode) + sizeof(PCodeArg) * (argcount + extra_args); + pc = lalloc(buffersize); + memset(pc, 0, buffersize); + pc->argCount = (ia->argcount > argcount) ? ia->argcount : argcount; + } + + pc->op = ia->opcode; + pc->flags = info->flags; + pc->sourceoffset = current_statement ? current_statement->sourceoffset : -1; + + dest = pc->args; + src = ia->args; + argcount += extra_args; + while (index < argcount) { + if (index >= ia->argcount) { + dest->kind = PCOp_PLACEHOLDEROPERAND; + } else { + switch (src->type) { + case IAOpnd_0: + dest->kind = PCOp_PLACEHOLDEROPERAND; + break; + + case IAOpnd_Imm: + dest->kind = PCOp_IMMEDIATE; + dest->data.imm.value = src->u.imm.value; + if (pc->flags & (fIsRead | fIsWrite)) + pc->flags |= fIsPtrOp; + dest->data.imm.obj = NULL; + break; + + case IAOpnd_Reg: { + int r20; + r20 = 0; + if (src->u.reg.object) { + if (Registers_GetVarInfo(src->u.reg.object)->flags & VarInfoFlag2) { + if (src->u.reg.num == 1) + r20 = OBJECT_REG_HI(src->u.reg.object); + else + r20 = OBJECT_REG(src->u.reg.object); + } else { + if (Registers_GetVarInfo(src->u.reg.object)->flags & VarInfoFlag40) + PPCError_Error(PPCErrorStr172, src->u.reg.object->name->name); + else + PPCError_Error(PPCErrorStr167, src->u.reg.object->name->name); + } + } else if (src->u.reg.num == INVALID_PIC_REG) { + r20 = pic_base_reg; + } else { + r20 = src->u.reg.num; + } + + dest->kind = PCOp_REGISTER; + dest->arg = src->u.reg.rclass; + dest->data.reg.reg = r20; + dest->data.reg.effect = src->u.reg.effect; + if (pc->op == PC_RLWIMI && (dest->data.reg.effect & EffectWrite) && dest->arg == RegClass_GPR && !(dest->data.reg.effect & EffectRead)) + CError_FATAL(3442); + + if (dest->arg == RegClass_SPR) { + int i; + dest->kind = PCOp_SYSREG; + for (i = 0; i < 4; i++) { + if (dest->data.reg.reg == spr_to_sysreg[i]) { + dest->kind = PCOp_REGISTER; + dest->arg = RegClass_SPR; + dest->data.reg.reg = i; + break; + } + } + pcsetsideeffects(pc); + } else if (dest->arg == RegClass_6 || dest->arg == RegClass_DCR) { + short save = dest->data.reg.reg; + dest->kind = PCOp_IMMEDIATE; + dest->data.imm.value = save; + dest->data.imm.obj = NULL; + break; + } + + if ((src->u.reg.effect & EffectWrite) && dest->data.reg.reg < n_real_registers[dest->arg]) { + if (src->u.reg.object) { + if (Registers_GetVarInfo(src->u.reg.object)->flags & VarInfoFlag4) { + int reg, regHi; + CError_ASSERT(3474, dest->arg == RegClass_GPR); + + regHi = OBJECT_REG_HI(src->u.reg.object); + reg = OBJECT_REG(src->u.reg.object); + retain_GPR_pair(src->u.reg.object, reg, regHi); + } else { + retain_register(src->u.reg.object, dest->arg, dest->data.reg.reg); + } + } else { + retain_register(NULL, dest->arg, dest->data.reg.reg); + } + } + + break; + } + + case IAOpnd_Lab: + if (!src->u.lab.label->pclabel) + src->u.lab.label->pclabel = makepclabel(); + dest->kind = PCOp_LABEL; + dest->data.label.label = src->u.lab.label->pclabel; + break; + + case IAOpnd_3: + case IAOpnd_4: + dest->kind = PCOp_MEMORY; + dest->arg = src->u.obj.unk; + dest->data.mem.obj = src->u.obj.obj; + dest->data.mem.offset = src->u.obj.offset; + if (pc->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) { + pc->alias = make_alias(dest->data.mem.obj, dest->data.mem.offset, nbytes_loaded_or_stored_by(pc)); + if (is_volatile_object(dest->data.mem.obj)) + pc->flags |= fIsVolatile; + if (OBJ_GET_TARGET_CONST(dest->data.mem.obj)) + pc->flags |= fIsConst; + } + break; + + case IAOpnd_LabDiff: + if (src->u.labdiff.label1->pclabel == NULL) + src->u.labdiff.label1->pclabel = makepclabel(); + if (src->u.labdiff.label2->pclabel == NULL) + src->u.labdiff.label2->pclabel = makepclabel(); + if (pc->flags & (fIsRead | fIsWrite)) + pc->flags |= fIsPtrOp; + dest->kind = PCOp_LABELDIFF; + dest->data.labeldiff.labelA = src->u.labdiff.label1->pclabel; + dest->data.labeldiff.labelB = src->u.labdiff.label2->pclabel; + dest->arg = src->negated; + dest->data.labeldiff.offset = src->u.labdiff.offset; + break; + + default: + CError_FATAL(3528); + } + } + + index++; + dest++; + src++; + } + + if (ia->opcode == PC_STMW || ia->opcode == PC_LMW) { + int i; + for (i = reg; i < 32; i++, dest++) { + dest->kind = PCOp_REGISTER; + dest->arg = RegClass_GPR; + dest->data.reg.reg = i; + dest->data.reg.effect = ((ia->opcode == PC_LMW) ? EffectWrite : EffectRead); + } + } + + if (ia->flags & IAFlag2) { + UInt32 masks[5] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; + branch_record_volatiles(dest, masks); + if (copts.exceptions && current_statement && assembler_type == 0) + noteexceptionactionregisters(current_statement->dobjstack, dest); + } + + return pc; +} + +void InlineAsm_TranslateIRtoPCode(Statement *stmt) { + InlineAsm *ia; + PCode *pc; + + ia = (InlineAsm *) stmt->expr; + pc = InlineAsm_TranslateIRtoPCodePPC(ia, opcodeinfo[ia->opcode].x8, assembler_type); + appendpcode(pclastblock, pc); + + if ((ia->flags2 & IAFlagsB_40) || !copts.optimizewithasm) + setpcodeflags(fSideEffects); + + if (ia->flags2 & IAFlagsB_1) { + if (PCODE_FLAG_SET_F(pc) & fCanSetRecordBit) + pcsetrecordbit(pclastblock->lastPCode); + else + CError_Error(CErrorStr261); + } + + if (ia->flags2 & IAFlagsB_2) { + if (PCODE_FLAG_SET_F(pc) & fCanSetCarry) + setpcodeflags(fOverflow); // idk? + else + CError_Error(CErrorStr261); + } + + if (ia->flags2 & IAFlagsB_4) { + if (PCODE_FLAG_SET_T(pc) & fCanBeAbsolute) { + int i; + for (i = 0; i < pc->argCount; i++) { + if (pc->args[i].kind == PCOp_LABEL || pc->args[i].kind == PCOp_MEMORY) { + PPCError_Error(PPCErrorStr177); + break; + } + } + setpcodeflags(fAbsolute); + } else { + CError_Error(CErrorStr261); + } + } + + if (ia->flags2 & IAFlagsB_8) { + if (PCODE_FLAG_SET_T(pc) & fCanLink) { + pcsetlinkbit(pclastblock->lastPCode); + if (!(ia->flags & IAFlag2)) { + pclastblock->lastPCode->flags &= ~fIsCall; + pclastblock->lastPCode->flags |= fIsBranch; + } + makes_call = 1; + } else { + CError_Error(CErrorStr261); + } + } + + if (ia->flags2 & IAFlagsB_10) + setpcodeflags(fCanSetRecordBit); + if (ia->flags2 & IAFlagsB_20) + setpcodeflags(fCanSetCarry); + + if (OPCODE_PART_1(opcodeinfo[pc->op].insn) == 16) { + PCodeLabel *dest = NULL; + PCodeLabel *src = makepclabel(); + switch (pc->op) { + case PC_BC: + if (pc->args[3].kind == PCOp_LABEL) + dest = pc->args[3].data.label.label; + break; + case PC_BT: + case PC_BF: + case PC_BDNZT: + case PC_BDNZF: + case PC_BDZT: + case PC_BDZF: + if (pc->args[2].kind == PCOp_LABEL) + dest = pc->args[2].data.label.label; + break; + case PC_BDNZ: + case PC_BDZ: + if (pc->args[0].kind == PCOp_LABEL) + dest = pc->args[0].data.label.label; + break; + default: + CError_FATAL(3715); + } + + if (dest) { + pcbranch(pclastblock, dest); + pcbranch(pclastblock, src); + makepcblock(); + pclabel(pclastblock, src); + } + return; + } + + if (OPCODE_PART_1(opcodeinfo[pc->op].insn) == 18) { + PCodeLabel *label; + if (ia->flags2 & IAFlagsB_8) { + label = makepclabel(); + pcbranch(pclastblock, label); + } + if (pc->args[0].kind == PCOp_LABEL) + pcbranch(pclastblock, pc->args[0].data.label.label); + makepcblock(); + if (ia->flags2 & IAFlagsB_8) { + pclabel(pclastblock, label); + } + return; + } + + if (OPCODE_PART_1(opcodeinfo[pc->op].insn) == 19) { + switch (pc->op) { + case PC_BLR: + case PC_RFI: + if (asm_alloc_flags[3]) + asm_alloc_flags[9] = 1; + else + asm_alloc_flags[8] = 1; + + if (asm_alloc_flags[4]) + asm_alloc_flags[5] = 1; + + if (pc->op == PC_BLR) + asm_alloc_flags[6] = 1; + else + asm_alloc_flags[7] = 1; + break; + } + } +} + +const char *InlineAsm_GetMnemonic(InlineAsm *ia) { + return opcodeinfo[ia->opcode].name; +} + +static void savepicbase(short reg, HashNameNode *name) { + IALookupResult result; + + if (!InlineAsm_LookupSymbol(name, &result)) + result.label = InlineAsm_DeclareLabel(name); + + pic_base_label = result.label; + pic_base_reg = reg; + uses_globals = 1; +} + +static SInt32 InlineAsm_OpcodeSize(InlineAsm *ia) { + if (opcodeinfo[ia->opcode].flags & (fIsRead | fIsWrite)) { + switch (ia->opcode) { + case PC_LBZ: + case PC_LBZU: + case PC_LBZX: + case PC_LBZUX: + case PC_STB: + case PC_STBU: + case PC_STBX: + case PC_STBUX: + return 1; + case PC_LHZ: + case PC_LHZU: + case PC_LHZX: + case PC_LHZUX: + case PC_LHA: + case PC_LHAU: + case PC_LHAX: + case PC_LHAUX: + case PC_LHBRX: + case PC_STH: + case PC_STHU: + case PC_STHX: + case PC_STHUX: + case PC_STHBRX: + return 2; + case PC_LWZ: + case PC_LWZU: + case PC_LWZX: + case PC_LWZUX: + case PC_LWBRX: + case PC_STW: + case PC_STWU: + case PC_STWX: + case PC_STWUX: + case PC_STWBRX: + case PC_LFS: + case PC_LFSU: + case PC_LFSX: + case PC_LFSUX: + case PC_STFS: + case PC_STFSU: + case PC_STFSX: + case PC_STFSUX: + case PC_LWARX: + case PC_STFIWX: + case PC_STWCX: + case PC_ECIWX: + case PC_ECOWX: + case PC_MFROM: + case PC_LSCBX: + return 4; + case PC_LMW: + case PC_STMW: + if (ia->args[0].type == IAOpnd_Reg && ia->args[0].u.reg.object == NULL) + return (32 - ia->args[0].u.reg.num) * 4; + else + return 128; + case PC_LFD: + case PC_LFDU: + case PC_LFDX: + case PC_LFDUX: + case PC_STFD: + case PC_STFDU: + case PC_STFDX: + case PC_STFDUX: + return 8; + case PC_LSWI: + case PC_STSWI: + return ia->args[2].u.imm.value; + case PC_LSWX: + case PC_STSWX: + return 128; + case PC_LVEBX: + case PC_STVEBX: + return 1; + case PC_LVEHX: + case PC_STVEHX: + return 2; + case PC_LVEWX: + case PC_STVEWX: + return 4; + case PC_LVSL: + case PC_LVSR: + case PC_LVX: + case PC_LVXL: + case PC_STVX: + case PC_STVXL: + return 16; + default: + CError_FATAL(3924); + } + } else { + if (opcodeinfo[ia->opcode].flags & fOpTypeGPR) + return 4; + if (opcodeinfo[ia->opcode].flags & fOpTypeFPR) + return 8; + if (opcodeinfo[ia->opcode].flags & fOpTypeVR) + return 16; + + if (opcodeinfo[ia->opcode].flags & fSideEffects) { + switch (ia->opcode) { + case PC_TLBIE: + case PC_TLBLD: + case PC_TLBLI: + return 4; + default: + CError_FATAL(3941); + } + } + } + + CError_FATAL(3944); + return 0; +} + +void CodeGen_GetAsmEffects(Statement *stmt, IAEffects *effects) { + InlineAsm *ia; + OpcodeInfo *info; + int i; + IAOperand *op; + VarInfo *vi; + + ia = (InlineAsm *) stmt->expr; + info = &opcodeinfo[ia->opcode]; + + effects->numoperands = 0; + effects->numlabels = 0; + effects->x1 = 0; + effects->x2 = 0; + effects->x3 = 0; + effects->x4 = 0; + effects->x0 = 0; + effects->x5 = 0; + + if (info->flags & fIsPtrOp) { + if (info->flags & fIsRead) + effects->x1 = 1; + if (info->flags & fIsWrite) + effects->x2 = 1; + } + + if (PCODE_FLAG_SET_T(info) & fCanLink) { + if (ia->flags2 & IAFlagsB_8) + effects->x4 = 1; + else if ((info->flags & fIsCall) || (info->flags & fIsWrite)) + effects->x3 = 1; + + if (ia->opcode == PC_B) { + if (ia->args[0].type == IAOpnd_Imm) + effects->x0 = 1; + effects->x5 = 1; + } + } + + if (info->flags & fSideEffects) + effects->x0 = 1; + + if (ia->opcode == PC_BC && (ia->flags2 & IAFlagsB_8)) + effects->x4 = 1; + + for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { + switch (op->type) { + case IAOpnd_0: + case IAOpnd_Imm: + break; + case IAOpnd_Reg: + if (op->u.reg.object) { + if ((vi = Registers_GetVarInfo(op->u.reg.object))) + vi->flags |= VarInfoFlag40; + if (op->u.reg.effect & EffectRead) { + if ( + TYPE_FITS_IN_REGISTER(op->u.reg.object->type) || + IS_TYPE_FLOAT(op->u.reg.object->type) || + IS_TYPE_VECTOR(op->u.reg.object->type) + ) { + effects->operands[effects->numoperands].type = IAEffect_0; + effects->operands[effects->numoperands].object = op->u.reg.object; + effects->operands[effects->numoperands].offset = 0; + effects->operands[effects->numoperands].size = op->u.reg.object->type->size; + effects->numoperands++; + } else { + CError_FATAL(4051); + } + } + } + break; + case IAOpnd_3: + case IAOpnd_4: + if (op->u.obj.obj) { + if (info->flags & fIsRead) { + effects->operands[effects->numoperands].type = IAEffect_0; + effects->operands[effects->numoperands].object = op->u.obj.obj; + effects->operands[effects->numoperands].offset = op->u.obj.offset; + effects->operands[effects->numoperands].size = InlineAsm_OpcodeSize(ia); + effects->numoperands++; + } else if (!(info->flags & (fIsBranch | fIsCall))) { + effects->operands[effects->numoperands].type = IAEffect_3; + effects->operands[effects->numoperands].object = op->u.obj.obj; + effects->operands[effects->numoperands].offset = op->u.obj.offset; + effects->operands[effects->numoperands].size = InlineAsm_OpcodeSize(ia); + effects->numoperands++; + } + } + break; + case IAOpnd_Lab: + effects->labels[effects->numlabels] = op->u.lab.label; + effects->numlabels++; + break; + case IAOpnd_LabDiff: + effects->labels[effects->numlabels] = op->u.labdiff.label1; + effects->numlabels++; + effects->labels[effects->numlabels] = op->u.labdiff.label2; + effects->numlabels++; + effects->x3 = 1; + break; + default: + CError_FATAL(4087); + } + + CError_ASSERT(4090, (UInt32) effects->numoperands <= IAMaxOperands); + CError_ASSERT(4093, (UInt32) effects->numlabels <= IAMaxLabels); + } + + for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { + switch (op->type) { + case IAOpnd_Reg: + if (op->u.reg.object) { + if ((vi = Registers_GetVarInfo(op->u.reg.object))) + vi->flags |= VarInfoFlag40; + if (op->u.reg.effect & EffectWrite) { + if ( + TYPE_FITS_IN_REGISTER(op->u.reg.object->type) || + IS_TYPE_FLOAT(op->u.reg.object->type) || + IS_TYPE_VECTOR(op->u.reg.object->type) + ) { + effects->operands[effects->numoperands].type = IAEffect_1; + effects->operands[effects->numoperands].object = op->u.reg.object; + effects->operands[effects->numoperands].offset = 0; + effects->operands[effects->numoperands].size = op->u.reg.object->type->size; + effects->numoperands++; + } else { + CError_FATAL(4132); + } + } + } + break; + case IAOpnd_3: + case IAOpnd_4: + if (op->u.obj.obj) { + if (info->flags & fIsWrite) { + effects->operands[effects->numoperands].type = IAEffect_1; + effects->operands[effects->numoperands].object = op->u.obj.obj; + effects->operands[effects->numoperands].offset = op->u.obj.offset; + effects->operands[effects->numoperands].size = InlineAsm_OpcodeSize(ia); + effects->numoperands++; + } + } + break; + } + + CError_ASSERT(4151, (UInt32) effects->numoperands <= IAMaxOperands); + } + + if ((info->flags & (fIsBranch | fIsCall)) && (SInt32)effects->numlabels == 0) + effects->x3 = 1; +} + +void CodeGen_PropagateIntoAsm(Statement *stmt, Object *obj, ENode *expr) { + InlineAsm *ia; + Object *newobj; + + ia = (InlineAsm *) stmt->expr; + if (ENODE_IS(expr, EOBJREF)) { + newobj = expr->data.objref; + if (obj->otype == newobj->otype && obj->datatype == newobj->datatype) { + int i; + for (i = 0; i < ia->argcount; i++) { + switch (ia->args[i].type) { + case IAOpnd_Reg: + if (ia->args[i].u.reg.object == obj && + (ia->args[i].u.reg.effect & (EffectRead | EffectWrite)) == EffectRead) { + if (TYPE_FITS_IN_REGISTER(newobj->type) && + ia->args[i].u.reg.rclass == RegClass_GPR) { + ia->args[i].u.reg.object = newobj; + } else if (IS_TYPE_FLOAT(newobj->type) && + ia->args[i].u.reg.rclass == RegClass_FPR) { + ia->args[i].u.reg.object = newobj; + } else if (IS_TYPE_VECTOR(newobj->type) && + ia->args[i].u.reg.rclass == RegClass_VR) { + ia->args[i].u.reg.object = newobj; + } + } + break; + case IAOpnd_3: + case IAOpnd_4: + if (!(opcodeinfo[ia->opcode].flags & (fIsWrite | fPCodeFlag40000)) && + ia->args[i].u.obj.obj == obj) + ia->args[i].u.obj.obj = newobj; + break; + } + } + } + } +} + +Statement *CodeGen_CopyAsmStat(Statement *stmt) { + Statement *copy; + SInt32 size; + InlineAsm *ia; + InlineAsm *iacopy; + + copy = galloc(sizeof(Statement)); + *copy = *stmt; + + ia = (InlineAsm *) stmt->expr; + size = sizeof(InlineAsm) + sizeof(IAOperand) * ia->argcount; + iacopy = galloc(size); + memcpy(iacopy, ia, size); + copy->expr = (ENode *) iacopy; + + return copy; +} + diff --git a/compiler_and_linker/BackEnd/PowerPC/PCode/PCodeInfo.c b/compiler_and_linker/BackEnd/PowerPC/PCode/PCodeInfo.c new file mode 100644 index 0000000..b2e2385 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/PCode/PCodeInfo.c @@ -0,0 +1,1354 @@ +#include "compiler/PCodeInfo.h" +#include "compiler/CError.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/Alias.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/PCode.h" +#include "compiler/PCodeListing.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/TOC.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +#pragma pool_strings on + +int pcode_bad_operand; +char *orig_buf; +static int do_show_basic_blocks; + +void pcode_get_hi_lo(int bits, char typechar, SInt32 *hi, SInt32 *lo) { + if (bits == 0) { + *hi = 0; + *lo = 0; + return; + } + if (bits == 32) { + *hi = 0x7FFFFFFF; + *lo = -0x80000000; + return; + } + + if (bits < 32 && bits > 0) { + switch (typechar) { + case 'u': + *hi = (1 << bits) - 1; + *lo = 0; + break; + case 'i': + case 'x': + *hi = (1 << bits) - 1; + *lo = -(1 << (bits - 1)); + break; + default: + *hi = (1 << (bits - 1)) - 1; + *lo = -(1 << (bits - 1)); + } + } else { + CError_FATAL(65); + } +} + +int pcode_check_imm_bits(SInt32 value, int bits, char typechar) { + char buf[2]; + int forcedBits; + SInt32 r6; + SInt32 r0; + + forcedBits = 0; + if (bits >= 0 && bits < 32) { + if (bits == 0) { + r6 = 0; + r0 = 0; + } else { + switch (typechar) { + case 'u': + r6 = (1 << bits) - 1; + r0 = 0; + break; + case 'i': + case 'x': + r6 = (1 << bits) - 1; + r0 = -(1 << (bits - 1)); + break; + case '1': + case '2': + case '3': + case '4': + buf[0] = typechar; + buf[1] = 0; + forcedBits = atoi(buf); + default: + r6 = (1 << (bits - 1)) - 1; + r0 = -(1 << (bits - 1)); + } + } + + if ((value < r0) || (value > r6)) + return 1; + if (forcedBits > 0 && value != ((value >> forcedBits) << forcedBits)) + return 1; + } else if (bits > 32) { + CError_FATAL(110); + } + + return 0; +} + +int pcode_const_from_format(const char *format, SInt32 *pResult) { + char buf[32]; + int len = 0; + + for (len = 0; len < 30 && isdigit(format[len]); len++) { + buf[len] = format[len]; + } + buf[len] = 0; + + *pResult = atoi(buf); + return len; +} + +PCode *vformatpcode(short opcode, va_list argList) { + // has many wrong registers but probably ok otherwise + int argcount; // r29 + OpcodeInfo *info; // r27 for a short time + int effect; // r27 + const char *format; // r26 + PCode *pcode; // r25 + PCodeArg *arg; // r24 + int unkreg_r23; // r23 + int unkreg_r22; // r22 + PCodeArg *lastArg; // r21 + int pcode_size; // r20 for a short time + int tmp; + int tmp2; // r19 + int i; + SInt32 thing; + SInt32 thing2; + SInt32 thing3; + SInt32 thing4; + Object *obj; + PCodeLabel *label; + char c; + + info = &opcodeinfo[opcode]; + format = info->format; + argcount = info->x8; + unkreg_r23 = 0; + unkreg_r22 = 0; + + if (format[0] == '#') { + unkreg_r23 = va_arg(argList, int); + argcount += unkreg_r23; + format++; + } + + if (info->flags & fCanSetRecordBit) + unkreg_r22 = 1; + + if ((argcount + unkreg_r22) < 5) + unkreg_r22 += 5 - (argcount + unkreg_r22); + + pcode_size = (argcount + unkreg_r22) * sizeof(PCodeArg) + sizeof(PCode); + pcode = lalloc(pcode_size); + memclrw(pcode, pcode_size); + + pcode->op = opcode; + pcode->argCount = argcount; + pcode->flags = info->flags; + lastArg = pcode->args + pcode->argCount; + arg = pcode->args; + while (*format) { + if (arg >= lastArg) + CError_FATAL(189); + + if (*format == ',' || *format == ';') + format++; + if (*format == '[' || *format == '(') + format++; + + effect = EffectRead; + if (*format == '=') { + effect = EffectWrite; + format++; + } else if (*format == '+') { + effect = EffectRead | EffectWrite; + format++; + } + + if (*format == '-') + format++; + if (*format == '?') + format++; + if (*format == '!') + format++; + + switch ((c = *format)) { + case 'b': + tmp = va_arg(argList, int); + if (!tmp) + effect = 0; + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_GPR; + arg->data.reg.reg = tmp; + arg->data.reg.effect = effect; + break; + case 'r': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_GPR; + arg->data.reg.reg = va_arg(argList, int); + arg->data.reg.effect = effect; + break; + case 'f': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_FPR; + arg->data.reg.reg = va_arg(argList, int); + arg->data.reg.effect = effect; + break; + case 'v': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_VR; + arg->data.reg.reg = va_arg(argList, int); + arg->data.reg.effect = effect; + break; + case 'c': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_CRFIELD; + arg->data.reg.reg = va_arg(argList, int); + arg->data.reg.effect = effect; + break; + case 'C': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_SPR; + arg->data.reg.reg = 2; + arg->data.reg.effect = effect; + break; + case 'L': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_SPR; + arg->data.reg.reg = 1; + arg->data.reg.effect = effect; + break; + case 'V': + i = unkreg_r23; + while (i > 0) { + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_GPR; + arg->data.reg.reg = 31 - --i; + arg->data.reg.effect = effect; + arg++; + } + arg--; + break; + case 'X': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_SPR; + arg->data.reg.reg = 0; + arg->data.reg.effect = effect; + break; + case 'Y': + if (pcode->op == PC_MTCRF) { + tmp = pcode->args[0].data.imm.value; + for (i = 0; i < 8; i++) { + if (tmp & (0x80 >> i)) { + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_CRFIELD; + arg->data.reg.reg = i; + arg->data.reg.effect = EffectWrite; + arg++; + } + } + } else { + i = 0; + while (i < 8) { + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_CRFIELD; + arg->data.reg.reg = i++; + arg->data.reg.effect = EffectRead; + arg++; + } + } + arg--; + break; + case 'Z': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_CRFIELD; + arg->data.reg.reg = 0; + arg->data.reg.effect = effect; + break; + case 'P': + if (isdigit(format[1])) + format += pcode_const_from_format(format + 1, &thing); + else + CError_FATAL(319); + case 's': + tmp = va_arg(argList, int); + tmp2 = -1; + for (i = 0; i < 4; i++) { + if (tmp == spr_to_sysreg[i]) { + tmp2 = i; + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_SPR; + arg->data.reg.reg = i; + arg->data.reg.effect = effect; + if ((effect & EffectWrite) && (tmp == 0x100)) + pcsetsideeffects(pcode); + break; + } + } + + if (tmp2 < 0) { + pcsetsideeffects(pcode); + arg->kind = PCOp_SYSREG; + arg->arg = RegClass_SPR; + arg->data.reg.reg = tmp; + arg->data.reg.effect = effect; + } + + break; + + case 'T': + tmp = va_arg(argList, int); + if (tmp == 0x10C) { + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_SPR; + arg->data.reg.reg = 0x11C; + arg->data.reg.effect = effect; + } else if (tmp == 0x10D) { + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_SPR; + arg->data.reg.reg = 0x11D; + arg->data.reg.effect = effect; + } else { + CError_FATAL(353); + } + pcsetsideeffects(pcode); + arg->kind = PCOp_SYSREG; + arg->arg = RegClass_SPR; + arg->data.reg.reg = va_arg(argList, int); + arg->data.reg.effect = effect; + break; + + case 'S': + tmp2 = -1; + if (isdigit(format[1])) + format += pcode_const_from_format(format + 1, &thing2); + else + CError_FATAL(371); + + for (i = 0; i < 4; i++) { + if (thing2 == spr_to_sysreg[i]) { + tmp2 = i; + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_SPR; + arg->data.reg.reg = i; + arg->data.reg.effect = effect; + if ((effect & EffectWrite) && (thing2 == 0x100)) + pcsetsideeffects(pcode); + break; + } + } + + if (tmp2 < 0) { + pcsetsideeffects(pcode); + arg->kind = PCOp_SYSREG; + arg->arg = RegClass_SPR; + arg->data.reg.reg = va_arg(argList, int); + arg->data.reg.effect = effect; + } + break; + + case 'a': + case 'i': + case 'n': + case 'u': + case 'w': + case 'x': + tmp2 = (unsigned char) c; + thing3 = 16; + if (*format == 'a') { + if (isdigit(format[1])) + tmp2 = (unsigned char) *(++format); + else + CError_FATAL(408); + } + if (isdigit(format[1])) { + format += pcode_const_from_format(format + 1, &thing3); + } + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.value = va_arg(argList, int); + arg->data.imm.obj = NULL; + if (pcode_check_imm_bits(arg->data.imm.value, thing3, tmp2)) + CError_FATAL(419); + break; + + case 'N': + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.value = va_arg(argList, int); + arg->data.imm.obj = NULL; + if (pcode_check_imm_bits(arg->data.imm.value, 6, 'u')) + CError_FATAL(429); + break; + + case 'D': + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.value = va_arg(argList, int); + arg->data.imm.obj = NULL; + if (pcode_check_imm_bits(arg->data.imm.value, 10, 'u')) + CError_FATAL(438); + break; + + case 'B': + case 't': + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.value = va_arg(argList, int); + arg->data.imm.obj = NULL; + if (pcode_check_imm_bits(arg->data.imm.value, 5, 'u')) + CError_FATAL(448); + break; + + case 'Q': + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_CRFIELD; + arg->data.reg.reg = va_arg(argList, int); + arg->data.reg.effect = effect; + arg++; + case 'q': + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.value = va_arg(argList, int); + arg->data.imm.obj = NULL; + if (pcode_check_imm_bits(arg->data.imm.value, 4, 'u')) + CError_FATAL(463); + break; + + case 'l': + if ((label = va_arg(argList, PCodeLabel *))) { + arg->kind = PCOp_LABEL; + arg->data.label.label = label; + } else { + arg->kind = PCOp_MEMORY; + obj = va_arg(argList, Object *); + CError_ASSERT(476, obj->otype == OT_OBJECT); + arg->data.mem.obj = obj; + arg->data.mem.offset = 0; + arg->arg = RefType_4; + } + break; + + case 'd': + CError_ASSERT(490, format[1] == '('); + effect = EffectRead; + format += 2; + if (*format == '=') { + effect = EffectWrite; + format++; + } else if (*format == '+') { + effect = EffectRead | EffectWrite; + format++; + } + + CError_ASSERT(502, format[0] == 'b'); + + tmp = va_arg(argList, int); + if (tmp == 0) + effect = 0; + arg->kind = PCOp_REGISTER; + arg->arg = RegClass_GPR; + arg->data.reg.reg = tmp; + arg->data.reg.effect = effect; + arg++; + + case 'm': + obj = va_arg(argList, Object *); + if (obj) { + CError_ASSERT(515, obj->otype == OT_OBJECT); + + if (obj->datatype == DABSOLUTE) { + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.obj = obj; + arg->data.imm.value = va_arg(argList, SInt32); + } else { + arg->kind = PCOp_MEMORY; + arg->data.mem.obj = obj; + arg->data.mem.offset = va_arg(argList, SInt32); + + if (pcode->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) { + pcode->alias = make_alias(obj, arg->data.mem.offset, nbytes_loaded_or_stored_by(pcode)); + if (is_volatile_object(obj)) + pcode->flags |= fIsVolatile; + //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_CONST) : (obj->qual & Q_CONST)) + if (OBJ_GET_TARGET_CONST(obj)) + pcode->flags |= fIsConst; + } else { + if (pcode->op == PC_ADDI) + pcode->alias = make_alias(obj, arg->data.mem.offset, 1); + } + CError_ASSERT(536, obj->datatype == DLOCAL || arg->data.mem.offset == 0); + if (pcode->flags & (fIsRead | fIsWrite)) { + //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_VOLATILE) : (obj->qual & Q_VOLATILE)) + if (OBJ_GET_TARGET_VOLATILE(obj)) + pcode->flags |= fIsVolatile; + //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_CONST) : (obj->qual & Q_CONST)) + if (OBJ_GET_TARGET_CONST(obj)) + pcode->flags |= fIsConst; + } + + if (pcode->flags & (fIsBranch | fIsCall)) { + arg->arg = RefType_4; + } else if (obj->datatype == DLOCAL) { + if (!local_is_16bit_offset(obj)) + arg->arg = RefType_D; + else + arg->arg = RefType_1; + } else { + arg->arg = RefType_6; + } + } + } else { + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.value = va_arg(argList, SInt32); + arg->data.imm.obj = NULL; + if (pcode->flags & (fIsRead | fIsWrite)) + pcode->flags |= fIsPtrOp; + } + break; + + case 'M': + obj = va_arg(argList, Object *); + if (obj) { + CError_ASSERT(578, obj->otype == OT_OBJECT); + + if (obj->datatype == DABSOLUTE) { + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.obj = obj; + arg->data.imm.value = va_arg(argList, SInt32); + } else { + arg->kind = PCOp_MEMORY; + arg->data.mem.obj = obj; + arg->data.mem.offset = va_arg(argList, SInt32); + + CError_ASSERT(590, obj->datatype == DLOCAL || arg->data.mem.offset == 0); + if (pcode->flags & (fIsRead | fIsWrite)) { + //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_VOLATILE) : (obj->qual & Q_VOLATILE)) + if (OBJ_GET_TARGET_VOLATILE(obj)) + pcode->flags |= fIsVolatile; + //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_CONST) : (obj->qual & Q_CONST)) + if (OBJ_GET_TARGET_CONST(obj)) + pcode->flags |= fIsConst; + } + + if (obj->datatype == DLOCAL) { + arg->arg = RefType_C; + } else { + arg->arg = RefType_8; + } + } + } else { + arg->kind = PCOp_IMMEDIATE; + arg->data.imm.value = va_arg(argList, SInt32); + arg->data.imm.obj = NULL; + if (pcode->flags & (fIsRead | fIsWrite)) + pcode->flags |= fIsPtrOp; + } + break; + + case 'p': + arg->kind = PCOp_PLACEHOLDEROPERAND; + break; + + case 'O': + arg--; + break; + + default: + CError_FATAL(629); + } + + while (format[1] && strchr("/<>|*", format[1])) { + switch (*(++format)) { + case '/': + if (format[1] == '2') + format++; + break; + case '<': + case '*': + case '|': + case '>': + if (format[1] == 'p') + format++; + else if (isdigit(format[1])) + format += pcode_const_from_format(format + 1, &thing4); + else + CError_FATAL(659); + break; + } + } + + if ((c = *(++format)) == ']' || c == ')') + format++; + arg++; + } + + while (arg < lastArg) { + arg->kind = PCOp_PLACEHOLDEROPERAND; + arg++; + } + while (unkreg_r22) { + arg->kind = PCOp_PLACEHOLDEROPERAND; + arg++; + unkreg_r22--; + } + return pcode; +} + +int expectandformatoperand(PCodeArg *operand, PCOpKind expectedKind, char a3, int bitCount, char *buf) { + int errorlen; + char *name; + int tmp; + int regclass; + int refis1; + int b_null; + + errorlen = 0; + + if (operand->kind != expectedKind) { + char *kindstr; + switch (expectedKind) { + case PCOp_REGISTER: kindstr = "REGISTER"; break; + case PCOp_SYSREG: kindstr = "SYSREG"; break; + case PCOp_IMMEDIATE: kindstr = "IMMEDIATE"; break; + case PCOp_MEMORY: kindstr = "MEMORY"; break; + case PCOp_LABEL: kindstr = "LABEL"; break; + case PCOp_LABELDIFF: kindstr = "LABELDIFF"; break; + case PCOp_PLACEHOLDEROPERAND: kindstr = "PLACEHOLDEROPERAND"; break; + default: kindstr = "unknown kind"; + } + tmp = sprintf(buf, "{EXPECTED %s}", kindstr); + errorlen += tmp; + buf += tmp; + pclist_bad_operand = 1; + } + + switch (operand->kind) { + case PCOp_REGISTER: + if (operand->arg != (regclass = a3)) { + tmp = sprintf(buf, "{EXPECTED %s}", register_class_name[regclass]); + errorlen += tmp; + buf += tmp; + } + if (operand->data.reg.reg < n_real_registers[regclass] && (name = special_register_names[operand->arg][operand->data.reg.reg])) + tmp = sprintf(buf, "%s", name); + else + tmp = sprintf(buf, register_class_format[operand->arg], operand->data.reg.reg); + errorlen += tmp; + break; + case PCOp_SYSREG: + if (operand->arg != RegClass_SPR) { + tmp = sprintf(buf, "{EXPECTED %s}", register_class_name[RegClass_SPR]); + errorlen += tmp; + buf += tmp; + } + tmp = sprintf(buf, register_class_format[RegClass_SPR], operand->data.reg.reg); + errorlen += tmp; + break; + case PCOp_IMMEDIATE: + switch (a3) { + case 'x': + tmp = sprintf(buf, "0x%x", operand->data.imm.value); + break; + case 'u': + tmp = sprintf(buf, "%u", operand->data.imm.value); + break; + default: + tmp = sprintf(buf, "%" PRId32, operand->data.imm.value); + break; + } + errorlen += tmp; + buf += tmp; + if (operand->data.imm.obj) { + name = CMangler_GetLinkName(operand->data.imm.obj)->name; + if (strlen(name) > 50) + tmp = sprintf(buf, "{%45.45s...}", name); + else + tmp = sprintf(buf, "{%s}", name); + errorlen += tmp; + buf += tmp; + } + if (pcode_check_imm_bits(operand->data.imm.value, bitCount, (char) a3)) { + errorlen += sprintf(buf, "{IMM too large %i bits}", bitCount); + pclist_bad_operand = 1; + } + break; + case PCOp_MEMORY: + switch ((unsigned char) operand->arg) { + case RefType_0: + case RefType_1: + case RefType_2: + case RefType_3: + case RefType_4: + case RefType_5: + case RefType_9: + break; + case RefType_8: + case RefType_B: + case RefType_C: + tmp = sprintf(buf, "HA("); + errorlen += tmp; + buf += tmp; + break; + case RefType_7: + tmp = sprintf(buf, "HI("); + errorlen += tmp; + buf += tmp; + break; + case RefType_6: + case RefType_A: + case RefType_D: + tmp = sprintf(buf, "LO("); + errorlen += tmp; + buf += tmp; + break; + default: + tmp = sprintf(buf, "{UNEXPECTED reftype = %d}", (unsigned char) operand->arg); + errorlen += tmp; + buf += tmp; + } + name = CMangler_GetLinkName(operand->data.mem.obj)->name; + if (strlen(name) == 0 || strlen(name) > 3200 || name[0] < 0) + CError_FATAL(849); + if (strlen(name) > 50) + tmp = sprintf(buf, "%45.45s...", name); + else + tmp = sprintf(buf, "%s", name); + errorlen += tmp; + buf += tmp; + if (operand->data.mem.offset > 0) + tmp = sprintf(buf, "+%d", operand->data.mem.offset); + else if (operand->data.mem.offset != 0) + tmp = sprintf(buf, "-%d", -operand->data.mem.offset); + else + tmp = 0; + errorlen += tmp; + buf += tmp; + if (copts.codegen_pic && uses_globals && pic_base_reg) { + tmp = sprintf(buf, "-B%d", pic_base_pcodelabel->block->blockIndex); + errorlen += tmp; + buf += tmp; + } + switch ((unsigned char) operand->arg) { + case RefType_6: + case RefType_7: + case RefType_8: + case RefType_A: + case RefType_B: + case RefType_C: + case RefType_D: + errorlen += sprintf(buf, ")"); + } + break; + case PCOp_LABEL: + if (do_show_basic_blocks) { + if (!operand->data.label.label->block) + tmp = sprintf(buf, "B"); + else + tmp = sprintf(buf, "B%" PRId32, operand->data.label.label->block->blockIndex); + } else { + tmp = sprintf(buf, "%.8" PRIX32, operand->data.label.label->block->codeOffset); + } + errorlen += tmp; + break; + case PCOp_LABELDIFF: + refis1 = ((unsigned char) operand->arg == 1); + b_null = !operand->data.labeldiff.labelB->block; + if (operand->data.labeldiff.labelA->block == NULL) { + if (b_null) + tmp = sprintf(buf, "%sB-B+%" PRId32, refis1 ? "-" : "", operand->data.labeldiff.offset); + else + tmp = sprintf(buf, "%sB-B%" PRId32 "+%" PRId32, refis1 ? "-" : "", operand->data.labeldiff.labelB->block->blockIndex, operand->data.labeldiff.offset); + } else { + if (b_null) + tmp = sprintf(buf, "%sB%" PRId32 "-B+%" PRId32, refis1 ? "-" : "", operand->data.labeldiff.labelA->block->blockIndex, operand->data.labeldiff.offset); + else + tmp = sprintf(buf, "%sB%" PRId32 "-B%" PRId32 "+%" PRId32, refis1 ? "-" : "", operand->data.labeldiff.labelA->block->blockIndex, operand->data.labeldiff.labelB->block->blockIndex, operand->data.labeldiff.offset); + } + errorlen += tmp; + break; + case PCOp_PLACEHOLDEROPERAND: + errorlen += sprintf(buf, "{placeholder}"); + break; + default: + errorlen += sprintf(buf, "{UNEXPECTED kind = %d}", operand->kind); + } + + return errorlen; +} + +int formatoperand(PCodeArg *operand, char *buf) { + return expectandformatoperand( + operand, + operand->kind, + (operand->kind == PCOp_REGISTER) ? operand->arg : 'x', + -1, + buf); +} + +void formatoperands(PCode *pcode, char *buf, int showBasicBlocks) { + const char *format; // r29 + // there might be a PCodeArg *arg in r28 + // not sure lol + PCodeArg *pa; + int arg_index; // r27 + + char *name; + int i; + int tmp; + int tmp2; + SInt32 thing; + SInt32 thing2; + SInt32 thing4; + char c; + int flagSetT; + int flagSetF; + + static char *cc[] = { + "lt", "gt", "eq", "un" + }; + static char *to[] = { + "", "lgt", "llt", "", + "eq", "lge", "lle", "", + "gt", "", "", "", + "ge", "", "", "", + "lt", "", "", "", + "le", "", "", "", + "ne", "", "", "", + "", "", "" + }; + + format = opcodeinfo[pcode->op].format; + orig_buf = buf; + do_show_basic_blocks = showBasicBlocks; + + if (format[0] == '#') { + format++; + if (format[0] == ',') + format++; + } + + arg_index = 0; + pa = pcode->args; + while (*format) { + if (*format == ';') + break; + if (arg_index == pcode->argCount) { + pclist_bad_operand = 1; + buf += sprintf(buf, "{EXCEDED noperands, remaning format = %s}", format); + break; + } + + if (*format == ',') { + *(buf++) = ','; + format++; + } + + if (*format == '[' || *format == '(') { + *(buf++) = *format; + format++; + } + + if (*format == '=' || *format == '+') + format++; + if (*format == '-') + format++; + + if (*format == '?') { + format++; + if (*format != 'c') + *(buf++) = ','; + } + + if (*format == '!') + format++; + + switch (*format) { + case 'b': + if (pa->kind == PCOp_REGISTER && pa->arg == RegClass_GPR && pa->data.reg.reg == 0) { + if (pa->data.reg.effect & EffectWrite) { + pclist_bad_operand = 1; + buf += sprintf(buf, "!!!r"); + } + buf += sprintf(buf, "0"); + break; + } + case 'r': + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_GPR, -1, buf); + break; + case 'f': + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_FPR, -1, buf); + break; + case 'v': + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_VR, -1, buf); + break; + case 'c': + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_CRFIELD, -1, buf); + break; + case 'X': + CError_ASSERT(1124, pa->data.reg.reg == 0); + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); + break; + case 'C': + CError_ASSERT(1129, pa->data.reg.reg == 2); + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); + break; + case 'L': + CError_ASSERT(1134, pa->data.reg.reg == 1); + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); + break; + case 'Z': + CError_ASSERT(1139, pa->data.reg.reg == 0); + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); + break; + case 'P': + if (isdigit(format[1])) + format += pcode_const_from_format(format + 1, &thing); + else + CError_FATAL(1149); + case 'S': + case 'T': + case 's': + if (pa->kind == PCOp_REGISTER && pa->arg == RegClass_SPR) { + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); + } else { + for (i = 0; i < 4; i++) { + if (pa->data.reg.reg == spr_to_sysreg[i]) { + CError_FATAL(1161); + break; + } + } + + buf += expectandformatoperand(pa, PCOp_SYSREG, RegClass_SPR, -1, buf); + } + break; + + case 'V': + do { + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_GPR, -1, buf); + *(buf++) = ','; + pa++; + arg_index++; + } while (arg_index < pcode->argCount && pa->kind == PCOp_REGISTER && pa->arg == RegClass_GPR); + buf--; + pa--; + arg_index--; + break; + + case 'Y': + do { + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_CRFIELD, -1, buf); + *(buf++) = ','; + pa++; + arg_index++; + } while (arg_index < pcode->argCount && pa->kind == PCOp_REGISTER && pa->arg == RegClass_CRFIELD); + buf--; + pa--; + arg_index--; + break; + + case 'Q': + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_CRFIELD, -1, buf); + *(buf++) = ','; + pa++; + arg_index++; + case 'q': + if (pa->kind == PCOp_IMMEDIATE && pa->data.imm.value >= 0 && pa->data.imm.value < 4 && (name = cc[pa->data.imm.value])[0]) { + buf += sprintf(buf, "%s", name); + } else { + buf += sprintf(buf, "{OUT OF RANGE}"); + buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 0, -1, buf); + } + break; + case 'a': + case 'i': + case 'u': + case 'x': + tmp = *format; + if (tmp == 'a') { + if (isdigit(format[1])) { + format++; + tmp = *format; + } else { + CError_FATAL(1227); + } + } + if ((tmp2 = isdigit(format[1]))) + format += pcode_const_from_format(format + 1, &thing2); + if (!tmp2) + thing2 = -1; + buf += expectandformatoperand(pa, PCOp_IMMEDIATE, tmp, thing2, buf); + break; + + case 'N': + buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 'u', 6, buf); + break; + + case 'D': + buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 'u', 10, buf); + break; + + case 't': + if (pa->kind == PCOp_IMMEDIATE && pa->data.imm.value > 0 && pa->data.imm.value < 31 && (name = to[pa->data.imm.value])[0]) { + buf += sprintf(buf, "%s", name); + break; + } + + case 'B': + buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 'x', 5, buf); + break; + + case 'l': + if (pa->kind == PCOp_IMMEDIATE) { + buf += sprintf(buf, "*%s%" PRId32, (pa->data.imm.value >= 0) ? "+" : "", pa->data.imm.value); + } else if (pa->kind == PCOp_LABELDIFF) { + buf += expectandformatoperand(pa, PCOp_LABELDIFF, 0, -1, buf); + } else if (pa->kind == PCOp_LABEL) { + buf += expectandformatoperand(pa, PCOp_LABEL, 0, -1, buf); + } else { + buf += expectandformatoperand(pa, PCOp_MEMORY, 0, -1, buf); + } + break; + + case 'd': + if (pa[1].kind == PCOp_MEMORY) + buf += expectandformatoperand(pa + 1, PCOp_MEMORY, 0, -1, buf); + else + buf += expectandformatoperand(pa + 1, PCOp_IMMEDIATE, 0, -1, buf); + CError_ASSERT(1283, format[1] == '('); + format++; + *(buf++) = *(format++); + if (*format == '+') + format++; + CError_ASSERT(1291, format[0] == 'b'); + if (pa->kind == PCOp_REGISTER && pa->arg == RegClass_GPR && pa->data.reg.reg == 0) { + if (pa->data.reg.effect & (EffectRead | EffectWrite)) { + pclist_bad_operand = 1; + buf += sprintf(buf, "!!!r"); + } + buf += sprintf(buf, "0"); + } else { + buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_GPR, -1, buf); + } + pa++; + i++; + break; + + case 'w': + if (pa->kind == PCOp_LABELDIFF) + buf += expectandformatoperand(pa, PCOp_LABELDIFF, 0, -1, buf); + else + buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 0, -1, buf); + break; + + case 'm': + case 'n': + if (pa->kind == PCOp_MEMORY) + buf += expectandformatoperand(pa, PCOp_MEMORY, 0, -1, buf); + else if (pa->kind == PCOp_LABELDIFF) + buf += expectandformatoperand(pa, PCOp_LABELDIFF, 0, -1, buf); + else if ((pcode->flags & (fIsBranch | fIsCall)) && (pa->kind == PCOp_LABEL)) + buf += expectandformatoperand(pa, PCOp_LABEL, 0, -1, buf); + else + buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 0, -1, buf); + break; + + case 'M': + if (pa->kind == PCOp_MEMORY) { + CError_ASSERT(1335, pa->arg == RefType_8 || pa->arg == RefType_B || pa->arg == RefType_C); + buf += expectandformatoperand(pa, PCOp_MEMORY, 0, -1, buf); + } else if (pa->kind == PCOp_LABELDIFF) + buf += expectandformatoperand(pa, PCOp_LABELDIFF, 0, -1, buf); + else + buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 0, -1, buf); + break; + + case 'O': + pa--; + arg_index--; + break; + + case 'p': + buf += expectandformatoperand(pa, PCOp_PLACEHOLDEROPERAND, 0, -1, buf); + break; + + default: + CError_FATAL(1465); + } + + while (format[1] && strchr("/<>|*", format[1])) { + switch (*(++format)) { + case '/': + if (format[1] == '2') + format++; + break; + case '<': + case '*': + case '|': + case '>': + if (format[1] == 'p') + format++; + else if (isdigit(format[1])) + format += pcode_const_from_format(format + 1, &thing4); + else + CError_FATAL(1495); + break; + } + } + + if ((c = *(++format)) == ']' || c == ')') { + *(buf++) = c; + format++; + } + + pa++; + arg_index++; + } + + if (buf[-1] == ',') + buf--; + + flagSetT = PCODE_FLAG_SET_T(pcode); + flagSetF = PCODE_FLAG_SET_F(pcode); + if (pcode->flags & fIsConst) + buf += sprintf(buf, "; fIsConst"); + if (pcode->flags & fIsVolatile) + buf += sprintf(buf, "; fIsVolatile"); + if (pcode->flags & fSideEffects) + buf += sprintf(buf, "; fSideEffects"); + if (pcode->flags & fIsCSE) + buf += sprintf(buf, "; fIsCSE"); + if (pcode->flags & fCommutative) + buf += sprintf(buf, "; fCommutative"); + + if (flagSetF & fIsPtrOp) + buf += sprintf(buf, "; fIsPtrOp"); + + if (flagSetT) { + if (flagSetT & fLink) + buf += sprintf(buf, "; fLink"); + if (flagSetT & fAbsolute) + buf += sprintf(buf, "; fAbsolute"); + if (flagSetT & fBranchTaken) + buf += sprintf(buf, "; fBranchTaken"); + if (flagSetT & fBranchNotTaken) + buf += sprintf(buf, "; fBranchNotTaken"); + } else if (flagSetF) { + if (flagSetF & fSetsCarry) + buf += sprintf(buf, "; fSetsCarry"); + if (flagSetF & fOverflow) + buf += sprintf(buf, "; fOverflow"); + } + + *buf = 0; +} + +PCode *makecopyinstruction(PCodeArg *a, PCodeArg *b) { + if (b->kind == PCOp_REGISTER) { + switch (b->arg) { + case RegClass_GPR: + return makepcode(PC_MR, b->data.reg.reg, a->data.reg.reg); + case RegClass_FPR: + return makepcode(PC_FMR, b->data.reg.reg, a->data.reg.reg); + case RegClass_VR: + return makepcode(PC_VMR, b->data.reg.reg, a->data.reg.reg); + case RegClass_CRFIELD: + return makepcode(PC_MCRF, b->data.reg.reg, a->data.reg.reg); + } + } + + CError_FATAL(1622); + return NULL; +} + +int is_location_independent(PCode *pcode) { + switch (pcode->op) { + case PC_LI: + case PC_LIS: + case PC_VSPLTISB: + case PC_VSPLTISH: + case PC_VSPLTISW: + return 1; + case PC_ADDI: + case PC_ADDIS: + case PC_ORI: + case PC_ORIS: + return pcode->args[1].data.reg.reg == _FP_; + case PC_LWZ: + if ( + pcode->args[1].data.reg.reg == 1 && + pcode->args[2].kind == PCOp_IMMEDIATE && + pcode->args[2].data.imm.value == 0 + ) + return 1; + } + + return 0; +} + +int can_reuse_stored_value(PCode *a, PCode *b) { + switch (b->op) { + case PC_LWZ: + case PC_LWZU: + case PC_LWZX: + case PC_LWZUX: + switch (a->op) { + case PC_STW: + case PC_STWU: + case PC_STWX: + case PC_STWUX: + return 1; + } + break; + + case PC_LFD: + case PC_LFDU: + case PC_LFDX: + case PC_LFDUX: + switch (a->op) { + case PC_STFD: + case PC_STFDU: + case PC_STFDX: + case PC_STFDUX: + return 1; + } + break; + + case PC_LVX: + if (a->op == PC_STVX) + return 1; + break; + } + + return 0; +} + +int nbytes_loaded_or_stored_by(PCode *pcode) { + OpcodeInfo *oinfo = opcodeinfo + pcode->op; + if (oinfo->flags & (fIsRead | fIsWrite)) { + switch (pcode->op) { + case PC_LBZ: + case PC_LBZU: + case PC_LBZX: + case PC_LBZUX: + case PC_STB: + case PC_STBU: + case PC_STBX: + case PC_STBUX: + return 1; + case PC_LHZ: + case PC_LHZU: + case PC_LHZX: + case PC_LHZUX: + case PC_LHA: + case PC_LHAU: + case PC_LHAX: + case PC_LHAUX: + case PC_LHBRX: + case PC_STH: + case PC_STHU: + case PC_STHX: + case PC_STHUX: + case PC_STHBRX: + return 2; + case PC_LWZ: + case PC_LWZU: + case PC_LWZX: + case PC_LWZUX: + case PC_LWBRX: + case PC_STW: + case PC_STWU: + case PC_STWX: + case PC_STWUX: + case PC_STWBRX: + case PC_LFS: + case PC_LFSU: + case PC_LFSX: + case PC_LFSUX: + case PC_STFS: + case PC_STFSU: + case PC_STFSX: + case PC_STFSUX: + case PC_LWARX: + case PC_STFIWX: + case PC_STWCX: + case PC_ECIWX: + case PC_ECOWX: + case PC_MFROM: + case PC_LSCBX: + return 4; + case PC_LMW: + case PC_STMW: + if (pcode->args[0].kind == PCOp_REGISTER && pcode->args[0].arg == RegClass_GPR) + return (32 - pcode->args[0].data.reg.reg) * 4; + else + return 128; + case PC_LFD: + case PC_LFDU: + case PC_LFDX: + case PC_LFDUX: + case PC_STFD: + case PC_STFDU: + case PC_STFDX: + case PC_STFDUX: + return 8; + case PC_LSWI: + case PC_STSWI: + return pcode->args[2].data.imm.value; // not sure if imm is the right union type here + case PC_LSWX: + case PC_STSWX: + return 128; + + // there's probably an ifdef here lmao + case PC_LVEBX: + case PC_STVEBX: + return 1; + case PC_LVEHX: + case PC_STVEHX: + return 2; + case PC_LVEWX: + case PC_STVEWX: + return 4; + case PC_LVSL: + case PC_LVSR: + case PC_LVX: + case PC_LVXL: + case PC_STVX: + case PC_STVXL: + return 16; + + default: + CError_FATAL(2011); + } + } + + CError_FATAL(2014); + return 0; +} + +void change_num_operands(PCode *pcode, int newNum) { + int i; + + CError_ASSERT(2026, ((pcode->argCount > 5) ? pcode->argCount : 5) >= newNum); + + for (i = pcode->argCount - 1; i >= newNum; i--) + pcode->args[i].kind = PCOp_PLACEHOLDEROPERAND; + + pcode->argCount = newNum; +} + +void change_opcode(PCode *pcode, short opcode) { + pcode->flags = (pcode->flags & ~(opcodeinfo[pcode->op].flags & ~fIsPtrOp)) | opcodeinfo[opcode].flags; + if ((pcode->flags & fIsMove) && (PCODE_FLAG_SET_F(pcode) & fRecordBit)) + pcode->flags &= ~fIsMove; + pcode->op = opcode; +} diff --git a/compiler_and_linker/BackEnd/PowerPC/PPCError.c b/compiler_and_linker/BackEnd/PowerPC/PPCError.c new file mode 100644 index 0000000..2d4c469 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/PPCError.c @@ -0,0 +1,70 @@ +#include "compiler/PPCError.h" +#include "compiler/CError.h" +#include "compiler/CParser.h" +#include "compiler/InlineAsm.h" +#include "cos.h" + +static void PPCError_GetErrorString(char *str, short code) { + short scode; + + scode = (short) code; + CError_ASSERT(40, scode >= 100 && scode < PPCErrorStrMAX); + + COS_GetString(str, 10001, scode - 99); +} + +static void PPCError_VAErrorMessage(int code, va_list list, Boolean flag1, Boolean flag2) { + char format[256]; + PPCError_GetErrorString(format, code); + CError_ErrorMessageVA(code + 10001, format, list, flag1, flag2); +} + +void PPCError_Error(int code, ...) { + va_list list; + + if (trychain) + longjmp(trychain->jmpbuf, 1); + + va_start(list, code); + PPCError_VAErrorMessage(code, list, 0, 0); + va_end(list); + + if (in_assembler) + AssemblerError(); +} + +void PPCError_Warning(int code, ...) { + va_list list; + + if (!trychain) { + va_start(list, code); + PPCError_VAErrorMessage(code, list, 0, 1); + va_end(list); + } +} + +void PPCError_Message(char *format, ...) { + va_list list; + + if (!trychain) { + va_start(list, format); + CError_ErrorMessageVA(10213, format, list, 0, 1); + va_end(list); + } +} + +void PPCError_ErrorTerm(short code, ...) { + va_list list; + + if (trychain) + longjmp(trychain->jmpbuf, 1); + + va_start(list, code); + PPCError_VAErrorMessage(code, list, 1, 0); + va_end(list); + + if (in_assembler) + AssemblerError(); + + longjmp(errorreturn, 1); +} diff --git a/compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/Coloring.c b/compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/Coloring.c new file mode 100644 index 0000000..8036435 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/Coloring.c @@ -0,0 +1,268 @@ +#include "compiler/Coloring.h" +#include "compiler/CFunc.h" +#include "compiler/CompilerTools.h" +#include "compiler/InterferenceGraph.h" +#include "compiler/PCode.h" +#include "compiler/PPCError.h" +#include "compiler/Registers.h" +#include "compiler/RegisterInfo.h" +#include "compiler/SpillCode.h" +#include "compiler/StackFrame.h" +#include "compiler/objects.h" + +RegClass coloring_class; +static short used_regs_before_coloring; + +static void markspecialregisters(RegClass rclass) { + ObjectList *list; + Object *object; + VarInfo *vi; + UInt32 i; + + for (i = 0; i < n_real_registers[rclass]; i++) + interferencegraph[i]->x14 = i; + + for (list = arguments; list; list = list->next) { + object = list->object; + vi = Registers_GetVarInfo(object); + if ((vi->flags & VarInfoFlag2) && vi->rclass == rclass) { + interferencegraph[vi->reg]->spillTemporary = object; + if (vi->flags & VarInfoFlag4) { + interferencegraph[vi->reg]->flags |= fPairLow; + interferencegraph[vi->regHi]->flags |= fPairHigh; + interferencegraph[vi->regHi]->spillTemporary = object; + } + } + } + + for (list = locals; list; list = list->next) { + object = list->object; + vi = Registers_GetVarInfo(object); + if ((vi->flags & VarInfoFlag2) && vi->rclass == rclass) { + interferencegraph[vi->reg]->spillTemporary = object; + if (vi->flags & VarInfoFlag4) { + interferencegraph[vi->reg]->flags |= fPairLow; + interferencegraph[vi->regHi]->flags |= fPairHigh; + interferencegraph[vi->regHi]->spillTemporary = object; + } + } + } +} + +static IGNode *simplifygraph(void) { + int availableRegs; + IGNode *spilledNodes; + IGNode *pushedNodes; + IGNode *best; + IGNode *node; + UInt32 i; + UInt32 j; + int flag; + float bestScore; + float score; + + availableRegs = available_registers(coloring_class); + pushedNodes = NULL; + + do { + spilledNodes = NULL; + flag = 0; + for (i = n_real_registers[coloring_class]; i < used_virtual_registers[coloring_class]; i++) { + node = interferencegraph[i]; + if (!(node->flags & (fPushed | fCoalesced))) { + if (node->x12 < availableRegs) { + for (j = 0; j < node->arraySize; j++) + interferencegraph[node->array[j]]->x12--; + node->flags |= fPushed; + node->next = pushedNodes; + pushedNodes = node; + flag = 1; + } else { + node->next = spilledNodes; + spilledNodes = node; + } + } + } + } while (flag); + + if (spilledNodes) + estimatespillcosts(); + + while (spilledNodes) { + best = spilledNodes; + bestScore = (spilledNodes->x10 >= used_regs_before_coloring) ? FLT_MAX : ((float) spilledNodes->spillCost / (float) spilledNodes->x12); + + for (node = spilledNodes->next; node; node = node->next) { + score = (node->x10 >= used_regs_before_coloring) ? FLT_MAX : ((float) node->spillCost / (float) node->x12); + if (score < bestScore) { + best = node; + bestScore = score; + } + } + + for (i = 0; i < best->arraySize; i++) + interferencegraph[best->array[i]]->x12--; + + best->flags |= fPushed; + best->next = pushedNodes; + pushedNodes = best; + + do { + spilledNodes = NULL; + flag = 0; + for (i = n_real_registers[coloring_class]; i < used_virtual_registers[coloring_class]; i++) { + node = interferencegraph[i]; + if (!(node->flags & (fPushed | fCoalesced))) { + if (node->x12 < availableRegs) { + for (j = 0; j < node->arraySize; j++) + interferencegraph[node->array[j]]->x12--; + node->flags |= fPushed; + node->next = pushedNodes; + pushedNodes = node; + flag = 1; + } else { + node->next = spilledNodes; + spilledNodes = node; + } + } + } + } while (flag); + } + + return pushedNodes; +} + +static int colorgraph(IGNode *node) { + UInt32 volatileRegs; + int result; + IGNode *otherNode; + int reg; + UInt32 workingMask; + int i; + short *array; + + result = 1; + + reset_nonvolatile_registers(coloring_class); + volatileRegs = volatile_registers(coloring_class); + + while (node) { + workingMask = volatileRegs; + for (array = node->array, i = 0; i < node->arraySize; i++) { + otherNode = interferencegraph[*(array++)]; + reg = otherNode->x14; + if (reg != -1 && reg < n_real_registers[coloring_class]) + workingMask &= ~(1 << reg); + } + + if (workingMask) { + for (i = 0; i < n_real_registers[coloring_class]; i++) { + if (workingMask & (1 << i)) { + node->x14 = i; + break; + } + } + } else { + reg = obtain_nonvolatile_register(coloring_class); + if (reg != -1) { + volatileRegs |= 1 << (node->x14 = reg); + } else { + node->flags |= fSpilled; + result = 0; + } + } + + node = node->next; + } + + return result; +} + +static void rewritepcode(void) { + PCodeBlock *block; + PCode *instr; + PCodeArg *op; + UInt32 i; + IGNode *node; + int reg; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + op = instr->args; + i = instr->argCount; + while (i--) { + if (PC_OP_IS_ANY_REGISTER(op, coloring_class)) + op->data.reg.reg = interferencegraph[op->data.reg.reg]->x14; + op++; + } + + if ( + (instr->flags & fIsMove) && + (instr->args[1].arg == coloring_class) && + instr->args[1].data.reg.reg == instr->args[0].data.reg.reg + ) + deletepcode(instr); + } + } + + for (i = n_real_registers[coloring_class]; i < used_virtual_registers[coloring_class]; i++) { + node = interferencegraph[i]; + if (node->spillTemporary && !(node->flags & fSpilled)) { + if (node->flags & fCoalesced) { + reg = node->x14; + while (reg >= n_real_registers[coloring_class]) { + reg = interferencegraph[reg]->x14; + if (reg < 0) + break; + } + node->x14 = reg; + } + + if (node->flags & fPairHigh) { + reg = node->x14; + Registers_GetVarInfo(node->spillTemporary)->regHi = reg; + } else { + reg = node->x14; + Registers_GetVarInfo(node->spillTemporary)->reg = reg; + } + } + } +} + +void colorinstructions(Object *proc) { + RegClass rclass; + int flag; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + coloring_class = rclass; + + if (rclass == RegClass_GPR) + check_dynamic_aligned_frame(); + + if (used_virtual_registers[rclass] > n_real_registers[rclass]) { + save_before_coloring_nonvolatile_registers(rclass); + used_regs_before_coloring = used_virtual_registers[rclass]; + if (!available_registers(rclass)) { + PPCError_Error(PPCErrorStr102, register_class_name[rclass]); + return; + } + + flag = 1; + while (flag && used_virtual_registers[rclass] > n_real_registers[rclass]) { + buildinterferencegraph(proc); + markspecialregisters(rclass); + flag = colorgraph(simplifygraph()) ? 0 : 1; + + if (flag) + insertspillcode(); + else + rewritepcode(); + freeoheap(); + } + } + + used_virtual_registers[rclass] = n_real_registers[rclass]; + } + + coloring = 0; +} diff --git a/compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/InterferenceGraph.c b/compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/InterferenceGraph.c new file mode 100644 index 0000000..d589502 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/InterferenceGraph.c @@ -0,0 +1,364 @@ +#include "compiler/InterferenceGraph.h" +#include "compiler/CError.h" +#include "compiler/CParser.h" +#include "compiler/BitVectors.h" +#include "compiler/Coloring.h" +#include "compiler/LiveInfo.h" +#include "compiler/PCode.h" +#include "compiler/PCodeListing.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/Registers.h" +#include "compiler/RegisterInfo.h" +#include "compiler/CompilerTools.h" + +IGNode **interferencegraph; +static UInt32 *interferencematrix; +Boolean coalesced_nregisters; +static SInt16 *coalesced; + +static void makeinterfere(UInt32 a, UInt32 b) { + if (a < b) + bitvectorsetbit(((b * b) / 2) + a, interferencematrix); + else if (a > b) + bitvectorsetbit(((a * a) / 2) + b, interferencematrix); +} + +int interferes(UInt32 a, UInt32 b) { + if (a < b) + return bitvectorgetbit(((b * b) / 2) + a, interferencematrix) > 0; + else if (a > b) + return bitvectorgetbit(((a * a) / 2) + b, interferencematrix) > 0; + else + return 0; +} + +static void buildinterferencematrix(void) { + PCodeBlock *block; // r30 + PCode *instr; // r29 + PCodeArg *op; + UInt32 *vec; // r28 + UInt32 i; + UInt32 j; + + UInt32 regs = used_virtual_registers[coloring_class]; + interferencematrix = oalloc(4 * ((((regs * regs) / 2) + 31) >> 5)); + bitvectorinitialize(interferencematrix, (regs * regs) / 2, 0); + + for (i = 0; i < 32; i++) + for (j = 0; j < 32; j++) + if (i != j) + makeinterfere(i, j); + + vec = oalloc(4 * ((regs + 31) >> 5)); + for (block = pcbasicblocks; block; block = block->nextBlock) { + bitvectorcopy(vec, liveinfo[block->blockIndex].out, regs); + for (instr = block->lastPCode; instr; instr = instr->prevPCode) { + for (op = instr->args, i = instr->argCount; i--; op++) { + if (PC_OP_IS_WRITE_ANY_REGISTER(op, coloring_class)) { + int reg = op->data.reg.reg; + bitvectorclearbit(reg, vec); + for (j = 0; j < regs; j++) { + if (bitvectorgetbit(j, vec)) { + if ( + (instr->flags & fIsMove) && + PC_OP_IS_ANY_REGISTER(&instr->args[0], coloring_class) && + instr->args[1].data.reg.reg == j + ) + continue; + makeinterfere(reg, j); + } + } + } + } + + for (op = instr->args, i = instr->argCount; i--; op++) { + if (PC_OP_IS_READ_ANY_REGISTER(op, coloring_class)) { + int reg = op->data.reg.reg; + if (bitvectorgetbit(op->data.reg.reg, vec) == 0) + op->data.reg.effect |= Effect4; + bitvectorsetbit(reg, vec); + } + } + + if (coloring_class == RegClass_GPR) { + if (PCODE_FLAG_SET_F(instr) & (fIsRead | fIsWrite | fPCodeFlag400000)) { + if (instr->args[1].data.reg.reg >= n_real_registers[coloring_class]) + makeinterfere(0, instr->args[1].data.reg.reg); + if (PCODE_FLAG_SET_F(instr) & fUpdatesPtr) + makeinterfere(instr->args[0].data.reg.reg, instr->args[1].data.reg.reg); + } else { + switch (instr->op) { + case PC_DCBF: + case PC_DCBST: + case PC_DCBT: + case PC_DCBTST: + case PC_DCBZ: + case PC_DCBI: + case PC_ICBI: + case PC_DCCCI: + case PC_ICBT: + case PC_ICCCI: + case PC_ICREAD: + case PC_DCBA: + case PC_DST: + case PC_DSTT: + case PC_DSTST: + case PC_DSTSTT: + if (instr->args[0].data.reg.reg >= n_real_registers[coloring_class]) + makeinterfere(0, instr->args[0].data.reg.reg); + break; + } + } + } + + if (coloring_class == RegClass_GPR && (instr->flags & fIsCall)) { + i = branch_count_volatiles(); + op = instr->args; + CError_ASSERT(219, instr->argCount != 0); + + while (op->kind != PCOp_REGISTER || !(op->data.reg.effect & EffectWrite)) { + i++; + op++; + CError_ASSERT(226, i <= instr->argCount); + } + + for (op = instr->args + i; i < instr->argCount; i++, op++) { + if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) { + for (j = 0; j < n_scratch_registers[coloring_class]; j++) + makeinterfere(op->data.reg.reg, scratch_registers[coloring_class][j]); + } + } + } + } + } +} + +static short coalesced_path(short id) { + while (id != coalesced[id]) + id = coalesced[id]; + return id; +} + +static void coalescenodes(void) { + PCodeArg *op; + UInt32 regs; + PCodeBlock *block; + PCode *instr; + UInt32 i; + short path1; + short path2; + short node1; + short node2; + + regs = used_virtual_registers[coloring_class]; + coalesced = oalloc(sizeof(SInt16) * regs); + + for (i = 0; i < regs; i++) + coalesced[i] = i; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + if ((instr->flags & fIsMove) && !(instr->flags & fSideEffects)) { + if (PCODE_FLAG_SET_F(instr) & fRecordBit) { + CError_FATAL(309); + continue; + } + + if (instr->argCount > 2) { + if (instr->argCount != 3 || instr->args[2].kind != PCOp_PLACEHOLDEROPERAND) { + CError_FATAL(316); + continue; + } + } + + if (PC_OP_IS_ANY_REGISTER(&instr->args[0], coloring_class)) { + path1 = coalesced_path(instr->args[0].data.reg.reg); + path2 = coalesced_path(instr->args[1].data.reg.reg); + if (path1 == path2) { + deletepcode(instr); + continue; + } + + if (!interferes(path1, path2)) { + if (path1 >= n_real_registers[coloring_class] && path2 >= n_real_registers[coloring_class]) { + if (path1 < first_fe_temporary_register[coloring_class]) + continue; + if (path1 > last_temporary_register[coloring_class]) + continue; + if (path2 < first_fe_temporary_register[coloring_class]) + continue; + if (path2 > last_temporary_register[coloring_class]) + continue; + } + + node1 = (path2 < path1) ? path2 : path1; + node2 = (path2 > path1) ? path2 : path1; + + if (coloring_class == RegClass_GPR && node2 == _CALLER_SP_) + continue; + + coalesced[node2] = node1; + for (i = 0; i < regs; i++) { + if (interferes(node2, i)) + makeinterfere(node1, i); + } + + deletepcode(instr); + } + } + } + } + } + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + op = instr->args; + i = instr->argCount; + while (i--) { + if (PC_OP_IS_ANY_REGISTER(op, coloring_class) && op->data.reg.reg != coalesced[op->data.reg.reg]) + op->data.reg.reg = coalesced_path(op->data.reg.reg); + op++; + } + } + } +} + +static void buildadjacencyvectors(void) { + IGNode *node; + UInt32 regs; + UInt32 i; + UInt32 counter; + short *array; + short *dest; + short *src; + UInt32 j; + + regs = used_virtual_registers[coloring_class]; + interferencegraph = oalloc(sizeof(IGNode *) * regs); + array = oalloc(sizeof(short) * regs); + + for (i = 0; i < regs; i++) { + counter = 0; + for (j = 0; j < regs; j++) { + if (interferes(i, j)) + array[counter++] = j; + } + + node = interferencegraph[i] = oalloc(sizeof(IGNode) + sizeof(short) * (counter - 1)); + memclrw(node, sizeof(IGNode) + sizeof(short) * (counter - 1)); + + node->x10 = i; + node->x14 = -1; + node->arraySize = counter; + node->x12 = counter; + + dest = node->array; + src = array; + for (j = 0; j < counter; j++) + *(dest++) = *(src++); + + if (i != coalesced[i]) { + node->flags |= fCoalesced; + j = coalesced_path(i); + interferencegraph[j]->flags |= fCoalescedInto; + node->x14 = j; + } + } +} + +static void eliminatedeadcode(void) { + UInt32 regs; + PCodeBlock *block; + PCode *instr; + UInt32 *vec; + UInt32 i; + PCodeArg *op; + + regs = used_virtual_registers[coloring_class]; + vec = oalloc(4 * ((regs + 31) >> 5)); + + for (block = pcbasicblocks; block; block = block->nextBlock) { + bitvectorcopy(vec, liveinfo[block->blockIndex].out, regs); + for (instr = block->lastPCode; instr; instr = instr->prevPCode) { + if (dead(instr, coloring_class, vec)) { + deletepcode(instr); + continue; + } + + op = instr->args; + i = instr->argCount; + while (i--) { + if (PC_OP_IS_WRITE_ANY_REGISTER(op, coloring_class)) + bitvectorclearbit(op->data.reg.reg, vec); + op++; + } + + op = instr->args; + i = instr->argCount; + while (i--) { + if (PC_OP_IS_READ_ANY_REGISTER(op, coloring_class)) { + int reg = op->data.reg.reg; + if (!bitvectorgetbit(reg, vec)) + op->data.reg.effect |= Effect4; + bitvectorsetbit(reg, vec); + } + op++; + } + } + } +} + +static void findrematerializations(void) { + UInt32 regs; + UInt32 i; + PCodeBlock *block; + PCode *instr; + PCodeArg *op; + IGNode *node; + + regs = used_virtual_registers[coloring_class]; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (instr = block->lastPCode; instr; instr = instr->prevPCode) { + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + PC_OP_IS_WRITE_ANY_REGISTER(op, coloring_class) && + op->data.reg.reg >= n_real_registers[coloring_class] && + !(interferencegraph[op->data.reg.reg]->flags & (fPairLow | fPairHigh)) && + !(interferencegraph[op->data.reg.reg]->flags & fIGNode40) + ) + { + node = interferencegraph[op->data.reg.reg]; + if (!node->instr8) { + node->instr8 = instr; + } else { + node->instr8 = NULL; + node->flags |= fIGNode40; + } + } + op++; + } + } + } + + for (i = 0; i < regs; i++) { + node = interferencegraph[i]; + if (node->instr8 && !is_location_independent(node->instr8)) + node->instr8 = NULL; + } +} + +void buildinterferencegraph(Object *proc) { + int regs = used_virtual_registers[coloring_class]; + + computelivevariables(proc); + eliminatedeadcode(); + buildinterferencematrix(); + if (copts.debuglisting) + pclistinterferences(register_class_format[coloring_class], regs); + coalescenodes(); + buildadjacencyvectors(); + findrematerializations(); +} diff --git a/compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/RegisterInfo.c b/compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/RegisterInfo.c new file mode 100644 index 0000000..177c2e0 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/RegisterInfo.c @@ -0,0 +1,381 @@ +#include "compiler/RegisterInfo.h" +#include "compiler/CodeGen.h" +#include "compiler/CError.h" +#include "compiler/CParser.h" +#include "compiler/PCode.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +short last_exception_register[RegClassMax]; +short first_fe_temporary_register[RegClassMax]; +short last_argument_register[RegClassMax]; +short _FP_; +short _CALLER_SP_; +char *special_register_names[RegClassMax][RegisterMax]; +static short used_regs_before_coloring; +static UInt8 save_state[RegisterMax]; + +short spr_to_sysreg[4] = {1, 8, 9, 0x100}; + +void asm_used_register(RegClass rclass, short reg) { + int i; + + if ((reg < n_real_registers[rclass]) && (reg_state[rclass][reg] == RegState0)) { + if (reg == nonvolatile_registers[rclass][used_nonvolatile_registers[rclass]]) { + if (assignable_registers[rclass] > 0) + assignable_registers[rclass]--; + reg_state[rclass][reg] = RegState1; + used_nonvolatile_registers[rclass]++; + } else { + for (i = used_nonvolatile_registers[rclass]; i < n_nonvolatile_registers[rclass]; i++) { + if (reg == nonvolatile_registers[rclass][i]) { + reg_state[rclass][reg] = RegState1; + if (assignable_registers[rclass] > 0) + assignable_registers[rclass]--; + } + } + } + } +} + +void retain_register(Object *obj, RegClass rclass, short reg) { + VarInfo *vi; + + CError_ASSERT(95, (short) reg < RegisterMax); + + if (reg_state[rclass][reg] == RegState0) { + assignable_registers[rclass]--; + reg_state[rclass][reg] = RegState1; + if (reg == nonvolatile_registers[rclass][used_nonvolatile_registers[rclass]]) + used_nonvolatile_registers[rclass]++; + } + + if (obj) { + vi = Registers_GetVarInfo(obj); + vi->rclass = rclass; + vi->flags |= VarInfoFlag2; + vi->reg = reg; + } +} + +void retain_GPR_pair(Object *obj, short reg, short regHi) { + VarInfo *vi; + + retain_register(NULL, RegClass_GPR, reg); + retain_register(NULL, RegClass_GPR, regHi); + + if (obj) { + vi = Registers_GetVarInfo(obj); + vi->rclass = RegClass_GPR; + vi->flags |= VarInfoFlag2 | VarInfoFlag4; + vi->reg = reg; + vi->regHi = regHi; + } +} + +int is_register_object(Object *obj) { + return obj->sclass == TK_REGISTER; +} + +int GetABIFirstNonVolatile(RegClass rclass) { + switch (rclass) { + case RegClass_SPR: return 3; + case RegClass_CRFIELD: return 2; + case RegClass_VR: return 20; + case RegClass_GPR: return 13; + case RegClass_FPR: return 14; + default: return -1; + } +} + +char GetRegisterClassName(RegClass rclass) { + switch (rclass) { + case RegClass_VR: return 'v'; + case RegClass_GPR: return 'r'; + case RegClass_FPR: return 'f'; + default: + CError_FATAL(242); + return '?'; + } +} + +static int first_nonvolatile_reg(RegClass rclass) { + return GetABIFirstNonVolatile(rclass); +} + +void setup_diagnostic_reg_strings(void) { + register_class_name[RegClass_SPR] = "SPR"; + register_class_format[RegClass_SPR] = "spr%" PRId32; + register_class_name[RegClass_CRFIELD] = "CRFIELD"; + register_class_format[RegClass_CRFIELD] = "cr%" PRId32; + register_class_name[RegClass_VR] = "VR"; + register_class_format[RegClass_VR] = "vr%" PRId32; + register_class_name[RegClass_FPR] = "FPR"; + register_class_format[RegClass_FPR] = "f%" PRId32; + register_class_name[RegClass_GPR] = "GPR"; + register_class_format[RegClass_GPR] = "r%" PRId32; +} + +void init_target_registers(void) { + int reg; + int end; + RegClass rclass; + + static int last_nonvolatile_reg[] = {3, 5, 31, 31, 31}; + static int nonvol_reserve[] = {0, 0, 0, 4, 3}; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + for (reg = 0; reg < RegisterMax; reg++) + special_register_names[rclass][reg] = NULL; + } + + special_register_names[RegClass_SPR][0] = "XER"; + special_register_names[RegClass_SPR][1] = "LR"; + special_register_names[RegClass_SPR][2] = "CTR"; + special_register_names[RegClass_SPR][3] = "VRSAVE"; + special_register_names[RegClass_GPR][1] = "SP"; + + setup_diagnostic_reg_strings(); + n_real_registers[RegClass_SPR] = 4; + n_real_registers[RegClass_CRFIELD] = 8; + n_real_registers[RegClass_VR] = 32; + n_real_registers[RegClass_FPR] = 32; + n_real_registers[RegClass_GPR] = 32; + reg_state[RegClass_GPR][1] = RegState2; + reg_state[RegClass_GPR][2] = RegState2; + reg_state[RegClass_CRFIELD][5] = RegState2; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + n_nonvolatile_registers[rclass] = 0; + if (last_nonvolatile_reg[rclass] >= 0) { + end = first_nonvolatile_reg(rclass); + for (reg = last_nonvolatile_reg[rclass]; reg >= end; reg--) { + if (reg_state[rclass][reg] == RegState0) { + nonvolatile_registers[rclass][n_nonvolatile_registers[rclass]++] = reg; + } + } + } + + assignable_registers[rclass] = n_nonvolatile_registers[rclass] - nonvol_reserve[rclass]; + if (assignable_registers[rclass] < 0) + assignable_registers[rclass] = 0; + + n_scratch_registers[rclass] = 0; + for (reg = 0; reg < n_real_registers[rclass]; reg++) { + if (reg < GetABIFirstNonVolatile(rclass) || reg > last_nonvolatile_reg[rclass]) { + if (reg_state[rclass][reg] == RegState0) { + scratch_registers[rclass][n_scratch_registers[rclass]++] = reg; + } + } + } + } + + _FP_ = -1; + _CALLER_SP_ = -1; + optimizing = (copts.optimizationlevel > 0) && !disable_optimizer; +} + +void assign_register_by_type(Object *obj) { + VarInfo *vi; + Type *ty; + Boolean flag; + + ty = obj->type; + vi = Registers_GetVarInfo(obj); + flag = 0; + vi->rclass = RegClassMax; + vi->reg = 0; + vi->regHi = 0; + + if ((ty->type == TYPEINT) || (ty->type == TYPEENUM) || ((ty->type == TYPEPOINTER || ty->type == TYPEARRAY) && (ty->type != TYPEARRAY)) || ((ty->type == TYPEMEMBERPOINTER) && (ty->size == 4U))) { + if (((ty->type == TYPEINT) || (ty->type == TYPEENUM)) && (ty->size == 8)) + flag = 1; + vi->rclass = RegClass_GPR; + } else if (ty->type == TYPEFLOAT) { + vi->rclass = RegClass_FPR; + } else if ((ty->type == TYPESTRUCT) && (TYPE_STRUCT(ty)->stype >= STRUCT_VECTOR_UCHAR) && (TYPE_STRUCT(ty)->stype <= STRUCT_VECTOR_PIXEL)) { + vi->rclass = RegClass_VR; + } else { + return; + } + + if (vi->rclass < RegClassMax) { + if (flag) { + CError_ASSERT(520, vi->rclass == RegClass_GPR); + if (assignable_registers[vi->rclass] > 1) + assign_GPR_pair(obj); + } else { + if (assignable_registers[vi->rclass] > 0) + assign_register_to_variable(obj, vi->rclass); + } + } +} + +void assign_GPR_pair(Object *obj) { + VarInfo *vi; + short reg; + short regHi; + + vi = Registers_GetVarInfo(obj); + if (optimizing) { + reg = used_virtual_registers[RegClass_GPR]++; + regHi = used_virtual_registers[RegClass_GPR]++; + } else { + CError_ASSERT(554, assignable_registers[RegClass_GPR] >= 2); + reg = obtain_nonvolatile_register(RegClass_GPR); + regHi = obtain_nonvolatile_register(RegClass_GPR); + retain_GPR_pair(obj, reg, regHi); + } + + vi->rclass = RegClass_GPR; + if (reg > 0 && regHi > 0) { + vi->flags |= VarInfoFlag2 | VarInfoFlag4; + vi->reg = reg; + vi->regHi = regHi; + } else { + CError_FATAL(567); + } +} + +void open_fe_temp_registers(void) { + int r; + + r = used_virtual_registers[RegClass_GPR]; + first_fe_temporary_register[RegClass_GPR] = last_temporary_register[RegClass_GPR] = r; + r = used_virtual_registers[RegClass_FPR]; + first_fe_temporary_register[RegClass_FPR] = last_temporary_register[RegClass_FPR] = r; + r = used_virtual_registers[RegClass_VR]; + first_fe_temporary_register[RegClass_VR] = last_temporary_register[RegClass_VR] = r; +} + +void set_last_exception_registers(void) { + last_exception_register[RegClass_GPR] = used_virtual_registers[RegClass_GPR] - 1; + last_exception_register[RegClass_FPR] = used_virtual_registers[RegClass_FPR] - 1; + last_exception_register[RegClass_VR] = used_virtual_registers[RegClass_VR] - 1; +} + +static VarInfo *Registers_GetNewVarInfo(void) { + VarInfo *vi = galloc(sizeof(VarInfo)); + memclrw(vi, sizeof(VarInfo)); + return vi; +} + +VarInfo *Registers_GetVarInfo(Object *obj) { + switch (obj->datatype) { + case DDATA: + if (!obj->u.data.info) + obj->u.data.info = Registers_GetNewVarInfo(); + return obj->u.data.info; + case DNONLAZYPTR: + if (!obj->u.toc.info) { + CError_FATAL(639); + obj->u.toc.info = CodeGen_GetNewVarInfo(); + } + return obj->u.toc.info; + case DLOCAL: + if (!obj->u.var.info) + CError_FATAL(647); + return obj->u.var.info; + case DABSOLUTE: + // not sure if this is the right union + if (!obj->u.data.info) + obj->u.data.info = Registers_GetNewVarInfo(); + return obj->u.data.info; + default: + CError_FATAL(660); + return NULL; + } +} + +int used_vrstate_VRs(void) { + int count = 0; + int i; + for (i = 0; i < RegisterMax; i++) { + if (reg_state[RegClass_VR][i]) + count++; + } + return count; +} + +UInt32 colored_vrs_as_vrsave(PCodeBlock *block) { + PCode *pc; + UInt32 mask; + int i; + + mask = 0; + if (copts.altivec_vrsave == 2) + return 0xFFFFFFFF; + if (copts.altivec_vrsave == 0) + return 0; + + while (block) { + for (pc = block->firstPCode; pc; pc = pc->nextPCode) { + if (pc->flags & fOpTypeVR) { + for (i = 0; i < pc->argCount; i++) { + if (pc->args[i].kind == PCOp_REGISTER && pc->args[i].arg == RegClass_VR) + mask |= 1 << (31 - pc->args[i].data.reg.reg); + } + } + } + block = block->nextBlock; + } + + return mask; +} + +void save_before_coloring_nonvolatile_registers(RegClass rclass) { + used_regs_before_coloring = used_nonvolatile_registers[rclass]; + memcpy(save_state, reg_state[rclass], sizeof(save_state)); +} + +void reset_nonvolatile_registers(RegClass rclass) { + used_nonvolatile_registers[rclass] = used_regs_before_coloring; + memcpy(reg_state[rclass], save_state, sizeof(save_state)); +} + +int is_nonvolatile_register(RegClass rclass, int reg) { + int i; + + for (i = 0; i < n_nonvolatile_registers[rclass]; i++) { + if (reg == nonvolatile_registers[rclass][i]) + return 1; + } + + return 0; +} + +void init_endian(void) { + if (copts.littleendian) { + high_offset = 4; + low_offset = 0; + high_reg = 4; + low_reg = 3; + high_reg2 = 6; + low_reg2 = 5; + } else { + high_offset = 0; + low_offset = 4; + high_reg = 3; + low_reg = 4; + high_reg2 = 5; + low_reg2 = 6; + } +} + +void update_asm_nonvolatile_registers(void) { + RegClass rclass; + int i; + int reg; + + for (rclass = 0; rclass < RegClassMax; rclass++) { + reg = n_nonvolatile_registers[rclass]; + for (i = n_nonvolatile_registers[rclass] - 1; i >= 0; i--) { + if (reg_state[rclass][nonvolatile_registers[rclass][i]] == RegState1) + break; + reg--; + } + if (reg > used_nonvolatile_registers[rclass]) + used_nonvolatile_registers[rclass] = reg; + } +} diff --git a/compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/SpillCode.c b/compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/SpillCode.c new file mode 100644 index 0000000..69e7e43 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/RegisterAllocator/SpillCode.c @@ -0,0 +1,452 @@ +#include "compiler/SpillCode.h" +#include "compiler/CError.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/Coloring.h" +#include "compiler/InterferenceGraph.h" +#include "compiler/Operands.h" +#include "compiler/PCode.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/Registers.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/objects.h" + +static int last_unused_vreg_before_spilling; +static short rTEMP_for_VR_spill; + +void estimatespillcosts(void) { + PCodeBlock *block; + PCode *instr; + IGNode *node; + PCodeArg *op; + int i; + int weight; + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if (copts.optimizesize) + weight = 1; + else + weight = block->loopWeight; + + for (instr = block->firstPCode; instr; instr = instr->nextPCode) { + op = instr->args; + i = instr->argCount; + while (i--) { + if (PC_OP_IS_READ_ANY_REGISTER(op, coloring_class)) { + node = interferencegraph[op->data.reg.reg]; + if (node->instr8 || copts.optimizesize) + node->spillCost += weight; + else + node->spillCost += weight * 2; + } + op++; + } + + op = instr->args; + i = instr->argCount; + while (i--) { + if (PC_OP_IS_WRITE_ANY_REGISTER(op, coloring_class)) { + node = interferencegraph[op->data.reg.reg]; + if (node->instr8 || (instr->flags & fIsArgInit)) + node->spillCost -= weight; + else + node->spillCost += weight; + } + op++; + } + } + } +} + +static Object *makespilltemporary(Type *type) { + Object *obj = lalloc(sizeof(Object)); + memclrw(obj, sizeof(Object)); + + obj->otype = OT_OBJECT; + obj->access = ACCESSPUBLIC; + obj->datatype = DLOCAL; + obj->type = type; + obj->name = CParser_GetUniqueName(); + obj->u.var.info = CodeGen_GetNewVarInfo(); + obj->u.var.uid = 0; + + return obj; +} + +static PCode *rematerialize_spilled_register(short reg, IGNode *node) { + PCode *instr = copypcode(node->instr8); + + CError_ASSERT(128, instr->args[0].kind == PCOp_REGISTER); + + instr->args[0].data.reg.reg = reg; + return instr; +} + +static void insert_load_spilled_register(PCode *instr, short reg, IGNode *node) { + Type *type; + Opcode opcode; + Object *object; + PCode *newInstr; + PCode *newInstr2; + SInt32 offset; + Operand operand; + + type = node->spillTemporary->type; + switch (coloring_class) { + case RegClass_CRFIELD: + case RegClass_GPR: + switch (type->size) { + case 1: + opcode = PC_LBZ; + break; + case 2: + opcode = is_unsigned(type) ? PC_LHZ : PC_LHA; + break; + case 4: + opcode = PC_LWZ; + break; + case 8: + opcode = PC_LWZ; + break; + default: + CError_FATAL(187); + } + + memclrw(&operand, sizeof(Operand)); + operand.optype = OpndType_Symbol; + operand.object = node->spillTemporary; + CError_ASSERT(222, node->spillTemporary->datatype == DLOCAL); + + coerce_to_addressable(&operand); + + CError_ASSERT(233, operand.optype == OpndType_GPR_ImmOffset); + + CError_ASSERT(237, node->spillTemporary->datatype == DLOCAL); + + if (node->flags & fPairLow) + offset = low_offset; + else if (node->flags & fPairHigh) + offset = high_offset; + else + offset = 0; + insertpcodebefore(instr, makepcode(opcode, reg, operand.reg, operand.object, operand.immOffset + offset)); + break; + + case RegClass_FPR: + CError_ASSERT(253, node->spillTemporary->datatype == DLOCAL); + + if (node->flags & fPairLow) + offset = low_offset; + else if (node->flags & fPairHigh) + offset = high_offset; + else + offset = 0; + + object = node->spillTemporary; + insertpcodebefore( + instr, + makepcode( + (type->size == 8) ? PC_LFD : PC_LFS, + reg, + local_base_register(object), + object, + offset + ) + ); + break; + + case RegClass_VR: + CError_ASSERT(320, node->spillTemporary->datatype == DLOCAL); + + object = node->spillTemporary; + newInstr = makepcode(PC_ADDI, rTEMP_for_VR_spill, local_base_register(object), object, 0); + newInstr2 = makepcode(PC_LVX, reg, 0, rTEMP_for_VR_spill); + insertpcodebefore(instr, newInstr); + insertpcodeafter(newInstr, newInstr2); + break; + + default: + CError_FATAL(333); + } +} + +static void insert_store_spilled_register(PCode *instr, Boolean flag, short reg, IGNode *node) { + Object *object; // r31 + Opcode opcode; // r30 + SInt32 offset; // r26 + PCode *newInstr2; // r26 + PCode *newInstr; // r25 + Type *type; // r25 + + object = node->spillTemporary; + type = object->type; + + switch (coloring_class) { + case RegClass_CRFIELD: + case RegClass_GPR: + switch (type->size) { + case 1: + opcode = PC_STB; + break; + case 2: + opcode = PC_STH; + break; + case 4: + opcode = PC_STW; + break; + case 8: + opcode = PC_STW; + break; + default: + CError_FATAL(391); + } + + if (node->flags & fPairLow) + offset = low_offset; + else if (node->flags & fPairHigh) + offset = high_offset; + else + offset = 0; + + newInstr = makepcode(opcode, reg, local_base_register(object), object, offset); + if (flag) + insertpcodebefore(instr, newInstr); + else + insertpcodeafter(instr, newInstr); + + break; + + case RegClass_FPR: + newInstr = makepcode((type->size == 8) ? PC_STFD : PC_STFS, reg, local_base_register(object), object, 0); + if (flag) + insertpcodebefore(instr, newInstr); + else + insertpcodeafter(instr, newInstr); + + break; + + case RegClass_VR: + newInstr = makepcode(PC_ADDI, rTEMP_for_VR_spill, local_base_register(object), object, 0); + newInstr2 = makepcode(PC_STVX, reg, 0, rTEMP_for_VR_spill); + if (flag) + insertpcodebefore(instr, newInstr); + else + insertpcodeafter(instr, newInstr); + insertpcodeafter(newInstr, newInstr2); + + break; + + default: + CError_FATAL(527); + } +} + +static void spillinstruction(PCodeBlock *block, PCode *instr) { + int reg; + int reg2; + int regs; + IGNode *node; + PCodeArg *op; + int i; + PCodeArg *op2; + int j; + int readCounter; + int writeCounter; + Boolean flag; + + regs = used_virtual_registers[coloring_class]; + flag = 0; + for (i = 0, op = instr->args; i < instr->argCount; i++, op++) { + CError_ASSERT(563, instr->block != NULL); + + if ( + PC_OP_IS_ANY_REGISTER(op, coloring_class) && + (reg = op->data.reg.reg) < regs && + ((node = interferencegraph[op->data.reg.reg])->flags & fSpilled) + ) + { + reg2 = used_virtual_registers[coloring_class]++; + readCounter = 0; + writeCounter = 0; + + for (j = i, op2 = op; j < instr->argCount; j++, op2++) { + if (PC_OP_IS_REGISTER(op2, coloring_class, reg)) { + if (op2->data.reg.effect & EffectRead) + readCounter++; + if (op2->data.reg.effect & EffectWrite) + writeCounter++; + op2->data.reg.reg = reg2; + op2->data.reg.effect |= Effect40; + } + } + + if (readCounter) { + if (node->instr8) + insertpcodebefore(instr, rematerialize_spilled_register(reg2, node)); + else + insert_load_spilled_register(instr, reg2, node); + } + + if (writeCounter) { + if (node->instr8 || (instr->flags & fIsArgInit)) + flag = 1; + else + insert_store_spilled_register(instr, 0, reg2, node); + } + } + } + + if (flag) + deletepcode(instr); +} + +static void spillcopy(PCodeBlock *block, PCode *instr) { + IGNode *node1; + IGNode *node2; + int reg; + + node1 = interferencegraph[instr->args[1].data.reg.reg]; + node2 = interferencegraph[instr->args[0].data.reg.reg]; + + if (node1->flags & fSpilled) { + if (node2->flags & fSpilled) { + reg = used_virtual_registers[coloring_class]++; + if (node1->instr8) + insertpcodebefore(instr, rematerialize_spilled_register(reg, node1)); + else + insert_load_spilled_register(instr, reg, node1); + insert_store_spilled_register(instr, 1, reg, node2); + } else { + if (node1->instr8) + insertpcodebefore(instr, rematerialize_spilled_register(instr->args[0].data.reg.reg, node1)); + else + insert_load_spilled_register(instr, instr->args[0].data.reg.reg, node1); + } + } else { + insert_store_spilled_register(instr, 1, instr->args[1].data.reg.reg, node2); + } + + deletepcode(instr); +} + +static void spillcall(PCodeBlock *block, PCode *instr) { + PCodeArg *opSrc; + PCodeArg *opDst; + int opCount; + int volatileCount; + int i; + + opCount = instr->argCount; + volatileCount = branch_count_volatiles(); + + opDst = instr->args + volatileCount; + opSrc = instr->args + volatileCount; + for (i = volatileCount; i < opCount; i++) { + if ( + PC_OP_IS_ANY_REGISTER(opSrc, coloring_class) && + opSrc->data.reg.reg >= n_real_registers[coloring_class] && + (interferencegraph[opSrc->data.reg.reg]->flags & fSpilled) + ) + { + instr->argCount--; + } else { + *opDst = *opSrc; + opDst++; + } + opSrc++; + } + + spillinstruction(block, instr); +} + +static void assign_spill_locations(void) { + UInt32 i; + IGNode *node; + Type *type; + + last_unused_vreg_before_spilling = used_virtual_registers[coloring_class]; + for (i = n_real_registers[coloring_class]; i < last_unused_vreg_before_spilling; i++) { + node = interferencegraph[i]; + if (node->flags & fCoalesced) + continue; + if (!(node->flags & fSpilled)) + continue; + + if (!node->spillTemporary) { + switch (coloring_class) { + case RegClass_GPR: + type = TYPE(&stunsignedlong); + break; + case RegClass_CRFIELD: + type = TYPE(&stunsignedlong); + break; + case RegClass_FPR: + type = TYPE(&stunsignedlong); + break; + case RegClass_VR: + type = TYPE(&stvectorunsignedchar); + break; + default: + CError_FATAL(771); + } + + node->spillTemporary = makespilltemporary(type); + } + + if (node->spillTemporary->datatype == DLOCAL && !(node->spillTemporary->u.var.info->flags & VarInfoFlag1)) + assign_local_memory(node->spillTemporary); + + if (node->flags & fPairHigh) + Registers_GetVarInfo(node->spillTemporary)->regHi = Register0; + else + Registers_GetVarInfo(node->spillTemporary)->reg = Register0; + } +} + +void insertspillcode(void) { + PCodeBlock *block; + PCode *instr; + PCode *nextInstr; + PCodeArg *op; + UInt32 i; + int flag; + + rTEMP_for_VR_spill = 0; + assign_spill_locations(); + + for (block = pcbasicblocks; block; block = block->nextBlock) { + for (instr = block->firstPCode; instr; instr = nextInstr) { + nextInstr = instr->nextPCode; + flag = 0; + op = instr->args; + i = instr->argCount; + while (i--) { + if ( + PC_OP_IS_ANY_REGISTER(op, coloring_class) && + op->data.reg.reg < last_unused_vreg_before_spilling && + (interferencegraph[op->data.reg.reg]->flags & fSpilled) + ) + { + flag = 1; + break; + } + op++; + } + + if (flag) { + if (coloring_class == RegClass_VR && rTEMP_for_VR_spill == 0) + rTEMP_for_VR_spill = used_virtual_registers[RegClass_GPR]++; + + if (instr->flags & fIsMove) + spillcopy(block, instr); + else if (instr->flags & fIsCall) + spillcall(block, instr); + else + spillinstruction(block, instr); + } + } + } +} diff --git a/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation601.c b/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation601.c new file mode 100644 index 0000000..2d54678 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation601.c @@ -0,0 +1,552 @@ +#include "compiler/Scheduler.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" + +// https://stuff.mit.edu/afs/sipb/contrib/doc/specs/ic/cpu/powerpc/mpc601.pdf +// https://www.nxp.com/docs/en/user-guide/MPC601UMAD.pdf + +typedef enum Stage { + IU, // Integer Unit + FD, // FP Decode + FPM, // FP Multiply + FPA, // FP Add + FWA, // FP Arithmetic Writeback + BPU, // Branch Processing Unit + NumStages, + Serialize, // special form for instructions that use IU but are serialised + Unsupported // instructions not supported by this processor +} Stage; + +static struct { + // the instruction currently in this pipeline stage + PCode *instr; + + // how many cycles are left for this instruction to finish + int remaining; +} pipeline[NumStages]; + +static struct { + // the initial stage for this instruction + Stage stage; + + // the total amount of cycles required by this instruction + char latency; + + // how long it takes to finish each stage + char cycles[4]; +} instruction_timing[OPCODE_MAX] = { + BPU, 0, 0, 0, 0, 1, // PC_B + BPU, 0, 0, 0, 0, 1, // PC_BL + BPU, 0, 0, 0, 0, 1, // PC_BC + BPU, 0, 0, 0, 0, 1, // PC_BCLR + BPU, 0, 0, 0, 0, 1, // PC_BCCTR + BPU, 0, 0, 0, 0, 1, // PC_BT + BPU, 0, 0, 0, 0, 1, // PC_BTLR + BPU, 0, 0, 0, 0, 1, // PC_BTCTR + BPU, 0, 0, 0, 0, 1, // PC_BF + BPU, 0, 0, 0, 0, 1, // PC_BFLR + BPU, 0, 0, 0, 0, 1, // PC_BFCTR + BPU, 0, 0, 0, 0, 1, // PC_BDNZ + BPU, 0, 0, 0, 0, 1, // PC_BDNZT + BPU, 0, 0, 0, 0, 1, // PC_BDNZF + BPU, 0, 0, 0, 0, 1, // PC_BDZ + BPU, 0, 0, 0, 0, 1, // PC_BDZT + BPU, 0, 0, 0, 0, 1, // PC_BDZF + BPU, 0, 0, 0, 0, 1, // PC_BLR + BPU, 0, 0, 0, 0, 1, // PC_BCTR + BPU, 0, 0, 0, 0, 1, // PC_BCTRL + BPU, 0, 0, 0, 0, 1, // PC_BLRL + IU, 2, 1, 0, 0, 0, // PC_LBZ + IU, 2, 1, 0, 0, 0, // PC_LBZU + IU, 2, 1, 0, 0, 0, // PC_LBZX + IU, 2, 1, 0, 0, 0, // PC_LBZUX + IU, 2, 1, 0, 0, 0, // PC_LHZ + IU, 2, 1, 0, 0, 0, // PC_LHZU + IU, 2, 1, 0, 0, 0, // PC_LHZX + IU, 2, 1, 0, 0, 0, // PC_LHZUX + IU, 2, 1, 0, 0, 0, // PC_LHA + IU, 2, 1, 0, 0, 0, // PC_LHAU + IU, 2, 1, 0, 0, 0, // PC_LHAX + IU, 2, 1, 0, 0, 0, // PC_LHAUX + IU, 2, 1, 0, 0, 0, // PC_LHBRX + IU, 2, 1, 0, 0, 0, // PC_LWZ + IU, 2, 1, 0, 0, 0, // PC_LWZU + IU, 2, 1, 0, 0, 0, // PC_LWZX + IU, 2, 1, 0, 0, 0, // PC_LWZUX + IU, 2, 1, 0, 0, 0, // PC_LWBRX + IU, 1, 1, 0, 0, 0, // PC_LMW + IU, 1, 1, 0, 0, 0, // PC_STB + IU, 1, 1, 0, 0, 0, // PC_STBU + IU, 1, 1, 0, 0, 0, // PC_STBX + IU, 1, 1, 0, 0, 0, // PC_STBUX + IU, 1, 1, 0, 0, 0, // PC_STH + IU, 1, 1, 0, 0, 0, // PC_STHU + IU, 1, 1, 0, 0, 0, // PC_STHX + IU, 1, 1, 0, 0, 0, // PC_STHUX + IU, 1, 1, 0, 0, 0, // PC_STHBRX + IU, 1, 1, 0, 0, 0, // PC_STW + IU, 1, 1, 0, 0, 0, // PC_STWU + IU, 1, 1, 0, 0, 0, // PC_STWX + IU, 1, 1, 0, 0, 0, // PC_STWUX + IU, 1, 1, 0, 0, 0, // PC_STWBRX + IU, 1, 1, 0, 0, 0, // PC_STMW + IU, 2, 1, 0, 0, 0, // PC_DCBF + IU, 2, 1, 0, 0, 0, // PC_DCBST + IU, 2, 1, 0, 0, 0, // PC_DCBT + IU, 2, 1, 0, 0, 0, // PC_DCBTST + IU, 2, 1, 0, 0, 0, // PC_DCBZ + IU, 1, 1, 0, 0, 0, // PC_ADD + IU, 1, 1, 0, 0, 0, // PC_ADDC + IU, 1, 1, 0, 0, 0, // PC_ADDE + IU, 1, 1, 0, 0, 0, // PC_ADDI + IU, 1, 1, 0, 0, 0, // PC_ADDIC + IU, 1, 1, 0, 0, 0, // PC_ADDICR + IU, 1, 1, 0, 0, 0, // PC_ADDIS + IU, 1, 1, 0, 0, 0, // PC_ADDME + IU, 1, 1, 0, 0, 0, // PC_ADDZE + IU, 36, 36, 0, 0, 0, // PC_DIVW + IU, 36, 36, 0, 0, 0, // PC_DIVWU + IU, 5, 5, 0, 0, 0, // PC_MULHW + IU, 5, 5, 0, 0, 0, // PC_MULHWU + IU, 5, 5, 0, 0, 0, // PC_MULLI + IU, 5, 5, 0, 0, 0, // PC_MULLW + IU, 1, 1, 0, 0, 0, // PC_NEG + IU, 1, 1, 0, 0, 0, // PC_SUBF + IU, 1, 1, 0, 0, 0, // PC_SUBFC + IU, 1, 1, 0, 0, 0, // PC_SUBFE + IU, 1, 1, 0, 0, 0, // PC_SUBFIC + IU, 1, 1, 0, 0, 0, // PC_SUBFME + IU, 1, 1, 0, 0, 0, // PC_SUBFZE + IU, 3, 1, 0, 0, 0, // PC_CMPI + IU, 3, 1, 0, 0, 0, // PC_CMP + IU, 3, 1, 0, 0, 0, // PC_CMPLI + IU, 3, 1, 0, 0, 0, // PC_CMPL + IU, 1, 1, 0, 0, 0, // PC_ANDI + IU, 1, 1, 0, 0, 0, // PC_ANDIS + IU, 1, 1, 0, 0, 0, // PC_ORI + IU, 1, 1, 0, 0, 0, // PC_ORIS + IU, 1, 1, 0, 0, 0, // PC_XORI + IU, 1, 1, 0, 0, 0, // PC_XORIS + IU, 1, 1, 0, 0, 0, // PC_AND + IU, 1, 1, 0, 0, 0, // PC_OR + IU, 1, 1, 0, 0, 0, // PC_XOR + IU, 1, 1, 0, 0, 0, // PC_NAND + IU, 1, 1, 0, 0, 0, // PC_NOR + IU, 1, 1, 0, 0, 0, // PC_EQV + IU, 1, 1, 0, 0, 0, // PC_ANDC + IU, 1, 1, 0, 0, 0, // PC_ORC + IU, 1, 1, 0, 0, 0, // PC_EXTSB + IU, 1, 1, 0, 0, 0, // PC_EXTSH + IU, 1, 1, 0, 0, 0, // PC_CNTLZW + IU, 1, 1, 0, 0, 0, // PC_RLWINM + IU, 1, 1, 0, 0, 0, // PC_RLWNM + IU, 1, 1, 0, 0, 0, // PC_RLWIMI + IU, 1, 1, 0, 0, 0, // PC_SLW + IU, 1, 1, 0, 0, 0, // PC_SRW + IU, 1, 1, 0, 0, 0, // PC_SRAWI + IU, 1, 1, 0, 0, 0, // PC_SRAW + IU, 1, 1, 0, 0, 0, // PC_CRAND + IU, 1, 1, 0, 0, 0, // PC_CRANDC + IU, 1, 1, 0, 0, 0, // PC_CREQV + IU, 1, 1, 0, 0, 0, // PC_CRNAND + IU, 1, 1, 0, 0, 0, // PC_CRNOR + IU, 1, 1, 0, 0, 0, // PC_CROR + IU, 1, 1, 0, 0, 0, // PC_CRORC + IU, 1, 1, 0, 0, 0, // PC_CRXOR + IU, 1, 1, 0, 0, 0, // PC_MCRF + IU, 4, 1, 0, 0, 0, // PC_MTXER + IU, 4, 1, 0, 0, 0, // PC_MTCTR + IU, 4, 1, 0, 0, 0, // PC_MTLR + IU, 2, 1, 0, 0, 0, // PC_MTCRF + IU, 1, 0, 0, 0, 0, // PC_MTMSR + IU, 1, 0, 0, 0, 0, // PC_MTSPR + IU, 1, 0, 0, 0, 0, // PC_MFMSR + IU, 1, 0, 0, 0, 0, // PC_MFSPR + IU, 1, 1, 0, 0, 0, // PC_MFXER + IU, 1, 1, 0, 0, 0, // PC_MFCTR + IU, 1, 1, 0, 0, 0, // PC_MFLR + IU, 1, 1, 0, 0, 0, // PC_MFCR + FD, 4, 1, 1, 1, 1, // PC_MFFS + FD, 4, 1, 1, 1, 1, // PC_MTFSF + Serialize, 1, 1, 0, 0, 1, // PC_EIEIO + Serialize, 1, 1, 0, 0, 1, // PC_ISYNC + Serialize, 1, 1, 0, 0, 1, // PC_SYNC + Serialize, 0, 0, 0, 0, 1, // PC_RFI + IU, 1, 1, 0, 0, 0, // PC_LI + IU, 1, 1, 0, 0, 0, // PC_LIS + IU, 1, 1, 0, 0, 0, // PC_MR + IU, 1, 1, 0, 0, 0, // PC_NOP + IU, 1, 1, 0, 0, 0, // PC_NOT + IU, 3, 1, 0, 0, 0, // PC_LFS + IU, 3, 1, 0, 0, 0, // PC_LFSU + IU, 3, 1, 0, 0, 0, // PC_LFSX + IU, 3, 1, 0, 0, 0, // PC_LFSUX + IU, 3, 1, 0, 0, 0, // PC_LFD + IU, 3, 1, 0, 0, 0, // PC_LFDU + IU, 3, 1, 0, 0, 0, // PC_LFDX + IU, 3, 1, 0, 0, 0, // PC_LFDUX + IU, 1, 1, 0, 0, 0, // PC_STFS + IU, 1, 1, 0, 0, 0, // PC_STFSU + IU, 1, 1, 0, 0, 0, // PC_STFSX + IU, 1, 1, 0, 0, 0, // PC_STFSUX + IU, 1, 1, 0, 0, 0, // PC_STFD + IU, 1, 1, 0, 0, 0, // PC_STFDU + IU, 1, 1, 0, 0, 0, // PC_STFDX + IU, 1, 1, 0, 0, 0, // PC_STFDUX + FD, 4, 1, 1, 1, 1, // PC_FMR + FD, 4, 1, 1, 1, 1, // PC_FABS + FD, 4, 1, 1, 1, 1, // PC_FNEG + FD, 4, 1, 1, 1, 1, // PC_FNABS + FD, 4, 1, 1, 1, 1, // PC_FADD + FD, 4, 1, 1, 1, 1, // PC_FADDS + FD, 4, 1, 1, 1, 1, // PC_FSUB + FD, 4, 1, 1, 1, 1, // PC_FSUBS + FD, 5, 1, 1, 2, 1, // PC_FMUL + FD, 4, 1, 1, 1, 1, // PC_FMULS + FD, 31, 1, 1, 28, 1, // PC_FDIV + FD, 17, 1, 1, 14, 1, // PC_FDIVS + FD, 5, 1, 1, 2, 1, // PC_FMADD + FD, 4, 1, 1, 1, 1, // PC_FMADDS + FD, 5, 1, 1, 2, 1, // PC_FMSUB + FD, 4, 1, 1, 1, 1, // PC_FMSUBS + FD, 5, 1, 1, 2, 1, // PC_FNMADD + FD, 4, 1, 1, 1, 1, // PC_FNMADDS + FD, 5, 1, 1, 2, 1, // PC_FNMSUB + FD, 4, 1, 1, 1, 1, // PC_FNMSUBS + FD, 4, 1, 1, 1, 1, // PC_FRES + FD, 4, 1, 1, 1, 1, // PC_FRSQRTE + FD, 4, 1, 1, 1, 1, // PC_FSEL + FD, 4, 1, 1, 1, 1, // PC_FRSP + FD, 4, 1, 1, 1, 1, // PC_FCTIW + FD, 4, 1, 1, 1, 1, // PC_FCTIWZ + FD, 6, 1, 1, 1, 1, // PC_FCMPU + FD, 6, 1, 1, 1, 1, // PC_FCMPO + IU, 0, 0, 0, 0, 0, // PC_LWARX + IU, 0, 0, 0, 0, 0, // PC_LSWI + IU, 0, 0, 0, 0, 0, // PC_LSWX + IU, 0, 0, 0, 0, 0, // PC_STFIWX + IU, 0, 0, 0, 0, 0, // PC_STSWI + IU, 0, 0, 0, 0, 0, // PC_STSWX + IU, 0, 0, 0, 0, 0, // PC_STWCX + IU, 0, 0, 0, 0, 0, // PC_ECIWX + IU, 0, 0, 0, 0, 0, // PC_ECOWX + IU, 0, 0, 0, 0, 0, // PC_DCBI + IU, 0, 0, 0, 0, 0, // PC_ICBI + IU, 0, 0, 0, 0, 0, // PC_MCRFS + IU, 0, 0, 0, 0, 0, // PC_MCRXR + IU, 0, 0, 0, 0, 0, // PC_MFTB + IU, 0, 0, 0, 0, 0, // PC_MFSR + IU, 0, 0, 0, 0, 0, // PC_MTSR + IU, 0, 0, 0, 0, 0, // PC_MFSRIN + IU, 0, 0, 0, 0, 0, // PC_MTSRIN + IU, 0, 0, 0, 0, 0, // PC_MTFSB0 + IU, 0, 0, 0, 0, 0, // PC_MTFSB1 + IU, 0, 0, 0, 0, 0, // PC_MTFSFI + Serialize, 0, 0, 0, 0, 0, // PC_SC + IU, 0, 0, 0, 0, 0, // PC_FSQRT + IU, 0, 0, 0, 0, 0, // PC_FSQRTS + IU, 0, 0, 0, 0, 0, // PC_TLBIA + IU, 0, 0, 0, 0, 0, // PC_TLBIE + IU, 0, 0, 0, 0, 0, // PC_TLBLD + IU, 0, 0, 0, 0, 0, // PC_TLBLI + IU, 0, 0, 0, 0, 0, // PC_TLBSYNC + Serialize, 0, 0, 0, 0, 0, // PC_TW + Serialize, 0, 0, 0, 0, 0, // PC_TRAP + Serialize, 0, 0, 0, 0, 0, // PC_TWI + Serialize, 0, 0, 0, 0, 0, // PC_OPWORD + IU, 0, 0, 0, 0, 0, // PC_MFROM + IU, 0, 0, 0, 0, 0, // PC_DSA + IU, 0, 0, 0, 0, 0, // PC_ESA + IU, 0, 0, 0, 0, 0, // PC_DCCCI + IU, 0, 0, 0, 0, 0, // PC_DCREAD + IU, 0, 0, 0, 0, 0, // PC_ICBT + IU, 0, 0, 0, 0, 0, // PC_ICCCI + IU, 0, 0, 0, 0, 0, // PC_ICREAD + IU, 0, 0, 0, 0, 0, // PC_RFCI + IU, 0, 0, 0, 0, 0, // PC_TLBRE + IU, 0, 0, 0, 0, 0, // PC_TLBSX + IU, 0, 0, 0, 0, 0, // PC_TLBWE + IU, 0, 0, 0, 0, 0, // PC_WRTEE + IU, 0, 0, 0, 0, 0, // PC_WRTEEI + IU, 0, 0, 0, 0, 0, // PC_MFDCR + IU, 0, 0, 0, 0, 0, // PC_MTDCR + Unsupported, 0, 0, 0, 0, 0, // PC_DCBA + Unsupported, 0, 0, 0, 0, 0, // PC_DSS + Unsupported, 0, 0, 0, 0, 0, // PC_DSSALL + Unsupported, 0, 0, 0, 0, 0, // PC_DST + Unsupported, 0, 0, 0, 0, 0, // PC_DSTT + Unsupported, 0, 0, 0, 0, 0, // PC_DSTST + Unsupported, 0, 0, 0, 0, 0, // PC_DSTSTT + Unsupported, 0, 0, 0, 0, 0, // PC_LVEBX + Unsupported, 0, 0, 0, 0, 0, // PC_LVEHX + Unsupported, 0, 0, 0, 0, 0, // PC_LVEWX + Unsupported, 0, 0, 0, 0, 0, // PC_LVSL + Unsupported, 0, 0, 0, 0, 0, // PC_LVSR + Unsupported, 0, 0, 0, 0, 0, // PC_LVX + Unsupported, 0, 0, 0, 0, 0, // PC_LVXL + Unsupported, 0, 0, 0, 0, 0, // PC_STVEBX + Unsupported, 0, 0, 0, 0, 0, // PC_STVEHX + Unsupported, 0, 0, 0, 0, 0, // PC_STVEWX + Unsupported, 0, 0, 0, 0, 0, // PC_STVX + Unsupported, 0, 0, 0, 0, 0, // PC_STVXL + Unsupported, 0, 0, 0, 0, 0, // PC_MFVSCR + Unsupported, 0, 0, 0, 0, 0, // PC_MTVSCR + Unsupported, 0, 0, 0, 0, 0, // PC_VADDCUW + Unsupported, 0, 0, 0, 0, 0, // PC_VADDFP + Unsupported, 0, 0, 0, 0, 0, // PC_VADDSBS + Unsupported, 0, 0, 0, 0, 0, // PC_VADDSHS + Unsupported, 0, 0, 0, 0, 0, // PC_VADDSWS + Unsupported, 0, 0, 0, 0, 0, // PC_VADDUBM + Unsupported, 0, 0, 0, 0, 0, // PC_VADDUBS + Unsupported, 0, 0, 0, 0, 0, // PC_VADDUHM + Unsupported, 0, 0, 0, 0, 0, // PC_VADDUHS + Unsupported, 0, 0, 0, 0, 0, // PC_VADDUWM + Unsupported, 0, 0, 0, 0, 0, // PC_VADDUWS + Unsupported, 0, 0, 0, 0, 0, // PC_VAND + Unsupported, 0, 0, 0, 0, 0, // PC_VANDC + Unsupported, 0, 0, 0, 0, 0, // PC_VAVGSB + Unsupported, 0, 0, 0, 0, 0, // PC_VAVGSH + Unsupported, 0, 0, 0, 0, 0, // PC_VAVGSW + Unsupported, 0, 0, 0, 0, 0, // PC_VAVGUB + Unsupported, 0, 0, 0, 0, 0, // PC_VAVGUH + Unsupported, 0, 0, 0, 0, 0, // PC_VAVGUW + Unsupported, 0, 0, 0, 0, 0, // PC_VCFSX + Unsupported, 0, 0, 0, 0, 0, // PC_VCFUX + Unsupported, 0, 0, 0, 0, 0, // PC_VCMPBFP + Unsupported, 0, 0, 0, 0, 0, // PC_VCMPEQFP + Unsupported, 0, 0, 0, 0, 0, // PC_VCMPEQUB + Unsupported, 0, 0, 0, 0, 0, // PC_VCMPEQUH + Unsupported, 0, 0, 0, 0, 0, // PC_VCMPEQUW + Unsupported, 0, 0, 0, 0, 0, // PC_VCMPGEFP + Unsupported, 0, 0, 0, 0, 0, // PC_VCMPGTFP + Unsupported, 0, 0, 0, 0, 0, // PC_VCMPGTSB + Unsupported, 0, 0, 0, 0, 0, // PC_VCMPGTSH + Unsupported, 0, 0, 0, 0, 0, // PC_VCMPGTSW + Unsupported, 0, 0, 0, 0, 0, // PC_VCMPGTUB + Unsupported, 0, 0, 0, 0, 0, // PC_VCMPGTUH + Unsupported, 0, 0, 0, 0, 0, // PC_VCMPGTUW + Unsupported, 0, 0, 0, 0, 0, // PC_VCTSXS + Unsupported, 0, 0, 0, 0, 0, // PC_VCTUXS + Unsupported, 0, 0, 0, 0, 0, // PC_VEXPTEFP + Unsupported, 0, 0, 0, 0, 0, // PC_VLOGEFP + Unsupported, 0, 0, 0, 0, 0, // PC_VMAXFP + Unsupported, 0, 0, 0, 0, 0, // PC_VMAXSB + Unsupported, 0, 0, 0, 0, 0, // PC_VMAXSH + Unsupported, 0, 0, 0, 0, 0, // PC_VMAXSW + Unsupported, 0, 0, 0, 0, 0, // PC_VMAXUB + Unsupported, 0, 0, 0, 0, 0, // PC_VMAXUH + Unsupported, 0, 0, 0, 0, 0, // PC_VMAXUW + Unsupported, 0, 0, 0, 0, 0, // PC_VMINFP + Unsupported, 0, 0, 0, 0, 0, // PC_VMINSB + Unsupported, 0, 0, 0, 0, 0, // PC_VMINSH + Unsupported, 0, 0, 0, 0, 0, // PC_VMINSW + Unsupported, 0, 0, 0, 0, 0, // PC_VMINUB + Unsupported, 0, 0, 0, 0, 0, // PC_VMINUH + Unsupported, 0, 0, 0, 0, 0, // PC_VMINUW + Unsupported, 0, 0, 0, 0, 0, // PC_VMRGHB + Unsupported, 0, 0, 0, 0, 0, // PC_VMRGHH + Unsupported, 0, 0, 0, 0, 0, // PC_VMRGHW + Unsupported, 0, 0, 0, 0, 0, // PC_VMRGLB + Unsupported, 0, 0, 0, 0, 0, // PC_VMRGLH + Unsupported, 0, 0, 0, 0, 0, // PC_VMRGLW + Unsupported, 0, 0, 0, 0, 0, // PC_VMULESB + Unsupported, 0, 0, 0, 0, 0, // PC_VMULESH + Unsupported, 0, 0, 0, 0, 0, // PC_VMULEUB + Unsupported, 0, 0, 0, 0, 0, // PC_VMULEUH + Unsupported, 0, 0, 0, 0, 0, // PC_VMULOSB + Unsupported, 0, 0, 0, 0, 0, // PC_VMULOSH + Unsupported, 0, 0, 0, 0, 0, // PC_VMULOUB + Unsupported, 0, 0, 0, 0, 0, // PC_VMULOUH + Unsupported, 0, 0, 0, 0, 0, // PC_VNOR + Unsupported, 0, 0, 0, 0, 0, // PC_VOR + Unsupported, 0, 0, 0, 0, 0, // PC_VPKPX + Unsupported, 0, 0, 0, 0, 0, // PC_VPKSHSS + Unsupported, 0, 0, 0, 0, 0, // PC_VPKSHUS + Unsupported, 0, 0, 0, 0, 0, // PC_VPKSWSS + Unsupported, 0, 0, 0, 0, 0, // PC_VPKSWUS + Unsupported, 0, 0, 0, 0, 0, // PC_VPKUHUM + Unsupported, 0, 0, 0, 0, 0, // PC_VPKUHUS + Unsupported, 0, 0, 0, 0, 0, // PC_VPKUWUM + Unsupported, 0, 0, 0, 0, 0, // PC_VPKUWUS + Unsupported, 0, 0, 0, 0, 0, // PC_VREFP + Unsupported, 0, 0, 0, 0, 0, // PC_VRFIM + Unsupported, 0, 0, 0, 0, 0, // PC_VRFIN + Unsupported, 0, 0, 0, 0, 0, // PC_VRFIP + Unsupported, 0, 0, 0, 0, 0, // PC_VRFIZ + Unsupported, 0, 0, 0, 0, 0, // PC_VRLB + Unsupported, 0, 0, 0, 0, 0, // PC_VRLH + Unsupported, 0, 0, 0, 0, 0, // PC_VRLW + Unsupported, 0, 0, 0, 0, 0, // PC_VRSQRTEFP + Unsupported, 0, 0, 0, 0, 0, // PC_VSL + Unsupported, 0, 0, 0, 0, 0, // PC_VSLB + Unsupported, 0, 0, 0, 0, 0, // PC_VSLH + Unsupported, 0, 0, 0, 0, 0, // PC_VSLO + Unsupported, 0, 0, 0, 0, 0, // PC_VSLW + Unsupported, 0, 0, 0, 0, 0, // PC_VSPLTB + Unsupported, 0, 0, 0, 0, 0, // PC_VSPLTH + Unsupported, 0, 0, 0, 0, 0, // PC_VSPLTW + Unsupported, 0, 0, 0, 0, 0, // PC_VSPLTISB + Unsupported, 0, 0, 0, 0, 0, // PC_VSPLTISH + Unsupported, 0, 0, 0, 0, 0, // PC_VSPLTISW + Unsupported, 0, 0, 0, 0, 0, // PC_VSR + Unsupported, 0, 0, 0, 0, 0, // PC_VSRAB + Unsupported, 0, 0, 0, 0, 0, // PC_VSRAH + Unsupported, 0, 0, 0, 0, 0, // PC_VSRAW + Unsupported, 0, 0, 0, 0, 0, // PC_VSRB + Unsupported, 0, 0, 0, 0, 0, // PC_VSRH + Unsupported, 0, 0, 0, 0, 0, // PC_VSRO + Unsupported, 0, 0, 0, 0, 0, // PC_VSRW + Unsupported, 0, 0, 0, 0, 0, // PC_VSUBCUW + Unsupported, 0, 0, 0, 0, 0, // PC_VSUBFP + Unsupported, 0, 0, 0, 0, 0, // PC_VSUBSBS + Unsupported, 0, 0, 0, 0, 0, // PC_VSUBSHS + Unsupported, 0, 0, 0, 0, 0, // PC_VSUBSWS + Unsupported, 0, 0, 0, 0, 0, // PC_VSUBUBM + Unsupported, 0, 0, 0, 0, 0, // PC_VSUBUBS + Unsupported, 0, 0, 0, 0, 0, // PC_VSUBUHM + Unsupported, 0, 0, 0, 0, 0, // PC_VSUBUHS + Unsupported, 0, 0, 0, 0, 0, // PC_VSUBUWM + Unsupported, 0, 0, 0, 0, 0, // PC_VSUBUWS + Unsupported, 0, 0, 0, 0, 0, // PC_VSUMSWS + Unsupported, 0, 0, 0, 0, 0, // PC_VSUFPMSWS + Unsupported, 0, 0, 0, 0, 0, // PC_VSUFWASBS + Unsupported, 0, 0, 0, 0, 0, // PC_VSUFWASHS + Unsupported, 0, 0, 0, 0, 0, // PC_VSUFWAUBS + Unsupported, 0, 0, 0, 0, 0, // PC_VUPKHPX + Unsupported, 0, 0, 0, 0, 0, // PC_VUPKHSB + Unsupported, 0, 0, 0, 0, 0, // PC_VUPKHSH + Unsupported, 0, 0, 0, 0, 0, // PC_VUPKLPX + Unsupported, 0, 0, 0, 0, 0, // PC_VUPKLSB + Unsupported, 0, 0, 0, 0, 0, // PC_VUPKLSH + Unsupported, 0, 0, 0, 0, 0, // PC_VXOR + Unsupported, 0, 0, 0, 0, 0, // PC_VMADDFP + Unsupported, 0, 0, 0, 0, 0, // PC_VMHADDSHS + Unsupported, 0, 0, 0, 0, 0, // PC_VMHRADDSHS + Unsupported, 0, 0, 0, 0, 0, // PC_VMLADDUHM + Unsupported, 0, 0, 0, 0, 0, // PC_VMSUMMBM + Unsupported, 0, 0, 0, 0, 0, // PC_VMSUMSHM + Unsupported, 0, 0, 0, 0, 0, // PC_VMSUMSHS + Unsupported, 0, 0, 0, 0, 0, // PC_VMSUMUBM + Unsupported, 0, 0, 0, 0, 0, // PC_VMSUMUHM + Unsupported, 0, 0, 0, 0, 0, // PC_VMSUMUHS + Unsupported, 0, 0, 0, 0, 0, // PC_VNMSUBFP + Unsupported, 0, 0, 0, 0, 0, // PC_VPERM + Unsupported, 0, 0, 0, 0, 0, // PC_VSEL + Unsupported, 0, 0, 0, 0, 0, // PC_VSLDOI + Unsupported, 0, 0, 0, 0, 0, // PC_VMR + Unsupported, 0, 0, 0, 0, 0, // PC_VMRP + IU, 0, 0, 0, 0, 0, // PC_SLE + IU, 0, 0, 0, 0, 0, // PC_SLEQ + IU, 0, 0, 0, 0, 0, // PC_SLIQ + IU, 0, 0, 0, 0, 0, // PC_SLLIQ + IU, 0, 0, 0, 0, 0, // PC_SLLQ + IU, 0, 0, 0, 0, 0, // PC_SLQ + IU, 0, 0, 0, 0, 0, // PC_SRAIQ + IU, 0, 0, 0, 0, 0, // PC_SRAQ + IU, 0, 0, 0, 0, 0, // PC_SRE + IU, 0, 0, 0, 0, 0, // PC_SREA + IU, 0, 0, 0, 0, 0, // PC_SREQ + IU, 0, 0, 0, 0, 0, // PC_SRIQ + IU, 0, 0, 0, 0, 0, // PC_SRLIQ + IU, 0, 0, 0, 0, 0, // PC_SRLQ + IU, 0, 0, 0, 0, 0, // PC_SRQ + IU, 0, 0, 0, 0, 0, // PC_MASKG + IU, 0, 0, 0, 0, 0, // PC_MASKIR + IU, 0, 0, 0, 0, 0, // PC_LSCBX + IU, 0, 0, 0, 0, 0, // PC_DIV + IU, 0, 0, 0, 0, 0, // PC_DIVS + IU, 0, 0, 0, 0, 0, // PC_DOZ + IU, 0, 0, 0, 0, 0, // PC_MUL + IU, 0, 0, 0, 0, 0, // PC_NABS + IU, 0, 0, 0, 0, 0, // PC_ABS + IU, 0, 0, 0, 0, 0, // PC_CLCS + IU, 0, 0, 0, 0, 0, // PC_DOZI + IU, 0, 0, 0, 0, 0, // PC_RLMI + IU, 0, 0, 0, 0, 0, // PC_RRIB +}; + +static void advance(int stageCount, int oldStage, int newStage) { + PCode *instr = pipeline[oldStage].instr; + int cycles = instruction_timing[instr->op].cycles[newStage - stageCount]; + pipeline[newStage].instr = instr; + pipeline[newStage].remaining = cycles; + pipeline[oldStage].instr = NULL; +} + +static void complete_instruction(int stage) { + pipeline[stage].instr = NULL; +} + +static int latency(PCode *instr) { + int cycles = instruction_timing[instr->op].latency; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + cycles += 2; + if (instr->op == PC_LMW || instr->op == PC_STMW) + cycles += instr->argCount - 2; + return cycles; +} + +static void initialize(void) { + int stage; + + for (stage = 0; stage < NumStages; stage++) + pipeline[stage].instr = NULL; +} + +static int can_issue(PCode *instr) { + int stage = instruction_timing[instr->op].stage; + if (stage == Serialize) + stage = IU; + if (pipeline[stage].instr) + return 0; + return 1; +} + +static void issue(PCode *instr) { + int stage = instruction_timing[instr->op].stage; + int cycles = instruction_timing[instr->op].cycles[IU]; + if (stage == Serialize) + stage = IU; + pipeline[stage].instr = instr; + pipeline[stage].remaining = cycles; +} + +static void advance_clock(void) { + int stage; + + for (stage = 0; stage < NumStages; stage++) { + if (pipeline[stage].instr && pipeline[stage].remaining) + --pipeline[stage].remaining; + } + + if (pipeline[IU].instr && pipeline[IU].remaining == 0) + complete_instruction(IU); + if (pipeline[FWA].instr && pipeline[FWA].remaining == 0) + complete_instruction(FWA); + if (pipeline[BPU].instr && pipeline[BPU].remaining == 0) + complete_instruction(BPU); + + if (pipeline[FPA].instr && pipeline[FPA].remaining == 0 && !pipeline[FWA].instr) + advance(1, FPA, FWA); + if (pipeline[FPM].instr && pipeline[FPM].remaining == 0 && !pipeline[FPA].instr) + advance(1, FPM, FPA); + if (pipeline[FD].instr && pipeline[FD].remaining == 0 && !pipeline[FPM].instr) + advance(1, FD, FPM); +} + +static int serializes(PCode *instr) { + return instruction_timing[instr->op].stage == Serialize; +} + +MachineInfo machine601 = { + 2, + 0, + 0, + &latency, + &initialize, + &can_issue, + &issue, + &advance_clock, + &serializes, + &default_uses_vpermute_unit +}; diff --git a/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation603.c b/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation603.c new file mode 100644 index 0000000..49d1ea0 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation603.c @@ -0,0 +1,626 @@ +#include "compiler/Scheduler.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" + +// this is actually for 603e, but i couldn't find the 603 doc +// https://www.nxp.com/docs/en/reference-manual/MPC603EUM.pdf + +typedef enum Stage { + BPU, // Branch Prediction Unit + IU, // Integer Unit + LSU1, // Load/Store Unit + LSU2, + FPU1, // Floating Point Unit + FPU2, + FPU3, + SRU, // System Register Unit + NumStages +} Stage; + +static struct { + // the instruction currently in this pipeline stage + PCode *instr; + + // how many cycles are left for this instruction to finish + int remaining; +} pipeline[NumStages]; + +enum { + MaxEntries = 5 +}; + +static struct { + // how many entries remain unused in the queue + unsigned int free; + + // how many entries are currently used in the queue + unsigned int used; + + // the index of the next instruction that will be retired + unsigned int nextToRetire; + + // the index of the next free slot that will be used when an instruction is dispatched + unsigned int nextFreeSlot; + + // circular array of entries in the completion queue + struct { + PCode *instr; + int completed; + } entries[MaxEntries]; +} completionbuffers; + +static struct { + // the initial stage for this instruction + Stage stage; + + // the total amount of cycles required by this instruction + char latency; + + // how long it takes to finish each stage + char cycles[3]; + + // does this instruction serialise? + char serializes; +} instruction_timing[OPCODE_MAX] = { + BPU, 0, 0, 0, 0, 1, // PC_B + BPU, 0, 0, 0, 0, 1, // PC_BL + BPU, 0, 0, 0, 0, 1, // PC_BC + BPU, 0, 0, 0, 0, 1, // PC_BCLR + BPU, 0, 0, 0, 0, 1, // PC_BCCTR + BPU, 0, 0, 0, 0, 1, // PC_BT + BPU, 0, 0, 0, 0, 1, // PC_BTLR + BPU, 0, 0, 0, 0, 1, // PC_BTCTR + BPU, 0, 0, 0, 0, 1, // PC_BF + BPU, 0, 0, 0, 0, 1, // PC_BFLR + BPU, 0, 0, 0, 0, 1, // PC_BFCTR + BPU, 0, 0, 0, 0, 1, // PC_BDNZ + BPU, 0, 0, 0, 0, 1, // PC_BDNZT + BPU, 0, 0, 0, 0, 1, // PC_BDNZF + BPU, 0, 0, 0, 0, 1, // PC_BDZ + BPU, 0, 0, 0, 0, 1, // PC_BDZT + BPU, 0, 0, 0, 0, 1, // PC_BDZF + BPU, 0, 0, 0, 0, 1, // PC_BLR + BPU, 0, 0, 0, 0, 1, // PC_BCTR + BPU, 0, 0, 0, 0, 1, // PC_BCTRL + BPU, 0, 0, 0, 0, 1, // PC_BLRL + LSU1, 2, 1, 1, 0, 0, // PC_LBZ + LSU1, 2, 1, 1, 0, 0, // PC_LBZU + LSU1, 2, 1, 1, 0, 0, // PC_LBZX + LSU1, 2, 1, 1, 0, 0, // PC_LBZUX + LSU1, 2, 1, 1, 0, 0, // PC_LHZ + LSU1, 2, 1, 1, 0, 0, // PC_LHZU + LSU1, 2, 1, 1, 0, 0, // PC_LHZX + LSU1, 2, 1, 1, 0, 0, // PC_LHZUX + LSU1, 2, 1, 1, 0, 0, // PC_LHA + LSU1, 2, 1, 1, 0, 0, // PC_LHAU + LSU1, 2, 1, 1, 0, 0, // PC_LHAX + LSU1, 2, 1, 1, 0, 0, // PC_LHAUX + LSU1, 2, 1, 1, 0, 0, // PC_LHBRX + LSU1, 2, 1, 1, 0, 0, // PC_LWZ + LSU1, 2, 1, 1, 0, 0, // PC_LWZU + LSU1, 2, 1, 1, 0, 0, // PC_LWZX + LSU1, 2, 1, 1, 0, 0, // PC_LWZUX + LSU1, 2, 1, 1, 0, 0, // PC_LWBRX + LSU1, 2, 1, 1, 0, 0, // PC_LMW + LSU1, 2, 1, 1, 0, 0, // PC_STB + LSU1, 2, 1, 1, 0, 0, // PC_STBU + LSU1, 2, 1, 1, 0, 0, // PC_STBX + LSU1, 2, 1, 1, 0, 0, // PC_STBUX + LSU1, 2, 1, 1, 0, 0, // PC_STH + LSU1, 2, 1, 1, 0, 0, // PC_STHU + LSU1, 2, 1, 1, 0, 0, // PC_STHX + LSU1, 2, 1, 1, 0, 0, // PC_STHUX + LSU1, 2, 1, 1, 0, 0, // PC_STHBRX + LSU1, 2, 1, 1, 0, 0, // PC_STW + LSU1, 2, 1, 1, 0, 0, // PC_STWU + LSU1, 2, 1, 1, 0, 0, // PC_STWX + LSU1, 2, 1, 1, 0, 0, // PC_STWUX + LSU1, 2, 1, 1, 0, 0, // PC_STWBRX + LSU1, 2, 1, 1, 0, 0, // PC_STMW + LSU1, 2, 1, 1, 0, 0, // PC_DCBF + LSU1, 2, 1, 1, 0, 0, // PC_DCBST + LSU1, 2, 1, 1, 0, 0, // PC_DCBT + LSU1, 2, 1, 1, 0, 0, // PC_DCBTST + LSU1, 2, 1, 1, 0, 0, // PC_DCBZ + IU, 1, 1, 0, 0, 0, // PC_ADD + IU, 1, 1, 0, 0, 0, // PC_ADDC + IU, 1, 1, 0, 0, 0, // PC_ADDE + IU, 1, 1, 0, 0, 0, // PC_ADDI + IU, 1, 1, 0, 0, 0, // PC_ADDIC + IU, 1, 1, 0, 0, 0, // PC_ADDICR + IU, 1, 1, 0, 0, 0, // PC_ADDIS + IU, 1, 1, 0, 0, 0, // PC_ADDME + IU, 1, 1, 0, 0, 0, // PC_ADDZE + IU, 37, 37, 0, 0, 0, // PC_DIVW + IU, 37, 37, 0, 0, 0, // PC_DIVWU + IU, 5, 5, 0, 0, 0, // PC_MULHW + IU, 5, 5, 0, 0, 0, // PC_MULHWU + IU, 3, 3, 0, 0, 0, // PC_MULLI + IU, 5, 5, 0, 0, 0, // PC_MULLW + IU, 1, 1, 0, 0, 0, // PC_NEG + IU, 1, 1, 0, 0, 0, // PC_SUBF + IU, 1, 1, 0, 0, 0, // PC_SUBFC + IU, 1, 1, 0, 0, 0, // PC_SUBFE + IU, 1, 1, 0, 0, 0, // PC_SUBFIC + IU, 1, 1, 0, 0, 0, // PC_SUBFME + IU, 1, 1, 0, 0, 0, // PC_SUBFZE + IU, 3, 1, 0, 0, 0, // PC_CMPI + IU, 3, 1, 0, 0, 0, // PC_CMP + IU, 3, 1, 0, 0, 0, // PC_CMPLI + IU, 3, 1, 0, 0, 0, // PC_CMPL + IU, 1, 1, 0, 0, 0, // PC_ANDI + IU, 1, 1, 0, 0, 0, // PC_ANDIS + IU, 1, 1, 0, 0, 0, // PC_ORI + IU, 1, 1, 0, 0, 0, // PC_ORIS + IU, 1, 1, 0, 0, 0, // PC_XORI + IU, 1, 1, 0, 0, 0, // PC_XORIS + IU, 1, 1, 0, 0, 0, // PC_AND + IU, 1, 1, 0, 0, 0, // PC_OR + IU, 1, 1, 0, 0, 0, // PC_XOR + IU, 1, 1, 0, 0, 0, // PC_NAND + IU, 1, 1, 0, 0, 0, // PC_NOR + IU, 1, 1, 0, 0, 0, // PC_EQV + IU, 1, 1, 0, 0, 0, // PC_ANDC + IU, 1, 1, 0, 0, 0, // PC_ORC + IU, 1, 1, 0, 0, 0, // PC_EXTSB + IU, 1, 1, 0, 0, 0, // PC_EXTSH + IU, 1, 1, 0, 0, 0, // PC_CNTLZW + IU, 1, 1, 0, 0, 0, // PC_RLWINM + IU, 1, 1, 0, 0, 0, // PC_RLWNM + IU, 1, 1, 0, 0, 0, // PC_RLWIMI + IU, 1, 1, 0, 0, 0, // PC_SLW + IU, 1, 1, 0, 0, 0, // PC_SRW + IU, 1, 1, 0, 0, 0, // PC_SRAWI + IU, 1, 1, 0, 0, 0, // PC_SRAW + SRU, 1, 1, 0, 0, 0, // PC_CRAND + SRU, 1, 1, 0, 0, 0, // PC_CRANDC + SRU, 1, 1, 0, 0, 0, // PC_CREQV + SRU, 1, 1, 0, 0, 0, // PC_CRNAND + SRU, 1, 1, 0, 0, 0, // PC_CRNOR + SRU, 1, 1, 0, 0, 0, // PC_CROR + SRU, 1, 1, 0, 0, 0, // PC_CRORC + SRU, 1, 1, 0, 0, 0, // PC_CRXOR + SRU, 1, 1, 0, 0, 0, // PC_MCRF + SRU, 2, 2, 0, 0, 0, // PC_MTXER + SRU, 2, 2, 0, 0, 0, // PC_MTCTR + SRU, 2, 2, 0, 0, 0, // PC_MTLR + SRU, 1, 1, 0, 0, 0, // PC_MTCRF + SRU, 1, 1, 0, 0, 1, // PC_MTMSR + SRU, 1, 1, 0, 0, 1, // PC_MTSPR + SRU, 1, 1, 0, 0, 1, // PC_MFMSR + SRU, 1, 1, 0, 0, 1, // PC_MFSPR + SRU, 1, 1, 0, 0, 0, // PC_MFXER + SRU, 1, 1, 0, 0, 0, // PC_MFCTR + SRU, 1, 1, 0, 0, 0, // PC_MFLR + SRU, 1, 1, 0, 0, 0, // PC_MFCR + FPU1, 3, 1, 1, 1, 0, // PC_MFFS + FPU1, 3, 1, 1, 1, 0, // PC_MTFSF + SRU, 1, 1, 0, 0, 1, // PC_EIEIO + SRU, 1, 1, 0, 0, 1, // PC_ISYNC + SRU, 1, 1, 0, 0, 1, // PC_SYNC + SRU, 1, 1, 0, 0, 1, // PC_RFI + IU, 1, 1, 0, 0, 0, // PC_LI + IU, 1, 1, 0, 0, 0, // PC_LIS + IU, 1, 1, 0, 0, 0, // PC_MR + IU, 1, 1, 0, 0, 0, // PC_NOP + IU, 1, 1, 0, 0, 0, // PC_NOT + LSU1, 2, 1, 1, 0, 0, // PC_LFS + LSU1, 2, 1, 1, 0, 0, // PC_LFSU + LSU1, 2, 1, 1, 0, 0, // PC_LFSX + LSU1, 2, 1, 1, 0, 0, // PC_LFSUX + LSU1, 2, 1, 1, 0, 0, // PC_LFD + LSU1, 2, 1, 1, 0, 0, // PC_LFDU + LSU1, 2, 1, 1, 0, 0, // PC_LFDX + LSU1, 2, 1, 1, 0, 0, // PC_LFDUX + LSU1, 2, 1, 1, 0, 0, // PC_STFS + LSU1, 2, 1, 1, 0, 0, // PC_STFSU + LSU1, 2, 1, 1, 0, 0, // PC_STFSX + LSU1, 2, 1, 1, 0, 0, // PC_STFSUX + LSU1, 2, 1, 1, 0, 0, // PC_STFD + LSU1, 2, 1, 1, 0, 0, // PC_STFDU + LSU1, 2, 1, 1, 0, 0, // PC_STFDX + LSU1, 2, 1, 1, 0, 0, // PC_STFDUX + FPU1, 3, 1, 1, 1, 0, // PC_FMR + FPU1, 3, 1, 1, 1, 0, // PC_FABS + FPU1, 3, 1, 1, 1, 0, // PC_FNEG + FPU1, 3, 1, 1, 1, 0, // PC_FNABS + FPU1, 3, 1, 1, 1, 0, // PC_FADD + FPU1, 3, 1, 1, 1, 0, // PC_FADDS + FPU1, 3, 1, 1, 1, 0, // PC_FSUB + FPU1, 3, 1, 1, 1, 0, // PC_FSUBS + FPU1, 4, 2, 1, 1, 0, // PC_FMUL + FPU1, 3, 1, 1, 1, 0, // PC_FMULS + FPU1, 33, 33, 0, 0, 0, // PC_FDIV + FPU1, 18, 18, 0, 0, 0, // PC_FDIVS + FPU1, 4, 2, 1, 1, 0, // PC_FMADD + FPU1, 3, 1, 1, 1, 0, // PC_FMADDS + FPU1, 4, 2, 1, 1, 0, // PC_FMSUB + FPU1, 3, 1, 1, 1, 0, // PC_FMSUBS + FPU1, 4, 2, 1, 1, 0, // PC_FNMADD + FPU1, 3, 1, 1, 1, 0, // PC_FNMADDS + FPU1, 4, 2, 1, 1, 0, // PC_FNMSUB + FPU1, 3, 1, 1, 1, 0, // PC_FNMSUBS + FPU1, 18, 18, 0, 0, 0, // PC_FRES + FPU1, 3, 1, 1, 1, 0, // PC_FRSQRTE + FPU1, 3, 1, 1, 1, 0, // PC_FSEL + FPU1, 3, 1, 1, 1, 0, // PC_FRSP + FPU1, 3, 1, 1, 1, 0, // PC_FCTIW + FPU1, 3, 1, 1, 1, 0, // PC_FCTIWZ + FPU1, 5, 1, 1, 1, 0, // PC_FCMPU + FPU1, 5, 1, 1, 1, 0, // PC_FCMPO + LSU1, 1, 1, 0, 0, 0, // PC_LWARX + LSU1, 1, 1, 0, 0, 0, // PC_LSWI + LSU1, 1, 1, 0, 0, 0, // PC_LSWX + LSU1, 1, 1, 0, 0, 0, // PC_STFIWX + LSU1, 1, 1, 0, 0, 0, // PC_STSWI + LSU1, 1, 1, 0, 0, 0, // PC_STSWX + LSU1, 1, 1, 0, 0, 0, // PC_STWCX + IU, 1, 1, 0, 0, 1, // PC_ECIWX + IU, 1, 1, 0, 0, 1, // PC_ECOWX + IU, 1, 1, 0, 0, 0, // PC_DCBI + IU, 1, 1, 0, 0, 0, // PC_ICBI + IU, 1, 1, 0, 0, 0, // PC_MCRFS + IU, 1, 1, 0, 0, 0, // PC_MCRXR + IU, 1, 1, 0, 0, 0, // PC_MFTB + IU, 1, 1, 0, 0, 0, // PC_MFSR + IU, 1, 1, 0, 0, 0, // PC_MTSR + IU, 1, 1, 0, 0, 0, // PC_MFSRIN + IU, 1, 1, 0, 0, 0, // PC_MTSRIN + IU, 1, 1, 0, 0, 0, // PC_MTFSB0 + IU, 1, 1, 0, 0, 0, // PC_MTFSB1 + IU, 1, 1, 0, 0, 0, // PC_MTFSFI + IU, 1, 1, 0, 0, 1, // PC_SC + FPU1, 1, 1, 0, 0, 0, // PC_FSQRT + FPU1, 1, 1, 0, 0, 0, // PC_FSQRTS + IU, 1, 1, 0, 0, 0, // PC_TLBIA + IU, 1, 1, 0, 0, 0, // PC_TLBIE + IU, 1, 1, 0, 0, 0, // PC_TLBLD + IU, 1, 1, 0, 0, 0, // PC_TLBLI + IU, 1, 1, 0, 0, 0, // PC_TLBSYNC + IU, 1, 1, 0, 0, 1, // PC_TW + IU, 1, 1, 0, 0, 1, // PC_TRAP + IU, 1, 1, 0, 0, 1, // PC_TWI + IU, 1, 1, 0, 0, 1, // PC_OPWORD + IU, 1, 1, 0, 0, 0, // PC_MFROM + IU, 1, 1, 0, 0, 1, // PC_DSA + IU, 1, 1, 0, 0, 1, // PC_ESA + IU, 0, 0, 0, 0, 0, // PC_DCCCI + IU, 0, 0, 0, 0, 0, // PC_DCREAD + IU, 0, 0, 0, 0, 0, // PC_ICBT + IU, 0, 0, 0, 0, 0, // PC_ICCCI + IU, 0, 0, 0, 0, 0, // PC_ICREAD + IU, 0, 0, 0, 0, 0, // PC_RFCI + IU, 0, 0, 0, 0, 0, // PC_TLBRE + IU, 0, 0, 0, 0, 0, // PC_TLBSX + IU, 0, 0, 0, 0, 0, // PC_TLBWE + IU, 0, 0, 0, 0, 0, // PC_WRTEE + IU, 0, 0, 0, 0, 0, // PC_WRTEEI + IU, 0, 0, 0, 0, 0, // PC_MFDCR + IU, 0, 0, 0, 0, 0, // PC_MTDCR + IU, 0, 0, 0, 0, 0, // PC_DCBA + BPU, 0, 0, 0, 0, 0, // PC_DSS + BPU, 0, 0, 0, 0, 0, // PC_DSSALL + BPU, 0, 0, 0, 0, 0, // PC_DST + BPU, 0, 0, 0, 0, 0, // PC_DSTT + BPU, 0, 0, 0, 0, 0, // PC_DSTST + BPU, 0, 0, 0, 0, 0, // PC_DSTSTT + BPU, 0, 0, 0, 0, 0, // PC_LVEBX + BPU, 0, 0, 0, 0, 0, // PC_LVEHX + BPU, 0, 0, 0, 0, 0, // PC_LVEWX + BPU, 0, 0, 0, 0, 0, // PC_LVSL + BPU, 0, 0, 0, 0, 0, // PC_LVSR + BPU, 0, 0, 0, 0, 0, // PC_LVX + BPU, 0, 0, 0, 0, 0, // PC_LVXL + BPU, 0, 0, 0, 0, 0, // PC_STVEBX + BPU, 0, 0, 0, 0, 0, // PC_STVEHX + BPU, 0, 0, 0, 0, 0, // PC_STVEWX + BPU, 0, 0, 0, 0, 0, // PC_STVX + BPU, 0, 0, 0, 0, 0, // PC_STVXL + BPU, 0, 0, 0, 0, 0, // PC_MFVSCR + BPU, 0, 0, 0, 0, 0, // PC_MTVSCR + BPU, 0, 0, 0, 0, 0, // PC_VADDCUW + BPU, 0, 0, 0, 0, 0, // PC_VADDFP + BPU, 0, 0, 0, 0, 0, // PC_VADDSBS + BPU, 0, 0, 0, 0, 0, // PC_VADDSHS + BPU, 0, 0, 0, 0, 0, // PC_VADDSWS + BPU, 0, 0, 0, 0, 0, // PC_VADDUBM + BPU, 0, 0, 0, 0, 0, // PC_VADDUBS + BPU, 0, 0, 0, 0, 0, // PC_VADDUHM + BPU, 0, 0, 0, 0, 0, // PC_VADDUHS + BPU, 0, 0, 0, 0, 0, // PC_VADDUWM + BPU, 0, 0, 0, 0, 0, // PC_VADDUWS + BPU, 0, 0, 0, 0, 0, // PC_VAND + BPU, 0, 0, 0, 0, 0, // PC_VANDC + BPU, 0, 0, 0, 0, 0, // PC_VAVGSB + BPU, 0, 0, 0, 0, 0, // PC_VAVGSH + BPU, 0, 0, 0, 0, 0, // PC_VAVGSW + BPU, 0, 0, 0, 0, 0, // PC_VAVGUB + BPU, 0, 0, 0, 0, 0, // PC_VAVGUH + BPU, 0, 0, 0, 0, 0, // PC_VAVGUW + BPU, 0, 0, 0, 0, 0, // PC_VCFSX + BPU, 0, 0, 0, 0, 0, // PC_VCFUX + BPU, 0, 0, 0, 0, 0, // PC_VCMPBFP + BPU, 0, 0, 0, 0, 0, // PC_VCMPEQFP + BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUB + BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUH + BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUW + BPU, 0, 0, 0, 0, 0, // PC_VCMPGEFP + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTFP + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSB + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSH + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSW + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUB + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUH + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUW + BPU, 0, 0, 0, 0, 0, // PC_VCTSXS + BPU, 0, 0, 0, 0, 0, // PC_VCTUXS + BPU, 0, 0, 0, 0, 0, // PC_VEXPTEFP + BPU, 0, 0, 0, 0, 0, // PC_VLOGEFP + BPU, 0, 0, 0, 0, 0, // PC_VMAXFP + BPU, 0, 0, 0, 0, 0, // PC_VMAXSB + BPU, 0, 0, 0, 0, 0, // PC_VMAXSH + BPU, 0, 0, 0, 0, 0, // PC_VMAXSW + BPU, 0, 0, 0, 0, 0, // PC_VMAXUB + BPU, 0, 0, 0, 0, 0, // PC_VMAXUH + BPU, 0, 0, 0, 0, 0, // PC_VMAXUW + BPU, 0, 0, 0, 0, 0, // PC_VMINFP + BPU, 0, 0, 0, 0, 0, // PC_VMINSB + BPU, 0, 0, 0, 0, 0, // PC_VMINSH + BPU, 0, 0, 0, 0, 0, // PC_VMINSW + BPU, 0, 0, 0, 0, 0, // PC_VMINUB + BPU, 0, 0, 0, 0, 0, // PC_VMINUH + BPU, 0, 0, 0, 0, 0, // PC_VMINUW + BPU, 0, 0, 0, 0, 0, // PC_VMRGHB + BPU, 0, 0, 0, 0, 0, // PC_VMRGHH + BPU, 0, 0, 0, 0, 0, // PC_VMRGHW + BPU, 0, 0, 0, 0, 0, // PC_VMRGLB + BPU, 0, 0, 0, 0, 0, // PC_VMRGLH + BPU, 0, 0, 0, 0, 0, // PC_VMRGLW + BPU, 0, 0, 0, 0, 0, // PC_VMULESB + BPU, 0, 0, 0, 0, 0, // PC_VMULESH + BPU, 0, 0, 0, 0, 0, // PC_VMULEUB + BPU, 0, 0, 0, 0, 0, // PC_VMULEUH + BPU, 0, 0, 0, 0, 0, // PC_VMULOSB + BPU, 0, 0, 0, 0, 0, // PC_VMULOSH + BPU, 0, 0, 0, 0, 0, // PC_VMULOUB + BPU, 0, 0, 0, 0, 0, // PC_VMULOUH + BPU, 0, 0, 0, 0, 0, // PC_VNOR + BPU, 0, 0, 0, 0, 0, // PC_VOR + BPU, 0, 0, 0, 0, 0, // PC_VPKPX + BPU, 0, 0, 0, 0, 0, // PC_VPKSHSS + BPU, 0, 0, 0, 0, 0, // PC_VPKSHUS + BPU, 0, 0, 0, 0, 0, // PC_VPKSWSS + BPU, 0, 0, 0, 0, 0, // PC_VPKSWUS + BPU, 0, 0, 0, 0, 0, // PC_VPKUHUM + BPU, 0, 0, 0, 0, 0, // PC_VPKUHUS + BPU, 0, 0, 0, 0, 0, // PC_VPKUWUM + BPU, 0, 0, 0, 0, 0, // PC_VPKUWUS + BPU, 0, 0, 0, 0, 0, // PC_VREFP + BPU, 0, 0, 0, 0, 0, // PC_VRFIM + BPU, 0, 0, 0, 0, 0, // PC_VRFIN + BPU, 0, 0, 0, 0, 0, // PC_VRFIP + BPU, 0, 0, 0, 0, 0, // PC_VRFIZ + BPU, 0, 0, 0, 0, 0, // PC_VRLB + BPU, 0, 0, 0, 0, 0, // PC_VRLH + BPU, 0, 0, 0, 0, 0, // PC_VRLW + BPU, 0, 0, 0, 0, 0, // PC_VRSQRTEFP + BPU, 0, 0, 0, 0, 0, // PC_VSL + BPU, 0, 0, 0, 0, 0, // PC_VSLB + BPU, 0, 0, 0, 0, 0, // PC_VSLH + BPU, 0, 0, 0, 0, 0, // PC_VSLO + BPU, 0, 0, 0, 0, 0, // PC_VSLW + BPU, 0, 0, 0, 0, 0, // PC_VSPLTB + BPU, 0, 0, 0, 0, 0, // PC_VSPLTH + BPU, 0, 0, 0, 0, 0, // PC_VSPLTW + BPU, 0, 0, 0, 0, 0, // PC_VSPLTISB + BPU, 0, 0, 0, 0, 0, // PC_VSPLTISH + BPU, 0, 0, 0, 0, 0, // PC_VSPLTISW + BPU, 0, 0, 0, 0, 0, // PC_VSR + BPU, 0, 0, 0, 0, 0, // PC_VSRAB + BPU, 0, 0, 0, 0, 0, // PC_VSRAH + BPU, 0, 0, 0, 0, 0, // PC_VSRAW + BPU, 0, 0, 0, 0, 0, // PC_VSRB + BPU, 0, 0, 0, 0, 0, // PC_VSRH + BPU, 0, 0, 0, 0, 0, // PC_VSRO + BPU, 0, 0, 0, 0, 0, // PC_VSRW + BPU, 0, 0, 0, 0, 0, // PC_VSUBCUW + BPU, 0, 0, 0, 0, 0, // PC_VSUBFP + BPU, 0, 0, 0, 0, 0, // PC_VSUBSBS + BPU, 0, 0, 0, 0, 0, // PC_VSUBSHS + BPU, 0, 0, 0, 0, 0, // PC_VSUBSWS + BPU, 0, 0, 0, 0, 0, // PC_VSUBUBM + BPU, 0, 0, 0, 0, 0, // PC_VSUBUBS + BPU, 0, 0, 0, 0, 0, // PC_VSUBUHM + BPU, 0, 0, 0, 0, 0, // PC_VSUBUHS + BPU, 0, 0, 0, 0, 0, // PC_VSUBUWM + BPU, 0, 0, 0, 0, 0, // PC_VSUBUWS + BPU, 0, 0, 0, 0, 0, // PC_VSUMSWS + BPU, 0, 0, 0, 0, 0, // PC_VSUM2SWS + BPU, 0, 0, 0, 0, 0, // PC_VSUM4SBS + BPU, 0, 0, 0, 0, 0, // PC_VSUM4SHS + BPU, 0, 0, 0, 0, 0, // PC_VSUM4UBS + BPU, 0, 0, 0, 0, 0, // PC_VUPKHPX + BPU, 0, 0, 0, 0, 0, // PC_VUPKHSB + BPU, 0, 0, 0, 0, 0, // PC_VUPKHSH + BPU, 0, 0, 0, 0, 0, // PC_VUPKLPX + BPU, 0, 0, 0, 0, 0, // PC_VUPKLSB + BPU, 0, 0, 0, 0, 0, // PC_VUPKLSH + BPU, 0, 0, 0, 0, 0, // PC_VXOR + BPU, 0, 0, 0, 0, 0, // PC_VMADDFP + BPU, 0, 0, 0, 0, 0, // PC_VMHADDSHS + BPU, 0, 0, 0, 0, 0, // PC_VMHRADDSHS + BPU, 0, 0, 0, 0, 0, // PC_VMLADDUHM + BPU, 0, 0, 0, 0, 0, // PC_VMSUMMBM + BPU, 0, 0, 0, 0, 0, // PC_VMSUMSHM + BPU, 0, 0, 0, 0, 0, // PC_VMSUMSHS + BPU, 0, 0, 0, 0, 0, // PC_VMSUMUBM + BPU, 0, 0, 0, 0, 0, // PC_VMSUMUHM + BPU, 0, 0, 0, 0, 0, // PC_VMSUMUHS + BPU, 0, 0, 0, 0, 0, // PC_VNMSUBFP + BPU, 0, 0, 0, 0, 0, // PC_VPERM + BPU, 0, 0, 0, 0, 0, // PC_VSEL + BPU, 0, 0, 0, 0, 0, // PC_VSLDOI + BPU, 0, 0, 0, 0, 0, // PC_VMR + BPU, 0, 0, 0, 0, 0, // PC_VMRP + BPU, 0, 0, 0, 0, 0, // PC_SLE + BPU, 0, 0, 0, 0, 0, // PC_SLEQ + BPU, 0, 0, 0, 0, 0, // PC_SLIQ + BPU, 0, 0, 0, 0, 0, // PC_SLLIQ + BPU, 0, 0, 0, 0, 0, // PC_SLLQ + BPU, 0, 0, 0, 0, 0, // PC_SLQ + BPU, 0, 0, 0, 0, 0, // PC_SRAIQ + BPU, 0, 0, 0, 0, 0, // PC_SRAQ + BPU, 0, 0, 0, 0, 0, // PC_SRE + BPU, 0, 0, 0, 0, 0, // PC_SREA + BPU, 0, 0, 0, 0, 0, // PC_SREQ + BPU, 0, 0, 0, 0, 0, // PC_SRIQ + BPU, 0, 0, 0, 0, 0, // PC_SRLIQ + BPU, 0, 0, 0, 0, 0, // PC_SRLQ + BPU, 0, 0, 0, 0, 0, // PC_SRQ + BPU, 0, 0, 0, 0, 0, // PC_MASKG + BPU, 0, 0, 0, 0, 0, // PC_MASKIR + BPU, 0, 0, 0, 0, 0, // PC_LSCBX + BPU, 0, 0, 0, 0, 0, // PC_DIV + BPU, 0, 0, 0, 0, 0, // PC_DIVS + BPU, 0, 0, 0, 0, 0, // PC_DOZ + BPU, 0, 0, 0, 0, 0, // PC_MUL + BPU, 0, 0, 0, 0, 0, // PC_NABS + BPU, 0, 0, 0, 0, 0, // PC_ABS + BPU, 0, 0, 0, 0, 0, // PC_CLCS + BPU, 0, 0, 0, 0, 0, // PC_DOZI + BPU, 0, 0, 0, 0, 0, // PC_RLMI + BPU, 0, 0, 0, 0, 0, // PC_RRIB +}; + +static void advance(int firstStage, int oldStage, int newStage) { + PCode *instr = pipeline[oldStage].instr; + int cycles = instruction_timing[instr->op].cycles[newStage - firstStage]; + pipeline[newStage].instr = instr; + pipeline[newStage].remaining = cycles; + pipeline[oldStage].instr = NULL; +} + +static void assign_completion_buffer(PCode *instr) { + completionbuffers.used++; + completionbuffers.free--; + completionbuffers.entries[completionbuffers.nextFreeSlot].instr = instr; + completionbuffers.entries[completionbuffers.nextFreeSlot].completed = 0; + completionbuffers.nextFreeSlot = (completionbuffers.nextFreeSlot + 1) % MaxEntries; +} + +static void complete_instruction(int stage) { + PCode *instr = pipeline[stage].instr; + int buf = 0; + while (buf < MaxEntries && completionbuffers.entries[buf].instr != instr) + buf++; + + completionbuffers.entries[buf].completed = 1; + pipeline[stage].instr = NULL; +} + +static void retire_instruction(void) { + completionbuffers.entries[completionbuffers.nextToRetire].instr = NULL; + completionbuffers.used--; + completionbuffers.free++; + completionbuffers.nextToRetire = (completionbuffers.nextToRetire + 1) % MaxEntries; +} + +static int latency(PCode *instr) { + int cycles = instruction_timing[instr->op].latency; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + cycles += 2; + if (instr->op == PC_LMW || instr->op == PC_STMW) + cycles += instr->argCount - 2; + return cycles; +} + +static void initialize(void) { + int stage; + int i; + + for (stage = 0; stage < NumStages; stage++) + pipeline[stage].instr = NULL; + + completionbuffers.free = 5; + completionbuffers.used = 0; + completionbuffers.nextToRetire = 0; + completionbuffers.nextFreeSlot = 0; + for (i = 0; i < MaxEntries; i++) + completionbuffers.entries[i].instr = NULL; +} + +static int can_issue(PCode *instr) { + if (completionbuffers.free == 0) + return 0; + if (pipeline[instruction_timing[instr->op].stage].instr) + return 0; + if ((instr->flags & fIsWrite) && pipeline[LSU2].instr && (pipeline[LSU2].instr->flags & fIsWrite)) + return 0; + return 1; +} + +static void issue(PCode *instr) { + int stage = instruction_timing[instr->op].stage; + int cycles = instruction_timing[instr->op].cycles[0]; + assign_completion_buffer(instr); + pipeline[stage].instr = instr; + pipeline[stage].remaining = cycles; +} + +static void advance_clock(void) { + int stage; + + for (stage = 0; stage < NumStages; stage++) { + if (pipeline[stage].instr && pipeline[stage].remaining) + --pipeline[stage].remaining; + } + + if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { + retire_instruction(); + if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { + retire_instruction(); + } + } + + if (pipeline[IU].instr && pipeline[IU].remaining == 0) + complete_instruction(IU); + if (pipeline[LSU2].instr && pipeline[LSU2].remaining == 0) + complete_instruction(LSU2); + if (pipeline[FPU3].instr && pipeline[FPU3].remaining == 0) + complete_instruction(FPU3); + if (pipeline[SRU].instr && pipeline[SRU].remaining == 0) + complete_instruction(SRU); + if (pipeline[BPU].instr && pipeline[BPU].remaining == 0) + complete_instruction(BPU); + + if ( + pipeline[FPU1].instr && + pipeline[FPU1].remaining == 0 && + (pipeline[FPU1].instr->op == PC_FDIV || pipeline[FPU1].instr->op == PC_FDIVS) + ) + complete_instruction(FPU1); + + if (pipeline[FPU2].instr && pipeline[FPU2].remaining == 0 && !pipeline[FPU3].instr) + advance(FPU1, FPU2, FPU3); + if (pipeline[FPU1].instr && pipeline[FPU1].remaining == 0 && !pipeline[FPU2].instr) + advance(FPU1, FPU1, FPU2); + if (pipeline[LSU1].instr && pipeline[LSU1].remaining == 0 && !pipeline[LSU2].instr) + advance(LSU1, LSU1, LSU2); +} + +static int serializes(PCode *instr) { + return instruction_timing[instr->op].serializes; +} + +MachineInfo machine603 = { + 2, + 1, + 0, + &latency, + &initialize, + &can_issue, + &issue, + &advance_clock, + &serializes, + &default_uses_vpermute_unit +}; diff --git a/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation603e.c b/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation603e.c new file mode 100644 index 0000000..d3e1e47 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation603e.c @@ -0,0 +1,650 @@ +#include "compiler/Scheduler.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" + +// https://www.nxp.com/docs/en/reference-manual/MPC603EUM.pdf + +typedef enum Stage { + BPU, // Branch Prediction Unit + IU, // Integer Unit + LSU1, // Load/Store Unit + LSU2, + FPU1, // Floating Point Unit + FPU2, + FPU3, + SRU, // System Register Unit + NumStages +} Stage; + +static struct { + // the instruction currently in this pipeline stage + PCode *instr; + + // how many cycles are left for this instruction to finish + int remaining; +} pipeline[NumStages]; + +enum { + MaxEntries = 5 +}; + +static struct { + // how many entries remain unused in the queue + unsigned int free; + + // how many entries are currently used in the queue + unsigned int used; + + // the index of the next instruction that will be retired + unsigned int nextToRetire; + + // the index of the next free slot that will be used when an instruction is dispatched + unsigned int nextFreeSlot; + + // circular array of entries in the completion queue + struct { + PCode *instr; + int completed; + } entries[MaxEntries]; +} completionbuffers; + +static struct { + // the initial stage for this instruction + Stage stage; + + // the total amount of cycles required by this instruction + char latency; + + // how long it takes to finish each stage + char cycles[3]; + + // does this instruction serialise? + char serializes; +} instruction_timing[OPCODE_MAX] = { + BPU, 0, 0, 0, 0, 1, // PC_B + BPU, 0, 0, 0, 0, 1, // PC_BL + BPU, 0, 0, 0, 0, 1, // PC_BC + BPU, 0, 0, 0, 0, 1, // PC_BCLR + BPU, 0, 0, 0, 0, 1, // PC_BCCTR + BPU, 0, 0, 0, 0, 1, // PC_BT + BPU, 0, 0, 0, 0, 1, // PC_BTLR + BPU, 0, 0, 0, 0, 1, // PC_BTCTR + BPU, 0, 0, 0, 0, 1, // PC_BF + BPU, 0, 0, 0, 0, 1, // PC_BFLR + BPU, 0, 0, 0, 0, 1, // PC_BFCTR + BPU, 0, 0, 0, 0, 1, // PC_BDNZ + BPU, 0, 0, 0, 0, 1, // PC_BDNZT + BPU, 0, 0, 0, 0, 1, // PC_BDNZF + BPU, 0, 0, 0, 0, 1, // PC_BDZ + BPU, 0, 0, 0, 0, 1, // PC_BDZT + BPU, 0, 0, 0, 0, 1, // PC_BDZF + BPU, 0, 0, 0, 0, 1, // PC_BLR + BPU, 0, 0, 0, 0, 1, // PC_BCTR + BPU, 0, 0, 0, 0, 1, // PC_BCTRL + BPU, 0, 0, 0, 0, 1, // PC_BLRL + LSU1, 2, 1, 1, 0, 0, // PC_LBZ + LSU1, 2, 1, 1, 0, 0, // PC_LBZU + LSU1, 2, 1, 1, 0, 0, // PC_LBZX + LSU1, 2, 1, 1, 0, 0, // PC_LBZUX + LSU1, 2, 1, 1, 0, 0, // PC_LHZ + LSU1, 2, 1, 1, 0, 0, // PC_LHZU + LSU1, 2, 1, 1, 0, 0, // PC_LHZX + LSU1, 2, 1, 1, 0, 0, // PC_LHZUX + LSU1, 2, 1, 1, 0, 0, // PC_LHA + LSU1, 2, 1, 1, 0, 0, // PC_LHAU + LSU1, 2, 1, 1, 0, 0, // PC_LHAX + LSU1, 2, 1, 1, 0, 0, // PC_LHAUX + LSU1, 2, 1, 1, 0, 0, // PC_LHBRX + LSU1, 2, 1, 1, 0, 0, // PC_LWZ + LSU1, 2, 1, 1, 0, 0, // PC_LWZU + LSU1, 2, 1, 1, 0, 0, // PC_LWZX + LSU1, 2, 1, 1, 0, 0, // PC_LWZUX + LSU1, 2, 1, 1, 0, 0, // PC_LWBRX + LSU1, 2, 1, 1, 0, 0, // PC_LMW + LSU1, 2, 1, 1, 0, 0, // PC_STB + LSU1, 2, 1, 1, 0, 0, // PC_STBU + LSU1, 2, 1, 1, 0, 0, // PC_STBX + LSU1, 2, 1, 1, 0, 0, // PC_STBUX + LSU1, 2, 1, 1, 0, 0, // PC_STH + LSU1, 2, 1, 1, 0, 0, // PC_STHU + LSU1, 2, 1, 1, 0, 0, // PC_STHX + LSU1, 2, 1, 1, 0, 0, // PC_STHUX + LSU1, 2, 1, 1, 0, 0, // PC_STHBRX + LSU1, 2, 1, 1, 0, 0, // PC_STW + LSU1, 2, 1, 1, 0, 0, // PC_STWU + LSU1, 2, 1, 1, 0, 0, // PC_STWX + LSU1, 2, 1, 1, 0, 0, // PC_STWUX + LSU1, 2, 1, 1, 0, 0, // PC_STWBRX + LSU1, 2, 1, 1, 0, 0, // PC_STMW + LSU1, 2, 1, 1, 0, 0, // PC_DCBF + LSU1, 2, 1, 1, 0, 0, // PC_DCBST + LSU1, 2, 1, 1, 0, 0, // PC_DCBT + LSU1, 2, 1, 1, 0, 0, // PC_DCBTST + LSU1, 2, 1, 1, 0, 0, // PC_DCBZ + IU, 1, 1, 0, 0, 0, // PC_ADD + IU, 1, 1, 0, 0, 0, // PC_ADDC + IU, 1, 1, 0, 0, 0, // PC_ADDE + IU, 1, 1, 0, 0, 0, // PC_ADDI + IU, 1, 1, 0, 0, 0, // PC_ADDIC + IU, 1, 1, 0, 0, 0, // PC_ADDICR + IU, 1, 1, 0, 0, 0, // PC_ADDIS + IU, 1, 1, 0, 0, 0, // PC_ADDME + IU, 1, 1, 0, 0, 0, // PC_ADDZE + IU, 37, 37, 0, 0, 0, // PC_DIVW + IU, 37, 37, 0, 0, 0, // PC_DIVWU + IU, 5, 5, 0, 0, 0, // PC_MULHW + IU, 5, 5, 0, 0, 0, // PC_MULHWU + IU, 3, 3, 0, 0, 0, // PC_MULLI + IU, 5, 5, 0, 0, 0, // PC_MULLW + IU, 1, 1, 0, 0, 0, // PC_NEG + IU, 1, 1, 0, 0, 0, // PC_SUBF + IU, 1, 1, 0, 0, 0, // PC_SUBFC + IU, 1, 1, 0, 0, 0, // PC_SUBFE + IU, 1, 1, 0, 0, 0, // PC_SUBFIC + IU, 1, 1, 0, 0, 0, // PC_SUBFME + IU, 1, 1, 0, 0, 0, // PC_SUBFZE + IU, 3, 1, 0, 0, 0, // PC_CMPI + IU, 3, 1, 0, 0, 0, // PC_CMP + IU, 3, 1, 0, 0, 0, // PC_CMPLI + IU, 3, 1, 0, 0, 0, // PC_CMPL + IU, 1, 1, 0, 0, 0, // PC_ANDI + IU, 1, 1, 0, 0, 0, // PC_ANDIS + IU, 1, 1, 0, 0, 0, // PC_ORI + IU, 1, 1, 0, 0, 0, // PC_ORIS + IU, 1, 1, 0, 0, 0, // PC_XORI + IU, 1, 1, 0, 0, 0, // PC_XORIS + IU, 1, 1, 0, 0, 0, // PC_AND + IU, 1, 1, 0, 0, 0, // PC_OR + IU, 1, 1, 0, 0, 0, // PC_XOR + IU, 1, 1, 0, 0, 0, // PC_NAND + IU, 1, 1, 0, 0, 0, // PC_NOR + IU, 1, 1, 0, 0, 0, // PC_EQV + IU, 1, 1, 0, 0, 0, // PC_ANDC + IU, 1, 1, 0, 0, 0, // PC_ORC + IU, 1, 1, 0, 0, 0, // PC_EXTSB + IU, 1, 1, 0, 0, 0, // PC_EXTSH + IU, 1, 1, 0, 0, 0, // PC_CNTLZW + IU, 1, 1, 0, 0, 0, // PC_RLWINM + IU, 1, 1, 0, 0, 0, // PC_RLWNM + IU, 1, 1, 0, 0, 0, // PC_RLWIMI + IU, 1, 1, 0, 0, 0, // PC_SLW + IU, 1, 1, 0, 0, 0, // PC_SRW + IU, 1, 1, 0, 0, 0, // PC_SRAWI + IU, 1, 1, 0, 0, 0, // PC_SRAW + SRU, 1, 1, 0, 0, 0, // PC_CRAND + SRU, 1, 1, 0, 0, 0, // PC_CRANDC + SRU, 1, 1, 0, 0, 0, // PC_CREQV + SRU, 1, 1, 0, 0, 0, // PC_CRNAND + SRU, 1, 1, 0, 0, 0, // PC_CRNOR + SRU, 1, 1, 0, 0, 0, // PC_CROR + SRU, 1, 1, 0, 0, 0, // PC_CRORC + SRU, 1, 1, 0, 0, 0, // PC_CRXOR + SRU, 1, 1, 0, 0, 0, // PC_MCRF + SRU, 2, 2, 0, 0, 0, // PC_MTXER + SRU, 2, 2, 0, 0, 0, // PC_MTCTR + SRU, 2, 2, 0, 0, 0, // PC_MTLR + SRU, 1, 1, 0, 0, 0, // PC_MTCRF + SRU, 1, 1, 0, 0, 1, // PC_MTMSR + SRU, 1, 1, 0, 0, 1, // PC_MTSPR + SRU, 1, 1, 0, 0, 1, // PC_MFMSR + SRU, 1, 1, 0, 0, 1, // PC_MFSPR + SRU, 1, 1, 0, 0, 0, // PC_MFXER + SRU, 1, 1, 0, 0, 0, // PC_MFCTR + SRU, 1, 1, 0, 0, 0, // PC_MFLR + SRU, 1, 1, 0, 0, 0, // PC_MFCR + FPU1, 3, 1, 1, 1, 0, // PC_MFFS + FPU1, 3, 1, 1, 1, 0, // PC_MTFSF + SRU, 1, 1, 0, 0, 1, // PC_EIEIO + SRU, 1, 1, 0, 0, 1, // PC_ISYNC + SRU, 1, 1, 0, 0, 1, // PC_SYNC + SRU, 1, 1, 0, 0, 1, // PC_RFI + IU, 1, 1, 0, 0, 0, // PC_LI + IU, 1, 1, 0, 0, 0, // PC_LIS + IU, 1, 1, 0, 0, 0, // PC_MR + IU, 1, 1, 0, 0, 0, // PC_NOP + IU, 1, 1, 0, 0, 0, // PC_NOT + LSU1, 2, 1, 1, 0, 0, // PC_LFS + LSU1, 2, 1, 1, 0, 0, // PC_LFSU + LSU1, 2, 1, 1, 0, 0, // PC_LFSX + LSU1, 2, 1, 1, 0, 0, // PC_LFSUX + LSU1, 2, 1, 1, 0, 0, // PC_LFD + LSU1, 2, 1, 1, 0, 0, // PC_LFDU + LSU1, 2, 1, 1, 0, 0, // PC_LFDX + LSU1, 2, 1, 1, 0, 0, // PC_LFDUX + LSU1, 2, 1, 1, 0, 0, // PC_STFS + LSU1, 2, 1, 1, 0, 0, // PC_STFSU + LSU1, 2, 1, 1, 0, 0, // PC_STFSX + LSU1, 2, 1, 1, 0, 0, // PC_STFSUX + LSU1, 2, 1, 1, 0, 0, // PC_STFD + LSU1, 2, 1, 1, 0, 0, // PC_STFDU + LSU1, 2, 1, 1, 0, 0, // PC_STFDX + LSU1, 2, 1, 1, 0, 0, // PC_STFDUX + FPU1, 3, 1, 1, 1, 0, // PC_FMR + FPU1, 3, 1, 1, 1, 0, // PC_FABS + FPU1, 3, 1, 1, 1, 0, // PC_FNEG + FPU1, 3, 1, 1, 1, 0, // PC_FNABS + FPU1, 3, 1, 1, 1, 0, // PC_FADD + FPU1, 3, 1, 1, 1, 0, // PC_FADDS + FPU1, 3, 1, 1, 1, 0, // PC_FSUB + FPU1, 3, 1, 1, 1, 0, // PC_FSUBS + FPU1, 4, 2, 1, 1, 0, // PC_FMUL + FPU1, 3, 1, 1, 1, 0, // PC_FMULS + FPU1, 33, 33, 0, 0, 0, // PC_FDIV + FPU1, 18, 18, 0, 0, 0, // PC_FDIVS + FPU1, 4, 2, 1, 1, 0, // PC_FMADD + FPU1, 3, 1, 1, 1, 0, // PC_FMADDS + FPU1, 4, 2, 1, 1, 0, // PC_FMSUB + FPU1, 3, 1, 1, 1, 0, // PC_FMSUBS + FPU1, 4, 2, 1, 1, 0, // PC_FNMADD + FPU1, 3, 1, 1, 1, 0, // PC_FNMADDS + FPU1, 4, 2, 1, 1, 0, // PC_FNMSUB + FPU1, 3, 1, 1, 1, 0, // PC_FNMSUBS + FPU1, 18, 18, 0, 0, 0, // PC_FRES + FPU1, 3, 1, 1, 1, 0, // PC_FRSQRTE + FPU1, 3, 1, 1, 1, 0, // PC_FSEL + FPU1, 3, 1, 1, 1, 0, // PC_FRSP + FPU1, 3, 1, 1, 1, 0, // PC_FCTIW + FPU1, 3, 1, 1, 1, 0, // PC_FCTIWZ + FPU1, 5, 1, 1, 1, 0, // PC_FCMPU + FPU1, 5, 1, 1, 1, 0, // PC_FCMPO + LSU1, 1, 1, 0, 0, 0, // PC_LWARX + LSU1, 1, 1, 0, 0, 0, // PC_LSWI + LSU1, 1, 1, 0, 0, 0, // PC_LSWX + LSU1, 1, 1, 0, 0, 0, // PC_STFIWX + LSU1, 1, 1, 0, 0, 0, // PC_STSWI + LSU1, 1, 1, 0, 0, 0, // PC_STSWX + LSU1, 1, 1, 0, 0, 0, // PC_STWCX + IU, 1, 1, 0, 0, 1, // PC_ECIWX + IU, 1, 1, 0, 0, 1, // PC_ECOWX + IU, 1, 1, 0, 0, 0, // PC_DCBI + IU, 1, 1, 0, 0, 0, // PC_ICBI + IU, 1, 1, 0, 0, 0, // PC_MCRFS + IU, 1, 1, 0, 0, 0, // PC_MCRXR + IU, 1, 1, 0, 0, 0, // PC_MFTB + IU, 1, 1, 0, 0, 0, // PC_MFSR + IU, 1, 1, 0, 0, 0, // PC_MTSR + IU, 1, 1, 0, 0, 0, // PC_MFSRIN + IU, 1, 1, 0, 0, 0, // PC_MTSRIN + IU, 1, 1, 0, 0, 0, // PC_MTFSB0 + IU, 1, 1, 0, 0, 0, // PC_MTFSB1 + IU, 1, 1, 0, 0, 0, // PC_MTFSFI + IU, 1, 1, 0, 0, 1, // PC_SC + FPU1, 1, 1, 0, 0, 0, // PC_FSQRT + FPU1, 1, 1, 0, 0, 0, // PC_FSQRTS + IU, 1, 1, 0, 0, 0, // PC_TLBIA + IU, 1, 1, 0, 0, 0, // PC_TLBIE + IU, 1, 1, 0, 0, 0, // PC_TLBLD + IU, 1, 1, 0, 0, 0, // PC_TLBLI + IU, 1, 1, 0, 0, 0, // PC_TLBSYNC + IU, 1, 1, 0, 0, 1, // PC_TW + IU, 1, 1, 0, 0, 1, // PC_TRAP + IU, 1, 1, 0, 0, 1, // PC_TWI + IU, 1, 1, 0, 0, 1, // PC_OPWORD + IU, 1, 1, 0, 0, 0, // PC_MFROM + IU, 1, 1, 0, 0, 1, // PC_DSA + IU, 1, 1, 0, 0, 1, // PC_ESA + IU, 0, 0, 0, 0, 0, // PC_DCCCI + IU, 0, 0, 0, 0, 0, // PC_DCREAD + IU, 0, 0, 0, 0, 0, // PC_ICBT + IU, 0, 0, 0, 0, 0, // PC_ICCCI + IU, 0, 0, 0, 0, 0, // PC_ICREAD + IU, 0, 0, 0, 0, 0, // PC_RFCI + IU, 0, 0, 0, 0, 0, // PC_TLBRE + IU, 0, 0, 0, 0, 0, // PC_TLBSX + IU, 0, 0, 0, 0, 0, // PC_TLBWE + IU, 0, 0, 0, 0, 0, // PC_WRTEE + IU, 0, 0, 0, 0, 0, // PC_WRTEEI + IU, 0, 0, 0, 0, 0, // PC_MFDCR + IU, 0, 0, 0, 0, 0, // PC_MTDCR + IU, 0, 0, 0, 0, 0, // PC_DCBA + BPU, 0, 0, 0, 0, 0, // PC_DSS + BPU, 0, 0, 0, 0, 0, // PC_DSSALL + BPU, 0, 0, 0, 0, 0, // PC_DST + BPU, 0, 0, 0, 0, 0, // PC_DSTT + BPU, 0, 0, 0, 0, 0, // PC_DSTST + BPU, 0, 0, 0, 0, 0, // PC_DSTSTT + BPU, 0, 0, 0, 0, 0, // PC_LVEBX + BPU, 0, 0, 0, 0, 0, // PC_LVEHX + BPU, 0, 0, 0, 0, 0, // PC_LVEWX + BPU, 0, 0, 0, 0, 0, // PC_LVSL + BPU, 0, 0, 0, 0, 0, // PC_LVSR + BPU, 0, 0, 0, 0, 0, // PC_LVX + BPU, 0, 0, 0, 0, 0, // PC_LVXL + BPU, 0, 0, 0, 0, 0, // PC_STVEBX + BPU, 0, 0, 0, 0, 0, // PC_STVEHX + BPU, 0, 0, 0, 0, 0, // PC_STVEWX + BPU, 0, 0, 0, 0, 0, // PC_STVX + BPU, 0, 0, 0, 0, 0, // PC_STVXL + BPU, 0, 0, 0, 0, 0, // PC_MFVSCR + BPU, 0, 0, 0, 0, 0, // PC_MTVSCR + BPU, 0, 0, 0, 0, 0, // PC_VADDCUW + BPU, 0, 0, 0, 0, 0, // PC_VADDFP + BPU, 0, 0, 0, 0, 0, // PC_VADDSBS + BPU, 0, 0, 0, 0, 0, // PC_VADDSHS + BPU, 0, 0, 0, 0, 0, // PC_VADDSWS + BPU, 0, 0, 0, 0, 0, // PC_VADDUBM + BPU, 0, 0, 0, 0, 0, // PC_VADDUBS + BPU, 0, 0, 0, 0, 0, // PC_VADDUHM + BPU, 0, 0, 0, 0, 0, // PC_VADDUHS + BPU, 0, 0, 0, 0, 0, // PC_VADDUWM + BPU, 0, 0, 0, 0, 0, // PC_VADDUWS + BPU, 0, 0, 0, 0, 0, // PC_VAND + BPU, 0, 0, 0, 0, 0, // PC_VANDC + BPU, 0, 0, 0, 0, 0, // PC_VAVGSB + BPU, 0, 0, 0, 0, 0, // PC_VAVGSH + BPU, 0, 0, 0, 0, 0, // PC_VAVGSW + BPU, 0, 0, 0, 0, 0, // PC_VAVGUB + BPU, 0, 0, 0, 0, 0, // PC_VAVGUH + BPU, 0, 0, 0, 0, 0, // PC_VAVGUW + BPU, 0, 0, 0, 0, 0, // PC_VCFSX + BPU, 0, 0, 0, 0, 0, // PC_VCFUX + BPU, 0, 0, 0, 0, 0, // PC_VCMPBFP + BPU, 0, 0, 0, 0, 0, // PC_VCMPEQFP + BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUB + BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUH + BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUW + BPU, 0, 0, 0, 0, 0, // PC_VCMPGEFP + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTFP + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSB + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSH + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSW + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUB + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUH + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUW + BPU, 0, 0, 0, 0, 0, // PC_VCTSXS + BPU, 0, 0, 0, 0, 0, // PC_VCTUXS + BPU, 0, 0, 0, 0, 0, // PC_VEXPTEFP + BPU, 0, 0, 0, 0, 0, // PC_VLOGEFP + BPU, 0, 0, 0, 0, 0, // PC_VMAXFP + BPU, 0, 0, 0, 0, 0, // PC_VMAXSB + BPU, 0, 0, 0, 0, 0, // PC_VMAXSH + BPU, 0, 0, 0, 0, 0, // PC_VMAXSW + BPU, 0, 0, 0, 0, 0, // PC_VMAXUB + BPU, 0, 0, 0, 0, 0, // PC_VMAXUH + BPU, 0, 0, 0, 0, 0, // PC_VMAXUW + BPU, 0, 0, 0, 0, 0, // PC_VMINFP + BPU, 0, 0, 0, 0, 0, // PC_VMINSB + BPU, 0, 0, 0, 0, 0, // PC_VMINSH + BPU, 0, 0, 0, 0, 0, // PC_VMINSW + BPU, 0, 0, 0, 0, 0, // PC_VMINUB + BPU, 0, 0, 0, 0, 0, // PC_VMINUH + BPU, 0, 0, 0, 0, 0, // PC_VMINUW + BPU, 0, 0, 0, 0, 0, // PC_VMRGHB + BPU, 0, 0, 0, 0, 0, // PC_VMRGHH + BPU, 0, 0, 0, 0, 0, // PC_VMRGHW + BPU, 0, 0, 0, 0, 0, // PC_VMRGLB + BPU, 0, 0, 0, 0, 0, // PC_VMRGLH + BPU, 0, 0, 0, 0, 0, // PC_VMRGLW + BPU, 0, 0, 0, 0, 0, // PC_VMULESB + BPU, 0, 0, 0, 0, 0, // PC_VMULESH + BPU, 0, 0, 0, 0, 0, // PC_VMULEUB + BPU, 0, 0, 0, 0, 0, // PC_VMULEUH + BPU, 0, 0, 0, 0, 0, // PC_VMULOSB + BPU, 0, 0, 0, 0, 0, // PC_VMULOSH + BPU, 0, 0, 0, 0, 0, // PC_VMULOUB + BPU, 0, 0, 0, 0, 0, // PC_VMULOUH + BPU, 0, 0, 0, 0, 0, // PC_VNOR + BPU, 0, 0, 0, 0, 0, // PC_VOR + BPU, 0, 0, 0, 0, 0, // PC_VPKPX + BPU, 0, 0, 0, 0, 0, // PC_VPKSHSS + BPU, 0, 0, 0, 0, 0, // PC_VPKSHUS + BPU, 0, 0, 0, 0, 0, // PC_VPKSWSS + BPU, 0, 0, 0, 0, 0, // PC_VPKSWUS + BPU, 0, 0, 0, 0, 0, // PC_VPKUHUM + BPU, 0, 0, 0, 0, 0, // PC_VPKUHUS + BPU, 0, 0, 0, 0, 0, // PC_VPKUWUM + BPU, 0, 0, 0, 0, 0, // PC_VPKUWUS + BPU, 0, 0, 0, 0, 0, // PC_VREFP + BPU, 0, 0, 0, 0, 0, // PC_VRFIM + BPU, 0, 0, 0, 0, 0, // PC_VRFIN + BPU, 0, 0, 0, 0, 0, // PC_VRFIP + BPU, 0, 0, 0, 0, 0, // PC_VRFIZ + BPU, 0, 0, 0, 0, 0, // PC_VRLB + BPU, 0, 0, 0, 0, 0, // PC_VRLH + BPU, 0, 0, 0, 0, 0, // PC_VRLW + BPU, 0, 0, 0, 0, 0, // PC_VRSQRTEFP + BPU, 0, 0, 0, 0, 0, // PC_VSL + BPU, 0, 0, 0, 0, 0, // PC_VSLB + BPU, 0, 0, 0, 0, 0, // PC_VSLH + BPU, 0, 0, 0, 0, 0, // PC_VSLO + BPU, 0, 0, 0, 0, 0, // PC_VSLW + BPU, 0, 0, 0, 0, 0, // PC_VSPLTB + BPU, 0, 0, 0, 0, 0, // PC_VSPLTH + BPU, 0, 0, 0, 0, 0, // PC_VSPLTW + BPU, 0, 0, 0, 0, 0, // PC_VSPLTISB + BPU, 0, 0, 0, 0, 0, // PC_VSPLTISH + BPU, 0, 0, 0, 0, 0, // PC_VSPLTISW + BPU, 0, 0, 0, 0, 0, // PC_VSR + BPU, 0, 0, 0, 0, 0, // PC_VSRAB + BPU, 0, 0, 0, 0, 0, // PC_VSRAH + BPU, 0, 0, 0, 0, 0, // PC_VSRAW + BPU, 0, 0, 0, 0, 0, // PC_VSRB + BPU, 0, 0, 0, 0, 0, // PC_VSRH + BPU, 0, 0, 0, 0, 0, // PC_VSRO + BPU, 0, 0, 0, 0, 0, // PC_VSRW + BPU, 0, 0, 0, 0, 0, // PC_VSUBCUW + BPU, 0, 0, 0, 0, 0, // PC_VSUBFP + BPU, 0, 0, 0, 0, 0, // PC_VSUBSBS + BPU, 0, 0, 0, 0, 0, // PC_VSUBSHS + BPU, 0, 0, 0, 0, 0, // PC_VSUBSWS + BPU, 0, 0, 0, 0, 0, // PC_VSUBUBM + BPU, 0, 0, 0, 0, 0, // PC_VSUBUBS + BPU, 0, 0, 0, 0, 0, // PC_VSUBUHM + BPU, 0, 0, 0, 0, 0, // PC_VSUBUHS + BPU, 0, 0, 0, 0, 0, // PC_VSUBUWM + BPU, 0, 0, 0, 0, 0, // PC_VSUBUWS + BPU, 0, 0, 0, 0, 0, // PC_VSUMSWS + BPU, 0, 0, 0, 0, 0, // PC_VSUM2SWS + BPU, 0, 0, 0, 0, 0, // PC_VSUM4SBS + BPU, 0, 0, 0, 0, 0, // PC_VSUM4SHS + BPU, 0, 0, 0, 0, 0, // PC_VSUM4UBS + BPU, 0, 0, 0, 0, 0, // PC_VUPKHPX + BPU, 0, 0, 0, 0, 0, // PC_VUPKHSB + BPU, 0, 0, 0, 0, 0, // PC_VUPKHSH + BPU, 0, 0, 0, 0, 0, // PC_VUPKLPX + BPU, 0, 0, 0, 0, 0, // PC_VUPKLSB + BPU, 0, 0, 0, 0, 0, // PC_VUPKLSH + BPU, 0, 0, 0, 0, 0, // PC_VXOR + BPU, 0, 0, 0, 0, 0, // PC_VMADDFP + BPU, 0, 0, 0, 0, 0, // PC_VMHADDSHS + BPU, 0, 0, 0, 0, 0, // PC_VMHRADDSHS + BPU, 0, 0, 0, 0, 0, // PC_VMLADDUHM + BPU, 0, 0, 0, 0, 0, // PC_VMSUMMBM + BPU, 0, 0, 0, 0, 0, // PC_VMSUMSHM + BPU, 0, 0, 0, 0, 0, // PC_VMSUMSHS + BPU, 0, 0, 0, 0, 0, // PC_VMSUMUBM + BPU, 0, 0, 0, 0, 0, // PC_VMSUMUHM + BPU, 0, 0, 0, 0, 0, // PC_VMSUMUHS + BPU, 0, 0, 0, 0, 0, // PC_VNMSUBFP + BPU, 0, 0, 0, 0, 0, // PC_VPERM + BPU, 0, 0, 0, 0, 0, // PC_VSEL + BPU, 0, 0, 0, 0, 0, // PC_VSLDOI + BPU, 0, 0, 0, 0, 0, // PC_VMR + BPU, 0, 0, 0, 0, 0, // PC_VMRP + BPU, 0, 0, 0, 0, 0, // PC_SLE + BPU, 0, 0, 0, 0, 0, // PC_SLEQ + BPU, 0, 0, 0, 0, 0, // PC_SLIQ + BPU, 0, 0, 0, 0, 0, // PC_SLLIQ + BPU, 0, 0, 0, 0, 0, // PC_SLLQ + BPU, 0, 0, 0, 0, 0, // PC_SLQ + BPU, 0, 0, 0, 0, 0, // PC_SRAIQ + BPU, 0, 0, 0, 0, 0, // PC_SRAQ + BPU, 0, 0, 0, 0, 0, // PC_SRE + BPU, 0, 0, 0, 0, 0, // PC_SREA + BPU, 0, 0, 0, 0, 0, // PC_SREQ + BPU, 0, 0, 0, 0, 0, // PC_SRIQ + BPU, 0, 0, 0, 0, 0, // PC_SRLIQ + BPU, 0, 0, 0, 0, 0, // PC_SRLQ + BPU, 0, 0, 0, 0, 0, // PC_SRQ + BPU, 0, 0, 0, 0, 0, // PC_MASKG + BPU, 0, 0, 0, 0, 0, // PC_MASKIR + BPU, 0, 0, 0, 0, 0, // PC_LSCBX + BPU, 0, 0, 0, 0, 0, // PC_DIV + BPU, 0, 0, 0, 0, 0, // PC_DIVS + BPU, 0, 0, 0, 0, 0, // PC_DOZ + BPU, 0, 0, 0, 0, 0, // PC_MUL + BPU, 0, 0, 0, 0, 0, // PC_NABS + BPU, 0, 0, 0, 0, 0, // PC_ABS + BPU, 0, 0, 0, 0, 0, // PC_CLCS + BPU, 0, 0, 0, 0, 0, // PC_DOZI + BPU, 0, 0, 0, 0, 0, // PC_RLMI + BPU, 0, 0, 0, 0, 0, // PC_RRIB +}; + +static void advance(int firstStage, int oldStage, int newStage) { + PCode *instr = pipeline[oldStage].instr; + int cycles = instruction_timing[instr->op].cycles[newStage - firstStage]; + pipeline[newStage].instr = instr; + pipeline[newStage].remaining = cycles; + pipeline[oldStage].instr = NULL; +} + +static void assign_completion_buffer(PCode *instr) { + completionbuffers.used++; + completionbuffers.free--; + completionbuffers.entries[completionbuffers.nextFreeSlot].instr = instr; + completionbuffers.entries[completionbuffers.nextFreeSlot].completed = 0; + completionbuffers.nextFreeSlot = (completionbuffers.nextFreeSlot + 1) % MaxEntries; +} + +static void complete_instruction(int stage) { + PCode *instr = pipeline[stage].instr; + int buf = 0; + while (buf < MaxEntries && completionbuffers.entries[buf].instr != instr) + buf++; + + completionbuffers.entries[buf].completed = 1; + pipeline[stage].instr = NULL; +} + +static void retire_instruction(void) { + completionbuffers.entries[completionbuffers.nextToRetire].instr = NULL; + completionbuffers.used--; + completionbuffers.free++; + completionbuffers.nextToRetire = (completionbuffers.nextToRetire + 1) % MaxEntries; +} + +static int latency(PCode *instr) { + int cycles = instruction_timing[instr->op].latency; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + cycles += 2; + if (instr->op == PC_LMW || instr->op == PC_STMW) + cycles += instr->argCount - 2; + return cycles; +} + +static void initialize(void) { + int stage; + int i; + + for (stage = 0; stage < NumStages; stage++) + pipeline[stage].instr = NULL; + + completionbuffers.free = MaxEntries; + completionbuffers.used = 0; + completionbuffers.nextToRetire = 0; + completionbuffers.nextFreeSlot = 0; + for (i = 0; i < MaxEntries; i++) + completionbuffers.entries[i].instr = NULL; +} + +static int can_issue(PCode *instr) { + int stage; + + if (completionbuffers.free == 0) + return 0; + + stage = instruction_timing[instr->op].stage; + if (pipeline[stage].instr) { + if (stage == IU) { + switch (instr->op) { + case PC_ADD: + case PC_ADDC: + case PC_ADDI: + case PC_ADDIS: + case PC_CMPI: + case PC_CMP: + case PC_CMPLI: + case PC_CMPL: + if (is_dependent(instr, pipeline[IU].instr, RegClass_GPR)) + return 0; + if (!pipeline[SRU].instr) + return 1; + } + } + return 0; + } + + if ((instr->flags & fIsWrite) && pipeline[LSU2].instr && (pipeline[LSU2].instr->flags & fIsWrite)) + return 0; + + return 1; +} + +static void issue(PCode *instr) { + int stage = instruction_timing[instr->op].stage; + int cycles = instruction_timing[instr->op].cycles[0]; + if (stage == IU && pipeline[IU].instr) + stage = SRU; + assign_completion_buffer(instr); + pipeline[stage].instr = instr; + pipeline[stage].remaining = cycles; +} + +static void advance_clock(void) { + int stage; + + for (stage = 0; stage < NumStages; stage++) { + if (pipeline[stage].instr && pipeline[stage].remaining) + --pipeline[stage].remaining; + } + + if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { + retire_instruction(); + if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { + retire_instruction(); + } + } + + if (pipeline[IU].instr && pipeline[IU].remaining == 0) + complete_instruction(IU); + if (pipeline[LSU2].instr && pipeline[LSU2].remaining == 0) + complete_instruction(LSU2); + if (pipeline[FPU3].instr && pipeline[FPU3].remaining == 0) + complete_instruction(FPU3); + if (pipeline[SRU].instr && pipeline[SRU].remaining == 0) + complete_instruction(SRU); + if (pipeline[BPU].instr && pipeline[BPU].remaining == 0) + complete_instruction(BPU); + + if ( + pipeline[FPU1].instr && + pipeline[FPU1].remaining == 0 && + (pipeline[FPU1].instr->op == PC_FDIV || pipeline[FPU1].instr->op == PC_FDIVS) + ) + complete_instruction(FPU1); + + if (pipeline[FPU2].instr && pipeline[FPU2].remaining == 0 && !pipeline[FPU3].instr) + advance(FPU1, FPU2, FPU3); + if (pipeline[FPU1].instr && pipeline[FPU1].remaining == 0 && !pipeline[FPU2].instr) + advance(FPU1, FPU1, FPU2); + if (pipeline[LSU1].instr && pipeline[LSU1].remaining == 0 && !pipeline[LSU2].instr) + advance(LSU1, LSU1, LSU2); +} + +static int serializes(PCode *instr) { + return instruction_timing[instr->op].serializes; +} + +MachineInfo machine603e = { + 2, + 1, + 0, + &latency, + &initialize, + &can_issue, + &issue, + &advance_clock, + &serializes, + &default_uses_vpermute_unit +}; diff --git a/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation604.c b/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation604.c new file mode 100644 index 0000000..9775c9e --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation604.c @@ -0,0 +1,670 @@ +#include "compiler/Scheduler.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" + +// https://archive.org/details/bitsavers_motorolaPosManualNov94_22719504 + +typedef enum Stage { + SCIU, // Single-Cycle Integer Unit 1 + SCIU2, // Single-Cycle Integer Unit 2 + MCIU, // Multiple-Cycle Integer Unit + FPU1, // Floating Point Unit + FPU2, + FPU3, + LSU1, // Load/Store Unit + LSU2, + BPU, // Branch Prediction Unit + NumStages +} Stage; + +static struct { + // the instruction currently in this pipeline stage + PCode *instr; + + // how many cycles are left for this instruction to finish + int remaining; +} pipeline[NumStages]; + +enum { + MaxEntries = 16 +}; + +static struct { + // how many entries remain unused in the queue + unsigned int free; + + // how many entries are currently used in the queue + unsigned int used; + + // the index of the next instruction that will be retired + unsigned int nextToRetire; + + // the index of the next free slot that will be used when an instruction is dispatched + unsigned int nextFreeSlot; + + // circular array of entries in the completion queue + struct { + PCode *instr; + int completed; + } entries[MaxEntries]; +} completionbuffers; + +static PCode *sciu_completed_instruction; +static PCode *sciu2_completed_instruction; + +static struct { + // the initial stage for this instruction + Stage stage; + + // the total amount of cycles required by this instruction + char latency; + + // how long it takes to finish each stage + char cycles[3]; + + // does this instruction serialise? + char serializes; +} instruction_timing[OPCODE_MAX] = { + BPU, 0, 0, 0, 0, 1, // PC_B + BPU, 0, 0, 0, 0, 1, // PC_BL + BPU, 0, 0, 0, 0, 1, // PC_BC + BPU, 0, 0, 0, 0, 1, // PC_BCLR + BPU, 0, 0, 0, 0, 1, // PC_BCCTR + BPU, 0, 0, 0, 0, 1, // PC_BT + BPU, 0, 0, 0, 0, 1, // PC_BTLR + BPU, 0, 0, 0, 0, 1, // PC_BTCTR + BPU, 0, 0, 0, 0, 1, // PC_BF + BPU, 0, 0, 0, 0, 1, // PC_BFLR + BPU, 0, 0, 0, 0, 1, // PC_BFCTR + BPU, 0, 0, 0, 0, 1, // PC_BDNZ + BPU, 0, 0, 0, 0, 1, // PC_BDNZT + BPU, 0, 0, 0, 0, 1, // PC_BDNZF + BPU, 0, 0, 0, 0, 1, // PC_BDZ + BPU, 0, 0, 0, 0, 1, // PC_BDZT + BPU, 0, 0, 0, 0, 1, // PC_BDZF + BPU, 0, 0, 0, 0, 1, // PC_BLR + BPU, 0, 0, 0, 0, 1, // PC_BCTR + BPU, 0, 0, 0, 0, 1, // PC_BCTRL + BPU, 0, 0, 0, 0, 1, // PC_BLRL + LSU1, 2, 1, 1, 0, 0, // PC_LBZ + LSU1, 2, 1, 1, 0, 0, // PC_LBZU + LSU1, 2, 1, 1, 0, 0, // PC_LBZX + LSU1, 2, 1, 1, 0, 0, // PC_LBZUX + LSU1, 2, 1, 1, 0, 0, // PC_LHZ + LSU1, 2, 1, 1, 0, 0, // PC_LHZU + LSU1, 2, 1, 1, 0, 0, // PC_LHZX + LSU1, 2, 1, 1, 0, 0, // PC_LHZUX + LSU1, 2, 1, 1, 0, 0, // PC_LHA + LSU1, 2, 1, 1, 0, 0, // PC_LHAU + LSU1, 2, 1, 1, 0, 0, // PC_LHAX + LSU1, 2, 1, 1, 0, 0, // PC_LHAUX + LSU1, 2, 1, 1, 0, 0, // PC_LHBRX + LSU1, 2, 1, 1, 0, 0, // PC_LWZ + LSU1, 2, 1, 1, 0, 0, // PC_LWZU + LSU1, 2, 1, 1, 0, 0, // PC_LWZX + LSU1, 2, 1, 1, 0, 0, // PC_LWZUX + LSU1, 2, 1, 1, 0, 0, // PC_LWBRX + LSU1, 2, 1, 1, 0, 0, // PC_LMW + LSU1, 3, 1, 1, 0, 0, // PC_STB + LSU1, 3, 1, 1, 0, 0, // PC_STBU + LSU1, 3, 1, 1, 0, 0, // PC_STBX + LSU1, 3, 1, 1, 0, 0, // PC_STBUX + LSU1, 3, 1, 1, 0, 0, // PC_STH + LSU1, 3, 1, 1, 0, 0, // PC_STHU + LSU1, 3, 1, 1, 0, 0, // PC_STHX + LSU1, 3, 1, 1, 0, 0, // PC_STHUX + LSU1, 3, 1, 1, 0, 0, // PC_STHBRX + LSU1, 3, 1, 1, 0, 0, // PC_STW + LSU1, 3, 1, 1, 0, 0, // PC_STWU + LSU1, 3, 1, 1, 0, 0, // PC_STWX + LSU1, 3, 1, 1, 0, 0, // PC_STWUX + LSU1, 3, 1, 1, 0, 0, // PC_STWBRX + LSU1, 2, 1, 1, 0, 0, // PC_STMW + LSU1, 2, 1, 1, 0, 0, // PC_DCBF + LSU1, 2, 1, 1, 0, 0, // PC_DCBST + LSU1, 2, 1, 1, 0, 0, // PC_DCBT + LSU1, 2, 1, 1, 0, 0, // PC_DCBTST + LSU1, 2, 1, 1, 0, 0, // PC_DCBZ + SCIU, 1, 1, 0, 0, 0, // PC_ADD + SCIU, 1, 1, 0, 0, 0, // PC_ADDC + SCIU, 1, 1, 0, 0, 0, // PC_ADDE + SCIU, 1, 1, 0, 0, 0, // PC_ADDI + SCIU, 1, 1, 0, 0, 0, // PC_ADDIC + SCIU, 1, 1, 0, 0, 0, // PC_ADDICR + SCIU, 1, 1, 0, 0, 0, // PC_ADDIS + SCIU, 1, 1, 0, 0, 0, // PC_ADDME + SCIU, 1, 1, 0, 0, 0, // PC_ADDZE + MCIU, 20, 20, 0, 0, 0, // PC_DIVW + MCIU, 20, 20, 0, 0, 0, // PC_DIVWU + MCIU, 4, 4, 0, 0, 0, // PC_MULHW + MCIU, 4, 4, 0, 0, 0, // PC_MULHWU + MCIU, 3, 3, 0, 0, 0, // PC_MULLI + MCIU, 4, 4, 0, 0, 0, // PC_MULLW + SCIU, 1, 1, 0, 0, 0, // PC_NEG + SCIU, 1, 1, 0, 0, 0, // PC_SUBF + SCIU, 1, 1, 0, 0, 0, // PC_SUBFC + SCIU, 1, 1, 0, 0, 0, // PC_SUBFE + SCIU, 1, 1, 0, 0, 0, // PC_SUBFIC + SCIU, 1, 1, 0, 0, 0, // PC_SUBFME + SCIU, 1, 1, 0, 0, 0, // PC_SUBFZE + SCIU, 3, 1, 0, 0, 0, // PC_CMPI + SCIU, 3, 1, 0, 0, 0, // PC_CMP + SCIU, 3, 1, 0, 0, 0, // PC_CMPLI + SCIU, 3, 1, 0, 0, 0, // PC_CMPL + SCIU, 1, 1, 0, 0, 0, // PC_ANDI + SCIU, 1, 1, 0, 0, 0, // PC_ANDIS + SCIU, 1, 1, 0, 0, 0, // PC_ORI + SCIU, 1, 1, 0, 0, 0, // PC_ORIS + SCIU, 1, 1, 0, 0, 0, // PC_XORI + SCIU, 1, 1, 0, 0, 0, // PC_XORIS + SCIU, 1, 1, 0, 0, 0, // PC_AND + SCIU, 1, 1, 0, 0, 0, // PC_OR + SCIU, 1, 1, 0, 0, 0, // PC_XOR + SCIU, 1, 1, 0, 0, 0, // PC_NAND + SCIU, 1, 1, 0, 0, 0, // PC_NOR + SCIU, 1, 1, 0, 0, 0, // PC_EQV + SCIU, 1, 1, 0, 0, 0, // PC_ANDC + SCIU, 1, 1, 0, 0, 0, // PC_ORC + SCIU, 1, 1, 0, 0, 0, // PC_EXTSB + SCIU, 1, 1, 0, 0, 0, // PC_EXTSH + SCIU, 1, 1, 0, 0, 0, // PC_CNTLZW + SCIU, 1, 1, 0, 0, 0, // PC_RLWINM + SCIU, 1, 1, 0, 0, 0, // PC_RLWNM + SCIU, 1, 1, 0, 0, 0, // PC_RLWIMI + SCIU, 1, 1, 0, 0, 0, // PC_SLW + SCIU, 1, 1, 0, 0, 0, // PC_SRW + SCIU, 1, 1, 0, 0, 0, // PC_SRAWI + SCIU, 1, 1, 0, 0, 0, // PC_SRAW + BPU, 1, 1, 0, 0, 0, // PC_CRAND + BPU, 1, 1, 0, 0, 0, // PC_CRANDC + BPU, 1, 1, 0, 0, 0, // PC_CREQV + BPU, 1, 1, 0, 0, 0, // PC_CRNAND + BPU, 1, 1, 0, 0, 0, // PC_CRNOR + BPU, 1, 1, 0, 0, 0, // PC_CROR + BPU, 1, 1, 0, 0, 0, // PC_CRORC + BPU, 1, 1, 0, 0, 0, // PC_CRXOR + BPU, 1, 1, 0, 0, 0, // PC_MCRF + MCIU, 1, 1, 0, 0, 0, // PC_MTXER + MCIU, 1, 1, 0, 0, 0, // PC_MTCTR + MCIU, 1, 1, 0, 0, 0, // PC_MTLR + MCIU, 1, 1, 0, 0, 0, // PC_MTCRF + MCIU, 1, 1, 0, 0, 0, // PC_MTMSR + MCIU, 1, 1, 0, 0, 0, // PC_MTSPR + MCIU, 1, 1, 0, 0, 0, // PC_MFMSR + MCIU, 1, 1, 0, 0, 0, // PC_MFSPR + MCIU, 3, 3, 0, 0, 0, // PC_MFXER + MCIU, 3, 3, 0, 0, 0, // PC_MFCTR + MCIU, 3, 3, 0, 0, 0, // PC_MFLR + MCIU, 3, 3, 0, 0, 0, // PC_MFCR + FPU1, 3, 1, 1, 1, 0, // PC_MFFS + FPU1, 3, 1, 1, 1, 0, // PC_MTFSF + LSU1, 1, 0, 0, 0, 1, // PC_EIEIO + LSU1, 1, 0, 0, 0, 1, // PC_ISYNC + LSU1, 1, 0, 0, 0, 1, // PC_SYNC + LSU1, 1, 1, 0, 0, 1, // PC_RFI + SCIU, 1, 1, 0, 0, 0, // PC_LI + SCIU, 1, 1, 0, 0, 0, // PC_LIS + SCIU, 1, 1, 0, 0, 0, // PC_MR + SCIU, 1, 1, 0, 0, 0, // PC_NOP + SCIU, 1, 1, 0, 0, 0, // PC_NOT + LSU1, 3, 1, 1, 0, 0, // PC_LFS + LSU1, 3, 1, 1, 0, 0, // PC_LFSU + LSU1, 3, 1, 1, 0, 0, // PC_LFSX + LSU1, 3, 1, 1, 0, 0, // PC_LFSUX + LSU1, 3, 1, 1, 0, 0, // PC_LFD + LSU1, 3, 1, 1, 0, 0, // PC_LFDU + LSU1, 3, 1, 1, 0, 0, // PC_LFDX + LSU1, 3, 1, 1, 0, 0, // PC_LFDUX + LSU1, 3, 1, 1, 0, 0, // PC_STFS + LSU1, 3, 1, 1, 0, 0, // PC_STFSU + LSU1, 3, 1, 1, 0, 0, // PC_STFSX + LSU1, 3, 1, 1, 0, 0, // PC_STFSUX + LSU1, 3, 1, 1, 0, 0, // PC_STFD + LSU1, 3, 1, 1, 0, 0, // PC_STFDU + LSU1, 3, 1, 1, 0, 0, // PC_STFDX + LSU1, 3, 1, 1, 0, 0, // PC_STFDUX + FPU1, 3, 1, 1, 1, 0, // PC_FMR + FPU1, 3, 1, 1, 1, 0, // PC_FABS + FPU1, 3, 1, 1, 1, 0, // PC_FNEG + FPU1, 3, 1, 1, 1, 0, // PC_FNABS + FPU1, 3, 1, 1, 1, 0, // PC_FADD + FPU1, 3, 1, 1, 1, 0, // PC_FADDS + FPU1, 3, 1, 1, 1, 0, // PC_FSUB + FPU1, 3, 1, 1, 1, 0, // PC_FSUBS + FPU1, 3, 1, 1, 1, 0, // PC_FMUL + FPU1, 3, 1, 1, 1, 0, // PC_FMULS + FPU1, 32, 32, 0, 0, 0, // PC_FDIV + FPU1, 18, 18, 0, 0, 0, // PC_FDIVS + FPU1, 3, 1, 1, 1, 0, // PC_FMADD + FPU1, 3, 1, 1, 1, 0, // PC_FMADDS + FPU1, 3, 1, 1, 1, 0, // PC_FMSUB + FPU1, 3, 1, 1, 1, 0, // PC_FMSUBS + FPU1, 3, 1, 1, 1, 0, // PC_FNMADD + FPU1, 3, 1, 1, 1, 0, // PC_FNMADDS + FPU1, 3, 1, 1, 1, 0, // PC_FNMSUB + FPU1, 3, 1, 1, 1, 0, // PC_FNMSUBS + FPU1, 18, 18, 0, 0, 0, // PC_FRES + FPU1, 3, 1, 1, 1, 0, // PC_FRSQRTE + FPU1, 3, 1, 1, 1, 0, // PC_FSEL + FPU1, 3, 1, 1, 1, 0, // PC_FRSP + FPU1, 3, 1, 1, 1, 0, // PC_FCTIW + FPU1, 3, 1, 1, 1, 0, // PC_FCTIWZ + FPU1, 5, 1, 1, 1, 0, // PC_FCMPU + FPU1, 5, 1, 1, 1, 0, // PC_FCMPO + LSU1, 1, 1, 0, 0, 0, // PC_LWARX + LSU1, 1, 1, 0, 0, 0, // PC_LSWI + LSU1, 1, 1, 0, 0, 0, // PC_LSWX + LSU1, 1, 1, 0, 0, 0, // PC_STFIWX + LSU1, 1, 1, 0, 0, 0, // PC_STSWI + LSU1, 1, 1, 0, 0, 0, // PC_STSWX + LSU1, 1, 1, 0, 0, 0, // PC_STWCX + MCIU, 1, 1, 0, 0, 1, // PC_ECIWX + MCIU, 1, 1, 0, 0, 1, // PC_ECOWX + MCIU, 1, 1, 0, 0, 0, // PC_DCBI + MCIU, 1, 1, 0, 0, 0, // PC_ICBI + MCIU, 1, 1, 0, 0, 0, // PC_MCRFS + MCIU, 1, 1, 0, 0, 0, // PC_MCRXR + MCIU, 1, 1, 0, 0, 0, // PC_MFTB + MCIU, 1, 1, 0, 0, 0, // PC_MFSR + MCIU, 1, 1, 0, 0, 0, // PC_MTSR + MCIU, 1, 1, 0, 0, 0, // PC_MFSRIN + MCIU, 1, 1, 0, 0, 0, // PC_MTSRIN + MCIU, 1, 1, 0, 0, 0, // PC_MTFSB0 + MCIU, 1, 1, 0, 0, 0, // PC_MTFSB1 + MCIU, 1, 1, 0, 0, 0, // PC_MTFSFI + MCIU, 1, 1, 0, 0, 1, // PC_SC + FPU1, 1, 1, 0, 0, 0, // PC_FSQRT + FPU1, 1, 1, 0, 0, 0, // PC_FSQRTS + MCIU, 1, 1, 0, 0, 0, // PC_TLBIA + MCIU, 1, 1, 0, 0, 0, // PC_TLBIE + MCIU, 1, 1, 0, 0, 0, // PC_TLBLD + MCIU, 1, 1, 0, 0, 0, // PC_TLBLI + MCIU, 1, 1, 0, 0, 0, // PC_TLBSYNC + MCIU, 1, 1, 0, 0, 1, // PC_TW + MCIU, 1, 1, 0, 0, 1, // PC_TRAP + MCIU, 1, 1, 0, 0, 1, // PC_TWI + MCIU, 1, 1, 0, 0, 1, // PC_OPWORD + MCIU, 1, 1, 0, 0, 0, // PC_MFROM + MCIU, 1, 1, 0, 0, 1, // PC_DSA + MCIU, 1, 1, 0, 0, 1, // PC_ESA + MCIU, 0, 0, 0, 0, 0, // PC_DCCCI + MCIU, 0, 0, 0, 0, 0, // PC_DCREAD + MCIU, 0, 0, 0, 0, 0, // PC_ICBT + MCIU, 0, 0, 0, 0, 0, // PC_ICCCI + MCIU, 0, 0, 0, 0, 0, // PC_ICREAD + MCIU, 0, 0, 0, 0, 0, // PC_RFCI + MCIU, 0, 0, 0, 0, 0, // PC_TLBRE + MCIU, 0, 0, 0, 0, 0, // PC_TLBSX + MCIU, 0, 0, 0, 0, 0, // PC_TLBWE + MCIU, 0, 0, 0, 0, 0, // PC_WRTEE + MCIU, 0, 0, 0, 0, 0, // PC_WRTEEI + MCIU, 0, 0, 0, 0, 0, // PC_MFDCR + MCIU, 0, 0, 0, 0, 0, // PC_MTDCR + MCIU, 0, 0, 0, 0, 0, // PC_DCBA + SCIU, 0, 0, 0, 0, 0, // PC_DSS + SCIU, 0, 0, 0, 0, 0, // PC_DSSALL + SCIU, 0, 0, 0, 0, 0, // PC_DST + SCIU, 0, 0, 0, 0, 0, // PC_DSTT + SCIU, 0, 0, 0, 0, 0, // PC_DSTST + SCIU, 0, 0, 0, 0, 0, // PC_DSTSTT + SCIU, 0, 0, 0, 0, 0, // PC_LVEBX + SCIU, 0, 0, 0, 0, 0, // PC_LVEHX + SCIU, 0, 0, 0, 0, 0, // PC_LVEWX + SCIU, 0, 0, 0, 0, 0, // PC_LVSL + SCIU, 0, 0, 0, 0, 0, // PC_LVSR + SCIU, 0, 0, 0, 0, 0, // PC_LVX + SCIU, 0, 0, 0, 0, 0, // PC_LVXL + SCIU, 0, 0, 0, 0, 0, // PC_STVEBX + SCIU, 0, 0, 0, 0, 0, // PC_STVEHX + SCIU, 0, 0, 0, 0, 0, // PC_STVEWX + SCIU, 0, 0, 0, 0, 0, // PC_STVX + SCIU, 0, 0, 0, 0, 0, // PC_STVXL + SCIU, 0, 0, 0, 0, 0, // PC_MFVSCR + SCIU, 0, 0, 0, 0, 0, // PC_MTVSCR + SCIU, 0, 0, 0, 0, 0, // PC_VADDCUW + SCIU, 0, 0, 0, 0, 0, // PC_VADDFP + SCIU, 0, 0, 0, 0, 0, // PC_VADDSBS + SCIU, 0, 0, 0, 0, 0, // PC_VADDSHS + SCIU, 0, 0, 0, 0, 0, // PC_VADDSWS + SCIU, 0, 0, 0, 0, 0, // PC_VADDUBM + SCIU, 0, 0, 0, 0, 0, // PC_VADDUBS + SCIU, 0, 0, 0, 0, 0, // PC_VADDUHM + SCIU, 0, 0, 0, 0, 0, // PC_VADDUHS + SCIU, 0, 0, 0, 0, 0, // PC_VADDUWM + SCIU, 0, 0, 0, 0, 0, // PC_VADDUWS + SCIU, 0, 0, 0, 0, 0, // PC_VAND + SCIU, 0, 0, 0, 0, 0, // PC_VANDC + SCIU, 0, 0, 0, 0, 0, // PC_VAVGSB + SCIU, 0, 0, 0, 0, 0, // PC_VAVGSH + SCIU, 0, 0, 0, 0, 0, // PC_VAVGSW + SCIU, 0, 0, 0, 0, 0, // PC_VAVGUB + SCIU, 0, 0, 0, 0, 0, // PC_VAVGUH + SCIU, 0, 0, 0, 0, 0, // PC_VAVGUW + SCIU, 0, 0, 0, 0, 0, // PC_VCFSX + SCIU, 0, 0, 0, 0, 0, // PC_VCFUX + SCIU, 0, 0, 0, 0, 0, // PC_VCMPBFP + SCIU, 0, 0, 0, 0, 0, // PC_VCMPEQFP + SCIU, 0, 0, 0, 0, 0, // PC_VCMPEQUB + SCIU, 0, 0, 0, 0, 0, // PC_VCMPEQUH + SCIU, 0, 0, 0, 0, 0, // PC_VCMPEQUW + SCIU, 0, 0, 0, 0, 0, // PC_VCMPGEFP + SCIU, 0, 0, 0, 0, 0, // PC_VCMPGTFP + SCIU, 0, 0, 0, 0, 0, // PC_VCMPGTSB + SCIU, 0, 0, 0, 0, 0, // PC_VCMPGTSH + SCIU, 0, 0, 0, 0, 0, // PC_VCMPGTSW + SCIU, 0, 0, 0, 0, 0, // PC_VCMPGTUB + SCIU, 0, 0, 0, 0, 0, // PC_VCMPGTUH + SCIU, 0, 0, 0, 0, 0, // PC_VCMPGTUW + SCIU, 0, 0, 0, 0, 0, // PC_VCTSXS + SCIU, 0, 0, 0, 0, 0, // PC_VCTUXS + SCIU, 0, 0, 0, 0, 0, // PC_VEXPTEFP + SCIU, 0, 0, 0, 0, 0, // PC_VLOGEFP + SCIU, 0, 0, 0, 0, 0, // PC_VMAXFP + SCIU, 0, 0, 0, 0, 0, // PC_VMAXSB + SCIU, 0, 0, 0, 0, 0, // PC_VMAXSH + SCIU, 0, 0, 0, 0, 0, // PC_VMAXSW + SCIU, 0, 0, 0, 0, 0, // PC_VMAXUB + SCIU, 0, 0, 0, 0, 0, // PC_VMAXUH + SCIU, 0, 0, 0, 0, 0, // PC_VMAXUW + SCIU, 0, 0, 0, 0, 0, // PC_VMINFP + SCIU, 0, 0, 0, 0, 0, // PC_VMINSB + SCIU, 0, 0, 0, 0, 0, // PC_VMINSH + SCIU, 0, 0, 0, 0, 0, // PC_VMINSW + SCIU, 0, 0, 0, 0, 0, // PC_VMINUB + SCIU, 0, 0, 0, 0, 0, // PC_VMINUH + SCIU, 0, 0, 0, 0, 0, // PC_VMINUW + SCIU, 0, 0, 0, 0, 0, // PC_VMRGHB + SCIU, 0, 0, 0, 0, 0, // PC_VMRGHH + SCIU, 0, 0, 0, 0, 0, // PC_VMRGHW + SCIU, 0, 0, 0, 0, 0, // PC_VMRGLB + SCIU, 0, 0, 0, 0, 0, // PC_VMRGLH + SCIU, 0, 0, 0, 0, 0, // PC_VMRGLW + SCIU, 0, 0, 0, 0, 0, // PC_VMULESB + SCIU, 0, 0, 0, 0, 0, // PC_VMULESH + SCIU, 0, 0, 0, 0, 0, // PC_VMULEUB + SCIU, 0, 0, 0, 0, 0, // PC_VMULEUH + SCIU, 0, 0, 0, 0, 0, // PC_VMULOSB + SCIU, 0, 0, 0, 0, 0, // PC_VMULOSH + SCIU, 0, 0, 0, 0, 0, // PC_VMULOUB + SCIU, 0, 0, 0, 0, 0, // PC_VMULOUH + SCIU, 0, 0, 0, 0, 0, // PC_VNOR + SCIU, 0, 0, 0, 0, 0, // PC_VOR + SCIU, 0, 0, 0, 0, 0, // PC_VPKPX + SCIU, 0, 0, 0, 0, 0, // PC_VPKSHSS + SCIU, 0, 0, 0, 0, 0, // PC_VPKSHUS + SCIU, 0, 0, 0, 0, 0, // PC_VPKSWSS + SCIU, 0, 0, 0, 0, 0, // PC_VPKSWUS + SCIU, 0, 0, 0, 0, 0, // PC_VPKUHUM + SCIU, 0, 0, 0, 0, 0, // PC_VPKUHUS + SCIU, 0, 0, 0, 0, 0, // PC_VPKUWUM + SCIU, 0, 0, 0, 0, 0, // PC_VPKUWUS + SCIU, 0, 0, 0, 0, 0, // PC_VREFP + SCIU, 0, 0, 0, 0, 0, // PC_VRFIM + SCIU, 0, 0, 0, 0, 0, // PC_VRFIN + SCIU, 0, 0, 0, 0, 0, // PC_VRFIP + SCIU, 0, 0, 0, 0, 0, // PC_VRFIZ + SCIU, 0, 0, 0, 0, 0, // PC_VRLB + SCIU, 0, 0, 0, 0, 0, // PC_VRLH + SCIU, 0, 0, 0, 0, 0, // PC_VRLW + SCIU, 0, 0, 0, 0, 0, // PC_VRSQRTEFP + SCIU, 0, 0, 0, 0, 0, // PC_VSL + SCIU, 0, 0, 0, 0, 0, // PC_VSLB + SCIU, 0, 0, 0, 0, 0, // PC_VSLH + SCIU, 0, 0, 0, 0, 0, // PC_VSLO + SCIU, 0, 0, 0, 0, 0, // PC_VSLW + SCIU, 0, 0, 0, 0, 0, // PC_VSPLTB + SCIU, 0, 0, 0, 0, 0, // PC_VSPLTH + SCIU, 0, 0, 0, 0, 0, // PC_VSPLTW + SCIU, 0, 0, 0, 0, 0, // PC_VSPLTISB + SCIU, 0, 0, 0, 0, 0, // PC_VSPLTISH + SCIU, 0, 0, 0, 0, 0, // PC_VSPLTISW + SCIU, 0, 0, 0, 0, 0, // PC_VSR + SCIU, 0, 0, 0, 0, 0, // PC_VSRAB + SCIU, 0, 0, 0, 0, 0, // PC_VSRAH + SCIU, 0, 0, 0, 0, 0, // PC_VSRAW + SCIU, 0, 0, 0, 0, 0, // PC_VSRB + SCIU, 0, 0, 0, 0, 0, // PC_VSRH + SCIU, 0, 0, 0, 0, 0, // PC_VSRO + SCIU, 0, 0, 0, 0, 0, // PC_VSRW + SCIU, 0, 0, 0, 0, 0, // PC_VSUBCUW + SCIU, 0, 0, 0, 0, 0, // PC_VSUBFP + SCIU, 0, 0, 0, 0, 0, // PC_VSUBSBS + SCIU, 0, 0, 0, 0, 0, // PC_VSUBSHS + SCIU, 0, 0, 0, 0, 0, // PC_VSUBSWS + SCIU, 0, 0, 0, 0, 0, // PC_VSUBUBM + SCIU, 0, 0, 0, 0, 0, // PC_VSUBUBS + SCIU, 0, 0, 0, 0, 0, // PC_VSUBUHM + SCIU, 0, 0, 0, 0, 0, // PC_VSUBUHS + SCIU, 0, 0, 0, 0, 0, // PC_VSUBUWM + SCIU, 0, 0, 0, 0, 0, // PC_VSUBUWS + SCIU, 0, 0, 0, 0, 0, // PC_VSUMSWS + SCIU, 0, 0, 0, 0, 0, // PC_VSUM2SWS + SCIU, 0, 0, 0, 0, 0, // PC_VSUM4SBS + SCIU, 0, 0, 0, 0, 0, // PC_VSUM4SHS + SCIU, 0, 0, 0, 0, 0, // PC_VSUM4UBS + SCIU, 0, 0, 0, 0, 0, // PC_VUPKHPX + SCIU, 0, 0, 0, 0, 0, // PC_VUPKHSB + SCIU, 0, 0, 0, 0, 0, // PC_VUPKHSH + SCIU, 0, 0, 0, 0, 0, // PC_VUPKLPX + SCIU, 0, 0, 0, 0, 0, // PC_VUPKLSB + SCIU, 0, 0, 0, 0, 0, // PC_VUPKLSH + SCIU, 0, 0, 0, 0, 0, // PC_VXOR + SCIU, 0, 0, 0, 0, 0, // PC_VMADDFP + SCIU, 0, 0, 0, 0, 0, // PC_VMHADDSHS + SCIU, 0, 0, 0, 0, 0, // PC_VMHRADDSHS + SCIU, 0, 0, 0, 0, 0, // PC_VMLADDUHM + SCIU, 0, 0, 0, 0, 0, // PC_VMSUMMBM + SCIU, 0, 0, 0, 0, 0, // PC_VMSUMSHM + SCIU, 0, 0, 0, 0, 0, // PC_VMSUMSHS + SCIU, 0, 0, 0, 0, 0, // PC_VMSUMUBM + SCIU, 0, 0, 0, 0, 0, // PC_VMSUMUHM + SCIU, 0, 0, 0, 0, 0, // PC_VMSUMUHS + SCIU, 0, 0, 0, 0, 0, // PC_VNMSUBFP + SCIU, 0, 0, 0, 0, 0, // PC_VPERM + SCIU, 0, 0, 0, 0, 0, // PC_VSEL + SCIU, 0, 0, 0, 0, 0, // PC_VSLDOI + SCIU, 0, 0, 0, 0, 0, // PC_VMR + SCIU, 0, 0, 0, 0, 0, // PC_VMRP + SCIU, 0, 0, 0, 0, 0, // PC_SLE + SCIU, 0, 0, 0, 0, 0, // PC_SLEQ + SCIU, 0, 0, 0, 0, 0, // PC_SLIQ + SCIU, 0, 0, 0, 0, 0, // PC_SLLIQ + SCIU, 0, 0, 0, 0, 0, // PC_SLLQ + SCIU, 0, 0, 0, 0, 0, // PC_SLQ + SCIU, 0, 0, 0, 0, 0, // PC_SRAIQ + SCIU, 0, 0, 0, 0, 0, // PC_SRAQ + SCIU, 0, 0, 0, 0, 0, // PC_SRE + SCIU, 0, 0, 0, 0, 0, // PC_SREA + SCIU, 0, 0, 0, 0, 0, // PC_SREQ + SCIU, 0, 0, 0, 0, 0, // PC_SRIQ + SCIU, 0, 0, 0, 0, 0, // PC_SRLIQ + SCIU, 0, 0, 0, 0, 0, // PC_SRLQ + SCIU, 0, 0, 0, 0, 0, // PC_SRQ + SCIU, 0, 0, 0, 0, 0, // PC_MASKG + SCIU, 0, 0, 0, 0, 0, // PC_MASKIR + SCIU, 0, 0, 0, 0, 0, // PC_LSCBX + SCIU, 0, 0, 0, 0, 0, // PC_DIV + SCIU, 0, 0, 0, 0, 0, // PC_DIVS + SCIU, 0, 0, 0, 0, 0, // PC_DOZ + SCIU, 0, 0, 0, 0, 0, // PC_MUL + SCIU, 0, 0, 0, 0, 0, // PC_NABS + SCIU, 0, 0, 0, 0, 0, // PC_ABS + SCIU, 0, 0, 0, 0, 0, // PC_CLCS + SCIU, 0, 0, 0, 0, 0, // PC_DOZI + SCIU, 0, 0, 0, 0, 0, // PC_RLMI + SCIU, 0, 0, 0, 0, 0, // PC_RRIB +}; + +static void advance(int firstStage, int oldStage, int newStage) { + PCode *instr = pipeline[oldStage].instr; + int cycles = instruction_timing[instr->op].cycles[newStage - firstStage]; + pipeline[newStage].instr = instr; + pipeline[newStage].remaining = cycles; + pipeline[oldStage].instr = NULL; +} + +static void assign_completion_buffer(PCode *instr) { + completionbuffers.used++; + completionbuffers.free--; + completionbuffers.entries[completionbuffers.nextFreeSlot].instr = instr; + completionbuffers.entries[completionbuffers.nextFreeSlot].completed = 0; + completionbuffers.nextFreeSlot = (completionbuffers.nextFreeSlot + 1) % MaxEntries; +} + +static void complete_instruction(int stage) { + PCode *instr = pipeline[stage].instr; + int buf = 0; + while (buf < MaxEntries && completionbuffers.entries[buf].instr != instr) + buf++; + + completionbuffers.entries[buf].completed = 1; + pipeline[stage].instr = NULL; + + if (stage == SCIU) + sciu_completed_instruction = instr; + else if (stage == SCIU2) + sciu2_completed_instruction = instr; +} + +static void retire_instruction(void) { + completionbuffers.entries[completionbuffers.nextToRetire].instr = NULL; + completionbuffers.used--; + completionbuffers.free++; + completionbuffers.nextToRetire = (completionbuffers.nextToRetire + 1) % MaxEntries; +} + +static int latency(PCode *instr) { + int cycles = instruction_timing[instr->op].latency; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + cycles += 2; + if (instr->op == PC_LMW || instr->op == PC_STMW) + cycles += instr->argCount - 2; + return cycles; +} + +static void initialize(void) { + int stage; + int i; + + for (stage = 0; stage < NumStages; stage++) + pipeline[stage].instr = NULL; + + completionbuffers.free = MaxEntries; + completionbuffers.used = 0; + completionbuffers.nextToRetire = 0; + completionbuffers.nextFreeSlot = 0; + for (i = 0; i < MaxEntries; i++) + completionbuffers.entries[i].instr = NULL; + + sciu_completed_instruction = NULL; + sciu2_completed_instruction = NULL; +} + +static int can_issue(PCode *instr) { + PCode *check; + int stage = instruction_timing[instr->op].stage; + + if (completionbuffers.free == 0) + return 0; + + if (stage == SCIU) { + int isClear1 = !pipeline[SCIU].instr; + int isClear2 = !pipeline[SCIU2].instr; + if (!isClear1 && !isClear2) + return 0; + if (isClear1 && isClear2) + return 1; + + if (isClear1) + check = pipeline[SCIU2].instr; + else + check = pipeline[SCIU].instr; + + if (is_dependent(instr, check, RegClass_GPR)) + return 0; + if (is_dependent(instr, sciu_completed_instruction, RegClass_GPR)) + return 0; + if (is_dependent(instr, sciu2_completed_instruction, RegClass_GPR)) + return 0; + } else { + if (pipeline[stage].instr) + return 0; + } + + return 1; +} + +static void issue(PCode *instr) { + int stage = instruction_timing[instr->op].stage; + int cycles = instruction_timing[instr->op].cycles[0]; + if (stage == SCIU && pipeline[SCIU].instr) + stage = SCIU2; + assign_completion_buffer(instr); + pipeline[stage].instr = instr; + pipeline[stage].remaining = cycles; +} + +static void advance_clock(void) { + int stage; + int i; + + sciu_completed_instruction = NULL; + sciu2_completed_instruction = NULL; + + for (stage = 0; stage < NumStages; stage++) { + if (pipeline[stage].instr && pipeline[stage].remaining) + --pipeline[stage].remaining; + } + + for (i = 0; i < 5; i++) { + if (completionbuffers.used == 0) + break; + if (completionbuffers.entries[completionbuffers.nextToRetire].completed == 0) + break; + retire_instruction(); + } + + if (pipeline[SCIU].instr && pipeline[SCIU].remaining == 0) + complete_instruction(SCIU); + if (pipeline[SCIU2].instr && pipeline[SCIU2].remaining == 0) + complete_instruction(SCIU2); + if (pipeline[MCIU].instr && pipeline[MCIU].remaining == 0) + complete_instruction(MCIU); + if (pipeline[LSU2].instr && pipeline[LSU2].remaining == 0) + complete_instruction(LSU2); + if (pipeline[FPU3].instr && pipeline[FPU3].remaining == 0) + complete_instruction(FPU3); + if (pipeline[BPU].instr && pipeline[BPU].remaining == 0) + complete_instruction(BPU); + + if ( + pipeline[FPU1].instr && + pipeline[FPU1].remaining == 0 && + (pipeline[FPU1].instr->op == PC_FDIV || pipeline[FPU1].instr->op == PC_FDIVS) + ) + complete_instruction(FPU1); + + if (pipeline[FPU2].instr && pipeline[FPU2].remaining == 0 && !pipeline[FPU3].instr) + advance(FPU1, FPU2, FPU3); + if (pipeline[FPU1].instr && pipeline[FPU1].remaining == 0 && !pipeline[FPU2].instr) + advance(FPU1, FPU1, FPU2); + if (pipeline[LSU1].instr && pipeline[LSU1].remaining == 0 && !pipeline[LSU2].instr) + advance(LSU1, LSU1, LSU2); +} + +static int serializes(PCode *instr) { + return instruction_timing[instr->op].serializes; +} + +MachineInfo machine604 = { + 4, + 1, + 0, + &latency, + &initialize, + &can_issue, + &issue, + &advance_clock, + &serializes, + &default_uses_vpermute_unit +}; diff --git a/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation7400.c b/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation7400.c new file mode 100644 index 0000000..56b375c --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation7400.c @@ -0,0 +1,744 @@ +#include "compiler/Scheduler.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" + +// https://www.nxp.com/docs/en/reference-manual/MPC7410UM.pdf + +typedef enum Stage { + BPU, // Branch Prediction Unit + IU1, // Integer Unit 1 + IU2, // Integer Unit 2 + + LSU1, // Load/Store Unit + LSU2, + + FPU1, // Floating Point Unit + FPU2, + FPU3, + + SRU, // System Register Unit + VSIU, // Vector Simple Integer Unit + VPU, // AltiVec Permute Unit + + VCIU1, // Vector Complex Integer Unit + VCIU2, + VCIU3, + + VFPU1, // Vector Floating-Point Unit + VFPU2, + VFPU3, + VFPU4, + + NumStages +} Stage; + +static struct { + // the instruction currently in this pipeline stage + PCode *instr; + + // how many cycles are left for this instruction to finish + int remaining; +} pipeline[NumStages]; + +static PCode *iu1_completed_instruction; +static PCode *iu2_completed_instruction; + +enum { + MaxEntries = 8 +}; + +static struct { + // how many entries remain unused in the queue + unsigned int free; + + // how many entries are currently used in the queue + unsigned int used; + + // the index of the next instruction that will be retired + unsigned int nextToRetire; + + // the index of the next free slot that will be used when an instruction is dispatched + unsigned int nextFreeSlot; + + // circular array of entries in the completion queue + struct { + PCode *instr; + int completed; + } entries[MaxEntries]; +} completionbuffers; + +static struct { + // the initial stage for this instruction + Stage stage; + + // the total amount of cycles required by this instruction + char latency; + + // how long it takes to finish each stage + char cycles[4]; + + // does this instruction serialise? + char serializes; + + char unused; +} instruction_timing[OPCODE_MAX] = { + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_B + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BL + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BC + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BCLR + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BCCTR + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BT + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BTLR + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BTCTR + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BF + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BFLR + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BFCTR + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDNZ + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDNZT + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDNZF + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDZ + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDZT + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDZF + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BLR + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BCTR + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BCTRL + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BLRL + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LBZ + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LBZU + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LBZX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LBZUX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHZ + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHZU + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHZX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHZUX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHA + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHAU + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHAX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHAUX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHBRX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LWZ + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LWZU + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LWZX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LWZUX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LWBRX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LMW + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STB + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STBU + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STBX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STBUX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STH + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STHU + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STHX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STHUX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STHBRX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STW + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STWU + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STWX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STWUX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STWBRX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STMW + LSU1, 3, 1, 2, 0, 0, 0, 0, // PC_DCBF + LSU1, 3, 1, 2, 0, 0, 0, 0, // PC_DCBST + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_DCBT + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_DCBTST + LSU1, 3, 1, 2, 0, 0, 0, 0, // PC_DCBZ + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADD + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADDC + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADDE + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADDI + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADDIC + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADDICR + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADDIS + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADDME + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADDZE + IU1, 19, 19, 0, 0, 0, 0, 0, // PC_DIVW + IU1, 19, 19, 0, 0, 0, 0, 0, // PC_DIVWU + IU1, 5, 5, 0, 0, 0, 0, 0, // PC_MULHW + IU1, 6, 5, 0, 0, 0, 0, 0, // PC_MULHWU + IU1, 3, 3, 0, 0, 0, 0, 0, // PC_MULLI + IU1, 5, 5, 0, 0, 0, 0, 0, // PC_MULLW + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_NEG + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SUBF + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFC + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFE + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFIC + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFME + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFZE + IU2, 3, 1, 0, 0, 0, 0, 0, // PC_CMPI + IU2, 3, 1, 0, 0, 0, 0, 0, // PC_CMP + IU2, 3, 1, 0, 0, 0, 0, 0, // PC_CMPLI + IU2, 3, 1, 0, 0, 0, 0, 0, // PC_CMPL + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ANDI + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ANDIS + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ORI + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ORIS + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_XORI + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_XORIS + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_AND + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_OR + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_XOR + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_NAND + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_NOR + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_EQV + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ANDC + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ORC + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_EXTSB + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_EXTSH + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_CNTLZW + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_RLWINM + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_RLWNM + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_RLWIMI + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SLW + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SRW + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SRAWI + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SRAW + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_CRAND + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_CRANDC + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_CREQV + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_CRNAND + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_CRNOR + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_CROR + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_CRORC + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_CRXOR + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MCRF + SRU, 2, 2, 0, 0, 0, 1, 0, // PC_MTXER + SRU, 2, 2, 0, 0, 0, 1, 0, // PC_MTCTR + SRU, 2, 2, 0, 0, 0, 1, 0, // PC_MTLR + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MTCRF + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MTMSR + SRU, 2, 2, 0, 0, 0, 1, 0, // PC_MTSPR + SRU, 1, 1, 0, 0, 0, 0, 0, // PC_MFMSR + SRU, 3, 3, 0, 0, 0, 1, 0, // PC_MFSPR + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MFXER + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MFCTR + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MFLR + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MFCR + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_MFFS + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_MTFSF + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_EIEIO + SRU, 2, 2, 0, 0, 0, 1, 0, // PC_ISYNC + SRU, 3, 3, 0, 0, 0, 1, 0, // PC_SYNC + SRU, 2, 2, 0, 0, 0, 1, 0, // PC_RFI + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_LI + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_LIS + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_MR + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_NOP + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_NOT + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LFS + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LFSU + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LFSX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LFSUX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LFD + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LFDU + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LFDX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LFDUX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFS + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFSU + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFSX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFSUX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFD + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFDU + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFDX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFDUX + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FMR + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FABS + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FNEG + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FNABS + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FADD + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FADDS + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FSUB + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FSUBS + FPU1, 4, 2, 1, 1, 0, 0, 0, // PC_FMUL + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FMULS + FPU1, 31, 31, 0, 0, 0, 0, 0, // PC_FDIV + FPU1, 17, 17, 0, 0, 0, 0, 0, // PC_FDIVS + FPU1, 4, 2, 1, 1, 0, 0, 0, // PC_FMADD + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FMADDS + FPU1, 4, 2, 1, 1, 0, 0, 0, // PC_FMSUB + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FMSUBS + FPU1, 4, 2, 1, 1, 0, 0, 0, // PC_FNMADD + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FNMADDS + FPU1, 4, 2, 1, 1, 0, 0, 0, // PC_FNMSUB + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FNMSUBS + FPU1, 10, 10, 0, 0, 0, 0, 0, // PC_FRES + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FRSQRTE + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FSEL + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FRSP + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FCTIW + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FCTIWZ + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FCMPU + FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FCMPO + LSU1, 2, 1, 1, 0, 0, 1, 0, // PC_LWARX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LSWI + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LSWX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFIWX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STSWI + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STSWX + LSU1, 2, 1, 1, 0, 0, 1, 0, // PC_STWCX + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ECIWX + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ECOWX + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_DCBI + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ICBI + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MCRFS + SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MCRXR + SRU, 1, 1, 0, 0, 0, 0, 0, // PC_MFTB + SRU, 3, 3, 0, 0, 0, 0, 0, // PC_MFSR + SRU, 2, 2, 0, 0, 0, 1, 0, // PC_MTSR + SRU, 3, 3, 0, 0, 0, 0, 0, // PC_MFSRIN + SRU, 2, 2, 0, 0, 0, 1, 0, // PC_MTSRIN + FPU1, 1, 1, 0, 0, 0, 0, 0, // PC_MTFSB0 + FPU1, 1, 1, 0, 0, 0, 0, 0, // PC_MTFSB1 + FPU1, 1, 1, 0, 0, 0, 0, 0, // PC_MTFSFI + SRU, 2, 2, 0, 0, 0, 1, 0, // PC_SC + FPU1, 1, 1, 0, 0, 0, 0, 0, // PC_FSQRT + FPU1, 1, 1, 0, 0, 0, 0, 0, // PC_FSQRTS + LSU1, 1, 1, 0, 0, 0, 0, 0, // PC_TLBIA + LSU1, 1, 1, 0, 0, 0, 0, 0, // PC_TLBIE + LSU1, 1, 1, 0, 0, 0, 0, 0, // PC_TLBLD + LSU1, 1, 1, 0, 0, 0, 0, 0, // PC_TLBLI + LSU1, 1, 1, 0, 0, 0, 1, 0, // PC_TLBSYNC + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_TW + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_TRAP + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_TWI + IU2, 1, 1, 0, 0, 0, 1, 0, // PC_OPWORD + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_MFROM + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_DSA + IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ESA + IU2, 1, 0, 0, 0, 0, 0, 0, // PC_DCCCI + IU2, 1, 0, 0, 0, 0, 0, 0, // PC_DCREAD + IU2, 1, 0, 0, 0, 0, 0, 0, // PC_ICBT + IU2, 1, 0, 0, 0, 0, 0, 0, // PC_ICCCI + IU2, 1, 0, 0, 0, 0, 0, 0, // PC_ICREAD + IU2, 1, 0, 0, 0, 0, 0, 0, // PC_RFCI + IU2, 1, 0, 0, 0, 0, 0, 0, // PC_TLBRE + IU2, 1, 0, 0, 0, 0, 0, 0, // PC_TLBSX + IU2, 1, 0, 0, 0, 0, 0, 0, // PC_TLBWE + IU2, 1, 0, 0, 0, 0, 0, 0, // PC_WRTEE + IU2, 1, 0, 0, 0, 0, 0, 0, // PC_WRTEEI + IU2, 1, 0, 0, 0, 0, 0, 0, // PC_MFDCR + IU2, 1, 0, 0, 0, 0, 0, 0, // PC_MTDCR + LSU1, 3, 1, 2, 0, 0, 0, 0, // PC_DCBA + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_DSS + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_DSSALL + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_DST + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_DSTT + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_DSTST + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_DSTSTT + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LVEBX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LVEHX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LVEWX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LVSL + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LVSR + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LVX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LVXL + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STVEBX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STVEHX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STVEWX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STVX + LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STVXL + VSIU, 1, 1, 0, 0, 0, 1, 0, // PC_MFVSCR + VSIU, 1, 1, 0, 0, 0, 1, 0, // PC_MTVSCR + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDCUW + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VADDFP + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDSBS + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDSHS + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDSWS + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUBM + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUBS + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUHM + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUHS + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUWM + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUWS + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VAND + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VANDC + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGSB + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGSH + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGSW + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGUB + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGUH + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGUW + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VCFSX + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VCFUX + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VCMPBFP + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VCMPEQFP + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPEQUB + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPEQUH + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPEQUW + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VCMPGEFP + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VCMPGTFP + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTSB + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTSH + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTSW + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTUB + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTUH + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTUW + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VCTSXS + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VCTUXS + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VEXPTEFP + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VLOGEFP + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VMAXFP + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXSB + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXSH + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXSW + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXUB + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXUH + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXUW + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VMINFP + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMINSB + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMINSH + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMINSW + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMINUB + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMINUH + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMINUW + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VMRGHB + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VMRGHH + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VMRGHW + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VMRGLB + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VMRGLH + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VMRGLW + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMULESB + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMULESH + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMULEUB + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMULEUH + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMULOSB + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMULOSH + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMULOUB + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMULOUH + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VNOR + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VOR + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKPX + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKSHSS + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKSHUS + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKSWSS + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKSWUS + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKUHUM + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKUHUS + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKUWUM + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKUWUS + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VREFP + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VRFIM + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VRFIN + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VRFIP + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VRFIZ + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VRLB + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VRLH + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VRLW + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VRSQRTEFP + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSL + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSLB + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSLH + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSLO + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSLW + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSPLTB + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSPLTH + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSPLTW + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSPLTISB + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSPLTISH + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSPLTISW + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSR + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSRAB + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSRAH + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSRAW + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSRB + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSRH + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSRO + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSRW + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBCUW + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VSUBFP + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBSBS + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBSHS + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBSWS + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUBM + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUBS + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUHM + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUHS + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUWM + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUWS + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VSUMSWS + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VSUM2SWS + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VSUM4SBS + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VSUM4SHS + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VSUM4UBS + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VUPKHPX + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VUPKHSB + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VUPKHSH + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VUPKLPX + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VUPKLSB + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VUPKLSH + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VXOR + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VMADDFP + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMHADDSHS + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMHRADDSHS + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMLADDUHM + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMSUMMBM + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMSUMSHM + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMSUMSHS + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMSUMUBM + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMSUMUHM + VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMSUMUHS + VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VNMSUBFP + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPERM + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSEL + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSLDOI + VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMR + VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VMRP + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SLE + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SLEQ + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SLIQ + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SLLIQ + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SLLQ + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SLQ + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SRAIQ + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SRAQ + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SRE + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SREA + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SREQ + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SRIQ + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SRLIQ + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SRLQ + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SRQ + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_MASKG + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_MASKIR + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_LSCBX + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_DIV + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_DIVS + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_DOZ + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_MUL + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_NABS + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_ABS + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_CLCS + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_DOZI + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_RLMI + BPU, 0, 0, 0, 0, 0, 0, 0, // PC_RRIB +}; + +static void advance(int firstStage, int oldStage, int newStage) { + PCode *instr = pipeline[oldStage].instr; + int cycles = instruction_timing[instr->op].cycles[newStage - firstStage]; + pipeline[newStage].instr = instr; + pipeline[newStage].remaining = cycles; + pipeline[oldStage].instr = NULL; +} + +static void assign_completion_buffer(PCode *instr) { + completionbuffers.used++; + completionbuffers.free--; + completionbuffers.entries[completionbuffers.nextFreeSlot].instr = instr; + completionbuffers.entries[completionbuffers.nextFreeSlot].completed = 0; + completionbuffers.nextFreeSlot = (completionbuffers.nextFreeSlot + 1) % MaxEntries; +} + +static void complete_instruction(int stage) { + PCode *instr = pipeline[stage].instr; + int buf = 0; + while (buf < MaxEntries && completionbuffers.entries[buf].instr != instr) + buf++; + + completionbuffers.entries[buf].completed = 1; + pipeline[stage].instr = NULL; + + if (stage == IU1) + iu1_completed_instruction = instr; + else if (stage == IU2) + iu2_completed_instruction = instr; +} + +static void retire_instruction(void) { + completionbuffers.entries[completionbuffers.nextToRetire].instr = NULL; + completionbuffers.used--; + completionbuffers.free++; + completionbuffers.nextToRetire = (completionbuffers.nextToRetire + 1) % MaxEntries; +} + +static int latency(PCode *instr) { + int cycles = instruction_timing[instr->op].latency; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + cycles += 2; + if (instr->op == PC_LMW || instr->op == PC_STMW) + cycles += instr->argCount - 2; + return cycles; +} + +static void initialize(void) { + int stage; + int i; + + for (stage = 0; stage < NumStages; stage++) + pipeline[stage].instr = NULL; + + completionbuffers.free = MaxEntries; + completionbuffers.used = 0; + completionbuffers.nextToRetire = 0; + completionbuffers.nextFreeSlot = 0; + for (i = 0; i < MaxEntries; i++) + completionbuffers.entries[i].instr = NULL; + + iu1_completed_instruction = NULL; + iu2_completed_instruction = NULL; +} + +static int can_issue(PCode *instr) { + int stage; + + if (completionbuffers.free == 0) + return 0; + + stage = instruction_timing[instr->op].stage; + + if (stage == IU2) { + PCode *check; + int isClear1 = !pipeline[IU1].instr; + int isClear2 = !pipeline[IU2].instr; + if (!isClear1 && !isClear2) + return 0; + if (isClear1 && isClear2) + return 1; + + if (isClear1) + check = pipeline[IU2].instr; + else + check = pipeline[IU1].instr; + + if (is_dependent(instr, check, RegClass_GPR)) + return 0; + if (is_dependent(instr, iu1_completed_instruction, RegClass_GPR)) + return 0; + if (is_dependent(instr, iu2_completed_instruction, RegClass_GPR)) + return 0; + } else if (stage == VFPU1 || stage == VCIU1 || stage == VSIU || stage == VPU) { + PCode *check; + int isVpuClear = !pipeline[VPU].instr; + int isVFpuClear = !pipeline[VFPU1].instr; + int isVCiuClear = !pipeline[VCIU1].instr; + int isVSiuClear = !pipeline[VSIU].instr; + + if (stage == VPU) { + if (!isVpuClear) + return 0; + + if (!isVFpuClear) + check = pipeline[VFPU1].instr; + else if (!isVCiuClear) + check = pipeline[VCIU1].instr; + else if (!isVSiuClear) + check = pipeline[VSIU].instr; + else + check = NULL; + + if (is_dependent(instr, check, RegClass_VR)) + return 0; + } else { + if (!isVFpuClear || !isVCiuClear || !isVSiuClear) + return 0; + + if (!isVpuClear && is_dependent(instr, pipeline[VPU].instr, RegClass_VR)) + return 0; + } + } else { + if (pipeline[stage].instr) + return 0; + } + + if ((instr->flags & fIsWrite) && pipeline[LSU2].instr && (pipeline[LSU2].instr->flags & fIsWrite)) + return 0; + + return 1; +} + +static void issue(PCode *instr) { + int stage = instruction_timing[instr->op].stage; + int cycles = instruction_timing[instr->op].cycles[0]; + assign_completion_buffer(instr); + if (stage == IU2 && !pipeline[IU1].instr) + stage = IU1; + pipeline[stage].instr = instr; + pipeline[stage].remaining = cycles; +} + +static void advance_clock(void) { + int stage; + + iu1_completed_instruction = NULL; + iu2_completed_instruction = NULL; + + for (stage = 0; stage < NumStages; stage++) { + if (pipeline[stage].instr && pipeline[stage].remaining) + --pipeline[stage].remaining; + } + + if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { + retire_instruction(); + if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { + retire_instruction(); + } + } + + if (pipeline[IU1].instr && pipeline[IU1].remaining == 0) + complete_instruction(IU1); + if (pipeline[VPU].instr && pipeline[VPU].remaining == 0) + complete_instruction(VPU); + if (pipeline[LSU2].instr && pipeline[LSU2].remaining == 0) + complete_instruction(LSU2); + if (pipeline[FPU3].instr && pipeline[FPU3].remaining == 0) + complete_instruction(FPU3); + if (pipeline[SRU].instr && pipeline[SRU].remaining == 0) + complete_instruction(SRU); + if (pipeline[BPU].instr && pipeline[BPU].remaining == 0) + complete_instruction(BPU); + if (pipeline[VSIU].instr && pipeline[VSIU].remaining == 0) + complete_instruction(VSIU); + if (pipeline[VCIU3].instr && pipeline[VCIU3].remaining == 0) + complete_instruction(VCIU3); + if (pipeline[VFPU4].instr && pipeline[VFPU4].remaining == 0) + complete_instruction(VFPU4); + if (pipeline[IU2].instr && pipeline[IU2].remaining == 0) + complete_instruction(IU2); + + if ( + pipeline[FPU1].instr && + pipeline[FPU1].remaining == 0 && + (pipeline[FPU1].instr->op == PC_FDIV || pipeline[FPU1].instr->op == PC_FDIVS) + ) + complete_instruction(FPU1); + + if (pipeline[FPU2].instr && pipeline[FPU2].remaining == 0 && !pipeline[FPU3].instr) + advance(FPU1, FPU2, FPU3); + if (pipeline[FPU1].instr && pipeline[FPU1].remaining == 0 && !pipeline[FPU2].instr) + advance(FPU1, FPU1, FPU2); + + if (pipeline[LSU1].instr && pipeline[LSU1].remaining == 0 && !pipeline[LSU2].instr) + advance(LSU1, LSU1, LSU2); + + if (pipeline[VCIU2].instr && pipeline[VCIU2].remaining == 0 && !pipeline[VCIU3].instr) + advance(VCIU1, VCIU2, VCIU3); + if (pipeline[VCIU1].instr && pipeline[VCIU1].remaining == 0 && !pipeline[VCIU2].instr) + advance(VCIU1, VCIU1, VCIU2); + + if (pipeline[VFPU3].instr && pipeline[VFPU3].remaining == 0 && !pipeline[VFPU4].instr) + advance(VFPU1, VFPU3, VFPU4); + if (pipeline[VFPU2].instr && pipeline[VFPU2].remaining == 0 && !pipeline[VFPU3].instr) + advance(VFPU1, VFPU2, VFPU3); + if (pipeline[VFPU1].instr && pipeline[VFPU1].remaining == 0 && !pipeline[VFPU2].instr) + advance(VFPU1, VFPU1, VFPU2); +} + +static int serializes(PCode *instr) { + return instruction_timing[instr->op].serializes; +} + +static int uses_vpermute_unit_7400(PCode *instr) { + return instruction_timing[instr->op].stage == VPU; +} + +MachineInfo machine7400 = { + 2, + 1, + 0, + &latency, + &initialize, + &can_issue, + &issue, + &advance_clock, + &serializes, + &uses_vpermute_unit_7400 +}; diff --git a/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation750.c b/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation750.c new file mode 100644 index 0000000..d412df3 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation750.c @@ -0,0 +1,678 @@ +#include "compiler/Scheduler.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" + +// https://www.nxp.com/docs/en/reference-manual/MPC750UM.pdf + +typedef enum Stage { + BPU, // Branch Prediction Unit + IU1, // Integer Unit 1 + IU2, // Integer Unit 2 + + LSU1, // Load/Store Unit + LSU2, + + FPU1, // Floating Point Unit + FPU2, + FPU3, + + SRU, // System Register Unit + + NumStages +} Stage; + +static struct { + // the instruction currently in this pipeline stage + PCode *instr; + + // how many cycles are left for this instruction to finish + int remaining; +} pipeline[NumStages]; + +static PCode *iu1_completed_instruction; +static PCode *iu2_completed_instruction; + +enum { + MaxEntries = 6 +}; + +static struct { + // how many entries remain unused in the queue + unsigned int free; + + // how many entries are currently used in the queue + unsigned int used; + + // the index of the next instruction that will be retired + unsigned int nextToRetire; + + // the index of the next free slot that will be used when an instruction is dispatched + unsigned int nextFreeSlot; + + // circular array of entries in the completion queue + struct { + PCode *instr; + int completed; + } entries[MaxEntries]; +} completionbuffers; + +static struct { + // the initial stage for this instruction + Stage stage; + + // the total amount of cycles required by this instruction + char latency; + + // how long it takes to finish each stage + char cycles[3]; + + // does this instruction serialise? + char serializes; +} instruction_timing[OPCODE_MAX] = { + BPU, 0, 0, 0, 0, 1, // PC_B + BPU, 0, 0, 0, 0, 1, // PC_BL + BPU, 0, 0, 0, 0, 1, // PC_BC + BPU, 0, 0, 0, 0, 1, // PC_BCLR + BPU, 0, 0, 0, 0, 1, // PC_BCCTR + BPU, 0, 0, 0, 0, 1, // PC_BT + BPU, 0, 0, 0, 0, 1, // PC_BTLR + BPU, 0, 0, 0, 0, 1, // PC_BTCTR + BPU, 0, 0, 0, 0, 1, // PC_BF + BPU, 0, 0, 0, 0, 1, // PC_BFLR + BPU, 0, 0, 0, 0, 1, // PC_BFCTR + BPU, 0, 0, 0, 0, 1, // PC_BDNZ + BPU, 0, 0, 0, 0, 1, // PC_BDNZT + BPU, 0, 0, 0, 0, 1, // PC_BDNZF + BPU, 0, 0, 0, 0, 1, // PC_BDZ + BPU, 0, 0, 0, 0, 1, // PC_BDZT + BPU, 0, 0, 0, 0, 1, // PC_BDZF + BPU, 0, 0, 0, 0, 1, // PC_BLR + BPU, 0, 0, 0, 0, 1, // PC_BCTR + BPU, 0, 0, 0, 0, 1, // PC_BCTRL + BPU, 0, 0, 0, 0, 1, // PC_BLRL + LSU1, 2, 1, 1, 0, 0, // PC_LBZ + LSU1, 2, 1, 1, 0, 0, // PC_LBZU + LSU1, 2, 1, 1, 0, 0, // PC_LBZX + LSU1, 2, 1, 1, 0, 0, // PC_LBZUX + LSU1, 2, 1, 1, 0, 0, // PC_LHZ + LSU1, 2, 1, 1, 0, 0, // PC_LHZU + LSU1, 2, 1, 1, 0, 0, // PC_LHZX + LSU1, 2, 1, 1, 0, 0, // PC_LHZUX + LSU1, 2, 1, 1, 0, 0, // PC_LHA + LSU1, 2, 1, 1, 0, 0, // PC_LHAU + LSU1, 2, 1, 1, 0, 0, // PC_LHAX + LSU1, 2, 1, 1, 0, 0, // PC_LHAUX + LSU1, 2, 1, 1, 0, 0, // PC_LHBRX + LSU1, 2, 1, 1, 0, 0, // PC_LWZ + LSU1, 2, 1, 1, 0, 0, // PC_LWZU + LSU1, 2, 1, 1, 0, 0, // PC_LWZX + LSU1, 2, 1, 1, 0, 0, // PC_LWZUX + LSU1, 2, 1, 1, 0, 0, // PC_LWBRX + LSU1, 2, 1, 1, 0, 0, // PC_LMW + LSU1, 2, 1, 1, 0, 0, // PC_STB + LSU1, 2, 1, 1, 0, 0, // PC_STBU + LSU1, 2, 1, 1, 0, 0, // PC_STBX + LSU1, 2, 1, 1, 0, 0, // PC_STBUX + LSU1, 2, 1, 1, 0, 0, // PC_STH + LSU1, 2, 1, 1, 0, 0, // PC_STHU + LSU1, 2, 1, 1, 0, 0, // PC_STHX + LSU1, 2, 1, 1, 0, 0, // PC_STHUX + LSU1, 2, 1, 1, 0, 0, // PC_STHBRX + LSU1, 2, 1, 1, 0, 0, // PC_STW + LSU1, 2, 1, 1, 0, 0, // PC_STWU + LSU1, 2, 1, 1, 0, 0, // PC_STWX + LSU1, 2, 1, 1, 0, 0, // PC_STWUX + LSU1, 2, 1, 1, 0, 0, // PC_STWBRX + LSU1, 2, 1, 1, 0, 0, // PC_STMW + LSU1, 3, 1, 2, 0, 0, // PC_DCBF + LSU1, 3, 1, 2, 0, 0, // PC_DCBST + LSU1, 2, 1, 1, 0, 0, // PC_DCBT + LSU1, 2, 1, 1, 0, 0, // PC_DCBTST + LSU1, 3, 1, 2, 0, 0, // PC_DCBZ + IU2, 1, 1, 0, 0, 0, // PC_ADD + IU2, 1, 1, 0, 0, 0, // PC_ADDC + IU2, 1, 1, 0, 0, 0, // PC_ADDE + IU2, 1, 1, 0, 0, 0, // PC_ADDI + IU2, 1, 1, 0, 0, 0, // PC_ADDIC + IU2, 1, 1, 0, 0, 0, // PC_ADDICR + IU2, 1, 1, 0, 0, 0, // PC_ADDIS + IU2, 1, 1, 0, 0, 0, // PC_ADDME + IU2, 1, 1, 0, 0, 0, // PC_ADDZE + IU1, 19, 19, 0, 0, 0, // PC_DIVW + IU1, 19, 19, 0, 0, 0, // PC_DIVWU + IU1, 5, 5, 0, 0, 0, // PC_MULHW + IU1, 6, 5, 0, 0, 0, // PC_MULHWU + IU1, 3, 3, 0, 0, 0, // PC_MULLI + IU1, 5, 5, 0, 0, 0, // PC_MULLW + IU2, 1, 1, 0, 0, 0, // PC_NEG + IU2, 1, 1, 0, 0, 0, // PC_SUBF + IU2, 1, 1, 0, 0, 0, // PC_SUBFC + IU2, 1, 1, 0, 0, 0, // PC_SUBFE + IU2, 1, 1, 0, 0, 0, // PC_SUBFIC + IU2, 1, 1, 0, 0, 0, // PC_SUBFME + IU2, 1, 1, 0, 0, 0, // PC_SUBFZE + IU2, 3, 1, 0, 0, 0, // PC_CMPI + IU2, 3, 1, 0, 0, 0, // PC_CMP + IU2, 3, 1, 0, 0, 0, // PC_CMPLI + IU2, 3, 1, 0, 0, 0, // PC_CMPL + IU2, 1, 1, 0, 0, 0, // PC_ANDI + IU2, 1, 1, 0, 0, 0, // PC_ANDIS + IU2, 1, 1, 0, 0, 0, // PC_ORI + IU2, 1, 1, 0, 0, 0, // PC_ORIS + IU2, 1, 1, 0, 0, 0, // PC_XORI + IU2, 1, 1, 0, 0, 0, // PC_XORIS + IU2, 1, 1, 0, 0, 0, // PC_AND + IU2, 1, 1, 0, 0, 0, // PC_OR + IU2, 1, 1, 0, 0, 0, // PC_XOR + IU2, 1, 1, 0, 0, 0, // PC_NAND + IU2, 1, 1, 0, 0, 0, // PC_NOR + IU2, 1, 1, 0, 0, 0, // PC_EQV + IU2, 1, 1, 0, 0, 0, // PC_ANDC + IU2, 1, 1, 0, 0, 0, // PC_ORC + IU2, 1, 1, 0, 0, 0, // PC_EXTSB + IU2, 1, 1, 0, 0, 0, // PC_EXTSH + IU2, 1, 1, 0, 0, 0, // PC_CNTLZW + IU2, 1, 1, 0, 0, 0, // PC_RLWINM + IU2, 1, 1, 0, 0, 0, // PC_RLWNM + IU2, 1, 1, 0, 0, 0, // PC_RLWIMI + IU2, 1, 1, 0, 0, 0, // PC_SLW + IU2, 1, 1, 0, 0, 0, // PC_SRW + IU2, 1, 1, 0, 0, 0, // PC_SRAWI + IU2, 1, 1, 0, 0, 0, // PC_SRAW + SRU, 1, 1, 0, 0, 1, // PC_CRAND + SRU, 1, 1, 0, 0, 1, // PC_CRANDC + SRU, 1, 1, 0, 0, 1, // PC_CREQV + SRU, 1, 1, 0, 0, 1, // PC_CRNAND + SRU, 1, 1, 0, 0, 1, // PC_CRNOR + SRU, 1, 1, 0, 0, 1, // PC_CROR + SRU, 1, 1, 0, 0, 1, // PC_CRORC + SRU, 1, 1, 0, 0, 1, // PC_CRXOR + SRU, 1, 1, 0, 0, 1, // PC_MCRF + SRU, 2, 2, 0, 0, 1, // PC_MTXER + SRU, 2, 2, 0, 0, 1, // PC_MTCTR + SRU, 2, 2, 0, 0, 1, // PC_MTLR + SRU, 1, 1, 0, 0, 1, // PC_MTCRF + SRU, 1, 1, 0, 0, 0, // PC_MTMSR + SRU, 1, 1, 0, 0, 1, // PC_MTSPR + SRU, 1, 1, 0, 0, 1, // PC_MFMSR + SRU, 1, 1, 0, 0, 1, // PC_MFSPR + SRU, 1, 1, 0, 0, 1, // PC_MFXER + SRU, 1, 1, 0, 0, 1, // PC_MFCTR + SRU, 1, 1, 0, 0, 1, // PC_MFLR + SRU, 1, 1, 0, 0, 1, // PC_MFCR + FPU1, 3, 1, 1, 1, 0, // PC_MFFS + FPU1, 3, 1, 1, 1, 0, // PC_MTFSF + SRU, 1, 1, 0, 0, 1, // PC_EIEIO + SRU, 2, 2, 0, 0, 1, // PC_ISYNC + SRU, 3, 3, 0, 0, 1, // PC_SYNC + SRU, 1, 1, 0, 0, 1, // PC_RFI + IU2, 1, 1, 0, 0, 0, // PC_LI + IU2, 1, 1, 0, 0, 0, // PC_LIS + IU2, 1, 1, 0, 0, 0, // PC_MR + IU2, 1, 1, 0, 0, 0, // PC_NOP + IU2, 1, 1, 0, 0, 0, // PC_NOT + LSU1, 2, 1, 1, 0, 0, // PC_LFS + LSU1, 2, 1, 1, 0, 0, // PC_LFSU + LSU1, 2, 1, 1, 0, 0, // PC_LFSX + LSU1, 2, 1, 1, 0, 0, // PC_LFSUX + LSU1, 2, 1, 1, 0, 0, // PC_LFD + LSU1, 2, 1, 1, 0, 0, // PC_LFDU + LSU1, 2, 1, 1, 0, 0, // PC_LFDX + LSU1, 2, 1, 1, 0, 0, // PC_LFDUX + LSU1, 2, 1, 1, 0, 0, // PC_STFS + LSU1, 2, 1, 1, 0, 0, // PC_STFSU + LSU1, 2, 1, 1, 0, 0, // PC_STFSX + LSU1, 2, 1, 1, 0, 0, // PC_STFSUX + LSU1, 2, 1, 1, 0, 0, // PC_STFD + LSU1, 2, 1, 1, 0, 0, // PC_STFDU + LSU1, 2, 1, 1, 0, 0, // PC_STFDX + LSU1, 2, 1, 1, 0, 0, // PC_STFDUX + FPU1, 3, 1, 1, 1, 0, // PC_FMR + FPU1, 3, 1, 1, 1, 0, // PC_FABS + FPU1, 3, 1, 1, 1, 0, // PC_FNEG + FPU1, 3, 1, 1, 1, 0, // PC_FNABS + FPU1, 3, 1, 1, 1, 0, // PC_FADD + FPU1, 3, 1, 1, 1, 0, // PC_FADDS + FPU1, 3, 1, 1, 1, 0, // PC_FSUB + FPU1, 3, 1, 1, 1, 0, // PC_FSUBS + FPU1, 4, 2, 1, 1, 0, // PC_FMUL + FPU1, 3, 1, 1, 1, 0, // PC_FMULS + FPU1, 31, 31, 0, 0, 0, // PC_FDIV + FPU1, 17, 17, 0, 0, 0, // PC_FDIVS + FPU1, 4, 2, 1, 1, 0, // PC_FMADD + FPU1, 3, 1, 1, 1, 0, // PC_FMADDS + FPU1, 4, 2, 1, 1, 0, // PC_FMSUB + FPU1, 3, 1, 1, 1, 0, // PC_FMSUBS + FPU1, 4, 2, 1, 1, 0, // PC_FNMADD + FPU1, 3, 1, 1, 1, 0, // PC_FNMADDS + FPU1, 4, 2, 1, 1, 0, // PC_FNMSUB + FPU1, 3, 1, 1, 1, 0, // PC_FNMSUBS + FPU1, 10, 10, 0, 0, 0, // PC_FRES + FPU1, 3, 1, 1, 1, 0, // PC_FRSQRTE + FPU1, 3, 1, 1, 1, 0, // PC_FSEL + FPU1, 3, 1, 1, 1, 0, // PC_FRSP + FPU1, 3, 1, 1, 1, 0, // PC_FCTIW + FPU1, 3, 1, 1, 1, 0, // PC_FCTIWZ + FPU1, 3, 1, 1, 1, 0, // PC_FCMPU + FPU1, 3, 1, 1, 1, 0, // PC_FCMPO + LSU1, 1, 1, 0, 0, 0, // PC_LWARX + LSU1, 1, 1, 0, 0, 0, // PC_LSWI + LSU1, 1, 1, 0, 0, 0, // PC_LSWX + LSU1, 1, 1, 0, 0, 0, // PC_STFIWX + LSU1, 1, 1, 0, 0, 0, // PC_STSWI + LSU1, 1, 1, 0, 0, 0, // PC_STSWX + LSU1, 1, 1, 0, 0, 0, // PC_STWCX + IU1, 1, 1, 0, 0, 1, // PC_ECIWX + IU1, 1, 1, 0, 0, 1, // PC_ECOWX + IU1, 1, 1, 0, 0, 0, // PC_DCBI + IU1, 1, 1, 0, 0, 0, // PC_ICBI + IU1, 1, 1, 0, 0, 0, // PC_MCRFS + IU1, 1, 1, 0, 0, 0, // PC_MCRXR + IU1, 1, 1, 0, 0, 0, // PC_MFTB + IU1, 1, 1, 0, 0, 0, // PC_MFSR + IU1, 1, 1, 0, 0, 0, // PC_MTSR + IU1, 1, 1, 0, 0, 0, // PC_MFSRIN + IU1, 1, 1, 0, 0, 0, // PC_MTSRIN + IU1, 1, 1, 0, 0, 0, // PC_MTFSB0 + IU1, 1, 1, 0, 0, 0, // PC_MTFSB1 + IU1, 1, 1, 0, 0, 0, // PC_MTFSFI + IU1, 1, 1, 0, 0, 1, // PC_SC + FPU1, 1, 1, 0, 0, 0, // PC_FSQRT + FPU1, 1, 1, 0, 0, 0, // PC_FSQRTS + IU1, 1, 1, 0, 0, 0, // PC_TLBIA + IU1, 1, 1, 0, 0, 0, // PC_TLBIE + IU1, 1, 1, 0, 0, 0, // PC_TLBLD + IU1, 1, 1, 0, 0, 0, // PC_TLBLI + IU1, 1, 1, 0, 0, 0, // PC_TLBSYNC + IU1, 1, 1, 0, 0, 1, // PC_TW + IU1, 1, 1, 0, 0, 1, // PC_TRAP + IU1, 1, 1, 0, 0, 1, // PC_TWI + IU1, 1, 1, 0, 0, 1, // PC_OPWORD + IU1, 1, 1, 0, 0, 0, // PC_MFROM + IU1, 1, 1, 0, 0, 1, // PC_DSA + IU1, 1, 1, 0, 0, 1, // PC_ESA + IU1, 0, 0, 0, 0, 0, // PC_DCCCI + IU1, 0, 0, 0, 0, 0, // PC_DCREAD + IU1, 0, 0, 0, 0, 0, // PC_ICBT + IU1, 0, 0, 0, 0, 0, // PC_ICCCI + IU1, 0, 0, 0, 0, 0, // PC_ICREAD + IU1, 0, 0, 0, 0, 0, // PC_RFCI + IU1, 0, 0, 0, 0, 0, // PC_TLBRE + IU1, 0, 0, 0, 0, 0, // PC_TLBSX + IU1, 0, 0, 0, 0, 0, // PC_TLBWE + IU1, 0, 0, 0, 0, 0, // PC_WRTEE + IU1, 0, 0, 0, 0, 0, // PC_WRTEEI + IU1, 0, 0, 0, 0, 0, // PC_MFDCR + IU1, 0, 0, 0, 0, 0, // PC_MTDCR + IU1, 0, 0, 0, 0, 0, // PC_DCBA + BPU, 0, 0, 0, 0, 0, // PC_DSS + BPU, 0, 0, 0, 0, 0, // PC_DSSALL + BPU, 0, 0, 0, 0, 0, // PC_DST + BPU, 0, 0, 0, 0, 0, // PC_DSTT + BPU, 0, 0, 0, 0, 0, // PC_DSTST + BPU, 0, 0, 0, 0, 0, // PC_DSTSTT + BPU, 0, 0, 0, 0, 0, // PC_LVEBX + BPU, 0, 0, 0, 0, 0, // PC_LVEHX + BPU, 0, 0, 0, 0, 0, // PC_LVEWX + BPU, 0, 0, 0, 0, 0, // PC_LVSL + BPU, 0, 0, 0, 0, 0, // PC_LVSR + BPU, 0, 0, 0, 0, 0, // PC_LVX + BPU, 0, 0, 0, 0, 0, // PC_LVXL + BPU, 0, 0, 0, 0, 0, // PC_STVEBX + BPU, 0, 0, 0, 0, 0, // PC_STVEHX + BPU, 0, 0, 0, 0, 0, // PC_STVEWX + BPU, 0, 0, 0, 0, 0, // PC_STVX + BPU, 0, 0, 0, 0, 0, // PC_STVXL + BPU, 0, 0, 0, 0, 0, // PC_MFVSCR + BPU, 0, 0, 0, 0, 0, // PC_MTVSCR + BPU, 0, 0, 0, 0, 0, // PC_VADDCUW + BPU, 0, 0, 0, 0, 0, // PC_VADDFP + BPU, 0, 0, 0, 0, 0, // PC_VADDSBS + BPU, 0, 0, 0, 0, 0, // PC_VADDSHS + BPU, 0, 0, 0, 0, 0, // PC_VADDSWS + BPU, 0, 0, 0, 0, 0, // PC_VADDUBM + BPU, 0, 0, 0, 0, 0, // PC_VADDUBS + BPU, 0, 0, 0, 0, 0, // PC_VADDUHM + BPU, 0, 0, 0, 0, 0, // PC_VADDUHS + BPU, 0, 0, 0, 0, 0, // PC_VADDUWM + BPU, 0, 0, 0, 0, 0, // PC_VADDUWS + BPU, 0, 0, 0, 0, 0, // PC_VAND + BPU, 0, 0, 0, 0, 0, // PC_VANDC + BPU, 0, 0, 0, 0, 0, // PC_VAVGSB + BPU, 0, 0, 0, 0, 0, // PC_VAVGSH + BPU, 0, 0, 0, 0, 0, // PC_VAVGSW + BPU, 0, 0, 0, 0, 0, // PC_VAVGUB + BPU, 0, 0, 0, 0, 0, // PC_VAVGUH + BPU, 0, 0, 0, 0, 0, // PC_VAVGUW + BPU, 0, 0, 0, 0, 0, // PC_VCFSX + BPU, 0, 0, 0, 0, 0, // PC_VCFUX + BPU, 0, 0, 0, 0, 0, // PC_VCMPBFP + BPU, 0, 0, 0, 0, 0, // PC_VCMPEQFP + BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUB + BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUH + BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUW + BPU, 0, 0, 0, 0, 0, // PC_VCMPGEFP + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTFP + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSB + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSH + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSW + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUB + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUH + BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUW + BPU, 0, 0, 0, 0, 0, // PC_VCTSXS + BPU, 0, 0, 0, 0, 0, // PC_VCTUXS + BPU, 0, 0, 0, 0, 0, // PC_VEXPTEFP + BPU, 0, 0, 0, 0, 0, // PC_VLOGEFP + BPU, 0, 0, 0, 0, 0, // PC_VMAXFP + BPU, 0, 0, 0, 0, 0, // PC_VMAXSB + BPU, 0, 0, 0, 0, 0, // PC_VMAXSH + BPU, 0, 0, 0, 0, 0, // PC_VMAXSW + BPU, 0, 0, 0, 0, 0, // PC_VMAXUB + BPU, 0, 0, 0, 0, 0, // PC_VMAXUH + BPU, 0, 0, 0, 0, 0, // PC_VMAXUW + BPU, 0, 0, 0, 0, 0, // PC_VMINFP + BPU, 0, 0, 0, 0, 0, // PC_VMINSB + BPU, 0, 0, 0, 0, 0, // PC_VMINSH + BPU, 0, 0, 0, 0, 0, // PC_VMINSW + BPU, 0, 0, 0, 0, 0, // PC_VMINUB + BPU, 0, 0, 0, 0, 0, // PC_VMINUH + BPU, 0, 0, 0, 0, 0, // PC_VMINUW + BPU, 0, 0, 0, 0, 0, // PC_VMRGHB + BPU, 0, 0, 0, 0, 0, // PC_VMRGHH + BPU, 0, 0, 0, 0, 0, // PC_VMRGHW + BPU, 0, 0, 0, 0, 0, // PC_VMRGLB + BPU, 0, 0, 0, 0, 0, // PC_VMRGLH + BPU, 0, 0, 0, 0, 0, // PC_VMRGLW + BPU, 0, 0, 0, 0, 0, // PC_VMULESB + BPU, 0, 0, 0, 0, 0, // PC_VMULESH + BPU, 0, 0, 0, 0, 0, // PC_VMULEUB + BPU, 0, 0, 0, 0, 0, // PC_VMULEUH + BPU, 0, 0, 0, 0, 0, // PC_VMULOSB + BPU, 0, 0, 0, 0, 0, // PC_VMULOSH + BPU, 0, 0, 0, 0, 0, // PC_VMULOUB + BPU, 0, 0, 0, 0, 0, // PC_VMULOUH + BPU, 0, 0, 0, 0, 0, // PC_VNOR + BPU, 0, 0, 0, 0, 0, // PC_VOR + BPU, 0, 0, 0, 0, 0, // PC_VPKPX + BPU, 0, 0, 0, 0, 0, // PC_VPKSHSS + BPU, 0, 0, 0, 0, 0, // PC_VPKSHUS + BPU, 0, 0, 0, 0, 0, // PC_VPKSWSS + BPU, 0, 0, 0, 0, 0, // PC_VPKSWUS + BPU, 0, 0, 0, 0, 0, // PC_VPKUHUM + BPU, 0, 0, 0, 0, 0, // PC_VPKUHUS + BPU, 0, 0, 0, 0, 0, // PC_VPKUWUM + BPU, 0, 0, 0, 0, 0, // PC_VPKUWUS + BPU, 0, 0, 0, 0, 0, // PC_VREFP + BPU, 0, 0, 0, 0, 0, // PC_VRFIM + BPU, 0, 0, 0, 0, 0, // PC_VRFIN + BPU, 0, 0, 0, 0, 0, // PC_VRFIP + BPU, 0, 0, 0, 0, 0, // PC_VRFIZ + BPU, 0, 0, 0, 0, 0, // PC_VRLB + BPU, 0, 0, 0, 0, 0, // PC_VRLH + BPU, 0, 0, 0, 0, 0, // PC_VRLW + BPU, 0, 0, 0, 0, 0, // PC_VRSQRTEFP + BPU, 0, 0, 0, 0, 0, // PC_VSL + BPU, 0, 0, 0, 0, 0, // PC_VSLB + BPU, 0, 0, 0, 0, 0, // PC_VSLH + BPU, 0, 0, 0, 0, 0, // PC_VSLO + BPU, 0, 0, 0, 0, 0, // PC_VSLW + BPU, 0, 0, 0, 0, 0, // PC_VSPLTB + BPU, 0, 0, 0, 0, 0, // PC_VSPLTH + BPU, 0, 0, 0, 0, 0, // PC_VSPLTW + BPU, 0, 0, 0, 0, 0, // PC_VSPLTISB + BPU, 0, 0, 0, 0, 0, // PC_VSPLTISH + BPU, 0, 0, 0, 0, 0, // PC_VSPLTISW + BPU, 0, 0, 0, 0, 0, // PC_VSR + BPU, 0, 0, 0, 0, 0, // PC_VSRAB + BPU, 0, 0, 0, 0, 0, // PC_VSRAH + BPU, 0, 0, 0, 0, 0, // PC_VSRAW + BPU, 0, 0, 0, 0, 0, // PC_VSRB + BPU, 0, 0, 0, 0, 0, // PC_VSRH + BPU, 0, 0, 0, 0, 0, // PC_VSRO + BPU, 0, 0, 0, 0, 0, // PC_VSRW + BPU, 0, 0, 0, 0, 0, // PC_VSUBCUW + BPU, 0, 0, 0, 0, 0, // PC_VSUBFP + BPU, 0, 0, 0, 0, 0, // PC_VSUBSBS + BPU, 0, 0, 0, 0, 0, // PC_VSUBSHS + BPU, 0, 0, 0, 0, 0, // PC_VSUBSWS + BPU, 0, 0, 0, 0, 0, // PC_VSUBUBM + BPU, 0, 0, 0, 0, 0, // PC_VSUBUBS + BPU, 0, 0, 0, 0, 0, // PC_VSUBUHM + BPU, 0, 0, 0, 0, 0, // PC_VSUBUHS + BPU, 0, 0, 0, 0, 0, // PC_VSUBUWM + BPU, 0, 0, 0, 0, 0, // PC_VSUBUWS + BPU, 0, 0, 0, 0, 0, // PC_VSUMSWS + BPU, 0, 0, 0, 0, 0, // PC_VSUM2SWS + BPU, 0, 0, 0, 0, 0, // PC_VSUM4SBS + BPU, 0, 0, 0, 0, 0, // PC_VSUM4SHS + BPU, 0, 0, 0, 0, 0, // PC_VSUM4UBS + BPU, 0, 0, 0, 0, 0, // PC_VUPKHPX + BPU, 0, 0, 0, 0, 0, // PC_VUPKHSB + BPU, 0, 0, 0, 0, 0, // PC_VUPKHSH + BPU, 0, 0, 0, 0, 0, // PC_VUPKLPX + BPU, 0, 0, 0, 0, 0, // PC_VUPKLSB + BPU, 0, 0, 0, 0, 0, // PC_VUPKLSH + BPU, 0, 0, 0, 0, 0, // PC_VXOR + BPU, 0, 0, 0, 0, 0, // PC_VMADDFP + BPU, 0, 0, 0, 0, 0, // PC_VMHADDSHS + BPU, 0, 0, 0, 0, 0, // PC_VMHRADDSHS + BPU, 0, 0, 0, 0, 0, // PC_VMLADDUHM + BPU, 0, 0, 0, 0, 0, // PC_VMSUMMBM + BPU, 0, 0, 0, 0, 0, // PC_VMSUMSHM + BPU, 0, 0, 0, 0, 0, // PC_VMSUMSHS + BPU, 0, 0, 0, 0, 0, // PC_VMSUMUBM + BPU, 0, 0, 0, 0, 0, // PC_VMSUMUHM + BPU, 0, 0, 0, 0, 0, // PC_VMSUMUHS + BPU, 0, 0, 0, 0, 0, // PC_VNMSUBFP + BPU, 0, 0, 0, 0, 0, // PC_VPERM + BPU, 0, 0, 0, 0, 0, // PC_VSEL + BPU, 0, 0, 0, 0, 0, // PC_VSLDOI + BPU, 0, 0, 0, 0, 0, // PC_VMR + BPU, 0, 0, 0, 0, 0, // PC_VMRP + BPU, 0, 0, 0, 0, 0, // PC_SLE + BPU, 0, 0, 0, 0, 0, // PC_SLEQ + BPU, 0, 0, 0, 0, 0, // PC_SLIQ + BPU, 0, 0, 0, 0, 0, // PC_SLLIQ + BPU, 0, 0, 0, 0, 0, // PC_SLLQ + BPU, 0, 0, 0, 0, 0, // PC_SLQ + BPU, 0, 0, 0, 0, 0, // PC_SRAIQ + BPU, 0, 0, 0, 0, 0, // PC_SRAQ + BPU, 0, 0, 0, 0, 0, // PC_SRE + BPU, 0, 0, 0, 0, 0, // PC_SREA + BPU, 0, 0, 0, 0, 0, // PC_SREQ + BPU, 0, 0, 0, 0, 0, // PC_SRIQ + BPU, 0, 0, 0, 0, 0, // PC_SRLIQ + BPU, 0, 0, 0, 0, 0, // PC_SRLQ + BPU, 0, 0, 0, 0, 0, // PC_SRQ + BPU, 0, 0, 0, 0, 0, // PC_MASKG + BPU, 0, 0, 0, 0, 0, // PC_MASKIR + BPU, 0, 0, 0, 0, 0, // PC_LSCBX + BPU, 0, 0, 0, 0, 0, // PC_DIV + BPU, 0, 0, 0, 0, 0, // PC_DIVS + BPU, 0, 0, 0, 0, 0, // PC_DOZ + BPU, 0, 0, 0, 0, 0, // PC_MUL + BPU, 0, 0, 0, 0, 0, // PC_NABS + BPU, 0, 0, 0, 0, 0, // PC_ABS + BPU, 0, 0, 0, 0, 0, // PC_CLCS + BPU, 0, 0, 0, 0, 0, // PC_DOZI + BPU, 0, 0, 0, 0, 0, // PC_RLMI + BPU, 0, 0, 0, 0, 0, // PC_RRIB +}; + +static void advance(int firstStage, int oldStage, int newStage) { + PCode *instr = pipeline[oldStage].instr; + int cycles = instruction_timing[instr->op].cycles[newStage - firstStage]; + pipeline[newStage].instr = instr; + pipeline[newStage].remaining = cycles; + pipeline[oldStage].instr = NULL; +} + +static void assign_completion_buffer(PCode *instr) { + completionbuffers.used++; + completionbuffers.free--; + completionbuffers.entries[completionbuffers.nextFreeSlot].instr = instr; + completionbuffers.entries[completionbuffers.nextFreeSlot].completed = 0; + completionbuffers.nextFreeSlot = (completionbuffers.nextFreeSlot + 1) % MaxEntries; +} + +static void complete_instruction(int stage) { + PCode *instr = pipeline[stage].instr; + int buf = 0; + while (buf < MaxEntries && completionbuffers.entries[buf].instr != instr) + buf++; + + completionbuffers.entries[buf].completed = 1; + pipeline[stage].instr = NULL; + + if (stage == IU1) + iu1_completed_instruction = instr; + else if (stage == IU2) + iu2_completed_instruction = instr; +} + +static void retire_instruction(void) { + completionbuffers.entries[completionbuffers.nextToRetire].instr = NULL; + completionbuffers.used--; + completionbuffers.free++; + completionbuffers.nextToRetire = (completionbuffers.nextToRetire + 1) % MaxEntries; +} + +static int latency(PCode *instr) { + int cycles = instruction_timing[instr->op].latency; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + cycles += 2; + if (instr->op == PC_LMW || instr->op == PC_STMW) + cycles += instr->argCount - 2; + return cycles; +} + +static void initialize(void) { + int stage; + int i; + + for (stage = 0; stage < NumStages; stage++) + pipeline[stage].instr = NULL; + + completionbuffers.free = MaxEntries; + completionbuffers.used = 0; + completionbuffers.nextToRetire = 0; + completionbuffers.nextFreeSlot = 0; + for (i = 0; i < MaxEntries; i++) + completionbuffers.entries[i].instr = NULL; + + iu1_completed_instruction = NULL; + iu2_completed_instruction = NULL; +} + +static int can_issue(PCode *instr) { + int stage; + + if (completionbuffers.free == 0) + return 0; + + stage = instruction_timing[instr->op].stage; + + if (stage == IU2) { + PCode *check; + int isClear1 = !pipeline[IU1].instr; + int isClear2 = !pipeline[IU2].instr; + if (!isClear1 && !isClear2) + return 0; + if (isClear1 && isClear2) + return 1; + + if (isClear1) + check = pipeline[IU2].instr; + else + check = pipeline[IU1].instr; + + if (is_dependent(instr, check, RegClass_GPR)) + return 0; + if (is_dependent(instr, iu1_completed_instruction, RegClass_GPR)) + return 0; + if (is_dependent(instr, iu2_completed_instruction, RegClass_GPR)) + return 0; + } else { + if (pipeline[stage].instr) + return 0; + } + + if ((instr->flags & fIsWrite) && pipeline[LSU2].instr && (pipeline[LSU2].instr->flags & fIsWrite)) + return 0; + + return 1; +} + +static void issue(PCode *instr) { + int stage = instruction_timing[instr->op].stage; + int cycles = instruction_timing[instr->op].cycles[0]; + assign_completion_buffer(instr); + if (stage == IU2 && !pipeline[IU1].instr) + stage = IU1; + pipeline[stage].instr = instr; + pipeline[stage].remaining = cycles; +} + +static void advance_clock(void) { + int stage; + + iu1_completed_instruction = NULL; + iu2_completed_instruction = NULL; + + for (stage = 0; stage < NumStages; stage++) { + if (pipeline[stage].instr && pipeline[stage].remaining) + --pipeline[stage].remaining; + } + + if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { + retire_instruction(); + if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { + retire_instruction(); + } + } + + if (pipeline[IU1].instr && pipeline[IU1].remaining == 0) + complete_instruction(IU1); + if (pipeline[LSU2].instr && pipeline[LSU2].remaining == 0) + complete_instruction(LSU2); + if (pipeline[FPU3].instr && pipeline[FPU3].remaining == 0) + complete_instruction(FPU3); + if (pipeline[SRU].instr && pipeline[SRU].remaining == 0) + complete_instruction(SRU); + if (pipeline[BPU].instr && pipeline[BPU].remaining == 0) + complete_instruction(BPU); + if (pipeline[IU2].instr && pipeline[IU2].remaining == 0) + complete_instruction(IU2); + + if ( + pipeline[FPU1].instr && + pipeline[FPU1].remaining == 0 && + (pipeline[FPU1].instr->op == PC_FDIV || pipeline[FPU1].instr->op == PC_FDIVS) + ) + complete_instruction(FPU1); + + if (pipeline[FPU2].instr && pipeline[FPU2].remaining == 0 && !pipeline[FPU3].instr) + advance(FPU1, FPU2, FPU3); + if (pipeline[FPU1].instr && pipeline[FPU1].remaining == 0 && !pipeline[FPU2].instr) + advance(FPU1, FPU1, FPU2); + + if (pipeline[LSU1].instr && pipeline[LSU1].remaining == 0 && !pipeline[LSU2].instr) + advance(LSU1, LSU1, LSU2); +} + +static int serializes(PCode *instr) { + return instruction_timing[instr->op].serializes; +} + +MachineInfo machine750 = { + 2, + 1, + 0, + &latency, + &initialize, + &can_issue, + &issue, + &advance_clock, + &serializes, + &default_uses_vpermute_unit +}; diff --git a/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation821.c b/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation821.c new file mode 100644 index 0000000..bbf0509 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulation821.c @@ -0,0 +1,615 @@ +#include "compiler/Scheduler.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" + +// https://www.nxp.com/docs/en/user-guide/MPC821UM.pdf + +typedef enum Stage { + BranchUnit, + Stage1, + Stage2, + LSU1, + LSU2, + CRUnit, + NumStages, + Stage7 +} Stage; + +static struct { + // the instruction currently in this pipeline stage + PCode *instr; + + // how many cycles are left for this instruction to finish + int remaining; +} pipeline[NumStages]; + +enum { + MaxEntries = 6 +}; + +static struct { + // how many entries remain unused in the queue + unsigned int free; + + // how many entries are currently used in the queue + unsigned int used; + + // the index of the next instruction that will be retired + unsigned int nextToRetire; + + // the index of the next free slot that will be used when an instruction is dispatched + unsigned int nextFreeSlot; + + // circular array of entries in the completion queue + struct { + PCode *instr; + int completed; + } entries[MaxEntries]; +} completionbuffers; + +static struct { + // the initial stage for this instruction + Stage stage; + + // the total amount of cycles required by this instruction + char latency; + + // how long it takes to finish each stage + char cycles[3]; + + // does this instruction serialise? + char serializes; +} instruction_timing[OPCODE_MAX] = { + BranchUnit, 0, 0, 0, 0, 0, // PC_B + BranchUnit, 0, 0, 0, 0, 0, // PC_BL + BranchUnit, 0, 0, 0, 0, 0, // PC_BC + BranchUnit, 0, 0, 0, 0, 0, // PC_BCLR + BranchUnit, 0, 0, 0, 0, 0, // PC_BCCTR + BranchUnit, 0, 0, 0, 0, 0, // PC_BT + BranchUnit, 0, 0, 0, 0, 0, // PC_BTLR + BranchUnit, 0, 0, 0, 0, 0, // PC_BTCTR + BranchUnit, 0, 0, 0, 0, 0, // PC_BF + BranchUnit, 0, 0, 0, 0, 0, // PC_BFLR + BranchUnit, 0, 0, 0, 0, 0, // PC_BFCTR + BranchUnit, 0, 0, 0, 0, 0, // PC_BDNZ + BranchUnit, 0, 0, 0, 0, 0, // PC_BDNZT + BranchUnit, 0, 0, 0, 0, 0, // PC_BDNZF + BranchUnit, 0, 0, 0, 0, 0, // PC_BDZ + BranchUnit, 0, 0, 0, 0, 0, // PC_BDZT + BranchUnit, 0, 0, 0, 0, 0, // PC_BDZF + BranchUnit, 0, 0, 0, 0, 0, // PC_BLR + BranchUnit, 0, 0, 0, 0, 0, // PC_BCTR + BranchUnit, 0, 0, 0, 0, 0, // PC_BCTRL + BranchUnit, 0, 0, 0, 0, 0, // PC_BLRL + BranchUnit, 0, 0, 0, 0, 0, // PC_LBZ + LSU1, 2, 1, 1, 0, 0, // PC_LBZU + LSU1, 2, 1, 1, 0, 0, // PC_LBZX + LSU1, 2, 1, 1, 0, 0, // PC_LBZUX + LSU1, 2, 1, 1, 0, 0, // PC_LHZ + LSU1, 2, 1, 1, 0, 0, // PC_LHZU + LSU1, 2, 1, 1, 0, 0, // PC_LHZX + LSU1, 2, 1, 1, 0, 0, // PC_LHZUX + LSU1, 2, 1, 1, 0, 0, // PC_LHA + LSU1, 2, 1, 1, 0, 0, // PC_LHAU + LSU1, 2, 1, 1, 0, 0, // PC_LHAX + LSU1, 2, 1, 1, 0, 0, // PC_LHAUX + LSU1, 2, 1, 1, 0, 0, // PC_LHBRX + LSU1, 2, 1, 1, 0, 0, // PC_LWZ + LSU1, 2, 1, 1, 0, 0, // PC_LWZU + LSU1, 2, 1, 1, 0, 0, // PC_LWZX + LSU1, 2, 1, 1, 0, 0, // PC_LWZUX + LSU1, 2, 1, 1, 0, 0, // PC_LWBRX + LSU1, 2, 1, 1, 0, 0, // PC_LMW + LSU1, 2, 1, 1, 0, 0, // PC_STB + LSU1, 2, 1, 1, 0, 0, // PC_STBU + LSU1, 2, 1, 1, 0, 0, // PC_STBX + LSU1, 2, 1, 1, 0, 0, // PC_STBUX + LSU1, 2, 1, 1, 0, 0, // PC_STH + LSU1, 2, 1, 1, 0, 0, // PC_STHU + LSU1, 2, 1, 1, 0, 0, // PC_STHX + LSU1, 2, 1, 1, 0, 0, // PC_STHUX + LSU1, 2, 1, 1, 0, 0, // PC_STHBRX + LSU1, 2, 1, 1, 0, 0, // PC_STW + LSU1, 2, 1, 1, 0, 0, // PC_STWU + LSU1, 2, 1, 1, 0, 0, // PC_STWX + LSU1, 2, 1, 1, 0, 0, // PC_STWUX + LSU1, 2, 1, 1, 0, 0, // PC_STWBRX + LSU1, 2, 1, 1, 0, 0, // PC_STMW + LSU1, 2, 1, 1, 0, 0, // PC_DCBF + LSU1, 2, 1, 1, 0, 0, // PC_DCBST + LSU1, 2, 1, 1, 0, 0, // PC_DCBT + LSU1, 2, 1, 1, 0, 0, // PC_DCBTST + LSU1, 2, 1, 1, 0, 0, // PC_DCBZ + LSU1, 2, 1, 1, 0, 0, // PC_ADD + Stage1, 1, 1, 0, 0, 0, // PC_ADDC + Stage1, 1, 1, 0, 0, 0, // PC_ADDE + Stage1, 1, 1, 0, 0, 0, // PC_ADDI + Stage1, 1, 1, 0, 0, 0, // PC_ADDIC + Stage1, 1, 1, 0, 0, 0, // PC_ADDICR + Stage1, 1, 1, 0, 0, 0, // PC_ADDIS + Stage1, 1, 1, 0, 0, 0, // PC_ADDME + Stage1, 1, 1, 0, 0, 0, // PC_ADDZE + Stage1, 1, 1, 0, 0, 0, // PC_DIVW + Stage1, 37, 37, 0, 0, 0, // PC_DIVWU + Stage1, 37, 37, 0, 0, 0, // PC_MULHW + Stage1, 5, 5, 0, 0, 0, // PC_MULHWU + Stage1, 5, 5, 0, 0, 0, // PC_MULLI + Stage1, 3, 3, 0, 0, 0, // PC_MULLW + Stage1, 5, 5, 0, 0, 0, // PC_NEG + Stage1, 1, 1, 0, 0, 0, // PC_SUBF + Stage1, 1, 1, 0, 0, 0, // PC_SUBFC + Stage1, 1, 1, 0, 0, 0, // PC_SUBFE + Stage1, 1, 1, 0, 0, 0, // PC_SUBFIC + Stage1, 1, 1, 0, 0, 0, // PC_SUBFME + Stage1, 1, 1, 0, 0, 0, // PC_SUBFZE + Stage1, 1, 1, 0, 0, 0, // PC_CMPI + Stage1, 3, 1, 0, 0, 0, // PC_CMP + Stage1, 3, 1, 0, 0, 0, // PC_CMPLI + Stage1, 3, 1, 0, 0, 0, // PC_CMPL + Stage1, 3, 1, 0, 0, 0, // PC_ANDI + Stage1, 1, 1, 0, 0, 0, // PC_ANDIS + Stage1, 1, 1, 0, 0, 0, // PC_ORI + Stage1, 1, 1, 0, 0, 0, // PC_ORIS + Stage1, 1, 1, 0, 0, 0, // PC_XORI + Stage1, 1, 1, 0, 0, 0, // PC_XORIS + Stage1, 1, 1, 0, 0, 0, // PC_AND + Stage1, 1, 1, 0, 0, 0, // PC_OR + Stage1, 1, 1, 0, 0, 0, // PC_XOR + Stage1, 1, 1, 0, 0, 0, // PC_NAND + Stage1, 1, 1, 0, 0, 0, // PC_NOR + Stage1, 1, 1, 0, 0, 0, // PC_EQV + Stage1, 1, 1, 0, 0, 0, // PC_ANDC + Stage1, 1, 1, 0, 0, 0, // PC_ORC + Stage1, 1, 1, 0, 0, 0, // PC_EXTSB + Stage1, 1, 1, 0, 0, 0, // PC_EXTSH + Stage1, 1, 1, 0, 0, 0, // PC_CNTLZW + Stage1, 1, 1, 0, 0, 0, // PC_RLWINM + Stage1, 1, 1, 0, 0, 0, // PC_RLWNM + Stage1, 1, 1, 0, 0, 0, // PC_RLWIMI + Stage1, 1, 1, 0, 0, 0, // PC_SLW + Stage1, 1, 1, 0, 0, 0, // PC_SRW + Stage1, 1, 1, 0, 0, 0, // PC_SRAWI + Stage1, 1, 1, 0, 0, 0, // PC_SRAW + Stage1, 1, 1, 0, 0, 0, // PC_CRAND + CRUnit, 1, 1, 0, 0, 0, // PC_CRANDC + CRUnit, 1, 1, 0, 0, 0, // PC_CREQV + CRUnit, 1, 1, 0, 0, 0, // PC_CRNAND + CRUnit, 1, 1, 0, 0, 0, // PC_CRNOR + CRUnit, 1, 1, 0, 0, 0, // PC_CROR + CRUnit, 1, 1, 0, 0, 0, // PC_CRORC + CRUnit, 1, 1, 0, 0, 0, // PC_CRXOR + CRUnit, 1, 1, 0, 0, 0, // PC_MCRF + CRUnit, 1, 1, 0, 0, 0, // PC_MTXER + Stage1, 1, 1, 0, 0, 0, // PC_MTCTR + BranchUnit, 2, 2, 0, 0, 0, // PC_MTLR + BranchUnit, 2, 2, 0, 0, 0, // PC_MTCRF + Stage1, 1, 1, 0, 0, 0, // PC_MTMSR + Stage1, 1, 1, 0, 0, 0, // PC_MTSPR + Stage1, 1, 1, 0, 0, 0, // PC_MFMSR + Stage1, 1, 1, 0, 0, 0, // PC_MFSPR + Stage1, 1, 1, 0, 0, 0, // PC_MFXER + Stage7, 3, 1, 1, 1, 0, // PC_MFCTR + Stage7, 3, 1, 1, 1, 0, // PC_MFLR + Stage1, 1, 1, 0, 0, 0, // PC_MFCR + Stage1, 1, 1, 0, 0, 0, // PC_MFFS + Stage1, 1, 1, 0, 0, 0, // PC_MTFSF + Stage1, 1, 1, 0, 0, 0, // PC_EIEIO + Stage1, 1, 1, 0, 0, 0, // PC_ISYNC + Stage1, 1, 1, 0, 0, 0, // PC_SYNC + Stage1, 1, 1, 0, 0, 0, // PC_RFI + Stage1, 1, 1, 0, 0, 0, // PC_LI + LSU1, 2, 1, 1, 0, 0, // PC_LIS + LSU1, 2, 1, 1, 0, 0, // PC_MR + LSU1, 2, 1, 1, 0, 0, // PC_NOP + LSU1, 2, 1, 1, 0, 0, // PC_NOT + LSU1, 2, 1, 1, 0, 0, // PC_LFS + LSU1, 2, 1, 1, 0, 0, // PC_LFSU + LSU1, 2, 1, 1, 0, 0, // PC_LFSX + LSU1, 2, 1, 1, 0, 0, // PC_LFSUX + LSU1, 2, 1, 1, 0, 0, // PC_LFD + LSU1, 2, 1, 1, 0, 0, // PC_LFDU + LSU1, 2, 1, 1, 0, 0, // PC_LFDX + LSU1, 2, 1, 1, 0, 0, // PC_LFDUX + LSU1, 2, 1, 1, 0, 0, // PC_STFS + LSU1, 2, 1, 1, 0, 0, // PC_STFSU + LSU1, 2, 1, 1, 0, 0, // PC_STFSX + LSU1, 2, 1, 1, 0, 0, // PC_STFSUX + Stage7, 3, 1, 1, 1, 0, // PC_STFD + Stage7, 3, 1, 1, 1, 0, // PC_STFDU + Stage7, 3, 1, 1, 1, 0, // PC_STFDX + Stage7, 3, 1, 1, 1, 0, // PC_STFDUX + Stage7, 3, 1, 1, 1, 0, // PC_FMR + Stage7, 3, 1, 1, 1, 0, // PC_FABS + Stage7, 3, 1, 1, 1, 0, // PC_FNEG + Stage7, 3, 1, 1, 1, 0, // PC_FNABS + Stage7, 4, 2, 1, 1, 0, // PC_FADD + Stage7, 3, 1, 1, 1, 0, // PC_FADDS + Stage7, 33, 33, 0, 0, 0, // PC_FSUB + Stage7, 18, 18, 0, 0, 0, // PC_FSUBS + Stage7, 4, 2, 1, 1, 0, // PC_FMUL + Stage7, 3, 1, 1, 1, 0, // PC_FMULS + Stage7, 4, 2, 1, 1, 0, // PC_FDIV + Stage7, 3, 1, 1, 1, 0, // PC_FDIVS + Stage7, 4, 2, 1, 1, 0, // PC_FMADD + Stage7, 3, 1, 1, 1, 0, // PC_FMADDS + Stage7, 4, 2, 1, 1, 0, // PC_FMSUB + Stage7, 3, 1, 1, 1, 0, // PC_FMSUBS + Stage7, 18, 18, 0, 0, 0, // PC_FNMADD + Stage7, 3, 1, 1, 1, 0, // PC_FNMADDS + Stage7, 3, 1, 1, 1, 0, // PC_FNMSUB + Stage7, 3, 1, 1, 1, 0, // PC_FNMSUBS + Stage7, 3, 1, 1, 1, 0, // PC_FRES + Stage7, 3, 1, 1, 1, 0, // PC_FRSQRTE + Stage7, 5, 1, 1, 1, 0, // PC_FSEL + Stage7, 5, 1, 1, 1, 0, // PC_FRSP + LSU1, 1, 0, 0, 0, 0, // PC_FCTIW + LSU1, 1, 0, 0, 0, 0, // PC_FCTIWZ + LSU1, 1, 0, 0, 0, 0, // PC_FCMPU + LSU1, 1, 0, 0, 0, 0, // PC_FCMPO + LSU1, 1, 0, 0, 0, 0, // PC_LWARX + LSU1, 1, 0, 0, 0, 0, // PC_LSWI + LSU1, 1, 0, 0, 0, 0, // PC_LSWX + Stage1, 1, 0, 0, 0, 0, // PC_STFIWX + Stage1, 1, 0, 0, 0, 0, // PC_STSWI + Stage1, 1, 0, 0, 0, 0, // PC_STSWX + Stage1, 1, 0, 0, 0, 0, // PC_STWCX + Stage1, 1, 0, 0, 0, 0, // PC_ECIWX + Stage1, 1, 0, 0, 0, 0, // PC_ECOWX + Stage1, 1, 0, 0, 0, 0, // PC_DCBI + Stage1, 1, 0, 0, 0, 0, // PC_ICBI + Stage1, 1, 0, 0, 0, 0, // PC_MCRFS + Stage1, 1, 0, 0, 0, 0, // PC_MCRXR + Stage1, 1, 0, 0, 0, 0, // PC_MFTB + Stage1, 1, 0, 0, 0, 0, // PC_MFSR + Stage1, 1, 0, 0, 0, 0, // PC_MTSR + Stage1, 1, 0, 0, 0, 0, // PC_MFSRIN + Stage1, 1, 0, 0, 0, 0, // PC_MTSRIN + Stage1, 1, 0, 0, 0, 0, // PC_MTFSB0 + Stage1, 1, 0, 0, 0, 0, // PC_MTFSB1 + Stage1, 1, 0, 0, 0, 0, // PC_MTFSFI + Stage1, 1, 0, 0, 0, 1, // PC_SC + Stage1, 1, 0, 0, 0, 1, // PC_FSQRT + Stage1, 1, 0, 0, 0, 0, // PC_FSQRTS + Stage1, 1, 0, 0, 0, 0, // PC_TLBIA + Stage1, 1, 0, 0, 0, 0, // PC_TLBIE + Stage1, 1, 0, 0, 0, 0, // PC_TLBLD + Stage1, 1, 0, 0, 0, 0, // PC_TLBLI + Stage1, 1, 0, 0, 0, 0, // PC_TLBSYNC + Stage1, 1, 0, 0, 0, 0, // PC_TW + Stage1, 1, 0, 0, 0, 1, // PC_TRAP + Stage1, 1, 0, 0, 0, 1, // PC_TWI + Stage1, 1, 0, 0, 0, 1, // PC_OPWORD + Stage1, 1, 0, 0, 0, 1, // PC_MFROM + Stage1, 1, 0, 0, 0, 0, // PC_DSA + Stage1, 1, 0, 0, 0, 0, // PC_ESA + Stage1, 1, 0, 0, 0, 0, // PC_DCCCI + Stage1, 0, 0, 0, 0, 0, // PC_DCREAD + Stage1, 0, 0, 0, 0, 0, // PC_ICBT + Stage1, 0, 0, 0, 0, 0, // PC_ICCCI + Stage1, 0, 0, 0, 0, 0, // PC_ICREAD + Stage1, 0, 0, 0, 0, 0, // PC_RFCI + Stage1, 0, 0, 0, 0, 0, // PC_TLBRE + Stage1, 0, 0, 0, 0, 0, // PC_TLBSX + Stage1, 0, 0, 0, 0, 0, // PC_TLBWE + Stage1, 0, 0, 0, 0, 0, // PC_WRTEE + Stage1, 0, 0, 0, 0, 0, // PC_WRTEEI + Stage1, 0, 0, 0, 0, 0, // PC_MFDCR + Stage1, 0, 0, 0, 0, 0, // PC_MTDCR + Stage1, 0, 0, 0, 0, 0, // PC_DCBA + Stage1, 0, 0, 0, 0, 0, // PC_DSS + BranchUnit, 0, 0, 0, 0, 0, // PC_DSSALL + BranchUnit, 0, 0, 0, 0, 0, // PC_DST + BranchUnit, 0, 0, 0, 0, 0, // PC_DSTT + BranchUnit, 0, 0, 0, 0, 0, // PC_DSTST + BranchUnit, 0, 0, 0, 0, 0, // PC_DSTSTT + BranchUnit, 0, 0, 0, 0, 0, // PC_LVEBX + BranchUnit, 0, 0, 0, 0, 0, // PC_LVEHX + BranchUnit, 0, 0, 0, 0, 0, // PC_LVEWX + BranchUnit, 0, 0, 0, 0, 0, // PC_LVSL + BranchUnit, 0, 0, 0, 0, 0, // PC_LVSR + BranchUnit, 0, 0, 0, 0, 0, // PC_LVX + BranchUnit, 0, 0, 0, 0, 0, // PC_LVXL + BranchUnit, 0, 0, 0, 0, 0, // PC_STVEBX + BranchUnit, 0, 0, 0, 0, 0, // PC_STVEHX + BranchUnit, 0, 0, 0, 0, 0, // PC_STVEWX + BranchUnit, 0, 0, 0, 0, 0, // PC_STVX + BranchUnit, 0, 0, 0, 0, 0, // PC_STVXL + BranchUnit, 0, 0, 0, 0, 0, // PC_MFVSCR + BranchUnit, 0, 0, 0, 0, 0, // PC_MTVSCR + BranchUnit, 0, 0, 0, 0, 0, // PC_VADDCUW + BranchUnit, 0, 0, 0, 0, 0, // PC_VADDFP + BranchUnit, 0, 0, 0, 0, 0, // PC_VADDSBS + BranchUnit, 0, 0, 0, 0, 0, // PC_VADDSHS + BranchUnit, 0, 0, 0, 0, 0, // PC_VADDSWS + BranchUnit, 0, 0, 0, 0, 0, // PC_VADDUBM + BranchUnit, 0, 0, 0, 0, 0, // PC_VADDUBS + BranchUnit, 0, 0, 0, 0, 0, // PC_VADDUHM + BranchUnit, 0, 0, 0, 0, 0, // PC_VADDUHS + BranchUnit, 0, 0, 0, 0, 0, // PC_VADDUWM + BranchUnit, 0, 0, 0, 0, 0, // PC_VADDUWS + BranchUnit, 0, 0, 0, 0, 0, // PC_VAND + BranchUnit, 0, 0, 0, 0, 0, // PC_VANDC + BranchUnit, 0, 0, 0, 0, 0, // PC_VAVGSB + BranchUnit, 0, 0, 0, 0, 0, // PC_VAVGSH + BranchUnit, 0, 0, 0, 0, 0, // PC_VAVGSW + BranchUnit, 0, 0, 0, 0, 0, // PC_VAVGUB + BranchUnit, 0, 0, 0, 0, 0, // PC_VAVGUH + BranchUnit, 0, 0, 0, 0, 0, // PC_VAVGUW + BranchUnit, 0, 0, 0, 0, 0, // PC_VCFSX + BranchUnit, 0, 0, 0, 0, 0, // PC_VCFUX + BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPBFP + BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPEQFP + BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPEQUB + BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPEQUH + BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPEQUW + BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPGEFP + BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPGTFP + BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPGTSB + BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPGTSH + BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPGTSW + BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPGTUB + BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPGTUH + BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPGTUW + BranchUnit, 0, 0, 0, 0, 0, // PC_VCTSXS + BranchUnit, 0, 0, 0, 0, 0, // PC_VCTUXS + BranchUnit, 0, 0, 0, 0, 0, // PC_VEXPTEFP + BranchUnit, 0, 0, 0, 0, 0, // PC_VLOGEFP + BranchUnit, 0, 0, 0, 0, 0, // PC_VMAXFP + BranchUnit, 0, 0, 0, 0, 0, // PC_VMAXSB + BranchUnit, 0, 0, 0, 0, 0, // PC_VMAXSH + BranchUnit, 0, 0, 0, 0, 0, // PC_VMAXSW + BranchUnit, 0, 0, 0, 0, 0, // PC_VMAXUB + BranchUnit, 0, 0, 0, 0, 0, // PC_VMAXUH + BranchUnit, 0, 0, 0, 0, 0, // PC_VMAXUW + BranchUnit, 0, 0, 0, 0, 0, // PC_VMINFP + BranchUnit, 0, 0, 0, 0, 0, // PC_VMINSB + BranchUnit, 0, 0, 0, 0, 0, // PC_VMINSH + BranchUnit, 0, 0, 0, 0, 0, // PC_VMINSW + BranchUnit, 0, 0, 0, 0, 0, // PC_VMINUB + BranchUnit, 0, 0, 0, 0, 0, // PC_VMINUH + BranchUnit, 0, 0, 0, 0, 0, // PC_VMINUW + BranchUnit, 0, 0, 0, 0, 0, // PC_VMRGHB + BranchUnit, 0, 0, 0, 0, 0, // PC_VMRGHH + BranchUnit, 0, 0, 0, 0, 0, // PC_VMRGHW + BranchUnit, 0, 0, 0, 0, 0, // PC_VMRGLB + BranchUnit, 0, 0, 0, 0, 0, // PC_VMRGLH + BranchUnit, 0, 0, 0, 0, 0, // PC_VMRGLW + BranchUnit, 0, 0, 0, 0, 0, // PC_VMULESB + BranchUnit, 0, 0, 0, 0, 0, // PC_VMULESH + BranchUnit, 0, 0, 0, 0, 0, // PC_VMULEUB + BranchUnit, 0, 0, 0, 0, 0, // PC_VMULEUH + BranchUnit, 0, 0, 0, 0, 0, // PC_VMULOSB + BranchUnit, 0, 0, 0, 0, 0, // PC_VMULOSH + BranchUnit, 0, 0, 0, 0, 0, // PC_VMULOUB + BranchUnit, 0, 0, 0, 0, 0, // PC_VMULOUH + BranchUnit, 0, 0, 0, 0, 0, // PC_VNOR + BranchUnit, 0, 0, 0, 0, 0, // PC_VOR + BranchUnit, 0, 0, 0, 0, 0, // PC_VPKPX + BranchUnit, 0, 0, 0, 0, 0, // PC_VPKSHSS + BranchUnit, 0, 0, 0, 0, 0, // PC_VPKSHUS + BranchUnit, 0, 0, 0, 0, 0, // PC_VPKSWSS + BranchUnit, 0, 0, 0, 0, 0, // PC_VPKSWUS + BranchUnit, 0, 0, 0, 0, 0, // PC_VPKUHUM + BranchUnit, 0, 0, 0, 0, 0, // PC_VPKUHUS + BranchUnit, 0, 0, 0, 0, 0, // PC_VPKUWUM + BranchUnit, 0, 0, 0, 0, 0, // PC_VPKUWUS + BranchUnit, 0, 0, 0, 0, 0, // PC_VREFP + BranchUnit, 0, 0, 0, 0, 0, // PC_VRFIM + BranchUnit, 0, 0, 0, 0, 0, // PC_VRFIN + BranchUnit, 0, 0, 0, 0, 0, // PC_VRFIP + BranchUnit, 0, 0, 0, 0, 0, // PC_VRFIZ + BranchUnit, 0, 0, 0, 0, 0, // PC_VRLB + BranchUnit, 0, 0, 0, 0, 0, // PC_VRLH + BranchUnit, 0, 0, 0, 0, 0, // PC_VRLW + BranchUnit, 0, 0, 0, 0, 0, // PC_VRSQRTEFP + BranchUnit, 0, 0, 0, 0, 0, // PC_VSL + BranchUnit, 0, 0, 0, 0, 0, // PC_VSLB + BranchUnit, 0, 0, 0, 0, 0, // PC_VSLH + BranchUnit, 0, 0, 0, 0, 0, // PC_VSLO + BranchUnit, 0, 0, 0, 0, 0, // PC_VSLW + BranchUnit, 0, 0, 0, 0, 0, // PC_VSPLTB + BranchUnit, 0, 0, 0, 0, 0, // PC_VSPLTH + BranchUnit, 0, 0, 0, 0, 0, // PC_VSPLTW + BranchUnit, 0, 0, 0, 0, 0, // PC_VSPLTISB + BranchUnit, 0, 0, 0, 0, 0, // PC_VSPLTISH + BranchUnit, 0, 0, 0, 0, 0, // PC_VSPLTISW + BranchUnit, 0, 0, 0, 0, 0, // PC_VSR + BranchUnit, 0, 0, 0, 0, 0, // PC_VSRAB + BranchUnit, 0, 0, 0, 0, 0, // PC_VSRAH + BranchUnit, 0, 0, 0, 0, 0, // PC_VSRAW + BranchUnit, 0, 0, 0, 0, 0, // PC_VSRB + BranchUnit, 0, 0, 0, 0, 0, // PC_VSRH + BranchUnit, 0, 0, 0, 0, 0, // PC_VSRO + BranchUnit, 0, 0, 0, 0, 0, // PC_VSRW + BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBCUW + BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBFP + BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBSBS + BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBSHS + BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBSWS + BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBUBM + BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBUBS + BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBUHM + BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBUHS + BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBUWM + BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBUWS + BranchUnit, 0, 0, 0, 0, 0, // PC_VSUMSWS + BranchUnit, 0, 0, 0, 0, 0, // PC_VSUM2SWS + BranchUnit, 0, 0, 0, 0, 0, // PC_VSUM4SBS + BranchUnit, 0, 0, 0, 0, 0, // PC_VSUM4SHS + BranchUnit, 0, 0, 0, 0, 0, // PC_VSUM4UBS + BranchUnit, 0, 0, 0, 0, 0, // PC_VUPKHPX + BranchUnit, 0, 0, 0, 0, 0, // PC_VUPKHSB + BranchUnit, 0, 0, 0, 0, 0, // PC_VUPKHSH + BranchUnit, 0, 0, 0, 0, 0, // PC_VUPKLPX + BranchUnit, 0, 0, 0, 0, 0, // PC_VUPKLSB + BranchUnit, 0, 0, 0, 0, 0, // PC_VUPKLSH + BranchUnit, 0, 0, 0, 0, 0, // PC_VXOR + BranchUnit, 0, 0, 0, 0, 0, // PC_VMADDFP + BranchUnit, 0, 0, 0, 0, 0, // PC_VMHADDSHS + BranchUnit, 0, 0, 0, 0, 0, // PC_VMHRADDSHS + BranchUnit, 0, 0, 0, 0, 0, // PC_VMLADDUHM + BranchUnit, 0, 0, 0, 0, 0, // PC_VMSUMMBM + BranchUnit, 0, 0, 0, 0, 0, // PC_VMSUMSHM + BranchUnit, 0, 0, 0, 0, 0, // PC_VMSUMSHS + BranchUnit, 0, 0, 0, 0, 0, // PC_VMSUMUBM + BranchUnit, 0, 0, 0, 0, 0, // PC_VMSUMUHM + BranchUnit, 0, 0, 0, 0, 0, // PC_VMSUMUHS + BranchUnit, 0, 0, 0, 0, 0, // PC_VNMSUBFP + BranchUnit, 0, 0, 0, 0, 0, // PC_VPERM + BranchUnit, 0, 0, 0, 0, 0, // PC_VSEL + BranchUnit, 0, 0, 0, 0, 0, // PC_VSLDOI + BranchUnit, 0, 0, 0, 0, 0, // PC_VMR + BranchUnit, 0, 0, 0, 0, 0, // PC_VMRP + BranchUnit, 0, 0, 0, 0, 0, // PC_SLE + BranchUnit, 0, 0, 0, 0, 0, // PC_SLEQ + BranchUnit, 0, 0, 0, 0, 0, // PC_SLIQ + BranchUnit, 0, 0, 0, 0, 0, // PC_SLLIQ + BranchUnit, 0, 0, 0, 0, 0, // PC_SLLQ + BranchUnit, 0, 0, 0, 0, 0, // PC_SLQ + BranchUnit, 0, 0, 0, 0, 0, // PC_SRAIQ + BranchUnit, 0, 0, 0, 0, 0, // PC_SRAQ + BranchUnit, 0, 0, 0, 0, 0, // PC_SRE + BranchUnit, 0, 0, 0, 0, 0, // PC_SREA + BranchUnit, 0, 0, 0, 0, 0, // PC_SREQ + BranchUnit, 0, 0, 0, 0, 0, // PC_SRIQ + BranchUnit, 0, 0, 0, 0, 0, // PC_SRLIQ + BranchUnit, 0, 0, 0, 0, 0, // PC_SRLQ + BranchUnit, 0, 0, 0, 0, 0, // PC_SRQ + BranchUnit, 0, 0, 0, 0, 0, // PC_MASKG + BranchUnit, 0, 0, 0, 0, 0, // PC_MASKIR + BranchUnit, 0, 0, 0, 0, 0, // PC_LSCBX + BranchUnit, 0, 0, 0, 0, 0, // PC_DIV + BranchUnit, 0, 0, 0, 0, 0, // PC_DIVS + BranchUnit, 0, 0, 0, 0, 0, // PC_DOZ + BranchUnit, 0, 0, 0, 0, 0, // PC_MUL + BranchUnit, 0, 0, 0, 0, 0, // PC_NABS + BranchUnit, 0, 0, 0, 0, 0, // PC_ABS + BranchUnit, 0, 0, 0, 0, 0, // PC_CLCS + BranchUnit, 0, 0, 0, 0, 0, // PC_DOZI + BranchUnit, 0, 0, 0, 0, 0, // PC_RLMI + BranchUnit, 0, 0, 0, 0, 0, // PC_RRIB +}; + +static void advance(int firstStage, int oldStage, int newStage) { + PCode *instr = pipeline[oldStage].instr; + int cycles = instruction_timing[instr->op].cycles[newStage - firstStage]; + pipeline[newStage].instr = instr; + pipeline[newStage].remaining = cycles; + pipeline[oldStage].instr = NULL; +} + +static void assign_completion_buffer(PCode *instr) { + completionbuffers.used++; + completionbuffers.free--; + completionbuffers.entries[completionbuffers.nextFreeSlot].instr = instr; + completionbuffers.entries[completionbuffers.nextFreeSlot].completed = 0; + completionbuffers.nextFreeSlot = (completionbuffers.nextFreeSlot + 1) % MaxEntries; +} + +static void complete_instruction(int stage) { + PCode *instr = pipeline[stage].instr; + int buf = 0; + while (buf < MaxEntries && completionbuffers.entries[buf].instr != instr) + buf++; + + completionbuffers.entries[buf].completed = 1; + pipeline[stage].instr = NULL; +} + +static void retire_instruction(void) { + completionbuffers.entries[completionbuffers.nextToRetire].instr = NULL; + completionbuffers.used--; + completionbuffers.free++; + completionbuffers.nextToRetire = (completionbuffers.nextToRetire + 1) % MaxEntries; +} + +static int latency(PCode *instr) { + int cycles = instruction_timing[instr->op].latency; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + cycles += 2; + if (instr->op == PC_LMW || instr->op == PC_STMW) + cycles += instr->argCount - 2; + return cycles; +} + +static void initialize(void) { + int stage; + int i; + + for (stage = 0; stage < NumStages; stage++) + pipeline[stage].instr = NULL; + + completionbuffers.free = MaxEntries; + completionbuffers.used = 0; + completionbuffers.nextToRetire = 0; + completionbuffers.nextFreeSlot = 0; + for (i = 0; i < MaxEntries; i++) + completionbuffers.entries[i].instr = NULL; +} + +static int can_issue(PCode *instr) { + int stage; + + if (completionbuffers.free == 0) + return 0; + + stage = instruction_timing[instr->op].stage; + if (pipeline[stage].instr) + return 0; + + if ((instr->flags & fIsWrite) && pipeline[LSU2].instr && (pipeline[LSU2].instr->flags & fIsWrite)) + return 0; + + return 1; +} + +static void issue(PCode *instr) { + int stage = instruction_timing[instr->op].stage; + int cycles = instruction_timing[instr->op].cycles[0]; + assign_completion_buffer(instr); + pipeline[stage].instr = instr; + pipeline[stage].remaining = cycles; +} + +static void advance_clock(void) { + int stage; + + for (stage = 0; stage < NumStages; stage++) { + if (pipeline[stage].instr && pipeline[stage].remaining) + --pipeline[stage].remaining; + } + + if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { + retire_instruction(); + if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { + retire_instruction(); + } + } + + if (pipeline[Stage1].instr && pipeline[Stage1].remaining == 0) + complete_instruction(Stage1); + if (pipeline[LSU2].instr && pipeline[LSU2].remaining == 0) + complete_instruction(LSU2); + if (pipeline[BranchUnit].instr && pipeline[BranchUnit].remaining == 0) + complete_instruction(BranchUnit); + + if (pipeline[LSU1].instr && pipeline[LSU1].remaining == 0 && !pipeline[LSU2].instr) + advance(LSU1, LSU1, LSU2); +} + +static int serializes(PCode *instr) { + return instruction_timing[instr->op].serializes; +} + +MachineInfo machine821 = { + 1, + 0, + 0, + &latency, + &initialize, + &can_issue, + &issue, + &advance_clock, + &serializes, + &default_uses_vpermute_unit +}; diff --git a/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulationAltiVec.c b/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulationAltiVec.c new file mode 100644 index 0000000..d261ee9 --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/Scheduler/MachineSimulationAltiVec.c @@ -0,0 +1,752 @@ +#include "compiler/Scheduler.h" +#include "compiler/CError.h" +#include "compiler/PCode.h" +#include "compiler/PCodeInfo.h" + +// https://www.nxp.com/docs/en/reference-manual/MPC7450UM.pdf + +typedef enum Stage { + BPU, // Branch Prediction Unit + + IU2_1, // Multiple-Cycle Integer Unit + IU2_2, + IU2_3, + + IU1a, // Single-Cycle Integer Unit + IU1b, // Single-Cycle Integer Unit + IU1c, // Single-Cycle Integer Unit + + LSU_1, // Load/Store Unit + LSU_2, + LSU_3, + LSU_4, + + FPU_1, // Floating-Point Unit + FPU_2, + FPU_3, + FPU_4, + + VIU1, // Vector Simple Integer Unit + + VPU_1, // Vector Permute Unit + VPU_2, + + VIU2_1, // Vector Complex Integer Unit + VIU2_2, + VIU2_3, + VIU2_4, + + VFPU_1, // Vector Floating-Point Unit + VFPU_2, + VFPU_3, + VFPU_4, + + NumStages +} Stage; + +static struct { + // the instruction currently in this pipeline stage + PCode *instr; + + // how many cycles are left for this instruction to finish + int remaining; +} pipeline_altivec[NumStages]; + +enum { + Queue0, + Queue1, + Queue2, + Queue3, + Queue4, + Queue5, + Queue6, + Queue7, + NumQueues +}; + +static int fetchqueues[NumQueues]; + +enum { + MaxEntries = 16 +}; + +static struct { + // how many entries remain unused in the queue + unsigned int free; + + // how many entries are currently used in the queue + unsigned int used; + + // the index of the next instruction that will be retired + unsigned int nextToRetire; + + // the index of the next free slot that will be used when an instruction is dispatched + unsigned int nextFreeSlot; + + // circular array of entries in the completion queue + struct { + PCode *instr; + int completed; + } entries[MaxEntries]; +} completionbuffers; + +static struct { + short index; + + // the initial stage for this instruction + Stage stage; + + // the total amount of cycles required by this instruction + char latency; + + // how long it takes to finish each stage + char cycles[4]; + + // does this instruction serialise? + char serializes; + + char unused; +} instruction_timing[] = { + 0, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_B + 1, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BL + 2, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BC + 3, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BCLR + 4, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BCCTR + 5, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BT + 6, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BTLR + 7, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BTCTR + 8, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BF + 9, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BFLR + 10, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BFCTR + 11, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDNZ + 12, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDNZT + 13, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDNZF + 14, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDZ + 15, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDZT + 16, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDZF + 17, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BLR + 18, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BCTR + 19, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BCTRL + 20, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BLRL + 21, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LBZ + 22, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LBZU + 23, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LBZX + 24, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LBZUX + 25, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHZ + 26, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHZU + 27, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHZX + 28, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHZUX + 29, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHA + 30, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHAU + 31, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHAX + 32, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHAUX + 33, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHBRX + 34, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LWZ + 35, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LWZU + 36, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LWZX + 37, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LWZUX + 38, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LWBRX + 39, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_LMW + 40, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STB + 41, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STBU + 42, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STBX + 43, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STBUX + 44, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STH + 45, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STHU + 46, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STHX + 47, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STHUX + 48, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STHBRX + 49, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STW + 50, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STWU + 51, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STWX + 52, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STWUX + 53, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STWBRX + 54, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STMW + 55, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_DCBF + 56, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_DCBST + 57, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DCBT + 58, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DCBTST + 59, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DCBZ + 60, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADD + 61, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADDC + 62, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADDE + 63, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADDI + 64, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADDIC + 65, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADDICR + 66, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADDIS + 67, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADDME + 68, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADDZE + 69, IU2_1, 23, 23, 0, 0, 0, 0, 0, // PC_DIVW + 70, IU2_1, 23, 23, 0, 0, 0, 0, 0, // PC_DIVWU + 71, IU2_1, 4, 2, 2, 0, 0, 0, 0, // PC_MULHW + 72, IU2_1, 4, 2, 2, 0, 0, 0, 0, // PC_MULHWU + 73, IU2_1, 3, 1, 1, 1, 0, 0, 0, // PC_MULLI + 74, IU2_1, 4, 2, 2, 0, 0, 0, 0, // PC_MULLW + 75, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_NEG + 76, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_SUBF + 77, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFC + 78, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFE + 79, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFIC + 80, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFME + 81, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFZE + 82, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_CMPI + 83, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_CMP + 84, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_CMPLI + 85, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_CMPL + 86, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ANDI + 87, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ANDIS + 88, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ORI + 89, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ORIS + 90, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_XORI + 91, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_XORIS + 92, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_AND + 93, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_OR + 94, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_XOR + 95, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_NAND + 96, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_NOR + 97, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_EQV + 98, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ANDC + 99, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ORC + 100, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_EXTSB + 101, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_EXTSH + 102, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_CNTLZW + 103, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_RLWINM + 104, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_RLWNM + 105, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_RLWIMI + 106, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_SLW + 107, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_SRW + 108, IU1a, 2, 2, 0, 0, 0, 0, 0, // PC_SRAWI + 109, IU1a, 2, 2, 0, 0, 0, 0, 0, // PC_SRAW + 110, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_CRAND + 111, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_CRANDC + 112, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_CREQV + 113, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_CRNAND + 114, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_CRNOR + 115, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_CROR + 116, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_CRORC + 117, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_CRXOR + 118, IU2_1, 1, 1, 0, 0, 0, 1, 0, // PC_MCRF + 119, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_MTXER + 120, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_MTCTR + 121, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_MTLR + 122, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_MTCRF + 123, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_MTMSR + 124, IU2_1, 3, 3, 0, 0, 0, 1, 0, // PC_MTSPR + 125, IU2_1, 3, 2, 1, 0, 0, 0, 0, // PC_MFMSR + 126, IU2_1, 3, 3, 0, 0, 0, 1, 0, // PC_MFSPR + 127, IU2_1, 1, 1, 0, 0, 0, 1, 0, // PC_MFXER + 128, IU2_1, 1, 1, 0, 0, 0, 1, 0, // PC_MFCTR + 129, IU2_1, 1, 1, 0, 0, 0, 1, 0, // PC_MFLR + 130, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_MFCR + 131, FPU_1, 5, 5, 0, 0, 0, 1, 0, // PC_MFFS + 132, FPU_1, 5, 5, 0, 0, 0, 1, 0, // PC_MTFSF + 133, LSU_1, 3, 3, 0, 0, 0, 1, 0, // PC_EIEIO + 134, IU2_1, 1, 1, 0, 0, 0, 1, 0, // PC_ISYNC + 135, LSU_1, 35, 35, 0, 0, 0, 1, 0, // PC_SYNC + 136, IU2_1, 1, 1, 0, 0, 0, 1, 0, // PC_RFI + 137, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_LI + 138, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_LIS + 139, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_MR + 140, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_NOP + 141, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_NOT + 142, LSU_1, 4, 1, 1, 1, 1, 0, 0, // PC_LFS + 143, LSU_1, 4, 1, 1, 1, 1, 0, 0, // PC_LFSU + 144, LSU_1, 4, 1, 1, 1, 1, 0, 0, // PC_LFSX + 145, LSU_1, 4, 1, 1, 1, 1, 0, 0, // PC_LFSUX + 146, LSU_1, 4, 1, 1, 1, 1, 0, 0, // PC_LFD + 147, LSU_1, 4, 1, 1, 1, 1, 0, 0, // PC_LFDU + 148, LSU_1, 4, 1, 1, 1, 1, 0, 0, // PC_LFDX + 149, LSU_1, 4, 1, 1, 1, 1, 0, 0, // PC_LFDUX + 150, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STFS + 151, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STFSU + 152, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STFSX + 153, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STFSUX + 154, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STFD + 155, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STFDU + 156, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STFDX + 157, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STFDUX + 158, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FMR + 159, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FABS + 160, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FNEG + 161, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FNABS + 162, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FADD + 163, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FADDS + 164, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FSUB + 165, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FSUBS + 166, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FMUL + 167, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FMULS + 168, FPU_1, 35, 35, 0, 0, 0, 0, 0, // PC_FDIV + 169, FPU_1, 21, 21, 0, 0, 0, 0, 0, // PC_FDIVS + 170, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FMADD + 171, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FMADDS + 172, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FMSUB + 173, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FMSUBS + 174, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FNMADD + 175, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FNMADDS + 176, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FNMSUB + 177, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FNMSUBS + 178, FPU_1, 14, 14, 0, 0, 0, 0, 0, // PC_FRES + 179, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FRSQRTE + 180, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FSEL + 181, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FRSP + 182, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FCTIW + 183, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FCTIWZ + 184, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FCMPU + 185, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FCMPO + 186, LSU_1, 3, 3, 0, 0, 0, 1, 0, // PC_LWARX + 187, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LSWI + 188, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_LSWX + 189, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STFIWX + 190, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STSWI + 191, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STSWX + 192, LSU_1, 3, 1, 1, 1, 0, 1, 0, // PC_STWCX + 193, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_ECIWX + 194, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_ECOWX + 195, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_DCBI + 196, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_ICBI + 197, IU2_1, 5, 5, 0, 0, 0, 1, 0, // PC_MCRFS + 198, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_MCRXR + 199, IU2_1, 5, 5, 0, 0, 0, 0, 0, // PC_MFTB + 200, IU2_1, 4, 1, 3, 0, 0, 0, 0, // PC_MFSR + 201, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_MTSR + 202, IU2_1, 4, 1, 3, 0, 0, 0, 0, // PC_MFSRIN + 203, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_MTSRIN + 204, FPU_1, 5, 5, 0, 0, 0, 1, 0, // PC_MTFSB0 + 205, FPU_1, 5, 5, 0, 0, 0, 1, 0, // PC_MTFSB1 + 206, FPU_1, 5, 5, 0, 0, 0, 0, 0, // PC_MTFSFI + 207, IU2_1, 1, 1, 0, 0, 0, 1, 0, // PC_SC + 208, FPU_1, 1, 1, 0, 0, 0, 0, 0, // PC_FSQRT + 209, FPU_1, 1, 1, 0, 0, 0, 0, 0, // PC_FSQRTS + 210, LSU_1, 1, 1, 0, 0, 0, 0, 0, // PC_TLBIA + 211, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_TLBIE + 212, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_TLBLD + 213, LSU_1, 3, 3, 0, 0, 0, 1, 0, // PC_TLBLI + 214, LSU_1, 3, 3, 0, 0, 0, 1, 0, // PC_TLBSYNC + 215, IU1a, 2, 2, 0, 0, 0, 0, 0, // PC_TW + 216, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_TRAP + 217, IU1a, 2, 2, 0, 0, 0, 0, 0, // PC_TWI + 218, IU1a, 1, 1, 0, 0, 0, 1, 0, // PC_OPWORD + 219, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_MFROM + 220, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_DSA + 221, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ESA + 222, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_DCCCI + 223, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_DCREAD + 224, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_ICBT + 225, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_ICCCI + 226, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_ICREAD + 227, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_RFCI + 228, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_TLBRE + 229, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_TLBSX + 230, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_TLBWE + 231, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_WRTEE + 232, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_WRTEEI + 233, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_MFDCR + 234, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_MTDCR + 235, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DCBA + 236, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DSS + 237, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DSSALL + 238, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DST + 239, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DSTT + 240, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DSTST + 241, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DSTSTT + 242, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LVEBX + 243, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LVEHX + 244, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LVEWX + 245, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LVSL + 246, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LVSR + 247, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LVX + 248, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LVXL + 249, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STVEBX + 250, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STVEHX + 251, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STVEWX + 252, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STVX + 253, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STVXL + 254, VFPU_1, 2, 2, 0, 0, 0, 1, 0, // PC_MFVSCR + 255, VFPU_1, 2, 2, 0, 0, 0, 1, 0, // PC_MTVSCR + 256, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDCUW + 257, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VADDFP + 258, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDSBS + 259, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDSHS + 260, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDSWS + 261, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUBM + 262, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUBS + 263, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUHM + 264, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUHS + 265, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUWM + 266, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUWS + 267, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VAND + 268, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VANDC + 269, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGSB + 270, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGSH + 271, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGSW + 272, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGUB + 273, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGUH + 274, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGUW + 275, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VCFSX + 276, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VCFUX + 277, VFPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VCMPBFP + 278, VFPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VCMPEQFP + 279, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPEQUB + 280, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPEQUH + 281, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPEQUW + 282, VFPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VCMPGEFP + 283, VFPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VCMPGTFP + 284, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTSB + 285, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTSH + 286, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTSW + 287, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTUB + 288, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTUH + 289, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTUW + 290, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VCTSXS + 291, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VCTUXS + 292, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VEXPTEFP + 293, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VLOGEFP + 294, VFPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMAXFP + 295, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXSB + 296, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXSH + 297, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXSW + 298, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXUB + 299, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXUH + 300, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXUW + 301, VFPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMINFP + 302, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMINSB + 303, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMINSH + 304, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMINSW + 305, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMINUB + 306, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMINUH + 307, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMINUW + 308, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMRGHB + 309, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMRGHH + 310, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMRGHW + 311, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMRGLB + 312, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMRGLH + 313, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMRGLW + 314, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMULESB + 315, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMULESH + 316, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMULEUB + 317, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMULEUH + 318, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMULOSB + 319, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMULOSH + 320, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMULOUB + 321, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMULOUH + 322, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VNOR + 323, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VOR + 324, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKPX + 325, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKSHSS + 326, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKSHUS + 327, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKSWSS + 328, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKSWUS + 329, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKUHUM + 330, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKUHUS + 331, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKUWUM + 332, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKUWUS + 333, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VREFP + 334, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VRFIM + 335, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VRFIN + 336, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VRFIP + 337, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VRFIZ + 338, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VRLB + 339, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VRLH + 340, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VRLW + 341, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VRSQRTEFP + 342, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSL + 343, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSLB + 344, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSLH + 345, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSLO + 346, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSLW + 347, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSPLTB + 348, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSPLTH + 349, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSPLTW + 350, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSPLTISB + 351, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSPLTISH + 352, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSPLTISW + 353, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSR + 354, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSRAB + 355, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSRAH + 356, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSRAW + 357, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSRB + 358, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSRH + 359, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSRO + 360, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSRW + 361, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBCUW + 362, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VSUBFP + 363, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBSBS + 364, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBSHS + 365, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBSWS + 366, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUBM + 367, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUBS + 368, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUHM + 369, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUHS + 370, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUWM + 371, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUWS + 372, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VSUMSWS + 373, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VSUM2SWS + 374, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VSUM4SBS + 375, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VSUM4SHS + 376, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VSUM4UBS + 377, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VUPKHPX + 378, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VUPKHSB + 379, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VUPKHSH + 380, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VUPKLPX + 381, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VUPKLSB + 382, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VUPKLSH + 383, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VXOR + 384, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMADDFP + 385, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMHADDSHS + 386, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMHRADDSHS + 387, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMLADDUHM + 388, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMSUMMBM + 389, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMSUMSHM + 390, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMSUMSHS + 391, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMSUMUBM + 392, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMSUMUHM + 393, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMSUMUHS + 394, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VNMSUBFP + 395, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPERM + 396, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSEL + 397, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSLDOI + 398, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMR + 399, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMRP + -1, IU2_1, 1, 1, 0, 0, 0, 1, 0 +}; + +enum { NumPipelineUnits = 6 }; +static struct { + Stage start, end; +} pipeline_units[8] = { + IU2_1, IU2_3, + LSU_1, LSU_4, + FPU_1, FPU_4, + VPU_1, VPU_2, + VIU2_1, VIU2_4, + VFPU_1, VFPU_4 +}; + +enum { NumFinalStages = 11 }; +static Stage finalstages[16] = { + BPU, IU2_3, IU1a, IU1b, + IU1c, LSU_4, FPU_4, VIU1, + VPU_2, VIU2_4, VFPU_4 +}; + +// forward decl +static void complete_instruction(int stage); + +static void advance(int firstStage, int oldStage, int newStage) { + PCode *instr = pipeline_altivec[oldStage].instr; + int cycles = instruction_timing[instr->op].cycles[newStage - firstStage]; + pipeline_altivec[newStage].instr = instr; + pipeline_altivec[newStage].remaining = cycles; + pipeline_altivec[oldStage].instr = NULL; + pipeline_altivec[oldStage].remaining = 0; + if (cycles == 0) + complete_instruction(newStage); +} + +static void assign_completion_buffer(PCode *instr) { + completionbuffers.used++; + completionbuffers.free--; + completionbuffers.entries[completionbuffers.nextFreeSlot].instr = instr; + completionbuffers.entries[completionbuffers.nextFreeSlot].completed = 0; + completionbuffers.nextFreeSlot = (completionbuffers.nextFreeSlot + 1) % MaxEntries; +} + +static void complete_instruction(int stage) { + PCode *instr = pipeline_altivec[stage].instr; + int buf = 0; + while (buf < MaxEntries && completionbuffers.entries[buf].instr != instr) + buf++; + + completionbuffers.entries[buf].completed = 1; + pipeline_altivec[stage].instr = NULL; +} + +static void retire_instruction(void) { + completionbuffers.entries[completionbuffers.nextToRetire].instr = NULL; + completionbuffers.entries[completionbuffers.nextToRetire].completed = 0; + completionbuffers.used--; + completionbuffers.free++; + completionbuffers.nextToRetire = (completionbuffers.nextToRetire + 1) % MaxEntries; +} + +static int latency(PCode *instr) { + int cycles = instruction_timing[instr->op].latency; + if (PCODE_FLAG_SET_F(instr) & fRecordBit) + cycles += 1; + if (instr->op == PC_LMW || instr->op == PC_STMW) + cycles += instr->argCount - 2; + return cycles; +} + +static void initialize(void) { + int stage; + int i; + + fetchqueues[Queue0] = 1; + for (i = 1; i < NumQueues; i++) + fetchqueues[i] = 0; + + for (stage = 0; stage < NumStages; stage++) + pipeline_altivec[stage].instr = NULL; + + completionbuffers.free = MaxEntries; + completionbuffers.used = 0; + completionbuffers.nextToRetire = 0; + completionbuffers.nextFreeSlot = 0; + for (i = 0; i < MaxEntries; i++) { + completionbuffers.entries[i].instr = NULL; + completionbuffers.entries[i].completed = 0; + } +} + +static int can_issue(PCode *instr) { + int stage; + + if (completionbuffers.free == 0) + return 0; + + stage = instruction_timing[instr->op].stage; + + if (stage == IU1a) { + int isClear1 = !pipeline_altivec[IU1a].instr; + int isClear2 = !pipeline_altivec[IU1b].instr; + if (!isClear1 && !isClear2) + return 0; + } else { + if (pipeline_altivec[stage].instr) + return 0; + } + + if (fetchqueues[Queue1] <= 0) + return 0; + + if (stage == FPU_1) { + if (fetchqueues[Queue2] < 1 || fetchqueues[Queue5] >= 1) + return 0; + } else if (stage >= VIU1 && stage <= VFPU_1) { + if (fetchqueues[Queue4] < 1 || fetchqueues[Queue7] >= 2) + return 0; + } else if (stage != BPU) { + if (fetchqueues[Queue3] < 1 || fetchqueues[Queue6] >= 3) + return 0; + } + + return 1; +} + +static void issue(PCode *instr) { + int stage = instruction_timing[instr->op].stage; + int cycles = instruction_timing[instr->op].cycles[0]; + assign_completion_buffer(instr); + + CError_ASSERT(879, --fetchqueues[Queue1] >= 0); + + if (stage == FPU_1) { + fetchqueues[Queue2]--; + fetchqueues[Queue5]++; + } else if (stage >= VIU1 && stage <= VFPU_1) { + fetchqueues[Queue4]--; + fetchqueues[Queue7]++; + } else if (stage != BPU) { + fetchqueues[Queue3]--; + fetchqueues[Queue6]++; + } + + fetchqueues[Queue2] = (fetchqueues[Queue1] < fetchqueues[Queue2]) ? fetchqueues[Queue1] : fetchqueues[Queue2]; + fetchqueues[Queue3] = (fetchqueues[Queue1] < fetchqueues[Queue3]) ? fetchqueues[Queue1] : fetchqueues[Queue3]; + fetchqueues[Queue4] = (fetchqueues[Queue1] < fetchqueues[Queue4]) ? fetchqueues[Queue1] : fetchqueues[Queue4]; + + if (stage == IU1a) { + if (!pipeline_altivec[IU1a].instr) + stage = IU1a; + else if (!pipeline_altivec[IU1b].instr) + stage = IU1b; + else if (!pipeline_altivec[IU1c].instr) + stage = IU1c; + } + + pipeline_altivec[stage].instr = instr; + pipeline_altivec[stage].remaining = cycles; +} + +static void advance_clock(void) { + int num; + int i; + unsigned int unit; + + for (i = 0; i < NumStages; i++) { + if (pipeline_altivec[i].instr && pipeline_altivec[i].remaining) + --pipeline_altivec[i].remaining; + } + + for (i = 0; i < 3; i++) { + if (completionbuffers.used == 0) + break; + if (completionbuffers.entries[completionbuffers.nextToRetire].completed == 0) + break; + retire_instruction(); + } + + unit = 0; + do { + if (pipeline_altivec[finalstages[unit]].instr && pipeline_altivec[finalstages[unit]].remaining == 0) + complete_instruction(finalstages[unit]); + } while (++unit < NumFinalStages); + + unit = 0; + do { + Stage first; + Stage current; + first = pipeline_units[unit].start; + for (current = first; current < pipeline_units[unit].end; current++) { + if (pipeline_altivec[current].instr && pipeline_altivec[current].remaining == 0 && !pipeline_altivec[current + 1].instr) + advance(first, current, current + 1); + } + } while (++unit < NumPipelineUnits); + + fetchqueues[Queue5] = 0; + fetchqueues[Queue6] = 0; + fetchqueues[Queue7] = 0; + +#define CHEAP_MIN(a, b) ( ((a) < (b)) ? (a) : (b) ) + num = 2 - fetchqueues[Queue2]; + num += 6 - fetchqueues[Queue3]; + num += 4 - fetchqueues[Queue4]; + num = (num > 3) ? 3 : num; + num = (completionbuffers.free < num) ? completionbuffers.free : num; + if (fetchqueues[Queue0] < num) + num = fetchqueues[Queue0]; + + fetchqueues[Queue1] += num; + fetchqueues[Queue0] -= num; + + fetchqueues[Queue2] = CHEAP_MIN(fetchqueues[Queue1], CHEAP_MIN(2, fetchqueues[Queue2] + num)); + fetchqueues[Queue3] = CHEAP_MIN(fetchqueues[Queue1], CHEAP_MIN(6, fetchqueues[Queue3] + num)); + fetchqueues[Queue4] = CHEAP_MIN(fetchqueues[Queue1], CHEAP_MIN(4, fetchqueues[Queue4] + num)); + + CError_ASSERT(991, fetchqueues[Queue1] <= (fetchqueues[Queue2] + fetchqueues[Queue3] + fetchqueues[Queue4])); + + if (fetchqueues[Queue0] <= 8) + fetchqueues[Queue0] += 4; +} + +static int serializes(PCode *instr) { + return instruction_timing[instr->op].serializes; +} + +static int uses_vpermute_unit_altivec(PCode *instr) { + return instruction_timing[instr->op].stage == VPU_1; +} + +MachineInfo machine7450 = { + 6, + 1, + 4, + &latency, + &initialize, + &can_issue, + &issue, + &advance_clock, + &serializes, + &uses_vpermute_unit_altivec +}; diff --git a/compiler_and_linker/BackEnd/PowerPC/Scheduler/Scheduler.c b/compiler_and_linker/BackEnd/PowerPC/Scheduler/Scheduler.c new file mode 100644 index 0000000..23b580f --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/Scheduler/Scheduler.c @@ -0,0 +1,547 @@ +#include "compiler/Scheduler.h" +#include "compiler/CError.h" +#include "compiler/CParser.h" +#include "compiler/Alias.h" +#include "compiler/CompilerTools.h" +#include "compiler/PCode.h" +#include "compiler/Registers.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct DGNode { + struct DGNode *x0; + struct DGNode *x4; + struct DGSuccessor *successors; + PCode *instr; + UInt16 x10; + UInt16 x12; + UInt16 x14; + UInt16 x16; + short predCount; +} DGNode; + +typedef struct DGSuccessor { + struct DGSuccessor *next; + DGNode *node; + UInt16 x8; +} DGSuccessor; + +typedef struct DGNodeList { + struct DGNodeList *next; + DGNode *node; +} DGNodeList; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static DGNodeList **register_uses[RegClassMax]; +static DGNodeList **register_defs[RegClassMax]; +static DGNodeList *memory_uses; +static DGNodeList *memory_defs; +static DGNodeList *side_effects; +static DGNodeList *volatile_refs; +static DGNode *defaultsuccessor; +static UInt16 criticalpath; +static MachineInfo *MI; + +static void initresources(void) { + int rclass; + int i; + + for (rclass = 0; (char) rclass < RegClassMax; rclass++) { + register_uses[(char) rclass] = oalloc(sizeof(DGNodeList *) * used_virtual_registers[(char) rclass]); + register_defs[(char) rclass] = oalloc(sizeof(DGNodeList *) * used_virtual_registers[(char) rclass]); + for (i = 0; i < used_virtual_registers[(char) rclass]; i++) { + register_uses[(char) rclass][i] = register_defs[(char) rclass][i] = NULL; + } + } + + memory_uses = memory_defs = NULL; + side_effects = NULL; + volatile_refs = NULL; + criticalpath = 0; +} + +static DGNode *makedgnode(PCode *instr) { + DGNode *node; + + node = oalloc(sizeof(DGNode)); + node->x0 = NULL; + node->x4 = NULL; + node->successors = NULL; + node->instr = instr; + node->x10 = node->x16 = MI->latency(instr); + node->x12 = 0; + node->x14 = 0; + node->predCount = 0; + return node; +} + +static DGNode *adddgnode(DGNode *head, DGNode *node) { + if (head) + head->x4 = node; + node->x0 = head; + return node; +} + +static DGNode *removedgnode(DGNode *head, DGNode *node) { + if (node->x4) + node->x4->x0 = node->x0; + else + head = node->x0; + + if (node->x0) + node->x0->x4 = node->x4; + + return head; +} + +static void addtolist(DGNodeList **list, DGNode *node) { + DGNodeList *entry = oalloc(sizeof(DGNodeList)); + entry->node = node; + entry->next = *list; + *list = entry; +} + +static DGNodeList *makedglistnode(DGNode *node) { + DGNodeList *list = oalloc(sizeof(DGNodeList)); + list->next = NULL; + list->node = node; + return list; +} + +int is_same_operand(PCodeArg *a, PCodeArg *b) { + if (a->kind != b->kind) + return 0; + + switch (a->kind) { + case PCOp_IMMEDIATE: + if (a->data.imm.value != b->data.imm.value) + return 0; + break; + case PCOp_REGISTER: + if ((char) a->arg != (char) b->arg) + return 0; + if (a->data.reg.reg != b->data.reg.reg) + return 0; + break; + case PCOp_MEMORY: + if (a->data.mem.offset != b->data.mem.offset) + return 0; + if (a->data.mem.obj != b->data.mem.obj) + return 0; + break; + case PCOp_LABEL: + if (a->data.label.label != b->data.label.label) + return 0; + break; + } + + return 1; +} + +static void addsuccessor(DGNode *a, DGNode *b, Boolean flag) { + int v6; + int r29; + DGSuccessor *succ; + + if (flag) + v6 = a->x10; + else + v6 = 0; + + if (a != b) { + r29 = (v6 > 0) ? v6 : 0; + for (succ = a->successors; succ; succ = succ->next) { + if (succ->node == b) { + if (succ->x8 < r29) { + succ->x8 = r29; + if (b->x16 + succ->x8 > a->x16) + a->x16 = b->x16 + succ->x8; + } + return; + } + } + + succ = oalloc(sizeof(DGSuccessor)); + succ->node = b; + succ->next = a->successors; + a->successors = succ; + succ->x8 = r29; + + if (flag && (succ->node->instr->flags & fIsBranch)) + succ->x8 += MI->x8; + + b->predCount++; + + if (b->x16 + succ->x8 > a->x16) + a->x16 = b->x16 + succ->x8; + } +} + +static void serializeall(DGNode *nodes, DGNode *node) { + DGNode *scan; + + for (scan = nodes; scan; scan = scan->x0) + addsuccessor(node, scan, 0); +} + +static void serializelist(DGNode *node, DGNodeList *list) { + while (list) { + if (list->node != node) + addsuccessor(node, list->node, 0); + list = list->next; + } +} + +static void serializeregister(int rclass, DGNode *node, DGNodeList **defs, DGNodeList **uses, int isWrite) { + DGNodeList *list; + + if (isWrite) { + for (list = *uses; list; list = list->next) { + if (list->node != node) + addsuccessor(node, list->node, 1); + } + for (list = *defs; list; list = list->next) { + if (list->node != node) + addsuccessor(node, list->node, ((char) rclass == RegClass_SPR) || (MI->x4 == 0)); + } + + list = makedglistnode(node); + list->next = *defs; + *defs = list; + } else { + for (list = *defs; list; list = list->next) { + if (list->node != node) + addsuccessor(node, list->node, ((char) rclass == RegClass_SPR) || (MI->x4 == 0)); + } + + list = makedglistnode(node); + list->next = *uses; + *uses = list; + } +} + +static void serialize_load(DGNode *node) { + DGNodeList *list; + + for (list = memory_defs; list; list = list->next) { + if (may_alias(node->instr, list->node->instr)) + addsuccessor(node, list->node, 1); + } + + addtolist(&memory_uses, node); +} + +static void serialize_store(DGNode *node) { + DGNodeList *list; + + for (list = memory_uses; list; list = list->next) { + if (may_alias(node->instr, list->node->instr)) + addsuccessor(node, list->node, 1); + } + for (list = memory_defs; list; list = list->next) { + if (may_alias(node->instr, list->node->instr)) + addsuccessor(node, list->node, 1); + } + + addtolist(&memory_defs, node); + if (node->instr->flags & fPCodeFlag40000) + addtolist(&memory_uses, node); +} + +static void findsuccessors(DGNode *nodes, DGNode *node) { + PCode *instr; + PCodeArg *op; + int i; + + instr = node->instr; + for (i = 0, op = instr->args; i < instr->argCount; i++, op++) { + switch (op->kind) { + case PCOp_IMMEDIATE: + case PCOp_MEMORY: + break; + case PCOp_REGISTER: + if ( + op->data.reg.reg < 0 || + op->data.reg.reg > used_virtual_registers[(char) op->arg] + ) + { + CError_FATAL(491); + } + + if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) { + if (op->data.reg.reg == Register2) + break; + if (op->data.reg.reg == Register0 && !(op->data.reg.effect & (EffectRead | EffectWrite))) + break; + } + + serializeregister( + op->arg, + node, + ®ister_defs[(char) op->arg][op->data.reg.reg], + ®ister_uses[(char) op->arg][op->data.reg.reg], + op->data.reg.effect & EffectWrite + ); + + break; + } + } + + if (instr->flags & (fIsRead | fPCodeFlag20000)) + serialize_load(node); + else if (instr->flags & (fIsWrite | fPCodeFlag40000)) + serialize_store(node); + + if (instr->flags & fIsVolatile) { + serializelist(node, volatile_refs); + addtolist(&volatile_refs, node); + } + + if ( + ((instr->flags & fIsCall | fIsBranch) && (instr->flags & fLink)) || + (instr->flags & fSideEffects) || + MI->serializes(instr) + ) + { + serializeall(nodes, node); + addtolist(&side_effects, node); + } + + if (side_effects) + serializelist(node, side_effects); + + if (!node->successors && defaultsuccessor) + addsuccessor(node, defaultsuccessor, 0); + + if (node->x16 > criticalpath) + criticalpath = node->x16; +} + +static void computedeadlines(DGNode *nodes) { + while (nodes) { + nodes->x14 = criticalpath - nodes->x16; + nodes = nodes->x0; + } +} + +static int uncovering(DGNode *node) { + int counter; + DGSuccessor *succ; + + counter = 0; + for (succ = node->successors; succ; succ = succ->next) { + if (succ->node->predCount == 1) + counter++; + } + + return counter; +} + +static DGNode *selectinstruction(DGNode *nodes, UInt16 counter) { + DGNode *node; + DGNode *node2; + int a; + int b; + + node = nodes; + while (node) { + if (node->predCount == 0 && node->x12 <= counter && MI->can_issue(node->instr)) + break; + node = node->x0; + } + + if (!node) + return NULL; + + for (node2 = node->x0; node2; node2 = node2->x0) { + if ( + node2->predCount == 0 && + node2->x12 <= counter && + MI->can_issue(node2->instr) && + (node->x14 > counter || node2->x14 <= counter) + ) + { + if (node->x14 > counter && node2->x14 <= counter) { + node = node2; + continue; + } + + if ((a = uncovering(node)) > (b = uncovering(node2))) + continue; + + if (a < b) { + node = node2; + continue; + } + + if (node->x16 > node2->x16) + continue; + + if (node->x16 < node2->x16) { + node = node2; + continue; + } + + if (coloring) { + if (opcodeinfo[node->instr->op].x9 < opcodeinfo[node2->instr->op].x9) + continue; + + if (opcodeinfo[node->instr->op].x9 > opcodeinfo[node2->instr->op].x9) + node = node2; + } + } + } + + return node; +} + +static void holdoffsuccessors(DGNode *node, UInt16 counter) { + DGSuccessor *succ; + DGNode *n; + + for (succ = node->successors; succ; succ = succ->next) { + n = succ->node; + n->predCount--; + if (n->x12 < counter + succ->x8) + n->x12 = counter + succ->x8; + } +} + +static void scheduleblock(PCodeBlock *block) { + DGNode *node; + UInt16 counter; + PCode *instr; + UInt16 i; + DGNode *head; + + initresources(); + defaultsuccessor = NULL; + head = NULL; + + for (instr = block->lastPCode; instr; instr = instr->prevPCode) { + DGNode *n = makedgnode(instr); + findsuccessors(head, n); + if (instr->flags & fIsBranch) + defaultsuccessor = n; + head = adddgnode(head, n); + } + + computedeadlines(head); + block->firstPCode = block->lastPCode = NULL; + block->pcodeCount = 0; + + MI->initialize(); + counter = 0; + while (head != NULL) { + for (i = 0; i < MI->x0; i++) { + if (head == NULL) + break; + + node = selectinstruction(head, counter); + if (!node) + break; + + instr = node->instr; + if (node->successors) + holdoffsuccessors(node, counter); + + appendpcode(block, instr); + MI->issue(instr); + head = removedgnode(head, node); + } + + MI->advance_clock(); + counter++; + } + + freeoheap(); +} + +void scheduleinstructions(Boolean flag) { + PCodeBlock *block; + int cpu; + + cpu = copts.scheduling; + if (cpu == 10) { + MI = &machine7450; + } else if (copts.altivec_model != 0 || cpu == 7) { + MI = &machine7400; + } else if (cpu == 2) { + MI = &machine603; + } else if (cpu == 5) { + MI = &machine603e; + } else if (cpu == 3) { + MI = &machine604; + } else if (cpu == 6) { + MI = &machine604; + } else if (cpu == 4) { + MI = &machine750; + } else if (cpu == 1) { + MI = &machine601; + } else if (cpu == 9) { + MI = &machine821; + } else { + MI = &machine603; + } + + gather_alias_info(); + + for (block = pcbasicblocks; block; block = block->nextBlock) { + if ( + block->pcodeCount > 2 && + (flag || !(block->flags & (fIsProlog | fIsEpilogue))) && + !(block->flags & fScheduled) + ) + { + scheduleblock(block); + block->flags |= fScheduled; + } + } +} + +int is_dependent(PCode *a, PCode *b, char rclass) { + int i; + int reg; + PCodeArg *op; + + if ( + b && + b->argCount >= 1 && + b->args[0].kind == PCOp_REGISTER && + (char) b->args[0].arg == rclass && + (b->args[0].data.reg.effect & EffectWrite) + ) + { + reg = b->args[0].data.reg.reg; + for (i = 0; i < a->argCount; i++) { + op = &a->args[i]; + if ( + op->kind == PCOp_REGISTER && + (char) op->arg == rclass && + (op->data.reg.effect & (EffectRead | EffectWrite)) && + op->data.reg.reg == reg + ) + return 1; + } + } + + return 0; +} + +int uses_vpermute_unit(PCode *instr) { + int cpu; + + cpu = copts.scheduling; + if (cpu == 10) + return machine7450.uses_vpermute_unit(instr); + if (copts.altivec_model != 0 || cpu == 7) + return machine7400.uses_vpermute_unit(instr); + return 0; +} + +int default_uses_vpermute_unit(PCode *instr) { + return 0; +} diff --git a/compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Src/Options/Glue/ParserGlue-mach-ppc-cc.c b/compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Src/Options/Glue/ParserGlue-mach-ppc-cc.c index ba38b17..1a2cdb1 100644 --- a/compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Src/Options/Glue/ParserGlue-mach-ppc-cc.c +++ b/compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Src/Options/Glue/ParserGlue-mach-ppc-cc.c @@ -1,22 +1,22 @@ #include "cmdline.h" #include "parser.h" -#include "compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Src/Options/Glue/ParserGlue-mach-ppc-common.h" +#include "ParserGlue-mach-ppc-common.h" static Boolean useDefaultIncludes = 1; static Boolean useDefaultLibraries = 1; -#include "compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Lib/mac-ppc-cc/OptsCmdLine.opt" -#include "compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Lib/mac-ppc-cc/OptsCmdLineCompiler.opt" -#include "compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Lib/mac-ppc-cc/OptsCmdLineLinker.opt" -#include "compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Lib/mac-ppc-cc/OptsFrontEndC.opt" -#include "compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Lib/mac-ppc-cc/OptsDebugging.opt" -#include "compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Lib/mac-ppc-cc/OptsOptimizer.opt" -#include "compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Lib/mac-ppc-cc/OptsWarningC.opt" -#include "compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Lib/mac-ppc-cc/OptsBackEnd.opt" -#include "compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Lib/mac-ppc-cc/OptsProject.opt" -#include "compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Lib/mac-ppc-cc/OptsLinker.opt" -#include "compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Lib/mac-ppc-cc/OptsDumper.opt" +#include "../../../Lib/mac-ppc-cc/OptsCmdLine.opt" +#include "../../../Lib/mac-ppc-cc/OptsCmdLineCompiler.opt" +#include "../../../Lib/mac-ppc-cc/OptsCmdLineLinker.opt" +#include "../../../Lib/mac-ppc-cc/OptsFrontEndC.opt" +#include "../../../Lib/mac-ppc-cc/OptsDebugging.opt" +#include "../../../Lib/mac-ppc-cc/OptsOptimizer.opt" +#include "../../../Lib/mac-ppc-cc/OptsWarningC.opt" +#include "../../../Lib/mac-ppc-cc/OptsBackEnd.opt" +#include "../../../Lib/mac-ppc-cc/OptsProject.opt" +#include "../../../Lib/mac-ppc-cc/OptsLinker.opt" +#include "../../../Lib/mac-ppc-cc/OptsDumper.opt" char *prefs[] = { "PPC CodeGen Mach-O", diff --git a/compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Src/Plugin/libimp-mach-ppc.c b/compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Src/Plugin/libimp-mach-ppc.c index 4eb55d5..fab0f00 100644 --- a/compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Src/Plugin/libimp-mach-ppc.c +++ b/compiler_and_linker/CmdLine_Tools/MacOS_PPC/Tools_PPC/Src/Plugin/libimp-mach-ppc.c @@ -139,7 +139,7 @@ int RegisterStaticLibImporterPlugin(void) { return RegisterStaticCompilerLinkerPlugin(&machlibimport_cb, &machlibimport_cl_cb); } -#include "compiler_and_linker/Plugin_Tools/MacOS_PPC/Lib_Importer_Mach/Resources/Errors.r" +#include "../../../../../Plugin_Tools/MacOS_PPC/Lib_Importer_Mach/Resources/Errors.r" int RegisterLibImporterResources(void) { return RegisterResource("Mach-O Lib Importer Errors", 911, STR911); diff --git a/compiler_and_linker/FrontEnd/C/CABI.c b/compiler_and_linker/FrontEnd/C/CABI.c new file mode 100644 index 0000000..2a88de1 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CABI.c @@ -0,0 +1,2033 @@ +#include "compiler/CABI.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CException.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInit.h" +#include "compiler/CInline.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CScope.h" +#include "compiler/CSOM.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/types.h" + +typedef struct OffsetList { + struct OffsetList *next; + SInt32 offset; +} OffsetList; + +static OffsetList *trans_vtboffsets; +static BClassList cabi_pathroot; +static BClassList *cabi_pathcur; +static TypeClass *cabi_loop_class; +static Boolean cabi_loop_construct; + +short CABI_GetStructResultArgumentIndex(TypeFunc *tfunc) { + return 0; +} + +Type *CABI_GetSizeTType(void) { + return TYPE(&stunsignedlong); +} + +Type *CABI_GetPtrDiffTType(void) { + return TYPE(&stsignedlong); +} + +SInt16 CABI_StructSizeAlignValue(Type *type, SInt32 size) { + SInt16 align = CMach_GetTypeAlign(type); + if (align <= 1) + return 0; + else + return (align - 1) & (align - ((size & (align - 1)))); +} + +void CABI_ReverseBitField(TypeBitfield *tbitfield) { + UInt8 bits; + UInt8 a; + UInt8 b; + + switch (tbitfield->bitfieldtype->size) { + case 1: + bits = 8; + break; + case 2: + bits = 16; + break; + case 4: + bits = 32; + break; + case 8: + bits = 64; + break; + default: + CError_FATAL(172); + } + + b = tbitfield->bitlength; + a = tbitfield->offset; + tbitfield->offset = (bits - a) - b; +} + +static void CABI_AllocateZeroVTablePointer(void *unk, TypeClass *tclass) { + ClassList *base; + + for (base = tclass->bases; base; base = base->next) { + if (!base->is_virtual && base->base->vtable) + return; + } + + tclass->size += void_ptr.size; +} + +static SInt32 CABI_GetBaseSize(TypeClass *tclass) { + SInt32 size = tclass->size; + + if (copts.vbase_abi_v2 && tclass->vbases) + return tclass->vbases->offset; + + return size; +} + +static void CABI_AllocateBases(ClassLayout *layout, TypeClass *tclass) { + Boolean flag; + TypeClass *baseclass; + ClassList *base; + VClassList *vbase; + SInt32 size; + + flag = 0; + size = tclass->size; + + for (base = tclass->bases; base; base = base->next) { + if (!base->is_virtual) { + baseclass = base->base; + if (!(baseclass->flags & CLASS_EMPTY)) { + base->offset = size + CMach_MemberAlignValue(TYPE(baseclass), size); + if (copts.vbase_abi_v2) { + size = base->offset + CABI_GetBaseSize(baseclass); + } else { + size = base->offset + baseclass->size; + for (vbase = baseclass->vbases; vbase; vbase = vbase->next) + size -= vbase->base->size; + } + flag = 0; + } else { + if (flag) + base->offset = ++size; + else + base->offset = size; + flag = 1; + } + } + } + + tclass->size = size; +} + +static void CABI_AllocateVirtualBasePointers(ClassLayout *layout, TypeClass *tclass) { + ClassList *base; + SInt32 size; + + size = tclass->size; + + for (base = tclass->bases; base; base = base->next) { + if (base->is_virtual) { + base->offset = size + CMach_MemberAlignValue(TYPE(&void_ptr), size); + size = base->offset + void_ptr.size; + } + } + + tclass->size = size; +} + +static SInt32 CABI_GetMemberOffset(TypeClass *tclass, HashNameNode *name) { + ObjMemberVar *ivar; + + if (!name) + return 0; + + ivar = tclass->ivars; + while (1) { + if (ivar->name == name) + return ivar->offset; + + if (!(ivar = ivar->next)) + CError_FATAL(362); + } +} + +static void CABI_AllocateMembers(ClassLayout *layout, TypeClass *tclass) { + ObjMemberVar *ivar; + SInt32 initialSize; + SInt32 maxSize; + TypeClass *unionClass; + SInt32 unionStart; + Boolean inAnonUnion; + Boolean removeNoNameIvars; + + removeNoNameIvars = 0; + initialSize = maxSize = tclass->size; + CMach_StructLayoutInitOffset(maxSize); + + unionClass = NULL; + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + if (!ivar->anonunion) { + if (!(ivar->offset & 0x80000000)) { + if (tclass->mode == CLASS_MODE_UNION) + CMach_StructLayoutInitOffset(initialSize); + + if (IS_TYPE_BITFIELD(ivar->type)) + ivar->offset = CMach_StructLayoutBitfield(TYPE_BITFIELD(ivar->type), ivar->qual); + else + ivar->offset = CMach_StructLayoutGetOffset(ivar->type, ivar->qual); + + if (tclass->mode == CLASS_MODE_UNION) { + SInt32 tmp = CMach_StructLayoutGetCurSize(); + if (tmp > maxSize) + maxSize = tmp; + } + + unionClass = NULL; + } else { + CError_ASSERT(412, unionClass); + ivar->offset = unionStart + CABI_GetMemberOffset(unionClass, ivar->name); + if (!inAnonUnion) + ivar->anonunion = 1; + inAnonUnion = 0; + } + + if (ivar->name == no_name_node || ivar->name == NULL) + removeNoNameIvars = 1; + } else { + CError_ASSERT(422, IS_TYPE_CLASS(ivar->type)); + + if (tclass->mode == CLASS_MODE_UNION) + CMach_StructLayoutInitOffset(initialSize); + + unionStart = CMach_StructLayoutGetOffset(ivar->type, ivar->qual); + unionClass = TYPE_CLASS(ivar->type); + inAnonUnion = 1; + + if (tclass->mode == CLASS_MODE_UNION) { + SInt32 tmp = CMach_StructLayoutGetCurSize(); + if (tmp > maxSize) + maxSize = tmp; + } + + removeNoNameIvars = 1; + } + + if (layout->vtable_ivar == ivar) + tclass->vtable->offset = ivar->offset; + } + + if (removeNoNameIvars) { + ObjMemberVar **ptr = &tclass->ivars; + while (*ptr) { + if ((*ptr)->name == NULL || (*ptr)->name == no_name_node) + *ptr = (*ptr)->next; + else + ptr = &(*ptr)->next; + } + } + + if (tclass->mode == CLASS_MODE_UNION) + tclass->size = maxSize; + else + tclass->size = CMach_StructLayoutGetCurSize(); + + if (copts.reverse_bitfields) { + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + if (IS_TYPE_BITFIELD(ivar->type)) + CABI_ReverseBitField(TYPE_BITFIELD(ivar->type)); + } + } +} + +static void CABI_AllocateVirtualBases(ClassLayout *layout, TypeClass *tclass) { + VClassList *vbase; + SInt32 size; + + size = tclass->size; + + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + vbase->offset = size + CMach_MemberAlignValue(TYPE(vbase->base), size); + size = vbase->offset + CABI_GetBaseSize(vbase->base); + + if (vbase->has_override) + size += CMach_MemberAlignValue(TYPE(&stunsignedlong), size) + 4; + } + + tclass->size = size; +} + +static Boolean CABI_FindZeroDeltaVPtr(TypeClass *tclass) { + ClassList *base; + + for (base = tclass->bases; base; base = base->next) { + if (!base->is_virtual && base->base->vtable && !base->offset) { + tclass->vtable->offset = base->base->vtable->offset; + return 1; + } + } + + return 0; +} + +static Object *CABI_FindZeroVirtualBaseMember(TypeClass *tclass, Object *obj) { + NameSpaceObjectList *nsol; + ClassList *base; + Object *chk; + + for (base = tclass->bases; base; base = base->next) { + if (!base->is_virtual && !base->offset && !base->voffset && base->base->vtable) { + for (nsol = CScope_FindName(base->base->nspace, obj->name); nsol; nsol = nsol->next) { + chk = OBJECT(nsol->object); + if ( + chk->otype == OT_OBJECT && + chk->datatype == DVFUNC && + CClass_GetOverrideKind(TYPE_FUNC(chk->type), TYPE_FUNC(obj->type), 0) == 1 + ) + return chk; + } + + if ((chk = CABI_FindZeroVirtualBaseMember(base->base, obj))) + return chk; + } + } + + return NULL; +} + +void CABI_AddVTable(TypeClass *tclass) { + tclass->vtable = galloc(sizeof(VTable)); + memclrw(tclass->vtable, sizeof(VTable)); +} + +SInt32 CABI_GetVTableOffset(TypeClass *tclass) { + return 0; +} + +static SInt32 CABI_GetBaseVTableSize(TypeClass *tclass) { + VClassList *vbase; + SInt32 size; + + size = tclass->vtable->size; + + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + if (vbase->base->vtable) + size -= CABI_GetBaseVTableSize(vbase->base); + } + + return size; +} + +static void CABI_ApplyClassFlags(Object *obj, UInt8 flags, Boolean unused) { + if (flags & CLASS_EFLAGS_INTERNAL) + obj->flags = obj->flags | OBJECT_INTERNAL; + if (flags & CLASS_EFLAGS_IMPORT) + obj->flags = obj->flags | OBJECT_IMPORT; + if (flags & CLASS_EFLAGS_EXPORT) + obj->flags = obj->flags | OBJECT_EXPORT; +} + +static void CABI_AllocateVTable(ClassLayout *layout, TypeClass *tclass) { + SInt32 size; + ObjBase *objbase; + Object *obj; + ObjMemberVar *ivar; + ClassList *base; + VClassList *vbase; + int i; + + size = 0; + + if (!tclass->vtable) { + CABI_AddVTable(tclass); + layout->xA = layout->lex_order_count - 1; + } + + if (!CABI_FindZeroDeltaVPtr(tclass)) { + ivar = galloc(sizeof(ObjMemberVar)); + memclrw(ivar, sizeof(ObjMemberVar)); + + ivar->otype = OT_MEMBERVAR; + ivar->access = ACCESSPUBLIC; + ivar->name = vptr_name_node; + ivar->type = TYPE(&void_ptr); + layout->vtable_ivar = ivar; + + for (i = layout->xA; ; i--) { + if (i < 0) { + ivar->next = tclass->ivars; + tclass->ivars = ivar; + break; + } + + CError_ASSERT(666, layout->objlist[i]); + + if (layout->objlist[i]->otype == OT_MEMBERVAR) { + ivar->next = OBJ_MEMBER_VAR(layout->objlist[i])->next; + OBJ_MEMBER_VAR(layout->objlist[i])->next = ivar; + break; + } + } + + if (tclass->flags & (CLASS_SINGLE_OBJECT | CLASS_COM_OBJECT)) + size = void_ptr.size; + else + size = 8; + } else { + layout->vtable_ivar = NULL; + } + + for (base = tclass->bases; base; base = base->next) { + if (base->base->vtable && !base->is_virtual) { + base->voffset = size; + if (copts.vbase_abi_v2) { + size += CABI_GetBaseVTableSize(base->base); + } else { + size += base->base->vtable->size; + for (vbase = base->base->vbases; vbase; vbase = vbase->next) { + if (vbase->base->vtable) + size -= vbase->base->vtable->size; + } + } + } + } + + for (i = 0; i < layout->lex_order_count; i++) { + CError_ASSERT(714, objbase = layout->objlist[i]); + + if (objbase->otype == OT_OBJECT && OBJECT(objbase)->datatype == DVFUNC) { + TypeMemberFunc *tmethod = TYPE_METHOD(OBJECT(objbase)->type); + Object *baseobj = CABI_FindZeroVirtualBaseMember(tclass, OBJECT(objbase)); + + if (baseobj) { + tmethod->vtbl_index = TYPE_METHOD(baseobj->type)->vtbl_index; + } else { + tmethod->vtbl_index = size; + size += 4; + } + } + } + + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + if (vbase->base->vtable) { + vbase->voffset = size; + if (copts.vbase_abi_v2) + size += CABI_GetBaseVTableSize(vbase->base); + else + size += vbase->base->vtable->size; + } + } + + obj = CParser_NewCompilerDefDataObject(); + CABI_ApplyClassFlags(obj, tclass->eflags, 0); + + obj->name = CMangler_VTableName(tclass); + obj->type = CDecl_NewStructType(size, 4); + obj->qual = Q_CONST; + obj->nspace = tclass->nspace; + switch (tclass->action) { + case CLASS_ACTION_0: + obj->sclass = TK_STATIC; + obj->qual |= Q_20000; + break; + } + + CParser_UpdateObject(obj, NULL); + + tclass->vtable->object = obj; + tclass->vtable->owner = tclass; + tclass->vtable->size = size; +} + +void CABI_LayoutClass(ClassLayout *layout, TypeClass *tclass) { + char saveAlignMode = copts.structalignment; + + tclass->size = 0; + if (!tclass->sominfo) { + if (tclass->bases) + CABI_AllocateBases(layout, tclass); + if (tclass->flags & CLASS_HAS_VBASES) + CABI_AllocateVirtualBasePointers(layout, tclass); + if (layout->has_vtable) + CABI_AllocateVTable(layout, tclass); + CABI_AllocateMembers(layout, tclass); + if (tclass->flags & CLASS_HAS_VBASES) + CABI_AllocateVirtualBases(layout, tclass); + } else { + copts.structalignment = AlignMode2_PPC; + CABI_AllocateMembers(layout, tclass); + } + + tclass->align = CMach_GetClassAlign(tclass); + if (tclass->size == 0) { + tclass->size = 1; + tclass->flags = tclass->flags | CLASS_EMPTY; + } else { + tclass->size += CABI_StructSizeAlignValue(TYPE(tclass), tclass->size); + } + + tclass->flags = tclass->flags | CLASS_COMPLETED; + + copts.structalignment = saveAlignMode; +} + +void CABI_MakeDefaultArgConstructor(TypeClass *tclass, Object *func) { + DefArgCtorInfo *info; + Boolean saveDebugInfo; + ENodeList *copied; + ENodeList *argexprs; + FuncArg *args; + CScopeSave savedScope; + Statement firstStmt; + Statement returnStmt; + + CError_FATAL(860); + + if (anyerrors || func->access == ACCESSNONE) + return; + + CError_ASSERT(866, info = func->u.func.defargdata); + + CABI_ApplyClassFlags(func, tclass->eflags, 0); + + CScope_SetFunctionScope(func, &savedScope); + + CFunc_FuncGenSetup(&firstStmt, func); + + saveDebugInfo = copts.filesyminfo; + copts.filesyminfo = 0; + + CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); + + if (tclass->flags & CLASS_HAS_VBASES) + arguments->next->object->name = no_name_node; + + firstStmt.next = &returnStmt; + + memclrw(&returnStmt, sizeof(Statement)); + returnStmt.type = ST_RETURN; + returnStmt.expr = lalloc(sizeof(ENode)); + returnStmt.expr->type = EFUNCCALL; + returnStmt.expr->cost = 200; + returnStmt.expr->flags = 0; + returnStmt.expr->rtype = TYPE(&void_ptr); + + returnStmt.expr->data.funccall.funcref = CExpr_MakeObjRefNode(info->default_func, 0); + returnStmt.expr->data.funccall.functype = TYPE_FUNC(info->default_func->type); + args = TYPE_FUNC(info->default_func->type)->args; + returnStmt.expr->data.funccall.args = lalloc(sizeof(ENodeList)); + argexprs = returnStmt.expr->data.funccall.args; + + argexprs->node = create_objectnode(arguments->object); + + if (tclass->flags & CLASS_HAS_VBASES) { + args = args->next; + argexprs->next = lalloc(sizeof(ENodeList)); + argexprs = argexprs->next; + argexprs->node = create_objectnode(arguments->next->object); + } + + args = args->next; + argexprs->next = lalloc(sizeof(ENodeList)); + argexprs = argexprs->next; + argexprs->node = CInline_CopyExpression(info->default_arg, CopyMode0); + + while ((args = args->next) && args->dexpr) { + argexprs->next = lalloc(sizeof(ENodeList)); + argexprs = argexprs->next; + argexprs->node = CInline_CopyExpression(args->dexpr, CopyMode0); + } + + argexprs->next = NULL; + + CFunc_CodeCleanup(&firstStmt); + CFunc_Gen(&firstStmt, func, 0); + + CScope_RestoreScope(&savedScope); + copts.filesyminfo = saveDebugInfo; + + func->u.func.defargdata = NULL; +} + +static Object *CABI_ThisArg(void) { + CError_ASSERT(931, arguments && IS_TYPE_POINTER_ONLY(arguments->object->type)); + return arguments->object; +} + +ENode *CABI_MakeThisExpr(TypeClass *tclass, SInt32 offset) { + ENode *expr; + + if (tclass) { + if (!tclass->sominfo) { + expr = create_objectnode(CABI_ThisArg()); + if (tclass->flags & CLASS_HANDLEOBJECT) + expr = makemonadicnode(expr, EINDIRECT); + } else { + expr = CSOM_SOMSelfObjectExpr(tclass); + } + } else { + expr = create_objectnode(CABI_ThisArg()); + expr->rtype = TYPE(&void_ptr); + } + + if (offset) + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); + + return expr; +} + +static Object *CABI_VArg(void) { + CError_ASSERT(976, arguments && arguments->next && IS_TYPE_INT(arguments->next->object->type)); + return arguments->next->object; +} + +static ENode *CABI_MakeVArgExpr(void) { + return create_objectnode(CABI_VArg()); +} + +static ENode *CABI_MakeCopyConArgExpr(TypeClass *tclass, Boolean flag) { + ObjectList *args; + + CError_ASSERT(1000, args = arguments); + CError_ASSERT(1001, args = args->next); + if (flag && (tclass->flags & CLASS_HAS_VBASES)) + CError_ASSERT(1002, args = args->next); + CError_ASSERT(1003, IS_TYPE_POINTER_ONLY(args->object->type)); + + return create_objectnode(args->object); +} + +static ENode *CABI_InitVBasePtr1(ENode *expr, TypeClass *tclass1, TypeClass *tclass2, TypeClass *tclass3, SInt32 offset) { + ClassList *base; + SInt32 newOffset; + OffsetList *list; + + for (base = tclass2->bases; base; base = base->next) { + if (base->base == tclass3 && base->is_virtual) { + newOffset = offset + base->offset; + + for (list = trans_vtboffsets; list; list = list->next) { + if (newOffset == list->offset) + break; + } + + if (!list) { + list = lalloc(sizeof(OffsetList)); + list->offset = newOffset; + list->next = trans_vtboffsets; + trans_vtboffsets = list; + + expr = makediadicnode( + makemonadicnode(CABI_MakeThisExpr(NULL, newOffset), EINDIRECT), + expr, + EASS); + } + } + + if (base->is_virtual) + newOffset = CClass_VirtualBaseOffset(tclass1, base->base); + else + newOffset = offset + base->offset; + + expr = CABI_InitVBasePtr1(expr, tclass1, base->base, tclass3, newOffset); + } + + return expr; +} + +static Statement *CABI_InitVBasePtrs(Statement *stmt, TypeClass *tclass) { + ENode *expr; + VClassList *vbase; + + for (vbase = tclass->vbases, trans_vtboffsets = NULL; vbase; vbase = vbase->next) { + expr = CABI_InitVBasePtr1(CABI_MakeThisExpr(NULL, vbase->offset), tclass, tclass, vbase->base, 0); + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = expr; + } + + return stmt; +} + +static OffsetList *CABI_GetVBasePath(TypeClass *tclass, TypeClass *baseclass) { + ClassList *base; + OffsetList *best; + OffsetList *list; + OffsetList *scan; + short bestLength; + short length; + + for (base = tclass->bases; base; base = base->next) { + if (base->base == baseclass && base->is_virtual) { + best = lalloc(sizeof(OffsetList)); + best->next = NULL; + best->offset = base->offset; + return best; + } + } + + best = NULL; + + for (base = tclass->bases; base; base = base->next) { + if ((list = CABI_GetVBasePath(base->base, baseclass))) { + for (scan = list->next, length = 1; scan; scan = scan->next) + length++; + + if (base->is_virtual) + length++; + + if (!best || length < bestLength) { + if (base->is_virtual) { + best = lalloc(sizeof(OffsetList)); + best->next = list; + best->offset = base->offset; + } else { + best = list; + best->offset += base->offset; + } + bestLength = length; + } + } + } + + return best; +} + +static ENode *CABI_GetVBasePtr(TypeClass *tclass, TypeClass *baseclass) { + OffsetList *path; + ENode *expr; + + CError_ASSERT(1127, path = CABI_GetVBasePath(tclass, baseclass)); + + expr = makemonadicnode(CABI_MakeThisExpr(NULL, path->offset), EINDIRECT); + + while ((path = path->next)) { + if (path->offset) + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), path->offset), EADD); + expr = makemonadicnode(expr, EINDIRECT); + } + + return expr; +} + +static SInt32 CABI_FindNVBase(TypeClass *tclass, TypeClass *baseclass, SInt32 offset) { + ClassList *base; + SInt32 tmp; + + if (tclass == baseclass) + return offset; + + for (base = tclass->bases; base; base = base->next) { + if (!base->is_virtual && (tmp = CABI_FindNVBase(base->base, baseclass, offset + base->offset)) >= 0) + return tmp; + } + + return -1; +} + +SInt32 CABI_GetCtorOffsetOffset(TypeClass *tclass, TypeClass *baseclass) { + SInt32 baseSize; + SInt32 size; + char saveAlignMode; + + size = CABI_GetBaseSize(tclass); + if (baseclass) { + baseSize = CABI_FindNVBase(tclass, baseclass, 0); + CError_ASSERT(1178, baseSize >= 0); + size -= baseSize; + } + + saveAlignMode = copts.structalignment; + if (tclass->eflags & CLASS_EFLAGS_F0) + copts.structalignment = ((tclass->eflags & CLASS_EFLAGS_F0) >> 4) - 1; + size += CMach_MemberAlignValue(TYPE(&stunsignedlong), size); + copts.structalignment = saveAlignMode; + + return size; +} + +static Statement *CABI_InitVBaseCtorOffsets(Statement *stmt, TypeClass *tclass) { + VClassList *vbase; + Object *tempObj; + ENode *expr; + ENode *vbaseptr; + SInt32 vboffset; + SInt32 ctorOffsetOffset; + + tempObj = NULL; + + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + if (vbase->has_override) { + if (!tempObj) + tempObj = create_temp_object(TYPE(&void_ptr)); + + vboffset = CClass_VirtualBaseOffset(tclass, vbase->base); + ctorOffsetOffset = CABI_GetCtorOffsetOffset(vbase->base, NULL); + vbaseptr = CABI_GetVBasePtr(tclass, vbase->base); + CError_ASSERT(1215, vbaseptr); + + expr = makediadicnode(create_objectnode(tempObj), vbaseptr, EASS); + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = expr; + + expr = makediadicnode( + create_objectnode(tempObj), + intconstnode(TYPE(&stunsignedlong), ctorOffsetOffset), + EADD); + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = TYPE(&stunsignedlong); + expr = makediadicnode( + expr, + makediadicnode( + CABI_MakeThisExpr(NULL, vboffset), + create_objectnode(tempObj), + ESUB), + EASS); + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = expr; + } + } + + return stmt; +} + +static Statement *CABI_InitVTablePtrs(Statement *stmt, Object *vtableObj, TypeClass *tclass, TypeClass *baseclass, SInt32 offset, SInt32 voffset) { + ClassList *base; + BClassList *orig_pathcur; + SInt32 newOffset; + SInt32 newVOffset; + OffsetList *offsetList; + SInt32 vtblOffset; + ENode *vtblExpr; + ENode *pathExpr; + BClassList path; + + if (baseclass->vtable->owner == baseclass) { + vtblOffset = offset + baseclass->vtable->offset; + for (offsetList = trans_vtboffsets; offsetList; offsetList = offsetList->next) { + if (vtblOffset == offsetList->offset) + break; + } + + if (!offsetList) { + offsetList = lalloc(sizeof(OffsetList)); + offsetList->offset = vtblOffset; + offsetList->next = trans_vtboffsets; + trans_vtboffsets = offsetList; + + vtblExpr = create_objectrefnode(vtableObj); + vtblExpr->rtype = TYPE(&void_ptr); + if ((vtblOffset = voffset + CABI_GetVTableOffset(baseclass))) + vtblExpr = makediadicnode(vtblExpr, intconstnode(TYPE(&stunsignedlong), vtblOffset), EADD); + + pathExpr = CClass_AccessPathCast(&cabi_pathroot, CABI_MakeThisExpr(tclass, 0), 0); + if (baseclass->vtable->offset && !canadd(pathExpr, baseclass->vtable->offset)) { + pathExpr = makediadicnode(pathExpr, intconstnode(TYPE(&stunsignedlong), baseclass->vtable->offset), EADD); + optimizecomm(pathExpr); + } + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = makediadicnode(makemonadicnode(pathExpr, EINDIRECT), vtblExpr, EASS); + } + } + + for (base = baseclass->bases; base; base = base->next) { + if (base->base->vtable) { + orig_pathcur = cabi_pathcur; + + cabi_pathcur->next = &path; + path.next = NULL; + path.type = TYPE(base->base); + cabi_pathcur = &path; + + if (base->is_virtual) { + newOffset = CClass_VirtualBaseOffset(tclass, base->base); + newVOffset = CClass_VirtualBaseVTableOffset(tclass, base->base); + } else { + newOffset = offset + base->offset; + newVOffset = voffset + base->voffset; + } + + stmt = CABI_InitVTablePtrs(stmt, vtableObj, tclass, base->base, newOffset, newVOffset); + + cabi_pathcur = orig_pathcur; + } + } + + return stmt; +} + +static Boolean CABI_IsOperatorNew(ObjBase *obj) { + return + obj->otype == OT_OBJECT && + IS_TYPE_FUNC(OBJECT(obj)->type) && + TYPE_FUNC(OBJECT(obj)->type)->args && + TYPE_FUNC(OBJECT(obj)->type)->args->type == CABI_GetSizeTType() && + !TYPE_FUNC(OBJECT(obj)->type)->args->next; +} + +Object *CABI_ConstructorCallsNew(TypeClass *tclass) { + NameSpaceObjectList *nsol; + NameResult pr; + + if (!tclass->sominfo && (tclass->flags & CLASS_HANDLEOBJECT)) { + if (CScope_FindClassMemberObject(tclass, &pr, CMangler_OperatorName(TK_NEW))) { + if (pr.obj_10) { + if (CABI_IsOperatorNew(pr.obj_10)) + return OBJECT(pr.obj_10); + } else { + for (nsol = pr.nsol_14; nsol; nsol = nsol->next) { + if (CABI_IsOperatorNew(nsol->object)) + return OBJECT(nsol->object); + } + } + } + + return newh_func; + } + + return NULL; +} + +void CABI_TransConstructor(Object *obj, Statement *firstStmt, TypeClass *tclass, TransConstructorCallback callback, Boolean has_try) { + Statement *stmt; + Object *tmpfunc; + Object *tmpfunc2; + CLabel *label; + ENode *expr; + ClassList *base; + VClassList *vbase; + ObjMemberVar *ivar; + Type *type; + CtorChain *chain; + Boolean errorflag; + + stmt = firstStmt; + + if ((tmpfunc = CABI_ConstructorCallsNew(tclass))) { + label = newlabel(); + + stmt = CFunc_InsertStatement(ST_IFGOTO, firstStmt); + stmt->expr = CABI_MakeThisExpr(NULL, 0); + stmt->label = label; + + expr = makediadicnode( + CABI_MakeThisExpr(NULL, 0), + funccallexpr(tmpfunc, intconstnode(CABI_GetSizeTType(), tclass->size), NULL, NULL, NULL), + EASS); + stmt = CFunc_InsertStatement(ST_IFGOTO, stmt); + stmt->expr = expr; + stmt->label = label; + + stmt = CFunc_InsertStatement(ST_RETURN, stmt); + stmt->expr = NULL; + + stmt = CFunc_InsertStatement(ST_LABEL, stmt); + stmt->label = label; + label->stmt = stmt; + } + + if (has_try) { + for (stmt = firstStmt; ; stmt = stmt->next) { + CError_ASSERT(1408, stmt); + if (stmt->type == ST_BEGINCATCH) + break; + } + } + + if (!tclass->sominfo) { + if (tclass->flags & CLASS_HAS_VBASES) { + label = newlabel(); + + stmt = CFunc_InsertStatement(ST_IFGOTO, stmt); + stmt->expr = CExpr_New_EEQU_Node(CABI_MakeVArgExpr(), intconstnode(TYPE(&stsignedshort), 0)); + stmt->label = label; + + stmt = CABI_InitVBasePtrs(stmt, tclass); + + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + if (!callback) { + for (chain = ctor_chain; chain; chain = chain->next) { + if (chain->what == CtorChain_VBase && chain->u.vbase == vbase) + break; + } + + if (chain) { + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = chain->objexpr; + } else { + expr = CClass_DefaultConstructorCall( + vbase->base, + tclass, + CABI_MakeThisExpr(NULL, vbase->offset), + 0, 1, 1, &errorflag); + if (expr) { + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = expr; + } else if (errorflag) { + CError_Error(CErrorStr213, tclass, 0, vbase->base, 0); + } + } + } else { + stmt = callback(stmt, tclass, vbase->base, vbase->offset, 1); + } + + if ((tmpfunc = CClass_Destructor(vbase->base))) + CExcept_RegisterMember(stmt, CABI_ThisArg(), vbase->offset, tmpfunc, CABI_VArg(), 0); + } + + stmt = CFunc_InsertStatement(ST_LABEL, stmt); + stmt->label = label; + label->stmt = stmt; + } + + for (base = tclass->bases; base; base = base->next) { + if (base->is_virtual) + continue; + + if (!callback) { + for (chain = ctor_chain; chain; chain = chain->next) { + if (chain->what == CtorChain_Base && chain->u.base == base) + break; + } + + if (chain) { + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = chain->objexpr; + } else { + expr = CClass_DefaultConstructorCall( + base->base, + tclass, + CABI_MakeThisExpr(NULL, base->offset), + 0, 1, 0, &errorflag); + if (expr) { + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = expr; + } else if (errorflag) { + CError_Error(CErrorStr213, tclass, 0, base->base, 0); + } + } + } else { + stmt = callback(stmt, tclass, base->base, base->offset, 1); + } + + if ((tmpfunc = CClass_Destructor(base->base))) + CExcept_RegisterMember(stmt, CABI_ThisArg(), base->offset, tmpfunc, NULL, 0); + } + + if (tclass->vtable && tclass->vtable->object && tclass->vtable->owner == tclass) { + cabi_pathroot.next = NULL; + cabi_pathroot.type = TYPE(tclass); + cabi_pathcur = &cabi_pathroot; + trans_vtboffsets = NULL; + + stmt = CABI_InitVTablePtrs(stmt, tclass->vtable->object, tclass, tclass, 0, 0); + } + } + + if (!tclass->sominfo && (tclass->flags & CLASS_FLAGS_8000)) + stmt = CABI_InitVBaseCtorOffsets(stmt, tclass); + + if (!callback) { + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + for (chain = ctor_chain; chain; chain = chain->next) { + if (chain->what == CtorChain_MemberVar && chain->u.membervar == ivar) { + if (IS_TYPE_ARRAY(ivar->type)) + chain = NULL; + break; + } + } + + if (chain) { + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = chain->objexpr; + type = ivar->type; + switch (type->type) { + case TYPEARRAY: + do { + type = TPTR_TARGET(type); + } while (IS_TYPE_ARRAY(type)); + if (IS_TYPE_CLASS(type)) { + if ((tmpfunc = CClass_Destructor(TYPE_CLASS(type)))) { + CError_ASSERT(1560, type->size); + CExcept_RegisterMemberArray( + stmt, + CABI_ThisArg(), + ivar->offset, + tmpfunc, + ivar->type->size / type->size, + type->size); + } + } + break; + case TYPECLASS: + if ((tmpfunc = CClass_Destructor(TYPE_CLASS(type)))) { + CExcept_RegisterMember( + stmt, + CABI_ThisArg(), + ivar->offset, + tmpfunc, + NULL, + 1); + } + break; + } + } else { + type = ivar->type; + switch (type->type) { + case TYPEARRAY: + do { + type = TPTR_TARGET(type); + } while (IS_TYPE_ARRAY(type)); + if (IS_TYPE_CLASS(type) && CClass_Constructor(TYPE_CLASS(type))) { + if ( + (tmpfunc = CClass_DefaultConstructor(TYPE_CLASS(type))) || + (tmpfunc = CClass_DummyDefaultConstructor(TYPE_CLASS(type))) + ) + { + tmpfunc2 = CClass_Destructor(TYPE_CLASS(type)); + if (tmpfunc2) + tmpfunc2 = CABI_GetDestructorObject(tmpfunc2, 1); + + stmt = CInit_ConstructClassArray( + stmt, + TYPE_CLASS(type), + tmpfunc, + tmpfunc2, + CABI_MakeThisExpr(tclass, ivar->offset), + ivar->type->size / type->size); + + if (tmpfunc2) + CExcept_RegisterMemberArray( + stmt, + CABI_ThisArg(), + ivar->offset, + tmpfunc2, + ivar->type->size / type->size, + type->size); + } else { + CError_Error(CErrorStr214, tclass, 0, ivar->name->name); + } + } + break; + case TYPECLASS: + expr = CClass_DefaultConstructorCall( + TYPE_CLASS(type), + NULL, + CABI_MakeThisExpr(tclass, ivar->offset), + 1, 1, 0, &errorflag); + if (expr) { + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = expr; + } else if (errorflag) { + CError_Error(CErrorStr214, tclass, 0, ivar->name->name); + } + + if ((tmpfunc = CClass_Destructor(TYPE_CLASS(type)))) { + if (!expr) { + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = nullnode(); + } + CExcept_RegisterMember( + stmt, + CABI_ThisArg(), + ivar->offset, + tmpfunc, + NULL, + 1); + } + break; + } + } + } + } else { + stmt = callback(stmt, tclass, NULL, 0, 1); + } + + if (!tclass->sominfo) { + for (stmt = firstStmt->next; stmt; stmt = stmt->next) { + if (stmt->type == ST_RETURN) { + CError_ASSERT(1661, !stmt->expr); + stmt->expr = CABI_MakeThisExpr(NULL, 0); + } + } + } +} + +void CABI_MakeDefaultConstructor(TypeClass *tclass, Object *func) { + Boolean saveDebugInfo; + CScopeSave savedScope; + Statement firstStmt; + Statement returnStmt; + + if (anyerrors || func->access == ACCESSNONE) + return; + + CABI_ApplyClassFlags(func, tclass->eflags, 0); + + CScope_SetFunctionScope(func, &savedScope); + + CFunc_FuncGenSetup(&firstStmt, func); + + saveDebugInfo = copts.filesyminfo; + copts.filesyminfo = 0; + + CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); + + ctor_chain = NULL; + if (tclass->flags & CLASS_HAS_VBASES) + arguments->next->object->name = CParser_GetUniqueName(); + + firstStmt.next = &returnStmt; + + memclrw(&returnStmt, sizeof(Statement)); + returnStmt.type = ST_RETURN; + + CABI_TransConstructor(func, &firstStmt, tclass, NULL, 0); + + CFunc_CodeCleanup(&firstStmt); + CFunc_Gen(&firstStmt, func, 0); + + CScope_RestoreScope(&savedScope); + copts.filesyminfo = saveDebugInfo; +} + +static ENode *CABI_AssignObject(TypeClass *tclass, ENode *expr1, ENode *expr2) { + Object *assignfunc; + FuncArg *arg; + + assignfunc = CClass_AssignmentOperator(tclass); + if (!assignfunc) { + expr1 = makemonadicnode(expr1, EINDIRECT); + expr1->rtype = TYPE(tclass); + return makediadicnode(expr1, expr2, EASS); + } + + CError_ASSERT(1731, + IS_TYPE_FUNC(assignfunc->type) && + (arg = TYPE_FUNC(assignfunc->type)->args) && + (arg = arg->next)); + + expr2 = argumentpromotion(expr2, arg->type, arg->qual, 1); + return funccallexpr(assignfunc, expr1, expr2, NULL, NULL); +} + +static Type *CABI_FindIntegralSizeType(SInt32 size) { + if (stunsignedchar.size == size) + return TYPE(&stunsignedchar); + if (stunsignedshort.size == size) + return TYPE(&stunsignedshort); + if (stunsignedint.size == size) + return TYPE(&stunsignedint); + if (stunsignedlong.size == size) + return TYPE(&stunsignedlong); + if (stunsignedlonglong.size == size) + return TYPE(&stunsignedlonglong); + + CError_FATAL(1756); + return NULL; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct CopyRegion { + struct CopyRegion *next; + Type *type; + SInt32 start; + SInt32 end; + Boolean flag; +} CopyRegion; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static CopyRegion *CABI_AppendCopyRegion(CopyRegion *regions, Type *type, SInt32 start, Boolean flag) { + CopyRegion *region; + SInt32 end; + + if (IS_TYPE_BITFIELD(type)) + type = TYPE_BITFIELD(type)->bitfieldtype; + + end = start + type->size; + + if (flag) { + for (region = regions; region; region = region->next) { + if (region->flag) { + if (region->start <= start && region->end >= end) + return regions; + + if (region->start >= start && region->end <= end) { + region->type = type; + region->start = start; + region->end = end; + for (region = region->next; region; region = region->next) { + if (region->start >= start && region->end <= end) + region->end = region->start; + } + return regions; + } + } + } + } + + if (regions) { + region = regions; + while (region->next) + region = region->next; + + region->next = lalloc(sizeof(CopyRegion)); + region = region->next; + } else { + regions = lalloc(sizeof(CopyRegion)); + region = regions; + } + + region->next = NULL; + region->type = type; + region->start = start; + region->end = end; + region->flag = flag; + + return regions; +} + +static ENode *CABI_ClassInitLoopCallBack(ENode *var1, ENode *var2) { + ENodeList *list; + + var2 = makemonadicnode(var2, EINDIRECT); + var2->rtype = TYPE(cabi_loop_class); + + if (cabi_loop_construct) { + list = lalloc(sizeof(ENodeList)); + memclrw(list, sizeof(ENodeList)); + list->node = var2; + return CExpr_ConstructObject(cabi_loop_class, var1, list, 1, 1, 0, 1, 1); + } else { + return CABI_AssignObject(cabi_loop_class, var1, var2); + } +} + +static Statement *CABI_CopyConAssignCB(Statement *stmt, TypeClass *tclass, TypeClass *baseclass, SInt32 offset, Boolean flag) { + ENode *expr; + ENode *expr2; + ENode *startExpr; + ENode *endExpr; + ENodeList *list; + ObjMemberVar *ivar; + CopyRegion *regions; + Type *type; + SInt32 i; + SInt32 count; + Boolean isFlagNotSet; + Object *tmpfunc; + + if (baseclass) { + if (baseclass->flags & CLASS_EMPTY) { + if ( + (flag && !CClass_CopyConstructor(baseclass)) || + (!flag && !CClass_AssignmentOperator(baseclass)) + ) + return stmt; + } + + expr = CABI_MakeCopyConArgExpr(tclass, flag); + expr->rtype = TYPE(baseclass); + expr->data.monadic = CClass_DirectBasePointerCast(expr->data.monadic, tclass, baseclass); + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + if (flag) { + list = lalloc(sizeof(ENodeList)); + list->next = NULL; + list->node = expr; + + stmt->expr = CExpr_ConstructObject( + baseclass, + CABI_MakeThisExpr(NULL, offset), + list, + 1, 0, 0, 0, 1); + } else { + stmt->expr = CABI_AssignObject( + baseclass, + CClass_DirectBasePointerCast(CABI_MakeThisExpr(NULL, 0), tclass, baseclass), + expr); + } + } else { + isFlagNotSet = !flag; + for (ivar = tclass->ivars, regions = NULL; ivar; ivar = ivar->next) { + if (ivar->name == vptr_name_node) + continue; + + type = ivar->type; + if (isFlagNotSet) { + if (CParser_IsConst(type, ivar->qual) || IS_TYPE_REFERENCE(type) != 0) { + CError_Error(CErrorStr387, tclass, 0); + isFlagNotSet = 0; + } + } + + switch (type->type) { + case TYPEARRAY: + while (IS_TYPE_ARRAY(type)) + type = TPTR_TARGET(type); + if (!IS_TYPE_CLASS(type)) { + regions = CABI_AppendCopyRegion(regions, ivar->type, ivar->offset, 1); + break; + } + case TYPECLASS: + if (flag) { + if (CClass_CopyConstructor(TYPE_CLASS(type)) || CClass_CopyConstructor(TYPE_CLASS(type))) { + regions = CABI_AppendCopyRegion(regions, ivar->type, ivar->offset, 0); + break; + } + } else { + if (CClass_AssignmentOperator(TYPE_CLASS(type))) { + regions = CABI_AppendCopyRegion(regions, ivar->type, ivar->offset, 0); + break; + } + } + default: + regions = CABI_AppendCopyRegion(regions, ivar->type, ivar->offset, 1); + } + } + + for (; regions; regions = regions->next) { + if (regions->start >= regions->end) + continue; + + type = regions->type; + expr = CABI_MakeCopyConArgExpr(tclass, flag); + expr->rtype = type; + + if (!canadd(expr->data.monadic, regions->start)) { + expr->data.monadic = makediadicnode( + expr->data.monadic, + intconstnode(TYPE(&stunsignedlong), regions->start), + EADD); + optimizecomm(expr->data.monadic); + } + + if (!regions->flag) { + if (IS_TYPE_ARRAY(type)) { + while (IS_TYPE_ARRAY(type)) + type = TPTR_TARGET(type); + + CError_ASSERT(1966, IS_TYPE_CLASS(type)); + + if (type->size) { + count = regions->type->size / type->size; + if (count > 4) { + startExpr = CABI_MakeThisExpr(tclass, regions->start); + endExpr = CABI_MakeThisExpr(tclass, regions->start + regions->type->size); + expr = CABI_MakeCopyConArgExpr(tclass, flag)->data.monadic; + if (!canadd(expr, regions->start)) { + expr = makediadicnode( + expr, + intconstnode(TYPE(&stunsignedlong), regions->start), + EADD); + optimizecomm(expr); + } + + cabi_loop_class = TYPE_CLASS(type); + cabi_loop_construct = flag; + stmt = CFunc_GenerateLoop( + stmt, + CDecl_NewPointerType(type), + startExpr, + endExpr, + intconstnode(TYPE(&stunsignedlong), type->size), + expr, + CABI_ClassInitLoopCallBack); + } else { + for (i = 0, offset = regions->start; i < count; i++, offset += type->size) { + expr = CABI_MakeCopyConArgExpr(tclass, flag); + expr->rtype = type; + + if (!canadd(expr->data.monadic, offset)) { + expr->data.monadic = makediadicnode( + expr->data.monadic, + intconstnode(TYPE(&stunsignedlong), offset), + EADD); + optimizecomm(expr->data.monadic); + } + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + if (flag) { + list = lalloc(sizeof(ENodeList)); + memclrw(list, sizeof(ENodeList)); + list->node = expr; + stmt->expr = CExpr_ConstructObject( + TYPE_CLASS(type), + CABI_MakeThisExpr(tclass, offset), + list, + 1, 1, 0, 1, 1); + } else { + stmt->expr = CABI_AssignObject( + TYPE_CLASS(type), + CABI_MakeThisExpr(tclass, offset), + expr); + } + } + } + + if (flag && (tmpfunc = CClass_Destructor(TYPE_CLASS(type)))) + CExcept_RegisterMemberArray(stmt, CABI_ThisArg(), regions->start, tmpfunc, count, type->size); + } + } else { + CError_ASSERT(2027, IS_TYPE_CLASS(type)); + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + + if (flag) { + list = lalloc(sizeof(ENodeList)); + memclrw(list, sizeof(ENodeList)); + list->node = expr; + stmt->expr = CExpr_ConstructObject( + TYPE_CLASS(type), + CABI_MakeThisExpr(tclass, regions->start), + list, + 1, 1, 0, 1, 1); + + if ((tmpfunc = CClass_Destructor(TYPE_CLASS(type)))) + CExcept_RegisterMember(stmt, CABI_ThisArg(), regions->start, tmpfunc, NULL, 1); + } else { + stmt->expr = CABI_AssignObject( + TYPE_CLASS(type), + CABI_MakeThisExpr(tclass, regions->start), + expr); + } + } + } else { + if (IS_TYPE_ARRAY(type)) { + if (type->size > 1 && ((regions->start & 1) || (type->size & 1))) { + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = funccallexpr( + copy_func, + CABI_MakeThisExpr(tclass, regions->start), + getnodeaddress(expr, 0), + intconstnode(CABI_GetSizeTType(), type->size), + NULL); + continue; + } + + type = CDecl_NewStructType(type->size, CMach_GetTypeAlign(type)); + expr->rtype = type; + } + + expr2 = makemonadicnode(CABI_MakeThisExpr(tclass, regions->start), EINDIRECT); + expr2->rtype = type; + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = makediadicnode(expr2, expr, EASS); + } + } + } + + return stmt; +} + +void CABI_MakeDefaultCopyConstructor(TypeClass *tclass, Object *func) { + Boolean saveDebugInfo; + CScopeSave savedScope; + Statement firstStmt; + Statement returnStmt; + + if (anyerrors || func->access == ACCESSNONE) + return; + + CABI_ApplyClassFlags(func, tclass->eflags, 0); + + CScope_SetFunctionScope(func, &savedScope); + + CFunc_FuncGenSetup(&firstStmt, func); + + saveDebugInfo = copts.filesyminfo; + copts.filesyminfo = 0; + + CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); + + ctor_chain = NULL; + if (tclass->flags & CLASS_HAS_VBASES) + arguments->next->object->name = CParser_GetUniqueName(); + + firstStmt.next = &returnStmt; + + memclrw(&returnStmt, sizeof(Statement)); + returnStmt.type = ST_RETURN; + + CABI_TransConstructor(func, &firstStmt, tclass, CABI_CopyConAssignCB, 0); + + CFunc_CodeCleanup(&firstStmt); + CFunc_Gen(&firstStmt, func, 0); + + CScope_RestoreScope(&savedScope); + copts.filesyminfo = saveDebugInfo; +} + +void CABI_MakeDefaultAssignmentOperator(TypeClass *tclass, Object *func) { + Boolean saveDebugInfo; + Statement *stmt; + ClassList *base; + VClassList *vbase; + ENode *expr1; + ENode *expr2; + CScopeSave savedScope; + Statement firstStmt; + + if (anyerrors || func->access == ACCESSNONE) + return; + + CABI_ApplyClassFlags(func, tclass->eflags, 0); + + CScope_SetFunctionScope(func, &savedScope); + + CFunc_FuncGenSetup(&firstStmt, func); + + saveDebugInfo = copts.filesyminfo; + copts.filesyminfo = 0; + + CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); + + stmt = curstmt; + + if (tclass->mode == CLASS_MODE_UNION) { + expr1 = makemonadicnode(CABI_MakeThisExpr(tclass, 0), EINDIRECT); + expr1->rtype = TYPE(tclass); + + expr2 = CABI_MakeCopyConArgExpr(tclass, 0); + expr2->rtype = TYPE(tclass); + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = makediadicnode(expr1, expr2, EASS); + } else { + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + stmt = CABI_CopyConAssignCB(stmt, tclass, vbase->base, vbase->offset, 0); + } + + for (base = tclass->bases; base; base = base->next) { + if (!base->is_virtual) + stmt = CABI_CopyConAssignCB(stmt, tclass, base->base, base->offset, 0); + } + + stmt = CABI_CopyConAssignCB(stmt, tclass, NULL, 0, 0); + } + + stmt = CFunc_InsertStatement(ST_RETURN, stmt); + stmt->expr = CABI_MakeThisExpr(NULL, 0); + + CFunc_CodeCleanup(&firstStmt); + CFunc_Gen(&firstStmt, func, 0); + + CScope_RestoreScope(&savedScope); + copts.filesyminfo = saveDebugInfo; +} + +static Statement *CABI_DestroyMembers(Statement *stmt, ObjMemberVar *ivars, TypeClass *tclass) { + Type *type; + Object *dtor; + ENode *expr; + + for (; ivars; ivars = ivars->next) { + type = ivars->type; + + if (IS_TYPE_ARRAY(type)) { + while (IS_TYPE_ARRAY(type)) + type = TPTR_TARGET(type); + + if (IS_TYPE_CLASS(type) && (dtor = CClass_Destructor(TYPE_CLASS(type)))) { + dtor = CABI_GetDestructorObject(dtor, 1); + stmt = CABI_DestroyMembers(stmt, ivars->next, tclass); + expr = create_objectrefnode(dtor); + expr->flags = expr->flags | ENODE_FLAG_80; + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = funccallexpr( + darr_func, + CABI_MakeThisExpr(tclass, ivars->offset), + expr, + intconstnode(TYPE(&stsignedlong), type->size), + intconstnode(TYPE(&stsignedlong), ivars->type->size / type->size) + ); + return stmt; + } + } else { + if (IS_TYPE_CLASS(type) && (dtor = CClass_Destructor(TYPE_CLASS(type)))) { + stmt = CABI_DestroyMembers(stmt, ivars->next, tclass); + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = CABI_DestroyObject( + dtor, + CABI_MakeThisExpr(tclass, ivars->offset), + CABIDestroy1, + 1, + 0 + ); + return stmt; + } + } + } + + return stmt; +} + +static Statement *CABI_DestroyBases(Statement *stmt, ClassList *bases) { + ClassList *base; + Object *dtor; + SInt32 count; + SInt32 i; + + base = bases; + count = 0; + while (base) { + base = base->next; + count++; + } + + while (count > 0) { + base = bases; + i = count; + while (i-- > 1) + base = base->next; + + if (!base->is_virtual && (dtor = CClass_Destructor(base->base))) { + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = CABI_DestroyObject( + dtor, + CABI_MakeThisExpr(NULL, base->offset), + CABIDestroy0, + 1, + 0); + } + + count--; + } + + return stmt; +} + +static Statement *CABI_DestroyVBases(Statement *stmt, VClassList *vbases) { + Object *dtor; + + for (; vbases; vbases = vbases->next) { + if ((dtor = CClass_Destructor(vbases->base))) { + stmt = CABI_DestroyVBases(stmt, vbases->next); + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = CABI_DestroyObject( + dtor, + CABI_MakeThisExpr(NULL, vbases->offset), + CABIDestroy0, + 1, + 0); + break; + } + } + + return stmt; +} + +void CABI_TransDestructor(Object *obj1, Object *obj2, Statement *stmt, TypeClass *tclass, CABIDestroyMode mode) { + CLabel *label2; + Boolean flag29; + CLabel *label; + Statement *scan; + Boolean flag25; + Boolean flag24; + Boolean flag23; + CLabel *label3; + Object *dealloc; + Boolean deallocFlag; + + if (tclass->sominfo) { + flag24 = 0; + flag25 = 0; + flag29 = 0; + flag23 = 1; + } else { + flag24 = 1; + flag23 = 1; + flag25 = 1; + flag29 = 1; + } + + label = newlabel(); + + for (scan = stmt; scan; scan = scan->next) { + if (scan->type == ST_RETURN) { + CError_ASSERT(2329, !scan->expr); + scan->type = ST_GOTO; + scan->label = label; + } + + if (scan->next && scan->next->type == ST_RETURN && !scan->next->next) { + CError_ASSERT(2334, !scan->next->expr); + scan->next = NULL; + break; + } + } + + scan = stmt; + + if (flag29) { + label2 = newlabel(); + scan = CFunc_InsertStatement(ST_IFNGOTO, scan); + scan->expr = CABI_MakeThisExpr(NULL, 0); + scan->label = label2; + } + + if (flag25 && tclass->vtable && tclass->vtable->object && tclass->vtable->owner == tclass) { + cabi_pathroot.next = NULL; + cabi_pathroot.type = TYPE(tclass); + cabi_pathcur = &cabi_pathroot; + trans_vtboffsets = NULL; + scan = CABI_InitVTablePtrs(scan, tclass->vtable->object, tclass, tclass, 0, 0); + } + + if (!tclass->sominfo && (tclass->flags & CLASS_FLAGS_8000)) + CABI_InitVBaseCtorOffsets(scan, tclass); + + scan = stmt; + while (scan->next) + scan = scan->next; + + scan = CFunc_InsertStatement(ST_LABEL, scan); + scan->label = label; + scan->dobjstack = NULL; + label->stmt = scan; + + if (flag23 && !(tclass->flags & CLASS_HANDLEOBJECT)) + scan = CABI_DestroyMembers(scan, tclass->ivars, tclass); + + if (flag25 && tclass->bases) + scan = CABI_DestroyBases(scan, tclass->bases); + + if (flag24 && (tclass->flags & CLASS_HAS_VBASES)) { + label3 = newlabel(); + scan = CFunc_InsertStatement(ST_IFNGOTO, scan); + scan->expr = CABI_MakeVArgExpr(); + scan->label = label3; + + scan = CABI_DestroyVBases(scan, tclass->vbases); + + scan = CFunc_InsertStatement(ST_LABEL, scan); + scan->label = label3; + label3->stmt = scan; + } + + if (flag29) { + scan = CFunc_InsertStatement(ST_IFGOTO, scan); + scan->expr = CExpr_New_ELESSEQU_Node(CABI_MakeVArgExpr(), intconstnode(TYPE(&stsignedshort), 0)); + scan->label = label2; + + scan = CFunc_InsertStatement(ST_EXPRESSION, scan); + dealloc = CParser_FindDeallocationObject(TYPE(tclass), NULL, 0, 0, &deallocFlag); + if (deallocFlag) { + scan->expr = funccallexpr( + dealloc, + CABI_MakeThisExpr(NULL, 0), + intconstnode(CABI_GetSizeTType(), tclass->size), + NULL, + NULL); + } else { + scan->expr = funccallexpr(dealloc, CABI_MakeThisExpr(NULL, 0), NULL, NULL, NULL); + } + + scan = CFunc_InsertStatement(ST_LABEL, scan); + scan->label = label2; + label2->stmt = scan; + } + + scan = CFunc_InsertStatement(ST_RETURN, scan); + if (tclass->sominfo) + scan->expr = NULL; + else + scan->expr = CABI_MakeThisExpr(NULL, 0); +} + +void CABI_MakeDefaultDestructor(TypeClass *tclass, Object *func) { + Boolean saveDebugInfo; + CScopeSave savedScope; + Statement firstStmt; + Statement returnStmt; + + if (anyerrors || func->access == ACCESSNONE) + return; + + CABI_ApplyClassFlags(func, tclass->eflags, 0); + + CScope_SetFunctionScope(func, &savedScope); + + CFunc_FuncGenSetup(&firstStmt, func); + + saveDebugInfo = copts.filesyminfo; + copts.filesyminfo = 0; + + CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); + + firstStmt.next = &returnStmt; + + memclrw(&returnStmt, sizeof(Statement)); + returnStmt.type = ST_RETURN; + + CFunc_CodeCleanup(&firstStmt); + + CABI_TransDestructor(func, func, &firstStmt, tclass, CABIDestroy0); + + CFunc_Gen(&firstStmt, func, 0); + + CScope_RestoreScope(&savedScope); + copts.filesyminfo = saveDebugInfo; +} + +static void CABI_CreateLayeredDestructor(TypeClass *tclass, Object *obj1, Object *func, CABIDestroyMode mode) { + Boolean saveDebugInfo; + CScopeSave savedScope; + Statement firstStmt; + Statement returnStmt; + + CError_FATAL(2524); + + CScope_SetFunctionScope(func, &savedScope); + + CFunc_FuncGenSetup(&firstStmt, func); + + saveDebugInfo = copts.filesyminfo; + copts.filesyminfo = 0; + + CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); + + firstStmt.next = &returnStmt; + + memclrw(&returnStmt, sizeof(Statement)); + returnStmt.type = ST_RETURN; + + CFunc_CodeCleanup(&firstStmt); + + CABI_TransDestructor(obj1, func, &firstStmt, tclass, mode); + + CFunc_Gen(&firstStmt, func, 0); + + CScope_RestoreScope(&savedScope); + copts.filesyminfo = saveDebugInfo; +} + +void CABI_MakeLayeredDestructor(TypeClass *tclass, Object *func) { + Object *dtor; + CABIDestroyMode mode; + + CError_FATAL(2557); + + if (anyerrors || func->access == ACCESSNONE) + return; + + if ((dtor = CClass_Destructor(tclass))) { + if (CABI_GetDestructorObject(dtor, CABIDestroy0) == func) + mode = CABIDestroy0; + else if (CABI_GetDestructorObject(dtor, CABIDestroy2) == func) + mode = CABIDestroy2; + else if (CABI_GetDestructorObject(dtor, CABIDestroy3) == func) + mode = CABIDestroy3; + else if (CABI_GetDestructorObject(dtor, CABIDestroy1) == func) + mode = CABIDestroy1; + else + CError_FATAL(2567); + } + + CABI_CreateLayeredDestructor(tclass, dtor, func, mode); +} + +Object *CABI_GetDestructorObject(Object *obj, CABIDestroyMode mode) { + return obj; +} + +static void CABI_AddLayeredDestructor(TypeClass *tclass, Object *dtor, HashNameNode *name, Boolean is_virtual) { + Object *func; + + CError_FATAL(2667); + + func = CParser_NewFunctionObject(NULL); + func->nspace = dtor->nspace; + func->name = name; + func->type = TYPE(CDecl_MakeDefaultDtorType(tclass, is_virtual)); + func->qual = Q_20000 | Q_MANGLE_NAME; + func->qual |= Q_INLINE; + CABI_ApplyClassFlags(func, tclass->eflags, 1); + + CError_ASSERT(2678, IS_TYPE_FUNC(func->type)); + TYPE_FUNC(func->type)->flags |= FUNC_AUTO_GENERATED; + + if (dtor->datatype == DVFUNC) { + func->datatype = DVFUNC; + CMangler_GetLinkName(func); + func->datatype = DFUNC; + } + + CScope_AddObject(func->nspace, func->name, OBJ_BASE(func)); +} + +void CABI_AddLayeredDestructors(TypeClass *tclass) { + Object *dtor; + + CError_FATAL(2707); + + if ((dtor = CClass_Destructor(tclass))) { + CABI_AddLayeredDestructor(tclass, dtor, CMangler_DeleteDtorName(), 1); + CABI_AddLayeredDestructor(tclass, dtor, CMangler_SDeleteDtorName(), 1); + if (tclass->vbases) + CABI_AddLayeredDestructor(tclass, dtor, CMangler_VBaseDtorName(), 0); + } +} + +ENode *CABI_DestroyObject(Object *dtor, ENode *objexpr, CABIDestroyMode mode, Boolean flag1, Boolean flag2) { + ENode *expr; + short arg; + ENodeList *list; + + switch (mode) { + case CABIDestroy2: + case CABIDestroy3: + if (flag2) + arg = 1; + else + arg = -1; + break; + case CABIDestroy1: + arg = -1; + break; + case CABIDestroy0: + arg = 0; + break; + default: + CError_FATAL(2786); + } + + expr = lalloc(sizeof(ENode)); + expr->type = EFUNCCALL; + expr->cost = 200; + expr->flags = 0; + expr->rtype = &stvoid; + expr->data.funccall.funcref = create_objectrefnode(dtor); + if (flag1) + expr->data.funccall.funcref->flags = expr->data.funccall.funcref->flags | ENODE_FLAG_80; + expr->data.funccall.functype = TYPE_FUNC(dtor->type); + dtor->flags = dtor->flags | OBJECT_USED; + + list = lalloc(sizeof(ENodeList)); + list->node = objexpr; + expr->data.funccall.args = list; + + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->next = NULL; + list->node = intconstnode(TYPE(&stsignedshort), arg); + + return expr; +} diff --git a/compiler_and_linker/FrontEnd/C/CBrowse.c b/compiler_and_linker/FrontEnd/C/CBrowse.c new file mode 100644 index 0000000..12ea4c8 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CBrowse.c @@ -0,0 +1,737 @@ +#include "compiler/CBrowse.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CompilerTools.h" +#include "compiler/Unmangle.h" +#include "compiler/objects.h" +#include "compiler/templates.h" +#include "cos.h" +#include "plugin.h" + +Boolean gUseTokenStreamSource; +Boolean gForceSourceLoc; +Boolean gUseNameTable; +static GList gBrowseData; +static GList gClassData; +static GList gMemberFuncList; +static int gNextMemberFuncID; + +enum ELanguage { + langUnknown, + langC, + langCPlus, + langPascal, + langObjectPascal, + langJava, + langAssembler, + langFortran, + langRez +}; + +enum EBrowserItem { + browseFunction, + browseGlobal, + browseClass, + browseMacro, + browseEnum, + browseTypedef, + browseConstant, + browseTemplate, + browsePackage, + browseCompSymbolStart = 0x70, + browseEnd = 0xFF +}; + +enum { + kAbstract = 1, + kStatic = 2, + kFinal = 4, + kMember = 8, + + kInterface = 0x80, + kPublic = 0x100, + + kInline = 0x80, + kPascal = 0x100, + kAsm = 0x200, + kVirtual = 0x400, + kCtor = 0x800, + kDtor = 0x1000, + kNative = 0x2000, + kSynch = 0x4000, + kIntrinsic = 0x8000, + kConst = 0x10000, + + kTransient = 0x80, + kVolatile = 0x100 +}; + +enum EAccess { + accessNone = 0, + accessPrivate = 1, + accessProtected = 2, + accessPublic = 4 +}; + +enum EMember { + memberFunction, + memberData, + memberEnd = 0xFF +}; + +enum ETemplateType { + templateClass, + templateFunction +}; + +static enum EAccess gFromAccessType[] = { + accessPublic, + accessPrivate, + accessProtected, + accessNone +}; + +typedef struct BrowseHeader { + SInt32 browse_header; + SInt32 browse_version; + SInt16 browse_language; + SInt16 uses_name_table; + SInt32 earliest_compatible_version; + SInt32 reserved[15]; +} BrowseHeader; + +// forward decls +static void RecordUndefinedMemberFunctions(void); + +void CBrowse_Setup(CompilerLinkerParamBlk *params) { + BrowseHeader hdr; + + CError_ASSERT(123, params != NULL); + + params->object.browsedata = NULL; + + InitGList(&gBrowseData, 0x10000); + InitGList(&gMemberFuncList, 1024); + + gNextMemberFuncID = 1; + gForceSourceLoc = 0; + gUseNameTable = 0; + + memclrw(&hdr, sizeof(hdr)); + hdr.browse_header = 0xBEABBAEB; + hdr.browse_version = 2; + hdr.earliest_compatible_version = 2; + hdr.browse_language = copts.cplusplus ? langCPlus : langC; + hdr.uses_name_table = gUseNameTable; + + AppendGListData(&gBrowseData, &hdr, sizeof(hdr)); +} + +void CBrowse_Finish(CompilerLinkerParamBlk *params) { + CWMemHandle hnd; + + CError_ASSERT(151, params != NULL); + + if (gBrowseData.size >= sizeof(BrowseHeader)) { + RecordUndefinedMemberFunctions(); + AppendGListByte(&gBrowseData, -1); + + COS_ResizeHandle(gBrowseData.data, gBrowseData.size); + + if (CWSecretAttachHandle(params->context, gBrowseData.data, &hnd) == cwNoErr) { + params->object.browsedata = hnd; + gBrowseData.data = NULL; + } + } +} + +void CBrowse_Cleanup(CompilerLinkerParamBlk *params) { + FreeGList(&gBrowseData); + FreeGList(&gClassData); + FreeGList(&gMemberFuncList); +} + +static void AppendGList(GList *dst, GList *src) { + SInt32 offset = dst->size; + + AppendGListNoData(dst, src->size); + memcpy(*dst->data + offset, *src->data, src->size); +} + +static void RecordName(GList *gl, const char *str, SInt32 id) { + HashNameNode *name; + + CError_ASSERT(190, gl && str && *str); + + if (id < 0 && gUseNameTable) { + for (name = name_hash_nodes[CHash(str)]; name; name = name->next) { + if (!strcmp(str, name->name)) { + id = name->id; + break; + } + } + } + + if (id >= 0 && gUseNameTable) { + AppendGListWord(gl, -1); + AppendGListLong(gl, id); + } else { + int len = strlen(str); + AppendGListWord(gl, len); + if (len) + AppendGListData(gl, str, len + 1); + } +} + +void CBrowse_BeginClass(DeclInfo *di, GList *gl) { + char *buf; + ClassList *base; + SInt32 i; + TypeClass *tclass; + + CError_ASSERT(227, di && di->thetype && gl); + + *gl = gClassData; + + if ( + !di->file || + !di->file->fileID || + !di->file->recordbrowseinfo || + !di->file2 || + !di->file2->fileID || + di->sourceoffset <= 0 + ) + { + memclrw(&gClassData, sizeof(gClassData)); + return; + } + + if (IsTempName(TYPE_CLASS(di->thetype)->classname)) { + memclrw(&gClassData, sizeof(gClassData)); + return; + } + + InitGList(&gClassData, 0x4000); + AppendGListByte(&gClassData, browseClass); + AppendGListWord(&gClassData, di->file->fileID); + AppendGListWord(&gClassData, di->file2->fileID); + AppendGListLong(&gClassData, di->sourceoffset - 1); + CError_ASSERT(270, gClassData.size == 9); + AppendGListLong(&gClassData, di->sourceoffset - 1); + AppendGListLong(&gClassData, 0); + RecordName(&gClassData, TYPE_CLASS(di->thetype)->classname->name, TYPE_CLASS(di->thetype)->classname->id); + + CMangler_MangleType(di->thetype, 0); + AppendGListByte(&name_mangle_list, 0); + + buf = lalloc(name_mangle_list.size + 1); + strcpy(buf, *name_mangle_list.data); + + while (*buf && *buf >= '0' && *buf <= '9') + buf++; + + if (strcmp(TYPE_CLASS(di->thetype)->classname->name, buf)) + RecordName(&gClassData, buf, -1); + else + AppendGListWord(&gClassData, 0); + + AppendGListLong(&gClassData, 0); + + i = 0; + base = TYPE_CLASS(di->thetype)->bases; + while (base) { + base = base->next; + i++; + } + + AppendGListByte(&gClassData, i); + + for (base = TYPE_CLASS(di->thetype)->bases; base; base = base->next) { + AppendGListByte(&gClassData, gFromAccessType[base->access]); + AppendGListByte(&gClassData, base->is_virtual); + + tclass = base->base; + if ((tclass->flags & CLASS_IS_TEMPL_INST) && !TEMPL_CLASS_INST(tclass)->is_specialized) + tclass = TYPE_CLASS(TEMPL_CLASS_INST(tclass)->templ); + + CMangler_MangleType(TYPE(tclass), 0); + AppendGListByte(&name_mangle_list, 0); + + buf = lalloc(name_mangle_list.size + 1); + strcpy(buf, *name_mangle_list.data); + + while (*buf && *buf >= '0' && *buf <= '9') + buf++; + + i = base->base->classname->id; + while (*buf && *buf >= '0' && *buf <= '9') { + i = -1; + buf++; + } + + RecordName(&gClassData, buf, i); + } +} + +void CBrowse_AddClassMemberVar(ObjMemberVar *ivar, SInt32 startOffset, SInt32 endOffset) { + short len; + + CError_ASSERT(360, ivar); + + if (gClassData.data && startOffset > 0 && endOffset >= startOffset) { + if (tk == ';') + endOffset++; + + AppendGListByte(&gClassData, memberData); + AppendGListByte(&gClassData, gFromAccessType[ivar->access]); + AppendGListLong(&gClassData, 0); + AppendGListLong(&gClassData, startOffset - 1); + AppendGListLong(&gClassData, endOffset - 1); + + len = strlen(ivar->name->name); + AppendGListWord(&gClassData, len); + AppendGListData(&gClassData, ivar->name->name, len + 1); + } +} + +void CBrowse_AddClassMemberFunction(Object *object, SInt32 startOffset, SInt32 endOffset) { + SInt32 flags; + SInt32 id; + TypeMemberFunc *tfunc; + + CError_ASSERT(380, object); + + if ( + !IsTempName(object->name) && + gClassData.data && + startOffset > 0 && + endOffset >= startOffset + ) + { + flags = 0; + CError_ASSERT(391, object->type && IS_TYPE_FUNC(object->type)); + tfunc = TYPE_METHOD(object->type); + + if (tfunc->flags & FUNC_AUTO_GENERATED) + return; + + if (object->datatype == DVFUNC) + flags |= kVirtual; + if (tfunc->flags & FUNC_PURE) + flags |= kAbstract; + if (tfunc->is_static) + flags |= kStatic; + if (tfunc->flags & FUNC_IS_CTOR) + flags |= kCtor; + if (tfunc->flags & FUNC_IS_DTOR) + flags |= kDtor; + + AppendGListByte(&gClassData, memberFunction); + AppendGListByte(&gClassData, gFromAccessType[object->access]); + AppendGListLong(&gClassData, flags); + + id = tfunc->funcid; + if (id <= 0) { + // TODO: this is not 64-bit safe + if (!(tfunc->flags & FUNC_DEFINED) || id == -1) + AppendGListLong(&gMemberFuncList, (SInt32) object); + tfunc->funcid = id = gNextMemberFuncID++; + } + + AppendGListLong(&gClassData, id); + AppendGListLong(&gClassData, startOffset - 1); + AppendGListLong(&gClassData, endOffset); + } +} + +void CBrowse_AddClassMemberData(Object *object, SInt32 startOffset, SInt32 endOffset) { + short len; + + CError_ASSERT(435, object); + + if (gClassData.data && startOffset > 0 && endOffset >= startOffset && object->datatype == DDATA) { + if (tk == ';') + endOffset++; + + AppendGListByte(&gClassData, memberData); + AppendGListByte(&gClassData, gFromAccessType[object->access]); + AppendGListLong(&gClassData, kStatic); + AppendGListLong(&gClassData, startOffset - 1); + AppendGListLong(&gClassData, endOffset - 1); + + len = strlen(object->name->name); + AppendGListWord(&gClassData, len); + AppendGListData(&gClassData, object->name->name, len + 1); + } +} + +void CBrowse_EndClass(SInt32 offset, GList *gl) { + CError_ASSERT(453, gl); + + if (gClassData.data) { + if (gClassData.size > 0) { + if (tk == ';') + offset++; + memcpy(*gClassData.data + 9, &offset, 4); + AppendGList(&gBrowseData, &gClassData); + AppendGListByte(&gBrowseData, memberEnd); + } + FreeGList(&gClassData); + } + + gClassData = *gl; +} + +void CBrowse_BeginStruct(DeclInfo *di, TypeStruct *tstruct, GList *gl) { + HashNameNode *name; + + CError_ASSERT(480, di && gl); + + *gl = gClassData; + + if ( + !di->file || + !di->file->fileID || + !di->file->recordbrowseinfo || + !di->file2 || + !di->file2->fileID || + di->sourceoffset <= 0 + ) + { + memclrw(&gClassData, sizeof(gClassData)); + return; + } + + name = tstruct->name; + if (!name || IsTempName(name)) { + memclrw(&gClassData, sizeof(gClassData)); + return; + } + + InitGList(&gClassData, 0x4000); + AppendGListByte(&gClassData, browseClass); + AppendGListWord(&gClassData, di->file->fileID); + AppendGListWord(&gClassData, di->file2->fileID); + AppendGListLong(&gClassData, di->sourceoffset - 1); + CError_ASSERT(521, gClassData.size == 9); + AppendGListLong(&gClassData, di->sourceoffset - 1); + AppendGListLong(&gClassData, 0); + RecordName(&gClassData, name->name, name->id); + AppendGListWord(&gClassData, 0); + AppendGListLong(&gClassData, 0); + AppendGListByte(&gClassData, 0); +} + +void CBrowse_AddStructMember(StructMember *member, SInt32 startOffset, SInt32 endOffset) { + short len; + + if (tk == ';') + endOffset++; + + if (gClassData.data && member && startOffset > 0 && endOffset >= startOffset) { + AppendGListByte(&gClassData, memberData); + AppendGListByte(&gClassData, accessPublic); + AppendGListLong(&gClassData, 0); + AppendGListLong(&gClassData, startOffset - 1); + AppendGListLong(&gClassData, endOffset - 1); + + len = strlen(member->name->name); + AppendGListWord(&gClassData, len); + AppendGListData(&gClassData, member->name->name, len + 1); + } +} + +void CBrowse_EndStruct(SInt32 offset, GList *gl) { + CError_ASSERT(558, gl); + + if (gClassData.data) { + if (offset > 0 && gClassData.size > 0) { + memcpy(*gClassData.data + 9, &offset, 4); + AppendGList(&gBrowseData, &gClassData); + AppendGListByte(&gBrowseData, memberEnd); + } + FreeGList(&gClassData); + } + + gClassData = *gl; +} + +static void EmitStandardData(int item, int fileID1, int fileID2, SInt32 startOffset, SInt32 endOffset, const char *str, SInt32 id, const char *str2, SInt32 id2) { + CError_ASSERT(584, str); + + AppendGListByte(&gBrowseData, item); + AppendGListWord(&gBrowseData, fileID1); + AppendGListWord(&gBrowseData, fileID2); + AppendGListLong(&gBrowseData, startOffset - 1); + AppendGListLong(&gBrowseData, endOffset - 1); + AppendGListLong(&gBrowseData, 0); + + RecordName(&gBrowseData, str, id); + if (str2 && str2 != str) + RecordName(&gBrowseData, str2, id2); + else + AppendGListWord(&gBrowseData, 0); +} + +void CBrowse_NewTypedef(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(618, file1 && file1->recordbrowseinfo); + + if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) { + EmitStandardData(browseTypedef, + file1->fileID, file2->fileID, + startOffset, endOffset, + name->name, name->id, + CError_GetQualifiedName(nspace, name), -1); + } +} + +void CBrowse_NewEnum(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(632, file1 && file1->recordbrowseinfo); + + if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) { + EmitStandardData(browseEnum, + file1->fileID, file2->fileID, + startOffset, endOffset, + name->name, name->id, + CError_GetQualifiedName(nspace, name), -1); + } +} + +void CBrowse_NewEnumConstant(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(646, file1 && file1->recordbrowseinfo); + + if (tk == ',') + endOffset++; + + if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) { + EmitStandardData(browseConstant, + file1->fileID, file2->fileID, + startOffset, endOffset, + name->name, name->id, + CError_GetQualifiedName(nspace, name), -1); + } +} + +static HashNameNode *CBrowse_GetLinkName(Object *object) { + return CMangler_GetLinkName(object); +} + +static void RecordFunction(Object *object, int fileID1, int fileID2, SInt32 startOffset, SInt32 endOffset) { + TypeFunc *tfunc; + char *tmp; + Boolean flag; + char *str29; + HashNameNode *linkname; + SInt32 flags; + char *namestr; + SInt32 nameid; + char *namestr2; + SInt32 nameid2; + int funcid; + char buf[2048]; + char buf2[256]; + + CError_ASSERT(740, object->type && IS_TYPE_FUNC(object->type)); + + if (IsTempName(object->name)) + return; + + tfunc = TYPE_FUNC(object->type); + if ((tfunc->flags & (FUNC_AUTO_GENERATED | FUNC_INTRINSIC)) && (!fileID2 || startOffset < 0)) + return; + + linkname = object->name; + tmp = linkname->name; + if (!(linkname->name[0] == '_' && linkname->name[1] == '_')) { + namestr = tmp; + nameid = linkname->id; + switch (tmp[0]) { + case '.': + nameid = -1; + namestr += 1; + break; + case '_': + switch (tmp[1]) { + case '#': + case '%': + case '@': + nameid = -1; + namestr += 2; + break; + } + break; + } + } else { + flag = 1; + if (tfunc->flags & (FUNC_IS_CTOR | FUNC_IS_DTOR)) { + tmp = TYPE_METHOD(tfunc)->theclass->classname->name; + while (*tmp >= '0' && *tmp <= '9') + tmp++; + MWUnmangleClassName(tmp, buf, sizeof(buf)); + + str29 = buf; + if ((tmp = strrchr(str29, ':'))) + str29 = tmp + 1; + + if (tfunc->flags & FUNC_IS_DTOR) { + buf2[0] = '~'; + strncpy(&buf2[1], str29, sizeof(buf2) - 1); + namestr = buf2; + } else { + namestr = str29; + } + + flag = 0; + } + + if (flag) { + MWUnmangle(object->name->name, buf, sizeof(buf)); + namestr = buf; + } + + nameid = -1; + } + + while (*namestr >= '0' && *namestr <= '9') { + nameid = -1; + namestr++; + } + + namestr2 = NULL; + nameid2 = -1; + + linkname = CBrowse_GetLinkName(object); + if (object->name != linkname) { + namestr2 = linkname->name; + if (linkname->name[0] == '.') + namestr2++; + else + nameid2 = linkname->id; + } + + EmitStandardData(browseFunction, fileID1, fileID2, startOffset, endOffset, namestr, nameid, namestr2, nameid2); + + flags = 0; + if (object->qual & Q_INLINE) + flags |= kInline; + if (object->qual & Q_PASCAL) + flags |= kPascal; + if (object->qual & Q_ASM) + flags |= kAsm; + if (object->sclass == TK_STATIC) + flags |= kStatic; + if (tfunc->flags & FUNC_METHOD) + flags |= kMember; + AppendGListLong(&gBrowseData, flags); + + funcid = 0; + if (tfunc->flags & FUNC_METHOD) { + funcid = TYPE_METHOD(tfunc)->funcid; + if (funcid <= 0) { + TYPE_METHOD(tfunc)->funcid = funcid = gNextMemberFuncID++; + } + } + AppendGListLong(&gBrowseData, funcid); +} + +void CBrowse_NewFunction(Object *object, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(890, file1 && file1->recordbrowseinfo); + + if (file2 && file2->fileID && startOffset > 0 && (endOffset + 1) >= startOffset) + RecordFunction(object, file1->fileID, file2->fileID, startOffset, endOffset + 1); +} + +void CBrowse_NewData(Object *object, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { + char *namestr = NULL; + SInt32 flags = 0; + Boolean is_const = is_const_object(object); + + CError_ASSERT(912, file1 && file1->recordbrowseinfo); + CError_ASSERT(913, object); + + if (tk == ';') + endOffset++; + + if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) { + HashNameNode *name = CBrowse_GetLinkName(object); + if (object->name != name) + namestr = name->name; + + EmitStandardData( + is_const ? browseConstant : browseGlobal, + file1->fileID, file2->fileID, + startOffset, endOffset, + object->name->name, object->name->id, + namestr, name->id + ); + + if (!is_const) { + if (object->sclass == TK_STATIC) + flags |= kStatic; + AppendGListLong(&gBrowseData, flags); + } + } +} + +void CBrowse_NewMacro(Macro *macro, CPrepFileInfo *file, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(951, !file || (file->recordbrowseinfo && !macro->is_special)); + + if (file && file->fileID && startOffset > 0 && endOffset >= startOffset) + EmitStandardData( + browseMacro, + file->fileID, file->fileID, + startOffset, endOffset, + macro->name->name, macro->name->id, + NULL, -1 + ); +} + +void CBrowse_NewTemplateClass(TemplClass *tmclass, CPrepFileInfo *file, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(965, !file || file->recordbrowseinfo); + + if (file && file->fileID && startOffset > 0 && endOffset >= startOffset) { + EmitStandardData( + browseTemplate, + file->fileID, file->fileID, + startOffset, endOffset, + tmclass->theclass.classname->name, tmclass->theclass.classname->id, + NULL, -1 + ); + AppendGListByte(&gBrowseData, templateClass); + } +} + +void CBrowse_NewTemplateFunc(TemplateFunction *tmfunc) { + CError_ASSERT(979, !tmfunc->srcfile || tmfunc->srcfile->recordbrowseinfo); + + if (tmfunc->srcfile && tmfunc->srcfile->fileID && tmfunc->startoffset > 0 && tmfunc->endoffset >= tmfunc->startoffset) { + EmitStandardData( + browseTemplate, + tmfunc->srcfile->fileID, tmfunc->srcfile->fileID, + tmfunc->startoffset, tmfunc->endoffset, + tmfunc->name->name, tmfunc->name->id, + NULL, -1 + ); + AppendGListByte(&gBrowseData, templateFunction); + } +} + +static void RecordUndefinedMemberFunctions(void) { + int i; + int count; + Object **array; + + COS_LockHandleHi(gMemberFuncList.data); + + count = gMemberFuncList.size / sizeof(Object *); + array = (Object **) *gMemberFuncList.data; + for (i = 0; i < count; i++, array++) { + if (IS_TYPE_FUNC((*array)->type) && !(TYPE_FUNC((*array)->type)->flags & FUNC_DEFINED)) + RecordFunction(*array, 0, 0, -1, -1); + } + + COS_UnlockHandle(gMemberFuncList.data); +} diff --git a/compiler_and_linker/FrontEnd/C/CClass.c b/compiler_and_linker/FrontEnd/C/CClass.c new file mode 100644 index 0000000..fad276e --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CClass.c @@ -0,0 +1,2312 @@ +#include "compiler/CClass.h" +#include "compiler/CABI.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CInit.h" +#include "compiler/CInline.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CObjC.h" +#include "compiler/CParser.h" +#include "compiler/CRTTI.h" +#include "compiler/CSOM.h" +#include "compiler/CompilerTools.h" +#include "compiler/CodeGen.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct OVClassBase { + struct OVClassBase *next; + struct OVClass *ovclass; + Boolean is_virtual; +} OVClassBase; + +typedef struct OVFunc { + struct OVFunc *next; + Object *obj; + struct OVClass *ovc8; + struct OVFunc *ovfC; + struct OVFunc *ovf10; +} OVFunc; + +typedef struct OVClass { + TypeClass *tclass; + OVFunc *vfuncs; + OVClassBase *bases; + SInt32 offset; + SInt32 voffset; + Boolean alloced_vtable; +} OVClass; + +typedef struct ThunkList { + struct ThunkList *next; + Object *thunkobj; + Object *obj; + SInt32 a; + SInt32 b; + SInt32 c; +} ThunkList; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static TypeClass *main_class; +static ThunkList *cclass_thunklist; +static TypeClass *cclass_isbase_mostderived; +static SInt32 cclass_isbase_foundoffset; +static Boolean cclass_isambigbase; +static short cclass_founddepth; +static char *vtable_object_data; +static SInt32 vtable_data_size; +static OLinkList *vtable_object_links; +static TypeClass *cclass_vbase; +static OVClass *cclass_ovbase; +static OVClass *cclass_root; +static Object *found_pure; +static Boolean check_pures; +static Object *cclass_dominator_vobject; +static SInt32 cclass_dominator_voffset; +static Object *cclass_dominator_oobject; +static TypeClass *cclass_dominator_oclass; +static SInt32 cclass_dominator_ooffset; +static Object *cclass_dominator_eobject; + +void CClass_Init(void) { + cclass_thunklist = NULL; +} + +void CClass_GenThunks(void) { + ThunkList *list; + + for (list = cclass_thunklist; list; list = list->next) { + list->thunkobj->flags |= OBJECT_DEFINED; + CodeGen_GenVDispatchThunk(list->thunkobj, list->obj, list->a, list->b, list->c); + } +} + +static Object *CClass_ThunkObject(Object *obj, SInt32 a, SInt32 b, SInt32 c) { + Object *thunkobj; + ThunkList *list; + + CInline_ObjectAddrRef(obj); + for (list = cclass_thunklist; list; list = list->next) { + if (obj == list->obj && a == list->a && b == list->b && c == list->c) + return list->thunkobj; + } + + thunkobj = CParser_NewCompilerDefFunctionObject(); + thunkobj->name = CMangler_ThunkName(obj, a, b, c); + thunkobj->type = TYPE(&rt_func); + thunkobj->sclass = TK_EXTERN; + thunkobj->qual = Q_20000; + thunkobj->u.func.linkname = thunkobj->name; + + list = galloc(sizeof(ThunkList)); + list->thunkobj = thunkobj; + list->obj = obj; + list->a = a; + list->b = b; + list->c = c; + list->next = cclass_thunklist; + cclass_thunklist = list; + + return thunkobj; +} + +static Boolean CClass_IsZeroOffsetClass(TypeClass *a, TypeClass *b) { + while (1) { + if (a == b) + return 1; + + if (!a->bases || a->bases->is_virtual) + return 0; + + a = a->bases->base; + } +} + +static UInt8 CClass_IsCovariantResult(Type *a, UInt32 qualA, Type *b, UInt32 qualB, Boolean errorflag) { + TypeClass *tclassA; + TypeClass *tclassB; + + if ( + IS_TYPE_POINTER_ONLY(a) && + IS_TYPE_POINTER_ONLY(b) && + TPTR_QUAL(a) == TPTR_QUAL(b) && + !CParser_IsMoreCVQualified(qualB, qualA) && + IS_TYPE_CLASS(TPTR_TARGET(a)) && + IS_TYPE_CLASS(TPTR_TARGET(b)) + ) + { + tclassA = TYPE_CLASS(TPTR_TARGET(a)); + tclassB = TYPE_CLASS(TPTR_TARGET(b)); + if (tclassA == tclassB || CClass_IsBaseClass(tclassB, tclassA, NULL, errorflag, errorflag)) { + if (!CClass_IsZeroOffsetClass(tclassB, tclassA)) + return 2; + else + return 1; + } + } + + return 0; +} + +UInt8 CClass_GetOverrideKind(TypeFunc *a, TypeFunc *b, Boolean errorflag) { + if (!a->args || !b->args) + return 0; + + if ( + (a->flags & FUNC_CALL_CONV_MASK) != (b->flags & FUNC_CALL_CONV_MASK) || + !is_arglistsame(a->args->next, b->args->next) || + a->args->qual != b->args->qual + ) + return 0; + + if (!is_typesame(a->functype, b->functype)) { + switch (CClass_IsCovariantResult(a->functype, a->qual, b->functype, b->qual, errorflag)) { + case 0: + if (errorflag) + CError_Error(CErrorStr227); + return 0; + case 1: + return 1; + case 2: + return 2; + default: + CError_FATAL(225); + } + } + + return 1; +} + +Boolean CClass_IsEmpty(TypeClass *tclass) { + ClassList *base; + + if (tclass->ivars) + return 0; + + for (base = tclass->bases; base; base = base->next) { + if (!CClass_IsEmpty(base->base)) + return 0; + } + + return 1; +} + +Boolean CClass_IsNonStaticMemberFunc(TypeFunc *tfunc) { + return IS_TYPEFUNC_NONSTATIC_METHOD(tfunc) || (tfunc->flags & FUNC_FLAGS_80); +} + +Object *CClass_DefaultConstructor(TypeClass *tclass) { + NameSpaceObjectList *nsol; + Object *object; + + for (nsol = CScope_FindName(tclass->nspace, constructor_name_node); nsol; nsol = nsol->next) { + object = OBJECT(nsol->object); + if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type)) { + if ((tclass->flags & CLASS_HAS_VBASES) && !tclass->sominfo) { + if (TYPE_FUNC(object->type)->args->next && !TYPE_FUNC(object->type)->args->next->next) + return object; + } else { + if (!TYPE_FUNC(object->type)->args->next) + return object; + } + } + } + + return NULL; +} + +Object *CClass_DummyDefaultConstructor(TypeClass *tclass) { + Object *ctor; + FuncArg *args; + NameSpaceObjectList *nsol; + HashNameNode *name; + TypeMemberFunc *tmethod; + Object *object; + ObjectList list; + + ctor = NULL; + + for (nsol = CScope_FindName(tclass->nspace, constructor_name_node); nsol; nsol = nsol->next) { + object = OBJECT(nsol->object); + if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type)) { + CError_ASSERT(305, args = TYPE_FUNC(object->type)->args); + args = args->next; + if ((tclass->flags & CLASS_HAS_VBASES) && !tclass->sominfo) { + CError_ASSERT(309, args); + args = args->next; + } + CError_ASSERT(312, args); + + if (args->dexpr) { + if (ctor) { + list.next = NULL; + list.object = object; + CError_OverloadedFunctionError(ctor, &list); + break; + } + ctor = object; + } + } + } + + if (!ctor) { + CError_Error(CErrorStr203); + return NULL; + } + + name = GetHashNameNodeExport("__defctor"); + if ((nsol = CScope_FindName(tclass->nspace, name))) { + CError_ASSERT(339, nsol->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(nsol->object)->type)); + return OBJECT(nsol->object); + } + + tmethod = galloc(sizeof(TypeMemberFunc)); + memclrw(tmethod, sizeof(TypeMemberFunc)); + + tmethod->type = TYPEFUNC; + tmethod->functype = TYPE(&void_ptr); + tmethod->flags = FUNC_METHOD; + tmethod->theclass = tclass; + CDecl_SetFuncFlags(TYPE_FUNC(tmethod), 0); + + if ((tclass->flags & CLASS_HAS_VBASES) && !tclass->sominfo) + CDecl_AddArgument(TYPE_FUNC(tmethod), TYPE(&stsignedshort)); + + CDecl_AddThisPointerArgument(TYPE_FUNC(tmethod), tclass); + + object = CParser_NewCompilerDefFunctionObject(); + object->type = TYPE(tmethod); + object->qual = Q_INLINE | Q_MANGLE_NAME; + object->nspace = tclass->nspace; + object->name = name; + + CScope_AddObject(tclass->nspace, name, OBJ_BASE(object)); + CParser_RegisterDummyCtorFunction(object, ctor); + return object; +} + +ENode *CClass_DefaultConstructorCall(TypeClass *tclass, TypeClass *b, ENode *objexpr, SInt32 varg, Boolean flag1, Boolean flag2, Boolean *errorflag) { + NameSpaceObjectList *nsol; + Object *ctor; + Object *object; + FuncArg *args; + ENodeList *argexprs; + ENode *expr; + BClassList *path; + BClassList list1; + ObjectList objlist; + BClassList list2; + short founddepth; + Boolean isambigbase; + + *errorflag = 0; + + if (!(nsol = CScope_FindName(tclass->nspace, constructor_name_node))) + return NULL; + + ctor = NULL; + do { + object = OBJECT(nsol->object); + if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type)) { + CError_ASSERT(397, args = TYPE_FUNC(object->type)->args); + + args = args->next; + + if ((tclass->flags & CLASS_HAS_VBASES) && !tclass->sominfo) { + CError_ASSERT(401, args); + args = args->next; + } + + if (!args || args->dexpr) { + if (ctor) { + objlist.next = NULL; + objlist.object = object; + CError_OverloadedFunctionError(ctor, &objlist); + break; + } + ctor = object; + } + } + } while ((nsol = nsol->next)); + + if (!ctor) { + *errorflag = 1; + return NULL; + } + + if (flag1) { + if (b) { + if (flag2) { + if ((path = CClass_GetBasePath(b, tclass, &founddepth, &isambigbase))) + list1 = *path; + else + goto skipCheck; + } else { + list1.next = &list2; + list1.type = TYPE(b); + list2.next = NULL; + list2.type = TYPE(tclass); + } + } else { + list1.next = NULL; + list1.type = TYPE(tclass); + } + CClass_CheckPathAccess(&list1, ctor, ctor->access); + } + +skipCheck: + if ((tclass->flags & CLASS_HAS_VBASES) && !tclass->sominfo) { + argexprs = lalloc(sizeof(ENodeList)); + argexprs->next = NULL; + argexprs->node = intconstnode(TYPE(&stsignedshort), varg); + } else { + argexprs = NULL; + } + + CError_ASSERT(471, IS_TYPE_POINTER_ONLY(objexpr->rtype)); + + objexpr = makemonadicnode(objexpr, EINDIRECT); + objexpr->rtype = TYPE(tclass); + + list1.next = NULL; + list1.type = TYPE(tclass); + + expr = CExpr_GenericFuncCall( + &list1, + objexpr, + 0, + ctor, + NULL, + NULL, + argexprs, + 0, + 0, + 0 + ); + + if (ENODE_IS2(expr, EFUNCCALL, EFUNCCALLP)) + expr->rtype = CDecl_NewPointerType(TYPE(tclass)); + + return expr; +} + +Object *CClass_AssignmentOperator(TypeClass *tclass) { + NameSpaceObjectList *nsol; + Object *object; + + for (nsol = CScope_FindName(tclass->nspace, asop_name_node); nsol; nsol = nsol->next) { + object = OBJECT(nsol->object); + if ( + object->otype == OT_OBJECT && + IS_TYPE_FUNC(object->type) && + TYPE_FUNC(object->type)->args && + TYPE_FUNC(object->type)->args->next && + !TYPE_FUNC(object->type)->args->next->next + ) + { + if ( + IS_TYPE_CLASS(TYPE_FUNC(object->type)->args->next->type) && + TYPE_CLASS(TYPE_FUNC(object->type)->args->next->type) == tclass + ) + return object; + + if ( + IS_TYPE_REFERENCE(TYPE_FUNC(object->type)->args->next->type) && + TPTR_TARGET(TYPE_FUNC(object->type)->args->next->type) == TYPE(tclass) + ) + return object; + } + } + + return NULL; +} + +Object *CClass_CopyConstructor(TypeClass *tclass) { + NameSpaceObjectList *nsol; + Object *object; + FuncArg *args; + + if (tclass->sominfo) + return NULL; + + for (nsol = CScope_FindName(tclass->nspace, constructor_name_node); nsol; nsol = nsol->next) { + object = OBJECT(nsol->object); + if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type)) { + CError_ASSERT(532, args = TYPE_FUNC(object->type)->args); + + args = args->next; + + if (tclass->flags & CLASS_HAS_VBASES) { + CError_ASSERT(536, args); + args = args->next; + } + + if ( + args && + args != &elipsis && + (!args->next || args->next->dexpr) && + IS_TYPE_REFERENCE(args->type) && + TPTR_TARGET(args->type) == TYPE(tclass) + ) + return object; + } + } + + return NULL; +} + +NameSpaceObjectList *CClass_MemberObject(TypeClass *tclass, HashNameNode *name) { + NameSpaceObjectList *nsol; + + if ((nsol = CScope_FindName(tclass->nspace, name)) && nsol->object->otype == OT_OBJECT) + return nsol; + + return NULL; +} + +NameSpaceObjectList *CClass_Constructor(TypeClass *tclass) { + NameSpaceObjectList *nsol; + + if ( + (nsol = CScope_FindName(tclass->nspace, constructor_name_node)) && + nsol->object->otype == OT_OBJECT && + IS_TYPE_FUNC(OBJECT(nsol->object)->type) + ) + return nsol; + + return NULL; +} + +Object *CClass_Destructor(TypeClass *tclass) { + NameSpaceObjectList *nsol; + + for (nsol = CScope_FindName(tclass->nspace, destructor_name_node); nsol; nsol = nsol->next) { + if ( + nsol->object->otype == OT_OBJECT && + IS_TYPE_FUNC(OBJECT(nsol->object)->type) + ) + return OBJECT(nsol->object); + } + + return NULL; +} + +Boolean CClass_IsConstructor(Object *obj) { + return obj && IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_IS_CTOR); +} + +Boolean CClass_IsDestructor(Object *obj) { + return obj && IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_IS_DTOR); +} + +Boolean CClass_IsPODClass(TypeClass *tclass) { + NameSpaceObjectList *nsol; + Object *object; + ObjMemberVar *ivar; + Type *type; + + if (tclass->vtable || tclass->bases || CClass_Destructor(tclass)) + return 0; + + for (nsol = CClass_Constructor(tclass); nsol; nsol = nsol->next) { + if ( + nsol->object->otype == OT_OBJECT && + IS_TYPE_FUNC(OBJECT(nsol->object)->type) && + !(TYPE_FUNC(OBJECT(nsol->object)->type)->flags & FUNC_AUTO_GENERATED) + ) + return 0; + } + + object = CClass_AssignmentOperator(tclass); + if (object && !(TYPE_FUNC(object->type)->flags & FUNC_AUTO_GENERATED)) + return 0; + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + if (ivar->access != ACCESSPUBLIC) + return 0; + + type = ivar->type; + while (IS_TYPE_ARRAY(type)) + type = TPTR_TARGET(type); + + switch (type->type) { + case TYPECLASS: + if (!CClass_IsPODClass(TYPE_CLASS(type))) + return 0; + break; + case TYPEMEMBERPOINTER: + return 0; + case TYPEPOINTER: + if (TPTR_QUAL(type) & Q_REFERENCE) + return 0; + break; + } + } + + return 1; +} + +Boolean CClass_IsTrivialCopyClass(TypeClass *tclass) { + Object *object; + ClassList *base; + ObjMemberVar *ivar; + Type *type; + + if (tclass->vtable || tclass->vbases || CClass_Destructor(tclass)) + return 0; + + object = CClass_CopyConstructor(tclass); + if (object && IS_TYPE_FUNC(object->type) && !(TYPE_FUNC(object->type)->flags & FUNC_AUTO_GENERATED)) + return 0; + + for (base = tclass->bases; base; base = base->next) { + if (!CClass_IsTrivialCopyClass(base->base)) + return 0; + } + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + type = ivar->type; + while (IS_TYPE_ARRAY(type)) + type = TPTR_TARGET(type); + + if (IS_TYPE_CLASS(type) && !CClass_IsTrivialCopyClass(TYPE_CLASS(type))) + return 0; + } + + return 1; +} + +Boolean CClass_IsTrivialCopyAssignClass(TypeClass *tclass) { + Object *object; + ObjMemberVar *ivar; + Type *type; + + if (tclass->vtable || tclass->bases || CClass_Destructor(tclass)) + return 0; + + object = CClass_AssignmentOperator(tclass); + if (object && !(TYPE_FUNC(object->type)->flags & FUNC_AUTO_GENERATED)) + return 0; + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + type = ivar->type; + while (IS_TYPE_ARRAY(type)) + type = TPTR_TARGET(type); + + if (IS_TYPE_REFERENCE(type)) + return 0; + if (CParser_IsConst(type, ivar->qual)) + return 0; + if (IS_TYPE_CLASS(type) && !CClass_IsTrivialCopyAssignClass(TYPE_CLASS(type))) + return 0; + } + + return 1; +} + +Boolean CClass_ReferenceArgument(TypeClass *tclass) { + if ((tclass->flags & (CLASS_COMPLETED | CLASS_IS_TEMPL_INST)) == CLASS_IS_TEMPL_INST) + CDecl_CompleteType(TYPE(tclass)); + + if (copts.simple_class_byval) + return !CClass_IsTrivialCopyClass(tclass); + + return CClass_Destructor(tclass) || CClass_CopyConstructor(tclass); +} + +BClassList *CClass_GetPathCopy(BClassList *path, Boolean is_global) { + BClassList *last; + BClassList *copy; + + if (!path) + return NULL; + + copy = last = is_global ? galloc(sizeof(BClassList)) : lalloc(sizeof(BClassList)); + last->next = path->next; + last->type = path->type; + + while ((path = path->next)) { + last->next = is_global ? galloc(sizeof(BClassList)) : lalloc(sizeof(BClassList)); + last = last->next; + last->next = path->next; + last->type = path->type; + } + + return copy; +} + +BClassList *CClass_AppendPath(BClassList *dest, BClassList *src) { + BClassList *last; + + if (!(last = dest)) + return src; + + while (last->next) + last = last->next; + + while (src && src->type == last->type) + src = src->next; + + last->next = src; + return dest; +} + +static AccessType CClass_GetPathAccess(BClassList *path) { + AccessType result; + ClassList *base; + TypeClass *tclass; + + CError_ASSERT(930, path); + + result = ACCESSPUBLIC; + + while (1) { + tclass = TYPE_CLASS(path->type); + if (!(path = path->next)) + break; + + for (base = tclass->bases; base; base = base->next) { + if (base->base == TYPE_CLASS(path->type)) + break; + } + + CError_ASSERT(939, base); + + switch (base->access) { + case ACCESSPUBLIC: + break; + case ACCESSPROTECTED: + if (result == ACCESSPUBLIC) + result = ACCESSPROTECTED; + break; + case ACCESSPRIVATE: + if (result == ACCESSPUBLIC || result == ACCESSPROTECTED) + result = ACCESSPRIVATE; + else + return ACCESSNONE; + break; + case ACCESSNONE: + return ACCESSNONE; + default: + CError_FATAL(960); + } + } + + return result; +} + +Boolean CClass_IsMoreAccessiblePath(BClassList *path1, BClassList *path2) { + switch (CClass_GetPathAccess(path2)) { + case ACCESSPUBLIC: + return 0; + case ACCESSNONE: + return 1; + default: + CError_FATAL(978); + case ACCESSPROTECTED: + switch (CClass_GetPathAccess(path1)) { + case ACCESSPUBLIC: + return 1; + case ACCESSPRIVATE: + case ACCESSPROTECTED: + case ACCESSNONE: + return 0; + default: + CError_FATAL(987); + } + case ACCESSPRIVATE: + switch (CClass_GetPathAccess(path1)) { + case ACCESSPUBLIC: + case ACCESSPROTECTED: + return 1; + case ACCESSPRIVATE: + case ACCESSNONE: + return 0; + default: + CError_FATAL(997); + } + } + + return 0; +} + +static BClassList *CClass_GetBasePathRec(TypeClass *a, TypeClass *b, SInt32 offset, short depth) { + ClassList *base; + BClassList *checkpath; + BClassList *bestpath; + BClassList *newpath; + SInt32 newOffset; + + for (base = a->bases, bestpath = NULL; base; base = base->next) { + if (base->is_virtual) + newOffset = CClass_VirtualBaseOffset(cclass_isbase_mostderived, base->base); + else + newOffset = offset + base->offset; + + if (base->base == b) { + if (cclass_founddepth && newOffset != cclass_isbase_foundoffset) { + cclass_isambigbase = 1; + return NULL; + } + + cclass_isbase_foundoffset = newOffset; + cclass_founddepth = depth; + + bestpath = lalloc(sizeof(BClassList)); + bestpath->next = NULL; + bestpath->type = TYPE(b); + } else if ((checkpath = CClass_GetBasePathRec(base->base, b, newOffset, depth + 1))) { + newpath = lalloc(sizeof(BClassList)); + newpath->next = checkpath; + newpath->type = TYPE(base->base); + if (!bestpath || CClass_IsMoreAccessiblePath(newpath, bestpath)) + bestpath = newpath; + } + } + + return bestpath; +} + +BClassList *CClass_GetBasePath(TypeClass *a, TypeClass *b, short *founddepth, Boolean *isambigbase) { + BClassList *path; + BClassList *result; + + if ((a->flags & (CLASS_COMPLETED | CLASS_IS_TEMPL_INST)) == CLASS_IS_TEMPL_INST) + CDecl_CompleteType(TYPE(a)); + if ((b->flags & (CLASS_COMPLETED | CLASS_IS_TEMPL_INST)) == CLASS_IS_TEMPL_INST) + CDecl_CompleteType(TYPE(b)); + + cclass_founddepth = 0; + cclass_isbase_mostderived = a; + cclass_isbase_foundoffset = -1; + cclass_isambigbase = 0; + + if ((path = CClass_GetBasePathRec(a, b, 0, 1))) { + *founddepth = cclass_founddepth; + *isambigbase = cclass_isambigbase; + + result = lalloc(sizeof(BClassList)); + result->next = path; + result->type = TYPE(a); + return result; + } else { + *isambigbase = 0; + return NULL; + } +} + +Boolean CClass_IsBaseClass(TypeClass *a, TypeClass *b, short *founddepth, Boolean pathcheckflag, Boolean ambigerrorflag) { + BClassList *path; + short depth; + Boolean isambigbase; + + if ((path = CClass_GetBasePath(a, b, &depth, &isambigbase))) { + if (isambigbase && ambigerrorflag) + CError_Error(CErrorStr188); + + if (pathcheckflag) + CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); + + if (founddepth) + *founddepth = depth; + + return 1; + } + + return 0; +} + +TypeClass *CClass_GetQualifiedClass(void) { + DeclInfo di; + + memclrw(&di, sizeof(di)); + CParser_GetDeclSpecs(&di, 0); + + if (IS_TYPE_CLASS(di.thetype)) + return TYPE_CLASS(di.thetype); + + return NULL; +} + +ENode *CClass_AccessPathCast(BClassList *path, ENode *expr, Boolean reverse) { + ClassList *base; + SInt32 offset; + + while (path && path->next) { + base = TYPE_CLASS(path->type)->bases; + while (1) { + if (base->base == TYPE_CLASS(path->next->type)) + break; + CError_ASSERT(1157, base = base->next); + } + + if (base->is_virtual) { + if (reverse) { + CError_Error(CErrorStr164); + break; + } + + if (!base->base->sominfo) { + offset = base->offset; + if (offset && !canadd(expr, offset)) { + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); + optimizecomm(expr); + } + + expr->rtype = CDecl_NewPointerType(CDecl_NewPointerType(TYPE(base->base))); + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = expr->data.monadic->rtype; + } + } else { + offset = base->offset; + if (offset) { + if (reverse) + offset = -offset; + if (!canadd(expr, offset)) { + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); + optimizecomm(expr); + } + } + } + + path = path->next; + } + + return expr; +} + +ENode *CClass_ClassPointerCast(ENode *expr, TypeClass *a, TypeClass *b, Boolean typconflag, Boolean ambigerrorflag, Boolean pathcheckflag) { + BClassList *path; + Boolean reverse; + short depth; + Boolean isambigbase; + + reverse = 0; + + if (a != b) { + if (!(path = CClass_GetBasePath(a, b, &depth, &isambigbase))) { + CError_ASSERT(1216, typconflag); + if ((path = CClass_GetBasePath(b, a, &depth, &isambigbase))) { + reverse = 1; + goto doCast; + } + } else { + doCast: + if (isambigbase && ambigerrorflag) + CError_Error(CErrorStr188); + if (pathcheckflag) + CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); + if (!(a->flags & CLASS_SINGLE_OBJECT) && !b->sominfo) + expr = CClass_AccessPathCast(path, expr, reverse); + } + } + + if (typconflag && ENODE_IS(expr, EINDIRECT) && IS_TYPE_POINTER_ONLY(expr->rtype)) + expr = makemonadicnode(expr, ETYPCON); + + return expr; +} + +ENode *CClass_DirectBasePointerCast(ENode *expr, TypeClass *a, TypeClass *b) { + ClassList *base; + VClassList *vbase; + BClassList *path; + BClassList list1; + BClassList list2; + short depth; + Boolean isambigbase; + + for (base = a->bases; base; base = base->next) { + if (base->base == b) { + list1.next = &list2; + list1.type = TYPE(a); + list2.next = NULL; + list2.type = TYPE(b); + return CClass_AccessPathCast(&list1, expr, 0); + } + } + + for (vbase = a->vbases; vbase; vbase = vbase->next) { + if (vbase->base == b) { + CError_ASSERT(1273, path = CClass_GetBasePath(a, b, &depth, &isambigbase)); + return CClass_AccessPathCast(path, expr, 0); + } + } + + CError_FATAL(1277); + return expr; +} + +SInt32 CClass_GetPathOffset(BClassList *path) { + SInt32 offset; + ClassList *base; + + offset = 0; + + while (path->next) { + if (path->type != path->next->type) { + for (base = TYPE_CLASS(path->type)->bases; base; base = base->next) { + if (base->base == TYPE_CLASS(path->next->type)) + break; + } + + if (!base) { + CError_Error(CErrorStr221); + return offset; + } + } + + if (base->is_virtual) + return -1; + offset += base->offset; + + path = path->next; + } + + return offset; +} + +Boolean CClass_ClassDominates(TypeClass *tclass, TypeClass *baseclass) { + ClassList *base; + + for (base = tclass->bases; base; base = base->next) { + if (base->base == baseclass || CClass_ClassDominates(base->base, baseclass)) + return 1; + } + + return 0; +} + +SInt32 CClass_VirtualBaseOffset(TypeClass *tclass, TypeClass *baseclass) { + VClassList *vbase; + + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + if (vbase->base == baseclass) + return vbase->offset; + } + + CError_FATAL(1342); + return 0; +} + +SInt32 CClass_VirtualBaseVTableOffset(TypeClass *tclass, TypeClass *baseclass) { + VClassList *vbase; + + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + if (vbase->base == baseclass) + return vbase->voffset; + } + + CError_FATAL(1359); + return 0; +} + +SInt32 CClass_GetMemberOffset(TypeClass *tclass, HashNameNode *name, ObjMemberVar **resultIvar) { + ObjMemberVar *ivar; + ClassList *base; + SInt32 offset; + SInt32 tmp; + Boolean foundflag; + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + if (ivar->name == name) { + if (resultIvar) + *resultIvar = ivar; + return ivar->offset; + } + } + + for (base = tclass->bases, foundflag = 0; base; base = base->next) { + switch ((tmp = CClass_GetMemberOffset(base->base, name, resultIvar))) { + case -3: + case -2: + return tmp; + case -1: + break; + default: + if (base->is_virtual) + return -3; + if (foundflag) + return -2; + foundflag = 1; + offset = base->offset + tmp; + } + } + + return foundflag ? offset : -1; +} + +Boolean CClass_OverridesBaseMember(TypeClass *tclass, HashNameNode *name, Object *obj) { + NameSpaceObjectList *nsol; + ClassList *base; + Boolean result; + + result = 0; + for (base = tclass->bases; base; base = base->next) { + if (base->base->vtable) { + for (nsol = CScope_FindName(base->base->nspace, name); nsol; nsol = nsol->next) { + if ( + nsol->object->otype == OT_OBJECT && + OBJECT(nsol->object)->datatype == DVFUNC && + CClass_GetOverrideKind(TYPE_FUNC(OBJECT(nsol->object)->type), TYPE_FUNC(obj->type), 1) + ) + result = 1; + } + + if (CClass_OverridesBaseMember(base->base, name, obj)) + result = 1; + } + } + + return result; +} + +static OVClass *CClass_FindOVClass(OVClass *ovclass, TypeClass *tclass, SInt32 offset) { + OVClassBase *ovbase; + + if (ovclass->tclass == tclass && ovclass->offset == offset) + return ovclass; + + for (ovbase = ovclass->bases; ovbase; ovbase = ovbase->next) { + if ((ovclass = CClass_FindOVClass(ovbase->ovclass, tclass, offset))) + return ovclass; + } + + return NULL; +} + +static OVClass *CClass_BuildOVClassTree(OVClass *root, TypeClass *tclass, SInt32 offset, SInt32 voffset) { + ClassList *base; + Object *object; + OVClass *tree; + OVFunc *ovfunc; + OVClassBase *ovbase; + SInt32 vboffset; + SInt32 vbvoffset; + CScopeObjectIterator iter; + + tree = lalloc(sizeof(OVClass)); + memclrw(tree, sizeof(OVClass)); + + tree->tclass = tclass; + tree->offset = offset; + tree->voffset = voffset; + if (!root) + root = tree; + + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (object->datatype == DVFUNC) { + ovfunc = lalloc(sizeof(OVFunc)); + memclrw(ovfunc, sizeof(OVFunc)); + + ovfunc->next = tree->vfuncs; + ovfunc->obj = object; + tree->vfuncs = ovfunc; + } + } + + for (base = tclass->bases; base; base = base->next) { + if (base->base->vtable || base->base->sominfo) { + ovbase = lalloc(sizeof(OVClassBase)); + memclrw(ovbase, sizeof(OVClassBase)); + + if (base->is_virtual) { + vboffset = CClass_VirtualBaseOffset(main_class, base->base); + if (!(ovbase->ovclass = CClass_FindOVClass(root, base->base, vboffset))) { + vbvoffset = CClass_VirtualBaseVTableOffset(main_class, base->base); + ovbase->ovclass = CClass_BuildOVClassTree(root, base->base, vboffset, vbvoffset); + } + ovbase->is_virtual = 1; + } else { + ovbase->ovclass = CClass_BuildOVClassTree( + root, + base->base, + offset + base->offset, + voffset + base->voffset); + ovbase->is_virtual = 0; + } + + ovbase->next = tree->bases; + tree->bases = ovbase; + } + } + + return tree; +} + +static Boolean CClass_IsBaseOf(OVClass *a, OVClass *b) { + OVClassBase *ovbase; + + for (ovbase = b->bases; ovbase; ovbase = ovbase->next) { + if ( + (ovbase->ovclass->tclass == a->tclass && ovbase->ovclass->offset == a->offset) || + CClass_IsBaseOf(a, ovbase->ovclass) + ) + { + if (!cclass_ovbase && ovbase->is_virtual) + cclass_ovbase = ovbase->ovclass; + return 1; + } + } + + return 0; +} + +static void CClass_FindOVFunc(OVClass *a, OVClass *b, OVFunc *func) { + OVFunc *scan; + OVClassBase *ovbase; + UInt8 overrideKind; + + if (CClass_IsBaseOf(b, a)) { + for (scan = a->vfuncs; scan; scan = scan->next) { + if ( + (func->obj->name == scan->obj->name) && + (overrideKind = CClass_GetOverrideKind(TYPE_FUNC(func->obj->type), TYPE_FUNC(scan->obj->type), 0)) + ) + { + if (func->ovc8) { + if (func->ovc8->tclass == a->tclass || CClass_ClassDominates(func->ovc8->tclass, a->tclass)) + return; + if (!CClass_ClassDominates(a->tclass, func->ovc8->tclass)) { + func->ovf10 = scan; + return; + } + } + + if (a == cclass_root) { + TYPE_FUNC(scan->obj->type)->flags |= FUNC_FLAGS_20; + if (overrideKind == 2) + TYPE_FUNC(scan->obj->type)->flags |= FUNC_FLAGS_400000; + } + + func->ovc8 = a; + func->ovfC = scan; + func->ovf10 = NULL; + return; + } + } + + for (ovbase = a->bases; ovbase; ovbase = ovbase->next) + CClass_FindOVFunc(ovbase->ovclass, b, func); + } +} + +static TypeList *CClass_GetCoVariantClassList(TypeList *list, TypeClass *tclass, Object *func, Boolean flag) { + Object *object; + TypeList *scan; + Type *type; + ClassList *base; + CScopeObjectIterator iter; + + if (!flag) { + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if ( + object->name == func->name && + object->datatype == DVFUNC && + CClass_GetOverrideKind(TYPE_FUNC(object->type), TYPE_FUNC(func->type), 0) == 2 + ) + { + CError_ASSERT(1686, + IS_TYPE_POINTER_ONLY(TYPE_FUNC(object->type)->functype) && + IS_TYPE_CLASS(TPTR_TARGET(TYPE_FUNC(object->type)->functype))); + + type = TPTR_TARGET(TYPE_FUNC(object->type)->functype); + for (scan = list; scan; scan = scan->next) { + if (scan->type == type) + break; + } + + if (!scan) { + scan = lalloc(sizeof(TypeList)); + scan->type = type; + scan->next = list; + list = scan; + } + } + } + } + + for (base = tclass->bases; base; base = base->next) { + if (base->base->vtable) + list = CClass_GetCoVariantClassList(list, base->base, func, 0); + } + + return list; +} + +static TypeMemberFunc *CClass_GetCovariantType(TypeMemberFunc *tmethod, Type *type) { + TypePointer *tptr; + TypeMemberFunc *result; + + CError_ASSERT(1724, + IS_TYPE_METHOD(tmethod) && + IS_TYPE_POINTER_ONLY(tmethod->functype)); + + tptr = galloc(sizeof(TypePointer)); + *tptr = *TYPE_POINTER(tmethod->functype); + tptr->target = type; + + result = galloc(sizeof(TypeMemberFunc)); + *result = *tmethod; + result->flags &= ~(FUNC_FLAGS_20 | FUNC_FLAGS_400000); + result->functype = TYPE(tptr); + return result; +} + +static Object *CClass_FindCovariantFunction(Object *func, Type *type) { + NameSpaceObjectList *nsol; + + nsol = CScope_FindName( + TYPE_METHOD(func->type)->theclass->nspace, + CMangler_GetCovariantFunctionName(func, TYPE_CLASS(type))); + + CError_ASSERT(1754, nsol && !nsol->next && nsol->object->otype == OT_OBJECT); + + return OBJECT(nsol->object); +} + +static ObjectList *CClass_DeclareCovariantFuncs(ObjectList *list, Object *func, TypeClass *tclass) { + Object *newfunc; + HashNameNode *name; + TypeList *types; + ObjectList *newlist; + + for (types = CClass_GetCoVariantClassList(NULL, tclass, func, 1); types; types = types->next) { + name = CMangler_GetCovariantFunctionName(func, TYPE_CLASS(types->type)); + + newfunc = galloc(sizeof(Object)); + memclrw(newfunc, sizeof(Object)); + + newfunc->otype = OT_OBJECT; + newfunc->datatype = DFUNC; + newfunc->section = func->section; + newfunc->nspace = func->nspace; + newfunc->name = name; + newfunc->type = TYPE(CClass_GetCovariantType(TYPE_METHOD(func->type), types->type)); + newfunc->qual = func->qual & ~Q_INLINE; + newfunc->sclass = func->sclass; + newfunc->u.func.linkname = name; + + newlist = lalloc(sizeof(ObjectList)); + newlist->object = newfunc; + newlist->next = list; + list = newlist; + } + + return list; +} + +void CClass_DefineCovariantFuncs(Object *method, CI_FuncData *ifuncdata) { + NameSpace *nspace; + TypeList *types; + Object *covariantFunc; + Statement *stmt; + Type *tptr; + Statement firstStmt; + + for (types = CClass_GetCoVariantClassList(NULL, TYPE_METHOD(method->type)->theclass, method, 1); types; types = types->next) { + covariantFunc = CClass_FindCovariantFunction(method, types->type); + tptr = CDecl_NewPointerType(types->type); + + nspace = CFunc_FuncGenSetup(&firstStmt, covariantFunc); + CInline_UnpackIFunctionData(covariantFunc, ifuncdata, &firstStmt); + + for (stmt = &firstStmt; stmt; stmt = stmt->next) { + if (stmt->type == ST_RETURN && stmt->expr) + stmt->expr = CExpr_AssignmentPromotion(stmt->expr, tptr, ENODE_QUALS(stmt->expr), 0); + } + + CFunc_Gen(&firstStmt, covariantFunc, 0); + cscope_current = nspace->parent; + } +} + +static void CClass_OverrideOVClassTree(OVClass *ovclass) { + OVClassBase *ovbase; + OVFunc *ovfunc; + + if (cclass_root != ovclass) { + for (ovfunc = ovclass->vfuncs; ovfunc; ovfunc = ovfunc->next) + CClass_FindOVFunc(cclass_root, ovclass, ovfunc); + } + + for (ovbase = ovclass->bases; ovbase; ovbase = ovbase->next) + CClass_OverrideOVClassTree(ovbase->ovclass); +} + +static void CClass_AllocVTableRec(OVClass *ovclass) { + OVFunc *ovfunc; + Object *object; + SInt32 offset27; + SInt32 offset26; + SInt32 offset23; + OVClassBase *ovbase; + OLinkList *link; + + if (ovclass->alloced_vtable) + return; + + for (ovfunc = ovclass->vfuncs; ovfunc; ovfunc = ovfunc->next) { + offset27 = ovclass->voffset + TYPE_METHOD(ovfunc->obj->type)->vtbl_index + CABI_GetVTableOffset(ovclass->tclass); + CError_ASSERT(1867, offset27 < vtable_data_size); + + if (!(vtable_object_data[offset27])) { + if (ovfunc->ovfC) { + object = ovfunc->ovfC->obj; + if ( + (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_400000) && + CClass_GetOverrideKind(TYPE_FUNC(ovfunc->obj->type), TYPE_FUNC(object->type), 0) == 2 + ) + { + CError_ASSERT(1887, + IS_TYPE_POINTER_ONLY(TYPE_FUNC(ovfunc->obj->type)->functype) && + IS_TYPE_CLASS(TPTR_TARGET(TYPE_FUNC(ovfunc->obj->type)->functype))); + object = CClass_FindCovariantFunction( + object, + TPTR_TARGET(TYPE_FUNC(ovfunc->obj->type)->functype)); + } + + if ((offset26 = ovfunc->ovc8->offset - ovclass->offset)) { + if (!(TYPE_FUNC(object->type)->flags & FUNC_PURE)) { + cclass_ovbase = NULL; + CError_ASSERT(1899, CClass_IsBaseOf(ovclass, ovfunc->ovc8)); + + if (cclass_ovbase && (main_class->flags & CLASS_FLAGS_8000)) { + offset23 = ovclass->offset - cclass_ovbase->offset; + offset23 = CABI_GetCtorOffsetOffset(cclass_ovbase->tclass, NULL) - offset23; + CError_ASSERT(1906, offset23 > 0); + object = CClass_ThunkObject(object, offset26, 0, offset23); + } else { + object = CClass_ThunkObject(object, offset26, 0, -1); + } + } + } + } else { + object = ovfunc->obj; + } + + if (!(TYPE_FUNC(object->type)->flags & FUNC_PURE)) { + link = lalloc(sizeof(OLinkList)); + link->next = vtable_object_links; + link->obj = object; + link->offset = offset27; + link->somevalue = 0; + vtable_object_links = link; + vtable_object_data[offset27] = 1; + } + } + } + + ovclass->alloced_vtable = 1; + + for (ovbase = ovclass->bases; ovbase; ovbase = ovbase->next) + CClass_AllocVTableRec(ovbase->ovclass); +} + +static Object *CClass_CheckClass(OVClass *ovclass, Boolean errorflag) { + Object *object; + Object *check; + OVFunc *ovfunc; + OVClassBase *ovbase; + + object = NULL; + + for (ovfunc = ovclass->vfuncs; ovfunc; ovfunc = ovfunc->next) { + if (ovfunc->ovf10 && errorflag) + CError_Error(CErrorStr251, main_class, 0, ovfunc->obj, ovfunc->ovfC->obj, ovfunc->ovf10->obj); + + if (!object) { + check = ovfunc->ovfC ? ovfunc->ovfC->obj : ovfunc->obj; + if (TYPE_FUNC(check->type)->flags & FUNC_PURE) + object = check; + } + } + + for (ovbase = ovclass->bases; ovbase; ovbase = ovbase->next) { + if (object) + CClass_CheckClass(ovbase->ovclass, errorflag); + else + object = CClass_CheckClass(ovbase->ovclass, errorflag); + } + + return object; +} + +static void CClass_AllocVTable(TypeClass *tclass) { + OVClass *ovclass; + + main_class = tclass; + ovclass = CClass_BuildOVClassTree(NULL, tclass, 0, 0); + cclass_root = ovclass; + CClass_OverrideOVClassTree(ovclass); + CClass_CheckClass(ovclass, 1); + CClass_AllocVTableRec(ovclass); +} + +static Object *CClass_CheckVirtuals(TypeClass *tclass) { + OVClass *ovclass; + + main_class = tclass; + ovclass = CClass_BuildOVClassTree(NULL, tclass, 0, 0); + cclass_root = ovclass; + CClass_OverrideOVClassTree(ovclass); + return CClass_CheckClass(ovclass, 0); +} + +static void CClass_CheckVirtualBaseOverrides(OVClass *a, OVClass *b, Boolean flag) { + VClassList *vbase; + OVFunc *ovfunc; + OVClassBase *ovbase; + + if (flag) { + for (ovfunc = b->vfuncs; ovfunc; ovfunc = ovfunc->next) { + if (ovfunc->ovfC) { + cclass_ovbase = NULL; + CError_ASSERT(2040, CClass_IsBaseOf(b, ovfunc->ovc8)); + + if (cclass_ovbase) { + for (vbase = a->tclass->vbases; vbase; vbase = vbase->next) { + if (vbase->base == cclass_ovbase->tclass) + break; + } + + CError_ASSERT(2047, vbase); + vbase->has_override = 1; + } + } + } + } + + for (ovbase = b->bases; ovbase; ovbase = ovbase->next) { + CClass_CheckVirtualBaseOverrides(a, ovbase->ovclass, flag || ovbase->is_virtual); + } +} + +static void CClass_CheckHideVirtual(OVClass *a, OVClass *b) { + OVClassBase *ovbase; + OVFunc *ovfunc; + Object *foundObject; + Boolean isAlias; + Object *object; + CScopeObjectIterator iter; + + if (a != b) { + for (ovfunc = b->vfuncs; ovfunc; ovfunc = ovfunc->next) { + if (ovfunc->ovc8 != a) { + foundObject = NULL; + isAlias = 0; + CScope_InitObjectIterator(&iter, a->tclass->nspace); + + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (object->name == ovfunc->obj->name && IS_TYPE_FUNC(object->type)) { + if (object->datatype != DALIAS) { + if (!(TYPE_FUNC(object->type)->flags & FUNC_FLAGS_20)) + foundObject = object; + } else { + if (object->u.alias.object == ovfunc->obj) { + // don't show a warning if this is just an alias to the base function + isAlias = 1; + break; + } + } + } + } + + if (foundObject && !isAlias) + CError_Warning(CErrorStr225, foundObject, ovfunc->obj); + } + } + } + + for (ovbase = b->bases; ovbase; ovbase = ovbase->next) + CClass_CheckHideVirtual(a, ovbase->ovclass); +} + +void CClass_CheckOverrides(TypeClass *tclass) { + OVClass *tree; + Object *object; + ObjectList *objlist; + ClassList *base; + VClassList *vbase; + int i; + CScopeObjectIterator iter; + + i = 0; + for (base = tclass->bases; base; base = base->next) { + base->offset = i; + base->voffset = i; + i++; + } + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + vbase->offset = i; + vbase->voffset = i; + i++; + } + + main_class = tclass; + tree = CClass_BuildOVClassTree(NULL, tclass, 0, 0); + cclass_root = tree; + + CClass_OverrideOVClassTree(tree); + if (CClass_CheckClass(tree, 0)) + tclass->flags |= CLASS_ABSTRACT; + + if (copts.warn_hidevirtual) + CClass_CheckHideVirtual(tree, tree); + + if (tclass->flags & CLASS_FLAGS_8000) + CClass_CheckVirtualBaseOverrides(tree, tree, 0); + + objlist = NULL; + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (object->datatype == DVFUNC) { + CError_ASSERT(2175, IS_TYPE_FUNC(object->type)); + if (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_400000) + objlist = CClass_DeclareCovariantFuncs(objlist, object, tclass); + } + } + + while (objlist) { + CScope_AddObject(tclass->nspace, objlist->object->name, OBJ_BASE(objlist->object)); + objlist = objlist->next; + } + + for (base = tclass->bases; base; base = base->next) { + base->offset = 0; + base->voffset = 0; + } + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + vbase->offset = 0; + vbase->voffset = 0; + } +} + +static void CClass_FindDominator(TypeClass *tclass1, SInt32 offset1, Object *object1, TypeClass *tclass2, SInt32 offset2, TypeClass *tclass3) { + Object *object; + ClassList *base; + CScopeObjectIterator iter; + + CScope_InitObjectIterator(&iter, tclass1->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if ( + object->name == cclass_dominator_vobject->name && + object->datatype == DVFUNC && + CClass_GetOverrideKind(TYPE_FUNC(cclass_dominator_vobject->type), TYPE_FUNC(object->type), 0) + ) + { + if (object == cclass_dominator_vobject && offset1 == cclass_dominator_voffset) { + if (object1) { + if (cclass_dominator_oobject && cclass_dominator_ooffset != offset2) { + if (CClass_ClassDominates(cclass_dominator_oclass, tclass2)) + return; + if (!CClass_ClassDominates(tclass2, cclass_dominator_oclass)) { + cclass_dominator_eobject = object1; + cclass_vbase = tclass3; + return; + } + } + + cclass_dominator_oobject = object1; + cclass_dominator_ooffset = offset2; + cclass_dominator_oclass = tclass2; + cclass_dominator_eobject = NULL; + cclass_vbase = tclass3; + } + return; + } else { + if (!object1) { + object1 = object; + tclass2 = tclass1; + offset2 = offset1; + } + break; + } + } + } + + for (base = tclass1->bases; base; base = base->next) { + if (base->base->vtable) { + if (!base->is_virtual) { + CClass_FindDominator(base->base, offset1 + base->offset, object1, tclass2, offset2, tclass3); + } else { + SInt32 vboffset = CClass_VirtualBaseOffset(main_class, base->base); + CClass_FindDominator(base->base, vboffset, object1, tclass2, offset2, base->base); + } + } + } +} + +static void CClass_ConstructVTable(TypeClass *tclass, SInt32 voffset, SInt32 offset, TypeClass *baseclass) { + Object *object; + Object *thunkobject; + SInt32 newoffset; + SInt32 newvoffset; + ClassList *base; + SInt32 thunkoffset; + OLinkList *olink; + CScopeObjectIterator iter; + + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (object->datatype == DVFUNC) { + newoffset = voffset + TYPE_METHOD(object->type)->vtbl_index + CABI_GetVTableOffset(tclass); + CError_ASSERT(2288, newoffset < vtable_data_size); + + if (!vtable_object_data[newoffset]) { + cclass_dominator_vobject = object; + cclass_dominator_voffset = offset; + cclass_dominator_oobject = NULL; + cclass_dominator_ooffset = offset; + CClass_FindDominator(main_class, 0, NULL, NULL, 0, NULL); + + if (cclass_dominator_oobject) { + if (cclass_dominator_eobject) + CError_Error(CErrorStr251, main_class, 0, cclass_dominator_vobject, cclass_dominator_oobject, cclass_dominator_eobject); + } else { + cclass_dominator_oobject = object; + cclass_vbase = NULL; + } + + vtable_object_data[newoffset] = 1; + + if (!(TYPE_FUNC(cclass_dominator_oobject->type)->flags & FUNC_PURE)) { + if (!check_pures) { + thunkobject = cclass_dominator_oobject; + if ((thunkoffset = cclass_dominator_ooffset - offset)) { + if (cclass_vbase && (main_class->flags & CLASS_FLAGS_8000)) { + thunkobject = CClass_ThunkObject(cclass_dominator_oobject, thunkoffset, 0, + CABI_GetCtorOffsetOffset(cclass_vbase, tclass)); + } else { + thunkobject = CClass_ThunkObject(cclass_dominator_oobject, thunkoffset, 0, -1); + } + } + + olink = lalloc(sizeof(OLinkList)); + olink->next = vtable_object_links; + olink->obj = thunkobject; + olink->offset = newoffset; + olink->somevalue = 0; + vtable_object_links = olink; + } + } else { + found_pure = cclass_dominator_oobject; + } + } + } + } + + for (base = tclass->bases; base; base = base->next) { + if (base->base->vtable) { + if (base->is_virtual) { + newoffset = CClass_VirtualBaseOffset(main_class, base->base); + newvoffset = CClass_VirtualBaseVTableOffset(main_class, base->base); + CClass_ConstructVTable( + base->base, + newvoffset, + newoffset, + base->base + ); + } else { + CClass_ConstructVTable( + base->base, + voffset + base->voffset, + offset + base->offset, + baseclass + ); + } + } + } +} + +void CClass_ClassDefaultFuncAction(TypeClass *tclass) { +} + +void CClass_ClassAction(TypeClass *tclass) { + if (tclass->sominfo) { + CSOM_GenerateClassStructures(tclass); + } else if (tclass->vtable) { + vtable_data_size = tclass->vtable->size; + vtable_object_data = lalloc(vtable_data_size); + memclrw(vtable_object_data, vtable_data_size); + + main_class = tclass; + vtable_object_links = NULL; + found_pure = NULL; + check_pures = 0; + + CClass_AllocVTable(tclass); + + memclrw(vtable_object_data, vtable_data_size); + if (copts.RTTI && !(tclass->flags & (CLASS_SINGLE_OBJECT | CLASS_COM_OBJECT))) + vtable_object_links = CRTTI_ConstructVTableHeaders(tclass, vtable_object_data, vtable_object_links); + + CError_ASSERT(2492, tclass->vtable->object->type->size == tclass->vtable->size); + CInit_DeclareData(tclass->vtable->object, vtable_object_data, vtable_object_links, tclass->vtable->size); + } +} + +void CClass_MakeStaticActionClass(TypeClass *tclass) { + if (tclass->vtable) { + tclass->vtable->object->sclass = TK_STATIC; + tclass->vtable->object->qual |= Q_20000; + if (!(tclass->vtable->object->flags & OBJECT_FLAGS_2)) { + CParser_NewCallBackAction(tclass->vtable->object, tclass); + } else if (cparamblkptr->precompile != 1) { + CParser_NewClassAction(tclass); + } + } +} + +Object *CClass_CheckPures(TypeClass *tclass) { + return CClass_CheckVirtuals(tclass); +} + +void CClass_MemberDef(Object *obj, TypeClass *tclass) { + switch (tclass->action) { + case CLASS_ACTION_0: + break; + case CLASS_ACTION_1: + if (IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_4)) { + if (obj->qual & Q_INLINE) { + if (tclass->sominfo) + CError_Error(CErrorStr280); + tclass->action = CLASS_ACTION_0; + CClass_MakeStaticActionClass(tclass); + } else if (cparamblkptr->precompile != 1) { + CParser_NewClassAction(tclass); + } + } + break; + case CLASS_ACTION_2: + CError_FATAL(2682); + break; + case CLASS_ACTION_3: + break; + default: + CError_FATAL(2701); + } +} + +Object *CClass_ThisSelfObject(void) { + ObjectList *list; + + if (cscope_currentfunc && cscope_currentclass) { + if (cscope_currentclass->objcinfo) { + for (list = arguments; list; list = list->next) { + if (list->object->name == self_name_node) + return list->object; + } + CError_Error(CErrorStr301); + } else { + if (cscope_is_member_func) { + for (list = arguments; list; list = list->next) { + if (list->object->name == this_name_node) + return list->object; + } + } + CError_Error(CErrorStr189); + } + } + + CError_Error(copts.cplusplus ? CErrorStr189 : CErrorStr301); + return NULL; +} + +ENode *CClass_CreateThisSelfExpr(void) { + Object *object; + ENode *expr; + + if (!(object = CClass_ThisSelfObject())) + return NULL; + + expr = create_objectrefnode(object); + expr->rtype = CDecl_NewPointerType(TYPE(cscope_currentclass)); + expr = makemonadicnode(expr, EINDIRECT); + expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); + + return expr; +} + +static AccessType CClass_BaseMemberAccess(BClassList *path, AccessType access) { + ClassList *base; + + if (path->next) { + access = CClass_BaseMemberAccess(path->next, access); + switch (access) { + case ACCESSPRIVATE: + case ACCESSNONE: + return ACCESSNONE; + } + + for (base = TYPE_CLASS(path->type)->bases; ; base = base->next) { + if (!base) + return ACCESSNONE; + + if (base->base == TYPE_CLASS(path->next->type)) { + switch (base->access) { + case ACCESSNONE: + access = ACCESSNONE; + break; + case ACCESSPROTECTED: + if (access == ACCESSPUBLIC) + access = ACCESSPROTECTED; + break; + case ACCESSPRIVATE: + if (access == ACCESSPRIVATE) + access = ACCESSNONE; + else + access = ACCESSPRIVATE; + break; + case ACCESSPUBLIC: + break; + } + break; + } + } + } + + return access; +} + +static Boolean CClass_CanAccess(BClassList *path, AccessType access) { + AccessType access2; + BClassList *scan; + BClassList *next; + TypeClass *prevclass; + TypeClass *tclass; + ClassList *base; + ClassFriend *cfriend; + + tclass = TYPE_CLASS(path->type); + access2 = access; + if ((scan = path->next)) { + if (access2 != ACCESSPRIVATE) { + prevclass = tclass; + while (scan) { + for (base = prevclass->bases; base; base = base->next) { + if (base->base == TYPE_CLASS(scan->type)) + break; + } + + if (!base) + return 0; + + switch (base->access) { + case ACCESSNONE: + access2 = ACCESSNONE; + break; + case ACCESSPROTECTED: + if (access2 == ACCESSPUBLIC) + access2 = ACCESSPROTECTED; + break; + case ACCESSPRIVATE: + if (access2 == ACCESSPRIVATE) + access2 = ACCESSNONE; + else + access2 = ACCESSPRIVATE; + break; + case ACCESSPUBLIC: + break; + } + + prevclass = TYPE_CLASS(scan->type); + scan = scan->next; + } + } else { + access2 = ACCESSNONE; + } + } + + if (access2 == ACCESSPUBLIC) + return 1; + + if (access2 != ACCESSNONE) { + if (cscope_currentclass == tclass) + return 1; + if (cobjc_currentclass == tclass) + return 1; + + for (cfriend = tclass->friends; cfriend; cfriend = cfriend->next) { + if (cfriend->isclass) { + if (cfriend->u.theclass == cscope_currentclass) + return 1; + } else { + if (cfriend->u.obj == cscope_currentfunc) + return 1; + } + } + } + + for (scan = path; scan->next; scan = scan->next) { + if (CClass_CanAccess(scan->next, access)) { + if ((next = scan->next->next) || access != ACCESSPUBLIC) { + scan->next->next = NULL; + if (CClass_CanAccess(path, ACCESSPUBLIC)) { + scan->next->next = next; + return 1; + } + scan->next->next = next; + } + } + } + + return 0; +} + +void CClass_CheckPathAccess(BClassList *path, Object *obj, AccessType access) { + if (!CClass_CanAccess(path, access)) { + if (path && obj) + CError_Error(CErrorStr381, path->type, 0, obj); + else + CError_Error(CErrorStr187); + } +} + +static BClassList *CClass_PathCleanup(BClassList *path, TypeClass *tclass) { + BClassList *first; + ClassList *base; + + first = path; + + while (1) { + if (!path->next) { + if (!tclass) + return first; + if (path->type == TYPE(tclass)) + return first; + return NULL; + } + + if (path->type != path->next->type) { + for (base = TYPE_CLASS(path->type)->bases; base; base = base->next) { + if (base->base == TYPE_CLASS(path->next->type)) + break; + } + + if (base) { + path = path->next; + } else { + first = path = path->next; + } + } else { + path->next = path->next->next; + } + } +} + +void CClass_CheckStaticAccess(BClassList *path, TypeClass *tclass, AccessType access) { + ClassFriend *cfriend; + + if (path) { + path = CClass_PathCleanup(path, tclass); + if (path && path->next) { + if (!CClass_CanAccess(path, access)) + CError_Error(CErrorStr187); + return; + } + } + + switch (access) { + case ACCESSPUBLIC: + return; + case ACCESSPRIVATE: + case ACCESSPROTECTED: + if (tclass == cscope_currentclass) + return; + + for (cfriend = tclass->friends; cfriend; cfriend = cfriend->next) { + if (cfriend->isclass) { + if (cfriend->u.theclass == cscope_currentclass) + return; + } else { + if (cfriend->u.obj == cscope_currentfunc) + return; + } + } + case ACCESSNONE: + CError_Warning(CErrorStr187); + return; + default: + CError_FATAL(3013); + } +} + +void CClass_CheckObjectAccess(BClassList *path, Object *obj) { + short depth; + Boolean isambigbase; + + if (obj->nspace && obj->nspace->theclass) { + if (!path && cscope_currentclass) + path = CClass_GetBasePath(cscope_currentclass, obj->nspace->theclass, &depth, &isambigbase); + + CClass_CheckStaticAccess(path, obj->nspace->theclass, obj->access); + } +} + +void CClass_CheckEnumAccess(BClassList *path, ObjEnumConst *objec) { + if (path) { + if ((path = CClass_PathCleanup(path, NULL))) { + if (!CClass_CanAccess(path, objec->access)) + CError_Error(CErrorStr187); + return; + } + } + + if ( + objec->access != ACCESSPUBLIC && + IS_TYPE_ENUM(objec->type) && + TYPE_ENUM(objec->type)->nspace && + TYPE_ENUM(objec->type)->nspace->theclass + ) + CClass_CheckStaticAccess(NULL, TYPE_ENUM(objec->type)->nspace->theclass, objec->access); +} + +static Type *CClass_PointerTypeCopy(Type *type) { + Type *copy; + + switch (type->type) { + case TYPEPOINTER: + case TYPEARRAY: + copy = galloc(sizeof(TypePointer)); + *TYPE_POINTER(copy) = *TYPE_POINTER(type); + TPTR_TARGET(copy) = CClass_PointerTypeCopy(TPTR_TARGET(copy)); + return copy; + case TYPEMEMBERPOINTER: + copy = galloc(sizeof(TypeMemberPointer)); + *TYPE_MEMBER_POINTER(copy) = *TYPE_MEMBER_POINTER(type); + return copy; + default: + return type; + } +} + +Type *CClass_CombineClassAccessQualifiers(Type *type, UInt32 qual1, UInt32 qual2, UInt32 *outflags) { + Type *inner; + + qual2 = qual2 & (Q_CONST | Q_VOLATILE); + if (qual1 & Q_MUTABLE) + qual2 &= ~Q_CONST; + qual1 = qual1 & (Q_CONST | Q_VOLATILE); + + inner = type; + while (IS_TYPE_ARRAY(inner)) + inner = TPTR_TARGET(inner); + + switch (inner->type) { + case TYPEMEMBERPOINTER: + case TYPEPOINTER: + if (qual2) { + type = CClass_PointerTypeCopy(type); + inner = type; + while (IS_TYPE_ARRAY(inner)) + inner = TPTR_TARGET(inner); + + switch (inner->type) { + case TYPEPOINTER: + TPTR_QUAL(inner) |= qual2; + break; + case TYPEMEMBERPOINTER: + TYPE_MEMBER_POINTER(inner)->qual |= qual2; + break; + default: + CError_FATAL(3125); + } + } + break; + default: + qual1 |= qual2; + } + + *outflags = qual1; + return type; +} + +static void CClass_OptimizeBitFieldAccess(Type **ptype, SInt32 *poffset) { + Type *innertype; + TypeBitfield *newtype; + short i; + + innertype = TYPE_BITFIELD(*ptype)->bitfieldtype; + if (TYPE_BITFIELD(*ptype)->bitlength == 8) { + switch (TYPE_BITFIELD(*ptype)->offset) { + case 0: + i = 0; + break; + case 8: + i = 1; + break; + case 16: + i = 2; + break; + case 24: + i = 3; + break; + default: + i = -1; + break; + } + + if (i >= 0) { + if (innertype->size != 1) { + if (is_unsigned(TYPE_BITFIELD(*ptype)->bitfieldtype)) + *ptype = TYPE(&stunsignedchar); + else + *ptype = TYPE(&stsignedchar); + } else { + *ptype = innertype; + } + *poffset += i; + return; + } + } + + if (TYPE_BITFIELD(*ptype)->bitlength == 16) { + switch (TYPE_BITFIELD(*ptype)->offset) { + case 0: + i = 0; + break; + case 16: + i = 2; + break; + default: + i = -1; + break; + } + + if (i >= 0) { + if (innertype->size != stsignedshort.size) { + if (is_unsigned(innertype)) + *ptype = TYPE(&stunsignedshort); + else + *ptype = TYPE(&stsignedshort); + } else { + *ptype = innertype; + } + *poffset += i; + return; + } + } + + if (TYPE_BITFIELD(*ptype)->bitlength == 32 && TYPE_BITFIELD(*ptype)->offset == 0) { + if (innertype->size != stsignedlong.size) { + if (is_unsigned(innertype)) + *ptype = TYPE(&stunsignedlong); + else + *ptype = TYPE(&stsignedlong); + } else { + *ptype = innertype; + } + return; + } + + if ((*ptype)->size != stsignedchar.size) { + i = TYPE_BITFIELD(*ptype)->offset + TYPE_BITFIELD(*ptype)->bitlength - 1; + + if (TYPE_BITFIELD(*ptype)->bitlength < 8 && (TYPE_BITFIELD(*ptype)->offset & 0xFFF8) == (i & 0xFFF8)) { + newtype = galloc(sizeof(TypeBitfield)); + *newtype = *TYPE_BITFIELD(*ptype); + *ptype = TYPE(newtype); + + i = 0; + if (newtype->offset >= 8) + i = 1; + if (newtype->offset >= 16) + i = 2; + if (newtype->offset >= 24) + i = 3; + *poffset += i; + newtype->offset -= 8 * i; + + newtype->bitfieldtype = is_unsigned(innertype) ? TYPE(&stunsignedchar) : TYPE(&stsignedchar); + newtype->size = newtype->bitfieldtype->size; + return; + } + + if ((*ptype)->size != stsignedshort.size) { + if (TYPE_BITFIELD(*ptype)->bitlength < 16 && (TYPE_BITFIELD(*ptype)->offset & 0xFFF0) == (i & 0xFFF0)) { + newtype = galloc(sizeof(TypeBitfield)); + *newtype = *TYPE_BITFIELD(*ptype); + *ptype = TYPE(newtype); + + i = 0; + if (newtype->offset >= 16) + i = stsignedshort.size; + *poffset += i; + newtype->offset -= 8 * i; + + newtype->bitfieldtype = is_unsigned(innertype) ? TYPE(&stunsignedshort) : TYPE(&stsignedshort); + newtype->size = newtype->bitfieldtype->size; + return; + } + } + } +} + +ENode *CClass_AccessMember(ENode *classexpr, Type *type, UInt32 qual, SInt32 offset) { + Type *innertype; + UInt32 flags; + + innertype = NULL; + + if (IS_TYPE_CLASS(classexpr->rtype) && (TYPE_CLASS(classexpr->rtype)->flags & CLASS_HANDLEOBJECT)) { + classexpr = makemonadicnode(classexpr, EINDIRECT); + classexpr->data.monadic->rtype = CDecl_NewPointerType(classexpr->rtype); + } + + if (IS_TYPE_BITFIELD(type)) { + innertype = TYPE_BITFIELD(type)->bitfieldtype; + CClass_OptimizeBitFieldAccess(&type, &offset); + } + + if (offset && !canadd(classexpr->data.monadic, offset)) { + classexpr->data.monadic = makediadicnode( + classexpr->data.monadic, + intconstnode(TYPE(&stunsignedlong), offset), + EADD); + optimizecomm(classexpr->data.monadic); + } + + if (innertype) { + if (IS_TYPE_BITFIELD(type)) { + classexpr->data.monadic = makemonadicnode(classexpr->data.monadic, EBITFIELD); + classexpr->data.monadic->rtype = type; + classexpr->rtype = TYPE_BITFIELD(type)->bitfieldtype; + } else { + classexpr->rtype = type; + } + } else { + classexpr->rtype = type; + } + + classexpr->rtype = CClass_CombineClassAccessQualifiers(classexpr->rtype, qual, ENODE_QUALS(classexpr), &flags); + classexpr->flags = flags; + return classexpr; +} diff --git a/compiler_and_linker/FrontEnd/C/CDecl.c b/compiler_and_linker/FrontEnd/C/CDecl.c new file mode 100644 index 0000000..43ca92e --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CDecl.c @@ -0,0 +1,4845 @@ +#include "compiler/CDecl.h" +#include "compiler/CABI.h" +#include "compiler/CBrowse.h" +#include "compiler/CClass.h" +#include "compiler/CError.h" +#include "compiler/CException.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInit.h" +#include "compiler/CInline.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CObjC.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CSOM.h" +#include "compiler/CTemplateClass.h" +#include "compiler/CTemplateFunc.h" +#include "compiler/CTemplateNew.h" +#include "compiler/CTemplateTools.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" +#include "compiler/tokens.h" + +AccessType global_access; +FileOffsetInfo member_fileoffset; + +// forward declarations +static void scandirectdecl1(DeclInfo *declinfo); + +Type *CDecl_NewStructType(SInt32 size, SInt16 align) { + TypeStruct *tstruct = galloc(sizeof(TypeStruct)); + memclrw(tstruct, sizeof(TypeStruct)); + + tstruct->type = TYPESTRUCT; + tstruct->size = size; + tstruct->align = align; + tstruct->stype = STRUCT_TYPE_STRUCT; + + return (Type *) tstruct; +} + +Type *CDecl_NewArrayType(Type *type, SInt32 size) { + TypePointer *tarray = galloc(sizeof(TypePointer)); + memclrw(tarray, sizeof(TypePointer)); + + tarray->type = TYPEARRAY; + tarray->size = size; + tarray->target = type; + tarray->qual = 0; + + return (Type *) tarray; +} + +Type *CDecl_NewPointerType(Type *type) { + TypePointer *tptr = galloc(sizeof(TypePointer)); + memclrw(tptr, sizeof(TypePointer)); + + tptr->type = TYPEPOINTER; + tptr->size = 4; + tptr->target = type; + + return (Type *) tptr; +} + +Type *CDecl_NewRefPointerType(Type *type) { + TypePointer *tptr = galloc(sizeof(TypePointer)); + memclrw(tptr, sizeof(TypePointer)); + + tptr->type = TYPEPOINTER; + tptr->size = 4; + tptr->target = type; + tptr->qual = Q_REFERENCE; + + return (Type *) tptr; +} + +Type *CDecl_NewTemplDepType(TypeTemplDepType tdt) { + TypeTemplDep *t = galloc(sizeof(TypeTemplDep)); + memclrw(t, sizeof(TypeTemplDep)); + + t->type = TYPETEMPLATE; + t->size = 1; + t->dtype = tdt; + + return (Type *) t; +} + +void CDecl_SetResultReg(TypeFunc *tfunc) { +} + +static void CDecl_SetFuncResultReg(TypeFunc *tfunc) { +} + +void CDecl_SetFuncFlags(TypeFunc *tfunc, UInt32 flags) { + CDecl_SetResultReg(tfunc); +} + +static void CDecl_ParseCPPFuncDecl(TypeFunc *tfunc) { + for (;;) { + if (tk == TK_CONST) { + if (tfunc->flags & FUNC_CONST) + CError_Warning(CErrorStr313, "const"); + tfunc->flags |= FUNC_CONST; + tk = lex(); + } else if (tk == TK_VOLATILE) { + if (tfunc->flags & FUNC_VOLATILE) + CError_Warning(CErrorStr313, "volatile"); + tfunc->flags |= FUNC_VOLATILE; + tk = lex(); + } else { + break; + } + } + + if (tk == TK_THROW) + CExcept_ScanExceptionSpecification(tfunc); +} + +void CDecl_NewConvFuncType(DeclInfo *declinfo) { + TypeFunc *tfunc; + + if (tk != '(') + CError_Error(CErrorStr114); + else + tk = lex(); + + if (tk == TK_VOID) + tk = lex(); + + if (tk != ')') + CError_Error(CErrorStr115); + else + tk = lex(); + + tfunc = galloc(sizeof(TypeFunc)); + memclrw(tfunc, sizeof(TypeFunc)); + declinfo->name = CMangler_ConversionFuncName(declinfo->thetype, declinfo->qual); + tfunc->type = TYPEFUNC; + tfunc->functype = declinfo->thetype; + tfunc->qual = declinfo->qual & (Q_CONST | Q_VOLATILE); + tfunc->flags = FUNC_CONVERSION; + declinfo->x49 = 0; + CDecl_SetFuncFlags(tfunc, 1); + CDecl_ParseCPPFuncDecl(tfunc); + + declinfo->thetype = (Type *) tfunc; + declinfo->qual &= ~(Q_CONST | Q_VOLATILE); + declinfo->storageclass = 0; +} + +void CDecl_CompleteType(Type *type) { + switch (type->type) { + case TYPEPOINTER: + if ((TYPE_POINTER(type)->qual & Q_REFERENCE) && IS_TYPE_CLASS(TYPE_POINTER(type)->target)) { + type = TYPE_POINTER(type)->target; + break; + } + return; + case TYPEARRAY: + do { + type = TYPE_POINTER(type)->target; + } while (IS_TYPE_ARRAY(type)); + if (IS_TYPE_CLASS(type)) + break; + return; + case TYPECLASS: + break; + default: + return; + } + + if ((TYPE_CLASS(type)->flags & (CLASS_COMPLETED | CLASS_IS_TEMPL_INST)) == CLASS_IS_TEMPL_INST) + CTempl_InstantiateTemplateClass(TYPE_CLASS(type)); +} + +Boolean IsCompleteType(Type *type) { + switch (type->type) { + case TYPEVOID: + CError_Error(CErrorStr126); + return 0; + case TYPEFUNC: + CError_Error(CErrorStr146); + return 0; + case TYPESTRUCT: + if (!type->size) { + CError_Error(CErrorStr136, type, 0); + return 0; + } + return 1; + case TYPECLASS: + if ( + !(TYPE_CLASS(type)->flags & CLASS_COMPLETED) && + ( + !(TYPE_CLASS(type)->flags & CLASS_IS_TEMPL_INST) || + !CTempl_InstantiateTemplateClass(TYPE_CLASS(type)) + ) + ) + { + CError_Error(CErrorStr136, type, 0); + return 0; + } + return 1; + default: + if (!type->size) { + CError_Error(CErrorStr145); + return 0; + } + return 1; + } +} + +Boolean CanAllocObject(Type *type) { + switch (type->type) { + case TYPEVOID: + CError_Error(CErrorStr126); + return 0; + case TYPEFUNC: + CError_Error(CErrorStr146); + return 0; + case TYPECLASS: + if (TYPE_CLASS(type)->flags & CLASS_ABSTRACT) { + CError_AbstractClassError(TYPE_CLASS(type)); + return 0; + } + default: + return 1; + } +} + +Boolean CanCreateObject(Type *type) { + if (!CanAllocObject(type)) + return 0; + + if (IS_TYPE_CLASS(type)) { + if (TYPE_CLASS(type)->flags & CLASS_HANDLEOBJECT) { + CError_Error(CErrorStr191); + return 0; + } + if (TYPE_CLASS(type)->objcinfo) { + CError_Error(CErrorStr307); + return 0; + } + } + + return 1; +} + +static Boolean CanCreateHandleMemberObject(Type *type) { + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + + if (!CanCreateObject(type)) + return 0; + + if (IS_TYPE_CLASS(type)) { + if (CClass_Destructor(TYPE_CLASS(type)) || CClass_Constructor(TYPE_CLASS(type))) { + CError_Error(CErrorStr191); + return 0; + } + } + + return 1; +} + +void makethetypepointer(DeclInfo *declinfo, UInt32 qual) { + declinfo->thetype = CDecl_NewPointerType(declinfo->thetype); + TYPE_POINTER(declinfo->thetype)->qual = qual; +} + +void CDecl_AddThisPointerArgument(TypeFunc *tfunc, TypeClass *tclass) { + Type *ptype; + FuncArg *arg; + + ptype = CDecl_NewPointerType(!tclass->sominfo ? (Type *) tclass : &stvoid); + TYPE_POINTER(ptype)->qual = Q_CONST; + + arg = CParser_NewFuncArg(); + arg->name = this_name_node; + arg->type = ptype; + if (tfunc->flags & FUNC_CONST) + arg->qual |= Q_CONST; + if (tfunc->flags & FUNC_VOLATILE) + arg->qual |= Q_VOLATILE; + arg->next = tfunc->args; + tfunc->args = arg; +} + +void CDecl_MakePTMFuncType(TypeFunc *tfunc) { + Type *cvoidp; + FuncArg *arg1; + FuncArg *arg2; + + cvoidp = CDecl_NewPointerType(&stvoid); + TYPE_POINTER(cvoidp)->qual = Q_CONST; + + arg1 = CParser_NewFuncArg(); + arg1->name = this_name_node; + arg1->type = cvoidp; + if (tfunc->flags & FUNC_CONST) + arg1->qual |= Q_CONST; + if (tfunc->flags & FUNC_VOLATILE) + arg1->qual |= Q_VOLATILE; + + arg2 = CParser_NewFuncArg(); + arg2->name = this_name_node; + arg2->type = cvoidp; + arg2->qual = Q_CONST; + + arg1->next = tfunc->args; + arg2->next = arg1; + tfunc->args = arg2; + tfunc->flags |= FUNC_FLAGS_80; +} + +void CDecl_AddArgument(TypeFunc *tfunc, Type *argtype) { + FuncArg *arg = CParser_NewFuncArg(); + arg->type = argtype; + + arg->next = tfunc->args; + tfunc->args = arg; + + if (arg->next && arg->next->type == &stvoid) + arg->next = NULL; +} + +Boolean CDecl_CheckArrayIntegr(Type *type) { + if (!IsCompleteType(type)) + return 0; + + if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo) { + CError_Error(CErrorStr289); + return 0; + } + + if (IS_TYPE_REFERENCE(type)) { + CError_Error(CErrorStr196); + return 0; + } + + return CanCreateObject(type); +} + +static Boolean checkfuncintegr(Type *type) { + if (IS_TYPE_VOID(type)) + return 1; + + if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo) { + CError_Error(CErrorStr283); + return 0; + } + + return CanCreateObject(type); +} + +void CDecl_ParseDirectFuncDecl(DeclInfo *declinfo) { + FuncArg *list; + TypeFunc *tfunc; + + if (tk == ')') { + if (copts.cplusplus) + list = NULL; + else + list = &oldstyle; + tk = lex(); + } else { + list = parameter_type_list(declinfo); + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + } + + tfunc = galloc(sizeof(TypeFunc)); + memclrw(tfunc, sizeof(TypeFunc)); + tfunc->type = TYPEFUNC; + tfunc->args = list; + if (declinfo->qual & Q_PASCAL) { + declinfo->qual &= ~Q_PASCAL; + tfunc->flags = FUNC_PASCAL; + } + + if (copts.cplusplus) { + CDecl_ParseCPPFuncDecl(tfunc); + if (declinfo->storageclass == TK_TYPEDEF && tfunc->exspecs) + CError_Error(CErrorStr264); + } + + scandirectdecl1(declinfo); + if (!checkfuncintegr(declinfo->thetype)) + declinfo->thetype = &stvoid; + + tfunc->functype = declinfo->thetype; + tfunc->qual = declinfo->qual & (Q_CONST | Q_VOLATILE); + declinfo->thetype = (Type *) tfunc; + declinfo->qual &= ~(Q_CONST | Q_VOLATILE); + declinfo->x49 = 0; +} + +static void scandirectdecl1(DeclInfo *declinfo) { + Boolean flag; + CInt64 len; + ENode *expr; + TypeTemplDep *ttempl; + + flag = 0; + if (tk == '[') { + if ((tk = lex()) == ']') { + len = cint64_zero; + tk = lex(); + flag = 1; + } else { + if (!declinfo->x46 || declinfo->x47) { + expr = CExpr_IntegralConstOrDepExpr(); + if (!ENODE_IS(expr, EINTCONST)) { + if (tk != ']') + CError_ErrorSkip(CErrorStr125); + else + tk = lex(); + declinfo->x47 = 1; + scandirectdecl1(declinfo); + if (!CDecl_CheckArrayIntegr(declinfo->thetype)) + declinfo->thetype = (Type *) &stsignedchar; + ttempl = (TypeTemplDep *) CDecl_NewTemplDepType(TEMPLDEP_ARRAY); + ttempl->u.array.type = declinfo->thetype; + ttempl->u.array.index = CInline_CopyExpression(expr, CopyMode1); + declinfo->thetype = (Type *) ttempl; + return; + } + len = expr->data.intval; + if (CInt64_IsNegative(&len)) { + CError_Error(CErrorStr124); + len = cint64_one; + } else if (CInt64_IsZero(&len)) { + if (!copts.ANSIstrict && declinfo->x50) { + flag = 1; + } else { + CError_Error(CErrorStr124); + len = cint64_one; + } + } + } else { + len = cint64_one; + expr = expression(); + if (IS_TYPE_INT(expr->rtype)) { + if (!ENODE_IS(expr, EINTCONST)) + declinfo->x24 = expr; + else + len = expr->data.intval; + } else { + CError_Error(CErrorStr124); + } + } + + if (tk != ']') + CError_ErrorSkip(CErrorStr125); + else + tk = lex(); + } + + declinfo->x47 = 1; + scandirectdecl1(declinfo); + + if (!flag && !CDecl_CheckArrayIntegr(declinfo->thetype)) + declinfo->thetype = (Type *) &stsignedchar; + + if (!declinfo->thetype->size && CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) { + ttempl = (TypeTemplDep *) CDecl_NewTemplDepType(TEMPLDEP_ARRAY); + ttempl->u.array.type = declinfo->thetype; + ttempl->u.array.index = CInline_CopyExpression(intconstnode((Type *) &stsignedint, CInt64_GetULong(&len)), CopyMode1); + declinfo->thetype = (Type *) ttempl; + } else { + declinfo->thetype = CDecl_NewArrayType(declinfo->thetype, declinfo->thetype->size * CInt64_GetULong(&len)); + } + } else if (tk == '(') { + if (!copts.cplusplus || !declinfo->name || IS_TYPE_VOID(declinfo->thetype) || CParser_TryParamList(!IS_TYPE_CLASS(declinfo->thetype))) { + tk = lex(); + CDecl_ParseDirectFuncDecl(declinfo); + } + } +} + +static void substitute_type(Type *type1, Type *type2) { + SInt32 oldsize; + + while (1) { + switch (type1->type) { + case TYPEPOINTER: + if (TYPE_POINTER(type1)->target == &stillegal) { + TYPE_POINTER(type1)->target = type2; + type1->size = 4; + return; + } + type1 = TYPE_POINTER(type1)->target; + break; + case TYPEMEMBERPOINTER: + if (TYPE_MEMBER_POINTER(type1)->ty1 == &stillegal) { + TYPE_MEMBER_POINTER(type1)->ty1 = type2; + if (IS_TYPE_FUNC(type2)) { + CDecl_MakePTMFuncType(TYPE_FUNC(type2)); + type1->size = 12; + } else { + type1->size = 4; + } + return; + } + type1 = TYPE_MEMBER_POINTER(type1)->ty1; + break; + case TYPEARRAY: + if (TYPE_POINTER(type1)->target == &stillegal) { + if (!CDecl_CheckArrayIntegr(type2)) + type2 = (Type *) &stsignedchar; + type1->size *= type2->size; + TYPE_POINTER(type1)->target = type2; + return; + } + oldsize = TYPE_POINTER(type1)->target->size; + substitute_type(TYPE_POINTER(type1)->target, type2); + if (oldsize != TYPE_POINTER(type1)->target->size && oldsize != 0) + type1->size = TYPE_POINTER(type1)->target->size * (type1->size / oldsize); + return; + case TYPEFUNC: + if (TYPE_FUNC(type1)->functype == &stillegal) { + if (!checkfuncintegr(type2)) + type2 = &stvoid; + TYPE_FUNC(type1)->functype = type2; + CDecl_SetFuncResultReg((TypeFunc *) type1); + return; + } + type1 = TYPE_FUNC(type1)->functype; + break; + case TYPETEMPLATE: + if (TYPE_TEMPLATE(type1)->dtype == TEMPLDEP_ARRAY) { + if (TYPE_TEMPLATE(type1)->u.array.type == &stillegal) { + if (!CDecl_CheckArrayIntegr(type2)) + type2 = (Type *) &stsignedchar; + TYPE_TEMPLATE(type1)->u.array.type = type2; + return; + } + type1 = TYPE_TEMPLATE(type1)->u.array.type; + } else { + CError_Error(CErrorStr146); + return; + } + break; + default: + CError_Error(CErrorStr121); + return; + } + } +} + +static void scandecl(DeclInfo *declinfo) { + Type *oldtype; + Type *newtype; + + oldtype = declinfo->thetype; + declinfo->thetype = &stillegal; + scandeclarator(declinfo); + + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + + newtype = declinfo->thetype; + if (newtype == &stillegal) { + declinfo->thetype = oldtype; + scandirectdecl1(declinfo); + } else { + declinfo->thetype = oldtype; + scandirectdecl1(declinfo); + substitute_type(newtype, declinfo->thetype); + declinfo->thetype = newtype; + } +} + +static Boolean CDecl_ParseOperatorDecl(DeclInfo *declinfo) { + if (declinfo->operator_token) { + CError_Error(CErrorStr121); + return 0; + } + + declinfo->operator_token = 0; + if (!CParser_ParseOperatorName(&declinfo->operator_token, declinfo->x4A && cscope_current->theclass, 0)) + return 0; + + if (!declinfo->operator_token) { + conversion_type_name(declinfo); + tkidentifier = CMangler_ConversionFuncName(declinfo->thetype, declinfo->qual); + declinfo->x54 = 1; + } + return 1; +} + +static Boolean CDecl_IsEnumClassTypeOrRef(Type *type) { + if (IS_TYPE_CLASS(type) || IS_TYPE_ENUM(type)) + return 1; + if (!IS_TYPE_REFERENCE(type)) + return 0; + type = TYPE_POINTER(type)->target; + return IS_TYPE_CLASS(type) || IS_TYPE_ENUM(type); +} + +static Boolean CDecl_CheckOperatorType(DeclInfo *declinfo, Boolean flag) { + FuncArg *args; + FuncArg *secondarg; + Type *functype; + short argCount; + Boolean isMethod; + + if (!IS_TYPE_FUNC(declinfo->thetype)) { + CError_Error(CErrorStr193); + return 0; + } + + functype = TYPE_FUNC(declinfo->thetype)->functype; + args = TYPE_FUNC(declinfo->thetype)->args; + if (args) { + if (args != &elipsis && args != &oldstyle) { + argCount = 1; + if (args->dexpr) { + switch (declinfo->operator_token) { + case TK_NEW: + case TK_DELETE: + case TK_NEW_ARRAY: + case TK_DELETE_ARRAY: + break; + default: + CError_Error(CErrorStr205); + } + } + + secondarg = args->next; + if (secondarg) { + argCount = ((secondarg != &elipsis && !secondarg->next) != 0) ? 2 : 3; + if (secondarg->dexpr) { + switch (declinfo->operator_token) { + case '(': + case TK_NEW: + case TK_DELETE: + case TK_NEW_ARRAY: + case TK_DELETE_ARRAY: + break; + default: + CError_Error(CErrorStr205); + } + } + } + } else { + argCount = 3; + } + } else { + CError_Error(CErrorStr193); + return 0; + } + + isMethod = flag && + IS_TYPEFUNC_METHOD(TYPE_FUNC(declinfo->thetype)) && + !TYPE_METHOD(declinfo->thetype)->is_static; + + switch (declinfo->operator_token) { + case TK_NEW: + case TK_NEW_ARRAY: + if (isMethod || !is_typesame(functype, TYPE(&void_ptr)) || argCount < 1 || args->type != CABI_GetSizeTType()) { + CError_Error(CErrorStr193); + return 0; + } + return 1; + case TK_DELETE: + case TK_DELETE_ARRAY: + if (isMethod || !IS_TYPE_VOID(functype) || argCount < 1 || !is_typesame(args->type, TYPE(&void_ptr))) { + CError_Error(CErrorStr193); + return 0; + } + return 1; + case '=': + if (!isMethod) { + CError_Error(CErrorStr193); + return 0; + } + break; + case '(': + if (!isMethod) { + CError_Error(CErrorStr193); + return 0; + } + return 1; + case '[': + if (!isMethod) { + CError_Error(CErrorStr193); + return 0; + } + break; + case TK_ARROW: + if (argCount != 1 || isMethod == 0) { + CError_Error(CErrorStr193); + return 0; + } + return 1; + case TK_INCREMENT: + case TK_DECREMENT: + if (argCount == 2 && secondarg->type != TYPE(&stsignedint)) { + CError_Error(CErrorStr193); + return 0; + } + break; + } + + if (flag && !isMethod) { + CError_Error(CErrorStr193); + return 0; + } + + switch (declinfo->operator_token) { + case '&': + case '*': + case '+': + case '-': + case TK_INCREMENT: + case TK_DECREMENT: + if (argCount != 1) + goto whatever; + case '!': + case '~': + if (argCount == 1) { + if (flag || CDecl_IsEnumClassTypeOrRef(args->type)) + return 1; + } + break; + case '%': + case ',': + case '/': + case '<': + case '=': + case '>': + case '[': + case '^': + case '|': + case TK_MULT_ASSIGN: + case TK_DIV_ASSIGN: + case TK_MOD_ASSIGN: + case TK_ADD_ASSIGN: + case TK_SUB_ASSIGN: + case TK_SHL_ASSIGN: + case TK_SHR_ASSIGN: + case TK_AND_ASSIGN: + case TK_XOR_ASSIGN: + case TK_OR_ASSIGN: + case TK_LOGICAL_OR: + case TK_LOGICAL_AND: + case TK_LOGICAL_EQ: + case TK_LOGICAL_NE: + case TK_LESS_EQUAL: + case TK_GREATER_EQUAL: + case TK_SHL: + case TK_SHR: + case TK_ARROW: + case TK_DOT_STAR: + case TK_ARROW_STAR: + whatever: + if (argCount == 2) { + if (flag || CDecl_IsEnumClassTypeOrRef(args->type) || CDecl_IsEnumClassTypeOrRef(secondarg->type)) + return 1; + } + break; + } + + CError_Error(CErrorStr193); + return 0; +} + +static void scandirectdeclarator(DeclInfo *declinfo, NameSpace *nspace) { + HashNameNode *saveident; + CScopeSave scopesave; + Boolean flag; + + if (nspace) + CScope_SetNameSpaceScope(nspace, &scopesave); + + if (tk == '(') { + if ((tk = lex()) == ')') { + if (declinfo->x55) { + CDecl_ParseDirectFuncDecl(declinfo); + if (nspace) + CScope_RestoreScope(&scopesave); + return; + } else { + CError_Error(CErrorStr121); + if (nspace) + CScope_RestoreScope(&scopesave); + return; + } + } + + if (!(tk >= TK_AUTO && tk <= TK_BYREF)) { + if (!(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) { + scandecl(declinfo); + if (nspace) + CScope_RestoreScope(&scopesave); + return; + } else { + saveident = tkidentifier; + switch (lookahead()) { + case ')': + case ',': + break; + default: + tkidentifier = saveident; + scandecl(declinfo); + if (nspace) + CScope_RestoreScope(&scopesave); + return; + } + } + } + + if (declinfo->name) + CError_Error(CErrorStr121); + + CDecl_ParseDirectFuncDecl(declinfo); + if (nspace) + CScope_RestoreScope(&scopesave); + return; + } + + if (nspace) { + if (tk == TK_OPERATOR) { + if (!CDecl_ParseOperatorDecl(declinfo)) { + CScope_RestoreScope(&scopesave); + return; + } + + if (declinfo->x54) { + declinfo->nspace = nspace; + declinfo->name = tkidentifier; + if (nspace) + CScope_RestoreScope(&scopesave); + + if (tk == '(') { + tk = lex(); + CDecl_ParseDirectFuncDecl(declinfo); + if (IS_TYPE_FUNC(declinfo->thetype)) + TYPE_FUNC(declinfo->thetype)->flags |= FUNC_CONVERSION; + else + CError_Error(CErrorStr121); + } else { + CError_Error(CErrorStr114); + } + return; + } + + flag = 1; + } else if (tk != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + CScope_RestoreScope(&scopesave); + return; + } else { + flag = 0; + } + + if (declinfo->name) { + CError_Error(CErrorStr121); + CScope_RestoreScope(&scopesave); + return; + } + + declinfo->nspace = nspace; + declinfo->name = tkidentifier; + if (!flag) + tk = lex(); + } else if (tk == TK_IDENTIFIER) { + if (declinfo->name) + CError_Error(CErrorStr121); + declinfo->name = tkidentifier; + tk = lex(); + } else if (tk == TK_OPERATOR) { + if (!CDecl_ParseOperatorDecl(declinfo)) + return; + declinfo->name = tkidentifier; + } + + if (tk == '<' && declinfo->x51) { + declinfo->expltargs = CTempl_ParseUncheckTemplArgs(NULL, 0); + declinfo->has_expltargs = 1; + declinfo->x51 = 0; + tk = lex(); + } + + scandirectdecl1(declinfo); + + if (nspace) + CScope_RestoreScope(&scopesave); +} + +void makememberpointertype(DeclInfo *declinfo, TypeClass *tclass, UInt32 qual) { + TypeMemberPointer *tmemp; + TypeFunc *tfunc; + + if (tclass->flags & CLASS_HANDLEOBJECT) { + CError_Error(CErrorStr191); + declinfo->thetype = (Type *) &stsignedint; + return; + } + if (tclass->sominfo) { + CError_Error(CErrorStr290); + declinfo->thetype = (Type *) &stsignedint; + return; + } + + tmemp = galloc(sizeof(TypeMemberPointer)); + memclrw(tmemp, sizeof(TypeMemberPointer)); + tmemp->type = TYPEMEMBERPOINTER; + tmemp->ty2 = (Type *) tclass; + tmemp->qual = qual; + + if (IS_TYPE_FUNC(declinfo->thetype)) { + tfunc = galloc(sizeof(TypeFunc)); + *tfunc = *TYPE_FUNC(declinfo->thetype); + tmemp->ty1 = (Type *) tfunc; + tmemp->size = 12; + CDecl_MakePTMFuncType(tfunc); + } else { + tmemp->size = 4; + tmemp->ty1 = declinfo->thetype; + } + declinfo->thetype = (Type *) tmemp; +} + +void CDecl_ScanPointer(DeclInfo *declinfo, NameSpace *nspace, Boolean flag) { + NameResult pr; + UInt32 qual; + + while (1) { + qual = (tk == '&') ? Q_REFERENCE : 0; + + for (tk = lex(); ; tk = lex()) { + switch (tk) { + case TK_CONST: + if (qual & Q_CONST) + CError_Error(CErrorStr121); + qual |= Q_CONST; + continue; + case TK_VOLATILE: + if (qual & Q_VOLATILE) + CError_Error(CErrorStr121); + qual |= Q_VOLATILE; + continue; + case TK_RESTRICT: + if (qual & Q_RESTRICT) + CError_Error(CErrorStr121); + qual |= Q_RESTRICT; + continue; + default: + break; + } + break; + } + + if (IS_TYPE_REFERENCE(declinfo->thetype) || ((qual & Q_REFERENCE) && IS_TYPE_VOID(declinfo->thetype))) { + CError_Error(CErrorStr196); + return; + } + + if (nspace) { + makememberpointertype(declinfo, nspace->theclass, qual); + nspace = NULL; + } else { + makethetypepointer(declinfo, qual); + } + + switch (tk) { + case '*': + continue; + case '&': + if (!copts.cplusplus) { + if (flag) + scandirectdeclarator(declinfo, NULL); + return; + } + continue; + case TK_IDENTIFIER: + if (!copts.cplusplus) + break; + if (copts.cpp_extensions && cscope_current->theclass && cscope_current->theclass->classname == tkidentifier && lookahead() == TK_COLON_COLON) { + tk = lex(); + tk = lex(); + break; + } + case TK_COLON_COLON: + if (CScope_ParseQualifiedNameSpace(&pr, 1, 0)) { + if ((nspace = pr.nspace_0)) { + if (nspace->theclass && tk == '*') + continue; + } else { + if (pr.type && IS_TYPE_TEMPLATE(pr.type) && declinfo->x30) { + if (CTempl_IsQualifiedMember(declinfo, pr.type, &nspace)) + scandirectdeclarator(declinfo, nspace); + else + declinfo->x20 = pr.type; + return; + } + CError_Error(CErrorStr121); + } + } + break; + } + break; + } + + if (flag) + scandirectdeclarator(declinfo, nspace); +} + +static void CDecl_TemplatePTM(DeclInfo *declinfo, Type *type) { + TypeMemberPointer *tmemp = galloc(sizeof(TypeMemberPointer)); + tmemp->type = TYPEMEMBERPOINTER; + if (IS_TYPE_FUNC(declinfo->thetype)) { + CDecl_MakePTMFuncType((TypeFunc *) declinfo->thetype); + tmemp->size = 12; + } else { + tmemp->size = 4; + } + + tmemp->ty1 = declinfo->thetype; + tmemp->ty2 = type; + tmemp->qual = 0; + declinfo->thetype = (Type *) tmemp; +} + +void scandeclarator(DeclInfo *declinfo) { + NameResult pr; + NameSpace *nspace; + + switch (tk) { + case '&': + if (!copts.cplusplus) + break; + case '*': + CDecl_ScanPointer(declinfo, NULL, 1); + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(NULL, declinfo); + return; + case TK_IDENTIFIER: + if (!copts.cplusplus) + break; + case TK_COLON_COLON: + if (CScope_ParseQualifiedNameSpace(&pr, 1, 0)) { + nspace = pr.nspace_0; + if (nspace) { + if (nspace->theclass && tk == '*') + CDecl_ScanPointer(declinfo, nspace, 1); + else + scandirectdeclarator(declinfo, nspace); + return; + } + if (pr.type && IS_TYPE_TEMPLATE(pr.type)) { + if (declinfo->x30 && CTempl_IsQualifiedMember(declinfo, pr.type, &nspace)) { + scandirectdeclarator(declinfo, nspace); + return; + } else if (declinfo->x30 && tk == TK_OPERATOR) { + declinfo->x20 = pr.type; + return; + } else if ((tk = lex()) == TK_COLON_COLON && (tk = lex()) == '*') { + CDecl_TemplatePTM(declinfo, pr.type); + tk = lex(); + break; + } else if (declinfo->x30) { + declinfo->x20 = pr.type; + return; + } + } + CError_Error(CErrorStr121); + } + break; + } + + scandirectdeclarator(declinfo, NULL); + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(NULL, declinfo); +} + +void conversion_type_name(DeclInfo *declinfo) { + NameResult pr; + DeclInfo subdeclinfo; + + memclrw(&subdeclinfo, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&subdeclinfo, 0); + + switch (tk) { + case '&': + case '*': + CDecl_ScanPointer(&subdeclinfo, NULL, 0); + break; + case TK_IDENTIFIER: + case TK_COLON_COLON: + if (CScope_ParseQualifiedNameSpace(&pr, 0, 0)) { + if (pr.nspace_0 && pr.nspace_0->theclass && tk == '*') + CDecl_ScanPointer(&subdeclinfo, pr.nspace_0, 0); + else + CError_Error(CErrorStr121); + } + break; + } + + declinfo->name = subdeclinfo.name; + declinfo->thetype = subdeclinfo.thetype; + declinfo->qual |= subdeclinfo.qual; +} + +static void scaninlinefunc(Object *obj) { + short array[256]; + short r29; + CInt64 val; + + if (tk == '{') { + tk = lex(); + r29 = 0; + while (1) { + if (r29 >= 256) { + CError_Error(CErrorStr127); + r29 = 255; + } + val = CExpr_IntegralConstExpr(); + array[r29++] = CInt64_GetULong(&val); + if (tk != '}') { + if (tk != ',') + CError_Error(CErrorStr116); + tk = lex(); + } else { + tk = lex(); + break; + } + } + } else { + val = CExpr_IntegralConstExpr(); + array[0] = CInt64_GetULong(&val); + r29 = 1; + } + + obj->datatype = DINLINEFUNC; + obj->u.ifunc.size = r29 * 2; + obj->u.ifunc.data = galloc(obj->u.ifunc.size); + obj->u.ifunc.xrefs = NULL; + memcpy(obj->u.ifunc.data, array, obj->u.ifunc.size); + + if (tk != ';') + CError_Error(CErrorStr123); +} + +typedef enum { + OverloadMode0, + OverloadMode1, + OverloadMode2, + OverloadMode3 +} OverloadMode; + +static Object *CDecl_OverloadFunctionObject(NameSpaceObjectList *list, DeclInfo *declinfo, Boolean *outflag, OverloadMode mode, Boolean flag2) { + TypeFunc *scanfunc; + NameSpaceObjectList *scan; + TypeFunc *tfunc; + FuncArg *args; + FuncArg *scanargs; + Object *obj; + Boolean r24; + short compareresult; + + if (outflag) + *outflag = 0; + + tfunc = (TypeFunc *) declinfo->thetype; + args = tfunc->args; + r24 = 0; + for (scan = list; scan; scan = scan->next) { + obj = OBJECT(scan->object); + if (obj->otype != OT_OBJECT) + continue; + + scanfunc = TYPE_FUNC(obj->type); + if (!IS_TYPE_FUNC(scanfunc)) + continue; + + scanargs = scanfunc->args; + if (scanfunc->flags & FUNC_IS_TEMPL) + r24 = 1; + + if (IS_TYPEFUNC_METHOD(scanfunc)) { + switch (mode) { + case OverloadMode0: + CError_Error(CErrorStr197); + break; + case OverloadMode1: + if (!TYPE_METHOD(scanfunc)->is_static) + continue; + break; + case OverloadMode2: + if (TYPE_METHOD(scanfunc)->is_static) + continue; + break; + case OverloadMode3: + if (!TYPE_METHOD(scanfunc)->is_static) { + if (scanargs->qual & Q_CV) + continue; + scanargs = scanargs->next; + } + break; + } + } else { + if (mode) + CError_Error(CErrorStr197); + } + + compareresult = CParser_CompareArgLists(args, scanargs); + if (compareresult == 1) { + if (scanfunc->flags & FUNC_CONVERSION) { + if (!(tfunc->flags & FUNC_CONVERSION)) { + CError_Error(CErrorStr197); + break; + } + if (!is_typesame(tfunc->functype, scanfunc->functype)) + continue; + if ((tfunc->qual & Q_CV) != (scanfunc->qual & Q_CV)) + continue; + if ((tfunc->flags & FUNC_CALL_CONV_MASK) != (scanfunc->flags & FUNC_CALL_CONV_MASK)) { + CError_Error(CErrorStr197); + break; + } + if (tfunc->exspecs || scanfunc->exspecs) + CExcept_CompareSpecifications(tfunc->exspecs, scanfunc->exspecs); + return obj; + } + + if (tfunc->flags & FUNC_CONVERSION) { + CError_Error(CErrorStr197); + break; + } + + if ( + !is_typesame(tfunc->functype, scanfunc->functype) || + ((tfunc->qual & (Q_CONST | Q_PASCAL)) != (scanfunc->qual & (Q_CONST | Q_PASCAL))) || + ((tfunc->flags & FUNC_CALL_CONV_MASK) != (scanfunc->flags & FUNC_CALL_CONV_MASK)) + ) + { + CError_Error(CErrorStr197); + break; + } + + if (tfunc->exspecs || scanfunc->exspecs) { + if (obj->name != newp_fobj->name && obj->name != newa_fobj->name && obj->name != delp_fobj->name && obj->name != dela_fobj->name) + CExcept_CompareSpecifications(tfunc->exspecs, scanfunc->exspecs); + } + + return obj; + } else if (compareresult == 2) { + CError_Error(CErrorStr197); + break; + } + } + + if (r24 && (flag2 || declinfo->x3C)) { + if ((obj = CTempl_TemplateFunctionCheck(declinfo, list))) + return obj; + } + + if (!outflag) { + CError_Error(CErrorStr197); + return NULL; + } + + if (declinfo->nspace) + CError_Error(CErrorStr336); + + *outflag = 1; + obj = CParser_NewFunctionObject(declinfo); + CheckDefaultArgs(TYPE_FUNC(obj->type)->args); + + if (tfunc->flags & FUNC_PASCAL) { + for (scan = list; scan; scan = scan->next) { + if (scan->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(scan->object)->type)) { + if (TYPE_FUNC(OBJECT(scan->object)->type)->flags & FUNC_PASCAL) + CError_Error(CErrorStr226); + } + } + } + + if (copts.cplusplus && declinfo->is_extern_c) { + for (scan = list; scan; scan = scan->next) { + if (scan->object->otype == OT_OBJECT && !(OBJECT(scan->object)->qual & Q_MANGLE_NAME)) + CError_Error(CErrorStr197); + } + } + + CScope_AddObject(cscope_current, declinfo->name, OBJ_BASE(obj)); + if (cscope_current->theclass && (cscope_current->theclass->flags & CLASS_IS_TEMPL) && + CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) + CTemplClass_RegisterObjectDef(TEMPL_CLASS(cscope_current->theclass), OBJ_BASE(obj)); + + return obj; +} + +void MergeDefaultArgs(FuncArg *a, FuncArg *b) { + FuncArg *scan_a; + FuncArg *scan_b; + + if (a == &oldstyle || b == &oldstyle) + return; + + scan_a = a; + scan_b = b; + while (scan_a && scan_b) { + if (scan_a->dexpr) { + while (scan_b) { + if (scan_b->dexpr) { + while (a) { + a->dexpr = NULL; + a = a->next; + } + while (b) { + b->dexpr = NULL; + b = b->next; + } + CError_Error(CErrorStr205); + return; + } + scan_b = scan_b->next; + } + break; + } else if (scan_b->dexpr) { + do { + scan_a = scan_a->next; + scan_b = scan_b->next; + if (!scan_a) goto secondpart; + if (scan_a == &elipsis) goto secondpart; + if (scan_a->dexpr && scan_b->dexpr) break; + } while (scan_a->dexpr || scan_b->dexpr); + + while (a) { + a->dexpr = NULL; + a = a->next; + } + while (b) { + b->dexpr = NULL; + b = b->next; + } + CError_Error(CErrorStr205); + return; + } else { + scan_a = scan_a->next; + scan_b = scan_b->next; + } + } + +secondpart: + while (a && b) { + if (b->dexpr) + a->dexpr = b->dexpr; + else + b->dexpr = a->dexpr; + a = a->next; + b = b->next; + } +} + +void CheckDefaultArgs(FuncArg *args) { + FuncArg *scan; + + scan = args; + while (scan && !scan->dexpr) + scan = scan->next; + + while (scan && scan != &elipsis && scan != &oldstyle) { + if (!scan->dexpr) { + while (args) { + args->dexpr = NULL; + args = args->next; + } + CError_Error(CErrorStr205); + return; + } + scan = scan->next; + } +} + +static void CDecl_FuncRedeclCheck(Object *obj, DeclInfo *declinfo, Boolean flag) { + if (declinfo->storageclass == TK_STATIC && obj->sclass != TK_STATIC) { + if (copts.cplusplus) + CError_Error(CErrorStr260); + else + obj->sclass = TK_STATIC; + } + + obj->qual |= declinfo->qual; + if (flag) + CheckDefaultArgs(TYPE_FUNC(obj->type)->args); + else + MergeDefaultArgs(TYPE_FUNC(obj->type)->args, TYPE_FUNC(declinfo->thetype)->args); + + if (!declinfo->x45) + TYPE_FUNC(obj->type)->args = TYPE_FUNC(declinfo->thetype)->args; +} + +Object *CDecl_GetFunctionObject(DeclInfo *declinfo, NameSpace *nspace, Boolean *pflag, Boolean someotherflag) { + NameSpace *nspace2; + Type *type; + Object *obj; + NameSpaceObjectList *list; + TypeMemberFunc tmp; + Boolean r27; + Boolean outflag; + + r27 = 0; + if (pflag) + *pflag = 0; + + nspace2 = declinfo->nspace; + if (!nspace2) + nspace2 = cscope_current; + + CError_QualifierCheck(declinfo->qual & ~(Q_ALIGNED_MASK | Q_WEAK | Q_20000 | Q_INLINE | Q_PASCAL | Q_ASM | Q_VOLATILE | Q_CONST)); + switch (TYPE_FUNC(declinfo->thetype)->functype->type) { + case TYPEFUNC: + case TYPEARRAY: + CError_Error(CErrorStr128); + TYPE_FUNC(declinfo->thetype)->functype = TYPE(&stsignedint); + break; + } + + if (nspace2->theclass) { + CError_ASSERT(1969, declinfo->name); + if (!nspace2->theclass->size) + CDecl_CompleteType(TYPE(nspace2->theclass)); + if (!(list = CScope_GetLocalObject(nspace2, declinfo->name))) { + CError_Error(CErrorStr140, declinfo->name->name); + return NULL; + } + + obj = OBJECT(list->object); + type = obj->type; + if (!IS_TYPE_FUNC(type)) { + CError_Error(CErrorStr249, CError_GetObjectName(obj), type, obj->qual, declinfo->thetype, declinfo->qual); + return NULL; + } + + if (declinfo->has_expltargs) + return CTempl_TemplateFunctionCheck(declinfo, list); + + if (declinfo->x3C || (list->next && list->next->object->otype == OT_OBJECT)) { + if (TYPE_FUNC(declinfo->thetype)->flags & (FUNC_CONST | FUNC_VOLATILE)) { + CDecl_AddThisPointerArgument(TYPE_FUNC(declinfo->thetype), nspace2->theclass); + obj = CDecl_OverloadFunctionObject(list, declinfo, NULL, OverloadMode2, someotherflag); + if (!obj) + return NULL; + } else { + obj = CDecl_OverloadFunctionObject(list, declinfo, NULL, OverloadMode3, someotherflag); + if (!obj) + return NULL; + if (!TYPE_METHOD(obj->type)->is_static) + CDecl_AddThisPointerArgument(TYPE_FUNC(declinfo->thetype), nspace2->theclass); + } + } else { + if (TYPE_METHOD(type)->is_static) { + if (nspace2->theclass->sominfo) + CSOM_FixNewDeleteFunctype(TYPE_FUNC(declinfo->thetype)); + } else { + CDecl_AddThisPointerArgument(TYPE_FUNC(declinfo->thetype), nspace2->theclass); + } + + if (copts.cpp_extensions) { + declinfo->qual |= obj->qual & (Q_PASCAL | Q_CONST); + TYPE_FUNC(declinfo->thetype)->qual |= TYPE_FUNC(obj->type)->qual & (Q_PASCAL | Q_CONST); + TYPE_FUNC(declinfo->thetype)->flags |= TYPE_FUNC(obj->type)->flags & (FUNC_FLAGS_4000000 | FUNC_FLAGS_10000000); + } + + if (!is_typesame(declinfo->thetype, obj->type) || (declinfo->qual & (Q_PASCAL | Q_CONST)) != (obj->qual & (Q_PASCAL | Q_CONST))) { + tmp = *TYPE_METHOD(obj->type); + *(TYPE_FUNC(&tmp)) = *TYPE_FUNC(declinfo->thetype); + tmp.flags |= FUNC_METHOD; + CError_Error(CErrorStr249, CError_GetObjectName(obj), obj->type, obj->qual, &tmp, declinfo->qual); + } + + if (TYPE_FUNC(declinfo->thetype)->exspecs || TYPE_FUNC(obj->type)->exspecs) + CExcept_CompareSpecifications(TYPE_FUNC(declinfo->thetype)->exspecs, TYPE_FUNC(obj->type)->exspecs); + } + + CDecl_FuncRedeclCheck(obj, declinfo, 0); + if (declinfo->x3C) { + if (obj->nspace->theclass && !(obj->nspace->theclass->flags & CLASS_IS_TEMPL_INST)) + CError_Error(CErrorStr335); + declinfo->x3C = 0; + } + } else { + if (TYPE_FUNC(declinfo->thetype)->flags & (FUNC_VOLATILE | FUNC_CONST)) + CError_Error(CErrorStr384); + + if (declinfo->operator_token && !CDecl_CheckOperatorType(declinfo, 0)) + return NULL; + + list = CScope_GetLocalObject(nspace2, declinfo->name); + if (declinfo->has_expltargs) + return CTempl_TemplateFunctionCheck(declinfo, list); + + if (list) { + if (copts.cplusplus) { + obj = CDecl_OverloadFunctionObject(list, declinfo, &outflag, OverloadMode0, someotherflag); + if (!obj) + return NULL; + if (pflag) + *pflag = outflag; + if (nspace) + obj->nspace = nspace; + } else { + obj = OBJECT(list->object); + if (!is_typesame(declinfo->thetype, obj->type) || (declinfo->qual & (Q_CONST | Q_PASCAL)) != (obj->qual & (Q_CONST | Q_PASCAL))) { + CError_Error(CErrorStr249, CError_GetObjectName(obj), obj->type, obj->qual, declinfo->thetype, declinfo->qual); + r27 = 1; + if (!IS_TYPE_FUNC(obj->type)) + return NULL; + } + } + + if (!r27 && pflag) + CDecl_FuncRedeclCheck(obj, declinfo, *pflag); + } else { + if (declinfo->nspace) + CError_Error(CErrorStr336); + + if (declinfo->has_expltargs) { + if (declinfo->name) + CError_Error(CErrorStr140, declinfo->name->name); + else + CError_Error(CErrorStr127); + } + + obj = CParser_NewFunctionObject(declinfo); + if (nspace) + obj->nspace = nspace; + if (pflag) + *pflag = 1; + else + CError_Error(CErrorStr127); + + CheckDefaultArgs(TYPE_FUNC(obj->type)->args); + CScope_AddObject(nspace2, declinfo->name, OBJ_BASE(obj)); + } + } + + return obj; +} + +void CDecl_TypedefDeclarator(DeclInfo *declinfo) { + NameSpace *nspace; + NameSpaceObjectList *list; + ObjType *objt; + + nspace = declinfo->nspace; + if (!nspace) + nspace = cscope_current; + + CError_QualifierCheck(declinfo->qual & ~(Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST)); + if (declinfo->x48 || declinfo->x44) + CError_Error(CErrorStr121); + if (declinfo->operator_token) + CError_Error(CErrorStr193); + + objt = NULL; + list = CScope_FindName(nspace, declinfo->name); + if (list) { + switch (list->object->otype) { + case OT_TYPE: + objt = OBJ_TYPE(list->object); + break; + case OT_TYPETAG: + break; + case OT_NAMESPACE: + CError_Error(CErrorStr321); + return; + case OT_ENUMCONST: + case OT_OBJECT: + CError_Error(CErrorStr322); + return; + default: + CError_FATAL(2156); + } + } + + if (objt) { + const UInt32 mask = Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST; + if (!is_typesame(objt->type, declinfo->thetype) || (objt->qual & mask) != (declinfo->qual & mask)) { + CError_Error(CErrorStr249, declinfo->name->name, objt->type, objt->qual, declinfo->thetype, declinfo->qual); + } else if (!copts.cplusplus && (copts.pedantic || copts.ANSIstrict)) { + if (copts.pedantic) + CError_Warning(CErrorStr122, declinfo->name->name); + else + CError_Error(CErrorStr122, declinfo->name->name); + } + return; + } + + objt = galloc(sizeof(ObjType)); + memclrw(objt, sizeof(ObjType)); + objt->otype = OT_TYPE; + objt->access = ACCESSPUBLIC; + objt->type = declinfo->thetype; + objt->qual = declinfo->qual; + CScope_AddObject(nspace, declinfo->name, OBJ_BASE(objt)); + + if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL) && + CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) + CTemplClass_RegisterObjectDef(TEMPL_CLASS(nspace->theclass), OBJ_BASE(objt)); + + if (copts.cplusplus) { + if (IS_TYPE_CLASS(declinfo->thetype) && IsTempName(TYPE_CLASS(declinfo->thetype)->classname)) { + TYPE_CLASS(declinfo->thetype)->classname = declinfo->name; + TYPE_CLASS(declinfo->thetype)->nspace->name = declinfo->name; + } + if (IS_TYPE_ENUM(declinfo->thetype) && IsTempName(TYPE_ENUM(declinfo->thetype)->enumname)) { + TYPE_ENUM(declinfo->thetype)->enumname = declinfo->name; + } + } + + if (cparamblkptr->browseoptions.recordTypedefs && declinfo->file->recordbrowseinfo) + CBrowse_NewTypedef(nspace, declinfo->name, declinfo->file, declinfo->file2, declinfo->sourceoffset, CPrep_BrowserFileOffset()); +} + +static void CDecl_DataDeclarator(DeclInfo *declinfo, AccessType access, Boolean flag) { + NameSpaceObjectList *list; + Object *obj; + NameSpace *nspace; + Boolean tmpflag; + ENode *expr; + + nspace = declinfo->nspace; + if (!nspace) + nspace = cscope_current; + + CError_QualifierCheck(declinfo->qual & ~(Q_ALIGNED_MASK | Q_WEAK | Q_20000 | Q_PASCAL | Q_VOLATILE | Q_CONST)); + if (declinfo->x48 || declinfo->x44) + CError_Error(CErrorStr121); + if (declinfo->operator_token) + CError_Error(CErrorStr193); + + obj = NULL; + list = CScope_FindName(nspace, declinfo->name); + if (list) { + switch (list->object->otype) { + case OT_OBJECT: + obj = OBJECT(list->object); + if (flag) + CError_Error(CErrorStr122, declinfo->name->name); + break; + case OT_TYPETAG: + break; + case OT_NAMESPACE: + CError_Error(CErrorStr321); + return; + case OT_ENUMCONST: + case OT_TYPE: + CError_Error(CErrorStr322); + break; + case OT_MEMBERVAR: + CError_Error(CErrorStr221); + break; + default: + CError_FATAL(2281); + } + } + + if (copts.cplusplus) { + if (!flag) + CDecl_CompleteType(declinfo->thetype); + switch (declinfo->storageclass) { + case TK_EXTERN: + if (tk == '=' || tk == '(') + declinfo->storageclass = 0; + break; + case 0: + if (CParser_IsConst(declinfo->thetype, declinfo->qual)) { + if ((!obj && !nspace->theclass) || (obj && obj->sclass != TK_EXTERN && !obj->nspace->theclass)) + declinfo->storageclass = TK_STATIC; + } + break; + } + } else { + if (declinfo->storageclass == TK_EXTERN && tk == '=') + declinfo->storageclass = 0; + } + + if (IS_TYPE_ARRAY(declinfo->thetype) && !declinfo->thetype->size && !declinfo->storageclass && tk != '=') + declinfo->storageclass = TK_EXTERN; + + if (obj) { + if ((!obj->type->size || !declinfo->thetype->size) && IS_TYPE_ARRAY(declinfo->thetype) && IS_TYPE_ARRAY(obj->type)) + tmpflag = is_typesame(TYPE_POINTER(declinfo->thetype)->target, TYPE_POINTER(obj->type)->target); + else + tmpflag = is_typesame(declinfo->thetype, obj->type); + + if (!tmpflag || (obj->qual & (Q_PASCAL | Q_VOLATILE | Q_CONST)) != (declinfo->qual & (Q_PASCAL | Q_VOLATILE | Q_CONST))) + CError_Error(CErrorStr249, CError_GetObjectName(obj), obj->type, obj->qual, declinfo->thetype, declinfo->qual); + + if (obj->qual & Q_INLINE_DATA) { + if (tk == ',' || tk == ';') + return; + CError_Error(CErrorStr333, obj); + } + + if (declinfo->storageclass != TK_EXTERN) { + if (obj->sclass != TK_EXTERN && declinfo->storageclass && obj->sclass != declinfo->storageclass) + CError_Error(CErrorStr333, obj); + + if (tmpflag) { + obj->sclass = declinfo->storageclass; + obj->qual |= declinfo->qual; + if (declinfo->thetype->size) + obj->type = declinfo->thetype; + } + + CParser_UpdateObject(obj, declinfo); + } else { + flag = 1; + } + } else { + if (declinfo->nspace) + CError_Error(CErrorStr336); + if (IS_TYPE_CLASS(declinfo->thetype) && TYPE_CLASS(declinfo->thetype)->sominfo) + CError_Error(CErrorStr288); + if (!CanCreateObject(declinfo->thetype)) + declinfo->thetype = TYPE(&stsignedint); + + obj = CParser_NewGlobalDataObject(declinfo); + obj->access = access; + CScope_AddObject(nspace, declinfo->name, OBJ_BASE(obj)); + + if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL) && + CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) + CTemplClass_RegisterObjectDef(TEMPL_CLASS(nspace->theclass), OBJ_BASE(obj)); + + if (flag && nspace->theclass && cparamblkptr->browseoptions.recordClasses) + CBrowse_AddClassMemberData(obj, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset()); + } + + if (!flag) { + if (declinfo->nspace) { + CScopeSave save; + CScope_SetNameSpaceScope(declinfo->nspace, &save); + CInit_InitializeData(obj); + CScope_RestoreScope(&save); + + if (declinfo->x3C && obj->nspace->theclass && (TYPE_CLASS(obj->nspace->theclass)->flags & CLASS_IS_TEMPL_INST)) + declinfo->x3C = 0; + } else { + CInit_InitializeData(obj); + } + + if (declinfo->file->recordbrowseinfo && obj->sclass != TK_EXTERN) + CBrowse_NewData(obj, declinfo->file, declinfo->file2, declinfo->sourceoffset, CPrep_BrowserFileOffset()); + } else if (tk == '=') { + tk = lex(); + expr = CExpr_IntegralConstOrDepExpr(); + if (IS_TYPE_TEMPLATE(obj->type) || !ENODE_IS(expr, EINTCONST)) { + CError_ASSERT(2426, nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL)); + CTemplClass_RegisterObjectInit(TEMPL_CLASS(nspace->theclass), obj, expr); + } else if ((obj->qual & Q_CONST) && IS_TYPE_INT_OR_ENUM(obj->type)) { + obj->u.data.u.intconst = expr->data.intval; + obj->qual |= Q_INLINE_DATA | Q_20000; + } else { + CError_Error(CErrorStr354, obj->name->name); + } + } +} + +Boolean CDecl_FunctionDeclarator(DeclInfo *declinfo, NameSpace *nspace, Boolean flag, Boolean flag2) { + Object *obj; + Boolean pflag; + + obj = CDecl_GetFunctionObject(declinfo, nspace, &pflag, 0); + if (obj) { + if (declinfo->x44 || tk == '{' || tk == TK_TRY || (declinfo->x4B && tk == ':') || (!copts.cplusplus && isdeclaration(0, 0, 0, 0))) { + if (!flag || cscope_currentfunc) { + CError_Error(CErrorStr127); + if (cscope_currentfunc) + return 0; + } + + if (obj->nspace == cscope_root && !strcmp(obj->name->name, "main")) { + if (obj->sclass == TK_STATIC || (copts.ANSIstrict && TYPE_FUNC(obj->type)->functype != (Type *) &stsignedint)) + CError_Error(CErrorStr334); + } else if (copts.checkprotos && (pflag || declinfo->x64)) { + if (obj->sclass != TK_STATIC && !(obj->qual & Q_INLINE) && !obj->nspace->is_unnamed) + CError_Warning(CErrorStr178); + } + + CFunc_ParseFuncDef(obj, declinfo, NULL, 0, 0, NULL); + if (declinfo->file->recordbrowseinfo) + CBrowse_NewFunction( + obj, + declinfo->file, + declinfo->file2, + declinfo->sourceoffset, + CPrep_BrowserFileOffset()); + + if (copts.cplusplus && lookahead() == ';') + tk = lex(); + return 0; + } + } + + return 1; +} + +static void CDecl_ParseSpecialMember(DeclInfo *declinfo, Boolean flag) { + Object *r28; + NameSpace *r25; + + if (!(r28 = declinfo->x10)) { + CError_ASSERT(2544, declinfo->x14); + r28 = OBJECT(declinfo->x14->object); + CError_ASSERT(2546, r28->otype == OT_OBJECT); + } + + if (!r28->nspace->theclass) { + CError_Error(CErrorStr121); + return; + } + + if (IS_TYPE_FUNC(r28->type)) { + if (TYPE_FUNC(r28->type)->flags & (FUNC_IS_CTOR | FUNC_IS_DTOR)) { + if (r28->nspace->theclass->sominfo) + declinfo->thetype = TYPE(&stvoid); + else + declinfo->thetype = TYPE(&void_ptr); + declinfo->nspace = r28->nspace; + declinfo->name = r28->name; + if (TYPE_FUNC(r28->type)->flags & FUNC_IS_CTOR) + declinfo->x4B = 1; + + if ((tk = lex()) == '(') { + tk = lex(); + + r25 = cscope_current; + cscope_current = r28->nspace; + CDecl_ParseDirectFuncDecl(declinfo); + cscope_current = r25; + + if (IS_TYPE_FUNC(declinfo->thetype)) { + if (TYPE_FUNC(r28->type)->flags & FUNC_IS_CTOR) { + if ((r28->nspace->theclass->flags & CLASS_HAS_VBASES) && !r28->nspace->theclass->sominfo) + CDecl_AddArgument(TYPE_FUNC(declinfo->thetype), TYPE(&stsignedshort)); + } else { + if (!r28->nspace->theclass->sominfo) + CDecl_AddArgument(TYPE_FUNC(declinfo->thetype), TYPE(&stsignedshort)); + } + if (flag) + CDecl_FunctionDeclarator(declinfo, NULL, 1, 1); + } else { + CError_Error(CErrorStr121); + } + } else { + CError_Error(CErrorStr114); + } + return; + } else if (TYPE_FUNC(r28->type)->flags & FUNC_CONVERSION) { + CError_FATAL(2603); + + declinfo->thetype = TYPE_FUNC(r28->type)->functype; + declinfo->qual |= TYPE_FUNC(r28->type)->qual; + declinfo->nspace = r28->nspace; + declinfo->name = r28->name; + + if ((tk = lex()) == '(') { + tk = lex(); + CDecl_ParseDirectFuncDecl(declinfo); + if (IS_TYPE_FUNC(declinfo->thetype)) { + TYPE_FUNC(declinfo->thetype)->flags |= FUNC_CONVERSION; + if (flag) + CDecl_FunctionDeclarator(declinfo, NULL, 1, 1); + } else { + CError_Error(CErrorStr121); + } + } else { + CError_Error(CErrorStr114); + } + return; + } else { + declinfo->thetype = TYPE(&stsignedint); + declinfo->nspace = r28->nspace; + declinfo->name = r28->name; + + if ((tk = lex()) == '(') { + tk = lex(); + + r25 = cscope_current; + cscope_current = r28->nspace; + CDecl_ParseDirectFuncDecl(declinfo); + cscope_current = r25; + + if (IS_TYPE_FUNC(declinfo->thetype)) { + if (flag) + CDecl_FunctionDeclarator(declinfo, NULL, 1, 1); + return; + } + } else { + CError_Error(CErrorStr114); + } + } + } + + CError_Error(CErrorStr121); +} + +void CDecl_ScanDeclarator(DeclInfo *declinfo) { + if (declinfo->x14 || declinfo->x10) { + CDecl_ParseSpecialMember(declinfo, 0); + CDecl_GetFunctionObject(declinfo, NULL, NULL, 1); + return; + } + + if (IS_TYPE_FUNC(declinfo->thetype)) { + TypeFunc *copy = galloc(sizeof(TypeFunc)); + *copy = *TYPE_FUNC(declinfo->thetype); + declinfo->thetype = TYPE(copy); + } + scandeclarator(declinfo); + if (!declinfo->name) { + CError_Error(CErrorStr121); + return; + } + + if (declinfo->storageclass && declinfo->storageclass != TK_EXTERN) + CError_Error(CErrorStr177); + + if (IS_TYPE_FUNC(declinfo->thetype)) { + CDecl_GetFunctionObject(declinfo, NULL, NULL, 1); + return; + } + + if (declinfo->x48 || declinfo->x44) + CError_Error(CErrorStr121); + + if (declinfo->operator_token) + CError_Error(CErrorStr193); + + if ( + (declinfo->qual & ~(Q_ALIGNED_MASK | Q_WEAK | Q_20000 | Q_PASCAL | Q_VOLATILE | Q_CONST)) || + (declinfo->storageclass == TK_TYPEDEF && (declinfo->qual & ~(Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST))) + ) + CError_Error(CErrorStr176); +} + +void scandeclaratorlist(DeclInfo *declinfo) { + CScopeSave savescope; + Type *r30; + UInt32 r29; + Boolean r28; + + if (declinfo->x14 || declinfo->x10) { + CDecl_ParseSpecialMember(declinfo, 1); + return; + } + + CScope_GetScope(&savescope); + CError_ASSERT(2707, declinfo->thetype); + + r28 = 1; + while (1) { + r30 = declinfo->thetype; + r29 = declinfo->qual; + declinfo->nspace = NULL; + declinfo->operator_token = 0; + if (IS_TYPE_FUNC(r30)) { + declinfo->thetype = galloc(sizeof(TypeFunc)); + *TYPE_FUNC(declinfo->thetype) = *TYPE_FUNC(r30); + } + declinfo->name = NULL; + scandeclarator(declinfo); + if (!declinfo->name) { + CError_Error(CErrorStr121); + break; + } + + if (declinfo->storageclass != TK_TYPEDEF) { + if (IS_TYPE_FUNC(declinfo->thetype)) { + if (!CDecl_FunctionDeclarator(declinfo, NULL, r28, 1)) + return; + } else { + CDecl_DataDeclarator(declinfo, ACCESSPUBLIC, 0); + } + } else { + CDecl_TypedefDeclarator(declinfo); + } + + CScope_RestoreScope(&savescope); + declinfo->thetype = r30; + declinfo->qual = r29; + + if (tk != ',') + break; + tk = lex(); + r28 = 0; + } + + if (tk != ';') + CError_Error(CErrorStr123); +} + +static TypeIntegral *CDecl_FindSignedType(short size) { + if (stsignedchar.size == size) + return &stsignedchar; + if (stsignedshort.size == size) + return &stsignedshort; + if (stsignedint.size == size) + return &stsignedint; + if (stsignedlong.size == size) + return &stsignedlong; + if (copts.longlong && copts.longlong_enums && stsignedlonglong.size == size) + return &stsignedlonglong; + return &stsignedlong; +} + +static TypeIntegral *CDecl_FindUnsignedType(short size) { + if (stunsignedchar.size == size) + return &stunsignedchar; + if (stunsignedshort.size == size) + return &stunsignedshort; + if (stunsignedint.size == size) + return &stunsignedint; + if (stunsignedlong.size == size) + return &stunsignedlong; + if (copts.longlong && copts.longlong_enums && stunsignedlonglong.size == size) + return &stunsignedlonglong; + return &stunsignedlong; +} + +static TypeIntegral *CDecl_IterateIntegralEnumType(int *t) { + switch (*t) { + case 0: + *t = 1; + return &stsignedchar; + case 1: + if (stsignedshort.size > stsignedchar.size) { + *t = 2; + return &stsignedshort; + } + case 2: + if (stsignedint.size > stsignedshort.size) { + *t = 3; + return &stsignedint; + } + case 3: + if (stsignedlong.size > stsignedint.size) { + *t = 4; + return &stsignedlong; + } + case 4: + *t = 5; + if (stsignedlonglong.size > stsignedlong.size && copts.longlong && copts.longlong_enums) + return &stsignedlonglong; + default: + return NULL; + } +} + +static TypeIntegral *CDecl_IterateUIntegralEnumType(int *t) { + switch (*t) { + case 0: + *t = 1; + return &stunsignedchar; + case 1: + if (stunsignedshort.size > stunsignedchar.size) { + *t = 2; + return &stunsignedshort; + } + case 2: + if (stunsignedint.size > stunsignedshort.size) { + *t = 3; + return &stunsignedint; + } + case 3: + if (stunsignedlong.size > stunsignedint.size) { + *t = 4; + return &stunsignedlong; + } + case 4: + *t = 5; + if (stunsignedlonglong.size > stunsignedlong.size && copts.longlong && copts.longlong_enums) + return &stunsignedlonglong; + default: + return NULL; + } +} + +static TypeEnum *CDecl_OldParseEnumList(TypeEnum *tenum, HashNameNode *name) { + AccessType access; + Boolean has_template_value; + Boolean r24; + Boolean r23; + ObjEnumConst *oec; + ObjEnumConst *last; + Boolean overflowed; + CInt64 val; + CInt64 minimum; + CInt64 maximum; + CInt64 var_74; + CInt64 unused; + Type *basetype; + Type *basetype2; + CPrepFileInfo *fileinfo; + SInt32 offset; + ENode *expr; + Type *tmp; + + if (!tenum) { + tenum = galloc(sizeof(TypeEnum)); + memclrw(tenum, sizeof(TypeEnum)); + tenum->type = TYPEENUM; + tenum->nspace = cscope_current; + + if (name) { + tenum->enumname = name; + CScope_DefineTypeTag(cscope_current, name, TYPE(tenum)); + } + + if (!cscope_current->is_global) { + do { + tenum->nspace = tenum->nspace->parent; + } while (!tenum->nspace->is_global); + if (tenum->enumname) + tenum->enumname = CParser_AppendUniqueNameFile(tenum->enumname->name); + } + } + + if (cscope_current->theclass && (cscope_current->theclass->flags & CLASS_IS_TEMPL)) { + CTemplClass_RegisterEnumType(TEMPL_CLASS(cscope_current->theclass), tenum); + } + + access = cscope_current->theclass ? global_access : ACCESSPUBLIC; + last = NULL; + unused = cint64_zero; + val = cint64_zero; + minimum = cint64_zero; + maximum = cint64_zero; + r23 = 0; + if (copts.enumsalwaysint) { + basetype = TYPE(&stsignedint); + r24 = 1; + } else { + basetype = TYPE(&stunsignedchar); + r24 = 0; + } + + tk = lex(); + if (!copts.cplusplus || tk != '}') { + do { + if (tk != TK_IDENTIFIER) { + if (tk == '}') { + if (copts.cpp_extensions) + break; + if (!copts.warn_extracomma) + break; + } + CError_Warning(CErrorStr107); + break; + } + + oec = galloc(sizeof(ObjEnumConst)); + memclrw(oec, sizeof(ObjEnumConst)); + oec->otype = OT_ENUMCONST; + oec->access = access; + oec->type = TYPE(tenum); + oec->name = tkidentifier; + CPrep_BrowserFilePosition(&fileinfo, &offset); + overflowed = 0; + if ((tk = lex()) == '=') { + tk = lex(); + val = CExpr_IntegralConstExprType(&basetype2); + if (!CInt64_IsNegative(&val) || is_unsigned(basetype2)) { + if (CInt64_GreaterU(val, minimum)) { + minimum = val; + overflowed = 1; + } + } else { + if (CInt64_Less(val, maximum)) { + maximum = val; + overflowed = 1; + } + if (!r24) { + basetype = TYPE(&stsignedchar); + r24 = 1; + } + } + r23 = 0; + } else { + if (r23) + CError_Error(CErrorStr154); + + if (!r24 || !CInt64_IsNegative(&val)) { + if (CInt64_GreaterU(val, minimum)) { + minimum = val; + overflowed = 1; + } + } else { + if (CInt64_Less(val, maximum)) { + maximum = val; + overflowed = 1; + } + } + } + + if (copts.enumsalwaysint) { + if (copts.ANSIstrict) { + if (!CInt64_IsInRange(val, stsignedint.size)) + CError_Error(CErrorStr154); + } else { + if (!CInt64_IsInRange(val, stsignedint.size) && !CInt64_IsInURange(val, stunsignedint.size)) + CError_Error(CErrorStr154); + } + } else if (r24) { + switch (basetype->size) { + case 1: + if (CInt64_IsInRange(minimum, 1) && CInt64_IsInRange(maximum, 1)) + break; + basetype = TYPE(CDecl_FindSignedType(2)); + case 2: + if (CInt64_IsInRange(minimum, 2) && CInt64_IsInRange(maximum, 2)) + break; + basetype = TYPE(CDecl_FindSignedType(4)); + case 4: + if (CInt64_IsInRange(minimum, 4) && CInt64_IsInRange(maximum, 4)) + break; + basetype = TYPE(CDecl_FindSignedType(8)); + if (basetype->size != 8) { + if (!copts.ANSIstrict && CInt64_IsInRange(maximum, 4) && CInt64_IsInURange(minimum, 4)) + break; + if (overflowed) + CError_Error(CErrorStr154); + break; + } + case 8: + if (CInt64_Equal(val, minimum) && CInt64_IsNegative(&val)) + CError_Error(CErrorStr154); + break; + default: + CError_FATAL(3071); + } + } else { + switch (basetype->size) { + case 1: + if (CInt64_IsInURange(minimum, 1)) + break; + basetype = TYPE(CDecl_FindUnsignedType(2)); + case 2: + if (CInt64_IsInURange(minimum, 2)) + break; + basetype = TYPE(CDecl_FindUnsignedType(4)); + case 4: + if (CInt64_IsInURange(minimum, 4)) + break; + basetype = TYPE(CDecl_FindUnsignedType(8)); + if (basetype->size != 8) { + if (overflowed) + CError_Error(CErrorStr154); + break; + } + case 8: + break; + default: + CError_FATAL(3099); + } + } + + tenum->size = basetype->size; + tenum->enumtype = basetype; + oec->val = val; + CScope_AddObject(cscope_current, oec->name, OBJ_BASE(oec)); + + if (last) { + last->next = oec; + last = oec; + } else { + last = oec; + tenum->enumlist = oec; + } + + if (cparamblkptr->browseoptions.recordEnums) { + CPrepFileInfo *f = CPrep_BrowserCurrentFile(); + if (f->recordbrowseinfo) { + CBrowse_NewEnumConstant(cscope_current, oec->name, f, fileinfo, offset, CPrep_BrowserFileOffset()); + } + } + + var_74 = CInt64_Add(val, cint64_one); + if (r24) { + if (CInt64_IsNegative(&var_74) && !CInt64_IsNegative(&val)) + r23 = 1; + } else { + if (CInt64_IsZero(&var_74)) + r23 = 1; + } + val = var_74; + + if (tk != ',') + break; + tk = lex(); + } while (1); + } + + tenum->size = basetype->size; + tenum->enumtype = basetype; + + for (oec = tenum->enumlist; oec; oec = oec->next) + oec->type = TYPE(tenum); + + if (tk != '}') + CError_ErrorSkip(CErrorStr130); + else + tk = lex(); + + return tenum; +} + +static Type *CDecl_MaxType(Type *a, Type *b) { + if (a->size > b->size) + return a; + if (b->size > a->size) + return b; + if (is_unsigned(b)) + return b; + else + return a; +} + +void CDecl_ComputeUnderlyingEnumType(TypeEnum *tenum) { + ObjEnumConst *oec; + ObjEnumConst *oec2; + Type *r26; + int t; + + if (!copts.enumsalwaysint) { + for (oec2 = tenum->enumlist; oec2; oec2 = oec2->next) { + if (CInt64_IsNegative(&oec2->val) && !is_unsigned(oec2->type)) + break; + } + + if (oec2) { + CInt64 unused = cint64_zero; + CInt64 minimum = cint64_zero; + CInt64 maximum = cint64_zero; + for (oec = tenum->enumlist; oec; oec = oec->next) { + if (CInt64_IsNegative(&oec->val) && !is_unsigned(oec->type)) { + if (CInt64_Less(oec->val, minimum)) + minimum = oec->val; + } else { + if (CInt64_GreaterU(oec->val, maximum)) + maximum = oec->val; + } + } + + if (CInt64_IsNegative(&maximum)) + CError_Error(CErrorStr154); + + t = 0; + do { + r26 = TYPE(CDecl_IterateIntegralEnumType(&t)); + if (!r26) { + r26 = TYPE(&stsignedlong); + CError_Error(CErrorStr154); + break; + } + + if (CInt64_IsInRange(maximum, r26->size) && CInt64_IsInRange(minimum, r26->size)) + break; + if (r26->size == stsignedlong.size && !copts.ANSIstrict && CInt64_IsInRange(minimum, r26->size) && CInt64_IsInURange(maximum, r26->size)) + break; + } while (1); + } else { + CInt64 val = cint64_zero; + + for (oec = tenum->enumlist; oec; oec = oec->next) { + if (CInt64_GreaterU(oec->val, val)) + val = oec->val; + } + + t = 0; + do { + r26 = TYPE(CDecl_IterateUIntegralEnumType(&t)); + if (!r26) { + r26 = TYPE(&stunsignedlong); + CError_Error(CErrorStr154); + break; + } + if (CInt64_IsInURange(val, r26->size)) + break; + } while (1); + } + } else { + r26 = TYPE(&stsignedint); + } + + tenum->size = r26->size; + tenum->enumtype = r26; + for (oec = tenum->enumlist; oec; oec = oec->next) + oec->type = TYPE(tenum); +} + +static Type *CDecl_FindUnderlyingType(short size, CInt64 *a, CInt64 *b) { + if (CInt64_IsZero(a)) { + if (size <= stsignedchar.size && CInt64_IsInURange(*b, stunsignedchar.size)) + return TYPE(&stunsignedchar); + if (size <= stsignedshort.size && CInt64_IsInURange(*b, stunsignedshort.size)) + return TYPE(&stunsignedshort); + if (size <= stsignedint.size && CInt64_IsInURange(*b, stunsignedint.size)) + return TYPE(&stunsignedint); + if (size <= stsignedlong.size && CInt64_IsInURange(*b, stunsignedlong.size)) + return TYPE(&stunsignedlong); + if (size <= stsignedlonglong.size && copts.longlong && copts.longlong_enums && CInt64_IsInURange(*b, stunsignedlonglong.size)) + return TYPE(&stunsignedlonglong); + } else { + if (size <= stsignedchar.size && CInt64_IsInRange(*a, stsignedchar.size) && CInt64_IsInRange(*b, stsignedchar.size)) + return TYPE(&stsignedchar); + if (size <= stsignedshort.size && CInt64_IsInRange(*a, stsignedshort.size) && CInt64_IsInRange(*b, stsignedshort.size)) + return TYPE(&stsignedshort); + if (size <= stsignedint.size && CInt64_IsInRange(*a, stsignedint.size) && CInt64_IsInRange(*b, stsignedint.size)) + return TYPE(&stsignedint); + if (size <= stsignedlong.size && CInt64_IsInRange(*a, stsignedlong.size) && CInt64_IsInRange(*b, stsignedlong.size)) + return TYPE(&stsignedlong); + if (size <= stsignedlonglong.size && copts.longlong && copts.longlong_enums && CInt64_IsInRange(*a, stsignedlonglong.size) && CInt64_IsInRange(*b, stsignedlonglong.size)) + return TYPE(&stsignedlonglong); + if (!copts.ANSIstrict && size <= stsignedlong.size && CInt64_IsInRange(*a, stsignedlong.size) && CInt64_IsInURange(*b, stunsignedlong.size)) + return TYPE(&stsignedlong); + } + + return NULL; +} + +static TypeEnum *CDecl_ParseEnumList(TypeEnum *tenum, HashNameNode *name) { + AccessType access; + TemplClass *tmclass; + ObjEnumConst *oec; + Boolean has_template_value; + Boolean overflowed; + Boolean is_first; + CInt64 val; + CInt64 minimum; + CInt64 maximum; + CInt64 unused; + Type *basetype; + CPrepFileInfo *fileinfo; + SInt32 offset; + ENode *expr; + Type *tmp; + ObjEnumConst *last; + + if (!tenum) { + tenum = galloc(sizeof(TypeEnum)); + memclrw(tenum, sizeof(TypeEnum)); + tenum->type = TYPEENUM; + tenum->nspace = cscope_current; + + if (name) { + tenum->enumname = name; + CScope_DefineTypeTag(cscope_current, name, TYPE(tenum)); + } + + if (!cscope_current->is_global) { + do { + tenum->nspace = tenum->nspace->parent; + } while (!tenum->nspace->is_global); + if (tenum->enumname) + tenum->enumname = CParser_AppendUniqueNameFile(tenum->enumname->name); + } + } + + if (cscope_current->theclass && (cscope_current->theclass->flags & CLASS_IS_TEMPL)) { + tmclass = TEMPL_CLASS(cscope_current->theclass); + CTemplClass_RegisterEnumType(tmclass, tenum); + } else { + tmclass = NULL; + } + + access = cscope_current->theclass ? global_access : ACCESSPUBLIC; + last = NULL; + is_first = 1; + has_template_value = 0; + unused = cint64_zero; + val = cint64_zero; + minimum = cint64_zero; + maximum = cint64_zero; + basetype = copts.enumsalwaysint ? TYPE(&stsignedint) : TYPE(&stsignedchar); + tenum->size = basetype->size; + tenum->enumtype = basetype; + + do { + if ((tk = lex()) != TK_IDENTIFIER) { + if (tk == '}') { + if (is_first) { + if (copts.cplusplus) + break; + } else { + if (!copts.warn_extracomma) + break; + if (copts.c9x) + break; + if (copts.cpp_extensions) + break; + } + CError_Warning(CErrorStr107); + } else { + CError_Error(CErrorStr107); + } + break; + } + + oec = galloc(sizeof(ObjEnumConst)); + memclrw(oec, sizeof(ObjEnumConst)); + oec->otype = OT_ENUMCONST; + oec->access = access; + oec->name = tkidentifier; + CPrep_BrowserFilePosition(&fileinfo, &offset); + overflowed = 0; + if ((tk = lex()) == '=') { + tk = lex(); + if (tmclass) { + expr = CExpr_IntegralConstOrDepExpr(); + if (ENODE_IS(expr, EINTCONST)) { + val = expr->data.intval; + basetype = expr->rtype; + has_template_value = 0; + } else { + val = cint64_zero; + basetype = TYPE(tenum); + CTemplClass_RegisterEnumerator(tmclass, oec, expr); + has_template_value = 1; + } + } else { + val = CExpr_IntegralConstExprType(&basetype); + has_template_value = 0; + } + } else if (has_template_value) { + CTemplClass_RegisterEnumerator(tmclass, oec, NULL); + } else if (!is_first) { + if (is_unsigned(basetype)) { + val = CInt64_Add(val, cint64_one); + if (CInt64_IsZero(&val)) + overflowed = 1; + } else if (!CInt64_IsNegative(&val)) { + val = CInt64_Add(val, cint64_one); + if (CInt64_IsNegative(&val)) + overflowed = 1; + } else { + val = CInt64_Add(val, cint64_one); + } + } + + if (!has_template_value) { + if (copts.enumsalwaysint) { + if (!CInt64_IsInRange(val, stsignedint.size) && (copts.ANSIstrict || !CInt64_IsInURange(val, stunsignedint.size))) + overflowed = 1; + basetype = TYPE(&stsignedint); + } else if (CInt64_IsNegative(&val) && !is_unsigned(basetype)) { + if (CInt64_Less(val, minimum)) { + minimum = val; + if ((tmp = CDecl_FindUnderlyingType(tenum->size, &minimum, &maximum))) { + tenum->size = tmp->size; + tenum->enumtype = tmp; + } else { + overflowed = 1; + } + } + } else { + if (CInt64_GreaterU(val, maximum)) { + maximum = val; + if ((tmp = CDecl_FindUnderlyingType(tenum->size, &minimum, &maximum))) { + tenum->size = tmp->size; + tenum->enumtype = tmp; + } else { + overflowed = 1; + } + } + } + } + + if (overflowed) + CError_Error(CErrorStr154); + + oec->val = val; + oec->type = basetype; + CScope_AddObject(cscope_current, oec->name, OBJ_BASE(oec)); + + if (last) { + last->next = oec; + last = oec; + } else { + last = oec; + tenum->enumlist = oec; + } + + if (cparamblkptr->browseoptions.recordEnums) { + CPrepFileInfo *f = CPrep_BrowserCurrentFile(); + if (f->recordbrowseinfo) { + CBrowse_NewEnumConstant(cscope_current, oec->name, f, fileinfo, offset, CPrep_BrowserFileOffset()); + } + } + + is_first = 0; + } while (tk == ','); + + for (oec = tenum->enumlist; oec; oec = oec->next) + oec->type = TYPE(tenum); + + if (tk != '}') + CError_ErrorSkip(CErrorStr130); + else + tk = lex(); + + return tenum; +} + +void scanenum(DeclInfo *declinfo) { + HashNameNode *name; + Type *type; + NameResult pr; + + if (tk == '{') { + declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, NULL)); + TYPE_ENUM(declinfo->thetype)->enumname = CParser_AppendUniqueNameFile("@enum"); + return; + } + + if (tk == TK_IDENTIFIER) { + name = tkidentifier; + if (lookahead() == '{') { + type = CScope_GetLocalTagType(cscope_current, name); + if (type) { + lex(); + do_shit: + if (type->size || !IS_TYPE_ENUM(type)) { + CError_Error(CErrorStr122, name->name); + declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, NULL)); + return; + } + declinfo->thetype = TYPE(CDecl_ParseEnumList(TYPE_ENUM(type), NULL)); + } else { + lex(); + declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, name)); + } + + if (cparamblkptr->browseoptions.recordEnums && declinfo->file->recordbrowseinfo) + CBrowse_NewEnum( + cscope_current, + TYPE_ENUM(declinfo->thetype)->enumname, + declinfo->file, + declinfo->file2, + declinfo->sourceoffset, + CPrep_BrowserFileOffset()); + return; + } else { + CError_ASSERT(3851, !copts.cplusplus || tk != ';'); + tkidentifier = name; + } + } + + if (CScope_ParseElaborateName(&pr)) { + if ((type = pr.type)) { + if (!IS_TYPE_ENUM(type)) + CError_Error(CErrorStr121); + if ((tk = lex()) == '{') + goto do_shit; + declinfo->thetype = type; + return; + } else { + CError_ASSERT(3865, pr.name_4); + if ((tk = lex()) == '{') { + declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, pr.name_4)); + return; + } else { + CError_Error(CErrorStr140, pr.name_4->name); + } + } + } else { + CError_Error(CErrorStr121); + } + + declinfo->thetype = TYPE(&stsignedint); +} + +void CDecl_ScanStructDeclarator(BigDeclInfo *bde) { + ENode *expr; + short val; + short bits; + Boolean is_bitfield; + TypeTemplDep *ttempl; + TypeBitfield *tbitfield; + Type *type; + + bde->declinfo2 = bde->declinfo; + bde->declinfo2.name = NULL; + bde->declinfo2.operator_token = 0; + bde->xCD = 0; + is_bitfield = 0; + + if (tk == ':') { + bde->declinfo2.name = no_name_node; + is_bitfield = 1; + } else { + bde->declinfo2.x50 = 1; + scandeclarator(&bde->declinfo2); + if (!bde->declinfo2.name) { + CError_Error(CErrorStr131); + return; + } + + if ((!copts.ANSIstrict || copts.c9x) && !bde->declinfo2.thetype->size && IS_TYPE_ARRAY(bde->declinfo2.thetype)) { + if (bde->declinfo2.storageclass != TK_STATIC && bde->declinfo2.storageclass != TK_TYPEDEF) { + type = TYPE_POINTER(bde->declinfo2.thetype)->target; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (!IsCompleteType(type)) + return; + if (tk != ';' || lookahead() != '}') { + CError_Error(CErrorStr145); + return; + } + } + } else { + if (bde->declinfo2.storageclass != TK_STATIC && bde->declinfo2.storageclass != TK_TYPEDEF) { + if (!IS_TYPE_FUNC(bde->declinfo2.thetype) && !IsCompleteType(bde->declinfo2.thetype)) + return; + } + } + + if (IS_TYPE_CLASS(bde->declinfo2.thetype) && TYPE_CLASS(bde->declinfo2.thetype)->sominfo) { + CError_Error(CErrorStr287); + return; + } + + if (tk != ':') + goto not_a_bitfield; + } + + if (!IS_TYPE_INT_OR_ENUM(bde->declinfo2.thetype)) { + if (CTemplTool_IsTemplateArgumentDependentType(bde->declinfo2.thetype)) + goto fuckup; + CError_Error(CErrorStr138); + bde->declinfo2.thetype = TYPE(&stunsignedint); + } else if (copts.ANSIstrict && !copts.cplusplus) { + if (bde->declinfo2.thetype != TYPE(&stsignedint) && bde->declinfo2.thetype != TYPE(&stunsignedint)) { + CError_Error(CErrorStr138); + bde->declinfo2.thetype = TYPE(&stunsignedint); + } + } + + switch (bde->declinfo2.thetype->size) { + case 1: + bits = 8; + break; + case 2: + bits = 16; + break; + case 4: + bits = 32; + break; + default: + CError_Error(CErrorStr138); + return; + } +fuckup: + tk = lex(); + expr = CExpr_IntegralConstOrDepExpr(); + if (!ENODE_IS(expr, EINTCONST)) { + ttempl = TYPE_TEMPLATE(CDecl_NewTemplDepType(TEMPLDEP_BITFIELD)); + ttempl->u.bitfield.type = bde->declinfo2.thetype; + ttempl->u.bitfield.size = CInline_CopyExpression(expr, CopyMode1); + bde->declinfo2.thetype = TYPE(ttempl); + bde->xCD = 1; + return; + } + val = CInt64_GetULong(&expr->data.intval); + if (is_bitfield) { + if (val < 0 || val > bits) { + CError_Error(CErrorStr138); + return; + } + } else { + if (val <= 0 || val > bits) { + CError_Error(CErrorStr138); + return; + } + } + + tbitfield = galloc(sizeof(TypeBitfield)); + memclrw(tbitfield, sizeof(TypeBitfield)); + tbitfield->type = TYPEBITFIELD; + tbitfield->size = bde->declinfo2.thetype->size; + tbitfield->bitfieldtype = bde->declinfo2.thetype; + tbitfield->bitlength = val; + bde->declinfo2.thetype = TYPE(tbitfield); + + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(NULL, &bde->declinfo2); + +not_a_bitfield: + bde->xCD = 1; +} + +static void CDecl_LayoutStruct(TypeStruct *tstruct) { + StructMember *member; + SInt32 r28; + StructMember *innermember; + SInt32 innerbase; + StructMember *newmember; + StructMember **memberp; + TypeBitfield *bf; + SInt32 r24; + Boolean r23; + SInt32 tmp; + + r28 = 0; + r23 = 0; + CMach_StructLayoutInitOffset(0); + for (member = tstruct->members; member; member = member->next) { + if (tstruct->stype == STRUCT_TYPE_UNION) + CMach_StructLayoutInitOffset(0); + + if (IS_TYPE_BITFIELD(member->type)) + member->offset = CMach_StructLayoutBitfield(TYPE_BITFIELD(member->type), member->qual); + else + member->offset = CMach_StructLayoutGetOffset(member->type, member->qual); + + if (tstruct->stype == STRUCT_TYPE_UNION) { + tmp = CMach_StructLayoutGetCurSize(); + if (tmp > r28) + r28 = tmp; + } + + if (member->name == no_name_node) + r23 = 1; + + if (!member->name) { + CError_ASSERT(4064, IS_TYPE_STRUCT(member->type)); + innerbase = member->offset; + innermember = TYPE_STRUCT(member->type)->members; + r23 = 1; + while (innermember) { + if (ismember(tstruct, innermember->name)) + CError_Error(CErrorStr133, innermember->name->name); + if (r23) { + member->type = innermember->type; + member->name = innermember->name; + member->qual = innermember->qual; + member->offset = innerbase + innermember->offset; + } else { + newmember = galloc(sizeof(StructMember)); + memclrw(newmember, sizeof(StructMember)); + newmember->next = member->next; + newmember->type = innermember->type; + newmember->name = innermember->name; + newmember->qual = innermember->qual | Q_WEAK; + newmember->offset = innerbase + innermember->offset; + member->next = newmember; + member = newmember; + } + if (copts.reverse_bitfields && IS_TYPE_BITFIELD(member->type)) { + bf = galloc(sizeof(TypeBitfield)); + *bf = *TYPE_BITFIELD(member->type); + CABI_ReverseBitField(bf); + member->type = TYPE(bf); + } + r23 = 0; + innermember = innermember->next; + } + r23 = 1; + } + } + + if (r23) { + memberp = &tstruct->members; + while (*memberp) { + if ((*memberp)->name == no_name_node || !(*memberp)->name) + *memberp = (*memberp)->next; + else + memberp = &(*memberp)->next; + } + } + + if (tstruct->stype == STRUCT_TYPE_UNION) + r24 = r28; + else + r24 = CMach_StructLayoutGetCurSize(); + tstruct->size = r24; + tstruct->align = CMach_GetStructAlign(tstruct); + tstruct->size = r24 + CABI_StructSizeAlignValue(TYPE(tstruct), r24); + + if (copts.reverse_bitfields) { + for (member = tstruct->members; member; member = member->next) { + if (IS_TYPE_BITFIELD(member->type)) + CABI_ReverseBitField(TYPE_BITFIELD(member->type)); + } + } + + if (copts.warn_padding && tstruct->stype != STRUCT_TYPE_UNION) { + StructMember *prev; + + member = tstruct->members; + prev = NULL; + while (member) { + if (prev && (prev->offset + prev->type->size) < member->offset) { + CError_Warning(CErrorStr350, member->offset - (prev->offset + prev->type->size), prev->name->name); + } + prev = member; + member = member->next; + } + + if (prev && (prev->offset + prev->type->size) < tstruct->size) { + CError_Warning(CErrorStr350, tstruct->size - (prev->offset + prev->type->size), prev->name->name); + } + } +} + +static SInt32 scanstructdeclarationlist(TypeStruct *tstruct, Boolean flag) { + SInt32 offset; + StructMember *member; + BigDeclInfo bde; + + offset = -1; + memclrw(&bde, sizeof(BigDeclInfo)); + + if (tk == TK_AT_DEFS) { + CPrep_NewFileOffsetInfo(&member_fileoffset, NULL); + CObjC_ParseDefs(tstruct); + if ((tk = lex()) != '}') + CError_Error(CErrorStr130); + } else { + do { + CPrep_NewFileOffsetInfo(&member_fileoffset, NULL); + memclrw(&bde.declinfo, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&bde.declinfo, 0); + if (bde.declinfo.storageclass || bde.declinfo.x44) { + CError_Error(CErrorStr131); + tstruct->members = NULL; + return -1; + } + + if (tk != ';') { + while (1) { + CDecl_ScanStructDeclarator(&bde); + if (!CanCreateObject(bde.declinfo2.thetype)) { + CError_Error(CErrorStr131); + bde.xCD = 0; + } + + if (bde.declinfo2.operator_token) { + CError_Error(CErrorStr131); + bde.xCD = 0; + } + + if (bde.xCD) { + if (bde.declinfo2.name == no_name_node || !ismember(tstruct, bde.declinfo2.name)) { + member = galloc(sizeof(StructMember)); + memclrw(member, sizeof(StructMember)); + member->type = bde.declinfo2.thetype; + member->name = bde.declinfo2.name; + member->qual = bde.declinfo2.qual; + appendmember(tstruct, member); + + if (flag) { + CBrowse_AddStructMember(member, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset()); + } + } else { + CError_Error(CErrorStr133, bde.declinfo2.name->name); + } + } + + if (tk != ',') + break; + tk = lex(); + } + } else if (!copts.ANSIstrict && IS_TYPE_STRUCT(bde.declinfo.thetype)) { + member = galloc(sizeof(StructMember)); + memclrw(member, sizeof(StructMember)); + member->type = bde.declinfo.thetype; + appendmember(tstruct, member); + } else { + CError_Error(CErrorStr131); + } + + if (tk != ';') { + tstruct->members = NULL; + CError_Error(CErrorStr123); + return -1; + } + + CPrep_TokenStreamFlush(); + } while ((tk = lex()) != '}'); + CDecl_LayoutStruct(tstruct); + } + + if (flag) { + offset = CPrep_BrowserFileOffset(); + if (tk == ';') + offset++; + } + + tk = lex(); + return offset; +} + +static TypeStruct *CDecl_DefineStruct(HashNameNode *name, short stype) { + TypeStruct *tstruct; + + tstruct = galloc(sizeof(TypeStruct)); + memclrw(tstruct, sizeof(TypeStruct)); + + tstruct->type = TYPESTRUCT; + tstruct->align = 1; + tstruct->stype = stype; + if (name) { + tstruct->name = name; + CScope_DefineTypeTag((in_func_arglist && !copts.cplusplus) ? cscope_root : cscope_current, name, (Type *) tstruct); + } + + return tstruct; +} + +void scanstruct(DeclInfo *declinfo, short structtype) { + Type *type; + HashNameNode *name; + TypeStruct typecopy; + Boolean add_to_browse; + GList gl; + SInt32 offset; + + if (copts.cplusplus) { + CDecl_ParseClass(declinfo, structtype, 1, 0); + return; + } + + if (tk == TK_IDENTIFIER) { + name = tkidentifier; + type = CScope_GetTagType(cscope_current, name); + if (type) { + if (IS_TYPE_CLASS(type)) { + CDecl_ParseClass(declinfo, structtype, 1, 0); + return; + } + + tk = lex(); + if (!CScope_GetLocalTagType(cscope_current, name) && (tk == ';' || tk == '{')) + type = (Type *) CDecl_DefineStruct(name, structtype); + + if (!IS_TYPE_STRUCT(type) || TYPE_STRUCT(type)->stype != structtype) { + CError_Error(CErrorStr132, name->name); + declinfo->thetype = type; + return; + } + + if (tk != '{') { + declinfo->thetype = type; + return; + } + + if (type->size) { + CError_Error(CErrorStr132, name->name); + type = (Type *) CDecl_DefineStruct(NULL, structtype); + } + } else { + type = (Type *) CDecl_DefineStruct(name, structtype); + if ((tk = lex()) != '{') { + declinfo->thetype = type; + return; + } + } + } else if (tk != '{') { + CError_Error(CErrorStr131); + declinfo->thetype = (Type *) &stsignedint; + return; + } else { + type = (Type *) CDecl_DefineStruct(NULL, structtype); + } + + if ((add_to_browse = cparamblkptr->browseoptions.recordClasses && declinfo->file->recordbrowseinfo)) + CBrowse_BeginStruct(declinfo, TYPE_STRUCT(type), &gl); + + typecopy = *TYPE_STRUCT(type); + tk = lex(); + offset = scanstructdeclarationlist(&typecopy, add_to_browse); + *TYPE_STRUCT(type) = typecopy; + declinfo->thetype = type; + + if (add_to_browse) + CBrowse_EndStruct(offset, &gl); +} + +static void InlineFunctionObject(Object *obj, TypeClass *tclass) { + TokenStream stream; + CPrepFileInfo *file; + + obj->qual |= Q_INLINE; + TYPE_FUNC(obj->type)->flags |= FUNC_DEFINED; + + CPrep_StreamGetBlock(&stream, NULL, 1); + if (stream.tokens) { + if (IS_TYPEFUNC_METHOD(TYPE_FUNC(obj->type)) && (TYPE_METHOD(obj->type)->theclass->flags & CLASS_IS_TEMPL)) { + TYPE_FUNC(obj->type)->flags |= FUNC_IS_TEMPL_INSTANCE; + CTemplClass_DefineMember(TEMPL_CLASS(TYPE_METHOD(obj->type)->theclass), obj, &member_fileoffset, &stream); + } else { + CInline_AddInlineFunctionAction(obj, tclass, &member_fileoffset, &stream, 0); + } + } + + file = CPrep_BrowserCurrentFile(); + if (file->recordbrowseinfo) { + CBrowse_NewFunction( + obj, file, + member_fileoffset.file, + CPrep_BrowserTokenOffset(&member_fileoffset) + 1, + CPrep_BrowserFileOffset()); + } + + if (lookahead() == ';') + tk = lex(); + else + tk = ';'; +} + +void CDecl_ExtractClassExportFlags(DeclInfo *declinfo, UInt8 flags) { + if (flags & CLASS_EFLAGS_INTERNAL) + declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_INTERNAL; + if (flags & CLASS_EFLAGS_IMPORT) + declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_IMPORT; + if (flags & CLASS_EFLAGS_EXPORT) + declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_EXPORT; +} + +TypeMemberFunc *CDecl_MakeTypeMemberFunc(TypeFunc *tfunc, TypeClass *tclass, Boolean flag) { + TypeMemberFunc *method; + + method = galloc(sizeof(TypeMemberFunc)); + memclrw(method, sizeof(TypeMemberFunc)); + *TYPE_FUNC(method) = *tfunc; + method->theclass = tclass; + method->is_static = flag; + method->flags |= FUNC_METHOD; + if (!flag) + CDecl_AddThisPointerArgument(TYPE_FUNC(method), tclass); + + if ((flag || (tfunc->flags & (FUNC_IS_CTOR | FUNC_IS_DTOR))) && (tfunc->flags & (FUNC_CONST | FUNC_VOLATILE))) + CError_Error(CErrorStr384); + + return method; +} + +static void CDecl_MakeFunctionVirtual(TypeClass *tclass, Object *func) { + if (is_pascal_object(func)) + CError_Error(CErrorStr219); + if (tclass->mode == CLASS_MODE_UNION) + CError_Error(CErrorStr352, func); + func->datatype = DVFUNC; +} + +static void CDecl_AddFunctionMember(ClassLayout *decle, TypeClass *tclass, DeclInfo *declinfo, AccessType access, Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4) { + NameSpaceObjectList *list; // r20 + Object *obj; // also r20 + TypeMemberFunc *tfunc; // r19 + Boolean r31; + Boolean outflag; + + if (IS_TYPE_ARRAY(TYPE_FUNC(declinfo->thetype)->functype) || IS_TYPE_FUNC(TYPE_FUNC(declinfo->thetype)->functype)) { + CError_Error(CErrorStr128); + TYPE_FUNC(declinfo->thetype)->functype = (Type *) &stsignedint; + } + + if (tclass->sominfo) + CSOM_CheckFuncType(TYPE_FUNC(declinfo->thetype)); + + r31 = 0; + if (declinfo->qual & Q_VIRTUAL) { + declinfo->qual &= ~Q_VIRTUAL; + r31 = 1; + flag1 = 1; + } + + if ((list = CScope_FindName(tclass->nspace, declinfo->name))) { + if (list->object->otype != OT_TYPETAG) { + if (list->object->otype != OT_OBJECT || !IS_TYPE_FUNC(OBJECT(list->object)->type)) + CError_Error(CErrorStr133, declinfo->name->name); + } else { + list = NULL; + } + } + + if (!IS_TYPEFUNC_METHOD(TYPE_FUNC(declinfo->thetype))) { + tfunc = CDecl_MakeTypeMemberFunc(TYPE_FUNC(declinfo->thetype), tclass, flag4); + declinfo->thetype = (Type *) tfunc; + } else { + tfunc = TYPE_METHOD(declinfo->thetype); + CError_ASSERT(4579, !tclass->sominfo); + } + + CDecl_ExtractClassExportFlags(declinfo, tclass->eflags); + + CError_ASSERT(4597, cscope_current == tclass->nspace); + + if (list) { + obj = CDecl_OverloadFunctionObject(list, declinfo, &outflag, flag4 ? OverloadMode1 : OverloadMode2, 0); + if (!obj) + return; + if (outflag) + tfunc->vtbl_index = ++decle->lex_order_count; + else + CError_Error(CErrorStr133, CError_GetObjectName(obj)); + } else { + tfunc->vtbl_index = ++decle->lex_order_count; + obj = CParser_NewFunctionObject(declinfo); + if ((tclass->flags & CLASS_IS_TEMPL) && CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) + CTemplClass_RegisterObjectDef(TEMPL_CLASS(tclass), OBJ_BASE(obj)); + CScope_AddObject(tclass->nspace, declinfo->name, OBJ_BASE(obj)); + } + + obj->access = access; + CheckDefaultArgs(TYPE_FUNC(obj->type)->args); + + if (flag2) { + tfunc->flags |= FUNC_CONVERSION; + tclass->flags = tclass->flags | CLASS_IS_CONVERTIBLE; + } + + if (r31) { + CDecl_MakeFunctionVirtual(tclass, obj); + decle->has_vtable = 1; + } + + if ((flag1 || r31) && flag3 && (tk == '=')) { + if ((tk = lex()) == TK_INTCONST) { + if (!CInt64_IsZero(&tkintconst)) + CError_Error(CErrorStr121); + tfunc->flags |= FUNC_PURE; + tclass->flags = tclass->flags | CLASS_ABSTRACT; + tk = lex(); + } else { + CError_Error(CErrorStr121); + } + } + + if (flag3 && ((tk == '{') || (tk == TK_TRY) || ((tk == ':') && CClass_IsConstructor(obj)))) { + if (declinfo->x49) + CError_Error(CErrorStr127); + InlineFunctionObject(obj, NULL); + } + + if (cparamblkptr->browseoptions.recordClasses) + CBrowse_AddClassMemberFunction(obj, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset()); +} + +static Boolean CDecl_IsAccessDeclaration(TypeClass *tclass, AccessType access) { + SInt32 state; + Boolean flag; + + CPrep_TokenStreamGetState(&state); + flag = 0; + +restart: + switch (tk) { + case TK_IDENTIFIER: + if ((tk = lex()) != ';') + break; + case TK_OPERATOR: + CPrep_TokenStreamSetCurState(&state); + if (flag) { + CScope_ParseUsingDeclaration(tclass->nspace, access, 1); + return 1; + } + return 0; + default: + CPrep_TokenStreamSetCurState(&state); + return 0; + } + + switch (tk) { + case TK_COLON_COLON: + flag = 1; + tk = lex(); + goto restart; + case '<': + tk = lex(); + while (1) { + switch (tk) { + case 0: + case ';': + case '{': + case '}': + CPrep_TokenStreamSetCurState(&state); + return 0; + case '>': + if ((tk = lex()) == TK_COLON_COLON) { + flag = 1; + tk = lex(); + goto restart; + } + default: + tk = lex(); + } + } + } + + CPrep_TokenStreamSetCurState(&state); + return 0; +} + +void CDecl_PackDeclInfo(PackedDeclInfo *packed, DeclInfo *declinfo) { + packed->thetype = declinfo->thetype; + packed->qual = declinfo->qual; + packed->nspace = declinfo->nspace; + packed->name = declinfo->name; + packed->expltargs = CTemplTool_MakeGlobalTemplArgCopy(declinfo->expltargs); + packed->storageclass = declinfo->storageclass; + packed->section = declinfo->section; + packed->exportflags = declinfo->exportflags; + packed->has_expltargs = declinfo->has_expltargs; +} + +void CDecl_UnpackDeclInfo(DeclInfo *declinfo, PackedDeclInfo *packed) { + memclrw(declinfo, sizeof(DeclInfo)); + declinfo->thetype = packed->thetype; + declinfo->qual = packed->qual; + declinfo->nspace = packed->nspace; + declinfo->name = packed->name; + declinfo->expltargs = packed->expltargs; + declinfo->storageclass = packed->storageclass; + declinfo->section = packed->section; + declinfo->exportflags = packed->exportflags; + declinfo->has_expltargs = packed->has_expltargs; +} + +void CDecl_AddFriend(TypeClass *tclass, Object *friendfunc, TypeClass *friendclass) { + ClassFriend *scan; + ClassFriend *newfriend; + + if (friendfunc) { + for (scan = tclass->friends; scan; scan = scan->next) { + if (!scan->isclass && scan->u.obj == friendfunc) + break; + } + if (!scan) { + newfriend = galloc(sizeof(ClassFriend)); + memclrw(newfriend, sizeof(ClassFriend)); + newfriend->next = tclass->friends; + tclass->friends = newfriend; + newfriend->u.obj = friendfunc; + newfriend->isclass = 0; + } + } + + if (friendclass) { + for (scan = tclass->friends; scan; scan = scan->next) { + if (scan->isclass && scan->u.theclass == friendclass) + break; + } + if (!scan) { + newfriend = galloc(sizeof(ClassFriend)); + memclrw(newfriend, sizeof(ClassFriend)); + newfriend->next = tclass->friends; + tclass->friends = newfriend; + newfriend->u.theclass = friendclass; + newfriend->isclass = 1; + } + } +} + +static void CDecl_ParseFriendDecl(TypeClass *tclass) { + DeclInfo declinfo; + DeclInfo declinfo_copy; + Boolean is_templ; + Boolean r27; + Boolean pflag; + CScopeSave save; + Object *obj; + NameSpace *nspace; + + is_templ = (tclass->flags & CLASS_IS_TEMPL) != 0; + r27 = (tk == TK_CLASS || tk == TK_STRUCT || tk == TK_UNION); + memclrw(&declinfo, sizeof(DeclInfo)); + + declinfo.in_friend_decl = 1; + CParser_GetDeclSpecs(&declinfo, 1); + if (declinfo.storageclass) { + CError_Error(CErrorStr177); + declinfo.storageclass = 0; + } + declinfo.in_friend_decl = 0; + + if (tk == ';') { + if (!r27) + CError_Error(CErrorStr201); + + if (IS_TYPE_CLASS(declinfo.thetype)) { + if (!(TYPE_CLASS(declinfo.thetype)->flags & CLASS_IS_TEMPL) || CParser_CheckTemplateClassUsage(TEMPL_CLASS(declinfo.thetype), 1)) { + if (!is_templ) + CDecl_AddFriend(tclass, NULL, TYPE_CLASS(declinfo.thetype)); + else + CTemplClass_RegisterFriend(TEMPL_CLASS(tclass), &declinfo); + } + } else { + if (IS_TYPE_TEMPLATE(declinfo.thetype) && is_templ) + CTemplClass_RegisterFriend(TEMPL_CLASS(tclass), &declinfo); + else + CError_Error(CErrorStr201); + } + } else { + if (declinfo.x14 || declinfo.x10) { + CDecl_ParseSpecialMember(&declinfo, 0); + if (declinfo.name) { + obj = CDecl_GetFunctionObject(&declinfo, NULL, &pflag, 0); + if (obj) + CDecl_AddFriend(tclass, obj, NULL); + if (tk != ';') + CError_Error(CErrorStr123); + else + tk = lex(); + } + return; + } else { + nspace = CScope_FindGlobalNS(cscope_current); + declinfo_copy = declinfo; + while (1) { + declinfo = declinfo_copy; + declinfo.x4D = 1; + declinfo.x51 = 1; + scandeclarator(&declinfo); + + if (IS_TYPE_FUNC(declinfo.thetype)) { + if (!is_templ) { + CScope_SetNameSpaceScope(nspace, &save); + obj = CDecl_GetFunctionObject(&declinfo, NULL, &pflag, 0); + CScope_RestoreScope(&save); + + if (obj) { + CDecl_AddFriend(tclass, obj, NULL); + if (!declinfo.nspace && tk == '{') { + InlineFunctionObject(obj, tclass); + } else { + if (!obj->sclass) + obj->sclass = TK_EXTERN; + } + } + } else { + CTemplClass_RegisterFriend(TEMPL_CLASS(tclass), &declinfo); + } + } else { + CError_Error(CErrorStr201); + } + + if (tk != ',') + break; + tk = lex(); + } + } + } + + if (tk == ';') + tk = lex(); + else + CError_Error(CErrorStr123); +} + +static ObjMemberVar *CDecl_InstanceDataDeclarator(ClassLayout *decle, TypeClass *tclass, Type *type, UInt32 qual, HashNameNode *name, AccessType access) { + NameSpaceObjectList *list; + ObjMemberVar *ivar; + ObjMemberVar *scan; + + if (name && (list = CScope_FindName(tclass->nspace, name))) { + switch (list->object->otype) { + case OT_NAMESPACE: + CError_Error(CErrorStr321); + return NULL; + case OT_ENUMCONST: + case OT_TYPE: + case OT_OBJECT: + CError_Error(CErrorStr322); + return NULL; + case OT_MEMBERVAR: + CError_Error(CErrorStr122, name->name); + return NULL; + case OT_TYPETAG: + break; + default: + CError_FATAL(4989); + } + } + + ivar = galloc(sizeof(ObjMemberVar)); + memclrw(ivar, sizeof(ObjMemberVar)); + ivar->otype = OT_MEMBERVAR; + ivar->access = access; + ivar->name = name; + ivar->type = type; + ivar->qual = qual; + if (!tclass->sominfo) + decle->lex_order_count++; + + if ((scan = tclass->ivars)) { + while (scan->next) + scan = scan->next; + scan->next = ivar; + } else { + tclass->ivars = ivar; + } + + if (name && name != no_name_node) { + CScope_AddObject(tclass->nspace, name, OBJ_BASE(ivar)); + if ((tclass->flags & CLASS_IS_TEMPL) && CTemplTool_IsTemplateArgumentDependentType(type)) + CTemplClass_RegisterObjectDef(TEMPL_CLASS(tclass), OBJ_BASE(ivar)); + if (cparamblkptr->browseoptions.recordClasses) + CBrowse_AddClassMemberVar(ivar, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset()); + } + + return ivar; +} + +void CDecl_CheckCtorIntegrity(FuncArg *args, TypeClass *tclass) { + if (args && args->type == TYPE(tclass)) { + if (!args->next || args->next->dexpr) { + CError_Error(CErrorStr239); + args->type = &stvoid; + } + } +} + +static void CDecl_ParseClassMembers(ClassLayout *decle, TypeClass *tclass, short mode) { + AccessType access; + Boolean r17; + BigDeclInfo bde; + DeclInfo declinfo; + //Type *newtype + ObjMemberVar *ivar; + ObjMemberVar *scanivar; + Type *tmptype; + UInt32 r22; + UInt32 r21; + UInt8 r20; + UInt8 r18; + Boolean r19; + short t; + + r17 = (tclass->flags & CLASS_IS_TEMPL) && TEMPL_CLASS(tclass)->pspec_owner; + memclrw(&bde, sizeof(BigDeclInfo)); + + access = (mode == CLASS_MODE_CLASS) ? ACCESSPRIVATE : ACCESSPUBLIC; + global_access = access; + + restart: + while (tk != '}') { + CPrep_NewFileOffsetInfo(&member_fileoffset, NULL); + r21 = 0; + r22 = 0; + r20 = 0; + r18 = 0; + + if (tk == TK_TEMPLATE) { + NameSpace *nspace = cscope_current; + TemplClass *tmclass; + + if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL)) { + tmclass = TEMPL_CLASS(nspace->theclass); + } else { + for (; nspace; nspace = nspace->parent) { + if (!nspace->name && !nspace->theclass && nspace->parent && !nspace->is_templ) { + CError_Error(CErrorStr347); + break; + } + } + } + + CTempl_Parse(TEMPL_CLASS(tclass), access); + tk = lex(); + continue; + } + + restart2: + r19 = 0; + switch (tk) { + case TK_UU_DECLSPEC: + if ((tk = lex()) != '(') + CError_Error(CErrorStr114); + memclrw(&declinfo, sizeof(DeclInfo)); + CParser_ParseDeclSpec(&declinfo, 1); + r21 |= declinfo.qual; + r20 |= declinfo.exportflags; + r18 = declinfo.section; + if ((tk = lex()) != ')') + CError_Error(CErrorStr115); + tk = lex(); + goto restart2; + case TK_PRIVATE: + global_access = access = ACCESSPRIVATE; + goto check_access; + case TK_PROTECTED: + global_access = access = ACCESSPROTECTED; + goto check_access; + case TK_PUBLIC: + global_access = access = ACCESSPUBLIC; + check_access: + if (r22 || r20) + CError_Error(CErrorStr121); + if ((tk = lex()) != ':') + CError_Error(CErrorStr170); + else + tk = lex(); + goto restart; + case TK_EXPLICIT: + CError_QualifierCheck(r22 & Q_EXPLICIT); + r22 |= Q_EXPLICIT; + tk = lex(); + goto restart2; + case TK_INLINE: + CError_QualifierCheck(r22 & Q_INLINE); + r22 |= Q_INLINE; + tk = lex(); + goto restart2; + case TK_ASM: + CError_QualifierCheck(r22 & Q_ASM); + r22 |= Q_ASM; + tk = lex(); + goto restart2; + case TK_VIRTUAL: + CError_QualifierCheck(r22 & Q_VIRTUAL); + r22 |= Q_VIRTUAL; + tk = lex(); + goto restart2; + case TK_IDENTIFIER: + while (1) { + if (tkidentifier == tclass->classname) { + t = lookahead(); + tkidentifier = tclass->classname; + r19 = 1; + if (copts.cpp_extensions && t == TK_COLON_COLON) { + lex(); + tk = lex(); + if (tk == TK_IDENTIFIER) + continue; + if (tk == '~') + goto restart2; + CError_Error(CErrorStr107); + } + + if (t == '(') { + redo_thing: + CError_QualifierCheck(r22 & ~(Q_EXPLICIT | Q_INLINE | Q_ASM)); + memclrw(&bde.declinfo2, sizeof(DeclInfo)); + if (tclass->sominfo) + bde.declinfo2.thetype = &stvoid; + else + bde.declinfo2.thetype = TYPE(&void_ptr); + + bde.declinfo2.qual = r22; + bde.declinfo2.exportflags = r20; + bde.declinfo2.section = r18; + bde.declinfo2.x4B = 1; + scandeclarator(&bde.declinfo2); + if (IS_TYPE_FUNC(bde.declinfo2.thetype)) { + if (r17) + bde.declinfo2.thetype = CTemplTool_ResolveMemberSelfRefs(TEMPL_CLASS(tclass), bde.declinfo2.thetype, &bde.declinfo2.qual); + if (tclass->sominfo) { + if (TYPE_FUNC(bde.declinfo2.thetype)->args) + CError_Error(CErrorStr272); + bde.declinfo2.qual |= Q_VIRTUAL; + } else { + CDecl_CheckCtorIntegrity(TYPE_FUNC(bde.declinfo2.thetype)->args, tclass); + if (tclass->flags & CLASS_HAS_VBASES) + CDecl_AddArgument(TYPE_FUNC(bde.declinfo2.thetype), TYPE(&stsignedshort)); + bde.declinfo2.qual &= ~Q_VIRTUAL; + } + TYPE_FUNC(bde.declinfo2.thetype)->flags |= FUNC_IS_CTOR; + bde.declinfo2.name = constructor_name_node; + bde.declinfo2.qual |= r21; + CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 0, 0, 1, 0); + } else { + CError_Error(CErrorStr241); + } + if (tk == ';') + tk = lex(); + else + CError_Error(CErrorStr123); + goto restart; + } + } + // 6F8D8 + if (!r22 && CDecl_IsAccessDeclaration(tclass, access)) { + tk = lex(); + goto restart; + } + break; + } + break; + case TK_USING: + CError_QualifierCheck(r22); + tk = lex(); + CScope_ParseUsingDeclaration(tclass->nspace, access, 0); + tk = lex(); + goto restart; + case '~': + if ((tk = lex()) != TK_IDENTIFIER || tkidentifier != tclass->classname) { + CError_Error(CErrorStr241); + goto restart; + } + CError_QualifierCheck(r22 & ~(Q_VIRTUAL | Q_INLINE | Q_ASM)); + if (tclass->flags & CLASS_IS_TEMPL_ANY) { + t = lookahead(); + tkidentifier = tclass->classname; + if (t == '<') { + memclrw(&bde.declinfo, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&bde.declinfo, 0); + if (tk != '(' || bde.declinfo.thetype != TYPE(tclass) || bde.declinfo.nspace) { + CError_Error(CErrorStr241); + goto restart; + } + CPrep_UnLex(); + tk = TK_IDENTIFIER; + tkidentifier = tclass->classname; + } + } + memclrw(&bde.declinfo2, sizeof(DeclInfo)); + bde.declinfo2.qual = r22; + bde.declinfo2.exportflags = r20; + bde.declinfo2.section = r18; + if (tclass->sominfo) + bde.declinfo2.thetype = &stvoid; + else + bde.declinfo2.thetype = TYPE(&void_ptr); + scandeclarator(&bde.declinfo2); + if (IS_TYPE_FUNC(bde.declinfo2.thetype) && !TYPE_FUNC(bde.declinfo2.thetype)->args) { + if (!CScope_FindName(tclass->nspace, destructor_name_node)) { + if (tclass->sominfo) + bde.declinfo2.qual |= Q_VIRTUAL; + else + CDecl_AddArgument(TYPE_FUNC(bde.declinfo2.thetype), TYPE(&stsignedshort)); + bde.declinfo2.name = destructor_name_node; + TYPE_FUNC(bde.declinfo2.thetype)->flags |= FUNC_IS_DTOR; + bde.declinfo2.qual |= r21; + CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 1, 0, 1, 0); + } else { + CError_Error(CErrorStr133, CError_GetFunctionName(tclass->nspace, destructor_name_node, NULL)); + } + } else { + CError_Error(CErrorStr146); + } + if (tk == ';') + tk = lex(); + else + CError_Error(CErrorStr123); + goto restart; + case TK_OPERATOR: + if (CMangler_OperatorName(lookahead())) { + memclrw(&bde.declinfo, sizeof(DeclInfo)); + bde.declinfo.thetype = TYPE(&stsignedint); + goto after_various_things; + } else { + tk = lex(); + CError_QualifierCheck(r22 & ~(Q_VIRTUAL | Q_INLINE | Q_ASM)); + memclrw(&bde.declinfo2, sizeof(DeclInfo)); + bde.declinfo2.qual = r22; + bde.declinfo2.exportflags = r20; + bde.declinfo2.section = r18; + conversion_type_name(&bde.declinfo2); + bde.declinfo2.qual |= r21; + tmptype = bde.declinfo2.thetype; + CDecl_NewConvFuncType(&bde.declinfo2); + if ((tclass->flags & CLASS_IS_TEMPL) && CTemplTool_IsTemplateArgumentDependentType(tmptype)) + bde.declinfo2.name = CParser_GetUniqueName(); + CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 1, 1, 1, 0); + if (tk == ';') + tk = lex(); + else + CError_Error(CErrorStr123); + goto restart; + } + case TK_FRIEND: + tk = lex(); + CDecl_ParseFriendDecl(tclass); + goto restart; + } + + CError_QualifierCheck(r22 & Q_EXPLICIT); + global_access = access; + memclrw(&bde.declinfo, sizeof(DeclInfo)); + bde.declinfo.qual = r22; + bde.declinfo.exportflags = r20; + bde.declinfo.section = r18; + CParser_GetDeclSpecs(&bde.declinfo, 0); + + if (r19 && tk == '(' && (tclass->flags & CLASS_IS_TEMPL_ANY) && bde.declinfo.thetype == TYPE(tclass) && !bde.declinfo.nspace) { + CPrep_UnLex(); + tk = TK_IDENTIFIER; + tkidentifier = tclass->classname; + r22 = bde.declinfo.qual; + goto redo_thing; + } + + after_various_things: + switch (bde.declinfo.storageclass) { + case 0: + case TK_STATIC: + case TK_TYPEDEF: + case TK_MUTABLE: + break; + default: + CError_Error(CErrorStr177); + bde.declinfo.storageclass = 0; + } + + if (tk != ';') { + while (1) { + CDecl_ScanStructDeclarator(&bde); + if (r17) + bde.declinfo2.thetype = CTemplTool_ResolveMemberSelfRefs(TEMPL_CLASS(tclass), bde.declinfo2.thetype, &bde.declinfo2.qual); + if (bde.declinfo2.nspace) + CError_Error(CErrorStr200); + if (bde.declinfo2.operator_token) { + if (bde.declinfo.storageclass == TK_MUTABLE) + CError_QualifierCheck(Q_MUTABLE); + r19 = 0; + switch (bde.declinfo2.operator_token) { + case TK_NEW: + case TK_NEW_ARRAY: + CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL); + r19 = 1; + break; + case TK_DELETE: + case TK_DELETE_ARRAY: + CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL); + r19 = 1; + break; + default: + if (bde.declinfo2.storageclass == TK_STATIC) + CError_Error(CErrorStr193); + if (tclass->sominfo) + CError_Error(CErrorStr193); + } + + bde.declinfo2.storageclass = 0; + if (IS_TYPE_FUNC(bde.declinfo2.thetype)) { + bde.declinfo2.qual |= r21; + CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, r19 == 0, 0, 1, r19); + CDecl_CheckOperatorType(&bde.declinfo2, 1); + if (tclass->sominfo) + CSOM_FixNewDeleteFunctype(TYPE_FUNC(bde.declinfo2.thetype)); + } else { + CError_Error(CErrorStr121); + } + } else if (bde.xCD) { + if (bde.declinfo2.name == constructor_name_node || bde.declinfo2.name == destructor_name_node) + CError_Error(CErrorStr241); + switch (bde.declinfo2.storageclass) { + case TK_TYPEDEF: + CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL); + CDecl_TypedefDeclarator(&bde.declinfo2); + break; + case TK_STATIC: + CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL); + if (tclass->sominfo) + CError_Error(CErrorStr271); + if (IS_TYPE_FUNC(bde.declinfo2.thetype)) { + bde.declinfo2.qual |= r21; + bde.declinfo2.storageclass = 0; + if (bde.declinfo2.name == tclass->classname) + CError_Error(CErrorStr241); + CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 0, 0, 1, 1); + } else { + CDecl_ExtractClassExportFlags(&bde.declinfo2, tclass->eflags); + bde.declinfo2.storageclass = 0; + CDecl_DataDeclarator(&bde.declinfo2, access, 1); + } + break; + case 0: + case TK_MUTABLE: + if (IS_TYPE_FUNC(bde.declinfo2.thetype)) { + if (bde.declinfo2.name == tclass->classname) + CError_Error(CErrorStr241); + if (bde.declinfo.storageclass == TK_MUTABLE) + CError_QualifierCheck(Q_MUTABLE); + bde.declinfo2.qual |= r21; + CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 1, 0, 1, 0); + } else { + CDecl_CompleteType(bde.declinfo2.thetype); + CanCreateObject(bde.declinfo2.thetype); + CError_QualifierCheck(bde.declinfo2.qual & (Q_VIRTUAL | Q_INLINE)); + if (bde.declinfo2.storageclass == TK_MUTABLE) + bde.declinfo2.qual |= Q_MUTABLE; + CDecl_InstanceDataDeclarator(decle, tclass, bde.declinfo2.thetype, bde.declinfo2.qual, bde.declinfo2.name, access); + } + break; + default: + CError_Error(CErrorStr177); + } + } + + // this should be 70058 + if (tk != ',') + break; // goes to 70148 + tk = lex(); + } + } else if (CParser_IsAnonymousUnion(&bde.declinfo, 1)) { + if ((ivar = CDecl_InstanceDataDeclarator(decle, tclass, bde.declinfo.thetype, 0, NULL, access))) + ivar->anonunion = 1; + for (scanivar = TYPE_CLASS(bde.declinfo.thetype)->ivars; scanivar; scanivar = scanivar->next) { + tmptype = scanivar->type; + if (IS_TYPE_BITFIELD(tmptype) && copts.reverse_bitfields) { + TypeBitfield *newtype = galloc(sizeof(TypeBitfield)); + *newtype = *TYPE_BITFIELD(tmptype); + CABI_ReverseBitField(newtype); + tmptype = TYPE(newtype); + } + if ((ivar = CDecl_InstanceDataDeclarator(decle, tclass, tmptype, scanivar->qual, scanivar->name, access))) + ivar->offset = scanivar->offset | 0x80000000; + } + } + + // this should be 70148 i think + if (tk != ';') { + CError_Error(CErrorStr123); + return; + } + CPrep_TokenStreamFlush(); + tk = lex(); + } +} + +static VClassList *AddVBaseToList(TypeClass *tclass, TypeClass *baseclass) { + VClassList *scan; + VClassList *vbase; + + for (scan = tclass->vbases; scan; scan = scan->next) { + if (scan->base == baseclass) + return NULL; + } + + vbase = galloc(sizeof(VClassList)); + memclrw(vbase, sizeof(VClassList)); + vbase->base = baseclass; + + if ((scan = tclass->vbases)) { + while (scan->next) + scan = scan->next; + scan->next = vbase; + } else { + tclass->vbases = vbase; + } + + return vbase; +} + +void CDecl_MakeVBaseList(TypeClass *tclass) { + ClassList *base; + VClassList *vbase; + VClassList *new_vbase; + SInt32 offset; + + if (copts.vbase_ctor_offset) + tclass->flags = tclass->flags | CLASS_FLAGS_8000; + + for (base = tclass->bases, offset = tclass->size; base; base = base->next) { + for (vbase = base->base->vbases; vbase; vbase = vbase->next) { + if ((new_vbase = AddVBaseToList(tclass, vbase->base))) { + new_vbase->offset = offset + CMach_MemberAlignValue(TYPE(vbase->base), offset); + offset = new_vbase->offset + vbase->base->size; + } + } + + if (base->is_virtual && (new_vbase = AddVBaseToList(tclass, base->base))) { + new_vbase->offset = offset + CMach_MemberAlignValue(TYPE(base->base), offset); + offset = new_vbase->offset + base->base->size; + } + } +} + +Boolean CDecl_CheckNewBase(TypeClass *tclass, TypeClass *baseclass, Boolean is_virtual) { + ClassList *scan; + + if (tclass == baseclass) { + CError_Error(CErrorStr131); + return 0; + } + + if (!(baseclass->flags & CLASS_COMPLETED)) { + CError_Error(CErrorStr136, baseclass, 0); + return 0; + } + + if (baseclass->flags & CLASS_SINGLE_OBJECT) { + if (is_virtual || tclass->bases) { + CError_Error(CErrorStr191); + return 0; + } + tclass->flags = tclass->flags | CLASS_SINGLE_OBJECT; + } + + if (baseclass->flags & CLASS_HANDLEOBJECT) { + if (is_virtual || tclass->bases) { + CError_Error(CErrorStr191); + return 0; + } + tclass->flags = tclass->flags | CLASS_HANDLEOBJECT; + } + + if (baseclass->sominfo) { + if (!is_virtual) + CError_Error(CErrorStr268); + CSOM_MakeSOMClass(tclass); + } else if (tclass->sominfo) { + CError_Error(CErrorStr267); + } + + if (tclass->bases && (tclass->flags & CLASS_SINGLE_OBJECT) && (tclass->flags & CLASS_SINGLE_OBJECT)) { + CError_Error(CErrorStr131); + return 0; + } + + if (copts.ecplusplus && (is_virtual || tclass->bases)) { + CError_Error(CErrorStr339); + return 0; + } + + for (scan = tclass->bases; scan; scan = scan->next) { + if (scan->base == baseclass) { + CError_Error(CErrorStr131); + return 0; + } + } + + if (baseclass->flags & CLASS_COM_OBJECT) + tclass->flags = tclass->flags | CLASS_COM_OBJECT; + if (baseclass->flags & CLASS_IS_CONVERTIBLE) + tclass->flags = tclass->flags | CLASS_IS_CONVERTIBLE; + if (baseclass->flags & CLASS_HAS_VBASES) + tclass->flags = tclass->flags | CLASS_HAS_VBASES; + + if (is_virtual) + tclass->flags = tclass->flags | CLASS_HAS_VBASES; + + return 1; +} + +static void CDecl_ParseBaseClassList(TypeClass *tclass, short mode, Boolean is_templ) { + Boolean is_virtual; + AccessType access; + NameResult pr; + ObjType *inherited_type; + ClassList *base; + ClassList *scan; + TypeClass *baseclass; + + do { + if (mode == CLASS_MODE_CLASS) + access = ACCESSPRIVATE; + else + access = ACCESSPUBLIC; + + is_virtual = 0; + if ((tk = lex()) == TK_VIRTUAL) { + tk = lex(); + is_virtual = 1; + } + + switch (tk) { + case TK_PRIVATE: + access = ACCESSPRIVATE; + tk = lex(); + break; + case TK_PUBLIC: + access = ACCESSPUBLIC; + tk = lex(); + break; + case TK_PROTECTED: + if (!copts.ARMconform) { + access = ACCESSPROTECTED; + tk = lex(); + } + break; + } + + if (tk == TK_VIRTUAL) { + if (is_virtual) + CError_Error(CErrorStr121); + is_virtual = 1; + tk = lex(); + } + + if (CScope_ParseDeclName(&pr)) { + if (!pr.type) { + if (!pr.name_4) { + CError_Error(CErrorStr121); + } else if (tk == TK_IDENTIFIER && pr.name_4 == tkidentifier) { + goto special_parsing; + } + CError_Error(CErrorStr140, tkidentifier->name); + continue; + } + + CDecl_CompleteType(pr.type); + if (is_templ && CTemplTool_IsTemplateArgumentDependentType(pr.type)) { + if (!IS_TYPE_CLASS(pr.type) || !(TYPE_CLASS(pr.type)->flags & CLASS_IS_TEMPL) || + CParser_CheckTemplateClassUsage(TEMPL_CLASS(pr.type), 1)) { + CTemplClass_RegisterBaseClass(TEMPL_CLASS(tclass), pr.type, access, is_virtual); + if (is_virtual) + tclass->flags = tclass->flags | CLASS_HAS_VBASES; + } + continue; + } + + if (!IS_TYPE_CLASS(pr.type) || (TYPE_CLASS(pr.type)->flags & CLASS_IS_TEMPL)) { + CError_Error(CErrorStr131); + continue; + } + baseclass = TYPE_CLASS(pr.type); + } else { + special_parsing: + if (!strcmp(tkidentifier->name, "HandleObject")) { + if (tclass->bases) + CError_Error(CErrorStr191); + tclass->flags |= CLASS_SINGLE_OBJECT | CLASS_HANDLEOBJECT; + tk = lex(); + break; + } + if (!strcmp(tkidentifier->name, "SingleObject") || !strcmp(tkidentifier->name, "SingleInheritance")) { + if (tclass->bases) + CError_Error(CErrorStr191); + tclass->flags = tclass->flags | CLASS_SINGLE_OBJECT; + tk = lex(); + break; + } + if (!strcmp(tkidentifier->name, "__comobject")) { + tclass->flags = tclass->flags | CLASS_COM_OBJECT; + tk = lex(); + break; + } + if (!strcmp(tkidentifier->name, "__somobject")) { + if (!is_virtual) + CError_Error(CErrorStr268); + CSOM_MakeSOMClass(tclass); + tk = lex(); + break; + } + if (!strcmp(tkidentifier->name, "__javaobject")) { + tk = lex(); + tclass->action = CLASS_ACTION_3; + break; + } + + CError_Error(CErrorStr140, tkidentifier->name); + continue; + } + + if (CDecl_CheckNewBase(tclass, baseclass, is_virtual)) { + base = galloc(sizeof(ClassList)); + memclrw(base, sizeof(ClassList)); + base->base = baseclass; + base->access = access; + base->is_virtual = is_virtual; + if ((scan = tclass->bases)) { + while (scan->next) + scan = scan->next; + scan->next = base; + } else { + tclass->bases = base; + } + } + } while ((tk = lex()) == ','); + + if (tclass->flags & CLASS_HAS_VBASES) + CDecl_MakeVBaseList(tclass); + + if (copts.def_inherited && tclass->bases && !tclass->bases->next) { + inherited_type = galloc(sizeof(ObjType)); + memclrw(inherited_type, sizeof(ObjType)); + inherited_type->otype = OT_TYPE; + inherited_type->access = ACCESSPUBLIC; + inherited_type->type = TYPE(tclass->bases->base); + CScope_AddObject(tclass->nspace, GetHashNameNodeExport("inherited"), OBJ_BASE(inherited_type)); + } +} + +static AccessType getaccesstype(AccessType a, AccessType b, AccessType c) { + if (a == ACCESSNONE || b == ACCESSNONE || b == ACCESSPRIVATE) + return ACCESSNONE; + + if (c == ACCESSPUBLIC && b != ACCESSPUBLIC) + return ACCESSNONE; + + return ACCESSPUBLIC; +} + +static TypeMemberFunc *CDecl_MakeDefaultCtorType(TypeClass *tclass) { + TypeMemberFunc *tmeth = galloc(sizeof(TypeMemberFunc)); + memclrw(tmeth, sizeof(TypeMemberFunc)); + tmeth->type = TYPEFUNC; + tmeth->functype = TYPE(&void_ptr); + tmeth->flags = FUNC_IS_CTOR | FUNC_AUTO_GENERATED | FUNC_METHOD; + tmeth->theclass = tclass; + CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1); + + if (tclass->flags & CLASS_HAS_VBASES) + CDecl_AddArgument(TYPE_FUNC(tmeth), TYPE(&stsignedshort)); + + CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass); + return tmeth; +} + +static void CDecl_AddDefArgConstructor(TypeClass *tclass) { + // empty +} + +static void CDecl_AddMemberFunctionObject(TypeClass *tclass, HashNameNode *name, TypeMemberFunc *tmeth, AccessType access) { + Object *obj = CParser_NewCompilerDefFunctionObject(); + obj->name = name; + obj->type = TYPE(tmeth); + obj->qual = Q_MANGLE_NAME; + obj->access = access; + obj->nspace = tclass->nspace; + obj->qual = obj->qual | Q_INLINE; + CScope_AddObject(tclass->nspace, obj->name, OBJ_BASE(obj)); +} + +static void CDecl_AddDefaultConstructor(ClassLayout *decle, TypeClass *tclass) { + ClassList *base; + ObjMemberVar *ivar; + Object *obj; + Boolean has_ctor; + + if (CClass_Constructor(tclass)) { + CDecl_AddDefArgConstructor(tclass); + return; + } + + has_ctor = 0; + + if (tclass->flags & CLASS_HAS_VBASES) + has_ctor = 1; + if (decle->has_vtable) + has_ctor = 1; + + for (base = tclass->bases; base; base = base->next) { + if (CClass_Constructor(base->base)) + has_ctor = 1; + } + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + Type *type = ivar->type; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (IS_TYPE_CLASS(type) && CClass_Constructor(TYPE_CLASS(type))) + has_ctor = 1; + } + + if (has_ctor) { + CDecl_AddMemberFunctionObject( + tclass, + constructor_name_node, + CDecl_MakeDefaultCtorType(tclass), + ACCESSPUBLIC + ); + } +} + +static TypeMemberFunc *CDecl_MakeCopyCtorType(TypeClass *tclass, Boolean is_const) { + FuncArg *arg; + TypeMemberFunc *tmeth = galloc(sizeof(TypeMemberFunc)); + memclrw(tmeth, sizeof(TypeMemberFunc)); + tmeth->type = TYPEFUNC; + tmeth->functype = TYPE(&void_ptr); + tmeth->flags = FUNC_IS_CTOR | FUNC_AUTO_GENERATED | FUNC_METHOD; + tmeth->theclass = tclass; + CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1); + + arg = CParser_NewFuncArg(); + if (is_const) + arg->qual = Q_CONST; + arg->type = CDecl_NewRefPointerType(TYPE(tclass)); + tmeth->args = arg; + + if (tclass->flags & CLASS_HAS_VBASES) + CDecl_AddArgument(TYPE_FUNC(tmeth), TYPE(&stsignedshort)); + + CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass); + return tmeth; +} + +static void CDecl_AddDefaultCopyConstructor(ClassLayout *decle, TypeClass *tclass) { + ClassList *base; + ObjMemberVar *ivar; + Object *obj; + AccessType access; + Boolean has_copyctor; + Boolean is_const; + FuncArg *arg; + + if (CClass_CopyConstructor(tclass)) + return; + + access = ACCESSPUBLIC; + is_const = 1; + has_copyctor = 0; + + if (CClass_Constructor(tclass)) + has_copyctor = 1; + if ((tclass->flags & CLASS_HAS_VBASES) || decle->has_vtable) + has_copyctor = 1; + + for (base = tclass->bases; base; base = base->next) { + if ((obj = CClass_CopyConstructor(base->base))) { + has_copyctor = 1; + access = getaccesstype(access, obj->access, ACCESSPRIVATE); + arg = TYPE_FUNC(obj->type)->args->next; + if (base->base->flags & CLASS_HAS_VBASES) + arg = arg->next; + if (!(arg->qual & Q_CONST)) + is_const = 0; + } + } + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + Type *type = ivar->type; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (IS_TYPE_CLASS(type) && (obj = CClass_CopyConstructor(TYPE_CLASS(type)))) { + has_copyctor = 1; + access = getaccesstype(access, obj->access, ACCESSPUBLIC); + arg = TYPE_FUNC(obj->type)->args->next; + if (TYPE_CLASS(type)->flags & CLASS_HAS_VBASES) + arg = arg->next; + if (!(arg->qual & Q_CONST)) + is_const = 0; + } + } + + if (has_copyctor) { + CDecl_AddMemberFunctionObject( + tclass, + constructor_name_node, + CDecl_MakeCopyCtorType(tclass, is_const), + access + ); + } +} + +static TypeMemberFunc *CDecl_MakeAssignmentOperatorType(TypeClass *tclass, Boolean is_const) { + FuncArg *arg; + TypeMemberFunc *tmeth = galloc(sizeof(TypeMemberFunc)); + memclrw(tmeth, sizeof(TypeMemberFunc)); + tmeth->type = TYPEFUNC; + tmeth->functype = CDecl_NewRefPointerType(TYPE(tclass)); + tmeth->flags = FUNC_AUTO_GENERATED | FUNC_METHOD; + tmeth->theclass = tclass; + CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1); + + arg = CParser_NewFuncArg(); + if (is_const) + arg->qual = Q_CONST; + arg->type = CDecl_NewRefPointerType(TYPE(tclass)); + tmeth->args = arg; + + CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass); + return tmeth; +} + +static void CDecl_AddDefaultAssignmentOperator(ClassLayout *decle, TypeClass *tclass) { + ClassList *base; + ObjMemberVar *ivar; + Object *obj; + AccessType access; + Boolean is_const; + Boolean has_ass; + DeclInfo declinfo; + + is_const = 1; + has_ass = 0; + access = ACCESSPUBLIC; + + if (!CClass_AssignmentOperator(tclass)) { + if (!copts.old_argmatch) + has_ass = 1; + + if ((tclass->flags & CLASS_HAS_VBASES) || decle->has_vtable || CClass_MemberObject(tclass, asop_name_node)) + has_ass = 1; + + for (base = tclass->bases; base; base = base->next) { + if ((obj = CClass_AssignmentOperator(base->base))) { + has_ass = 1; + access = getaccesstype(access, obj->access, ACCESSPRIVATE); + if (!(TYPE_FUNC(obj->type)->args->next->qual & Q_CONST)) + is_const = 0; + } + } + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + Type *type = ivar->type; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (IS_TYPE_CLASS(type) && (obj = CClass_AssignmentOperator(TYPE_CLASS(type)))) { + has_ass = 1; + access = getaccesstype(access, obj->access, ACCESSPUBLIC); + if (!(TYPE_FUNC(obj->type)->args->next->qual & Q_CONST)) + is_const = 0; + } + } + } + + if (has_ass) { + memclrw(&declinfo, sizeof(DeclInfo)); + declinfo.qual |= Q_INLINE; + declinfo.thetype = (Type *) CDecl_MakeAssignmentOperatorType(tclass, is_const); + declinfo.name = asop_name_node; + CDecl_AddFunctionMember(decle, tclass, &declinfo, access, 1, 0, 0, 0); + } +} + +TypeMemberFunc *CDecl_MakeDefaultDtorType(TypeClass *tclass, Boolean is_virtual) { + TypeMemberFunc *tmeth = galloc(sizeof(TypeMemberFunc)); + memclrw(tmeth, sizeof(TypeMemberFunc)); + tmeth->type = TYPEFUNC; + tmeth->functype = (Type *) &void_ptr; + tmeth->flags = FUNC_IS_DTOR | FUNC_AUTO_GENERATED | FUNC_METHOD; + tmeth->theclass = tclass; + CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1); + if (is_virtual) + CDecl_AddArgument(TYPE_FUNC(tmeth), TYPE(&stsignedshort)); + CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass); + return tmeth; +} + +static void CDecl_AddDefaultDestructor(ClassLayout *decle, TypeClass *tclass) { + ClassList *base; + ObjMemberVar *ivar; + Object *obj; + AccessType access; + Boolean has_dtor; + Boolean is_virtual; + DeclInfo declinfo; + + if (CClass_Destructor(tclass)) + return; + + has_dtor = 0; + is_virtual = 0; + access = ACCESSPUBLIC; + + for (base = tclass->bases; base; base = base->next) { + if ((obj = CClass_Destructor(base->base))) { + has_dtor = 1; + if (obj->datatype == DVFUNC) + is_virtual = 1; + access = getaccesstype(access, obj->access, ACCESSPRIVATE); + } + } + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + Type *type = ivar->type; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (IS_TYPE_CLASS(type) && (obj = CClass_Destructor(TYPE_CLASS(type)))) { + has_dtor = 1; + access = getaccesstype(access, obj->access, ACCESSPUBLIC); + } + } + + if (has_dtor) { + memclrw(&declinfo, sizeof(DeclInfo)); + declinfo.qual |= Q_INLINE; + if (is_virtual) + declinfo.qual |= Q_VIRTUAL; + + declinfo.thetype = (Type *) CDecl_MakeDefaultDtorType(tclass, 1); + declinfo.name = destructor_name_node; + CDecl_AddFunctionMember(decle, tclass, &declinfo, access, 1, 0, 0, 0); + } +} + +static void CDecl_SetupClassLayout(ClassLayout *decle, TypeClass *tclass, ObjBase **objbuf) { + SInt32 index; + SInt32 i; + Object *obj; + CScopeObjectIterator iter; + ObjMemberVar *ivar; + SInt32 bufsize; + + if (decle->lex_order_count > 32) { + bufsize = decle->lex_order_count * sizeof(ObjBase *); + objbuf = lalloc(bufsize); + } else { + bufsize = 32 * sizeof(ObjBase *); + } + memclrw(objbuf, bufsize); + decle->objlist = objbuf; + + CScope_InitObjectIterator(&iter, tclass->nspace); + index = 0; + while (1) { + obj = OBJECT(CScope_NextObjectIteratorObject(&iter)); + if (!obj) break; + + if (!IS_TYPE_FUNC(obj->type)) + continue; + if (!IS_TYPEFUNC_METHOD(TYPE_FUNC(obj->type))) + continue; + if (obj->datatype == DALIAS) + continue; + + i = TYPE_METHOD(obj->type)->vtbl_index; + if (i > 0) { + CError_ASSERT(6363, (i - 1) < decle->lex_order_count && !objbuf[(int) (i - 1)]); + objbuf[(int) (i - 1)] = OBJ_BASE(obj); + index++; + if (obj->datatype != DVFUNC && !TYPE_METHOD(obj->type)->is_static && CClass_OverridesBaseMember(tclass, obj->name, obj)) + CDecl_MakeFunctionVirtual(tclass, obj); + + if (obj->datatype == DVFUNC) { + decle->has_vtable = 1; + if (!tclass->vtable) { + CABI_AddVTable(tclass); + decle->xA = i - 1; + } else { + if ((i - 1) < decle->xA) + decle->xA = i - 1; + } + } else if (TYPE_FUNC(obj->type)->flags & FUNC_PURE) { + CError_Error(CErrorStr351, obj); + TYPE_FUNC(obj->type)->flags &= ~FUNC_PURE; + } + } else { + CError_ASSERT(6412, i == 0); + } + + if (!tclass->sominfo) + TYPE_METHOD(obj->type)->vtbl_index = 0; + } + + if (!tclass->action) { + for (i = 0; i < decle->lex_order_count; i++) { + Object *obj2 = OBJECT(objbuf[i]); + if (obj2 && obj2->datatype == DVFUNC && !(obj2->qual & Q_INLINE) && !(TYPE_FUNC(obj2->type)->flags & FUNC_PURE)) { + tclass->action = CLASS_ACTION_1; + TYPE_FUNC(obj2->type)->flags |= FUNC_FLAGS_4; + break; + } + } + } + + if (!tclass->sominfo) { + for (i = 0, ivar = tclass->ivars; i < decle->lex_order_count; i++) { + if (!objbuf[i]) { + CError_ASSERT(6449, ivar); + objbuf[i] = OBJ_BASE(ivar); + ivar = ivar->next; + index++; + } + } + CError_ASSERT(6455, ivar == NULL); + } + + CError_ASSERT(6458, index == decle->lex_order_count); +} + +void CDecl_CompleteClass(ClassLayout *decle, TypeClass *tclass) { + ClassList *base; + ObjBase *buf[32]; + + for (base = tclass->bases; base; base = base->next) { + if (base->base->vtable) + decle->has_vtable = 1; + } + + if (!tclass->sominfo) { + CDecl_AddDefaultDestructor(decle, tclass); + CDecl_AddDefaultAssignmentOperator(decle, tclass); + CDecl_AddDefaultConstructor(decle, tclass); + CDecl_AddDefaultCopyConstructor(decle, tclass); + } + + CDecl_SetupClassLayout(decle, tclass, buf); + if (decle->has_vtable) + CClass_CheckOverrides(tclass); + CABI_LayoutClass(decle, tclass); + if (tclass->sominfo) + CSOM_ClassComplete(tclass); + + if ((tclass->flags & CLASS_IS_TEMPL_INST) && !TEMPL_CLASS_INST(tclass)->is_specialized) + tclass->action = CLASS_ACTION_0; + + if (!tclass->action) + CClass_MakeStaticActionClass(tclass); + CClass_ClassDefaultFuncAction(tclass); +} + +TypeClass *CDecl_DefineClass(NameSpace *nspace, HashNameNode *name, TypeClass *tclass, short mode, Boolean flag2, Boolean flag3) { + NameSpace *mynspace; + ObjType *objtype; + + if (!tclass && nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL)) { + CError_ASSERT(6556, !flag2); + return TYPE_CLASS(CTemplClass_DefineNestedClass(TEMPL_CLASS(nspace->theclass), name, mode)); + } + + mynspace = CScope_NewListNameSpace(name, 1); + if (!tclass) { + tclass = galloc(sizeof(TypeClass)); + memclrw(tclass, sizeof(TypeClass)); + } + + tclass->type = TYPECLASS; + tclass->align = 1; + tclass->mode = mode; + tclass->action = CLASS_ACTION_0; + if (name) { + tclass->classname = name; + if (flag3) { + if (flag2) { + objtype = galloc(sizeof(ObjType)); + memclrw(objtype, sizeof(ObjType)); + objtype->otype = OT_TYPE; + objtype->access = ACCESSPUBLIC; + objtype->type = (Type *) tclass; + CScope_AddObject(nspace, name, OBJ_BASE(objtype)); + } else { + CScope_DefineTypeTag(nspace, name, (Type *) tclass); + } + } + CScope_DefineTypeTag(mynspace, name, (Type *) tclass); + + if (cscope_currentfunc) + mynspace->name = CParser_AppendUniqueNameFile(name->name); + + if (copts.direct_to_som && nspace == cscope_root && !strcmp(name->name, "SOMObject")) + CSOM_MakeSOMClass(tclass); + } else { + tclass->classname = CParser_AppendUniqueNameFile("@class"); + mynspace->name = tclass->classname; + } + + tclass->nspace = mynspace; + mynspace->theclass = tclass; + mynspace->parent = nspace; + if (!nspace->is_global) + CParser_RegisterNonGlobalClass(tclass); + + return tclass; +} + +void CDecl_ParseClassDeclSpec(UInt8 *declspec) { + DeclInfo declinfo; + + if ((tk = lex()) == '(') { + memclrw(&declinfo, sizeof(DeclInfo)); + CParser_ParseDeclSpec(&declinfo, 1); + if (declinfo.exportflags & EXPORT_FLAGS_INTERNAL) + *declspec = *declspec | CLASS_EFLAGS_INTERNAL; + if (declinfo.exportflags & EXPORT_FLAGS_IMPORT) + *declspec = *declspec | CLASS_EFLAGS_IMPORT; + if (declinfo.exportflags & EXPORT_FLAGS_EXPORT) + *declspec = *declspec | CLASS_EFLAGS_EXPORT; + if ((tk = lex()) != ')') + CError_Error(CErrorStr115); + else + tk = lex(); + } else { + CError_Error(CErrorStr114); + } +} + +static TemplClass *CDecl_SpecializeTemplateClass(TemplClass *tmclass) { + tmclass->theclass.nspace->names = 0; + tmclass->theclass.nspace->data.list = NULL; + tmclass->theclass.ivars = NULL; + tmclass->theclass.bases = NULL; + tmclass->theclass.vbases = NULL; + tmclass->theclass.friends = NULL; + tmclass->theclass.vtable = NULL; + tmclass->members = NULL; + tmclass->instances = NULL; + tmclass->pspec_owner = NULL; + tmclass->pspecs = NULL; + tmclass->actions = NULL; + tmclass->lex_order_count = 0; + tmclass->align = 0; + tmclass->flags = TEMPLCLASS_FLAGS_2; + return tmclass; +} + +void CDecl_ParseClass(DeclInfo *declinfo, short mode, Boolean flag1, UInt8 class_declspec) { + ClassLayout decle; + TypeClass *tclass; + HashNameNode *classname; + Type *search; + short t; + NameSpace *nspace; + NameResult pr; + CScopeSave scopesave; + GList gl; + FileOffsetInfo offsetsave; + SInt32 offset; + Boolean is_templ; + Boolean add_to_browse; + + memclrw(&decle, sizeof(ClassLayout)); + if (declinfo->x28) { + tclass = TYPE_CLASS(declinfo->x28); + } else { + if (tk == TK_UU_DECLSPEC) + CDecl_ParseClassDeclSpec(&class_declspec); + + switch (tk) { + case ':': + case '{': + tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1); + tclass->eflags |= class_declspec; + break; + case TK_IDENTIFIER: + classname = tkidentifier; + if (!declinfo->in_friend_decl && !declinfo->x4F && ((t = lookahead()) == ':' || t == ';' || t == '{')) { + tk = lex(); + search = CScope_GetLocalTagType(cscope_current, classname); + if (search) { + tagtype_search: + if (!IS_TYPE_CLASS(search)) { + if ((IS_TYPE_TEMPLATE(search) || IS_TYPE_STRUCT(search)) && tk != '{' && tk != ':') { + declinfo->thetype = search; + return; + } + if (!IS_TYPE_TEMPLATE(search) || !(tclass = TYPE_CLASS(CTemplTool_GetSelfRefTemplate(search)))) { + CError_Error(CErrorStr132, classname->name); + tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1); + break; + } + } else { + tclass = TYPE_CLASS(search); + } + if (tclass->mode != mode) { + if ( + (mode == CLASS_MODE_CLASS && tclass->mode == CLASS_MODE_STRUCT) || + (mode == CLASS_MODE_STRUCT && tclass->mode == CLASS_MODE_CLASS) + ) + { + if (copts.warn_structclass) + CError_Warning(CErrorStr343); + } else { + CError_Error(CErrorStr132, classname); + } + } + tclass->eflags |= class_declspec; + break; + } else { + tclass = CDecl_DefineClass(cscope_current, classname, NULL, mode, 0, 1); + tclass->eflags |= class_declspec; + break; + } + } else { + tkidentifier = classname; + } + default: + if (!CScope_ParseElaborateName(&pr)) { + CError_Error(CErrorStr121); + declinfo->thetype = TYPE(&stsignedint); + return; + } + + tk = lex(); + if ((search = pr.type)) { + goto tagtype_search; + } + + CError_ASSERT(6786, pr.name_4); + + tclass = CDecl_DefineClass(CScope_FindNonClassNonFunctionNS(cscope_current), pr.name_4, NULL, mode, 0, 1); + tclass->eflags |= class_declspec; + } + } + + declinfo->thetype = TYPE(tclass); + if (tk == ':' || tk == '{') { + if (declinfo->in_friend_decl) + CError_Error(CErrorStr201); + + if (tclass->flags & CLASS_COMPLETED) { + if ( + (tclass->flags & CLASS_IS_TEMPL) && + !TEMPL_CLASS(tclass)->instances && + !(TEMPL_CLASS(tclass)->flags & TEMPLCLASS_FLAGS_2) + ) + { + tclass = TYPE_CLASS(CDecl_SpecializeTemplateClass(TEMPL_CLASS(tclass))); + } else { + CError_Error(CErrorStr132, tclass->classname->name); + tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1); + } + } + + for (nspace = cscope_current; nspace; nspace = nspace->parent) { + if (nspace == tclass->nspace) { + CError_Error(CErrorStr132, tclass->classname->name); + tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1); + break; + } + } + + is_templ = (tclass->flags & CLASS_IS_TEMPL) != 0; + if (tclass->flags & CLASS_IS_TEMPL_INST) { + TEMPL_CLASS_INST(tclass)->is_instantiated = 1; + if (!declinfo->x28) + TEMPL_CLASS_INST(tclass)->is_specialized = 1; + } + + CError_ASSERT(6853, copts.structalignment >= 0 && copts.structalignment <= 14); + + tclass->eflags = tclass->eflags | (((copts.structalignment + 1) << 4) & 0xF0); + if (tk == ':') + CDecl_ParseBaseClassList(tclass, mode, is_templ); + + CScope_SetClassDefScope(tclass, &scopesave); + if (tk == '{') { + tk = lex(); + if ((add_to_browse = cparamblkptr->browseoptions.recordClasses && declinfo->file->recordbrowseinfo)) { + offsetsave = member_fileoffset; + CBrowse_BeginClass(declinfo, &gl); + } + CDecl_ParseClassMembers(&decle, tclass, mode); + offset = CPrep_BrowserFileOffset(); + if (flag1) + tk = lex(); + if (add_to_browse) { + member_fileoffset = offsetsave; + if (flag1 && tk == ';') + CPrep_BrowserFileOffset(); + CBrowse_EndClass(offset, &gl); + } + } else { + CError_Error(CErrorStr135); + } + + if (is_templ) + CTemplClass_CompleteClass(TEMPL_CLASS(tclass), &decle); + else + CDecl_CompleteClass(&decle, tclass); + CScope_RestoreScope(&scopesave); + } +} diff --git a/compiler_and_linker/FrontEnd/C/CError.c b/compiler_and_linker/FrontEnd/C/CError.c new file mode 100644 index 0000000..02265c3 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CError.c @@ -0,0 +1,1098 @@ +#include "cos.h" +#include "compiler/CClass.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CTemplateNew.h" +#include "compiler/CompilerTools.h" +#include "compiler/InlineAsm.h" +#include "compiler/Unmangle.h" +#include "compiler/enode.h" +#include "compiler/objc.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" +#include "compiler/tokens.h" + +TStreamElement *cerror_locktoken; +static TStreamElement *cerror_token; +static short cerror_errorcount; +static SInt32 cerror_lasterrorline; +char cerror_synchdata[32]; +short cerror_synchoffset; +int CError_BreakPointcount; + +// forward decls +static void CError_BufferAppendType(CErrorBuffer *eb, Type *ty, UInt32 qual); +static void CError_AppendObjectName(CErrorBuffer *eb, Object *obj); + +void CError_Init(void) { + cerror_errorcount = 0; + cerror_lasterrorline = -1; + cerror_token = 0; + cerror_locktoken = 0; +} + +void CError_SetErrorToken(TStreamElement *token) { + if (token && token->tokenfile) + cerror_token = token; +} + +void CError_SetNullErrorToken(void) { + cerror_token = (TStreamElement *) -1; +} + +void CError_LockErrorPos(TStreamElement *token, TStreamElement **saved) { + *saved = cerror_locktoken; + if (token && token->tokenfile) + cerror_locktoken = token; +} + +void CError_UnlockErrorPos(TStreamElement **saved) { + cerror_locktoken = *saved; +} + +void CError_ResetErrorSkip(void) { + cerror_lasterrorline = -1; +} + +static void CError_GetErrorString(char *buf, short code) { + CError_ASSERT(142, code >= CErrorStr100 && code < CErrorStrMAX); + COS_GetString(buf, 10000, code - 99); +} + +static void CError_BufferInit(CErrorBuffer *eb, char *buf, SInt32 bufSize) { + eb->start = eb->end = buf; + eb->size = eb->remaining = bufSize - 1; +} + +static void CError_BufferGrow(CErrorBuffer *eb, SInt32 amount) { + char *newBuf; + + newBuf = lalloc(eb->size + amount); + memcpy(newBuf, eb->start, eb->size); + eb->start = newBuf; + eb->end = newBuf + eb->size - eb->remaining; + eb->size += amount; + eb->remaining += amount; +} + +static void CError_BufferAppendChar(CErrorBuffer *eb, char ch) { + if (eb) { + if (!eb->remaining) + CError_BufferGrow(eb, 256); + *(eb->end++) = ch; + eb->remaining--; + } +} + +static void CError_BufferAppendString(CErrorBuffer *eb, const char *str) { + size_t len; + + if (eb) { + len = strlen(str); + if (eb->remaining < len) + CError_BufferGrow(eb, len); + memcpy(eb->end, str, len); + eb->end += len; + eb->remaining -= len; + } +} + +static void CError_BufferTerminate(CErrorBuffer *eb) { + if (eb->remaining == 0) + CError_BufferGrow(eb, 1); + *eb->end = 0; + eb->remaining = 0; +} + +static void CError_BufferAppendQualifier(CErrorBuffer *eb, UInt32 qual) { + if (qual & Q_PASCAL) + CError_BufferAppendString(eb, "pascal "); + if (qual & Q_CONST) + CError_BufferAppendString(eb, "const "); + if (qual & Q_VOLATILE) + CError_BufferAppendString(eb, "volatile "); + if (qual & Q_EXPLICIT) + CError_BufferAppendString(eb, "explicit "); + if (qual & Q_RESTRICT) + CError_BufferAppendString(eb, "restrict "); +} + +static void CError_BufferAppendTemplArgExpr(CErrorBuffer *eb, ENode *node) { + char buf[32]; + + if (node) { + switch (node->type) { + case EINTCONST: + CInt64_PrintDec(buf, node->data.intval); + CError_BufferAppendString(eb, buf); + return; + case EOBJREF: + CError_BufferAppendChar(eb, '&'); + CError_AppendObjectName(eb, node->data.objref); + return; + } + } + + CError_BufferAppendString(eb, "{targ_expr}"); +} + +static void CError_BufferAppendTemplArg(CErrorBuffer *eb, TemplArg *targ) { + switch (targ->pid.type) { + case TPT_TYPE: + CError_BufferAppendType(eb, targ->data.typeparam.type, targ->data.typeparam.qual); + break; + case TPT_NONTYPE: + CError_BufferAppendTemplArgExpr(eb, targ->data.paramdecl.expr); + break; + case TPT_TEMPLATE: + CError_BufferAppendType(eb, targ->data.ttargtype, 0); + break; + default: + CError_FATAL(300); + } +} + +static void CError_BufferAppendTemplArgs(CErrorBuffer *eb, TemplArg *targs) { + if (targs) { + CError_BufferAppendChar(eb, '<'); + while (targs) { + CError_BufferAppendTemplArg(eb, targs); + if (targs->next) + CError_BufferAppendString(eb, ", "); + targs = targs->next; + } + CError_BufferAppendChar(eb, '>'); + } +} + +static void CError_BufferAppendNameSpace(CErrorBuffer *eb, NameSpace *nspace) { + while (nspace) { + if (nspace->name) { + CError_BufferAppendNameSpace(eb, nspace->parent); + if (nspace->theclass) { + CError_BufferAppendString(eb, nspace->theclass->classname->name); + if (nspace->theclass->flags & CLASS_IS_TEMPL_INST) + CError_BufferAppendTemplArgs( + eb, + !TEMPL_CLASS_INST(nspace->theclass)->oargs ? TEMPL_CLASS_INST(nspace->theclass)->inst_args : TEMPL_CLASS_INST(nspace->theclass)->oargs + ); + } else { + CError_BufferAppendString(eb, nspace->name->name); + } + CError_BufferAppendString(eb, "::"); + return; + } + nspace = nspace->parent; + } +} + +static void CError_BufferAppendPType(CErrorBuffer *eb, Type *ty) { + switch (ty->type) { + case TYPEPOINTER: + CError_BufferAppendPType(eb, TYPE_POINTER(ty)->target); + if (TYPE_POINTER(ty)->qual & Q_REFERENCE) + CError_BufferAppendString(eb, "&"); + else + CError_BufferAppendString(eb, "*"); + CError_BufferAppendQualifier(eb, TYPE_POINTER(ty)->qual); + break; + case TYPEMEMBERPOINTER: + CError_BufferAppendPType(eb, TYPE_MEMBER_POINTER(ty)->ty1); + CError_BufferAppendType(eb, TYPE_MEMBER_POINTER(ty)->ty2, 0); + CError_BufferAppendString(eb, "::*"); + CError_BufferAppendQualifier(eb, TYPE_MEMBER_POINTER(ty)->qual); + break; + } +} + +static void CError_BufferAppendTemplDepType(CErrorBuffer *eb, TypeTemplDep *type) { + char buf[64]; + switch (type->dtype) { + case TEMPLDEP_ARGUMENT: + if (type->u.pid.nindex) + sprintf(buf, "T%" PRId32 "_%" PRId32, type->u.pid.nindex, type->u.pid.index); + else + sprintf(buf, "T%" PRId32, type->u.pid.index); + CError_BufferAppendString(eb, buf); + break; + case TEMPLDEP_QUALNAME: + CError_BufferAppendTemplDepType(eb, type->u.qual.type); + CError_BufferAppendString(eb, "::"); + CError_BufferAppendString(eb, type->u.qual.name->name); + break; + case TEMPLDEP_TEMPLATE: + CError_BufferAppendType(eb, (Type *) type->u.templ.templ, 0); + CError_BufferAppendTemplArgs(eb, type->u.templ.args); + break; + case TEMPLDEP_ARRAY: + CError_BufferAppendType(eb, type->u.array.type, 0); + CError_BufferAppendChar(eb, '['); + CError_BufferAppendTemplArgExpr(eb, type->u.array.index); + CError_BufferAppendChar(eb, ']'); + break; + case TEMPLDEP_QUALTEMPL: + CError_BufferAppendTemplDepType(eb, type->u.qualtempl.type); + CError_BufferAppendString(eb, "::"); + CError_BufferAppendTemplArgs(eb, type->u.qualtempl.args); + break; + case TEMPLDEP_BITFIELD: + CError_BufferAppendType(eb, type->u.bitfield.type, 0); + CError_BufferAppendChar(eb, '['); + CError_BufferAppendTemplArgExpr(eb, type->u.bitfield.size); + CError_BufferAppendChar(eb, ']'); + break; + default: + CError_FATAL(463); + } +} + +static void CError_BufferAppendFuncArgs(CErrorBuffer *eb, TypeFunc *tfunc, Boolean isMethod) { + FuncArg *arg; + UInt32 qual; + + qual = 0; + CError_BufferAppendChar(eb, '('); + if ((arg = tfunc->args)) { + if (isMethod) { + qual = arg->qual; + arg = arg->next; + if (arg) + arg = arg->next; + } else if ((tfunc->flags & FUNC_METHOD) && !TYPE_METHOD(tfunc)->is_static) { + qual = arg->qual; + arg = arg->next; + if (arg) { + if ((tfunc->flags & FUNC_IS_DTOR) || ((tfunc->flags & FUNC_IS_CTOR) && (TYPE_METHOD(tfunc)->theclass->flags & CLASS_HAS_VBASES))) + arg = arg->next; + } + } + + while (arg) { + if (arg == &elipsis || arg == &oldstyle) { + CError_BufferAppendString(eb, "..."); + break; + } + + CError_BufferAppendType(eb, arg->type, arg->qual); + + if ((arg = arg->next)) + CError_BufferAppendString(eb, ", "); + else + break; + } + } + CError_BufferAppendChar(eb, ')'); + if (qual) + CError_BufferAppendQualifier(eb, qual); +} + +static void CError_BufferAppendType(CErrorBuffer *eb, Type *ty, UInt32 qual) { + // not matching - register issues + Type *scan; + Type *scan2; + char buf[16]; + + switch (ty->type) { + case TYPEVOID: + CError_BufferAppendQualifier(eb, qual); + CError_BufferAppendString(eb, "void"); + return; + case TYPEINT: + case TYPEFLOAT: + CError_BufferAppendQualifier(eb, qual); + switch (TYPE_INTEGRAL(ty)->integral) { + case IT_BOOL: + CError_BufferAppendString(eb, "bool"); + return; + case IT_CHAR: + CError_BufferAppendString(eb, "char"); + return; + case IT_UCHAR: + CError_BufferAppendString(eb, "unsigned char"); + return; + case IT_SCHAR: + CError_BufferAppendString(eb, "signed char"); + return; + case IT_WCHAR_T: + CError_BufferAppendString(eb, "wchar_t"); + return; + case IT_SHORT: + CError_BufferAppendString(eb, "short"); + return; + case IT_USHORT: + CError_BufferAppendString(eb, "unsigned short"); + return; + case IT_INT: + CError_BufferAppendString(eb, "int"); + return; + case IT_UINT: + CError_BufferAppendString(eb, "unsigned int"); + return; + case IT_LONG: + CError_BufferAppendString(eb, "long"); + return; + case IT_ULONG: + CError_BufferAppendString(eb, "unsigned long"); + return; + case IT_LONGLONG: + CError_BufferAppendString(eb, "long long"); + return; + case IT_ULONGLONG: + CError_BufferAppendString(eb, "unsigned long long"); + return; + case IT_FLOAT: + CError_BufferAppendString(eb, "float"); + return; + case IT_SHORTDOUBLE: + CError_BufferAppendString(eb, "short double"); + return; + case IT_DOUBLE: + CError_BufferAppendString(eb, "double"); + return; + case IT_LONGDOUBLE: + CError_BufferAppendString(eb, "long double"); + return; + default: + CError_FATAL(584); + } + case TYPEENUM: + CError_BufferAppendQualifier(eb, qual); + CError_BufferAppendNameSpace(eb, TYPE_ENUM(ty)->nspace); + if (TYPE_ENUM(ty)->enumname) + CError_BufferAppendString(eb, TYPE_ENUM(ty)->enumname->name); + else + CError_BufferAppendString(eb, "{unnamed-enum}"); + return; + case TYPESTRUCT: + CError_BufferAppendQualifier(eb, qual); + switch (TYPE_STRUCT(ty)->stype) { + case STRUCT_TYPE_STRUCT: + CError_BufferAppendString(eb, "struct "); + break; + case STRUCT_TYPE_UNION: + CError_BufferAppendString(eb, "union "); + break; + case STRUCT_VECTOR_UCHAR: + case STRUCT_VECTOR_SCHAR: + case STRUCT_VECTOR_BCHAR: + case STRUCT_VECTOR_USHORT: + case STRUCT_VECTOR_SSHORT: + case STRUCT_VECTOR_BSHORT: + case STRUCT_VECTOR_UINT: + case STRUCT_VECTOR_SINT: + case STRUCT_VECTOR_BINT: + case STRUCT_VECTOR_FLOAT: + case STRUCT_VECTOR_PIXEL: + break; + default: + CError_FATAL(618); + } + if (TYPE_STRUCT(ty)->name) + CError_BufferAppendString(eb, TYPE_STRUCT(ty)->name->name); + return; + case TYPECLASS: + CError_BufferAppendQualifier(eb, qual); + CError_BufferAppendNameSpace(eb, TYPE_CLASS(ty)->nspace->parent); + if (TYPE_CLASS(ty)->classname) { + CError_BufferAppendString(eb, TYPE_CLASS(ty)->classname->name); + if (TYPE_CLASS(ty)->flags & CLASS_IS_TEMPL_INST) + CError_BufferAppendTemplArgs( + eb, + TEMPL_CLASS_INST(ty)->oargs ? TEMPL_CLASS_INST(ty)->oargs : TEMPL_CLASS_INST(ty)->inst_args + ); + } else { + CError_BufferAppendString(eb, "{unnamed-class}"); + } + return; + case TYPEPOINTER: + case TYPEMEMBERPOINTER: + scan = ty; + next_ptr: + switch (scan->type) { + case TYPEPOINTER: + scan = TYPE_POINTER(scan)->target; + goto next_ptr; + case TYPEMEMBERPOINTER: + scan = TYPE_MEMBER_POINTER(scan)->ty1; + goto next_ptr; + } + + CError_BufferAppendQualifier(eb, qual); + switch (scan->type) { + case TYPEFUNC: + if (TYPE_FUNC(scan)->flags & FUNC_PASCAL) + CError_BufferAppendString(eb, "pascal "); + CError_BufferAppendType(eb, TYPE_FUNC(scan)->functype, 0); + CError_BufferAppendString(eb, " ("); + CError_BufferAppendPType(eb, ty); + CError_BufferAppendChar(eb, ')'); + CError_BufferAppendFuncArgs(eb, TYPE_FUNC(scan), ty->type == TYPEMEMBERPOINTER); + return; + case TYPEARRAY: + scan2 = scan; + while (scan->type == TYPEARRAY) + scan = TYPE_POINTER(scan)->target; + CError_BufferAppendType(eb, scan, 0); + CError_BufferAppendString(eb, " ("); + CError_BufferAppendPType(eb, ty); + CError_BufferAppendChar(eb, ')'); + ty = scan2; + goto append_array_lengths; + default: + CError_BufferAppendType(eb, scan, 0); + CError_BufferAppendChar(eb, ' '); + CError_BufferAppendPType(eb, ty); + return; + } + break; + case TYPEFUNC: + if (TYPE_FUNC(ty)->flags & FUNC_PASCAL) + CError_BufferAppendString(eb, "pascal "); + CError_BufferAppendQualifier(eb, qual); + CError_BufferAppendType(eb, TYPE_FUNC(ty)->functype, 0); + CError_BufferAppendChar(eb, ' '); + CError_BufferAppendFuncArgs(eb, TYPE_FUNC(ty), 0); + return; + case TYPEARRAY: + CError_BufferAppendQualifier(eb, qual); + scan = ty; + while (scan->type == TYPEARRAY) + scan = TYPE_POINTER(scan)->target; + CError_BufferAppendType(eb, scan, 0); + append_array_lengths: + while (ty->type == TYPEARRAY) { + CError_BufferAppendChar(eb, '['); + if (ty->size && TYPE_POINTER(ty)->target->size) { + sprintf(buf, "%" PRId32, ty->size / TYPE_POINTER(ty)->target->size); + CError_BufferAppendString(eb, buf); + } + CError_BufferAppendChar(eb, ']'); + ty = TYPE_POINTER(ty)->target; + } + return; + case TYPETEMPLATE: + CError_BufferAppendQualifier(eb, qual); + CError_BufferAppendTemplDepType(eb, TYPE_TEMPLATE(ty)); + return; + case TYPETEMPLDEPEXPR: + CError_BufferAppendString(eb, "T"); + return; + case TYPEBITFIELD: + sprintf(buf, "bitfield:%" PRId32, TYPE_BITFIELD(ty)->bitlength); + CError_BufferAppendString(eb, buf); + return; + default: + CError_FATAL(752); + } +} + +char *CError_GetTypeName(Type *ty, UInt32 qual, Boolean useGlobalHeap) { + CErrorBuffer eb; + char buf[256]; + char *ptr; + + CError_BufferInit(&eb, buf, sizeof(buf)); + CError_BufferAppendType(&eb, ty, qual); + CError_BufferTerminate(&eb); + + if (useGlobalHeap) + ptr = galloc(eb.size + 1); + else + ptr = lalloc(eb.size + 1); + + return strcpy(ptr, eb.start); +} + +static void CError_AppendUnqualFunctionName(CErrorBuffer *eb, NameSpace *nspace, HashNameNode *name, TypeFunc *tfunc) { + Boolean flag = 0; + char *opname; + + if (nspace && nspace->theclass) { + if (name == constructor_name_node) { + CError_BufferAppendString(eb, nspace->theclass->classname->name); + flag = 1; + } else if (name == destructor_name_node) { + CError_BufferAppendChar(eb, '~'); + CError_BufferAppendString(eb, nspace->theclass->classname->name); + flag = 1; + } + } + + if (!flag) { + opname = CMangler_GetOperator(name); + if (!opname) { + if (tfunc && (tfunc->flags & FUNC_CONVERSION)) { + CError_BufferAppendString(eb, "operator "); + CError_BufferAppendType(eb, tfunc->functype, tfunc->qual); + } else { + CError_BufferAppendString(eb, name->name); + } + } else { + CError_BufferAppendString(eb, opname); + } + } +} + +static void CError_AppendFunctionName(CErrorBuffer *eb, NameSpace *nspace, HashNameNode *name, TemplArg *templargs, TypeFunc *tfunc) { + while (nspace->is_templ && nspace->parent) + nspace = nspace->parent; + + CError_BufferAppendNameSpace(eb, nspace); + CError_AppendUnqualFunctionName(eb, nspace, name, tfunc); + CError_BufferAppendTemplArgs(eb, templargs); + if (tfunc) { + if (!templargs && (tfunc->flags & FUNC_IS_TEMPL)) + CError_BufferAppendString(eb, "<...>"); + CError_BufferAppendFuncArgs(eb, tfunc, 0); + } else { + CError_BufferAppendString(eb, "()"); + } +} + +static void CError_AppendObjectName(CErrorBuffer *eb, Object *obj) { + if (obj->type->type == TYPEFUNC) { + CError_AppendFunctionName(eb, obj->nspace, obj->name, obj->u.func.inst ? obj->u.func.inst->args : NULL, TYPE_FUNC(obj->type)); + } else { + CError_BufferAppendNameSpace(eb, obj->nspace); + CError_BufferAppendString(eb, obj->name->name); + } +} + +static void CError_AppendMethodName(CErrorBuffer *eb, ObjCMethod *meth) { + ObjCMethodArg *arg; + + CError_BufferAppendChar(eb, meth->is_class_method ? '+' : '-'); + CError_BufferAppendChar(eb, '('); + CError_BufferAppendType(eb, meth->return_type, meth->return_qual); + CError_BufferAppendChar(eb, ')'); + for (arg = meth->selector_args; arg; arg = arg->next) { + if (arg->selector) + CError_BufferAppendString(eb, arg->selector->name); + if (arg->type) { + CError_BufferAppendString(eb, ":("); + CError_BufferAppendType(eb, arg->type, arg->qual); + CError_BufferAppendChar(eb, ')'); + } + } + if (meth->has_valist) + CError_BufferAppendString(eb, ",..."); +} + +char *CError_GetQualifiedName(NameSpace *nspace, HashNameNode *name) { + CErrorBuffer eb; + char buf[256]; + char *ptr; + + CError_BufferInit(&eb, buf, sizeof(buf)); + CError_BufferAppendNameSpace(&eb, nspace); + CError_BufferAppendString(&eb, name->name); + CError_BufferTerminate(&eb); + + ptr = lalloc(eb.size + 1); + return strcpy(ptr, eb.start); +} + +char *CError_GetFunctionName(NameSpace *nspace, HashNameNode *name, TypeFunc *tfunc) { + CErrorBuffer eb; + char buf[256]; + char *ptr; + + CError_BufferInit(&eb, buf, sizeof(buf)); + CError_AppendFunctionName(&eb, nspace, name, 0, tfunc); + CError_BufferTerminate(&eb); + + ptr = lalloc(eb.size + 1); + return strcpy(ptr, eb.start); +} + +char *CError_GetObjectName(Object *obj) { + CErrorBuffer eb; + char buf[256]; + char *ptr; + + CError_BufferInit(&eb, buf, sizeof(buf)); + CError_AppendObjectName(&eb, obj); + CError_BufferTerminate(&eb); + + ptr = lalloc(eb.size + 1); + return strcpy(ptr, eb.start); +} + +char *CError_GetNameString(NameSpace *nspace, HashNameNode *operatorName) { + CErrorBuffer eb; + char buf[256]; + char *ptr; + char *opStr; + + CError_ASSERT(973, operatorName); + + opStr = CMangler_GetOperator(operatorName); + if (!opStr) + opStr = operatorName->name; + + if (nspace && nspace->name) { + CError_BufferInit(&eb, buf, sizeof(buf)); + CError_BufferAppendNameSpace(&eb, nspace); + CError_BufferAppendString(&eb, opStr); + CError_BufferTerminate(&eb); + ptr = lalloc(eb.size + 1); + return strcpy(ptr, eb.start); + } else { + return opStr; + } +} + +void CError_ErrorMessage(int errTable, char *str, Boolean flag1, Boolean flag2) { + TStreamElement *token; + short tokensize; + CPrepFileInfo *tokenfile; + CWMessageRef myref; + char buf[128]; + CWMessageRef *ref; + unsigned char messagetype; + + if (CWDisplayLines(cparamblkptr->context, lines) != cwNoErr) + CError_UserBreak(); + + if (!in_assembler && !flag1 && cerror_lasterrorline == lines) { + if (cerror_errorcount++ >= 50) { + if (cerror_errorcount > 60) + longjmp(errorreturn, 1); + tk = lex(); + cerror_errorcount = 0; + if (tk == 0) { + CompilerGetCString(1, buf); + CWReportMessage(cparamblkptr->context, NULL, buf, NULL, messagetypeError, errTable); + longjmp(errorreturn, 1); + } + } + } else { + if (!flag2) { + cerror_lasterrorline = lines; + cerror_errorcount = 0; + } + if (copts.warningerrors) + flag2 = 0; + + if (cerror_token) + token = cerror_token; + else if (cerror_locktoken) + token = cerror_locktoken; + else + token = NULL; + //token = cerror_token ? cerror_token : cerror_locktoken ? cerror_locktoken : NULL; + if ((SInt32) token == -1) { + ref = NULL; + } else { + CPrep_GetTokenContext(token, &tokenfile, &myref.selectionoffset, &tokensize, &myref.linenumber, buf, &myref.tokenoffset, &myref.tokenlength, cerror_synchdata, &cerror_synchoffset); + myref.selectionlength = tokensize; + myref.sourcefile = tokenfile->textfile; + ref = &myref; + } + messagetype = flag2 ? messagetypeWarning : messagetypeError; + if (!flag2) { + anyerrors = 1; + fatalerrors = 1; + } + if (CWReportMessage(cparamblkptr->context, ref, str, buf, messagetype, errTable) != cwNoErr) + longjmp(errorreturn, 1); + } + + cerror_token = NULL; +} + +static void CError_BufferAppendTemplateStack(CErrorBuffer *eb) { + TemplStack *stack[64]; + TemplStack *scan; + int index; + int indent; + int count; + + scan = ctempl_curinstance; + for (count = 0; scan && count < 64; count++) { + stack[count] = scan; + scan = scan->next; + } + + for (index = count - 1; index >= 0; index--) { + CError_BufferAppendChar(eb, LF); + for (indent = index; indent < count; indent++) + CError_BufferAppendChar(eb, ' '); + CError_BufferAppendString(eb, "(instantiating: '"); + if (stack[index]->is_func) + CError_AppendObjectName(eb, stack[index]->u.func); + else + CError_BufferAppendType(eb, (Type *) stack[index]->u.theclass, 0); + CError_BufferAppendString(eb, "')"); + } + + CError_BufferTerminate(eb); +} + +void CError_ErrorMessageVA(int code, const char *format, va_list list, Boolean flag1, Boolean flag2) { + // register allocation is fucked, matches otherwise + CErrorBuffer eb; + char buf[256]; + char unmangleBuf[256]; + SInt32 moddate; + Type *type; + UInt32 qual; + const char *p; + CError_BufferInit(&eb, buf, sizeof(buf)); + + p = format; + do { + switch (p[0]) { + case 0: + break; + case '%': + switch (p[1]) { + case 'n': + MWUnmangle(va_arg(list, const char *), unmangleBuf, sizeof(unmangleBuf)); + CError_BufferAppendString(&eb, unmangleBuf); + p += 2; + continue; + case 'u': + CError_BufferAppendString(&eb, va_arg(list, const char *)); + p += 2; + continue; + case 'o': + CError_AppendObjectName(&eb, va_arg(list, Object *)); + p += 2; + continue; + case 'm': + CError_AppendMethodName(&eb, va_arg(list, ObjCMethod *)); + p += 2; + continue; + case 't': + type = va_arg(list, Type *); + qual = va_arg(list, UInt32); + CError_BufferAppendType(&eb, type, qual); + p += 2; + continue; + case '%': + CError_BufferAppendChar(&eb, '%'); + p += 2; + continue; + case 'i': + sprintf(unmangleBuf, "%" PRId32, va_arg(list, SInt32)); + CError_BufferAppendString(&eb, unmangleBuf); + p += 2; + continue; + case 'f': + CError_BufferAppendString(&eb, CTool_GetPathName(va_arg(list, FSSpec *), &moddate)->name); + p += 2; + continue; + default: + CError_FATAL(1174); + } + break; + default: + CError_BufferAppendChar(&eb, *(p++)); + continue; + } + break; + } while (1); + + CError_BufferAppendTemplateStack(&eb); + CError_ErrorMessage(code, eb.start, flag1, flag2); +} + +static void CError_VAErrorMessage(int code, va_list list, Boolean flag1, Boolean flag2) { + char buf[256]; + + CError_GetErrorString(buf, code); + CError_ErrorMessageVA(code + 10000, buf, list, flag1, flag2); +} + +void CError_Error(int code, ...) { + va_list va; + + if (trychain) + longjmp(trychain->jmpbuf, 1); + + va_start(va, code); + CError_VAErrorMessage(code, va, 0, 0); + va_end(va); + + if (in_assembler && !preprocessing_only) + AssemblerError(); +} + +void CError_ErrorTerm(short code) { + CError_GetErrorString(string, code); + CError_ErrorMessage(code + 10000, string, 0, 0); + longjmp(errorreturn, 1); +} + +void CError_ErrorSkip(int code, ...) { + va_list va; + + if (trychain) + longjmp(trychain->jmpbuf, 1); + + va_start(va, code); + CError_VAErrorMessage(code, va, 0, 0); + va_end(va); + + if (tk != ';' && tk != ')' && tk != '}' && tk != ',' && tk != ']') + tk = lex(); +} + +void CError_ErrorFuncCall(short code, NameSpaceObjectList *args, ENodeList *argNodes) { + // does not match - one branch has loop weirdness + CErrorBuffer eb; + char buf[256]; + char *p; + ENodeList *argscan; + + if (trychain) + longjmp(trychain->jmpbuf, 1); + + CError_GetErrorString(string, code); + CError_BufferInit(&eb, buf, sizeof(buf)); + + while (args && args->object->otype != OT_OBJECT) + args = args->next; + CError_ASSERT(1268, args); + + p = string; + do { + switch (*p) { + case 0: + goto exit_main_loop; + case '*': + if (OBJECT(args->object)->type->type == TYPEFUNC) { + CError_AppendUnqualFunctionName( + &eb, + OBJECT(args->object)->nspace, + OBJECT(args->object)->name, + TYPE_FUNC(OBJECT(args->object)->type)); + if (TYPE_FUNC(OBJECT(args->object)->type)->flags & FUNC_METHOD) + if (TYPE_FUNC(OBJECT(args->object)->type)->flags & FUNC_IS_CTOR) + if (TYPE_METHOD(OBJECT(args->object)->type)->theclass->flags & CLASS_HAS_VBASES) + if (argNodes) + argNodes = argNodes->next; + } else { + CError_BufferAppendString(&eb, OBJECT(args->object)->name->name); + } + CError_BufferAppendChar(&eb, '('); + argscan = argNodes; + while (argscan) { + CError_BufferAppendType(&eb, argscan->node->rtype, argscan->node->flags & ENODE_FLAG_QUALS); + if ((argscan = argscan->next)) + CError_BufferAppendString(&eb, ", "); + else + break; + } + CError_BufferAppendChar(&eb, ')'); + break; + default: + CError_BufferAppendChar(&eb, *p); + } + p++; + } while (1); + +exit_main_loop: + while (args) { + if (args->object->otype == OT_OBJECT) { + CError_BufferAppendChar(&eb, LF); + CError_BufferAppendChar(&eb, '\''); + CError_AppendObjectName(&eb, (Object *) args->object); + CError_BufferAppendChar(&eb, '\''); + } + args = args->next; + } + + CError_BufferAppendTemplateStack(&eb); + CError_ErrorMessage(10000 + code, eb.start, 0, 0); +} + +void CError_OverloadedFunctionError2(Object *obj, ObjectList *olst, ENodeList *argNodes) { + // not sure if the arg is actually ObjectList since it's never called lmao + NameSpaceObjectList first; + NameSpaceObjectList *current; + + first.object = (ObjBase *) obj; + current = &first; + while (olst) { + current->next = lalloc(sizeof(NameSpaceObjectList)); + current = current->next; + current->object = (ObjBase *) olst->object; + olst = olst->next; + } + current->next = NULL; + + CError_ErrorFuncCall(CErrorStr392, &first, argNodes); +} + +void CError_OverloadedFunctionError(Object *obj, ObjectList *olst) { + // not sure if this arg is ObjectList or NameSpaceObjectList + CErrorBuffer eb; + char buf[256]; + + if (trychain) + longjmp(trychain->jmpbuf, 1); + + CError_GetErrorString(string, CErrorStr199); + CError_BufferInit(&eb, buf, sizeof(buf)); + CError_BufferAppendString(&eb, string); + + if (obj) { + CError_BufferAppendChar(&eb, LF); + CError_BufferAppendChar(&eb, '\''); + CError_AppendObjectName(&eb, obj); + CError_BufferAppendChar(&eb, '\''); + } + while (olst) { + CError_BufferAppendChar(&eb, LF); + CError_BufferAppendChar(&eb, '\''); + CError_AppendObjectName(&eb, olst->object); + CError_BufferAppendChar(&eb, '\''); + olst = olst->next; + } + CError_BufferAppendTemplateStack(&eb); + CError_ErrorMessage(10199, eb.start, 0, 0); +} + +void CError_AbstractClassError(TypeClass *tclass) { + Object *result = CClass_CheckPures(tclass); + if (!result) + CError_Error(CErrorStr372, tclass, 0); + else + CError_Error(CErrorStr194, result); +} + +void CError_Warning(int code, ...) { + va_list va; + if (trychain || copts.supress_warnings) + return; + + va_start(va, code); + CError_VAErrorMessage(code, va, 0, 1); + va_end(va); +} + +void CError_BreakPoint(const char *a, const char *b) { + if (!a || !strcmp(a, b)) + CError_BreakPointcount++; +} + +void CError_Internal(char *filename, int line) { + char tmp[128]; + CompilerGetCString(5, tmp); + sprintf(string, tmp, filename, line); + CError_ErrorMessage(10001, string, 1, 0); + longjmp(errorreturn, 1); + CError_BreakPoint(0, 0); +} + +void CError_ExpressionTooComplex(void) { + CompilerGetCString(6, string); + CError_ErrorMessage(10002, string, 1, 0); + longjmp(errorreturn, 1); +} + +void CError_NoMem(void) { + cprep_nomem_exit = 1; + longjmp(errorreturn, 1); +} + +void CError_UserBreak(void) { + CompilerGetCString(8, string); + longjmp(errorreturn, 1); +} + +void CError_CannotOpen(void) { + CompilerGetCString(9, string); + CWReportMessage(cparamblkptr->context, NULL, string, NULL, messagetypeError, 0); + longjmp(errorreturn, 1); +} + +void CError_QualifierCheck(UInt32 qual) { + if (qual) { + Boolean anything = 0; + + if (qual & Q_CONST) { + CError_Error(CErrorStr313, "const"); + anything = 1; + } + if (qual & Q_VOLATILE) { + CError_Error(CErrorStr313, "volatile"); + anything = 1; + } + if (qual & Q_RESTRICT) { + CError_Error(CErrorStr313, "restrict"); + anything = 1; + } + if (qual & Q_ASM) { + CError_Error(CErrorStr313, "asm"); + anything = 1; + } + if (qual & Q_PASCAL) { + CError_Error(CErrorStr313, "pascal"); + anything = 1; + } + if (qual & Q_INLINE) { + CError_Error(CErrorStr313, "inline"); + anything = 1; + } + if (qual & Q_REFERENCE) { + CError_Error(CErrorStr313, "& reference type"); + anything = 1; + } + if (qual & Q_EXPLICIT) { + CError_Error(CErrorStr313, "explicit"); + anything = 1; + } + if (qual & Q_MUTABLE) { + CError_Error(CErrorStr313, "mutable"); + anything = 1; + } + if (qual & Q_VIRTUAL) { + CError_Error(CErrorStr313, "virtual"); + anything = 1; + } + if (qual & Q_FRIEND) { + CError_Error(CErrorStr313, "friend"); + anything = 1; + } + if (qual & Q_IN) { + CError_Error(CErrorStr313, "in"); + anything = 1; + } + if (qual & Q_OUT) { + CError_Error(CErrorStr313, "out"); + anything = 1; + } + if (qual & Q_INOUT) { + CError_Error(CErrorStr313, "inout"); + anything = 1; + } + if (qual & Q_BYCOPY) { + CError_Error(CErrorStr313, "bycopy"); + anything = 1; + } + if (qual & Q_BYREF) { + CError_Error(CErrorStr313, "byref"); + anything = 1; + } + if (qual & Q_ONEWAY) { + CError_Error(CErrorStr313, "oneway"); + anything = 1; + } + if (qual & Q_ALIGNED_MASK) { + CError_Error(CErrorStr313, "__attribute__((aligned(?)))"); + anything = 1; + } + + if (!anything) + CError_Error(CErrorStr176); + } +} diff --git a/compiler_and_linker/FrontEnd/C/CException.c b/compiler_and_linker/FrontEnd/C/CException.c new file mode 100644 index 0000000..d68ce13 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CException.c @@ -0,0 +1,2183 @@ +#include "compiler/CException.h" +#include "compiler/CABI.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInline.h" +#include "compiler/CInit.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/CompilerTools.h" +#include "compiler/Exceptions.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/types.h" + +typedef struct UniqueObj { + struct UniqueObj *next; + Object *object; + SInt32 uniqueid; +} UniqueObj; + +ExceptionAction *cexcept_dobjstack; +Boolean cexcept_hasdobjects; +Boolean cexcept_magic; +static UniqueObj *cexcept_uniqueobjs; +static Boolean cexcept_canthrow; +static DtorTemp *cexcept_dtortemps; +static Statement *cexcept_prevstmt; +static ExceptionAction *cexcept_eabefore; +static ExceptionAction *cexcept_eaafter; +static Boolean cexcept_expandtrycatch; +static Boolean cexcept_hastrycatch; +static Boolean cexcept_serialize; + +// forward decls +static ENode *CExcept_TempTransExprCond(ENode *expr); +static ENode *CExcept_TempTransExpr(ENode *expr); + +void CExcept_Setup(void) { + cexcept_dobjstack = NULL; + cexcept_uniqueobjs = NULL; + cexcept_hasdobjects = 0; + cexcept_magic = 0; +} + +Boolean CExcept_CanThrowException(Object *object, Boolean flag) { + if (copts.optEH && IS_TYPE_FUNC(object->type)) { + if (flag) + return 1; + + if (TYPE_FUNC(object->type)->flags & FUNC_NOTHROW) + return 0; + + if ( + !flag && + TYPE_FUNC(object->type)->exspecs && + TYPE_FUNC(object->type)->exspecs && + !TYPE_FUNC(object->type)->exspecs->type + ) + return 0; + + if ( + copts.optEH2 && + !(object->qual & Q_MANGLE_NAME) && + object != rt_ptmf_call && + object != rt_ptmf_scall && + object != Rdync_func && + object != rt_som_glue1 && + object != rt_som_glue2 && + object != rt_som_glue3 && + object != carr_func && + object != cnar_func && + object != darr_func && + object != dnar_func && + object != dnar3_func && + object != Xthrw_func + ) + return 0; + } + + return 1; +} + +void CExcept_CheckStackRefs(ExceptionAction *actions) { + while (actions) { + switch (actions->type) { + case EAT_DESTROYLOCAL: + CInline_ObjectAddrRef(actions->data.destroy_local.dtor); + break; + case EAT_DESTROYLOCALCOND: + CInline_ObjectAddrRef(actions->data.destroy_local_cond.dtor); + break; + case EAT_DESTROYLOCALOFFSET: + CInline_ObjectAddrRef(actions->data.destroy_local_offset.dtor); + break; + case EAT_DESTROYLOCALPOINTER: + CInline_ObjectAddrRef(actions->data.destroy_local_pointer.dtor); + break; + case EAT_DESTROYLOCALARRAY: + CInline_ObjectAddrRef(actions->data.destroy_local_array.dtor); + break; + case EAT_DESTROYPARTIALARRAY: + CInline_ObjectAddrRef(actions->data.destroy_partial_array.dtor); + break; + case EAT_DESTROYMEMBER: + case EAT_DESTROYBASE: + CInline_ObjectAddrRef(actions->data.destroy_member.dtor); + break; + case EAT_DESTROYMEMBERCOND: + CInline_ObjectAddrRef(actions->data.destroy_member_cond.dtor); + break; + case EAT_DESTROYMEMBERARRAY: + CInline_ObjectAddrRef(actions->data.destroy_member_array.dtor); + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + CInline_ObjectAddrRef(actions->data.delete_pointer.deletefunc); + break; + case EAT_DELETEPOINTERCOND: + CInline_ObjectAddrRef(actions->data.delete_pointer_cond.deletefunc); + break; + case EAT_CATCHBLOCK: + case EAT_ACTIVECATCHBLOCK: + case EAT_SPECIFICATION: + case EAT_TERMINATE: + break; + default: + CError_FATAL(192); + } + actions = actions->prev; + } +} + +void CExcept_CompareSpecifications(ExceptSpecList *a, ExceptSpecList *b) { + ExceptSpecList *aa; + ExceptSpecList *bb; + + aa = a; + bb = b; + while (1) { + if (!aa) { + if (!bb) + break; + CError_Error(CErrorStr265); + return; + } + + if (!bb) { + CError_Error(CErrorStr265); + return; + } + + aa = aa->next; + bb = bb->next; + } + + if (a->type == NULL) { + if (b->type != NULL) + CError_Error(CErrorStr265); + } else if (b->type == NULL) { + CError_Error(CErrorStr265); + } else { + for (aa = a; aa; aa = aa->next) { + for (bb = b; bb; bb = bb->next) { + if (is_typesame(aa->type, bb->type) && aa->qual == bb->qual) + break; + } + + if (bb == NULL) { + CError_Error(CErrorStr265); + return; + } + } + } +} + +Boolean CExcept_ActionCompare(ExceptionAction *a, ExceptionAction *b) { + if (a->type == b->type) { + switch (a->type) { + case EAT_DESTROYLOCAL: + return a->data.destroy_local.local == b->data.destroy_local.local; + case EAT_DESTROYLOCALCOND: + return a->data.destroy_local_cond.local == b->data.destroy_local_cond.local; + case EAT_DESTROYLOCALOFFSET: + return a->data.destroy_local_offset.local == b->data.destroy_local_offset.local && + a->data.destroy_local_offset.offset == b->data.destroy_local_offset.offset; + case EAT_DESTROYLOCALPOINTER: + return a->data.destroy_local_pointer.pointer == b->data.destroy_local_pointer.pointer; + case EAT_DESTROYLOCALARRAY: + return a->data.destroy_local_array.localarray == b->data.destroy_local_array.localarray; + case EAT_DESTROYPARTIALARRAY: + return a->data.destroy_partial_array.arraypointer == b->data.destroy_partial_array.arraypointer; + case EAT_DESTROYMEMBER: + case EAT_DESTROYBASE: + return a->data.destroy_member.objectptr == b->data.destroy_member.objectptr && + a->data.destroy_member.offset == b->data.destroy_member.offset; + case EAT_DESTROYMEMBERCOND: + return a->data.destroy_member_cond.objectptr == b->data.destroy_member_cond.objectptr && + a->data.destroy_member_cond.offset == b->data.destroy_member_cond.offset; + case EAT_DESTROYMEMBERARRAY: + return a->data.destroy_member_array.objectptr == b->data.destroy_member_array.objectptr && + a->data.destroy_member_array.offset == b->data.destroy_member_array.offset; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + return a->data.delete_pointer.pointerobject == b->data.delete_pointer.pointerobject && + a->data.delete_pointer.deletefunc == b->data.delete_pointer.deletefunc; + case EAT_DELETEPOINTERCOND: + return a->data.delete_pointer_cond.cond == b->data.delete_pointer_cond.cond; + case EAT_CATCHBLOCK: + return a->data.catch_block.catch_label == b->data.catch_block.catch_label; + case EAT_ACTIVECATCHBLOCK: + return a->data.active_catch_block.catch_info_object == b->data.active_catch_block.catch_info_object; + case EAT_TERMINATE: + return 1; + case EAT_SPECIFICATION: + return a->data.specification.unexp_id == b->data.specification.unexp_id; + default: + CError_FATAL(314); + } + } + + return 0; +} + +int CExcept_IsSubList(ExceptionAction *a, ExceptionAction *b) { + int diff; + int i; + int count1; + int count2; + ExceptionAction *scan; + + if (a == b) + return 0; + + count1 = 0; + scan = a; + while (scan) { + scan = scan->prev; + count1++; + } + + scan = b; + count2 = 0; + while (scan) { + scan = scan->prev; + count2++; + } + + diff = count2 - count1; + if (diff < 0) + return -1; + + for (i = 0; i < diff; i++) + b = b->prev; + + while (a != b) { + if (!a || !b || !CExcept_ActionCompare(a, b)) + return -1; + a = a->prev; + b = b->prev; + } + + return diff; +} + +Boolean CExcept_ActionNeedsDestruction(ExceptionAction *action) { + switch (action->type) { + case EAT_CATCHBLOCK: + return 0; + case EAT_DESTROYLOCAL: + case EAT_DESTROYLOCALOFFSET: + case EAT_DESTROYLOCALARRAY: + case EAT_DELETELOCALPOINTER: + case EAT_ACTIVECATCHBLOCK: + return 1; + case EAT_NOP: + case EAT_DESTROYMEMBER: + case EAT_DESTROYMEMBERCOND: + case EAT_DESTROYMEMBERARRAY: + case EAT_DESTROYBASE: + break; + default: + CError_FATAL(363); + } + + return 0; +} + +ENode *CExcept_RegisterDestructorObject(Object *local, SInt32 offset, Object *dtor, Boolean flag) { + ExceptionAction *action; + ENode *expr; + Object *dtorObject; + + action = lalloc(sizeof(ExceptionAction)); + memclrw(action, sizeof(ExceptionAction)); + + action->prev = cexcept_dobjstack; + cexcept_dobjstack = action; + + expr = create_objectrefnode(local); + dtorObject = CABI_GetDestructorObject(dtor, CABIDestroy1); + + if (offset == 0) { + action->type = EAT_DESTROYLOCAL; + action->data.destroy_local.local = local; + action->data.destroy_local.dtor = dtorObject; + } else { + action->type = EAT_DESTROYLOCALOFFSET; + action->data.destroy_local_offset.local = local; + action->data.destroy_local_offset.dtor = dtorObject; + action->data.destroy_local_offset.offset = offset; + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); + } + + cexcept_hasdobjects = 1; + return expr; +} + +void CExcept_RegisterLocalArray(Statement *stmt, Object *localarray, Object *dtor, SInt32 elements, SInt32 element_size) { + ExceptionAction *action; + Object *dtorObject; + + action = lalloc(sizeof(ExceptionAction)); + memclrw(action, sizeof(ExceptionAction)); + + action->prev = cexcept_dobjstack; + cexcept_dobjstack = action; + + dtorObject = CABI_GetDestructorObject(dtor, CABIDestroy1); + + action->type = EAT_DESTROYLOCALARRAY; + action->data.destroy_local_array.localarray = localarray; + action->data.destroy_local_array.dtor = dtorObject; + action->data.destroy_local_array.elements = elements; + action->data.destroy_local_array.element_size = element_size; + + cexcept_hasdobjects = 1; +} + +void CExcept_RegisterDeleteObject(Statement *stmt, Object *pointerobject, Object *deletefunc) { + ExceptionAction *action; + + action = lalloc(sizeof(ExceptionAction)); + memclrw(action, sizeof(ExceptionAction)); + + action->prev = cexcept_dobjstack; + cexcept_dobjstack = action; + + action->type = EAT_DELETELOCALPOINTER; + action->data.delete_pointer.pointerobject = pointerobject; + action->data.delete_pointer.deletefunc = deletefunc; + + cexcept_hasdobjects = 1; +} + +static void CExcept_PatchConstructorAction(Statement *stmt, ExceptionAction *actionArg) { + ExceptionAction *action30; + ExceptionAction *action; + ExceptionAction *scan; + + for (action = stmt->dobjstack; action; action = action->prev) { + switch (action->type) { + case EAT_DESTROYMEMBER: + case EAT_DESTROYMEMBERCOND: + case EAT_DESTROYMEMBERARRAY: + case EAT_SPECIFICATION: + case EAT_DESTROYBASE: + goto exitFirstLoop; + case EAT_CATCHBLOCK: + action30 = action; + while (1) { + if (!action30->prev) + goto exitFirstLoop; + action30 = action30->prev; + if (action30->type != EAT_CATCHBLOCK) { + CError_FATAL(481); + } + } + } + } + exitFirstLoop: + if (action == NULL) { + while (stmt) { + if ((scan = stmt->dobjstack)) { + while (1) { + if (scan == actionArg) + break; + if (scan->prev == NULL) { + scan->prev = actionArg; + break; + } + scan = scan->prev; + } + } else { + stmt->dobjstack = actionArg; + } + stmt = stmt->next; + } + } else { + actionArg->prev = action; + while (stmt) { + if (stmt->dobjstack != action) { + scan = stmt->dobjstack; + do { + if (scan == actionArg) + goto nextStmt; + if (scan->prev == action) { + scan->prev = actionArg; + goto nextStmt; + } + } while ((scan = scan->prev)); + + while (1) { + if (action->type == EAT_CATCHBLOCK && action->prev == NULL) + return; + + action = action->prev; + if (!action) + CError_FATAL(531); + } + } else { + stmt->dobjstack = actionArg; + } + nextStmt: + stmt = stmt->next; + } + } +} + +void CExcept_Terminate(void) { + ExceptionAction *action; + + action = lalloc(sizeof(ExceptionAction)); + memclrw(action, sizeof(ExceptionAction)); + + action->type = EAT_TERMINATE; + + action->prev = cexcept_dobjstack; + cexcept_dobjstack = action; +} + +void CExcept_Magic(void) { + cexcept_magic = 1; +} + +static Object *CExcept_FindLocalObject(char *name) { + NameResult result; + NameSpaceObjectList *list; + + list = CScope_FindObjectList(&result, GetHashNameNodeExport(name)); + if (list && list->object->otype == OT_OBJECT && OBJECT(list->object)->datatype == DLOCAL) + return OBJECT(list->object); + + CError_FATAL(580); + return NULL; +} + +void CExcept_ArrayInit(void) { + ExceptionAction *action; + + action = lalloc(sizeof(ExceptionAction)); + memclrw(action, sizeof(ExceptionAction)); + + action->type = EAT_DESTROYPARTIALARRAY; + action->data.destroy_partial_array.arraypointer = CExcept_FindLocalObject("ptr"); + action->data.destroy_partial_array.arraycounter = CExcept_FindLocalObject("i"); + action->data.destroy_partial_array.dtor = CExcept_FindLocalObject("dtor"); + action->data.destroy_partial_array.element_size = CExcept_FindLocalObject("size"); + + action->prev = cexcept_dobjstack; + cexcept_dobjstack = action; +} + +void CExcept_RegisterMember(Statement *stmt, Object *objectptr, SInt32 offset, Object *dtor, Object *cond, Boolean isMember) { + ExceptionAction *action; + + action = lalloc(sizeof(ExceptionAction)); + memclrw(action, sizeof(ExceptionAction)); + + if (cond == NULL) { + if (isMember) { + action->type = EAT_DESTROYMEMBER; + action->data.destroy_member.dtor = CABI_GetDestructorObject(dtor, CABIDestroy1); + } else { + action->type = EAT_DESTROYBASE; + action->data.destroy_member.dtor = CABI_GetDestructorObject(dtor, CABIDestroy0); + } + action->data.destroy_member.objectptr = objectptr; + action->data.destroy_member.offset = offset; + } else { + CError_ASSERT(632, cond->type == TYPE(&stsignedshort)); + action->type = EAT_DESTROYMEMBERCOND; + action->data.destroy_member_cond.objectptr = objectptr; + action->data.destroy_member_cond.cond = cond; + action->data.destroy_member_cond.dtor = CABI_GetDestructorObject(dtor, CABIDestroy1); + action->data.destroy_member_cond.offset = offset; + } + + CExcept_PatchConstructorAction(stmt, action); + stmt->flags |= StmtFlag_2; +} + +void CExcept_RegisterMemberArray(Statement *stmt, Object *objectptr, SInt32 offset, Object *dtor, SInt32 elements, SInt32 element_size) { + ExceptionAction *action; + + action = lalloc(sizeof(ExceptionAction)); + memclrw(action, sizeof(ExceptionAction)); + + action->type = EAT_DESTROYMEMBERARRAY; + action->data.destroy_member_array.objectptr = objectptr; + action->data.destroy_member_array.dtor = CABI_GetDestructorObject(dtor, CABIDestroy1); + action->data.destroy_member_array.offset = offset; + action->data.destroy_member_array.elements = elements; + action->data.destroy_member_array.element_size = element_size; + + CExcept_PatchConstructorAction(stmt, action); + stmt->flags |= StmtFlag_2; +} + +static Statement *CExcept_DestroyLocal(ExceptionAction *ea, Statement *stmt, Object *object, Object *dtor, SInt32 offset) { + ENode *expr; + + expr = create_objectrefnode(object); + if (offset) + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); + + expr = CABI_DestroyObject(dtor, expr, CABIDestroy1, 1, 0); + + CError_ASSERT(687, expr->type == EFUNCCALL && expr->data.funccall.funcref->type == EOBJREF); + if (expr->data.funccall.funcref->data.objref->datatype == DVFUNC) + expr->data.funccall.funcref->flags |= ENODE_FLAG_80; + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = expr; + stmt->dobjstack = ea->prev; + return stmt; +} + +static Statement *CExcept_DestroyLocalPointer(ExceptionAction *ea, Statement *stmt, Object *object, Object *deletefunc) { + Statement *newStmt; + + newStmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + newStmt->expr = funccallexpr(deletefunc, create_objectnode2(object), NULL, NULL, NULL); + newStmt->dobjstack = ea->prev; + return newStmt; +} + +static Statement *CExcept_DestroyLocalArray(ExceptionAction *ea, Statement *stmt, Object *object, Object *dtor, SInt32 elements, SInt32 element_size) { + Statement *newStmt; + ENode *dtorExpr; + + newStmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + + if (dtor) + dtorExpr = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1)); + else + dtorExpr = nullnode(); + + newStmt->expr = funccallexpr( + darr_func, + create_objectrefnode(object), + dtorExpr, + intconstnode(TYPE(&stunsignedlong), element_size), + intconstnode(TYPE(&stunsignedlong), elements) + ); + + newStmt->dobjstack = ea->prev; + return newStmt; +} + +static Statement *CExcept_EndCatch(ExceptionAction *ea, Statement *stmt) { + stmt = CFunc_InsertStatement(ST_ENDCATCHDTOR, stmt); + stmt->expr = create_objectrefnode(ea->data.active_catch_block.catch_info_object); + stmt->dobjstack = ea->prev; + if (!ea->data.active_catch_block.call_dtor) + stmt->type = ST_ENDCATCH; + return stmt; +} + +Statement *CExcept_ActionCleanup(ExceptionAction *ea, Statement *stmt) { + switch (ea->type) { + case EAT_DESTROYLOCALCOND: + case EAT_DESTROYLOCALPOINTER: + case EAT_DESTROYPARTIALARRAY: + case EAT_DESTROYMEMBER: + case EAT_DESTROYMEMBERCOND: + case EAT_DESTROYMEMBERARRAY: + case EAT_DELETEPOINTER: + case EAT_DELETEPOINTERCOND: + case EAT_CATCHBLOCK: + case EAT_SPECIFICATION: + case EAT_TERMINATE: + case EAT_DESTROYBASE: + break; + case EAT_DESTROYLOCAL: + stmt = CExcept_DestroyLocal( + ea, stmt, + ea->data.destroy_local.local, + ea->data.destroy_local.dtor, + 0); + break; + case EAT_DESTROYLOCALOFFSET: + stmt = CExcept_DestroyLocal( + ea, stmt, + ea->data.destroy_local.local, + ea->data.destroy_local.dtor, + ea->data.destroy_local_offset.offset); + break; + case EAT_DELETELOCALPOINTER: + stmt = CExcept_DestroyLocalPointer( + ea, stmt, + ea->data.delete_pointer.pointerobject, + ea->data.delete_pointer.deletefunc); + break; + case EAT_DESTROYLOCALARRAY: + stmt = CExcept_DestroyLocalArray( + ea, stmt, + ea->data.destroy_local_array.localarray, + ea->data.destroy_local_array.dtor, + ea->data.destroy_local_array.elements, + ea->data.destroy_local_array.element_size); + break; + case EAT_ACTIVECATCHBLOCK: + stmt = CExcept_EndCatch(ea, stmt); + break; + default: + CError_FATAL(827); + } + + return stmt; +} + +static void CExcept_MangleNameSpaceName(NameSpace *nspace) { + while (nspace) { + if (nspace->name) { + CExcept_MangleNameSpaceName(nspace->parent); + AppendGListName(&name_mangle_list, nspace->name->name); + AppendGListName(&name_mangle_list, "::"); + break; + } + nspace = nspace->parent; + } +} + +static void CExcept_MangleClassName(TypeClass *tclass) { + NameSpace *nspace; + char buf[64]; + + CExcept_MangleNameSpaceName(tclass->nspace->parent); + AppendGListName(&name_mangle_list, tclass->classname->name); + + for (nspace = tclass->nspace->parent; nspace; nspace = nspace->parent) { + if (!nspace->is_global && !nspace->is_templ && !nspace->name) { + CError_ASSERT(868, cscope_currentfunc != NULL); + + sprintf(buf, "*%" PRIxPTR "*%" PRIxPTR "*", &cscope_currentfunc, &nspace); + AppendGListName(&name_mangle_list, buf); + break; + } + } +} + +typedef struct BCL { + struct BCL *next; + TypeClass *tclass; + SInt32 offset; + Boolean is_virtual; + Boolean is_public; + Boolean is_ambig; +} BCL; + +static void CExcept_MakeBaseClassListAmbig(BCL *bcl, TypeClass *tclass) { + BCL *scan; + ClassList *list; + + for (scan = bcl; scan; scan = scan->next) { + if (scan->tclass == tclass) + scan->is_ambig = 1; + } + + for (list = tclass->bases; list; list = list->next) + CExcept_MakeBaseClassListAmbig(bcl, list->base); +} + +static BCL *CExcept_GetBaseClassList(BCL *bcl, TypeClass *tclass1, TypeClass *tclass2, SInt32 offset, Boolean is_virtual, Boolean is_public) { + BCL *node; + ClassList *base; + Boolean new_is_public; + + for (node = bcl; node; node = node->next) { + if (node->tclass == tclass2) { + if (is_virtual && node->is_virtual) { + if (is_public) + node->is_public = 1; + } else { + CExcept_MakeBaseClassListAmbig(bcl, tclass2); + } + return bcl; + } + } + + node = lalloc(sizeof(BCL)); + node->tclass = tclass2; + node->offset = offset; + node->is_virtual = is_virtual; + node->is_public = is_public; + node->is_ambig = 0; + node->next = bcl; + bcl = node; + + for (base = tclass2->bases; base; base = base->next) { + new_is_public = is_public && (base->access == ACCESSPUBLIC); + bcl = base->is_virtual + ? CExcept_GetBaseClassList(bcl, tclass1, base->base, CClass_VirtualBaseOffset(tclass1, base->base), 1, new_is_public) + : CExcept_GetBaseClassList(bcl, tclass1, base->base, offset + base->offset, 0, new_is_public); + } + + return bcl; +} + +static void CExcept_MangleClass(TypeClass *tclass) { + BCL *bcl; + char buf[20]; + + for (bcl = CExcept_GetBaseClassList(NULL, tclass, tclass, 0, 0, 1); bcl; bcl = bcl->next) { + if (bcl->is_public && !bcl->is_ambig) { + CExcept_MangleClassName(bcl->tclass); + AppendGListByte(&name_mangle_list, '!'); + + if (bcl->offset) { + sprintf(buf, "%" PRId32 "!", bcl->offset); + AppendGListName(&name_mangle_list, buf); + } else { + AppendGListByte(&name_mangle_list, '!'); + } + } + } +} + +static ENode *CExcept_GetTypeID(Type *type, UInt32 qual, Boolean flag) { + ENode *expr; + TypePointer my_tptr; + + if (IS_TYPE_REFERENCE(type)) + type = TPTR_TARGET(type); + + if (IS_TYPE_CLASS(type) || (IS_TYPE_POINTER_ONLY(type) && IS_TYPE_CLASS(TPTR_TARGET(type)))) { + name_mangle_list.size = 0; + if (IS_TYPE_POINTER_ONLY(type)) { + AppendGListByte(&name_mangle_list, '*'); + type = TPTR_TARGET(type); + } else { + AppendGListByte(&name_mangle_list, '!'); + } + + if (flag) { + CExcept_MangleClass(TYPE_CLASS(type)); + } else { + CExcept_MangleClassName(TYPE_CLASS(type)); + AppendGListByte(&name_mangle_list, '!'); + } + } else { + if (IS_TYPE_POINTER_ONLY(type)) { + if (TPTR_QUAL(type) & (Q_CONST | Q_VOLATILE)) { + my_tptr = *TYPE_POINTER(type); + my_tptr.qual = 0; + type = TYPE(&my_tptr); + } + } else { + qual = 0; + } + CMangler_MangleType(type, qual); + } + + AppendGListByte(&name_mangle_list, 0); + + expr = CExpr_NewENode(ESTRINGCONST); + expr->rtype = CDecl_NewPointerType(TYPE(&stchar)); + expr->data.string.size = name_mangle_list.size; + expr->data.string.data = galloc(name_mangle_list.size); + memcpy(expr->data.string.data, *name_mangle_list.data, name_mangle_list.size); + return expr; +} + +static Object *CExcept_TypeID(Type *type, UInt32 qual) { + ENode *expr = CExcept_GetTypeID(type, qual, 0); + CError_ASSERT(1086, expr->type == ESTRINGCONST); + return CInit_DeclareString(expr->data.string.data, expr->data.string.size, 0, 0); +} + +void CExcept_ScanExceptionSpecification(TypeFunc *tfunc) { + ExceptSpecList *exspecs; + ExceptSpecList *exspec; + DeclInfo di; + + exspecs = NULL; + + if (lex() != '(') { + CError_Error(CErrorStr114); + return; + } + + if ((tk = lex()) != ')') { + while (1) { + memclrw(&di, sizeof(di)); + CParser_GetDeclSpecs(&di, 0); + if (di.storageclass) + CError_Error(CErrorStr177); + + CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_ALIGNED_MASK)); + + scandeclarator(&di); + if (di.name) + CError_Error(CErrorStr146); + + if (IS_TYPE_POINTER_ONLY(di.thetype)) { + if (TPTR_QUAL(di.thetype) & (Q_CONST | Q_VOLATILE)) { + TypePointer *newtype = galloc(sizeof(TypePointer)); + *newtype = *TYPE_POINTER(di.thetype); + newtype->qual = 0; + di.thetype = TYPE(newtype); + } + } else { + di.qual = 0; + } + + for (exspec = exspecs; exspec; exspec = exspec->next) { + if (is_typesame(exspec->type, di.thetype) && exspec->qual == di.qual) + break; + } + + if (!exspec) { + exspec = galloc(sizeof(ExceptSpecList)); + memclrw(exspec, sizeof(ExceptSpecList)); + exspec->next = exspecs; + exspec->type = di.thetype; + exspec->qual = di.qual; + exspecs = exspec; + } + + if (tk == ')') + break; + + if (tk != ',') { + CError_Error(CErrorStr115); + break; + } + + tk = lex(); + } + } + + if (!exspecs) { + exspecs = galloc(sizeof(ExceptSpecList)); + memclrw(exspecs, sizeof(ExceptSpecList)); + } + tfunc->exspecs = exspecs; + tk = lex(); +} + +static ENode *CExcept_CallCopyCtor(Object *object, Type *type, ENode *expr1, ENode *expr2) { + ENodeList *list; + ENode *expr; + FuncArg *arg; + + if ( + !IS_TYPE_FUNC(object->type) || + !(arg = TYPE_FUNC(object->type)->args) || + !(arg = arg->next) + ) + CError_FATAL(1169); + + expr = funccallexpr(object, expr1, NULL, NULL, NULL); + list = expr->data.funccall.args; + + if (TYPE_CLASS(type)->flags & CLASS_HAS_VBASES) { + CError_ASSERT(1179, arg = arg->next); + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->next = NULL; + list->node = intconstnode(TYPE(&stsignedshort), 1); + } + + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->next = NULL; + list->node = expr2; + + while ((arg = arg->next)) { + CError_ASSERT(1195, arg->dexpr); + + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->next = NULL; + list->node = CExpr_GetDefaultArgument(expr->data.funccall.funcref, arg); + } + + return expr; +} + +ENode *CExcept_ScanThrowExpression(void) { + ENode *expr; + Object *func; + ENode *resultExpr; + Object *obj; + ENode *thrownExpr; + ENode *tempExpr; + + if (!copts.exceptions) + CError_Error(CErrorStr252); + + switch ((tk = lex())) { + case ')': + case ',': + case ':': + case ';': + expr = funccallexpr(Xthrw_func, nullnode(), nullnode(), nullnode(), NULL); + break; + default: + thrownExpr = pointer_generation(assignment_expression()); + obj = create_temp_object(thrownExpr->rtype); + if (!IS_TYPE_CLASS(thrownExpr->rtype) || !(resultExpr = CExpr_IsTempConstruction(thrownExpr, thrownExpr->rtype, &expr))) { + tempExpr = create_objectrefnode(obj); + if (IS_TYPE_CLASS(thrownExpr->rtype) && (func = CClass_CopyConstructor(TYPE_CLASS(thrownExpr->rtype)))) { + resultExpr = CExcept_CallCopyCtor(func, thrownExpr->rtype, tempExpr, getnodeaddress(thrownExpr, 0)); + } else { + if (thrownExpr->rtype->size == 0) + CError_Error(CErrorStr146); + + tempExpr = makemonadicnode(tempExpr, EINDIRECT); + tempExpr->rtype = thrownExpr->rtype; + resultExpr = makediadicnode(tempExpr, thrownExpr, EASS); + resultExpr = makediadicnode(resultExpr, create_objectrefnode(obj), ECOMMA); + resultExpr->rtype = TYPE(&void_ptr); + } + } else { + *expr = *create_objectrefnode(obj); + } + + expr = CExcept_GetTypeID(thrownExpr->rtype, ENODE_QUALS(thrownExpr), 1); + if (IS_TYPE_CLASS(thrownExpr->rtype) && (func = CClass_Destructor(TYPE_CLASS(thrownExpr->rtype)))) { + expr = funccallexpr( + Xthrw_func, + expr, + resultExpr, + create_objectrefnode(CABI_GetDestructorObject(func, CABIDestroy1)), + NULL); + } else { + expr = funccallexpr( + Xthrw_func, + expr, + resultExpr, + nullnode(), + NULL); + } + } + + expr->flags |= ENODE_FLAG_VOLATILE; + return expr; +} + +static Boolean CExcept_MightNeedDtor(Type *type) { + if (type) { + if (IS_TYPE_CLASS(type)) { + if (!CClass_Destructor(TYPE_CLASS(type))) + return 0; + } else if (IS_TYPE_POINTER_ONLY(type)) { + if (!(TPTR_QUAL(type) & Q_REFERENCE) || !IS_TYPE_CLASS(TPTR_TARGET(type))) + return 0; + } else { + return 0; + } + } + + return 1; +} + +typedef struct CatchBlock { + struct CatchBlock *next; + Object *catch_object; + Object *catch_info_object; + Statement *stmt; + Statement *anotherStmt; + Type *type; + UInt32 qual; +} CatchBlock; + +static void CExcept_PatchDObjStack(Statement *beginCatchStmt, Statement *tryEndStmt, Statement *endStmt, CatchBlock *catchBlock) { + ExceptionAction *ea; + ExceptionAction *stackHead; + ExceptionAction *stackTail; + ExceptionAction *firstEA; + Statement *stmt; + Object *catch_info_object; + Boolean call_dtor; + + catch_info_object = catchBlock->catch_info_object; + call_dtor = 0; + stackHead = stackTail = beginCatchStmt->dobjstack; + firstEA = NULL; + + while (catchBlock) { + ea = lalloc(sizeof(ExceptionAction)); + memclrw(ea, sizeof(ExceptionAction)); + + ea->prev = stackTail; + stackTail = ea; + + if (!firstEA) + firstEA = ea; + + ea->type = EAT_CATCHBLOCK; + ea->data.catch_block.catch_object = catchBlock->catch_object; + ea->data.catch_block.catch_label = catchBlock->stmt->label; + if (catchBlock->type) + ea->data.catch_block.catch_typeid = CExcept_TypeID(catchBlock->type, catchBlock->qual); + ea->data.catch_block.catch_info_object = catch_info_object; + + if (!call_dtor && CExcept_MightNeedDtor(catchBlock->type)) + call_dtor = 1; + + ea->data.catch_block.catch_type = catchBlock->type; + ea->data.catch_block.catch_qual = catchBlock->qual; + catchBlock = catchBlock->next; + } + + stmt = beginCatchStmt; + while (1) { + if ((ea = stmt->dobjstack) != stackHead) { + while (1) { + CError_ASSERT(1404, ea); + if (ea->prev == stackTail) + break; + if (ea->prev == stackHead) { + ea->prev = stackTail; + break; + } + ea = ea->prev; + } + } else { + stmt->dobjstack = stackTail; + } + + if (stmt == endStmt) + break; + + if (stmt == tryEndStmt) { + ea = lalloc(sizeof(ExceptionAction)); + memclrw(ea, sizeof(ExceptionAction)); + ea->prev = stackHead; + ea->type = EAT_ACTIVECATCHBLOCK; + ea->data.active_catch_block.catch_info_object = catch_info_object; + ea->data.active_catch_block.call_dtor = call_dtor; + stackTail = ea; + } + + stmt = stmt->next; + CError_ASSERT(1426, stmt); + } + + cexcept_hasdobjects = 1; +} + +static void CExcept_CheckTryObjects(ENode *expr) { + if (expr->data.objref->datatype == DLOCAL && expr->data.objref->u.var.info) + expr->data.objref->u.var.info->noregister = 1; +} + +static ENode *CExcept_CatchExpressionInit(DeclInfo *di, CatchBlock *catchBlock) { + Object *catch_object; + Object *copyCtor; + Object *dtor; + ENode *expr; + + if (CScope_FindName(cscope_current, di->name)) + CError_Error(CErrorStr122, di->name->name); + + catch_object = CParser_NewLocalDataObject(di, 1); + CFunc_SetupLocalVarInfo(catch_object); + CScope_AddObject(cscope_current, di->name, OBJ_BASE(catch_object)); + catchBlock->catch_object = catch_object; + + expr = makediadicnode( + create_objectrefnode(catchBlock->catch_info_object), + intconstnode(TYPE(&stunsignedlong), 12), + EADD); + expr->rtype = CDecl_NewPointerType(CDecl_NewPointerType(di->thetype)); + + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = CDecl_NewPointerType(di->thetype); + + if (IS_TYPE_REFERENCE(di->thetype)) + return makediadicnode(create_objectnode2(catch_object), expr, EASS); + + if (IS_TYPE_CLASS(di->thetype) && (copyCtor = CClass_CopyConstructor(TYPE_CLASS(di->thetype)))) { + dtor = CClass_Destructor(TYPE_CLASS(di->thetype)); + return CExcept_CallCopyCtor( + copyCtor, + di->thetype, + (dtor == NULL) ? create_objectrefnode(catch_object) : CExcept_RegisterDestructorObject(catch_object, 0, dtor, 0), + expr); + } + + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = di->thetype; + return makediadicnode(create_objectnode(catch_object), expr, EASS); +} + +void CExcept_ScanTryBlock(DeclThing *dt, Boolean flag) { + Object *catch_info_object; // r27 + Statement *beginCatchStmt; // r14 + Statement *tryEndStmt; // r16 + Statement *endStmt; // r17 + Statement *stmt; // r14 + CLabel *catchEndLabel; // r19 + CLabel *endLabel; // r24 + CatchBlock *catchStack; // r23 + CatchBlock *catchBlock; // r22 + DeclBlock *declBlock; // r20 + DeclInfo di; + + if (!copts.exceptions) + CError_Error(CErrorStr252); + + catch_info_object = create_temp_object(TYPE(&catchinfostruct)); + if (cexcept_magic) { + catch_info_object->name = GetHashNameNodeExport("__exception_magic"); + CScope_AddObject(cscope_current, catch_info_object->name, OBJ_BASE(catch_info_object)); + } + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->flags = StmtFlag_1; + stmt->label = newlabel(); + stmt->label->stmt = stmt; + + beginCatchStmt = CFunc_AppendStatement(ST_BEGINCATCH); + beginCatchStmt->expr = create_objectrefnode(catch_info_object); + + if (tk != '{') { + CError_Error(CErrorStr135); + return; + } + + CFunc_CompoundStatement(dt); + + if (tk != TK_CATCH) { + CError_Error(CErrorStr242); + return; + } + + stmt = CFunc_AppendStatement(ST_GOTO); + catchEndLabel = stmt->label = newlabel(); + tryEndStmt = stmt; + + endLabel = newlabel(); + catchStack = NULL; + + while (1) { + CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->flags = StmtFlag_1; + stmt->label = newlabel(); + stmt->label->stmt = stmt; + + declBlock = NULL; + + catchBlock = lalloc(sizeof(ExceptionAction)); + memclrw(catchBlock, sizeof(ExceptionAction)); + catchBlock->next = catchStack; + catchStack = catchBlock; + + catchBlock->stmt = stmt; + catchBlock->catch_info_object = catch_info_object; + + if ((tk = lex()) != '(') { + CError_Error(CErrorStr114); + break; + } + + if ((tk = lex()) == TK_ELLIPSIS) { + tk = lex(); + } else { + memclrw(&di, sizeof(di)); + CParser_GetDeclSpecs(&di, 0); + + if (di.x48) + CError_Error(CErrorStr121); + if (di.storageclass) + CError_Error(CErrorStr177); + + CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_ALIGNED_MASK)); + + scandeclarator(&di); + + if (IS_TYPE_FUNC(di.thetype)) + di.thetype = CDecl_NewPointerType(di.thetype); + else if (IS_TYPE_ARRAY(di.thetype)) + di.thetype = CDecl_NewPointerType(TPTR_TARGET(di.thetype)); + + IsCompleteType(di.thetype); + if (IS_TYPE_CLASS(di.thetype) && (TYPE_CLASS(di.thetype)->flags & CLASS_ABSTRACT)) + CError_AbstractClassError(TYPE_CLASS(di.thetype)); + + catchBlock->type = di.thetype; + catchBlock->qual = di.qual; + + if (di.name) { + ENode *expr; + declBlock = CFunc_NewDeclBlock(); + expr = CExcept_CatchExpressionInit(&di, catchBlock); + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = expr; + } + } + + if (tk != ')') { + CError_Error(CErrorStr115); + break; + } + + if ((tk = lex()) != '{') { + CError_Error(CErrorStr123); + break; + } + + CFunc_CompoundStatement(dt); + if (flag) { + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = funccallexpr(Xthrw_func, nullnode(), nullnode(), nullnode(), NULL); + } + + catchBlock->anotherStmt = stmt; + + if (declBlock) + CFunc_RestoreBlock(declBlock); + + if (tk != TK_CATCH) + break; + + CFunc_AppendStatement(ST_GOTO)->label = endLabel; + } + + endStmt = CFunc_AppendStatement(ST_LABEL); + endStmt->label = endLabel; + endLabel->stmt = endStmt; + + CExcept_PatchDObjStack(beginCatchStmt, tryEndStmt, endStmt, catchBlock); + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = catchEndLabel; + catchEndLabel->stmt = stmt; +} + +static Statement *CExcept_InsertPrevStatement(StatementType sttype) { + Statement *stmt = CFunc_InsertStatement(sttype, cexcept_prevstmt); + stmt->sourceoffset = stmt->next->sourceoffset; + stmt->sourcefilepath = stmt->next->sourcefilepath; + stmt->dobjstack = cexcept_eabefore; + return stmt; +} + +static Object *CExcept_GetETEMPObject(ENode *expr) { + UniqueObj *uobj; + SInt32 id; + + if ((id = expr->data.temp.uniqueid)) { + for (uobj = cexcept_uniqueobjs; uobj; uobj = uobj->next) { + if (uobj->uniqueid == id) + return uobj->object; + } + + uobj = galloc(sizeof(UniqueObj)); + uobj->next = cexcept_uniqueobjs; + cexcept_uniqueobjs = uobj; + uobj->uniqueid = id; + return (uobj->object = create_temp_object(expr->data.temp.type)); + } else { + return create_temp_object(expr->data.temp.type); + } +} + +static ENode *CExcept_TempTrans_ETEMP(ENode *expr) { + Object *object; + ExceptionAction *ea; + DtorTemp *dtorTemp; + Object *dtor; + + object = CExcept_GetETEMPObject(expr); + if (expr->data.temp.needs_dtor) { + dtorTemp = lalloc(sizeof(DtorTemp)); + dtorTemp->next = cexcept_dtortemps; + cexcept_dtortemps = dtorTemp; + dtorTemp->object = object; + dtorTemp->temp = NULL; + + if ( + !IS_TYPE_CLASS(expr->data.temp.type) || + !(dtorTemp->dtor = CClass_Destructor(TYPE_CLASS(expr->data.temp.type))) + ) + CError_FATAL(1749); + + ea = lalloc(sizeof(ExceptionAction)); + ea->prev = cexcept_eabefore; + cexcept_eabefore = ea; + ea->type = EAT_DESTROYLOCAL; + ea->data.destroy_local.local = dtorTemp->object; + ea->data.destroy_local.dtor = CABI_GetDestructorObject(dtorTemp->dtor, CABIDestroy1); + + ea = lalloc(sizeof(ExceptionAction)); + *ea = *cexcept_eabefore; + ea->prev = cexcept_eaafter; + cexcept_eaafter = ea; + } + + expr->type = EOBJREF; + expr->data.objref = object; + return expr; +} + +static ENode *CExcept_TransNewException(ENode *expr, Boolean isCond) { + Object *tempObj; + CLabel *label; + Boolean isArray; + Statement *stmt; + ExceptionAction *ea; + ENode *result; + + isArray = expr->type == ENEWEXCEPTIONARRAY; + + if (isCond) { + expr->data.newexception.initexpr = CExcept_TempTransExprCond(expr->data.newexception.initexpr); + expr->data.newexception.tryexpr = CExcept_TempTransExprCond(expr->data.newexception.tryexpr); + tempObj = create_temp_object(TYPE(&stchar)); + + stmt = CExcept_InsertPrevStatement(ST_EXPRESSION); + stmt->expr = makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 0), EASS); + cexcept_prevstmt = stmt; + + ea = lalloc(sizeof(ExceptionAction)); + ea->prev = cexcept_eabefore; + cexcept_eabefore = ea; + + ea->type = EAT_DELETEPOINTERCOND; + ea->data.delete_pointer_cond.pointerobject = expr->data.newexception.pointertemp; + ea->data.delete_pointer_cond.deletefunc = expr->data.newexception.deletefunc; + ea->data.delete_pointer_cond.cond = tempObj; + + if (isArray) { + result = makediadicnode( + makediadicnode( + expr->data.newexception.initexpr, + makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 1), EASS), + ECOMMA + ), + expr->data.newexception.tryexpr, + ECOMMA + ); + + result = makediadicnode( + result, + makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 0), EASS), + ECOMMA + ); + + result = makediadicnode( + result, + create_objectnode(expr->data.newexception.pointertemp), + ECOMMA + ); + } else { + result = makediadicnode( + makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 1), EASS), + expr->data.newexception.tryexpr, + ECOMMA + ); + + result = makediadicnode( + expr->data.newexception.initexpr, + makediadicnode( + result, + makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 0), EASS), + ECOMMA + ), + ELAND + ); + + result = makediadicnode( + result, + create_objectnode(expr->data.newexception.pointertemp), + ECOMMA + ); + } + } else { + expr->data.newexception.initexpr = CExcept_TempTransExpr(expr->data.newexception.initexpr); + expr->data.newexception.tryexpr = CExcept_TempTransExpr(expr->data.newexception.tryexpr); + + if (isArray) { + stmt = CExcept_InsertPrevStatement(ST_EXPRESSION); + stmt->expr = expr->data.newexception.initexpr; + } else { + stmt = CExcept_InsertPrevStatement(ST_IFNGOTO); + stmt->expr = expr->data.newexception.initexpr; + label = newlabel(); + stmt->label = label; + } + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = expr->data.newexception.tryexpr; + + ea = lalloc(sizeof(ExceptionAction)); + ea->prev = cexcept_eabefore; + ea->type = EAT_DELETEPOINTER; + ea->data.delete_pointer.pointerobject = expr->data.newexception.pointertemp; + ea->data.delete_pointer.deletefunc = expr->data.newexception.deletefunc; + stmt->dobjstack = ea; + + if (!isArray) { + stmt = CFunc_InsertStatement(ST_LABEL, stmt); + stmt->label = label; + label->stmt = stmt; + stmt->dobjstack = cexcept_eabefore; + } + + cexcept_prevstmt = stmt; + result = create_objectnode(expr->data.newexception.pointertemp); + } + + result->rtype = expr->rtype; + return result; +} + +static ENode *CExcept_TransInitTryCatch(ENode *expr, Boolean isCond) { + CLabel *label1; + CLabel *label2; + CLabel *label3; + Object *catch_info_object; + Statement *stmt; + ExceptionAction *ea; + + cexcept_hastrycatch = 1; + + if (isCond) { + CError_ASSERT(1877, !cexcept_expandtrycatch); + + cexcept_serialize = 1; + expr->data.itc.initexpr = CExcept_TempTransExprCond(expr->data.itc.initexpr); + expr->data.itc.tryexpr = CExcept_TempTransExprCond(expr->data.itc.tryexpr); + expr->data.itc.catchexpr = CExcept_TempTransExprCond(expr->data.itc.catchexpr); + expr->data.itc.result = CExcept_TempTransExprCond(expr->data.itc.result); + return expr; + } + + expr->data.itc.initexpr = CExcept_TempTransExpr(expr->data.itc.initexpr); + expr->data.itc.tryexpr = CExcept_TempTransExpr(expr->data.itc.tryexpr); + expr->data.itc.catchexpr = CExcept_TempTransExpr(expr->data.itc.catchexpr); + expr->data.itc.result = CExcept_TempTransExpr(expr->data.itc.result); + + if (!cexcept_expandtrycatch) + return expr; + + label1 = newlabel(); + label2 = newlabel(); + label3 = newlabel(); + + catch_info_object = create_temp_object(TYPE(&catchinfostruct)); + + stmt = CExcept_InsertPrevStatement(ST_IFNGOTO); + stmt->expr = expr->data.itc.initexpr; + stmt->label = label3; + + ea = lalloc(sizeof(ExceptionAction)); + memclrw(ea, sizeof(ExceptionAction)); + ea->type = EAT_CATCHBLOCK; + ea->data.catch_block.catch_label = label2; + ea->data.catch_block.catch_info_object = catch_info_object; + ea->prev = stmt->dobjstack; + + stmt = CFunc_InsertStatement(ST_LABEL, stmt); + stmt->flags = StmtFlag_1; + stmt->label = label1; + label1->stmt = stmt; + stmt->dobjstack = ea; + + stmt = CFunc_InsertStatement(ST_BEGINCATCH, stmt); + stmt->expr = create_objectrefnode(catch_info_object); + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = expr->data.itc.tryexpr; + + stmt = CFunc_InsertStatement(ST_GOTO, stmt); + stmt->label = label3; + + CError_ASSERT(1928, stmt->dobjstack == ea); + + stmt->dobjstack = ea->prev; + + ea = lalloc(sizeof(ExceptionAction)); + memclrw(ea, sizeof(ExceptionAction)); + ea->type = EAT_ACTIVECATCHBLOCK; + ea->data.active_catch_block.catch_info_object = catch_info_object; + ea->prev = stmt->dobjstack; + + stmt = CFunc_InsertStatement(ST_LABEL, stmt); + stmt->flags = StmtFlag_1; + stmt->label = label2; + label2->stmt = stmt; + stmt->dobjstack = ea; + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = expr->data.itc.catchexpr; + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = funccallexpr(Xthrw_func, nullnode(), nullnode(), nullnode(), NULL); + + stmt = CFunc_InsertStatement(ST_LABEL, stmt); + stmt->label = label3; + label3->stmt = stmt; + + CError_ASSERT(1968, stmt->dobjstack == ea); + + stmt->dobjstack = ea->prev; + + cexcept_prevstmt = stmt; + return expr->data.itc.result; +} + +static ENode *CExcept_TempTransFuncCall(ENode *expr, Boolean isCond) { + ENodeList *tempArg; + ENodeList **argArray; + ENodeList *args; + ExceptionAction *ea; + Statement *stmt; + DtorTemp *dtorTemp; + ENode *tempNode; + + tempArg = NULL; + if ((args = expr->data.funccall.args)) { + tempNode = args->node; + if (tempNode->type == ETEMP) { + if (tempNode->data.temp.needs_dtor) + tempArg = args; + } else if (args->next) { + tempNode = args->next->node; + if (tempNode->type == ETEMP) { + if (tempNode->data.temp.needs_dtor) + tempArg = args->next; + } + } + } + + if (tempArg) { + if (isCond) { + ENodeList *arg = args; + SInt32 i = 0; + while (arg) { + arg = arg->next; + i++; + } + + argArray = lalloc(sizeof(ENodeList *) * i); + for (args = expr->data.funccall.args, i = 0; args; args = args->next) + argArray[i++] = args; + + while (i > 0) { + i--; + if (argArray[i] != tempArg) + argArray[i]->node = CExcept_TempTransExprCond(argArray[i]->node); + } + } else { + while (args) { + if (args != tempArg) + args->node = CExcept_TempTransExpr(args->node); + args = args->next; + } + } + + dtorTemp = lalloc(sizeof(DtorTemp)); + dtorTemp->next = cexcept_dtortemps; + cexcept_dtortemps = dtorTemp; + + dtorTemp->object = CExcept_GetETEMPObject(tempNode); + dtorTemp->temp = NULL; + + if ( + !IS_TYPE_CLASS(tempNode->data.temp.type) || + !(dtorTemp->dtor = CClass_Destructor(TYPE_CLASS(tempNode->data.temp.type))) + ) + CError_FATAL(2046); + + tempNode->type = EOBJREF; + tempNode->data.objref = dtorTemp->object; + + if (isCond) { + Type *type24 = expr->rtype; + dtorTemp->temp = create_temp_object(TYPE(&stchar)); + + expr = makediadicnode( + expr, + makediadicnode(create_objectnode(dtorTemp->temp), intconstnode(TYPE(&stchar), 1), EASS), + ECOMMA + ); + + expr = makediadicnode( + expr, + create_objectrefnode(dtorTemp->object), + ECOMMA + ); + expr->rtype = type24; + + stmt = CExcept_InsertPrevStatement(ST_EXPRESSION); + stmt->expr = makediadicnode( + create_objectnode(dtorTemp->temp), + intconstnode(TYPE(&stchar), 0), + EASS + ); + cexcept_prevstmt = stmt; + + ea = lalloc(sizeof(ExceptionAction)); + ea->prev = cexcept_eabefore; + cexcept_eabefore = ea; + + ea->type = EAT_DESTROYLOCALCOND; + ea->data.destroy_local_cond.local = dtorTemp->object; + ea->data.destroy_local_cond.dtor = CABI_GetDestructorObject(dtorTemp->dtor, CABIDestroy1); + ea->data.destroy_local_cond.cond = dtorTemp->temp; + + ea = lalloc(sizeof(ExceptionAction)); + *ea = *cexcept_eabefore; + ea->prev = cexcept_eaafter; + cexcept_eaafter = ea; + } else { + stmt = CExcept_InsertPrevStatement(ST_EXPRESSION); + stmt->expr = expr; + cexcept_prevstmt = stmt; + + ea = lalloc(sizeof(ExceptionAction)); + ea->prev = cexcept_eabefore; + cexcept_eabefore = ea; + + ea->type = EAT_DESTROYLOCAL; + ea->data.destroy_local.local = dtorTemp->object; + ea->data.destroy_local.dtor = CABI_GetDestructorObject(dtorTemp->dtor, CABIDestroy1); + + ea = lalloc(sizeof(ExceptionAction)); + *ea = *cexcept_eabefore; + ea->prev = cexcept_eaafter; + cexcept_eaafter = ea; + + expr = lalloc(sizeof(ENode)); + *expr = *stmt->expr; + expr->type = EOBJREF; + expr->data.objref = tempArg->node->data.objref; + } + return expr; + } else { + if (isCond) { + SInt32 i = 0; + while (args) { + args = args->next; + i++; + } + + argArray = lalloc(sizeof(ENodeList *) * i); + for (args = expr->data.funccall.args, i = 0; args; args = args->next) + argArray[i++] = args; + + while (i > 0) { + i--; + argArray[i]->node = CExcept_TempTransExprCond(argArray[i]->node); + } + + expr->data.funccall.funcref = CExcept_TempTransExprCond(expr->data.funccall.funcref); + } else { + while (args) { + args->node = CExcept_TempTransExpr(args->node); + args = args->next; + } + + expr->data.funccall.funcref = CExcept_TempTransExpr(expr->data.funccall.funcref); + } + + return expr; + } +} + +static ENode *CExcept_TempTransExprCond(ENode *expr) { + switch (expr->type) { + case ETEMP: + return CExcept_TempTrans_ETEMP(expr); + case ENEWEXCEPTION: + case ENEWEXCEPTIONARRAY: + return CExcept_TransNewException(expr, 1); + case EINITTRYCATCH: + return CExcept_TransInitTryCatch(expr, 1); + case ENULLCHECK: + expr->data.nullcheck.nullcheckexpr = CExcept_TempTransExprCond(expr->data.nullcheck.nullcheckexpr); + expr->data.nullcheck.condexpr = CExcept_TempTransExprCond(expr->data.nullcheck.condexpr); + return expr; + case ECOND: + expr->data.cond.cond = CExcept_TempTransExprCond(expr->data.cond.cond); + expr->data.cond.expr1 = CExcept_TempTransExprCond(expr->data.cond.expr1); + expr->data.cond.expr2 = CExcept_TempTransExprCond(expr->data.cond.expr2); + return expr; + case ELAND: + case ELOR: + expr->data.diadic.left = CExcept_TempTransExprCond(expr->data.diadic.left); + expr->data.diadic.right = CExcept_TempTransExprCond(expr->data.diadic.right); + return expr; + case EFUNCCALL: + case EFUNCCALLP: + return CExcept_TempTransFuncCall(expr, 1); + case EMUL: + case EDIV: + case EMODULO: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + case EROTL: + case EROTR: + expr->data.diadic.left = CExcept_TempTransExprCond(expr->data.diadic.left); + expr->data.diadic.right = CExcept_TempTransExprCond(expr->data.diadic.right); + return expr; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case ETYPCON: + case EBITFIELD: + expr->data.monadic = CExcept_TempTransExprCond(expr->data.monadic); + return expr; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ELABEL: + case EINSTRUCTION: + case EVECTOR128CONST: + return expr; + default: + CError_FATAL(2236); + return expr; + } +} + +static ENode *CExcept_TempTransExpr(ENode *expr) { + switch (expr->type) { + case ETEMP: + return CExcept_TempTrans_ETEMP(expr); + case ENEWEXCEPTION: + case ENEWEXCEPTIONARRAY: + return CExcept_TransNewException(expr, 0); + case EINITTRYCATCH: + return CExcept_TransInitTryCatch(expr, 0); + case ENULLCHECK: + expr->data.nullcheck.nullcheckexpr = CExcept_TempTransExpr(expr->data.nullcheck.nullcheckexpr); + expr->data.nullcheck.condexpr = CExcept_TempTransExprCond(expr->data.nullcheck.condexpr); + return expr; + case ECOND: + expr->data.cond.cond = CExcept_TempTransExpr(expr->data.cond.cond); + expr->data.cond.expr1 = CExcept_TempTransExprCond(expr->data.cond.expr1); + expr->data.cond.expr2 = CExcept_TempTransExprCond(expr->data.cond.expr2); + return expr; + case ELAND: + case ELOR: + case ECOMMA: + expr->data.diadic.left = CExcept_TempTransExpr(expr->data.diadic.left); + expr->data.diadic.right = CExcept_TempTransExprCond(expr->data.diadic.right); + return expr; + case EFUNCCALL: + case EFUNCCALLP: + return CExcept_TempTransFuncCall(expr, 0); + case EMUL: + case EDIV: + case EMODULO: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case EROTL: + case EROTR: + expr->data.diadic.left = CExcept_TempTransExpr(expr->data.diadic.left); + expr->data.diadic.right = CExcept_TempTransExpr(expr->data.diadic.right); + return expr; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case ETYPCON: + case EBITFIELD: + expr->data.monadic = CExcept_TempTransExpr(expr->data.monadic); + return expr; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EMFPOINTER: + case EPRECOMP: + case ELABEL: + case EOBJLIST: + case EMEMBER: + case EINSTRUCTION: + case EVECTOR128CONST: + return expr; + default: + CError_FATAL(2350); + return expr; + } +} + +static Statement *CExcept_DtorTransform(Statement *stmt) { + DtorTemp *dtorTemp; + Statement *curStmt; + CLabel *lastLabel; + + dtorTemp = cexcept_dtortemps; + curStmt = stmt; + while (dtorTemp) { + if ( + cexcept_eaafter && + (cexcept_eaafter->type == EAT_DESTROYLOCAL || cexcept_eaafter->type == EAT_DESTROYLOCALCOND) && + cexcept_eaafter->data.destroy_local.local == dtorTemp->object + ) + { + cexcept_eaafter = cexcept_eaafter->prev; + } else { + CError_FATAL(2374); + } + + if (dtorTemp->temp) { + curStmt = CFunc_InsertStatement(ST_IFNGOTO, curStmt); + curStmt->expr = create_objectnode(dtorTemp->temp); + curStmt->dobjstack = cexcept_eaafter; + lastLabel = curStmt->label = newlabel(); + } + + curStmt = CFunc_InsertStatement(ST_EXPRESSION, curStmt); + curStmt->expr = CABI_DestroyObject(dtorTemp->dtor, create_objectrefnode(dtorTemp->object), CABIDestroy1, 1, 0); + curStmt->dobjstack = cexcept_eaafter; + + if (dtorTemp->temp) { + curStmt = CFunc_InsertStatement(ST_LABEL, curStmt); + curStmt->label = lastLabel; + lastLabel->stmt = curStmt; + } + + dtorTemp = dtorTemp->next; + } + + return curStmt; +} + +static void CExcept_TempTransform(Statement *stmt, Boolean flag1, Boolean flag2) { + Statement *prevStmt; + Statement *iter; + Statement copy; + Object *tempObj; + + prevStmt = cexcept_prevstmt; + cexcept_dtortemps = NULL; + cexcept_serialize = 0; + cexcept_expandtrycatch = 0; + cexcept_hastrycatch = 0; + stmt->expr = CExcept_TempTransExpr(stmt->expr); + + if (cexcept_hastrycatch) { + cexcept_expandtrycatch = 1; + if (cexcept_serialize) { + CInline_SerializeStatement(stmt); + cexcept_prevstmt = stmt; + } else { + cexcept_prevstmt = prevStmt; + } + + iter = prevStmt; + while (1) { + CError_ASSERT(2425, iter); + + switch (iter->type) { + case ST_RETURN: + CError_ASSERT(2429, iter->expr != NULL); + case ST_EXPRESSION: + case ST_SWITCH: + case ST_IFGOTO: + case ST_IFNGOTO: + iter->expr = CExcept_TempTransExpr(iter->expr); + } + + if (iter == stmt) + break; + cexcept_prevstmt = iter; + iter = iter->next; + } + } + + if (cexcept_dtortemps) { + if (!flag1) { + if (flag2) { + ENode *expr = stmt->expr; + CError_ASSERT(2456, !IS_TYPE_CLASS(expr->rtype) || !CClass_Destructor(TYPE_CLASS(expr->rtype))); + + tempObj = create_temp_object(expr->rtype); + stmt->expr = makediadicnode(create_objectnode(tempObj), expr, EASS); + } + + copy = *stmt; + stmt->type = ST_EXPRESSION; + stmt = CExcept_DtorTransform(stmt); + stmt = CFunc_InsertStatement(copy.type, stmt); + stmt->label = copy.label; + + if (flag2) + stmt->expr = create_objectnode(tempObj); + else + stmt->expr = nullnode(); + } else { + CExcept_DtorTransform(stmt); + } + } +} + +static void CExcept_CleanupExceptionActions(Statement *stmt) { + Statement *iter; + ENode *expr; + ExceptionAction *ea; + + cexcept_prevstmt = stmt; + for (iter = stmt; iter; iter = iter->next) { + cexcept_eabefore = cexcept_eaafter = ea = iter->dobjstack; + + if (iter->flags & StmtFlag_2) { + cexcept_eabefore = ea->prev; + } else if (iter->type == ST_EXPRESSION) { + expr = iter->expr; + while (ENODE_IS(expr, ECOMMA)) + expr = expr->data.diadic.left; + if (ENODE_IS(expr, EINDIRECT)) + expr = expr->data.monadic; + + if ( + ENODE_IS(expr, EFUNCCALL) && + ENODE_IS(expr->data.funccall.funcref, EOBJREF) && + CClass_IsConstructor(expr->data.funccall.funcref->data.objref) && + iter->dobjstack && + iter->dobjstack->type == EAT_DESTROYLOCAL && + expr->data.funccall.args && + ENODE_IS(expr->data.funccall.args->node, EOBJREF) && + expr->data.funccall.args->node->data.objref == iter->dobjstack->data.destroy_local.local + ) + cexcept_eabefore = cexcept_eabefore->prev; + } + + switch (iter->type) { + case ST_EXPRESSION: + CExcept_TempTransform(iter, 1, 0); + break; + case ST_SWITCH: + case ST_IFGOTO: + case ST_IFNGOTO: + CExcept_TempTransform(iter, 0, 1); + break; + case ST_RETURN: + if (iter->expr) { + CExcept_TempTransform( + iter, + 0, + CMach_GetFunctionResultClass(TYPE_FUNC(cscope_currentfunc->type)) != 1 + ); + } + break; + } + + iter->dobjstack = cexcept_eabefore; + cexcept_prevstmt = iter; + } +} + +static void CExcept_InsertSpecificationActions(Statement *stmt, ExceptSpecList *exspecs) { + Statement *iter; + Statement *last; + ExceptionAction *ea_spec; + ExceptionAction *ea; + ExceptSpecList *spec_iter; + SInt32 i; + Object *catch_info_object; + CLabel *label; + + ea_spec = lalloc(sizeof(ExceptionAction)); + memclrw(ea_spec, sizeof(ExceptionAction)); + ea_spec->type = EAT_SPECIFICATION; + + for (iter = stmt; iter; iter = iter->next) { + if ((ea = iter->dobjstack)) { + while (1) { + if (ea->type == EAT_SPECIFICATION) + break; + if (ea->prev == NULL) { + ea->prev = ea_spec; + break; + } + ea = ea->prev; + } + } else { + iter->dobjstack = ea_spec; + } + } + + last = stmt; + while (last->next) + last = last->next; + + if (last->type != ST_GOTO && last->type != ST_RETURN) { + last = CFunc_InsertStatement(ST_RETURN, last); + last->expr = NULL; + last->dobjstack = NULL; + if (TYPE_FUNC(cscope_currentfunc->type)->functype != &stvoid && (copts.pedantic || copts.cplusplus)) + CError_Warning(CErrorStr184); + } + + last = CFunc_InsertStatement(ST_LABEL, last); + last->label = newlabel(); + last->label->stmt = last; + last->flags = StmtFlag_1; + last->dobjstack = NULL; + + catch_info_object = create_temp_object(TYPE(&catchinfostruct)); + + if (!exspecs->type) + exspecs = NULL; + + i = 0; + spec_iter = exspecs; + while (spec_iter) { + spec_iter = spec_iter->next; + i++; + } + + ea_spec->data.specification.unexp_ids = i; + ea_spec->data.specification.unexp_id = galloc(sizeof(Object *) * i); + ea_spec->data.specification.unexp_label = last->label; + ea_spec->data.specification.unexp_info_object = catch_info_object; + + i = 0; + while (exspecs) { + ea_spec->data.specification.unexp_id[i] = CExcept_TypeID(exspecs->type, exspecs->qual); + exspecs = exspecs->next; + i++; + } + + last = CFunc_InsertStatement(ST_EXPRESSION, last); + last->expr = funccallexpr(Xunex_func, create_objectrefnode(catch_info_object), NULL, NULL, NULL); + + ea = lalloc(sizeof(ExceptionAction)); + memclrw(ea, sizeof(ExceptionAction)); + ea->type = EAT_ACTIVECATCHBLOCK; + ea->data.active_catch_block.catch_info_object = catch_info_object; + ea->data.active_catch_block.call_dtor = 1; + last->dobjstack = ea; + + last = CFunc_InsertStatement(ST_LABEL, last); + last->label = label = newlabel(); + last->label->stmt = last; + last->dobjstack = NULL; + + last = CFunc_InsertStatement(ST_GOTO, last); + last->label = label; +} + +static void CExcept_HasFuncCallCallBack(ENode *expr) { + ENode *funcref = expr->data.funccall.funcref; + if (ENODE_IS(funcref, EOBJREF)) { + Object *func = funcref->data.objref; + if (CExcept_CanThrowException(func, func->datatype == DVFUNC && !(expr->flags & ENODE_FLAG_80))) + cexcept_canthrow = 1; + } else { + cexcept_canthrow = 1; + } +} + +static Boolean CExcept_CanThrowCheck(Object *func, Statement *stmt) { + cexcept_canthrow = 0; + + while (stmt) { + switch (stmt->type) { + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + case ST_ASM: + break; + case ST_RETURN: + if (!stmt->expr) + break; + case ST_EXPRESSION: + case ST_SWITCH: + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_GOTOEXPR: + CExpr_SearchExprTree(stmt->expr, CExcept_HasFuncCallCallBack, 2, EFUNCCALL, EFUNCCALLP); + break; + default: + CError_FATAL(2687); + } + stmt = stmt->next; + } + + if (!cexcept_canthrow) { + TYPE_FUNC(cscope_currentfunc->type)->flags |= FUNC_NOTHROW; + return 0; + } else { + return 1; + } +} + +void CExcept_ExceptionTansform(Statement *stmt) { + cexcept_uniqueobjs = NULL; + CExcept_CleanupExceptionActions(stmt); + + if (cscope_currentfunc && CExcept_CanThrowCheck(cscope_currentfunc, stmt)) { + CError_ASSERT(2716, IS_TYPE_FUNC(cscope_currentfunc->type)); + if (TYPE_FUNC(cscope_currentfunc->type)->exspecs && copts.exceptions) + CExcept_InsertSpecificationActions(stmt, TYPE_FUNC(cscope_currentfunc->type)->exspecs); + } +} diff --git a/compiler_and_linker/FrontEnd/C/CExpr.c b/compiler_and_linker/FrontEnd/C/CExpr.c new file mode 100644 index 0000000..484f56d --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CExpr.c @@ -0,0 +1,4971 @@ +#include "compiler/CExpr.h" +#include "compiler/CABI.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CException.h" +#include "compiler/CInit.h" +#include "compiler/CInline.h" +#include "compiler/CIRTransform.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CInt64.h" +#include "compiler/CObjC.h" +#include "compiler/CObjCModern.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CRTTI.h" +#include "compiler/CSOM.h" +#include "compiler/CTemplateNew.h" +#include "compiler/CTemplateTools.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/PPCError.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" + +Boolean (*name_obj_check)(HashNameNode *, Object *); +Boolean disallowgreaterthan; + +// forward declarations +static ENode *makeaddnode(ENode *left, ENode *right); +static ENode *makesubnode(ENode *left, ENode *right); + +ENode *CExpr_RewriteConst(ENode *expr) { + Object *obj; + +restart: + if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EOBJREF)) { + obj = expr->data.monadic->data.objref; + if (obj->datatype == DALIAS) { + CExpr_AliasTransform(expr->data.monadic); + goto restart; + } + + if ((obj->qual & Q_INLINE_DATA) && expr->rtype == obj->type) { + switch (expr->rtype->type) { + case TYPEINT: + case TYPEENUM: + expr->type = EINTCONST; + expr->data.intval = obj->u.data.u.intconst; + break; + case TYPEPOINTER: + expr->type = EINTCONST; + expr->data.intval = obj->u.data.u.intconst; + expr->rtype = TYPE(&stunsignedlong); + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = obj->type; + break; + case TYPEFLOAT: + expr->type = EFLOATCONST; + if (obj->u.data.u.floatconst) + expr->data.floatval = *obj->u.data.u.floatconst; + else + expr->data.floatval = CMach_CalcFloatConvertFromInt(TYPE(&stsignedlong), cint64_zero); + break; + default: + CError_FATAL(105); + } + } + } + + return expr; +} + +void optimizecomm(ENode *expr) { + ENode *right; + ENode *left; + + if (ENODE_IS((right = expr->data.diadic.right), EINTCONST)) + return; + if (ENODE_IS((left = expr->data.diadic.left), EINTCONST)) { + swap: + expr->data.diadic.right = left; + expr->data.diadic.left = right; + return; + } + + if (ENODE_IS(left, EFLOATCONST)) + return; + if (ENODE_IS(right, EFLOATCONST)) + goto swap; + + if (expr->rtype->type > TYPEFLOAT) + return; + + if (left->cost > right->cost) + goto swap; +} + +static void checkadditive(ENode *expr) { + switch (expr->rtype->type) { + case TYPEINT: + if (expr->rtype == TYPE(&stbool)) + break; + case TYPEFLOAT: + return; + case TYPEENUM: + if (copts.cplusplus) + break; + return; + case TYPEPOINTER: + if (TPTR_TARGET(expr->rtype)->size == 0) + CDecl_CompleteType(TPTR_TARGET(expr->rtype)); + if (TPTR_TARGET(expr->rtype)->size == 0) + break; + return; + case TYPEARRAY: + if (ENODE_IS(expr, EOBJREF)) + return; + } + + CError_Error(CErrorStr376, expr->rtype, ENODE_QUALS(expr)); +} + +static void CExpr_CompareConvert(ENode **leftp, char *opname, ENode **rightp, Boolean flag) { + ENode *left; + ENode *right; + CInt64 val; + + left = *leftp; + right = *rightp; + + switch (left->rtype->type) { + case TYPEINT: + break; + case TYPEFLOAT: + if (left->rtype != right->rtype) + CExpr_ArithmeticConversion(leftp, rightp); + return; + case TYPEENUM: + left->rtype = TYPE_ENUM(left->rtype)->enumtype; + break; + default: + CError_Error(CErrorStr377, + left->rtype, ENODE_QUALS(left), + opname, + right->rtype, ENODE_QUALS(right)); + left = nullnode(); + } + + switch (right->rtype->type) { + case TYPEINT: + break; + case TYPEFLOAT: + CExpr_ArithmeticConversion(leftp, rightp); + return; + case TYPEENUM: + right->rtype = TYPE_ENUM(right->rtype)->enumtype; + break; + default: + CError_Error(CErrorStr377, + left->rtype, ENODE_QUALS(left), + opname, + right->rtype, ENODE_QUALS(right)); + right = nullnode(); + } + + if (left->rtype == right->rtype) { + *leftp = left; + *rightp = right; + return; + } + + if (left->rtype->size == right->rtype->size) { + if (is_unsigned(left->rtype) == is_unsigned(right->rtype)) { + left->rtype = right->rtype; + *leftp = left; + *rightp = right; + return; + } + } else { + if (ENODE_IS(right, EINTCONST) && left->rtype->size <= right->rtype->size && (is_unsigned(left->rtype) == is_unsigned(right->rtype) || is_unsigned(left->rtype))) { + val = CMach_CalcIntDiadic(left->rtype, right->data.intval, '+', cint64_zero); + val = CMach_CalcIntDiadic(right->rtype, val, '+', cint64_zero); + if (CInt64_Equal(val, right->data.intval)) { + right->rtype = left->rtype; + *leftp = left; + *rightp = right; + return; + } + } + + if (ENODE_IS(left, EINTCONST) && left->rtype->size >= right->rtype->size && (is_unsigned(left->rtype) == is_unsigned(right->rtype) || is_unsigned(right->rtype))) { + val = CMach_CalcIntDiadic(right->rtype, left->data.intval, '+', cint64_zero); + val = CMach_CalcIntDiadic(left->rtype, val, '+', cint64_zero); + if (CInt64_Equal(val, left->data.intval)) { + left->rtype = right->rtype; + *leftp = left; + *rightp = right; + return; + } + } + } + + *leftp = left; + *rightp = right; + CExpr_ArithmeticConversion(leftp, rightp); +} + +static ENode *CExpr_ConstResult(ENode *expr, SInt32 value) { + ENode *constnode; + + if (IS_TYPE_FLOAT(expr->rtype)) { + constnode = intconstnode(TYPE(&stsignedint), value); + constnode->type = EFLOATCONST; + constnode->data.floatval = CMach_CalcFloatConvertFromInt(TYPE(&stsignedint), constnode->data.intval); + constnode->rtype = expr->rtype; + } else { + constnode = intconstnode(expr->rtype, value); + } + + if (CInline_ExpressionHasSideEffect(expr)) + return makediadicnode(expr, constnode, ECOMMA); + else + return constnode; +} + +static ENode *makemultnode(ENode *left, ENode *right) { + CExpr_ArithmeticConversion(&left, &right); + if (iszero(left)) + return CExpr_ConstResult(right, 0); + if (iszero(right)) + return CExpr_ConstResult(left, 0); + + if (CExpr_IsOne(right)) + return left; + if (CExpr_IsOne(left)) + return right; + + if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { + left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '*', right->data.intval); + return left; + } + if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { + left->data.floatval = CMach_CalcFloatDiadic(left->rtype, left->data.floatval, '*', right->data.floatval); + return left; + } + + left = makediadicnode(left, right, EMUL); + optimizecomm(left); + if (IS_TYPE_INT(left->rtype) && left->rtype->size > 2) { + left->cost++; + if (left->cost > 200) + left->cost = 200; + } + + if (IS_TYPE_FLOAT(left->rtype)) + left = CExpr_BinaryFloatExpression(left); + + return left; +} + +static ENode *makedivnode(ENode *left, ENode *right, Boolean no_warning) { + CExpr_ArithmeticConversion(&left, &right); + if (iszero(right) && IS_TYPE_INT(right->rtype)) { + if (!no_warning) + CError_Warning(CErrorStr139); + return right; + } + + if (CExpr_IsOne(right)) + return left; + + if (iszero(left) && IS_TYPE_INT(left->rtype)) + return CExpr_ConstResult(right, 0); + + if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { + left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '/', right->data.intval); + return left; + } + if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { + left->data.floatval = CMach_CalcFloatDiadic(left->rtype, left->data.floatval, '/', right->data.floatval); + return left; + } + + left = makediadicnode(left, right, EDIV); + if (IS_TYPE_FLOAT(left->rtype)) + left = CExpr_BinaryFloatExpression(left); + + return left; +} + +static short canadd2(ENode *expr, CInt64 value) { + Float tmp; + + if (CInt64_IsZero(&value)) + return 1; + + switch (expr->type) { + case EINTCONST: + expr->data.intval = CMach_CalcIntDiadic(expr->rtype, expr->data.intval, '+', value); + return 1; + case EFLOATCONST: + tmp = CMach_CalcFloatConvertFromInt(TYPE(&stsignedlong), value); + expr->data.floatval = CMach_CalcFloatDiadic(expr->rtype, expr->data.floatval, '+', tmp); + return 1; + case EADD: + if (canadd2(expr->data.diadic.left, value)) + return 1; + if (canadd2(expr->data.diadic.right, value)) + return 1; + return 0; + case ESUB: + if (canadd2(expr->data.diadic.left, value)) + return 1; + if (canadd2(expr->data.diadic.right, CInt64_Neg(value))) + return 1; + return 0; + case ETYPCON: + if (IS_TYPE_POINTER_ONLY(expr->rtype) && ENODE_IS(expr->data.monadic, EINTCONST)) { + expr->data.monadic->data.intval = CMach_CalcIntDiadic(TYPE(&stunsignedlong), expr->data.monadic->data.intval, '+', value); + return 1; + } + return 0; + default: + return 0; + } +} + +short canadd(ENode *expr, SInt32 value) { + CInt64 value64; + CInt64_SetLong(&value64, value); + return canadd2(expr, value64); +} + +static ENode *addconst(ENode *expr, SInt32 value) { + ENode *right; + + if (canadd(expr, value)) + return expr; + + if (stsignedint.size < 4 && (value > 0x7FFF || value < -0x8000)) + right = intconstnode(TYPE(&stsignedlong), value); + else + right = intconstnode(TYPE(&stsignedint), value); + + CExpr_ArithmeticConversion(&expr, &right); + expr = makediadicnode(expr, right, EADD); + return expr; +} + +static ENode *integralpointerpromote(ENode *expr) { + Boolean uns; + Type *type; + + if (!IS_TYPE_INT(expr->rtype)) + expr = forceintegral(expr); + + if (expr->rtype->size != 4) { + type = TYPE(&stunsignedlong); + if (is_unsigned(type) != (uns = is_unsigned(expr->rtype))) { + if (uns) { + if (stunsignedlong.size == 4) { + type = TYPE(&stunsignedlong); + } else if (stunsignedint.size == 4) { + type = TYPE(&stunsignedint); + } else { + CError_FATAL(480); + } + } else { + if (stsignedlong.size == 4) { + type = TYPE(&stsignedlong); + } else if (stsignedint.size == 4) { + type = TYPE(&stsignedint); + } else { + CError_FATAL(486); + } + } + } + + if (ENODE_IS(expr, EINTCONST)) + expr->data.intval = CExpr_IntConstConvert(type, expr->rtype, expr->data.intval); + else + expr = makemonadicnode(expr, ETYPCON); + + expr->rtype = type; + } + + return expr; +} + +static ENode *padd(ENode *left, ENode *right) { + Type *innertype; + SInt32 innersize; + ENode *expr; + + right = integralpointerpromote(right); + innertype = TPTR_TARGET(left->rtype); + innersize = innertype->size; + if (innersize == 0) { + CDecl_CompleteType(innertype); + innersize = innertype->size; + if (innersize == 0) { + CError_Error(CErrorStr146); + return left; + } + } + + expr = makemultnode( + right, + intconstnode((innersize > 0x7FFF) ? TYPE(&stsignedlong) : TYPE(&stsignedint), innersize)); + + if (ENODE_IS(expr, EINTCONST) && canadd2(left, expr->data.intval)) + return left; + + if (ENODE_IS(left, EADD) && ENODE_IS(left->data.diadic.right, EINTCONST)) { + left->data.diadic.left = makediadicnode(left->data.diadic.left, expr, EADD); + return left; + } + + expr = makediadicnode(left, expr, EADD); + expr->rtype = left->rtype; + expr->flags = left->flags; + return expr; +} + +static ENode *psub(ENode *left, ENode *right) { + Type *innertype; + SInt32 innersize; + ENode *expr; + + if (IS_TYPE_POINTER(right->rtype)) { + innersize = TPTR_TARGET(left->rtype)->size; + if (innersize == 0) { + CDecl_CompleteType(TPTR_TARGET(left->rtype)); + innersize = TPTR_TARGET(left->rtype)->size; + if (innersize == 0) { + CError_Error(CErrorStr146); + return left; + } + } + + if (!is_typeequal(left->rtype, right->rtype)) { + CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); + return left; + } + + if (ENODE_IS(left, ETYPCON) && ENODE_IS(left->data.monadic, EINTCONST) && ENODE_IS(right, ETYPCON) && ENODE_IS(right->data.monadic, EINTCONST)) { + left->data.monadic->rtype = right->data.monadic->rtype = CABI_GetPtrDiffTType(); + expr = makesubnode(left->data.monadic, right->data.monadic); + if (innersize > 1) + expr = makedivnode(expr, intconstnode(CABI_GetPtrDiffTType(), innersize), 11); + return expr; + } + + expr = makediadicnode(left, right, ESUB); + expr->rtype = CABI_GetPtrDiffTType(); + if (innersize > 1) + expr = makediadicnode(expr, intconstnode(CABI_GetPtrDiffTType(), innersize), EDIV); + return expr; + } + + right = integralpointerpromote(right); + innertype = TPTR_TARGET(left->rtype); + innersize = innertype->size; + if (innersize == 0) { + CDecl_CompleteType(innertype); + innersize = innertype->size; + if (innersize == 0) { + CError_Error(CErrorStr146); + return left; + } + } + + expr = makemultnode(right, intconstnode(CABI_GetPtrDiffTType(), innersize)); + if (ENODE_IS(expr, EINTCONST) && canadd2(left, CInt64_Neg(expr->data.intval))) + return left; + + expr = makediadicnode(left, expr, ESUB); + expr->rtype = left->rtype; + expr->flags = left->flags; + return expr; +} + +static ENode *makeaddnode(ENode *left, ENode *right) { + if (IS_TYPE_POINTER(left->rtype)) + return padd(left, right); + if (IS_TYPE_POINTER(right->rtype)) + return padd(right, left); + + CExpr_ArithmeticConversion(&left, &right); + if (iszero(right)) + return left; + if (iszero(left)) + return right; + + if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { + left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '+', right->data.intval); + return left; + } + if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { + left->data.floatval = CMach_CalcFloatDiadic(left->rtype, left->data.floatval, '+', right->data.floatval); + return left; + } + + if (ENODE_IS(left, EINTCONST) && canadd2(right, left->data.intval)) + return right; + if (ENODE_IS(right, EINTCONST) && canadd2(left, right->data.intval)) + return left; + + left = makediadicnode(left, right, EADD); + optimizecomm(left); + if (IS_TYPE_FLOAT(left->rtype)) + left = CExpr_BinaryFloatExpression(left); + return left; +} + +static ENode *makesubnode(ENode *left, ENode *right) { + if (ENODE_IS(right, EINTCONST) && !is_unsigned(right->rtype) && !IS_TYPE_FLOAT(left->rtype)) { + right->data.intval = CInt64_Neg(right->data.intval); + return makeaddnode(left, right); + } + + if (IS_TYPE_POINTER(left->rtype)) + return psub(left, right); + + CExpr_ArithmeticConversion(&left, &right); + if (iszero(right)) + return left; + if (iszero(left)) { + if (ENODE_IS(right, EINTCONST)) { + right->data.intval = CInt64_Neg(right->data.intval); + return right; + } + if (ENODE_IS(right, EFLOATCONST)) { + right->data.floatval = CMach_CalcFloatMonadic(right->rtype, '-', right->data.floatval); + return right; + } + return CExpr_UnaryFloatExpression(makemonadicnode(right, EMONMIN)); + } + + if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { + left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '-', right->data.intval); + return left; + } + if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { + left->data.floatval = CMach_CalcFloatDiadic(left->rtype, left->data.floatval, '-', right->data.floatval); + return left; + } + + if (ENODE_IS(right, EINTCONST) && canadd2(left, CInt64_Neg(right->data.intval))) + return left; + + left = makediadicnode(left, right, ESUB); + if (IS_TYPE_FLOAT(left->rtype)) + left = CExpr_BinaryFloatExpression(left); + return left; +} + +ENode *checkreference(ENode *expr) { + if (!IS_TYPE_REFERENCE(expr->rtype)) + return expr; + + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = TPTR_TARGET(expr->rtype); + return expr; +} + +static ENode *pointer_generation2(ENode *expr) { + switch (expr->type) { + case EINDIRECT: + switch (expr->rtype->type) { + case TYPEARRAY: + switch (expr->data.monadic->type) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + expr->type = ETYPCON; + expr->rtype = CDecl_NewPointerType(TPTR_TARGET(expr->rtype)); + return expr; + default: + expr->data.monadic->rtype = CDecl_NewPointerType(TPTR_TARGET(expr->rtype)); + expr->data.monadic->flags = expr->flags; + return expr->data.monadic; + } + case TYPEFUNC: + expr = expr->data.monadic; + if (ENODE_IS(expr, EOBJREF) && expr->data.objref->datatype == DINLINEFUNC) + CError_Error(CErrorStr175); + return expr; + } + } + return expr; +} + +ENode *pointer_generation(ENode *expr) { + return CExpr_RewriteConst(pointer_generation2(expr)); +} + +ENode *CExpr_PointerGeneration(ENode *expr) { + switch (expr->type) { + case EINDIRECT: + switch (expr->rtype->type) { + case TYPEARRAY: + expr->data.monadic->rtype = CDecl_NewPointerType(TPTR_TARGET(expr->rtype)); + return expr->data.monadic; + case TYPEFUNC: + return expr->data.monadic; + } + } + return expr; +} + +static void CExpr_ConstPointerCheck(ENode *expr, Type *type, short qual) { + Type *exprtype; + Type *b; + Type *a; + short exprqual; + + exprtype = expr->rtype; + if (IS_TYPE_POINTER_ONLY(type) && IS_TYPE_POINTER_ONLY(exprtype)) { + exprqual = expr->flags; + + if (TPTR_TARGET(type) == &stvoid) { + exprqual = CParser_GetCVTypeQualifiers(TPTR_TARGET(exprtype), exprqual); + } else { + a = TPTR_TARGET(type); + b = TPTR_TARGET(exprtype); + while (IS_TYPE_POINTER_ONLY(a) && IS_TYPE_POINTER_ONLY(b)) { + if (CParser_IsMoreCVQualified(TPTR_QUAL(b), TPTR_QUAL(a))) { + CError_Warning(CErrorStr220, expr->rtype, ENODE_QUALS(expr), type, qual); + return; + } + a = TPTR_TARGET(a); + b = TPTR_TARGET(b); + } + } + + if (CParser_IsMoreCVQualified(exprqual, qual)) { + CError_Warning(CErrorStr220, expr->rtype, ENODE_QUALS(expr), type, (UInt32) qual); + } + } +} + +ENode *oldassignmentpromotion(ENode *expr, Type *type, short qual, Boolean flag) { + Boolean is_ref; + UInt32 ref_qual; + short orig_qual; + + is_ref = 0; + if (!IS_TYPE_MEMBERPOINTER(type)) { + if (IS_TYPE_REFERENCE(type)) { + if (ENODE_IS(expr, ECOND)) + expr = CExpr_LValue(expr, 0, 0); + expr = pointer_generation2(expr); + ref_qual = CParser_GetCVTypeQualifiers(expr->rtype, expr->flags); + is_ref = 1; + } else { + expr = pointer_generation(expr); + } + } + + if (ENODE_IS(expr, EMEMBER)) + expr = getpointertomemberfunc(expr, type, 1); + + if (!is_ref) + CExpr_ConstPointerCheck(expr, type, qual); + else + CExpr_ConstPointerCheck(expr, TPTR_TARGET(type), qual); + + if (!(assign_check(expr, type, orig_qual = qual, 1, 0, flag))) + return expr; + + if (is_ref) { + if (temp_reference_init) { + switch (TPTR_TARGET(type)->type) { + case TYPEPOINTER: + qual = TPTR_QUAL(TPTR_TARGET(type)); + } + if (!(qual & Q_CONST)) + CError_Warning(CErrorStr228); + } else { + if (ref_qual && ref_qual > CParser_GetCVTypeQualifiers(TPTR_TARGET(type), orig_qual)) + CError_Warning(CErrorStr259); + } + } + + return assign_node; +} + +ENode *argumentpromotion(ENode *expr, Type *type, short qual, Boolean flag) { + ENode *tmp; + ENodeList *list; + + if (IS_TYPE_CLASS(type) && CClass_ReferenceArgument(TYPE_CLASS(type))) { + if ((tmp = CExpr_IsTempConstruction(expr, type, NULL))) + return tmp; + + list = lalloc(sizeof(ENodeList)); + list->next = NULL; + list->node = expr; + tmp = CExpr_ConstructObject( + TYPE_CLASS(type), + create_temp_node(type), + list, 1, 1, 1, 1, 0); + return getnodeaddress(tmp, 0); + } + + return CExpr_AssignmentPromotion(expr, type, qual, flag); +} + +ENode *classargument(ENode *expr) { + ENodeList *list; + + if (CClass_CopyConstructor(TYPE_CLASS(expr->rtype))) { + list = lalloc(sizeof(ENodeList)); + list->next = NULL; + list->node = expr; + return CExpr_ConstructObject( + TYPE_CLASS(expr->rtype), + create_temp_node(expr->rtype), + list, 1, 1, 1, 1, 0); + } + + return expr; +} + +ENodeList *CExpr_ScanExpressionList(Boolean is_parens) { + ENodeList *list; + ENodeList *current; + + if (is_parens && tk == ')') + return NULL; + + list = current = lalloc(sizeof(ENodeList)); + + while (1) { + current->next = NULL; + current->node = assignment_expression(); + if (copts.old_argmatch && !ENODE_IS(current->node, EMEMBER)) + current->node = pointer_generation(current->node); + + if (is_parens) { + if (tk == ')') + break; + } else { + if (tk == ']') + break; + } + + if (tk != ',') { + CError_ErrorSkip(CErrorStr116); + break; + } + + tk = lex(); + current->next = lalloc(sizeof(ENodeList)); + current = current->next; + } + + return list; +} + +static ENode *skipcommaexpr(ENode *expr) { + while (ENODE_IS(expr, ECOMMA)) + expr = expr->data.diadic.right; + return expr; +} + +ENode *CExpr_DoExplicitConversion(Type *type, UInt32 qual, ENodeList *list) { + Object *obj; + ENode *tmp; + + if (!IS_TYPE_CLASS(type)) { + if (!list) + return do_typecast(nullnode(), type, qual); + if (list->next) + CError_Error(CErrorStr356); + return do_typecast(pointer_generation(list->node), type, qual); + } + + CDecl_CompleteType(type); + if (!(TYPE_CLASS(type)->flags & CLASS_COMPLETED)) + CError_Error(CErrorStr136, type, 0); + + CanCreateObject(type); + if (!list && CClass_IsPODClass(TYPE_CLASS(type))) { + obj = CParser_NewGlobalDataObject(NULL); + obj->name = CParser_GetUniqueName(); + obj->nspace = cscope_root; + obj->type = type; + obj->qual = qual; + obj->sclass = TK_STATIC; + CInit_DeclareData(obj, NULL, NULL, type->size); + + tmp = makemonadicnode(create_temp_node(type), EINDIRECT); + tmp->rtype = type; + tmp->flags = qual & ENODE_FLAG_QUALS; + return makediadicnode(tmp, create_objectnode(obj), EASS); + } + + return CExpr_ConstructObject(TYPE_CLASS(type), create_temp_node(type), list, 1, 1, 1, 1, 1); +} + +static ENode *CExpr_TemplArgDepCast(Type *type, UInt32 qual, ENodeList *args) { + ENode *expr = CExpr_NewTemplDepENode(TDE_CAST); + expr->data.templdep.u.cast.args = args; + expr->data.templdep.u.cast.type = type; + expr->data.templdep.u.cast.qual = qual; + return expr; +} + +static ENode *CExpr_ParseExplicitConversion(Type *type, UInt32 qual) { + ENodeList *args; + ENodeList *scan; + + if (IS_TEMPL_CLASS(type) && !CParser_CheckTemplateClassUsage(TEMPL_CLASS(type), 1)) + type = TYPE(&stsignedint); + + if (tk == '(') + tk = lex(); + else + CError_Error(CErrorStr114); + + args = CExpr_ScanExpressionList(1); + if (tk != ')') { + CError_Error(CErrorStr115); + return nullnode(); + } + + tk = lex(); + if (CTemplTool_IsTemplateArgumentDependentType(type)) + return CExpr_TemplArgDepCast(type, qual, args); + + for (scan = args; scan; scan = scan->next) { + if (CTemplTool_IsTemplateArgumentDependentExpression(scan->node)) + return CExpr_TemplArgDepCast(type, qual, args); + } + + return CExpr_DoExplicitConversion(type, qual, args); +} + +static ENode *CExpr_MemberVarAccess(BClassList *path, ObjMemberVar *var, ENode *expr) { + ENode *accessnode; + BClassList *varpath; + + CError_ASSERT(1152, path); + + if (TYPE_CLASS(path->type)->sominfo) + return CSOM_MemberVarAccess(path, var, expr); + + varpath = NULL; + if (var->has_path) + varpath = OBJ_MEMBER_VAR_PATH(var)->path; + accessnode = CExpr_GetClassAccessNode(path, varpath, expr, NULL, var->access, 1); + if (!accessnode) + return nullnode(); + + return CClass_AccessMember(accessnode, var->type, var->qual, var->offset); +} + +static Boolean CExpr_IsTemplateFunc(Object *obj) { + return IS_TEMPL_FUNC(obj->type); +} + +static ENode *CExpr_ExplicitTemplateArgCheck(NameResult *pr) { + NameSpaceObjectList *list; + NameSpaceObjectList *newhead; + NameSpaceObjectList *newlist; + ENode *expr; + + if (pr->obj_10) { + if (pr->obj_10->otype != OT_OBJECT || !CExpr_IsTemplateFunc(OBJECT(pr->obj_10))) + return NULL; + + list = lalloc(sizeof(NameSpaceObjectList)); + memclrw(list, sizeof(NameSpaceObjectList)); + list->object = pr->obj_10; + } else if (pr->nsol_14) { + for (list = pr->nsol_14; list; list = list->next) { + if (list->object->otype == OT_OBJECT && CExpr_IsTemplateFunc(OBJECT(list->object))) { + newhead = newlist = galloc(sizeof(NameSpaceObjectList)); + *newlist = *list; + newlist->next = NULL; + while ((list = list->next)) { + if (list->object->otype == OT_OBJECT && CExpr_IsTemplateFunc(OBJECT(list->object))) { + newlist->next = galloc(sizeof(NameSpaceObjectList)); + newlist = newlist->next; + *newlist = *list; + newlist->next = NULL; + } + } + list = newhead; + break; + } + } + if (!list) + return NULL; + } else { + return NULL; + } + + expr = CExpr_NewENode(EOBJLIST); + expr->rtype = OBJECT(list->object)->type; + expr->data.objlist.list = list; + expr->data.objlist.templargs = CTempl_ParseUncheckTemplArgs(NULL, 0); + + tk = lex(); + return expr; +} + +ENode *CExpr_MakeNameLookupResultExpr(NameResult *pr) { + ENode *expr; + + if (pr->obj_10) { + switch (pr->obj_10->otype) { + case OT_OBJECT: + CClass_CheckObjectAccess(pr->bcl_18, OBJECT(pr->obj_10)); + return create_objectnode(OBJECT(pr->obj_10)); + case OT_ENUMCONST: + CClass_CheckEnumAccess(pr->bcl_18, OBJ_ENUM_CONST(pr->obj_10)); + expr = lalloc(sizeof(ENode)); + expr->type = EINTCONST; + expr->cost = 0; + expr->flags = 0; + expr->rtype = OBJ_ENUM_CONST(pr->obj_10)->type; + expr->data.intval = OBJ_ENUM_CONST(pr->obj_10)->val; + return expr; + case OT_MEMBERVAR: + CError_Error(CErrorStr221); + return nullnode(); + default: + CError_FATAL(1268); + } + } + + if (pr->nsol_14) { + expr = CExpr_NewENode(EOBJLIST); + expr->rtype = OBJECT(pr->nsol_14->object)->type; + expr->data.objlist.list = pr->nsol_14; + return expr; + } + + CError_FATAL(1278); + return NULL; +} + +static Type *CExpr_NewPTMType(EMemberInfo *member, Object *obj) { + TypeMemberPointer *ptm; + TypeMemberFunc *tmethod; + BClassList *path; + + ptm = galloc(sizeof(TypeMemberPointer)); + memclrw(ptm, sizeof(TypeMemberPointer)); + ptm->type = TYPEMEMBERPOINTER; + + if (member->list->object->otype == OT_MEMBERVAR) { + path = member->path; + while (path->next) + path = path->next; + ptm->size = 4; + ptm->ty2 = path->type; + ptm->ty1 = OBJ_MEMBER_VAR(member->list->object)->type; + } else { + if (!obj) { + CError_ASSERT(1306, member->list->object->otype == OT_OBJECT); + obj = OBJECT(member->list->object); + CError_ASSERT(1308, IS_TYPE_FUNC(obj->type)); + } + + tmethod = galloc(sizeof(TypeMemberFunc)); + memclrw(tmethod, sizeof(TypeMemberFunc)); + *tmethod = *TYPE_METHOD(obj->type); + + CError_ASSERT(1312, tmethod->args); + + tmethod->args = tmethod->args->next; + CDecl_MakePTMFuncType(TYPE_FUNC(tmethod)); + tmethod->flags &= ~FUNC_DEFINED; + + ptm->size = 12; + ptm->ty2 = TYPE(tmethod->theclass); + ptm->ty1 = TYPE(tmethod); + } + + return TYPE(ptm); +} + +static ENode *CExpr_ParseNameResultExpr(NameResult *pr, ENode *expr, Boolean flag1, Boolean flag2) { + ENode *result; + ENode *ta_expr; + ObjEnumConst *oec; + TemplateAction *act; + EMemberInfo *member; + NameSpaceObjectList *list; + Object *obj; + TypeFunc *tfunc; + SInt32 val; + + if (pr->type) { + if (copts.cplusplus) { + if (IS_TYPE_TEMPLATE(pr->type)) { + if (TYPE_TEMPLATE(pr->type)->dtype == TEMPLDEP_ARGUMENT && TYPE_TEMPLATE(pr->type)->u.pid.type == TPT_NONTYPE) { + result = CExpr_NewTemplDepENode(TDE_PARAM); + result->data.templdep.u.pid = TYPE_TEMPLATE(pr->type)->u.pid; + tk = lex(); + return result; + } + if (TYPE_TEMPLATE(pr->type)->dtype == TEMPLDEP_QUALNAME && !pr->x20) { + result = CExpr_NewTemplDepENode(TDE_QUALNAME); + result->data.templdep.u.qual.type = TYPE_TEMPLATE(pr->type)->u.qual.type; + result->data.templdep.u.qual.name = TYPE_TEMPLATE(pr->type)->u.qual.name; + tk = lex(); + return result; + } + } + tk = lex(); + return CExpr_ParseExplicitConversion(pr->type, pr->qual); + } + CError_ErrorSkip(CErrorStr141); + tk = lex(); + return nullnode(); + } + + if (pr->obj_10) { + switch (pr->obj_10->otype) { + case OT_OBJECT: + if (OBJECT(pr->obj_10)->nspace && OBJECT(pr->obj_10)->nspace->theclass && (OBJECT(pr->obj_10)->nspace->theclass->flags & CLASS_IS_TEMPL)) { + result = CExpr_NewTemplDepENode(TDE_OBJ); + result->data.templdep.u.obj = OBJECT(pr->obj_10); + tk = lex(); + return result; + } + if (!expr || !IS_TEMPL_FUNC(OBJECT(pr->obj_10)->type)) { + if (!IS_TYPE_NONSTATIC_METHOD(OBJECT(pr->obj_10)->type)) { + tk = lex(); + if (tk == '<' && (ta_expr = CExpr_ExplicitTemplateArgCheck(pr))) + return ta_expr; + if (OBJECT(pr->obj_10)->datatype == DLOCAL && OBJECT(pr->obj_10)->u.var.info->func != cscope_currentfunc) { + CError_Error(CErrorStr330); + return nullnode(); + } + if (OBJECT(pr->obj_10)->datatype == DEXPR) { + result = CInline_CopyExpression(OBJECT(pr->obj_10)->u.expr, CopyMode0); + if (IS_TYPE_POINTER_ONLY(result->rtype) && ENODE_IS(result, EINTCONST)) { + result = makemonadicnode(result, ETYPCON); + result->data.monadic->rtype = TYPE(&stunsignedlong); + } + return result; + } + CClass_CheckObjectAccess(pr->bcl_18, OBJECT(pr->obj_10)); + if (tk == '(' && flag2 && OBJECT(pr->obj_10)->datatype == DFUNC && copts.cplusplus && !pr->x1D && !IS_TYPEFUNC_METHOD(TYPE_FUNC(OBJECT(pr->obj_10)->type))) { + result = CExpr_NewENode(EOBJLIST); + result->rtype = OBJECT(pr->obj_10)->type; + result->data.objlist.list = galloc(sizeof(NameSpaceObjectList)); + result->data.objlist.list->next = pr->nsol_14; + result->data.objlist.list->object = pr->obj_10; + result->data.objlist.name = OBJECT(pr->obj_10)->name; + return result; + } + + result = create_objectnode(OBJECT(pr->obj_10)); + if (expr) { + while (ENODE_IS(expr, EINDIRECT)) + expr = expr->data.monadic; + switch (expr->type) { + case EINTCONST: + case EOBJREF: + case EOBJLIST: + break; + default: + result = makecommaexpression(expr, result); + } + } + return result; + } + if (CClass_IsDestructor(OBJECT(pr->obj_10))) { + if ((tk = lex()) != '(') { + CError_Error(CErrorStr114); + return nullnode(); + } + if ((tk = lex()) != ')') { + CError_Error(CErrorStr115); + return nullnode(); + } + if (!expr && (!cscope_currentfunc || !cscope_currentclass || !cscope_is_member_func)) { + CError_Error(CErrorStr221); + return nullnode(); + } + if (pr->isambig) + CError_Error(CErrorStr188); + + if ((expr = CExpr_GetClassAccessNode(pr->bcl_18, NULL, expr, OBJECT(pr->obj_10), pr->obj_10->access, 1))) { + tk = lex(); + return CABI_DestroyObject(OBJECT(pr->obj_10), expr->data.monadic, 1, pr->x1D, 0); + } + } + } + break; + case OT_ENUMCONST: + CClass_CheckEnumAccess(pr->bcl_18, OBJ_ENUM_CONST(pr->obj_10)); + oec = OBJ_ENUM_CONST(pr->obj_10); + if (CInt64_IsZero(&oec->val) && IS_TYPE_ENUM(oec->type) && TYPE_ENUM(oec->type)->nspace && TYPE_ENUM(oec->type)->nspace->theclass && (TYPE_ENUM(oec->type)->nspace->theclass->flags & CLASS_IS_TEMPL)) { + val = 0; + expr = NULL; + for (act = TEMPL_CLASS(TYPE_ENUM(oec->type)->nspace->theclass)->actions; act; act = act->next) { + if (act->type == TAT_ENUMERATOR) { + if (act->u.enumerator.initexpr) { + expr = act->u.enumerator.initexpr; + val = 0; + } else { + val++; + } + if (act->u.enumerator.objenumconst == oec) { + CError_ASSERT(1521, expr); + expr = CInline_CopyExpression(expr, CopyMode0); + if (val) + expr = makediadicnode(expr, intconstnode(TYPE(&stsignedlong), val), EADD); + tk = lex(); + return expr; + } + } + } + } + result = lalloc(sizeof(ENode)); + result->type = EINTCONST; + result->cost = 0; + result->flags = 0; + result->rtype = OBJ_ENUM_CONST(pr->obj_10)->type; + result->data.intval = OBJ_ENUM_CONST(pr->obj_10)->val; + tk = lex(); + return result; + case OT_MEMBERVAR: + if (!flag1 || expr || !pr->x1D) { + if (pr->isambig) + CError_Error(CErrorStr188); + result = checkreference(CExpr_MemberVarAccess(pr->bcl_18, OBJ_MEMBER_VAR(pr->obj_10), expr)); + tk = lex(); + return result; + } + break; + default: + CError_FATAL(1552); + } + + member = lalloc(sizeof(EMemberInfo)); + memclrw(member, sizeof(EMemberInfo)); + member->path = pr->bcl_18; + member->expr = expr; + member->pr_1D = pr->x1D; + member->isambig = pr->isambig; + if ((tk = lex()) == '<' && (ta_expr = CExpr_ExplicitTemplateArgCheck(pr))) { + CError_ASSERT(1564, ENODE_IS(ta_expr, EOBJLIST)); + member->list = ta_expr->data.objlist.list; + member->templargs = ta_expr->data.objlist.templargs; + } else { + member->list = galloc(sizeof(NameSpaceObjectList)); + member->list->next = NULL; + member->list->object = pr->obj_10; + } + + result = CExpr_NewENode(EMEMBER); + result->data.emember = member; + result->rtype = &stvoid; + return result; + } + + if (pr->nsol_14) { + if ((tk = lex()) == '<' && (ta_expr = CExpr_ExplicitTemplateArgCheck(pr))) { + CError_ASSERT(1591, ENODE_IS(ta_expr, EOBJLIST)); + for (list = ta_expr->data.objlist.list; list; list = list->next) { + if (list->object->otype == OT_OBJECT && IS_TYPE_NONSTATIC_METHOD(OBJECT(list->object)->type)) { + member = lalloc(sizeof(EMemberInfo)); + memclrw(member, sizeof(EMemberInfo)); + + member->path = pr->bcl_18; + member->expr = expr; + member->list = ta_expr->data.objlist.list; + member->templargs = ta_expr->data.objlist.templargs; + member->pr_1D = pr->x1D; + member->isambig = pr->isambig; + + result = CExpr_NewENode(EMEMBER); + result->data.emember = member; + result->rtype = &stvoid; + return result; + } + } + return ta_expr; + } + + for (list = pr->nsol_14; list; list = list->next) { + if (list->object->otype == OT_OBJECT && IS_TYPE_NONSTATIC_METHOD(OBJECT(list->object)->type)) { + member = lalloc(sizeof(EMemberInfo)); + memclrw(member, sizeof(EMemberInfo)); + + member->path = pr->bcl_18; + member->expr = expr; + member->list = pr->nsol_14; + member->pr_1D = pr->x1D; + member->isambig = pr->isambig; + + result = CExpr_NewENode(EMEMBER); + result->data.emember = member; + result->rtype = &stvoid; + return result; + } + } + + if (tk == '<' && (ta_expr = CExpr_ExplicitTemplateArgCheck(pr))) + return ta_expr; + + result = CExpr_NewENode(EOBJLIST); + result->rtype = OBJECT(pr->nsol_14->object)->type; + result->data.objlist.list = pr->nsol_14; + if (tk == '(' && copts.cplusplus && flag2 && !pr->x1D && pr->nsol_14->object->otype == OT_OBJECT) + result->data.objlist.name = OBJECT(pr->nsol_14->object)->name; + return result; + } + + if (pr->name_4) { + if (copts.cplusplus && flag2) { + if (lookahead() == '(') { + result = CExpr_NewENode(EOBJLIST); + result->rtype = &stvoid; + result->data.objlist.name = pr->name_4; + tk = lex(); + return result; + } + CError_Error(CErrorStr140, pr->name_4->name); + tk = lex(); + return nullnode(); + } + + if (lookahead() != '(') { + CError_Error(CErrorStr140, pr->name_4->name); + tk = lex(); + return nullnode(); + } + + if (copts.checkprotos) + CError_Error(CErrorStr178); + + tfunc = galloc(sizeof(TypeFunc)); + memclrw(tfunc, sizeof(TypeFunc)); + tfunc->type = TYPEFUNC; + tfunc->functype = TYPE(&stsignedint); + tfunc->args = &oldstyle; + CDecl_SetFuncFlags(tfunc, 0); + + obj = CParser_NewFunctionObject(NULL); + obj->name = pr->name_4; + obj->sclass = TK_EXTERN; + obj->nspace = cscope_root; + obj->type = TYPE(tfunc); + + CScope_AddGlobalObject(obj); + tk = lex(); + return create_objectrefnode(obj); + } + + CError_FATAL(1711); + return NULL; +} + +static ENode *CExpr_ParseRotate(Boolean is_right) { + ENode *expr1; + ENode *expr2; + + if (lex() != '(') { + CError_Error(CErrorStr114); + return nullnode(); + } + + tk = lex(); + expr1 = assignment_expression(); + + if (tk != ',') { + CError_Error(CErrorStr116); + return nullnode(); + } + + tk = lex(); + expr2 = assignment_expression(); + + if (tk != ')') { + CError_Error(CErrorStr115); + return nullnode(); + } + + if (!IS_TYPE_INT(expr1->rtype)) + expr1 = forceintegral(expr1); + expr2 = integralpromote(expr2); + + tk = lex(); + if (iszero(expr1) || iszero(expr2)) + return expr1; + + return makediadicnode(expr1, expr2, is_right ? EROTR : EROTL); +} + +static ENode *CExpr_ParseNextArg(void) { + NameSpaceObjectList *list; + NameResult pr; + ENode *expr; + SInt32 rounded_size; + + if ((tk = lex()) != '(') { + CError_Error(CErrorStr114); + return nullnode(); + } + if ((tk = lex()) != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + return nullnode(); + } + + list = CScope_FindObjectList(&pr, tkidentifier); + if (!list) { + CError_Error(CErrorStr140, tkidentifier->name); + return nullnode(); + } + + if (list->object->otype != OT_OBJECT || OBJECT(list->object)->datatype != DLOCAL) { + CError_Error(CErrorStr140, tkidentifier->name); + return nullnode(); + } + + rounded_size = CMach_RoundedSizeOf(OBJECT(list->object)); + expr = CExpr_MakeObjRefNode(OBJECT(list->object), 1); + expr = makediadicnode(expr, intconstnode(CABI_GetPtrDiffTType(), rounded_size), EADD); + expr->rtype = TYPE(&void_ptr); + + if ((tk = lex()) != ')') { + CError_Error(CErrorStr115); + return expr; + } else { + tk = lex(); + return expr; + } +} + +static ENode *CExpr_ParseVecStep(void) { + ENode *expr; + Type *type; + SInt32 value; + DeclInfo di; + + expr = intconstnode(TYPE(&stsignedint), 0); + if ((tk = lex()) == '(') { + if (tk == '(' && islookaheaddeclaration()) { + tk = lex(); + memclrw(&di, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&di, 0); + scandeclarator(&di); + if (di.name) + CError_Error(CErrorStr121); + + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + + type = di.thetype; + if (IS_TYPE_REFERENCE(type)) + type = TPTR_TARGET(type); + } else { + expr = unary_expression(); + if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EBITFIELD)) + CError_Error(CErrorStr144); + type = expr->rtype; + } + + CDecl_CompleteType(type); + if (IS_TYPE_VECTOR(type)) { + switch (TYPE_STRUCT(type)->stype) { + case STRUCT_VECTOR_UCHAR: + case STRUCT_VECTOR_SCHAR: + case STRUCT_VECTOR_BCHAR: + value = 16; + break; + case STRUCT_VECTOR_USHORT: + case STRUCT_VECTOR_SSHORT: + case STRUCT_VECTOR_BSHORT: + case STRUCT_VECTOR_PIXEL: + value = 8; + break; + default: + value = 4; + } + expr = intconstnode(TYPE(&stsignedint), value); + } else { + PPCError_Error(PPCErrorStr104, "vec_step", "vec_step", type, 0); + } + } else { + CError_Error(CErrorStr114); + } + + return expr; +} + +static SInt32 CExpr_BuiltInComputeAlign(Type *type) { + return CMach_GetTypeAlign(type); +} + +static SInt32 CExpr_AtomTypeID(IntegralType what) { + switch (what) { + case IT_BOOL: return 1; + case IT_CHAR: return 2; + case IT_SCHAR: return 3; + case IT_UCHAR: return 4; + case IT_WCHAR_T: return 5; + case IT_SHORT: return 6; + case IT_USHORT: return 7; + case IT_INT: return 8; + case IT_UINT: return 9; + case IT_LONG: return 10; + case IT_ULONG: return 10; + case IT_LONGLONG: return 12; + case IT_ULONGLONG: return 13; + case IT_FLOAT: return 14; + case IT_SHORTDOUBLE: return 15; + case IT_DOUBLE: return 16; + case IT_LONGDOUBLE: return 17; + case IT_17: return 32; + case IT_18: return 33; + case IT_19: return 34; + case IT_20: return 35; + case IT_21: return 36; + case IT_22: return 37; + case IT_23: return 38; + case IT_24: return 39; + default: + CError_FATAL(1976); + return 0; + } +} + +static SInt32 CExpr_BuiltInComputeType(Type *type) { + switch (type->type) { + case TYPEINT: + return 0x100 | CExpr_AtomTypeID(TYPE_INTEGRAL(type)->integral); + case TYPEFLOAT: + return 0x200 | CExpr_AtomTypeID(TYPE_INTEGRAL(type)->integral); + case TYPEENUM: + return 0x400 | (CExpr_BuiltInComputeType(TYPE_ENUM(type)->enumtype) & 0xFF); + case TYPEPOINTER: + return 0x800; + case TYPEARRAY: + return 0x1000; + case TYPESTRUCT: + return 0x2000; + case TYPECLASS: + return 0x2000; + case TYPEMEMBERPOINTER: + return 0x4000; + case TYPEFUNC: + return 0x8000; + default: + CError_Error(CErrorStr146); + case TYPEVOID: + return 0; + } +} + +static SInt32 CExpr_BuiltInClassifyType(Type *type) { + switch (type->type) { + case TYPEVOID: return 0; + case TYPEFUNC: return 10; + case TYPEENUM: return 3; + case TYPEINT: return 1; + case TYPEFLOAT: return 8; + case TYPEPOINTER: case TYPEMEMBERPOINTER: return 5; + case TYPEARRAY: return 14; + case TYPESTRUCT: return 12; + case TYPECLASS: return 12; + case TYPEBITFIELD: return -1; + case TYPETEMPLATE: return -1; + default: return -1; + } +} + +static SInt32 CExpr_BuiltInComputeVArgType(Type *type) { + switch (type->type) { + case TYPEINT: + case TYPEENUM: + return 0; + case TYPEFLOAT: + return 1; + default: + return 2; + } +} + +static Type *CExpr_ParseTypeExpression(Boolean *outflag) { + ENode *expr; + Type *type; + DeclInfo di; + + tk = lex(); + if (tk == '(' && islookaheaddeclaration()) { + tk = lex(); + memclrw(&di, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&di, 0); + scandeclarator(&di); + if (di.name) + CError_Error(CErrorStr121); + + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + + type = di.thetype; + if (IS_TYPE_REFERENCE(type)) + type = TPTR_TARGET(type); + } else { + expr = unary_expression(); + if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EBITFIELD)) + CError_Error(CErrorStr144); + + if (outflag) + *outflag = ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval); + + type = expr->rtype; + } + + CDecl_CompleteType(type); + return type; +} + +static ENode *CExpr_ParseBuiltin(SInt32 (*parser)(Type *)) { + ENode *expr; + expr = intconstnode(TYPE(&stsignedint), 0); + CInt64_SetLong(&expr->data.intval, parser(CExpr_ParseTypeExpression(NULL))); + return expr; +} + +static ENode *CExpr_ParseBuiltin_isintconst(void) { + ENode *expr; + expr = intconstnode(TYPE(&stsignedint), 0); + + tk = lex(); + if (tk != '(') + CError_ErrorSkip(CErrorStr121); + else + tk = lex(); + + if (ENODE_IS(expression(), EINTCONST)) + CInt64_SetLong(&expr->data.intval, 1); + + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + + return expr; +} + +static ENode *primary_expression(Boolean flag) { + NameResult pr; + ENode *expr; + + switch (tk) { + case TK_TRUE: + expr = lalloc(sizeof(ENode)); + expr->type = EINTCONST; + expr->cost = 0; + expr->flags = 0; + expr->rtype = TYPE(&stbool); + CInt64_SetULong(&expr->data.intval, 1); + tk = lex(); + return expr; + case TK_FALSE: + expr = lalloc(sizeof(ENode)); + expr->type = EINTCONST; + expr->cost = 0; + expr->flags = 0; + expr->rtype = TYPE(&stbool); + CInt64_SetULong(&expr->data.intval, 0); + tk = lex(); + return expr; + case TK_INTCONST: + expr = lalloc(sizeof(ENode)); + expr->type = EINTCONST; + expr->cost = 0; + expr->flags = 0; + expr->rtype = atomtype(); + expr->data.intval = tkintconst; + tk = lex(); + return expr; + case TK_FLOATCONST: + expr = lalloc(sizeof(ENode)); + expr->type = EFLOATCONST; + expr->cost = 0; + expr->flags = 0; + expr->rtype = atomtype(); + expr->data.floatval = tkfloatconst; + tk = lex(); + return expr; + case TK_STRING: + expr = CExpr_NewENode(ESTRINGCONST); + expr->rtype = CDecl_NewArrayType(ispascalstring ? TYPE(&stunsignedchar) : TYPE(&stchar), tksize); + expr->data.string.size = tksize; + expr->data.string.data = tkstring; + expr->data.string.ispascal = ispascalstring; + if (copts.const_strings) + expr->flags = ENODE_FLAG_CONST; + expr = makemonadicnode(expr, EINDIRECT); + expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); + tk = lex(); + return expr; + case TK_STRING_WIDE: + expr = CExpr_NewENode(ESTRINGCONST); + expr->rtype = CDecl_NewArrayType(CParser_GetWCharType(), tksize); + expr->data.string.size = tksize; + expr->data.string.data = tkstring; + expr->data.string.ispascal = ispascalstring; + if (copts.const_strings) + expr->flags = ENODE_FLAG_CONST; + expr = makemonadicnode(expr, EINDIRECT); + expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); + tk = lex(); + return expr; + case TK_THIS: + case TK_SELF: + expr = CClass_CreateThisSelfExpr(); + if (!expr) + expr = nullnode(); + tk = lex(); + return expr; + case TK_AT_SELECTOR: + return CObjC_ParseSelectorExpression(); + case TK_AT_ENCODE: + return CObjC_ParseEncodeExpression(); + case TK_AT_PROTOCOL: + return CObjC_ParseProtocolExpression(); + case '@': + if (copts.objective_c) + return CObjC_ParseAtExpression(); + break; + case '(': + tk = lex(); + expr = s_expression(); + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + if (ENODE_IS(expr, EASS)) + expr->flags = expr->flags | ENODE_FLAG_80; + return expr; + case '[': + if (copts.objective_c) + return CObjC_ParseMessageExpression(); + break; + case TK_IDENTIFIER: + if (tkidentifier->name[0] == '_' && tkidentifier->name[1] == '_') { + if (!strcmp(tkidentifier->name, "__builtin_align")) + return CExpr_ParseBuiltin(CExpr_BuiltInComputeAlign); + if (!strcmp(tkidentifier->name, "__builtin_ntype")) + return CExpr_ParseBuiltin(CExpr_BuiltInComputeType); + if (!strcmp(tkidentifier->name, "__builtin_type") || !strcmp(tkidentifier->name, "__builtin_vargtype")) + return CExpr_ParseBuiltin(CExpr_BuiltInComputeVArgType); + if (!strcmp(tkidentifier->name, "__builtin_classify_type")) + return CExpr_ParseBuiltin(CExpr_BuiltInClassifyType); + if (!strcmp(tkidentifier->name, "__builtin_next_arg")) + return CExpr_ParseNextArg(); + } + if (copts.altivec_model && !strcmp("vec_step", tkidentifier->name)) + return CExpr_ParseVecStep(); + case '~': + case TK_OPERATOR: + case TK_INHERITED: + case TK_COLON_COLON: + if (CScope_ParseExprName(&pr)) + return CExpr_ParseNameResultExpr(&pr, NULL, flag, 1); + tk = lex(); + return nullnode(); + } + + CError_ErrorSkip(CErrorStr141); + return nullnode(); +} + +static ENode *CExpr_SimpleExplicitConversion(void) { + DeclInfo di; + + memclrw(&di, sizeof(DeclInfo)); + + if (!copts.cpp_extensions && tk != TK_UU_TYPEOF_UU && tk != TK_TYPENAME && lookahead() != '(') + CError_Error(CErrorStr114); + + CParser_GetDeclSpecs(&di, 0); + return CExpr_ParseExplicitConversion(di.thetype, di.qual); +} + +static ENode *CExpr_NewPTMFCall(void) { + tk = lex(); + CExpr_ScanExpressionList(1); + + if (tk != ')') { + CError_Error(CErrorStr115); + return nullnode(); + } else { + CError_FATAL(2465); + return nullnode(); + } +} + +static ENode *call_ptmf(ENode *expr) { + Type *rettype; + ENodeList *args; + ENodeList *list1; + ENodeList *list2; + Object *callobj; + + rettype = TYPE_FUNC(TPTR_TARGET(expr->data.mfpointer.mfpointer->rtype))->functype; + tk = lex(); + args = CExpr_ScanExpressionList(1); + + if (tk != ')') { + CError_Error(CErrorStr115); + return nullnode(); + } + + if (IS_TYPE_STRUCT(rettype) || IS_TYPE_CLASS(rettype) || IS_TYPE_12BYTES_MEMBERPOINTER(rettype)) + callobj = rt_ptmf_scall4; + else + callobj = rt_ptmf_scall; + + list1 = lalloc(sizeof(ENodeList)); + list1->next = args; + list1->node = expr->data.mfpointer.accessnode->data.monadic; + + list2 = lalloc(sizeof(ENodeList)); + list2->next = list1; + list2->node = expr->data.mfpointer.mfpointer->data.monadic; + + if (!copts.old_argmatch) { + CError_ASSERT(2568, IS_TYPE_POINTER_ONLY(list2->node->rtype)); + list2->node->rtype = TYPE(&void_ptr); + } + + expr = CExpr_GenericPtmfCall( + callobj, + TYPE_FUNC(TPTR_TARGET(expr->data.mfpointer.mfpointer->rtype)), + list2); + tk = lex(); + return expr; +} + +static ENode *CExpr_DummyDestr(ENode *expr) { + SInt32 state; + NameResult pr; + DeclInfo di; + NameSpace *nspace; + + CPrep_TokenStreamGetState(&state); + nspace = cscope_current; + if ((tk = lex()) == TK_COLON_COLON) { + nspace = cscope_root; + tk = lex(); + } else if (tk != '~' && tk != TK_IDENTIFIER && !(tk >= TK_AUTO && tk <= TK_BYREF)) { + CPrep_TokenStreamSetCurState(&state); + return NULL; + } + +loop: + if (tk == '~') + goto is_tilde; + if (tk == TK_IDENTIFIER) { + if (CScope_FindTypeName(nspace, tkidentifier, &pr)) { + tk = lex(); + if (pr.nspace_0) { + if (tk == TK_COLON_COLON) { + tk = lex(); + nspace = pr.nspace_0; + goto loop; + } + } else if (IS_TYPE_CLASS(pr.type) && tk == TK_COLON_COLON) { + tk = lex(); + nspace = TYPE_CLASS(pr.type)->nspace; + goto loop; + } else { + if (!is_typesame(pr.type, expr->rtype)) + CError_Error(CErrorStr146); + if (tk == TK_COLON_COLON && ((tk = lex()) == '~') && ((tk = lex()) == TK_IDENTIFIER)) { + parse_dtor: + if (CScope_FindTypeName(nspace, tkidentifier, &pr) && !pr.nspace_0) { + if (!is_typesame(pr.type, expr->rtype)) + CError_Error(CErrorStr146); + tk = lex(); + goto parsed; + } + } + } + } + } else if (tk >= TK_AUTO && tk <= TK_BYREF) { + memclrw(&di, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&di, 0); + if (di.storageclass || di.qual || !is_typesame(di.thetype, expr->rtype)) + CError_Error(CErrorStr146); + if (tk == TK_COLON_COLON && ((tk = lex()) == '~')) { + is_tilde: + if ((tk = lex()) == TK_IDENTIFIER) + goto parse_dtor; + memclrw(&di, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&di, 0); + if (di.storageclass || !is_typesame(di.thetype, expr->rtype)) + CError_Error(CErrorStr146); + goto parsed; + } + } + + CError_Error(CErrorStr141); + return NULL; + +parsed: + if (tk == '(') { + if ((tk = lex()) != ')') + CError_Error(CErrorStr115); + else + tk = lex(); + } else { + CError_Error(CErrorStr114); + } + + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = &stvoid; + return expr; +} + +static ENode *postfix_expression(Boolean flag) { + NameResult pr; + Conversion conv; + ENode *expr; + ENode *subexpr; + ENode *funcexpr; + ENodeList *args; + ENode *copy; + ENode *tmp; + StructMember *member; + + if (copts.cplusplus) { + switch (tk) { + case TK_VOID: + case TK_CHAR: + case TK_SHORT: + case TK_INT: + case TK_LONG: + case TK_FLOAT: + case TK_DOUBLE: + case TK_SIGNED: + case TK_UNSIGNED: + case TK_UNK_113: + case TK_UNK_114: + case TK_UNK_115: + case TK_UNK_116: + case TK_UNK_117: + case TK_UNK_118: + case TK_UNK_119: + case TK_UNK_11A: + case TK_UU_TYPEOF_UU: + case TK_BOOL: + case TK_WCHAR_T: + case TK_TYPENAME: + expr = CExpr_SimpleExplicitConversion(); + break; + default: + expr = primary_expression(flag); + break; + case TK_CONST_CAST: + expr = CRTTI_Parse_const_cast(); + break; + case TK_DYNAMIC_CAST: + expr = CRTTI_Parse_dynamic_cast(); + break; + case TK_REINTERPRET_CAST: + expr = CRTTI_Parse_reinterpret_cast(); + break; + case TK_STATIC_CAST: + expr = CRTTI_Parse_static_cast(); + break; + case TK_TYPEID: + expr = CRTTI_ParseTypeID(); + break; + } + } else { + expr = primary_expression(flag); + } + +loop: + switch (tk) { + case '[': + expr = pointer_generation(expr); + tk = lex(); + subexpr = expression(); + if (copts.cplusplus && CExpr_CheckOperator('[', expr, subexpr, &conv)) { + if ((expr = conv.x0)) { + if (tk != ']') + CError_ErrorSkip(CErrorStr125); + else + tk = lex(); + goto loop; + } + + CError_ASSERT(2753, expr = conv.left); + CError_ASSERT(2754, subexpr = conv.right); + } + + if (IS_TYPE_POINTER(expr->rtype)) { + expr = padd(expr, subexpr); + } else if (IS_TYPE_POINTER(subexpr->rtype)) { + expr = padd(subexpr, expr); + } else { + CError_Error(CErrorStr148); + goto dont_do_indirect; + } + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = TPTR_TARGET(expr->rtype); + dont_do_indirect: + if (tk != ']') + CError_ErrorSkip(CErrorStr125); + else + tk = lex(); + goto loop; + + case '(': + funcexpr = CExpr_PointerGeneration(expr); + if (copts.cplusplus) { + if (CExpr_CheckOperator('(', funcexpr, NULL, &conv)) { + CError_ASSERT(2775, expr = conv.x0); + goto loop; + } + if (ENODE_IS(funcexpr, EMFPOINTER)) { + expr = checkreference(call_ptmf(funcexpr)); + goto loop; + } + } + + tk = lex(); + args = CExpr_ScanExpressionList(1); + if (tk != ')') + CError_Error(CErrorStr115); + + if (ENODE_IS(funcexpr, ETEMPLDEP)) { + expr = CExpr_NewENode(EFUNCCALL); + expr->rtype = &sttemplexpr; + expr->data.funccall.funcref = funcexpr; + expr->data.funccall.args = args; + expr->data.funccall.functype = &rt_func; + tk = lex(); + } else { + expr = checkreference(CExpr_MakeFunctionCall(funcexpr, args)); + tk = lex(); + } + goto loop; + + case TK_ARROW: + expr = pointer_generation(expr); + if (copts.cplusplus) { + while (IS_TYPE_CLASS(expr->rtype) && CExpr_CheckOperator(TK_ARROW, expr, NULL, &conv)) { + CError_ASSERT(2810, subexpr = conv.x0); + expr = pointer_generation(subexpr); + } + } + + if (!IS_TYPE_POINTER(expr->rtype)) { + CError_ErrorSkip(CErrorStr148); + return expr; + } + + if (copts.cplusplus && copts.objective_c && CObjC_IsType_id(expr->rtype)) { + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = TPTR_TARGET(expr->rtype); + if ((subexpr = CObjC_CheckModernSendMessage(NULL, expr))) + return subexpr; + } else { + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = TPTR_TARGET(expr->rtype); + } + case '.': + expr = pointer_generation(expr); + if (IS_TYPE_CLASS(expr->rtype)) { + CDecl_CompleteType(expr->rtype); + if (TYPE_CLASS(expr->rtype)->objcinfo && copts.cplusplus && (subexpr = CObjC_CheckModernSendMessage(TYPE_CLASS(expr->rtype), expr))) + return subexpr; + + if (!(TYPE_CLASS(expr->rtype)->flags & CLASS_COMPLETED)) + CError_Error(CErrorStr136, expr->rtype, 0); + + if ((tk = lex()) == TK_TEMPLATE && (tk = lex()) != TK_IDENTIFIER) + CError_Error(CErrorStr107); + + if (CScope_ParseMemberName(TYPE_CLASS(expr->rtype), &pr, 0)) { + if (pr.x1C) { + if ((tk = lex()) == '(') { + if ((tk = lex()) != ')') + CError_Error(CErrorStr115); + else + tk = lex(); + } else { + CError_Error(CErrorStr114); + } + + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = &stvoid; + } else { + expr = checkreference(CExpr_ParseNameResultExpr(&pr, expr, 0, 0)); + } + } + goto loop; + } + if (!IS_TYPE_STRUCT(expr->rtype) || TYPE_STRUCT(expr->rtype)->stype > STRUCT_TYPE_MAX) { + if (copts.cplusplus && (subexpr = CExpr_DummyDestr(expr))) + return subexpr; + CError_ErrorSkip(CErrorStr149); + return expr; + } + if (!ENODE_IS(expr, EINDIRECT)) { + subexpr = CExpr_NewETEMPNode(expr->rtype, 1); + copy = lalloc(sizeof(ENode)); + *copy = *subexpr; + + tmp = makemonadicnode(subexpr, EINDIRECT); + tmp->rtype = expr->rtype; + + tmp = makediadicnode(tmp, expr, EASS); + tmp = makediadicnode(tmp, copy, ECOMMA); + tmp->rtype = copy->rtype; + + tmp = makemonadicnode(tmp, EINDIRECT); + tmp->rtype = expr->rtype; + expr = tmp; + } + if ((tk = lex()) != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + return expr; + } + + member = ismember(TYPE_STRUCT(expr->rtype), tkidentifier); + if (!member) { + if (!expr->rtype->size) + CError_Error(CErrorStr136, expr->rtype, 0); + else + CError_Error(CErrorStr150, tkidentifier->name); + return expr; + } + + if (!IS_TYPE_POINTER(expr->data.monadic->rtype)) { + CError_ErrorSkip(CErrorStr149); + return expr; + } + + expr = checkreference(CClass_AccessMember(expr, member->type, member->qual, member->offset)); + tk = lex(); + goto loop; + + case TK_INCREMENT: + tmp = pointer_generation(expr); + if (copts.cplusplus && CExpr_CheckOperator(TK_INCREMENT, tmp, nullnode(), &conv)) { + if ((expr = conv.x0)) { + tk = lex(); + goto loop; + } + CError_ASSERT(2952, tmp = conv.left); + } + tmp = CExpr_LValue(tmp, 1, 1); + if (tmp->rtype == TYPE(&stbool)) { + expr = CExpr_TempModifyExpr(tmp); + tk = lex(); + } else { + checkadditive(tmp); + expr = makemonadicnode(tmp, EPOSTINC); + tk = lex(); + } + goto loop; + + case TK_DECREMENT: + tmp = pointer_generation(expr); + if (copts.cplusplus && CExpr_CheckOperator(TK_DECREMENT, tmp, nullnode(), &conv)) { + if ((expr = conv.x0)) { + tk = lex(); + goto loop; + } + CError_ASSERT(2976, tmp = conv.left); + } + tmp = CExpr_LValue(tmp, 1, 1); + checkadditive(tmp); + expr = makemonadicnode(tmp, EPOSTDEC); + tk = lex(); + goto loop; + } + + return expr; +} + +static ENode *CExpr_ParseSizeof(void) { + Type *type; + ENode *expr; + + type = CExpr_ParseTypeExpression(NULL); + if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo) + CError_Error(CErrorStr286); + + if (CTemplTool_IsTemplateArgumentDependentType(type)) { + expr = CExpr_NewTemplDepENode(TDE_SIZEOF); + expr->data.templdep.u.typeexpr.type = type; + return expr; + } + + if (type->size == 0) { + if (copts.gcc_extensions && (IS_TYPE_FUNC(type) || IS_TYPE_VOID(type))) + return intconstnode(CABI_GetSizeTType(), 1); + + if (IS_TYPE_CLASS(type) || IS_TYPE_STRUCT(type)) + CError_Error(CErrorStr136, type, 0); + else + CError_Error(CErrorStr146); + } + + return intconstnode(CABI_GetSizeTType(), type->size); +} + +SInt32 scansizeof(void) { + ENode *expr; + + expr = CExpr_ParseSizeof(); + if (!ENODE_IS(expr, EINTCONST)) { + CError_Error(CErrorStr190); + return 0; + } + + return CInt64_GetULong(&expr->data.intval); +} + +static ENode *CExpr_ParseAlignof(void) { + Type *type; + ENode *expr; + SInt16 align; + + type = CExpr_ParseTypeExpression(NULL); + if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo) + CError_Error(CErrorStr364); + + if (CTemplTool_IsTemplateArgumentDependentType(type)) { + expr = CExpr_NewTemplDepENode(TDE_ALIGNOF); + expr->data.templdep.u.typeexpr.type = type; + return expr; + } + + if (type->size == 0) { + if (IS_TYPE_CLASS(type) || IS_TYPE_STRUCT(type)) + CError_Error(CErrorStr136, type, 0); + else + CError_Error(CErrorStr146); + } + + align = CMach_GetTypeAlign(type); + if (align == 0) + align = 1; + + return intconstnode(CABI_GetSizeTType(), align); +} + +SInt32 scanalignof(void) { + ENode *expr; + + expr = CExpr_ParseAlignof(); + if (!ENODE_IS(expr, EINTCONST)) { + CError_Error(CErrorStr190); + return 0; + } + + return CInt64_GetULong(&expr->data.intval); +} + +static ENode *logicalexpression(ENode *expr) { + if (copts.cplusplus && copts.booltruefalse) + expr->rtype = TYPE(&stbool); + else + expr->rtype = TYPE(&stsignedint); + return expr; +} + +ENode *getnodeaddress(ENode *expr, Boolean flag) { + ENode *result; + Object *obj; + + if (!ENODE_IS(expr, EINDIRECT)) { + expr = CExpr_LValue(expr, flag, flag); + if (!ENODE_IS(expr, EINDIRECT)) { + if (!flag) + CError_Error(CErrorStr142); + return nullnode(); + } + } else { + if (flag && + ENODE_IS(expr->data.monadic, EOBJREF) && + expr->data.monadic->data.objref->name == this_name_node && + cscope_currentfunc && + cscope_currentclass && + expr->data.monadic->data.objref == CClass_ThisSelfObject()) + CError_Error(CErrorStr189); + } + + result = lalloc(sizeof(ENode)); + *result = *expr; +restart: + switch (result->data.monadic->type) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + result->type = ETYPCON; + if (IS_TYPE_POINTER_ONLY(result->rtype)) + result->flags = TPTR_QUAL(result->rtype) & ENODE_FLAG_QUALS; + result->rtype = CDecl_NewPointerType(result->rtype); + return result; + case EOBJREF: + obj = result->data.monadic->data.objref; + if (obj->datatype == DALIAS) { + CExpr_AliasTransform(result->data.monadic); + goto restart; + } + if (obj->datatype == DINLINEFUNC) + CError_Error(CErrorStr175); + obj->flags = obj->flags | OBJECT_FLAGS_2; + if (flag && !copts.cplusplus && obj->sclass == TK_REGISTER) + CError_Error(CErrorStr163); + break; + case EFUNCCALL: + if (flag && !IS_TYPE_POINTER_ONLY(result->data.monadic->data.funccall.functype->functype)) + CError_Warning(CErrorStr142); + break; + case EBITFIELD: + CError_Error(CErrorStr144); + return nullnode(); + } + + switch (result->rtype->type) { + case TYPEPOINTER: + result->data.monadic->rtype = CDecl_NewPointerType(result->rtype); + result->data.monadic->flags = result->flags; + break; + default: + result->data.monadic->rtype = CDecl_NewPointerType(result->rtype); + result->data.monadic->flags = result->flags; + } + + return result->data.monadic; +} + +static ENode *CExpr_MakeStaticMemberList(NameSpaceObjectList *list) { + NameSpaceObjectList *newlist; + NameSpaceObjectList *n; + ENode *result; + + newlist = NULL; + while (list) { + if (list->object->otype == OT_OBJECT && IS_TYPE_STATIC_METHOD(OBJECT(list->object)->type)) { + n = galloc(sizeof(NameSpaceObjectList)); + *n = *list; + n->next = newlist; + newlist = n; + } + list = list->next; + } + + if (!newlist) { + CError_Warning(CErrorStr331); + return nullnode(); + } + + result = CExpr_NewENode(EOBJLIST); + result->rtype = OBJECT(newlist->object)->type; + result->data.objlist.list = newlist; + return result; +} + +static ENode *CExpr_MakePTDM(ENode *expr) { + ENode *result; + + CError_ASSERT(3414, ENODE_IS(expr, EMEMBER) && expr->data.emember->list->object->otype == OT_MEMBERVAR); + + result = nullnode(); + result->rtype = CExpr_NewPTMType(expr->data.emember, NULL); + CInt64_SetLong(&result->data.intval, OBJ_MEMBER_VAR(expr->data.emember->list->object)->offset + 1); + return result; +} + +ENode *getpointertomemberfunc(ENode *expr, Type *type, Boolean flag) { + NameSpaceObjectList *list; + Object *obj; + Object *dataobj; + Type *ptmtype; + TypeMemberFunc *tmethod; + OLinkList *olist; + SInt32 data[3]; + + CError_ASSERT(3442, ENODE_IS(expr, EMEMBER)); + + if (expr->data.emember->expr && !copts.cpp_extensions) + CError_Error(CErrorStr141); + + if (!copts.cpp_extensions) { + if (!(expr->data.emember->x11 && expr->data.emember->pr_1D)) { + if (type && IS_TYPE_MEMBERPOINTER(type)) + CError_Warning(CErrorStr331); + } + } + + if (expr->data.emember->list->next) { + if (type) { + if (IS_TYPE_MEMBERPOINTER(type)) { + type = TYPE_MEMBER_POINTER(type)->ty1; + for (list = expr->data.emember->list; list; list = list->next) { + if (list->object->otype == OT_OBJECT && is_memberpointerequal(OBJECT(list->object)->type, type)) { + obj = OBJECT(list->object); + break; + } + } + if (!list) { + CError_Error(CErrorStr146); + return nullnode(); + } + } else { + return CExpr_MakeStaticMemberList(expr->data.emember->list); + } + } else { + obj = OBJECT(expr->data.emember->list->object); + } + } else { + obj = OBJECT(expr->data.emember->list->object); + } + + while (obj->datatype == DALIAS) + obj = obj->u.alias.object; + + CError_ASSERT(3503, obj->otype == OT_OBJECT && IS_TYPE_NONSTATIC_METHOD(obj->type)); + + if (TYPE_FUNC(obj->type)->flags & FUNC_IS_TEMPL) + CError_Error(CErrorStr190); + + ptmtype = CExpr_NewPTMType(expr->data.emember, obj); + tmethod = TYPE_METHOD(obj->type); + dataobj = CParser_NewGlobalDataObject(NULL); + dataobj->name = CParser_GetUniqueName(); + dataobj->nspace = cscope_root; + dataobj->type = ptmtype; + dataobj->sclass = TK_STATIC; + + if (flag) { + data[0] = 0; + if (obj->datatype == DVFUNC) { + olist = NULL; + data[1] = tmethod->vtbl_index; + data[2] = tmethod->theclass->vtable->offset; + } else { + data[1] = -1; + data[2] = 0; + olist = galloc(sizeof(OLinkList)); + olist->next = NULL; + olist->obj = obj; + olist->somevalue = 0; + olist->offset = 8; + } + CInit_DeclareData(dataobj, data, olist, dataobj->type->size); + } + + return create_objectnode(dataobj); +} + +static ENode *getpointertomember(ENode *expr) { + CError_ASSERT(3554, ENODE_IS(expr, EMEMBER)); + + if (expr->data.emember->expr) + CError_Error(CErrorStr141); + + expr->data.emember->x11 = 1; + if (!expr->data.emember->list->next) { + if (expr->data.emember->list->object->otype == OT_MEMBERVAR) + return CExpr_MakePTDM(expr); + else + return getpointertomemberfunc(expr, NULL, 1); + } + + return expr; +} + +ENode *CExpr_New_ELOGNOT_Node(ENode *input) { + ENode *expr; + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(input->rtype)) + return CTempl_MakeTemplDepExpr(NULL, ELOGNOT, input); + + expr = pointer_generation(input); + if (copts.cplusplus && CExpr_CheckOperator('!', expr, NULL, &conv)) { + if ((input = conv.x0)) + return input; + CError_ASSERT(3593, expr = conv.left); + } + + switch (expr->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + case TYPEPOINTER: + case TYPEARRAY: + break; + case TYPEENUM: + expr = forceintegral(expr); + break; + case TYPEMEMBERPOINTER: + expr = CExpr_ConvertToCondition(expr); + break; + default: + CError_Error(CErrorStr144); + return expr; + } + + switch (expr->type) { + case EINTCONST: + expr->data.intval = CInt64_Not(expr->data.intval); + break; + case EFLOATCONST: + expr->type = EINTCONST; + CInt64_SetLong(&expr->data.intval, CMach_FloatIsZero(expr->data.floatval)); + break; + default: + expr = makemonadicnode(expr, ELOGNOT); + } + + return logicalexpression(expr); +} + +ENode *CExpr_New_EMONMIN_Node(ENode *input) { + ENode *expr; + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(input->rtype)) + return CTempl_MakeTemplDepExpr(NULL, EMONMIN, input); + + expr = pointer_generation(input); + if (copts.cplusplus && CExpr_CheckOperator('-', expr, NULL, &conv)) { + if ((input = conv.x0)) + return input; + CError_ASSERT(3652, expr = conv.left); + } + + switch (expr->rtype->type) { + case TYPEINT: + case TYPEENUM: + expr = integralpromote(expr); + if (ENODE_IS(expr, EINTCONST)) { + expr->data.intval = CMach_CalcIntMonadic(expr->rtype, '-', expr->data.intval); + return expr; + } + return makemonadicnode(expr, EMONMIN); + case TYPEFLOAT: + if (ENODE_IS(expr, EFLOATCONST)) { + expr->data.floatval = CMach_CalcFloatMonadic(expr->rtype, '-', expr->data.floatval); + return expr; + } + return CExpr_UnaryFloatExpression(makemonadicnode(expr, EMONMIN)); + default: + CError_Error(CErrorStr144); + return expr; + } +} + +ENode *CExpr_New_EBINNOT_Node(ENode *input) { + ENode *expr; + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(input->rtype)) + return CTempl_MakeTemplDepExpr(NULL, EBINNOT, input); + + expr = pointer_generation(input); + if (copts.cplusplus && CExpr_CheckOperator('~', expr, NULL, &conv)) { + if ((input = conv.x0)) + return input; + CError_ASSERT(3702, expr = conv.left); + } + + expr = integralpromote(expr); + + if (ENODE_IS(expr, EINTCONST)) { + expr->data.intval = CMach_CalcIntMonadic(expr->rtype, '~', expr->data.intval); + return expr; + } + return makemonadicnode(expr, EBINNOT); +} + +ENode *unary_expression(void) { + ENode *expr; + ENode *tmp; + Conversion conv; + + switch (tk) { + case TK_COLON_COLON: + switch (lookahead()) { + case TK_NEW: + tk = lex(); + return scannew(1); + case TK_DELETE: + tk = lex(); + return scandelete(1); + } + return postfix_expression(0); + + case TK_NEW: + return scannew(0); + case TK_DELETE: + return scandelete(0); + case TK_INCREMENT: + tk = lex(); + if (copts.cplusplus) { + expr = pointer_generation(cast_expression()); + if (CExpr_CheckOperator(TK_INCREMENT, expr, NULL, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(3748, expr = conv.left); + } + } else { + expr = pointer_generation(unary_expression()); + } + expr = CExpr_LValue(expr, 1, 1); + if (expr->rtype == TYPE(&stbool)) { + tmp = nullnode(); + tmp->rtype = TYPE(&stbool); + CInt64_SetLong(&tmp->data.intval, 1); + return makediadicnode(expr, tmp, EASS); + } else { + checkadditive(expr); + return makemonadicnode(expr, EPREINC); + } + case TK_DECREMENT: + tk = lex(); + if (copts.cplusplus) { + expr = pointer_generation(cast_expression()); + if (CExpr_CheckOperator(TK_DECREMENT, expr, NULL, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(3776, expr = conv.left); + } + } else { + expr = pointer_generation(unary_expression()); + } + expr = CExpr_LValue(expr, 1, 1); + checkadditive(expr); + return makemonadicnode(expr, EPREDEC); + + case '&': + if (copts.cplusplus) { + switch ((tk = lex())) { + case TK_IDENTIFIER: + case TK_INHERITED: + case TK_COLON_COLON: + expr = postfix_expression(1); + if (ENODE_IS(expr, EMEMBER)) + return getpointertomember(expr); + break; + default: + expr = cast_expression(); + } + + if (CExpr_CheckOperator('&', expr, NULL, &conv)) { + CError_ASSERT(3809, conv.x0); + return conv.x0; + } + } else { + tk = lex(); + expr = cast_expression(); + } + + if (copts.mpwc_relax && !copts.cplusplus && IS_TYPE_ARRAY(expr->rtype) && ENODE_IS(expr, EINDIRECT)) + return pointer_generation(expr); + if (ENODE_IS(expr, EOBJLIST)) + return expr; + + if (IS_TYPE_TEMPLDEPEXPR(expr->rtype)) { + tmp = CExpr_NewTemplDepENode(TDE_ADDRESS_OF); + tmp->data.templdep.u.monadic = expr; + return tmp; + } + + return getnodeaddress(expr, 1); + + case '*': + tk = lex(); + expr = pointer_generation(cast_expression()); + if (copts.cplusplus && CExpr_CheckOperator('*', expr, NULL, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(3840, expr = conv.left); + } + + if (!IS_TYPE_POINTER(expr->rtype)) { + CError_Error(CErrorStr148); + return expr; + } + + tmp = makemonadicnode(expr, EINDIRECT); + CDecl_CompleteType(tmp->rtype = TPTR_TARGET(tmp->rtype)); + return tmp; + + case '+': + tk = lex(); + expr = pointer_generation(cast_expression()); + if (copts.cplusplus && CExpr_CheckOperator('+', expr, NULL, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(3852, expr = conv.left); + } + + switch (expr->rtype->type) { + case TYPEINT: + case TYPEENUM: + return integralpromote(expr); + case TYPEFLOAT: + case TYPEPOINTER: + case TYPEARRAY: + return expr; + default: + CError_Error(CErrorStr144); + return expr; + } + + case '-': + tk = lex(); + return CExpr_New_EMONMIN_Node(cast_expression()); + case '~': + tk = lex(); + return CExpr_New_EBINNOT_Node(cast_expression()); + case '!': + tk = lex(); + return CExpr_New_ELOGNOT_Node(cast_expression()); + + case TK_SIZEOF: + return CExpr_ParseSizeof(); + case TK_UU_ALIGNOF_UU: + return CExpr_ParseAlignof(); + + case TK_LOGICAL_AND: + if (copts.ANSIstrict) + break; + + if ((tk = lex()) != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + return nullnode(); + } + + expr = lalloc(sizeof(ENode)); + expr->type = ELABEL; + expr->cost = 0; + expr->flags = 0; + expr->rtype = TYPE(&void_ptr); + expr->data.label = findlabel(); + if (!expr->data.label) { + expr->data.label = newlabel(); + expr->data.label->name = tkidentifier; + expr->data.label->next = Labels; + Labels = expr->data.label; + } + tk = lex(); + return expr; + } + + return postfix_expression(0); +} + +ENode *do_castnullcheck(ENode *condexpr, ENode *nullcheckexpr) { + ENode *result; + + if (isnotzero(nullcheckexpr)) + return condexpr; + + result = lalloc(sizeof(ENode)); + *result = *condexpr; + result->type = ENULLCHECK; + result->data.nullcheck.nullcheckexpr = lalloc(sizeof(ENode)); + *result->data.nullcheck.nullcheckexpr = *nullcheckexpr; + result->data.nullcheck.condexpr = condexpr; + result->data.nullcheck.precompid = CParser_GetUniqueID(); + + nullcheckexpr->type = EPRECOMP; + nullcheckexpr->data.precompid = result->data.nullcheck.precompid; + + return result; +} + +ENode *CExpr_SafeClassPointerCast(ENode *expr, TypeClass *a, TypeClass *b, Boolean typconflag, Boolean pathcheckflag) { + ENode *result; + + result = CClass_ClassPointerCast(expr, a, b, typconflag, 1, pathcheckflag); + if (result != expr) { + if (!(ENODE_IS(result, ETYPCON) && result->data.monadic == expr)) + result = do_castnullcheck(result, expr); + } + return result; +} + +ENode *PointerToMemberCast(ENode *expr, TypeMemberPointer *tm1, TypeMemberPointer *tm2, Boolean flag) { + BClassList *path; + Boolean negate; + short depth; + Boolean isambig; + SInt32 pathoffset; + CInt64 pathoffset64; + ENode *tmp; + + CError_ASSERT(3984, IS_TYPE_CLASS(tm1->ty2)); + CError_ASSERT(3985, IS_TYPE_CLASS(tm2->ty2)); + + if (tm1->ty2 == tm2->ty2) { + expr->rtype = TYPE(tm2); + return expr; + } + + negate = 0; + path = CClass_GetBasePath(TYPE_CLASS(tm2->ty2), TYPE_CLASS(tm1->ty2), &depth, &isambig); + if (!path) { + path = CClass_GetBasePath(TYPE_CLASS(tm1->ty2), TYPE_CLASS(tm2->ty2), &depth, &isambig); + if (!path) + goto failed; + negate = 1; + } + + if (isambig) + CError_Error(CErrorStr188); + + if ((pathoffset = CClass_GetPathOffset(path)) < 0) + goto failed; + if (negate) + pathoffset = -pathoffset; + + if (flag) + CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); + + if (tm1->size != tm2->size) { + failed: + CError_Error(CErrorStr247, tm1, 0, tm2, 0); + return nullnode(); + } + + if (!pathoffset) { + expr->rtype = TYPE(tm2); + return expr; + } + + if (tm1->size == 4u) { + if (ENODE_IS(expr, EINTCONST)) { + if (!CInt64_IsZero(&expr->data.intval)) { + CInt64_SetLong(&pathoffset64, pathoffset); + expr->data.intval = CInt64_Add(expr->data.intval, pathoffset64); + } + expr->rtype = TYPE(tm2); + return expr; + } else { + expr->rtype = TYPE(&stunsignedlong); + tmp = intconstnode(TYPE(&stunsignedlong), pathoffset); + tmp = makediadicnode(expr, tmp, EADD); + tmp = makemonadicnode(tmp, ETYPCON); + tmp->rtype = TYPE(tm2); + return do_castnullcheck(tmp, expr); + } + } else { + tmp = create_temp_node(TYPE(&ptmstruct)); + expr = getnodeaddress(expr, 0); + tmp = funccallexpr(rt_ptmf_cast, intconstnode(TYPE(&stsignedlong), pathoffset), expr, tmp, NULL); + tmp = makemonadicnode(tmp, EINDIRECT); + tmp->rtype = TYPE(tm2); + return tmp; + } +} + +ENode *CExpr_MemberPointerConversion(ENode *expr, TypeMemberPointer *type, Boolean flag1) { + if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval)) { + if (IS_TYPE_FUNC(type->ty1)) + expr = create_objectnode(rt_ptmf_null); + expr->rtype = TYPE(type); + } else if (ENODE_IS(expr, EMEMBER)) { + expr = getpointertomemberfunc(expr, TYPE(type), flag1); + } + + return expr; +} + +static ENode *CExpr_MemberPointerCast(ENode *expr, TypeMemberPointer *type, UInt32 qual) { + if (!IS_TYPE_MEMBERPOINTER(expr->rtype)) + expr = CExpr_MemberPointerConversion(expr, type, 1); + + if (!IS_TYPE_MEMBERPOINTER(expr->rtype)) { + CError_Error(CErrorStr164); + return nullnode(); + } + + expr = PointerToMemberCast(expr, TYPE_MEMBER_POINTER(expr->rtype), type, 0); + expr->flags = qual & ENODE_FLAG_QUALS; + return expr; +} + +ENode *do_typecast(ENode *expr, Type *type, UInt32 qual) { + TypePointer *tptr; + ENode *tmp; + short flags; + + if (!copts.old_argmatch) + return CExpr_Convert(expr, type, qual, 1, 0); + + if (copts.cpp_extensions && is_typesame(expr->rtype, type) && !ENODE_IS(expr, EOBJLIST)) { + expr->rtype = type; + expr->flags &= ~ENODE_FLAG_QUALS; + expr->flags |= qual & ENODE_FLAG_QUALS; + return expr; + } + + switch (type->type) { + case TYPEARRAY: + CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); + return expr; + case TYPEMEMBERPOINTER: + if (!IS_TYPE_CLASS(expr->rtype)) + return CExpr_MemberPointerCast(expr, TYPE_MEMBER_POINTER(type), qual); + } + + flags = qual & ENODE_FLAG_QUALS; + + if (ENODE_IS(expr, EOBJLIST)) + return CExpr_AssignmentPromotion(expr, type, qual & ENODE_FLAG_QUALS, 1); + + if (ENODE_IS(expr, EOBJREF) && IS_TYPE_NONSTATIC_METHOD(expr->data.objref->type)) { + CError_Error(CErrorStr221); + return nullnode(); + } + + if (type == &stvoid) { + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = type; + expr->flags = flags; + return expr; + } + + if (IS_TYPE_REFERENCE(type)) { + tmp = getnodeaddress(expr, 0); + tptr = galloc(sizeof(TypePointer)); + *tptr = *TYPE_POINTER(type); + tptr->qual &= ~Q_REFERENCE; + + tmp = do_typecast(tmp, TYPE(tptr), qual); + tmp = makemonadicnode(tmp, EINDIRECT); + tmp->rtype = TPTR_TARGET(type); + tmp->flags = flags; + return tmp; + } + + if (IS_TYPE_CLASS(expr->rtype) || IS_TYPE_CLASS(type)) { + if (expr->rtype->size == 0) + CDecl_CompleteType(expr->rtype); + + if (expr->rtype == type && !CClass_CopyConstructor(TYPE_CLASS(type))) + return expr; + + if (user_assign_check(expr, type, qual, 1, 1, 1)) { + assign_node->flags = flags; + return assign_node; + } + + CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); + return nullnode(); + } + + if (IS_TYPE_STRUCT(type) && copts.cplusplus && is_typesame(expr->rtype, type)) { + expr->rtype = type; + expr->flags = flags; + return expr; + } + + if (type == TYPE(&stbool)) { + expr = CExpr_ConvertToBool(expr, 1); + expr->flags = flags; + return expr; + } + + if (IS_TYPE_ENUM(type)) { + tmp = do_typecast(expr, TYPE_ENUM(type)->enumtype, qual); + if (!ENODE_IS(tmp, EINTCONST)) + tmp = makemonadicnode(tmp, ETYPCON); + tmp->rtype = type; + tmp->flags = flags; + return tmp; + } + + if (IS_TYPE_INT_OR_FLOAT(type)) { + if (ENODE_IS(expr, ETYPCON) && expr->rtype->type == type->type && expr->rtype->size == type->size) { + if (is_unsigned(expr->rtype) == is_unsigned(type) && ENODE_QUALS(expr) == qual) { + expr->rtype = type; + expr->flags = expr->flags | ENODE_FLAG_80; + return expr; + } + } + + if (IS_TYPE_ENUM(expr->rtype)) + expr = forceintegral(expr); + + if (IS_TYPE_INT_OR_FLOAT(expr->rtype)) { + expr = promote(expr, type); + expr->flags = flags; + return expr; + } + + if (!(IS_TYPE_POINTER_ONLY(expr->rtype) && !IS_TYPE_FLOAT(type))) + CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); + + if (ENODE_IS(expr, ETYPCON) && ENODE_IS(tmp = expr->data.monadic, EINTCONST)) { + tmp->rtype = type; + tmp->flags = flags; + tmp->data.intval = CExpr_IntConstConvert(type, TYPE(&stunsignedlong), tmp->data.intval); + return tmp; + } + + if (type->size != 4) { + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = TYPE(&stunsignedlong); + } + + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = type; + expr->flags = flags; + return expr; + } + + if (IS_TYPE_POINTER(type)) { + if (IS_TYPE_POINTER(expr->rtype)) { + if (IS_TYPE_CLASS(TPTR_TARGET(expr->rtype)) && IS_TYPE_CLASS(TPTR_TARGET(type))) + expr = CExpr_SafeClassPointerCast(expr, TYPE_CLASS(TPTR_TARGET(expr->rtype)), TYPE_CLASS(TPTR_TARGET(type)), 1, 0); + + if (!ENODE_IS(expr, ETYPCON)) + expr = makemonadicnode(expr, ETYPCON); + + expr->rtype = type; + expr->flags = flags; + return expr; + } + + if (!IS_TYPE_INT(expr->rtype)) { + if (!IS_TYPE_ENUM(expr->rtype)) { + CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); + return expr; + } + expr = forceintegral(expr); + } + + if (expr->rtype->size != 4) { + if (!ENODE_IS(expr, EINTCONST)) + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = TYPE(&stunsignedlong); + } + + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = type; + expr->flags = flags; + return expr; + } + + if ((tmp = CodeGen_HandleTypeCast(expr, type, qual))) + return tmp; + + CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); + return nullnode(); +} + +static Boolean isvectorconst(ENode *node) { + if (ENODE_IS3(node, ECOMMA, EINTCONST, EFLOATCONST)) + return 1; + else + return 0; +} + +ENode *cast_expression(void) { + ENode *expr; + ENode *tmp; + ENodeList *args; + MWVector128 vec; + DeclInfo di; + + if (!(tk == '(' && islookaheaddeclaration())) + return unary_expression(); + tk = lex(); + + memclrw(&di, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&di, 0); + scandeclarator(&di); + + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + + if (di.name) + CError_Error(CErrorStr164); + + if (copts.altivec_model && tk == '(' && IS_TYPE_VECTOR(di.thetype)) { + tk = lex(); + expr = s_expression(); + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + + if (CodeGen_CollapseVectorExpression(expr, &vec, di.thetype)) { + tmp = lalloc(sizeof(ENode)); + tmp->type = EVECTOR128CONST; + if ((tmp->cost = expr->cost) == 0) + tmp->cost = 1; + tmp->flags = ENODE_QUALS(expr); + tmp->rtype = di.thetype; + tmp->data.vector128val = vec; + } else { + tmp = makemonadicnode(expr, ETYPCON); + } + tmp->rtype = di.thetype; + tmp->flags = expr->flags; + return tmp; + } + + if (tk == '{' && (!copts.ANSIstrict || copts.c9x) && !IS_TYPE_VECTOR(di.thetype)) + return CInit_AutoObject(NULL, di.thetype, di.qual); + + expr = cast_expression(); + if (copts.cplusplus && (CTemplTool_IsTemplateArgumentDependentType(di.thetype) || + CTemplTool_IsTemplateArgumentDependentExpression(expr))) { + args = lalloc(sizeof(ENodeList)); + args->next = NULL; + args->node = expr; + return CExpr_TemplArgDepCast(di.thetype, di.qual, args); + } + + if (!IS_TYPE_REFERENCE(di.thetype)) + expr = pointer_generation(expr); + return do_typecast(expr, di.thetype, di.qual); +} + +static ENode *pm_expression(void) { + ENode *left; + ENode *right; + ENode *tmp; + Type *type; + UInt32 qual; + short flags; + Conversion conv; + + left = cast_expression(); +restart: + switch (tk) { + case TK_ARROW_STAR: + left = pointer_generation(left); + tk = lex(); + right = pointer_generation(cast_expression()); + + if (CExpr_CheckOperator(TK_ARROW_STAR, left, right, &conv)) { + CError_ASSERT(4457, left = conv.x0); + goto restart; + } + + if (!IS_TYPE_POINTER(left->rtype)) { + CError_Error(CErrorStr148); + return left; + } + + left = makemonadicnode(left, EINDIRECT); + left->rtype = TPTR_TARGET(left->rtype); + goto common_part; + case TK_DOT_STAR: + left = pointer_generation(left); + tk = lex(); + right = pointer_generation(cast_expression()); + if (!ENODE_IS(left, EINDIRECT)) { + CError_Error(CErrorStr142); + return left; + } + common_part: + if (!IS_TYPE_CLASS(left->rtype)) { + CError_Error(CErrorStr149); + return left; + } + if (!IS_TYPE_MEMBERPOINTER(right->rtype)) { + CError_Error(CErrorStr144); + return left; + } + if (left->rtype != TYPE_MEMBER_POINTER(right->rtype)->ty2) { + if (CClass_IsBaseClass(TYPE_CLASS(left->rtype), TYPE_CLASS(TYPE_MEMBER_POINTER(right->rtype)->ty2), NULL, 1, 1)) { + left->data.monadic = CClass_ClassPointerCast( + left->data.monadic, + TYPE_CLASS(left->rtype), + TYPE_CLASS(TYPE_MEMBER_POINTER(right->rtype)->ty2), + 0, 1, 1); + left->rtype = TYPE_MEMBER_POINTER(right->rtype)->ty2; + } else { + CError_Error(CErrorStr146); + return left; + } + } + type = CClass_CombineClassAccessQualifiers( + TYPE_MEMBER_POINTER(right->rtype)->ty1, + ENODE_QUALS(right), + left->flags, + &qual); + flags = qual; + if (!IS_TYPE_FUNC(type)) { + if (!ENODE_IS(right, EINTCONST)) { + if (!canadd(left->data.monadic, -1)) { + left->data.monadic = makediadicnode(left->data.monadic, nullnode(), EADD); + CInt64_SetLong(&left->data.monadic->data.diadic.right->data.intval, -1); + optimizecomm(left->data.monadic); + } + right->rtype = TYPE(&stunsignedlong); + left->data.monadic = makediadicnode(left->data.monadic, right, EADD); + optimizecomm(left->data.monadic); + } else { + right->data.intval = CInt64_Sub(right->data.intval, cint64_one); + if (!canadd2(left->data.monadic, right->data.intval)) { + right->rtype = TYPE(&stunsignedlong); + left->data.monadic = makediadicnode(left->data.monadic, right, EADD); + optimizecomm(left->data.monadic); + } + } + + if (IS_TYPE_BITFIELD(type)) { + left->data.monadic = makemonadicnode(left->data.monadic, EBITFIELD); + left->data.monadic->rtype = type; + left->rtype = TYPE_BITFIELD(type)->bitfieldtype; + } else { + left->rtype = type; + } + left->flags = flags; + left = checkreference(left); + goto restart; + } else { + CError_ASSERT(4535, ENODE_IS(right, EINDIRECT)); + tmp = lalloc(sizeof(ENode)); + tmp->type = EMFPOINTER; + tmp->cost = 4; + tmp->flags = 0; + tmp->rtype = &stvoid; + tmp->data.mfpointer.accessnode = left; + tmp->data.mfpointer.mfpointer = right; + return tmp; + } + default: + return left; + } +} + +ENode *CExpr_New_EMUL_Node(ENode *left, ENode *right) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, EMUL, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator('*', left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(4566, left = conv.left); + CError_ASSERT(4567, right = conv.right); + } + + return makemultnode(left, right); +} + +ENode *CExpr_New_EDIV_Node(ENode *left, ENode *right, Boolean no_warning) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, EDIV, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator('/', left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(4592, left = conv.left); + CError_ASSERT(4593, right = conv.right); + } + + return makedivnode(left, right, no_warning); +} + +ENode *CExpr_New_EMODULO_Node(ENode *left, ENode *right, Boolean no_warning) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, EMODULO, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator('%', left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(4618, left = conv.left); + CError_ASSERT(4619, right = conv.right); + } + + left = integralpromote(left); + right = integralpromote(right); + CExpr_ArithmeticConversion(&left, &right); + + if (iszero(right)) { + if (!no_warning) + CError_Warning(CErrorStr139); + return left; + } + + if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { + left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '%', right->data.intval); + return left; + } + + if (iszero(left)) + return makediadicnode(right, left, ECOMMA); + + if (CExpr_IsOne(right)) { + right = nullnode(); + right->rtype = left->rtype; + return makediadicnode(left, right, ECOMMA); + } + + return makediadicnode(left, right, EMODULO); +} + +ENode *CExpr_New_EADD_Node(ENode *left, ENode *right) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, EADD, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator('+', left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(4665, left = conv.left); + CError_ASSERT(4666, right = conv.right); + } + + return makeaddnode(left, right); +} + +ENode *CExpr_New_ESUB_Node(ENode *left, ENode *right) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, ESUB, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator('-', left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(4690, left = conv.left); + CError_ASSERT(4691, right = conv.right); + } + + return makesubnode(left, right); +} + +ENode *CExpr_New_ESHL_Node(ENode *left, ENode *right) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, ESHL, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator(TK_SHL, left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(4715, left = conv.left); + CError_ASSERT(4716, right = conv.right); + } + + left = integralpromote(left); + right = integralpromote(right); + + if (iszero(left) || iszero(right)) { + return left; + } + + if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { + left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_SHL, right->data.intval); + return left; + } + + return makediadicnode(left, right, ESHL); +} + +ENode *CExpr_New_ESHR_Node(ENode *left, ENode *right) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, ESHR, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator(TK_SHR, left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(4752, left = conv.left); + CError_ASSERT(4753, right = conv.right); + } + + left = integralpromote(left); + right = integralpromote(right); + + if (iszero(left) || iszero(right)) { + return left; + } + + if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { + left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_SHR, right->data.intval); + return left; + } + + return makediadicnode(left, right, ESHR); +} + +static ENode *pointercompare(ENodeType nt, ENode *left, ENode *right) { + Type *ltype; + Type *rtype; + + ltype = left->rtype; + rtype = right->rtype; + if (IS_TYPE_POINTER_ONLY(ltype) && IS_TYPE_POINTER_ONLY(rtype)) { + ltype = TPTR_TARGET(left->rtype); + rtype = TPTR_TARGET(right->rtype); + if (IS_TYPE_CLASS(ltype) && IS_TYPE_CLASS(rtype)) { + if (ltype != rtype) { + if (ltype == TPTR_TARGET(left->rtype)) { + if (CClass_IsBaseClass(TYPE_CLASS(ltype), TYPE_CLASS(rtype), NULL, 0, 1)) { + left = CExpr_SafeClassPointerCast(left, TYPE_CLASS(ltype), TYPE_CLASS(rtype), 0, 1); + } else if (CClass_IsBaseClass(TYPE_CLASS(rtype), TYPE_CLASS(ltype), NULL, 0, 1)) { + right = CExpr_SafeClassPointerCast(right, TYPE_CLASS(rtype), TYPE_CLASS(ltype), 0, 1); + } else { + CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); + } + } else { + CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); + } + } + } else if (!is_typeequal(left->rtype, right->rtype)) { + if (!copts.objective_c || !CObjC_IsCompatibleType(left->rtype, right->rtype)) { + CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); + } + } + } else if (nt == EEQU || nt == ENOTEQU) { + if (IS_TYPE_INT(ltype)) { + if (!(ENODE_IS(left, EINTCONST) && CInt64_IsZero(&left->data.intval))) + CError_Error(CErrorStr144); + CError_ASSERT(4847, IS_TYPE_POINTER_ONLY(rtype)); + left->rtype = TYPE(&stunsignedlong); + } else if (IS_TYPE_INT(rtype)) { + if (!(ENODE_IS(right, EINTCONST) && CInt64_IsZero(&right->data.intval))) + CError_Error(CErrorStr144); + CError_ASSERT(4855, IS_TYPE_POINTER_ONLY(ltype)); + right->rtype = TYPE(&stunsignedlong); + } else if (!is_typeequal(ltype, rtype)) { + CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); + } + } else { + if (!is_typeequal(ltype, rtype)) + CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); + } + + return logicalexpression(makediadicnode(left, right, nt)); +} + +static ENode *unsigncheck(ENode *expr, Boolean flag1, Boolean flag2) { + if (is_unsigned(expr->data.diadic.left->rtype)) { + if (ENODE_IS(expr->data.diadic.left, EINTCONST) && CInt64_IsZero(&expr->data.diadic.left->data.intval)) { + flag1 = !flag1; + } else if (!(ENODE_IS(expr->data.diadic.right, EINTCONST) && CInt64_IsZero(&expr->data.diadic.right->data.intval))) { + return logicalexpression(expr); + } + + if (flag1 && flag2) { + expr->type = EEQU; + return logicalexpression(expr); + } + if (!flag1 && !flag2) { + expr->type = ENOTEQU; + return logicalexpression(expr); + } + return CExpr_ConstResult(logicalexpression(expr), !flag1); + } + return logicalexpression(expr); +} + +ENode *CExpr_New_ELESS_Node(ENode *left, ENode *right) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, ELESS, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator('<', left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(4929, left = conv.left); + CError_ASSERT(4930, right = conv.right); + } + + if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) + return pointercompare(ELESS, left, right); + + CExpr_CompareConvert(&left, "<", &right, 0); + if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { + left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '<', right->data.intval); + left->rtype = CParser_GetBoolType(); + } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { + CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, '<', right->data.floatval)); + left->type = EINTCONST; + left->rtype = CParser_GetBoolType(); + } else { + left = unsigncheck(makediadicnode(left, right, ELESS), 1, 0); + } + + return left; +} + +ENode *CExpr_New_ELESSEQU_Node(ENode *left, ENode *right) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, ELESSEQU, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator(TK_LESS_EQUAL, left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(4976, left = conv.left); + CError_ASSERT(4977, right = conv.right); + } + + if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) + return pointercompare(ELESSEQU, left, right); + + CExpr_CompareConvert(&left, "<=", &right, 0); + if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { + left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_LESS_EQUAL, right->data.intval); + left->rtype = CParser_GetBoolType(); + } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { + CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, TK_LESS_EQUAL, right->data.floatval)); + left->type = EINTCONST; + left->rtype = CParser_GetBoolType(); + } else { + left = unsigncheck(makediadicnode(left, right, ELESSEQU), 1, 1); + } + + return left; +} + +ENode *CExpr_New_EGREATER_Node(ENode *left, ENode *right) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, EGREATER, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator('>', left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(5023, left = conv.left); + CError_ASSERT(5024, right = conv.right); + } + + if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) + return pointercompare(EGREATER, left, right); + + CExpr_CompareConvert(&left, ">", &right, 0); + if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { + left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '>', right->data.intval); + left->rtype = CParser_GetBoolType(); + } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { + CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, '>', right->data.floatval)); + left->type = EINTCONST; + left->rtype = CParser_GetBoolType(); + } else { + left = unsigncheck(makediadicnode(left, right, EGREATER), 0, 0); + } + + return left; +} + +ENode *CExpr_New_EGREATEREQU_Node(ENode *left, ENode *right) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, EGREATEREQU, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator(TK_GREATER_EQUAL, left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(5070, left = conv.left); + CError_ASSERT(5071, right = conv.right); + } + + if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) + return pointercompare(EGREATEREQU, left, right); + + CExpr_CompareConvert(&left, ">=", &right, 0); + if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { + left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_GREATER_EQUAL, right->data.intval); + left->rtype = CParser_GetBoolType(); + } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { + CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, TK_GREATER_EQUAL, right->data.floatval)); + left->type = EINTCONST; + left->rtype = CParser_GetBoolType(); + } else { + left = unsigncheck(makediadicnode(left, right, EGREATEREQU), 0, 1); + } + + return left; +} + +ENode *memberpointercompare(ENodeType nt, ENode *left, ENode *right) { + Object *func; + ENodeList *arg; + + if (!IS_TYPE_MEMBERPOINTER(left->rtype)) { + if (!(IS_TYPE_INT(left->rtype) && ENODE_IS(left, EINTCONST) && CInt64_IsZero(&left->data.intval))) { + CError_Error(CErrorStr144); + return nullnode(); + } + } else if (!IS_TYPE_MEMBERPOINTER(right->rtype)) { + if (!(IS_TYPE_INT(right->rtype) && ENODE_IS(right, EINTCONST) && CInt64_IsZero(&right->data.intval))) { + CError_Error(CErrorStr144); + return nullnode(); + } + } else if (!is_typeequal(left->rtype, right->rtype)) { + left = PointerToMemberCast(left, TYPE_MEMBER_POINTER(left->rtype), TYPE_MEMBER_POINTER(right->rtype), 1); + } + + if ((ENODE_IS(left, EINTCONST) || !IS_TYPE_FUNC(TYPE_MEMBER_POINTER(left->rtype)->ty1)) && (ENODE_IS(right, EINTCONST) || !IS_TYPE_FUNC(TYPE_MEMBER_POINTER(right->rtype)->ty1))) { + left->rtype = TYPE(&stunsignedlong); + right->rtype = TYPE(&stunsignedlong); + return logicalexpression(makediadicnode(left, right, nt)); + } + + arg = lalloc(sizeof(ENodeList)); + if (ENODE_IS(left, EINTCONST) || ENODE_IS(right, EINTCONST)) { + func = rt_ptmf_test; + if (ENODE_IS(left, EINTCONST)) + arg->node = getnodeaddress(right, 0); + else + arg->node = getnodeaddress(left, 0); + arg->next = NULL; + } else { + func = rt_ptmf_cmpr; + arg->next = lalloc(sizeof(ENodeList)); + arg->node = getnodeaddress(left, 0); + arg->next->node = getnodeaddress(right, 0); + arg->next->next = NULL; + } + + left = lalloc(sizeof(ENode)); + left->type = EFUNCCALL; + left->rtype = TYPE(&stsignedlong); + left->cost = 4; + left->data.funccall.funcref = create_objectrefnode(func); + left->data.funccall.args = arg; + left->data.funccall.functype = TYPE_FUNC(func->type); + left->flags = TYPE_FUNC(func->type)->qual & ENODE_FLAG_QUALS; + + if (nt == EEQU) + left = makemonadicnode(left, ELOGNOT); + + return left; +} + +ENode *CExpr_New_EEQU_Node(ENode *left, ENode *right) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, EEQU, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator(TK_LOGICAL_EQ, left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(5201, left = conv.left); + CError_ASSERT(5202, right = conv.right); + } + + if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) + return pointercompare(EEQU, left, right); + if (IS_TYPE_MEMBERPOINTER(left->rtype) || IS_TYPE_MEMBERPOINTER(right->rtype)) + return memberpointercompare(EEQU, left, right); + + CExpr_CompareConvert(&left, "==", &right, 1); + if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { + left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_LOGICAL_EQ, right->data.intval); + left->rtype = CParser_GetBoolType(); + } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { + left->type = EINTCONST; + CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, TK_LOGICAL_EQ, right->data.floatval)); + left->type = EINTCONST; + left->rtype = CParser_GetBoolType(); + } else { + left = makediadicnode(left, right, EEQU); + optimizecomm(left); + } + + return logicalexpression(left); +} + +ENode *CExpr_New_ENOTEQU_Node(ENode *left, ENode *right) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, ENOTEQU, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator(TK_LOGICAL_NE, left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(5261, left = conv.left); + CError_ASSERT(5262, right = conv.right); + } + + if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) + return pointercompare(ENOTEQU, left, right); + if (IS_TYPE_MEMBERPOINTER(left->rtype) || IS_TYPE_MEMBERPOINTER(right->rtype)) + return memberpointercompare(ENOTEQU, left, right); + + CExpr_CompareConvert(&left, "!=", &right, 1); + if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { + left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_LOGICAL_NE, right->data.intval); + left->rtype = CParser_GetBoolType(); + } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { + CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, TK_LOGICAL_NE, right->data.floatval)); + left->type = EINTCONST; + left->rtype = CParser_GetBoolType(); + } else { + left = makediadicnode(left, right, ENOTEQU); + optimizecomm(left); + } + + return logicalexpression(left); +} + +ENode *CExpr_New_EAND_Node(ENode *left, ENode *right) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, EAND, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator('&', left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(5321, left = conv.left); + CError_ASSERT(5322, right = conv.right); + } + + left = integralpromote(left); + right = integralpromote(right); + CExpr_ArithmeticConversion(&left, &right); + + if (iszero(left) || CExpr_AllBitsSet(right)) + return left; + if (iszero(right) || CExpr_AllBitsSet(left)) + return right; + + if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { + left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '&', right->data.intval); + return left; + } + + left = makediadicnode(left, right, EAND); + optimizecomm(left); + return left; +} + +ENode *CExpr_New_EXOR_Node(ENode *left, ENode *right) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, EXOR, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator('^', left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(5360, left = conv.left); + CError_ASSERT(5361, right = conv.right); + } + + left = integralpromote(left); + right = integralpromote(right); + CExpr_ArithmeticConversion(&left, &right); + + if (iszero(right)) + return left; + if (iszero(left)) + return right; + + if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { + left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '^', right->data.intval); + return left; + } + + left = makediadicnode(left, right, EXOR); + optimizecomm(left); + return left; +} + +ENode *CExpr_New_EOR_Node(ENode *left, ENode *right) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, EOR, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator('|', left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(5399, left = conv.left); + CError_ASSERT(5400, right = conv.right); + } + + left = integralpromote(left); + right = integralpromote(right); + CExpr_ArithmeticConversion(&left, &right); + + if (iszero(right) || CExpr_AllBitsSet(left)) + return left; + if (iszero(left) || CExpr_AllBitsSet(right)) + return right; + + if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { + left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '|', right->data.intval); + return left; + } + + left = makediadicnode(left, right, EOR); + optimizecomm(left); + return left; +} + +ENode *CExpr_New_ELAND_Node(ENode *left, ENode *right) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, ELAND, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator(TK_LOGICAL_AND, left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(5438, left = conv.left); + CError_ASSERT(5439, right = conv.right); + } + + switch (left->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + case TYPEPOINTER: + case TYPEARRAY: + break; + case TYPEENUM: + case TYPEMEMBERPOINTER: + left = CExpr_ConvertToCondition(left); + break; + default: + CError_Error(CErrorStr144); + left = nullnode(); + } + switch (right->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + case TYPEPOINTER: + case TYPEARRAY: + break; + case TYPEENUM: + case TYPEMEMBERPOINTER: + right = CExpr_ConvertToCondition(right); + break; + default: + CError_Error(CErrorStr144); + right = nullnode(); + } + + if (iszero(left)) { + left->type = EINTCONST; + left->rtype = CParser_GetBoolType(); + CInt64_SetLong(&left->data.intval, 0); + return left; + } + + if (isnotzero(left)) { + if (iszero(right)) { + left->type = EINTCONST; + left->rtype = CParser_GetBoolType(); + CInt64_SetLong(&left->data.intval, 0); + return left; + } else if (isnotzero(right)) { + left->type = EINTCONST; + left->rtype = CParser_GetBoolType(); + CInt64_SetLong(&left->data.intval, 1); + return left; + } else { + left = makemonadicnode(right, ELOGNOT); + left->rtype = CParser_GetBoolType(); + return makemonadicnode(left, ELOGNOT); + } + } else { + if (isnotzero(right)) { + left = makemonadicnode(left, ELOGNOT); + left->rtype = CParser_GetBoolType(); + return makemonadicnode(left, ELOGNOT); + } else if (iszero(right)) { + right->type = EINTCONST; + right->rtype = CParser_GetBoolType(); + CInt64_SetLong(&right->data.intval, 0); + return makecommaexpression(left, right); + } else { + left = makediadicnode(left, right, ELAND); + left->rtype = CParser_GetBoolType(); + return left; + } + } +} + +ENode *CExpr_New_ELOR_Node(ENode *left, ENode *right) { + Conversion conv; + + if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) + return CTempl_MakeTemplDepExpr(left, ELOR, right); + + left = pointer_generation(left); + right = pointer_generation(right); + if (copts.cplusplus && CExpr_CheckOperator(TK_LOGICAL_OR, left, right, &conv)) { + if (conv.x0) + return conv.x0; + CError_ASSERT(5543, left = conv.left); + CError_ASSERT(5544, right = conv.right); + } + + switch (left->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + case TYPEPOINTER: + case TYPEARRAY: + break; + case TYPEENUM: + case TYPEMEMBERPOINTER: + left = CExpr_ConvertToCondition(left); + break; + default: + CError_Error(CErrorStr144); + left = nullnode(); + } + switch (right->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + case TYPEPOINTER: + case TYPEARRAY: + break; + case TYPEENUM: + case TYPEMEMBERPOINTER: + right = CExpr_ConvertToCondition(right); + break; + default: + CError_Error(CErrorStr144); + right = nullnode(); + } + + if (isnotzero(left)) { + left->type = EINTCONST; + left->rtype = CParser_GetBoolType(); + CInt64_SetLong(&left->data.intval, 1); + return left; + } + + if (iszero(left)) { + if (iszero(right)) { + left->type = EINTCONST; + left->rtype = CParser_GetBoolType(); + CInt64_SetLong(&left->data.intval, 0); + return left; + } else if (isnotzero(right)) { + left->type = EINTCONST; + left->rtype = CParser_GetBoolType(); + CInt64_SetLong(&left->data.intval, 1); + return left; + } else { + left = makemonadicnode(right, ELOGNOT); + left->rtype = CParser_GetBoolType(); + return makemonadicnode(left, ELOGNOT); + } + } else { + if (isnotzero(right)) { + right->type = EINTCONST; + right->rtype = CParser_GetBoolType(); + CInt64_SetLong(&right->data.intval, 1); + } else if (iszero(right)) { + left = makemonadicnode(left, ELOGNOT); + left->rtype = CParser_GetBoolType(); + return makemonadicnode(left, ELOGNOT); + } + left = makediadicnode(left, right, ELOR); + left->rtype = CParser_GetBoolType(); + return left; + } +} + +ENode *CExpr_NewDyadicNode(ENode *left, ENodeType nt, ENode *right) { + switch (nt) { + default: + CError_FATAL(5642); + case EADD: return CExpr_New_EADD_Node(left, right); + case ESUB: return CExpr_New_ESUB_Node(left, right); + case EMUL: return CExpr_New_EMUL_Node(left, right); + case EDIV: return CExpr_New_EDIV_Node(left, right, 1); + case EMODULO: return CExpr_New_EMODULO_Node(left, right, 1); + case EAND: return CExpr_New_EAND_Node(left, right); + case EXOR: return CExpr_New_EXOR_Node(left, right); + case EOR: return CExpr_New_EOR_Node(left, right); + case ESHL: return CExpr_New_ESHL_Node(left, right); + case ESHR: return CExpr_New_ESHR_Node(left, right); + case ELESS: return CExpr_New_ELESS_Node(left, right); + case EGREATER: return CExpr_New_EGREATER_Node(left, right); + case ELESSEQU: return CExpr_New_ELESSEQU_Node(left, right); + case EGREATEREQU: return CExpr_New_EGREATEREQU_Node(left, right); + case EEQU: return CExpr_New_EEQU_Node(left, right); + case ENOTEQU: return CExpr_New_ENOTEQU_Node(left, right); + case ELAND: return CExpr_New_ELAND_Node(left, right); + case ELOR: return CExpr_New_ELOR_Node(left, right); + } +} + +typedef struct DyadicInfo { + ENodeType t; + UInt8 prec; +} DyadicInfo; + +static Boolean CExpr_GetDyadicInfo(short token, DyadicInfo *info) { + switch (token) { + case '*': + info->t = EMUL; + info->prec = 20; + return 1; + case '/': + info->t = EDIV; + info->prec = 20; + return 1; + case '%': + info->t = EMODULO; + info->prec = 20; + return 1; + case '+': + info->t = EADD; + info->prec = 19; + return 1; + case '-': + info->t = ESUB; + info->prec = 19; + return 1; + case TK_SHL: + info->t = ESHL; + info->prec = 18; + return 1; + case TK_SHR: + info->t = ESHR; + info->prec = 18; + return 1; + case '<': + info->t = ELESS; + info->prec = 17; + return 1; + case TK_LESS_EQUAL: + info->t = ELESSEQU; + info->prec = 17; + return 1; + case '>': + if (disallowgreaterthan) + return 0; + info->t = EGREATER; + info->prec = 17; + return 1; + case TK_GREATER_EQUAL: + info->t = EGREATEREQU; + info->prec = 17; + return 1; + case TK_LOGICAL_EQ: + info->t = EEQU; + info->prec = 16; + return 1; + case TK_LOGICAL_NE: + info->t = ENOTEQU; + info->prec = 16; + return 1; + case '&': + info->t = EAND; + info->prec = 15; + return 1; + case '^': + info->t = EXOR; + info->prec = 14; + return 1; + case '|': + info->t = EOR; + info->prec = 13; + return 1; + case TK_LOGICAL_AND: + info->t = ELAND; + info->prec = 12; + return 1; + case TK_LOGICAL_OR: + info->t = ELOR; + info->prec = 11; + return 1; + default: + return 0; + } +} + +static ENode *CExpr_ParseDyadicExpression(ENode *left, UInt8 prec, Boolean no_warning) { + ENode *right; + Boolean is_eland_or_elor; + Boolean save_dgt; + Boolean cont; + DyadicInfo left_info; + DyadicInfo right_info; + + save_dgt = disallowgreaterthan; + if (!left) { + disallowgreaterthan = 0; + left = pm_expression(); + disallowgreaterthan = save_dgt; + } + + do { + if (!CExpr_GetDyadicInfo(tk, &left_info)) + return left; + + switch (left_info.t) { + case ELAND: + CExpr_CheckUnwantedAssignment(left); + if (iszero(left)) + no_warning = 1; + is_eland_or_elor = 1; + break; + case ELOR: + CExpr_CheckUnwantedAssignment(left); + if (isnotzero(left)) + no_warning = 1; + is_eland_or_elor = 1; + break; + default: + is_eland_or_elor = 0; + } + + tk = lex(); + disallowgreaterthan = 0; + right = pm_expression(); + disallowgreaterthan = save_dgt; + inner_loop: + if (CExpr_GetDyadicInfo(tk, &right_info)) { + if (left_info.prec >= right_info.prec) { + cont = (prec >= right_info.prec); + } else { + right = CExpr_ParseDyadicExpression(right, left_info.prec, no_warning); + goto inner_loop; + } + } else { + cont = 1; + } + + if (is_eland_or_elor) + CExpr_CheckUnwantedAssignment(right); + + switch (left_info.t) { + case EDIV: + left = CExpr_New_EDIV_Node(left, right, no_warning); + break; + case EMODULO: + left = CExpr_New_EMODULO_Node(left, right, no_warning); + break; + default: + left = CExpr_NewDyadicNode(left, left_info.t, right); + } + } while (!cont); + + return left; +} + +static Boolean CExpr_IsBlockMoveType(Type *type) { + switch (type->type) { + case TYPESTRUCT: + case TYPECLASS: + return 1; + case TYPEMEMBERPOINTER: + return type->size != 4; + default: + return 0; + } +} + +ENode *CExpr_New_ECOND_Node(ENode *cond, ENode *expr1, ENode *expr2) { + ENode *result; + ENodeList *args; + short cost; + Conversion conv; + + cond = CExpr_ConvertToCondition(pointer_generation(cond)); + expr1 = pointer_generation(expr1); + expr2 = pointer_generation(expr2); + + if (!IS_TYPE_INT_OR_FLOAT(cond->rtype) && !IS_TYPE_POINTER_ONLY(cond->rtype)) { + CError_Error(CErrorStr144); + return nullnode(); + } + + cost = cond->cost + 1; + if (expr1->cost > expr2->cost) + cost += expr1->cost; + else + cost += expr2->cost; + if (expr2->cost > cost) + cost = expr2->cost; + if (cost > 200) + cost = 200; + + result = CExpr_NewENode(ECOND); + result->cost = cost; + result->rtype = expr1->rtype; + result->flags = expr1->flags | expr2->flags; + result->data.cond.cond = cond; + if (ENODE_IS(expr1, EFUNCCALL) && expr1->rtype == &stvoid && (expr1->flags & ENODE_FLAG_VOLATILE) != 0) { + result->rtype = expr2->rtype; + result->flags = expr2->flags; + result->data.cond.expr1 = expr1; + result->data.cond.expr2 = expr2; + return result; + } + if (ENODE_IS(expr2, EFUNCCALL) && expr2->rtype == &stvoid && (expr2->flags & ENODE_FLAG_VOLATILE) != 0) { + result->rtype = expr1->rtype; + result->flags = expr1->flags; + result->data.cond.expr1 = expr1; + result->data.cond.expr2 = expr2; + return result; + } + + if ( + ENODE_IS(expr1, EINDIRECT) && + ENODE_IS(expr2, EINDIRECT) && + is_typesame(expr1->rtype, expr2->rtype) && + ENODE_QUALS(expr1) == ENODE_QUALS(expr2) && + CExpr_IsBlockMoveType(expr1->rtype) && + !ENODE_IS(expr1->data.monadic, EBITFIELD) && + !ENODE_IS(expr2->data.monadic, EBITFIELD) + ) { + if (isnotzero(cond)) + return expr1; + if (iszero(cond)) + return expr2; + result->data.cond.expr1 = getnodeaddress(expr1, 0); + result->data.cond.expr2 = getnodeaddress(expr2, 0); + result->rtype = result->data.cond.expr1->rtype; + result = makemonadicnode(result, EINDIRECT); + result->rtype = TPTR_TARGET(result->rtype); + return result; + } + + if ((IS_TYPE_CLASS(expr1->rtype) || IS_TYPE_CLASS(expr2->rtype)) && !is_typesame(expr1->rtype, expr2->rtype)) { + if (!copts.old_argmatch) { + if (CExpr_CondOperatorMatch(expr1, expr2, &conv)) { + CError_ASSERT(6246, !conv.x0); + expr1 = conv.left; + expr2 = conv.right; + } else if (CExpr_CanImplicitlyConvert(expr1, expr2->rtype, ENODE_QUALS(expr2))) { + if (CExpr_CanImplicitlyConvert(expr2, expr1->rtype, ENODE_QUALS(expr1))) + CError_Error(CErrorStr188); + expr1 = CExpr_Convert(expr1, expr2->rtype, ENODE_QUALS(expr2), 0, 1); + } else if (CExpr_CanImplicitlyConvert(expr2, expr1->rtype, ENODE_QUALS(expr1))) { + expr2 = CExpr_Convert(expr2, expr1->rtype, ENODE_QUALS(expr1), 0, 1); + } else { + goto failed; + } + + result->rtype = expr1->rtype; + } else { + args = lalloc(sizeof(ENodeList)); + args->node = expr1; + args->next = lalloc(sizeof(ENodeList)); + args->next->node = expr2; + args->next->next = NULL; + + if (CExpr_CheckOperatorConversion(':', expr1, expr2, args, &conv)) { + CError_ASSERT(6274, !conv.x0); + expr1 = conv.left; + expr2 = conv.right; + } + + result->rtype = expr1->rtype; + } + } + + switch (expr1->rtype->type) { + case TYPEENUM: + if (expr1->rtype == expr2->rtype) + break; + expr1 = forceintegral(expr1); + case TYPEINT: + if (IS_TYPE_POINTER_ONLY(expr2->rtype) || IS_TYPE_MEMBERPOINTER(expr2->rtype)) { + expr1 = CExpr_Convert(expr1, expr2->rtype, ENODE_QUALS(expr2), 0, 1); + result->rtype = expr2->rtype; + break; + } + case TYPEFLOAT: + if (expr1->rtype != expr2->rtype) { + CExpr_ArithmeticConversion(&expr1, &expr2); + result->rtype = expr1->rtype; + } + break; + case TYPEPOINTER: + if (ENODE_IS(expr2, EINTCONST) && CInt64_IsZero(&expr2->data.intval)) { + expr2->rtype = TYPE(&stunsignedlong); + break; + } + if (IS_TYPE_POINTER_ONLY(expr2->rtype)) { + if (IS_TYPE_CLASS(TPTR_TARGET(expr1->rtype)) && IS_TYPE_CLASS(TPTR_TARGET(expr2->rtype))) { + if (TPTR_TARGET(expr1->rtype) != TPTR_TARGET(expr2->rtype)) { + if (CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(expr1->rtype)), TYPE_CLASS(TPTR_TARGET(expr2->rtype)), NULL, 0, 1)) { + expr1 = CExpr_SafeClassPointerCast( + expr1, + TYPE_CLASS(TPTR_TARGET(expr1->rtype)), + TYPE_CLASS(TPTR_TARGET(expr2->rtype)), + 0, 1); + expr1->rtype = expr2->rtype; + } else if (CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(expr2->rtype)), TYPE_CLASS(TPTR_TARGET(expr1->rtype)), NULL, 0, 1)) { + expr2 = CExpr_SafeClassPointerCast( + expr2, + TYPE_CLASS(TPTR_TARGET(expr2->rtype)), + TYPE_CLASS(TPTR_TARGET(expr1->rtype)), + 0, 1); + expr2->rtype = expr1->rtype; + } else { + goto failed; + } + } + result->rtype = expr1->rtype; + break; + } + if (TPTR_TARGET(expr2->rtype) == &stvoid) + result->rtype = expr2->rtype; + } + if (!is_typeequal(expr1->rtype, expr2->rtype)) { + if (!copts.objective_c) + goto failed; + if (!CObjC_IsCompatibleType(expr1->rtype, expr2->rtype)) + goto failed; + expr1->rtype = expr2->rtype = CObjC_GetObjCType_id(1); + } + break; + case TYPEVOID: + if (!is_typeequal(expr1->rtype, expr2->rtype)) + goto failed; + break; + case TYPESTRUCT: + case TYPECLASS: + if (!is_typeequal(expr1->rtype, expr2->rtype)) + goto failed; + result->rtype = expr1->rtype; + break; + case TYPEMEMBERPOINTER: + if (IS_TYPE_MEMBERPOINTER(expr2->rtype) && TYPE_MEMBER_POINTER(expr1->rtype)->ty2 == TYPE_MEMBER_POINTER(expr2->rtype)->ty2) { + expr2 = CExpr_Convert(expr2, expr1->rtype, ENODE_QUALS(expr1), 0, 1); + } else if (CExpr_CanImplicitlyConvert(expr1, expr2->rtype, ENODE_QUALS(expr2))) { + if (CExpr_CanImplicitlyConvert(expr2, expr1->rtype, ENODE_QUALS(expr1))) + CError_Error(CErrorStr188); + expr1 = CExpr_Convert(expr1, expr2->rtype, ENODE_QUALS(expr2), 0, 1); + } else if (CExpr_CanImplicitlyConvert(expr2, expr1->rtype, ENODE_QUALS(expr1))) { + expr2 = CExpr_Convert(expr2, expr1->rtype, ENODE_QUALS(expr1), 0, 1); + } else { + goto failed; + } + result->rtype = expr1->rtype; + break; + default: + failed: + CError_Error(CErrorStr245, expr1->rtype, ENODE_QUALS(expr1), expr2->rtype, ENODE_QUALS(expr2)); + return nullnode(); + } + + result->data.cond.expr1 = expr1; + result->data.cond.expr2 = expr2; + if (isnotzero(cond)) + result = expr1; + else if (iszero(cond)) + result = expr2; + return result; +} + +static ENode *conditional_expression(void) { + ENode *cond; + ENode *expr1; + ENode *expr2; + ENode *result; + Boolean is_templdep_cond; + + is_templdep_cond = 0; + cond = CExpr_ParseDyadicExpression(NULL, 0, 0); + if (tk != '?') + return cond; + + cond = pointer_generation(cond); + if (!IS_TYPE_TEMPLDEPEXPR(cond->rtype)) { + cond = CExpr_ConvertToCondition(cond); + if (!IS_TYPE_INT_OR_FLOAT(cond->rtype) && !IS_TYPE_POINTER_ONLY(cond->rtype)) { + CError_Error(CErrorStr144); + return nullnode(); + } + } else { + is_templdep_cond = 1; + } + + tk = lex(); + expr1 = expression(); + if (tk != ':') + CError_ErrorSkip(CErrorStr141); + else + tk = lex(); + + expr2 = (copts.cplusplus && !copts.ARMconform) ? assignment_expression() : conditional_expression(); + + if (is_templdep_cond || IS_TYPE_TEMPLDEPEXPR(expr1->rtype) || IS_TYPE_TEMPLDEPEXPR(expr2->rtype)) { + result = CExpr_NewENode(ECOND); + result->rtype = &sttemplexpr; + result->data.cond.cond = cond; + result->data.cond.expr1 = expr1; + result->data.cond.expr2 = expr2; + return result; + } + + return CExpr_New_ECOND_Node(cond, expr1, expr2); +} + +static ENode *CExpr_MakeOpAssNode(ENode *left, ENode *right, ENodeType nt) { + if (left->rtype != right->rtype) { + switch (right->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + break; + case TYPEENUM: + right->rtype = TYPE_ENUM(right->rtype)->enumtype; + break; + default: + right = CExpr_AssignmentPromotion(right, left->rtype, 0, 1); + } + if (IS_TYPE_FLOAT(left->rtype)) { + if (IS_TYPE_INT(right->rtype) || (IS_TYPE_FLOAT(right->rtype) && left->rtype->size >= right->rtype->size)) + right = CExpr_AssignmentPromotion(right, left->rtype, 0, 1); + } else if (IS_TYPE_INT(left->rtype)) { + if (IS_TYPE_INT(right->rtype) && (left->rtype->size > right->rtype->size || (left->rtype->size == right->rtype->size && is_unsigned(left->rtype) == is_unsigned(right->rtype)))) + right = CExpr_AssignmentPromotion(right, left->rtype, 0, 1); + } + } + + return makediadicnode(left, right, nt); +} + +static ENode *makeassignmentnode(ENode *left, ENodeType nt, short token) { + ENode *right; + ENode *tmp; + ENode *funcexpr; + ENodeList *args; + Conversion conv; + + tk = lex(); + right = assignment_expression(); + if (copts.cplusplus) { + if (copts.old_argmatch && !ENODE_IS(right, EMEMBER)) + right = pointer_generation(right); + if (CExpr_CheckOperator(token, left, right, &conv)) { + if (!conv.x0) { + if (nt == EASS) + goto continue_anyway; + CError_FATAL(6531); + } + return conv.x0; + } + if (IS_TYPE_CLASS(left->rtype) && CClass_AssignmentOperator(TYPE_CLASS(left->rtype))) + CError_Error(CErrorStr144); + } +continue_anyway: + if (IS_TYPE_ARRAY(left->rtype)) { + if (copts.gcc_extensions && nt == EASS && is_typesame(left->rtype, right->rtype)) { + tmp = makediadicnode(left, right, nt); + tmp->flags = left->flags; + return tmp; + } + CError_Error(CErrorStr144); + return nullnode(); + } + + left = CExpr_LValue(pointer_generation(left), 1, 1); + if (nt != EASS) { + if (!IS_TYPE_INT(right->rtype)) { + if (!IS_TYPE_ENUM(right->rtype)) { + CError_Error(CErrorStr144); + return left; + } + right = forceintegral(right); + } + if (!IS_TYPE_INT(left->rtype)) { + if (copts.cplusplus) { + CError_Error(CErrorStr144); + return left; + } + left = forceintegral(left); + if (!IS_TYPE_INT(left->rtype)) { + CError_Error(CErrorStr144); + return left; + } + } + return CExpr_MakeOpAssNode(left, right, nt); + } + + if (IS_TYPE_CLASS(left->rtype) && TYPE_CLASS(left->rtype)->sominfo) { + CError_Error(CErrorStr285); + return left; + } + + if (copts.warn_implicitconv && ENODE_IS(left, EINDIRECT) && ENODE_IS(left->data.monadic, EBITFIELD) && !ENODE_IS(right, EINTCONST)) { + copts.warn_implicitconv = 0; + right = CExpr_AssignmentPromotion(right, left->rtype, left->flags, 1); + copts.warn_implicitconv = 1; + } else { + right = CExpr_AssignmentPromotion(right, left->rtype, left->flags, 1); + } + + tmp = right; + if (IS_TYPE_FLOAT(right->rtype) && ENODE_IS(right, ETYPCON) && right->rtype->size == right->data.monadic->rtype->size) + tmp = right->data.monadic; + + if ( + ENODE_IS(left, EINDIRECT) && + ENODE_IS(left->data.monadic, EOBJREF) && + ENODE_IS(tmp, EINDIRECT) && + (ENODE_IS(funcexpr = right->data.monadic, EFUNCCALL) || ENODE_IS(funcexpr, EFUNCCALLP)) && + left->rtype == funcexpr->data.funccall.functype->functype && + CMach_GetFunctionResultClass(funcexpr->data.funccall.functype) == 1 && + (args = funcexpr->data.funccall.args) + ) { + switch (CABI_GetStructResultArgumentIndex(funcexpr->data.funccall.functype)) { + case 0: + break; + case 1: + if ((args = args->next)) + break; + CError_FATAL(6625); + default: + CError_FATAL(6626); + } + if (ENODE_IS(args->node, ETEMP)) { + if (!(IS_TYPE_CLASS(left->rtype) && CClass_Destructor(TYPE_CLASS(left->rtype)))) { + args->node = getnodeaddress(left, 0); + return right; + } + } + } + + right = makediadicnode(left, right, nt); + right->flags = left->flags; + return right; +} + +static ENode *makepassignmentnode(ENode *left, ENodeType nt, short token) { + ENode *right; + Boolean is_array; + Conversion conv; + + is_array = IS_TYPE_ARRAY(left->rtype); + left = pointer_generation(left); + if (copts.cplusplus) { + tk = lex(); + right = pointer_generation(assignment_expression()); + if (CExpr_CheckOperator(token, left, right, &conv)) { + CError_ASSERT(6669, conv.x0); + return conv.x0; + } + left = CExpr_LValue(left, 1, 1); + } else { + left = CExpr_LValue(left, 1, 1); + tk = lex(); + right = pointer_generation(assignment_expression()); + } + + if (is_array) + CError_Error(CErrorStr144); + + switch (left->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + case TYPEPOINTER: + break; + case TYPEENUM: + if (copts.cplusplus) { + CError_Error(CErrorStr144); + return left; + } + left = forceintegral(left); + break; + default: + CError_Error(CErrorStr144); + return left; + } + + if (IS_TYPE_ENUM(right->rtype)) + right = forceintegral(right); + + if (iszero(right)) + return left; + + if (IS_TYPE_POINTER_ONLY(left->rtype)) { + if (IS_TYPE_INT(right->rtype)) { + if (nt == ESUBASS) { + left = psub(left, right); + if (ENODE_IS(left, ESUB)) + left->type = ESUBASS; + return left; + } else { + left = padd(left, right); + if (ENODE_IS(left, EADD)) + left->type = EADDASS; + return left; + } + } + CError_Error(CErrorStr144); + return left; + } else { + return CExpr_MakeOpAssNode(left, right, nt); + } +} + +static ENode *makemulassignmentnode(ENode *left, ENodeType nt, short token) { + ENode *right; + Boolean is_array; + Conversion conv; + + is_array = IS_TYPE_ARRAY(left->rtype); + left = pointer_generation(left); + if (copts.cplusplus) { + tk = lex(); + right = pointer_generation(assignment_expression()); + if (CExpr_CheckOperator(token, left, right, &conv)) { + CError_ASSERT(6753, conv.x0); + return conv.x0; + } + if (!IS_TYPE_INT(left->rtype) && !(IS_TYPE_FLOAT(left->rtype) && nt != EMODASS)) { + CError_Error(CErrorStr144); + return nullnode(); + } + left = CExpr_LValue(left, 1, 1); + } else { + if (IS_TYPE_ENUM(left->rtype)) + left = forceintegral(left); + if (!IS_TYPE_INT(left->rtype) && !(IS_TYPE_FLOAT(left->rtype) && nt != EMODASS)) { + CError_Error(CErrorStr144); + return nullnode(); + } + + left = CExpr_LValue(left, 1, 1); + tk = lex(); + right = pointer_generation(assignment_expression()); + } + + if (is_array) + CError_Error(CErrorStr144); + + if (IS_TYPE_ENUM(right->rtype)) + right = forceintegral(right); + + if (IS_TYPE_INT(left->rtype) && IS_TYPE_FLOAT(right->rtype) && nt == EMODASS) { + CError_Error(CErrorStr144); + return nullnode(); + } + + return CExpr_MakeOpAssNode(left, right, nt); +} + +static ENode *CExpr_TransformOpAssign(ENode *expr) { + switch (expr->type) { + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + if (expr->rtype == TYPE(&stbool)) { + expr = CIRTrans_TransformOpAss(expr); + if (ENODE_IS(expr, EASS)) { + expr->data.diadic.right = makemonadicnode(expr->data.diadic.right, ELOGNOT); + expr->data.diadic.right->rtype = TYPE(&stbool); + expr->data.diadic.right = makemonadicnode(expr->data.diadic.right, ELOGNOT); + } + } + } + + return expr; +} + +ENode *assignment_expression(void) { + ENode *expr; + + if (tk == TK_THROW) + return CExcept_ScanThrowExpression(); + + expr = conditional_expression(); + switch (tk) { + case '=': + return makeassignmentnode(expr, EASS, tk); + case TK_ADD_ASSIGN: + return CExpr_TransformOpAssign(makepassignmentnode(expr, EADDASS, tk)); + case TK_SUB_ASSIGN: + return CExpr_TransformOpAssign(makepassignmentnode(expr, ESUBASS, tk)); + case TK_MULT_ASSIGN: + expr = makemulassignmentnode(expr, EMULASS, tk); + if (ENODE_IS(expr, EMULASS) && CExpr_IsOne(expr->data.diadic.right)) + return expr->data.diadic.left; + return CExpr_TransformOpAssign(expr); + case TK_DIV_ASSIGN: + expr = makemulassignmentnode(expr, EDIVASS, tk); + if (ENODE_IS(expr, EDIVASS)) { + if (iszero(expr->data.diadic.right) && !IS_TYPE_FLOAT(expr->rtype)) { + CError_Warning(CErrorStr139); + return expr->data.diadic.left; + } + if (CExpr_IsOne(expr->data.diadic.right)) + return expr->data.diadic.left; + } + return CExpr_TransformOpAssign(expr); + case TK_MOD_ASSIGN: + expr = makemulassignmentnode(expr, EMODASS, tk); + if (ENODE_IS(expr, EMODASS)) { + if (iszero(expr->data.diadic.right)) { + CError_Warning(CErrorStr139); + return expr->data.diadic.left; + } + } + return CExpr_TransformOpAssign(expr); + case TK_SHL_ASSIGN: + expr = makeassignmentnode(expr, ESHLASS, tk); + if (ENODE_IS(expr, ESHLASS) && iszero(expr->data.diadic.right)) + return expr->data.diadic.left; + return CExpr_TransformOpAssign(expr); + case TK_SHR_ASSIGN: + expr = makeassignmentnode(expr, ESHRASS, tk); + if (ENODE_IS(expr, ESHRASS) && iszero(expr->data.diadic.right)) + return expr->data.diadic.left; + return CExpr_TransformOpAssign(expr); + case TK_AND_ASSIGN: + expr = makeassignmentnode(expr, EANDASS, tk); + if (ENODE_IS(expr, EANDASS) && CExpr_AllBitsSet(expr->data.diadic.right)) + return expr->data.diadic.left; + return expr; + case TK_XOR_ASSIGN: + expr = makeassignmentnode(expr, EXORASS, tk); + if (ENODE_IS(expr, EXORASS) && iszero(expr->data.diadic.right)) + return expr->data.diadic.left; + return CExpr_TransformOpAssign(expr); + case TK_OR_ASSIGN: + expr = makeassignmentnode(expr, EORASS, tk); + if (ENODE_IS(expr, EORASS) && iszero(expr->data.diadic.right)) + return expr->data.diadic.left; + return CExpr_TransformOpAssign(expr); + default: + return expr; + } +} + +ENode *conv_assignment_expression(void) { + return pointer_generation(assignment_expression()); +} + +static Boolean CExpr_HasSideEffect(ENode *expr) { + switch (expr->type) { + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EMUL: + case EDIV: + case EMODULO: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case EROTL: + case EROTR: + case EBITFIELD: + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case ETEMP: + case EARGOBJ: + case ELOCOBJ: + case EOBJLIST: + case EMEMBER: + case EVECTOR128CONST: + return 0; + case ETYPCON: + return IS_TYPE_VOID(expr->rtype); + case EINDIRECT: + switch (expr->data.monadic->type) { + case EFUNCCALL: + case EFUNCCALLP: + return 1; + default: + return 0; + } + case ECOMMA: + return CInline_ExpressionHasSideEffect(expr->data.diadic.right); + case ECOND: + return CInline_ExpressionHasSideEffect(expr->data.cond.expr1) || CInline_ExpressionHasSideEffect(expr->data.cond.expr2); + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EFORCELOAD: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case EFUNCCALL: + case EFUNCCALLP: + case EMFPOINTER: + case ENULLCHECK: + case EPRECOMP: + case ELABEL: + case ENEWEXCEPTION: + case ENEWEXCEPTIONARRAY: + case EINITTRYCATCH: + case EINSTRUCTION: + return 1; + default: + CError_FATAL(7056); + return 0; + } +} + +void CExpr_CheckUnusedExpression(ENode *expr) { + ENode *scan; + ENodeList *arg; + + if (copts.warn_possunwant) { + scan = expr; + while (ENODE_IS(scan, ETYPCON)) + scan = scan->data.monadic; + if (ENODE_IS(scan, EEQU)) { + CError_Warning(CErrorStr208); + return; + } + } + + if (copts.warn_no_side_effect) { + if (!CExpr_HasSideEffect(expr)) { + CError_Warning(CErrorStr369); + return; + } + } + + if (copts.warn_resultnotused) { + scan = expr; + if (IS_TYPE_VOID(expr->rtype)) + return; + if (ENODE_IS(expr, EINDIRECT)) + scan = expr->data.monadic; + + switch (scan->type) { + case EFUNCCALL: + case EFUNCCALLP: + if (ENODE_IS(scan->data.funccall.funcref, EOBJREF) && scan->data.funccall.funcref->data.objref->name == asop_name_node) + return; + if (CMach_GetFunctionResultClass(scan->data.funccall.functype) == 1 && (arg = scan->data.funccall.args)) { + switch (CABI_GetStructResultArgumentIndex(scan->data.funccall.functype)) { + case 0: + break; + case 1: + if ((arg = arg->next)) + break; + CError_FATAL(7110); + default: + CError_FATAL(7111); + } + + if (!ENODE_IS(arg->node, ETEMP)) + return; + } + CError_Warning(CErrorStr370); + } + } +} + +ENode *s_expression(void) { + ENode *left; + ENode *right; + Conversion conv; + + left = assignment_expression(); + while (tk == ',') { + left = pointer_generation(left); + tk = lex(); + right = pointer_generation(assignment_expression()); + + if (copts.cplusplus && CExpr_CheckOperator(',', left, right, &conv)) { + CError_ASSERT(7143, left = conv.x0); + } else { + CExpr_CheckUnusedExpression(left); + left = makecommaexpression(left, right); + left->rtype = right->rtype; + } + } + + return left; +} + +ENode *expression(void) { + return pointer_generation(s_expression()); +} + +CInt64 CExpr_IntegralConstExprType(Type **tint) { + ENode *expr; + + expr = pointer_generation(conditional_expression()); + if (ENODE_IS(expr, EINTCONST)) { + switch (expr->rtype->type) { + case TYPEINT: + *tint = expr->rtype; + return expr->data.intval; + case TYPEENUM: + *tint = TYPE_ENUM(expr->rtype)->enumtype; + return expr->data.intval; + } + } + + CError_Error(CErrorStr124); + *tint = TYPE(&stchar); + return cint64_zero; +} + +ENode *CExpr_IntegralConstOrDepExpr(void) { + ENode *expr; + + expr = pointer_generation(conditional_expression()); + if (ENODE_IS(expr, EINTCONST)) { + switch (expr->rtype->type) { + case TYPEINT: + return expr; + case TYPEENUM: + expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; + return expr; + default: + CError_FATAL(7209); + } + } + + if (CTemplTool_IsTemplateArgumentDependentExpression(expr)) + return expr; + + CError_Error(CErrorStr124); + expr = nullnode(); + expr->rtype = TYPE(&stchar); + return expr; +} + +CInt64 CExpr_IntegralConstExpr(void) { + Type *throwaway; + return CExpr_IntegralConstExprType(&throwaway); +} + +void CExpr_CheckUnwantedAssignment(ENode *expr) { + if (copts.warn_possunwant) { + if (ENODE_IS(expr, EASS) && !(expr->flags & ENODE_FLAG_80)) + CError_Warning(CErrorStr207); + } +} + +Boolean CExpr_ParseAsmExpr(Object **objptr, CInt64 *valptr) { + ENode *expr; + + if (objptr) + *objptr = NULL; + *valptr = cint64_zero; + + expr = pointer_generation(assignment_expression()); + if (ENODE_IS(expr, EINTCONST)) { + *valptr = expr->data.intval; + return 1; + } + + if (objptr) { + switch (expr->type) { + case EINDIRECT: + if (CInit_RelocInitCheck(expr->data.monadic, objptr, valptr, 1)) + return 1; + break; + case EOBJREF: + *objptr = expr->data.objref; + while ((*objptr)->datatype == DALIAS) + *objptr = (*objptr)->u.alias.object; + return 1; + case EMEMBER: + if (expr->data.emember->list->object->otype == OT_OBJECT) { + if (expr->data.emember->list->next && expr->data.emember->list->next->object->otype == OT_OBJECT) + CError_Error(CErrorStr199); + *objptr = OBJECT(expr->data.emember->list->object); + while ((*objptr)->datatype == DALIAS) + *objptr = (*objptr)->u.alias.object; + return 1; + } + break; + case EOBJLIST: + CError_Error(CErrorStr199); + return 0; + } + } + + CError_Error(CErrorStr155); + return 0; +} diff --git a/compiler_and_linker/FrontEnd/C/CExpr2.c b/compiler_and_linker/FrontEnd/C/CExpr2.c new file mode 100644 index 0000000..fc26c7e --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CExpr2.c @@ -0,0 +1,4206 @@ +#include "compiler/CExpr.h" +#include "compiler/CABI.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CInit.h" +#include "compiler/CInt64.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CInline.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CObjC.h" +#include "compiler/CObjCModern.h" +#include "compiler/CParser.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/CSOM.h" +#include "compiler/CTemplateFunc.h" +#include "compiler/CTemplateTools.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" + +#ifdef __MWERKS__ +#undef va_start +#undef va_arg +#define va_start(ap, parm) ap = __va_start(parm) +#define __va_start(parm) (va_list) (&parm + 1) +//#define va_arg(ap, type) ((((type *) (ap = (va_list) (( ((long) ap + sizeof(type) - 1) & ~(sizeof(type)) ) + sizeof(type) ) ))[-1])) +#define va_arg(ap, type) (*(((type *) (ap = (char *)((((unsigned long)ap + __builtin_align(type) - 1) & ~(__builtin_align(type) - 1) ) + sizeof(type)))) - 1)) +#endif + +ENode *assign_node; +Boolean temp_reference_init; +static SInt32 assign_value; // type? +static ENode *firstarrayexpr; +static Match5 user_std_match; +static Boolean cexpr_hascall; +static Boolean cexpr_esearch_bool[MAXEXPR]; +static Boolean cexpr_rsearch_bool[MAXEXPR]; +static CExprSearchCB cexpr_esearch_callback; +static CExprReplaceCB cexpr_rsearch_callback; +static Type *cexpr_left_conversion_type; +static Type *cexpr_right_conversion_type; + +static FuncArg mon_arg = {NULL, NULL, NULL, NULL, 0, 0, 0}; +static FuncArg diadic_arg2 = {NULL, NULL, NULL, NULL, 0, 0, 0}; +static FuncArg diadic_arg1 = {&diadic_arg1, NULL, NULL, NULL, 0, 0, 0}; + +static void CExpr_RecSearchExprTree(ENode *expr) { + ENodeList *list; + +restart: + if (cexpr_esearch_bool[expr->type]) + cexpr_esearch_callback(expr); + + switch (expr->type) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + expr = expr->data.monadic; + goto restart; + case EMUL: + case EMULV: + case EDIV: + case EMODULO: + case EADDV: + case ESUBV: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBCLR: + case EBTST: + case EBSET: + CExpr_RecSearchExprTree(expr->data.diadic.left); + expr = expr->data.diadic.right; + goto restart; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ETEMP: + case EARGOBJ: + case ELOCOBJ: + case ELABEL: + case EOBJLIST: + case EMEMBER: + case EINSTRUCTION: + case EVECTOR128CONST: + return; + case EFUNCCALL: + case EFUNCCALLP: + for (list = expr->data.funccall.args; list; list = list->next) + CExpr_RecSearchExprTree(list->node); + expr = expr->data.funccall.funcref; + goto restart; + case ENULLCHECK: + CExpr_RecSearchExprTree(expr->data.nullcheck.nullcheckexpr); + expr = expr->data.nullcheck.condexpr; + goto restart; + case EMFPOINTER: + CExpr_RecSearchExprTree(expr->data.mfpointer.accessnode); + expr = expr->data.mfpointer.mfpointer; + goto restart; + case ECOND: + CExpr_RecSearchExprTree(expr->data.cond.cond); + CExpr_RecSearchExprTree(expr->data.cond.expr1); + expr = expr->data.cond.expr2; + goto restart; + case ENEWEXCEPTION: + case ENEWEXCEPTIONARRAY: + CExpr_RecSearchExprTree(expr->data.newexception.initexpr); + expr = expr->data.newexception.tryexpr; + goto restart; + case EINITTRYCATCH: + if (expr->data.itc.initexpr) + CExpr_RecSearchExprTree(expr->data.itc.initexpr); + if (expr->data.itc.tryexpr) + CExpr_RecSearchExprTree(expr->data.itc.tryexpr); + if (expr->data.itc.catchexpr) + CExpr_RecSearchExprTree(expr->data.itc.catchexpr); + if (expr->data.itc.result) + CExpr_RecSearchExprTree(expr->data.itc.result); + return; + default: + CError_FATAL(128); + } +} + +void CExpr_SearchExprTree(ENode *expr, CExprSearchCB callback, int count, ...) { + va_list ap; + short i; + + cexpr_esearch_callback = callback; + + va_start(ap, count); + for (i = 0; i < MAXEXPR; i++) + cexpr_esearch_bool[i] = 0; + i = 0; + while ((short) i < count) { + cexpr_esearch_bool[va_arg(ap, int)] = 1; + ++i; + } + va_end(ap); + + CExpr_RecSearchExprTree(expr); +} + +static ENode *CExpr_RecSearchExprTreeReplace(ENode *expr) { + ENodeList *list; + ENode *replaced; + + if (cexpr_rsearch_bool[expr->type]) { + replaced = cexpr_rsearch_callback(expr); + if (!replaced) + return expr; + expr = replaced; + } + + switch (expr->type) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + expr->data.monadic = CExpr_RecSearchExprTreeReplace(expr->data.monadic); + return expr; + case EMUL: + case EMULV: + case EDIV: + case EMODULO: + case EADDV: + case ESUBV: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBCLR: + case EBTST: + case EBSET: + expr->data.diadic.left = CExpr_RecSearchExprTreeReplace(expr->data.diadic.left); + expr->data.diadic.right = CExpr_RecSearchExprTreeReplace(expr->data.diadic.right); + return expr; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ETEMP: + case EARGOBJ: + case ELOCOBJ: + case ELABEL: + case EMEMBER: + case EINSTRUCTION: + case EVECTOR128CONST: + return expr; + case EFUNCCALL: + case EFUNCCALLP: + for (list = expr->data.funccall.args; list; list = list->next) + list->node = CExpr_RecSearchExprTreeReplace(list->node); + expr->data.funccall.funcref = CExpr_RecSearchExprTreeReplace(expr->data.funccall.funcref); + return expr; + case ENULLCHECK: + expr->data.nullcheck.nullcheckexpr = CExpr_RecSearchExprTreeReplace(expr->data.nullcheck.nullcheckexpr); + expr->data.nullcheck.condexpr = CExpr_RecSearchExprTreeReplace(expr->data.nullcheck.condexpr); + return expr; + case EMFPOINTER: + expr->data.mfpointer.accessnode = CExpr_RecSearchExprTreeReplace(expr->data.mfpointer.accessnode); + expr->data.mfpointer.mfpointer = CExpr_RecSearchExprTreeReplace(expr->data.mfpointer.mfpointer); + return expr; + case ECOND: + expr->data.cond.cond = CExpr_RecSearchExprTreeReplace(expr->data.cond.cond); + expr->data.cond.expr1 = CExpr_RecSearchExprTreeReplace(expr->data.cond.expr1); + expr->data.cond.expr2 = CExpr_RecSearchExprTreeReplace(expr->data.cond.expr2); + return expr; + default: + CError_FATAL(220); + return NULL; + } +} + +ENode *CExpr_SearchExprTreeReplace(ENode *expr, CExprReplaceCB callback, int count, ...) { + va_list ap; + short i; + + cexpr_rsearch_callback = callback; + + va_start(ap, count); + for (i = 0; i < MAXEXPR; i++) + cexpr_rsearch_bool[i] = 0; + i = 0; + while ((short) i < count) { + cexpr_rsearch_bool[va_arg(ap, int)] = 1; + ++i; + } + va_end(ap); + + return CExpr_RecSearchExprTreeReplace(expr); +} + +static void CExpr_HasFuncCallCallBack(ENode *expr) { + cexpr_hascall = 1; +} + +Boolean CExpr_HasFuncCall(ENode *expr) { + cexpr_hascall = 0; + CExpr_SearchExprTree(expr, CExpr_HasFuncCallCallBack, 2, EFUNCCALL, EFUNCCALLP); + return cexpr_hascall; +} + +void CExpr_AliasTransform(ENode *expr) { + ENode *n; + + Object *obj = expr->data.objref; + if (obj->u.alias.offset) { + n = makediadicnode( + create_objectrefnode(obj->u.alias.object), + intconstnode(TYPE(&stunsignedlong), obj->u.alias.offset), + EADD); + *expr = *n; + } else { + expr->data.objref = obj->u.alias.object; + } +} + +ENode *CExpr_UnaryFloatExpression(ENode *expr) { + return expr; +} + +ENode *CExpr_BinaryFloatExpression(ENode *expr) { + return expr; +} + +ENode *CExpr_NewENode(ENodeType ty) { + ENode *expr = lalloc(sizeof(ENode)); + memclrw(expr, sizeof(ENode)); + expr->type = ty; + return expr; +} + +ENode *CExpr_NewTemplDepENode(TemplDepSubType t) { + ENode *expr = CExpr_NewENode(ETEMPLDEP); + expr->rtype = &sttemplexpr; + expr->data.templdep.subtype = t; + return expr; +} + +ENode *nullnode(void) { + ENode *expr = CExpr_NewENode(EINTCONST); + expr->rtype = (Type *) &stsignedlong; + return expr; +} + +ENode *intconstnode(Type *type, SInt32 value) { + ENode *expr = CExpr_NewENode(EINTCONST); + expr->rtype = type; + CInt64_SetLong(&expr->data.intval, value); + return expr; +} + +ENode *stringconstnode(char *str) { + ENode *expr; + SInt32 size; + + size = strlen(str) + 1; + expr = CExpr_NewENode(ESTRINGCONST); + expr->rtype = CDecl_NewArrayType((Type *) &stchar, size); + expr->data.string.size = size; + expr->data.string.data = str; + expr->data.string.ispascal = 0; + if (copts.const_strings) + expr->flags = Q_CONST; + + expr = makemonadicnode(expr, EINDIRECT); + expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); + return expr; +} + +ENode *forceintegral(ENode *expr) { + if (!IS_TYPE_ENUM(expr->rtype)) { + CError_Error(CErrorStr144); + return nullnode(); + } else { + expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; + return expr; + } +} + +ENode *makemonadicnode(ENode *inner, ENodeType ty) { + ENode *expr = lalloc(sizeof(ENode)); + expr->type = ty; + if ((expr->cost = inner->cost) == 0) + expr->cost = 1; + expr->flags = inner->flags & ENODE_FLAG_QUALS; + expr->rtype = inner->rtype; + expr->data.monadic = inner; + return expr; +} + +ENode *makediadicnode(ENode *left, ENode *right, ENodeType ty) { + ENode *expr = lalloc(sizeof(ENode)); + expr->type = ty; + expr->rtype = left->rtype; + expr->data.diadic.left = left; + expr->data.diadic.right = right; + + if (left->cost != right->cost) { + expr->cost = right->cost; + if (left->cost > expr->cost) + expr->cost = left->cost; + } else { + expr->cost = right->cost + 1; + if (expr->cost > 200) + expr->cost = 200; + } + + expr->flags = (left->flags | right->flags) & ENODE_FLAG_QUALS; + return expr; +} + +ENode *makecommaexpression(ENode *left, ENode *right) { + ENode *expr; + + if (ENODE_IS(right, EINDIRECT) && !ENODE_IS(right->data.monadic, EBITFIELD)) { + Boolean savecpp = copts.cplusplus; + copts.cplusplus = 1; + expr = makediadicnode(left, getnodeaddress(right, 0), ECOMMA); + copts.cplusplus = savecpp; + expr->rtype = expr->data.diadic.right->rtype; + expr = makemonadicnode(expr, EINDIRECT); + } else { + expr = makediadicnode(left, right, ECOMMA); + } + + expr->rtype = right->rtype; + expr->flags = right->flags; + return expr; +} + +short iszero(ENode *expr) { + switch (expr->type) { + case EINTCONST: + return CInt64_IsZero(&expr->data.intval); + case EFLOATCONST: + return CMach_FloatIsZero(expr->data.floatval); + default: + return 0; + } +} + +short isnotzero(ENode *expr) { + Object *obj; + + switch (expr->type) { + case EINTCONST: + return !CInt64_IsZero(&expr->data.intval); + case EFLOATCONST: + return !CMach_FloatIsZero(expr->data.floatval); + case ESTRINGCONST: + case ETEMP: + return 1; + case EOBJREF: + obj = expr->data.objref; + break; + case EADD: + case ESUB: + if (ENODE_IS(expr->data.diadic.left, EOBJREF) && ENODE_IS(expr->data.diadic.right, EINTCONST)) { + obj = expr->data.diadic.left->data.objref; + break; + } + if (ENODE_IS(expr->data.diadic.left, EINTCONST) && ENODE_IS(expr->data.diadic.right, EOBJREF)) { + obj = expr->data.diadic.right->data.objref; + break; + } + return 0; + default: + return 0; + } + + switch (obj->datatype) { + case DLOCAL: + return 1; + default: + return 0; + } +} + +Boolean CExpr_IsOne(ENode *expr) { + if (ENODE_IS(expr, EINTCONST)) + return CInt64_Equal(expr->data.intval, cint64_one); + else if (ENODE_IS(expr, EFLOATCONST)) + return CMach_FloatIsOne(expr->data.floatval); + else + return 0; +} + +Boolean CExpr_AllBitsSet(ENode *expr) { + SInt32 v; + + if (ENODE_IS(expr, EINTCONST)) { + switch (expr->rtype->size) { + case 1: + v = CInt64_GetULong(&expr->data.intval) & 0xFF; + return v == 0xFF; + case 2: + v = CInt64_GetULong(&expr->data.intval) & 0xFFFF; + return v == 0xFFFF; + case 3: + v = CInt64_GetULong(&expr->data.intval) & 0xFFFFFF; + return v == 0xFFFFFF; + case 4: + v = CInt64_GetULong(&expr->data.intval) & 0xFFFFFFFF; + return v == 0xFFFFFFFF; + default: + return CInt64_Equal(expr->data.intval, cint64_negone); + } + } + + return 0; +} + +ENode *CExpr_NewETEMPNode(Type *type, Boolean assign_id) { + ENode *expr = lalloc(sizeof(ENode)); + expr->type = ETEMP; + expr->cost = 0; + expr->flags = 0; + expr->rtype = CDecl_NewPointerType(type); + expr->data.temp.type = type; + expr->data.temp.uniqueid = assign_id ? CParser_GetUniqueID() : 0; + expr->data.temp.needs_dtor = 0; + return expr; +} + +static ENode *CExpr_DerefETEMPCopy(ENode *expr) { + ENode *copy; + + CError_ASSERT(636, IS_TYPE_POINTER_ONLY(expr->rtype)); + + copy = lalloc(sizeof(ENode)); + *copy = *expr; + copy = makemonadicnode(copy, EINDIRECT); + copy->rtype = TYPE_POINTER(copy->rtype)->target; + return copy; +} + +ENode *CExpr_GetETEMPCopy(ENode *expr) { + ENode *newnode; + ENode *assnode; + ENode *finalnode; + + newnode = CExpr_NewETEMPNode(expr->rtype, 1); + newnode->flags = expr->flags; + + assnode = makediadicnode(CExpr_DerefETEMPCopy(newnode), expr, EASS); + assnode->data.diadic.right = lalloc(sizeof(ENode)); + *assnode->data.diadic.right = *expr; + *expr = *assnode; + + finalnode = makemonadicnode(newnode, EINDIRECT); + finalnode->rtype = expr->rtype; + return finalnode; +} + +ENode *integralpromote(ENode *expr) { + if (!IS_TYPE_INT(expr->rtype)) + expr = forceintegral(expr); + + if (TYPE_INTEGRAL(expr->rtype)->integral >= IT_INT) + return expr; + + if (!ENODE_IS(expr, EINTCONST)) + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = (Type *) &stsignedint; + + return expr; +} + +CInt64 CExpr_IntConstConvert(Type *a, Type *b, CInt64 val) { + if (a == (Type *) &stbool) + return CMach_CalcIntDiadic(b, val, TK_LOGICAL_NE, cint64_zero); + else + return CMach_CalcIntDiadic(a, val, '+', cint64_zero); +} + +ENode *promote(ENode *expr, Type *type) { + if (ENODE_IS(expr, EINTCONST)) { + if (IS_TYPE_FLOAT(type)) { + expr->type = EFLOATCONST; + expr->data.floatval = CMach_CalcFloatConvertFromInt(expr->rtype, expr->data.intval); + } else { + expr->data.intval = CExpr_IntConstConvert(type, expr->rtype, expr->data.intval); + } + expr->rtype = type; + return expr; + } + if (ENODE_IS(expr, EFLOATCONST)) { + if (IS_TYPE_FLOAT(type)) { + expr->data.floatval = CMach_CalcFloatConvert(type, expr->data.floatval); + expr->rtype = type; + return expr; + } else if (IS_TYPE_INT(type)) { + expr->data.intval = CMach_CalcIntConvertFromFloat(type, expr->data.floatval); + expr->type = EINTCONST; + expr->rtype = type; + return expr; + } + } + + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = type; + return expr; +} + +void CExpr_ArithmeticConversion(ENode **left, ENode **right) { + switch ((*left)->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + break; + case TYPEENUM: + (*left)->rtype = TYPE_ENUM((*left)->rtype)->enumtype; + break; + default: + CError_Error(CErrorStr144); + (*left) = nullnode(); + } + + switch ((*right)->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + break; + case TYPEENUM: + (*right)->rtype = TYPE_ENUM((*right)->rtype)->enumtype; + break; + default: + CError_Error(CErrorStr144); + (*right) = nullnode(); + } + + if (IS_TYPE_FLOAT((*left)->rtype) || IS_TYPE_FLOAT((*right)->rtype)) { + if ((*left)->rtype != (*right)->rtype) { + if (TYPE_INTEGRAL((*left)->rtype)->integral > TYPE_INTEGRAL((*right)->rtype)->integral) + *right = promote(*right, (*left)->rtype); + else + *left = promote(*left, (*right)->rtype); + } + return; + } + + *left = integralpromote(*left); + *right = integralpromote(*right); + if ((*left)->rtype != (*right)->rtype) { + if (TYPE_INTEGRAL((*left)->rtype)->integral < TYPE_INTEGRAL((*right)->rtype)->integral) { + ENode **tmp = left; + left = right; + right = tmp; + } + + if ((*left)->rtype->size == (*right)->rtype->size && !is_unsigned((*left)->rtype) && is_unsigned((*right)->rtype)) { + if ((*left)->rtype == (Type *) &stsignedlong) { + *left = promote(*left, (Type *) &stunsignedlong); + } else { + CError_ASSERT(838, (*left)->rtype == (Type *) &stsignedlonglong); + *left = promote(*left, (Type *) &stunsignedlonglong); + } + } + + *right = promote(*right, (*left)->rtype); + } +} + +static ENode *CExpr_GetEA(ENode *expr) { + ENode *copy; + + for (;;) { + switch (expr->type) { + case EINDIRECT: + expr = expr->data.monadic; + for (;;) { + switch (expr->type) { + case EOBJREF: + copy = lalloc(sizeof(ENode)); + *copy = *expr; + return copy; + case ECOMMA: + expr = expr->data.diadic.right; + continue; + default: + return CExpr_GetETEMPCopy(expr); + } + } + break; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + expr = expr->data.monadic; + continue; + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + expr = expr->data.monadic; + continue; + case ECOMMA: + expr = expr->data.diadic.right; + continue; + default: + return NULL; + } + } +} + +ENode *CExpr_TempModifyExpr(ENode *expr) { + Type *type; + ENode *left; + ENode *right; + ENode *eanode; + ENode *tempnode; + ENode *indnode; + ENode *truenode; + + type = expr->rtype; + tempnode = CExpr_NewETEMPNode(type, 1); + eanode = CExpr_GetEA(expr); + if (!eanode) { + CError_Error(CErrorStr142); + return expr; + } + + // tempnode = expr + left = makemonadicnode(tempnode, EINDIRECT); + left->rtype = type; + left = makediadicnode(left, expr, EASS); + + // eanode = true + indnode = makemonadicnode(eanode, EINDIRECT); + indnode->rtype = type; + truenode = nullnode(); + truenode->rtype = (Type *) &stbool; + CInt64_SetLong(&truenode->data.intval, 1); + right = makediadicnode(indnode, truenode, EASS); + + expr = makediadicnode(left, right, ECOMMA); + + indnode = makemonadicnode(tempnode, EINDIRECT); + indnode->rtype = type; + return makediadicnode(expr, indnode, ECOMMA); +} + +Boolean CExpr_IsLValue(ENode *expr) { + while (!ENODE_IS(expr, EINDIRECT)) { + switch (expr->type) { + case EPREINC: + case EPREDEC: + return copts.cplusplus; + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + if (!copts.cplusplus) + return 0; + expr = expr->data.diadic.left; + continue; + case ECOMMA: + if (!copts.cplusplus) + return 0; + expr = expr->data.diadic.right; + continue; + case ECOND: + if ( + copts.cplusplus && + is_typesame(expr->data.cond.expr1->rtype, expr->data.cond.expr2->rtype) && + (expr->data.cond.expr1->rtype->type != TYPEPOINTER || (UInt32) (expr->data.cond.expr1->flags & ENODE_FLAG_QUALS) == (expr->data.cond.expr2->flags & ENODE_FLAG_QUALS)) + ) { + return CExpr_IsLValue(expr->data.cond.expr1) && CExpr_IsLValue(expr->data.cond.expr2); + } + return 0; + default: + return 0; + } + } + + expr = expr->data.monadic; + switch (expr->type) { + case ETEMP: + return 0; + case EFUNCCALL: + if (expr->data.funccall.functype->functype->type != TYPEPOINTER || (expr->data.funccall.functype->flags & FUNC_IS_CTOR)) + return 0; + default: + return 1; + } +} + +ENode *CExpr_LValue(ENode *expr, Boolean flag1, Boolean flag2) { + ENode *eanode; + ENode *tmpnode; + +loop: + switch (expr->type) { + case ETYPCON: + if (copts.pointercast_lvalue || !copts.ANSIstrict) { + if (expr->rtype->type == TYPEPOINTER && expr->data.monadic->rtype->type == TYPEPOINTER) { + switch (expr->data.monadic->type) { + case EINDIRECT: + case ETYPCON: + expr->data.monadic->rtype = expr->rtype; + expr->data.monadic->flags = expr->flags; + expr = expr->data.monadic; + goto loop; + } + } + } + break; + case EINDIRECT: + if (flag2) { + if (!CExpr_IsLValue(expr)) + CError_Warning(CErrorStr142); + + if ( + ENODE_IS(expr->data.monadic, EOBJREF) && + expr->data.monadic->data.objref->name == this_name_node && + cscope_currentfunc && + cscope_currentclass && + expr->data.monadic->data.objref == CClass_ThisSelfObject()) + CError_Error(CErrorStr189); + } + if (flag1) { + if (CParser_IsConst(expr->rtype, expr->flags & ENODE_FLAG_QUALS)) + CError_Error(CErrorStr179); + } + return expr; + case EPREINC: + case EPREDEC: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + if (copts.cplusplus) { + if ((eanode = CExpr_GetEA(expr))) { + tmpnode = makediadicnode(expr, eanode, ECOMMA); + tmpnode->rtype = tmpnode->data.diadic.right->rtype; + tmpnode = makemonadicnode(tmpnode, EINDIRECT); + tmpnode->rtype = expr->rtype; + return tmpnode; + } + CError_Error(CErrorStr190); + return expr; + } + break; + case ECOND: + if ( + copts.cplusplus && + is_typesame(expr->data.cond.expr1->rtype, expr->data.cond.expr2->rtype) && + (expr->data.cond.expr1->rtype->type != TYPEPOINTER || (UInt32) (expr->data.cond.expr1->flags & ENODE_FLAG_QUALS) == (expr->data.cond.expr2->flags & ENODE_FLAG_QUALS)) + ) { + expr->data.cond.expr1 = CExpr_LValue(expr->data.cond.expr1, flag1, flag2); + expr->data.cond.expr2 = CExpr_LValue(expr->data.cond.expr2, flag1, flag2); + if (ENODE_IS(expr->data.cond.expr1, EINDIRECT) && ENODE_IS(expr->data.cond.expr2, EINDIRECT)) { + if (!ENODE_IS(expr->data.cond.expr1->data.monadic, EBITFIELD) && !ENODE_IS(expr->data.cond.expr2->data.monadic, EBITFIELD)) { + expr->data.cond.expr1 = getnodeaddress(expr->data.cond.expr1, 0); + expr->data.cond.expr2 = getnodeaddress(expr->data.cond.expr2, 0); + expr->rtype = expr->data.cond.expr1->rtype; + tmpnode = makemonadicnode(expr, EINDIRECT); + tmpnode->rtype = TYPE_POINTER(tmpnode->rtype)->target; + return tmpnode; + } + } + } + break; + } + + if (flag2) + CError_Error(CErrorStr142); + return expr; +} + +ENode *CExpr_MakeObjRefNode(Object *obj, Boolean flag) { + ENode *expr; + + if (obj->sclass == TK_TYPEDEF) { + CError_Error(CErrorStr141); + return intconstnode((Type *) &void_ptr, 0); + } + + expr = lalloc(sizeof(ENode)); + memclrw(expr, sizeof(ENode)); + expr->type = EOBJREF; + expr->data.objref = obj; + expr->rtype = CDecl_NewPointerType(obj->type); + + if (!IS_TYPE_FUNC(obj->type)) + expr->flags = obj->qual & ENODE_FLAG_QUALS; + if (flag) + obj->flags |= OBJECT_USED; + + return expr; +} + +ENode *create_objectrefnode(Object *obj) { + if (name_obj_check && !name_obj_check(NULL, obj)) + return intconstnode((Type *) &void_ptr, 0); + return CExpr_MakeObjRefNode(obj, 1); +} + +ENode *create_objectnode2(Object *obj) { + ENode *expr; + + if (name_obj_check && !name_obj_check(NULL, obj)) + return nullnode(); + + expr = makemonadicnode(CExpr_MakeObjRefNode(obj, 1), EINDIRECT); + expr->rtype = TYPE_POINTER(expr->rtype)->target; + return expr; +} + +ENode *create_objectnode(Object *obj) { + return checkreference(create_objectnode2(obj)); +} + +static ENode *CExpr_ExpandArg(ENode *expr, Type *type) { + if (ENODE_IS(expr, ETYPCON) && IS_TYPE_FLOAT(type)) { + expr->rtype = type; + return expr; + } else { + return promote(expr, type); + } +} + +ENode *CExpr_IsTempConstruction(ENode *expr, Type *type, ENode **resultexpr) { + ENodeList *args; + ENode *funccall; + ENode *funcref; + + if ( + !ENODE_IS(expr, EINDIRECT) || + expr->rtype != type || + !ENODE_IS((funccall = expr->data.monadic), EFUNCCALL) || + !(args = funccall->data.funccall.args) + ) + return NULL; + + if (!ENODE_IS((funcref = funccall->data.funccall.funcref), EOBJREF) || !CClass_IsConstructor(funcref->data.objref)) { + if (expr->data.monadic->data.funccall.functype->functype != type) + return NULL; + if (CABI_GetStructResultArgumentIndex(expr->data.monadic->data.funccall.functype) == 1) { + args = args->next; + CError_ASSERT(1277, args); + } + } + + if (resultexpr) + *resultexpr = args->node; + return expr->data.monadic; +} + +ENode *CExpr_AdjustFunctionCall(ENode *expr) { + ENodeList *list; + + switch (expr->data.funccall.functype->functype->type) { + case TYPECLASS: + CDecl_CompleteType(expr->data.funccall.functype->functype); + case TYPESTRUCT: + if (!expr->data.funccall.functype->functype->size) + CError_Error(CErrorStr136, expr->data.funccall.functype->functype, 0); + } + + if (CMach_GetFunctionResultClass(expr->data.funccall.functype)) { + list = lalloc(sizeof(ENodeList)); + if (IS_TYPE_CLASS(expr->data.funccall.functype->functype)) { + CDecl_CompleteType(expr->data.funccall.functype->functype); + if (CClass_Destructor(TYPE_CLASS(expr->data.funccall.functype->functype))) + list->node = create_temp_node2(expr->rtype); + else + list->node = create_temp_node(expr->rtype); + } else { + list->node = create_temp_node(expr->rtype); + } + list->next = expr->data.funccall.args; + expr->data.funccall.args = list; + + if (expr->data.funccall.funcref->flags & ENODE_FLAG_10) + expr = CSOM_EnvCheck(expr, list); + + expr = makemonadicnode(expr, EINDIRECT); + expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); + return expr; + } + + if (expr->data.funccall.funcref->flags & ENODE_FLAG_10) + expr = CSOM_EnvCheck(expr, NULL); + return expr; +} + +ENode *funccallexpr(Object *func, ENode *arg1, ENode *arg2, ENode *arg3, ENode *arg4) { + ENode *expr; + TypeFunc *tfunc; + ENodeList *list; + + tfunc = TYPE_FUNC(func->type); + CError_ASSERT(1411, IS_TYPE_FUNC(tfunc)); + + expr = lalloc(sizeof(ENode)); + expr->type = EFUNCCALL; + expr->cost = 4; + expr->rtype = tfunc->functype; + expr->flags = tfunc->qual & ENODE_FLAG_QUALS; + expr->data.funccall.funcref = create_objectrefnode(func); + expr->data.funccall.functype = tfunc; + + if (arg1) { + list = lalloc(sizeof(ENodeList)); + expr->data.funccall.args = list; + list->node = arg1; + if (arg2) { + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = arg2; + if (arg3) { + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = arg3; + if (arg4) { + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = arg4; + } + } + } + list->next = NULL; + } else { + expr->data.funccall.args = NULL; + } + + return CExpr_AdjustFunctionCall(expr); +} + +ENode *CExpr_FuncCallSix(Object *func, ENode *arg1, ENode *arg2, ENode *arg3, ENode *arg4, ENode *arg5, ENode *arg6) { + ENode *expr; + TypeFunc *tfunc; + ENodeList *list; + + tfunc = TYPE_FUNC(func->type); + CError_ASSERT(1460, IS_TYPE_FUNC(tfunc)); + + expr = lalloc(sizeof(ENode)); + expr->type = EFUNCCALL; + expr->cost = 4; + expr->rtype = tfunc->functype; + expr->flags = tfunc->qual & ENODE_FLAG_QUALS; + expr->data.funccall.funcref = create_objectrefnode(func); + expr->data.funccall.functype = tfunc; + + list = lalloc(sizeof(ENodeList)); + expr->data.funccall.args = list; + list->node = arg1; + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = arg2; + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = arg3; + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = arg4; + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = arg5; + if (arg6) { + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = arg6; + } + list->next = NULL; + + return CExpr_AdjustFunctionCall(expr); +} + +static void CExpr_CalcStdAssign(short checkresult, Match5 *match, Type *t1, UInt32 q1, Type *t2, UInt32 q2, Boolean flag) { + memclrw(match, sizeof(Match5)); + switch (checkresult) { + case CheckResult1: + match->x0++; + break; + case CheckResult2: + match->x2++; + break; + case CheckResult3: + match->x4++; + match->x6 += assign_value; + break; + default: + CError_FATAL(1504); + } + + if (flag || (IS_TYPE_POINTER_ONLY(t2) && (IS_TYPE_POINTER_ONLY(t1) || IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(t2))) != 0)) { + if ((q2 & Q_CONST) == (q1 & Q_CONST)) + match->x8++; + if ((q2 & Q_VOLATILE) == (q1 & Q_VOLATILE)) + match->x8++; + } +} + +void CExpr_MatchCV(Type *t1, UInt32 q1, Type *t2, UInt32 q2, Match13 *match) { + Boolean r8; + + if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(t2))) { + t2 = TYPE_POINTER(t2)->target; + r8 = 1; + } else { + r8 = 0; + } + + while (IS_TYPE_POINTER_ONLY(t2) && IS_TYPE_POINTER_ONLY(t1)) { + if (r8) { + if ((TYPE_POINTER(t1)->qual & Q_CONST) != (TYPE_POINTER(t2)->qual & Q_CONST)) + match->anotherm5.x8--; + if ((TYPE_POINTER(t1)->qual & Q_VOLATILE) != (TYPE_POINTER(t2)->qual & Q_VOLATILE)) + match->anotherm5.x8--; + } + t2 = TYPE_POINTER(t2)->target; + t1 = TYPE_POINTER(t1)->target; + r8 = 1; + } + + if ((q1 & Q_CONST) != (q2 & Q_CONST)) + match->anotherm5.x8--; + if ((q1 & Q_VOLATILE) != (q2 & Q_VOLATILE)) + match->anotherm5.x8--; +} + +Boolean CExpr_MatchAssign(Type *type, UInt32 qual, ENode *expr, Match13 *match) { + switch (assign_check(expr, type, qual, 0, 0, 1)) { + case CheckResult0: + return 0; + case CheckResult1: + match->anotherm5.x0++; + break; + case CheckResult2: + match->anotherm5.x2++; + break; + case CheckResult3: + match->anotherm5.x4++; + match->anotherm5.x6 += assign_value; + break; + case CheckResult4: + match->xE++; + match->match5.x0 += user_std_match.x0; + match->match5.x2 += user_std_match.x2; + match->match5.x4 += user_std_match.x4; + match->match5.x6 += user_std_match.x6; + match->match5.x8 += user_std_match.x8; + break; + default: + CError_FATAL(1585); + } + + if (IS_TYPE_POINTER_ONLY(type)) + CExpr_MatchCV(expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, qual, match); + + return 1; +} + +static short CExpr_StdMatchCompare(Match5 *a, Match5 *b, Boolean flag) { + if (a->x0 > b->x0) return 1; + if (a->x0 == b->x0) { + if (a->x2 > b->x2) return 1; + if (a->x2 == b->x2) { + if (a->x4 > b->x4) return 1; + if (a->x4 == b->x4) { + if (a->x6 > b->x6) return 1; + if (a->x6 == b->x6) { + if (!flag) + return 0; + if (a->x8 > b->x8) return 1; + if (a->x8 == b->x8) return 0; + } + } + } + } + return -1; +} + +static short CExpr2_MemberPointerConversion(Type *type, ENode *expr, Boolean flag1) { + ENode *newnode; + short depth; + + newnode = lalloc(sizeof(ENode)); + *newnode = *expr; + if (!IS_TYPE_MEMBERPOINTER(newnode->rtype)) { + newnode = CExpr_MemberPointerConversion(newnode, TYPE_MEMBER_POINTER(type), flag1); + if (iscpp_typeequal(newnode->rtype, type)) { + if (flag1) + assign_node = newnode; + return CheckResult3; + } + } + + if (IS_TYPE_MEMBERPOINTER(newnode->rtype)) { + CError_ASSERT(1656, IS_TYPE_CLASS(TYPE_MEMBER_POINTER(type)->ty2)); + CError_ASSERT(1657, IS_TYPE_CLASS(TYPE_MEMBER_POINTER(newnode->rtype)->ty2)); + + if (CClass_IsBaseClass(TYPE_CLASS(TYPE_MEMBER_POINTER(type)->ty2), TYPE_CLASS(TYPE_MEMBER_POINTER(newnode->rtype)->ty2), &depth, 0, 0)) { + assign_value = 1000 - depth; + if (flag1) + assign_node = PointerToMemberCast(newnode, TYPE_MEMBER_POINTER(newnode->rtype), TYPE_MEMBER_POINTER(type), 1); + return CheckResult3; + } + } + + return CheckResult0; +} + +ENode *CExpr_ClassPointerCast(BClassList *cls, ENode *origexpr, Boolean nullcheckflag) { + ENode *expr; + ClassList *base; + Boolean do_nullcheck; + TypeClass *tclass; + SInt32 offset; + ENode *tmp; + + expr = origexpr; + tclass = TYPE_CLASS(cls->type); + do_nullcheck = 0; + CError_ASSERT(1691, cls); + + if (!IS_TYPE_POINTER_ONLY(origexpr->rtype)) { + CError_Error(CErrorStr141); + return origexpr; + } + + cls = cls->next; + while (cls) { + for (base = tclass->bases; base; base = base->next) { + if (base->base == TYPE_CLASS(cls->type)) + break; + } + + if (!base) { + CError_Error(CErrorStr221); + while (cls->next) + cls = cls->next; + + tmp = nullnode(); + tmp->rtype = CDecl_NewPointerType(cls->type); + return tmp; + } + + if (base->is_virtual) { + if (!base->base->sominfo) { + do_nullcheck = 1; + if ((offset = base->offset) && !canadd(expr, offset)) { + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); + optimizecomm(expr); + } + expr->rtype = CDecl_NewPointerType(CDecl_NewPointerType(TYPE(base->base))); + expr = makemonadicnode(expr, EINDIRECT); + } + } else { + if ((offset = base->offset)) { + do_nullcheck = 1; + if (!canadd(expr, offset)) { + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); + optimizecomm(expr); + } + } + } + + switch (expr->type) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + expr = makemonadicnode(expr, ETYPCON); + } + + expr->rtype = CDecl_NewPointerType(TYPE(base->base)); + tclass = TYPE_CLASS(cls->type); + cls = cls->next; + } + + if (nullcheckflag && do_nullcheck) + expr = do_castnullcheck(expr, origexpr); + return expr; +} + +ENode *CExpr_GetClassAccessNode(BClassList *a, BClassList *b, ENode *expr, Object *obj, AccessType access, Boolean flag) { + TypeClass *tclass; + ENode *tmp; + + if (!expr) { + if (!cscope_currentfunc || !cscope_currentclass || !cscope_is_member_func || !(expr = CClass_CreateThisSelfExpr())) { + CError_Error(CErrorStr221); + return NULL; + } + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = TYPE(cscope_currentclass); + } + + CError_ASSERT(1786, a); + CError_ASSERT(1787, IS_TYPE_CLASS(expr->rtype)); + + tclass = TYPE_CLASS(expr->rtype); + a = CScope_GetClassAccessPath(a, tclass); + if (!a || a->type != TYPE(tclass)) { + CError_Error(CErrorStr221); + return NULL; + } + + if (flag) + CClass_CheckPathAccess(a, obj, access); + + if (!TYPE_CLASS(a->type)->sominfo) { + if (b) + a = CClass_AppendPath(a, b); + + if (!ENODE_IS(expr, EINDIRECT)) + expr = CExpr_LValue(expr, 0, 0); + + if (ENODE_IS(expr, EINDIRECT)) { + expr->data.monadic->flags = expr->flags; + tmp = expr->data.monadic; + switch (tmp->type) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + tmp = makemonadicnode(tmp, ETYPCON); + } + expr = makemonadicnode(CExpr_ClassPointerCast(a, tmp, 0), EINDIRECT); + expr->rtype = TYPE(tclass); + } + } + + return expr; +} + +static short std_assign_check_overload(NameSpaceObjectList *list, TemplArg *templargs, Type *type, Boolean flag1) { + Object *obj; + Object *used_obj; + Boolean found_non_template_func; + Boolean is_ambig; + TemplFuncInstance *instance; + ENode *expr; + Object *cmp1; + Object *cmp2; + + if (!IS_TYPE_POINTER_ONLY(type) || !IS_TYPE_FUNC(TYPE_POINTER(type)->target)) + return CheckResult0; + + used_obj = NULL; + type = TYPE_POINTER(type)->target; + found_non_template_func = 0; + is_ambig = 0; + for (; list; list = list->next) { + obj = OBJECT(list->object); + if (obj->otype != OT_OBJECT) + continue; + + if (IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_IS_TEMPL)) { + if (!found_non_template_func && CTempl_CanDeduceFunc(obj, TYPE_FUNC(type), templargs)) { + instance = CTempl_DeduceFunc(obj, TYPE_FUNC(type), templargs, NULL, 0); + CError_ASSERT(1861, instance); + if (is_typesame(instance->object->type, type)) { + if (used_obj && used_obj != instance->object) + is_ambig = 1; + else + used_obj = instance->object; + } + } + } else { + if (is_typesame(obj->type, type)) { + if (used_obj && found_non_template_func) { + cmp1 = obj; + if (obj->datatype == DALIAS) + cmp1 = obj->u.alias.object; + cmp2 = used_obj; + if (used_obj->datatype == DALIAS) + cmp2 = used_obj->u.alias.object; + if (cmp1 != cmp2) + is_ambig = 1; + } else { + is_ambig = 0; + used_obj = obj; + } + found_non_template_func = 1; + } + } + } + + if (used_obj) { + if (flag1) { + if (is_ambig) + CError_Error(CErrorStr199); + expr = CExpr_MakeObjRefNode(used_obj, 1); + assign_node = expr; + expr->rtype = CDecl_NewPointerType(used_obj->type); + expr->flags = obj->qual & ENODE_FLAG_QUALS; + used_obj->flags |= OBJECT_USED; + if (used_obj->datatype == DINLINEFUNC) + CError_Error(CErrorStr175); + } + return CheckResult1; + } else { + return CheckResult0; + } +} + +ENode *CExpr_ConvertToBool(ENode *expr, Boolean isExplicit) { + if (IS_TYPE_MEMBERPOINTER(expr->rtype)) + expr = CExpr_ConvertToCondition(expr); + + switch (expr->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPEPOINTER: + if (IS_TYPE_ENUM(expr->rtype)) + expr = forceintegral(expr); + switch (expr->type) { + case EINTCONST: + CInt64_SetLong(&expr->data.intval, !CInt64_IsZero(&expr->data.intval)); + break; + case EFLOATCONST: + CInt64_SetLong(&expr->data.intval, !CMach_FloatIsZero(expr->data.floatval)); + expr->type = EINTCONST; + break; + default: + expr = makemonadicnode(expr, ELOGNOT); + expr->rtype = TYPE(&stbool); + expr = makemonadicnode(expr, ELOGNOT); + } + break; + default: + CError_Error( + isExplicit ? CErrorStr247 : CErrorStr209, + expr->rtype, + expr->flags & ENODE_FLAG_QUALS, + &stbool, + 0); + expr = nullnode(); + } + + expr->rtype = TYPE(&stbool); + return expr; +} + +static short std_assign_check(ENode *expr, Type *type, Boolean flag1, Boolean flag2) { + short result; + + if (copts.cplusplus) { + illegalimplicitconversion = 0; + + if ((result = iscpp_typeequal(expr->rtype, type))) { + assign_node = expr; + if (result == -1) { + assign_value = 1; + return CheckResult3; + } else { + return CheckResult1; + } + } + + if (flag1 && illegalimplicitconversion) { + CError_Error(CErrorStr209, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, 0); + return CheckResult0; + } + } else { + if (is_typeequal(expr->rtype, type)) { + assign_node = expr; + return CheckResult1; + } + } + + if (type == TYPE(&stbool)) { + switch (expr->rtype->type) { + case TYPEPOINTER: + case TYPEMEMBERPOINTER: + assign_value = 0; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + if (flag1) + assign_node = CExpr_ConvertToBool(expr, 0); + return CheckResult3; + default: + return CheckResult0; + } + } + + if (IS_TYPE_ENUM(expr->rtype) && (IS_TYPE_INT(type) || IS_TYPE_FLOAT(type))) { + result = CheckResult3; + if (IS_TYPE_INT(type)) { + if (TYPE_ENUM(expr->rtype)->enumtype == type) { + result = CheckResult2; + } else if (TYPE_INTEGRAL(TYPE_ENUM(expr->rtype)->enumtype)->integral < IT_INT) { + switch (TYPE_INTEGRAL(type)->integral) { + case IT_INT: + if (expr->rtype->size < stsignedint.size || TYPE_ENUM(expr->rtype)->enumtype == TYPE(&stsignedshort)) + result = CheckResult2; + break; + case IT_UINT: + if (expr->rtype->size >= stsignedint.size && TYPE_ENUM(expr->rtype)->enumtype != TYPE(&stsignedshort)) + result = CheckResult2; + break; + } + } + } + if (flag1) { + expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; + assign_node = promote(expr, type); + } + return result; + } + + if (IS_TYPE_INT(expr->rtype) && (IS_TYPE_INT(type) || IS_TYPE_FLOAT(type))) { + result = CheckResult3; + if (TYPE_INTEGRAL(expr->rtype)->integral <= IT_INT) { + if (type == TYPE(&stsignedint) || type == TYPE(&stunsignedint)) { + switch (TYPE_INTEGRAL(type)->integral) { + case IT_INT: + if (expr->rtype->size < stsignedint.size || type != TYPE(&stunsignedshort)) + result = CheckResult2; + break; + case IT_UINT: + if (expr->rtype->size == stsignedint.size && type == TYPE(&stunsignedshort)) + result = CheckResult2; + break; + } + } + } + + if (flag1 && type != expr->rtype) + assign_node = promote(expr, type); + else + assign_node = expr; + return result; + } + + if (IS_TYPE_FLOAT(expr->rtype) && (IS_TYPE_INT(type) || IS_TYPE_FLOAT(type))) { + if (type == TYPE(&stdouble) && (expr->rtype == TYPE(&stfloat) || expr->rtype == TYPE(&stshortdouble))) + result = CheckResult2; + else + result = CheckResult3; + + if (flag1 && (!IS_TYPE_FLOAT(type) || type->size != expr->rtype->size)) + assign_node = promote(expr, type); + else + assign_node = expr; + return result; + } + + if (IS_TYPE_POINTER_ONLY(type)) { + if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval) && (IS_TYPE_INT(expr->rtype) || (!copts.cplusplus && IS_TYPE_ENUM(expr->rtype)))) { + if (flag1) + expr->rtype = TYPE(&stunsignedlong); + assign_node = expr; + return CheckResult3; + } + if (ENODE_IS(expr, EOBJLIST)) { + return std_assign_check_overload(expr->data.objlist.list, expr->data.objlist.templargs, type, flag1); + } + if (IS_TYPE_POINTER_ONLY(expr->rtype)) { + if (ENODE_IS(expr, EOBJREF) && IS_TYPE_FUNC(expr->data.objref->type) && (TYPE_FUNC(expr->data.objref->type)->flags & FUNC_IS_TEMPL)) { + NameSpaceObjectList list; + list.next = NULL; + list.object = OBJ_BASE(expr->data.objref); + return std_assign_check_overload(&list, NULL, type, flag1); + } + if (copts.objective_c && CObjC_IsCompatibleType(expr->rtype, type)) { + assign_value = 1; + return CheckResult3; + } + if (IS_TYPE_CLASS(TYPE_POINTER(expr->rtype)->target) && IS_TYPE_CLASS(TYPE_POINTER(type)->target)) { + short depth; + Boolean isambig; + BClassList *path; + path = CClass_GetBasePath( + TYPE_CLASS(TYPE_POINTER(expr->rtype)->target), + TYPE_CLASS(TYPE_POINTER(type)->target), + &depth, &isambig + ); + if (path) { + assign_value = 1000 - depth; + if (flag1) { + if (isambig) + CError_Error(CErrorStr188); + if (flag2) + CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); + assign_node = CExpr_ClassPointerCast(path, expr, 1); + } + return CheckResult3; + } else { + if (flag1) { + if (isambig) + CError_Error(CErrorStr188); + else + CError_Error( + CErrorStr244, + expr->rtype, + expr->flags & ENODE_FLAG_QUALS, + type, + 0); + } + return CheckResult0; + } + } + } + } + + if (IS_TYPE_MEMBERPOINTER(type) && !IS_TYPE_CLASS(expr->rtype)) { + return CExpr2_MemberPointerConversion(type, expr, flag1); + } + + if (IS_TYPE_CLASS(expr->rtype) && IS_TYPE_CLASS(type)) { + short depth; + Boolean isambig; + BClassList *path; + path = CClass_GetBasePath( + TYPE_CLASS(expr->rtype), + TYPE_CLASS(type), + &depth, &isambig + ); + if (path) { + assign_value = 1000 - depth; + if (flag1) { + if (isambig) + CError_Error(CErrorStr188); + CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); + assign_node = getnodeaddress(expr, 0); + assign_node = CExpr_ClassPointerCast(path, assign_node, 0); + assign_node = makemonadicnode(assign_node, EINDIRECT); + assign_node->rtype = type; + } + return CheckResult3; + } + } + + if (IS_TYPE_ENUM(type)) { + switch (expr->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + if (!copts.cplusplus) { + if (flag1) { + if (copts.pedantic) + CError_Warning(CErrorStr217, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, 0); + assign_node = do_typecast(expr, type, 0); + assign_node->flags = expr->flags; + } + return CheckResult2; + } else { + if (flag1) + CError_Error(CErrorStr217, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, 0); + } + } + } + + return CodeGen_AssignCheck(expr, type, flag1, flag2); +} + +static short is_compatible_conversion(Type *a, Type *b) { + if (IS_TYPE_REFERENCE(a)) + a = TYPE_POINTER(a)->target; + if (IS_TYPE_REFERENCE(b)) + b = TYPE_POINTER(b)->target; + return iscpp_typeequal(b, a); +} + +static void CExpr_ConIteratorInit(ConIterator *iter) { + ClassList *base; + ConIterator *subiter; + ConIteratorList *list; + + for (base = iter->tclass->bases; base; base = base->next) { + if (base->base->flags & CLASS_IS_CONVERTIBLE) { + subiter = galloc(sizeof(ConIterator)); + memclrw(subiter, sizeof(ConIterator)); + subiter->parent = iter; + subiter->tclass = base->base; + CExpr_ConIteratorInit(subiter); + + list = galloc(sizeof(ConIteratorList)); + memclrw(list, sizeof(ConIteratorList)); + list->iter = subiter; + list->next = iter->children; + iter->children = list; + } + } +} + +void CExpr_ConversionIteratorInit(ConversionIterator *iter, TypeClass *tclass) { + memclrw(iter, sizeof(ConversionIterator)); + if (tclass->flags & CLASS_IS_CONVERTIBLE) { + iter->coniter = &iter->myconiter; + iter->myconiter.tclass = tclass; + CExpr_ConIteratorInit(&iter->myconiter); + CScope_InitObjectIterator(&iter->objiter, tclass->nspace); + } +} + +static Boolean CExpr_ConversionIteratorIsHidden(ConIterator *iter, TypeFunc *tfunc) { + CScopeObjectIterator objiter; + ObjBase *obj; + TypeFunc *objtfunc; + + while (iter) { + CScope_InitObjectIterator(&objiter, iter->tclass->nspace); + while (1) { + if (!(obj = CScope_NextObjectIteratorObject(&objiter))) + break; + + objtfunc = TYPE_FUNC(OBJECT(obj)->type); + if ( + IS_TYPE_FUNC(objtfunc) && + (objtfunc->flags & FUNC_CONVERSION) && + is_compatible_conversion(tfunc->functype, objtfunc->functype) && + (tfunc->args->qual & Q_CONST) == (objtfunc->args->qual & Q_CONST) && + (tfunc->qual & Q_CONST) == (objtfunc->qual & Q_CONST) + ) + return 1; + } + iter = iter->parent; + } + + return 0; +} + +Object *CExpr_ConversionIteratorNext(ConversionIterator *iter) { + ConIterator *ci; + Object *obj; + + ci = iter->coniter; + if (!ci) + return NULL; + +restart: + if ((obj = OBJECT(CScope_NextObjectIteratorObject(&iter->objiter)))) { + if ( + IS_TYPE_FUNC(obj->type) && + (TYPE_FUNC(obj->type)->flags & FUNC_CONVERSION) && + !CExpr_ConversionIteratorIsHidden(ci->parent, TYPE_FUNC(obj->type)) + ) { + return obj; + } + goto restart; + } + + do { + if (ci->children) { + iter->coniter = ci->children->iter; + ci->children = ci->children->next; + ci = iter->coniter; + CScope_InitObjectIterator(&iter->objiter, ci->tclass->nspace); + goto restart; + } + } while ((ci = ci->parent)); + + return NULL; +} + +short user_assign_check(ENode *expr, Type *type, UInt32 qual, Boolean flag1, Boolean flag2, Boolean flag3) { + Object *r26; + ENode *r25; + Boolean r24; + Boolean r23; + Boolean r22; + Type *r18b; + short r18; + TypeFunc *r17; + Object *r17b; + NameSpaceObjectList *r16b; + Object *r16; + Object *r15; + ENode *r15b; + ENode *r14; + short r14b; + TypeFunc *r14c; + ENodeList *r14d; + TypeMemberFunc *r13; + ENodeList *r13b; + short result; + FuncArg *arg; + ConversionIterator iter; + Match5 stdmatch; + Match5 match_8C; + Match5 match_98; + BClassList path; + UInt16 chk; + Boolean is_const, is_volatile; + + CError_ASSERT(2378, copts.old_argmatch); + + memclrw(&stdmatch, sizeof(Match5)); + r24 = 0; + r22 = 0; + r23 = 0; + + if (!type->size) + CDecl_CompleteType(type); + if (!expr->rtype->size) + CDecl_CompleteType(expr->rtype); + + if (IS_TYPE_CLASS(expr->rtype)) { + r18 = 0; + CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(expr->rtype)); + while ((r16 = CExpr_ConversionIteratorNext(&iter))) { + r17 = TYPE_FUNC(r16->type); + r14 = CExpr_NewENode(ETEMP); + r14->rtype = r17->functype; + if (IS_TYPE_REFERENCE(r14->rtype)) { + r14->rtype = TYPE_POINTER(r14->rtype)->target; + if (!CParser_IsConst(r14->rtype, r17->qual)) { + r14 = makemonadicnode(r14, EINDIRECT); + r14->data.monadic->rtype = TYPE(&void_ptr); + r14 = makemonadicnode(r14, EINDIRECT); + r14->data.monadic->rtype = TYPE(&void_ptr); + } + } + if ((result = std_assign_check(r14, type, 0, flag3))) { + CExpr_CalcStdAssign(result, &match_98, r17->functype, r17->qual, type, qual, 1); + CError_ASSERT(2419, r17->args && IS_TYPE_POINTER_ONLY(r17->args->type)); + chk = expr->flags; + if (!(is_const = (r17->args->qual & Q_CONST)) && (chk & Q_CONST) != 0) + continue; + if (!(is_volatile = (r17->args->qual & Q_VOLATILE)) && (chk & Q_VOLATILE) != 0) + continue; + //if (((r17->args->qual & Q_CONST) == 0 && (chk & Q_CONST) != 0) || ((r17->args->qual & Q_VOLATILE) == 0 && (chk & Q_VOLATILE) != 0)) + // continue; + + r14b = 0; + if (is_const == (expr->flags & Q_CONST)) + r14b++; + if (is_volatile == (expr->flags & Q_VOLATILE)) + r14b++; + switch (CExpr_StdMatchCompare(&match_98, &stdmatch, 1)) { + case -1: + continue; + case 0: + if (r26 == r16) + continue; + if (r14b < r18) + continue; + if (r14b != r18) + break; + r22 = 1; + continue; + } + r26 = r16; + stdmatch = match_98; + r24 = 1; + r22 = 0; + r18 = r14b; + } + } + } + + if (IS_TYPE_CLASS(type) && (r16b = CClass_Constructor(TYPE_CLASS(type)))) { + memclrw(&match_8C, sizeof(Match5)); + for (; r16b; r16b = r16b->next) { + r17b = OBJECT(r16b->object); + if (r17b->otype != OT_OBJECT) + continue; + r14c = TYPE_FUNC(r17b->type); + if (!IS_TYPE_FUNC(r14c)) + continue; + if (!flag2 && (r14c->qual & Q_EXPLICIT)) + continue; + if (!r14c->args) + continue; + if (!(arg = r14c->args->next)) + continue; + if ((TYPE_CLASS(type)->flags & CLASS_HAS_VBASES) && !(arg = arg->next)) + continue; + if (arg == &elipsis) + continue; + if (arg->next && !arg->next->dexpr && arg->next != &elipsis) + continue; + + r18b = arg->type; + if (IS_TYPE_REFERENCE(r18b)) { + r18b = TYPE_POINTER(r18b)->target; + if (!CParser_IsConst(r18b, arg->qual) && !CExpr_IsLValue(expr)) + continue; + } + + if ((result = std_assign_check(expr, r18b, 0, flag3))) { + CExpr_CalcStdAssign(result, &match_98, r14c->functype, r14c->qual, type, qual, 0); + switch (CExpr_StdMatchCompare(&match_98, &match_8C, 1)) { + case -1: + case 0: + continue; + } + r25 = expr; + match_8C = match_98; + r23 = 1; + r15 = r17b; + } + } + + if (r23) { + if (r24) { + switch (CExpr_StdMatchCompare(&stdmatch, &match_8C, 1)) { + case -1: + stdmatch = match_8C; + r24 = 0; + break; + case 0: + r22 = 1; + break; + } + } else { + stdmatch = match_8C; + } + } + } + + if (r22 && flag1) + CError_Error(CErrorStr199); + + if (r24 || r23) { + if (flag1) { + if (r24) { + r13 = TYPE_METHOD(r26->type); + CError_ASSERT(2537, r13->flags & FUNC_METHOD); + r15b = create_objectrefnode(r26); + r26->flags |= OBJECT_USED; + r14d = lalloc(sizeof(ENodeList)); + r14d->next = NULL; + expr = getnodeaddress(expr, 0); + r14d->node = CExpr_AssignmentPromotion(expr, CDecl_NewPointerType(TYPE(r13->theclass)), expr->flags, 0); + + expr = lalloc(sizeof(ENode)); + expr->type = EFUNCCALL; + expr->cost = 4; + expr->rtype = r13->functype; + expr->flags = r13->qual & ENODE_FLAG_QUALS; + expr->data.funccall.funcref = r15b; + expr->data.funccall.args = r14d; + expr->data.funccall.functype = TYPE_FUNC(r26->type); + assign_node = checkreference(CExpr_AdjustFunctionCall(expr)); + if (assign_node->rtype != type) + assign_node = CExpr_AssignmentPromotion(assign_node, type, qual, 1); + if (!IS_TYPE_REFERENCE(r13->functype)) + temp_reference_init = 1; + } else { + r13b = lalloc(sizeof(ENodeList)); + r13b->next = NULL; + r13b->node = r25; + if (TYPE_CLASS(type)->flags & CLASS_HAS_VBASES) { + r13b->next = lalloc(sizeof(ENodeList)); + r13b->next->node = r25; + r13b->next->next = NULL; + r13b->node = intconstnode(TYPE(&stsignedshort), 1); + } + path.next = NULL; + path.type = type; + assign_node = makemonadicnode(create_temp_node(type), EINDIRECT); + assign_node->rtype = type; + assign_node = CExpr_GenericFuncCall(&path, assign_node, 0, r15, NULL, NULL, r13b, 0, 0, 1); + if (ENODE_IS2(assign_node, EFUNCCALL, EFUNCCALLP)) { + assign_node->rtype = CDecl_NewPointerType(type); + assign_node = makemonadicnode(assign_node, EINDIRECT); + assign_node->rtype = type; + } + temp_reference_init = 1; + } + } + + user_std_match = stdmatch; + return CheckResult4; + } else { + if (flag1) + CError_Error(CErrorStr244, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, qual); + return CheckResult0; + } +} + +ENode *CExpr_ConvertToCondition(ENode *expr) { + switch (expr->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + case TYPEPOINTER: + return expr; + case TYPEENUM: + expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; + return expr; + case TYPEMEMBERPOINTER: + return memberpointercompare(ENOTEQU, expr, nullnode()); + case TYPECLASS: + return CExpr_Convert(expr, TYPE(&stbool), 0, 0, 1); + default: + CError_Error(CErrorStr376, expr->rtype, expr->flags & ENODE_FLAG_QUALS); + return nullnode(); + } +} + +ENode *CExpr_ConvertToIntegral(ENode *expr) { + ConversionIterator iter; + Type *found; + Object *obj; + + switch (expr->rtype->type) { + case TYPEINT: + case TYPEENUM: + return integralpromote(expr); + case TYPECLASS: + CDecl_CompleteType(expr->rtype); + found = NULL; + CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(expr->rtype)); + while ((obj = CExpr_ConversionIteratorNext(&iter))) { + if (IS_TYPE_INT_OR_ENUM(TYPE_FUNC(obj->type)->functype)) { + if (found) { + CError_Error(CErrorStr199); + break; + } + found = TYPE_FUNC(obj->type)->functype; + } + } + if (found) + return integralpromote(CExpr_Convert(expr, found, 0, 0, 1)); + break; + } + + CError_Error(CErrorStr376, expr->rtype, expr->flags & ENODE_FLAG_QUALS); + return nullnode(); +} + +void CExpr_CheckArithmConversion(ENode *expr, Type *type) { + CInt64 val; + + if (expr->rtype == type) + return; + if (expr->rtype == TYPE(&stbool)) + return; + + if (IS_TYPE_INT(expr->rtype)) { + if (IS_TYPE_FLOAT(type)) + return; + CError_ASSERT(2772, IS_TYPE_INT(type)); + + if (type->size > expr->rtype->size) + return; + if (type->size == expr->rtype->size && is_unsigned(type) == is_unsigned(expr->rtype)) + return; + + switch (expr->type) { + case EINTCONST: + if (!CInt64_IsNegative(&expr->data.intval) || is_unsigned(expr->rtype) || !is_unsigned(type)) { + val = CExpr_IntConstConvert(type, expr->rtype, expr->data.intval); + val = CExpr_IntConstConvert(expr->rtype, type, val); + if (CInt64_Equal(val, expr->data.intval)) + return; + } + break; + case ELOGNOT: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case ELAND: + case ELOR: + return; + } + } else { + if (IS_TYPE_FLOAT(type) && type->size >= expr->rtype->size) + return; + } + + CError_Warning(CErrorStr317, expr->rtype, 0, type, 0); +} + +ENode *get_address_of_temp_copy(ENode *expr, Boolean flag) { + char buf[64]; + ENode *result; + Object *obj; + Type *innertype; + + if (flag) { + if (ENODE_IS2(expr, EINTCONST, EFLOATCONST)) { + obj = CParser_NewCompilerDefDataObject(); + obj->type = expr->rtype; + obj->name = CParser_GetUniqueName(); + obj->sclass = TK_STATIC; + if (ENODE_IS(expr, EINTCONST)) { + innertype = expr->rtype; + switch (innertype->type) { + case TYPEINT: + break; + case TYPEENUM: + innertype = TYPE_ENUM(innertype)->enumtype; + break; + case TYPEPOINTER: + innertype = TYPE(&stunsignedlong); + break; + default: + CError_FATAL(2857); + } + CMach_InitIntMem(innertype, expr->data.intval, buf); + } else { + CMach_InitFloatMem(expr->rtype, expr->data.floatval, buf); + } + CInit_DeclareData(obj, buf, NULL, obj->type->size); + return create_objectrefnode(obj); + } + + if (cinit_tempnodefunc == NULL) + result = CExpr_NewETEMPNode(expr->rtype, 1); + else + result = cinit_tempnodefunc(expr->rtype, 0); + result = makemonadicnode(result, EINDIRECT); + result->rtype = TYPE_POINTER(result->rtype)->target; + return makecommaexpression(makediadicnode(result, expr, EASS), result->data.monadic); + } else { + result = nullnode(); + CInt64_SetLong(&result->data.intval, -1); + result->rtype = CDecl_NewPointerType(expr->rtype); + return result; + } +} + +short assign_check(ENode *expr, Type *type, UInt32 qual, Boolean flag1, Boolean flag2, Boolean flag3) { + Type *type2; + Boolean r30; + Boolean r29; + short result; + + assign_value = 1000; + r30 = 0; + r29 = 0; + temp_reference_init = 0; + + type2 = type; + if (IS_TYPE_REFERENCE(type) && !IS_TYPE_FUNC(TYPE_POINTER(type)->target)) { + type2 = TYPE_POINTER(type)->target; + r30 = 1; + } + + assign_node = expr; + if (IS_TYPE_ARRAY(type2)) { + r29 = 1; + type2 = CDecl_NewPointerType(TYPE_POINTER(type2)->target); + } + + if (!type2->size) { + CDecl_CompleteType(type2); + if (!type2->size && !r30) { + if (flag1) { + if (IS_TYPE_CLASS(type2)) + CError_Error(CErrorStr136, type2, 0); + else + CError_Error(CErrorStr244, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type2, qual); + } + return CheckResult0; + } + } + + if (copts.warn_implicitconv && flag1 && !flag2) { + if (IS_TYPE_INT_OR_FLOAT(type2) && IS_TYPE_INT_OR_FLOAT(expr->rtype)) + CExpr_CheckArithmConversion(expr, type2); + } + + result = std_assign_check(expr, type2, flag1, flag3); + if (!result) { + if (IS_TYPE_CLASS(expr->rtype) || IS_TYPE_CLASS(type2)) { + result = user_assign_check(expr, type2, qual, flag1, flag2, flag3); + } else if (flag1) { + CError_Error(CErrorStr244, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type2, qual); + } + } + + if (r30 && result) { + if (flag1) { + if (!ENODE_IS(assign_node, EINDIRECT)) { + if (!r29) { + assign_node = CExpr_LValue(assign_node, 0, 0); + if (!ENODE_IS(assign_node, EINDIRECT)) { + assign_node = get_address_of_temp_copy(assign_node, 1); + temp_reference_init = 1; + } else { + assign_node = getnodeaddress(assign_node, 0); + } + } + } else { + if (!CExpr_IsLValue(assign_node)) + temp_reference_init = 1; + if (!r29) + assign_node = getnodeaddress(assign_node, 0); + } + } else { + if (!r29 && !CExpr_IsLValue(assign_node) && !CParser_IsConst(TYPE_POINTER(type)->target, qual)) { + result = CheckResult0; + } + } + } + + return result; +} + +Boolean CExpr_MatchCompare(Object *obj, Match13 *a, Match13 *b) { + Object *tmp; + ObjectList *list; + + switch (CExpr_StdMatchCompare(&b->anotherm5, &a->anotherm5, 0)) { + case -1: + return 0; + case 0: + if (a->xE > b->xE) + return 0; + if (a->xE != b->xE) + break; + switch (CExpr_StdMatchCompare(&b->match5, &a->match5, 1)) { + case -1: + return 0; + case 0: + if (a->anotherm5.x8 > b->anotherm5.x8) + return 0; + if (a->anotherm5.x8 == b->anotherm5.x8 && (tmp = a->obj)) { + if (tmp->datatype == obj->datatype) { + add_it: + list = lalloc(sizeof(ObjectList)); + list->next = a->list; + a->list = list; + list->object = obj; + return 0; + } + if (obj->datatype == DALIAS) + return 0; + if (tmp->datatype != DALIAS) + goto add_it; + } + } + } + + *a = *b; + a->obj = obj; + return 1; +} + +static void MatchOverloadFunc(Object *obj, FuncArg *args, ENodeList *argexprs, Match13 *match) { + Match13 match2; + + if (IS_TYPE_FUNC(obj->type) && !(TYPE_FUNC(obj->type)->flags & FUNC_IS_TEMPL)) { + memclrw(&match2, sizeof(Match13)); + while (1) { + if (!args || args->type == &stvoid) { + if (!argexprs) + break; + return; + } + + if (args == &elipsis) + break; + if (args == &oldstyle) + break; + + if (!argexprs) { + if (args->dexpr) + break; + return; + } + + if (!CExpr_MatchAssign(args->type, args->qual, argexprs->node, &match2)) + return; + + argexprs = argexprs->next; + args = args->next; + } + + CExpr_MatchCompare(obj, match, &match2); + } +} + +Boolean CExpr_GetFuncMatchArgs(Object *obj, ENodeList *argexprs, ENode *expr, FuncMatchArgs *result) { + ENode *intexpr; + + if (!(TYPE_FUNC(obj->type)->flags & FUNC_METHOD)) { + result->exprs = argexprs; + result->args = TYPE_FUNC(obj->type)->args; + return 1; + } + + if (TYPE_METHOD(obj->type)->is_static) { + result->exprs = argexprs; + result->args = TYPE_FUNC(obj->type)->args; + return 1; + } + + if (TYPE_FUNC(obj->type)->flags & FUNC_IS_CTOR) { + result->exprs = argexprs; + result->args = TYPE_FUNC(obj->type)->args->next; + return 1; + } + + if (expr) { + intexpr = lalloc(sizeof(ENode)); + intexpr->type = EINTCONST; + intexpr->cost = 0; + intexpr->flags = expr->flags; + intexpr->rtype = CDecl_NewPointerType(expr->rtype); + intexpr->data.intval = cint64_zero; + + result->exprs = lalloc(sizeof(ENodeList)); + result->exprs->next = argexprs; + result->exprs->node = intexpr; + + if (obj->datatype == DALIAS) { + result->args = lalloc(sizeof(FuncArg)); + *result->args = *TYPE_FUNC(obj->type)->args; + result->args->type = CDecl_NewPointerType(expr->rtype); + } else { + result->args = TYPE_FUNC(obj->type)->args; + } + + return 1; + } + + return 0; +} + +static NameSpaceObjectList *CExpr_CopyNameSpaceObjectList(NameSpaceObjectList *list) { + NameSpaceObjectList *first; + NameSpaceObjectList *work; + + first = work = lalloc(sizeof(NameSpaceObjectList)); + while (1) { + work->object = list->object; + list = list->next; + if (!list) { + work->next = NULL; + break; + } else { + work->next = lalloc(sizeof(NameSpaceObjectList)); + work = work->next; + } + } + return first; +} + +static void CExpr_MatchArgList(NameSpaceObjectList *list, TemplArg *templargs, ENodeList *argexprs, Match13 *match, ENode *expr, Boolean flag) { + NameSpaceObjectList *copied_list; + NameSpaceObjectList *scan_list; + Object *obj; + ENodeList *scan_expr; + Boolean is_template; + FuncMatchArgs fma; + + if (!copts.old_argmatch) { + CExpr_FuncArgMatch(CExpr_CopyNameSpaceObjectList(list), templargs, argexprs, match, expr, flag); + return; + } + + copied_list = CExpr_CopyNameSpaceObjectList(list); + + for (scan_expr = argexprs; scan_expr; scan_expr = scan_expr->next) + CDecl_CompleteType(scan_expr->node->rtype); + + scan_list = copied_list; + is_template = 0; + for (; scan_list; scan_list = scan_list->next) { + obj = OBJECT(scan_list->object); + if (obj->otype != OT_OBJECT) + continue; + if (IS_TYPE_FUNC(obj->type) && (!flag || !(obj->qual & Q_EXPLICIT))) { + if (!(TYPE_FUNC(obj->type)->flags & FUNC_IS_TEMPL)) { + if (CExpr_GetFuncMatchArgs(obj, argexprs, expr, &fma)) + MatchOverloadFunc(obj, fma.args, fma.exprs, match); + } else { + is_template = 1; + } + } + } + + if (is_template) { + if (!match->obj || match->anotherm5.x2 || match->anotherm5.x4 || match->xE) + CTempl_FuncMatch(copied_list, templargs, argexprs, match, expr); + } +} + +ENode *CExpr_GetDefaultArgument(ENode *funcexpr, FuncArg *arg) { + ENode *tmp; + + if (CTemplTool_IsTemplateArgumentDependentExpression(arg->dexpr)) { + CError_ASSERT(3264, ENODE_IS(funcexpr, EOBJREF)); + tmp = CTemplTool_DeduceDefaultArg( + funcexpr->data.objref, + CInline_CopyExpression(arg->dexpr, CopyMode0) + ); + return argumentpromotion(tmp, arg->type, arg->qual, 1); + } + + return CInline_CopyExpression(arg->dexpr, CopyMode0); +} + +static ENode *CExpr_GenericCall(ENode *funcexpr, ENodeList *argexprs, TypeFunc *tfunc, FuncArg *args) { + ENodeList *list; + ENode *callexpr; + + while (args) { + if (args->dexpr) { + if (argexprs) { + list = argexprs; + while (list->next) + list = list->next; + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + } else { + list = argexprs = lalloc(sizeof(ENodeList)); + } + list->next = NULL; + list->node = CExpr_GetDefaultArgument(funcexpr, args); + } + args = args->next; + } + + callexpr = lalloc(sizeof(ENode)); + callexpr->type = EFUNCCALL; + callexpr->cost = 4; + callexpr->rtype = tfunc->functype; + callexpr->flags = tfunc->qual & ENODE_FLAG_QUALS; + callexpr->data.funccall.funcref = funcexpr; + callexpr->data.funccall.funcref->rtype = CDecl_NewPointerType(TYPE(tfunc)); + callexpr->data.funccall.args = argexprs; + callexpr->data.funccall.functype = tfunc; + funcexpr->data.objref->flags |= OBJECT_USED; + return CExpr_AdjustFunctionCall(callexpr); +} + +static Boolean CExpr_IsObjrefPlusX(ENode *expr) { + Type *type; + + if (ENODE_IS(expr, EOBJREF)) { + type = expr->data.objref->type; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + return IS_TYPE_CLASS(type); + } + + if (ENODE_IS2(expr, EADD, ESUB)) { + if (CExpr_IsObjrefPlusX(expr->data.diadic.left)) + return 1; + if (CExpr_IsObjrefPlusX(expr->data.diadic.right)) + return 1; + } + + return 0; +} + +static Boolean CExpr_IsStaticType(ENode *expr) { + return ENODE_IS(expr, EINDIRECT) && CExpr_IsObjrefPlusX(expr->data.monadic); +} + +ENode *CExpr_VarArgPromotion(ENode *expr, Boolean flag) { + if (!copts.old_argmatch) + expr = pointer_generation(expr); + + switch (expr->rtype->type) { + case TYPEVOID: + case TYPEFUNC: + CError_Error(CErrorStr353); + expr = nullnode(); + break; + case TYPEINT: + case TYPEENUM: + expr = integralpromote(expr); + break; + case TYPEFLOAT: + if (TYPE_INTEGRAL(expr->rtype)->integral < IT_DOUBLE) + expr = promote(expr, TYPE(&stdouble)); + break; + case TYPECLASS: + expr = classargument(expr); + break; + } + + if (!flag && copts.warn_largeargs) { + if ((IS_TYPE_INT(expr->rtype) && TYPE_INTEGRAL(expr->rtype)->integral >= IT_LONGLONG) || IS_TYPE_FLOAT(expr->rtype)) + CError_Warning(CErrorStr316); + } + + return expr; +} + +ENode *CExpr_GenericFuncCall(BClassList *path, ENode *funcexpr, Boolean flag1, Object *obj, NameSpaceObjectList *nsol, TemplArg *templargs, ENodeList *nodes, Boolean flag2, Boolean flag3, Boolean flag4) { + TypeFunc *tfunc; + AccessType access; + FuncArg *scan_arg; + BClassList *buildpath; + ENode *objexpr; + ENodeList *scan_expr; + BClassList *pathcopy; + Boolean had_alias; + NameSpaceObjectList my_list; + Match13 match; + + memclrw(&match, sizeof(Match13)); + + if (!obj || IS_TEMPL_FUNC(obj->type)) { + if (!funcexpr && cscope_currentfunc && cscope_currentclass && cscope_is_member_func) { + funcexpr = CClass_CreateThisSelfExpr(); + if (funcexpr) { + funcexpr = makemonadicnode(funcexpr, EINDIRECT); + funcexpr->rtype = TYPE(cscope_currentclass); + } + } + + if (obj) { + my_list.next = NULL; + my_list.object = OBJ_BASE(obj); + nsol = &my_list; + } + + CExpr_MatchArgList(nsol, templargs, nodes, &match, funcexpr, flag2); + if (!match.obj) { + CError_ErrorFuncCall(CErrorStr248, nsol, nodes); + return nullnode(); + } + if (match.list) + CError_OverloadedFunctionError(match.obj, match.list); + obj = match.obj; + } + + objexpr = create_objectrefnode(obj); + tfunc = TYPE_FUNC(obj->type); + if (!IS_TYPE_FUNC(tfunc)) { + CError_Error(CErrorStr161); + return nullnode(); + } + + if (IS_TYPEFUNC_METHOD(tfunc) && !TYPE_METHOD(tfunc)->is_static) { + had_alias = 0; + buildpath = NULL; + access = obj->access; + while (obj->datatype == DALIAS) { + buildpath = buildpath ? CClass_AppendPath(buildpath, CClass_GetPathCopy(obj->u.alias.member, 0)) : CClass_GetPathCopy(obj->u.alias.member, 0); + obj = obj->u.alias.object; + objexpr = create_objectrefnode(obj); + had_alias = 1; + } + if (flag3) + CError_Error(CErrorStr188); + + if (TYPE_METHOD(tfunc)->theclass->sominfo && (!(obj->qual & Q_INLINE) || (obj->datatype == DVFUNC && !flag1))) { + pathcopy = CClass_GetPathCopy(path, 0); + funcexpr = CExpr_GetClassAccessNode(path, buildpath, funcexpr, obj, access, flag4); + if (!funcexpr) + return nullnode(); + objexpr = CSOM_MethodAccess(pathcopy, obj, flag1); + } else { + if (obj->datatype == DVFUNC) { + if (flag1 || (!copts.always_vdispatch && !had_alias && funcexpr && CExpr_IsStaticType(funcexpr))) + objexpr->flags |= ENODE_FLAG_80; + } + funcexpr = CExpr_GetClassAccessNode(path, buildpath, funcexpr, obj, access, flag4); + if (!funcexpr) + return nullnode(); + } + + if ( + (tfunc->flags & FUNC_PURE) && + cscope_currentfunc && + (TYPE_FUNC(cscope_currentfunc->type)->flags & (FUNC_IS_CTOR | FUNC_IS_DTOR)) && + cscope_currentclass == TYPE_METHOD(tfunc)->theclass && + ENODE_IS(funcexpr, EINDIRECT) && + ENODE_IS(funcexpr->data.monadic, EINDIRECT) && + ENODE_IS(funcexpr->data.monadic->data.monadic, EOBJREF) && + funcexpr->data.monadic->data.monadic->data.objref->name == this_name_node && + !(objexpr->flags & ENODE_FLAG_80) + ) + CError_Warning(CErrorStr195); + + scan_expr = lalloc(sizeof(ENodeList)); + scan_expr->next = nodes; + scan_expr->node = funcexpr->data.monadic; + if (ENODE_IS(scan_expr->node, EOBJREF)) + scan_expr->node->data.objref->flags |= OBJECT_FLAGS_2; + + if (((funcexpr->flags & Q_CONST) && !(tfunc->args->qual & Q_CONST)) || ((funcexpr->flags & Q_VOLATILE) && !(tfunc->args->qual & Q_VOLATILE))) { + if (!(tfunc->flags & (FUNC_IS_CTOR | FUNC_IS_DTOR))) + CError_Error(CErrorStr236); + } + + nodes = scan_expr; + scan_expr = scan_expr->next; + scan_arg = tfunc->args->next; + } else { + if (flag4 && obj->access != ACCESSPROTECTED) + CClass_CheckObjectAccess(path, obj); + + scan_arg = tfunc->args; + scan_expr = nodes; + if (tfunc->flags & FUNC_METHOD) { + CError_ASSERT(3599, TYPE_METHOD(tfunc)->theclass->sominfo == NULL); + } + } + + while (scan_expr) { + if (scan_arg && scan_arg != &elipsis && scan_arg != &oldstyle) { + scan_expr->node = argumentpromotion(scan_expr->node, scan_arg->type, scan_arg->qual, 1); + scan_arg = scan_arg->next; + } else { + if (!scan_arg) { + my_list.next = NULL; + my_list.object = OBJ_BASE(obj); + CError_ErrorFuncCall(CErrorStr248, &my_list, nodes); + } + scan_expr->node = CExpr_VarArgPromotion(scan_expr->node, scan_arg == &elipsis); + } + scan_expr = scan_expr->next; + } + + if (scan_arg) { + if (scan_arg != &elipsis && scan_arg != &oldstyle) { + if (!scan_arg->dexpr) { + my_list.next = NULL; + my_list.object = OBJ_BASE(obj); + CError_ErrorFuncCall(CErrorStr248, &my_list, nodes); + scan_arg = NULL; + } + } else { + scan_arg = NULL; + } + } + + return CExpr_GenericCall(objexpr, nodes, tfunc, scan_arg); +} + +ENode *CExpr_GenericPtmfCall(Object *obj, TypeFunc *tfunc, ENodeList *arg_exprs) { + ENodeList *scan_expr; + FuncArg *arg; + + scan_expr = arg_exprs; + arg = tfunc->args; + while (scan_expr) { + if (!arg) { + CError_Error(CErrorStr162); + return nullnode(); + } + + if (arg != &elipsis && arg != &oldstyle) { + scan_expr->node = argumentpromotion(scan_expr->node, arg->type, arg->qual, 1); + arg = arg->next; + } else { + scan_expr->node = CExpr_VarArgPromotion(scan_expr->node, arg == &elipsis); + } + scan_expr = scan_expr->next; + } + + if (arg) { + if (arg != &elipsis && arg != &oldstyle) { + if (!arg->dexpr) { + CError_Error(CErrorStr162); + arg = NULL; + } + } else { + arg = NULL; + } + } + + return CExpr_GenericCall(create_objectrefnode(obj), arg_exprs, tfunc, arg); +} + +static ENode *CExpr_ConvertEMember(ENode *expr) { + ENode *result; + + if (expr->data.emember->list->next || expr->data.emember->templargs) { + result = CExpr_NewENode(EOBJLIST); + result->rtype = OBJECT(expr->data.emember->list->object)->type; + result->data.objlist.list = expr->data.emember->list; + result->data.objlist.templargs = expr->data.emember->templargs; + return result; + } + + if (expr->data.emember->list->object->otype != OT_OBJECT) + return NULL; + return CExpr_MakeObjRefNode(OBJECT(expr->data.emember->list->object), 1); +} + +ENode *CExpr_MakeFunctionCall(ENode *funcexpr, ENodeList *arg_exprs) { + ENode *expr; + TypeFunc *tfunc; + BClassList *save_path; + ENode *save_expr; + Boolean save_1D; + Boolean save_isambig; + + FuncArg *scan_arg; + ENodeList *scan_expr; + Boolean has_varargs; + + if (ENODE_IS(funcexpr, EOBJLIST) && funcexpr->data.objlist.name) { + funcexpr->data.objlist.list = CScope_ArgumentDependentNameLookup( + funcexpr->data.objlist.list, + funcexpr->data.objlist.name, + arg_exprs, 0); + if (!funcexpr->data.objlist.list) { + CError_Error(CErrorStr140, CError_GetNameString(NULL, funcexpr->data.objlist.name)); + return nullnode(); + } + + if ( + funcexpr->data.objlist.list->object->otype == OT_OBJECT && + (TYPE_FUNC(OBJECT(funcexpr->data.objlist.list->object)->type)->flags & FUNC_INTRINSIC) && + (expr = CodeGen_HandleIntrinsicCall(OBJECT(funcexpr->data.objlist.list->object), arg_exprs))) + return expr; + + return CExpr_GenericFuncCall( + NULL, NULL, 0, NULL, + funcexpr->data.objlist.list, + funcexpr->data.objlist.templargs, + arg_exprs, 0, 0, 1); + } + + if (ENODE_IS(funcexpr, EMEMBER)) { + save_path = funcexpr->data.emember->path; + save_expr = funcexpr->data.emember->expr; + save_1D = funcexpr->data.emember->pr_1D; + save_isambig = funcexpr->data.emember->isambig; + funcexpr = CExpr_ConvertEMember(funcexpr); + if (!funcexpr) { + CError_Error(CErrorStr161); + return nullnode(); + } + } else { + save_path = NULL; + save_expr = NULL; + save_1D = 0; + save_isambig = 0; + } + + if (ENODE_IS(funcexpr, EOBJREF) && IS_TYPE_FUNC(funcexpr->data.objref->type) && (TYPE_FUNC(funcexpr->data.objref->type)->flags & FUNC_INTRINSIC)) { + if (!(expr = CodeGen_HandleIntrinsicCall(funcexpr->data.objref, arg_exprs))) { + expr = CExpr_GenericFuncCall( + save_path, save_expr, save_1D, funcexpr->data.objref, + NULL, NULL, + arg_exprs, 0, save_isambig, 1); + } + return expr; + } + + if (ENODE_IS(funcexpr, EOBJLIST)) { + return CExpr_GenericFuncCall( + save_path, save_expr, save_1D, NULL, + funcexpr->data.objlist.list, funcexpr->data.objlist.templargs, + arg_exprs, 0, save_isambig, 1); + } + + if (!IS_TYPE_POINTER_ONLY(funcexpr->rtype) || !IS_TYPE_FUNC((tfunc = TYPE_FUNC(TYPE_POINTER(funcexpr->rtype)->target)))) { + CError_Error(CErrorStr161); + return nullnode(); + } + + if (ENODE_IS(funcexpr, EOBJREF)) { + return CExpr_GenericFuncCall( + save_path, save_expr, save_1D, funcexpr->data.objref, + NULL, NULL, arg_exprs, 0, save_isambig, 1); + } + + scan_expr = arg_exprs; // r25 + scan_arg = tfunc->args; // r26 + has_varargs = 0; + while (scan_expr) { + if (!has_varargs) { + if (!scan_arg) { + CError_Error(CErrorStr162); + return nullnode(); + } + if (scan_arg == &elipsis || scan_arg == &oldstyle) { + scan_expr->node = CExpr_VarArgPromotion(scan_expr->node, scan_arg == &elipsis); + has_varargs = 1; + } else { + scan_expr->node = argumentpromotion(scan_expr->node, scan_arg->type, scan_arg->qual, 1); + scan_arg = scan_arg->next; + } + } else { + scan_expr->node = CExpr_VarArgPromotion(scan_expr->node, 0); + } + scan_expr = scan_expr->next; + } + + if (!has_varargs && scan_arg && scan_arg != &elipsis && scan_arg != &oldstyle) { + do { + if (!scan_arg->dexpr) { + CError_Error(CErrorStr162); + return nullnode(); + } + + if (arg_exprs) { + scan_expr = arg_exprs; + while (scan_expr->next) + scan_expr = scan_expr->next; + scan_expr->next = lalloc(sizeof(ENodeList)); + scan_expr = scan_expr->next; + } else { + scan_expr = lalloc(sizeof(ENodeList)); + arg_exprs = scan_expr; + } + + scan_expr->next = NULL; + scan_expr->node = CExpr_GetDefaultArgument(funcexpr, scan_arg); + } while ((scan_arg = scan_arg->next) && scan_arg != &elipsis && scan_arg != &oldstyle); + } + + expr = CExpr_NewENode(EFUNCCALL); + expr->cost = 4; + expr->rtype = tfunc->functype; + expr->flags = tfunc->qual & ENODE_FLAG_QUALS; + expr->data.funccall.funcref = funcexpr; + expr->data.funccall.args = arg_exprs; + expr->data.funccall.functype = tfunc; + return CExpr_AdjustFunctionCall(expr); +} + +static Boolean accept_conversion_type(Type *type, short mode) { + switch (mode) { + case 0: + return IS_TYPE_INT(type); + case 1: + return IS_TYPE_INT_OR_FLOAT(type); + case 2: + return IS_TYPE_INT_OR_FLOAT(type) || IS_TYPE_POINTER_ONLY(type); + case 3: + return IS_TYPE_POINTER_ONLY(type); + default: + CError_FATAL(3912); + return 0; + } +} + +static ENode *CExpr_OperatorConversion(ENode *expr, Type *type, UInt32 qual) { + if (IS_TYPE_CLASS(expr->rtype) && type) { + if (user_assign_check(expr, type, qual, 1, 0, 1)) + return assign_node; + CError_Error(CErrorStr144); + } + return expr; +} + +static Boolean wild_conversion_check(ENode *left, ENode *right, Conversion *conv) { + ConversionIterator iter; + Object *obj; + + Type *check; + Type *left_type; + Type *right_type; + + left_type = right_type = NULL; + if (IS_TYPE_CLASS(left->rtype)) { + CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(left->rtype)); + while ((obj = CExpr_ConversionIteratorNext(&iter))) { + check = TYPE_FUNC(obj->type)->functype; + if (accept_conversion_type(check, 2)) { + while ((obj = CExpr_ConversionIteratorNext(&iter))) { + if (accept_conversion_type(TYPE_FUNC(obj->type)->functype, 2)) + CError_Error(CErrorStr199); + } + left_type = check; + goto found_left; + } + } + return 0; + } +found_left: + if (IS_TYPE_CLASS(right->rtype)) { + CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(right->rtype)); + while ((obj = CExpr_ConversionIteratorNext(&iter))) { + check = TYPE_FUNC(obj->type)->functype; + if (accept_conversion_type(check, 2)) { + while ((obj = CExpr_ConversionIteratorNext(&iter))) { + if (accept_conversion_type(TYPE_FUNC(obj->type)->functype, 2)) + CError_Error(CErrorStr199); + } + right_type = check; + goto found_right; + } + } + return 0; + } +found_right: + conv->x0 = NULL; + conv->left = CExpr_OperatorConversion(left, left_type, 0); + conv->right = CExpr_OperatorConversion(right, right_type, 0); + return 1; +} + +static Boolean monadic_conversion_check(ENode *expr, short which, Conversion *conv) { + ConversionIterator iter; + Object *obj; + Type *check; + + if (!IS_TYPE_CLASS(expr->rtype)) + return 0; + + if (which == 4) + which = 2; + else if (which == 5) + which = 1; + + CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(expr->rtype)); + while ((obj = CExpr_ConversionIteratorNext(&iter))) { + check = TYPE_FUNC(obj->type)->functype; + if (accept_conversion_type(check, which)) { + while ((obj = CExpr_ConversionIteratorNext(&iter))) { + if (accept_conversion_type(TYPE_FUNC(obj->type)->functype, which)) + CError_Error(CErrorStr199); + } + + conv->x0 = NULL; + conv->left = CExpr_OperatorConversion(expr, check, 0); + conv->right = NULL; + return 1; + } + } + + return 0; +} + +static Boolean is_legal_type_combination(Type *left, Type *right, short mode) { + int left_type; + int right_type; + + if (IS_TYPE_ENUM(left)) + left = TYPE_ENUM(left)->enumtype; + if (IS_TYPE_ENUM(right)) + right = TYPE_ENUM(right)->enumtype; + + if (IS_TYPE_REFERENCE(left)) + left = TYPE_POINTER(left)->target; + if (IS_TYPE_REFERENCE(right)) + right = TYPE_POINTER(right)->target; + + left_type = left->type; // r7 + right_type = right->type; // r8 + switch (mode) { + case 3: + if (left_type != TYPEPOINTER || right_type != TYPEPOINTER) + return 0; + use_cpp_typeequal: + diadic_arg1.type = left; + diadic_arg2.type = right; + return iscpp_typeequal(left, right); + case 7: + if ((left_type == TYPEPOINTER && right_type == TYPEINT) || (left_type == TYPEINT && right_type == TYPEPOINTER)) { + diadic_arg1.type = left; + diadic_arg2.type = right; + return 1; + } + return 0; + case 6: + if ((left_type == TYPEPOINTER && right_type == TYPEINT) || (left_type == TYPEINT && right_type == TYPEPOINTER)) { + diadic_arg1.type = left; + diadic_arg2.type = right; + return 1; + } + case 2: + if (left_type == TYPEPOINTER || right_type == TYPEPOINTER) + goto use_cpp_typeequal; + case 1: + mode1: + if (left_type == TYPEFLOAT || right_type == TYPEFLOAT) { + if (left_type == TYPEFLOAT) { + if (right_type == TYPEFLOAT) { + if (TYPE_INTEGRAL(right)->integral > TYPE_INTEGRAL(left)->integral) + left = right; + diadic_arg2.type = left; + diadic_arg1.type = left; + return 1; + } + if (right_type != TYPEINT) + return 0; + diadic_arg2.type = left; + diadic_arg1.type = left; + return 1; + } + if (left_type != TYPEINT) + return 0; + diadic_arg2.type = right; + diadic_arg1.type = right; + return 1; + } + case 0: + if (left_type != TYPEINT || right_type != TYPEINT) + return 0; + if (TYPE_INTEGRAL(right)->integral > TYPE_INTEGRAL(left)->integral) + left = right; + if (TYPE_INTEGRAL(left)->integral < IT_INT) + left = TYPE(&stsignedint); + diadic_arg2.type = left; + diadic_arg1.type = left; + return 1; + case 4: + if (left_type == TYPEPOINTER) { + if (right_type != TYPEINT) + return 0; + diadic_arg1.type = left; + diadic_arg2.type = right; + return 1; + } + if (right_type == TYPEPOINTER) { + if (left_type != TYPEINT) + return 0; + diadic_arg1.type = left; + diadic_arg2.type = right; + return 1; + } + goto mode1; + case 5: + if (left_type != TYPEPOINTER) + goto mode1; + if (right_type == TYPEPOINTER) + goto use_cpp_typeequal; + if (right_type != TYPEINT) + return 0; + diadic_arg1.type = left; + diadic_arg2.type = right; + return 1; + default: + CError_FATAL(4132); + return 0; + } +} + +static void match_class_type_conversion(Match13 *match, ENode *left, ENode *right, ENodeList *list, short which) { + ConversionIterator iter; + Object *obj; + + if (which == 6) { + if (!ENODE_IS(right, EINTCONST) || !CInt64_IsZero(&right->data.intval) || !IS_TYPE_INT(right->rtype)) + which = 2; + } + + CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(left->rtype)); + while ((obj = CExpr_ConversionIteratorNext(&iter))) { + if (is_legal_type_combination(TYPE_FUNC(obj->type)->functype, right->rtype, which)) { + MatchOverloadFunc(obj, &diadic_arg1, list, match); + if (match->obj == obj) { + cexpr_left_conversion_type = diadic_arg1.type; + cexpr_right_conversion_type = diadic_arg2.type; + } + } + } +} + +static void match_type_class_conversion(Match13 *match, ENode *left, ENode *right, ENodeList *list, short which) { + ConversionIterator iter; + Object *obj; + + if (which == 6) { + if (!ENODE_IS(left, EINTCONST) || !CInt64_IsZero(&left->data.intval) || !IS_TYPE_INT(left->rtype)) + which = 2; + } + + CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(right->rtype)); + while ((obj = CExpr_ConversionIteratorNext(&iter))) { + if (is_legal_type_combination(left->rtype, TYPE_FUNC(obj->type)->functype, which)) { + MatchOverloadFunc(obj, &diadic_arg1, list, match); + if (match->obj == obj) { + cexpr_left_conversion_type = diadic_arg1.type; + cexpr_right_conversion_type = diadic_arg2.type; + } + } + } +} + +static void match_class_class_conversion(Match13 *match, ENode *left, ENode *right, ENodeList *list, short which) { + ConversionIterator iter_left; + ConversionIterator iter_right; + Object *obj_left; + Object *obj_right; + + if (which == 6) + which = 2; + + CExpr_ConversionIteratorInit(&iter_left, TYPE_CLASS(left->rtype)); + while ((obj_left = CExpr_ConversionIteratorNext(&iter_left))) { + CExpr_ConversionIteratorInit(&iter_right, TYPE_CLASS(right->rtype)); + while ((obj_right = CExpr_ConversionIteratorNext(&iter_right))) { + if (is_legal_type_combination(TYPE_FUNC(obj_left->type)->functype, TYPE_FUNC(obj_right->type)->functype, which)) { + MatchOverloadFunc(obj_left, &diadic_arg1, list, match); + if (match->obj == obj_left) { + cexpr_left_conversion_type = diadic_arg1.type; + cexpr_right_conversion_type = diadic_arg2.type; + } + } + } + } +} + +Boolean CExpr_CheckOperatorConversion(short token, ENode *left, ENode *right, ENodeList *list, Conversion *conv) { + Match13 match; + short which; + + switch (token) { + case '*': + if (!right) { + which = 3; + break; + } + case '/': + which = 1; + break; + case '&': + if (!right) + return 0; + case '%': + case '^': + case '|': + case '~': + case TK_SHL: + case TK_SHR: + which = 0; + break; + case '[': + which = 7; + break; + case '+': + which = 4; + break; + case '-': + which = 5; + break; + case '!': + case ':': + case '<': + case '>': + case TK_LESS_EQUAL: + case TK_GREATER_EQUAL: + which = 2; + break; + case TK_LOGICAL_EQ: + case TK_LOGICAL_NE: + which = 6; + break; + case TK_LOGICAL_OR: + case TK_LOGICAL_AND: + return wild_conversion_check(left, right, conv); + default: + return 0; + } + + if (!right) + return monadic_conversion_check(left, which, conv); + + cexpr_left_conversion_type = cexpr_right_conversion_type = NULL; + memclrw(&match, sizeof(Match13)); + + if (IS_TYPE_CLASS(left->rtype)) { + if (IS_TYPE_CLASS(right->rtype)) + match_class_class_conversion(&match, left, right, list, which); + else + match_class_type_conversion(&match, left, right, list, which); + } else { + if (IS_TYPE_CLASS(right->rtype)) + match_type_class_conversion(&match, left, right, list, which); + else + return 0; + } + + if (!match.obj) + return 0; + if (match.list) + CError_OverloadedFunctionError(match.obj, match.list); + + conv->x0 = NULL; + conv->left = CExpr_OperatorConversion(left, cexpr_left_conversion_type, 0); + conv->right = CExpr_OperatorConversion(right, cexpr_right_conversion_type, 0); + return 1; +} + +Boolean CExpr_CheckOperator(short token, ENode *left, ENode *right, Conversion *conv) { + Match13 match; + NameResult pr; + NameResult pr2; + ENode *expr; + Object *obj; + ENodeList *nodes; + HashNameNode *name; + BClassList *path; + EMemberInfo *member; + Object *prev_obj; + NameSpaceObjectList mylist_A8; + NameSpaceObjectList mylist_B0; + + if (!copts.old_argmatch) { + if (token == '(') { + CDecl_CompleteType(left->rtype); + if (IS_TYPE_CLASS(left->rtype) && CScope_FindClassMemberObject(TYPE_CLASS(left->rtype), &pr, + CMangler_OperatorName(token))) { + if (pr.nsol_14 || (pr.obj_10 && pr.obj_10->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(pr.obj_10)->type))) { + member = lalloc(sizeof(EMemberInfo)); + memclrw(member, sizeof(EMemberInfo)); + member->path = pr.bcl_18; + member->expr = left; + member->pr_1D = pr.x1D; + if (!pr.nsol_14) { + member->list = galloc(sizeof(NameSpaceObjectList)); + member->list->next = NULL; + member->list->object = pr.obj_10; + } else { + member->list = pr.nsol_14; + } + expr = CExpr_NewENode(EMEMBER); + expr->rtype = &stvoid; + expr->data.emember = member; + tk = lex(); + conv->x0 = checkreference(CExpr_MakeFunctionCall(expr, CExpr_ScanExpressionList(1))); + conv->left = NULL; + conv->right = NULL; + tk = lex(); + return 1; + } else { + CError_FATAL(4371); + } + } + return 0; + } else { + return CExpr_OperatorMatch(token, left, right, conv); + } + } + + if (!IS_TYPE_CLASS(left->rtype)) { + if (!IS_TYPE_ENUM(left->rtype)) { + if (!right) + return 0; + if (!IS_TYPE_CLASS(right->rtype) && !IS_TYPE_ENUM(right->rtype)) + return 0; + } + } else { + CDecl_CompleteType(left->rtype); + } + + memclrw(&match, sizeof(Match13)); + name = CMangler_OperatorName(token); + if (token == '(') { + if (IS_TYPE_CLASS(left->rtype) && CScope_FindClassMemberObject(TYPE_CLASS(left->rtype), &pr2, name)) { + if (pr2.nsol_14 || (pr2.obj_10 && pr2.obj_10->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(pr2.obj_10)->type))) { + member = lalloc(sizeof(EMemberInfo)); + memclrw(member, sizeof(EMemberInfo)); + member->path = pr2.bcl_18; + member->expr = left; + member->pr_1D = pr2.x1D; + if (!pr2.nsol_14) { + member->list = galloc(sizeof(NameSpaceObjectList)); + member->list->next = NULL; + member->list->object = pr2.obj_10; + } else { + member->list = pr2.nsol_14; + } + expr = CExpr_NewENode(EMEMBER); + expr->rtype = &stvoid; + expr->data.emember = member; + tk = lex(); + conv->x0 = checkreference(CExpr_MakeFunctionCall(expr, CExpr_ScanExpressionList(1))); + conv->left = NULL; + conv->right = NULL; + tk = lex(); + return 1; + } else { + CError_FATAL(4439); + } + } + return 0; + } + + nodes = lalloc(sizeof(ENodeList)); + nodes->node = left; + if (right) { + nodes->next = lalloc(sizeof(ENodeList)); + nodes->next->node = right; + nodes->next->next = NULL; + } else { + nodes->next = NULL; + } + + obj = NULL; + if (IS_TYPE_CLASS(left->rtype) && CScope_FindClassMemberObject(TYPE_CLASS(left->rtype), &pr2, name)) { + if (pr2.obj_10) { + mylist_B0.next = NULL; + mylist_B0.object = pr2.obj_10; + pr2.nsol_14 = &mylist_B0; + } else { + CError_ASSERT(4470, pr2.nsol_14); + } + + if (token != '=' || (pr2.bcl_18->type == left->rtype && pr2.bcl_18->next == NULL)) { + prev_obj = match.obj; + CExpr_MatchArgList(pr2.nsol_14, NULL, nodes->next, &match, left, 0); + if (prev_obj != match.obj) { + obj = match.obj; + path = pr2.bcl_18; + } + } + } + + if (CScope_FindNonClassObject(cscope_current, &pr2, name)) { + if (pr2.obj_10) { + mylist_A8.next = NULL; + mylist_A8.object = pr2.obj_10; + pr2.nsol_14 = &mylist_A8; + } + } else { + pr2.nsol_14 = NULL; + } + + if (copts.arg_dep_lookup) + pr2.nsol_14 = CScope_ArgumentDependentNameLookup(pr2.nsol_14, name, nodes, 1); + if (pr2.nsol_14) + CExpr_MatchArgList(pr2.nsol_14, NULL, nodes, &match, NULL, 0); + + if (!match.obj) { + if (!IS_TYPE_CLASS(left->rtype) && (!right || !IS_TYPE_CLASS(right->rtype))) + return 0; + return CExpr_CheckOperatorConversion(token, left, right, nodes, conv); + } + + if (!(token == '&' && !right) && (token != ',')) { + if (!IS_TYPE_CLASS(left->rtype) && (!right || !IS_TYPE_CLASS(right->rtype)) && match.xE) + return 0; + if (right && match.xE == 2 && CExpr_CheckOperatorConversion(token, left, right, nodes, conv)) + return 1; + } + + if (match.list) + CError_OverloadedFunctionError(match.obj, match.list); + + if (match.obj == obj) { + conv->x0 = CExpr_GenericFuncCall(path, nodes->node, 0, match.obj, NULL, NULL, nodes->next, 0, 0, 1); + } else { + conv->x0 = CExpr_GenericFuncCall(NULL, NULL, 0, match.obj, NULL, NULL, nodes, 0, 0, 1); + } + + conv->x0 = checkreference(conv->x0); + conv->left = NULL; + conv->right = NULL; + return 1; +} + +ENode *CExpr_ConstructObject(TypeClass *tclass, ENode *addr_expr, ENodeList *args, Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4, Boolean flag5) { + ENode *expr; + NameSpaceObjectList *ctorlist; + BClassList path; + + CError_ASSERT(4595, IS_TYPE_POINTER_ONLY(addr_expr->rtype)); + + addr_expr = makemonadicnode(addr_expr, EINDIRECT); + addr_expr->rtype = TYPE(tclass); + + if (!flag3 && args && !args->next && args->node->rtype == TYPE(tclass) && !CClass_CopyConstructor(tclass)) { + CError_ASSERT(4605, IS_TYPE_CLASS(addr_expr->rtype)); + expr = makediadicnode(addr_expr, args->node, EASS); + if (!flag1) + expr = getnodeaddress(expr, 0); + return expr; + } + + if ((ctorlist = CClass_Constructor(tclass))) { + if (tclass->flags & CLASS_HAS_VBASES) { + ENodeList *list = lalloc(sizeof(ENodeList)); + list->next = args; + args = list; + list->node = intconstnode(TYPE(&stsignedshort), flag2 != 0); + } + path.next = NULL; + path.type = TYPE(tclass); + expr = CExpr_GenericFuncCall(&path, addr_expr, 0, NULL, ctorlist, NULL, args, !flag5, 0, flag4); + if (ENODE_IS2(expr, EFUNCCALL, EFUNCCALLP)) + expr->rtype = CDecl_NewPointerType(TYPE(tclass)); + if (flag1) { + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = TYPE(tclass); + } + return expr; + } else { + if (args) { + if (!args->next && ENODE_IS(addr_expr, EINDIRECT)) { + return makediadicnode( + addr_expr, + CExpr_AssignmentPromotion(args->node, TYPE(tclass), 0, 1), + EASS); + } + CError_Error(CErrorStr174); + } + return addr_expr; + } +} + +static ENode *CExpr_DeleteFuncCall(Object *obj, ENode *arg, Type *type, Boolean include_size) { + ENode *expr; + ENodeList *list; + + expr = lalloc(sizeof(ENode)); + expr->type = EFUNCCALL; + expr->cost = 4; + expr->flags = 0; + expr->rtype = &stvoid; + expr->data.funccall.funcref = create_objectrefnode(obj); + expr->data.funccall.functype = TYPE_FUNC(obj->type); + obj->flags |= OBJECT_USED; + + list = lalloc(sizeof(ENodeList)); + list->node = arg; + expr->data.funccall.args = list; + + if (include_size) { + list->next = lalloc(sizeof(ENodeList)); + list->next->node = nullnode(); + CInt64_SetLong(&list->next->node->data.intval, type->size); + list->next->node->rtype = CABI_GetSizeTType(); + list->next->next = NULL; + } else { + list->next = NULL; + } + + return expr; +} + +static ENode *CExpr_CopyPlacementNewArg(ENodeList *list) { + switch (list->node->type) { + case EINDIRECT: + if (!ENODE_IS(list->node->data.monadic, EOBJREF)) + break; + if (list->node->data.monadic->data.objref->datatype != DLOCAL && !is_const_object(list->node->data.monadic->data.objref)) + break; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EARGOBJ: + case ELOCOBJ: + case EOBJLIST: + case EVECTOR128CONST: + return CInline_CopyExpression(list->node, CopyMode0); + } + + switch (list->node->rtype->type) { + default: + CError_FATAL(4726); + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPESTRUCT: + case TYPECLASS: + case TYPEMEMBERPOINTER: + case TYPEPOINTER: + case TYPEOBJCID: + return CExpr_GetETEMPCopy(list->node); + } +} + +static ENode *CExpr_PlacementDeleteCall(Type *type, ENode *expr, Object *obj, Boolean flag1, Boolean flag2) { + ENodeList *list; + Object *funcobj; + ENode *result; + ENodeList *inputarg; + Boolean outflag; + + CError_ASSERT(4752, ENODE_IS(expr, EFUNCCALL) && ENODE_IS(expr->data.funccall.funcref, EOBJREF)); + + funcobj = expr->data.funccall.funcref->data.objref; + CError_ASSERT(4756, IS_TYPE_FUNC(funcobj->type) && TYPE_FUNC(funcobj->type)->args && TYPE_FUNC(funcobj->type)->args->next); + + funcobj = CParser_FindDeallocationObject(type, TYPE_FUNC(funcobj->type)->args->next, flag1, flag2, &outflag); + if (!funcobj) + return NULL; + + result = CExpr_NewENode(EFUNCCALL); + result->type = EFUNCCALL; + result->cost = 4; + result->rtype = &stvoid; + result->data.funccall.funcref = create_objectrefnode(funcobj); + result->data.funccall.functype = TYPE_FUNC(funcobj->type); + funcobj->flags |= OBJECT_USED; + + list = lalloc(sizeof(ENodeList)); + list->node = create_objectnode(obj); + result->data.funccall.args = list; + + CError_ASSERT(4780, (inputarg = expr->data.funccall.args) && (inputarg = inputarg->next)); + + do { + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = CExpr_CopyPlacementNewArg(inputarg); + inputarg = inputarg->next; + } while (inputarg); + list->next = NULL; + + return result; +} + +static Type *scan_type_name(UInt32 *qual) { + DeclInfo di; + memclrw(&di, sizeof(DeclInfo)); + + CParser_GetDeclSpecs(&di, 0); + di.x46 = 1; + scandeclarator(&di); + + if (di.name) + CError_Error(CErrorStr146); + + firstarrayexpr = di.x24; + *qual = di.qual; + return di.thetype; +} + +static UInt32 cv_qualifier_list(void) { + UInt32 qual; + + qual = 0; + tk = lex(); + while (tk >= TK_CONST && tk <= TK_ASM) { + switch (tk) { + case TK_CONST: + if (qual & Q_CONST) + CError_Error(CErrorStr121); + qual |= Q_CONST; + break; + case TK_VOLATILE: + if (qual & Q_VOLATILE) + CError_Error(CErrorStr121); + qual |= Q_VOLATILE; + break; + default: + CError_Error(CErrorStr121); + } + + tk = lex(); + } + + return qual; +} + +static void scan_new_declarator(DeclInfo *di, Boolean flag) { + NameResult pr; + SInt32 size; + ENode *expr; + + switch (tk) { + case '*': + makethetypepointer(di, cv_qualifier_list()); + if (tk != '[') + scan_new_declarator(di, flag); + break; + case TK_IDENTIFIER: + case TK_COLON_COLON: + if (CScope_ParseQualifiedNameSpace(&pr, 1, 0) && pr.nspace_0 && pr.nspace_0->theclass && tk == '*') { + makememberpointertype(di, pr.nspace_0->theclass, cv_qualifier_list()); + if (tk != '[') + scan_new_declarator(di, flag); + } else { + CError_Error(CErrorStr121); + } + break; + } + + if (tk == '[') { + tk = lex(); + expr = expression(); + + if (IS_TYPE_ENUM(expr->rtype)) + expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; + if (!IS_TYPE_INT(expr->rtype)) + CError_Error(CErrorStr146); + + if (tk != ']') + CError_Error(CErrorStr125); + else + tk = lex(); + + if (tk == '[') + scan_new_declarator(di, 0); + + if (CanCreateObject(di->thetype) && IsCompleteType(di->thetype)) { + di->thetype = CDecl_NewArrayType(di->thetype, 0); + if (!ENODE_IS(expr, EINTCONST)) { + size = 1; + if (!flag) + CError_Error(CErrorStr124); + else + firstarrayexpr = expr; + } else { + size = CInt64_GetULong(&expr->data.intval); + } + TYPE_POINTER(di->thetype)->size = size * TYPE_POINTER(di->thetype)->target->size; + } else { + CError_Error(CErrorStr129); + } + } +} + +static Type *scan_new_type_name(UInt32 *qual) { + DeclInfo di; + memclrw(&di, sizeof(DeclInfo)); + + di.x4F = 1; + CParser_GetDeclSpecs(&di, 0); + scan_new_declarator(&di, 1); + + *qual = di.qual; + return di.thetype; +} + +static ENode *CExpr_NewAlloc(Type *type, ENodeList *args, Boolean flag1, Boolean flag2) { + NameSpaceObjectList *list; + Object *obj; + Boolean found; + HashNameNode *name; + NameResult pr; + + found = 0; + if (!flag1 && IS_TYPE_CLASS(type)) { + list = NULL; + obj = NULL; + name = (flag2 && copts.array_new_delete) ? newa_fobj->name : newp_fobj->name; + if (CScope_FindClassMemberObject(TYPE_CLASS(type), &pr, name)) { + list = pr.nsol_14; + obj = OBJECT(pr.obj_10); + CError_ASSERT(4935, list || obj); + found = 1; + } else if (TYPE_CLASS(type)->flags & CLASS_HANDLEOBJECT) { + CError_ASSERT(4942, !flag2); + obj = newh_func; + found = 1; + } + } + + if (!found) { + if (flag2 && copts.array_new_delete) + list = &newa_fobj->first; + else + list = &newp_fobj->first; + obj = NULL; + } + + return CExpr_GenericFuncCall(NULL, NULL, 0, obj, list, NULL, args, 0, 0, 1); +} + +static ENode *CExpr_NewExceptionSafeAlloc(Type *type, ENode *node, ENodeList *args, Boolean flag1, Boolean flag2, Object **objptr) { + Object *obj; + ENode *result; + ENode *catchexpr; + Object *deletefunc; + Boolean include_size; + + if (!cscope_currentfunc || !copts.delete_exception || !copts.exceptions) + return NULL; + + obj = create_temp_object(TYPE(&void_ptr)); + *objptr = obj; + deletefunc = NULL; + catchexpr = NULL; + include_size = 0; + if (args) + catchexpr = CExpr_PlacementDeleteCall(type, node, obj, flag1, flag2); + if (!args) + deletefunc = CParser_FindDeallocationObject(type, NULL, flag1, flag2, &include_size); + + if (!deletefunc && !catchexpr) + return NULL; + + result = lalloc(sizeof(ENode)); + *result = *node; + node = makediadicnode(create_objectnode(obj), node, EASS); + if (!catchexpr && !include_size) { + result->type = ENEWEXCEPTION; + result->data.newexception.initexpr = node; + result->data.newexception.tryexpr = NULL; + result->data.newexception.pointertemp = obj; + result->data.newexception.deletefunc = deletefunc; + } else { + if (!catchexpr) + catchexpr = CExpr_DeleteFuncCall(deletefunc, create_objectnode(obj), type, include_size); + result->type = EINITTRYCATCH; + result->data.itc.initexpr = node; + result->data.itc.tryexpr = NULL; + result->data.itc.result = create_objectnode(obj); + result->data.itc.catchexpr = catchexpr; + } + + return result; +} + +static ENode *CExpr_NewExceptionSafeInit(ENode *expr, ENode *tryexpr) { + switch (expr->type) { + case ENEWEXCEPTION: + expr->data.newexception.tryexpr = tryexpr; + break; + case EINITTRYCATCH: + expr->data.itc.tryexpr = tryexpr; + break; + default: + CError_FATAL(5056); + } + return expr; +} + +static ENode *CExpr_NewArray(Type *type, UInt32 qual, ENodeList *nodelist, Boolean flag) { + Type *tptr; + Type *sizetype; + Type *innertype; + ENodeList *newlist; + ENode *result; + Object *ctor; + Object *dtor; + ENode *ass; + ENode *etemp; + ENode *mul; + SInt32 count; + ENode *newalloc; + ENode *newESalloc; + Object *tempobj; + ENode *callexpr; + + tptr = CDecl_NewPointerType(TYPE_POINTER(type)->target); + sizetype = CABI_GetSizeTType(); + innertype = TYPE_POINTER(type)->target; + while (IS_TYPE_ARRAY(innertype)) + innertype = TYPE_POINTER(innertype)->target; + + if (!CanAllocObject(innertype) || !IsCompleteType(innertype)) + return nullnode(); + + newlist = lalloc(sizeof(ENodeList)); + newlist->next = nodelist; + if (tk == '(') { + tk = lex(); + if (CExpr_ScanExpressionList(1)) + CError_Error(CErrorStr174); + if (tk == ')') + tk = lex(); + else + CError_Error(CErrorStr115); + } + + if (!IS_TYPE_CLASS(innertype) || CClass_IsPODClass(TYPE_CLASS(innertype))) { + newlist->node = intconstnode(sizetype, type->size); + if (firstarrayexpr) { + newlist->node = makediadicnode(newlist->node, promote(firstarrayexpr, sizetype), EMUL); + optimizecomm(newlist->node); + } + result = CExpr_NewAlloc(innertype, newlist, flag, 1); + result->rtype = tptr; + result->flags |= (qual & ENODE_FLAG_QUALS); + return result; + } + + ctor = NULL; + if (CClass_Constructor(TYPE_CLASS(innertype))) { + ctor = CClass_DefaultConstructor(TYPE_CLASS(innertype)); + if (ctor) { + ctor->flags |= OBJECT_USED; + } else { + ctor = CClass_DummyDefaultConstructor(TYPE_CLASS(innertype)); + if (!ctor) + CError_Error(CErrorStr203); + } + } + + dtor = CClass_Destructor(TYPE_CLASS(innertype)); + if (dtor) + dtor = CABI_GetDestructorObject(dtor, CABIDestroy1); + + ass = NULL; + if (firstarrayexpr) { + etemp = CExpr_NewETEMPNode(sizetype, 1); + mul = promote(firstarrayexpr, sizetype); + if (innertype->size) + count = type->size / innertype->size; + else + count = 0; + if (count > 1) { + mul = makediadicnode(mul, intconstnode(sizetype, count), EMUL); + optimizecomm(mul); + } + ass = makediadicnode(CExpr_DerefETEMPCopy(etemp), mul, EASS); + mul = makediadicnode(CExpr_DerefETEMPCopy(etemp), intconstnode(sizetype, innertype->size), EMUL); + optimizecomm(mul); + mul = makediadicnode(mul, intconstnode(sizetype, 16), EADD); + optimizecomm(mul); + newlist->node = mul; + etemp = CExpr_DerefETEMPCopy(etemp); + } else { + newlist->node = intconstnode(sizetype, type->size + 16); + if (innertype->size) + count = type->size / innertype->size; + else + count = 0; + etemp = intconstnode(sizetype, count); + } + + newalloc = CExpr_NewAlloc(innertype, newlist, flag, 1); + newalloc->rtype = tptr; + newESalloc = CExpr_NewExceptionSafeAlloc(innertype, newalloc, nodelist, 1, flag, &tempobj); + if (newESalloc) { + callexpr = CExpr_FuncCallSix( + cnar_func, + create_objectnode(tempobj), + ctor ? create_objectrefnode(ctor) : nullnode(), + dtor ? create_objectrefnode(dtor) : nullnode(), + intconstnode(sizetype, innertype->size), + etemp, + NULL + ); + result = CExpr_NewExceptionSafeInit(newESalloc, makediadicnode(create_objectnode(tempobj), callexpr, EASS)); + } else { + result = CExpr_FuncCallSix( + cnar_func, + newalloc, + ctor ? create_objectrefnode(ctor) : nullnode(), + dtor ? create_objectrefnode(dtor) : nullnode(), + intconstnode(sizetype, innertype->size), + etemp, + NULL + ); + } + + if (ass) + result = makecommaexpression(ass, result); + result->rtype = tptr; + result->flags |= (qual & ENODE_FLAG_QUALS); + return result; +} + +static ENode *CExpr_NewSimpleClass(TypeClass *tclass, ENode *expr, ENodeList *args) { + ENode *precomp; + ENode *nullcheck; + + precomp = lalloc(sizeof(ENode)); + *precomp = *expr; + precomp->type = EPRECOMP; + precomp->data.precompid = CParser_GetUniqueID(); + + nullcheck = lalloc(sizeof(ENode)); + *nullcheck = *expr; + nullcheck->type = ENULLCHECK; + nullcheck->cost = 4; + nullcheck->data.nullcheck.nullcheckexpr = expr; + nullcheck->data.nullcheck.condexpr = CExpr_ConstructObject(tclass, precomp, args, 0, 1, 1, 1, 1); + nullcheck->data.nullcheck.precompid = precomp->data.precompid; + return nullcheck; +} + +static ENode *CExpr_NewClass(TypeClass *tclass, ENode *expr, ENodeList *args1, ENodeList *args2, Boolean flag) { + Object *objptr; + ENode *newESalloc; + + if (!args2 && !flag && CABI_ConstructorCallsNew(tclass)) { + expr = nullnode(); + expr->rtype = CDecl_NewPointerType(TYPE(tclass)); + return CExpr_ConstructObject(tclass, expr, args1, 0, 1, 1, 1, 1); + } else { + newESalloc = CExpr_NewExceptionSafeAlloc(TYPE(tclass), expr, args2, 0, flag, &objptr); + if (newESalloc) { + return CExpr_NewExceptionSafeInit( + newESalloc, + CExpr_ConstructObject(tclass, create_objectnode(objptr), args1, 0, 1, 1, 1, 1)); + } else { + return CExpr_NewSimpleClass(tclass, expr, args1); + } + } +} + +ENode *scannew(Boolean flag) { + Type *type; // r27 + UInt32 qual; + ENodeList *args; // r28 + Boolean placement_flag; // r26 + ENodeList *newargs; // r26 + ENode *expr; // r26 + ENodeList *args2; // r29 + Object *tempobj; + ENode *newESalloc; // r28 + ENode *tempobj_expr; // r25 + ENode *etemp_expr; // r28 + ENode *indirect_expr; // r25 + ENode *ass; // r25 + ENode *cond; // r27 + + type = NULL; + args = NULL; + firstarrayexpr = NULL; + if ((tk = lex()) == '(') { + tk = lex(); + placement_flag = isdeclaration(1, 1, 1, ')'); + if (!placement_flag) + args = CExpr_ScanExpressionList(1); + if (placement_flag) + type = scan_type_name(&qual); + if (tk != ')') + CError_Error(CErrorStr115); + else + tk = lex(); + } + + if (!type) { + if (tk == '(') { + tk = lex(); + type = scan_type_name(&qual); + if (tk != ')') + CError_Error(CErrorStr115); + else + tk = lex(); + } else { + type = scan_new_type_name(&qual); + } + } + + if (IS_TYPE_ARRAY(type)) + return CExpr_NewArray(type, qual, args, flag); + + if (IS_TYPE_CLASS(type)) { + if (TYPE_CLASS(type)->sominfo) + return CSOM_New(TYPE_CLASS(type)); + if (TYPE_CLASS(type)->objcinfo) + return CObjC_New(TYPE_CLASS(type)); + } + + if (!IsCompleteType(type) || !CanAllocObject(type)) + return nullnode(); + + newargs = lalloc(sizeof(ENodeList)); + newargs->next = args; + newargs->node = intconstnode(CABI_GetSizeTType(), type->size); + + expr = CExpr_NewAlloc(type, newargs, flag, 0); + expr->rtype = CDecl_NewPointerType(type); + expr->flags |= (qual & ENODE_FLAG_QUALS); + + if (tk == '(') { + tk = lex(); + args2 = CExpr_ScanExpressionList(1); + if (!args2 && !IS_TYPE_CLASS(type)) { + args2 = lalloc(sizeof(ENodeList)); + memclrw(args2, sizeof(ENodeList)); + args2->node = do_typecast(nullnode(), type, 0); + } + if (tk == ')') + tk = lex(); + else + CError_Error(CErrorStr115); + } else { + args2 = NULL; + } + + if (ENODE_IS(expr, EINTCONST)) + return expr; + + if (IS_TYPE_CLASS(type) && CClass_Constructor(TYPE_CLASS(type))) + return CExpr_NewClass(TYPE_CLASS(type), expr, args2, args, flag); + + if (args2) { + if (args2->next) { + CError_Error(CErrorStr174); + return nullnode(); + } + + newESalloc = CExpr_NewExceptionSafeAlloc(type, expr, args, 0, flag, &tempobj); + if (newESalloc) { + tempobj_expr = makemonadicnode(create_objectnode(tempobj), EINDIRECT); + tempobj_expr->rtype = type; + tempobj_expr->flags = args2->node->flags & ENODE_FLAG_QUALS; + return CExpr_NewExceptionSafeInit( + newESalloc, + makediadicnode(tempobj_expr, CExpr_AssignmentPromotion(args2->node, type, newESalloc->flags, 1), EASS) + ); + } else { + etemp_expr = CExpr_GetETEMPCopy(expr); + indirect_expr = makemonadicnode(etemp_expr, EINDIRECT); + indirect_expr->rtype = type; + indirect_expr->flags = args2->node->flags & ENODE_FLAG_QUALS; + ass = makediadicnode(indirect_expr, CExpr_AssignmentPromotion(args2->node, type, indirect_expr->flags, 1), EASS); + cond = CExpr_NewENode(ECOND); + cond->cost = 4; + cond->rtype = &stvoid; + cond->data.cond.cond = expr; + cond->data.cond.expr1 = ass; + cond->data.cond.expr2 = nullnode(); + cond = makecommaexpression(cond, etemp_expr); + cond->rtype = etemp_expr->rtype; + cond->flags = etemp_expr->flags; + return cond; + } + } else { + return expr; + } +} + +static ENode *CExpr_DeleteArray(ENode *expr, Type *type, Boolean flag) { + Object *obj; + Object *dtor; + Boolean outflag; + ENode *precomp; + SInt32 precompid; + ENode *tmp; + ENode *result; + + obj = CParser_FindDeallocationObject(type, NULL, 1, flag, &outflag); + + if (!IS_TYPE_CLASS(type) || CClass_IsPODClass(TYPE_CLASS(type))) + return CExpr_DeleteFuncCall(obj, expr, type, outflag); + + dtor = CClass_Destructor(TYPE_CLASS(type)); + if (dtor || outflag) { + if (obj->nspace == cscope_root && !outflag) { + return funccallexpr(dnar_func, expr, dtor ? create_objectrefnode(dtor) : nullnode(), NULL, NULL); + } + return funccallexpr( + dnar3_func, + expr, + dtor ? create_objectrefnode(dtor) : nullnode(), + create_objectrefnode(obj), + intconstnode(TYPE(&stsignedshort), outflag)); + } + + precomp = lalloc(sizeof(ENode)); + *precomp = *expr; + precomp->type = EPRECOMP; + precomp->data.precompid = precompid = CParser_GetUniqueID(); + tmp = CExpr_DeleteFuncCall(obj, makediadicnode(precomp, intconstnode(CABI_GetSizeTType(), 16), ESUB), type, 0); + + result = CExpr_NewENode(ENULLCHECK); + result->rtype = &stvoid; + result->cost = 4; + result->data.nullcheck.nullcheckexpr = expr; + result->data.nullcheck.condexpr = tmp; + result->data.nullcheck.precompid = precompid; + + return result; +} + +ENode *scandelete(Boolean flag) { + Boolean is_array; // r24 + ENode *expr; // r25 + Type *conv_type; // r22 + UInt32 conv_qual; // r23 + Type *innertype; // r23 + Type *t; + Object *obj; + Object *dtor; // r24 + ENode *result_expr; // r24??? + ENode *precomp_orig; // r31 + SInt32 precompid; // r30 + Boolean is_virtual; // r23 + ENode *nc; + ConversionIterator iter; + Boolean outflag; + BClassList path; + + if ((tk = lex()) == '[') { + if ((tk = lex()) != ']') + CError_Error(CErrorStr125); + else + tk = lex(); + is_array = 1; + } else { + is_array = 0; + } + + expr = cast_expression(); + if (!IS_TYPE_POINTER_ONLY(expr->rtype)) { + if (IS_TYPE_CLASS(expr->rtype)) { + conv_type = NULL; + CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(expr->rtype)); + while ((obj = CExpr_ConversionIteratorNext(&iter))) { + if (IS_TYPE_POINTER_ONLY(TYPE_FUNC(obj->type)->functype)) { + if (conv_type) { + CError_Error(CErrorStr199); + break; + } + conv_type = TYPE_FUNC(obj->type)->functype; + conv_qual = TYPE_FUNC(obj->type)->qual; + } + } + if (conv_type) { + if (!copts.old_argmatch) { + expr = CExpr_Convert(expr, conv_type, conv_qual, 1, 1); + } else { + if (user_assign_check(expr, conv_type, conv_qual, 1, 0, 1)) + expr = assign_node; + } + } + } + if (!IS_TYPE_POINTER_ONLY(expr->rtype)) { + CError_Error(CErrorStr146); + return nullnode(); + } + } + + innertype = TYPE_POINTER(expr->rtype)->target; + if (innertype->size == 0) + CDecl_CompleteType(innertype); + + if (IS_TYPE_ARRAY(innertype) && !is_array) + CError_Error(CErrorStr146); + + if (is_array) { + t = innertype; + while (IS_TYPE_ARRAY(t)) + t = TYPE_POINTER(t)->target; + return CExpr_DeleteArray(expr, t, flag); + } + + if (copts.objective_c && CObjC_IsType_id(expr->rtype)) + return CObjC_Delete(NULL, expr); + + if (!IS_TYPE_CLASS(innertype)) { + obj = CParser_FindDeallocationObject(innertype, NULL, 0, flag, &outflag); + CClass_CheckObjectAccess(NULL, obj); + return CExpr_DeleteFuncCall(obj, expr, innertype, outflag); + } + + if (TYPE_CLASS(innertype)->sominfo) + return CSOM_Delete(TYPE_CLASS(innertype), expr); + + if (TYPE_CLASS(innertype)->objcinfo) + return CObjC_Delete(TYPE_CLASS(innertype), expr); + + if (!(TYPE_CLASS(innertype)->flags & CLASS_COMPLETED) && copts.pedantic) + CError_Warning(CErrorStr136, innertype, 0); + + obj = CParser_FindDeallocationObject(innertype, NULL, 0, flag, &outflag); + CClass_CheckObjectAccess(NULL, obj); + dtor = CClass_Destructor(TYPE_CLASS(innertype)); + if (!dtor) + return CExpr_DeleteFuncCall(obj, expr, innertype, outflag); + + path.next = NULL; + path.type = innertype; + CClass_CheckObjectAccess(&path, dtor); + + result_expr = lalloc(sizeof(ENode)); + result_expr->type = EFUNCCALL; + result_expr->cost = 4; + result_expr->flags = 0; + result_expr->rtype = &stvoid; + if (dtor->datatype == DVFUNC) { + precomp_orig = expr; + expr = lalloc(sizeof(ENode)); + *expr = *precomp_orig; + expr->type = EPRECOMP; + expr->data.precompid = precompid = CParser_GetUniqueID(); + is_virtual = 1; + } else { + is_virtual = 0; + } + + if (!flag) { + result_expr = CABI_DestroyObject(dtor, expr, 2, 0, 1); + } else { + CError_ASSERT(5650, !outflag); + result_expr = CABI_DestroyObject(dtor, expr, 2, 0, 0); + result_expr->rtype = TYPE(&void_ptr); + result_expr = funccallexpr(obj, result_expr, NULL, NULL, NULL); + obj->flags |= OBJECT_USED; + } + + if (is_virtual) { + nc = lalloc(sizeof(ENode)); + nc->type = ENULLCHECK; + nc->rtype = &stvoid; + nc->cost = 4; + nc->flags = 0; + nc->data.nullcheck.nullcheckexpr = precomp_orig; + nc->data.nullcheck.condexpr = result_expr; + nc->data.nullcheck.precompid = precompid; + return nc; + } else { + return result_expr; + } +} diff --git a/compiler_and_linker/FrontEnd/C/CExprConvMatch.c b/compiler_and_linker/FrontEnd/C/CExprConvMatch.c new file mode 100644 index 0000000..5cc145f --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CExprConvMatch.c @@ -0,0 +1,2518 @@ +#include "compiler/CExpr.h" +#include "compiler/CABI.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CInt64.h" +#include "compiler/CFunc.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CObjC.h" +#include "compiler/CParser.h" +#include "compiler/CScope.h" +#include "compiler/CTemplateFunc.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct StandardConv { + Type *type1; + Type *type2; + UInt32 qual1; + UInt32 qual2; + Boolean x10; // unknown + Boolean x11; + Boolean x12; + Boolean x13; + Boolean x14; + Boolean x15; +} StandardConv; + +typedef enum EImplicitConvType { + ICT_0, + ICT_1, + ICT_2, + ICT_3 +} EImplicitConvType; + +typedef struct ImplicitConv { + EImplicitConvType type; + union { + struct { + Object *x2; + StandardConv standardConv; + } ic2; + struct { + StandardConv standardConv; + } ic3; + } u; +} ImplicitConv; + +typedef struct ConversionTypeList { + struct ConversionTypeList *next; + Object *func; + Type *type; + UInt32 qual; +} ConversionTypeList; + +typedef struct Match { + struct Match *next; + Object *object; + Object *specialfunc; + Type *type; + UInt32 qual; + Type *type2; + UInt32 qual2; + ImplicitConv conv[3]; +} Match; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +// forward decls +static ENode *CExpr_DerivedToBase(ENode *expr, Type *type2, UInt32 qual2, Boolean flag1, Boolean flag2, Boolean flag3); + +static Type *CExpr_GetImplictObjectParamType(Object *object, UInt32 *qual) { + Type *type; + + CError_ASSERT(98, IS_TYPE_FUNC(object->type)); + CError_ASSERT(99, TYPE_FUNC(object->type)->flags & FUNC_METHOD); + CError_ASSERT(100, !TYPE_METHOD(object->type)->is_static); + CError_ASSERT(101, TYPE_METHOD(object->type)->args); + + type = CDecl_NewRefPointerType(TYPE(TYPE_METHOD(object->type)->theclass)); + *qual = TYPE_METHOD(object->type)->args->qual & Q_CV; + return type; +} + +static Type *CExpr_GetParamType(Object *object, int index, UInt32 *qual) { + FuncArg *arg; + + CError_ASSERT(120, IS_TYPE_FUNC(object->type)); + CError_ASSERT(121, arg = TYPE_FUNC(object->type)->args); + if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(object->type))) + CError_ASSERT(125, arg = arg->next); + + while (index > 0) { + CError_ASSERT(129, arg = arg->next); + index--; + } + + *qual = arg->qual & Q_CV; + return arg->type; +} + +static Boolean CExpr_HasNParams(Object *object, int count) { + FuncArg *arg; + int i; + + CError_ASSERT(146, IS_TYPE_FUNC(object->type)); + CError_ASSERT(147, arg = TYPE_FUNC(object->type)->args); + if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(object->type))) + arg = arg->next; + + i = 0; + while (arg) { + arg = arg->next; + i++; + } + + return i == count; +} + +typedef enum TypeCompareMode { + TCM_0, + TCM_1, + TCM_2 +} TypeCompareMode; + +static Boolean CExpr_TypeCompare(Type *typeA, UInt32 qualA, Type *typeB, UInt32 qualB, TypeCompareMode mode) { + if (typeA->type != typeB->type) + return 0; + + switch (mode) { + case TCM_0: + while (1) { + switch (typeA->type) { + case TYPEPOINTER: + typeA = TPTR_TARGET(typeA); + typeB = TPTR_TARGET(typeB); + if (typeA->type != typeB->type) + return 0; + continue; + + case TYPEMEMBERPOINTER: + if (!is_typesame(TYPE_MEMBER_POINTER(typeA)->ty2, TYPE_MEMBER_POINTER(typeB)->ty2)) + return 0; + typeA = TYPE_MEMBER_POINTER(typeA)->ty1; + typeB = TYPE_MEMBER_POINTER(typeB)->ty1; + if (typeA->type != typeB->type) + return 0; + continue; + } + break; + } + break; + + case TCM_1: + switch (typeA->type) { + case TYPEPOINTER: + if ((qualA & Q_CV) != (qualB & Q_CV)) + return 0; + + typeA = TPTR_TARGET(typeA); + typeB = TPTR_TARGET(typeB); + break; + + case TYPEMEMBERPOINTER: + if ((qualA & Q_CV) != (qualB & Q_CV)) + return 0; + + if (!is_typesame(TYPE_MEMBER_POINTER(typeA)->ty2, TYPE_MEMBER_POINTER(typeB)->ty2)) + return 0; + typeA = TYPE_MEMBER_POINTER(typeA)->ty1; + typeB = TYPE_MEMBER_POINTER(typeB)->ty1; + break; + } + break; + + case TCM_2: + if ((qualA & Q_CV) != (qualB & Q_CV)) + return 0; + break; + } + + return is_typesame(typeA, typeB); +} + +static int CExpr_IsReferenceCompatible(Type *typeA, UInt32 qualA, Type *typeB, UInt32 qualB) { + if (CParser_IsSameOrMoreCVQualified(CParser_GetCVTypeQualifiers(typeA, qualA), CParser_GetCVTypeQualifiers(typeB, qualB))) { + if (CExpr_TypeCompare(typeA, qualA, typeB, qualB, TCM_1)) + return 1; + + if (IS_TYPE_CLASS(typeB) && IS_TYPE_CLASS(typeA)) { + short depth; + Boolean isambigbase; + if (CClass_GetBasePath(TYPE_CLASS(typeB), TYPE_CLASS(typeA), &depth, &isambigbase)) + return 2; + } + } + + return 0; +} + +static Boolean CExpr_IsBaseOf(TypeClass *baseclass, TypeClass *superclass) { + ClassList *base; + + for (base = superclass->bases; base; base = base->next) { + if (base->base == baseclass || CExpr_IsBaseOf(baseclass, base->base)) + return 1; + } + + return 0; +} + +static Boolean CExpr_IsBetterClassConversion(TypeClass *a, TypeClass *b, TypeClass *c, TypeClass *d) { + if (a == c) + return CExpr_IsBaseOf(d, b); + if (b == d) + return CExpr_IsBaseOf(a, c); + return 0; +} + +CW_INLINE Boolean Inline_501D40(Type *a, Type *b) { + return (a == TYPE(&stbool)) && (IS_TYPE_POINTER_ONLY(b) || IS_TYPE_MEMBERPOINTER(b)); +} + +static Boolean CExpr_IsBetterStandardConv(StandardConv *a, StandardConv *b) { + Boolean flag10; + Boolean flag3; + + flag10 = 1; + flag3 = 0; + + if (b->x11) { + if (!a->x11) + flag3 = 1; + } else { + if (a->x11) + flag10 = 0; + } + + if (b->x12) { + if (!a->x12) + flag3 = 1; + } else { + if (a->x12) + flag10 = 0; + } + + if (b->x13) { + if (a->x13) { + if (Inline_501D40(b->type2, b->type1)) { + if (!Inline_501D40(a->type2, a->type1)) + return 1; + } else { + if (Inline_501D40(a->type2, a->type1)) + return 0; + } + } else { + flag3 = 1; + } + } else { + if (a->x13) + flag10 = 0; + } + + if (flag10 && flag3) + return 1; + + if (!a->x13) { + if (b->x13) + return 1; + + if (a->x12) { + if (!b->x12) + return 0; + } else { + if (b->x12) + return 1; + } + } else { + if (!b->x13) + return 0; + } + + if ( + IS_TYPE_POINTER_ONLY(a->type1) && + IS_TYPE_CLASS(TPTR_TARGET(a->type1)) && + IS_TYPE_POINTER_ONLY(a->type2) && + IS_TYPE_POINTER_ONLY(b->type1) && + IS_TYPE_CLASS(TPTR_TARGET(b->type1)) && + IS_TYPE_POINTER_ONLY(b->type2) + ) + { + if (TPTR_TARGET(b->type2) == &stvoid) { + if (TPTR_TARGET(a->type2) == &stvoid) { + if (CExpr_IsBaseOf(TYPE_CLASS(TPTR_TARGET(a->type1)), TYPE_CLASS(TPTR_TARGET(b->type1)))) + return 1; + } else { + if (TPTR_TARGET(a->type1) == TPTR_TARGET(b->type1) && IS_TYPE_CLASS(TPTR_TARGET(a->type2))) + return 1; + } + } else if (IS_TYPE_CLASS(TPTR_TARGET(a->type2)) && IS_TYPE_CLASS(TPTR_TARGET(b->type2))) { + if (CExpr_IsBetterClassConversion( + TYPE_CLASS(TPTR_TARGET(a->type1)), + TYPE_CLASS(TPTR_TARGET(a->type2)), + TYPE_CLASS(TPTR_TARGET(b->type1)), + TYPE_CLASS(TPTR_TARGET(b->type2)) + )) + return 1; + } + } + + if ( + IS_TYPE_CLASS(a->type1) && + IS_TYPE_CLASS(a->type2) && + IS_TYPE_CLASS(b->type1) && + IS_TYPE_CLASS(b->type2) && + CExpr_IsBetterClassConversion( + TYPE_CLASS(a->type1), + TYPE_CLASS(a->type2), + TYPE_CLASS(b->type1), + TYPE_CLASS(b->type2) + ) + ) + return 1; + + if ( + IS_TYPE_MEMBERPOINTER(a->type1) && + IS_TYPE_MEMBERPOINTER(a->type2) && + IS_TYPE_MEMBERPOINTER(b->type1) && + IS_TYPE_MEMBERPOINTER(b->type2) && + IS_TYPE_CLASS(TYPE_MEMBER_POINTER(a->type1)->ty2) && + IS_TYPE_CLASS(TYPE_MEMBER_POINTER(a->type2)->ty2) && + IS_TYPE_CLASS(TYPE_MEMBER_POINTER(b->type1)->ty2) && + IS_TYPE_CLASS(TYPE_MEMBER_POINTER(b->type2)->ty2) && + CExpr_IsBetterClassConversion( + TYPE_CLASS(TYPE_MEMBER_POINTER(b->type1)->ty2), + TYPE_CLASS(TYPE_MEMBER_POINTER(b->type2)->ty2), + TYPE_CLASS(TYPE_MEMBER_POINTER(a->type1)->ty2), + TYPE_CLASS(TYPE_MEMBER_POINTER(a->type2)->ty2) + ) + ) + return 1; + + if ( + a->x14 && + b->x14 && + CExpr_TypeCompare(a->type2, a->qual2, b->type2, b->qual2, TCM_1) && + CParser_IsMoreCVQualified( + CParser_GetTypeQualifiers(b->type2, b->qual2), + CParser_GetTypeQualifiers(a->type2, a->qual2) + ) + ) + return 1; + + return 0; +} + +static Boolean CExpr_IsBetterImplicitConv(ImplicitConv *a, ImplicitConv *b) { + if (a->type > b->type) + return 1; + if (a->type != b->type) + return 0; + + if (a->type == ICT_3) + return CExpr_IsBetterStandardConv(&a->u.ic3.standardConv, &b->u.ic3.standardConv); + + if (a->type == ICT_2 && a->u.ic2.x2 == b->u.ic2.x2 && CExpr_IsBetterStandardConv(&a->u.ic2.standardConv, &b->u.ic2.standardConv)) + return 1; + + return 0; +} + +typedef enum SSCRMode { + SSCR_0, + SSCR_1, + SSCR_2 +} SSCRMode; + +static Boolean CExpr_SetupStandardConversionResult(ENode *expr, Type *type2, UInt32 qual2, SSCRMode mode, Boolean x14, Boolean refFlag, StandardConv *result) { + UInt32 cv1; + UInt32 cv2; + + if (x14) { + if (!CParser_IsConst(type2, qual2)) { + if (!refFlag && !CExpr_IsLValue(expr)) + return 0; + if (mode != SSCR_0 && !IS_TYPE_CLASS(type2)) + return 0; + } + + cv2 = CParser_GetTypeQualifiers(type2, qual2) & Q_CV; + cv1 = CParser_GetTypeQualifiers(expr->rtype, ENODE_QUALS(expr)) & Q_CV; + if (cv2 != cv1 && !CParser_IsMoreCVQualified(cv2, cv1)) + return 0; + } + + memclrw(result, sizeof(StandardConv)); + result->type2 = type2; + result->qual2 = qual2; + result->type1 = expr->rtype; + result->qual1 = ENODE_QUALS(expr); + result->x14 = x14; + + switch (mode) { + case SSCR_0: + break; + case SSCR_1: + result->x12 = 1; + break; + case SSCR_2: + result->x13 = 1; + break; + default: + CError_FATAL(581); + } + + return 1; +} + +typedef enum MysteryEnum { + ME_0, + ME_1, + ME_255 = 255 +} MysteryEnum; + +CW_INLINE MysteryEnum Inline_501FF0(UInt32 qual1, UInt32 qual2) { + if ((qual1 & Q_CV) == (qual2 & Q_CV)) + return ME_0; + + if (((qual2 & Q_CONST) && !(qual1 & Q_CONST)) || ((qual2 & Q_VOLATILE) && !(qual1 & Q_VOLATILE))) + return ME_255; + + return ME_1; +} + +static Boolean CExpr_SetQualConversionResult(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, StandardConv *result) { + Boolean flag = 1; + UInt32 cv1; + UInt32 cv2; + + while (1) { + cv1 = CParser_GetCVTypeQualifiers(type1, qual1); + cv2 = CParser_GetCVTypeQualifiers(type2, qual2); + + switch (Inline_501FF0(cv1, cv2)) { + case ME_0: + break; + + case ME_1: + result->x11 = 1; + if (!flag) + return 0; + break; + + default: + return 0; + } + + if (!(cv1 & Q_CONST)) + flag = 0; + + if (IS_TYPE_POINTER_ONLY(type1)) { + CError_ASSERT(635, IS_TYPE_POINTER_ONLY(type2)); + type1 = TPTR_TARGET(type1); + type2 = TPTR_TARGET(type2); + } else { + if (!IS_TYPE_MEMBERPOINTER(type1)) + return 1; + + CError_ASSERT(642, IS_TYPE_MEMBERPOINTER(type2)); + type1 = TYPE_MEMBER_POINTER(type1)->ty1; + type2 = TYPE_MEMBER_POINTER(type2)->ty1; + } + } +} + +static Boolean CExpr_OverloadFuncMatch(NameSpaceObjectList *list, TemplArg *templargs, Type *type, ENode **outExpr) { + Object *object; + TemplFuncInstance *inst; + ENode *expr; + FuncArg *arg; + int i; + ObjectList *objlist; + Object *object26; + ObjectList *objlist25; + ObjectList *objlist24; + Boolean flag23; + + if (!IS_TYPE_POINTER_ONLY(type) || !IS_TYPE_FUNC(type = TPTR_TARGET(type))) + return 0; + + object26 = NULL; + objlist25 = NULL; + objlist24 = NULL; + flag23 = 0; + + while (list) { + object = OBJECT(list->object); + if (object->otype == OT_OBJECT) { + if (IS_TEMPL_FUNC(object->type)) { + if (!flag23 && CTempl_CanDeduceFunc(object, TYPE_FUNC(type), templargs)) { + CError_ASSERT(685, inst = CTempl_DeduceFunc(object, TYPE_FUNC(type), templargs, NULL, 0)); + if (is_typesame(inst->object->type, type)) { + objlist = lalloc(sizeof(ObjectList)); + objlist->next = objlist24; + objlist->object = object; + objlist24 = objlist; + + if (object26 && object26 != inst->object) { + objlist = lalloc(sizeof(ObjectList)); + objlist->next = objlist25; + objlist->object = inst->object; + objlist25 = objlist; + } else { + object26 = inst->object; + } + } + } + } else if (is_typesame(object->type, type)) { + if (object26 && flag23) { + Object *checkA, *checkB; + checkA = object; + if (checkA->datatype == DALIAS) + checkA = checkA->u.alias.object; + checkB = object26; + if (checkB->datatype == DALIAS) + checkB = checkB->u.alias.object; + if (checkA != checkB) { + objlist = lalloc(sizeof(ObjectList)); + objlist->next = objlist25; + objlist->object = object; + objlist25 = objlist; + } + } else { + objlist25 = NULL; + object26 = object; + } + flag23 = 1; + } + } + list = list->next; + } + + if (object26) { + if (outExpr) { + if (objlist25) { + i = 0; + for (arg = TYPE_FUNC(object->type)->args; arg; arg = arg->next) + i++; + + if (!flag23 && (object = CTempl_PartialOrdering(objlist24->object, objlist24->next, i))) { + CError_ASSERT(741, inst = CTempl_DeduceFunc(object, TYPE_FUNC(type), templargs, NULL, 0)); + object26 = inst->object; + } else { + CError_OverloadedFunctionError(object26, objlist25); + } + } + + expr = CExpr_MakeObjRefNode(object26, 1); + *outExpr = expr; + expr->rtype = CDecl_NewPointerType(object26->type); + expr->flags = object->qual & ENODE_FLAG_QUALS; + object26->flags |= OBJECT_USED; + if (object26->datatype == DINLINEFUNC) + CError_Error(CErrorStr175); + } + + return 1; + } + + return 0; +} + +static Boolean CExpr_StandardConversionMatch(ENode *expr, Type *type2, UInt32 qual2, Boolean x14, StandardConv *result) { + Type *type1; + UInt32 qual1; + Boolean refFlag; + Type *inner2; + Type *inner1; + SSCRMode mode; + NameSpaceObjectList list; + + if (IS_TYPE_REFERENCE(type2)) { + type2 = TPTR_TARGET(type2); + if (IS_TYPE_POINTER_ONLY(type2)) + expr = pointer_generation(expr); + refFlag = 1; + } else { + if ( + (IS_TYPE_ARRAY(expr->rtype) && !IS_TYPE_ARRAY(type2)) || + (IS_TYPE_FUNC(expr->rtype) && !IS_TYPE_FUNC(type2)) + ) + expr = pointer_generation(expr); + refFlag = 0; + } + + type1 = expr->rtype; + qual1 = ENODE_QUALS(expr); + + if (IS_TYPE_POINTER_ONLY(type2)) { + if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval)) { + if (IS_TYPE_INT(type1) || (!copts.cplusplus && IS_TYPE_ENUM(type1))) + return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, x14, refFlag, result); + } + + if ( + IS_TYPE_INT(expr->rtype) && + ENODE_IS_INDIRECT_TO(expr, EOBJREF) && + (expr->data.monadic->data.objref->qual & Q_INLINE_DATA) && + CInt64_IsZero(&expr->data.monadic->data.objref->u.data.u.intconst) + ) + return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, x14, refFlag, result); + + if (ENODE_IS(expr, EOBJLIST)) + return CExpr_OverloadFuncMatch(expr->data.objlist.list, expr->data.objlist.templargs, type2, NULL) && + CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result); + + if (ENODE_IS(expr, EOBJREF) && IS_TEMPL_FUNC(expr->data.objref->type)) { + list.next = NULL; + list.object = OBJ_BASE(expr->data.objref); + return CExpr_OverloadFuncMatch(&list, NULL, type2, NULL) && + CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result); + } + + if (IS_TYPE_POINTER_ONLY(type1)) { + if ( + ENODE_IS(expr, ESTRINGCONST) && + TPTR_TARGET(type2) == TPTR_TARGET(type1) && + !(qual2 & Q_CONST) && + ( + TPTR_TARGET(type2) == TYPE(&stchar) || + TPTR_TARGET(type2) == TYPE(&stunsignedchar) || + TPTR_TARGET(type2) == CParser_GetWCharType() + ) + ) + { + if ( + CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result) && + CExpr_SetQualConversionResult(TPTR_TARGET(type2), qual2, TPTR_TARGET(type1), qual1 & ~Q_CONST, result) + ) + { + result->x11 = 1; + return 1; + } else { + return 0; + } + } + + if (copts.objective_c && CObjC_IsCompatibleType(expr->rtype, type2)) + return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, x14, refFlag, result); + + if (IS_TYPE_VOID(TPTR_TARGET(type2)) || (!copts.cplusplus && IS_TYPE_VOID(TPTR_TARGET(type1)))) { + if (CExpr_SetupStandardConversionResult(expr, type2, qual2, IS_TYPE_VOID(TPTR_TARGET(type1)) ? SSCR_0 : SSCR_2, refFlag, x14, result)) { + switch (Inline_501FF0(qual2, CParser_GetCVTypeQualifiers(TPTR_TARGET(type1), qual1))) { + case ME_1: + result->x11 = 1; + case ME_0: + return 1; + default: + return 0; + } + } else { + return 0; + } + } + + inner2 = TPTR_TARGET(type2); + inner1 = TPTR_TARGET(type1); + while (1) { + if (inner2->type != inner1->type) + break; + + switch (inner2->type) { + case TYPEPOINTER: + inner2 = TPTR_TARGET(inner2); + inner1 = TPTR_TARGET(inner1); + continue; + case TYPEMEMBERPOINTER: + if (!is_typesame(TYPE_MEMBER_POINTER(inner2)->ty2, TYPE_MEMBER_POINTER(inner1)->ty2)) + break; + + inner2 = TYPE_MEMBER_POINTER(inner2)->ty1; + inner1 = TYPE_MEMBER_POINTER(inner1)->ty1; + if (!IS_TYPE_POINTER_ONLY(inner2) && !IS_TYPE_MEMBERPOINTER(inner2)) { + if (!is_memberpointerequal(inner2, inner1)) + break; + + if (CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result)) + return CExpr_SetQualConversionResult(TPTR_TARGET(type2), qual2, TPTR_TARGET(type1), qual1, result); + else + return 0; + } + continue; + default: + if (!is_typesame(inner2, inner1)) + break; + + if (CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result)) + return CExpr_SetQualConversionResult(TPTR_TARGET(type2), qual2, TPTR_TARGET(type1), qual1, result); + else + return 0; + } + + break; + } + + if (IS_TYPE_CLASS(TPTR_TARGET(type2)) && IS_TYPE_CLASS(TPTR_TARGET(type1))) { + short depth; + Boolean isambigbase; + if (CClass_GetBasePath(TYPE_CLASS(TPTR_TARGET(type1)), TYPE_CLASS(TPTR_TARGET(type2)), &depth, &isambigbase)) { + if (CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, refFlag, x14, result)) + return CExpr_SetQualConversionResult(TPTR_TARGET(type2), qual2, TPTR_TARGET(type1), qual1, result); + else + return 0; + } + } + } + + if (copts.mpwc_relax && !copts.cplusplus && IS_TYPE_POINTER_ONLY(type1)) { + if (CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, refFlag, x14, result)) + return 1; + } + + return 0; + } + + if (is_typesame(type2, type1)) + return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result); + + if (type2 == TYPE(&stbool)) { + switch (type1->type) { + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPEMEMBERPOINTER: + case TYPEPOINTER: + return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, refFlag, x14, result); + default: + return 0; + } + } + + if (IS_TYPE_MEMBERPOINTER(type2)) { + if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval)) { + if (IS_TYPE_INT(type1) || (!copts.cplusplus && IS_TYPE_ENUM(type1))) + return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, refFlag, x14, result); + } + + if (ENODE_IS(expr, EMEMBER)) { + expr = getpointertomemberfunc(expr, type2, 0); + type1 = expr->rtype; + } + + if (IS_TYPE_MEMBERPOINTER(type1)) { + short depth; + Boolean isambigbase; + + CError_ASSERT(996, IS_TYPE_CLASS(TYPE_MEMBER_POINTER(type2)->ty2) && IS_TYPE_CLASS(TYPE_MEMBER_POINTER(type1)->ty2)); + if (!is_memberpointerequal(TYPE_MEMBER_POINTER(type2)->ty1, TYPE_MEMBER_POINTER(type1)->ty1)) + return 0; + + if ( + TYPE_MEMBER_POINTER(type2)->ty2 == TYPE_MEMBER_POINTER(type1)->ty2 || + CClass_GetBasePath(TYPE_CLASS(TYPE_MEMBER_POINTER(type2)->ty2), TYPE_CLASS(TYPE_MEMBER_POINTER(type1)->ty2), &depth, &isambigbase) + ) + { + if (CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, refFlag, x14, result)) + return CExpr_SetQualConversionResult(TYPE_MEMBER_POINTER(type2)->ty1, qual2, TYPE_MEMBER_POINTER(type1)->ty1, qual1, result); + else + return 0; + } + } + + return 0; + } + + mode = SSCR_2; + switch (type1->type) { + case TYPEINT: + switch (type2->type) { + case TYPEINT: + if (TYPE_INTEGRAL(type1)->integral < IT_INT) { + if (type2 == TYPE(&stsignedint)) { + if (type1->size < type2->size || !is_unsigned(type1)) + mode = SSCR_1; + } else if (type2 == TYPE(&stunsignedint)) { + if (type2->size == type1->size && is_unsigned(type1)) + mode = SSCR_1; + } + } + break; + case TYPEFLOAT: + break; + case TYPEENUM: + if (copts.cplusplus) + return 0; + break; + default: + return 0; + } + break; + + case TYPEFLOAT: + switch (type2->type) { + case TYPEINT: + break; + case TYPEFLOAT: + if (type2 == TYPE(&stdouble)) { + if (type1 == TYPE(&stfloat) || type1 == TYPE(&stshortdouble)) + mode = SSCR_1; + } + break; + case TYPEENUM: + if (copts.cplusplus) + return 0; + break; + default: + return 0; + } + break; + + case TYPEENUM: + switch (type2->type) { + case TYPEINT: + if (TYPE_INTEGRAL(TYPE_ENUM(expr->rtype)->enumtype)->integral < IT_INT) { + if (type1->size == type2->size && is_unsigned(TYPE_ENUM(type1)->enumtype)) { + if (type2 == TYPE(&stunsignedint)) + mode = SSCR_1; + } else { + if (type2 == TYPE(&stsignedint)) + mode = SSCR_1; + } + } else { + if (TYPE_ENUM(type1)->enumtype == type2) + mode = SSCR_1; + } + break; + case TYPEFLOAT: + break; + case TYPEENUM: + if (copts.cplusplus) + return 0; + break; + default: + return 0; + } + break; + + case TYPECLASS: { + short depth; + Boolean isambigbase; + + if (!IS_TYPE_CLASS(type1) || !CClass_GetBasePath(TYPE_CLASS(type1), TYPE_CLASS(type2), &depth, &isambigbase)) + return 0; + break; + } + + default: + return 0; + } + + return CExpr_SetupStandardConversionResult(expr, type2, qual2, mode, refFlag, x14, result); +} + +static ENode *CExpr_UserConversion(ENode *expr, Type *type2, UInt32 qual2, ImplicitConv *result, Boolean flag1, Boolean isExplicit, Boolean flag3) { + Object *object28; + Object *object27; + Object *object26; + ObjectList *objlist25; + ObjectList *objlist24; + ObjectList *objlist; + TypeFunc *tfunc23; + Type *tmptype23; + NameSpaceObjectList *list22; + Boolean flag22; + Boolean flag21; + FuncArg *arg21; + Boolean flag20; + ENode *newExpr; + ENode *funcref; + ENode *tmpExpr; + ENodeList *arglist; + UInt32 q1; + UInt32 q2; + StandardConv sc3; + StandardConv sc2; + StandardConv sc1; + ConversionIterator convIter; + ENodeList myarglist; + ObjectList myobjlist; + BClassList path; + + object28 = NULL; + object27 = NULL; + objlist25 = NULL; + objlist24 = NULL; + + if (type2->size == 0) + CDecl_CompleteType(type2); + if (expr->rtype->size == 0) + CDecl_CompleteType(expr->rtype); + + if (IS_TYPE_CLASS(expr->rtype)) { + CExpr_ConversionIteratorInit(&convIter, TYPE_CLASS(expr->rtype)); + flag22 = 1; + while ((object26 = CExpr_ConversionIteratorNext(&convIter))) { + tfunc23 = TYPE_FUNC(object26->type); + if (tfunc23->flags & FUNC_IS_TEMPL) { + object26 = CTempl_DeduceFromConversion(object26, type2, qual2); + if (!object26) + continue; + tfunc23 = TYPE_FUNC(object26->type); + } + + if (flag3) { + if ( + !IS_TYPE_REFERENCE(tfunc23->functype) || + !CExpr_IsReferenceCompatible(type2, qual2, TPTR_TARGET(tfunc23->functype), tfunc23->qual) + ) + continue; + } + + CError_ASSERT(1230, tfunc23->args && IS_TYPE_POINTER_ONLY(tfunc23->args->type)); + + q1 = ENODE_QUALS(expr); + q2 = tfunc23->args->qual; + if ((q1 & Q_CV) != (q2 & Q_CV)) { + if (!flag22) + continue; + if ((q1 & Q_CONST) && !(q2 & Q_CONST)) + continue; + if ((q1 & Q_VOLATILE) && !(q2 & Q_VOLATILE)) + continue; + flag21 = 1; + } else { + flag21 = 0; + } + + newExpr = CExpr_NewENode(ETEMP); + newExpr->rtype = tfunc23->functype; + newExpr->flags = tfunc23->qual & ENODE_FLAG_QUALS; + flag20 = 0; + + if (IS_TYPE_REFERENCE(newExpr->rtype)) { + newExpr->rtype = TPTR_TARGET(newExpr->rtype); + if (!CParser_IsConst(newExpr->rtype, tfunc23->qual)) { + newExpr = makemonadicnode(newExpr, EINDIRECT); + newExpr->data.monadic->rtype = TYPE(&void_ptr); + newExpr = makemonadicnode(newExpr, EINDIRECT); + newExpr->data.monadic->rtype = TYPE(&void_ptr); + flag20 = 1; + } + } + + if (CExpr_StandardConversionMatch(newExpr, type2, qual2, 0, &sc1)) { + if (flag22 && !flag21) { + object28 = NULL; + objlist25 = NULL; + flag22 = 0; + } + + if (object28 && object28 != object26) { + if (CExpr_IsBetterStandardConv(&sc3, &sc1)) + continue; + + if (!CExpr_IsBetterStandardConv(&sc1, &sc3)) { + objlist = lalloc(sizeof(ObjectList)); + objlist->next = objlist25; + objlist->object = object28; + objlist25 = objlist; + } else { + objlist25 = NULL; + } + } + + object28 = object26; + sc3 = sc1; + sc3.x15 = flag20; + } + } + } + + if (!flag3 && IS_TYPE_CLASS(type2) && (list22 = CClass_Constructor(TYPE_CLASS(type2)))) { + for (; list22; list22 = list22->next) { + object26 = OBJECT(list22->object); + if ( + object26->otype == OT_OBJECT && + IS_TYPE_FUNC(tfunc23 = TYPE_FUNC(object26->type)) && + (isExplicit || !(object26->qual & Q_EXPLICIT)) + ) + { + if (tfunc23->flags & FUNC_IS_TEMPL) { + myarglist.next = NULL; + myarglist.node = expr; + object26 = CTempl_DeduceFromFunctionCall(object26, NULL, &myarglist); + if (!object26) + continue; + tfunc23 = TYPE_FUNC(object26->type); + } + + if (!(arg21 = tfunc23->args)) + continue; + if (!(arg21 = arg21->next)) + continue; + if ((TYPE_CLASS(type2)->flags & CLASS_HAS_VBASES) && !(arg21 = arg21->next)) + continue; + if (arg21 == &elipsis) + continue; + if (arg21->next && !arg21->next->dexpr && arg21->next != &elipsis) + continue; + + tmptype23 = arg21->type; + if (IS_TYPE_REFERENCE(tmptype23)) { + tmptype23 = TPTR_TARGET(tmptype23); + if (!CParser_IsConst(tmptype23, arg21->qual) && !CExpr_IsLValue(expr)) + continue; + } + + if (CExpr_StandardConversionMatch(expr, tmptype23, arg21->qual, 0, &sc1)) { + if (object27) { + if (object26->u.func.inst && !object27->u.func.inst) + continue; + if (CExpr_IsBetterStandardConv(&sc2, &sc1)) + continue; + + if (!CExpr_IsBetterStandardConv(&sc1, &sc2)) { + if (!object26->u.func.inst && object27->u.func.inst) { + objlist24 = NULL; + } else { + objlist = lalloc(sizeof(ObjectList)); + objlist->next = objlist25; + objlist->object = object28; + objlist25 = objlist; + } + } else { + objlist25 = NULL; + } + } + + object27 = object26; + sc2 = sc1; + } + } + } + } + + if (object28 && object27) { + if (!CExpr_IsBetterStandardConv(&sc2, &sc3)) { + if (!CExpr_IsBetterStandardConv(&sc3, &sc2)) { + if (result) { + result->type = ICT_2; + result->u.ic2.x2 = object28; + result->u.ic2.standardConv = sc3; + } + if (flag1) { + myobjlist.next = NULL; + myobjlist.object = object27; + CError_OverloadedFunctionError(object28, &myobjlist); + } + } else { + object27 = NULL; + } + } else { + object28 = NULL; + } + } + + if (object28) { + if (result) { + result->type = ICT_2; + result->u.ic2.x2 = object28; + result->u.ic2.standardConv = sc3; + } + if (!flag1) + return expr; + if (objlist25) + CError_OverloadedFunctionError(object28, objlist25); + tfunc23 = TYPE_FUNC(object28->type); + CError_ASSERT(1416, IS_TYPEFUNC_METHOD(tfunc23)); + + funcref = create_objectrefnode(object28); + object28->flags |= OBJECT_USED; + + arglist = lalloc(sizeof(ENodeList)); + arglist->next = NULL; + + expr = getnodeaddress(expr, 0); + arglist->node = CExpr_AssignmentPromotion( + expr, + CDecl_NewPointerType(TYPE(TYPE_METHOD(tfunc23)->theclass)), + expr->flags, + 0); + + newExpr = lalloc(sizeof(ENode)); + newExpr->type = EFUNCCALL; + newExpr->cost = 4; + newExpr->rtype = tfunc23->functype; + newExpr->flags = tfunc23->qual & ENODE_FLAG_QUALS; + newExpr->data.funccall.funcref = funcref; + newExpr->data.funccall.args = arglist; + newExpr->data.funccall.functype = TYPE_FUNC(object28->type); + newExpr = CExpr_AdjustFunctionCall(newExpr); + newExpr = checkreference(newExpr); + + if (newExpr->rtype != type2) { + if (flag3) { + tmpExpr = CExpr_DerivedToBase(newExpr, type2, qual2, 1, 0, 1); + if (tmpExpr) + return tmpExpr; + } + newExpr = CExpr_Convert(newExpr, type2, qual2, 0, 1); + } + return newExpr; + } + + if (object27) { + if (result) { + result->type = ICT_2; + result->u.ic2.x2 = object27; + result->u.ic2.standardConv = sc2; + } + if (!flag1) + return expr; + if (objlist24) + CError_OverloadedFunctionError(object27, objlist24); + + arglist = lalloc(sizeof(ENodeList)); + arglist->next = NULL; + arglist->node = expr; + + if (TYPE_CLASS(type2)->flags & CLASS_HAS_VBASES) { + arglist->next = lalloc(sizeof(ENodeList)); + arglist->next->node = expr; + arglist->next->next = NULL; + arglist->node = intconstnode(TYPE(&stsignedshort), 1); + } + + path.next = NULL; + path.type = type2; + + tmpExpr = makemonadicnode(create_temp_node(type2), EINDIRECT); + tmpExpr->rtype = type2; + + newExpr = CExpr_GenericFuncCall( + &path, tmpExpr, 0, object27, NULL, NULL, arglist, 0, 0, 1 + ); + + if (ENODE_IS2(newExpr, EFUNCCALL, EFUNCCALLP)) { + newExpr->rtype = CDecl_NewPointerType(type2); + newExpr = makemonadicnode(newExpr, EINDIRECT); + newExpr->rtype = type2; + } + + return newExpr; + } + + return NULL; +} + +static Boolean CExpr_UserConversionMatch(ENode *expr, Type *type2, UInt32 qual2, ImplicitConv *result) { + Boolean flag; + + if (IS_TYPE_REFERENCE(type2)) { + type2 = TPTR_TARGET(type2); + flag = !CParser_IsConst(type2, qual2); + } else { + expr = pointer_generation(expr); + flag = 0; + } + + if (CExpr_UserConversion(expr, type2, qual2, result, 0, 0, flag)) + return 1; + + return 0; +} + +static Boolean CExpr_ImplicitConversionMatch(ENode *expr, Type *type2, UInt32 qual2, ImplicitConv *result) { + if (CExpr_StandardConversionMatch(expr, type2, qual2, 0, &result->u.ic3.standardConv)) { + result->type = ICT_3; + return 1; + } + + if (IS_TYPE_CLASS(expr->rtype) || IS_TYPE_CLASS(type2) || (IS_TYPE_REFERENCE(type2) && IS_TYPE_CLASS(TPTR_TARGET(type2)))) { + if (CExpr_UserConversionMatch(expr, type2, qual2, result)) { + result->type = ICT_2; + return 1; + } + } + + return 0; +} + +Boolean CExpr_CanImplicitlyConvert(ENode *expr, Type *type2, UInt32 qual2) { + ImplicitConv result; + return CExpr_ImplicitConversionMatch(expr, type2, qual2, &result); +} + +static ENode *CExpr_DerivedToBase(ENode *expr, Type *type2, UInt32 qual2, Boolean flag1, Boolean nullcheckflag, Boolean pathcheckflag) { + BClassList *path; + short depth; + Boolean isambigbase; + + if ( + IS_TYPE_CLASS(type2) && + IS_TYPE_CLASS(expr->rtype) && + (path = CClass_GetBasePath(TYPE_CLASS(expr->rtype), TYPE_CLASS(type2), &depth, &isambigbase)) + ) + { + if (isambigbase) + CError_Error(CErrorStr188); + if (flag1) + CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); + + if (pathcheckflag) { + expr = getnodeaddress(expr, 0); + expr = makemonadicnode(CExpr_ClassPointerCast(path, expr, nullcheckflag), EINDIRECT); + expr->rtype = type2; + expr->flags = qual2 & ENODE_FLAG_QUALS; + } + + return expr; + } + else { + return NULL; + } +} + +static ENode *CExpr_ClassReferenceConversion(ENode *expr, Type *type2, UInt32 qual2, Boolean pathcheckflag) { + int refcompat; + + if (CExpr_IsLValue(expr) && IS_TYPE_CLASS(type2) && IS_TYPE_CLASS(expr->rtype)) { + refcompat = CExpr_IsReferenceCompatible(type2, 0, expr->rtype, 0); + if (refcompat > 0) { + if (refcompat == 2) { + CError_ASSERT(1668, IS_TYPE_CLASS(type2) && IS_TYPE_CLASS(expr->rtype)); + expr = CExpr_DerivedToBase(expr, type2, qual2, pathcheckflag, 0, 1); + } + expr->flags = qual2 & ENODE_FLAG_QUALS; + return expr; + } + + refcompat = CExpr_IsReferenceCompatible(expr->rtype, 0, type2, 0); + if (refcompat > 0) { + expr = CClass_ClassPointerCast( + getnodeaddress(expr, 0), + TYPE_CLASS(expr->rtype), TYPE_CLASS(type2), + 1, 1, pathcheckflag + ); + CError_ASSERT(1680, IS_TYPE_POINTER_ONLY(expr->rtype)); + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = type2; + expr->flags = qual2 & ENODE_FLAG_QUALS; + return expr; + } + } + + if (IS_TYPE_CLASS(expr->rtype)) { + if ((expr = CExpr_UserConversion(expr, type2, qual2, NULL, 1, 0, 1))) + return expr; + } + + return NULL; +} + +static ENode *CExpr_BindToReference(ENode *expr, Type *type2, UInt32 qual2) { + UInt32 cv; + int refcompat; + ENode *tmp; + + cv = CParser_GetCVTypeQualifiers(type2, qual2); + + if (CExpr_IsLValue(expr)) { + refcompat = CExpr_IsReferenceCompatible(type2, qual2, expr->rtype, ENODE_QUALS(expr)); + if (refcompat > 0) { + if (refcompat == 2) { + CError_ASSERT(1718, IS_TYPE_CLASS(type2) && IS_TYPE_CLASS(expr->rtype)); + expr = CExpr_DerivedToBase(expr, type2, qual2, 1, 0, 1); + } + return getnodeaddress(expr, 0); + } + } else if (IS_TYPE_CLASS(type2) && IS_TYPE_CLASS(expr->rtype)) { + refcompat = CExpr_IsReferenceCompatible(type2, qual2, expr->rtype, ENODE_QUALS(expr)); + if (refcompat > 0) { + if (refcompat == 2) + expr = CExpr_DerivedToBase(expr, type2, qual2, 1, 0, 1); + return getnodeaddress(expr, 0); + } + } + + if (IS_TYPE_CLASS(expr->rtype)) { + if ((tmp = CExpr_UserConversion(expr, type2, qual2, NULL, 1, 0, 1))) + return getnodeaddress(tmp, 0); + } + + if (!(cv & Q_CONST)) + CError_Error(CErrorStr228); + if (cv & Q_VOLATILE) + CError_Error(CErrorStr259); + + if (expr->rtype != type2) + expr = CExpr_Convert(expr, type2, qual2, 0, 1); + + if (!CExpr_IsLValue(expr)) { + expr = CExpr_LValue(expr, 0, 0); + if (!ENODE_IS(expr, EINDIRECT)) + expr = get_address_of_temp_copy(expr, 1); + else + expr = getnodeaddress(expr, 0); + } else { + expr = getnodeaddress(expr, 0); + } + + return expr; +} + +ENode *CExpr_Convert(ENode *expr, Type *type, UInt32 qual, Boolean isExplicit, Boolean flag2) { + UInt32 cv; + ENode *refExpr; + ENode *newExpr; + Type *typeCopy; + NameSpaceObjectList myList; + + cv = qual & Q_CV; + + if (copts.cpp_extensions && is_typesame(expr->rtype, type) && !ENODE_IS(expr, EOBJLIST)) { + expr = CExpr_RewriteConst(expr); + expr->rtype = type; + expr->flags &= ~ENODE_FLAG_QUALS; + expr->flags |= cv; + return expr; + } + + if (type == TYPE(&stvoid)) { + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = type; + expr->flags = cv; + return expr; + } + + if (IS_TYPE_REFERENCE(type)) { + if (isExplicit) { + refExpr = CExpr_ClassReferenceConversion(expr, TPTR_TARGET(type), qual, flag2); + if (refExpr) + return refExpr; + + expr = getnodeaddress(expr, 0); + typeCopy = galloc(sizeof(TypePointer)); + *TYPE_POINTER(typeCopy) = *TYPE_POINTER(type); + TPTR_QUAL(typeCopy) &= ~Q_REFERENCE; + expr = CExpr_Convert(expr, typeCopy, qual, 0, flag2); + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = TPTR_TARGET(type); + expr->flags = cv; + return expr; + } else { + return CExpr_BindToReference(expr, TPTR_TARGET(type), qual); + } + } + + if ( + (IS_TYPE_ARRAY(expr->rtype) && !IS_TYPE_ARRAY(type)) || + (IS_TYPE_FUNC(expr->rtype) && !IS_TYPE_FUNC(type)) + ) + { + expr = pointer_generation(expr); + } else { + expr = CExpr_RewriteConst(expr); + } + + if (ENODE_IS(expr, EOBJLIST)) { + if (CExpr_OverloadFuncMatch(expr->data.objlist.list, expr->data.objlist.templargs, type, &refExpr)) + return refExpr; + } else if (ENODE_IS(expr, EOBJREF) && IS_TEMPL_FUNC(expr->data.objref->type)) { + myList.next = NULL; + myList.object = OBJ_BASE(expr->data.objref); + if (CExpr_OverloadFuncMatch(&myList, NULL, type, &refExpr)) + return refExpr; + } else if (IS_TYPE_CLASS(expr->rtype) || IS_TYPE_CLASS(type)) { + if (expr->rtype->size == 0) + CDecl_CompleteType(expr->rtype); + + if (IS_TYPE_CLASS(type)) { + CanAllocObject(type); + if (!CClass_CopyConstructor(TYPE_CLASS(type)) || CClass_IsTrivialCopyClass(TYPE_CLASS(type))) { + if (expr->rtype == type) + return expr; + + refExpr = CExpr_DerivedToBase(expr, type, qual, flag2, 0, 1); + if (refExpr) + return refExpr; + } + } + + refExpr = CExpr_UserConversion(expr, type, qual, NULL, 1, isExplicit, 0); + if (refExpr) { + refExpr->flags = cv; + return refExpr; + } + } else if (!isExplicit && is_typesame(expr->rtype, type)) { + if (ENODE_IS(expr, EINDIRECT) && ENODE_QUALS(expr) != cv) + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = type; + expr->flags = cv; + return expr; + } else { + if ( + copts.warn_implicitconv && + !isExplicit && + IS_TYPE_INT_OR_FLOAT(type) && + IS_TYPE_INT_OR_FLOAT(expr->rtype) + ) + CExpr_CheckArithmConversion(expr, type); + + switch (type->type) { + case TYPEINT: + if (type == TYPE(&stbool)) { + switch (expr->rtype->type) { + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPEMEMBERPOINTER: + case TYPEPOINTER: + return CExpr_ConvertToBool(expr, isExplicit); + } + } else { + switch (expr->rtype->type) { + case TYPEENUM: + expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; + case TYPEINT: + case TYPEFLOAT: + do_int_float_conversion: + if ( + ENODE_IS(expr, ETYPCON) && + expr->rtype->type == type->type && + expr->rtype->size == type->size && + is_unsigned(expr->rtype) == is_unsigned(type) && + ENODE_QUALS(expr) == qual + ) + { + expr->rtype = type; + expr->flags |= ENODE_FLAG_80; + return expr; + } else { + refExpr = promote(expr, type); + refExpr->flags = cv; + return refExpr; + } + break; + case TYPEPOINTER: + if (expr->rtype->size > type->size && copts.warn_ptr_int_conv) + CError_Warning(CErrorStr382); + if (ENODE_IS(expr, ETYPCON)) { + ENode *inner = expr->data.monadic; + if (ENODE_IS(inner, EINTCONST)) { + inner->rtype = type; + inner->flags = cv; + inner->data.intval = CExpr_IntConstConvert(type, TYPE(&stunsignedlong), inner->data.intval); + return inner; + } + } + if (type->size != 4) { + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = TYPE(&stunsignedlong); + } + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = type; + expr->flags = cv; + return expr; + } + } + break; + + case TYPEFLOAT: + switch (expr->rtype->type) { + case TYPEENUM: + expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; + case TYPEINT: + case TYPEFLOAT: + goto do_int_float_conversion; + } + break; + + case TYPEENUM: + expr = CExpr_Convert(expr, TYPE_ENUM(type)->enumtype, qual, isExplicit, flag2); + if (!ENODE_IS(expr, EINTCONST)) + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = type; + expr->flags = cv; + return expr; + + case TYPEPOINTER: + switch (expr->rtype->type) { + case TYPEENUM: + expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; + case TYPEINT: + if (expr->rtype->size != 4) { + if (!ENODE_IS(expr, EINTCONST)) + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = TYPE(&stunsignedlong); + } + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = type; + expr->flags = cv; + return expr; + + case TYPEPOINTER: + if (IS_TYPE_CLASS(TPTR_TARGET(expr->rtype)) && IS_TYPE_CLASS(TPTR_TARGET(type))) + expr = CExpr_SafeClassPointerCast(expr, TYPE_CLASS(TPTR_TARGET(expr->rtype)), TYPE_CLASS(TPTR_TARGET(type)), 1, flag2); + if (!ENODE_IS(expr, ETYPCON)) + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = type; + expr->flags = cv; + return expr; + } + break; + + case TYPEMEMBERPOINTER: + if (!IS_TYPE_MEMBERPOINTER(expr->rtype)) + expr = CExpr_MemberPointerConversion(expr, TYPE_MEMBER_POINTER(type), 1); + + if (IS_TYPE_MEMBERPOINTER(expr->rtype)) { + expr = PointerToMemberCast(expr, TYPE_MEMBER_POINTER(expr->rtype), TYPE_MEMBER_POINTER(type), flag2); + expr->flags = cv; + return expr; + } + break; + } + } + + if (isExplicit) { + if ((newExpr = CodeGen_HandleTypeCast(expr, type, qual))) + return newExpr; + } + + CError_Error( + isExplicit ? CErrorStr247 : CErrorStr209, + expr->rtype, ENODE_QUALS(expr), + type, qual); + return nullnode(); +} + +ENode *CExpr_AssignmentPromotion(ENode *expr, Type *type2, UInt32 qual2, Boolean flag) { + ImplicitConv result; + + if (copts.old_argmatch) + return oldassignmentpromotion(expr, type2, qual2, flag); + + if (ENODE_IS(expr, EMEMBER)) + expr = getpointertomemberfunc(expr, type2, 1); + + if (!CExpr_ImplicitConversionMatch(expr, type2, qual2, &result)) { + CError_Error(CErrorStr209, expr->rtype, ENODE_QUALS(expr), type2, qual2); + return nullnode(); + } + + return CExpr_Convert(expr, type2, qual2, 0, flag); +} + +static Boolean CExpr_IsBetterMatch(Match *a, Match *b, int count) { + ImplicitConv *convA; + ImplicitConv *convB; + int i; + Boolean flag; + + convA = a->conv; + convB = b->conv; + flag = 0; + + if (convA->type != ICT_0 && convB->type != ICT_0) { + if (CExpr_IsBetterImplicitConv(convB, convA)) + return 0; + if (CExpr_IsBetterImplicitConv(convA, convB)) + flag = 1; + } + + for (i = 0; i < count; i++) { + if (CExpr_IsBetterImplicitConv(++convB, ++convA)) + return 0; + if (CExpr_IsBetterImplicitConv(convA, convB)) + flag = 1; + } + + if (flag) + return 1; + + if (b->object) { + CError_ASSERT(2165, IS_TYPE_FUNC(b->object->type)); + if (b->object->u.func.inst) { + if (!a->object) + return 1; + + CError_ASSERT(2169, IS_TYPE_FUNC(a->object->type)); + if (!a->object->u.func.inst) + return 1; + + CError_ASSERT(2174, a->specialfunc && b->specialfunc); + if (CTempl_FuncIsMoreSpecialized(a->specialfunc, b->specialfunc)) + return 1; + } + } + + return 0; +} + +static Boolean CExpr_MatchArgs(Object *func, ENodeList *argexprs, ENode *expr, ImplicitConv *convs) { + FuncArg *args; + ENode *newExpr; + Type *type; + + args = TYPE_FUNC(func->type)->args; + + if (!(TYPE_FUNC(func->type)->flags & FUNC_METHOD)) { + convs->type = ICT_0; + } else if (TYPE_METHOD(func->type)->is_static) { + convs->type = ICT_0; + } else if (TYPE_FUNC(func->type)->flags & FUNC_IS_CTOR) { + convs->type = ICT_0; + args = args->next; + } else { + if (!expr) + return 0; + + newExpr = lalloc(sizeof(ENode)); + newExpr->type = EINTCONST; + newExpr->cost = 0; + newExpr->flags = expr->flags; + newExpr->rtype = CDecl_NewPointerType(expr->rtype); + newExpr->data.intval = cint64_zero; + + if (func->datatype == DALIAS) { + CError_ASSERT(2231, func->u.alias.member); + type = CDecl_NewPointerType(func->u.alias.member->type); + } else { + type = args->type; + } + + if (!CExpr_ImplicitConversionMatch(newExpr, type, args->qual, convs)) + return 0; + args = args->next; + } + + convs++; + while (1) { + if (!args || args->type == &stvoid) { + if (argexprs) + return 0; + else + return 1; + } + + if (args == &elipsis || args == &oldstyle) { + while (argexprs) { + convs->type = ICT_1; + argexprs = argexprs->next; + convs++; + } + return 1; + } + + if (!argexprs) + return args->dexpr != NULL; + + if (!CExpr_ImplicitConversionMatch(argexprs->node, args->type, args->qual, convs)) + return 0; + + argexprs = argexprs->next; + args = args->next; + convs++; + } +} + +static Object *CExpr_GetMatchObject(Match *match, HashNameNode *name) { + Object *object; + FuncArg *arg; + TypeFunc *tfunc; + + if (match->object) + return match->object; + + tfunc = lalloc(sizeof(TypeFunc)); + memclrw(tfunc, sizeof(TypeFunc)); + tfunc->type = TYPEFUNC; + tfunc->functype = &stvoid; + + arg = lalloc(sizeof(FuncArg)); + memclrw(arg, sizeof(FuncArg)); + arg->type = match->type; + arg->qual = match->qual; + tfunc->args = arg; + + if (match->type2) { + arg = lalloc(sizeof(FuncArg)); + memclrw(arg, sizeof(FuncArg)); + arg->type = match->type2; + arg->qual = match->qual2; + tfunc->args->next = arg; + } + + object = lalloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + object->name = name; + object->datatype = DFUNC; + object->nspace = cscope_root; + object->type = TYPE(tfunc); + return object; +} + +static Match *CExpr_FindBestMatch(Match *matches, int count, HashNameNode *name, ObjectList **outList, ENodeList *argExprs) { + Match *scan; + Match *best; + ObjectList *listHead; + ObjectList *list; + + best = matches; + for (scan = matches->next; scan; scan = scan->next) { + if (CExpr_IsBetterMatch(scan, best, count)) + best = scan; + } + + for (scan = matches, listHead = NULL; scan; scan = scan->next) { + if (scan != best && !CExpr_IsBetterMatch(best, scan, count)) { + list = lalloc(sizeof(ObjectList)); + list->next = listHead; + list->object = CExpr_GetMatchObject(scan, name); + listHead = list; + } + } + + if (!outList) { + if (listHead) + CError_OverloadedFunctionError(CExpr_GetMatchObject(best, name), listHead); + } else { + *outList = listHead; + } + + return best; +} + +void CExpr_FuncArgMatch(NameSpaceObjectList *list, TemplArg *templargs, ENodeList *argexprs, Match13 *match13, ENode *expr, Boolean flag) { + NameSpaceObjectList *i; + NameSpaceObjectList *j; + Match *match; + Match *matches; + Object *object; + Object *object2; + Object *specialfunc; + ENodeList *argscan; + int argcount; + + for (argscan = argexprs, argcount = 0; argscan; argscan = argscan->next) { + CDecl_CompleteType(argscan->node->rtype); + argcount++; + } + + matches = NULL; + match = lalloc(sizeof(Match) + ((argcount - 2) * sizeof(ImplicitConv))); + + for (i = list; i; i = i->next) { + object = OBJECT(i->object); + if ( + object->otype == OT_OBJECT && + IS_TYPE_FUNC(object->type) && + (!flag || !(object->qual & Q_EXPLICIT)) + ) + { + if (object->datatype == DALIAS && (TYPE_FUNC(object->type)->flags & FUNC_METHOD)) { + for (j = list; j; j = j->next) { + if (j == i) + continue; + + object2 = OBJECT(j->object); + if ( + object2->otype == OT_OBJECT && + IS_TYPE_METHOD(object2->type) && + (TYPE_FUNC(object2->type)->flags & FUNC_FLAGS_CV) == (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_CV) + ) + { + FuncArg *argsA; + FuncArg *argsB; + argsA = TYPE_FUNC(object->type)->args; + if (argsA && !TYPE_METHOD(object->type)->is_static) + argsA = argsA->next; + argsB = TYPE_FUNC(object2->type)->args; + if (argsB && !TYPE_METHOD(object2->type)->is_static) + argsB = argsB->next; + if (is_arglistsame(argsA, argsB)) + break; + } + } + + if (j) + continue; + } + + if (TYPE_FUNC(object->type)->flags & FUNC_IS_TEMPL) { + specialfunc = object; + object = CTempl_DeduceFromFunctionCall(object, templargs, argexprs); + if (!object) + continue; + } else { + if (templargs) + continue; + specialfunc = NULL; + } + + if (CExpr_MatchArgs(object, argexprs, expr, match->conv)) { + match->object = object; + match->specialfunc = specialfunc; + match->next = matches; + matches = match; + match = lalloc(sizeof(Match) + ((argcount - 2) * sizeof(ImplicitConv))); + } + } + } + + if (matches) { + matches = CExpr_FindBestMatch(matches, argcount, NULL, &match13->list, argexprs); + match13->obj = matches->object; + } +} + +static ConversionTypeList *CExpr_BuildConversionTypeList(ENode *expr) { + ConversionTypeList *first; + ConversionTypeList *list; + Object *object; + Type *type; + ConversionIterator convIter; + + if (!IS_TYPE_CLASS(expr->rtype)) { + first = lalloc(sizeof(ConversionTypeList)); + first->next = NULL; + first->func = NULL; + first->type = expr->rtype; + first->qual = ENODE_QUALS(expr); + if (IS_TYPE_ENUM(first->type)) + first->qual = 0; + } else { + first = NULL; + CExpr_ConversionIteratorInit(&convIter, TYPE_CLASS(expr->rtype)); + while ((object = CExpr_ConversionIteratorNext(&convIter))) { + type = TYPE_FUNC(object->type)->functype; + if (IS_TYPE_REFERENCE(type)) + type = TPTR_TARGET(type); + + if (!IS_TYPE_CLASS(type)) { + list = lalloc(sizeof(ConversionTypeList)); + list->next = first; + list->func = object; + list->type = type; + list->qual = TYPE_FUNC(object->type)->qual & Q_CV; + first = list; + } + } + } + + return first; +} + +static Type *CExpr_NextPromotedIntegralType(int *p) { + switch (++(*p)) { + case 1: return TYPE(&stsignedint); + case 2: return TYPE(&stunsignedint); + case 3: return TYPE(&stsignedlong); + case 4: return TYPE(&stunsignedlong); + case 5: + if (copts.longlong) + return TYPE(&stsignedlonglong); + else + return NULL; + case 6: + if (copts.longlong) + return TYPE(&stunsignedlonglong); + else + return NULL; + } + + return NULL; +} + +static Type *CExpr_NextArithmeticType(int *p) { + switch (++(*p)) { + case 1: return TYPE(&stbool); + case 2: return TYPE(&stchar); + case 3: return TYPE(&stsignedchar); + case 4: return TYPE(&stunsignedchar); + case 5: return TYPE(&stwchar); + case 6: return TYPE(&stsignedshort); + case 7: return TYPE(&stunsignedshort); + case 8: return TYPE(&stsignedint); + case 9: return TYPE(&stunsignedint); + case 10: return TYPE(&stsignedlong); + case 11: return TYPE(&stunsignedlong); + case 12: return TYPE(&stfloat); + case 13: return TYPE(&stdouble); + case 14: return TYPE(&stlongdouble); + case 15: + if (copts.longlong) + return TYPE(&stsignedlonglong); + else + return NULL; + case 16: + if (copts.longlong) + return TYPE(&stunsignedlonglong); + else + return NULL; + } + + return NULL; +} + +static Type *CExpr_NextPromotedArithmeticType(int *p) { + switch (++(*p)) { + case 1: return TYPE(&stsignedint); + case 2: return TYPE(&stunsignedint); + case 3: return TYPE(&stsignedlong); + case 4: return TYPE(&stunsignedlong); + case 5: return TYPE(&stdouble); + case 6: return TYPE(&stlongdouble); + case 7: + if (copts.longlong) + return TYPE(&stsignedlonglong); + else + return NULL; + case 8: + if (copts.longlong) + return TYPE(&stunsignedlonglong); + else + return NULL; + } + + return NULL; +} + +static Match *CExpr_MatchBuiltin(Match *matches, ENode *left, Type *leftType, UInt32 leftQual, ENode *right, Type *rightType, UInt32 rightQual) { + Match *scan; + Match mymatch; + + if (CExpr_ImplicitConversionMatch(left, leftType, leftQual, &mymatch.conv[0])) { + if (!right || CExpr_ImplicitConversionMatch(right, rightType, rightQual, &mymatch.conv[1])) { + if (right) { + for (scan = matches; scan; scan = scan->next) { + if ( + !scan->object && + is_typesame(scan->type, leftType) && + scan->qual == leftQual && + is_typesame(scan->type2, rightType) && + scan->qual2 == rightQual + ) + return matches; + } + } + + mymatch.next = matches; + mymatch.object = NULL; + mymatch.specialfunc = NULL; + mymatch.type = leftType; + mymatch.qual = leftQual; + mymatch.type2 = rightType; + mymatch.qual2 = rightQual; + + matches = lalloc(sizeof(Match)); + *matches = mymatch; + } + } + + return matches; +} + +static Match *CExpr_CheckIncDecBuiltin(Match *matches, short token, ENode *expr1, ENode *expr2) { + Object *object; + Type *type; + TypeFunc *tfunc; + ConversionIterator convIter; + + if (IS_TYPE_CLASS(expr1->rtype)) { + CExpr_ConversionIteratorInit(&convIter, TYPE_CLASS(expr1->rtype)); + while ((object = CExpr_ConversionIteratorNext(&convIter))) { + tfunc = TYPE_FUNC(object->type); + if (IS_TYPE_REFERENCE(tfunc->functype)) { + type = TPTR_TARGET(tfunc->functype); + switch (type->type) { + case TYPEINT: + if (type == TYPE(&stbool) && token == TK_DECREMENT) + break; + case TYPEFLOAT: + case TYPEPOINTER: + if (!CParser_IsConst(type, tfunc->qual)) { + matches = CExpr_MatchBuiltin( + matches, + expr1, type, tfunc->qual, + expr2, expr2 ? TYPE(&stsignedint) : NULL, 0 + ); + } + break; + } + } + } + } + + return matches; +} + +static Match *CExpr_CheckUnaryBuiltin(Match *matches, short token, ENode *expr) { + ConversionTypeList *typelist; + Type *type; + int typenum; + + switch (token) { + case TK_INCREMENT: + case TK_DECREMENT: + return CExpr_CheckIncDecBuiltin(matches, token, expr, NULL); + + case '!': + matches = CExpr_MatchBuiltin(matches, expr, TYPE(&stbool), 0, NULL, NULL, 0); + break; + + case '~': + typenum = 0; + while ((type = CExpr_NextPromotedIntegralType(&typenum))) { + matches = CExpr_MatchBuiltin(matches, expr, type, 0, NULL, NULL, 0); + } + break; + + case '*': + case '+': + for (typelist = CExpr_BuildConversionTypeList(expr); typelist; typelist = typelist->next) { + if (IS_TYPE_POINTER_ONLY(typelist->type)) + matches = CExpr_MatchBuiltin(matches, expr, typelist->type, typelist->qual, NULL, NULL, 0); + } + if (token != '+') + break; + + case '-': + typenum = 0; + while ((type = CExpr_NextPromotedArithmeticType(&typenum))) { + matches = CExpr_MatchBuiltin(matches, expr, type, 0, NULL, NULL, 0); + } + break; + } + + return matches; +} + +static Match *CExpr_CheckBinaryBuiltin(Match *matches, ENode *left, short token, ENode *right) { + int typenum1; + int typenum2; + Type *type1; + Type *type2; + Type *ptrdiff; + Boolean allowPtrDiffOnRight; + Boolean allowPtrCV; + Boolean allowPtrDiffOnLeft; + Boolean allowMemberPtrs; + Boolean allowEnum; + ConversionTypeList *leftList; + ConversionTypeList *rightList; + ConversionTypeList *scan; + + switch (token) { + case TK_INCREMENT: + case TK_DECREMENT: + return CExpr_CheckIncDecBuiltin(matches, token, left, right); + + case '*': + case '+': + case '-': + case '/': + case ':': + case '<': + case '>': + case TK_LOGICAL_EQ: + case TK_LOGICAL_NE: + case TK_LESS_EQUAL: + case TK_GREATER_EQUAL: + typenum1 = 0; + while ((type1 = CExpr_NextPromotedArithmeticType(&typenum1))) { + typenum2 = 0; + while ((type2 = CExpr_NextPromotedArithmeticType(&typenum2))) { + matches = CExpr_MatchBuiltin(matches, left, type1, 0, right, type2, 0); + } + } + break; + + case '%': + case '&': + case '^': + case '|': + case TK_SHL: + case TK_SHR: + typenum1 = 0; + while ((type1 = CExpr_NextPromotedIntegralType(&typenum1))) { + typenum2 = 0; + while ((type2 = CExpr_NextPromotedIntegralType(&typenum2))) { + matches = CExpr_MatchBuiltin(matches, left, type1, 0, right, type2, 0); + } + } + return matches; + + case TK_LOGICAL_OR: + case TK_LOGICAL_AND: + return CExpr_MatchBuiltin(matches, left, TYPE(&stbool), 0, right, TYPE(&stbool), 0); + } + + allowEnum = 0; + allowMemberPtrs = 0; + allowPtrCV = 0; + allowPtrDiffOnLeft = 0; + allowPtrDiffOnRight = 0; + + switch (token) { + case '+': + case '[': + allowPtrDiffOnLeft = 1; + allowPtrDiffOnRight = 1; + break; + case '-': + allowPtrCV = 1; + allowPtrDiffOnRight = 1; + break; + case ':': + case TK_LOGICAL_EQ: + case TK_LOGICAL_NE: + allowMemberPtrs = 1; + case '<': + case '>': + case TK_LESS_EQUAL: + case TK_GREATER_EQUAL: + allowPtrCV = 1; + allowEnum = 1; + break; + default: + return matches; + } + + leftList = CExpr_BuildConversionTypeList(left); + rightList = CExpr_BuildConversionTypeList(right); + ptrdiff = CABI_GetPtrDiffTType(); + + for (scan = leftList; ; scan = scan->next) { + if (!scan) { + scan = rightList; + if (!rightList) + break; + rightList = NULL; + } + + type1 = scan->type; + if (IS_TYPE_REFERENCE(type1)) + type1 = TPTR_TARGET(type1); + + switch (type1->type) { + case TYPEENUM: + if (allowEnum) + matches = CExpr_MatchBuiltin(matches, left, type1, scan->qual, right, type1, scan->qual); + break; + + case TYPEPOINTER: + if (allowPtrDiffOnRight) + matches = CExpr_MatchBuiltin(matches, left, type1, scan->qual, right, ptrdiff, 0); + if (allowPtrDiffOnLeft) + matches = CExpr_MatchBuiltin(matches, left, ptrdiff, 0, right, type1, scan->qual); + if (allowPtrCV) { + if (IS_TYPE_POINTER_ONLY(TPTR_TARGET(type1))) { + type2 = galloc(sizeof(TypePointer)); + *TYPE_POINTER(type2) = *TYPE_POINTER(type1); + TPTR_QUAL(type2) |= Q_CONST | Q_VOLATILE; + matches = CExpr_MatchBuiltin(matches, left, type2, scan->qual, right, type2, scan->qual); + } else { + matches = CExpr_MatchBuiltin(matches, left, type1, Q_CONST | Q_VOLATILE, right, type1, Q_CONST | Q_VOLATILE); + } + } + break; + + case TYPEMEMBERPOINTER: + if (allowMemberPtrs) + matches = CExpr_MatchBuiltin(matches, left, type1, scan->qual, right, type1, scan->qual); + break; + } + } + + return matches; +} + +static Boolean CExpr_MatchOperands(ENode *left, Type *leftType, UInt32 leftQual, ENode *right, Type *rightType, UInt32 rightQual, ImplicitConv *twoResults, Boolean flag) { + if (flag) { + if (!CExpr_StandardConversionMatch(left, leftType, leftQual, 1, &twoResults[0].u.ic3.standardConv)) + return 0; + twoResults[0].type = ICT_3; + } else { + if (!CExpr_ImplicitConversionMatch(left, leftType, leftQual, &twoResults[0])) + return 0; + } + + if (right) { + if (!CExpr_ImplicitConversionMatch(right, rightType, rightQual, &twoResults[1])) + return 0; + } + + return 1; +} + +Boolean CExpr_CondOperatorMatch(ENode *left, ENode *right, Conversion *conv) { + Match *match; + + if ((match = CExpr_CheckBinaryBuiltin(NULL, left, ':', right))) { + match = CExpr_FindBestMatch(match, 1, GetHashNameNode("operator?:"), NULL, NULL); + CError_ASSERT(2931, !match->object); + + conv->x0 = NULL; + conv->left = CExpr_Convert(left, match->type, match->qual, 0, 1); + conv->right = CExpr_Convert(right, match->type2, match->qual2, 0, 1); + return 1; + } + + return 0; +} + +Boolean CExpr_OperatorMatch(short token, ENode *left, ENode *right, Conversion *conv) { + HashNameNode *name; + ENodeList *argExprs; + BClassList *path; + int hasArg; + Match *matches; + Object *object; + Object *specialfunc; + NameSpaceObjectList *list; + Type *leftType; + UInt32 leftQual; + Type *rightType; + UInt32 rightQual; + NameResult pr; + NameSpaceObjectList myList; + Match myMatch; + + if (!IS_TYPE_CLASS(left->rtype)) { + if (!IS_TYPE_ENUM(left->rtype)) { + if (!right || !(IS_TYPE_CLASS(right->rtype) || IS_TYPE_ENUM(right->rtype))) + return 0; + } + } else { + CDecl_CompleteType(left->rtype); + } + + name = CMangler_OperatorName(token); + path = NULL; + + argExprs = lalloc(sizeof(ENodeList)); + argExprs->node = left; + if (right) { + argExprs->next = lalloc(sizeof(ENodeList)); + argExprs->next->node = right; + argExprs->next->next = NULL; + hasArg = 1; + } else { + argExprs->next = NULL; + hasArg = 0; + } + + matches = NULL; + + if (IS_TYPE_CLASS(left->rtype) && CScope_FindClassMemberObject(TYPE_CLASS(left->rtype), &pr, name)) { + if (token != '=' || (pr.bcl_18->type == left->rtype && !pr.bcl_18->next)) { + if (pr.obj_10) { + myList.next = NULL; + myList.object = pr.obj_10; + pr.nsol_14 = &myList; + } else { + CError_ASSERT(3009, pr.nsol_14); + } + + for (list = pr.nsol_14; list; list = list->next) { + object = OBJECT(list->object); + if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type)) { + if (TYPE_FUNC(object->type)->flags & FUNC_IS_TEMPL) { + specialfunc = object; + object = CTempl_DeduceFromFunctionCall(object, NULL, argExprs->next); + if (!object) + continue; + } else { + specialfunc = NULL; + } + + leftType = CExpr_GetImplictObjectParamType(object, &leftQual); + if (right) { + if (!CExpr_HasNParams(object, 1)) + continue; + rightType = CExpr_GetParamType(object, 0, &rightQual); + } else { + if (!CExpr_HasNParams(object, 0)) + continue; + } + + if (CExpr_MatchOperands(left, leftType, leftQual, right, rightType, rightQual, myMatch.conv, 1)) { + myMatch.object = object; + myMatch.specialfunc = specialfunc; + myMatch.next = matches; + matches = lalloc(sizeof(Match)); + *matches = myMatch; + path = pr.bcl_18; + } + } + } + } + } + + if (CScope_FindNonClassObject(cscope_current, &pr, name)) { + if (pr.obj_10) { + myList.next = NULL; + myList.object = pr.obj_10; + pr.nsol_14 = &myList; + } + } else { + pr.nsol_14 = NULL; + } + + if (copts.arg_dep_lookup) + pr.nsol_14 = CScope_ArgumentDependentNameLookup(pr.nsol_14, name, argExprs, 1); + + for (list = pr.nsol_14; list; list = list->next) { + object = OBJECT(list->object); + if (object->otype == OT_OBJECT && IS_TYPE_NONMETHOD(object->type)) { + if (TYPE_FUNC(object->type)->flags & FUNC_IS_TEMPL) { + specialfunc = object; + object = CTempl_DeduceFromFunctionCall(object, NULL, argExprs); + if (!object) + continue; + } else { + specialfunc = NULL; + } + + leftType = CExpr_GetParamType(object, 0, &leftQual); + if (right) { + if (!CExpr_HasNParams(object, 2)) + continue; + rightType = CExpr_GetParamType(object, 1, &rightQual); + } else { + if (!CExpr_HasNParams(object, 1)) + continue; + } + + if (CExpr_MatchOperands(left, leftType, leftQual, right, rightType, rightQual, myMatch.conv, 0)) { + myMatch.object = object; + myMatch.specialfunc = specialfunc; + myMatch.next = matches; + matches = lalloc(sizeof(Match)); + *matches = myMatch; + } + } + } + + if (right) + matches = CExpr_CheckBinaryBuiltin(matches, left, token, right); + else + matches = CExpr_CheckUnaryBuiltin(matches, token, left); + + if (matches) { + conv->x0 = NULL; + conv->left = NULL; + conv->right = NULL; + + matches = CExpr_FindBestMatch(matches, hasArg, name, NULL, argExprs); + object = matches->object; + if (!object) { + if (IS_TYPE_CLASS(left->rtype)) + conv->left = CExpr_Convert(left, matches->type, matches->qual, 0, 1); + else + conv->left = left; + + if (right) { + if (IS_TYPE_CLASS(right->rtype)) + conv->right = CExpr_Convert(right, matches->type2, matches->qual2, 0, 1); + else + conv->right = right; + } + + return 1; + } + + if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(object->type))) { + CError_ASSERT(3125, path); + left = CExpr_GenericFuncCall(path, argExprs->node, 0, object, NULL, NULL, argExprs->next, 0, 0, 1); + } else { + left = CExpr_GenericFuncCall(NULL, NULL, 0, object, NULL, NULL, argExprs, 0, 0, 1); + } + + conv->x0 = checkreference(left); + return 1; + } + + return 0; +} + +static ENode *CExpr_ClassCopyInit(TypeClass *tclass, ENode *expr1, ENode *expr2) { + Object *best; + NameSpaceObjectList *list; + ObjectList *objlist; + ObjectList *objlistEntry; + ENodeList *argExprs; + FuncArg *arg; + Type *type; + Object *object; + ImplicitConv bestConv; + ImplicitConv conv; + BClassList path; + ConversionIterator convIter; + + best = NULL; + objlist = NULL; + + for (list = CClass_Constructor(tclass); list; list = list->next) { + object = OBJECT(list->object); + if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type) && !(object->qual & Q_EXPLICIT)) { + arg = TYPE_FUNC(object->type)->args; + + CError_ASSERT(3199, arg); + arg = arg->next; + + if (tclass->flags & CLASS_HAS_VBASES) { + CError_ASSERT(3203, arg); + arg = arg->next; + } + + if ( + arg && + arg != &elipsis && + (!arg->next || arg->next->dexpr) && + CExpr_ImplicitConversionMatch(expr2, arg->type, arg->qual, &conv) + ) + { + if (!best || CExpr_IsBetterImplicitConv(&conv, &bestConv)) { + best = object; + bestConv = conv; + objlist = NULL; + } else if (!CExpr_IsBetterImplicitConv(&bestConv, &conv)) { + objlistEntry = lalloc(sizeof(ObjectList)); + objlistEntry->next = objlist; + objlistEntry->object = object; + objlist = objlistEntry; + } + } + } + } + + if (IS_TYPE_CLASS(expr2->rtype)) { + CExpr_ConversionIteratorInit(&convIter, TYPE_CLASS(expr2->rtype)); + while ((object = CExpr_ConversionIteratorNext(&convIter))) { + type = TYPE_FUNC(object->type)->functype; + if (IS_TYPE_REFERENCE(type)) + type = TPTR_TARGET(type); + + if ( + IS_TYPE_CLASS(type) && + (tclass == TYPE_CLASS(type) || CClass_IsBaseClass(tclass, TYPE_CLASS(type), NULL, 0, 0)) + ) + { + CError_ASSERT(3248, TYPE_FUNC(object->type)->args && + IS_TYPE_POINTER_ONLY(TYPE_FUNC(object->type)->args->type)); + + type = galloc(sizeof(TypePointer)); + *TYPE_POINTER(type) = *TYPE_POINTER(TYPE_FUNC(object->type)->args->type); + TPTR_QUAL(type) = Q_REFERENCE; + if (CExpr_ImplicitConversionMatch(expr2, type, TYPE_FUNC(object->type)->args->qual, &conv)) { + if (!best || CExpr_IsBetterImplicitConv(&conv, &bestConv)) { + best = object; + bestConv = conv; + objlist = NULL; + } else if (!CExpr_IsBetterImplicitConv(&bestConv, &conv)) { + objlistEntry = lalloc(sizeof(ObjectList)); + objlistEntry->next = objlist; + objlistEntry->object = object; + objlist = objlistEntry; + } + } + } + } + } + + if (objlist) + CError_OverloadedFunctionError(best, objlist); + + if (!best) { + CError_Error(CErrorStr209, expr2->rtype, ENODE_QUALS(expr2), tclass, 0); + return expr1; + } + + CError_ASSERT(3284, IS_TYPE_POINTER_ONLY(expr1->rtype)); + + expr1 = makemonadicnode(expr1, EINDIRECT); + expr1->rtype = TYPE(tclass); + + argExprs = lalloc(sizeof(ENodeList)); + argExprs->node = expr2; + if (tclass->flags & CLASS_HAS_VBASES) { + argExprs->next = lalloc(sizeof(ENodeList)); + argExprs->next->next = NULL; + argExprs->next->node = intconstnode(TYPE(&stsignedshort), 1); + } else { + argExprs->next = NULL; + } + + path.next = NULL; + path.type = TYPE(tclass); + expr1 = CExpr_GenericFuncCall(&path, expr1, 0, best, NULL, NULL, argExprs, 0, 0, 1); + + if (ENODE_IS2(expr1, EFUNCCALL, EFUNCCALLP)) + expr1->rtype = CDecl_NewPointerType(TYPE(tclass)); + + expr1 = makemonadicnode(expr1, EINDIRECT); + expr1->rtype = TYPE(tclass); + return expr1; +} diff --git a/compiler_and_linker/FrontEnd/C/CFunc.c b/compiler_and_linker/FrontEnd/C/CFunc.c new file mode 100644 index 0000000..38cfab3 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CFunc.c @@ -0,0 +1,3224 @@ +#include "compiler/CFunc.h" +#include "compiler/CABI.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CException.h" +#include "compiler/CExpr.h" +#include "compiler/CInit.h" +#include "compiler/CInline.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CSOM.h" +#include "compiler/CTemplateTools.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/Exceptions.h" +#include "compiler/FuncLevelAsmPPC.h" +#include "compiler/InlineAsmPPC.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/Switch.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/types.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +struct CFuncSave { + CScopeSave scope; + ObjectList *arguments; + ObjectList *locals; + CLabel *labels; + Statement *curstmt; + DeclBlock *firstblock; + DeclBlock *currentblock; + ExceptionAction *cexcept_dobjstack; + CLabel *sinit_label; + ENode *ainit_expr; + CtorChain *ctor_chain; + ParserTryBlock *trychain; + TempNodeCB cinit_tempnodefunc; + HashNameNode *tkidentifier; + Object *sinit_first_object; + FileOffsetInfo cparser_fileoffset; + TStreamElement symdecltoken; + SInt32 functionbodyoffset; + HashNameNode *functionbodypath; + SInt32 symdecloffset; + SInt32 symdeclend; + SInt32 sourceoffset; + HashNameNode *sourcefilepath; + SInt32 curstmtvalue; + NameObjCheckCB name_obj_check; + FuncArg *check_arglist; + short blockcount; + short localcount; + short tk; + AccessType global_access; + Boolean cexcept_hasdobjects; + Boolean ainit_only_one; + Boolean cfunc_is_extern_c; + Boolean temp_reference_init; +}; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +FuncArg elipsis; +FuncArg oldstyle; +ObjectList *arguments; +ObjectList *locals; +short localcount; +SInt32 curstmtvalue; +SInt32 sourceoffset; +HashNameNode *sourcefilepath; +SInt32 functionbodyoffset; +HashNameNode *functionbodypath; +InitExpr *init_expressions; +CLabel *Labels; +CtorChain *ctor_chain; +Statement *curstmt; +static short temp_destructor_object_regmem; +static short temp_destructor_objects; +static short temp_expression_has_conditionals; +static DeclBlock *firstblock; +static DeclBlock *currentblock; +static short blockcount; +static Object *sinit_first_object; +static CLabel *sinit_label; +static Boolean ainit_only_one; +static ENode *ainit_expr; +static FuncArg *check_arglist; +static Boolean cfunc_is_extern_c; +static short cfunc_staticvarcount; +static void *destroyobjects; +static Boolean cfunc_hasdtortemp; + +// forward decls +static void statement(DeclThing *thing); + +static void CFunc_LoopIncrement(void) { + if (curstmtvalue >= 0x1000) { + if (curstmtvalue >= 0xF000) + curstmtvalue++; + else + curstmtvalue += 0x1000; + } else { + curstmtvalue <<= 3; + } +} + +static void CFunc_LoopDecrement(void) { + if (curstmtvalue > 0x1000) { + if (curstmtvalue > 0xF000) + curstmtvalue--; + else + curstmtvalue -= 0x1000; + } else { + curstmtvalue >>= 3; + } + + if (curstmtvalue < 1) + curstmtvalue = 1; +} + +DeclBlock *CFunc_NewDeclBlock(void) { + DeclBlock *block; + NameSpace *nspace; + + block = lalloc(sizeof(DeclBlock)); + if (firstblock) { + currentblock->next = block; + currentblock = block; + } else { + firstblock = block; + currentblock = block; + } + + block->index = blockcount++; + block->parent_nspace = cscope_current; + block->dobjstack = cexcept_dobjstack; + + nspace = CScope_NewListNameSpace(NULL, 0); + nspace->parent = cscope_current; + cscope_current = nspace; + + return block; +} + +void CFunc_RestoreBlock(DeclBlock *block) { + if (curstmt && curstmt->dobjstack != cexcept_dobjstack) { + Statement *stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = nullnode(); + } + + cscope_current = block->parent_nspace; + cexcept_dobjstack = block->dobjstack; +} + +void CFunc_SetupLocalVarInfo(Object *obj) { + obj->u.var.info = CodeGen_GetNewVarInfo(); + obj->u.var.info->func = cscope_currentfunc; + + if (obj->sclass == TK_REGISTER) { + if (!copts.optimizesize) + obj->u.var.info->usage = 100; + else + obj->u.var.info->usage = 5; + } + + if (obj->type && is_volatile_object(obj)) + obj->u.var.info->noregister = 1; +} + +static void adjustargumenttype(DeclInfo *declinfo) { + switch (declinfo->thetype->type) { + case TYPECLASS: + if (TYPE_CLASS(declinfo->thetype)->sominfo) { + CError_Error(CErrorStr284); + declinfo->thetype = TYPE(&stsignedint); + } + break; + case TYPEFUNC: + makethetypepointer(declinfo, 0); + return; + case TYPEARRAY: + declinfo->thetype = CDecl_NewPointerType(TPTR_TARGET(declinfo->thetype)); + return; + case TYPETEMPLATE: + if (TYPE_TEMPLATE(declinfo->thetype)->dtype == TEMPLDEP_ARRAY) + declinfo->thetype = CDecl_NewPointerType(TYPE_TEMPLATE(declinfo->thetype)->u.array.type); + return; + } + + if (!CanCreateObject(declinfo->thetype)) + declinfo->thetype = TYPE(&stsignedint); +} + +static FuncArg *CFunc_IsInArgList(FuncArg *list, HashNameNode *name) { + while (list) { + if (name == list->name) + return list; + list = list->next; + } + + return NULL; +} + +static Object *CFunc_IsInObjList(ObjectList *list, HashNameNode *name) { + while (list) { + if (name == list->object->name) + return list->object; + list = list->next; + } + + return NULL; +} + +static void CFunc_AppendArg(FuncArg **list, FuncArg *arg) { + FuncArg *tail; + + if ((tail = *list)) { + while (tail->next) + tail = tail->next; + tail->next = arg; + } else { + *list = arg; + } +} + +static void identifier_list(DeclInfo *declinfo) { + FuncArg *arg; + + declinfo->x45 = 1; + + while (1) { + if (tk != TK_IDENTIFIER) { + CError_Error(CErrorStr121); + } else { + if (CFunc_IsInArgList(declinfo->x18, tkidentifier)) + CError_Error(CErrorStr122, tkidentifier->name); + + arg = CParser_NewFuncArg(); + arg->name = tkidentifier; + CFunc_AppendArg(&declinfo->x18, arg); + declinfo->x44 = 1; + } + + if ((tk = lex()) != ',') + break; + tk = lex(); + } +} + +static Boolean defarg_name_obj_check(HashNameNode *name, Object *obj) { + FuncArg *arg; + + if (name) { + for (arg = check_arglist; arg; arg = arg->next) { + if (arg->name == name) { + CError_Error(CErrorStr205); + return 0; + } + } + } + + if (obj && obj->datatype == DLOCAL) { + CError_Error(CErrorStr205); + return 0; + } + + return 1; +} + +ENode *CFunc_DefaultArg(Type *type, UInt32 qual, FuncArg *args) { + TStreamElement *element; + ENode *expr; + ENode *templdepexpr; + + name_obj_check = defarg_name_obj_check; + check_arglist = args; + expr = conv_assignment_expression(); + name_obj_check = NULL; + + if ( + !CTemplTool_IsTemplateArgumentDependentExpression(expr) && + !CTemplTool_IsTemplateArgumentDependentType(type) + ) + { + expr = argumentpromotion(expr, type, qual, 1); + } else { + element = CPrep_CurStreamElement(); + if (element && element->tokenfile) { + templdepexpr = CExpr_NewTemplDepENode(TDE_SOURCEREF); + templdepexpr->data.templdep.u.sourceref.expr = expr; + templdepexpr->data.templdep.u.sourceref.token = galloc(sizeof(TStreamElement)); + *templdepexpr->data.templdep.u.sourceref.token = *element; + expr = templdepexpr; + } + } + + return CInline_CopyExpression(expr, CopyMode1); +} + +static FuncArg *parameter_list(DeclInfo *declinfo) { + Boolean flag26; + FuncArg *args; + FuncArg *arg; + DeclInfo my_di; + Boolean isArray; + + args = NULL; + flag26 = 1; + + while (1) { + if (tk == TK_ELLIPSIS) { + if (flag26) { + if (!copts.cplusplus && copts.ANSIstrict) + CError_Warning(CErrorStr127); + args = &elipsis; + } else { + CFunc_AppendArg(&args, &elipsis); + } + + tk = lex(); + return args; + } + + memclrw(&my_di, sizeof(my_di)); + CParser_GetDeclSpecs(&my_di, 0); + if (my_di.x48) + CError_Error(CErrorStr127); + + if ( + my_di.storageclass && + my_di.storageclass != TK_REGISTER && + (!copts.cplusplus || my_di.storageclass != TK_AUTO) + ) + { + CError_Error(CErrorStr127); + my_di.storageclass = 0; + } + + my_di.name = NULL; + + scandeclarator(&my_di); + + if (flag26) { + flag26 = 0; + if (my_di.thetype == &stvoid) { + if (my_di.storageclass || my_di.qual || my_di.name) + CError_Error(CErrorStr127); + return NULL; + } + } + + isArray = IS_TYPE_ARRAY(my_di.thetype); + adjustargumenttype(&my_di); + + if (my_di.name) { + if (args && CFunc_IsInArgList(args, my_di.name)) + CError_Error(CErrorStr122, my_di.name->name); + } else { + my_di.name = no_name_node; + } + + if (my_di.thetype == &stvoid) + CError_Error(CErrorStr126); + + arg = CParser_NewFuncArg(); + arg->name = my_di.name; + arg->type = my_di.thetype; + arg->qual = my_di.qual; + arg->sclass = my_di.storageclass; + arg->is_array = isArray; + CFunc_AppendArg(&args, arg); + + if (copts.cplusplus && tk == '=') { + tk = lex(); + arg->dexpr = CFunc_DefaultArg(arg->type, arg->qual, args); + } + + if (tk != ',') { + if (tk != TK_ELLIPSIS || !copts.cplusplus) + return args; + } else { + tk = lex(); + } + } +} + +Boolean CFunc_ParseFakeArgList(Boolean flag) { + DeclInfo di; + + if (tk == TK_ELLIPSIS) + return 1; + + do { + memclrw(&di, sizeof(di)); + CParser_GetDeclSpecs(&di, 0); + + if (di.x48) + return 0; + + scandeclarator(&di); + + if (tk == '=') { + tk = lex(); + assignment_expression(); + } + + switch (tk) { + case TK_ELLIPSIS: + return 1; + case ',': + if (!flag) + tk = lex(); + else + return 1; + break; + default: + return 0; + } + } while (tk != TK_ELLIPSIS); + + return 1; +} + +FuncArg *parameter_type_list(DeclInfo *declinfo) { + FuncArg *args; + NameSpace *nspace; + Boolean save_in_func_arglist; + + declinfo->x44 = 0; + declinfo->x45 = 0; + declinfo->x1C = NULL; + + if (tk == TK_ELLIPSIS || isdeclaration(0, 0, 0, 0)) { + if (!copts.cplusplus) { + nspace = CScope_NewListNameSpace(NULL, 0); + nspace->parent = cscope_current; + cscope_current = nspace; + + save_in_func_arglist = in_func_arglist; + in_func_arglist = 1; + args = parameter_list(declinfo); + in_func_arglist = save_in_func_arglist; + + cscope_current = nspace->parent; + + if (!CScope_IsEmptyNameSpace(nspace)) + declinfo->x1C = nspace; + } else { + args = parameter_list(declinfo); + } + } else if (copts.cplusplus) { + args = NULL; + if (tk != ')') + CError_Error(CErrorStr127); + } else { + identifier_list(declinfo); + args = &oldstyle; + } + + return args; +} + +CLabel *findlabel(void) { + CLabel *scan; + + for (scan = Labels; scan; scan = scan->next) { + if (tkidentifier == scan->name) + return scan; + } + + return NULL; +} + +CLabel *newlabel(void) { + CLabel *label = lalloc(sizeof(CLabel)); + memclrw(label, sizeof(CLabel)); + + label->name = label->uniquename = CParser_GetUniqueName(); + return label; +} + +Statement *CFunc_AppendStatement(StatementType sttype) { + Statement *stmt = lalloc(sizeof(Statement)); + + stmt->next = NULL; + stmt->type = sttype; + stmt->value = curstmtvalue; + stmt->flags = 0; + stmt->sourceoffset = sourceoffset; + stmt->sourcefilepath = sourcefilepath; + stmt->dobjstack = cexcept_dobjstack; + + curstmt->next = stmt; + curstmt = stmt; + return stmt; +} + +Statement *CFunc_InsertStatement(StatementType sttype, Statement *after) { + Statement *stmt = lalloc(sizeof(Statement)); + + stmt->next = after->next; + after->next = stmt; + stmt->type = sttype; + stmt->value = after->value; + stmt->flags = 0; + stmt->sourceoffset = after->sourceoffset; + stmt->sourcefilepath = after->sourcefilepath; + stmt->dobjstack = after->dobjstack; + + return stmt; +} + +Statement *CFunc_InsertBeforeStatement(StatementType sttype, Statement *before) { + Statement *stmt = lalloc(sizeof(Statement)); + + *stmt = *before; + before->next = stmt; + before->type = sttype; + before->flags = 0; + + return before; +} + +void CheckCLabels(void) { + CLabel *scan; + + for (scan = Labels; scan; scan = scan->next) { + if (!scan->stmt) + CError_Error(CErrorStr159, scan->name->name); + } +} + +Object *create_temp_object(Type *type) { + Object *object = CParser_NewLocalDataObject(NULL, 1); + object->name = CParser_GetUniqueName(); + object->type = type; + CFunc_SetupLocalVarInfo(object); + return object; +} + +ENode *create_temp_node(Type *type) { + ENode *node; + + if (cinit_tempnodefunc) + return cinit_tempnodefunc(type, 0); + + node = CExpr_NewETEMPNode(type, 0); + if (IS_TYPE_CLASS(type) && CClass_Destructor(TYPE_CLASS(type))) + node->data.temp.needs_dtor = 1; + return node; +} + +ENode *create_temp_node2(Type *type) { + ENode *node; + + if (cinit_tempnodefunc) + return cinit_tempnodefunc(type, 1); + + node = CExpr_NewETEMPNode(type, 0); + node->data.temp.needs_dtor = 1; + return node; +} + +static ENode *CFunc_DestroyReverse(ENode *expr, DtorTemp *list) { + expr = makediadicnode(expr, CABI_DestroyObject(list->dtor, create_objectrefnode(list->object), CABIDestroy1, 1, 0), ECOMMA); + expr->rtype = &stvoid; + if (list->next) + expr = CFunc_DestroyReverse(expr, list->next); + return expr; +} + +static ENode *CFunc_TempTransDestroy(ENode *expr, DtorTemp *list, Boolean flag) { + Object *tempobj; + + if (flag) { + CError_ASSERT(738, !(IS_TYPE_CLASS(expr->rtype) && CClass_Destructor(TYPE_CLASS(expr->rtype)))); + tempobj = create_temp_object(expr->rtype); + expr = makediadicnode(create_objectnode(tempobj), expr, EASS); + } + + expr = CFunc_DestroyReverse(expr, list); + + if (flag) { + expr = makediadicnode(expr, create_objectnode(tempobj), ECOMMA); + expr->rtype = tempobj->type; + } + + return expr; +} + +void CFunc_WarnUnused(void) { + if (copts.warn_unusedvar) { + ObjectList *list; + for (list = locals; list; list = list->next) { + if ( + !(list->object->flags & OBJECT_USED) && + !IsTempName(list->object->name) && + !(list->object->qual & Q_INLINE_DATA) + ) + { + CError_SetErrorToken(&list->object->u.var.info->deftoken); + CError_Warning(CErrorStr182, &list->object->name->name); + } + } + } + + if (copts.warn_unusedarg) { + ObjectList *list; + for (list = arguments; list; list = list->next) { + if ( + !(list->object->flags & OBJECT_USED) && + !IsTempName(list->object->name) && + list->object->name != this_name_node && + list->object->name != self_name_node + ) + { + CError_SetErrorToken(&symdecltoken); + CError_Warning(CErrorStr182, &list->object->name->name); + } + } + } +} + +void CFunc_CodeCleanup(Statement *stmt) { + if (cscope_currentclass && cscope_currentclass->sominfo) + CSOM_InitSOMSelf(cscope_currentclass, stmt); + + CFunc_WarnUnused(); + CExcept_ExceptionTansform(stmt); +} + +static Boolean DestructorNeeded(ExceptionAction *ea, ExceptionAction *end) { + while (ea) { + if (CExcept_ActionNeedsDestruction(ea)) + return 1; + if (ea == end) + break; + ea = ea->prev; + } + + return 0; +} + +static Statement *DestructLocals(Statement *stmt, ExceptionAction *ea, ExceptionAction *end) { + while (ea) { + stmt = CExcept_ActionCleanup(ea, stmt); + if (ea == end) + break; + ea = ea->prev; + } + + return stmt; +} + +static Boolean NeedsDestruction(Statement *stmt1, Statement *stmt2) { + ExceptionAction *ea2; + ExceptionAction *ea1; + ExceptionAction *scan; + + ea1 = stmt1->dobjstack; + ea2 = stmt2->dobjstack; + + for (scan = ea2; scan; scan = scan->prev) { + if (scan == ea1) + return 0; + } + + while (ea1 && ea1 != ea2) { + if (CExcept_ActionNeedsDestruction(ea1)) + return 1; + ea1 = ea1->prev; + } + + return 0; +} + +static ExceptionAction *FindLastNonCommonStackObj(Statement *stmt1, Statement *stmt2) { + ExceptionAction *ea1; + ExceptionAction *ea2; + + for (ea2 = stmt2->dobjstack; ea2; ea2 = ea2->prev) { + for (ea1 = stmt1->dobjstack; ea1; ea1 = ea1->prev) { + if (ea1->prev == ea2) + return ea1; + } + } + + return NULL; +} + +static void DestructorReturnTransform(Statement *stmt1, Statement *stmt2) { + Statement *stmt; + Object *tempobj; + + if (stmt1->dobjstack != stmt2->dobjstack && NeedsDestruction(stmt1, stmt2)) + stmt1 = DestructLocals(stmt1, stmt1->dobjstack, FindLastNonCommonStackObj(stmt1, stmt2)); + + if (DestructorNeeded(stmt2->dobjstack, NULL)) { + if (CMach_GetFunctionResultClass(TYPE_FUNC(cscope_currentfunc->type)) != 1) { + tempobj = create_temp_object(stmt2->expr->rtype); + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt1); + stmt->expr = makediadicnode(create_objectnode(tempobj), stmt2->expr, EASS); + stmt->sourceoffset = stmt2->sourceoffset; + stmt->sourcefilepath = stmt2->sourcefilepath; + DestructLocals(stmt, stmt2->dobjstack, NULL); + stmt2->expr = create_objectnode(tempobj); + } else { + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt1); + stmt->expr = stmt2->expr; + stmt->sourceoffset = stmt2->sourceoffset; + stmt->sourcefilepath = stmt2->sourcefilepath; + DestructLocals(stmt, stmt2->dobjstack, NULL); + stmt2->expr = nullnode(); + } + } +} + +static Statement *DestructorIfTransform(Statement *stmt) { + CLabel *label; + Statement *newStmt; + + if (stmt->type == ST_IFGOTO) + stmt->type = ST_IFNGOTO; + else + stmt->type = ST_IFGOTO; + + label = newlabel(); + newStmt = DestructLocals(stmt, stmt->dobjstack, FindLastNonCommonStackObj(stmt, stmt->label->stmt)); + newStmt = CFunc_InsertStatement(ST_GOTO, newStmt); + newStmt->label = stmt->label; + newStmt = CFunc_InsertStatement(ST_LABEL, newStmt); + newStmt->label = label; + label->stmt = newStmt; + stmt->label = label; + newStmt->dobjstack = stmt->dobjstack; + return newStmt; +} + +static Boolean IsSubStack(ExceptionAction *exc1, ExceptionAction *exc2) { + if (!exc1) + return 1; + + while (exc2) { + if (exc2 == exc1) + return 1; + exc2 = exc2->prev; + } + + return 0; +} + +static void CFunc_CheckInitSkip(Statement *stmt, ExceptionAction *exc) { + if (stmt->dobjstack != exc && !IsSubStack(exc, stmt->dobjstack)) { + while (exc) { + if (CExcept_ActionNeedsDestruction(exc) && exc->type != EAT_ACTIVECATCHBLOCK) { + CError_Warning(CErrorStr211); + break; + } + exc = exc->prev; + } + } +} + +void CFunc_DestructorCleanup(Statement *stmt) { + Statement *scan; + Statement *next; + SwitchCase *swcase; + + if (copts.cplusplus) { + for (scan = stmt; scan; scan = scan->next) { + switch (scan->type) { + case ST_NOP: + case ST_LABEL: + case ST_EXPRESSION: + case ST_RETURN: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_GOTOEXPR: + case ST_ASM: + break; + case ST_SWITCH: + CFunc_CheckInitSkip(scan, ((SwitchInfo *) scan->label)->defaultlabel->stmt->dobjstack); + for (swcase = ((SwitchInfo *) scan->label)->cases; swcase; swcase = swcase->next) { + CFunc_CheckInitSkip(scan, swcase->label->stmt->dobjstack); + } + break; + case ST_GOTO: + case ST_IFGOTO: + case ST_IFNGOTO: + CFunc_CheckInitSkip(scan, scan->label->stmt->dobjstack); + break; + default: + CError_FATAL(1045); + } + } + + if (cexcept_hasdobjects) { + while (1) { + next = stmt->next; + if (!next) { + if (stmt->type != ST_RETURN && stmt->dobjstack) + DestructLocals(stmt, stmt->dobjstack, NULL); + return; + } + + switch (next->type) { + case ST_GOTO: + if ( + stmt->dobjstack != next->label->stmt->dobjstack && + NeedsDestruction(stmt, next->label->stmt) + ) + { + DestructLocals(stmt, stmt->dobjstack, FindLastNonCommonStackObj(stmt, next->label->stmt)); + } + stmt = next; + continue; + + case ST_RETURN: + if (next->expr && DestructorNeeded(stmt->dobjstack, NULL)) { + DestructorReturnTransform(stmt, next); + } else if (stmt->dobjstack) { + DestructLocals(stmt, stmt->dobjstack, NULL); + } + stmt = next; + continue; + } + + switch (stmt->type) { + case ST_GOTO: + case ST_SWITCH: + case ST_RETURN: + case ST_GOTOEXPR: + break; + case ST_NOP: + case ST_LABEL: + case ST_EXPRESSION: + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_ASM: + if ( + stmt->dobjstack != next->dobjstack && + NeedsDestruction(stmt, next) + ) + { + DestructLocals(stmt, stmt->dobjstack, FindLastNonCommonStackObj(stmt, next)); + } + break; + default: + CError_FATAL(1109); + } + + switch (next->type) { + case ST_NOP: + case ST_LABEL: + case ST_EXPRESSION: + case ST_SWITCH: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_ASM: + stmt = next; + continue; + + case ST_IFGOTO: + case ST_IFNGOTO: + if ( + next->dobjstack != next->label->stmt->dobjstack && + NeedsDestruction(next, next->label->stmt) + ) + { + stmt = DestructorIfTransform(next); + } else { + stmt = next; + } + break; + + default: + CError_FATAL(1138); + } + } + } + } +} + +static void scancase(DeclThing *thing) { + SwitchCase *swcase; + Statement *stmt; + CInt64 min; + CInt64 max; + + if (!thing->switchinfo) { + CError_Error(CErrorStr169); + return; + } + + tk = lex(); + min = CExpr_IntConstConvert(thing->switchinfo->x8, thing->switchinfo->x8, CExpr_IntegralConstExpr()); + if (!copts.ANSIstrict && tk == TK_ELLIPSIS) { + tk = lex(); + max = CExpr_IntConstConvert(thing->switchinfo->x8, thing->switchinfo->x8, CExpr_IntegralConstExpr()); + if (CInt64_Greater(min, max)) + CError_Error(CErrorStr366); + if (thing->switchinfo->x8->size == stsignedlonglong.size) + CError_Error(CErrorStr368); + } else { + max = min; + } + + for (swcase = thing->switchinfo->cases; swcase; swcase = swcase->next) { + if (CInt64_GreaterEqual(swcase->min, min) && CInt64_LessEqual(swcase->min, max)) + CError_Error(CErrorStr172); + if (CInt64_GreaterEqual(swcase->max, min) && CInt64_LessEqual(swcase->max, max)) + CError_Error(CErrorStr172); + if (CInt64_Less(swcase->min, min) && CInt64_Greater(swcase->max, max)) + CError_Error(CErrorStr172); + } + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = newlabel(); + stmt->label->stmt = stmt; + + swcase = lalloc(sizeof(SwitchCase)); + swcase->min = min; + swcase->label = stmt->label; + swcase->next = thing->switchinfo->cases; + thing->switchinfo->cases = swcase; + swcase->max = max; + + if (tk != ':') + CError_ErrorSkip(CErrorStr170); + else + tk = lex(); + + statement(thing); +} + +static void CFunc_NameLocalStaticDataObject(Object *obj, char *str) { + char buf[64]; + HashNameNode *name; + + if (!(cscope_currentfunc && (cscope_currentfunc->qual & Q_INLINE)) || CParser_HasInternalLinkage(cscope_currentfunc)) { + obj->name = CParser_AppendUniqueName(str); + } else { + sprintf(buf, "$localstatic%" PRId32 "$", cfunc_staticvarcount++); + name = CMangler_GetLinkName(cscope_currentfunc); + name = CParser_NameConcat(buf, name->name); + name = CParser_NameConcat(str, name->name); + obj->name = name; + obj->qual |= Q_20000; + obj->sclass = 0; + } +} + +static void sinit_insert_expr(ENode *expr) { + Statement *stmt; + + if (!sinit_first_object) { + sinit_first_object = CParser_NewCompilerDefDataObject(); + sinit_first_object->type = TYPE(&stsignedchar); + sinit_first_object->sclass = TK_STATIC; + CFunc_NameLocalStaticDataObject(sinit_first_object, "init"); + CInit_DeclareData(sinit_first_object, NULL, NULL, sinit_first_object->type->size); + + sinit_label = newlabel(); + stmt = CFunc_AppendStatement(ST_IFGOTO); + stmt->expr = create_objectnode(sinit_first_object); + stmt->label = sinit_label; + } + + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = expr; +} + +static void ainit_insert_expr(ENode *expr) { + Statement *stmt; + + if (ainit_only_one) { + if (ainit_expr) { + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = ainit_expr; + } + ainit_expr = expr; + } else { + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = expr; + } +} + +static ENode *ainit_register_object(Type *type, Object *local, SInt32 offset, Boolean flag) { + return CExcept_RegisterDestructorObject(local, offset, CClass_Destructor(TYPE_CLASS(type)), flag); +} + +static void CFunc_LocalDataDeclarator(DeclInfo *di, TStreamElement *deftoken, Boolean flag1, Boolean flag2) { + Object *object; + Object *aliasObject; + NameSpace *globalNS; + NameSpaceObjectList *nsol; + NameSpaceName *nsname; + Statement *stmt; + + if (di->nspace) + CError_Error(CErrorStr121); + + CDecl_CompleteType(di->thetype); + + object = NULL; + + if ((nsol = CScope_FindName(cscope_current, di->name))) { + switch (nsol->object->otype) { + case OT_OBJECT: + object = OBJECT(nsol->object); + break; + case OT_NAMESPACE: + CError_Error(CErrorStr321); + return; + case OT_ENUMCONST: + case OT_TYPE: + CError_Error(CErrorStr322); + break; + case OT_TYPETAG: + break; + default: + CError_FATAL(1344); + } + } + + if (object) + CError_Error(CErrorStr333, object); + + if (di->storageclass == TK_EXTERN) { + object = NULL; + globalNS = CScope_FindGlobalNS(cscope_current); + if ((nsol = CScope_FindName(globalNS, di->name))) { + switch (nsol->object->otype) { + case OT_OBJECT: + object = OBJECT(nsol->object); + break; + case OT_NAMESPACE: + CError_Error(CErrorStr321); + return; + case OT_ENUMCONST: + case OT_TYPE: + CError_Error(CErrorStr322); + break; + case OT_TYPETAG: + break; + default: + CError_FATAL(1381); + } + } + + if (object) { + if ( + !is_typesame(di->thetype, object->type) || + (di->qual & (Q_CONST | Q_VOLATILE | Q_PASCAL | Q_20000 | Q_WEAK | Q_ALIGNED_MASK)) != (object->qual & (Q_CONST | Q_VOLATILE | Q_PASCAL | Q_20000 | Q_WEAK | Q_ALIGNED_MASK)) + ) + { + CError_Error(CErrorStr249, di->name->name, object->type, object->qual, di->thetype, di->qual); + } + } else { + object = CParser_NewGlobalDataObject(di); + object->nspace = globalNS; + } + + CParser_NewAliasObject(object, 0); + return; + } + + if (di->storageclass != TK_STATIC) + object = CParser_NewObject(di); + else + object = CParser_NewGlobalDataObject(di); + + object->name = di->name; + object->type = di->thetype; + object->qual = di->qual; + object->sclass = di->storageclass; + + switch (di->storageclass) { + case TK_STATIC: + if (flag1) { + CError_Error(CErrorStr177); + return; + } + if (flag2) + CError_Error(CErrorStr174); + + if (CanCreateObject(di->thetype)) { + CError_QualifierCheck(di->qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_20000 | Q_WEAK | Q_ALIGNED_MASK)); + CParser_NewAliasObject(object, 0); + object->nspace = cscope_root; + object->datatype = DDATA; + CFunc_NameLocalStaticDataObject(object, object->name->name); + + if (copts.cplusplus) { + sinit_first_object = NULL; + CInit_InitializeStaticData(object, sinit_insert_expr); + if (sinit_first_object) { + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = makediadicnode( + create_objectnode(sinit_first_object), + intconstnode(TYPE(&stsignedchar), 1), + EASS); + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = sinit_label; + sinit_label->stmt = stmt; + } + } else { + CInit_InitializeData(object); + } + } + break; + + case 0: + case TK_AUTO: + case TK_REGISTER: + if (CanCreateObject(di->thetype)) { + CError_QualifierCheck(di->qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_ALIGNED_MASK)); + object->datatype = DLOCAL; + CFunc_SetupLocalVarInfo(object); + + object->u.var.info->deftoken = *deftoken; + if (object->sclass == TK_REGISTER && flag1) + object->u.var.info->usage = 100; + + CScope_AddObject(cscope_current, object->name, OBJ_BASE(object)); + + if (!flag1) { + if (IS_TYPE_SOM_CLASS(di->thetype)) { + CSOM_InitAutoClass(object); + } else { + CInit_InitializeAutoData(object, ainit_insert_expr, ainit_register_object); + if (object->type != di->thetype && (IS_TYPE_STRUCT(object->type) || IS_TYPE_CLASS(object->type))) { + CError_ASSERT(1478, !cscope_current->is_hash); + CError_ASSERT(1479, nsname = CScope_FindNameSpaceName(cscope_current, object->name)); + CError_ASSERT(1480, nsname->first.object == OBJ_BASE(object)); + CError_ASSERT(1481, !nsname->first.next); + nsname->name = CParser_AppendUniqueName(object->name->name); + + aliasObject = CParser_NewAliasObject(object, 0); + aliasObject->type = di->thetype; + } + } + } + + if (object->datatype == DLOCAL) { + ObjectList *list = lalloc(sizeof(ObjectList)); + list->object = object; + list->next = locals; + locals = list; + } + + IsCompleteType(di->thetype); + } + break; + + default: + CError_FATAL(1504); + } +} + +static ENode *CFunc_ParseLocalDeclarationList(Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4) { + Type *type; + UInt32 qual; + DeclInfo di; + TStreamElement deftoken; + + ainit_expr = NULL; + ainit_only_one = flag2; + + while (flag2 || isdeclaration(copts.cplusplus, 0, 0, 0)) { + CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); + + memclrw(&di, sizeof(di)); + di.is_extern_c = cfunc_is_extern_c; + CParser_GetDeclSpecs(&di, 0); + + if (IS_TYPE_TEMPLATE(di.thetype)) { + CError_Error(CErrorStr146); + di.thetype = TYPE(&stsignedint); + } + + type = di.thetype; + qual = di.qual; + + if (tk != ';') { + while (1) { + deftoken = *CPrep_CurStreamElement(); + di.name = NULL; + scandeclarator(&di); + + if (di.name) { + if (di.storageclass != TK_TYPEDEF) { + if (IS_TYPE_FUNC(di.thetype)) { + if (!CDecl_FunctionDeclarator(&di, CScope_FindGlobalNS(cscope_current), 0, 0)) + break; + } else { + CFunc_LocalDataDeclarator(&di, &deftoken, flag1, flag2); + } + } else { + CDecl_TypedefDeclarator(&di); + } + } else { + CError_Error(CErrorStr134); + } + + if (tk == ';') + break; + + if (tk != ',') { + if (!flag2) + CError_Error(CErrorStr123); + break; + } + + di.nspace = NULL; + di.thetype = type; + di.qual = qual; + tk = lex(); + } + } else { + CParser_CheckAnonymousUnion(&di, 1); + } + + if (flag2) + break; + if (flag4) + break; + tk = lex(); + } + + if (flag2) { + if (!ainit_expr) { + if (!flag3) { + CError_Error(CErrorStr141); + ainit_expr = nullnode(); + } + } else { + ainit_expr = checkreference(ainit_expr); + } + } + + return ainit_expr; +} + +static void makeifstatement(ENode *expr, CLabel *label1, CLabel *label2, Boolean flag1, Boolean flag2) { + Statement *stmt; + CLabel *tmplabel; + + if (!expr) { + if (flag1) { + stmt = CFunc_AppendStatement(ST_GOTO); + stmt->label = label1; + return; + } + return; + } + + if ( + ENODE_IS(expr, ETYPCON) && + IS_TYPE_INT(expr->rtype) && + IS_TYPE_INT(expr->data.monadic->rtype) && + expr->rtype->size >= expr->data.monadic->rtype->size + ) + expr = expr->data.monadic; + + if (isnotzero(expr)) { + if (flag1) { + stmt = CFunc_AppendStatement(ST_GOTO); + stmt->label = label1; + return; + } + return; + } + + if (iszero(expr)) { + if (!flag1) { + stmt = CFunc_AppendStatement(ST_GOTO); + stmt->label = label1; + return; + } + return; + } + + if (ENODE_IS(expr, ELOGNOT)) { + makeifstatement(expr->data.monadic, label1, label2, !flag1, flag2); + return; + } + + if (ENODE_IS(expr, ELOR)) { + tmplabel = newlabel(); + if (flag1) { + makeifstatement(expr->data.diadic.left, label1, tmplabel, 1, flag2); + tmplabel->stmt = CFunc_AppendStatement(ST_LABEL); + tmplabel->stmt->label = tmplabel; + makeifstatement(expr->data.diadic.right, label1, label2, 1, flag2); + return; + } else { + makeifstatement(expr->data.diadic.left, label2, tmplabel, 1, flag2); + tmplabel->stmt = CFunc_AppendStatement(ST_LABEL); + tmplabel->stmt->label = tmplabel; + makeifstatement(expr->data.diadic.right, label1, label2, 0, flag2); + return; + } + } + + if (ENODE_IS(expr, ELAND)) { + tmplabel = newlabel(); + if (flag1) { + makeifstatement(expr->data.diadic.left, label2, tmplabel, 0, flag2); + tmplabel->stmt = CFunc_AppendStatement(ST_LABEL); + tmplabel->stmt->label = tmplabel; + makeifstatement(expr->data.diadic.right, label1, label2, 1, flag2); + return; + } else { + makeifstatement(expr->data.diadic.left, label1, tmplabel, 0, flag2); + tmplabel->stmt = CFunc_AppendStatement(ST_LABEL); + tmplabel->stmt->label = tmplabel; + makeifstatement(expr->data.diadic.right, label1, label2, 0, flag2); + return; + } + } + + stmt = CFunc_AppendStatement(ST_IFGOTO); + stmt->label = label1; + stmt->expr = expr; + if (!flag1) + stmt->type = ST_IFNGOTO; + if (flag2) + stmt->flags = stmt->flags | StmtFlag_4; +} + +static void CFunc_HasDtorTempCallBack(ENode *expr) { + if (expr->data.temp.needs_dtor || expr->data.temp.uniqueid) + cfunc_hasdtortemp = 1; +} + +static void ifstatement(Boolean flag1, ENode *expr, CLabel *label, Boolean flag2) { + Statement *stmt; + CLabel *tmplabel; + + if (expr && copts.cplusplus && copts.exceptions) { + cfunc_hasdtortemp = 0; + CExpr_SearchExprTree(expr, CFunc_HasDtorTempCallBack, 1, ETEMP); + if (cfunc_hasdtortemp) { + stmt = CFunc_AppendStatement(flag1 ? ST_IFGOTO : ST_IFNGOTO); + stmt->label = label; + stmt->expr = expr; + if (flag2) + stmt->flags = stmt->flags | StmtFlag_4; + return; + } + } + + tmplabel = newlabel(); + makeifstatement(expr, label, tmplabel, flag1, flag2); + tmplabel->stmt = CFunc_AppendStatement(ST_LABEL); + tmplabel->stmt->label = tmplabel; +} + +Statement *CFunc_GenerateLoop(Statement *stmt, Type *type, ENode *lowerBound, ENode *upperBound, ENode *increment1, ENode *increment2, ENode *(*callback)(ENode *, ENode *)) { + ENode *var1; + ENode *var2; + CLabel *label; + ENode *ind; + ENode *ind2; + Statement *s; + + var1 = CExpr_NewETEMPNode(type, 1); + ind = lalloc(sizeof(ENode)); + *ind = *var1; + ind = makemonadicnode(ind, EINDIRECT); + ind->rtype = type; + + // initialise var1 to lowerBound + if (stmt) { + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + s = stmt; + } else { + s = CFunc_AppendStatement(ST_EXPRESSION); + } + s->expr = makediadicnode(ind, lowerBound, EASS); + + if (increment2) { + var2 = CExpr_NewETEMPNode(type, 1); + ind = lalloc(sizeof(ENode)); + *ind = *var2; + ind = makemonadicnode(ind, EINDIRECT); + ind->rtype = type; + + // initialise var2 to upperBound + if (stmt) { + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + s = stmt; + } else { + s = CFunc_AppendStatement(ST_EXPRESSION); + } + s->expr = makediadicnode(ind, upperBound, EASS); + } + + // label for loop body + label = newlabel(); + if (stmt) { + stmt = CFunc_InsertStatement(ST_LABEL, stmt); + s = stmt; + } else { + s = CFunc_AppendStatement(ST_LABEL); + } + s->label = label; + label->stmt = s; + + if (callback) { + ind = lalloc(sizeof(ENode)); + *ind = *var1; + ind = makemonadicnode(ind, EINDIRECT); + ind->rtype = type; + + if (increment2) { + ind2 = lalloc(sizeof(ENode)); + *ind2 = *var2; + ind2 = makemonadicnode(ind2, EINDIRECT); + ind2->rtype = type; + } else { + ind2 = NULL; + } + + // generate a loop body + if ((ind = callback(ind, ind2))) { + if (stmt) { + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + s = stmt; + } else { + s = CFunc_AppendStatement(ST_EXPRESSION); + } + s->expr = ind; + } + } + + if (increment1) { + ind = lalloc(sizeof(ENode)); + *ind = *var1; + ind = makemonadicnode(ind, EINDIRECT); + ind->rtype = type; + + // add increment1 to var1 + if (stmt) { + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + s = stmt; + } else { + s = CFunc_AppendStatement(ST_EXPRESSION); + } + s->expr = makediadicnode(ind, increment1, EADDASS); + + if (increment2) { + ind = lalloc(sizeof(ENode)); + *ind = *var2; + ind = makemonadicnode(ind, EINDIRECT); + ind->rtype = type; + + // add increment2 to var2 + if (stmt) { + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + s = stmt; + } else { + s = CFunc_AppendStatement(ST_EXPRESSION); + } + s->expr = makediadicnode(ind, increment2, EADDASS); + } + } + + ind = lalloc(sizeof(ENode)); + *ind = *var1; + ind = makemonadicnode(ind, EINDIRECT); + ind->rtype = type; + + // loop if var1 < upperBound + if (stmt) { + stmt = CFunc_InsertStatement(ST_IFGOTO, stmt); + s = stmt; + } else { + s = CFunc_AppendStatement(ST_IFGOTO); + } + s->expr = makediadicnode(ind, upperBound, ELESS); + s->expr->rtype = TYPE(&stbool); + s->label = label; + s->flags = StmtFlag_4; + + return stmt; +} + +static Boolean checklabel(void) { + HashNameNode *savename; + short savesize; + short token; + + savename = tkidentifier; + savesize = tksize; + token = lookahead(); + tkidentifier = savename; + tksize = savesize; + + return token == ':'; +} + +static ENode *returnstatementadjust(ENode *expr, Type *type, UInt32 qual) { + Object *object; + ENode *expr2; + ENode *objexpr; + ObjectList *list; + ENodeList *exprlist; + + for (list = arguments; list; list = list->next) { + if (list->object->name == temp_argument_name) + break; + } + + CError_ASSERT(1907, list); + + object = list->object; + if ((expr2 = CExpr_IsTempConstruction(expr, type, &objexpr)) && ENODE_IS(objexpr, ETEMP)) { + *objexpr = *create_objectnode(object); + return expr2; + } + + if (IS_TYPE_CLASS(type)) { + expr2 = create_objectnode(object); + exprlist = lalloc(sizeof(ENodeList)); + exprlist->next = NULL; + exprlist->node = expr; + return CExpr_ConstructObject(TYPE_CLASS(type), expr2, exprlist, 1, 1, 0, 1, 0); + } + + expr2 = create_objectnode(object); + expr2 = makemonadicnode(expr2, EINDIRECT); + expr2->rtype = type; + + return makediadicnode(expr2, CExpr_AssignmentPromotion(expr, type, qual, 1), EASS); +} + +static void CFunc_AutoResultCheck(ENode *expr) { + while (1) { + while (ENODE_IS(expr, ECOMMA)) + expr = expr->data.diadic.right; + + switch (expr->type) { + case EOBJREF: + if (expr->data.objref->datatype != DLOCAL) + break; + case ETEMP: + CError_Warning(CErrorStr326); + break; + case EADD: + case ESUB: + CFunc_AutoResultCheck(expr->data.diadic.left); + expr = expr->data.diadic.right; + continue; + default: + break; + } + break; + } +} + +static void statement(DeclThing *thing) { + Statement *stmt; + Statement *stmt2; + CLabel *label; + DeclBlock *block; + ENode *expr; + HashNameNode *name; + DeclThing subthing; + + CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); + + switch (tk) { + case TK_RETURN: + tk = lex(); + if ( + (thing->thetype == &stvoid && !copts.cplusplus) || + CClass_IsConstructor(cscope_currentfunc) || + CClass_IsDestructor(cscope_currentfunc) + ) + { + if (tk != ';') { + CError_Error(CErrorStr315); + expression(); + } + + stmt = CFunc_AppendStatement(ST_RETURN); + stmt->expr = NULL; + CError_ResetErrorSkip(); + tk = lex(); + return; + } + + if (tk == ';') { + if (thing->thetype != &stvoid && (copts.pedantic || copts.cplusplus)) + CError_Warning(CErrorStr184); + + stmt = CFunc_AppendStatement(ST_RETURN); + stmt->expr = NULL; + CError_ResetErrorSkip(); + tk = lex(); + return; + } + + if (copts.old_argmatch) + expr = expression(); + else + expr = s_expression(); + + if (thing->thetype == &stvoid) { + if (expr->rtype != &stvoid) + CError_Error(CErrorStr315); + + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = expr; + + stmt = CFunc_AppendStatement(ST_RETURN); + stmt->expr = NULL; + } else { + if (CMach_GetFunctionResultClass(TYPE_FUNC(cscope_currentfunc->type)) == 1) + expr = returnstatementadjust(expr, thing->thetype, thing->qual); + else + expr = CExpr_AssignmentPromotion(expr, thing->thetype, thing->qual, 1); + + stmt = CFunc_AppendStatement(ST_RETURN); + stmt->expr = expr; + + if (IS_TYPE_POINTER_ONLY(thing->thetype)) + CFunc_AutoResultCheck(expr); + } + + break; + + case TK_CASE: + scancase(thing); + return; + + case TK_DEFAULT: + if (!thing->switchinfo) { + CError_Error(CErrorStr169); + return; + } + + if (lex() != ':') + CError_ErrorSkip(CErrorStr170); + else + tk = lex(); + + if (thing->switchinfo->defaultlabel) + CError_ErrorSkip(CErrorStr173); + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = newlabel(); + stmt->label->stmt = stmt; + thing->switchinfo->defaultlabel = stmt->label; + statement(thing); + return; + + case TK_SWITCH: + if (lex() != '(') + CError_ErrorSkip(CErrorStr114); + else + tk = lex(); + + if (copts.cplusplus && !copts.ARMscoping && isdeclaration(1, 0, 0, '=')) { + block = CFunc_NewDeclBlock(); + expr = CFunc_ParseLocalDeclarationList(0, 1, 0, 0); + if (CScope_IsEmptyNameSpace(cscope_current)) { + CFunc_RestoreBlock(block); + block = NULL; + } + } else { + expr = expression(); + block = NULL; + } + + stmt = CFunc_AppendStatement(ST_SWITCH); + stmt->expr = CExpr_ConvertToIntegral(expr); + + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + + stmt->label = (CLabel *) lalloc(sizeof(SwitchInfo)); + ((SwitchInfo *) stmt->label)->defaultlabel = NULL; + ((SwitchInfo *) stmt->label)->cases = NULL; + ((SwitchInfo *) stmt->label)->x8 = stmt->expr->rtype; + + label = newlabel(); + subthing = *thing; + subthing.loopBreak = label; + subthing.switchinfo = (SwitchInfo *) stmt->label; + CFunc_CompoundStatement(&subthing); + + if (!subthing.switchinfo->defaultlabel) + subthing.switchinfo->defaultlabel = label; + + if (!subthing.switchinfo->cases) { + stmt->type = ST_EXPRESSION; + stmt2 = lalloc(sizeof(Statement)); + *stmt2 = *stmt; + stmt->next = stmt2; + stmt2->type = ST_GOTO; + stmt2->label = subthing.switchinfo->defaultlabel; + stmt2->dobjstack = cexcept_dobjstack; + } + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = label; + label->stmt = stmt; + + if (block) + CFunc_RestoreBlock(block); + return; + + case TK_GOTO: + if ((tk = lex()) != TK_IDENTIFIER) { + if (tk == '*' && !copts.ANSIstrict) { + tk = lex(); + stmt = CFunc_AppendStatement(ST_GOTOEXPR); + stmt->expr = expression(); + if (!IS_TYPE_POINTER_ONLY(stmt->expr->rtype)) { + CError_Error(CErrorStr146); + stmt->expr = nullnode(); + stmt->expr->rtype = TYPE(&void_ptr); + } + } else { + CError_Error(CErrorStr107); + return; + } + } else { + stmt = CFunc_AppendStatement(ST_GOTO); + if (!(stmt->label = findlabel())) { + stmt->label = newlabel(); + stmt->label->next = Labels; + Labels = stmt->label; + stmt->label->name = tkidentifier; + } + tk = lex(); + } + break; + + case TK_BREAK: + if (thing->loopBreak) { + stmt = CFunc_AppendStatement(ST_GOTO); + stmt->label = thing->loopBreak; + } else { + CError_Error(CErrorStr169); + } + tk = lex(); + break; + + case TK_CONTINUE: + if (thing->loopContinue) { + stmt = CFunc_AppendStatement(ST_GOTO); + stmt->label = thing->loopContinue; + } else { + CError_Error(CErrorStr169); + } + tk = lex(); + break; + + case TK_FOR: { + CLabel *forLabel1; + CLabel *forLabel2; + CLabel *forLabel3; + ENode *forCond; + ENode *forInc; + + if (lex() != '(') + CError_ErrorSkip(CErrorStr114); + else + tk = lex(); + + block = NULL; + if (tk != ';') { + if (!copts.cplusplus || !isdeclaration(1, 0, 0, 0)) { + expr = expression(); + CExpr_CheckUnusedExpression(expr); + } else { + if (!copts.ARMscoping) + block = CFunc_NewDeclBlock(); + expr = CFunc_ParseLocalDeclarationList(0, 1, 1, 0); + if (block && CScope_IsEmptyNameSpace(cscope_current)) { + CFunc_RestoreBlock(block); + block = NULL; + } + } + + if (expr) { + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = expr; + } + + if (tk == ';') + CError_ResetErrorSkip(); + else + CError_Error(CErrorStr123); + } else { + CError_ResetErrorSkip(); + } + + if ((tk = lex()) != ';') { + if (copts.cplusplus && !copts.ARMscoping && isdeclaration(1, 0, 0, '=')) { + if (!block) + block = CFunc_NewDeclBlock(); + expr = CFunc_ParseLocalDeclarationList(0, 1, 0, 0); + if (CScope_IsEmptyNameSpace(cscope_current)) { + CFunc_RestoreBlock(block); + block = NULL; + } + } else { + expr = expression(); + CExpr_CheckUnwantedAssignment(expr); + } + + forCond = CExpr_ConvertToCondition(expr); + + if (tk == ';') + CError_ResetErrorSkip(); + else + CError_Error(CErrorStr123); + } else { + CError_ResetErrorSkip(); + forCond = NULL; + } + + if ((tk = lex()) != ')') { + forInc = expression(); + CExpr_CheckUnusedExpression(forInc); + if (tk == ')') + CError_ResetErrorSkip(); + else + CError_Error(CErrorStr115); + } else { + CError_ResetErrorSkip(); + forInc = NULL; + } + + if (copts.warn_possunwant) { + spaceskip = 0; + if ((tk = lex()) == ';' && !spaceskip) + CError_Warning(CErrorStr206); + } else { + tk = lex(); + } + + if (forCond) { + stmt = CFunc_AppendStatement(ST_GOTO); + label = newlabel(); + stmt->label = label; + } else { + label = newlabel(); + } + + CFunc_LoopIncrement(); + + stmt = CFunc_AppendStatement(ST_LABEL); + forLabel1 = stmt->label = newlabel(); + forLabel1->stmt = stmt; + + forLabel2 = newlabel(); + forLabel3 = newlabel(); + + subthing = *thing; + subthing.loopContinue = forLabel3; + subthing.loopBreak = forLabel2; + + if (tk != '{') { + DeclBlock *b = CFunc_NewDeclBlock(); + CFunc_CompoundStatement(&subthing); + CFunc_RestoreBlock(b); + } else { + CFunc_CompoundStatement(&subthing); + } + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = forLabel3; + forLabel3->stmt = stmt; + + if (forInc) { + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = forInc; + } + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = label; + label->stmt = stmt; + + ifstatement(1, forCond, forLabel1, 1); + CFunc_LoopDecrement(); + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = forLabel2; + forLabel2->stmt = stmt; + + if (block) + CFunc_RestoreBlock(block); + + return; + } + + case TK_DO: { + CLabel *label1; + CLabel *label2; + CLabel *label3; + + CFunc_LoopIncrement(); + stmt = CFunc_AppendStatement(ST_LABEL); + label1 = stmt->label = newlabel(); + label1->stmt = stmt; + + label2 = newlabel(); + label3 = newlabel(); + + subthing = *thing; + subthing.loopContinue = label2; + subthing.loopBreak = label3; + + tk = lex(); + CFunc_CompoundStatement(&subthing); + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = label2; + label2->stmt = stmt; + + if (tk != TK_WHILE) + CError_Error(CErrorStr105); + + if (lex() != '(') + CError_ErrorSkip(CErrorStr114); + else + tk = lex(); + + expr = CExpr_ConvertToCondition(expression()); + CExpr_CheckUnwantedAssignment(expr); + + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + + ifstatement(1, expr, label1, 1); + + CFunc_LoopDecrement(); + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = label3; + label3->stmt = stmt; + break; + } + + case TK_WHILE: { + CLabel *label1; + CLabel *label2; + CLabel *label3; + + if ((tk = lex()) != '(') + CError_ErrorSkip(CErrorStr114); + else + tk = lex(); + + if (copts.cplusplus && !copts.ARMscoping && isdeclaration(1, 0, 0, '=')) { + block = CFunc_NewDeclBlock(); + expr = CFunc_ParseLocalDeclarationList(0, 1, 0, 0); + if (CScope_IsEmptyNameSpace(cscope_current)) { + CFunc_RestoreBlock(block); + block = NULL; + } + } else { + expr = expression(); + block = NULL; + CExpr_CheckUnwantedAssignment(expr); + } + expr = CExpr_ConvertToCondition(expr); + + if (tk != ')') { + CError_ErrorSkip(CErrorStr115); + } else { + if (copts.warn_possunwant) { + spaceskip = 0; + if ((tk = lex()) == ';' && !spaceskip) + CError_Warning(CErrorStr206); + } else { + tk = lex(); + } + } + + stmt = CFunc_AppendStatement(ST_GOTO); + label1 = newlabel(); + stmt->label = label1; + + CFunc_LoopIncrement(); + + stmt = CFunc_AppendStatement(ST_LABEL); + label2 = stmt->label = newlabel(); + label2->stmt = stmt; + + label3 = newlabel(); + + subthing = *thing; + subthing.loopContinue = label1; + subthing.loopBreak = label3; + + CFunc_CompoundStatement(&subthing); + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = label1; + label1->stmt = stmt; + + ifstatement(1, expr, label2, 1); + + CFunc_LoopDecrement(); + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = label3; + label3->stmt = stmt; + + if (block) + CFunc_RestoreBlock(block); + return; + } + + case TK_IF: { + CLabel *label1; + if ((tk = lex()) != '(') + CError_ErrorSkip(CErrorStr114); + else + tk = lex(); + + if (copts.cplusplus && !copts.ARMscoping && isdeclaration(1, 0, 0, '=')) { + block = CFunc_NewDeclBlock(); + expr = CFunc_ParseLocalDeclarationList(0, 1, 0, 0); + if (CScope_IsEmptyNameSpace(cscope_current)) { + CFunc_RestoreBlock(block); + block = NULL; + } + } else { + expr = expression(); + block = NULL; + CExpr_CheckUnwantedAssignment(expr); + } + + expr = CExpr_ConvertToCondition(expr); + + label1 = newlabel(); + ifstatement(0, expr, label1, 0); + + if (tk != ')') { + CError_ErrorSkip(CErrorStr115); + } else { + if (copts.warn_possunwant) { + spaceskip = 0; + if ((tk = lex()) == ';' && !spaceskip) + CError_Warning(CErrorStr206); + } else { + tk = lex(); + } + } + + CFunc_CompoundStatement(thing); + + if (tk == TK_ELSE) { + if (copts.warn_possunwant) { + spaceskip = 0; + if ((tk = lex()) == ';' && !spaceskip) + CError_Warning(CErrorStr206); + } else { + tk = lex(); + } + + stmt = CFunc_AppendStatement(ST_GOTO); + label = stmt->label = newlabel(); + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = label1; + label1->stmt = stmt; + + CFunc_CompoundStatement(thing); + + label1 = label; + } + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = label1; + label1->stmt = stmt; + + if (block) + CFunc_RestoreBlock(block); + + return; + } + + case '{': + CFunc_CompoundStatement(thing); + return; + + case TK_ASM: + if (copts.cplusplus || !copts.ANSIstrict) { + tk = lex(); + volatileasm = 0; + + if (tk == TK_VOLATILE || (tk == TK_IDENTIFIER && !strcmp(tkidentifier->name, "__volatile__"))) { + tk = lex(); + volatileasm = 1; + } + + if (tk == '(') { + InlineAsm_Assemble(); + if (tk == ')') { + tk = lex(); + break; + } else { + CError_Error(CErrorStr115); + return; + } + } + + if (tk == '{') { + InlineAsm_Assemble(); + if (tk != '}') { + CError_Error(CErrorStr130); + return; + } + if ((tk = lex()) == ';') + tk = lex(); + CError_ResetErrorSkip(); + return; + } + + CError_Error(CErrorStr114); + } else { + CError_Error(CErrorStr121); + } + return; + + case TK_TRY: + tk = lex(); + CExcept_ScanTryBlock(thing, 0); + return; + + case TK_USING: + if ((tk = lex()) == TK_NAMESPACE) { + tk = lex(); + CScope_ParseUsingDirective(cscope_current); + } else { + CScope_ParseUsingDeclaration(cscope_current, 0, 0); + } + return; + + case TK_NAMESPACE: + if ((tk = lex()) != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + return; + } + name = tkidentifier; + if ((tk = lex()) != '=') { + CError_Error(CErrorStr121); + return; + } + + CScope_ParseNameSpaceAlias(name); + break; + + case ';': + break; + + case TK_IDENTIFIER: + if (checklabel()) { + stmt = CFunc_AppendStatement(ST_LABEL); + if ((stmt->label = findlabel())) { + if (stmt->label->stmt) + CError_Error(CErrorStr171, tkidentifier->name); + } else { + stmt->label = newlabel(); + stmt->label->next = Labels; + Labels = stmt->label; + stmt->label->name = tkidentifier; + } + + stmt->label->stmt = stmt; + tk = lex(); + tk = lex(); + statement(thing); + return; + } + tk = TK_IDENTIFIER; + + default: + if (copts.cplusplus && isdeclaration(1, 0, 0, 0)) { + CFunc_ParseLocalDeclarationList(0, 0, 0, 1); + tk = lex(); + return; + } + + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = expression(); + CExpr_CheckUnusedExpression(stmt->expr); + } + + if (tk == ';') { + CPrep_TokenStreamFlush(); + tk = lex(); + CError_ResetErrorSkip(); + } else { + CError_ErrorSkip(CErrorStr123); + } +} + +void CFunc_CompoundStatement(DeclThing *thing) { + DeclBlock *block; + + block = CFunc_NewDeclBlock(); + + if (tk == '{') { + tk = lex(); + if (!copts.cplusplus && isdeclaration(0, 0, 0, 0)) + CFunc_ParseLocalDeclarationList(0, 0, 0, 0); + + while (tk != '}') + statement(thing); + + CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); + tk = lex(); + } else { + statement(thing); + } + + CFunc_RestoreBlock(block); +} + +static void CFunc_InsertArgumentCopyConversion(Object *obj, Type *type1, Type *type2, Boolean flag) { + Object *newobj; + Statement *stmt; + ENode *expr; + NameSpaceObjectList *nsol; + ObjectList *list; + + newobj = lalloc(sizeof(Object)); + *newobj = *obj; + newobj->type = type2; + + CFunc_SetupLocalVarInfo(newobj); + + obj->name = CParser_GetUniqueName(); + if (flag) + obj->type = CDecl_NewPointerType(type1); + else + obj->type = type1; + + CError_ASSERT(2527, (nsol = CScope_FindName(cscope_current, newobj->name)) && nsol->object == OBJ_BASE(obj)); + nsol->object = OBJ_BASE(newobj); + + list = lalloc(sizeof(ObjectList)); + list->object = newobj; + list->next = locals; + locals = list; + + stmt = CFunc_AppendStatement(ST_EXPRESSION); + expr = create_objectnode(obj); + if (flag) { + expr->rtype = CDecl_NewPointerType(type1); + expr = makemonadicnode(expr, EINDIRECT); + } + expr->rtype = type1; + + if (type1 != type2) + expr = promote(expr, type2); + + stmt->expr = makediadicnode(create_objectnode(newobj), expr, EASS); +} + +static void CFunc_AdjustOldStyleArgs(void) { + ObjectList *list; + + for (list = arguments; list; list = list->next) { + if (IS_TYPE_FLOAT(list->object->type) && list->object->type->size < stdouble.size) + CFunc_InsertArgumentCopyConversion(list->object, TYPE(&stdouble), list->object->type, 0); + } +} + +void CFunc_SetupNewFuncArgs(Object *func, FuncArg *args) { + Object *obj; + ObjectList *newlist; + + arguments = NULL; + + if (args != &elipsis && args != &oldstyle) { + newlist = NULL; + + while (args && args != &elipsis) { + IsCompleteType(args->type); + + obj = CParser_NewLocalDataObject(NULL, 0); + obj->name = !args->name ? no_name_node : args->name; + obj->type = args->type; + obj->qual = args->qual; + obj->sclass = args->sclass; + + CFunc_SetupLocalVarInfo(obj); + + if (IS_TYPE_CLASS(obj->type) && CClass_ReferenceArgument(TYPE_CLASS(obj->type))) { + obj->type = CDecl_NewPointerType(obj->type); + TPTR_QUAL(obj->type) = Q_REFERENCE | Q_RESTRICT; + } + + if (obj->name == no_name_node && copts.ANSIstrict && !copts.cplusplus && !(func->qual & Q_MANGLE_NAME)) + CError_Error(CErrorStr127); + + if (newlist) { + newlist->next = lalloc(sizeof(ObjectList)); + newlist = newlist->next; + } else { + newlist = lalloc(sizeof(ObjectList)); + arguments = newlist; + } + + newlist->next = NULL; + newlist->object = obj; + + args = args->next; + } + } +} + +static ObjectList *CFunc_CopyObjectList(const FuncArg *args) { + Object *obj; + ObjectList *list; + ObjectList *last; + + list = NULL; + + while (args) { + if (list) { + last->next = lalloc(sizeof(ObjectList)); + last = last->next; + } else { + last = lalloc(sizeof(ObjectList)); + list = last; + } + + obj = CParser_NewLocalDataObject(NULL, 0); + obj->name = args->name; + obj->type = args->type; + obj->qual = args->qual; + obj->sclass = args->sclass; + CFunc_SetupLocalVarInfo(obj); + + last->object = obj; + last->next = NULL; + + args = args->next; + } + + return list; +} + +static void SetupFunctionArguments(Object *func, DeclInfo *di, Statement *firstStmt) { + ObjectList *list; + Object *resultobj; + Object *obj; + Type *type; + DeclInfo my_di; + + if (TYPE_FUNC(func->type)->args) { + if (di->x45) { + arguments = CFunc_CopyObjectList(di->x18); + while (1) { + if (tk == '{') + break; + + memclrw(&my_di, sizeof(my_di)); + CParser_GetDeclSpecs(&my_di, 0); + + type = my_di.thetype; + if (my_di.storageclass && my_di.storageclass != TK_REGISTER) + CError_Error(CErrorStr127); + + while (1) { + my_di.thetype = type; + my_di.name = NULL; + scandeclarator(&my_di); + if (!my_di.name) { + CError_Error(CErrorStr107); + break; + } + + adjustargumenttype(&my_di); + IsCompleteType(my_di.thetype); + + if ((obj = CFunc_IsInObjList(arguments, my_di.name))) { + if (obj->type) + CError_Error(CErrorStr333, obj); + obj->type = my_di.thetype; + obj->sclass = my_di.storageclass; + obj->qual = my_di.qual; + } else { + CError_Error(CErrorStr127); + } + + if (tk != ',') + break; + tk = lex(); + } + + if (tk != ';') + CError_ErrorSkip(CErrorStr123); + else + tk = lex(); + } + + for (list = arguments; list; list = list->next) { + if (!list->object->type) + list->object->type = TYPE(&stsignedint); + } + } else { + CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); + } + } + + if (CMach_GetFunctionResultClass(TYPE_FUNC(func->type)) == 1) { + resultobj = CParser_NewLocalDataObject(NULL, 0); + resultobj->name = temp_argument_name; + resultobj->type = CDecl_NewPointerType(TYPE_FUNC(func->type)->functype); + CFunc_SetupLocalVarInfo(resultobj); + + list = lalloc(sizeof(ObjectList)); + list->object = resultobj; + if (CABI_GetStructResultArgumentIndex(TYPE_FUNC(func->type))) { + CError_ASSERT(2797, arguments); + list->next = arguments->next; + arguments->next = list; + } else { + list->next = arguments; + arguments = list; + } + } + + for (list = arguments; list; list = list->next) { + NameSpaceObjectList *nsol = CScope_InsertName(cscope_current, list->object->name); + nsol->object = OBJ_BASE(list->object); + } +} + +NameSpace *CFunc_FuncGenSetup(Statement *stmt, Object *func) { + NameSpace *nspace; + DeclBlock *block; + + nspace = CScope_NewListNameSpace(NULL, 0); + nspace->parent = cscope_current; + cscope_current = nspace; + + arguments = NULL; + locals = NULL; + Labels = NULL; + + localcount = 0; + cfunc_staticvarcount = 0; + + CExcept_Setup(); + + memclrw(stmt, sizeof(Statement)); + curstmt = stmt; + stmt->type = ST_NOP; + curstmtvalue = 1; + stmt->value = 1; + + blockcount = 0; + block = lalloc(sizeof(DeclBlock)); + memclrw(block, sizeof(DeclBlock)); + block->index = blockcount++; + block->parent_nspace = cscope_current; + + firstblock = block; + currentblock = block; + + return nspace; +} + +CFuncSave *CFunc_GetGlobalCompilerState(void) { + CFuncSave *state; + + if (!cscope_currentfunc && !cscope_currentclass && cscope_current == cscope_root) + return NULL; + + locklheap(); + state = lalloc(sizeof(CFuncSave)); + + CScope_SetNameSpaceScope(cscope_root, &state->scope); + + state->arguments = arguments; + arguments = NULL; + + state->locals = locals; + locals = NULL; + + state->labels = Labels; + Labels = NULL; + + state->curstmt = curstmt; + curstmt = NULL; + + state->firstblock = firstblock; + firstblock = NULL; + + state->currentblock = currentblock; + currentblock = NULL; + + state->cexcept_dobjstack = cexcept_dobjstack; + cexcept_dobjstack = NULL; + + state->sinit_label = sinit_label; + sinit_label = NULL; + + state->ainit_expr = ainit_expr; + ainit_expr = NULL; + + state->ctor_chain = ctor_chain; + ctor_chain = NULL; + + state->cinit_tempnodefunc = cinit_tempnodefunc; + cinit_tempnodefunc = NULL; + + state->trychain = trychain; + trychain = NULL; + + state->cparser_fileoffset = cparser_fileoffset; + state->symdecltoken = symdecltoken; + + state->functionbodyoffset = functionbodyoffset; + functionbodyoffset = 0; + + state->functionbodypath = functionbodypath; + functionbodypath = NULL; + + state->symdecloffset = symdecloffset; + symdecloffset = 0; + + state->symdeclend = symdeclend; + + state->sourceoffset = sourceoffset; + sourceoffset = 0; + + state->sourcefilepath = sourcefilepath; + sourcefilepath = NULL; + + state->curstmtvalue = curstmtvalue; + curstmtvalue = 0; + + state->name_obj_check = name_obj_check; + name_obj_check = NULL; + + state->check_arglist = check_arglist; + check_arglist = NULL; + + state->blockcount = blockcount; + blockcount = 0; + + state->localcount = localcount; + localcount = 0; + + state->tk = tk; + state->tkidentifier = tkidentifier; + + state->global_access = global_access; + + state->cexcept_hasdobjects = cexcept_hasdobjects; + cexcept_hasdobjects = 0; + + state->sinit_first_object = sinit_first_object; + sinit_first_object = NULL; + + state->ainit_only_one = ainit_only_one; + ainit_only_one = 0; + + state->cfunc_is_extern_c = cfunc_is_extern_c; + cfunc_is_extern_c = 0; + + state->temp_reference_init = temp_reference_init; + + return state; +} + +void CFunc_SetGlobalCompilerState(CFuncSave *state) { + if (state) { + CScope_RestoreScope(&state->scope); + + arguments = state->arguments; + locals = state->locals; + Labels = state->labels; + curstmt = state->curstmt; + firstblock = state->firstblock; + currentblock = state->currentblock; + cexcept_dobjstack = state->cexcept_dobjstack; + sinit_label = state->sinit_label; + ainit_expr = state->ainit_expr; + ctor_chain = state->ctor_chain; + cinit_tempnodefunc = state->cinit_tempnodefunc; + trychain = state->trychain; + name_obj_check = state->name_obj_check; + check_arglist = state->check_arglist; + curstmtvalue = state->curstmtvalue; + cparser_fileoffset = state->cparser_fileoffset; + symdecltoken = state->symdecltoken; + functionbodyoffset = state->functionbodyoffset; + functionbodypath = state->functionbodypath; + symdecloffset = state->symdecloffset; + symdeclend = state->symdeclend; + sourceoffset = state->sourceoffset; + sourcefilepath = state->sourcefilepath; + blockcount = state->blockcount; + tk = state->tk; + tkidentifier = state->tkidentifier; + global_access = state->global_access; + localcount = state->localcount; + cexcept_hasdobjects = state->cexcept_hasdobjects; + sinit_first_object = state->sinit_first_object; + ainit_only_one = state->ainit_only_one; + cfunc_is_extern_c = state->cfunc_is_extern_c; + temp_reference_init = state->temp_reference_init; + + unlocklheap(); + } +} + +void CFunc_Gen(Statement *stmt, Object *func, UInt8 unk) { + Boolean flag; + CI_FuncData packed; + + if ((TYPE_FUNC(func->type)->flags & FUNC_FLAGS_400000) && !anyerrors) { + CInline_PackIFunctionData(&packed, stmt, func); + flag = 1; + } else { + flag = 0; + } + + CInline_GenFunc(stmt, func, unk); + + if (flag) + CClass_DefineCovariantFuncs(func, &packed); +} + +static void CFunc_CheckCtorInitializer(TypeClass *tclass, CtorChain *chain) { + ObjMemberVar *ivar; + CtorChain *scan; + + if (tclass->mode != CLASS_MODE_UNION) { + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + if (IS_TYPE_REFERENCE(ivar->type)) { + for (scan = chain; scan; scan = scan->next) { + if (scan->what == CtorChain_MemberVar && scan->u.membervar == ivar) + break; + } + + if (!scan) + CError_Error(CErrorStr256, ivar->name->name); + } else if (CParser_IsConst(ivar->type, ivar->qual)) { + for (scan = chain; scan; scan = scan->next) { + if (scan->what == CtorChain_MemberVar && scan->u.membervar == ivar) + break; + } + + if (!scan && !IS_TYPE_CLASS(ivar->type)) + CError_Error(CErrorStr255, ivar->name->name); + } + } + } +} + +void CFunc_CheckClassCtors(TypeClass *tclass) { + CFunc_CheckCtorInitializer(tclass, NULL); +} + +static void CFunc_ParseCtorInitializer(void) { + CtorChain *chain; + ENodeList *args; + TypeClass *tclass; + ObjMemberVar *ivar; + ClassList *base; + VClassList *vbase; + ENode *expr; + Type *origtype; + + ctor_chain = NULL; + + if (tk == ':') { + do { + tclass = NULL; + switch ((tk = lex())) { + case TK_IDENTIFIER: + for (ivar = cscope_currentclass->ivars; ivar; ivar = ivar->next) { + if (ivar->name == tkidentifier && lookahead() == '(') + goto do_ivar; + } + for (base = cscope_currentclass->bases; base; base = base->next) { + if (base->base->classname == tkidentifier) { + if (lookahead() == '(') { + tclass = base->base; + tk = lex(); + } else { + tkidentifier = base->base->classname; + } + break; + } + } + break; + + case TK_COLON_COLON: + break; + + default: + CError_Error(CErrorStr212); + return; + } + + if (!tclass) + tclass = CClass_GetQualifiedClass(); + + if (tclass) { + for (vbase = cscope_currentclass->vbases; vbase; vbase = vbase->next) { + if (vbase->base == tclass) + break; + } + + if (vbase) { + for (chain = ctor_chain; chain; chain = chain->next) { + if (chain->what == CtorChain_VBase && chain->u.vbase == vbase) { + CError_Error(CErrorStr212); + return; + } + } + + chain = lalloc(sizeof(CtorChain)); + chain->what = CtorChain_VBase; + chain->u.vbase = vbase; + } else { + for (base = cscope_currentclass->bases; base; base = base->next) { + if (base->base == tclass) + break; + } + + if (base) { + for (chain = ctor_chain; chain; chain = chain->next) { + if (chain->what == CtorChain_Base && chain->u.base == base) { + CError_Error(CErrorStr212); + return; + } + } + + chain = lalloc(sizeof(CtorChain)); + chain->what = CtorChain_Base; + chain->u.base = base; + } else { + CError_Error(CErrorStr212); + return; + } + } + } else { + for (ivar = cscope_currentclass->ivars; ivar; ivar = ivar->next) { + if (ivar->name == tkidentifier) + break; + } + + if (ivar) { + do_ivar: + for (chain = ctor_chain; chain; chain = chain->next) { + if (chain->what == CtorChain_MemberVar && chain->u.membervar == ivar) + CError_Error(CErrorStr212); + } + + chain = lalloc(sizeof(CtorChain)); + chain->what = CtorChain_MemberVar; + chain->u.membervar = ivar; + } else { + CError_Error(CErrorStr212); + return; + } + + tk = lex(); + } + + if (tk != '(') { + CError_Error(CErrorStr114); + return; + } + + tk = lex(); + args = CExpr_ScanExpressionList(1); + + if (tk != ')') { + CError_Error(CErrorStr115); + return; + } + + switch (chain->what) { + case CtorChain_Base: + expr = CABI_MakeThisExpr(NULL, chain->u.base->offset); + chain->objexpr = CExpr_ConstructObject(chain->u.base->base, expr, args, 1, 0, 0, 0, 1); + break; + case CtorChain_VBase: + expr = CABI_MakeThisExpr(chain->u.vbase->base, chain->u.vbase->offset); + chain->objexpr = CExpr_ConstructObject(chain->u.vbase->base, expr, args, 1, 0, 0, 0, 1); + break; + case CtorChain_MemberVar: + expr = CABI_MakeThisExpr(cscope_currentclass, chain->u.membervar->offset); + expr->flags = chain->u.membervar->qual & ENODE_FLAG_QUALS; + switch (chain->u.membervar->type->type) { + case TYPECLASS: + chain->objexpr = CExpr_ConstructObject(TYPE_CLASS(chain->u.membervar->type), expr, args, 1, 1, 0, 1, 1); + break; + case TYPEARRAY: + if (args) { + CError_Error(CErrorStr212); + continue; + } + chain->objexpr = NULL; + break; + default: + if (!args) { + args = lalloc(sizeof(ENodeList)); + args->next = NULL; + args->node = CExpr_DoExplicitConversion(chain->u.membervar->type, chain->u.membervar->qual, NULL); + } + if (args->next) { + CError_Error(CErrorStr212); + return; + } + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = chain->u.membervar->type; + if (IS_TYPE_BITFIELD(origtype = expr->rtype)) { + expr->data.monadic = makemonadicnode(expr->data.monadic, EBITFIELD); + expr->data.monadic->rtype = origtype; + expr->rtype = TYPE_BITFIELD(origtype)->bitfieldtype; + } + + chain->objexpr = makediadicnode(expr, CExpr_AssignmentPromotion(args->node, expr->rtype, expr->flags, 1), EASS); + } + break; + default: + CError_FATAL(3286); + } + + chain->next = ctor_chain; + ctor_chain = chain; + } while ((tk = lex()) == ','); + } +} + +static void CFunc_FunctionRedefinedCheck(Object *func) { + if (TYPE_FUNC(func->type)->flags & FUNC_AUTO_GENERATED) + CError_Error(CErrorStr333, func); + + if ((TYPE_FUNC(func->type)->flags & FUNC_DEFINED) && func->datatype != DINLINEFUNC) + CError_Error(CErrorStr333, func); + + TYPE_FUNC(func->type)->flags |= FUNC_DEFINED; +} + +static Object *CFunc_DeclareFuncName(char *str, HashNameNode *name) { + Object *obj; + Object *aliasobj; + DeclInfo di; + + memclrw(&di, sizeof(di)); + di.name = name; + di.storageclass = TK_STATIC; + di.qual = Q_CONST; + di.thetype = CDecl_NewArrayType(TYPE(&stchar), strlen(str) + 1); + + obj = CParser_NewGlobalDataObject(&di); + aliasobj = CParser_NewAliasObject(obj, 0); + obj->nspace = cscope_root; + obj->datatype = DDATA; + CFunc_NameLocalStaticDataObject(obj, obj->name->name); + + return aliasobj; +} + +void CFunc_ParseFuncDef(Object *func, DeclInfo *di, TypeClass *tclass, Boolean is_method, Boolean is_static, NameSpace *nspace) { + Boolean has_try; + Object *nameobj_func; + Object *nameobj_FUNCTION; + Object *nameobj_pretty; + char *prettyname; + Statement *stmt18; + Statement *stmt16; + Statement firstStmt; + DeclThing thing; + CScopeSave scope; + + nameobj_func = NULL; + nameobj_FUNCTION = NULL; + nameobj_pretty = NULL; + prettyname = NULL; + + CError_ASSERT(3373, IS_TYPE_FUNC(func->type)); + + CFunc_FunctionRedefinedCheck(func); + CParser_UpdateObject(func, di); + + if (!is_method) { + CScope_SetFunctionScope(func, &scope); + if (tclass) + cscope_current = tclass->nspace; + } else { + CScope_SetMethodScope(func, tclass, is_static, &scope); + } + + if (nspace) + cscope_current = nspace; + + if (cscope_currentclass) + CClass_MemberDef(func, cscope_currentclass); + + cfunc_is_extern_c = di->is_extern_c; + + CError_ASSERT(3392, IS_TYPE_FUNC(func->type)); + if (di->x45 && (func->qual & Q_ASM)) + CError_Error(CErrorStr176); + + if (cparamblkptr->precompile == 1 && !(func->qual & Q_INLINE)) + CError_ErrorTerm(CErrorStr180); + + if (di->x49) + CError_Error(CErrorStr127); + + CFunc_FuncGenSetup(&firstStmt, func); + if (!IS_TYPE_VOID(TYPE_FUNC(func->type)->functype)) + IsCompleteType(TYPE_FUNC(func->type)->functype); + + SetupFunctionArguments(func, di, &firstStmt); + + stmt18 = curstmt; + CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); + functionbodyoffset = sourceoffset; + firstStmt.sourceoffset = sourceoffset; + functionbodypath = sourcefilepath; + firstStmt.sourcefilepath = sourcefilepath; + + if (di->x45) + CFunc_AdjustOldStyleArgs(); + + if (di->x1C) + CScope_MergeNameSpace(cscope_current, di->x1C); + + if (tk == TK_TRY) { + tk = lex(); + has_try = 1; + } else { + has_try = 0; + } + + if (CClass_IsConstructor(func)) { + CError_ASSERT(3445, cscope_currentclass); + CFunc_ParseCtorInitializer(); + CFunc_CheckCtorInitializer(cscope_currentclass, ctor_chain); + } + + CPrep_TokenStreamFlush(); + + if (!(func->qual & Q_ASM)) { + if (tk == '{') { + if (!has_try) + tk = lex(); + } else { + CError_ErrorSkip(CErrorStr135); + has_try = 0; + } + + if (func->name) { + nameobj_func = CFunc_DeclareFuncName(func->name->name, GetHashNameNode("__func__")); + nameobj_FUNCTION = CFunc_DeclareFuncName(func->name->name, GetHashNameNode("__FUNCTION__")); + prettyname = CError_GetObjectName(func); + nameobj_pretty = CFunc_DeclareFuncName(prettyname, GetHashNameNode("__PRETTY_FUNCTION__")); + } + + if (!copts.cplusplus) + CFunc_ParseLocalDeclarationList(0, 0, 0, 0); + + thing.switchinfo = NULL; + thing.loopContinue = NULL; + thing.loopBreak = NULL; + thing.thetype = TYPE_FUNC(func->type)->functype; + thing.qual = TYPE_FUNC(func->type)->qual; + + if (has_try) { + CExcept_ScanTryBlock(&thing, CClass_IsConstructor(func) || CClass_IsDestructor(func)); + if (tk != 0) + CPrep_UnLex(); + tk = '}'; + } else { + while (tk != '}') + statement(&thing); + } + + stmt16 = curstmt; + + if (stmt16->type != ST_RETURN && stmt16->type != ST_GOTO) { + CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); + CFunc_AppendStatement(ST_RETURN); + + curstmt->dobjstack = NULL; + curstmt->expr = NULL; + + if ( + (copts.cplusplus || copts.c9x) && + !strcmp(func->name->name, "main") && + TYPE_FUNC(func->type)->functype == TYPE(&stsignedint) + ) + curstmt->expr = intconstnode(TYPE(&stsignedint), 0); + + if ( + stmt16->type == ST_EXPRESSION && + stmt16->expr->type == EFUNCCALL && + stmt16->expr->rtype == &stvoid && + (stmt16->expr->flags & ENODE_FLAG_VOLATILE) + ) + curstmt->flags = curstmt->flags | StmtFlag_8; + } + + CheckCLabels(); + + if (nameobj_func && (nameobj_func->flags & OBJECT_USED)) + CInit_DeclareData(nameobj_func->u.alias.object, func->name->name, NULL, strlen(func->name->name) + 1); + if (nameobj_FUNCTION && (nameobj_FUNCTION->flags & OBJECT_USED)) + CInit_DeclareData(nameobj_FUNCTION->u.alias.object, func->name->name, NULL, strlen(func->name->name) + 1); + if (nameobj_pretty && (nameobj_pretty->flags & OBJECT_USED)) + CInit_DeclareData(nameobj_pretty->u.alias.object, prettyname, NULL, strlen(prettyname) + 1); + + if (!fatalerrors) { + if (CClass_IsConstructor(func)) + CABI_TransConstructor(func, stmt18, cscope_currentclass, NULL, has_try); + if (CClass_IsDestructor(func)) + CABI_TransDestructor(func, func, &firstStmt, cscope_currentclass, 0); + + CFunc_DestructorCleanup(&firstStmt); + CFunc_CodeCleanup(&firstStmt); + symdeclend = CPrep_GetFileOffsetInfo(&cparser_fileoffset); + CFunc_Gen(&firstStmt, func, di->x45); + } + } else { + if (tk == '{') { + in_assembler = 1; + tk = lex(); + in_assembler = 0; + } else { + CError_ErrorSkip(CErrorStr135); + } + + CFunc_ParseLocalDeclarationList(1, 0, 0, 0); + Assembler(func); + } + + if (tk != '}') + CError_Error(CErrorStr130); + + CScope_RestoreScope(&scope); +} + +void InitExpr_Register(ENode *expr, Object *object) { + InitExpr *initexpr; + InitExpr *scan; + + if ( + cparamblkptr->precompile == 1 && + object->sclass != TK_STATIC && + !(object->qual & (Q_20000 | Q_WEAK)) + ) + { + CError_Error(CErrorStr180); + return; + } + + if (copts.suppress_init_code) + return; + + initexpr = galloc(sizeof(InitExpr)); + initexpr->next = NULL; + initexpr->object = object; + initexpr->expr = CInline_CopyExpression(expr, CopyMode1); + + if (init_expressions) { + scan = init_expressions; + while (scan->next) + scan = scan->next; + scan->next = initexpr; + } else { + init_expressions = initexpr; + } +} + +void CFunc_GenerateDummyFunction(Object *func) { + NameSpace *nspace; + Boolean saveDebugInfo; + Statement firstStmt; + + if (!anyerrors) { + nspace = CFunc_FuncGenSetup(&firstStmt, NULL); + + saveDebugInfo = copts.filesyminfo; + copts.filesyminfo = 0; + + CFunc_CodeCleanup(&firstStmt); + CFunc_Gen(&firstStmt, func, 0); + + cscope_current = nspace->parent; + copts.filesyminfo = saveDebugInfo; + } +} + +void CFunc_GenerateSingleExprFunc(Object *func, ENode *expr) { + NameSpace *nspace; + Boolean saveDebugInfo; + Statement firstStmt; + Statement *stmt; + + if (cparamblkptr->precompile == 1) { + CError_Error(CErrorStr180); + return; + } + + if (!anyerrors) { + nspace = CFunc_FuncGenSetup(&firstStmt, func); + + saveDebugInfo = copts.filesyminfo; + copts.filesyminfo = 0; + + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = expr; + + CFunc_CodeCleanup(&firstStmt); + CInline_GenFunc(&firstStmt, func, 0); + + cscope_current = nspace->parent; + copts.filesyminfo = saveDebugInfo; + } +} + +void CFunc_GenerateDummyCtorFunc(Object *func, Object *real_ctor) { + ENode *expr; + NameSpace *nspace; + FuncArg *arg1; + FuncArg *arg0; + ENodeList *list; + Boolean saveDebugInfo; + Statement firstStmt; + Statement *stmt; + + if (cparamblkptr->precompile == 1) { + CError_Error(CErrorStr180); + return; + } + + if (!anyerrors) { + cscope_currentfunc = func; + + nspace = CFunc_FuncGenSetup(&firstStmt, func); + + saveDebugInfo = copts.filesyminfo; + copts.filesyminfo = 0; + + CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); + + expr = CExpr_NewENode(EFUNCCALL); + expr->type = EFUNCCALL; + expr->cost = 200; + expr->rtype = TYPE(&void_ptr); + expr->data.funccall.funcref = CExpr_MakeObjRefNode(real_ctor, 0); + expr->data.funccall.functype = TYPE_FUNC(func->type); + + CError_ASSERT(3716, IS_TYPE_FUNC(real_ctor->type)); + CError_ASSERT(3717, TYPE_FUNC(real_ctor->type)->flags & FUNC_METHOD); + CError_ASSERT(3718, arg0 = TYPE_FUNC(real_ctor->type)->args); + CError_ASSERT(3720, arg1 = arg0->next); + CError_ASSERT(3721, arguments); + + list = lalloc(sizeof(ENodeList)); + expr->data.funccall.args = list; + list->node = create_objectnode(arguments->object); + + if (TYPE_METHOD(real_ctor->type)->theclass->flags & CLASS_HAS_VBASES) { + CError_ASSERT(3727, arg1 = arg1->next); + CError_ASSERT(3728, arguments->next); + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = create_objectnode(arguments->next->object); + } + + while (arg1) { + CError_ASSERT(3737, arg1->dexpr); + list->next = lalloc(sizeof(ENodeList)); + list = list->next; + list->node = CExpr_GetDefaultArgument(expr->data.funccall.funcref, arg1); + arg1 = arg1->next; + } + + list->next = NULL; + + stmt = CFunc_AppendStatement(ST_RETURN); + stmt->expr = expr; + + CFunc_CodeCleanup(&firstStmt); + CInline_GenFunc(&firstStmt, func, 0); + + cscope_current = nspace->parent; + cscope_currentfunc = NULL; + copts.filesyminfo = saveDebugInfo; + } +} diff --git a/compiler_and_linker/FrontEnd/C/CInit.c b/compiler_and_linker/FrontEnd/C/CInit.c new file mode 100644 index 0000000..c2d2299 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CInit.c @@ -0,0 +1,3082 @@ +#include "compiler/CInit.h" +#include "compiler/CABI.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CException.h" +#include "compiler/CExpr.h" +#include "compiler/CInline.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CPrec.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/CompilerTools.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +TempNodeCB cinit_tempnodefunc; +InitInfo *cinit_initinfo; +static PooledString *cinit_stringlist; +static PooledString *cinit_pooledstringlist; +static PooledString *cinit_pooledwstringlist; +static ObjectList *cinit_tentative; +static TypeClass *cinit_loop_class; +static ENodeList *cinit_fdtnode; +static Boolean cinit_fdtambig; + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct CInit_1C { + struct CInit_1C *next; + Type *type; + ENode *expr; + SInt32 offset; +} CInit_1C; + +typedef struct CInit_Stuff { + struct CInit_Stuff *x0; + struct CInit_Stuff *x4; + char *buffer; + SInt32 xC; + SInt32 size; + SInt32 bufferSize; + SInt32 x18; + CInit_1C *x1C; + OLinkList *list; + Boolean flag; +} CInit_Stuff; + +typedef enum { + Stage0, + Stage1, + Stage2, + Stage3, + Stage4 +} Stage; + +typedef struct CInit_Stuff2 { + ENode *expr; + ENode myexpr; + Stage stage; + Boolean x23; + SInt32 x24; + Type *type; +} CInit_Stuff2; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +// forward decls +static void CInit_InitType(CInit_Stuff *s, CInit_Stuff2 *s2, Type *type, UInt32 qual, Boolean flag); +static void CInit_Type(Type *type, UInt32 qual, Boolean flag); + +void CInit_Init(void) { + cinit_tempnodefunc = NULL; + cinit_initinfo = NULL; + cinit_stringlist = NULL; + cinit_pooledstringlist = NULL; + cinit_pooledwstringlist = NULL; + cinit_tentative = NULL; +} + +static void CInit_SetupInitInfo(InitInfo *info, Object *obj) { + memclrw(info, sizeof(InitInfo)); + info->obj = obj; + info->next = cinit_initinfo; + cinit_initinfo = info; +} + +static void CInit_CleanupInitInfo(InitInfo *info) { + cinit_initinfo = info->next; +} + +static void CInit_SetupInitInfoBuffer(Type *type) { + SInt32 size = type->size; + cinit_initinfo->size = size; + + if (!size) + size = 512; + else if (size & 1) + size++; + + cinit_initinfo->buffer = lalloc(size); + cinit_initinfo->bufferSize = size; + memclrw(cinit_initinfo->buffer, size); +} + +static void CInit_SetData(void *data, SInt32 offset, SInt32 size) { + SInt32 end; + char *buffer; + + end = offset + size; + if (end > cinit_initinfo->size) + cinit_initinfo->size = end; + + if (end > cinit_initinfo->bufferSize) { + if (cinit_initinfo->obj->type->size == 0) { + if (end < 8000) + end += 0x400; + else + end += 0x4000; + } + if (end & 1) + end++; + + buffer = lalloc(end); + memclrw(buffer, end); + memcpy(buffer, cinit_initinfo->buffer, cinit_initinfo->bufferSize); + cinit_initinfo->buffer = buffer; + cinit_initinfo->bufferSize = end; + } + + if (data) + memcpy(cinit_initinfo->buffer + offset, data, size); +} + +typedef struct CInit_Initializer { + struct CInit_Initializer *next; + struct CInit_Initializer *sublist; + ENode *expr; + TStreamElement element; +} CInit_Initializer; + +static CInit_Initializer *CInit_ParseInitializerList(void) { + CInit_Initializer *r30; + CInit_Initializer *r29; + CInit_Initializer *tmp; + + if ((tk = lex()) == '}') + return NULL; + + r30 = NULL; + do { + if (r30) { + tmp = lalloc(sizeof(CInit_Initializer)); + r29->next = tmp; + r29 = tmp; + } + if (!r30) { + r30 = r29 = lalloc(sizeof(CInit_Initializer)); + } + r29->next = NULL; + + if (tk == '{') { + r29->element = *CPrep_CurStreamElement(); + r29->sublist = CInit_ParseInitializerList(); + r29->expr = NULL; + tk = lex(); + } else { + r29->sublist = NULL; + r29->expr = conv_assignment_expression(); + r29->element = *CPrep_CurStreamElement(); + } + + if (tk == '}') + return r30; + + if (tk != ',') { + CError_Error(CErrorStr116); + return r30; + } + } while ((tk = lex()) != '}'); + + return r30; +} + +static CInit_Initializer *CInit_ParseInitializerClause(void) { + CInit_Initializer *init; + + init = lalloc(sizeof(CInit_Initializer)); + init->next = NULL; + if (tk != '{') { + init->sublist = NULL; + init->expr = conv_assignment_expression(); + init->element = *CPrep_CurStreamElement(); + } else { + init->element = *CPrep_CurStreamElement(); + init->expr = NULL; + init->sublist = CInit_ParseInitializerList(); + tk = lex(); + } + + return init; +} + +static ENode *CInit_ParseInitializer(ENode *expr) { + CInt64 save_int; + Float save_float; + SInt32 save_size; + short t; + + switch (tk) { + case TK_INTCONST: + case TK_FLOATCONST: + save_int = tkintconst; + save_float = tkfloatconst; + save_size = tksize; + t = lookahead(); + tkintconst = save_int; + tkfloatconst = save_float; + tksize = save_size; + + switch (t) { + case ',': + case ';': + case '}': + memclrw(expr, sizeof(ENode)); + switch (tk) { + case TK_INTCONST: + expr->type = EINTCONST; + expr->rtype = atomtype(); + expr->data.intval = tkintconst; + break; + case TK_FLOATCONST: + expr->type = EFLOATCONST; + expr->rtype = atomtype(); + expr->data.floatval = tkfloatconst; + break; + } + tk = lex(); + CPrep_TokenStreamFlush(); + return expr; + } + } + + expr = assignment_expression(); + CPrep_TokenStreamFlush(); + return expr; +} + +static Stage CInit_ParseNextInit(CInit_Stuff2 *s) { + DeclInfo di; + short t; + + s->expr = NULL; + if (tk == ';') { + s->stage = Stage4; + return Stage4; + } + switch (s->stage) { + case Stage0: + if (s->x23) { + if (tk == '(') { + tk = lex(); + CParser_GetDeclSpecs(&di, 1); + s->type = di.thetype; + if (tk == ')') + tk = lex(); + else + CError_Error(CErrorStr115); + + if (tk == '(') + tk = lex(); + else + CError_Error(CErrorStr114); + s->x24++; + t = lookahead(); + if (t == TK_UU_VECTOR || (t == TK_IDENTIFIER && !strcmp("vector", tkidentifier->name))) + CInit_ParseNextInit(s); + s->stage = Stage1; + return Stage1; + } + } else { + if (tk == '{') { + tk = lex(); + s->x24 = 0; + s->stage = Stage1; + return Stage1; + } + } + s->expr = CInit_ParseInitializer(&s->myexpr); + s->stage = Stage2; + return Stage2; + case Stage1: + break; + case Stage2: + case Stage3: + if (tk == ',') { + tk = lex(); + break; + } + if (s->x24) { + if (tk != ')') + CError_Error(CErrorStr174); + if (s->x24 > 1) { + s->x24--; + tk = lex(); + CInit_ParseNextInit(s); + } + } else { + if (tk != '}') + CError_Error(CErrorStr174); + } + s->stage = Stage3; + return Stage3; + default: + CError_FATAL(389); + } + + switch (tk) { + case '{': + tk = lex(); + s->stage = Stage1; + return Stage1; + case '}': + s->stage = Stage3; + return Stage3; + case '(': + if (s->x23) { + tk = lex(); + s->stage = Stage1; + return Stage1; + } + case ')': + if (s->x23 && s->x24) { + if (s->x24 > 1) { + s->x24--; + tk = lex(); + CInit_ParseNextInit(s); + } + s->stage = Stage3; + return Stage3; + } + default: + s->expr = CInit_ParseInitializer(&s->myexpr); + s->stage = Stage2; + return Stage2; + } +} + +static void CInit_CloseInitList(void) { + if (tk == ',' && copts.cplusplus) + tk = lex(); + + if (tk != '}') + CError_ErrorSkip(CErrorStr130); + else + tk = lex(); +} + +static Boolean CInit_IsAllZero(char *buf, SInt32 size) { + SInt32 i; + + if (copts.explicit_zero_data) + return 0; + + for (i = 0; i < size; i++) + if (buf[i]) return 0; + + return 1; +} + +static Boolean CInit_ClassNeedsConstruction(TypeClass *tclass) { + return CClass_Constructor(tclass) || CClass_Destructor(tclass); +} + +static Boolean CInit_IsSimpleStructArrayInit(Type *type) { + switch (type->type) { + case TYPESTRUCT: + return 1; + case TYPEARRAY: + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (!IS_TYPE_CLASS(type)) + return 1; + case TYPECLASS: + return !CInit_ClassNeedsConstruction(TYPE_CLASS(type)); + default: + return 0; + } +} + +static Boolean CInit_IsSimpleInit(Type *type) { + switch (type->type) { + case TYPEPOINTER: + return (TYPE_POINTER(type)->qual & Q_REFERENCE) == 0; + case TYPEARRAY: + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (!IS_TYPE_CLASS(type)) + return 1; + case TYPECLASS: + return !CInit_ClassNeedsConstruction(TYPE_CLASS(type)); + default: + return 1; + } +} + +static Object *CInit_GetInitObject(Object *obj) { + if (obj->datatype == DALIAS) { + CError_ASSERT(521, !obj->u.alias.offset); + obj = obj->u.alias.object; + } + return obj; +} + +static Object *CInit_CreateStaticDataObject(Type *type, UInt32 qual, HashNameNode *name) { + Object *obj; + DeclInfo di; + + memclrw(&di, sizeof(DeclInfo)); + di.thetype = type; + di.name = name ? name : CParser_GetUniqueName(); + di.qual = qual; + di.storageclass = TK_STATIC; + di.is_extern_c = 1; + + obj = CParser_NewGlobalDataObject(&di); + obj->nspace = cscope_root; + return obj; +} + +static Type *CInit_GetRegMemType(void) { + return CDecl_NewStructType(void_ptr.size * 3, CMach_GetTypeAlign((Type *) &void_ptr)); +} + +static Object *CInit_CreateStaticData(Type *type) { + Object *obj = CInit_CreateStaticDataObject(type, 0, NULL); + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + return obj; +} + +static void CInit_InitNonConst(CInit_Stuff *s, Type *type, ENode *expr) { + CInit_1C *entry; + CInit_1C *scan; + MWVector128 *vec; + + if (s->x4->flag || IS_TYPE_VECTOR(type)) { + if (IS_TYPE_VECTOR(type) && ENODE_IS(expr, EVECTOR128CONST)) { + vec = (MWVector128 *) (s->buffer + s->size); + *vec = expr->data.vector128val; + CMach_InitVectorMem(type, *vec, vec, 1); + } + + entry = lalloc(sizeof(CInit_1C)); + memclrw(entry, sizeof(CInit_1C)); + entry->next = NULL; + entry->type = type; + entry->expr = expr; + entry->offset = s->xC + s->size; + if ((scan = s->x4->x1C)) { + while (scan->next) + scan = scan->next; + scan->next = entry; + } else { + s->x4->x1C = entry; + } + } else { + CError_Error(CErrorStr124); + } +} + +static CInit_Stuff *CInit_GrowBuffer(CInit_Stuff *s, SInt32 size) { + CInit_Stuff *newbuf; + + newbuf = lalloc(sizeof(CInit_Stuff)); + memclrw(newbuf, sizeof(CInit_Stuff)); + newbuf->x4 = s->x4; + newbuf->buffer = lalloc(size); + newbuf->xC = s->xC + s->size; + newbuf->bufferSize = size; + s->x0 = newbuf; + memset(newbuf->buffer, 0, newbuf->bufferSize); + return newbuf; +} + +Boolean CInit_RelocInitCheck(ENode *expr, Object **objptr, CInt64 *valptr, Boolean flag) { + Object *objcheck1; + Object *objcheck2; + CInt64 valcheck1; + CInt64 valcheck2; + + *objptr = NULL; + valptr->lo = 0; + valptr->hi = 0; + + while (1) { + switch (expr->type) { + case EINTCONST: + *valptr = expr->data.intval; + return 1; + case EOBJREF: + objcheck1 = CInit_GetInitObject(expr->data.objref); + if (objcheck1->datatype == DLOCAL && !flag) + return 0; + *objptr = objcheck1; + return 1; + case ESTRINGCONST: + CInit_RewriteString(expr, 0); + continue; + case ETYPCON: + do { + if (expr->rtype->size != expr->data.monadic->rtype->size) + return 0; + expr = expr->data.monadic; + if (!IS_TYPE_POINTER_ONLY(expr->rtype) && !IS_TYPE_INT(expr->rtype)) + return 0; + } while (ENODE_IS(expr, ETYPCON)); + continue; + case EADD: + if (!CInit_RelocInitCheck(expr->data.diadic.left, &objcheck1, &valcheck1, flag)) + return 0; + if (!CInit_RelocInitCheck(expr->data.diadic.right, &objcheck2, &valcheck2, flag)) + return 0; + + if (objcheck1) { + if (objcheck2) + return 0; + *objptr = objcheck1; + } else { + *objptr = objcheck1; + } + + *valptr = CMach_CalcIntDiadic(TYPE(&stunsignedlong), valcheck1, '+', valcheck2); + return 1; + case ESUB: + if (!CInit_RelocInitCheck(expr->data.diadic.left, &objcheck1, &valcheck1, flag)) + return 0; + if (!CInit_RelocInitCheck(expr->data.diadic.right, &objcheck2, &valcheck2, flag)) + return 0; + + if (objcheck2) + return 0; + + *objptr = objcheck1; + *valptr = CMach_CalcIntDiadic(TYPE(&stunsignedlong), valcheck1, '-', valcheck2); + return 1; + default: + return 0; + } + } +} + +static void CInit_InitTypePointer(CInit_Stuff *s, ENode *expr, TypePointer *tptr, UInt32 qual) { + Object *obj; + CInt64 val; + OLinkList *list; + + expr = CExpr_AssignmentPromotion(expr, TYPE(tptr), qual & (Q_CONST | Q_VOLATILE), 1); + if (IS_TYPE_POINTER_ONLY(expr->rtype) || ENODE_IS(expr, EINTCONST)) { + if (CInit_RelocInitCheck(expr, &obj, &val, 0)) { + if (obj) { + list = lalloc(sizeof(OLinkList)); + list->next = s->x4->list; + list->obj = obj; + list->somevalue = CInt64_GetULong(&val); + list->offset = s->xC + s->size; + s->x4->list = list; + } else { + CMach_InitIntMem(TYPE(&stunsignedlong), val, s->buffer + s->size); + } + } else { + CInit_InitNonConst(s, TYPE(tptr), expr); + } + } else { + CError_Error(CErrorStr174); + } +} + +static void CInit_InitTypeInt(CInit_Stuff *s, ENode *expr, TypeIntegral *tint, UInt32 qual) { + expr = CExpr_AssignmentPromotion(expr, TYPE(tint), qual & (Q_CONST | Q_VOLATILE), 1); + if (IS_TYPE_INT(expr->rtype)) { + if (ENODE_IS(expr, EINTCONST)) { + CMach_InitIntMem(TYPE(tint), expr->data.intval, s->buffer + s->size); + } else if (ENODE_IS(expr, ETYPCON) && IS_TYPE_POINTER_ONLY(expr->data.monadic->rtype) && expr->rtype->size == 4 && (copts.cplusplus || !copts.ANSIstrict)) { + CInit_InitTypePointer(s, expr->data.monadic, TYPE_POINTER(expr->data.monadic->rtype), qual); + } else { + CInit_InitNonConst(s, TYPE(tint), expr); + } + } else { + CError_Error(CErrorStr174); + } +} + +static void CInit_InitTypeFloat(CInit_Stuff *s, ENode *expr, TypeIntegral *tint, UInt32 qual) { + expr = CExpr_AssignmentPromotion(expr, TYPE(tint), qual & (Q_CONST | Q_VOLATILE), 1); + if (IS_TYPE_FLOAT(expr->rtype)) { + if (ENODE_IS(expr, EFLOATCONST)) { + CMach_InitFloatMem(TYPE(tint), expr->data.floatval, s->buffer + s->size); + } else { + CInit_InitNonConst(s, TYPE(tint), expr); + } + } else { + CError_Error(CErrorStr174); + } +} + +static void CInit_InitTypeEnum(CInit_Stuff *s, ENode *expr, TypeEnum *tenum, UInt32 qual) { + expr = CExpr_AssignmentPromotion(expr, TYPE(tenum), qual & (Q_CONST | Q_VOLATILE), 1); + if (IS_TYPE_ENUM(expr->rtype)) { + if (ENODE_IS(expr, EINTCONST)) { + CMach_InitIntMem(tenum->enumtype, expr->data.intval, s->buffer + s->size); + } else { + CInit_InitNonConst(s, TYPE(tenum), expr); + } + } else { + CError_Error(CErrorStr174); + } +} + +static void CInit_InitTypeMemberPointer(CInit_Stuff *s, ENode *expr, TypeMemberPointer *tmptr, UInt32 qual) { + expr = CExpr_AssignmentPromotion(expr, TYPE(tmptr), qual & (Q_CONST | Q_VOLATILE), 1); + if (ENODE_IS(expr, EINTCONST)) { + CMach_InitIntMem(TYPE(&stsignedlong), expr->data.intval, s->buffer + s->size); + } else { + CInit_InitNonConst(s, TYPE(tmptr), expr); + } +} + +static void CInit_SetBitfield(TypeBitfield *tbitfield, UInt8 *buffer, CInt64 val) { + int i; + int pos; + int step; + + if (copts.littleendian) { + pos = tbitfield->offset; + step = 1; + } else { + pos = tbitfield->bitlength + tbitfield->offset - 1; + step = -1; + } + for (i = 0; i < tbitfield->bitlength; i++, pos += step) { + if (CInt64_GetULong(&val) & 1) { + if (copts.littleendian) { + buffer[pos >> 3] |= 1 << (pos & 7); + } else { + buffer[pos >> 3] |= 0x80 >> (pos & 7); + } + } + val = CInt64_ShrU(val, cint64_one); + } +} + +static void CInit_InitTypeBitfield(CInit_Stuff *s, ENode *expr, TypeBitfield *tbitfield, UInt32 qual) { + Type *inner; + + inner = tbitfield->bitfieldtype; + if (IS_TYPE_ENUM(inner)) + inner = TYPE_ENUM(inner)->enumtype; + expr = CExpr_AssignmentPromotion(expr, inner, qual & (Q_CONST | Q_VOLATILE), 1); + + if (IS_TYPE_INT(expr->rtype)) { + if (ENODE_IS(expr, EINTCONST)) { + CInit_SetBitfield(tbitfield, (UInt8 *) s->buffer + s->size, expr->data.intval); + } else { + CInit_InitNonConst(s, TYPE(tbitfield), expr); + } + } else { + CError_Error(CErrorStr174); + } +} + +static void CInit_InitTypeArray(CInit_Stuff *s, CInit_Stuff2 *s2, TypePointer *tptr, UInt32 qual, Boolean errorflag) { + SInt32 targetsize; + SInt32 start; + SInt32 i; + Boolean flag; + Boolean is_zero_size; + SInt32 size; + SInt32 tmp; + Boolean is_char_ptr; + Boolean is_wchar_ptr; + + is_zero_size = tptr->size == 0; + targetsize = tptr->target->size; + if (!targetsize) { + CError_Error(CErrorStr145); + return; + } + + is_char_ptr = IS_TYPE_INT(tptr->target) && (targetsize == 1); + is_wchar_ptr = IS_TYPE_INT(tptr->target) && (targetsize == stwchar.size); + switch (s2->stage) { + case Stage1: + flag = 1; + if (CInit_ParseNextInit(s2) == Stage3) { + if (is_zero_size) + CError_Error(CErrorStr174); + tk = lex(); + return; + } + break; + case Stage2: + flag = 0; + break; + } + switch (s2->stage) { + case Stage1: + case Stage2: + break; + default: + CError_Error(CErrorStr174); + return; + } + + if (s2->stage == Stage2) + s2->expr = pointer_generation(s2->expr); + + if (s2->stage == Stage2 && ENODE_IS(s2->expr, ESTRINGCONST) && (is_char_ptr || is_wchar_ptr)) { + if (IS_TYPE_POINTER_ONLY(s2->expr->rtype) && tptr->target->size != TYPE_POINTER(s2->expr->rtype)->target->size) + CError_Warning(CErrorStr174); + size = tmp = s2->expr->data.string.size; + if (is_zero_size) { + tptr->size = s2->expr->data.string.size; + if (s->bufferSize < tmp) + s = CInit_GrowBuffer(s, tmp); + memcpy(s->buffer, s2->expr->data.string.data, size); + s->size = size; + } else { + if (s2->expr->data.string.size > tptr->size) { + if (copts.cplusplus || (s2->expr->data.string.size - 1) > tptr->size) + CError_Error(CErrorStr147); + s2->expr->data.string.size = tptr->size; + size = tptr->size; + } + memcpy(s->buffer + s->size, s2->expr->data.string.data, size); + } + } else { + if (!flag && errorflag) { + CError_Error(CErrorStr174); + return; + } + + start = s->size; + i = 0; + while (1) { + if (is_zero_size) { + size = (i + 1) * targetsize; + s->size = start + size - targetsize - s->xC; + if (s->size + targetsize > s->bufferSize) + s = CInit_GrowBuffer(s, targetsize * 16); + CInit_InitType(s, s2, tptr->target, qual, 0); + tptr->size = size; + s->size = start + size - s->xC; + } else { + if (tptr->size <= i * targetsize) { + i--; + CError_Error(CErrorStr147); + } + s->size = start + i * targetsize; + CInit_InitType(s, s2, tptr->target, qual, 0); + if (!flag && tptr->size <= (i + 1) * targetsize) + break; + } + + switch (CInit_ParseNextInit(s2)) { + case Stage1: + case Stage2: + break; + case Stage3: + if (flag) + tk = lex(); + return; + default: + CError_Error(CErrorStr130); + return; + } + + i++; + } + } + + if (flag) { + switch (CInit_ParseNextInit(s2)) { + case Stage3: + tk = lex(); + return; + case Stage2: + CError_Error(CErrorStr147); + return; + default: + CError_Error(CErrorStr130); + } + } +} + +static void CInit_InitTypeStruct(CInit_Stuff *s, CInit_Stuff2 *s2, const TypeStruct *tstruct, UInt32 qual, Boolean errorflag) { + StructMember *member; + SInt32 start; + Boolean flag; + SInt32 count; + TypePointer arraytype; + MWVector128 *vecp; + int i; + + count = 0; + if (s2->type) + tstruct = TYPE_STRUCT(s2->type); + + if (!(member = tstruct->members)) { + CError_Error(CErrorStr145); + return; + } + + switch (s2->stage) { + case Stage1: + flag = 1; + if (CInit_ParseNextInit(s2) == Stage3) { + tk = lex(); + return; + } + break; + case Stage2: + flag = 0; + break; + } + + switch (s2->stage) { + case Stage1: + case Stage2: + break; + default: + CError_Error(CErrorStr174); + return; + } + + if (!flag && s2->stage == Stage2 && (errorflag || s2->expr->rtype == TYPE(tstruct))) { + s2->expr = CExpr_AssignmentPromotion(s2->expr, TYPE(tstruct), qual, 1); + if (IS_TYPE_STRUCT(s2->expr->rtype)) + CInit_InitNonConst(s, TYPE(tstruct), s2->expr); + return; + } + + start = s->size; + while (1) { + s->size = start + member->offset; + if (!member->type->size) { + if (!errorflag || !IS_TYPE_ARRAY(member->type)) { + CError_Error(CErrorStr147); + if (!IS_TYPE_ARRAY(member->type)) + return; + } + + arraytype = *TYPE_POINTER(member->type); + CInit_InitTypeArray(s, s2, &arraytype, member->qual, 1); + s->x18 = arraytype.size; + } else { + CInit_InitType(s, s2, member->type, member->qual, 0); + } + + count++; + if (IS_TYPESTRUCT_VECTOR(tstruct) && s2->expr) + CError_ASSERT(1218, !ENODE_IS(s2->expr, EVECTOR128CONST)); + + do { + member = member->next; + } while (member && (member->qual & Q_WEAK)); + + if (!member || tstruct->stype == STRUCT_TYPE_UNION) { + if (flag) { + switch (CInit_ParseNextInit(s2)) { + case Stage3: + if (IS_TYPESTRUCT_VECTOR(tstruct)) { + vecp = (MWVector128 *) (s->buffer + start); + CMach_InitVectorMem(TYPE(tstruct), *vecp, vecp, 0); + } + tk = lex(); + return; + case Stage2: + CError_Error(CErrorStr147); + return; + default: + CError_Error(CErrorStr130); + return; + } + } + return; + } else { + switch (CInit_ParseNextInit(s2)) { + case Stage1: + case Stage2: + continue; + case Stage3: + if (flag) + tk = lex(); + if (IS_TYPESTRUCT_VECTOR(tstruct)) { + switch (TYPE_STRUCT(tstruct)->stype) { + case STRUCT_VECTOR_UCHAR: + case STRUCT_VECTOR_SCHAR: + case STRUCT_VECTOR_BCHAR: + if (count != 16) { + if (count == 1) { + UInt8 val, *p; + p = (UInt8 *) s->buffer; + val = p[0]; + for (i = 1; i < 16; i++) + p[i] = val; + } else { + CError_Error(CErrorStr174); + } + } + break; + case STRUCT_VECTOR_USHORT: + case STRUCT_VECTOR_SSHORT: + case STRUCT_VECTOR_BSHORT: + case STRUCT_VECTOR_PIXEL: + if (count != 8) { + if (count == 1) { + SInt16 val, *p; + p = (SInt16 *) s->buffer; + val = p[0]; + for (i = 1; i < 8; i++) + p[i] = val; + } else { + CError_Error(CErrorStr174); + } + } + break; + case STRUCT_VECTOR_UINT: + case STRUCT_VECTOR_SINT: + case STRUCT_VECTOR_BINT: + case STRUCT_VECTOR_FLOAT: + if (count != 4) { + if (count == 1) { + UInt32 val, *p; + p = (UInt32 *) s->buffer; + val = p[0]; + for (i = 1; i < 4; i++) + p[i] = val; + } else { + CError_Error(CErrorStr174); + } + } + break; + } + } + return; + default: + CError_Error(CErrorStr174); + return; + } + } + } +} + +static ObjMemberVar *CInit_FindNextMember(ObjMemberVar *ivar) { + ObjMemberVar *scan = ivar; + while (1) { + scan = scan->next; + if (!scan) + return NULL; + if (!scan->anonunion) + return scan; + if (scan->offset > ivar->offset) + return scan; + if (IS_TYPE_BITFIELD(scan->type) && IS_TYPE_BITFIELD(ivar->type) && TYPE_BITFIELD(scan->type)->offset != TYPE_BITFIELD(ivar->type)->offset) + return scan; + } +} + +static void CInit_InitTypeClass(CInit_Stuff *s, CInit_Stuff2 *s2, TypeClass *tclass, UInt32 qual, Boolean errorflag) { + ObjMemberVar *ivar; + SInt32 start; + Boolean flag; + SInt32 last_offset; + TypePointer arraytype; + + if (tclass->bases || tclass->vtable) { + CError_Error(CErrorStr174); + return; + } + + switch (s2->stage) { + case Stage1: + flag = 1; + if (CInit_ParseNextInit(s2) == Stage3) { + tk = lex(); + return; + } + break; + case Stage2: + flag = 0; + break; + } + + switch (s2->stage) { + case Stage1: + case Stage2: + break; + default: + CError_Error(CErrorStr174); + return; + } + + if (!flag && s2->stage == Stage2 && (errorflag || s2->expr->rtype == TYPE(tclass) || CExpr_CanImplicitlyConvert(s2->expr, TYPE(tclass), 0))) { + s2->expr = CExpr_AssignmentPromotion(s2->expr, TYPE(tclass), qual, 1); + if (IS_TYPE_CLASS(s2->expr->rtype)) + CInit_InitNonConst(s, TYPE(tclass), s2->expr); + return; + } + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + if (ivar->access != ACCESSPUBLIC) { + CError_Error(CErrorStr174); + break; + } + } + + if (!(ivar = tclass->ivars)) { + CError_Error(CErrorStr147); + return; + } + start = s->size; + while (1) { + s->size = start + ivar->offset; + if (!ivar->type->size) { + if (!errorflag || !IS_TYPE_ARRAY(ivar->type)) { + CError_Error(CErrorStr147); + if (!IS_TYPE_ARRAY(ivar->type)) + return; + } + + arraytype = *TYPE_POINTER(ivar->type); + CInit_InitTypeArray(s, s2, &arraytype, ivar->qual, 1); + s->x18 = arraytype.size; + } else { + CInit_InitType(s, s2, ivar->type, ivar->qual, 0); + } + + last_offset = ivar->offset; + if (!(ivar = CInit_FindNextMember(ivar)) || (tclass->mode == CLASS_MODE_UNION && ivar->offset == last_offset)) { + if (flag) { + switch (CInit_ParseNextInit(s2)) { + case Stage3: + tk = lex(); + return; + case Stage2: + CError_Error(CErrorStr147); + return; + default: + CError_Error(CErrorStr130); + return; + } + } + return; + } else { + switch (CInit_ParseNextInit(s2)) { + case Stage1: + case Stage2: + continue; + case Stage3: + if (flag) + tk = lex(); + break; + default: + CError_Error(CErrorStr174); + } + return; + } + } +} + +static void CInit_InitType(CInit_Stuff *s, CInit_Stuff2 *s2, Type *type, UInt32 qual, Boolean errorflag) { + Boolean flag; + + switch (type->type) { + case TYPEVOID: + CError_Error(CErrorStr174); + break; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPEBITFIELD: + case TYPEMEMBERPOINTER: + case TYPEPOINTER: + switch (s2->stage) { + case Stage1: + flag = 1; + CInit_ParseNextInit(s2); + break; + case Stage2: + flag = 0; + break; + } + if (s2->stage != Stage2) { + CError_Error(CErrorStr174); + return; + } + + switch (type->type) { + case TYPEINT: + CInit_InitTypeInt(s, s2->expr, TYPE_INTEGRAL(type), qual); + break; + case TYPEFLOAT: + CInit_InitTypeFloat(s, s2->expr, TYPE_INTEGRAL(type), qual); + break; + case TYPEENUM: + CInit_InitTypeEnum(s, s2->expr, TYPE_ENUM(type), qual); + break; + case TYPEPOINTER: + CInit_InitTypePointer(s, s2->expr, TYPE_POINTER(type), qual); + break; + case TYPEMEMBERPOINTER: + CInit_InitTypeMemberPointer(s, s2->expr, TYPE_MEMBER_POINTER(type), qual); + break; + case TYPEBITFIELD: + CInit_InitTypeBitfield(s, s2->expr, TYPE_BITFIELD(type), qual); + break; + default: + CError_FATAL(1542); + } + + if (flag) { + switch (CInit_ParseNextInit(s2)) { + case Stage3: + tk = lex(); + break; + case Stage2: + CError_Error(CErrorStr147); + break; + default: + CError_Error(CErrorStr130); + } + } + break; + case TYPESTRUCT: + CInit_InitTypeStruct(s, s2, TYPE_STRUCT(type), qual, errorflag); + break; + case TYPEARRAY: + CInit_InitTypeArray(s, s2, TYPE_POINTER(type), qual, errorflag); + break; + case TYPECLASS: + CInit_InitTypeClass(s, s2, TYPE_CLASS(type), qual, errorflag); + break; + default: + CError_FATAL(1573); + } +} + +static void CInit_InitData(CInit_Stuff *s, Type *type, UInt32 qual, Boolean flag) { + CInit_Stuff2 s2; + SInt32 size; + CInit_Stuff *tmp; + char *buffer; + + locklheap(); + memclrw(s, sizeof(CInit_Stuff)); + s->x4 = s; + if (type->size == 0) { + if (IS_TYPE_ARRAY(type)) + s->bufferSize = 16 * TYPE_POINTER(type)->target->size; + else + CError_Error(CErrorStr145); + } else { + s->bufferSize = type->size; + } + + s->buffer = lalloc(s->bufferSize); + memset(s->buffer, 0, s->bufferSize); + s->flag = flag; + + s2.stage = Stage0; + s2.x23 = 0; + if (IS_TYPE_VECTOR(type)) { + s2.x23 = 1; + s->flag = 1; + } + if (IS_TYPE_ARRAY(type) && IS_TYPE_VECTOR(TYPE_POINTER(type)->target)) { + s->flag = 1; + } + + s2.type = NULL; + s2.x24 = 0; + CInit_ParseNextInit(&s2); + CInit_InitType(s, &s2, type, qual, 1); + + if ((size = type->size + s->x18)) { + if (s->x0) { + buffer = lalloc(size); + for (tmp = s; tmp; tmp = tmp->x0) { + CError_ASSERT(1647, (tmp->xC + tmp->size) <= size); + memcpy(buffer + tmp->xC, tmp->buffer, tmp->size); + } + s->buffer = buffer; + } + } else { + CError_Error(CErrorStr174); + } + + s->size = size; + s->x0 = NULL; + unlocklheap(); +} + +static ENode *CInit_InitConcat(ENode *a1, ENode *a2, SInt32 offset, Type *type, ENode *a5) { + ENode *r30; + ENode *r28; + ENode *tmp; + + r28 = lalloc(sizeof(ENode)); + *r28 = *a2; + if (offset) + r28 = makediadicnode(r28, intconstnode(TYPE(&stunsignedlong), offset), EADD); + + if (IS_TYPE_BITFIELD(type)) { + tmp = makemonadicnode(r28, EBITFIELD); + tmp->rtype = type; + tmp = makemonadicnode(tmp, EINDIRECT); + tmp->rtype = TYPE_BITFIELD(type)->bitfieldtype; + } else { + tmp = makemonadicnode(r28, EINDIRECT); + tmp->rtype = type; + } + + r30 = makediadicnode(tmp, a5, EASS); + if (!a1) { + return r30; + } else { + tmp = makediadicnode(a1, r30, ECOMMA); + tmp->rtype = r30->rtype; + return tmp; + } +} + +static ENode *CInit_RegisterDtorObject(Type *type, Object *dtor, ENode *objexpr) { + ENode *expr; + + if (copts.no_static_dtors) + return objexpr; + + expr = lalloc(sizeof(ENode)); + expr->type = EFUNCCALL; + expr->cost = 4; + expr->flags = 0; + expr->rtype = CDecl_NewPointerType(type); + expr->data.funccall.funcref = create_objectrefnode(Xgreg_func); + expr->data.funccall.functype = TYPE_FUNC(Xgreg_func->type); + expr->data.funccall.args = lalloc(sizeof(ENodeList)); + expr->data.funccall.args->node = objexpr; + expr->data.funccall.args->next = lalloc(sizeof(ENodeList)); + expr->data.funccall.args->next->node = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1)); + expr->data.funccall.args->next->next = lalloc(sizeof(ENodeList)); + expr->data.funccall.args->next->next->node = create_objectrefnode(CInit_CreateStaticData(CInit_GetRegMemType())); + expr->data.funccall.args->next->next->next = NULL; + + return expr; +} + +static Boolean CInit_ConstructGlobalObject(Object *obj, TypeClass *tclass, ENode *valueexpr, SInt32 offset, Boolean flag) { + NameSpaceObjectList *ctor; + Object *dtor; + ENodeList *list; + ENode *expr; + Boolean ctorflag; + + ctor = CClass_Constructor(tclass); + dtor = CClass_Destructor(tclass); + if (!ctor && !dtor) + return 0; + + if (flag && !ctor && tk == '=' && lookahead() == '{') + return 0; + + if (flag && tk == '(') { + tk = lex(); + list = CExpr_ScanExpressionList(1); + if (tk == ')') + tk = lex(); + else + CError_Error(CErrorStr115); + } else if (valueexpr) { + list = lalloc(sizeof(ENodeList)); + list->node = valueexpr; + list->next = NULL; + } else { + list = NULL; + } + + expr = create_objectrefnode(obj); + if (offset) + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); + + if (ctor) { + ctorflag = 1; + if (tk == '=') { + ctorflag = 0; + if (list) + CError_Error(CErrorStr174); + + list = lalloc(sizeof(ENodeList)); + list->next = NULL; + tk = lex(); + list->node = conv_assignment_expression(); + } + + expr = CExpr_ConstructObject(tclass, expr, list, 0, 1, 0, 1, ctorflag); + if (expr->rtype->type != TYPEPOINTER) { + CError_Error(CErrorStr174); + return 1; + } + } else { + if (list) + CError_Error(CErrorStr174); + } + + if (dtor) + expr = CInit_RegisterDtorObject(TYPE(tclass), dtor, expr); + + if (cinit_initinfo->x16) + cinit_initinfo->init_expr_register_cb(expr); + else + InitExpr_Register(expr, obj); + + return 1; +} + +static Boolean CInit_ConstructAutoObject(TypeClass *tclass, ENode *expr, SInt32 offset, Boolean flag) { + ENodeList *r30; + ENode *r29; + NameSpaceObjectList *ctor; + Object *dtor; + Boolean r24; + + ctor = CClass_Constructor(tclass); + dtor = CClass_Destructor(tclass); + if (!ctor && !dtor) + return 0; + + if (dtor) + CClass_CheckStaticAccess(NULL, tclass, dtor->access); + + if (flag && !ctor && tk == '=' && lookahead() == '{') + return 0; + + if (flag && tk == '(') { + tk = lex(); + r30 = CExpr_ScanExpressionList(1); + if (tk == ')') + tk = lex(); + else + CError_Error(CErrorStr115); + } else if (expr) { + r30 = lalloc(sizeof(ENodeList)); + r30->node = expr; + r30->next = NULL; + } else { + r30 = NULL; + } + + if (ctor) { + r24 = 1; + if (tk == '=') { + if (r30) + CError_Error(CErrorStr174); + r30 = lalloc(sizeof(ENodeList)); + r30->next = NULL; + tk = lex(); + r30->node = conv_assignment_expression(); + r24 = 0; + } + + if (!dtor) { + r29 = create_objectrefnode(cinit_initinfo->obj1C); + if (offset) + r29 = makediadicnode(r29, intconstnode(TYPE(&stunsignedlong), offset), EADD); + } else { + r29 = cinit_initinfo->register_object_cb(TYPE(tclass), cinit_initinfo->obj1C, offset, 0); + } + + r29 = CExpr_ConstructObject(tclass, r29, r30, 0, 1, 0, 1, r24); + if (!IS_TYPE_POINTER_ONLY(r29->rtype)) { + CError_Error(CErrorStr174); + return 1; + } + r29 = makemonadicnode(r29, EINDIRECT); + r29->rtype = TYPE_POINTER(r29->rtype)->target; + cinit_initinfo->insert_expr_cb(r29); + } else { + if (r30) + CError_Error(CErrorStr174); + if (dtor) + r29 = cinit_initinfo->register_object_cb(TYPE(tclass), cinit_initinfo->obj1C, offset, 0); + cinit_initinfo->insert_expr_cb(r29); + } + + return 1; +} + +static void CInit_ExprPointer(TypePointer *tptr, ENode *expr) { + Object *obj; + CInt64 val; + OLinkList *list; + + if (CInit_RelocInitCheck(expr, &obj, &val, 0)) { + if (obj) { + list = lalloc(sizeof(OLinkList)); + list->next = cinit_initinfo->list; + list->obj = obj; + list->somevalue = CInt64_GetULong(&val); + list->offset = cinit_initinfo->expr_offset; + cinit_initinfo->list = list; + } else { + CMach_InitIntMem(TYPE(&stunsignedlong), val, cinit_initinfo->buffer + cinit_initinfo->expr_offset); + } + } else if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(TYPE(tptr), expr, 0); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(CErrorStr124); + } + + cinit_initinfo->expr_offset += 4; +} + +static void CInit_ExprInt(TypeIntegral *tint, ENode *expr) { + if (ENODE_IS(expr, EINTCONST)) { + CMach_InitIntMem(TYPE(tint), expr->data.intval, cinit_initinfo->buffer + cinit_initinfo->expr_offset); + } else if (ENODE_IS(expr, ETYPCON) && IS_TYPE_POINTER_ONLY(expr->data.monadic->rtype) && expr->rtype->size == 4 && (copts.cplusplus || !copts.ANSIstrict)) { + CInit_ExprPointer(TYPE_POINTER(expr->data.monadic->rtype), expr->data.monadic); + } else if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(TYPE(tint), expr, 0); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(CErrorStr124); + } + + cinit_initinfo->expr_offset += tint->size; +} + +static void CInit_ExprFloat(TypeIntegral *tint, ENode *expr) { + if (ENODE_IS(expr, EFLOATCONST)) { + CMach_InitFloatMem(TYPE(tint), expr->data.floatval, cinit_initinfo->buffer + cinit_initinfo->expr_offset); + } else if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(TYPE(tint), expr, 0); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(CErrorStr124); + } + + cinit_initinfo->expr_offset += tint->size; +} + +static void CInit_ExprEnum(TypeEnum *tenum, ENode *expr) { + if (ENODE_IS(expr, EINTCONST)) { + CMach_InitIntMem(tenum->enumtype, expr->data.intval, cinit_initinfo->buffer + cinit_initinfo->expr_offset); + } else if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(TYPE(tenum), expr, 0); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(CErrorStr124); + } + + cinit_initinfo->expr_offset += tenum->size; +} + +static void CInit_ExprMemberPointer(TypeMemberPointer *tmptr, ENode *expr) { + if (ENODE_IS(expr, EINTCONST)) { + CMach_InitIntMem(TYPE(&stsignedlong), expr->data.intval, cinit_initinfo->buffer + cinit_initinfo->expr_offset); + } else if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(TYPE(tmptr), expr, 0); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(CErrorStr124); + } + + cinit_initinfo->expr_offset += tmptr->size; +} + +static void CInit_TypeExpr(Type *type, ENode *expr) { + switch (type->type) { + case TYPEINT: + CInit_ExprInt(TYPE_INTEGRAL(type), expr); + break; + case TYPEFLOAT: + CInit_ExprFloat(TYPE_INTEGRAL(type), expr); + break; + case TYPEENUM: + CInit_ExprEnum(TYPE_ENUM(type), expr); + break; + case TYPEPOINTER: + CInit_ExprPointer(TYPE_POINTER(type), expr); + break; + case TYPEMEMBERPOINTER: + CInit_ExprMemberPointer(TYPE_MEMBER_POINTER(type), expr); + break; + case TYPESTRUCT: + case TYPECLASS: + if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(type, expr, 0); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(CErrorStr124); + } + break; + case TYPEARRAY: + CError_Error(CErrorStr174); + break; + default: + CError_FATAL(2082); + } +} + +static void CInit_Bitfield(TypeBitfield *tbitfield) { + Boolean r30; + ENode *expr; + ENode myexpr; + + r30 = tk == '{'; + if (r30) + tk = lex(); + + expr = CInit_ParseInitializer(&myexpr); + expr = CExpr_AssignmentPromotion( + expr, + IS_TYPE_ENUM(tbitfield->bitfieldtype) ? TYPE_ENUM(tbitfield->bitfieldtype)->enumtype : tbitfield->bitfieldtype, + 0, + 1); + if (ENODE_IS(expr, EINTCONST)) + CInit_SetBitfield(tbitfield, (UInt8 *) cinit_initinfo->buffer + cinit_initinfo->expr_offset, expr->data.intval); + else + CError_Error(CErrorStr124); + + if (r30) + CInit_CloseInitList(); +} + +static void CInit_Array(TypePointer *tptr, UInt32 qual, Boolean flag) { + SInt32 start; + SInt32 i; + SInt32 targetsize1; + SInt32 targetsize2; + Boolean in_block; + Boolean is_char_ptr; + Boolean needs_construction; + Boolean is_wchar_ptr; + + targetsize1 = tptr->target->size; + targetsize2 = tptr->target->size; + if (!tptr->target->size) { + if (!IS_TYPE_ARRAY(tptr->target)) { + CError_Error(CErrorStr145); + return; + } + targetsize1 = tptr->target->size; + targetsize2 = tptr->target->size; + if (!tptr->target->size) { + CError_Error(CErrorStr145); + return; + } + } + + is_char_ptr = IS_TYPE_INT(tptr->target) && (tptr->target->size == 1); + is_wchar_ptr = IS_TYPE_INT(tptr->target) && (tptr->target->size == stwchar.size); + + in_block = 1; + if (flag && !(tk == TK_STRING && is_char_ptr) && !(tk == TK_STRING_WIDE && is_wchar_ptr)) { + if (tk != '{') { + CError_ErrorSkip(CErrorStr135); + return; + } + tk = lex(); + } else { + if (tk == '{') + tk = lex(); + else + in_block = 0; + } + + if ((tk == TK_STRING && is_char_ptr) || (tk == TK_STRING_WIDE && is_wchar_ptr)) { + if (tptr->size) { + if (tksize > tptr->size) { + if (copts.cplusplus || (tksize - (is_wchar_ptr ? stwchar.size : 1)) > tptr->size) + CError_Error(CErrorStr147); + tksize = tptr->size; + } + memcpy(cinit_initinfo->buffer + cinit_initinfo->expr_offset, tkstring, tksize); + } else { + tptr->size = tksize; + CInit_SetData(tkstring, cinit_initinfo->expr_offset, tptr->size); + } + cinit_initinfo->expr_offset += tptr->size; + tk = lex(); + if (in_block) + CInit_CloseInitList(); + return; + } + + if (IS_TYPE_CLASS(tptr->target) && CInit_ClassNeedsConstruction(TYPE_CLASS(tptr->target))) + needs_construction = 1; + else + needs_construction = 0; + + start = cinit_initinfo->expr_offset; + i = 0; + while (1) { + if (tk == '}') { + innerloop: + if (tptr->size) { + if (needs_construction) { + while (tptr->size > (i * targetsize1)) { + cinit_initinfo->expr_offset = start + i * targetsize2; + if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(tptr->target, NULL, 1); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(CErrorStr174); + } + i++; + } + } + } else { + tptr->size = i * targetsize1; + } + cinit_initinfo->expr_offset = start + tptr->size; + if (in_block) + tk = lex(); + return; + } + + if (!tptr->size) { + cinit_initinfo->expr_offset = start + i * targetsize2; + CInit_SetData(NULL, cinit_initinfo->expr_offset, targetsize2); + if (needs_construction) { + if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(tptr->target, conv_assignment_expression(), 1); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(CErrorStr174); + } + } else { + CInit_Type(tptr->target, qual, 0); + } + } else { + if (tptr->size <= i * targetsize1) { + i--; + CError_Error(CErrorStr147); + } + + cinit_initinfo->expr_offset = start + i * targetsize2; + if (needs_construction) { + if (cinit_initinfo->expr_cb) { + cinit_initinfo->expr_cb(tptr->target, conv_assignment_expression(), 1); + cinit_initinfo->expr_cb_called = 1; + } else { + CError_Error(CErrorStr174); + } + } else { + CInit_Type(tptr->target, qual, 0); + } + + if (!in_block) { + if (tptr->size <= (i + 1) * targetsize1) + return; + } + } + + if (tk != '}') { + if (tk != ',') { + CError_ErrorSkip(CErrorStr121); + in_block = 0; + i++; + goto innerloop; + } + tk = lex(); + } + i++; + } +} + +static void CInit_Struct(TypeStruct *tstruct, Boolean flag) { + StructMember *member; + SInt32 start; + Boolean in_block; + + if (!(member = tstruct->members)) { + CError_Error(CErrorStr145); + return; + } + + if (tstruct->stype == STRUCT_TYPE_UNION) { + if (tk == '{') { + tk = lex(); + CInit_Type(member->type, member->qual, 0); + if (tk == '}') + tk = lex(); + } else { + CInit_Type(member->type, member->qual, 0); + } + return; + } + + if (IS_TYPE_VECTOR(tstruct) && tk != '{') { + CInit_TypeExpr(TYPE(tstruct), CExpr_AssignmentPromotion(conv_assignment_expression(), TYPE(tstruct), 0, 1)); + return; + } + + if (tk != '{') { + if (flag) + CError_ErrorSkip(CErrorStr135); + in_block = 0; + } else { + in_block = 1; + tk = lex(); + } + + start = cinit_initinfo->expr_offset; + while (1) { + if (tk == '}') + break; + + cinit_initinfo->expr_offset = start + member->offset; + if (!member->type->size && IS_TYPE_ARRAY(member->type)) { + CError_Error(CErrorStr147); + break; + } + + CInit_Type(member->type, member->qual, 0); + if (tk == '}') + break; + + if (tk != ',') { + CError_Error(CErrorStr121); + break; + } + + do { + member = member->next; + } while (member && (member->qual & Q_WEAK)); + + if (!member) { + if (!in_block) + break; + if ((tk = lex()) != '}') { + CError_Error(CErrorStr147); + break; + } + } else { + tk = lex(); + } + } + + cinit_initinfo->expr_offset = start + tstruct->size; + if (tk == '}' && in_block) + tk = lex(); +} + +static void CInit_Class(TypeClass *tclass, Boolean flag) { + ObjMemberVar *ivar; + SInt32 start; + Boolean in_block; + + if (tk == '{') { + in_block = 1; + tk = lex(); + } else { + in_block = 0; + } + + if (tclass->bases || tclass->vtable) { + CError_Error(CErrorStr174); + return; + } + + for (ivar = tclass->ivars; ivar; ivar = ivar->next) { + if (ivar->access != ACCESSPUBLIC) + break; + } + + if (!ivar && !CClass_Constructor(tclass) && (!CClass_Destructor(tclass) || in_block)) { + if ((ivar = tclass->ivars)) { + start = cinit_initinfo->expr_offset; + while (1) { + if (tk == '}') + break; + + if (!ivar->type->size && IS_TYPE_ARRAY(ivar->type)) { + CError_Error(CErrorStr147); + break; + } + + cinit_initinfo->expr_offset = start + ivar->offset; + CInit_Type(ivar->type, ivar->qual, 0); + + if (tk == '}') + break; + + if (tk != ',') { + CError_Error(CErrorStr121); + break; + } + + do { + ivar = ivar->next; + } while (ivar && ivar->anonunion); + + if (!ivar) { + if (!in_block) + break; + if ((tk = lex()) != '}') { + CError_Error(CErrorStr147); + break; + } + } else { + tk = lex(); + } + } + } else { + if (in_block && tk != '}') + CError_Error(CErrorStr147); + } + } else { + if (in_block) + CError_Error(CErrorStr174); + CInit_TypeExpr(TYPE(tclass), CExpr_AssignmentPromotion(conv_assignment_expression(), TYPE(tclass), 0, 1)); + } + + cinit_initinfo->expr_offset = start + tclass->size; + if (tk == '}' && in_block) + tk = lex(); +} + +static void CInit_Type(Type *type, UInt32 qual, Boolean flag) { + ENode *expr; + ENode myexpr; + + switch (type->type) { + case TYPEVOID: + CError_Error(CErrorStr174); + break; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPEPOINTER: + case TYPEMEMBERPOINTER: + if (tk == '{') { + tk = lex(); + expr = CInit_ParseInitializer(&myexpr); + expr = CExpr_AssignmentPromotion(expr, type, qual & (Q_CONST | Q_VOLATILE), 1); + CInit_CloseInitList(); + } else { + expr = CInit_ParseInitializer(&myexpr); + expr = CExpr_AssignmentPromotion(expr, type, qual & (Q_CONST | Q_VOLATILE), 1); + } + CInit_TypeExpr(type, expr); + break; + case TYPEBITFIELD: + CInit_Bitfield(TYPE_BITFIELD(type)); + break; + case TYPEARRAY: + CInit_Array(TYPE_POINTER(type), qual, flag); + break; + case TYPESTRUCT: + CInit_Struct(TYPE_STRUCT(type), flag); + break; + case TYPECLASS: + CInit_Class(TYPE_CLASS(type), flag); + break; + default: + CError_FATAL(2482); + } +} + +static void CInit_GlobalStaticInit(Type *type, ENode *valueexpr, Boolean flag) { + ENode *expr; + ENode *tmp; + + cinit_initinfo->x15 = 1; + if (flag) { + CInit_ConstructGlobalObject(cinit_initinfo->obj, TYPE_CLASS(type), valueexpr, cinit_initinfo->expr_offset, 0); + } else { + expr = create_objectrefnode(cinit_initinfo->obj); + if (!IS_TYPE_POINTER_ONLY(expr->rtype)) { + CError_Error(CErrorStr174); + return; + } + TYPE_POINTER(expr->rtype)->target = type; + + if (cinit_initinfo->expr_offset) + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), cinit_initinfo->expr_offset), EADD); + + tmp = makemonadicnode(expr, EINDIRECT); + tmp->rtype = type; + expr = makediadicnode(tmp, valueexpr, EASS); + if (cinit_initinfo->x16) + cinit_initinfo->init_expr_register_cb(expr); + else + InitExpr_Register(expr, cinit_initinfo->obj); + } +} + +static void CInit_AutoInit(Type *type, ENode *valueexpr, Boolean flag) { + ENode *expr; + ENode *tmp; + Type *copy; + SInt32 size; + + if (flag) { + CInit_ConstructAutoObject(TYPE_CLASS(type), valueexpr, cinit_initinfo->expr_offset, 0); + } else { + if (IS_TYPE_ARRAY(type) && (type->size & 1)) { + copy = galloc(sizeof(TypePointer)); + *TYPE_POINTER(copy) = *TYPE_POINTER(type); + type = copy; + copy->size++; + } + expr = create_objectrefnode(cinit_initinfo->obj1C); + if (!IS_TYPE_POINTER_ONLY(expr->rtype)) { + CError_Error(CErrorStr174); + return; + } + TYPE_POINTER(expr->rtype)->target = type; + + if (cinit_initinfo->expr_offset) + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), cinit_initinfo->expr_offset), EADD); + + tmp = makemonadicnode(expr, EINDIRECT); + tmp->rtype = type; + expr = makediadicnode(tmp, valueexpr, EASS); + if (!copts.cplusplus) + CError_Error(CErrorStr124); + cinit_initinfo->insert_expr_cb(expr); + } +} + +static SInt32 CInit_AdjustObjectDataSize(Object *obj) { + if (obj->type->size <= 1) + return obj->type->size; + if (obj->type->size & 1) + return obj->type->size + 1; + else + return obj->type->size; +} + +static ENode *CInit_GenericData(Object *obj, Type *type, UInt32 qual, ExprCB expr_cb, Boolean flag) { + Object *r31; + ENode *expr; + ENode *tmpexpr; + Type *inner; + Type *copy; + SInt32 size; + Boolean lastflag; + SInt16 cv; + + cinit_initinfo->expr_cb = expr_cb; + expr = NULL; + + if (tk == '(') { + if (IS_TYPE_ARRAY(type)) + CError_Error(CErrorStr174); + tk = lex(); + expr = CExpr_AssignmentPromotion(assignment_expression(), type, qual, 1); + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + goto jump_ahead; + } + + tk = lex(); + switch (type->type) { + case TYPECLASS: + if (tk == '{' && CClass_Constructor(TYPE_CLASS(type))) + CError_Error(CErrorStr174); + case TYPESTRUCT: + if (tk != '{') + goto generic_type; + case TYPEARRAY: + if (!obj) { + if (IS_TYPE_ARRAY(type)) { + inner = type; + while (IS_TYPE_ARRAY(inner)) + inner = TYPE_POINTER(inner)->target; + + if (IS_TYPE_CLASS(inner) && CInit_ClassNeedsConstruction(TYPE_CLASS(inner))) { + CInit_SetupInitInfoBuffer(type); + cinit_initinfo->obj = cinit_initinfo->obj1C; + CInit_Type(type, cinit_initinfo->obj->qual, 1); + return 0; + } + if (type->size & 1) { + copy = galloc(sizeof(TypePointer)); + *TYPE_POINTER(copy) = *TYPE_POINTER(type); + type = copy; + type->size++; + } + } + + obj = CInit_CreateStaticDataObject(type, qual, NULL); + cinit_initinfo->obj = obj; + expr = create_objectnode(obj); + cinit_initinfo->obj1C = obj; + } + CInit_SetupInitInfoBuffer(type); + CInit_Type(type, obj->qual, 1); + CError_ASSERT(2639, obj->type->size == (size = cinit_initinfo->size)); + if (cinit_initinfo->list || !CInit_IsAllZero(cinit_initinfo->buffer, size)) { + CInit_AdjustObjectDataSize(obj); + CInit_DeclareData(obj, cinit_initinfo->buffer, cinit_initinfo->list, obj->type->size); + } else { + CInit_AdjustObjectDataSize(obj); + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + } + return expr; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPEPOINTER: + case TYPEMEMBERPOINTER: + generic_type: + if (obj) + cv = obj->qual & Q_CV; + else + cv = cinit_initinfo->obj1C->qual & Q_CV; + + if (tk == '{') { + tk = lex(); + expr = assignment_expression(); + CInit_CloseInitList(); + } else { + expr = assignment_expression(); + } + expr = CExpr_AssignmentPromotion(expr, type, cv, 1); + jump_ahead: + if (obj == NULL) + r31 = cinit_initinfo->obj1C; + else + r31 = obj; + + if (is_const_object(r31)) { + switch (r31->type->type) { + case TYPEINT: + case TYPEENUM: + if (ENODE_IS(expr, EINTCONST)) { + r31->u.data.u.intconst = expr->data.intval; + goto common_8068C; + } + break; + case TYPEFLOAT: + if (ENODE_IS(expr, EFLOATCONST)) { + Float fl; + r31->u.data.u.floatconst = galloc(sizeof(Float)); + fl = CMach_CalcFloatConvert(r31->type, expr->data.floatval); + *r31->u.data.u.floatconst = fl; + goto common_8068C; + } + break; + case TYPEPOINTER: + tmpexpr = expr; + while (ENODE_IS(tmpexpr, ETYPCON)) + tmpexpr = tmpexpr->data.monadic; + if (!ENODE_IS(tmpexpr, EINTCONST)) + break; + r31->u.data.u.intconst = tmpexpr->data.intval; + common_8068C: + r31->qual |= Q_INLINE_DATA; + if (!obj) { + r31->sclass = TK_STATIC; + r31->datatype = DDATA; + r31->u.data.linkname = CParser_AppendUniqueName(r31->name->name); + } else if (r31->sclass != TK_STATIC || (r31->flags & OBJECT_FLAGS_2)) { + CInit_ExportConst(r31); + } + return NULL; + } + } + + if (!obj || (flag && copts.cplusplus)) { + if (obj) { + IsCompleteType(obj->type); + CError_ASSERT(2747, obj->type->size == type->size); + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + } + return expr; + } + + CInit_SetupInitInfoBuffer(type); + CInit_TypeExpr(type, expr); + CError_ASSERT(2756, obj->type->size == cinit_initinfo->size); + + IsCompleteType(obj->type); + CInit_AdjustObjectDataSize(obj); + lastflag = !cinit_initinfo->x15 && is_const_object(r31); + if (cinit_initinfo->list || !CInit_IsAllZero(cinit_initinfo->buffer, obj->type->size)) { + if (lastflag) + CInit_DeclareReadOnlyData(obj, cinit_initinfo->buffer, cinit_initinfo->list, obj->type->size); + else + CInit_DeclareData(obj, cinit_initinfo->buffer, cinit_initinfo->list, obj->type->size); + } else { + if (lastflag) + CInit_DeclareReadOnlyData(obj, NULL, NULL, obj->type->size); + else + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + } + break; + + default: + CError_FATAL(2776); + } + + return NULL; +} + +void CInit_ExportConst(Object *obj) { + char buffer[64]; + + if (obj->flags & OBJECT_DEFINED) + return; + + switch (obj->type->type) { + case TYPEINT: + CMach_InitIntMem(obj->type, obj->u.data.u.intconst, buffer); + break; + case TYPEENUM: + CMach_InitIntMem(TYPE_ENUM(obj->type)->enumtype, obj->u.data.u.intconst, buffer); + break; + case TYPEPOINTER: + CMach_InitIntMem(TYPE(&stunsignedlong), obj->u.data.u.intconst, buffer); + break; + case TYPEFLOAT: + CMach_InitFloatMem(obj->type, *obj->u.data.u.floatconst, buffer); + break; + default: + CError_FATAL(2807); + } + + if (is_const_object(obj)) + CInit_DeclareReadOnlyData(obj, buffer, NULL, obj->type->size); + else + CInit_DeclareData(obj, buffer, NULL, obj->type->size); +} + +static ENode *CInit_ClassInitLoopCallBack(ENode *expr) { + return CExpr_ConstructObject(cinit_loop_class, expr, NULL, 0, 1, 0, 1, 1); +} + +Statement *CInit_ConstructClassArray(Statement *stmt, TypeClass *tclass, Object *ctor, Object *dtor, ENode *firstarg, SInt32 count) { + ENode *dtor_expr; + + if (stmt) + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + else + stmt = CFunc_AppendStatement(ST_EXPRESSION); + + if (dtor) + dtor_expr = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1)); + else + dtor_expr = nullnode(); + + stmt->expr = CExpr_FuncCallSix( + carr_func, + firstarg, + create_objectrefnode(ctor), + dtor_expr, + intconstnode(TYPE(&stunsignedlong), tclass->size), + intconstnode(TYPE(&stunsignedlong), count), + NULL + ); + + return stmt; +} + +static void CInit_InitializeClassArray(Object *obj, TypeClass *tclass, Boolean flag) { + Object *ctor; + Object *dtor; + SInt32 count; + SInt32 i; + ENode *expr; + SInt32 offset; + ENode *dtor_expr; + Statement *stmt; + TypeFunc *tfunc; + Object *funcobj; + + dtor = CClass_Destructor(tclass); + count = obj->type->size / tclass->size; + if (CClass_Constructor(tclass)) { + ctor = CClass_DefaultConstructor(tclass); + if (!ctor) { + ctor = CClass_DummyDefaultConstructor(tclass); + if (!ctor) { + CError_Error(CErrorStr203); + return; + } + } + } else { + ctor = NULL; + } + + if (count <= 1 || (!flag && count <= 8)) { + if (flag) { + for (i = 0; i < count; i++) { + CInit_ConstructGlobalObject(obj, tclass, NULL, i * tclass->size, 0); + } + } else { + for (i = 0; i < count; i++) { + offset = i * tclass->size; + expr = create_objectrefnode(obj); + if (offset) + expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); + if (ctor) + expr = CExpr_ConstructObject(tclass, expr, NULL, 0, 1, 0, 1, 1); + cinit_initinfo->insert_expr_cb(expr); + if (dtor) + CExcept_RegisterDestructorObject(obj, offset, dtor, 1); + } + if (dtor) { + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = nullnode(); + } + } + } else { + if (ctor) { + if (!flag && !dtor) { + CInit_ConstructClassArray(NULL, tclass, ctor, dtor, create_objectrefnode(obj), count); + expr = nullnode(); + } else { + if (dtor) + dtor_expr = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1)); + else + dtor_expr = nullnode(); + expr = CExpr_FuncCallSix( + carr_func, + create_objectrefnode(obj), + create_objectrefnode(ctor), + dtor_expr, + intconstnode(TYPE(&stunsignedlong), tclass->size), + intconstnode(TYPE(&stunsignedlong), count), + NULL + ); + } + } else { + expr = nullnode(); + } + + if (flag) { + if (dtor && !copts.no_static_dtors) { + tfunc = galloc(sizeof(TypeFunc)); + memclrw(tfunc, sizeof(TypeFunc)); + tfunc->type = TYPEFUNC; + tfunc->functype = &stvoid; + CDecl_SetFuncFlags(tfunc, 1); + + funcobj = CParser_NewCompilerDefFunctionObject(); + funcobj->name = CParser_AppendUniqueName("__arraydtor"); + funcobj->type = TYPE(tfunc); + funcobj->sclass = TK_STATIC; + funcobj->qual = Q_INLINE; + + CParser_RegisterSingleExprFunction(funcobj, funccallexpr( + darr_func, + create_objectrefnode(obj), + create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1)), + intconstnode(TYPE(&stsignedlong), tclass->size), + intconstnode(TYPE(&stsignedlong), count) + )); + + expr = makediadicnode(expr, nullnode(), ECOMMA); + expr->rtype = TYPE(&void_ptr); + + expr = funccallexpr( + Xgreg_func, + expr, + create_objectrefnode(funcobj), + create_objectrefnode(CInit_CreateStaticData(CInit_GetRegMemType())), + NULL + ); + } + if (cinit_initinfo->x16) + cinit_initinfo->init_expr_register_cb(expr); + else + InitExpr_Register(expr, obj); + } else { + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = expr; + if (dtor) { + CExcept_RegisterLocalArray(stmt, obj, dtor, count, tclass->size); + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = nullnode(); + } + } + } +} + +static ENode *CInit_AutoTempNode(Type *type, Boolean flag) { + ENode *node; + node = CExpr_NewETEMPNode(type, 0); + if (IS_TYPE_CLASS(type) && CClass_Destructor(TYPE_CLASS(type))) + node->data.temp.needs_dtor = 1; + return node; +} + +static ENode *CInit_GlobalTempNode(Type *type, Boolean flag) { + Object *dtor; + ENode *node; + ENode *funcnode; + + node = create_objectrefnode(CInit_CreateStaticData(type)); + if (IS_TYPE_CLASS(type) && (dtor = CClass_Destructor(TYPE_CLASS(type))) && !copts.no_static_dtors) { + if (flag) + CError_Error(CErrorStr190); + + funcnode = galloc(sizeof(ENode)); + funcnode->type = EFUNCCALL; + funcnode->cost = 200; + funcnode->flags = 0; + funcnode->rtype = CDecl_NewPointerType(type); + funcnode->data.funccall.funcref = create_objectrefnode(Xgreg_func); + funcnode->data.funccall.functype = TYPE_FUNC(Xgreg_func->type); + funcnode->data.funccall.args = lalloc(sizeof(ENodeList)); + funcnode->data.funccall.args->node = node; + funcnode->data.funccall.args->next = lalloc(sizeof(ENodeList)); + funcnode->data.funccall.args->next->node = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1)); + funcnode->data.funccall.args->next->next = lalloc(sizeof(ENodeList)); + funcnode->data.funccall.args->next->next->node = create_objectrefnode(CInit_CreateStaticData(CInit_GetRegMemType()));; + funcnode->data.funccall.args->next->next->next = NULL; + node = funcnode; + } + return node; +} + +static void CInit_RefInit(Type *type, ENode *expr, Boolean flag) { + ENode *objexpr; + + objexpr = create_objectrefnode(cinit_initinfo->obj); + if (!IS_TYPE_POINTER_ONLY(objexpr->rtype)) { + CError_Error(CErrorStr174); + return; + } + TYPE_POINTER(objexpr->rtype)->target = type; + + if (cinit_initinfo->expr_offset) + objexpr = makediadicnode(objexpr, intconstnode(TYPE(&stunsignedlong), cinit_initinfo->expr_offset), EADD); + + objexpr = makemonadicnode(objexpr, EINDIRECT); + objexpr->rtype = type; + + expr = makediadicnode(objexpr, expr, EASS); + if (cinit_initinfo->x16) + cinit_initinfo->init_expr_register_cb(expr); + else + InitExpr_Register(expr, cinit_initinfo->obj); +} + +static Boolean CInit_IsDtorTemp(ENode *expr) { + return ENODE_IS(expr, ETEMP) && expr->data.temp.needs_dtor; +} + +static void CInit_FindDtorTemp(ENode *expr) { + ENodeList *list; + + while (ENODE_IS(expr, ECOMMA)) + expr = expr->data.diadic.right; + + if (IS_TYPE_POINTER_ONLY(expr->rtype) && IS_TYPE_CLASS(TYPE_POINTER(expr->rtype)->target)) { + switch (expr->type) { + case ETYPCON: + CInit_FindDtorTemp(expr->data.monadic); + break; + case EADD: + case ESUB: + CInit_FindDtorTemp(expr->data.diadic.left); + CInit_FindDtorTemp(expr->data.diadic.right); + break; + case EFUNCCALL: + case EFUNCCALLP: + if ((list = expr->data.funccall.args)) { + if (CInit_IsDtorTemp(list->node) || ((list = list->next) && CInit_IsDtorTemp(list->node))) { + if (!cinit_fdtnode) + cinit_fdtnode = list; + else + cinit_fdtambig = 1; + } + } + break; + } + } +} + +static void CInit_RefTempTransform(Type *type, ENode *expr) { + Object *obj; + + CError_ASSERT(3164, IS_TYPE_POINTER_ONLY(type)); + + if (IS_TYPE_CLASS(TYPE_POINTER(type)->target)) { + cinit_fdtnode = NULL; + cinit_fdtambig = 0; + CInit_FindDtorTemp(expr); + if (cinit_fdtnode) { + CError_ASSERT(3172, !cinit_fdtambig); + obj = create_temp_object(cinit_fdtnode->node->data.temp.type); + cinit_initinfo->register_object_cb(cinit_fdtnode->node->data.temp.type, obj, 0, 0); + cinit_fdtnode->node = create_objectrefnode(obj); + } + } +} + +static Boolean CInit_InitReference(Object *obj, Boolean flag) { + ENode *expr; + + if (tk == '=') { + cinit_tempnodefunc = flag ? CInit_AutoTempNode : CInit_GlobalTempNode; + tk = lex(); + expr = CExpr_AssignmentPromotion(assignment_expression(), obj->type, obj->qual & (Q_CONST | Q_VOLATILE), 1); + cinit_tempnodefunc = NULL; + + if (flag) { + CInit_RefTempTransform(obj->type, expr); + expr = makediadicnode(create_objectnode2(obj), expr, EASS); + cinit_initinfo->insert_expr_cb(expr); + } else { + cinit_initinfo->expr_cb = CInit_RefInit; + CInit_SetupInitInfoBuffer(obj->type); + CInit_ExprPointer(TYPE_POINTER(obj->type), expr); + CError_ASSERT(3213, obj->type->size == cinit_initinfo->size); + + if (cinit_initinfo->list || !CInit_IsAllZero(cinit_initinfo->buffer, obj->type->size)) { + IsCompleteType(obj->type); + CInit_AdjustObjectDataSize(obj); + CInit_DeclareData(obj, cinit_initinfo->buffer, cinit_initinfo->list, obj->type->size); + } else { + IsCompleteType(obj->type); + CInit_AdjustObjectDataSize(obj); + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + } + } + + return 1; + } + + return 0; +} + +ENode *CInit_AutoObject(Object *obj, Type *type, UInt32 qual) { + CInit_Stuff s; + CInit_1C *entry; + ENode *expr; + ENode *indirect_expr; + ENode *obj_expr; + ENode *const_expr; + Type *newtype; + Object *newobj; + + CInit_InitData(&s, type, qual, copts.cplusplus || copts.gcc_extensions || copts.c9x || !obj); + if (!obj && !cscope_currentfunc) { + obj = CParser_NewCompilerDefDataObject(); + obj->name = CParser_GetUniqueName(); + obj->type = type; + obj->qual = qual; + obj->sclass = TK_STATIC; + CScope_AddGlobalObject(obj); + } + + if (IS_TYPE_VECTOR(type) && !s.x1C) { + if (obj) + obj_expr = create_objectrefnode(obj); + else + obj_expr = CExpr_NewETEMPNode(type, 1); + + const_expr = CExpr_NewENode(EVECTOR128CONST); + const_expr->rtype = type; + const_expr->data.vector128val = *((MWVector128 *) s.buffer); + + indirect_expr = makemonadicnode(obj_expr, EINDIRECT); + indirect_expr->rtype = type; + + expr = makediadicnode(indirect_expr, const_expr, EASS); + if (!obj) { + ENode *tmp = lalloc(sizeof(ENode)); + *tmp = *obj_expr; + tmp = makemonadicnode(tmp, EINDIRECT); + tmp->rtype = type; + tmp->flags = qual & ENODE_FLAG_QUALS; + expr = makecommaexpression(expr, tmp); + } + return expr; + } + + if (s.x18) { + type = CDecl_NewStructType(type->size + s.x18, CMach_GetTypeAlign(type)); + if (obj) + obj->type = type; + } + + if (obj) + obj_expr = create_objectrefnode(obj); + else + obj_expr = CExpr_NewETEMPNode(type, 1); + + newtype = type; + if (IS_TYPE_ARRAY(type)) + newtype = CDecl_NewStructType(type->size, CMach_GetTypeAlign(type)); + newobj = CInit_CreateStaticDataObject(newtype, 0, NULL); + if (s.list || !CInit_IsAllZero(s.buffer, s.size)) + CInit_DeclareReadOnlyData(newobj, s.buffer, s.list, s.size); + else + CInit_DeclareReadOnlyData(newobj, NULL, NULL, s.size); + + indirect_expr = makemonadicnode(obj_expr, EINDIRECT); + indirect_expr->rtype = newtype; + expr = makediadicnode(indirect_expr, create_objectnode(newobj), EASS); + + for (entry = s.x1C; entry; entry = entry->next) { + expr = CInit_InitConcat(expr, obj_expr, entry->offset, entry->type, entry->expr); + } + + if (!obj) { + ENode *tmp = lalloc(sizeof(ENode)); + *tmp = *obj_expr; + tmp = makemonadicnode(tmp, EINDIRECT); + tmp->rtype = type; + tmp->flags = qual & ENODE_FLAG_QUALS; + expr = makecommaexpression(expr, tmp); + } else if (IS_TYPE_ARRAY(type)) { + expr = makecommaexpression(expr, create_objectnode(obj)); + } + + return expr; +} + +static void CInit_GlobalObject(Object *obj) { + CInit_Stuff s; + CInit_1C *entry; + ENode *obj_expr; + ENode *expr; + + CInit_InitData(&s, obj->type, obj->qual, copts.cplusplus); + obj_expr = create_objectrefnode(obj); + + IsCompleteType(obj->type); + + if (!s.x1C && is_const_object(obj)) + CInit_DeclareReadOnlyData(obj, s.buffer, s.list, s.size); + else + CInit_DeclareData(obj, s.buffer, s.list, s.size); + + if (s.x1C) { + entry = s.x1C; + expr = NULL; + while (entry) { + if (!ENODE_IS(entry->expr, EVECTOR128CONST)) + expr = CInit_InitConcat(expr, obj_expr, entry->offset, entry->type, entry->expr); + entry = entry->next; + } + + if (expr) + InitExpr_Register(expr, obj); + } +} + +void CInit_InitializeAutoData(Object *obj, InsertExprCB insert_cb, RegisterObjectCB register_cb) { + ENode *expr; + Type *type; + InitInfo initinfo; + + if (CInit_IsSimpleStructArrayInit(obj->type)) { + if (tk == '=' || (tk == '(' && copts.cplusplus)) { + if (tk == '(') { + tk = lex(); + expr = conv_assignment_expression(); + if (tk != ')') + CError_Error(CErrorStr115); + tk = lex(); + } else if (tk == '=' && ((tk = lex()) == '{' || IS_TYPE_ARRAY(obj->type))) { + insert_cb(CInit_AutoObject(obj, obj->type, obj->qual)); + return; + } else { + expr = conv_assignment_expression(); + } + expr = CExpr_AssignmentPromotion(expr, obj->type, obj->qual & (Q_CONST | Q_VOLATILE), 1); + insert_cb(makediadicnode(create_objectnode2(obj), expr, EASS)); + } else if (copts.cplusplus && is_const_object(obj)) { + CError_Error(CErrorStr224); + } + + return; + } + + CInit_SetupInitInfo(&initinfo, obj); + initinfo.obj1C = obj; + initinfo.insert_expr_cb = insert_cb; + initinfo.register_object_cb = register_cb; + + if (IS_TYPE_CLASS(obj->type) && CInit_ConstructAutoObject(TYPE_CLASS(obj->type), NULL, 0, 1)) { + CInit_CleanupInitInfo(&initinfo); + return; + } + + if (IS_TYPE_REFERENCE(obj->type) && CInit_InitReference(obj, 1)) { + CInit_CleanupInitInfo(&initinfo); + return; + } + + if (tk != '=' && (tk != '(' || !copts.cplusplus)) { + if (IS_TYPE_ARRAY(obj->type)) { + type = obj->type; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (IS_TYPE_CLASS(type)) { + if (CInit_ClassNeedsConstruction(TYPE_CLASS(type))) { + CInit_InitializeClassArray(obj, TYPE_CLASS(type), 0); + CInit_CleanupInitInfo(&initinfo); + return; + } + CFunc_CheckClassCtors(TYPE_CLASS(type)); + } + } + + if (IS_TYPE_CLASS(obj->type)) + CFunc_CheckClassCtors(TYPE_CLASS(obj->type)); + + if ((IS_TYPE_REFERENCE(obj->type) || is_const_object(obj)) && copts.cplusplus) + CError_Error(CErrorStr224); + } else { + if (obj->type->size || IS_TYPE_ARRAY(obj->type)) { + if ((expr = CInit_GenericData(NULL, obj->type, obj->qual, CInit_AutoInit, 0))) + insert_cb(makediadicnode(create_objectnode2(obj), expr, EASS)); + } else { + CError_Error(CErrorStr145); + } + } + + if (IS_TYPE_CLASS(obj->type) && CClass_Destructor(TYPE_CLASS(obj->type))) + register_cb(obj->type, obj, 0, 0); + + CInit_CleanupInitInfo(&initinfo); +} + +void CInit_InitializeStaticData(Object *obj, InitExprRegisterCB cb) { + ENode *expr; + Type *type; + InitInfo initinfo; + CInit_Stuff s; + CInit_1C *entry; + ENode *obj_expr; + + if (CInit_IsSimpleStructArrayInit(obj->type)) { + if (tk == '=' || (tk == '(' && copts.cplusplus)) { + if (tk == '=') + tk = lex(); + CInit_InitData(&s, obj->type, obj->qual, copts.cplusplus); + + IsCompleteType(obj->type); + + if (!s.x1C && is_const_object(obj)) + CInit_DeclareReadOnlyData(obj, s.buffer, s.list, s.size); + else + CInit_DeclareData(obj, s.buffer, s.list, s.size); + + if (s.x1C) { + obj_expr = create_objectrefnode(obj); + entry = s.x1C; + expr = NULL; + while (entry) { + expr = CInit_InitConcat(expr, obj_expr, entry->offset, entry->type, entry->expr); + entry = entry->next; + } + cb(expr); + } + } else { + if (copts.cplusplus && is_const_object(obj)) + CError_Error(CErrorStr224); + + if (is_const_object(obj)) + CInit_DeclareReadOnlyData(obj, NULL, NULL, obj->type->size); + else + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + } + return; + } + + CInit_SetupInitInfo(&initinfo, obj); + initinfo.x16 = 1; + initinfo.init_expr_register_cb = cb; + + if (IS_TYPE_CLASS(obj->type) && CInit_ConstructGlobalObject(obj, TYPE_CLASS(obj->type), NULL, 0, 1)) { + IsCompleteType(obj->type); + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + CInit_CleanupInitInfo(&initinfo); + return; + } + + if (IS_TYPE_REFERENCE(obj->type) && CInit_InitReference(obj, 0)) { + CInit_CleanupInitInfo(&initinfo); + return; + } + + if (tk != '=' && (tk != '(' || !copts.cplusplus)) { + if (IsCompleteType(obj->type)) + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + + if (IS_TYPE_ARRAY(obj->type)) { + type = obj->type; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (IS_TYPE_CLASS(type)) { + if (CInit_ClassNeedsConstruction(TYPE_CLASS(type))) { + CInit_InitializeClassArray(obj, TYPE_CLASS(type), 1); + CInit_CleanupInitInfo(&initinfo); + return; + } + CFunc_CheckClassCtors(TYPE_CLASS(type)); + } + } + + if (IS_TYPE_CLASS(obj->type)) + CFunc_CheckClassCtors(TYPE_CLASS(obj->type)); + + if ((IS_TYPE_REFERENCE(obj->type) || is_const_object(obj)) && copts.cplusplus) + CError_Error(CErrorStr224); + } else { + if (obj->type->size || IS_TYPE_ARRAY(obj->type)) { + if ((expr = CInit_GenericData(obj, obj->type, obj->qual, CInit_GlobalStaticInit, 1))) + cb(makediadicnode(create_objectnode2(obj), expr, EASS)); + } else { + CError_Error(CErrorStr145); + } + } + + CInit_CleanupInitInfo(&initinfo); +} + +void CInit_InitializeData(Object *obj) { + Object *dtor; + ObjectList *list; + CInt64 val; + InitInfo initinfo; + Boolean needs_construction; + Type *type; + + if (tk == ':') { + tk = lex(); + obj->datatype = DABSOLUTE; + val = CExpr_IntegralConstExpr(); + obj->u.address = CInt64_GetULong(&val); + return; + } + + if (tk != '=' && (tk != '(' || !copts.cplusplus)) { + if (obj->sclass != TK_EXTERN) { + if (!copts.cplusplus) { + if (IsCompleteType(obj->type)) { + for (list = cinit_tentative; list; list = list->next) { + if (list->object == obj) + break; + } + if (!list) { + list = galloc(sizeof(ObjectList)); + list->object = obj; + list->next = cinit_tentative; + cinit_tentative = list; + obj->qual |= Q_1000000; + } + } + } else { + if (obj->flags & OBJECT_DEFINED) + CError_Error(CErrorStr329, obj); + obj->flags = obj->flags | OBJECT_DEFINED; + + needs_construction = 0; + if (IS_TYPE_ARRAY(obj->type)) { + type = obj->type; + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + if (IS_TYPE_CLASS(type)) { + if (CInit_ClassNeedsConstruction(TYPE_CLASS(type))) { + CInit_SetupInitInfo(&initinfo, obj); + CInit_InitializeClassArray(obj, TYPE_CLASS(type), 1); + CInit_CleanupInitInfo(&initinfo); + needs_construction = 1; + } else { + CFunc_CheckClassCtors(TYPE_CLASS(type)); + } + } + } else { + if (IS_TYPE_CLASS(obj->type)) { + if (CInit_ClassNeedsConstruction(TYPE_CLASS(obj->type))) { + CInit_SetupInitInfo(&initinfo, obj); + CInit_ConstructGlobalObject(obj, TYPE_CLASS(obj->type), NULL, 0, 0); + CInit_CleanupInitInfo(&initinfo); + needs_construction = 1; + } else { + CFunc_CheckClassCtors(TYPE_CLASS(obj->type)); + } + } + } + + if (!needs_construction && copts.cplusplus) { + if (IS_TYPE_REFERENCE(obj->type) || is_const_object(obj)) + CError_Error(CErrorStr224); + } + if (IsCompleteType(obj->type)) + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + } + } + return; + } + + if (obj->flags & OBJECT_DEFINED) + CError_Error(CErrorStr329, obj); + + if (CInit_IsSimpleStructArrayInit(obj->type)) { + if (tk == '=') + tk = lex(); + else + CError_Error(CErrorStr121); + CInit_GlobalObject(obj); + return; + } + + CInit_SetupInitInfo(&initinfo, obj); + if (IS_TYPE_CLASS(obj->type) && CInit_ConstructGlobalObject(obj, TYPE_CLASS(obj->type), NULL, 0, 1)) { + IsCompleteType(obj->type); + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + CInit_CleanupInitInfo(&initinfo); + return; + } + + if (IS_TYPE_REFERENCE(obj->type) && CInit_InitReference(obj, 0)) { + CInit_CleanupInitInfo(&initinfo); + return; + } + + if (obj->type->size == 0 && !IS_TYPE_ARRAY(obj->type)) { + CError_Error(CErrorStr145); + CInit_CleanupInitInfo(&initinfo); + return; + } + + if (copts.cplusplus) + CInit_GenericData(obj, obj->type, obj->qual, &CInit_GlobalStaticInit, 0); + else + CInit_GenericData(obj, obj->type, obj->qual, NULL, 0); + + if (IS_TYPE_CLASS(obj->type) && (dtor = CClass_Destructor(TYPE_CLASS(obj->type)))) + InitExpr_Register(CInit_RegisterDtorObject(obj->type, dtor, create_objectrefnode(obj)), obj); + + CInit_CleanupInitInfo(&initinfo); +} + +Object *CInit_DeclareString(char *data, SInt32 size, Boolean ispascal, Boolean iswide) { + PooledString *str; + Object *obj; + PooledString *scan; + + if (!copts.dont_reuse_strings) { + for (scan = cinit_stringlist; scan; scan = scan->next) { + if (scan->size == size && scan->ispascal == ispascal && scan->iswide == iswide && !memcmp(scan->data, data, size)) + return scan->obj; + } + } + + obj = CParser_NewCompilerDefDataObject(); + obj->name = CParser_GetUniqueName(); + if (iswide) { + obj->type = CDecl_NewArrayType(CParser_GetWCharType(), size); + } else { + obj->type = CDecl_NewArrayType(ispascal ? TYPE(&stunsignedchar) : TYPE(&stchar), size); + } + obj->sclass = TK_STATIC; + CScope_AddGlobalObject(obj); + + if (!iswide && !ispascal && size == (strlen(data) + 1)) + obj->section = SECT_TEXT_CSTRING; + else + obj->section = SECT_CONST; + + if (copts.readonly_strings) + CInit_DeclareReadOnlyData(obj, data, NULL, obj->type->size); + else + CInit_DeclareData(obj, data, NULL, obj->type->size); + + str = galloc(sizeof(PooledString)); + str->next = cinit_stringlist; + cinit_stringlist = str; + str->obj = obj; + str->offset = 0; + str->size = size; + str->ispascal = ispascal; + str->iswide = iswide; + str->data = galloc(size); + memcpy(str->data, data, size); + + return obj; +} + +PooledString *CInit_DeclarePooledString(char *data, SInt32 size, Boolean ispascal) { + PooledString *str; + Object *obj; + PooledString *scan; + SInt32 offset; + + if (!copts.dont_reuse_strings) { + for (scan = cinit_pooledstringlist; scan; scan = scan->next) { + if (scan->size == size && scan->ispascal == ispascal && !memcmp(scan->data, data, size)) + return scan; + } + } + + if (cinit_pooledstringlist) { + obj = cinit_pooledstringlist->obj; + offset = cinit_pooledstringlist->offset + cinit_pooledstringlist->size; + } else { + obj = CInit_CreateStaticDataObject( + CDecl_NewArrayType(ispascal ? TYPE(&stunsignedchar) : TYPE(&stchar), size), + 0, GetHashNameNodeExport("@stringBase0")); + obj->section = SECT_CONST; + offset = 0; + } + + str = galloc(sizeof(PooledString)); + str->next = cinit_pooledstringlist; + cinit_pooledstringlist = str; + str->obj = obj; + str->offset = offset; + str->size = size; + str->ispascal = ispascal; + str->data = galloc(size); + memcpy(str->data, data, size); + return str; +} + +PooledString *CInit_DeclarePooledWString(char *data, SInt32 size) { + PooledString *str; + Object *obj; + PooledString *scan; + SInt32 offset; + + if (!copts.dont_reuse_strings) { + for (scan = cinit_pooledwstringlist; scan; scan = scan->next) { + if (scan->size == size && !memcmp(scan->data, data, size)) + return scan; + } + } + + if (cinit_pooledwstringlist) { + obj = cinit_pooledwstringlist->obj; + offset = cinit_pooledwstringlist->offset + cinit_pooledwstringlist->size; + } else { + obj = CInit_CreateStaticDataObject( + CDecl_NewArrayType(CParser_GetWCharType(), size), + 0, GetHashNameNodeExport("@wstringBase0")); + obj->section = SECT_CONST; + offset = 0; + } + + str = galloc(sizeof(PooledString)); + str->next = cinit_pooledwstringlist; + cinit_pooledwstringlist = str; + str->obj = obj; + str->offset = offset; + str->size = size; + str->ispascal = 0; + str->data = galloc(size); + memcpy(str->data, data, size); + return str; +} + +void CInit_RewriteString(ENode *expr, Boolean flag) { + PooledString *str; + Boolean is_wide; + + if (cparamblkptr->precompile == 1) + CError_Error(CErrorStr180); + + CError_ASSERT(4220, expr->rtype->type == TYPEPOINTER); + + is_wide = TYPE_POINTER(expr->rtype)->target->size != 1; + if (copts.poolstrings) { + if (is_wide) + str = CInit_DeclarePooledWString(expr->data.string.data, expr->data.string.size); + else + str = CInit_DeclarePooledString(expr->data.string.data, expr->data.string.size, expr->data.string.ispascal); + + if (str->offset) { + expr->type = EADD; + expr->data.diadic.right = intconstnode(TYPE(&stunsignedlong), str->offset); + expr->data.diadic.left = create_objectrefnode(str->obj); + expr->cost = 1; + } else { + expr->type = EOBJREF; + expr->data.objref = str->obj; + } + } else { + expr->type = EOBJREF; + expr->data.objref = CInit_DeclareString(expr->data.string.data, expr->data.string.size, expr->data.string.ispascal, is_wide); + } +} + +void CInit_DeclarePooledStrings(void) { + SInt32 size; + char *buffer; + PooledString *str; + + size = 0; + for (str = cinit_pooledstringlist; str; str = str->next) + size += str->size; + + if (size) { + cinit_pooledstringlist->obj->type = CDecl_NewArrayType(TYPE(&stchar), size); + buffer = galloc(size); + for (str = cinit_pooledstringlist; str; str = str->next) + memcpy(buffer + str->offset, str->data, str->size); + + if (copts.readonly_strings) + CInit_DeclareReadOnlyData(cinit_pooledstringlist->obj, buffer, NULL, size); + else + CInit_DeclareData(cinit_pooledstringlist->obj, buffer, NULL, size); + } + + size = 0; + for (str = cinit_pooledwstringlist; str; str = str->next) + size += str->size; + + if (size) { + cinit_pooledwstringlist->obj->type = CDecl_NewArrayType(CParser_GetWCharType(), size); + buffer = galloc(size); + for (str = cinit_pooledwstringlist; str; str = str->next) + memcpy(buffer + str->offset, str->data, str->size); + + if (copts.readonly_strings) + CInit_DeclareReadOnlyData(cinit_pooledwstringlist->obj, buffer, NULL, size); + else + CInit_DeclareData(cinit_pooledwstringlist->obj, buffer, NULL, size); + } +} + +static void declaredata(Object *obj, void *data, OLinkList *list, SInt32 size, Boolean is_readonly) { + OLinkList *scan; + UInt32 qual; + + qual = obj->qual; + + if (cparamblkptr->precompile == 1) { + PreComp_StaticData(obj, data, list, size); + } else { + obj->flags = obj->flags | OBJECT_DEFINED; + if (!fatalerrors) { + for (scan = list; scan; scan = scan->next) + CInline_ObjectAddrRef(scan->obj); + if (copts.filesyminfo) + CPrep_SetSourceFile(&cparser_fileoffset); + if (is_readonly) + ObjGen_DeclareReadOnlyData(obj, data, list, size); + else + ObjGen_DeclareData(obj, data, list, size); + obj->qual = qual; + } + } +} + +void CInit_DeclareData(Object *obj, void *data, OLinkList *list, SInt32 size) { + declaredata(obj, data, list, size, 0); +} + +void CInit_DeclareReadOnlyData(Object *obj, void *data, OLinkList *list, SInt32 size) { + declaredata(obj, data, list, size, 1); +} + +void CInit_DefineTentativeData(void) { + ObjectList *list; + + for (list = cinit_tentative; list; list = list->next) { + if (!(list->object->flags & OBJECT_DEFINED)) + CInit_DeclareData(list->object, NULL, NULL, list->object->type->size); + } + + cinit_tentative = NULL; +} diff --git a/compiler_and_linker/FrontEnd/C/CInline.c b/compiler_and_linker/FrontEnd/C/CInline.c new file mode 100644 index 0000000..de51ab7 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CInline.c @@ -0,0 +1,4206 @@ +#include "compiler/CInline.h" +#include "compiler/CABI.h" +#include "compiler/CClass.h" +#include "compiler/CError.h" +#include "compiler/CException.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInit.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/COptimizer.h" +#include "compiler/CParser.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CTemplateNew.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/Exceptions.h" +#include "compiler/InlineAsm.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/Switch.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct IDTrans { + struct IDTrans *next; + SInt32 from; + SInt32 to; +} IDTrans; + +typedef struct LabelTrans { + struct LabelTrans *next; + CLabel **labelptr; + short id; +} LabelTrans; + +typedef struct UIDTemp { + struct UIDTemp *next; + Object *object; + SInt32 uid; +} UIDTemp; + +typedef struct CI_Export { + struct CI_Export *next; + Object *object; + CI_FuncData *funcdata; + Boolean xC; +} CI_Export; + +typedef struct AObject { + Object *object; + ENode *expr1; + ENode *expr2; +} AObject; + +typedef struct CI_StmtLink { + struct CI_StmtLink *next; + Statement *stmt; + CI_Statement *ciStmt; +} CI_StmtLink; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static CInlineCopyMode enode_copymode; +static Boolean enode_globalcopy; +static IDTrans *enode_idtrans; +static Object **local_dobjects; +static AObject *local_aobjects; +static CI_Var *loc_args; +static CI_Var *loc_vars; +static Boolean inline_expanded; +static Boolean any_inline_expanded; +static short cinline_level; +static LabelTrans *cinline_label_trans; +static Statement *cinline_first_stmt; +static ENode *cinline_stmtlevelexpr[16]; +static short cinline_stmtlevelexprs; +static Boolean cinline_unconditionalpart; +static Boolean cinline_serialize_stmt; +static CI_Export *cinline_exportlist; // type? +static CI_Action *cinline_actionlist; +CI_Action *cinline_tactionlist; +static ObjectList *cinline_freflist; +static Boolean cinline_gendeps; +static Statement *cinline_serial_stmt; +static Statement *cinline_cur_serial_stmt; +static UIDTemp *cinline_uid_temps; +static Boolean cinline_has_sideeffect; +static SInt32 inline_max_size; +static Boolean recursive_inline; +static Object *expanding_function; +static Boolean cinline_funccallfound; + +// forward decls +static ENode *CInline_FoldConst(ENode *expr); +static ENode *CInline_CopyNodes(ENode *node); +static SInt32 CInline_EstimateSizeOfFunc(CI_FuncData *funcdata, SInt32 size, SInt32 level); +static ENode *CInline_SerializeExpr(ENode *expr); +static void CInline_AddFRefList_InlineFunc(CI_FuncData *data); + +void CInline_Init(void) { + cinline_exportlist = NULL; + cinline_actionlist = NULL; + cinline_tactionlist = NULL; + cinline_gendeps = 0; +} + +static ENode *CInline_MakeNotNot(ENode *expr) { + expr = CInline_FoldConst(expr); + + if (!ENODE_IS(expr, EINTCONST)) { + expr = makemonadicnode(expr, ELOGNOT); + expr->rtype = CParser_GetBoolType(); + expr = makemonadicnode(expr, ELOGNOT); + } else { + expr->data.intval = CInt64_Not(CInt64_Not(expr->data.intval)); + } + + return expr; +} + +static ENode *CInline_FoldConst(ENode *expr) { + ENode *inner; + ENode *right; + ENode *left; + ENodeList *list; + + switch (expr->type) { + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ETEMP: + case ELABEL: + case EOBJLIST: + case EINSTRUCTION: + case EVECTOR128CONST: + return expr; + + case EMONMIN: + case EBINNOT: + case ELOGNOT: + expr->data.monadic = CInline_FoldConst(expr->data.monadic); + inner = expr->data.monadic; + switch (inner->type) { + case EINTCONST: + if (!ENODE_IS(expr, ELOGNOT)) { + inner->data.intval = CMach_CalcIntMonadic( + expr->rtype, CParser_GetOperator(expr->type), inner->data.intval); + } else { + inner->data.intval = CInt64_Not(inner->data.intval); + } + inner->rtype = expr->rtype; + return inner; + + case EFLOATCONST: + if (ENODE_IS(expr, ELOGNOT)) { + inner->type = EINTCONST; + CInt64_SetLong(&inner->data.intval, CMach_FloatIsZero(inner->data.floatval)); + } else { + inner->data.floatval = CMach_CalcFloatMonadic( + expr->rtype, CParser_GetOperator(expr->type), inner->data.floatval); + } + inner->rtype = expr->rtype; + return inner; + } + + return expr; + + case ETYPCON: + expr->data.monadic = CInline_FoldConst(expr->data.monadic); + switch (expr->data.monadic->type) { + case EINTCONST: + switch (expr->rtype->type) { + case TYPEFLOAT: + expr->type = EFLOATCONST; + expr->data.floatval = CMach_CalcFloatConvertFromInt( + expr->data.monadic->rtype, expr->data.monadic->data.intval); + return expr; + + case TYPEINT: + expr->type = EINTCONST; + expr->data.intval = CExpr_IntConstConvert( + expr->rtype, expr->data.monadic->rtype, expr->data.monadic->data.intval); + break; + } + break; + + case EFLOATCONST: + switch (expr->rtype->type) { + case TYPEFLOAT: + expr->type = EFLOATCONST; + expr->data.floatval = CMach_CalcFloatConvert( + expr->rtype, expr->data.monadic->data.floatval); + return expr; + + case TYPEINT: + expr->type = EINTCONST; + expr->data.intval = CMach_CalcIntConvertFromFloat( + expr->rtype, expr->data.monadic->data.floatval); + return expr; + } + break; + } + + return expr; + + case EPOSTINC: + case EPOSTDEC: + expr->data.monadic = CInline_FoldConst(expr->data.monadic); + switch (expr->data.monadic->type) { + case EINTCONST: + case EFLOATCONST: + expr->data.monadic->rtype = expr->rtype; + return expr->data.monadic; + } + + return expr; + + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EFORCELOAD: + case EBITFIELD: + expr->data.monadic = CInline_FoldConst(expr->data.monadic); + return expr; + + case EMUL: + case EDIV: + case EMODULO: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case EAND: + case EXOR: + case EOR: + expr->data.diadic.left = CInline_FoldConst(expr->data.diadic.left); + expr->data.diadic.right = CInline_FoldConst(expr->data.diadic.right); + if ((left = expr->data.diadic.left)->type == (right = expr->data.diadic.right)->type) { + switch (left->type) { + case EINTCONST: + left->data.intval = CMach_CalcIntDiadic( + expr->rtype, + expr->data.diadic.left->data.intval, + CParser_GetOperator(expr->type), + right->data.intval); + left->rtype = expr->rtype; + return left; + + case EFLOATCONST: + left->data.floatval = CMach_CalcFloatDiadic( + expr->rtype, + expr->data.diadic.left->data.floatval, + CParser_GetOperator(expr->type), + right->data.floatval); + left->rtype = expr->rtype; + return left; + } + } + + return expr; + + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + expr->data.diadic.left = CInline_FoldConst(expr->data.diadic.left); + expr->data.diadic.right = CInline_FoldConst(expr->data.diadic.right); + if ((left = expr->data.diadic.left)->type == (right = expr->data.diadic.right)->type) { + switch (left->type) { + case EINTCONST: + left->data.intval = CMach_CalcIntDiadic( + left->rtype, + expr->data.diadic.left->data.intval, + CParser_GetOperator(expr->type), + right->data.intval); + left->rtype = expr->rtype; + return left; + + case EFLOATCONST: + CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool( + left->rtype, + expr->data.diadic.left->data.floatval, + CParser_GetOperator(expr->type), + right->data.floatval + )); + left->type = EINTCONST; + left->rtype = expr->rtype; + return left; + } + } + + return expr; + + case ELAND: + expr->data.diadic.left = CInline_FoldConst(expr->data.diadic.left); + if (iszero(expr->data.diadic.left)) + return expr->data.diadic.left; + if (isnotzero(expr->data.diadic.left)) + return CInline_MakeNotNot(expr->data.diadic.right); + + expr->data.diadic.right = CInline_FoldConst(expr->data.diadic.right); + if (isnotzero(expr->data.diadic.right)) + return CInline_MakeNotNot(expr->data.diadic.left); + + return expr; + + case ELOR: + expr->data.diadic.left = CInline_FoldConst(expr->data.diadic.left); + if (iszero(expr->data.diadic.left)) + return CInline_MakeNotNot(expr->data.diadic.right); + if (isnotzero(expr->data.diadic.left)) + return CInline_MakeNotNot(expr->data.diadic.left); + + expr->data.diadic.right = CInline_FoldConst(expr->data.diadic.right); + if (iszero(expr->data.diadic.right)) + return CInline_MakeNotNot(expr->data.diadic.left); + + return expr; + + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + case EROTL: + case EROTR: + expr->data.diadic.left = CInline_FoldConst(expr->data.diadic.left); + expr->data.diadic.right = CInline_FoldConst(expr->data.diadic.right); + return expr; + + case ECOND: + expr->data.cond.cond = CInline_FoldConst(expr->data.cond.cond); + if (isnotzero(expr->data.cond.cond)) + return CInline_FoldConst(expr->data.cond.expr1); + if (iszero(expr->data.cond.cond)) + return CInline_FoldConst(expr->data.cond.expr2); + + expr->data.cond.expr1 = CInline_FoldConst(expr->data.cond.expr1); + expr->data.cond.expr2 = CInline_FoldConst(expr->data.cond.expr2); + return expr; + + case EMFPOINTER: + expr->data.mfpointer.accessnode = CInline_FoldConst(expr->data.mfpointer.accessnode); + expr->data.mfpointer.mfpointer = CInline_FoldConst(expr->data.mfpointer.mfpointer); + return expr; + + case EFUNCCALL: + case EFUNCCALLP: + expr->data.funccall.funcref = CInline_FoldConst(expr->data.funccall.funcref); + for (list = expr->data.funccall.args; list; list = list->next) + list->node = CInline_FoldConst(list->node); + return expr; + + case ENULLCHECK: + expr->data.nullcheck.nullcheckexpr = CInline_FoldConst(expr->data.nullcheck.nullcheckexpr); + expr->data.nullcheck.condexpr = CInline_FoldConst(expr->data.nullcheck.condexpr); + return expr; + + case EMEMBER: + if (expr->data.emember->expr) + expr->data.emember->expr = CInline_FoldConst(expr->data.emember->expr); + return expr; + + default: + CError_FATAL(421); + return expr; + } +} + +// unknown name +CW_INLINE SInt32 CInline_GetLocalID2(Object *object) { + ObjectList *list; + SInt32 counter; + + for (list = locals, counter = 0; list; list = list->next) { + if (list->object->datatype == DLOCAL) { + if (list->object == object) + return counter; + counter++; + } + } + + return -1; +} + +SInt32 CInline_GetLocalID(Object *object) { + ObjectList *list; + SInt32 counter; + + if (object) { + for (list = arguments, counter = 0; list; list = list->next, counter++) { + if (list->object == object) { + loc_args[counter].xD = 1; + loc_args[counter].xE = 0; + return counter - 0x7FFFFFFF; + } + } + + counter = CInline_GetLocalID2(object); + CError_ASSERT(465, counter >= 0); + loc_vars[counter].xD = 1; + return counter + 1; + } + + return 0; +} + +static Boolean CInline_IsTrivialExpression(ENode *expr) { + while (1) { + switch (expr->type) { + case EINTCONST: + case EFLOATCONST: + case EOBJREF: + case EARGOBJ: + case ELOCOBJ: + case EOBJLIST: + case EVECTOR128CONST: + return 0; + + case ESTRINGCONST: + return copts.dont_reuse_strings; + + case EMEMBER: + if (expr->data.emember->expr) + return CInline_IsTrivialExpression(expr->data.emember->expr); + return 0; + + case EINDIRECT: + if (ENODE_IS(expr->data.monadic, EOBJREF)) { + if (expr->data.monadic->data.objref->datatype == DLOCAL && + !(expr->data.monadic->data.objref->flags & OBJECT_FLAGS_2)) + return 0; + + if (is_const_object(expr->data.monadic->data.objref)) + return 0; + + return 1; + } + + return 1; + + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EFORCELOAD: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case EFUNCCALL: + case EFUNCCALLP: + case EMFPOINTER: + case ENULLCHECK: + case EPRECOMP: + case ETEMP: + case ELABEL: + case EINSTRUCTION: + return 1; + + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case ETYPCON: + case EBITFIELD: + expr = expr->data.monadic; + continue; + + case EMUL: + case EDIV: + case EMODULO: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case ECOMMA: + case EROTL: + case EROTR: + if (CInline_IsTrivialExpression(expr->data.diadic.left)) + return 1; + expr = expr->data.diadic.right; + continue; + + case ECOND: + if (CInline_IsTrivialExpression(expr->data.cond.cond)) + return 1; + if (CInline_IsTrivialExpression(expr->data.cond.expr1)) + return 1; + expr = expr->data.cond.expr2; + continue; + + default: + CError_FATAL(582); + } + } +} + +Boolean CInline_ExpressionHasSideEffect(ENode *expr) { + while (1) { + switch (expr->type) { + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ETEMP: + case EARGOBJ: + case ELOCOBJ: + case ELABEL: + case EOBJLIST: + case EVECTOR128CONST: + return 0; + + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case EFUNCCALL: + case EFUNCCALLP: + case EINSTRUCTION: + return 1; + + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + expr = expr->data.monadic; + continue; + + case EMUL: + case EDIV: + case EMODULO: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case ECOMMA: + case EROTL: + case EROTR: + if (CInline_ExpressionHasSideEffect(expr->data.diadic.left)) + return 1; + expr = expr->data.diadic.right; + continue; + + case EMEMBER: + if (expr->data.emember->expr) + return CInline_ExpressionHasSideEffect(expr->data.emember->expr); + return 0; + + case EMFPOINTER: + if (CInline_ExpressionHasSideEffect(expr->data.mfpointer.accessnode)) + return 1; + expr = expr->data.mfpointer.mfpointer; + continue; + + case ENULLCHECK: + if (CInline_ExpressionHasSideEffect(expr->data.nullcheck.nullcheckexpr)) + return 1; + expr = expr->data.nullcheck.condexpr; + continue; + + case ECOND: + if (CInline_ExpressionHasSideEffect(expr->data.cond.cond)) + return 1; + if (CInline_ExpressionHasSideEffect(expr->data.cond.expr1)) + return 1; + expr = expr->data.cond.expr2; + continue; + + default: + CError_FATAL(689); + } + } +} + +static ENode *CInline_CopyExpressionSave(ENode *expr) { + CInlineCopyMode save_copymode; + Boolean save_globalcopy; + IDTrans *save_idtrans; + + save_globalcopy = enode_globalcopy; + enode_globalcopy = 1; + + save_copymode = enode_copymode; + enode_copymode = CopyMode4; + + save_idtrans = enode_idtrans; + enode_idtrans = NULL; + + expr = CInline_CopyNodes(expr); + + enode_globalcopy = save_globalcopy; + enode_copymode = save_copymode; + enode_idtrans = save_idtrans; + + return expr; +} + +static SInt32 CInline_TranslateID(SInt32 id) { + IDTrans *trans; + + for (trans = enode_idtrans; trans; trans = trans->next) { + if (trans->from == id) + return trans->to; + } + + trans = lalloc(sizeof(IDTrans)); + trans->next = enode_idtrans; + enode_idtrans = trans; + + trans->from = id; + trans->to = CParser_GetUniqueID(); + + return trans->to; +} + +static short CInline_GetLabelStatementNumber(HashNameNode *name) { + Statement *stmt; + short i; + + for (stmt = cinline_first_stmt, i = 0; stmt; stmt = stmt->next, i++) { + if (stmt->type == ST_LABEL && stmt->label->uniquename == name) + return i; + } + + CError_FATAL(742); + return 0; +} + +static ENodeList *CInline_CopyNodeList(ENodeList *list) { + ENodeList *copy; + ENodeList *first; + ENodeList *last; + + first = NULL; + while (list) { + if (enode_globalcopy) + copy = galloc(sizeof(ENodeList)); + else + copy = lalloc(sizeof(ENodeList)); + + copy->node = CInline_CopyNodes(list->node); + copy->next = NULL; + + if (first) { + last->next = copy; + last = copy; + } else { + first = last = copy; + } + + list = list->next; + } + + return first; +} + +static EMemberInfo *CInline_CopyEMemberInfo(EMemberInfo *mi) { + EMemberInfo *copy; + + if (enode_globalcopy) + copy = galloc(sizeof(EMemberInfo)); + else + copy = lalloc(sizeof(EMemberInfo)); + + *copy = *mi; + if (copy->path) + copy->path = CClass_GetPathCopy(copy->path, enode_globalcopy); + if (copy->expr) + copy->expr = CInline_CopyNodes(copy->expr); + + return copy; +} + +static ENode *CInline_CopyNodes(ENode *node) { + ENode *copy; + + if (enode_globalcopy) + copy = galloc(sizeof(ENode)); + else + copy = lalloc(sizeof(ENode)); + + while (1) { + *copy = *node; + switch (copy->type) { + case ETEMPLDEP: + switch (copy->data.templdep.subtype) { + case TDE_PARAM: + case TDE_SIZEOF: + case TDE_ALIGNOF: + case TDE_QUALNAME: + case TDE_OBJ: + break; + case TDE_CAST: + copy->data.templdep.u.cast.args = CInline_CopyNodeList(copy->data.templdep.u.cast.args); + break; + case TDE_SOURCEREF: + copy->data.templdep.u.sourceref.expr = CInline_CopyNodes(copy->data.templdep.u.sourceref.expr); + break; + case TDE_ADDRESS_OF: + copy->data.templdep.u.monadic = CInline_CopyNodes(copy->data.templdep.u.monadic); + break; + default: + CError_FATAL(840); + } + break; + + case ETEMP: + if (enode_copymode == CopyMode3 && copy->data.temp.uniqueid) + copy->data.temp.uniqueid = CInline_TranslateID(copy->data.temp.uniqueid); + break; + + case ELABEL: + switch (enode_copymode) { + case CopyMode2: + copy->data.precompid = CInline_GetLabelStatementNumber(copy->data.label->uniquename); + return copy; + case CopyMode3: + case CopyMode4: { + LabelTrans *trans = lalloc(sizeof(LabelTrans)); + trans->next = cinline_label_trans; + cinline_label_trans = trans; + trans->id = copy->data.precompid; + trans->labelptr = ©->data.label; + return copy; + } + } + break; + + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJLIST: + case EINSTRUCTION: + case EVECTOR128CONST: + break; + + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + copy->data.monadic = CInline_CopyNodes(copy->data.monadic); + break; + + ENODE_CASE_DIADIC_ALL: + copy->data.diadic.left = CInline_CopyNodes(copy->data.diadic.left); + copy->data.diadic.right = CInline_CopyNodes(copy->data.diadic.right); + break; + + case ECOND: + copy->data.cond.cond = CInline_CopyNodes(copy->data.cond.cond); + copy->data.cond.expr1 = CInline_CopyNodes(copy->data.cond.expr1); + copy->data.cond.expr2 = CInline_CopyNodes(copy->data.cond.expr2); + break; + + case EMFPOINTER: + copy->data.mfpointer.accessnode = CInline_CopyNodes(copy->data.mfpointer.accessnode); + copy->data.mfpointer.mfpointer = CInline_CopyNodes(copy->data.mfpointer.mfpointer); + break; + + case EFUNCCALL: + case EFUNCCALLP: + copy->data.funccall.funcref = CInline_CopyNodes(copy->data.funccall.funcref); + copy->data.funccall.args = CInline_CopyNodeList(copy->data.funccall.args); + break; + + case ENULLCHECK: + copy->data.nullcheck.precompid = CInline_TranslateID(copy->data.nullcheck.precompid); + copy->data.nullcheck.nullcheckexpr = CInline_CopyNodes(copy->data.nullcheck.nullcheckexpr); + copy->data.nullcheck.condexpr = CInline_CopyNodes(copy->data.nullcheck.condexpr); + break; + + case EPRECOMP: + copy->data.precompid = CInline_TranslateID(copy->data.precompid); + break; + + case EINDIRECT: + if ( + enode_copymode == CopyMode4 && + ENODE_IS(copy->data.monadic, EARGOBJ) && + local_aobjects[copy->data.monadic->data.longval].object == NULL + ) + { + CError_ASSERT(910, local_aobjects[copy->data.monadic->data.longval].expr1); + copy = CInline_CopyExpressionSave(local_aobjects[copy->data.monadic->data.longval].expr1); + if (copy->rtype != node->rtype) { + if (IS_TYPE_INT(copy->rtype) && IS_TYPE_INT(node->rtype)) + copy = makemonadicnode(copy, ETYPCON); + copy->rtype = node->rtype; + } + return copy; + } + + copy->data.monadic = CInline_CopyNodes(copy->data.monadic); + break; + + case EOBJREF: + if (enode_copymode == CopyMode2) { + ObjectList *list; + int i; + + if (node->data.objref->datatype == DALIAS) { + CExpr_AliasTransform(node); + continue; + } + + if (node->data.objref->datatype == DDATA) + return copy; + + for (list = arguments, i = 0; list; list = list->next, i++) { + if (list->object == copy->data.objref) { + copy->type = EARGOBJ; + copy->data.longval = i; + return copy; + } + } + + i = CInline_GetLocalID2(copy->data.objref); + if (i >= 0) { + copy->type = ELOCOBJ; + copy->data.longval = i; + return copy; + } + + if (node->data.objref->datatype == DLOCAL) + CError_FATAL(949); + } + break; + + case EARGOBJ: + switch (enode_copymode) { + case CopyMode4: + CError_ASSERT(957, local_aobjects[copy->data.longval].object); + copy->type = EOBJREF; + copy->data.objref = local_aobjects[copy->data.longval].object; + return copy; + + case CopyMode3: { + ObjectList *list; + int i; + for (list = arguments, i = 0; list; list = list->next, i++) { + if (i == copy->data.longval) { + copy->type = EOBJREF; + copy->data.objref = list->object; + CError_ASSERT(966, copy->data.objref); + return copy; + } + } + } + + default: + CError_FATAL(971); + } + + case ELOCOBJ: + switch (enode_copymode) { + case CopyMode4: + copy->type = EOBJREF; + copy->data.objref = local_dobjects[copy->data.longval]; + return copy; + + case CopyMode3: { + ObjectList *list; + int i; + for (list = locals, i = 0; list; list = list->next, i++) { + if (i == copy->data.longval) { + copy->type = EOBJREF; + copy->data.objref = list->object; + CError_ASSERT(986, copy->data.objref); + return copy; + } + } + } + + default: + CError_FATAL(991); + } + break; + + case ENEWEXCEPTION: + case ENEWEXCEPTIONARRAY: + copy->data.newexception.initexpr = CInline_CopyNodes(copy->data.newexception.initexpr); + copy->data.newexception.tryexpr = CInline_CopyNodes(copy->data.newexception.tryexpr); + break; + + case EINITTRYCATCH: + copy->data.itc.initexpr = CInline_CopyNodes(copy->data.itc.initexpr); + copy->data.itc.tryexpr = CInline_CopyNodes(copy->data.itc.tryexpr); + copy->data.itc.catchexpr = CInline_CopyNodes(copy->data.itc.catchexpr); + copy->data.itc.result = CInline_CopyNodes(copy->data.itc.result); + break; + + case EMEMBER: + copy->data.emember = CInline_CopyEMemberInfo(copy->data.emember); + break; + + default: + CError_FATAL(1015); + } + + return copy; + } +} + +static void CInline_CheckUsage(ENode *expr, Boolean flag) { + ENodeList *list; + ENode *inner; + + while (1) { + switch (expr->type) { + case EARGOBJ: + loc_args[expr->data.longval].xD = 1; + loc_args[expr->data.longval].xE = 0; + return; + + case ELOCOBJ: + loc_vars[expr->data.longval].xD = 1; + return; + + case EINDIRECT: + if (ENODE_IS((inner = expr->data.monadic), EARGOBJ)) { + loc_args[inner->data.longval].xD = 1; + if (flag) + loc_args[inner->data.longval].xE = 0; + return; + } + expr = expr->data.monadic; + flag = 0; + continue; + + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + expr = expr->data.monadic; + flag = 0; + continue; + + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + expr = expr->data.monadic; + flag = 1; + continue; + + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + CInline_CheckUsage(expr->data.diadic.left, 1); + expr = expr->data.diadic.right; + flag = 0; + continue; + + case EMUL: + case EDIV: + case EMODULO: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case ECOMMA: + case EROTL: + case EROTR: + CInline_CheckUsage(expr->data.diadic.left, 0); + expr = expr->data.diadic.right; + flag = 0; + continue; + + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ETEMP: + case ELABEL: + case EOBJLIST: + case EVECTOR128CONST: + return; + + case EMEMBER: + if (expr->data.emember->expr) + CInline_CheckUsage(expr->data.emember->expr, 0); + return; + + case EFUNCCALL: + case EFUNCCALLP: + CInline_CheckUsage(expr->data.funccall.funcref, 0); + for (list = expr->data.funccall.args; list; list = list->next) + CInline_CheckUsage(list->node, 0); + return; + + case ENULLCHECK: + CInline_CheckUsage(expr->data.nullcheck.nullcheckexpr, 0); + expr = expr->data.nullcheck.condexpr; + flag = 0; + continue; + + case EMFPOINTER: + CInline_CheckUsage(expr->data.mfpointer.accessnode, 0); + expr = expr->data.mfpointer.mfpointer; + flag = 0; + continue; + + case ECOND: + CInline_CheckUsage(expr->data.cond.cond, 0); + CInline_CheckUsage(expr->data.cond.expr1, 0); + expr = expr->data.cond.expr2; + flag = 0; + continue; + + case EINSTRUCTION: + return; + + default: + CError_FATAL(1146); + } + } +} + +ENode *CInline_CopyExpression(ENode *expr, CInlineCopyMode mode) { + enode_copymode = mode; + + switch (mode) { + case CopyMode0: + case CopyMode4: + enode_idtrans = NULL; + enode_globalcopy = 0; + expr = CInline_CopyNodes(expr); + break; + case CopyMode3: + enode_globalcopy = 0; + expr = CInline_CopyNodes(expr); + break; + case CopyMode1: + enode_idtrans = NULL; + enode_globalcopy = 1; + expr = CInline_CopyNodes(expr); + break; + case CopyMode2: + enode_idtrans = NULL; + enode_globalcopy = 1; + expr = CInline_CopyNodes(expr); + CInline_CheckUsage(expr, 0); + break; + } + + return expr; +} + +static UInt8 CInline_GetObjectSFlags(Object *object) { + UInt8 flags; + + switch (object->sclass) { + case 0: + flags = CI_SFLAGS_NoClass; + break; + case TK_REGISTER: + flags = CI_SFLAGS_Register; + break; + case TK_AUTO: + flags = CI_SFLAGS_Auto; + break; + default: + CError_FATAL(1204); + } + + if (object->flags & OBJECT_FLAGS_2) + flags |= CI_SFLAGS_HasObjectFlag2; + + return flags; +} + +static void CInline_SetObjectSFlags(Object *object, UInt8 sflags) { + if (sflags & CI_SFLAGS_HasObjectFlag2) { + object->flags |= OBJECT_FLAGS_2; + sflags &= ~CI_SFLAGS_HasObjectFlag2; + } + + switch (sflags) { + case CI_SFLAGS_NoClass: + object->sclass = 0; + break; + case CI_SFLAGS_Register: + object->sclass = TK_REGISTER; + break; + case CI_SFLAGS_Auto: + object->sclass = TK_AUTO; + break; + default: + CError_FATAL(1229); + } +} + +static Object *CInline_NewLocalObject(Type *type, short qual, UInt8 sflags, int unk) { + Object *object = CParser_NewLocalDataObject(NULL, 1); + object->name = CParser_GetUniqueName(); + object->type = type; + object->qual = qual; + CInline_SetObjectSFlags(object, sflags); + CFunc_SetupLocalVarInfo(object); + return object; +} + +static ENode *CInline_FuncArgConvert(ENode *expr) { + ENode *copy; + + switch (expr->type) { + case EOBJREF: + copy = lalloc(sizeof(ENode)); + *copy = *expr; + return copy; + case ETEMP: + CError_FATAL(1272); + } + + return NULL; +} + +static ENode *CInline_RefArgTransform(ENode *expr, Boolean flag) { + ENodeList *arg; + + while (ENODE_IS(expr, ECOMMA)) + expr = expr->data.diadic.right; + + switch (expr->type) { + case EOBJREF: + case ETEMP: + if (flag) + return CInline_FuncArgConvert(expr); + break; + + case EFUNCCALL: + if (IS_TYPE_POINTER_ONLY(expr->rtype) && IS_TYPE_CLASS(TPTR_TARGET(expr->rtype))) { + if ( + ENODE_IS(expr->data.funccall.funcref, EOBJREF) && + CClass_IsConstructor(expr->data.funccall.funcref->data.objref) && + expr->data.funccall.args + ) + return CInline_FuncArgConvert(expr->data.funccall.args->node); + + if ( + TPTR_TARGET(expr->rtype) == expr->data.funccall.functype->functype && + CMach_GetFunctionResultClass(expr->data.funccall.functype) == 1 && + (arg = expr->data.funccall.args) + ) + { + switch (CABI_GetStructResultArgumentIndex(expr->data.funccall.functype)) { + case 0: + break; + case 1: + if ((arg = arg->next)) + break; + CError_FATAL(1313); + default: + CError_FATAL(1314); + } + + return CInline_FuncArgConvert(arg->node); + } + } + break; + } + + return NULL; +} + +static ENode *CInline_SetupArgsExpression(Object *object, CI_FuncData *data, ENodeList *list) { + ENode *commaNodes; + CI_Var *var; + ENodeList *scan; + ENode *expr; + SInt32 i; + Boolean is_oldstyle; + + is_oldstyle = 0; + if (TYPE_FUNC(object->type)->args == &oldstyle) + is_oldstyle = 1; + + local_dobjects = lalloc(sizeof(Object *) * data->numlocals); + local_aobjects = lalloc(sizeof(AObject) * data->numarguments); + + for (i = 0, var = data->locals; i < data->numlocals; i++, var++) { + if (var->xD) { + object = CInline_NewLocalObject(var->type, var->qual, var->sflags, 0); + local_dobjects[i] = object; + if (!var->xE) + object->flags |= OBJECT_FLAGS_2; + } else { + local_dobjects[i] = NULL; + } + } + + for (i = 0, var = data->arguments, scan = list; i < data->numarguments; i++, var++) { + local_aobjects[i].expr2 = NULL; + + if (!var->xD) { + local_aobjects[i].object = NULL; + local_aobjects[i].expr1 = NULL; + } else if ( + scan && + var->xE && + !CInline_IsTrivialExpression(scan->node) && + (!is_oldstyle || scan->node->rtype->size == var->type->size) + ) + { + local_aobjects[i].object = NULL; + local_aobjects[i].expr1 = scan->node; + } else if ( + scan && + var->xE && + IS_TYPE_REFERENCE(var->type) && + (expr = CInline_RefArgTransform(scan->node, 1)) + ) + { + local_aobjects[i].object = NULL; + local_aobjects[i].expr1 = expr; + local_aobjects[i].expr2 = scan->node; + } else { + local_aobjects[i].object = CInline_NewLocalObject(var->type, var->qual, var->sflags, 0); + local_aobjects[i].expr1 = NULL; + } + + if (scan) + scan = scan->next; + } + + commaNodes = NULL; + + for (i = 0, scan = list; scan; scan = scan->next, i++) { + if (i >= data->numarguments) { + if (!commaNodes) + commaNodes = scan->node; + else + commaNodes = makecommaexpression(scan->node, commaNodes); + } else if (!local_aobjects[i].object || local_aobjects[i].expr2) { + if (local_aobjects[i].expr2) { + if (!commaNodes) + commaNodes = local_aobjects[i].expr2; + else + commaNodes = makecommaexpression(local_aobjects[i].expr2, commaNodes); + } else if (!local_aobjects[i].expr1 && CInline_IsTrivialExpression(scan->node)) { + commaNodes = !commaNodes ? scan->node : makecommaexpression(scan->node, commaNodes); + CError_ASSERT(1470, !ENODE_IS(scan->node, EPRECOMP)); + } + } else { + if (is_oldstyle && scan->node->rtype->size != local_aobjects[i].object->type->size) { + scan->node = makemonadicnode(scan->node, ETYPCON); + scan->node->rtype = local_aobjects[i].object->type; + } + + expr = makediadicnode(create_objectnode2(local_aobjects[i].object), scan->node, EASS); + if (!commaNodes) + commaNodes = expr; + else + commaNodes = makecommaexpression(expr, commaNodes); + } + } + + return commaNodes; +} + +static void CInline_ReturnCheckCB(ENode *expr) { + cinline_has_sideeffect = 1; +} + +static ENode *CInline_ReturnCheck(ENode *expr) { + ENode *copy; + + if (ENODE_IS(expr, EFORCELOAD)) + return expr; + + cinline_has_sideeffect = 0; + CExpr_SearchExprTree(expr, CInline_ReturnCheckCB, 3, EINDIRECT, EFUNCCALL, EFUNCCALLP); + + if (!cinline_has_sideeffect) + return expr; + + copy = lalloc(sizeof(ENode)); + *copy = *expr; + copy->type = EFORCELOAD; + + copy->data.monadic = expr; + return copy; +} + +static ENode *CInline_ReturnMemResult(Object *object) { + int index = CABI_GetStructResultArgumentIndex(TYPE_FUNC(object->type)); + if (local_aobjects[index].object == NULL) + return CInline_CopyExpressionSave(local_aobjects[index].expr1); + else + return create_objectnode(local_aobjects[index].object); +} + +static ENode *CInline_InlineFunctionExpression(ENode *expr) { + Object *object; + CI_FuncData *funcdata; + short i; + Boolean flag26; + ENode *argsExpr; + + object = expr->data.funccall.funcref->data.objref; + if (object->datatype == DALIAS) + object = object->u.alias.object; + + funcdata = object->u.func.u.ifuncdata; + if (!funcdata) + return expr; + + if (funcdata->can_inline < CI_CanInline6) { + if (funcdata->can_inline == CI_CanInline3) { + if (cinline_unconditionalpart && cinline_stmtlevelexprs < 16) + cinline_stmtlevelexpr[cinline_stmtlevelexprs++] = expr; + cinline_serialize_stmt = 1; + } + return expr; + } + + flag26 = CMach_GetFunctionResultClass(TYPE_FUNC(object->type)) == 1; + argsExpr = CInline_SetupArgsExpression(object, funcdata, expr->data.funccall.args); + + for (i = 0; i < funcdata->numstatements; i++) { + switch (funcdata->statements[i].type) { + case ST_RETURN: + if (funcdata->statements[i].u.expr) { + ENode *copy = CInline_CopyExpression(funcdata->statements[i].u.expr, CopyMode4); + if (flag26) { + if (argsExpr) + argsExpr = makecommaexpression(argsExpr, copy); + else + argsExpr = copy; + + argsExpr = makecommaexpression(argsExpr, CInline_ReturnMemResult(object)); + } else { + if (argsExpr) + argsExpr = makecommaexpression(argsExpr, CInline_ReturnCheck(copy)); + else + argsExpr = CInline_ReturnCheck(copy); + } + } + break; + case ST_EXPRESSION: + if (argsExpr) + argsExpr = makecommaexpression(argsExpr, CInline_CopyExpression(funcdata->statements[i].u.expr, CopyMode4)); + else + argsExpr = CInline_CopyExpression(funcdata->statements[i].u.expr, CopyMode4); + break; + + default: + CError_FATAL(1632); + } + } + + if (!argsExpr) + argsExpr = nullnode(); + if (!IS_TYPE_VOID(expr->rtype)) + argsExpr->rtype = expr->rtype; + + inline_expanded = 1; + return CInline_FoldConst(argsExpr); +} + +static Boolean CInline_CanExpand(ENode *expr) { + TypeFunc *tfunc; + Object *object; + + object = expr->data.objref; + tfunc = TYPE_FUNC(object->type); + + if ( + IS_TYPE_FUNC(tfunc) && + ((object->qual & Q_INLINE) || (tfunc->flags & FUNC_FLAGS_800)) && + (object->datatype == DFUNC || (object->datatype == DVFUNC && (expr->flags & ENODE_FLAG_80))) + ) + return 1; + + return 0; +} + +static SInt32 CInline_EstimateSizeOfExpr(ENode *expr, SInt32 size, SInt32 level) { + ENodeList *list; + + switch (expr->type) { + ENODE_CASE_MONADIC: + size = CInline_EstimateSizeOfExpr(expr->data.monadic, size, level) + 1; + break; + + ENODE_CASE_DIADIC_ALL: + size = CInline_EstimateSizeOfExpr(expr->data.diadic.left, size, level); + if (size <= inline_max_size) + size = CInline_EstimateSizeOfExpr(expr->data.diadic.right, size, level) + 1; + break; + + case EFUNCCALL: + case EFUNCCALLP: + if ( + ENODE_IS(expr->data.funccall.funcref, EOBJREF) && + expr->data.funccall.funcref->data.objref->u.func.u.ifuncdata && + CInline_CanExpand(expr->data.funccall.funcref) + ) + { + recursive_inline |= expr->data.funccall.funcref->data.objref == expanding_function; + if (level == 0) { + if (!recursive_inline) + size = inline_max_size + 1; + } else { + size = CInline_EstimateSizeOfFunc(expr->data.funccall.funcref->data.objref->u.func.u.ifuncdata, size, level - 1); + } + } else { + size++; + } + + for (list = expr->data.funccall.args; list; list = list->next) { + if (size > inline_max_size) + break; + + size = CInline_EstimateSizeOfExpr(list->node, size, level); + } + break; + + case ECOND: + size = CInline_EstimateSizeOfExpr(expr->data.cond.cond, size, level); + if (size <= inline_max_size) + size = CInline_EstimateSizeOfExpr(expr->data.cond.expr1, size, level) + 1; + if (size <= inline_max_size) + size = CInline_EstimateSizeOfExpr(expr->data.cond.expr2, size, level) + 1; + break; + + case ENULLCHECK: + size = CInline_EstimateSizeOfExpr(expr->data.nullcheck.nullcheckexpr, size, level); + if (size <= inline_max_size) + size = CInline_EstimateSizeOfExpr(expr->data.nullcheck.condexpr, size, level) + 1; + break; + + case EMFPOINTER: + size = CInline_EstimateSizeOfExpr(expr->data.mfpointer.accessnode, size, level); + if (size <= inline_max_size) + size = CInline_EstimateSizeOfExpr(expr->data.mfpointer.mfpointer, size, level) + 1; + break; + + case EMEMBER: + if (expr->data.emember->expr) + size = CInline_EstimateSizeOfExpr(expr->data.emember->expr, size, level) + 1; + break; + + default: + size++; + } + + return size; +} + +static SInt32 CInline_EstimateSizeOfFunc(CI_FuncData *funcdata, SInt32 size, SInt32 level) { + CI_Statement *stmt; + SInt32 i; + + size += funcdata->numstatements; + if (size > inline_max_size) + return size; + + for (i = 0, stmt = funcdata->statements; i < funcdata->numstatements; i++, stmt++) { + switch (stmt->type) { + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + case ST_ASM: + break; + case ST_EXPRESSION: + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_GOTOEXPR: + size = CInline_EstimateSizeOfExpr(stmt->u.expr, size, level); + break; + case ST_SWITCH: + size = CInline_EstimateSizeOfExpr(stmt->u.switchdata->expr, size, level); + break; + case ST_RETURN: + if (stmt->u.expr) + size = CInline_EstimateSizeOfExpr(stmt->u.expr, size, level); + break; + default: + CError_FATAL(1840); + } + + if (size > inline_max_size) + break; + } + + return size; +} + +static SInt32 EstimateExpandedSizeOfExpr(ENode *expr, SInt32 level) { + ENodeList *list; + SInt32 size; + + size = 0; + + switch (expr->type) { + ENODE_CASE_MONADIC: + size = EstimateExpandedSizeOfExpr(expr->data.monadic, level) + 1; + break; + + ENODE_CASE_DIADIC_ALL: + size = EstimateExpandedSizeOfExpr(expr->data.diadic.left, level) + 1; + size += EstimateExpandedSizeOfExpr(expr->data.diadic.right, level); + break; + + case EFUNCCALL: + case EFUNCCALLP: + if ( + ENODE_IS(expr->data.funccall.funcref, EOBJREF) && + expr->data.funccall.funcref->data.objref->u.func.u.ifuncdata && + CInline_CanExpand(expr->data.funccall.funcref) + ) + { + if (level) { + SInt32 est = CInline_EstimateSizeOfFunc(expr->data.funccall.funcref->data.objref->u.func.u.ifuncdata, size, level - 1); + if (est > inline_max_size) + size++; + else + size += est; + } else { + size++; + } + } else { + size++; + } + + for (list = expr->data.funccall.args; list; list = list->next) + size += EstimateExpandedSizeOfExpr(list->node, level); + break; + + case ECOND: + size = EstimateExpandedSizeOfExpr(expr->data.cond.cond, level) + 1; + size += EstimateExpandedSizeOfExpr(expr->data.cond.expr1, level); + size += EstimateExpandedSizeOfExpr(expr->data.cond.expr2, level); + break; + + case ENULLCHECK: + size = EstimateExpandedSizeOfExpr(expr->data.nullcheck.nullcheckexpr, level) + 1; + size += EstimateExpandedSizeOfExpr(expr->data.nullcheck.condexpr, level); + break; + + case EMFPOINTER: + size = EstimateExpandedSizeOfExpr(expr->data.mfpointer.accessnode, level) + 1; + size += EstimateExpandedSizeOfExpr(expr->data.mfpointer.mfpointer, level); + break; + + case EMEMBER: + if (expr->data.emember->expr) + size = EstimateExpandedSizeOfExpr(expr->data.emember->expr, level); + break; + + default: + size++; + } + + return size; +} + +static SInt32 EstimateExpandedSizeOfFunction(Statement *stmt) { + SInt32 size; + SInt32 level; + + level = copts.inlinelevel; + if (!level) + level = 8; + + size = 0; + + while (stmt) { + switch (stmt->type) { + case ST_NOP: + break; + case ST_EXPRESSION: + case ST_SWITCH: + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_GOTOEXPR: + size++; + size += EstimateExpandedSizeOfExpr(stmt->expr, level); + break; + case ST_RETURN: + size++; + if (stmt->expr) + size = EstimateExpandedSizeOfExpr(stmt->expr, level); + break; + case ST_LABEL: + case ST_GOTO: + case ST_ASM: + size++; + break; + default: + CError_FATAL(2015); + } + + stmt = stmt->next; + } + + return size; +} + +static Boolean CInline_InlineFunctionCheck(ENode *expr) { + Object *object; + SInt32 level; + CI_FuncData *funcdata; + + object = expr->data.objref; + if (object->datatype == DALIAS) + object = object->u.alias.object; + + if ( + IS_TYPE_FUNC(object->type) && + ((object->qual & Q_INLINE) || (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_800)) && + (object->datatype == DFUNC || (object->datatype == DVFUNC && (expr->flags & ENODE_FLAG_80))) + ) + { + if (copts.alwaysinline) + return 1; + + if (copts.inline_bottom_up) { + if (!object->u.func.u.ifuncdata) + return 0; + + level = (copts.inlinelevel == 0) ? (7 - cinline_level) : (copts.inlinelevel - cinline_level - 1); + if ((object->qual & Q_INLINE) && level == 0) + return 1; + + if (CInline_EstimateSizeOfFunc(object->u.func.u.ifuncdata, 0, level) > inline_max_size) + return 0; + } else if (cinline_level > 0 && copts.inlinelevel == 0) { + funcdata = object->u.func.u.ifuncdata; + if (!funcdata) + return 0; + + if (funcdata->numstatements > 10) + return 0; + if (cinline_level > 1 && funcdata->numstatements > 7) + return 0; + if (cinline_level > 2 && funcdata->numstatements > 3) + return 0; + } + + return 1; + } else { + return 0; + } + + return 0; +} + +static ENode *CInline_ExpandExpression(ENode *expr) { + ENodeList *list; + Boolean save; + + switch (expr->type) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case ETYPCON: + case EBITFIELD: + expr->data.monadic = CInline_ExpandExpression(expr->data.monadic); + break; + + case EFORCELOAD: + expr->data.monadic = CInline_ExpandExpression(expr->data.monadic); + if (ENODE_IS(expr->data.monadic, EFORCELOAD)) + expr->data.monadic = expr->data.monadic->data.monadic; + break; + + case EMUL: + case EDIV: + case EMODULO: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case EPMODULO: + case EROTL: + case EROTR: + expr->data.diadic.left = CInline_ExpandExpression(expr->data.diadic.left); + expr->data.diadic.right = CInline_ExpandExpression(expr->data.diadic.right); + break; + + case ELAND: + case ELOR: + case ECOMMA: + expr->data.diadic.left = CInline_ExpandExpression(expr->data.diadic.left); + save = cinline_unconditionalpart; + cinline_unconditionalpart = 0; + expr->data.diadic.right = CInline_ExpandExpression(expr->data.diadic.right); + cinline_unconditionalpart = save; + break; + + case EFUNCCALL: + case EFUNCCALLP: + expr->data.funccall.funcref = CInline_ExpandExpression(expr->data.funccall.funcref); + for (list = expr->data.funccall.args; list; list = list->next) + list->node = CInline_ExpandExpression(list->node); + + if (ENODE_IS(expr->data.funccall.funcref, EOBJREF) && CInline_InlineFunctionCheck(expr->data.funccall.funcref)) + expr = CInline_InlineFunctionExpression(expr); + break; + + case ENULLCHECK: + expr->data.nullcheck.nullcheckexpr = CInline_ExpandExpression(expr->data.nullcheck.nullcheckexpr); + save = cinline_unconditionalpart; + cinline_unconditionalpart = 0; + expr->data.nullcheck.condexpr = CInline_ExpandExpression(expr->data.nullcheck.condexpr); + cinline_unconditionalpart = save; + break; + + case EMFPOINTER: + expr->data.mfpointer.accessnode = CInline_ExpandExpression(expr->data.mfpointer.accessnode); + expr->data.mfpointer.mfpointer = CInline_ExpandExpression(expr->data.mfpointer.mfpointer); + break; + + case ECOND: + expr->data.cond.cond = CInline_ExpandExpression(expr->data.cond.cond); + save = cinline_unconditionalpart; + cinline_unconditionalpart = 0; + expr->data.cond.expr1 = CInline_ExpandExpression(expr->data.cond.expr1); + expr->data.cond.expr2 = CInline_ExpandExpression(expr->data.cond.expr2); + cinline_unconditionalpart = save; + break; + + case EMEMBER: + if (expr->data.emember->expr) + expr = CInline_ExpandExpression(expr->data.emember->expr); + else + expr = nullnode(); + break; + + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ELABEL: + case EOBJLIST: + case EINSTRUCTION: + case EVECTOR128CONST: + break; + + default: + CError_FATAL(2235); + } + + return expr; +} + +static Statement *CInline_NewStatement(StatementType sttype) { + Statement *stmt = lalloc(sizeof(Statement)); + memclrw(stmt, sizeof(Statement)); + + stmt->type = sttype; + if (cinline_serial_stmt) + cinline_cur_serial_stmt->next = stmt; + else + cinline_serial_stmt = stmt; + cinline_cur_serial_stmt = stmt; + + return stmt; +} + +static ENode *CInline_LoadToTemp(ENode *expr, Object **objectptr) { + Object *object; + + object = *objectptr; + if (!object) { + switch (expr->rtype->type) { + case TYPEVOID: + return expr; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPESTRUCT: + case TYPECLASS: + case TYPEMEMBERPOINTER: + case TYPEPOINTER: + object = create_temp_object(expr->rtype); + *objectptr = object; + break; + default: + CError_FATAL(2288); + } + } + + return makediadicnode(create_objectnode(object), expr, EASS); +} + +static ENode *CInline_SerializeEFORCELOAD(ENode *expr) { + Statement *stmt; + Object *temp = NULL; + + while (ENODE_IS(expr->data.monadic, EFORCELOAD)) { + expr->data.monadic = expr->data.monadic->data.monadic; + } + + expr->data.monadic = CInline_SerializeExpr(expr->data.monadic); + stmt = CInline_NewStatement(ST_EXPRESSION); + stmt->expr = CInline_LoadToTemp(expr->data.monadic, &temp); + return create_objectnode(temp); +} + +static ENode *CInline_SerializeECOMMA(ENode *expr) { + Statement *stmt; + + expr->data.diadic.left = CInline_SerializeExpr(expr->data.diadic.left); + stmt = CInline_NewStatement(ST_EXPRESSION); + stmt->expr = expr->data.diadic.left; + return CInline_SerializeExpr(expr->data.diadic.right); +} + +static ENode *CInline_SerializeELOR(ENode *expr) { + ENode *n; + Statement *stmt; + CLabel *label; + Object *temp = NULL; + + label = newlabel(); + + n = makemonadicnode(CInline_SerializeExpr(expr->data.diadic.left), ELOGNOT); + n->rtype = expr->rtype; + n = makemonadicnode(n, ELOGNOT); + n = CInline_LoadToTemp(n, &temp); + stmt = CInline_NewStatement(ST_IFGOTO); + stmt->expr = n; + stmt->label = label; + + n = makemonadicnode(CInline_SerializeExpr(expr->data.diadic.right), ELOGNOT); + n->rtype = expr->rtype; + n = makemonadicnode(n, ELOGNOT); + n = CInline_LoadToTemp(n, &temp); + stmt = CInline_NewStatement(ST_EXPRESSION); + stmt->expr = n; + + stmt = CInline_NewStatement(ST_LABEL); + stmt->label = label; + label->stmt = stmt; + + return create_objectnode(temp); +} + +static ENode *CInline_SerializeELAND(ENode *expr) { + ENode *n; + Statement *stmt; + CLabel *label; + Object *temp = NULL; + + label = newlabel(); + + n = makemonadicnode(CInline_SerializeExpr(expr->data.diadic.left), ELOGNOT); + n->rtype = expr->rtype; + n = makemonadicnode(n, ELOGNOT); + n = CInline_LoadToTemp(n, &temp); + stmt = CInline_NewStatement(ST_IFNGOTO); + stmt->expr = n; + stmt->label = label; + + n = makemonadicnode(CInline_SerializeExpr(expr->data.diadic.right), ELOGNOT); + n->rtype = expr->rtype; + n = makemonadicnode(n, ELOGNOT); + n = CInline_LoadToTemp(n, &temp); + stmt = CInline_NewStatement(ST_EXPRESSION); + stmt->expr = n; + + stmt = CInline_NewStatement(ST_LABEL); + stmt->label = label; + label->stmt = stmt; + + return create_objectnode(temp); +} + +static ENode *CInline_SerializeEPRECOMP(ENode *expr) { + UIDTemp *uidtemp; + + uidtemp = cinline_uid_temps; + while (1) { + if (!uidtemp) + CError_FATAL(2449); + if (uidtemp->uid == expr->data.precompid) + return create_objectnode(uidtemp->object); + uidtemp = uidtemp->next; + } +} + +static ENode *CInline_SerializeENULLCHECK(ENode *expr) { + Statement *stmt; + CLabel *label; + ENode *n; + Object *temp = NULL; + UIDTemp uidtemp; + + label = newlabel(); + + n = CInline_SerializeExpr(expr->data.nullcheck.nullcheckexpr); + stmt = CInline_NewStatement(ST_IFNGOTO); + stmt->expr = CInline_LoadToTemp(n, &temp); + stmt->label = label; + + uidtemp.next = cinline_uid_temps; + uidtemp.object = temp; + uidtemp.uid = expr->data.nullcheck.precompid; + cinline_uid_temps = &uidtemp; + + n = CInline_SerializeExpr(expr->data.nullcheck.condexpr); + stmt = CInline_NewStatement(ST_EXPRESSION); + stmt->expr = CInline_LoadToTemp(n, &temp); + + cinline_uid_temps = uidtemp.next; + + stmt = CInline_NewStatement(ST_LABEL); + stmt->label = label; + label->stmt = stmt; + + return create_objectnode(temp); +} + +static ENode *CInline_SerializeECOND(ENode *expr) { + Statement *stmt; + CLabel *label1; + CLabel *label2; + ENode *n; + Object *temp = NULL; + + label1 = newlabel(); + label2 = newlabel(); + + n = CInline_SerializeExpr(expr->data.cond.cond); + stmt = CInline_NewStatement(ST_IFNGOTO); + stmt->expr = n; + stmt->label = label1; + + n = CInline_SerializeExpr(expr->data.cond.expr1); + n = CInline_LoadToTemp(n, &temp); + stmt = CInline_NewStatement(ST_EXPRESSION); + stmt->expr = n; + + stmt = CInline_NewStatement(ST_GOTO); + stmt->label = label2; + + stmt = CInline_NewStatement(ST_LABEL); + stmt->label = label1; + label1->stmt = stmt; + + n = CInline_SerializeExpr(expr->data.cond.expr2); + n = CInline_LoadToTemp(n, &temp); + stmt = CInline_NewStatement(ST_EXPRESSION); + stmt->expr = n; + + stmt = CInline_NewStatement(ST_LABEL); + stmt->label = label2; + label2->stmt = stmt; + + if (!temp) { + n = nullnode(); + n->rtype = &stvoid; + return n; + } + + return create_objectnode(temp); +} + +static ENode *CInline_SerializeExpr(ENode *expr) { + ENodeList *list; + + switch (expr->type) { + case EFORCELOAD: + return CInline_SerializeEFORCELOAD(expr); + case ECOMMA: + return CInline_SerializeECOMMA(expr); + case ELAND: + return CInline_SerializeELAND(expr); + case ELOR: + return CInline_SerializeELOR(expr); + case EPRECOMP: + return CInline_SerializeEPRECOMP(expr); + case ENULLCHECK: + return CInline_SerializeENULLCHECK(expr); + case ECOND: + return CInline_SerializeECOND(expr); + + case EINITTRYCATCH: + expr->data.itc.initexpr = CInline_SerializeExpr(expr->data.itc.initexpr); + expr->data.itc.tryexpr = CInline_SerializeExpr(expr->data.itc.tryexpr); + expr->data.itc.catchexpr = CInline_SerializeExpr(expr->data.itc.catchexpr); + expr->data.itc.result = CInline_SerializeExpr(expr->data.itc.result); + return expr; + + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case ETYPCON: + case EBITFIELD: + expr->data.monadic = CInline_SerializeExpr(expr->data.monadic); + return expr; + + case EMUL: + case EDIV: + case EMODULO: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case EPMODULO: + case EROTL: + case EROTR: + expr->data.diadic.left = CInline_SerializeExpr(expr->data.diadic.left); + expr->data.diadic.right = CInline_SerializeExpr(expr->data.diadic.right); + return expr; + + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case ELABEL: + case EOBJLIST: + case EINSTRUCTION: + case EVECTOR128CONST: + return expr; + + case EFUNCCALL: + case EFUNCCALLP: + expr->data.funccall.funcref = CInline_SerializeExpr(expr->data.funccall.funcref); + for (list = expr->data.funccall.args; list; list = list->next) + list->node = CInline_SerializeExpr(list->node); + return expr; + + case EMFPOINTER: + // bug??? + expr->data.mfpointer.accessnode = CInline_SerializeExpr(expr->data.mfpointer.accessnode); + expr->data.mfpointer.accessnode = CInline_SerializeExpr(expr->data.mfpointer.mfpointer); + return expr; + + case EMEMBER: + if (expr->data.emember->expr) + return CInline_SerializeExpr(expr->data.emember->expr); + return expr; + + default: + CError_FATAL(2684); + return expr; + } +} + +void CInline_SerializeStatement(Statement *stmt) { + Statement *scan; + Statement *copy; + + cinline_serial_stmt = NULL; + cinline_uid_temps = NULL; + stmt->expr = CInline_SerializeExpr(stmt->expr); + + if (cinline_serial_stmt) { + for (scan = cinline_serial_stmt; scan; scan = scan->next) { + scan->value = stmt->value; + scan->dobjstack = stmt->dobjstack; + scan->sourceoffset = stmt->sourceoffset; + scan->sourcefilepath = stmt->sourcefilepath; + } + + copy = CInline_NewStatement(ST_EXPRESSION); + *copy = *stmt; + + *stmt = *cinline_serial_stmt; + } +} + +static void CInline_UnpackSwitch(Statement *stmt, CI_Statement *packstmt, CLabel **labels) { + SwitchInfo *info; + SwitchCase *swcase; + short i; + + info = lalloc(sizeof(SwitchInfo)); + stmt->label = (CLabel *) info; + CError_ASSERT(2730, info->defaultlabel = labels[packstmt->u.switchdata->defaultlabelID]); + info->x8 = packstmt->u.switchdata->unkSwitch8; + + for (i = 0; i < packstmt->u.switchdata->numcases; i++) { + if (i == 0) { + swcase = lalloc(sizeof(SwitchCase)); + info->cases = swcase; + } else { + swcase->next = lalloc(sizeof(SwitchCase)); + swcase = swcase->next; + } + + swcase->next = NULL; + swcase->min = packstmt->u.switchdata->cases[i].min; + swcase->max = packstmt->u.switchdata->cases[i].max; + CError_ASSERT(2740, swcase->label = labels[packstmt->u.switchdata->cases[i].labelID]); + } +} + +Object *CInline_GetLocalObj(SInt32 id, Boolean flag) { + ObjectList *list; + + if (id) { + if (id & 0x80000000) { + id = (id & 0x7FFFFFFF) - 1; + if (flag) { + CError_ASSERT(2761, local_aobjects[id].object); + return local_aobjects[id].object; + } + + for (list = arguments; list; list = list->next, id--) { + if (id == 0) + return list->object; + } + + CError_FATAL(2765); + } else { + id--; + if (flag) { + CError_ASSERT(2772, local_dobjects[id]); + return local_dobjects[id]; + } + + for (list = locals; list; list = list->next, id--) { + if (id == 0) + return list->object; + } + + CError_FATAL(2776); + } + } + + return NULL; +} + +static ExceptionAction *CInline_UnpackActions(CI_Statement *packstmt, Boolean flag) { + ExceptionAction *packexc; + ExceptionAction *last; + ExceptionAction *exc; + + packexc = packstmt->dobjstack; + last = NULL; + + while (packexc) { + exc = galloc(sizeof(ExceptionAction)); + exc->prev = last; + last = exc; + + exc->type = packexc->type; + + switch (packexc->type) { + case EAT_DESTROYLOCAL: + exc->data.destroy_local.local = CInline_GetLocalObj((SInt32) packexc->data.destroy_local.local, flag); + exc->data.destroy_local.dtor = packexc->data.destroy_local.dtor; + break; + case EAT_DESTROYLOCALCOND: + exc->data.destroy_local_cond.local = CInline_GetLocalObj((SInt32) packexc->data.destroy_local_cond.local, flag); + exc->data.destroy_local_cond.dtor = packexc->data.destroy_local_cond.dtor; + exc->data.destroy_local_cond.cond = CInline_GetLocalObj((SInt32) packexc->data.destroy_local_cond.cond, flag); + break; + case EAT_DESTROYLOCALOFFSET: + exc->data.destroy_local_offset.local = CInline_GetLocalObj((SInt32) packexc->data.destroy_local_offset.local, flag); + exc->data.destroy_local_offset.dtor = packexc->data.destroy_local_offset.dtor; + exc->data.destroy_local_offset.offset = packexc->data.destroy_local_offset.offset; + break; + case EAT_DESTROYLOCALPOINTER: + exc->data.destroy_local_pointer.pointer = CInline_GetLocalObj((SInt32) packexc->data.destroy_local_pointer.pointer, flag); + exc->data.destroy_local_pointer.dtor = packexc->data.destroy_local_pointer.dtor; + break; + case EAT_DESTROYLOCALARRAY: + exc->data.destroy_local_array.localarray = CInline_GetLocalObj((SInt32) packexc->data.destroy_local_array.localarray, flag); + exc->data.destroy_local_array.dtor = packexc->data.destroy_local_array.dtor; + exc->data.destroy_local_array.elements = packexc->data.destroy_local_array.elements; + exc->data.destroy_local_array.element_size = packexc->data.destroy_local_array.element_size; + break; + case EAT_DESTROYPARTIALARRAY: + exc->data.destroy_partial_array.arraypointer = CInline_GetLocalObj((SInt32) packexc->data.destroy_partial_array.arraypointer, flag); + exc->data.destroy_partial_array.arraycounter = CInline_GetLocalObj((SInt32) packexc->data.destroy_partial_array.arraycounter, flag); + exc->data.destroy_partial_array.dtor = CInline_GetLocalObj((SInt32) packexc->data.destroy_partial_array.dtor, flag); + exc->data.destroy_partial_array.element_size = CInline_GetLocalObj((SInt32) packexc->data.destroy_partial_array.element_size, flag); + break; + case EAT_DESTROYMEMBER: + case EAT_DESTROYBASE: + exc->data.destroy_member.objectptr = CInline_GetLocalObj((SInt32) packexc->data.destroy_member.objectptr, flag); + exc->data.destroy_member.dtor = packexc->data.destroy_member.dtor; + exc->data.destroy_member.offset = packexc->data.destroy_member.offset; + break; + case EAT_DESTROYMEMBERCOND: + exc->data.destroy_member_cond.objectptr = CInline_GetLocalObj((SInt32) packexc->data.destroy_member_cond.objectptr, flag); + exc->data.destroy_member_cond.cond = CInline_GetLocalObj((SInt32) packexc->data.destroy_member_cond.cond, flag); + exc->data.destroy_member_cond.dtor = packexc->data.destroy_member_cond.dtor; + exc->data.destroy_member_cond.offset = packexc->data.destroy_member_cond.offset; + break; + case EAT_DESTROYMEMBERARRAY: + exc->data.destroy_member_array.objectptr = CInline_GetLocalObj((SInt32) packexc->data.destroy_member_array.objectptr, flag); + exc->data.destroy_member_array.dtor = packexc->data.destroy_member_array.dtor; + exc->data.destroy_member_array.offset = packexc->data.destroy_member_array.offset; + exc->data.destroy_member_array.elements = packexc->data.destroy_member_array.elements; + exc->data.destroy_member_array.element_size = packexc->data.destroy_member_array.element_size; + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + exc->data.delete_pointer.pointerobject = CInline_GetLocalObj((SInt32) packexc->data.delete_pointer.pointerobject, flag); + exc->data.delete_pointer.deletefunc = packexc->data.delete_pointer.deletefunc; + break; + case EAT_DELETEPOINTERCOND: + exc->data.delete_pointer_cond.pointerobject = CInline_GetLocalObj((SInt32) packexc->data.delete_pointer_cond.pointerobject, flag); + exc->data.delete_pointer_cond.deletefunc = packexc->data.delete_pointer_cond.deletefunc; + exc->data.delete_pointer_cond.cond = CInline_GetLocalObj((SInt32) packexc->data.delete_pointer_cond.cond, flag); + break; + case EAT_CATCHBLOCK: { + LabelTrans *trans; + exc->data.catch_block.catch_object = CInline_GetLocalObj((SInt32) packexc->data.catch_block.catch_object, flag); + exc->data.catch_block.catch_info_object = CInline_GetLocalObj((SInt32) packexc->data.catch_block.catch_info_object, flag); + + trans = lalloc(sizeof(LabelTrans)); + trans->next = cinline_label_trans; + cinline_label_trans = trans; + + trans->id = (SInt32) packexc->data.catch_block.catch_label; + trans->labelptr = &exc->data.catch_block.catch_label; + + exc->data.catch_block.catch_typeid = packexc->data.catch_block.catch_typeid; + exc->data.catch_block.catch_type = packexc->data.catch_block.catch_type; + exc->data.catch_block.catch_qual = packexc->data.catch_block.catch_qual; + break; + } + case EAT_ACTIVECATCHBLOCK: + exc->data.active_catch_block.catch_info_object = CInline_GetLocalObj((SInt32) packexc->data.active_catch_block.catch_info_object, flag); + break; + case EAT_SPECIFICATION: { + LabelTrans *trans; + exc->data.specification.unexp_ids = packexc->data.specification.unexp_ids; + exc->data.specification.unexp_id = packexc->data.specification.unexp_id; + + trans = lalloc(sizeof(LabelTrans)); + trans->next = cinline_label_trans; + cinline_label_trans = trans; + + trans->id = (SInt32) packexc->data.specification.unexp_label; + trans->labelptr = &exc->data.specification.unexp_label; + + exc->data.specification.unexp_info_object = CInline_GetLocalObj((SInt32) packexc->data.specification.unexp_info_object, flag); + break; + } + case EAT_TERMINATE: + break; + default: + CError_FATAL(2904); + } + + packexc = packexc->prev; + } + + return last; +} + +static Statement *CInline_ExpandStatements(Object *funcobj, Statement *stmt, CI_FuncData *funcdata, ENode *funccall, CLabel *label, Object *resultobj, Boolean flag) { + CLabel **labels; + CI_Statement *packstmt; + short i; + CI_StmtLink *stmtLinks; + CI_StmtLink *link; + ENode *setupArgs; + Boolean is_result_class_1; + Statement origStmt; + + origStmt = *stmt; + is_result_class_1 = CMach_GetFunctionResultClass(TYPE_FUNC(funcobj->type)) == 1; + + if ((setupArgs = CInline_SetupArgsExpression(funcobj, funcdata, funccall->data.funccall.args))) { + stmt->type = ST_EXPRESSION; + stmt->expr = CInline_FoldConst(setupArgs); + } else { + stmt->type = ST_NOP; + } + + stmtLinks = NULL; + cinline_label_trans = NULL; + + labels = lalloc(sizeof(CLabel *) * funcdata->numstatements); + memclrw(labels, sizeof(CLabel *) * funcdata->numstatements); + + for (i = 0, packstmt = funcdata->statements; i < funcdata->numstatements; i++, packstmt++) { + stmt->next = lalloc(sizeof(Statement)); + stmt = stmt->next; + *stmt = origStmt; + + stmt->type = packstmt->type; + stmt->flags = packstmt->flags; + stmt->value += packstmt->value; + + if (packstmt->dobjstack) { + ExceptionAction *unpacked = CInline_UnpackActions(packstmt, 1); + if (stmt->dobjstack) { + ExceptionAction *scan = unpacked; + while (scan->prev) + scan = scan->prev; + scan->prev = stmt->dobjstack; + } + stmt->dobjstack = unpacked; + } + + switch (stmt->type) { + case ST_NOP: + break; + + case ST_EXPRESSION: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_GOTOEXPR: + stmt->expr = CInline_FoldConst(CInline_CopyExpression(packstmt->u.expr, CopyMode4)); + break; + + case ST_RETURN: + if (packstmt->u.expr) { + stmt->expr = CInline_FoldConst(CInline_CopyExpression(packstmt->u.expr, CopyMode4)); + if (is_result_class_1) + stmt->expr = makecommaexpression(stmt->expr, CInline_ReturnMemResult(funcobj)); + + if (resultobj) { + stmt->type = ST_EXPRESSION; + stmt->expr = makediadicnode(create_objectnode2(resultobj), stmt->expr, EASS); + } else { + stmt->type = origStmt.type; + if (stmt->type == ST_EXPRESSION && !CInline_ExpressionHasSideEffect(stmt->expr)) + stmt->type = ST_NOP; + } + + if (label) { + stmt->next = lalloc(sizeof(Statement)); + stmt = stmt->next; + *stmt = origStmt; + stmt->type = ST_GOTO; + stmt->label = label; + } + } else { + if (label) { + stmt->type = ST_GOTO; + stmt->label = label; + } else { + stmt->type = ST_NOP; + } + } + break; + + case ST_LABEL: + labels[i] = stmt->label = newlabel(); + stmt->label->stmt = stmt; + break; + + case ST_IFGOTO: + case ST_IFNGOTO: + stmt->expr = CInline_FoldConst(CInline_CopyExpression(packstmt->u.ifgoto.expr, CopyMode4)); + case ST_GOTO: + link = lalloc(sizeof(CI_StmtLink)); + link->next = stmtLinks; + stmtLinks = link; + + link->stmt = stmt; + link->ciStmt = packstmt; + break; + + case ST_SWITCH: + stmt->expr = CInline_FoldConst(CInline_CopyExpression(packstmt->u.switchdata->expr, CopyMode4)); + case ST_ASM: + link = lalloc(sizeof(CI_StmtLink)); + link->next = stmtLinks; + stmtLinks = link; + + link->stmt = stmt; + link->ciStmt = packstmt; + break; + + default: + CError_FATAL(3040); + } + } + + if (label) { + stmt->next = lalloc(sizeof(Statement)); + stmt = stmt->next; + *stmt = origStmt; + + stmt->type = ST_LABEL; + stmt->label = label; + label->stmt = stmt; + + if (flag) { + stmt->next = lalloc(sizeof(Statement)); + stmt = stmt->next; + *stmt = origStmt; + } + } + + while (stmtLinks) { + Statement *linkstmt = stmtLinks->stmt; + packstmt = stmtLinks->ciStmt; + + switch (linkstmt->type) { + case ST_GOTO: + CError_ASSERT(3060, linkstmt->label = labels[packstmt->u.statementnum]); + break; + case ST_IFGOTO: + case ST_IFNGOTO: + CError_ASSERT(3065, linkstmt->label = labels[packstmt->u.ifgoto.statementnum]); + break; + case ST_SWITCH: + CInline_UnpackSwitch(linkstmt, packstmt, labels); + break; + case ST_ASM: + InlineAsm_UnpackAsmStatement(linkstmt, labels, 1, packstmt->u.asmdata.data, packstmt->u.asmdata.size); + break; + default: + CError_FATAL(3076); + } + + stmtLinks = stmtLinks->next; + } + + while (cinline_label_trans) { + CError_ASSERT(3083, *cinline_label_trans->labelptr = labels[cinline_label_trans->id]); + cinline_label_trans = cinline_label_trans->next; + } + + return stmt; +} + +static Statement *CInline_InlineFunctionStatement(Statement *stmt, Boolean *changed) { + Object *object; + CI_FuncData *funcdata; + CLabel *label; + + *changed = 0; + + object = stmt->expr->data.funccall.funcref->data.objref; + if (object->datatype == DALIAS) + object = object->u.alias.object; + + funcdata = object->u.func.u.ifuncdata; + if (!funcdata || funcdata->can_inline < CI_CanInline3) + return stmt; + + if (stmt->type != ST_EXPRESSION) { + short i; + for (i = 0; i < (funcdata->numstatements - 1); i++) { + if (funcdata->statements[i].type == ST_RETURN) + return stmt; + } + + if (funcdata->statements[funcdata->numstatements - 1].type != ST_RETURN) + return stmt; + + label = NULL; + } else { + label = newlabel(); + } + + *changed = 1; + return CInline_ExpandStatements(object, stmt, funcdata, stmt->expr, label, NULL, 0); +} + +static Statement *CInline_ExtractInlineFunction(Statement *stmt) { + ENode *expr; + CI_FuncData *funcdata; + short i; + Object *funcObject; + Object *resultObject; + + for (i = 0; i < cinline_stmtlevelexprs; i++) { + expr = cinline_stmtlevelexpr[i]; + + funcObject = expr->data.funccall.funcref->data.objref; + if (funcObject->datatype == DALIAS) + funcObject = funcObject->u.alias.object; + + if ((funcdata = funcObject->u.func.u.ifuncdata)) { + TypeFunc *tfunc = TYPE_FUNC(funcObject->type); + CError_ASSERT(3141, IS_TYPE_FUNC(tfunc)); + + if (!IS_TYPE_VOID(tfunc->functype)) { + if (CMach_GetFunctionResultClass(TYPE_FUNC(funcObject->type)) == 1) + resultObject = CInline_NewLocalObject(CDecl_NewPointerType(tfunc->functype), 0, 0, 0); + else + resultObject = CInline_NewLocalObject(tfunc->functype, 0, 0, 0); + } else { + resultObject = NULL; + } + + stmt = CInline_ExpandStatements(funcObject, stmt, funcdata, expr, newlabel(), resultObject, 1); + + if (resultObject) + *expr = *create_objectnode2(resultObject); + else + *expr = *nullnode(); + } + } + + return stmt; +} + +static Statement *CInline_ExpandStatement(Statement *stmt) { + Boolean changed; + + do { + changed = 0; + + if ( + stmt->type == ST_EXPRESSION && + ENODE_IS(stmt->expr, EINDIRECT) && + !CParser_IsVolatile(stmt->expr->rtype, ENODE_QUALS(stmt->expr)) + ) + { + stmt->expr = stmt->expr->data.monadic; + changed = 1; + if (ENODE_IS2(stmt->expr, EOBJREF, EBITFIELD)) + stmt->expr = nullnode(); + } + + if (ENODE_IS(stmt->expr, ECOMMA)) { + Statement *newStmt = lalloc(sizeof(Statement)); + *newStmt = *stmt; + + stmt->next = newStmt; + stmt->type = ST_EXPRESSION; + stmt->expr = stmt->expr->data.diadic.left; + newStmt->expr = newStmt->expr->data.diadic.right; + + changed = 1; + } + } while (changed); + + if ( + ENODE_IS2(stmt->expr, EFUNCCALL, EFUNCCALLP) && + ENODE_IS(stmt->expr->data.funccall.funcref, EOBJREF) && + CInline_InlineFunctionCheck(stmt->expr->data.funccall.funcref) + ) + { + stmt = CInline_InlineFunctionStatement(stmt, &changed); + if (changed) { + any_inline_expanded = 1; + return stmt; + } + } + + inline_expanded = 0; + cinline_unconditionalpart = 1; + cinline_serialize_stmt = 0; + cinline_stmtlevelexprs = 0; + stmt->expr = CInline_ExpandExpression(stmt->expr); + + if (cinline_serialize_stmt) { + cinline_unconditionalpart = 1; + cinline_serialize_stmt = 0; + cinline_stmtlevelexprs = 0; + CInline_SerializeStatement(stmt); + stmt->expr = CInline_ExpandExpression(stmt->expr); + } + + if (inline_expanded) { + stmt->expr = CInline_FoldConst(stmt->expr); + any_inline_expanded = 1; + } + + if (cinline_stmtlevelexprs) { + stmt = CInline_ExtractInlineFunction(stmt); + any_inline_expanded = 1; + } + + return stmt; +} + +static void CInline_ForceReverseSearch(ENode *) { + cinline_funccallfound = 1; +} + +static ENode *CInline_ForceReverseEvaluation(ENode *expr) { + ENode *commanodes; + ENodeList *list; + int counter; + ENode *ass; + ENode *inner; + ENode *copy; + + list = expr->data.funccall.args; + counter = 0; + commanodes = NULL; + + while (list) { + cinline_funccallfound = 0; + inner = list->node; + CExpr_SearchExprTree(inner, CInline_ForceReverseSearch, 2, EFUNCCALL, EFUNCCALLP); + + if (cinline_funccallfound && ++counter > 0) { + inner = create_objectrefnode(create_temp_object(inner->rtype)); + copy = lalloc(sizeof(ENode)); + *copy = *inner; + + copy = makemonadicnode(copy, EINDIRECT); + copy->rtype = TPTR_TARGET(copy->rtype); + + inner = makemonadicnode(inner, EINDIRECT); + inner->rtype = TPTR_TARGET(inner->rtype); + + ass = makediadicnode(inner, copy, EASS); + list->node = copy; + + if (commanodes) + commanodes = makediadicnode(ass, commanodes, ECOMMA); + else + commanodes = ass; + } + + list = list->next; + } + + if (commanodes) { + commanodes = makediadicnode(commanodes, expr, ECOMMA); + commanodes->rtype = expr->rtype; + return commanodes; + } + + return expr; +} + +static void CInline_ExportCheck(ENode *expr) { + while (1) { + switch (expr->type) { + case EOBJREF: + CInline_ObjectAddrRef(expr->data.objref); + if (expr->data.objref->datatype == DALIAS) { + CExpr_AliasTransform(expr); + continue; + } + return; + + ENODE_CASE_MONADIC: + expr = expr->data.monadic; + continue; + + ENODE_CASE_DIADIC_ALL: + CInline_ExportCheck(expr->data.diadic.left); + expr = expr->data.diadic.right; + continue; + + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EPRECOMP: + case EINSTRUCTION: + case EVECTOR128CONST: + return; + + case ELABEL: + if (expr->data.label->stmt) + expr->data.label->stmt->flags |= StmtFlag_1; + return; + + case EFUNCCALL: + case EFUNCCALLP: { + ENodeList *list; + TypeClass *tclass; + SInt32 index; + + for (list = expr->data.funccall.args; list; list = list->next) + CInline_ExportCheck(list->node); + + expr = expr->data.funccall.funcref; + if ( + copts.warn_notinlined && + !copts.dontinline && + ENODE_IS(expr, EOBJREF) && + (expr->data.objref->qual & Q_INLINE) && + expr->data.objref->datatype != DINLINEFUNC && + !CParser_IsVirtualFunction(expr->data.objref, &tclass, &index) + ) + CError_Warning(CErrorStr342, expr->data.objref); + + continue; + } + + case ENULLCHECK: + CInline_ExportCheck(expr->data.nullcheck.nullcheckexpr); + expr = expr->data.nullcheck.condexpr; + continue; + + case EMFPOINTER: + *expr = *nullnode(); + continue; + + case ECOND: + CInline_ExportCheck(expr->data.cond.cond); + CInline_ExportCheck(expr->data.cond.expr1); + expr = expr->data.cond.expr2; + continue; + + case EMEMBER: + if (expr->data.emember->expr) { + *expr = *expr->data.emember->expr; + continue; + } + case EOBJLIST: + *expr = *nullnode(); + continue; + + default: + CError_FATAL(3372); + } + } +} + +static void CInline_Expand(Statement *stmt) { + Statement *scan; + + if (!copts.dontinline && copts.inlinelevel >= 0) { + if (copts.inline_bottom_up) { + inline_max_size = copts.inlinemaxsize; + while (inline_max_size > 1 && EstimateExpandedSizeOfFunction(stmt) > copts.inlinemaxtotalsize) + inline_max_size >>= 1; + } + + cinline_level = 0; + while (1) { + any_inline_expanded = 0; + for (scan = stmt; scan; scan = scan->next) { + switch (scan->type) { + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_ASM: + break; + case ST_RETURN: + if (!scan->expr) + break; + case ST_EXPRESSION: + case ST_SWITCH: + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_GOTOEXPR: + scan = CInline_ExpandStatement(scan); + break; + default: + CError_FATAL(3438); + } + } + + if (!copts.inline_bottom_up && !any_inline_expanded) + break; + + if (!copts.alwaysinline || copts.inline_bottom_up) { + if (copts.inlinelevel == 0) { + if (copts.inline_bottom_up) { + if ((cinline_level + 1) >= 8) + break; + } else { + if (cinline_level >= 3) + break; + } + } else { + if ((cinline_level + 1) >= copts.inlinelevel) + break; + } + } + + if (CWDisplayLines(cparamblkptr->context, lines) != cwNoErr) + CError_UserBreak(); + + cinline_level++; + } + } + + while (stmt) { + if (stmt->dobjstack) + CExcept_CheckStackRefs(stmt->dobjstack); + + switch (stmt->type) { + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_ASM: + break; + case ST_RETURN: + if (!stmt->expr) + break; + case ST_EXPRESSION: + case ST_SWITCH: + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_GOTOEXPR: + CInline_ExportCheck(stmt->expr); + break; + default: + CError_FATAL(3501); + } + + stmt = stmt->next; + } +} + +SInt16 CInline_GetStatementNumber(Statement *first, Statement *stmt) { + SInt16 number = 0; + + while (first) { + if (first == stmt) + return number; + + first = first->next; + number++; + } + + CError_FATAL(3517); + return 0; +} + +static CI_Switch *CInline_PackSwitch(Statement *start, Statement *stmt) { + SwitchInfo *info; + SwitchCase *swcase; + short numcases; + CI_Switch *packed; + + info = (SwitchInfo *) stmt->label; + swcase = info->cases; + numcases = 0; + while (swcase) { + swcase = swcase->next; + numcases++; + } + + packed = galloc(sizeof(CI_Switch) + numcases * sizeof(CI_SwitchCase)); + packed->expr = CInline_CopyExpression(stmt->expr, CopyMode2); + packed->defaultlabelID = CInline_GetStatementNumber(start, info->defaultlabel->stmt); + packed->unkSwitch8 = info->x8; + packed->numcases = numcases; + + for (swcase = info->cases, numcases = 0; swcase; swcase = swcase->next, numcases++) { + packed->cases[numcases].labelID = CInline_GetStatementNumber(start, swcase->label->stmt); + packed->cases[numcases].min = swcase->min; + packed->cases[numcases].max = swcase->max; + } + + return packed; +} + +static UInt8 CInline_CanInline(Object *object, Statement *stmt) { + UInt8 resultClass; + FuncArg *arg; + UInt8 result; + + resultClass = CMach_GetFunctionResultClass(TYPE_FUNC(object->type)); + if ( + resultClass && + (resultClass != 1 || (IS_TYPE_CLASS(TYPE_FUNC(object->type)->functype) && CClass_Destructor(TYPE_CLASS(TYPE_FUNC(object->type)->functype)))) + ) + return CI_CanInline0; + + for (arg = TYPE_FUNC(object->type)->args; arg; arg = arg->next) { + if (arg == &elipsis) + return CI_CanInline0; + if (arg == &oldstyle) + break; + + if (IS_TYPE_CLASS(arg->type) && CClass_Destructor(TYPE_CLASS(arg->type))) + return CI_CanInline0; + } + + result = CI_CanInline6; + + while (stmt) { + if (stmt->dobjstack) + return CI_CanInline3; + + switch (stmt->type) { + case ST_EXPRESSION: + break; + case ST_RETURN: + if (stmt->next || (stmt->expr == NULL && TYPE_FUNC(object->type)->functype != &stvoid)) + result = CI_CanInline3; + break; + default: + result = CI_CanInline3; + } + + stmt = stmt->next; + } + + return result; +} + +static ExceptionAction *CInline_PackActions(Statement *start, Statement *stmt) { + ExceptionAction *exc; + ExceptionAction *last; + ExceptionAction *packexc; + + exc = stmt->dobjstack; + last = NULL; + + while (exc) { + packexc = galloc(sizeof(ExceptionAction)); + packexc->prev = last; + last = packexc; + + packexc->type = exc->type; + + switch (exc->type) { + case EAT_DESTROYLOCAL: + packexc->data.destroy_local.local = (void *) CInline_GetLocalID(exc->data.destroy_local.local); + packexc->data.destroy_local.dtor = exc->data.destroy_local.dtor; + break; + case EAT_DESTROYLOCALCOND: + packexc->data.destroy_local_cond.local = (void *) CInline_GetLocalID(exc->data.destroy_local_cond.local); + packexc->data.destroy_local_cond.dtor = exc->data.destroy_local_cond.dtor; + packexc->data.destroy_local_cond.cond = (void *) CInline_GetLocalID(exc->data.destroy_local_cond.cond); + break; + case EAT_DESTROYLOCALOFFSET: + packexc->data.destroy_local_offset.local = (void *) CInline_GetLocalID(exc->data.destroy_local_offset.local); + packexc->data.destroy_local_offset.dtor = exc->data.destroy_local_offset.dtor; + packexc->data.destroy_local_offset.offset = exc->data.destroy_local_offset.offset; + break; + case EAT_DESTROYLOCALPOINTER: + packexc->data.destroy_local_pointer.pointer = (void *) CInline_GetLocalID(exc->data.destroy_local_pointer.pointer); + packexc->data.destroy_local_pointer.dtor = exc->data.destroy_local_pointer.dtor; + break; + case EAT_DESTROYLOCALARRAY: + packexc->data.destroy_local_array.localarray = (void *) CInline_GetLocalID(exc->data.destroy_local_array.localarray); + packexc->data.destroy_local_array.dtor = exc->data.destroy_local_array.dtor; + packexc->data.destroy_local_array.elements = exc->data.destroy_local_array.elements; + packexc->data.destroy_local_array.element_size = exc->data.destroy_local_array.element_size; + break; + case EAT_DESTROYPARTIALARRAY: + packexc->data.destroy_partial_array.arraypointer = (void *) CInline_GetLocalID(exc->data.destroy_partial_array.arraypointer); + packexc->data.destroy_partial_array.arraycounter = (void *) CInline_GetLocalID(exc->data.destroy_partial_array.arraycounter); + packexc->data.destroy_partial_array.dtor = (void *) CInline_GetLocalID(exc->data.destroy_partial_array.dtor); + packexc->data.destroy_partial_array.element_size = (void *) CInline_GetLocalID(exc->data.destroy_partial_array.element_size); + break; + case EAT_DESTROYMEMBER: + case EAT_DESTROYBASE: + packexc->data.destroy_member.objectptr = (void *) CInline_GetLocalID(exc->data.destroy_member.objectptr); + packexc->data.destroy_member.dtor = exc->data.destroy_member.dtor; + packexc->data.destroy_member.offset = exc->data.destroy_member.offset; + break; + case EAT_DESTROYMEMBERCOND: + packexc->data.destroy_member_cond.objectptr = (void *) CInline_GetLocalID(exc->data.destroy_member_cond.objectptr); + packexc->data.destroy_member_cond.cond = (void *) CInline_GetLocalID(exc->data.destroy_member_cond.cond); + packexc->data.destroy_member_cond.dtor = exc->data.destroy_member_cond.dtor; + packexc->data.destroy_member_cond.offset = exc->data.destroy_member_cond.offset; + break; + case EAT_DESTROYMEMBERARRAY: + packexc->data.destroy_member_array.objectptr = (void *) CInline_GetLocalID(exc->data.destroy_member_array.objectptr); + packexc->data.destroy_member_array.dtor = exc->data.destroy_member_array.dtor; + packexc->data.destroy_member_array.offset = exc->data.destroy_member_array.offset; + packexc->data.destroy_member_array.elements = exc->data.destroy_member_array.elements; + packexc->data.destroy_member_array.element_size = exc->data.destroy_member_array.element_size; + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + packexc->data.delete_pointer.pointerobject = (void *) CInline_GetLocalID(exc->data.delete_pointer.pointerobject); + packexc->data.delete_pointer.deletefunc = exc->data.delete_pointer.deletefunc; + break; + case EAT_DELETEPOINTERCOND: + packexc->data.delete_pointer_cond.pointerobject = (void *) CInline_GetLocalID(exc->data.delete_pointer_cond.pointerobject); + packexc->data.delete_pointer_cond.deletefunc = exc->data.delete_pointer_cond.deletefunc; + packexc->data.delete_pointer_cond.cond = (void *) CInline_GetLocalID(exc->data.delete_pointer_cond.cond); + break; + case EAT_CATCHBLOCK: + packexc->data.catch_block.catch_object = (void *) CInline_GetLocalID(exc->data.catch_block.catch_object); + packexc->data.catch_block.catch_info_object = (void *) CInline_GetLocalID(exc->data.catch_block.catch_info_object); + packexc->data.catch_block.catch_label = (void *) CInline_GetStatementNumber(start->next, exc->data.catch_block.catch_label->stmt); + packexc->data.catch_block.catch_typeid = exc->data.catch_block.catch_typeid; + packexc->data.catch_block.catch_type = exc->data.catch_block.catch_type; + packexc->data.catch_block.catch_qual = exc->data.catch_block.catch_qual; + break; + case EAT_ACTIVECATCHBLOCK: + packexc->data.active_catch_block.catch_info_object = (void *) CInline_GetLocalID(exc->data.active_catch_block.catch_info_object); + packexc->data.active_catch_block.call_dtor = exc->data.active_catch_block.call_dtor; + break; + case EAT_SPECIFICATION: + packexc->data.specification.unexp_ids = exc->data.specification.unexp_ids; + packexc->data.specification.unexp_id = exc->data.specification.unexp_id; + packexc->data.specification.unexp_label = (void *) CInline_GetStatementNumber(start->next, exc->data.specification.unexp_label->stmt); + packexc->data.specification.unexp_info_object = (void *) CInline_GetLocalID(exc->data.specification.unexp_info_object); + break; + case EAT_TERMINATE: + break; + default: + CError_FATAL(3720); + } + + exc = exc->prev; + } + + return last; +} + +void CInline_PackIFunctionData(CI_FuncData *funcdata, Statement *stmt, Object *object) { + ObjectList *list; + CI_Var *var; + Statement *scan; + CI_Statement *packstmt; + int i; + + cinline_first_stmt = stmt->next; + memclrw(funcdata, sizeof(CI_FuncData)); + + funcdata->can_inline = CInline_CanInline(object, stmt->next); + + if (copts.filesyminfo) { + funcdata->fileoffset = cparser_fileoffset; + funcdata->fileoffset.is_inline = 1; + funcdata->symdecloffset = symdecloffset; + funcdata->functionbodyoffset = functionbodyoffset; + funcdata->functionbodypath = functionbodypath; + funcdata->symdeclend = symdeclend; + } + + list = arguments; + i = 0; + while (list) { + list = list->next; + i++; + } + + if ((funcdata->numarguments = i) > 0) { + loc_args = funcdata->arguments = galloc(sizeof(CI_Var) * i); + memclrw(funcdata->arguments, sizeof(CI_Var) * i); + + for (list = arguments, var = funcdata->arguments; list; list = list->next, var++) { + var->name = list->object->name; + var->type = list->object->type; + var->qual = list->object->qual; + var->sflags = CInline_GetObjectSFlags(list->object); + var->xD = 0; + var->xE = 1; + } + } + + list = locals; + i = 0; + while (list) { + if (list->object->datatype == DLOCAL) + i++; + list = list->next; + } + + if ((funcdata->numlocals = i) > 0) { + loc_vars = funcdata->locals = galloc(sizeof(CI_Var) * i); + memclrw(funcdata->locals, sizeof(CI_Var) * i); + + for (list = locals, var = funcdata->locals; list; list = list->next) { + if (list->object->datatype == DLOCAL) { + var->name = list->object->name; + var->type = list->object->type; + var->qual = list->object->qual; + var->sflags = CInline_GetObjectSFlags(list->object); + var->xD = 0; + var->xE = 0; + var++; + } + } + } + + scan = stmt->next; + i = 0; + while (scan) { + scan = scan->next; + i++; + } + + funcdata->numstatements = i; + funcdata->statements = galloc(sizeof(CI_Statement) * i); + + for (scan = stmt->next, packstmt = funcdata->statements; scan; scan = scan->next, packstmt++) { + packstmt->type = scan->type; + packstmt->flags = scan->flags; + packstmt->value = scan->value; + packstmt->dobjstack = CInline_PackActions(stmt, scan); + packstmt->sourceoffset = scan->sourceoffset; + packstmt->sourcefilepath = scan->sourcefilepath; + + switch (scan->type) { + case ST_NOP: + case ST_LABEL: + break; + case ST_EXPRESSION: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_GOTOEXPR: + packstmt->u.expr = CInline_CopyExpression(scan->expr, CopyMode2); + break; + case ST_RETURN: + if (scan->expr) + packstmt->u.expr = CInline_CopyExpression(scan->expr, CopyMode2); + else + packstmt->u.expr = NULL; + break; + case ST_GOTO: + packstmt->u.statementnum = CInline_GetStatementNumber(stmt->next, scan->label->stmt); + break; + case ST_IFGOTO: + case ST_IFNGOTO: + packstmt->u.ifgoto.expr = CInline_CopyExpression(scan->expr, CopyMode2); + packstmt->u.ifgoto.statementnum = CInline_GetStatementNumber(stmt->next, scan->label->stmt); + break; + case ST_SWITCH: + packstmt->u.switchdata = CInline_PackSwitch(stmt->next, scan); + break; + case ST_ASM: + InlineAsm_PackAsmStatement(scan, stmt->next, &packstmt->u.asmdata.data, &packstmt->u.asmdata.size); + break; + default: + CError_FATAL(3862); + } + } +} + +void CInline_UnpackIFunctionData(Object *object, CI_FuncData *funcdata, Statement *firstStmt) { + CLabel **labels; + CI_Var *var; + ObjectList *last; + Statement *stmt; + CI_Statement *packstmt; + int i; + + cparser_fileoffset = funcdata->fileoffset; + symdecloffset = funcdata->symdecloffset; + functionbodyoffset = funcdata->functionbodyoffset; + functionbodypath = funcdata->functionbodypath; + symdeclend = funcdata->symdeclend; + + for (i = 0, var = funcdata->arguments; i < funcdata->numarguments; i++, var++) { + if (i == 0) { + last = lalloc(sizeof(ObjectList)); + arguments = last; + } else { + last->next = lalloc(sizeof(ObjectList)); + last = last->next; + } + + object = galloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + last->object = object; + last->next = NULL; + + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->datatype = DLOCAL; + object->name = var->name; + object->type = var->type; + object->qual = var->qual; + CInline_SetObjectSFlags(object, var->sflags); + CFunc_SetupLocalVarInfo(object); + + if (funcdata->fileoffset.file) { + object->u.var.info->deftoken.tokenfile = funcdata->fileoffset.file; + object->u.var.info->deftoken.tokenoffset = funcdata->functionbodyoffset; + } + } + + for (i = 0, var = funcdata->locals; i < funcdata->numlocals; i++, var++) { + if (i == 0) { + last = lalloc(sizeof(ObjectList)); + locals = last; + } else { + last->next = lalloc(sizeof(ObjectList)); + last = last->next; + } + + object = galloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + last->object = object; + last->next = NULL; + + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->datatype = DLOCAL; + object->name = var->name; + object->type = var->type; + object->qual = var->qual; + CInline_SetObjectSFlags(object, var->sflags); + CFunc_SetupLocalVarInfo(object); + + if (funcdata->fileoffset.file) { + object->u.var.info->deftoken.tokenfile = funcdata->fileoffset.file; + object->u.var.info->deftoken.tokenoffset = funcdata->functionbodyoffset; + } + } + + enode_idtrans = NULL; + cinline_label_trans = NULL; + + labels = lalloc(sizeof(CLabel *) * funcdata->numstatements); + memclrw(labels, sizeof(CLabel *) * funcdata->numstatements); + + for (i = 0, stmt = firstStmt, packstmt = funcdata->statements; i < funcdata->numstatements; i++, packstmt++) { + stmt->next = lalloc(sizeof(Statement)); + stmt = stmt->next; + + stmt->type = packstmt->type; + stmt->flags = packstmt->flags; + stmt->value = packstmt->value; + stmt->sourceoffset = packstmt->sourceoffset; + stmt->sourcefilepath = packstmt->sourcefilepath; + stmt->dobjstack = CInline_UnpackActions(packstmt, 0); + stmt->next = NULL; + + switch (stmt->type) { + case ST_NOP: + case ST_GOTO: + case ST_ASM: + break; + case ST_EXPRESSION: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_GOTOEXPR: + stmt->expr = CInline_CopyExpression(packstmt->u.expr, CopyMode3); + break; + case ST_RETURN: + if (packstmt->u.expr) + stmt->expr = CInline_CopyExpression(packstmt->u.expr, CopyMode3); + else + stmt->expr = NULL; + break; + case ST_LABEL: + labels[i] = stmt->label = newlabel(); + stmt->label->stmt = stmt; + break; + case ST_IFGOTO: + case ST_IFNGOTO: + stmt->expr = CInline_CopyExpression(packstmt->u.ifgoto.expr, CopyMode3); + break; + case ST_SWITCH: + stmt->expr = CInline_CopyExpression(packstmt->u.switchdata->expr, CopyMode3); + break; + default: + CError_FATAL(4017); + } + } + + for (stmt = firstStmt->next, packstmt = funcdata->statements; stmt; stmt = stmt->next, packstmt++) { + switch (stmt->type) { + case ST_GOTO: + CError_ASSERT(4024, stmt->label = labels[packstmt->u.statementnum]); + break; + case ST_IFGOTO: + case ST_IFNGOTO: + CError_ASSERT(4029, stmt->label = labels[packstmt->u.ifgoto.statementnum]); + break; + case ST_SWITCH: + CInline_UnpackSwitch(stmt, packstmt, labels); + break; + case ST_ASM: + InlineAsm_UnpackAsmStatement(stmt, labels, 0, packstmt->u.asmdata.data, packstmt->u.asmdata.size); + break; + } + } + + cinline_first_stmt = firstStmt->next; + + while (cinline_label_trans) { + CError_ASSERT(4045, *cinline_label_trans->labelptr = labels[cinline_label_trans->id]); + cinline_label_trans = cinline_label_trans->next; + } +} + +static void CInline_GenIFunctionCode(Object *object, CI_FuncData *func, UInt8 unk) { + Boolean saveDebugInfo; + CScopeSave saveScope; + Statement firstStmt; + + if (cparamblkptr->precompile != 1 && func) { + ObjGen_SetupSym(); + CScope_SetFunctionScope(object, &saveScope); + CFunc_FuncGenSetup(&firstStmt, object); + CInline_UnpackIFunctionData(object, func, &firstStmt); + + saveDebugInfo = copts.filesyminfo; + if (copts.nosyminline || (!symdecloffset && !symdeclend)) + copts.filesyminfo = 0; + + expanding_function = object; + recursive_inline = 0; + CInline_Expand(&firstStmt); + + if (!anyerrors) { + if (copts.filesyminfo) + CPrep_SetSourceFile(&cparser_fileoffset); + CodeGen_Generator(&firstStmt, object, unk, 0); + } + + CScope_RestoreScope(&saveScope); + copts.filesyminfo = saveDebugInfo; + } +} + +void CInline_AddDefaultFunctionAction(Object *object) { + CI_Action *action; + + for (action = cinline_actionlist; action; action = action->next) { + if (action->obj == object) + return; + } + + action = galloc(sizeof(CI_Action)); + memclrw(action, sizeof(CI_Action)); + + action->actiontype = CI_ActionDefaultFunc; + action->obj = object; + + action->next = cinline_actionlist; + cinline_actionlist = action; +} + +void CInline_AddInlineFunctionAction(Object *object, TypeClass *tclass, FileOffsetInfo *fileoffset, TokenStream *stream, Boolean flag) { + CI_Action *action; + + for (action = flag ? cinline_tactionlist : cinline_actionlist; action; action = action->next) { + if (action->obj == object) + return; + } + + CError_ASSERT(4132, IS_TYPE_FUNC(object->type)); + + TYPE_FUNC(object->type)->flags |= FUNC_IS_TEMPL_INSTANCE; + + action = galloc(sizeof(CI_Action)); + memclrw(action, sizeof(CI_Action)); + + action->actiontype = CI_ActionInlineFunc; + action->obj = object; + action->u.inlinefunc.tclass = tclass; + action->u.inlinefunc.fileoffset = *fileoffset; + action->u.inlinefunc.stream = *stream; + + if (flag) { + action->next = cinline_tactionlist; + cinline_tactionlist = action; + TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_200000; + } else { + action->next = cinline_actionlist; + cinline_actionlist = action; + } +} + +void CInline_AddMemberFunctionAction(Object *object, TemplClass *templ, TemplClassInst *inst, TemplateMember *tmemb) { + CI_Action *action; + + for (action = cinline_tactionlist; action; action = action->next) { + if (action->obj == object) + return; + } + + action = galloc(sizeof(CI_Action)); + memclrw(action, sizeof(CI_Action)); + + action->actiontype = CI_ActionMemberFunc; + action->obj = object; + action->u.memberfunc.templ = templ; + action->u.memberfunc.inst = inst; + action->u.memberfunc.tmemb = tmemb; + + action->next = cinline_tactionlist; + cinline_tactionlist = action; + + TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_200000; +} + +void CInline_AddTemplateFunctionAction(Object *object, TemplateFunction *func, TemplFuncInstance *inst) { + CI_Action *action; + + for (action = cinline_tactionlist; action; action = action->next) { + if (action->obj == object) + return; + } + + action = galloc(sizeof(CI_Action)); + memclrw(action, sizeof(CI_Action)); + + action->actiontype = CI_ActionTemplateFunc; + action->obj = object; + action->u.templatefunc.func = func; + action->u.templatefunc.inst = inst; + + action->next = cinline_tactionlist; + cinline_tactionlist = action; + + TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_200000; +} + +static void CInline_AddFRefList_Object(Object *object) { + ObjectList *list; + + if ( + !(object->datatype == DFUNC || object->datatype == DVFUNC) || + (object->flags & OBJECT_DEFINED) || + IS_TEMPL_FUNC(object->type) + ) + return; + + for (list = cinline_freflist; list; list = list->next) { + if (list->object == object) + return; + } + + list = lalloc(sizeof(ObjectList)); + list->object = object; + list->next = cinline_freflist; + cinline_freflist = list; + + if ((object->qual & Q_INLINE) && object->u.func.u.ifuncdata) + CInline_AddFRefList_InlineFunc(object->u.func.u.ifuncdata); +} + +static void CInline_AddFRefList_ExAction(ExceptionAction *exc) { + while (exc) { + switch (exc->type) { + case EAT_DESTROYLOCAL: + CInline_AddFRefList_Object(exc->data.destroy_local.dtor); + break; + case EAT_DESTROYLOCALCOND: + CInline_AddFRefList_Object(exc->data.destroy_local_cond.dtor); + break; + case EAT_DESTROYLOCALOFFSET: + CInline_AddFRefList_Object(exc->data.destroy_local_offset.dtor); + break; + case EAT_DESTROYLOCALPOINTER: + CInline_AddFRefList_Object(exc->data.destroy_local_pointer.dtor); + break; + case EAT_DESTROYLOCALARRAY: + CInline_AddFRefList_Object(exc->data.destroy_local_array.dtor); + break; + case EAT_DESTROYPARTIALARRAY: + CInline_AddFRefList_Object(exc->data.destroy_partial_array.dtor); + break; + case EAT_DESTROYMEMBER: + case EAT_DESTROYBASE: + CInline_AddFRefList_Object(exc->data.destroy_member.dtor); + break; + case EAT_DESTROYMEMBERCOND: + CInline_AddFRefList_Object(exc->data.destroy_member_cond.dtor); + break; + case EAT_DESTROYMEMBERARRAY: + CInline_AddFRefList_Object(exc->data.destroy_member_array.dtor); + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + CInline_AddFRefList_Object(exc->data.delete_pointer.deletefunc); + break; + case EAT_DELETEPOINTERCOND: + CInline_AddFRefList_Object(exc->data.delete_pointer_cond.deletefunc); + break; + case EAT_CATCHBLOCK: + case EAT_ACTIVECATCHBLOCK: + case EAT_SPECIFICATION: + case EAT_TERMINATE: + break; + default: + CError_FATAL(4307); + } + exc = exc->prev; + } +} + +static void CInline_AddFRefList_ExprCB(ENode *expr) { + CInline_AddFRefList_Object(expr->data.objref); +} + +static void CInline_AddFRefList_Expr(ENode *expr) { + CExpr_SearchExprTree(expr, CInline_AddFRefList_ExprCB, 1, EOBJREF); +} + +static void CInline_AddFRefList_Statement(Statement *stmt) { + while (stmt) { + if (stmt->dobjstack) + CInline_AddFRefList_ExAction(stmt->dobjstack); + + switch (stmt->type) { + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_ASM: + break; + case ST_RETURN: + if (!stmt->expr) + break; + case ST_EXPRESSION: + case ST_SWITCH: + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_GOTOEXPR: + CInline_AddFRefList_Expr(stmt->expr); + break; + default: + CError_FATAL(4368); + } + + stmt = stmt->next; + } +} + +static void CInline_AddFRefList_InlineFunc(CI_FuncData *data) { + short i; + CI_Statement *stmt; + ExceptionAction *exc; + + for (i = 0; i < data->numstatements; i++) { + stmt = data->statements + i; + + switch (stmt->type) { + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + case ST_ASM: + break; + case ST_EXPRESSION: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_GOTOEXPR: + CInline_AddFRefList_Expr(stmt->u.expr); + break; + case ST_RETURN: + if (stmt->u.expr) + CInline_AddFRefList_Expr(stmt->u.expr); + break; + case ST_IFGOTO: + case ST_IFNGOTO: + CInline_AddFRefList_Expr(stmt->u.ifgoto.expr); + break; + case ST_SWITCH: + CInline_AddFRefList_Expr(stmt->u.switchdata->expr); + break; + default: + CError_FATAL(4420); + } + + for (exc = data->statements[i].dobjstack; exc; exc = exc->prev) { + switch (exc->type) { + case EAT_DESTROYLOCAL: + CInline_AddFRefList_Object(exc->data.destroy_local.dtor); + break; + case EAT_DESTROYLOCALCOND: + CInline_AddFRefList_Object(exc->data.destroy_local_cond.dtor); + break; + case EAT_DESTROYLOCALOFFSET: + CInline_AddFRefList_Object(exc->data.destroy_local_offset.dtor); + break; + case EAT_DESTROYLOCALPOINTER: + CInline_AddFRefList_Object(exc->data.destroy_local_pointer.dtor); + break; + case EAT_DESTROYLOCALARRAY: + CInline_AddFRefList_Object(exc->data.destroy_local_array.dtor); + break; + case EAT_DESTROYPARTIALARRAY: + break; + case EAT_DESTROYMEMBER: + case EAT_DESTROYBASE: + CInline_AddFRefList_Object(exc->data.destroy_member.dtor); + break; + case EAT_DESTROYMEMBERCOND: + CInline_AddFRefList_Object(exc->data.destroy_member_cond.dtor); + break; + case EAT_DESTROYMEMBERARRAY: + CInline_AddFRefList_Object(exc->data.destroy_member_array.dtor); + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + CInline_AddFRefList_Object(exc->data.delete_pointer.deletefunc); + break; + case EAT_DELETEPOINTERCOND: + CInline_AddFRefList_Object(exc->data.delete_pointer_cond.deletefunc); + break; + case EAT_CATCHBLOCK: + case EAT_ACTIVECATCHBLOCK: + case EAT_SPECIFICATION: + case EAT_TERMINATE: + break; + default: + CError_FATAL(4470); + } + } + } +} + +static void CInline_GenerateTemplateInline(Object *object) { + CI_Action **ptr; + CI_Action *action; + + ptr = &cinline_tactionlist; + while ((action = *ptr)) { + if (object == action->obj) { + *ptr = action->next; + action->next = cinline_actionlist; + cinline_actionlist = action; + + TYPE_FUNC(object->type)->flags &= ~FUNC_FLAGS_200000; + return; + } + + ptr = &action->next; + } + + CError_FATAL(4499); +} + +void CInline_ObjectAddrRef(Object *object) { + CI_FuncData *funcdata; + + object->flags |= OBJECT_FLAGS_2; + + switch (object->datatype) { + case DFUNC: + case DVFUNC: + if ( + (object->qual & Q_INLINE) && + (funcdata = object->u.func.u.ifuncdata) && + !(object->flags & OBJECT_DEFINED) && + !(TYPE_FUNC(object->type)->flags & FUNC_IS_TEMPL) + ) + { + CI_Export *export = galloc(sizeof(CI_Export)); + + export->object = object; + export->funcdata = funcdata; + export->xC = 0; + + export->next = cinline_exportlist; + cinline_exportlist = export; + + object->flags |= OBJECT_DEFINED; + return; + } + else if ( + (TYPE_FUNC(object->type)->flags & FUNC_AUTO_GENERATED) && + !(TYPE_FUNC(object->type)->flags & FUNC_DEFINED) + ) + { + CInline_AddDefaultFunctionAction(object); + return; + } + else if (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_200000) + { + CInline_GenerateTemplateInline(object); + return; + } + return; + + case DALIAS: + CInline_ObjectAddrRef(object->u.alias.object); + return; + + case DDATA: + if (object->qual & Q_INLINE_DATA) + CInit_ExportConst(object); + + if (object->flags & OBJECT_LAZY) { + object->flags &= ~OBJECT_LAZY; + CParser_CallBackAction(object); + } + return; + } +} + +static Boolean CInline_CheckDependencies(ObjectList *list) { + Object *object; + Boolean result; + + result = 0; + + while (list) { + object = list->object; + + if ( + (TYPE_FUNC(object->type)->flags & FUNC_AUTO_GENERATED) && + !(TYPE_FUNC(object->type)->flags & FUNC_DEFINED) + ) + { + CInline_AddDefaultFunctionAction(object); + result = 1; + } + else if ( + (object->qual & Q_IS_TEMPLATED) && + CTempl_InlineFunctionCheck(object) + ) + { + result = 1; + } + else { + CI_Action *action; + for (action = cinline_actionlist; action; action = action->next) { + if (object == action->obj) { + result = 1; + break; + } + } + + if (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_200000) { + CInline_GenerateTemplateInline(object); + result = 1; + } + } + + list = list->next; + } + + return result; +} + +static Boolean CInline_IsSmallFunction(Object *object, Statement *stmt) { + SInt32 statementCount; + ObjectList *list; + SInt32 localSize; + + statementCount = 0; + while (stmt) { + if (stmt->type != ST_NOP && stmt->type != ST_LABEL) + statementCount++; + if (statementCount > 15) + return 0; + stmt = stmt->next; + } + + for (list = locals, localSize = 0; list; list = list->next) + localSize += list->object->type->size; + + if (localSize > 1024) + return 0; + + return 1; +} + +static Boolean CInline_NoFPLocals(void) { + ObjectList *list; + + for (list = locals; list; list = list->next) { + if (IS_TYPE_FLOAT(list->object->type)) + return 0; + } + + return 1; +} + +void CInline_GenFunc(Statement *stmt, Object *object, UInt8 unk) { + CI_FuncData *funcdata; + CI_Export *export; + Boolean flag24; + Boolean flag30; + + TYPE_FUNC(object->type)->flags |= OBJECT_FLAGS_2; + + flag24 = 0; + flag30 = 0; + if (!(object->qual & Q_INLINE)) { + if ( + copts.auto_inline && + !copts.dontinline && + CInline_CanInline(object, stmt->next) && + CInline_IsSmallFunction(object, stmt->next) + ) + { + flag24 = 1; + flag30 = 1; + TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_800; + } + } else { + flag30 = 1; + } + + if (flag30) { + COpt_SimpleOptimizer(object, stmt); + + funcdata = galloc(sizeof(CI_FuncData)); + CInline_PackIFunctionData(funcdata, stmt, object); + + object->u.func.u.ifuncdata = funcdata; + + if (!flag24 && !(object->flags & OBJECT_FLAGS_2)) { + if (cinline_gendeps) { + cinline_freflist = NULL; + CInline_AddFRefList_Statement(stmt); + CInline_CheckDependencies(cinline_freflist); + } + return; + } + } + + object->flags |= OBJECT_DEFINED; + + cinline_freflist = NULL; + CInline_AddFRefList_Statement(stmt); + + if (CInline_CheckDependencies(cinline_freflist) || copts.defer_codegen) { + if (!flag30) { + funcdata = galloc(sizeof(CI_FuncData)); + CInline_PackIFunctionData(funcdata, stmt, object); + } else { + funcdata = object->u.func.u.ifuncdata; + } + + export = galloc(sizeof(CI_Export)); + export->object = object; + export->funcdata = funcdata; + export->xC = unk; + + export->next = cinline_exportlist; + cinline_exportlist = export; + + return; + } + + expanding_function = object; + recursive_inline = 0; + CInline_Expand(stmt); + + if (copts.filesyminfo) + CPrep_SetSourceFile(&cparser_fileoffset); + + if (!anyerrors) + CodeGen_Generator(stmt, object, unk, 0); +} + +static void CInline_GenerateDefaultFunc(Object *object) { + TypeClass *tclass; + + CError_ASSERT(4770, TYPE_FUNC(object->type)->flags & FUNC_AUTO_GENERATED); + CError_ASSERT(4771, TYPE_FUNC(object->type)->flags & FUNC_METHOD); + + tclass = TYPE_METHOD(object->type)->theclass; + + if (object == CClass_DefaultConstructor(tclass)) { + if (object->u.func.defargdata) + CABI_MakeDefaultArgConstructor(tclass, object); + else + CABI_MakeDefaultConstructor(tclass, object); + } else if (object == CClass_CopyConstructor(tclass)) { + CABI_MakeDefaultCopyConstructor(tclass, object); + } else if (object == CClass_AssignmentOperator(tclass)) { + CABI_MakeDefaultAssignmentOperator(tclass, object); + } else if (object == CClass_Destructor(tclass)) { + CABI_MakeDefaultDestructor(tclass, object); + } else { + CError_FATAL(4805); + } +} + +static TemplClassInst *CInline_FindNestedTemplInst(TypeClass *tclass) { + NameSpace *nspace; + + while (tclass) { + if ((tclass->flags & CLASS_IS_TEMPL_INST)) + return TEMPL_CLASS_INST(tclass); + + if (!copts.template_patch) + break; + + nspace = tclass->nspace->parent; + tclass = NULL; + while (nspace) { + if (nspace->theclass) { + tclass = nspace->theclass; + break; + } + nspace = nspace->parent; + } + } + + return NULL; +} + +static void CInline_GenerateInlineFunc(CI_Action *action) { + Object *object; + TemplClassInst *inst; + DeclInfo di; + SInt32 streamState; + + object = action->obj; + + CPrep_StreamInsert(&action->u.inlinefunc.stream, &streamState); + cparser_fileoffset = action->u.inlinefunc.fileoffset; + symdecloffset = cparser_fileoffset.tokenline; + + switch ((tk = lex())) { + case ':': + case '{': + case TK_TRY: + break; + default: + CError_FATAL(4860); + } + + symdecltoken = *CPrep_CurStreamElement(); + + TYPE_FUNC(object->type)->flags &= ~FUNC_DEFINED; + if (IS_TYPE_METHOD(object->type) && (inst = CInline_FindNestedTemplInst(TYPE_METHOD(object->type)->theclass))) { + CTempl_ParseInstanceScopeFunction(object, inst, NULL); + } else { + memclrw(&di, sizeof(di)); + if (action->u.inlinefunc.tclass) { + if ((inst = CInline_FindNestedTemplInst(action->u.inlinefunc.tclass))) { + CTempl_ParseInstanceScopeFunction(object, inst, action->u.inlinefunc.tclass); + } else { + CFunc_ParseFuncDef(object, &di, action->u.inlinefunc.tclass, 0, 0, NULL); + } + } else { + CFunc_ParseFuncDef(object, &di, NULL, 0, 0, NULL); + } + } + + CPrep_StreamRemove(&action->u.inlinefunc.stream, &streamState); +} + +Boolean CInline_CanFreeLHeap(void) { + CI_Action *action; + + if (!anyerrors) { + for (action = cinline_actionlist; action; action = action->next) { + if (action->actiontype == CI_ActionInlineFunc) + return 0; + } + } + + return 1; +} + +Boolean CInline_GenerateDeferredFuncs(void) { + CI_Action *action; + CI_Export *export; + + if (!anyerrors) { + if ((action = cinline_actionlist)) { + cinline_actionlist = action->next; + cinline_gendeps = 1; + + switch (action->actiontype) { + case CI_ActionDefaultFunc: + CInline_GenerateDefaultFunc(action->obj); + break; + case CI_ActionInlineFunc: + if (!(action->obj->flags & OBJECT_DEFINED)) + CInline_GenerateInlineFunc(action); + break; + case CI_ActionMemberFunc: + if (!(TYPE_FUNC(action->obj->type)->flags & FUNC_DEFINED)) + CTempl_InstantiateMember( + action->u.memberfunc.templ, action->u.memberfunc.inst, + action->u.memberfunc.tmemb, action->obj, 0); + break; + case CI_ActionTemplateFunc: + if (!(TYPE_FUNC(action->obj->type)->flags & FUNC_DEFINED) && !action->u.templatefunc.inst->is_specialized) + CTempl_GenFuncInstance(action->u.templatefunc.func, action->u.templatefunc.inst, 0); + break; + default: + CError_FATAL(5001); + } + + cinline_gendeps = 0; + return 1; + } else { + if ((export = cinline_exportlist) && !copts.defer_codegen) { + cinline_exportlist = export->next; + CInline_GenIFunctionCode(export->object, export->funcdata, export->xC); + return 1; + } + } + } + + return 0; +} + +static InitExpr *CInline_InitTemplateData(InitExpr *init) { + Statement *stmt; + CLabel *label; + Object *object; + Object *data; + + object = init->object; + + data = CParser_NewCompilerDefDataObject(); + data->type = TYPE(&stsignedchar); + data->name = CParser_NameConcat("__init__", CMangler_GetLinkName(object)->name); + data->qual = Q_WEAK; + CInit_DeclareData(data, NULL, NULL, data->type->size); + + stmt = CFunc_AppendStatement(ST_IFGOTO); + stmt->expr = create_objectnode(data); + label = newlabel(); + stmt->label = label; + + do { + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = CInline_CopyExpression(init->expr, CopyMode0); + init = init->next; + } while (init && init->object == object); + + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = makediadicnode(create_objectnode(data), intconstnode(TYPE(&stsignedchar), 1), EASS); + + stmt = CFunc_AppendStatement(ST_LABEL); + stmt->label = label; + label->stmt = stmt; + + return init; +} + +void CInline_Finish(void) { + NameSpace *nspace; + Boolean saveDebugInfo; + Statement firstStmt; + Statement *stmt; + InitExpr *init; + Boolean doMore; + + if (!init_expressions || anyerrors) + return; + + cinline_freflist = NULL; + + for (init = init_expressions; init; init = init->next) + CInline_AddFRefList_Expr(init->expr); + + CInline_CheckDependencies(cinline_freflist); + + do { + doMore = CInline_GenerateDeferredFuncs(); + } while (doMore); + + nspace = CFunc_FuncGenSetup(&firstStmt, NULL); + saveDebugInfo = copts.filesyminfo; + copts.filesyminfo = 0; + + init = init_expressions; + while (init) { + if (init->object->nspace->theclass && (init->object->nspace->theclass->flags & CLASS_IS_TEMPL_INST)) { + init = CInline_InitTemplateData(init); + } else { + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = CInline_CopyExpression(init->expr, CopyMode0); + init = init->next; + } + } + + CFunc_CodeCleanup(&firstStmt); + + expanding_function = NULL; + recursive_inline = 0; + CInline_Expand(&firstStmt); + + if (!anyerrors) { + if (copts.filesyminfo) + CPrep_SetSourceFile(&cparser_fileoffset); + CodeGen_Generator(&firstStmt, NULL, 0, 1); + } + + cscope_current = nspace->parent; + copts.filesyminfo = saveDebugInfo; +} diff --git a/compiler_and_linker/FrontEnd/C/CMangler.c b/compiler_and_linker/FrontEnd/C/CMangler.c new file mode 100644 index 0000000..615abf5 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CMangler.c @@ -0,0 +1,713 @@ +#include "compiler/CMangler.h" +#include "compiler/CError.h" +#include "compiler/CInt64.h" +#include "compiler/CFunc.h" +#include "compiler/CParser.h" +#include "compiler/CTemplateTools.h" +#include "compiler/CompilerTools.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" +#include "compiler/types.h" +#include "cos.h" + +HashNameNode *constructor_name_node; +HashNameNode *destructor_name_node; +HashNameNode *asop_name_node; + +// forward decls +static void CMangler_MangleClassName(TypeClass *tclass); +static void CMangler_MangleTypeAppend(Type *type, UInt32 qual); +static void CMangler_MangleArgs(FuncArg *args); + +void CMangler_Setup(void) { + constructor_name_node = GetHashNameNodeExport("__ct"); + destructor_name_node = GetHashNameNodeExport("__dt"); + asop_name_node = GetHashNameNodeExport("__as"); +} + +HashNameNode *CMangler_BasicDtorName(void) { + return GetHashNameNodeExport("__dtb"); +} + +HashNameNode *CMangler_VBaseDtorName(void) { + return GetHashNameNodeExport("__dtv"); +} + +HashNameNode *CMangler_ArrayDtorName(void) { + return GetHashNameNodeExport("__dta"); +} + +HashNameNode *CMangler_SDeleteDtorName(void) { + return GetHashNameNodeExport("__dts"); +} + +HashNameNode *CMangler_DeleteDtorName(void) { + return GetHashNameNodeExport("__dt"); +} + +char *CMangler_GetOperator(HashNameNode *name) { + char *str; + + if (name == asop_name_node) + return "operator="; + + str = name->name; + if (!strcmp(str, "__nw")) return "operator new"; + if (!strcmp(str, "__dl")) return "operator delete"; + if (!strcmp(str, "__nwa")) return "operator new[]"; + if (!strcmp(str, "__dla")) return "operator delete[]"; + if (!strcmp(str, "__pl")) return "operator+"; + if (!strcmp(str, "__mi")) return "operator-"; + if (!strcmp(str, "__ml")) return "operator*"; + if (!strcmp(str, "__dv")) return "operator/"; + if (!strcmp(str, "__md")) return "operator%"; + if (!strcmp(str, "__er")) return "operator^"; + if (!strcmp(str, "__ad")) return "operator&"; + if (!strcmp(str, "__or")) return "operator|"; + if (!strcmp(str, "__co")) return "operator~"; + if (!strcmp(str, "__nt")) return "operator!"; + if (!strcmp(str, "__lt")) return "operator<"; + if (!strcmp(str, "__gt")) return "operator>"; + if (!strcmp(str, "__apl")) return "operator+="; + if (!strcmp(str, "__ami")) return "operator-="; + if (!strcmp(str, "__amu")) return "operator*="; + if (!strcmp(str, "__adv")) return "operator/="; + if (!strcmp(str, "__amd")) return "operator%="; + if (!strcmp(str, "__aer")) return "operator^="; + if (!strcmp(str, "__aad")) return "operator&="; + if (!strcmp(str, "__aor")) return "operator|="; + if (!strcmp(str, "__ls")) return "operator<<"; + if (!strcmp(str, "__rs")) return "operator>>"; + if (!strcmp(str, "__als")) return "operator<<="; + if (!strcmp(str, "__ars")) return "operator>>="; + if (!strcmp(str, "__eq")) return "operator=="; + if (!strcmp(str, "__ne")) return "operator!="; + if (!strcmp(str, "__le")) return "operator<="; + if (!strcmp(str, "__ge")) return "operator>="; + if (!strcmp(str, "__aa")) return "operator&&"; + if (!strcmp(str, "__oo")) return "operator||"; + if (!strcmp(str, "__pp")) return "operator++"; + if (!strcmp(str, "__mm")) return "operator--"; + if (!strcmp(str, "__cm")) return "operator,"; + if (!strcmp(str, "__rm")) return "operator->*"; + if (!strcmp(str, "__rf")) return "operator*"; + if (!strcmp(str, "__cl")) return "operator()"; + if (!strcmp(str, "__vc")) return "operator[]"; + return NULL; +} + +HashNameNode *CMangler_OperatorName(short token) { + switch (token) { + case TK_NEW: return GetHashNameNodeExport("__nw"); + case TK_DELETE: return GetHashNameNodeExport("__dl"); + case TK_NEW_ARRAY: return GetHashNameNodeExport("__nwa"); + case TK_DELETE_ARRAY: return GetHashNameNodeExport("__dla"); + case '+': return GetHashNameNodeExport("__pl"); + case '-': return GetHashNameNodeExport("__mi"); + case '*': return GetHashNameNodeExport("__ml"); + case '/': return GetHashNameNodeExport("__dv"); + case '%': return GetHashNameNodeExport("__md"); + case '^': return GetHashNameNodeExport("__er"); + case '&': return GetHashNameNodeExport("__ad"); + case '|': return GetHashNameNodeExport("__or"); + case '~': return GetHashNameNodeExport("__co"); + case '!': return GetHashNameNodeExport("__nt"); + case '=': return asop_name_node; + case '<': return GetHashNameNodeExport("__lt"); + case '>': return GetHashNameNodeExport("__gt"); + case TK_ADD_ASSIGN: return GetHashNameNodeExport("__apl"); + case TK_SUB_ASSIGN: return GetHashNameNodeExport("__ami"); + case TK_MULT_ASSIGN: return GetHashNameNodeExport("__amu"); + case TK_DIV_ASSIGN: return GetHashNameNodeExport("__adv"); + case TK_MOD_ASSIGN: return GetHashNameNodeExport("__amd"); + case TK_XOR_ASSIGN: return GetHashNameNodeExport("__aer"); + case TK_AND_ASSIGN: return GetHashNameNodeExport("__aad"); + case TK_OR_ASSIGN: return GetHashNameNodeExport("__aor"); + case TK_SHL: return GetHashNameNodeExport("__ls"); + case TK_SHR: return GetHashNameNodeExport("__rs"); + case TK_SHL_ASSIGN: return GetHashNameNodeExport("__als"); + case TK_SHR_ASSIGN: return GetHashNameNodeExport("__ars"); + case TK_LOGICAL_EQ: return GetHashNameNodeExport("__eq"); + case TK_LOGICAL_NE: return GetHashNameNodeExport("__ne"); + case TK_LESS_EQUAL: return GetHashNameNodeExport("__le"); + case TK_GREATER_EQUAL: return GetHashNameNodeExport("__ge"); + case TK_LOGICAL_AND: return GetHashNameNodeExport("__aa"); + case TK_LOGICAL_OR: return GetHashNameNodeExport("__oo"); + case TK_INCREMENT: return GetHashNameNodeExport("__pp"); + case TK_DECREMENT: return GetHashNameNodeExport("__mm"); + case ',': return GetHashNameNodeExport("__cm"); + case TK_ARROW_STAR: return GetHashNameNodeExport("__rm"); + case TK_ARROW: return GetHashNameNodeExport("__rf"); + case '(': return GetHashNameNodeExport("__cl"); + case '[': return GetHashNameNodeExport("__vc"); + default: return NULL; + } +} + +HashNameNode *CMangler_VTableName(TypeClass *theclass) { + HashNameNode *name; + + name_mangle_list.size = 0; + AppendGListName(&name_mangle_list, "__vt__"); + CMangler_MangleClassName(theclass); + AppendGListByte(&name_mangle_list, 0); + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +HashNameNode *CMangler_RTTIObjectName(Type *type, UInt32 qual) { + HashNameNode *name; + + name_mangle_list.size = 0; + AppendGListName(&name_mangle_list, "__RTTI__"); + CMangler_MangleTypeAppend(type, qual); + AppendGListByte(&name_mangle_list, 0); + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +HashNameNode *CMangler_ThunkName(Object *vfunc, SInt32 this_delta, SInt32 return_delta, SInt32 ctoroffset) { + HashNameNode *linkname; + HashNameNode *name; + char buf[64]; + + linkname = CMangler_GetLinkName(vfunc); + name_mangle_list.size = 0; + if (return_delta == 0) { + if (ctoroffset < 0) + sprintf(buf, "_@%" PRId32 "@", -this_delta); + else + sprintf(buf, "_@%" PRId32 "@%" PRId32 "@", -this_delta, ctoroffset); + } else { + sprintf(buf, "_@%" PRId32 "@%" PRId32 "@%" PRId32 "@", -this_delta, ctoroffset, return_delta); + } + AppendGListName(&name_mangle_list, buf); + AppendGListID(&name_mangle_list, linkname->name + 1); + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +static void CMangler_CheckTemplateArguments(TemplArg *arg) { + ENode *expr; + + while (arg) { + if (arg->pid.type == TPT_NONTYPE) { + expr = arg->data.paramdecl.expr; + CError_ASSERT(360, expr); + if (expr->rtype->type != TYPETEMPLDEPEXPR) { + switch (expr->type) { + case EINTCONST: + break; + case EOBJREF: + CMangler_GetLinkName(expr->data.objref); + break; + default: + CError_FATAL(383); + } + } + } + arg = arg->next; + } +} + +static void CMangler_AppendTemplateArgumentList(TemplArg *arg) { + ENode *expr; + char buf[32]; + + AppendGListByte(&name_mangle_list, '<'); + + while (arg) { + if (arg->pid.type == TPT_NONTYPE) { + expr = arg->data.paramdecl.expr; + CError_ASSERT(409, expr); + if (expr->rtype->type != TYPETEMPLDEPEXPR) { + switch (expr->type) { + case EINTCONST: + CInt64_PrintDec(buf, expr->data.intval); + AppendGListName(&name_mangle_list, buf); + break; + case EOBJREF: + AppendGListByte(&name_mangle_list, '&'); + AppendGListName(&name_mangle_list, CMangler_GetLinkName(expr->data.objref)->name); + break; + default: + CError_FATAL(452); + } + } else { + AppendGListByte(&name_mangle_list, 'T'); + } + } else if (arg->pid.type == TPT_TYPE) { + CMangler_MangleTypeAppend(arg->data.typeparam.type, arg->data.typeparam.qual); + } else { + CError_ASSERT(467, arg->pid.type == TPT_TEMPLATE); + CMangler_MangleTypeAppend(arg->data.ttargtype, 0); + } + + if (arg->next) + AppendGListByte(&name_mangle_list, ','); + arg = arg->next; + } + + AppendGListByte(&name_mangle_list, '>'); +} + +HashNameNode *CMangler_TemplateInstanceName(HashNameNode *basename, TemplArg *args) { + HashNameNode *name; + + CMangler_CheckTemplateArguments(args); + name_mangle_list.size = 0; + AppendGListName(&name_mangle_list, basename->name); + CMangler_AppendTemplateArgumentList(args); + AppendGListByte(&name_mangle_list, 0); + + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +static void CMangler_MangleTypeName(char *str) { + char buf[16]; + + sprintf(buf, "%d", strlen(str)); + AppendGListName(&name_mangle_list, buf); + AppendGListName(&name_mangle_list, str); +} + +static void CMangler_MangleNameSpaceName(NameSpace *nspace, char *str) { + char *stack[10]; + int stackp; + + stack[0] = str; + stackp = 1; + while (nspace) { + if (nspace->name) { + stack[stackp++] = nspace->name->name; + if (stackp >= 9) + break; + } + nspace = nspace->parent; + } + + if (stackp > 1) { + AppendGListByte(&name_mangle_list, 'Q'); + AppendGListByte(&name_mangle_list, '0' + stackp); + } + + while (--stackp >= 0) + CMangler_MangleTypeName(stack[stackp]); +} + +static void CMangler_MangleClassName(TypeClass *tclass) { + if (!tclass->classname) + CMangler_MangleNameSpaceName(tclass->nspace->parent, "class"); + else + CMangler_MangleNameSpaceName(tclass->nspace->parent, tclass->nspace->name->name); +} + +static void CMangler_MangleQualifier(UInt32 qual) { + if (qual & Q_CONST) + AppendGListByte(&name_mangle_list, 'C'); + if (qual & Q_VOLATILE) + AppendGListByte(&name_mangle_list, 'V'); +} + +static void CMangler_MangleTypeAppend(Type *type, UInt32 qual) { + char buf[16]; + + switch (type->type) { + case TYPEVOID: + CMangler_MangleQualifier(qual); + AppendGListByte(&name_mangle_list, 'v'); + break; + case TYPEINT: + case TYPEFLOAT: + CMangler_MangleQualifier(qual); + switch (TYPE_INTEGRAL(type)->integral) { + case IT_BOOL: + AppendGListByte(&name_mangle_list, 'b'); + return; + case IT_CHAR: + AppendGListByte(&name_mangle_list, 'c'); + return; + case IT_WCHAR_T: + AppendGListByte(&name_mangle_list, 'w'); + return; + case IT_UCHAR: + AppendGListName(&name_mangle_list, "Uc"); + return; + case IT_SCHAR: + AppendGListName(&name_mangle_list, "Sc"); + return; + case IT_SHORT: + AppendGListByte(&name_mangle_list, 's'); + return; + case IT_USHORT: + AppendGListName(&name_mangle_list, "Us"); + return; + case IT_INT: + AppendGListByte(&name_mangle_list, 'i'); + return; + case IT_UINT: + AppendGListName(&name_mangle_list, "Ui"); + return; + case IT_LONG: + AppendGListByte(&name_mangle_list, 'l'); + return; + case IT_ULONG: + AppendGListName(&name_mangle_list, "Ul"); + return; + case IT_LONGLONG: + AppendGListByte(&name_mangle_list, 'x'); + return; + case IT_ULONGLONG: + AppendGListName(&name_mangle_list, "Ux"); + return; + case IT_FLOAT: + AppendGListByte(&name_mangle_list, 'f'); + return; + case IT_SHORTDOUBLE: + AppendGListByte(&name_mangle_list, 'D'); + return; + case IT_DOUBLE: + AppendGListByte(&name_mangle_list, 'd'); + return; + case IT_LONGDOUBLE: + AppendGListByte(&name_mangle_list, 'r'); + return; + default: + CError_FATAL(619); + } + case TYPEENUM: + CMangler_MangleQualifier(qual); + if (!TYPE_ENUM(type)->enumname) + CMangler_MangleNameSpaceName(TYPE_ENUM(type)->nspace, "enum"); + else + CMangler_MangleNameSpaceName(TYPE_ENUM(type)->nspace, TYPE_ENUM(type)->enumname->name); + break; + case TYPEPOINTER: + CMangler_MangleQualifier(TYPE_POINTER(type)->qual); + if (TYPE_POINTER(type)->qual & Q_REFERENCE) + AppendGListByte(&name_mangle_list, 'R'); + else + AppendGListByte(&name_mangle_list, 'P'); + CMangler_MangleTypeAppend(TYPE_POINTER(type)->target, qual); + break; + case TYPEMEMBERPOINTER: + if (TYPE_MEMBER_POINTER(type)->ty2->type != TYPECLASS) { + AppendGListName(&name_mangle_list, "3"); + } else { + CMangler_MangleQualifier(TYPE_MEMBER_POINTER(type)->qual); + AppendGListByte(&name_mangle_list, 'M'); + CMangler_MangleClassName(TYPE_CLASS(TYPE_MEMBER_POINTER(type)->ty2)); + CMangler_MangleTypeAppend(TYPE_MEMBER_POINTER(type)->ty1, qual); + } + break; + case TYPEARRAY: + AppendGListByte(&name_mangle_list, 'A'); + if (TYPE_POINTER(type)->target->size) { + sprintf(buf, "%" PRId32 "", type->size / TYPE_POINTER(type)->target->size); + AppendGListName(&name_mangle_list, buf); + } else { + AppendGListByte(&name_mangle_list, '0'); + } + AppendGListByte(&name_mangle_list, '_'); + CMangler_MangleTypeAppend(TYPE_POINTER(type)->target, qual); + break; + case TYPEFUNC: + CMangler_MangleQualifier(qual); + AppendGListByte(&name_mangle_list, 'F'); + CMangler_MangleArgs(TYPE_FUNC(type)->args); + AppendGListByte(&name_mangle_list, '_'); + CMangler_MangleTypeAppend(TYPE_FUNC(type)->functype, TYPE_FUNC(type)->qual); + break; + case TYPESTRUCT: + CMangler_MangleQualifier(qual); + switch (TYPE_STRUCT(type)->stype) { + case STRUCT_VECTOR_UCHAR: + AppendGListName(&name_mangle_list, "XUc"); + return; + case STRUCT_VECTOR_SCHAR: + AppendGListName(&name_mangle_list, "Xc"); + return; + case STRUCT_VECTOR_BCHAR: + AppendGListName(&name_mangle_list, "XC"); + return; + case STRUCT_VECTOR_USHORT: + AppendGListName(&name_mangle_list, "XUs"); + return; + case STRUCT_VECTOR_SSHORT: + AppendGListName(&name_mangle_list, "Xs"); + return; + case STRUCT_VECTOR_BSHORT: + AppendGListName(&name_mangle_list, "XS"); + return; + case STRUCT_VECTOR_UINT: + AppendGListName(&name_mangle_list, "XUi"); + return; + case STRUCT_VECTOR_SINT: + AppendGListName(&name_mangle_list, "Xi"); + return; + case STRUCT_VECTOR_BINT: + AppendGListName(&name_mangle_list, "XI"); + return; + case STRUCT_VECTOR_FLOAT: + AppendGListName(&name_mangle_list, "Xf"); + return; + case STRUCT_VECTOR_PIXEL: + AppendGListName(&name_mangle_list, "Xp"); + return; + } + + if (TYPE_STRUCT(type)->name && !IsTempName(TYPE_STRUCT(type)->name)) { + CMangler_MangleTypeName(TYPE_STRUCT(type)->name->name); + return; + } + + switch (TYPE_STRUCT(type)->stype) { + case STRUCT_TYPE_STRUCT: + AppendGListName(&name_mangle_list, "struct"); + break; + case STRUCT_TYPE_UNION: + AppendGListName(&name_mangle_list, "union"); + break; + case STRUCT_TYPE_CLASS: + AppendGListName(&name_mangle_list, "class"); + break; + default: + CError_FATAL(701); + } + break; + + case TYPECLASS: + CMangler_MangleQualifier(qual); + CMangler_MangleClassName(TYPE_CLASS(type)); + break; + + case TYPETEMPLATE: + AppendGListName(&name_mangle_list, "1T"); + break; + + default: + CError_FATAL(716); + } +} + +void CMangler_MangleType(Type *type, UInt32 qual) { + name_mangle_list.size = 0; + CMangler_MangleTypeAppend(type, qual); +} + +static void CMangler_MangleArgs(FuncArg *args) { + TypePointer ptr; + + if (args) { + if (args->type) { + while (args) { + if (args != &elipsis && args != &oldstyle) { + if (args->type->type == TYPEPOINTER) { + ptr = *TYPE_POINTER(args->type); + ptr.qual &= ~(Q_CONST | Q_VOLATILE); + CMangler_MangleTypeAppend(TYPE(&ptr), args->qual); + } else { + CMangler_MangleTypeAppend(args->type, 0); + } + } else { + AppendGListByte(&name_mangle_list, 'e'); + } + args = args->next; + } + } else { + AppendGListByte(&name_mangle_list, 'e'); + } + } else { + AppendGListByte(&name_mangle_list, 'v'); + } +} + +static void CMangler_MangleFunction(Object *obj, NameSpace *nspace) { + TypeFunc *tfunc = TYPE_FUNC(obj->type); + FuncArg *arg = tfunc->args; + + AppendGListName(&name_mangle_list, obj->name->name); + if (obj->u.func.inst) { + if (tfunc->flags & FUNC_CONVERSION) + CMangler_MangleTypeAppend(tfunc->functype, tfunc->qual); + CMangler_AppendTemplateArgumentList(obj->u.func.inst->args); + } + AppendGListName(&name_mangle_list, "__"); + while (nspace && nspace->name == NULL) + nspace = nspace->parent; + + if (nspace) { + CMangler_MangleNameSpaceName(nspace->parent, nspace->name->name); + if (nspace->theclass) { + if (obj->name == destructor_name_node) { + AppendGListName(&name_mangle_list, "Fv"); + return; + } + if (arg) { + if (obj->name == constructor_name_node) { + arg = arg->next; + if (arg && (nspace->theclass->flags & CLASS_HAS_VBASES)) + arg = arg->next; + } else { + if ((tfunc->flags & FUNC_METHOD) && !TYPE_METHOD(tfunc)->is_static) { + CMangler_MangleQualifier(arg->qual); + arg = arg->next; + } + } + } + } + } + + AppendGListByte(&name_mangle_list, 'F'); + CMangler_MangleArgs(arg); + if (obj->u.func.inst && copts.new_mangler) { + AppendGListByte(&name_mangle_list, '_'); + CMangler_MangleTypeAppend(tfunc->functype, tfunc->qual); + } +} + +HashNameNode *CMangler_ConversionFuncName(Type *type, UInt32 qual) { + HashNameNode *name; + + if (CTemplTool_IsTemplateArgumentDependentType(type)) + return GetHashNameNodeExport("__op"); + + name_mangle_list.size = 0; + AppendGListName(&name_mangle_list, "__op"); + CMangler_MangleTypeAppend(type, qual); + AppendGListByte(&name_mangle_list, 0); + + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +static HashNameNode *CMangler_MangleNameToUpper(char *str) { + HashNameNode *name; + + name_mangle_list.size = 0; + while (*str) { + AppendGListByte(&name_mangle_list, toupper(*(str++))); + } + AppendGListByte(&name_mangle_list, 0); + + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +static HashNameNode *CMangler_FunctionLinkName(Object *obj) { + HashNameNode *name; + NameSpace *nspace; + + if (obj->u.func.inst) + CMangler_CheckTemplateArguments(obj->u.func.inst->args); + + for (nspace = obj->nspace; nspace; nspace = nspace->parent) { + if (nspace->name) + break; + } + + name_mangle_list.size = 0; + if (is_pascal_object(obj) && (!nspace || !nspace->theclass)) { + AppendGListData(&name_mangle_list, "_", 1); + AppendGListID(&name_mangle_list, obj->name->name); + } else if ((obj->qual & Q_MANGLE_NAME) && (strcmp("main", obj->name->name) || (obj->nspace != cscope_root))) { + AppendGListData(&name_mangle_list, "_", 1); + CMangler_MangleFunction(obj, nspace); + AppendGListByte(&name_mangle_list, 0); + } else { + AppendGListData(&name_mangle_list, "_", 1); + AppendGListID(&name_mangle_list, obj->name->name); + } + + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +HashNameNode *CMangler_GetCovariantFunctionName(Object *dobj, TypeClass *theclass) { + HashNameNode *name; + + name = CMangler_GetLinkName(dobj); + name_mangle_list.size = 0; + AppendGListName(&name_mangle_list, name->name); + AppendGListName(&name_mangle_list, "@@"); + CMangler_MangleTypeAppend(TYPE(theclass), 0); + AppendGListByte(&name_mangle_list, 0); + + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +static HashNameNode *CMangler_DataLinkName(Object *obj) { + NameSpace *nspace; + HashNameNode *name; + + nspace = obj->nspace; + while (nspace && nspace->name == NULL) + nspace = nspace->parent; + + name_mangle_list.size = 0; + AppendGListData(&name_mangle_list, "_", 1); + AppendGListName(&name_mangle_list, obj->name->name); + + while (nspace && nspace->name == NULL) + nspace = nspace->parent; + if (nspace && (obj->qual & Q_MANGLE_NAME)) { + AppendGListName(&name_mangle_list, "__"); + CMangler_MangleNameSpaceName(nspace->parent, nspace->name->name); + } + AppendGListByte(&name_mangle_list, 0); + + COS_LockHandle(name_mangle_list.data); + name = GetHashNameNodeExport(*name_mangle_list.data); + COS_UnlockHandle(name_mangle_list.data); + return name; +} + +HashNameNode *CMangler_GetLinkName(Object *obj) { + while (obj->datatype == DALIAS) + obj = obj->u.alias.object; + + switch (obj->datatype) { + case DFUNC: + case DVFUNC: + if (!obj->u.func.linkname) + obj->u.func.linkname = CMangler_FunctionLinkName(obj); + return obj->u.func.linkname; + case DDATA: + if (!obj->u.data.linkname) + obj->u.data.linkname = CMangler_DataLinkName(obj); + return obj->u.data.linkname; + case DINLINEFUNC: + return CMangler_FunctionLinkName(obj); + case DLOCAL: + case DABSOLUTE: + case DLABEL: + return obj->name; + case DNONLAZYPTR: + if (!obj->u.toc.linkname) + obj->u.toc.linkname = CMangler_DataLinkName(obj); + return obj->u.toc.linkname; + default: + CError_FATAL(1110); + return NULL; + } +} diff --git a/compiler_and_linker/FrontEnd/C/CParser.c b/compiler_and_linker/FrontEnd/C/CParser.c new file mode 100644 index 0000000..b089e47 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CParser.c @@ -0,0 +1,3477 @@ +#include "compiler/CParser.h" +#include "compiler/CABI.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInit.h" +#include "compiler/CInline.h" +#include "compiler/CInt64.h" +#include "compiler/CIRTransform.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CObjC.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/CSOM.h" +#include "compiler/CTemplateNew.h" +#include "compiler/CTemplateTools.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "../Optimizer/IrOptimizer.h" +#include "../Optimizer/IroPointerAnalysis.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" +#include "cos.h" + +FileOffsetInfo cparser_fileoffset; +TStreamElement symdecltoken; +ParserTryBlock *trychain; +Boolean inassembler; +Boolean dont_set_references; +TypeStruct ptmstruct; +TypeStruct catchinfostruct; +Boolean in_assembler; +Boolean illegalimplicitconversion; +Boolean in_func_arglist; +NameSpaceName *newp_fobj; +NameSpaceName *newa_fobj; +NameSpaceName *delp_fobj; +NameSpaceName *dela_fobj; +Object *newh_func; +Object *delh_func; +Object *copy_func; +Object *clear_func; +Object *Rgtid_func; +Object *Rdync_func; +Object *rt_ptmf_cast; +Object *rt_ptmf_cmpr; +Object *rt_ptmf_test; +Object *rt_ptmf_call; +Object *rt_ptmf_scall; +Object *rt_ptmf_call4; +Object *rt_ptmf_scall4; +Object *rt_ptmf_null; +Object *rt_som_new; +Object *rt_som_newcheck; +Object *rt_som_check; +Object *rt_som_glue1; +Object *rt_som_glue2; +Object *rt_som_glue3; +Object *carr_func; +Object *cnar_func; +Object *darr_func; +Object *dnar_func; +Object *dnar3_func; +Object *Xgreg_func; +Object *Xthrw_func; +Object *Xicth_func; +Object *Xecth_func; +Object *Xunex_func; +CompilerLinkerOptions copts; +GList name_mangle_list; +HashNameNode *no_name_node; +HashNameNode *temp_argument_name; +HashNameNode *this_name_node; +HashNameNode *self_name_node; +HashNameNode *vptr_name_node; +CallbackAction *callbackactions; +Boolean fatalerrors; +Boolean anyerrors; +jmp_buf errorreturn; +static HashNameNode *uniquenamespacename; +static SInt32 uniqueid; + +struct ClassAction { + struct ClassAction *next; + TypeClass *tclass; +}; +static struct ClassAction *cparser_classactions; + +struct ParentCleanup { + struct ParentCleanup *next; + TypeClass *tclass; +}; +static struct ParentCleanup *cparser_parentcleanup; + +struct SFuncList { + struct SFuncList *next; + Object *func; + Object *obj; + ENode *expr; +}; +static struct SFuncList *cparser_sfunclist; + +char string[256]; +SInt32 compilererrornum; +SInt32 compilererrfile; +SInt32 compilererrline; + +Type sttemplexpr = {TYPETEMPLDEPEXPR, 0}; +Type stillegal = {TYPEILLEGAL, 1}; +Type stvoid = {TYPEVOID, 0}; +TypePointer void_ptr = {TYPEPOINTER, 0, &stvoid, 0}; +TypeFunc rt_func = {TYPEFUNC, 0, NULL, NULL, &stvoid, 0, 0}; + +// forward declarations +static void CParser_ParseDeclaration(DeclInfo *di); + +Object *CParser_NewRTFunc(Type *rettype, HashNameNode *name, Boolean flag, int argcount, ...) { + Object *obj; + FuncArg *args; + FuncArg *arg; + TypeFunc *tfunc; + va_list va; + + args = NULL; + if (argcount) { + va_start(va, argcount); + while (--argcount >= 0) { + if (args) { + arg->next = CParser_NewFuncArg(); + arg = arg->next; + } else { + arg = CParser_NewFuncArg(); + args = arg; + } + arg->type = va_arg(va, Type *); + } + va_end(va); + } + + obj = CParser_NewFunctionObject(NULL); + + tfunc = galloc(sizeof(TypeFunc)); + memclrw(tfunc, sizeof(TypeFunc)); + tfunc->type = TYPEFUNC; + tfunc->functype = rettype; + tfunc->args = args; + CDecl_SetFuncFlags(tfunc, 0); + + obj->name = name; + obj->type = TYPE(tfunc); + if (flag == 1) + obj->qual = Q_MANGLE_NAME; + + return obj; +} + +Boolean CParser_IsPublicRuntimeObject(Object *obj) { + if (newp_fobj->first.object == OBJ_BASE(obj) && !newp_fobj->first.next) + return 1; + if (newa_fobj->first.object == OBJ_BASE(obj) && !newa_fobj->first.next) + return 1; + if (delp_fobj->first.object == OBJ_BASE(obj) && !delp_fobj->first.next) + return 1; + if (dela_fobj->first.object == OBJ_BASE(obj) && !dela_fobj->first.next) + return 1; + return CodeGen_IsPublicRuntimeObject(obj); +} + +Object *CParser_FindPublicRuntimeObject(HashNameNode *name) { + NameSpaceObjectList *list = CScope_FindName(cscope_root, name); + if (list && list->object->otype == OT_OBJECT && (!list->next || list->next->object->otype == OT_TYPETAG)) + return OBJECT(list->object); + else + return NULL; +} + +Boolean CParser_ReInitRuntimeObjects(Boolean is_precompiler) { + if (!(newp_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_NEW)))) + return 0; + if (!(newa_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_NEW_ARRAY)))) + return 0; + if (!(delp_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_DELETE)))) + return 0; + if (!(dela_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_DELETE_ARRAY)))) + return 0; + + newh_func->name = GetHashNameNodeExport("__new_hdl"); + delh_func->name = GetHashNameNodeExport("__del_hdl"); + copy_func->name = GetHashNameNodeExport("__copy"); + clear_func->name = GetHashNameNodeExport("__clear"); + Rgtid_func->name = GetHashNameNodeExport("__get_typeid"); + Rdync_func->name = GetHashNameNodeExport("__dynamic_cast"); + rt_ptmf_cast->name = GetHashNameNodeExport("__ptmf_cast"); + rt_ptmf_cmpr->name = GetHashNameNodeExport("__ptmf_cmpr"); + rt_ptmf_test->name = GetHashNameNodeExport("__ptmf_test"); + rt_ptmf_call->name = GetHashNameNodeExport("__ptmf_call"); + rt_ptmf_scall->name = GetHashNameNodeExport("__ptmf_scall"); + rt_ptmf_call4->name = GetHashNameNodeExport("__ptmf_call4"); + rt_ptmf_scall4->name = GetHashNameNodeExport("__ptmf_scall4"); + rt_ptmf_null->name = GetHashNameNodeExport("__ptmf_null"); + rt_som_new->name = GetHashNameNodeExport("__som_new"); + rt_som_newcheck->name = GetHashNameNodeExport("__som_check_new"); + rt_som_check->name = GetHashNameNodeExport("__som_check_ev"); + rt_som_glue1->name = GetHashNameNodeExport("_som_ptrgl4"); + rt_som_glue2->name = GetHashNameNodeExport("_som_ptrgl5"); + rt_som_glue3->name = GetHashNameNodeExport("_som_ptrgl_"); + carr_func->name = GetHashNameNodeExport("__construct_array"); + cnar_func->name = GetHashNameNodeExport("__construct_new_array"); + darr_func->name = GetHashNameNodeExport("__destroy_arr"); + dnar_func->name = GetHashNameNodeExport("__destroy_new_array"); + dnar3_func->name = GetHashNameNodeExport("__destroy_new_array3"); + Xgreg_func->name = GetHashNameNodeExport("__register_global_object"); + Xthrw_func->name = GetHashNameNodeExport("__throw"); + Xicth_func->name = GetHashNameNodeExport("__init__catch"); + Xecth_func->name = GetHashNameNodeExport("__end__catch"); + Xunex_func->name = GetHashNameNodeExport("__unexpected"); + + CMangler_Setup(); + + no_name_node = GetHashNameNodeExport("@no_name@"); + temp_argument_name = GetHashNameNodeExport("@temp_ptr@"); + this_name_node = GetHashNameNodeExport("this"); + self_name_node = GetHashNameNodeExport("self"); + vptr_name_node = GetHashNameNodeExport("__vptr$"); + + CSOM_Setup(is_precompiler); + return CodeGen_ReInitRuntimeObjects(is_precompiler); +} + +static void CParser_SetupRuntimeObjects(void) { + ExceptSpecList *exspecs; + Type *sizet; + Object *func; + + exspecs = galloc(sizeof(ExceptSpecList)); + memclrw(exspecs, sizeof(ExceptSpecList)); + + sizet = CABI_GetSizeTType(); + + func = CParser_NewRTFunc( + TYPE(&void_ptr), CMangler_OperatorName(TK_NEW), 1, + 1, sizet); + CScope_AddGlobalObject(func); + + func = CParser_NewRTFunc( + TYPE(&void_ptr), CMangler_OperatorName(TK_NEW_ARRAY), 1, + 1, sizet); + CScope_AddGlobalObject(func); + + func = CParser_NewRTFunc( + TYPE(&stvoid), CMangler_OperatorName(TK_DELETE), 1, + 1, &void_ptr); + CError_ASSERT(379, IS_TYPE_FUNC(func->type)); + TYPE_FUNC(func->type)->exspecs = exspecs; + CScope_AddGlobalObject(func); + + func = CParser_NewRTFunc( + TYPE(&stvoid), CMangler_OperatorName(TK_DELETE_ARRAY), 1, + 1, &void_ptr); + CError_ASSERT(387, IS_TYPE_FUNC(func->type)); + TYPE_FUNC(func->type)->exspecs = exspecs; + CScope_AddGlobalObject(func); + + newh_func = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 0, + 1, sizet); + delh_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 1, &void_ptr); + + Rgtid_func = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 0, + 2, &void_ptr, &stsignedlong); + Rdync_func = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 0, + 5, &void_ptr, &stsignedlong, &void_ptr, &void_ptr, &stsignedshort); + + copy_func = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 2, + 3, &void_ptr, &void_ptr, sizet); + clear_func = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 2, + 2, &void_ptr, sizet); + + rt_ptmf_cast = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 2, + 3, &stsignedlong, &void_ptr, &void_ptr); + rt_ptmf_cmpr = CParser_NewRTFunc( + TYPE(&stsignedlong), NULL, 2, + 2, &void_ptr, &void_ptr); + rt_ptmf_test = CParser_NewRTFunc( + TYPE(&stsignedlong), NULL, 2, + 1, &void_ptr); + + rt_ptmf_call = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); + rt_ptmf_scall = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); + rt_ptmf_call4 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); + rt_ptmf_scall4 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); + + rt_ptmf_null = CParser_NewGlobalDataObject(NULL); + rt_ptmf_null->type = &stvoid; + + rt_som_new = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 2, + 3, &void_ptr, &stsignedlong, &stsignedlong); + rt_som_newcheck = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 1, &void_ptr); + rt_som_check = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 1, &void_ptr); + rt_som_glue1 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); + rt_som_glue2 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); + rt_som_glue3 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); + + carr_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 5, &void_ptr, &void_ptr, &void_ptr, sizet, sizet); + cnar_func = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 0, + 5, &void_ptr, &void_ptr, &void_ptr, sizet, sizet); + darr_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 4, &void_ptr, &void_ptr, sizet, sizet); + dnar_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 2, &void_ptr, &void_ptr); + dnar3_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 4, &void_ptr, &void_ptr, &void_ptr, &stsignedshort); + + Xgreg_func = CParser_NewRTFunc( + TYPE(&void_ptr), NULL, 0, + 3, &void_ptr, &void_ptr, &void_ptr); + Xthrw_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 3, &void_ptr, &void_ptr, &void_ptr); + Xicth_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 1, &void_ptr); + Xecth_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 1, &void_ptr); + Xunex_func = CParser_NewRTFunc( + TYPE(&stvoid), NULL, 0, + 1, &void_ptr); + + CodeGen_SetupRuntimeObjects(); + CError_ASSERT(534, CParser_ReInitRuntimeObjects(0)); +} + +void CParser_Setup(void) { + CScope_Setup(); + + name_mangle_list.data = NULL; + if (InitGList(&name_mangle_list, 256)) + CError_NoMem(); + + void_ptr.size = 4; + CError_Init(); + CInit_Init(); + CClass_Init(); + CIRTrans_Setup(); + CObjC_Setup(); + CInline_Init(); + + in_assembler = 0; + in_func_arglist = 0; + CParser_SetUniqueID(1); + dont_set_references = 0; + + copts.sideeffects = 1; + cparser_classactions = NULL; + name_obj_check = NULL; + callbackactions = NULL; + init_expressions = NULL; + cparser_sfunclist = NULL; + trychain = NULL; + cparser_parentcleanup = NULL; + + memclrw(&cparser_fileoffset, sizeof(FileOffsetInfo)); + + memclrw(&catchinfostruct, sizeof(TypeStruct)); + catchinfostruct.type = TYPESTRUCT; + catchinfostruct.size = 24; + catchinfostruct.stype = STRUCT_TYPE_STRUCT; + catchinfostruct.align = 4; + + memclrw(&ptmstruct, sizeof(TypeStruct)); + ptmstruct.type = TYPESTRUCT; + ptmstruct.size = 12; + ptmstruct.stype = STRUCT_TYPE_STRUCT; + ptmstruct.align = 4; + + CMach_Configure(); + CTempl_Setup(); + + uniquenamespacename = NULL; + disallowgreaterthan = 0; + + CParser_SetupRuntimeObjects(); +} + +void CParser_Cleanup(void) { + CTempl_Cleanup(); + CIRTrans_Cleanup(); + CObjC_Cleanup(); + CScope_Cleanup(); + FreeGList(&name_mangle_list); +} + +short GetPrec(short token) { + switch (token) { + case '%': + case '*': + case '/': + return 11; + case '+': + case '-': + return 10; + case TK_SHL: + case TK_SHR: + return 9; + case '<': + case '>': + case TK_LESS_EQUAL: + case TK_GREATER_EQUAL: + return 8; + case TK_LOGICAL_EQ: + case TK_LOGICAL_NE: + return 7; + case '&': + return 6; + case '^': + return 5; + case '|': + return 4; + case TK_LOGICAL_AND: + return 3; + case TK_LOGICAL_OR: + return 2; + default: + return 0; + } +} + +Boolean CParser_ParseOperatorName(short *token, Boolean flag1, Boolean flag2) { + HashNameNode *name; + + switch ((tk = lex())) { + case TK_NEW: + case TK_DELETE: + if (lookahead() == '[') { + lex(); + if (lex() != ']') + CError_Error(CErrorStr125); + //if (tk == TK_NEW) + // tk = TK_NEW_ARRAY; + //else + // tk = TK_DELETE_ARRAY; + tk = (tk == TK_NEW) ? TK_NEW_ARRAY : TK_DELETE_ARRAY; + } + break; + case '(': + if ((tk = lex()) != ')') { + CError_Error(CErrorStr204); + return 0; + } + tk = '('; + break; + case '[': + if ((tk = lex()) != ']') { + CError_Error(CErrorStr204); + return 0; + } + tk = '['; + break; + } + + if ((name = CMangler_OperatorName(tk))) { + if (token) + *token = tk; + tk = lex(); + tkidentifier = name; + return 1; + } + + if (flag1) { + if (flag2) { + DeclInfo declinfo; + memclrw(&declinfo, sizeof(DeclInfo)); + conversion_type_name(&declinfo); + tkidentifier = CMangler_ConversionFuncName(declinfo.thetype, declinfo.qual); + } + if (token) + *token = 0; + return 1; + } else { + CError_Error(CErrorStr204); + return 0; + } +} + +SInt32 CParser_GetUniqueID(void) { + return uniqueid++; +} + +void CParser_PrintUniqueID(char *buf) { + SInt32 id; + char mybuf[16]; + char *ptr; + + ptr = mybuf; + id = CParser_GetUniqueID(); + while (id) { + *(ptr++) = '0' + (id - ((id / 10) * 10)); + id = id / 10; + } + + while (ptr > mybuf) + *(buf++) = *(--ptr); + + *buf = 0; +} + +void CParser_SetUniqueID(SInt32 id) { + uniqueid = id; +} + +HashNameNode *CParser_GetUniqueName(void) { + char buf[20]; + buf[0] = '@'; + CParser_PrintUniqueID(buf + 1); + return GetHashNameNodeExport(buf); +} + +HashNameNode *CParser_NameConcat(const char *a, const char *b) { + char mybuf[256]; + char *buf; + char *dst; + int len; + + len = strlen(a) + strlen(b); + if (len > (sizeof(mybuf) - 1)) { + buf = lalloc(len + 1); + dst = buf; + } else { + buf = mybuf; + dst = buf; + } + + while (*a) + *(dst++) = *(a++); + while (*b) + *(dst++) = *(b++); + *dst = 0; + + return GetHashNameNodeExport(buf); +} + +HashNameNode *CParser_AppendUniqueName(char *prefix) { + char buf[256]; + char *dst; + int i; + + dst = buf; + for (i = 0; *prefix && i < 240; i++) { + *(dst++) = *(prefix++); + } + *(dst++) = '$'; + + CParser_PrintUniqueID(dst); + return GetHashNameNodeExport(buf); +} + +HashNameNode *CParser_AppendUniqueNameFile(char *prefix) { + Str255 filename; + char buf[256]; + char *src; + char *dst; + char c; + int i; + int j; + int len; + + dst = buf; + for (i = 0; *prefix && i < 200; i++) { + *(dst++) = *(prefix++); + } + *(dst++) = '$'; + + CParser_PrintUniqueID(dst); + + while (*dst) { + dst++; + i++; + } + + COS_FileGetFSSpecInfo(&cparamblkptr->sourcefile, NULL, NULL, filename); + src = (char *) &filename[1]; + len = filename[0]; + for (j = 0; j < len && i < 255; j++, i++) { + c = *(src++); + if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9')) + c = '_'; + *(dst++) = c; + } + + dst[0] = 0; + return GetHashNameNodeExport(buf); +} + +static HashNameNode *CParser_GetUnnamedNameSpaceName(void) { + Str255 filename; + char buf[256]; + char *src; + char *dst; + char c; + int i; + int len; + + if (!uniquenamespacename) { + strcpy(buf, "@unnamed@"); + dst = buf + strlen(buf); + + COS_FileGetFSSpecInfo(&cparamblkptr->sourcefile, NULL, NULL, filename); + src = (char *) &filename[1]; + len = filename[0]; + for (i = 0; i < len && dst < &buf[254]; i++) { + c = *(src++); + if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9')) + c = '_'; + *(dst++) = c; + } + + dst[0] = '@'; + dst[1] = 0; + uniquenamespacename = GetHashNameNodeExport(buf); + } + + return uniquenamespacename; +} + +Boolean IsTempName(HashNameNode *name) { + return !name || (name->name[0] == '@') || (name->name[0] == '$'); +} + +static void CParser_SetCFMFlags(Object *object, DeclInfo *declinfo) { + if (declinfo && declinfo->exportflags) + object->flags |= declinfo->exportflags; + + if (object->datatype == DDATA) { + if (copts.cfm_export) + object->flags = object->flags | OBJECT_EXPORT; + if (copts.cfm_internal) + object->flags = object->flags | OBJECT_INTERNAL; + } else if (copts.cfm_internal) { + object->flags = object->flags | OBJECT_INTERNAL; + } else { + if (copts.cfm_import) + object->flags = object->flags | OBJECT_IMPORT; + if (copts.cfm_export) + object->flags = object->flags | OBJECT_EXPORT; + if (copts.cfm_lib_export) + object->flags = object->flags | OBJECT_IMPORT | OBJECT_EXPORT; + } +} + +void CParser_UpdateObject(Object *object, DeclInfo *declinfo) { + if (declinfo && declinfo->section) + object->section = declinfo->section; + + CParser_SetCFMFlags(object, declinfo); + CodeGen_UpdateObject(object); +} + +Object *CParser_NewObject(DeclInfo *declinfo) { + Object *object = galloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + CParser_SetCFMFlags(object, declinfo); + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->section = SECT_DEFAULT; + return object; +} + +Object *CParser_NewLocalDataObject(DeclInfo *declinfo, Boolean add_to_locals) { + Object *object = lalloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->datatype = DLOCAL; + + if (declinfo) { + object->type = declinfo->thetype; + object->name = declinfo->name; + object->qual = declinfo->qual; + object->sclass = declinfo->storageclass; + } + + if (add_to_locals) { + ObjectList *list = lalloc(sizeof(ObjectList)); + list->object = object; + list->next = locals; + locals = list; + } + + return object; +} + +Object *CParser_NewGlobalDataObject(DeclInfo *declinfo) { + Object *object = galloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->section = SECT_DEFAULT; + object->datatype = DDATA; + object->nspace = cscope_current; + + if (declinfo) { + object->type = declinfo->thetype; + object->name = declinfo->name; + object->qual = declinfo->qual; + object->sclass = declinfo->storageclass; + if (copts.cplusplus && !declinfo->is_extern_c) + object->qual |= Q_MANGLE_NAME; + } + + CParser_UpdateObject(object, declinfo); + return object; +} + +Object *CParser_NewCompilerDefDataObject(void) { + Object *object = galloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->section = SECT_DEFAULT; + object->datatype = DDATA; + object->nspace = cscope_root; + + return object; +} + +Object *CParser_NewFunctionObject(DeclInfo *declinfo) { + Object *object = galloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->section = SECT_DEFAULT; + object->datatype = DFUNC; + object->nspace = cscope_current; + + if (declinfo) { + object->type = declinfo->thetype; + object->name = declinfo->name; + object->qual = declinfo->qual; + object->sclass = declinfo->storageclass; + if (copts.cplusplus && !declinfo->is_extern_c) + object->qual |= Q_MANGLE_NAME; + } + + CParser_UpdateObject(object, declinfo); + return object; +} + +Object *CParser_NewCompilerDefFunctionObject(void) { + Object *object = galloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->section = SECT_DEFAULT; + object->datatype = DFUNC; + object->nspace = cscope_root; + return object; +} + +Object *CParser_NewAliasObject(Object *object, SInt32 offset) { + Object *alias = galloc(sizeof(Object)); + *alias = *object; + alias->datatype = DALIAS; + alias->u.alias.object = object; + alias->u.alias.member = NULL; + alias->u.alias.offset = offset; + CScope_AddObject(cscope_current, alias->name, OBJ_BASE(alias)); + return alias; +} + +FuncArg *CParser_NewFuncArg(void) { + FuncArg *arg = galloc(sizeof(FuncArg)); + memclrw(arg, sizeof(FuncArg)); + return arg; +} + +Type *atomtype(void) { + switch (tksize) { + default: + CError_FATAL(1145); + case ATOM_VOID: return &stvoid; + case ATOM_CHAR: return TYPE(&stchar); + case ATOM_WCHAR: return TYPE(&stwchar); + case ATOM_UCHAR: return TYPE(&stunsignedchar); + case ATOM_SHORT: return TYPE(&stsignedshort); + case ATOM_USHORT: return TYPE(&stunsignedshort); + case ATOM_INT: return TYPE(&stsignedint); + case ATOM_UINT: return TYPE(&stunsignedint); + case ATOM_LONG: return TYPE(&stsignedlong); + case ATOM_ULONG: return TYPE(&stunsignedlong); + case ATOM_LONGLONG: return TYPE(&stsignedlonglong); + case ATOM_ULONGLONG: return TYPE(&stunsignedlonglong); + case ATOM_FLOAT: return TYPE(&stfloat); + case ATOM_SHORTDOUBLE: return TYPE(&stshortdouble); + case ATOM_DOUBLE: return TYPE(&stdouble); + case ATOM_LONGDOUBLE: return TYPE(&stlongdouble); + } +} + +Object *CParser_FindDeallocationObject(Type *type, FuncArg *args, Boolean flag1, Boolean flag2, Boolean *outflag) { + NameSpaceObjectList *list; + NameSpaceObjectList *scan; + NameSpaceObjectList mylist; + NameResult pr; + Boolean first_time; + Boolean retry_flag; + Object *obj; + Type *sizet; + + list = NULL; + *outflag = 0; + if (IS_TYPE_CLASS(type) && !flag2) { + HashNameNode *name; + name = (flag1 && copts.array_new_delete) ? dela_fobj->name : delp_fobj->name; + if (CScope_FindClassMemberObject(TYPE_CLASS(type), &pr, name)) { + if (pr.obj_10) { + mylist.next = NULL; + mylist.object = pr.obj_10; + list = &mylist; + } else { + CError_ASSERT(1202, pr.nsol_14); + list = pr.nsol_14; + } + } else if (TYPE_CLASS(type)->flags & CLASS_HANDLEOBJECT) { + CError_ASSERT(1210, !args && !flag1); + return delh_func; + } + } + + first_time = 1; + retry_flag = flag1; + while (1) { + if (!args) { + for (scan = list; scan; scan = scan->next) { + obj = OBJECT(scan->object); + if ( + obj->otype == OT_OBJECT && + IS_TYPE_FUNC(obj->type) && + TYPE_FUNC(obj->type)->args && + !TYPE_FUNC(obj->type)->args->next && + is_typesame(TYPE_FUNC(obj->type)->args->type, TYPE(&void_ptr)) + ) + return obj; + } + + CError_ASSERT(1231, first_time); + + sizet = CABI_GetSizeTType(); + for (scan = list; scan; scan = scan->next) { + obj = OBJECT(scan->object); + if ( + obj->otype == OT_OBJECT && + IS_TYPE_FUNC(obj->type) && + TYPE_FUNC(obj->type)->args && + TYPE_FUNC(obj->type)->args->next && + !TYPE_FUNC(obj->type)->args->next->next && + is_typesame(TYPE_FUNC(obj->type)->args->type, TYPE(&void_ptr)) && + TYPE_FUNC(obj->type)->args->next->type == sizet + ) { + *outflag = 1; + return obj; + } + } + } else { + for (scan = list; scan; scan = scan->next) { + obj = OBJECT(scan->object); + if ( + obj->otype == OT_OBJECT && + IS_TYPE_FUNC(obj->type) && + TYPE_FUNC(obj->type)->args && + TYPE_FUNC(obj->type)->args->next && + is_arglistsame(TYPE_FUNC(obj->type)->args->next, args) + ) { + *outflag = 1; + return obj; + } + } + + if (!first_time) + return NULL; + } + + if (list) + CError_Warning(CErrorStr375, type, 0); + + list = (retry_flag && copts.array_new_delete) ? &dela_fobj->first : &delp_fobj->first; + first_time = 0; + } +} + +static Boolean oldstylecompatible(FuncArg *arg) { + if (copts.ignore_oldstyle) + return 1; + + while (arg) { + if (arg == &elipsis) + return 0; + switch (arg->type->type) { + case TYPEINT: + if (TYPE_INTEGRAL(arg->type)->integral < IT_INT) + return 0; + break; + case TYPEFLOAT: + if (TYPE_INTEGRAL(arg->type)->integral < IT_DOUBLE) + return 0; + break; + } + arg = arg->next; + } + + return 1; +} + +static Boolean is_arglistequal(FuncArg *a, FuncArg *b) { + if (a == &oldstyle) { + if (b == &oldstyle) + return 1; + else + return oldstylecompatible(b); + } else { + if (b == &oldstyle) + return oldstylecompatible(a); + } + + while (1) { + if (a == &elipsis || b == &elipsis) + return 1; + + if (!a) + return !b; + if (!b) + return 0; + + if (copts.mpwc_relax && !copts.cplusplus) { + if (!is_typeequal(a->type, b->type)) + return 0; + } else { + if (!is_typesame(a->type, b->type)) + return 0; + } + + if (a->type->type == TYPEPOINTER && a->qual != b->qual) + return 0; + + a = a->next; + b = b->next; + } +} + +short is_memberpointerequal(Type *a, Type *b) { + FuncArg *arg_a; + FuncArg *arg_b; + + if (a->type != b->type) + return 0; + if (!IS_TYPE_FUNC(a)) + return is_typeequal(a, b); + + if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) + return 0; + + if ((TYPE_FUNC(a)->flags & FUNC_CALL_CONV_MASK) != (TYPE_FUNC(b)->flags & FUNC_CALL_CONV_MASK)) + return 0; + + CError_ASSERT(1345, arg_a = TYPE_FUNC(a)->args); + CError_ASSERT(1346, arg_b = TYPE_FUNC(b)->args); + + if (TYPE_FUNC(a)->flags & FUNC_FLAGS_80) + CError_ASSERT(1351, arg_a = arg_a->next); + + if (TYPE_FUNC(b)->flags & FUNC_FLAGS_80) + CError_ASSERT(1355, arg_b = arg_b->next); + + if (arg_a->qual != arg_b->qual) + return 0; + + return is_arglistsame(arg_a->next, arg_b->next); +} + +short is_typeequal(Type *a, Type *b) { +restart: + if (a->type != b->type) + return 0; + switch (a->type) { + case TYPEVOID: + return 1; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPECLASS: + return a == b; + case TYPESTRUCT: + return a == b; + case TYPEPOINTER: + if (TYPE_POINTER(a)->target == &stvoid || TYPE_POINTER(b)->target == &stvoid) + return 1; + a = TYPE_POINTER(a)->target; + b = TYPE_POINTER(b)->target; + if (copts.mpwc_relax && !copts.cplusplus) + return 1; + goto restart; + case TYPEMEMBERPOINTER: + if (TYPE_MEMBER_POINTER(a)->ty2 != TYPE_MEMBER_POINTER(b)->ty2) + return 0; + return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1); + case TYPEARRAY: + if (a->size && b->size && a->size != b->size) + return 0; + a = TYPE_POINTER(a)->target; + b = TYPE_POINTER(b)->target; + goto restart; + case TYPEFUNC: + if (copts.cplusplus || !copts.cpp_extensions) { + if (copts.mpwc_relax && !copts.cplusplus) { + if (!is_typeequal(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) + return 0; + } else { + if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) + return 0; + } + if ((TYPE_FUNC(a)->flags & FUNC_CALL_CONV_MASK) != (TYPE_FUNC(b)->flags & FUNC_CALL_CONV_MASK)) + return 0; + } + return is_arglistequal(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args); + case TYPETEMPLATE: + return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b)); + default: + CError_FATAL(1441); + return 0; + } +} + +short iscpp_typeequal(Type *a, Type *b) { + restart: + if (a->type != b->type) + return 0; + switch (a->type) { + case TYPEVOID: + return 1; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPECLASS: + return a == b; + case TYPESTRUCT: + return a == b; + case TYPEPOINTER: + if (TYPE_POINTER(b)->target == &stvoid) { + if (TYPE_POINTER(a)->target == &stvoid) + return 1; + else + return -1; + } + if (TYPE_POINTER(a)->target == &stvoid) { + illegalimplicitconversion = 1; + return 0; + } + a = TYPE_POINTER(a)->target; + b = TYPE_POINTER(b)->target; + goto restart; + case TYPEMEMBERPOINTER: + if (TYPE_MEMBER_POINTER(a)->ty2 != TYPE_MEMBER_POINTER(b)->ty2) + return 0; + return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1); + case TYPEARRAY: + if (a->size && b->size && a->size != b->size) + return 0; + a = TYPE_POINTER(a)->target; + b = TYPE_POINTER(b)->target; + goto restart; + case TYPEFUNC: + if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) + return 0; + if ((TYPE_FUNC(a)->flags & FUNC_CALL_CONV_MASK) != (TYPE_FUNC(b)->flags & FUNC_CALL_CONV_MASK)) + return 0; + return is_arglistequal(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args); + case TYPETEMPLATE: + return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b)); + default: + CError_FATAL(1500); + return 0; + } +} + +short CParser_CompareArgLists(FuncArg *a, FuncArg *b) { + Boolean r30; + + r30 = 0; + if (a == &oldstyle) { + if (b == &oldstyle) + return 1; + else + return 2; + } + if (b == &oldstyle) + return 2; + + while (1) { + if (a == &elipsis) { + if (b != &elipsis) + return 0; + break; + } + if (b == &elipsis) + return 0; + + if (a == NULL) { + if (b) + return 0; + break; + } + if (b == NULL) + return 0; + + if (a->type->type == TYPEPOINTER) { + if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(a->type))) { + if (IS_TYPE_REFERENCE(b->type)) { + if (!is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target)) + return 0; + if ((a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE))) + return 0; + } else { + if (!copts.old_argmatch) + return 0; + if (!is_typesame(TYPE_POINTER(a->type)->target, b->type)) + return 0; + if (b->type->type == TYPEPOINTER && (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE))) + return 0; + r30 = 1; + } + } else { + if (b->type->type == TYPEPOINTER) { + if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type))) { + if (!copts.old_argmatch) + return 0; + if (!is_typesame(a->type, TYPE_POINTER(b->type)->target)) + return 0; + if (a->type->type == TYPEPOINTER && (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE))) + return 0; + r30 = 1; + } else { + if (!is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target)) + return 0; + if ((a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE))) + return 0; + } + } else { + return 0; + } + } + } else { + if (b->type->type == TYPEPOINTER) { + if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type))) { + if (!copts.old_argmatch) + return 0; + if (!is_typesame(a->type, TYPE_POINTER(b->type)->target)) + return 0; + r30 = 1; + } else { + return 0; + } + } else { + if (!is_typesame(a->type, b->type)) + return 0; + } + } + + a = a->next; + b = b->next; + } + + if (r30) + return 2; + return 1; +} + +Boolean is_arglistsame(FuncArg *a, FuncArg *b) { + if (a == &oldstyle) { + if (b == &oldstyle) + return 1; + else + return oldstylecompatible(b); + } else { + if (b == &oldstyle) + return oldstylecompatible(a); + } + + while (1) { + if (!a || !b || a == &elipsis || b == &elipsis) + return a == b; + + if (a->type->type == TYPEPOINTER) { + if (b->type->type != TYPEPOINTER || + (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE)) || + !is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target) || + IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(a->type)) != IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type))) + return 0; + } else { + if (!is_typesame(a->type, b->type)) + return 0; + } + + a = a->next; + b = b->next; + } +} + +short is_typesame(Type *a, Type *b) { +restart: + if (a->type != b->type) { + if (IS_TYPE_TEMPLATE(a) && IS_TYPE_CLASS(b) && (TYPE_CLASS(b)->flags & CLASS_IS_TEMPL)) + return CTemplTool_IsSameTemplateType(b, a); + if (IS_TYPE_TEMPLATE(b) && IS_TYPE_CLASS(a) && (TYPE_CLASS(a)->flags & CLASS_IS_TEMPL)) + return CTemplTool_IsSameTemplateType(a, b); + return 0; + } + + switch (a->type) { + case TYPEVOID: + return 1; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPECLASS: + return a == b; + case TYPETEMPLATE: + return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b)); + case TYPESTRUCT: + return a == b; + case TYPEPOINTER: + if ((TYPE_POINTER(a)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE)) != (TYPE_POINTER(b)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE))) + return 0; + a = TYPE_POINTER(a)->target; + b = TYPE_POINTER(b)->target; + goto restart; + case TYPEMEMBERPOINTER: + if (!is_typesame(TYPE_MEMBER_POINTER(a)->ty2, TYPE_MEMBER_POINTER(b)->ty2)) + return 0; + if ((TYPE_MEMBER_POINTER(a)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE)) != (TYPE_MEMBER_POINTER(b)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE))) + return 0; + return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1); + case TYPEARRAY: + if (a->size != b->size) + return 0; + a = TYPE_POINTER(a)->target; + b = TYPE_POINTER(b)->target; + goto restart; + case TYPEFUNC: + if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) + return 0; + if (TYPE_FUNC(a)->qual != TYPE_FUNC(b)->qual) + return 0; + if ((TYPE_FUNC(a)->flags & FUNC_CALL_CONV_MASK) != (TYPE_FUNC(b)->flags & FUNC_CALL_CONV_MASK)) + return 0; + return is_arglistsame(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args); + default: + CError_FATAL(1709); + return 0; + } +} + +Type *CParser_GetBoolType(void) { + if (copts.cplusplus && copts.booltruefalse) + return TYPE(&stbool); + else + return TYPE(&stsignedint); +} + +Type *CParser_GetWCharType(void) { + if (copts.cplusplus && copts.wchar_type) + return TYPE(&stwchar); + else + return TYPE(&stsignedint); +} + +short CParser_GetOperator(ENodeType t) { + switch (t) { + default: + CError_FATAL(1748); + case EMONMIN: return '-'; + case EBINNOT: return '~'; + case ELOGNOT: return '!'; + case EADD: return '+'; + case ESUB: return '-'; + case EMUL: return '*'; + case EDIV: return '/'; + case EMODULO: return '%'; + case EAND: return '&'; + case EXOR: return '^'; + case EOR: return '|'; + case ESHL: return TK_SHL; + case ESHR: return TK_SHR; + case ELESS: return '<'; + case EGREATER: return '>'; + case ELESSEQU: return TK_LESS_EQUAL; + case EGREATEREQU: return TK_GREATER_EQUAL; + case EEQU: return TK_LOGICAL_EQ; + case ENOTEQU: return TK_LOGICAL_NE; + } +} + +Boolean CParser_IsMoreCVQualified(UInt32 a, UInt32 b) { + if ((a & Q_CONST) && !(b & Q_CONST)) { + return ((a & Q_VOLATILE) || !(b & Q_VOLATILE)); + } else if ((a & Q_VOLATILE) && !(b & Q_VOLATILE)) { + return ((a & Q_CONST) || !(b & Q_CONST)); + } + return 0; +} + +Boolean CParser_IsSameOrMoreCVQualified(UInt32 a, UInt32 b) { + if ((a & (Q_CONST | Q_VOLATILE)) == (b & (Q_CONST | Q_VOLATILE))) + return 1; + + if ((a & Q_CONST) && !(b & Q_CONST)) { + return ((a & Q_VOLATILE) || !(b & Q_VOLATILE)); + } else if ((a & Q_VOLATILE) && !(b & Q_VOLATILE)) { + return ((a & Q_CONST) || !(b & Q_CONST)); + } + return 0; +} + +Boolean is_unsigned(Type *type) { + if (IS_TYPE_ENUM(type)) + type = TYPE_ENUM(type)->enumtype; + + if ( + (type == TYPE(&stunsignedchar)) || + (type == TYPE(&stunsignedshort)) || + (type == TYPE(&stunsignedint)) || + (type == TYPE(&stunsignedlong)) || + (type == TYPE(&stunsignedlonglong)) || + (type == TYPE(&stbool)) || + (copts.unsigned_char && (type == TYPE(&stchar))) || + (type->type == TYPEPOINTER)) + return 1; + + return 0; +} + +StructMember *ismember(TypeStruct *tstruct, HashNameNode *name) { + StructMember *member; + + for (member = tstruct->members; member; member = member->next) { + if (member->name == name) + return member; + } + + return NULL; +} + +void appendmember(TypeStruct *tstruct, StructMember *member) { + StructMember *last; + + if (!tstruct->members) { + tstruct->members = member; + return; + } + + for (last = tstruct->members; last->next; last = last->next) {} + last->next = member; +} + +static void CParser_InsertTryBlock(ParserTryBlock *block) { + block->cscope_current = cscope_current; + block->cscope_currentclass = cscope_currentclass; + block->cscope_currentfunc = cscope_currentfunc; + block->ctempl_curinstance = ctempl_curinstance; + block->cerror_locktoken = cerror_locktoken; + block->cscope_is_member_func = cscope_is_member_func; + block->next = trychain; + trychain = block; +} + +static void CParser_RemoveTryBlock(ParserTryBlock *block) { + cscope_current = block->cscope_current; + cscope_currentclass = block->cscope_currentclass; + cscope_currentfunc = block->cscope_currentfunc; + ctempl_curinstance = block->ctempl_curinstance; + cerror_locktoken = block->cerror_locktoken; + cscope_is_member_func = block->cscope_is_member_func; + trychain = block->next; +} + +static Boolean TryIsDeclaration(Boolean flag1, Boolean flag2, Boolean flag3, short token) { + Boolean result; + DeclInfo declinfo; + struct ParserTryBlock tryblock; + + switch (tk) { + case TK_IDENTIFIER: + case TK_COLON_COLON: + break; + case TK_VOID: + case TK_CHAR: + case TK_SHORT: + case TK_INT: + case TK_LONG: + case TK_FLOAT: + case TK_DOUBLE: + case TK_SIGNED: + case TK_UNSIGNED: + case TK_UNK_113: + case TK_UNK_114: + case TK_UNK_115: + case TK_UNK_116: + case TK_UNK_117: + case TK_UNK_118: + case TK_UNK_119: + case TK_UNK_11A: + case TK_BOOL: + case TK_WCHAR_T: + if (lookahead() != '(') + return 1; + break; + default: + return 1; + } + + result = 0; + CParser_InsertTryBlock(&tryblock); + if (setjmp(tryblock.jmpbuf) == 0) { + memclrw(&declinfo, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&declinfo, 0); + if (!(IS_TYPE_TEMPLATE(declinfo.thetype) && TYPE_TEMPLATE(declinfo.thetype)->dtype == TEMPLDEP_QUALNAME && !declinfo.x53 && !declinfo.x49)) { + if (flag1) { + declinfo.x46 = flag3; + scandeclarator(&declinfo); + if (!(flag2 && declinfo.name)) { + if (!token) { + if (tk == ';' || tk == ',' || tk == '=' || tk == '(' || tk == ')' || tk == '>') + result = 1; + } else { + result = (tk == token); + } + } + } else { + result = 1; + } + } + } + + CParser_RemoveTryBlock(&tryblock); + return result; +} + +Boolean isdeclaration(UInt8 flag1, UInt8 flag2, UInt8 flag3, short token) { + SInt32 state; + + if (!(tk >= TK_AUTO && tk <= TK_BYREF) && tk != TK_COLON_COLON && !(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) { + if (!(tk == TK_IDENTIFIER && copts.altivec_model && !strcmp(tkidentifier->name, "vector"))) + return 0; + } else { + if (!copts.cplusplus) + return 1; + } + + CPrep_TokenStreamGetState(&state); + if (TryIsDeclaration(flag1, flag2, flag3, token)) { + CPrep_TokenStreamSetCurState(&state); + return 1; + } else { + CPrep_TokenStreamSetCurState(&state); + return 0; + } +} + +Boolean islookaheaddeclaration(void) { + SInt32 state; + + CPrep_TokenStreamGetState(&state); + tk = lex(); + if (!(tk >= TK_AUTO && tk <= TK_BYREF) && tk != TK_COLON_COLON && !(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) { + if (!(tk == TK_IDENTIFIER && copts.altivec_model && !strcmp(tkidentifier->name, "vector"))) { + CPrep_TokenStreamSetCurState(&state); + return 0; + } + } else { + if (!copts.cplusplus) { + CPrep_TokenStreamSetCurState(&state); + return 1; + } + } + + if (TryIsDeclaration(1, 1, 0, ')')) { + CPrep_TokenStreamSetCurState(&state); + return 1; + } else { + CPrep_TokenStreamSetCurState(&state); + return 0; + } +} + +Type *CParser_ParseTypeID(UInt32 *qual, Boolean *flag) { + SInt32 state; + DeclInfo di; + struct ParserTryBlock tryblock; + + memclrw(&di, sizeof(DeclInfo)); + CPrep_TokenStreamGetState(&state); + CParser_InsertTryBlock(&tryblock); + + if (setjmp(tryblock.jmpbuf) == 0) { + if (copts.cplusplus) + di.x55 = 1; + + if (flag) { + di.x56 = 1; + *flag = 0; + } + + CParser_GetDeclSpecs(&di, 0); + if (di.x57 && IS_TYPE_CLASS(di.thetype) && (TYPE_CLASS(di.thetype)->flags & CLASS_IS_TEMPL)) { + CParser_RemoveTryBlock(&tryblock); + *qual = di.qual; + *flag = 1; + return di.thetype; + } + + if (flag && IS_TYPE_TEMPLATE(di.thetype) && TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_ARGUMENT && + TYPE_TEMPLATE(di.thetype)->u.pid.type == TPT_TEMPLATE) { + CParser_RemoveTryBlock(&tryblock); + *qual = di.qual; + *flag = 1; + return di.thetype; + } + + scandeclarator(&di); + if (!di.name) { + CParser_RemoveTryBlock(&tryblock); + *qual = di.qual; + return di.thetype; + } + } + + CPrep_TokenStreamSetCurState(&state); + CParser_RemoveTryBlock(&tryblock); + return 0; +} + +Boolean CParser_TryFuncDecl(void) { + Boolean result; + SInt32 state; + DeclInfo di; + struct ParserTryBlock tryblock; + + result = 0; + CPrep_TokenStreamGetState(&state); + CParser_InsertTryBlock(&tryblock); + + if (setjmp(tryblock.jmpbuf) == 0) { + memclrw(&di, sizeof(DeclInfo)); + di.thetype = &stvoid; + scandeclarator(&di); + + if (IS_TYPE_FUNC(di.thetype)) + result = 1; + } + + CParser_RemoveTryBlock(&tryblock); + CPrep_TokenStreamSetCurState(&state); + return result; +} + +Boolean CParser_TryParamList(Boolean flag) { + Boolean result; + SInt32 state; + struct ParserTryBlock tryblock; + + result = 0; + CPrep_TokenStreamGetState(&state); + + switch ((tk = lex())) { + case ')': + case TK_ELLIPSIS: + result = 1; + break; + default: + CParser_InsertTryBlock(&tryblock); + if (setjmp(tryblock.jmpbuf) == 0) { + if (CFunc_ParseFakeArgList(flag) || tk == ')') + result = 1; + } + CParser_RemoveTryBlock(&tryblock); + break; + } + + CPrep_TokenStreamSetCurState(&state); + return result; +} + +Type *CParser_RemoveTopMostQualifiers(Type *type, UInt32 *qual) { + switch (type->type) { + case TYPEARRAY: + TYPE_POINTER(type)->target = CParser_RemoveTopMostQualifiers(TYPE_POINTER(type)->target, qual); + return type; + case TYPEPOINTER: + if (TYPE_POINTER(type)->qual & Q_CONST) { + TypePointer *newtype = galloc(sizeof(TypePointer)); + *newtype = *TYPE_POINTER(type); + newtype->qual = 0; + return TYPE(newtype); + } + return type; + case TYPEMEMBERPOINTER: + if (TYPE_MEMBER_POINTER(type)->qual & Q_CONST) { + TypeMemberPointer *newtype = galloc(sizeof(TypeMemberPointer)); + *newtype = *TYPE_MEMBER_POINTER(type); + newtype->qual = 0; + return TYPE(newtype); + } + return type; + default: + *qual = 0; + return type; + } +} + +UInt32 CParser_GetTypeQualifiers(Type *type, UInt32 qual) { + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + + switch (type->type) { + case TYPEPOINTER: + qual = TYPE_POINTER(type)->qual; + break; + case TYPEMEMBERPOINTER: + qual = TYPE_MEMBER_POINTER(type)->qual; + break; + } + + return qual; +} + +UInt32 CParser_GetCVTypeQualifiers(Type *type, UInt32 qual) { + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + + switch (type->type) { + case TYPEPOINTER: + qual = TYPE_POINTER(type)->qual; + break; + case TYPEMEMBERPOINTER: + qual = TYPE_MEMBER_POINTER(type)->qual; + break; + } + + return qual & (Q_CONST | Q_VOLATILE); +} + +Boolean CParser_IsConst(Type *type, UInt32 qual) { + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + + switch (type->type) { + case TYPEPOINTER: + qual = TYPE_POINTER(type)->qual; + break; + case TYPEMEMBERPOINTER: + qual = TYPE_MEMBER_POINTER(type)->qual; + break; + } + + return (qual & Q_CONST) != 0; +} + +Boolean CParser_IsVolatile(Type *type, UInt32 qual) { + while (IS_TYPE_ARRAY(type)) + type = TYPE_POINTER(type)->target; + + switch (type->type) { + case TYPEPOINTER: + qual = TYPE_POINTER(type)->qual; + break; + case TYPEMEMBERPOINTER: + qual = TYPE_MEMBER_POINTER(type)->qual; + break; + } + + return (qual & Q_VOLATILE) != 0; +} + +Boolean is_const_object(Object *obj) { + return CParser_IsConst(obj->type, obj->qual); +} + +Boolean is_volatile_object(Object *obj) { + return CParser_IsVolatile(obj->type, obj->qual); +} + +Boolean CParserIsConstExpr(ENode *expr) { + return CParser_IsConst(expr->rtype, expr->flags & ENODE_FLAG_QUALS); +} + +Boolean CParserIsVolatileExpr(ENode *expr) { + return CParser_IsVolatile(expr->rtype, expr->flags & ENODE_FLAG_QUALS); +} + +Boolean CParser_HasInternalLinkage(const Object *obj) { + NameSpace *nspace; + + for (nspace = obj->nspace; nspace; nspace = nspace->parent) { + if (nspace->is_unnamed) + return 1; + } + + if (obj->datatype == DLOCAL) + return 1; + if (obj->qual & (Q_20000 | Q_WEAK)) + return 0; + if (obj->sclass == TK_STATIC) + return 1; + + // this feels *wrong* but it's the only way to match this function that I can see + if (obj->qual & Q_INLINE) + ((Object *) obj)->qual |= Q_20000; + return 0; +} + +Boolean CParser_HasInternalLinkage2(const Object *obj) { + if (obj->datatype == DLOCAL) + return 1; + if (obj->qual & (Q_20000 | Q_WEAK)) + return 0; + if (obj->sclass == TK_STATIC) + return 1; + + // this feels *wrong* but it's the only way to match this function that I can see + if (obj->qual & Q_INLINE) + ((Object *) obj)->qual |= Q_20000; + return 0; +} + +Boolean CParser_IsVirtualFunction(Object *obj, TypeClass **tclass, SInt32 *index) { + if (obj->datatype == DVFUNC) { + *tclass = TYPE_METHOD(obj->type)->theclass; + *index = TYPE_METHOD(obj->type)->vtbl_index; + return 1; + } + + return 0; +} + +Boolean is_pascal_object(Object *obj) { + return IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_PASCAL); +} + +Boolean is_cfm_type(Type *type) { + return 0; +} + +Boolean CParser_IsVTableObject(Object *obj) { + return + obj->datatype == DDATA && + obj->nspace && + obj->nspace->theclass && + obj->nspace->theclass->vtable && + obj->nspace->theclass->vtable->object == obj; +} + +static Type *getthetype(short token, short size, short signedness) { + switch (token) { + case 0: + case TK_INT: + if (signedness == 1) { + switch (size) { + case 1: return TYPE(&stunsignedshort); + case 2: return TYPE(&stunsignedlong); + case 3: return TYPE(&stunsignedlonglong); + default: return TYPE(&stunsignedint); + } + } else { + switch (size) { + case 1: return TYPE(&stsignedshort); + case 2: return TYPE(&stsignedlong); + case 3: return TYPE(&stsignedlonglong); + default: return TYPE(&stsignedint); + } + } + case TK_BOOL: + return TYPE(&stbool); + case TK_WCHAR_T: + return TYPE(&stwchar); + case TK_CHAR: + switch (signedness) { + case 1: return TYPE(&stunsignedchar); + default: return TYPE(&stchar); + case -1: return TYPE(&stsignedchar); + } + case TK_DOUBLE: + switch (size) { + case 1: return TYPE(&stshortdouble); + case 2: return TYPE(&stlongdouble); + default: return TYPE(&stdouble); + } + case TK_FLOAT: + return TYPE(&stfloat); + case TK_VOID: + return TYPE(&stvoid); + default: + CError_Error(CErrorStr121); + return TYPE(&stvoid); + } +} + +void TypedefDeclInfo(DeclInfo *declinfo, Type *type, UInt32 qual) { + if (type->type == TYPEPOINTER) { + if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(type))) { + declinfo->thetype = type; + declinfo->qual &= ~(Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); + declinfo->qual |= qual; + return; + } + + declinfo->thetype = galloc(sizeof(TypePointer)); + *TYPE_POINTER(declinfo->thetype) = *TYPE_POINTER(type); + TYPE_POINTER(declinfo->thetype)->qual |= declinfo->qual & (Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); + declinfo->qual &= ~(Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); + declinfo->qual |= qual & (Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST); + } else if (type->type == TYPEMEMBERPOINTER) { + declinfo->thetype = galloc(sizeof(TypeMemberPointer)); + *TYPE_MEMBER_POINTER(declinfo->thetype) = *TYPE_MEMBER_POINTER(type); + TYPE_MEMBER_POINTER(declinfo->thetype)->qual |= declinfo->qual & (Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); + declinfo->qual &= ~(Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); + declinfo->qual |= qual & (Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST); + } else { + declinfo->thetype = type; + declinfo->qual |= qual & (Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST); + if (IS_TYPE_ARRAY(declinfo->thetype) && !declinfo->thetype->size) { + declinfo->thetype = galloc(sizeof(TypePointer)); + *TYPE_POINTER(declinfo->thetype) = *TYPE_POINTER(type); + } + } + declinfo->x49 = 1; +} + +static void CParser_ParseAttributeFunctionSummary(DeclInfo *declinfo) { + Boolean flag; + + if ((tk = lex()) != '(') { + CError_Error(CErrorStr114); + return; + } + + flag = 1; + tk = lookahead(); + while (tk == TK_IDENTIFIER) { + if (flag && !strcmp(tkidentifier->name, "entry_points_to")) { + PointerAnalysis_ParseEntryPointsToSpecifier(declinfo); + } else if (!strcmp(tkidentifier->name, "exit_points_to")) { + PointerAnalysis_ParseExitPointsToSpecifier(declinfo); + flag = 0; + } else if (!strcmp(tkidentifier->name, "function_modifies")) { + PointerAnalysis_ParseFunctionModifiesSpecifier(declinfo); + flag = 0; + } else { + lex(); + CError_Error(CErrorStr121); + return; + } + + tk = lookahead(); + if (tk == ',') { + lex(); + tk = lookahead(); + } + } + + lex(); + if (tk != ')') + CError_Error(CErrorStr121); +} + +void CParser_ParseAttribute(Type *type, DeclInfo *declinfo) { + CInt64 val64; + SInt32 val; + + do { + if ((tk = lex()) != '(') { + CError_Error(CErrorStr121); + return; + } + if ((tk = lex()) != '(') { + CError_Error(CErrorStr121); + return; + } + if ((tk = lex()) != TK_IDENTIFIER && tk != TK_CONST) { + CError_Error(CErrorStr121); + return; + } + + if (!strcmp(tkidentifier->name, "aligned") || !strcmp(tkidentifier->name, "__aligned__")) { + if ((tk = lex()) != '(') { + CError_Error(CErrorStr121); + return; + } + + tk = lex(); + val64 = CExpr_IntegralConstExpr(); + switch ((val = CInt64_GetULong(&val64))) { + case 1: + case 2: + case 4: + case 8: + case 0x10: + case 0x20: + case 0x40: + case 0x80: + case 0x100: + case 0x200: + case 0x400: + case 0x800: + case 0x1000: + case 0x2000: + break; + default: + CError_Error(CErrorStr124); + return; + } + if (type) { + if (IS_TYPE_STRUCT(type)) { + if (val > TYPE_STRUCT(type)->align) { + TYPE_STRUCT(type)->align = val; + type->size += CABI_StructSizeAlignValue(type, type->size); + } + } else if (IS_TYPE_CLASS(type)) { + if (val > TYPE_CLASS(type)->align) { + TYPE_CLASS(type)->align = val; + type->size += CABI_StructSizeAlignValue(type, type->size); + } + } else { + CError_Error(CErrorStr149); + } + } else if (declinfo) { + declinfo->qual &= ~Q_ALIGNED_MASK; + switch (val) { + case 1: + declinfo->qual |= Q_ALIGNED_1; + break; + case 2: + declinfo->qual |= Q_ALIGNED_2; + break; + case 4: + declinfo->qual |= Q_ALIGNED_4; + break; + case 8: + declinfo->qual |= Q_ALIGNED_8; + break; + case 16: + declinfo->qual |= Q_ALIGNED_16; + break; + case 32: + declinfo->qual |= Q_ALIGNED_32; + break; + case 64: + declinfo->qual |= Q_ALIGNED_64; + break; + case 128: + declinfo->qual |= Q_ALIGNED_128; + break; + case 256: + declinfo->qual |= Q_ALIGNED_256; + break; + case 512: + declinfo->qual |= Q_ALIGNED_512; + break; + case 1024: + declinfo->qual |= Q_ALIGNED_1024; + break; + case 2048: + declinfo->qual |= Q_ALIGNED_2048; + break; + case 4096: + declinfo->qual |= Q_ALIGNED_4096; + break; + case 8192: + declinfo->qual |= Q_ALIGNED_8192; + break; + default: + CError_FATAL(2779); + break; + } + } else { + CError_Error(CErrorStr359); + } + + if (tk != ')') { + CError_Error(CErrorStr121); + return; + } + } else if (!strcmp(tkidentifier->name, "nothrow") || !strcmp(tkidentifier->name, "__nothrow__")) { + if (declinfo && declinfo->thetype && IS_TYPE_FUNC(declinfo->thetype)) + TYPE_FUNC(declinfo->thetype)->flags |= FUNC_NOTHROW; + else + CError_Error(CErrorStr359); + } else if (!strcmp("function_summary", tkidentifier->name)) { + CParser_ParseAttributeFunctionSummary(declinfo); + } else if (!strcmp(tkidentifier->name, "packed") || !strcmp(tkidentifier->name, "__packed__")) { + CError_Error(CErrorStr359); + } else if (!strcmp(tkidentifier->name, "unused") || !strcmp(tkidentifier->name, "__unused__")) { + } else if (!strcmp(tkidentifier->name, "noreturn") || !strcmp(tkidentifier->name, "__noreturn__")) { + } else if (tk == TK_CONST || !strcmp(tkidentifier->name, "__const__")) { + } else if (!strcmp(tkidentifier->name, "format") || !strcmp(tkidentifier->name, "__format__")) { + CError_Warning(CErrorStr359); + if ((tk = lex()) != '(') { + CError_Warning(CErrorStr114); + return; + } + tk = lex(); + if ((tk = lex()) != ',') { + CError_Warning(CErrorStr116); + return; + } + tk = lex(); + if ((tk = lex()) != ',') { + CError_Warning(CErrorStr116); + return; + } + tk = lex(); + if ((tk = lex()) != ')') { + CError_Warning(CErrorStr115); + return; + } + } else if (!strcmp(tkidentifier->name, "mode") || !strcmp(tkidentifier->name, "__mode__")) { + CError_Warning(CErrorStr359); + if ((tk = lex()) != '(') { + CError_Warning(CErrorStr114); + return; + } + tk = lex(); + if ((tk = lex()) != ')') { + CError_Warning(CErrorStr115); + return; + } + } else { + CError_Error(CErrorStr359); + } + + if ((tk = lex()) != ')') { + CError_Error(CErrorStr121); + return; + } + if ((tk = lex()) != ')') { + CError_Error(CErrorStr121); + return; + } + tk = lex(); + } while (tk == TK_UU_ATTRIBUTE_UU); +} + +static void CParser_ParseTypeOf(DeclInfo *declinfo) { + DeclInfo subdi; + ENode *expr; + + if ((tk = lex()) == '(' && islookaheaddeclaration()) { + tk = lex(); + + memclrw(&subdi, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&subdi, 0); + scandeclarator(&subdi); + if (subdi.name) + CError_Error(CErrorStr121); + + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + + TypedefDeclInfo(declinfo, subdi.thetype, subdi.qual); + } else { + expr = unary_expression(); + if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EBITFIELD)) + CError_Error(CErrorStr144); + TypedefDeclInfo(declinfo, expr->rtype, expr->flags & ENODE_FLAG_QUALS); + } +} + +void CParser_ParseDeclSpec(DeclInfo *declinfo, Boolean flag) { + if ((tk = lex()) != TK_IDENTIFIER) { + if (tk != TK_EXPORT) + CError_Error(CErrorStr107); + else + declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_EXPORT; + } else if (!strcmp("internal", tkidentifier->name)) { + declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_INTERNAL; + } else if (!strcmp("import", tkidentifier->name) || !strcmp("dllimport", tkidentifier->name)) { + declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_IMPORT; + } else if (!strcmp("export", tkidentifier->name) || !strcmp("dllexport", tkidentifier->name)) { + declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_EXPORT; + } else if (!strcmp("lib_export", tkidentifier->name)) { + declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_IMPORT | EXPORT_FLAGS_EXPORT; + } else if (!strcmp("weak", tkidentifier->name)) { + declinfo->qual |= Q_WEAK; + } else { + CodeGen_ParseDeclSpec(tkidentifier, declinfo); + } +} + +static int CParser_GetVectorDeclSpec(Type **type) { + tk = lex(); + switch (tk) { + case TK_CHAR: + tk = lex(); + switch (tk) { + case TK_BOOL: + *type = TYPE(&stvectorboolchar); + tk = lex(); + return 1; + case TK_UNSIGNED: + *type = TYPE(&stvectorunsignedchar); + tk = lex(); + return 1; + case TK_SIGNED: + *type = TYPE(&stvectorsignedchar); + tk = lex(); + return 1; + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("bool")) { + *type = TYPE(&stvectorboolchar); + tk = lex(); + return 1; + } + default: + CError_Error(CErrorStr121); + } + break; + case TK_SIGNED: + tk = lex(); + switch (tk) { + case TK_CHAR: + *type = TYPE(&stvectorsignedchar); + tk = lex(); + return 1; + case TK_SHORT: + *type = TYPE(&stvectorsignedshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorsignedlong); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_INT: + tk = lex(); + switch (tk) { + case TK_SHORT: + *type = TYPE(&stvectorsignedshort); + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorsignedlong); + tk = lex(); + return 1; + default: + *type = TYPE(&stvectorsignedlong); + return 1; + } + default: + CError_Error(CErrorStr121); + } + break; + case TK_UNSIGNED: + tk = lex(); + switch (tk) { + case TK_CHAR: + *type = TYPE(&stvectorunsignedchar); + tk = lex(); + return 1; + case TK_SHORT: + *type = TYPE(&stvectorunsignedshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorunsignedlong); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_INT: + tk = lex(); + switch (tk) { + case TK_SHORT: + *type = TYPE(&stvectorunsignedshort); + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorunsignedlong); + tk = lex(); + return 1; + default: + *type = TYPE(&stvectorunsignedlong); + return 1; + } + default: + CError_Error(CErrorStr121); + } + break; + case TK_BOOL: + tk = lex(); + switch (tk) { + case TK_CHAR: + *type = TYPE(&stvectorboolchar); + tk = lex(); + return 1; + case TK_SHORT: + *type = TYPE(&stvectorboolshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorboollong); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_INT: + tk = lex(); + switch (tk) { + case TK_SHORT: + *type = TYPE(&stvectorboolshort); + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorboollong); + tk = lex(); + return 1; + default: + *type = TYPE(&stvectorboollong); + return 1; + } + default: + CError_Error(CErrorStr121); + } + break; + case TK_SHORT: + tk = lex(); + switch (tk) { + case TK_BOOL: + *type = TYPE(&stvectorboolshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_SIGNED: + *type = TYPE(&stvectorsignedshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_UNSIGNED: + *type = TYPE(&stvectorunsignedshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_INT: + tk = lex(); + switch (tk) { + case TK_BOOL: + *type = TYPE(&stvectorboolshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_SIGNED: + *type = TYPE(&stvectorsignedshort); + tk = lex(); + return 1; + case TK_UNSIGNED: + *type = TYPE(&stvectorunsignedshort); + tk = lex(); + return 1; + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("bool")) { + *type = TYPE(&stvectorboolshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + } + default: + CError_Error(CErrorStr121); + } + break; + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("bool")) { + *type = TYPE(&stvectorboolshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + } + default: + CError_Error(CErrorStr121); + } + break; + case TK_LONG: + tk = lex(); + switch (tk) { + case TK_BOOL: + *type = TYPE(&stvectorboollong); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_SIGNED: + *type = TYPE(&stvectorsignedlong); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_UNSIGNED: + *type = TYPE(&stvectorunsignedlong); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_INT: + tk = lex(); + switch (tk) { + case TK_BOOL: + *type = TYPE(&stvectorboollong); + tk = lex(); + return 1; + case TK_SIGNED: + *type = TYPE(&stvectorsignedlong); + tk = lex(); + return 1; + case TK_UNSIGNED: + *type = TYPE(&stvectorunsignedlong); + tk = lex(); + return 1; + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("bool")) { + *type = TYPE(&stvectorboollong); + tk = lex(); + return 1; + } + default: + CError_Error(CErrorStr121); + } + break; + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("bool")) { + *type = TYPE(&stvectorboollong); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + } + default: + CError_Error(CErrorStr121); + } + break; + case TK_INT: + tk = lex(); + switch (tk) { + case TK_BOOL: + tk = lex(); + switch (tk) { + case TK_SHORT: + *type = TYPE(&stvectorboolshort); + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorboollong); + tk = lex(); + return 1; + default: + *type = TYPE(&stvectorboollong); + return 1; + } + case TK_SIGNED: + tk = lex(); + switch (tk) { + case TK_SHORT: + *type = TYPE(&stvectorsignedshort); + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorsignedlong); + tk = lex(); + return 1; + default: + *type = TYPE(&stvectorsignedlong); + return 1; + } + case TK_UNSIGNED: + tk = lex(); + switch (tk) { + case TK_SHORT: + *type = TYPE(&stvectorunsignedshort); + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorunsignedlong); + tk = lex(); + return 1; + default: + *type = TYPE(&stvectorunsignedlong); + return 1; + } + case TK_SHORT: + tk = lex(); + switch (tk) { + case TK_BOOL: + *type = TYPE(&stvectorboolshort); + tk = lex(); + return 1; + case TK_SIGNED: + *type = TYPE(&stvectorsignedshort); + tk = lex(); + return 1; + case TK_UNSIGNED: + *type = TYPE(&stvectorunsignedshort); + tk = lex(); + return 1; + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("bool")) { + *type = TYPE(&stvectorboolshort); + tk = lex(); + return 1; + } + default: + CError_Error(CErrorStr121); + } + break; + case TK_LONG: + tk = lex(); + switch (tk) { + case TK_BOOL: + *type = TYPE(&stvectorboollong); + tk = lex(); + return 1; + case TK_SIGNED: + *type = TYPE(&stvectorsignedlong); + tk = lex(); + return 1; + case TK_UNSIGNED: + *type = TYPE(&stvectorunsignedlong); + tk = lex(); + return 1; + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("bool")) { + *type = TYPE(&stvectorboollong); + tk = lex(); + return 1; + } + } + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("bool")) { + tk = lex(); + switch (tk) { + case TK_LONG: + *type = TYPE(&stvectorboollong); + tk = lex(); + return 1; + case TK_SHORT: + *type = TYPE(&stvectorboolshort); + tk = lex(); + return 1; + default: + *type = TYPE(&stvectorboolshort); + return 1; + } + } + default: + CError_Error(CErrorStr121); + } + break; + case TK_FLOAT: + *type = TYPE(&stvectorfloat); + tk = lex(); + return 1; + case TK_IDENTIFIER: + if (tkidentifier == GetHashNameNode("pixel") || tkidentifier == GetHashNameNode("__pixel")) { + *type = TYPE(&stvectorpixel); + tk = lex(); + return 1; + } + if (tkidentifier == GetHashNameNode("bool")) { + tk = lex(); + switch (tk) { + case TK_CHAR: + *type = TYPE(&stvectorboolchar); + tk = lex(); + return 1; + case TK_SHORT: + *type = TYPE(&stvectorboolshort); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorboollong); + tk = lex(); + if (tk == TK_INT) + tk = lex(); + return 1; + case TK_INT: + tk = lex(); + switch (tk) { + case TK_SHORT: + *type = TYPE(&stvectorboolshort); + tk = lex(); + return 1; + case TK_LONG: + *type = TYPE(&stvectorboollong); + tk = lex(); + return 1; + default: + *type = TYPE(&stvectorboollong); + return 1; + } + } + } + default: + CError_Error(CErrorStr121); + } + + return 0; +} + +Boolean CParser_CheckTemplateClassUsage(TemplClass *tmclass, Boolean flag) { + NameSpace *nspace; + + if (tmclass->templ__params) { + nspace = cscope_current; + while (1) { + if (!nspace) { + if (flag) + CError_Error(CErrorStr230); + return 0; + } + if (nspace->theclass == TYPE_CLASS(tmclass)) + break; + nspace = nspace->parent; + } + } + + return 1; +} + +static Boolean CParser_IsAltiVecPrefix(void) { + HashNameNode *save = tkidentifier; + + switch (lookahead()) { + case TK_CHAR: + case TK_SHORT: + case TK_INT: + case TK_LONG: + case TK_FLOAT: + case TK_SIGNED: + case TK_UNSIGNED: + case TK_BOOL: + return 1; + case TK_IDENTIFIER: + if (!strcmp(tkidentifier->name, "bool") || !strcmp(tkidentifier->name, "pixel") || !strcmp(tkidentifier->name, "__pixel")) + return 1; + } + + tkidentifier = save; + return 0; +} + +void CParser_GetDeclSpecs(DeclInfo *di, Boolean flag) { + short typesize; + short signedness; + short typetoken; + Boolean r24; + Boolean r23; + SInt32 state; + NameResult pr; + + di->file = CPrep_BrowserCurrentFile(); + CPrep_BrowserFilePosition(&di->file2, &di->sourceoffset); + + r24 = 1; + r23 = copts.cplusplus; + typetoken = 0; + signedness = 0; + typesize = 0; + +restart: + switch (tk) { + case TK_AUTO: + case TK_REGISTER: + case TK_STATIC: + case TK_EXTERN: + case TK_TYPEDEF: + case TK_MUTABLE: + if (di->storageclass) + CError_Error(CErrorStr121); + di->storageclass = tk; + break; + case TK_CONST: + if (di->thetype) { + if (di->thetype->type == TYPEPOINTER) { + if (TYPE_POINTER(di->thetype)->qual & Q_CONST) + CError_QualifierCheck(Q_CONST); + TYPE_POINTER(di->thetype)->qual |= Q_CONST; + break; + } else if (di->thetype->type == TYPEMEMBERPOINTER) { + if (TYPE_MEMBER_POINTER(di->thetype)->qual & Q_CONST) + CError_QualifierCheck(Q_CONST); + TYPE_MEMBER_POINTER(di->thetype)->qual |= Q_CONST; + break; + } + } + if (di->qual & Q_CONST) + CError_QualifierCheck(Q_CONST); + di->qual |= Q_CONST; + break; + case TK_VOLATILE: + if (di->thetype) { + if (di->thetype->type == TYPEPOINTER) { + if (TYPE_POINTER(di->thetype)->qual & Q_VOLATILE) + CError_QualifierCheck(Q_VOLATILE); + TYPE_POINTER(di->thetype)->qual |= Q_VOLATILE; + break; + } else if (di->thetype->type == TYPEMEMBERPOINTER) { + if (TYPE_MEMBER_POINTER(di->thetype)->qual & Q_VOLATILE) + CError_QualifierCheck(Q_VOLATILE); + TYPE_MEMBER_POINTER(di->thetype)->qual |= Q_VOLATILE; + break; + } + } + if (di->qual & Q_VOLATILE) + CError_QualifierCheck(Q_VOLATILE); + di->qual |= Q_VOLATILE; + break; + case TK_PASCAL: + if (di->qual & Q_PASCAL) + CError_QualifierCheck(Q_PASCAL); + di->qual |= Q_PASCAL; + break; + case TK_EXPLICIT: + CError_QualifierCheck(di->qual & Q_EXPLICIT); + di->qual |= Q_EXPLICIT; + break; + case TK_VIRTUAL: + CError_QualifierCheck(di->qual & Q_VIRTUAL); + di->qual |= Q_VIRTUAL; + break; + case TK_IN: + CError_QualifierCheck(di->qual & Q_IN); + di->qual |= Q_IN; + break; + case TK_OUT: + CError_QualifierCheck(di->qual & Q_OUT); + di->qual |= Q_OUT; + break; + case TK_INOUT: + CError_QualifierCheck(di->qual & Q_INOUT); + di->qual |= Q_INOUT; + break; + case TK_BYCOPY: + CError_QualifierCheck(di->qual & Q_BYCOPY); + di->qual |= Q_BYCOPY; + break; + case TK_BYREF: + CError_QualifierCheck(di->qual & Q_BYREF); + di->qual |= Q_BYREF; + break; + case TK_ONEWAY: + CError_QualifierCheck(di->qual & Q_ONEWAY); + di->qual |= Q_ONEWAY; + break; + case TK_UU_DECLSPEC: + if ((tk = lex()) != '(') + CError_Error(CErrorStr114); + CParser_ParseDeclSpec(di, 0); + if ((tk = lex()) != ')') + CError_Error(CErrorStr115); + break; + case TK_ASM: + if (di->qual & Q_ASM) + CError_QualifierCheck(Q_ASM); + di->qual |= Q_ASM; + break; + case TK_INLINE: + if (di->qual & Q_INLINE) + CError_QualifierCheck(Q_INLINE); + di->qual |= Q_INLINE; + break; + case TK_SHORT: + if (typesize || (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE)) + CError_Error(CErrorStr121); + typesize = 1; + break; + case TK_LONG: + if (copts.longlong) { + if (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE) + CError_Error(CErrorStr121); + if (typesize) { + if (typesize != 2 || typetoken == TK_DOUBLE) + CError_Error(CErrorStr121); + typesize = 3; + } else { + typesize = 2; + } + } else { + if (typesize || (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE)) + CError_Error(CErrorStr121); + typesize = 2; + } + break; + case TK_SIGNED: + if (signedness || (typetoken && typetoken != TK_INT && typetoken != TK_CHAR)) + CError_Error(CErrorStr121); + signedness = -1; + break; + case TK_UNSIGNED: + if (signedness || (typetoken && typetoken != TK_INT && typetoken != TK_CHAR)) + CError_Error(CErrorStr121); + signedness = 1; + break; + case TK_VOID: + if (typetoken || typesize || signedness) + CError_Error(CErrorStr121); + typetoken = TK_VOID; + break; + case TK_FLOAT: + if (typetoken || typesize || signedness) + CError_Error(CErrorStr121); + typetoken = TK_FLOAT; + break; + case TK_BOOL: + if (typetoken || typesize) + CError_Error(CErrorStr121); + typetoken = TK_BOOL; + break; + case TK_CHAR: + if (typetoken || typesize) + CError_Error(CErrorStr121); + typetoken = TK_CHAR; + break; + case TK_WCHAR_T: + if (typetoken || typesize || signedness) + CError_Error(CErrorStr121); + typetoken = TK_WCHAR_T; + break; + case TK_INT: + if (typetoken) + CError_Error(CErrorStr121); + typetoken = TK_INT; + break; + case TK_DOUBLE: + if (typetoken || signedness) + CError_Error(CErrorStr121); + typetoken = TK_DOUBLE; + break; + case TK_STRUCT: + if (typetoken || signedness || typesize) + CError_Error(CErrorStr121); + tk = lex(); + scanstruct(di, STRUCT_TYPE_STRUCT); + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(di->thetype, NULL); + if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) { + typetoken = -1; + goto restart; + } + return; + case TK_CLASS: + if (typetoken || signedness || typesize) + CError_Error(CErrorStr121); + tk = lex(); + CDecl_ParseClass(di, CLASS_MODE_CLASS, 1, 0); + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(di->thetype, NULL); + if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) { + typetoken = -1; + goto restart; + } + return; + case TK_UNION: + if (typetoken || signedness || typesize) + CError_Error(CErrorStr121); + tk = lex(); + scanstruct(di, STRUCT_TYPE_UNION); + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(di->thetype, NULL); + if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) { + typetoken = -1; + goto restart; + } + return; + case TK_ENUM: + if (typetoken || signedness || typesize) + CError_Error(CErrorStr121); + tk = lex(); + scanenum(di); + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(di->thetype, NULL); + if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) { + typetoken = -1; + goto restart; + } + return; + case TK_TYPENAME: + if (typetoken || signedness || typesize || di->x53) + CError_Error(CErrorStr121); + di->x53 = 1; + tk = lex(); + if (tk != TK_COLON_COLON && tk != TK_IDENTIFIER) { + CError_Error(CErrorStr121); + break; + } + goto some_shared_label; + case TK_COLON_COLON: + if (typetoken || signedness || typesize) + goto switchDefault; + goto some_shared_label; + case TK_UU_VECTOR: + if (typetoken || signedness || typesize) + CError_Error(CErrorStr121); + handle_vector: + if (CParser_GetVectorDeclSpec(&di->thetype)) { + if (tk == TK_CONST) { + if (di->qual == 0) { + di->qual |= Q_CONST; + tk = lex(); + } else { + CError_Error(CErrorStr121); + } + } + if (tk == TK_VOLATILE) { + if (di->qual == 0) { + di->qual |= Q_VOLATILE; + tk = lex(); + } else { + CError_Error(CErrorStr121); + } + } + return; + } + break; + case TK_UU_TYPEOF_UU: + if (typetoken || signedness || typesize) + CError_Error(CErrorStr121); + CParser_ParseTypeOf(di); + typetoken = -1; + goto bailOut; + case TK_IDENTIFIER: + if (copts.altivec_model && !typetoken && !signedness && !typesize && !strcmp(tkidentifier->name, "vector")) { + if (CParser_IsAltiVecPrefix()) + goto handle_vector; + } + if (!typetoken && !signedness && !typesize) { + if (copts.objective_c && !strcmp(tkidentifier->name, "id")) { + di->thetype = CObjC_ParseID(); + typetoken = -1; + goto bailOut; + } + some_shared_label: + CPrep_TokenStreamGetState(&state); + if (CScope_ParseDeclName(&pr)) { + if (pr.type) { + if (IS_TYPE_TEMPLATE(pr.type)) { + switch (TYPE_TEMPLATE(pr.type)->dtype) { + case TEMPLDEP_ARGUMENT: + switch (TYPE_TEMPLATE(pr.type)->u.pid.type) { + case TPT_TYPE: + break; + case TPT_NONTYPE: + CError_Error(CErrorStr348); + pr.type = TYPE(&stsignedint); + break; + case TPT_TEMPLATE: + CError_Error(CErrorStr230); + pr.type = TYPE(&stsignedint); + break; + default: + CError_FATAL(4109); + } + break; + case TEMPLDEP_QUALNAME: + if (!di->x53 && !pr.x20 && di->x55) + CError_Error(CErrorStr355); + break; + case TEMPLDEP_TEMPLATE: + case TEMPLDEP_ARRAY: + case TEMPLDEP_QUALTEMPL: + case TEMPLDEP_BITFIELD: + break; + default: + CError_FATAL(4136); + } + } + + if (IS_TYPE_CLASS(pr.type) && (TYPE_CLASS(pr.type)->flags & CLASS_IS_TEMPL)) { + if (!CParser_CheckTemplateClassUsage(TEMPL_CLASS(pr.type), 0)) { + if (di->x56) { + if (di->qual) + CError_Error(CErrorStr121); + di->thetype = pr.type; + di->x57 = 1; + tk = lex(); + return; + } else { + CError_Error(CErrorStr230); + pr.type = TYPE(&stsignedint); + } + } + } + + TypedefDeclInfo(di, pr.type, pr.qual); + di->x49 = pr.x20; + typetoken = -1; + tk = lex(); + if (tk == '<' && copts.objective_c && IS_TYPE_CLASS(di->thetype) && TYPE_CLASS(di->thetype)->objcinfo) + di->thetype = CObjC_ParseTypeProtocol(TYPE_CLASS(di->thetype)); + goto bailOut; + } else if (pr.nsol_14) { + if (pr.x1D) { + if (flag && (OBJECT(pr.nsol_14->object)->nspace == pr.nspace_0 || di->in_friend_decl)) { + di->x14 = pr.nsol_14; + if (IS_TYPE_FUNC(OBJECT(di->x14->object)->type) && ((TYPE_FUNC(OBJECT(di->x14->object)->type)->flags & FUNC_IS_CTOR) | FUNC_IS_DTOR)) + r23 = 0; + } else { + CError_Error(CErrorStr121); + } + } + } else if (pr.obj_10) { + switch (pr.obj_10->otype) { + case OT_OBJECT: + if (pr.x1D) { + if (flag && (OBJECT(pr.obj_10)->nspace == pr.nspace_0 || di->in_friend_decl)) { + di->x10 = OBJECT(pr.obj_10); + if (IS_TYPE_FUNC(di->x10->type) && ((TYPE_FUNC(di->x10->type)->flags & FUNC_IS_CTOR) | FUNC_IS_DTOR)) + r23 = 0; + } else { + CError_Error(CErrorStr121); + } + } + break; + case OT_ENUMCONST: + case OT_MEMBERVAR: + CError_Error(CErrorStr121); + break; + default: + CError_FATAL(4217); + } + } else if (pr.name_4) { + if (copts.cplusplus) + CError_Error(CErrorStr121); + } else if (pr.x21) { + CPrep_TokenStreamSetState(&state); + CPrep_UnLex(); + tk = lex(); + r23 = 0; + } else { + CError_FATAL(4234); + } + } + } + default: + switchDefault: + if (!typetoken && !signedness && !typesize) { + di->x4A = 1; + if (r23) { + if (!di->storageclass && !di->qual && !di->exportflags) + CError_Error(CErrorStr121); + else + CError_Warning(CErrorStr349); + } + } + if (typetoken >= 0) + di->thetype = getthetype(typetoken, typesize, signedness); + if (r24) + di->x48 = 1; + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(NULL, di); + return; + case ';': + if (!typetoken && !signedness && !typesize && copts.warn_emptydecl) + CError_Warning(CErrorStr216); + if (typetoken >= 0) + di->thetype = getthetype(typetoken, typesize, signedness); + return; + } + + tk = lex(); +bailOut: + r24 = 0; + goto restart; +} + +void CParser_RegisterNonGlobalClass(TypeClass *tclass) { + struct ParentCleanup *p = lalloc(sizeof(struct ParentCleanup)); + p->next = cparser_parentcleanup; + p->tclass = tclass; + cparser_parentcleanup = p; +} + +void CParser_RegisterSingleExprFunction(Object *func, ENode *expr) { + struct SFuncList *p = lalloc(sizeof(struct SFuncList)); + p->next = cparser_sfunclist; + p->func = func; + p->obj = NULL; + p->expr = expr; + cparser_sfunclist = p; +} + +void CParser_RegisterDummyCtorFunction(Object *func, Object *obj) { + struct SFuncList *p = lalloc(sizeof(struct SFuncList)); + p->next = cparser_sfunclist; + p->func = func; + p->obj = obj; + p->expr = NULL; + cparser_sfunclist = p; +} + +static void CParser_FreeLocalHeap(void) { + struct SFuncList *s; + struct ParentCleanup *p; + + while ((s = cparser_sfunclist)) { + cparser_sfunclist = s->next; + if (s->expr) + CFunc_GenerateSingleExprFunc(s->func, s->expr); + else + CFunc_GenerateDummyCtorFunc(s->func, s->obj); + } + + if (cparser_parentcleanup) { + if (!CInline_CanFreeLHeap()) + return; + + for (p = cparser_parentcleanup; p; p = p->next) { + while (!p->tclass->nspace->parent->is_global) + p->tclass->nspace->parent = p->tclass->nspace->parent->parent; + } + + cparser_parentcleanup = NULL; + } + + freelheap(); +} + +static void CParser_GlobalCleanup(Boolean flag) { + Boolean working; + + do { + CParser_FreeLocalHeap(); + working = 0; + + if (flag) { + if (cparser_classactions) { + CClass_ClassAction(cparser_classactions->tclass); + cparser_classactions = cparser_classactions->next; + working = 1; + } else if (CTempl_Instantiate()) { + working = 1; + } + } + + while (CInline_GenerateDeferredFuncs()) { + CParser_FreeLocalHeap(); + working = 1; + } + } while (working); +} + +Boolean CParser_IsAnonymousUnion(DeclInfo *di, Boolean flag) { + return IS_TYPE_CLASS(di->thetype) && + ((TYPE_CLASS(di->thetype)->mode == CLASS_MODE_UNION || (flag && copts.cpp_extensions))) && + IsTempName(TYPE_CLASS(di->thetype)->classname); +} + +void CParser_CheckAnonymousUnion(DeclInfo *di, Boolean flag) { + ObjMemberVar *ivar; + Object *obj; + Object *ivar_obj; + + if (!CParser_IsAnonymousUnion(di, 0)) { + if (copts.warn_emptydecl) { + switch (di->thetype->type) { + case TYPEENUM: + case TYPESTRUCT: + case TYPECLASS: + if (!di->storageclass && !di->qual) + return; + } + CError_Warning(CErrorStr216); + } + return; + } + + if (!flag && di->storageclass != TK_STATIC) + CError_Error(CErrorStr177); + + if (flag && di->storageclass != TK_STATIC) { + obj = CParser_NewLocalDataObject(di, 1); + obj->name = CParser_GetUniqueName(); + CFunc_SetupLocalVarInfo(obj); + obj->u.var.info->noregister = 1; + } else { + obj = CParser_NewGlobalDataObject(di); + obj->name = CParser_GetUniqueName(); + obj->nspace = cscope_root; + obj->sclass = TK_STATIC; + CInit_DeclareData(obj, NULL, NULL, obj->type->size); + } + + for (ivar = TYPE_CLASS(di->thetype)->ivars; ivar; ivar = ivar->next) { + ivar_obj = galloc(sizeof(Object)); + *ivar_obj = *obj; + ivar_obj->name = ivar->name; + ivar_obj->type = ivar->type; + ivar_obj->qual = ivar->qual; + ivar_obj->datatype = DALIAS; + ivar_obj->u.alias.object = obj; + ivar_obj->u.alias.offset = ivar->offset; + ivar_obj->u.alias.member = NULL; + CScope_AddObject(cscope_current, ivar_obj->name, OBJ_BASE(ivar_obj)); + } +} + +void CParser_NewCallBackAction(Object *obj, TypeClass *tclass) { + CallbackAction *act = galloc(sizeof(CallbackAction)); + act->next = callbackactions; + act->obj = obj; + act->tclass = tclass; + callbackactions = act; + obj->flags = obj->flags | OBJECT_LAZY; +} + +void CParser_NewClassAction(TypeClass *tclass) { + struct ClassAction *act = galloc(sizeof(struct ClassAction)); + act->next = cparser_classactions; + act->tclass = tclass; + cparser_classactions = act; +} + +void CParser_CallBackAction(Object *obj) { + CallbackAction *act; + + for (act = callbackactions; act; act = act->next) { + if (act->obj == obj) { + CParser_NewClassAction(act->tclass); + return; + } + } + + CError_FATAL(4551); +} + +static Object *CParser_FindOverloadFunc(NameSpaceObjectList *list, TypeFunc *tfunc) { + while (list) { + if (list->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(list->object)->type)) + if (CParser_CompareArgLists(tfunc->args, TYPE_FUNC(OBJECT(list->object)->type)->args) == 1) + return OBJECT(list->object); + list = list->next; + } + + return NULL; +} + +Object *CParser_ParseObject(void) { + DeclInfo di; + NameResult pr; + NameSpaceObjectList *list; + Object *obj; + + memclrw(&di, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&di, 1); + scandeclarator(&di); + + if (di.name && (list = CScope_FindObjectList(&pr, di.name))) { + if (list->object->otype == OT_OBJECT) { + if (IS_TYPE_FUNC(di.thetype)) + return CParser_FindOverloadFunc(list, TYPE_FUNC(di.thetype)); + + if (is_typesame(di.thetype, OBJECT(list->object)->type) && OBJECT(list->object)->qual == di.qual) + return OBJECT(list->object); + + obj = OBJECT(list->object); + CError_Error(CErrorStr249, CError_GetObjectName(obj), obj->type, obj->qual, di.thetype, di.qual); + } + } + + return NULL; +} + +void CParser_ParseGlobalDeclaration(void) { + DeclInfo di; + + if (tk) { + CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL); + symdecloffset = cparser_fileoffset.tokenline; + symdecltoken = *CPrep_CurStreamElement(); + + memclrw(&di, sizeof(DeclInfo)); + CParser_GetDeclSpecs(&di, 1); + if (di.storageclass == TK_REGISTER || di.storageclass == TK_AUTO) { + CError_Error(CErrorStr177); + di.storageclass = 0; + } + + if (tk != ';') + scandeclaratorlist(&di); + else + CParser_CheckAnonymousUnion(&di, 0); + + tk = lex(); + } else { + CError_Error(CErrorStr102); + } +} + +static void CParser_ParseLinkageSpecification(DeclInfo *di) { + UInt32 qual; + UInt8 r28; + + if (!strcmp(tkstring, "C") || !strcmp(tkstring, "Objective C")) { + qual = 0; + r28 = 1; + } else if (!strcmp(tkstring, "C++")) { + qual = 0; + r28 = 0; + } else if (!strcmp(tkstring, "Pascal")) { + qual = Q_PASCAL; + r28 = 1; + } else { + CError_Error(CErrorStr121); + qual = 0; + r28 = 1; + } + + if ((tk = lex()) == '{') { + while (1) { + if ((tk = lex()) == 0) { + CError_Error(CErrorStr130); + return; + } + + if (tk == '}') + break; + + CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL); + symdecloffset = cparser_fileoffset.tokenline; + symdecltoken = *CPrep_CurStreamElement(); + + memclrw(di, sizeof(DeclInfo)); + di->is_extern_c = r28; + di->qual = qual; + CParser_ParseDeclaration(di); + } + } else if (tk == TK_EXTERN && copts.cpp_extensions && lookahead() == TK_STRING) { + tk = lex(); + CParser_ParseLinkageSpecification(di); + } else { + memclrw(di, sizeof(DeclInfo)); + di->is_extern_c = r28; + di->qual = qual; + CParser_GetDeclSpecs(di, 1); + + if (di->storageclass != TK_TYPEDEF) { + if (di->storageclass && copts.pedantic) + CError_Warning(CErrorStr177); + if (!di->storageclass) + di->storageclass = TK_EXTERN; + } + if (copts.cpp_extensions) + di->x48 = 0; + if (tk != ';') + scandeclaratorlist(di); + } +} + +static void CParser_ParseNameSpace(DeclInfo *di) { + NameSpace *nspace; + ObjNameSpace *objns; + HashNameNode *name; + Boolean flag; + CScopeSave save; + NameSpaceObjectList *list; + NameSpaceList *nsl; + + if ((tk = lex()) == TK_IDENTIFIER) { + name = tkidentifier; + flag = 0; + if ((tk = lex()) == '=') { + CScope_ParseNameSpaceAlias(name); + return; + } + } else { + if (tk != '{') { + CError_Error(CErrorStr107); + return; + } + name = CParser_GetUnnamedNameSpaceName(); + flag = 1; + } + + nspace = cscope_current; + if (!(list = CScope_FindName(nspace, name))) { + objns = galloc(sizeof(ObjNameSpace)); + memclrw(objns, sizeof(ObjNameSpace)); + objns->otype = OT_NAMESPACE; + objns->access = ACCESSPUBLIC; + if (flag) { + nspace = CScope_NewListNameSpace(name, 1); + nspace->is_unnamed = 1; + nsl = galloc(sizeof(NameSpaceList)); + nsl->next = cscope_current->usings; + nsl->nspace = nspace; + cscope_current->usings = nsl; + } else { + nspace = CScope_NewHashNameSpace(name); + if (cscope_current->is_unnamed) + nspace->is_unnamed = 1; + } + + nspace->parent = cscope_current; + objns->nspace = nspace; + CScope_AddObject(cscope_current, name, OBJ_BASE(objns)); + } else { + if (list->object->otype != OT_NAMESPACE) + CError_Error(CErrorStr320); + else + nspace = OBJ_NAMESPACE(list->object)->nspace; + } + + if (tk != '{') { + CError_Error(CErrorStr135); + return; + } + + CScope_SetNameSpaceScope(nspace, &save); + while (1) { + if ((tk = lex()) == 0) { + CError_Error(CErrorStr130); + break; + } + + if (tk == '}') + break; + + CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL); + symdecloffset = cparser_fileoffset.tokenline; + symdecltoken = *CPrep_CurStreamElement(); + + memclrw(di, sizeof(DeclInfo)); + CParser_ParseDeclaration(di); + } + CScope_RestoreScope(&save); +} + +static void CParser_ParseDeclaration(DeclInfo *di) { + switch (tk) { + case TK_AT_INTERFACE: + CObjC_ParseInterface(); + break; + case TK_AT_IMPLEMENTATION: + CObjC_ParseImplementation(); + break; + case TK_AT_PROTOCOL: + CObjC_ParseProtocol(); + break; + case TK_AT_CLASS: + CObjC_ParseClassDeclaration(); + break; + case TK_NAMESPACE: + CParser_ParseNameSpace(di); + break; + case TK_EXPORT: + CError_Error(CErrorStr190); + if ((tk = lex()) != TK_TEMPLATE) { + CError_Error(CErrorStr121); + return; + } + case TK_TEMPLATE: + CTempl_Parse(NULL, 0); + break; + case TK_USING: + if ((tk = lex()) == TK_NAMESPACE) { + tk = lex(); + CScope_ParseUsingDirective(cscope_current); + } else { + CScope_ParseUsingDeclaration(cscope_current, 0, 0); + } + break; + case TK_EXTERN: + if (copts.cplusplus) { + di->storageclass = TK_EXTERN; + if ((tk = lex()) == TK_STRING) { + CParser_ParseLinkageSpecification(di); + break; + } + } + default: + CParser_GetDeclSpecs(di, 1); + if ((di->storageclass == TK_REGISTER || di->storageclass == TK_AUTO) != 0) { + CError_Error(CErrorStr177); + di->storageclass = 0; + } + if (tk != ';') + scandeclaratorlist(di); + else + CParser_CheckAnonymousUnion(di, 0); + CParser_GlobalCleanup(0); + } +} + +void cparser(void) { + DeclInfo di; + + if (copts.crippled && copts.optimizationlevel > 1) { + CError_Warning(CErrorStr385); + copts.optimizationlevel = 1; + CodeGen_UpdateOptimizerOptions(); + CodeGen_UpdateBackEndOptions(); + } + + if ((tk = lex())) { + do { + CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL); + symdecloffset = cparser_fileoffset.tokenline; + symdecltoken = *CPrep_CurStreamElement(); + + memclrw(&di, sizeof(DeclInfo)); + CParser_ParseDeclaration(&di); + } while (tk && (tk = lex())); + } else { + if (!copts.cplusplus && copts.ANSIstrict) + CError_Error(CErrorStr102); + } + + CInit_DefineTentativeData(); + copts.defer_codegen = 0; + CParser_GlobalCleanup(1); + + if (cparamblkptr->precompile != 1) { + CInline_Finish(); + CParser_GlobalCleanup(1); + } + + CClass_GenThunks(); + if (cparamblkptr->precompile != 1) + CObjC_GenerateModule(); + + CSOM_Cleanup(); + CInit_DefineTentativeData(); +} diff --git a/compiler_and_linker/FrontEnd/C/CPrec.c b/compiler_and_linker/FrontEnd/C/CPrec.c new file mode 100644 index 0000000..e61b96e --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CPrec.c @@ -0,0 +1,3482 @@ +#include "compiler/CPrec.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CInit.h" +#include "compiler/CInline.h" +#include "compiler/CMachine.h" +#include "compiler/CObjC.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CScope.h" +#include "compiler/CSOM.h" +#include "compiler/CTemplateNew.h" +#include "compiler/CompilerTools.h" +#include "compiler/Exceptions.h" +#include "compiler/enode.h" +#include "compiler/objc.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/som.h" +#include "compiler/templates.h" +#include "compiler/types.h" +#include "cos.h" +#include "compiler/CCompiler.h" +#include "compiler/InlineAsm.h" + +#define RESOLVE_BUFFER(offset) ((void *) (((char *) cprec_buffer) + ((uintptr_t) (offset)))) +#define RESOLVE_RAW_BUFFER(offset) ((void *) (((char *) cprec_rawbuffer) + ((uintptr_t) (offset)))) +#define RESOLVE_SAFE(offset) (!(offset) ? NULL : ((void *) (((char *) cprec_rawbuffer) + ((uintptr_t) (offset))))) + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct StaticData { + struct StaticData *next; + Object *object; + void *buffer; + OLinkList *links; + SInt32 size; +} StaticData; + +typedef struct Header { + UInt32 magic; + UInt16 version; + UInt16 x6; + char target; + Boolean check_header_flags; + Boolean cplusplus; + UInt32 xC; + UInt32 x10; + UInt32 x14; + UInt32 x18; + UInt32 x1C; + UInt32 x20; + UInt32 x24; + UInt32 x28; + UInt32 x2C; + UInt32 x30; + UInt32 compressedPatchCount; + UInt32 compressedPatchSize; + UInt32 compressedPatchOffset; + UInt32 builtinPatchSize; + UInt32 builtinPatchOffset; + UInt32 tokenStreamPatchSize; + UInt32 tokenStreamPatchOffset; + UInt32 root_names; + NameSpaceList *usings; + TemplClass *ctempl_templates; + CSOMStub *csom_stubs; + StaticData *cprec_staticdata; + UInt32 uniqueID; + CallbackAction *callbackactions; + Type *cobjc_type_class; + Type *cobjc_type_id; + Type *cobjc_type_sel; + ObjCSelector **cobjc_selhashtable; + BClassList *cobjc_classdefs; + ObjCProtocol *cobjc_protocols; + UInt32 cobjc_selrefcount; + UInt32 cobjc_classrefcount; + UInt32 cobjc_stringcount; + InitExpr *init_expressions; + CI_Action *cinline_tactionlist; + TemplateFunction *ctempl_templatefuncs; + UInt32 x9C; + UInt32 xA0; + UInt32 xA4; + UInt32 xA8; + UInt32 xAC; + UInt32 xB0; + UInt32 xB4; + UInt32 xB8; + UInt32 xBC; + UInt32 xC0; + UInt32 xC4; + UInt32 xC8; + UInt32 xCC; + UInt32 xD0; + UInt32 xD4; + UInt32 xD8; + UInt32 xDC; + UInt32 xE0; + UInt32 xE4; + HashNameNode *nametable[0x800]; + Macro *macrotable[0x800]; + NameSpaceName *root_nametable[0x400]; +} Header; + +typedef struct Patch { + struct Patch *next; + SInt32 offset; +} Patch; + +typedef struct AddrPatch { + struct AddrPatch *next; + void *addr; + void *value; +} AddrPatch; + +typedef struct BuiltIn { + void *target; + SInt32 idx; + Patch *patches; +} BuiltIn; + +static Boolean cprec_exportargnames; +static Boolean cprec_dowrite; +static OSErr cprec_ioerror; +static void *cprec_rawbuffer; +static void *cprec_buffer; +static SInt32 cprec_zero_offset; +static SInt32 cprec_offset; +static int cprec_builtins; +static void **cprec_builtin_array; + +typedef struct TokenPatch { + struct TokenPatch *next; + TStreamElement *tokens; + SInt32 count; +} TokenPatch; +static TokenPatch *cprec_tokenpatches; +static StaticData *cprec_staticdata; + +typedef struct PointerHash { + struct PointerHash *next; + TypePointer *tptr; + TypePointer *prec_tptr; +} PointerHash; +static PointerHash **cprec_pointerhash; + +static BuiltIn *cprec_builtin; +static Patch *cprec_patch_list; +static AddrPatch **cprec_addrhash; +static Header *cprec_header; +static GList cprec_glist; +static short cprec_refnum; +char *precomp_target_str; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +// Assorted forward declarations +static NameSpace *CPrec_GetNameSpacePatch(NameSpace *nspace); +static ObjEnumConst *CPrec_GetObjEnumConstPatch(ObjEnumConst *obj); +static Object *CPrec_GetObjectPatch(Object *obj); +static ObjBase *CPrec_GetObjBasePatch(ObjBase *obj); +static ObjMemberVar *CPrec_GetObjMemberVarPatch(ObjMemberVar *ivar); +static Type *CPrec_GetTypePatch(Type *type); +static ENode *CPrec_GetExpressionPatch(ENode *expr); +static ObjCMethod *CPrec_GetObjCMethodPatch(ObjCMethod *meth); +static ObjCProtocolList *CPrec_GetObjCProtocolListPatch(ObjCProtocolList *lst); +static TemplArg *CPrec_GetTemplateArgPatch(TemplArg *arg); +static NameSpaceObjectList *CPrec_GetNameSpaceObjectListPatch(NameSpaceObjectList *nsol); +static OSErr CPrec_FlushBufferCheck(void); + +void SetupPrecompiler(Boolean isPrecompiling) { + cprec_refnum = 0; + cprec_glist.data = NULL; + cprec_header = NULL; + cprec_staticdata = NULL; + cprec_ioerror = noErr; +} + +void CleanupPrecompiler(void) { + if (cprec_refnum) { + COS_FileClose(cprec_refnum); + cprec_refnum = 0; + } + + if (cprec_glist.data) + FreeGList(&cprec_glist); +} + +static OLinkList *CPrec_OLinkListCopy(OLinkList *list) { + OLinkList *copy; + + if (!list) + return NULL; + + copy = galloc(sizeof(OLinkList)); + *copy = *list; + copy->next = CPrec_OLinkListCopy(copy->next); + return copy; +} + +void PreComp_StaticData(Object *obj, const void *data, OLinkList *links, SInt32 size) { + StaticData *entry; + + if (obj->sclass != TK_STATIC && !(obj->qual & (Q_20000 | Q_WEAK))) + CError_Error(CErrorStr180); + + entry = galloc(sizeof(StaticData)); + entry->object = obj; + entry->size = size; + + entry->next = cprec_staticdata; + cprec_staticdata = entry; + + if (data) { + entry->buffer = galloc(obj->type->size); + memcpy(entry->buffer, data, obj->type->size); + } else { + entry->buffer = NULL; + } + + entry->links = CPrec_OLinkListCopy(links); +} + +static void CPrec_InitAddressHashTable(void) { + cprec_addrhash = lalloc(0x4000 * sizeof(AddrPatch *)); + memclrw(cprec_addrhash, 0x4000 * sizeof(AddrPatch *)); +} + +static void CPrec_InitPointerHashTable(void) { + cprec_pointerhash = lalloc(0x400 * sizeof(PointerHash *)); + memclrw(cprec_pointerhash, 0x400 * sizeof(PointerHash *)); +} + +static int CPrec_AddressHashVal(void *addr) { + UInt32 v = (UInt32) addr; + return ( + v + + ((unsigned char *) &v)[0] + + ((unsigned char *) &v)[1] + + ((unsigned char *) &v)[2] + + ((unsigned char *) &v)[3] + ) & 0x3FFF; +} + +static AddrPatch *CPrec_FindAddrPatch(void *addr) { + AddrPatch *scan; + + for (scan = cprec_addrhash[CPrec_AddressHashVal(addr)]; scan; scan = scan->next) { + if (scan->addr == addr) + return scan; + } + + return NULL; +} + +static AddrPatch *CPrec_NewAddrPatch(void *addr, void *value) { + AddrPatch **loc; + AddrPatch *patch; + + loc = cprec_addrhash + CPrec_AddressHashVal(addr); + patch = lalloc(sizeof(AddrPatch)); + patch->addr = addr; + patch->value = value; + patch->next = *loc; + *loc = patch; + return patch; +} + +static void CPrec_SetupBuiltInArray(void) { + int count1, count2; + Boolean flag; + void **array; + +#define REG_BUILTIN(a) \ + if (!flag) { array[count2++] = (a); } else { count1++; } + + for (count2 = count1 = 0, flag = 1; ;) { + REG_BUILTIN(cscope_root); + REG_BUILTIN(&stvoid); + REG_BUILTIN(&stbool); + REG_BUILTIN(&stchar); + REG_BUILTIN(&stsignedchar); + REG_BUILTIN(&stunsignedchar); + REG_BUILTIN(&stwchar); + REG_BUILTIN(&stsignedshort); + REG_BUILTIN(&stunsignedshort); + REG_BUILTIN(&stsignedint); + REG_BUILTIN(&stunsignedint); + REG_BUILTIN(&stsignedlong); + REG_BUILTIN(&stunsignedlong); + REG_BUILTIN(&stsignedlonglong); + REG_BUILTIN(&stunsignedlonglong); + REG_BUILTIN(&stfloat); + REG_BUILTIN(&stshortdouble); + REG_BUILTIN(&stdouble); + REG_BUILTIN(&stlongdouble); + REG_BUILTIN(&elipsis); + REG_BUILTIN(&oldstyle); + REG_BUILTIN(&stillegal); + REG_BUILTIN(&sttemplexpr); + REG_BUILTIN(&stvoid); + REG_BUILTIN(&void_ptr); + REG_BUILTIN(&rt_func); + REG_BUILTIN(&catchinfostruct); + REG_BUILTIN(newh_func); + REG_BUILTIN(delh_func); + REG_BUILTIN(copy_func); + REG_BUILTIN(clear_func); + REG_BUILTIN(Rgtid_func); + REG_BUILTIN(Rdync_func); + REG_BUILTIN(rt_ptmf_cast); + REG_BUILTIN(rt_ptmf_cmpr); + REG_BUILTIN(rt_ptmf_test); + REG_BUILTIN(rt_ptmf_call); + REG_BUILTIN(rt_ptmf_scall); + REG_BUILTIN(rt_ptmf_null); + REG_BUILTIN(rt_som_glue1); + REG_BUILTIN(rt_som_glue2); + REG_BUILTIN(rt_som_glue3); + REG_BUILTIN(rt_som_check); + REG_BUILTIN(rt_som_new); + REG_BUILTIN(rt_som_newcheck); + REG_BUILTIN(rt_ptmf_call4); + REG_BUILTIN(rt_ptmf_scall4); + REG_BUILTIN(carr_func); + REG_BUILTIN(cnar_func); + REG_BUILTIN(darr_func); + REG_BUILTIN(dnar_func); + REG_BUILTIN(dnar3_func); + REG_BUILTIN(Xgreg_func); + REG_BUILTIN(Xthrw_func); + REG_BUILTIN(Xicth_func); + REG_BUILTIN(Xecth_func); + REG_BUILTIN(Xunex_func); + REG_BUILTIN(&stvectorunsignedchar); + REG_BUILTIN(&stvectorsignedchar); + REG_BUILTIN(&stvectorboolchar); + REG_BUILTIN(&stvectorunsignedshort); + REG_BUILTIN(&stvectorsignedshort); + REG_BUILTIN(&stvectorboolshort); + REG_BUILTIN(&stvectorunsignedlong); + REG_BUILTIN(&stvectorsignedlong); + REG_BUILTIN(&stvectorboollong); + REG_BUILTIN(&stvectorfloat); + REG_BUILTIN(&stvectorpixel); + + if (flag) { + array = lalloc(sizeof(void *) * count1); + cprec_builtin_array = array; + cprec_builtins = count1; + flag = 0; + } else { + return; + } + } +} + +static void CPrec_SetupBuiltIn(void) { + int x; + + CPrec_SetupBuiltInArray(); + cprec_builtin = lalloc(sizeof(BuiltIn) * cprec_builtins); + memclrw(cprec_builtin, sizeof(BuiltIn) * cprec_builtins); + + for (x = 0; x < cprec_builtins; x++) { + cprec_builtin[x].target = cprec_builtin_array[x]; + cprec_builtin[x].idx = ~x; + CPrec_NewAddrPatch(cprec_builtin[x].target, (void *) cprec_builtin[x].idx); + } +} + +static void CPrec_NewPointerPatch(void *src, void *ptr) { + if (cprec_dowrite) { + Patch *patch = lalloc(sizeof(Patch)); + patch->offset = (SInt32) src; + CError_ASSERT(507, (patch->offset & 0x80000001) == 0); + + if ((SInt32) ptr < 0) { + ptr = (void *) ~((SInt32) ptr); + CError_ASSERT(513, (SInt32) ptr < cprec_builtins); + + patch->next = cprec_builtin[(SInt32) ptr].patches; + cprec_builtin[(SInt32) ptr].patches = patch; + ptr = NULL; + } else { + patch->next = cprec_patch_list; + cprec_patch_list = patch; + } + + src = (void *)((char *) src - cprec_zero_offset); + CError_ASSERT(525, (SInt32) src >= 0 && (SInt32) src <= cprec_glist.size); + *((void **) (*cprec_glist.data + (SInt32) src)) = ptr; + } +} + +static void CPrec_ExistingPointerPatch(void *src, void *ptr) { + if (cprec_dowrite) { + AddrPatch *addrPatch; + Patch *patch; + + CError_ASSERT(543, addrPatch = CPrec_FindAddrPatch(ptr)); + + patch = lalloc(sizeof(Patch)); + patch->offset = (SInt32) src; + patch->next = cprec_patch_list; + cprec_patch_list = patch; + + CError_ASSERT(548, (patch->offset & 0x80000001) == 0); + + src = (void *)((char *) src - cprec_zero_offset); + CError_ASSERT(552, (SInt32) src >= 0 && (SInt32) src <= cprec_glist.size); + *((void **) (*cprec_glist.data + (SInt32) src)) = addrPatch->value; + } +} + +static void CPrec_NamePatch(void *src, HashNameNode *name) { + name->id = 1; + CPrec_ExistingPointerPatch(src, name); +} + +static void *CPrec_AppendAlign(void) { + if (cprec_dowrite) { + while (cprec_offset & 3) { + AppendGListByte(&cprec_glist, 0); + ++cprec_offset; + } + } + + return (void *) cprec_offset; +} + +static UInt32 CPrec_AppendByte(UInt8 v) { + if (cprec_dowrite) + AppendGListByte(&cprec_glist, v); + return cprec_offset++; +} + +static UInt32 CPrec_AppendWord16(UInt16 v) { + UInt32 offset; + if (cprec_dowrite) + AppendGListWord(&cprec_glist, v); + offset = cprec_offset; + cprec_offset += 2; + return offset; +} + +static UInt32 CPrec_AppendWord32(UInt32 v) { + UInt32 offset; + if (cprec_dowrite) + AppendGListLong(&cprec_glist, v); + offset = cprec_offset; + cprec_offset += 4; + return offset; +} + +static UInt32 CPrec_AppendPointer(void *v) { + UInt32 offset; + if (cprec_dowrite) + AppendGListLong(&cprec_glist, (SInt32) v); + offset = cprec_offset; + cprec_offset += 4; + return offset; +} + +static UInt32 CPrec_AppendPointerPatch(void *v) { + AddrPatch *addrPatch; + + if (v) { + CError_ASSERT(644, addrPatch = CPrec_FindAddrPatch(v)); + + if (cprec_dowrite) { + Patch *patch = lalloc(sizeof(Patch)); + patch->offset = cprec_offset; + patch->next = cprec_patch_list; + cprec_patch_list = patch; + CError_ASSERT(651, (patch->offset & 0x80000001) == 0); + } + + return CPrec_AppendPointer(addrPatch->value); + } else { + return CPrec_AppendPointer(NULL); + } +} + +static void CPrec_AppendNamePatch(HashNameNode *name) { + if (name) { + CPrec_AppendPointerPatch(name); + name->id = 1; + } +} + +static void CPrec_AppendString(const char *str) { + int len = strlen(str) + 1; + if (cprec_dowrite) + AppendGListData(&cprec_glist, str, len); + cprec_offset += len; +} + +static void CPrec_AppendData(const void *data, int len) { + if (cprec_dowrite) + AppendGListData(&cprec_glist, data, len); + cprec_offset += len; +} + +static void CPrec_RawMemPatch(void *source, const void *data, int len) { + void *ptr = CPrec_AppendAlign(); + CPrec_AppendData(data, len); + CPrec_NewPointerPatch(source, ptr); +} + +static void CPrec_DumpNameTable(void) { + HashNameNode *name; + int i; + HashNameNode *p; + HashNameNode *next; + + if (cprec_dowrite) { + i = 0; + do { + name = name_hash_nodes[i]; + while (name && name->id == 0) + name = name->next; + + if (name) { + p = CPrec_AppendAlign(); + cprec_header->nametable[i] = p; + + while (1) { + CPrec_NewAddrPatch(name, p); + CPrec_AppendPointer(NULL); + CPrec_AppendWord32(0); + CPrec_AppendWord16(name->hashval); + CPrec_AppendString(name->name); + + name = name->next; + while (name && name->id == 0) + name = name->next; + + if (!name) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(&p->next, next); + p = next; + } + } + } while (++i < 0x800); + } else { + i = 0; + do { + if ((name = name_hash_nodes[i])) { + p = CPrec_AppendAlign(); + while (1) { + CPrec_NewAddrPatch(name, p); + CPrec_AppendPointer(NULL); + CPrec_AppendWord32(0); + CPrec_AppendWord16(name->hashval); + CPrec_AppendString(name->name); + + name = name->next; + if (!name) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(&p->next, next); + p = next; + } + } + } while (++i < 0x800); + } +} + +static void CPrec_DumpMacroTable(void) { + Macro *macro; + int i; + int j; + Macro *p; + Macro *next; + + i = 0; + do { + for (macro = macrohashtable[i]; macro; macro = macro->next) { + if (macro->c) { + CPrec_NewAddrPatch(macro->c, (void *) cprec_offset); + CPrec_AppendString(macro->c); + } + } + } while (++i < 0x800); + + i = 0; + do { + macro = macrohashtable[i]; + + if (macro) { + p = CPrec_AppendAlign(); + if (cprec_dowrite) + cprec_header->macrotable[i] = p; + + while (1) { + CPrec_AppendPointer(NULL); + CPrec_AppendNamePatch(macro->name); + CPrec_AppendPointerPatch(macro->c); + CPrec_AppendWord16(macro->xC); + CPrec_AppendByte(macro->is_special); + CPrec_AppendByte(macro->xF); + + for (j = 1; j < (macro->xC & 0x7FFF); j++) + CPrec_AppendNamePatch(macro->names[j - 1]); + + macro = macro->next; + if (!macro) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(&p->next, next); + p = next; + } + } + } while (++i < 0x800); +} + +static BClassList *CPrec_GetClassAccessPatch(BClassList *path) { + AddrPatch *addrPatch; + BClassList *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(path))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(path, first); + + while (1) { + CPrec_AppendData(path, sizeof(BClassList)); + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(path->type)); + if (!path->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + path = path->next; + } + + return first; +} + +static int CPrec_PointerHash(TypePointer *type) { + Type *target; + int work; + FuncArg *arg; + + work = type->qual; + target = type->target; + +restart: + switch (target->type) { + case TYPECLASS: + if (TYPE_CLASS(target)->classname) + work += TYPE_CLASS(target)->classname->hashval; + break; + case TYPEENUM: + if (TYPE_ENUM(target)->enumname) + work += TYPE_ENUM(target)->enumname->hashval; + target = TYPE_ENUM(target)->enumtype; + work += 3; + case TYPEINT: + case TYPEFLOAT: + work += TYPE_INTEGRAL(target)->integral; + break; + case TYPEPOINTER: + work += TYPE_POINTER(target)->qual; + target = TYPE_POINTER(target)->target; + goto restart; + case TYPEARRAY: + work += target->size; + target = TYPE_POINTER(target)->target; + goto restart; + case TYPEFUNC: + work += TYPE_FUNC(target)->functype->type; + work += TYPE_FUNC(target)->functype->size; + for (arg = TYPE_FUNC(target)->args; arg; arg = arg->next) { + if (arg->type) { + work += arg->type->type; + work += arg->type->size; + } + } + break; + } + + work += target->type + target->size; + return (work + (work >> 24) + (work >> 16) + (work >> 8)) & 0x3FF; +} + +static TypePointer *CPrec_GetTypePointerPatch(TypePointer *tptr) { + TypePointer *p; + int hash; + PointerHash *phash; + TypePointer *scan1; + TypePointer *scan2; + + if (tptr->qual & Q_IS_OBJC_ID) { + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(tptr, p); + CPrec_AppendData(tptr, sizeof(TypeObjCID)); + if (TYPE_OBJC_ID(tptr)->protocols) + CPrec_NewPointerPatch(&TYPE_OBJC_ID(p)->protocols, CPrec_GetObjCProtocolListPatch(TYPE_OBJC_ID(tptr)->protocols)); + } else { + if (!copts.faster_pch_gen && cprec_dowrite && tptr->size > 0) { + hash = CPrec_PointerHash(tptr); + for (phash = cprec_pointerhash[hash]; phash; phash = phash->next) { + scan1 = tptr; + scan2 = phash->tptr; + check_again: + if (scan1->type == scan2->type && scan1->size == scan2->size && scan1->qual == scan2->qual) { + scan1 = TYPE_POINTER(TPTR_TARGET(scan1)); + scan2 = TYPE_POINTER(TPTR_TARGET(scan2)); + if (scan1->type == TYPEPOINTER && scan1->type == TYPEARRAY) + goto check_again; + if (scan1 == scan2) + return phash->prec_tptr; + } + } + + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(tptr, p); + + phash = lalloc(sizeof(PointerHash)); + phash->tptr = tptr; + phash->prec_tptr = p; + phash->next = cprec_pointerhash[hash]; + cprec_pointerhash[hash] = phash; + } else { + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(tptr, p); + } + + CPrec_AppendData(tptr, sizeof(TypePointer)); + } + + CPrec_NewPointerPatch(&p->target, CPrec_GetTypePatch(tptr->target)); + return p; +} + +static TypeEnum *CPrec_GetTypeEnumPatch(TypeEnum *type) { + TypeEnum *p = CPrec_AppendAlign(); + + CPrec_NewAddrPatch(type, p); + CPrec_AppendData(type, sizeof(TypeEnum)); + + if (type->nspace) + CPrec_NewPointerPatch(&p->nspace, CPrec_GetNameSpacePatch(type->nspace)); + if (type->enumlist) + CPrec_NewPointerPatch(&p->enumlist, CPrec_GetObjEnumConstPatch(type->enumlist)); + + CPrec_NewPointerPatch(&p->enumtype, CPrec_GetTypePatch(type->enumtype)); + if (type->enumname) + CPrec_NamePatch(&p->enumname, type->enumname); + + return p; +} + +static TypeBitfield *CPrec_GetTypeBitfieldPatch(TypeBitfield *type) { + TypeBitfield *p = CPrec_AppendAlign(); + + CPrec_NewAddrPatch(type, p); + CPrec_AppendData(type, sizeof(TypeBitfield)); + CPrec_NewPointerPatch(&p->bitfieldtype, CPrec_GetTypePatch(type->bitfieldtype)); + + return p; +} + +static TypeStruct *CPrec_GetTypeStructPatch(TypeStruct *tstruct) { + StructMember *member; + TypeStruct *p; + StructMember *current, *next; + + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(tstruct, p); + CPrec_AppendData(tstruct, sizeof(TypeStruct)); + + if (tstruct->name) + CPrec_NamePatch(&p->name, tstruct->name); + + if ((member = tstruct->members)) { + current = CPrec_AppendAlign(); + CPrec_NewPointerPatch(&p->members, current); + + while (1) { + CPrec_AppendData(member, sizeof(StructMember)); + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(member->type)); + CPrec_NamePatch(¤t->name, member->name); + + if (!member->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + + member = member->next; + } + } + + return p; +} + +static ExceptSpecList *CPrec_GetExceptSpecPatch(ExceptSpecList *exspec) { + ExceptSpecList *first, *current, *next; + + first = current = CPrec_AppendAlign(); + while (exspec) { + CPrec_AppendData(exspec, sizeof(ExceptSpecList)); + if (exspec->type) + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(exspec->type)); + + if (!exspec->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + exspec = exspec->next; + } + + return first; +} + +static FuncArg *CPrec_GetArgListPatch(FuncArg *lst, Boolean includeNames) { + FuncArg *first, *current, *next; + AddrPatch *addrPatch; + + if ((addrPatch = CPrec_FindAddrPatch(lst))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + while (1) { + if (!includeNames) + lst->name = NULL; + CPrec_AppendData(lst, sizeof(FuncArg)); + if (includeNames && lst->name) + CPrec_NamePatch(¤t->name, lst->name); + + if (lst->dexpr) + CPrec_NewPointerPatch(¤t->dexpr, CPrec_GetExpressionPatch(lst->dexpr)); + if (lst->type) + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(lst->type)); + else + CError_FATAL(1167); + + if (!lst->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(lst->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + lst = lst->next; + CPrec_NewAddrPatch(lst, next); + } + + return first; +} + +static TypeFunc *CPrec_GetTypeFuncPatch(TypeFunc *type) { + TypeFunc *p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(type, p); + + CPrec_AppendData(type, (type->flags & FUNC_METHOD) ? sizeof(TypeMemberFunc) : sizeof(TypeFunc)); + + CPrec_NewPointerPatch(&p->functype, CPrec_GetTypePatch(type->functype)); + if (type->args) + CPrec_NewPointerPatch(&p->args, CPrec_GetArgListPatch(type->args, (type->flags & FUNC_IS_TEMPL_ANY) != 0)); + if (type->exspecs) + CPrec_NewPointerPatch(&p->exspecs, CPrec_GetExceptSpecPatch(type->exspecs)); + if (type->flags & FUNC_METHOD) + CPrec_NewPointerPatch(&TYPE_METHOD(p)->theclass, CPrec_GetTypePatch((Type *) TYPE_METHOD(type)->theclass)); + + return p; +} + +static TypeMemberPointer *CPrec_GetTypeMemberPointerPatch(TypeMemberPointer *type) { + TypeMemberPointer *p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(type, p); + + CPrec_AppendData(type, sizeof(TypeMemberPointer)); + + CPrec_NewPointerPatch(&p->ty1, CPrec_GetTypePatch(type->ty1)); + CPrec_NewPointerPatch(&p->ty2, CPrec_GetTypePatch(type->ty2)); + + return p; +} + +static TypeTemplDep *CPrec_GetTypeTemplDepPatch(TypeTemplDep *type) { + TypeTemplDep *p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(type, p); + + CPrec_AppendData(type, sizeof(TypeTemplDep)); + + switch (type->dtype) { + case TEMPLDEP_ARGUMENT: + break; + case TEMPLDEP_QUALNAME: + CPrec_NewPointerPatch(&p->u.qual.type, CPrec_GetTypeTemplDepPatch(type->u.qual.type)); + CPrec_NamePatch(&p->u.qual.name, type->u.qual.name); + break; + case TEMPLDEP_TEMPLATE: + CPrec_NewPointerPatch(&p->u.templ.templ, CPrec_GetTypePatch((Type *) type->u.templ.templ)); + CPrec_NewPointerPatch(&p->u.templ.args, CPrec_GetTemplateArgPatch(type->u.templ.args)); + break; + case TEMPLDEP_ARRAY: + CPrec_NewPointerPatch(&p->u.array.type, CPrec_GetTypePatch(type->u.array.type)); + CPrec_NewPointerPatch(&p->u.array.index, CPrec_GetExpressionPatch(type->u.array.index)); + break; + case TEMPLDEP_QUALTEMPL: + CPrec_NewPointerPatch(&p->u.qualtempl.type, CPrec_GetTypeTemplDepPatch(type->u.qualtempl.type)); + CPrec_NewPointerPatch(&p->u.qualtempl.args, CPrec_GetTemplateArgPatch(type->u.qualtempl.args)); + break; + case TEMPLDEP_BITFIELD: + CPrec_NewPointerPatch(&p->u.bitfield.type, CPrec_GetTypePatch(type->u.bitfield.type)); + CPrec_NewPointerPatch(&p->u.bitfield.size, CPrec_GetExpressionPatch(type->u.bitfield.size)); + break; + default: + CError_FATAL(1295); + } + + return p; +} + +static ClassList *CPrec_GetClassListPatch(ClassList *cl) { + AddrPatch *addrPatch; + ClassList *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(cl))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(cl, first); + + do { + CPrec_AppendData(cl, sizeof(ClassList)); + CPrec_NewPointerPatch(¤t->base, CPrec_GetTypePatch((Type *) cl->base)); + + if (!cl->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(cl->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + cl = cl->next; + } + } while (1); + + return first; +} + +static VClassList *CPrec_GetVClassListPatch(VClassList *vcl) { + VClassList *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(vcl, sizeof(VClassList)); + CPrec_NewPointerPatch(¤t->base, CPrec_GetTypePatch((Type *) vcl->base)); + + if (!vcl->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + vcl = vcl->next; + } while (1); + + return first; +} + +static ClassFriend *CPrec_GetClassFriendPatch(ClassFriend *cf) { + ClassFriend *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(cf, sizeof(ClassFriend)); + if (cf->isclass) + CPrec_NewPointerPatch(¤t->u.theclass, CPrec_GetTypePatch((Type *) cf->u.theclass)); + else + CPrec_NewPointerPatch(¤t->u.theclass, CPrec_GetObjectPatch(cf->u.obj)); + + if (!cf->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + cf = cf->next; + } while (1); + + return first; +} + +static BClassList *CPrec_GetBClassListPatch(BClassList *bcl) { + BClassList *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(bcl, sizeof(BClassList)); + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch((Type *) bcl->type)); + + if (!bcl->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + bcl = bcl->next; + } while (1); + + return first; +} + +static VTable *CPrec_GetVTablePatch(VTable *vtbl) { + VTable *p = CPrec_AppendAlign(); + CPrec_AppendData(vtbl, sizeof(VTable)); + + if (vtbl->object) + CPrec_NewPointerPatch(&p->object, CPrec_GetObjectPatch(vtbl->object)); + if (vtbl->owner) + CPrec_NewPointerPatch(&p->owner, CPrec_GetTypePatch((Type *) vtbl->owner)); + + return p; +} + +static SOMReleaseOrder *CPrec_GetSOMReleaseOrderPatch(SOMReleaseOrder *sro) { + SOMReleaseOrder *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(sro, sizeof(SOMReleaseOrder)); + CPrec_NamePatch(¤t->name, sro->name); + if (!sro->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + sro = sro->next; + } while (1); + + return first; +} + +static SOMInfo *CPrec_GetSOMInfoPatch(SOMInfo *som) { + SOMInfo *p = CPrec_AppendAlign(); + CPrec_AppendData(som, sizeof(SOMInfo)); + + if (som->metaclass) + CPrec_NewPointerPatch(&p->metaclass, CPrec_GetTypePatch((Type *) som->metaclass)); + if (som->classdataobject) + CPrec_NewPointerPatch(&p->classdataobject, CPrec_GetObjectPatch(som->classdataobject)); + if (som->order) + CPrec_NewPointerPatch(&p->order, CPrec_GetSOMReleaseOrderPatch(som->order)); + + return p; +} + +static ObjCMethodArg *CPrec_GetObjCMethodArgPatch(ObjCMethodArg *arg) { + ObjCMethodArg *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(arg, sizeof(ObjCMethod)); + if (arg->selector) + CPrec_NamePatch(¤t->selector, arg->selector); + if (arg->name) + CPrec_NamePatch(¤t->name, arg->name); + if (arg->type) + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(arg->type)); + + if (!arg->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + arg = arg->next; + } while (1); + + return first; +} + +static ObjCMethodList *CPrec_GetObjCMethodListPatch(ObjCMethodList *lst) { + AddrPatch *addrPatch; + ObjCMethodList *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(lst))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(lst, first); + + do { + CPrec_AppendData(lst, sizeof(ObjCMethodList)); + if (lst->method) + CPrec_NewPointerPatch(¤t->method, CPrec_GetObjCMethodPatch(lst->method)); + + if (!lst->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(lst->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + lst = lst->next; + CPrec_NewAddrPatch(lst, next); + } + } while (1); + + return first; +} + +static ObjCSelector *CPrec_GetObjCSelectorPatch(ObjCSelector *sel) { + AddrPatch *addrPatch; + ObjCSelector *current, *first, *next; + + if ((addrPatch = CPrec_FindAddrPatch(sel))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(sel, first); + + do { + CPrec_AppendData(sel, sizeof(ObjCSelector)); + if (sel->selobject) + CPrec_NewPointerPatch(¤t->selobject, CPrec_GetObjectPatch(sel->selobject)); + CPrec_NamePatch(¤t->name, sel->name); + if (sel->methods) + CPrec_NewPointerPatch(¤t->methods, CPrec_GetObjCMethodListPatch(sel->methods)); + + if (!sel->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(sel->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + sel = sel->next; + CPrec_NewAddrPatch(sel, next); + } + } while (1); + + return first; +} + +static ObjCMethod *CPrec_GetObjCMethodPatch(ObjCMethod *meth) { + // does not match - affected by weirdness where the arg goes into r31 instead of r28 + AddrPatch *addrPatch; + ObjCMethod *current, *first, *next; + + if ((addrPatch = CPrec_FindAddrPatch(meth))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(meth, first); + + do { + CPrec_AppendData(meth, sizeof(ObjCMethod)); + if (meth->object) + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(meth->object)); + if (meth->functype) + CPrec_NewPointerPatch(¤t->functype, CPrec_GetTypePatch((Type *) meth->functype)); + if (meth->selector) + CPrec_NewPointerPatch(¤t->selector, CPrec_GetObjCSelectorPatch(meth->selector)); + if (meth->return_type) + CPrec_NewPointerPatch(¤t->return_type, CPrec_GetTypePatch(meth->return_type)); + if (meth->selector_args) + CPrec_NewPointerPatch(¤t->selector_args, CPrec_GetObjCMethodArgPatch(meth->selector_args)); + + if (!meth->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(meth->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + meth = meth->next; + CPrec_NewAddrPatch(meth, next); + } + } while (1); + + return first; +} + +static ObjCProtocol *CPrec_GetObjCProtocolPatch(ObjCProtocol *prot) { + AddrPatch *addrPatch; + ObjCProtocol *current, *first, *next; + + if ((addrPatch = CPrec_FindAddrPatch(prot))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(prot, first); + + do { + CPrec_AppendData(prot, sizeof(ObjCProtocol)); + CPrec_NamePatch(¤t->name, prot->name); + if (prot->protocols) + CPrec_NewPointerPatch(¤t->protocols, CPrec_GetObjCProtocolListPatch(prot->protocols)); + if (prot->methods) + CPrec_NewPointerPatch(¤t->methods, CPrec_GetObjCMethodPatch(prot->methods)); + if (prot->object) + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(prot->object)); + + if (!prot->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(prot->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + prot = prot->next; + CPrec_NewAddrPatch(prot, next); + } + } while (1); + + return first; +} + +static ObjCProtocolList *CPrec_GetObjCProtocolListPatch(ObjCProtocolList *lst) { + AddrPatch *addrPatch; + ObjCProtocolList *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(lst))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(lst, first); + + do { + CPrec_AppendData(lst, sizeof(ObjCProtocolList)); + CPrec_NewPointerPatch(¤t->protocol, CPrec_GetObjCProtocolPatch(lst->protocol)); + + if (!lst->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + lst = lst->next; + } while (1); + + return first; +} + +static ObjCCategory *CPrec_GetObjCCategoryPatch(ObjCCategory *cat) { + AddrPatch *addrPatch; + ObjCCategory *current, *first, *next; + + if ((addrPatch = CPrec_FindAddrPatch(cat))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(cat, first); + + do { + CPrec_AppendData(cat, sizeof(ObjCCategory)); + CPrec_NamePatch(¤t->name, cat->name); + if (cat->protocols) + CPrec_NewPointerPatch(¤t->protocols, CPrec_GetObjCProtocolListPatch(cat->protocols)); + if (cat->methods) + CPrec_NewPointerPatch(¤t->methods, CPrec_GetObjCMethodPatch(cat->methods)); + + if (!cat->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(cat->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + cat = cat->next; + CPrec_NewAddrPatch(cat, next); + } + } while (1); + + return first; +} + +static ObjCInfo *CPrec_GetObjCInfoPatch(ObjCInfo *info) { + ObjCInfo *p = CPrec_AppendAlign(); + CPrec_AppendData(info, sizeof(ObjCInfo)); + + if (info->classobject) + CPrec_NewPointerPatch(&p->classobject, CPrec_GetObjectPatch(info->classobject)); + if (info->metaobject) + CPrec_NewPointerPatch(&p->metaobject, CPrec_GetObjectPatch(info->metaobject)); + if (info->classrefobj) + CPrec_NewPointerPatch(&p->classrefobj, CPrec_GetObjectPatch(info->classrefobj)); + if (info->methods) + CPrec_NewPointerPatch(&p->methods, CPrec_GetObjCMethodPatch(info->methods)); + if (info->protocols) + CPrec_NewPointerPatch(&p->protocols, CPrec_GetObjCProtocolListPatch(info->protocols)); + if (info->categories) + CPrec_NewPointerPatch(&p->categories, CPrec_GetObjCCategoryPatch(info->categories)); + + return p; +} + +static TemplArg *CPrec_GetTemplateArgPatch(TemplArg *arg) { + TemplArg *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(arg, sizeof(TemplArg)); + switch (arg->pid.type) { + case TPT_TYPE: + if (arg->data.typeparam.type) + CPrec_NewPointerPatch(¤t->data.typeparam.type, CPrec_GetTypePatch(arg->data.typeparam.type)); + break; + case TPT_NONTYPE: + if (arg->data.paramdecl.expr) + CPrec_NewPointerPatch(¤t->data.paramdecl.expr, CPrec_GetExpressionPatch(arg->data.paramdecl.expr)); + break; + case TPT_TEMPLATE: + if (arg->data.ttargtype) + CPrec_NewPointerPatch(¤t->data.ttargtype, CPrec_GetTypePatch(arg->data.ttargtype)); + break; + default: + CError_FATAL(1879); + } + + if (!arg->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + arg = arg->next; + } while (1); + + return first; +} + +static TemplParam *CPrec_GetTemplateParamPatch(TemplParam *param) { + // register swap issues + TemplParam *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(param, sizeof(TemplParam)); + if (param->name) + CPrec_NamePatch(¤t->name, param->name); + + switch (param->pid.type) { + case TPT_TYPE: + if (param->data.typeparam.type) + CPrec_NewPointerPatch(¤t->data.typeparam.type, CPrec_GetTypePatch(param->data.typeparam.type)); + break; + case TPT_NONTYPE: + CPrec_NewPointerPatch(¤t->data.paramdecl.type, CPrec_GetTypePatch(param->data.paramdecl.type)); + if (param->data.paramdecl.defaultarg) + CPrec_NewPointerPatch(¤t->data.paramdecl.defaultarg, CPrec_GetExpressionPatch(param->data.paramdecl.defaultarg)); + break; + case TPT_TEMPLATE: + if (param->data.templparam.plist) + CPrec_NewPointerPatch(¤t->data.templparam.plist, CPrec_GetTemplateParamPatch(param->data.templparam.plist)); + CError_ASSERT(1953, !param->data.templparam.defaultarg); + break; + default: + CError_FATAL(1958); + } + + if (!param->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + param = param->next; + } while (1); + + return first; +} + +static TStreamElement *CPrec_GetTStreamPatch(TStreamElement *tokens, SInt32 count) { + TStreamElement elem; + TStreamElement *first, *current, *scan; + SInt32 x; + + scan = tokens; + x = 0; + while (x < count) { + elem = *scan; + memclrw(scan, sizeof(TStreamElement)); + + scan->tokentype = elem.tokentype; + switch (elem.tokentype) { + case TK_IDENTIFIER: + scan->data.tkidentifier = elem.data.tkidentifier; + break; + case TK_INTCONST: + scan->subtype = elem.subtype; + scan->data.tkintconst = elem.data.tkintconst; + break; + case TK_FLOATCONST: + scan->subtype = elem.subtype; + scan->data.tkfloatconst = elem.data.tkfloatconst; + break; + case TK_STRING: + case TK_STRING_WIDE: + scan->subtype = elem.subtype; + scan->data.tkstring = elem.data.tkstring; + break; + } + x++; + scan++; + } + + first = current = CPrec_AppendAlign(); + CPrec_AppendData(tokens, count * sizeof(TStreamElement)); + + if (cprec_dowrite) { + TokenPatch *tp = lalloc(sizeof(TokenPatch)); + tp->tokens = current; + tp->count = count; + tp->next = cprec_tokenpatches; + cprec_tokenpatches = tp; + } + + x = 0; + while (x < count) { + switch (tokens->tokentype) { + case TK_IDENTIFIER: + CPrec_NamePatch(¤t->data.tkidentifier, tokens->data.tkidentifier); + break; + case TK_INTCONST: + case TK_FLOATCONST: + break; + case TK_STRING: + case TK_STRING_WIDE: + CPrec_RawMemPatch(¤t->data.tkstring.data, tokens->data.tkstring.data, tokens->data.tkstring.size); + break; + case TK_EOL: + break; + default: + if (tokens->tokentype < 0) + CError_FATAL(2063); + } + x++; + tokens++; + current++; + } + + return first; +} + +static TemplFuncInstance *CPrec_GetTemplFuncInstancePatch(TemplFuncInstance *inst) { + AddrPatch *addrPatch; + TemplFuncInstance *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(inst))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(inst, first); + + do { + CPrec_AppendData(inst, sizeof(TemplFuncInstance)); + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(inst->object)); + CPrec_NewPointerPatch(¤t->args, CPrec_GetTemplateArgPatch(inst->args)); + + if (!inst->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(inst->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + inst = inst->next; + CPrec_NewAddrPatch(inst, next); + } + } while (1); + + return first; +} + +static TemplateMember *CPrec_GetTemplateMemberPatch(TemplateMember *memb) { + TemplateMember *current, *first, *next; + first = current = CPrec_AppendAlign(); + + do { + memclrw(&memb->fileoffset, sizeof(FileOffsetInfo)); + memb->srcfile = NULL; + memb->startoffset = 0; + memb->endoffset = 0; + + CPrec_AppendData(memb, sizeof(TemplateMember)); + if (memb->params) + CPrec_NewPointerPatch(¤t->params, CPrec_GetTemplateParamPatch(memb->params)); + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(memb->object)); + if (memb->stream.firsttoken) + CPrec_NewPointerPatch(¤t->stream.firsttoken, CPrec_GetTStreamPatch(memb->stream.firsttoken, memb->stream.tokens)); + + if (!memb->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + memb = memb->next; + } while (1); + + return first; +} + +static TemplPartialSpec *CPrec_GetTemplPartialSpecPatch(TemplPartialSpec *pspec) { + TemplPartialSpec *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(pspec, sizeof(TemplPartialSpec)); + if (pspec->templ) + CPrec_NewPointerPatch(¤t->templ, CPrec_GetTypePatch((Type *) pspec->templ)); + if (pspec->args) + CPrec_NewPointerPatch(¤t->args, CPrec_GetTemplateArgPatch(pspec->args)); + + if (!pspec->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + pspec = pspec->next; + } while (1); + + return first; +} + +static TemplateFriend *CPrec_GetTemplateFriendPatch(TemplateFriend *frnd) { + TemplateFriend *p; + + memclrw(&frnd->fileoffset, sizeof(FileOffsetInfo)); + p = CPrec_AppendAlign(); + CPrec_AppendData(frnd, sizeof(TemplateFriend)); + + if (frnd->decl.thetype) + CPrec_NewPointerPatch(&p->decl.thetype, CPrec_GetTypePatch(frnd->decl.thetype)); + if (frnd->decl.nspace) + CPrec_NewPointerPatch(&p->decl.nspace, CPrec_GetNameSpacePatch(frnd->decl.nspace)); + if (frnd->decl.name) + CPrec_NamePatch(&p->decl.name, frnd->decl.name); + if (frnd->decl.expltargs) + CPrec_NewPointerPatch(&p->decl.expltargs, CPrec_GetTemplateArgPatch(frnd->decl.expltargs)); + if (frnd->stream.firsttoken) + CPrec_NewPointerPatch(&p->stream.firsttoken, CPrec_GetTStreamPatch(frnd->stream.firsttoken, frnd->stream.tokens)); + + return p; +} + +static TemplateAction *CPrec_GetTemplateActionPatch(TemplateAction *act) { + // register swap issue + TemplateAction *current, *first, *next; + first = current = CPrec_AppendAlign(); + + do { + memclrw(&act->source_ref, sizeof(TStreamElement)); + CPrec_AppendData(act, sizeof(TemplateAction)); + + switch (act->type) { + case TAT_NESTEDCLASS: + CPrec_NewPointerPatch(¤t->u.tclasstype, CPrec_GetTypePatch((Type *) act->u.tclasstype)); + break; + case TAT_ENUMTYPE: + CPrec_NewPointerPatch(¤t->u.enumtype, CPrec_GetTypePatch((Type *) act->u.enumtype)); + break; + case TAT_FRIEND: + CPrec_NewPointerPatch(¤t->u.tfriend, CPrec_GetTemplateFriendPatch(act->u.tfriend)); + break; + case TAT_ENUMERATOR: + CPrec_NewPointerPatch(¤t->u.enumerator.objenumconst, CPrec_GetObjEnumConstPatch(act->u.enumerator.objenumconst)); + if (act->u.enumerator.initexpr) + CPrec_NewPointerPatch(¤t->u.enumerator.initexpr, CPrec_GetExpressionPatch(act->u.enumerator.initexpr)); + break; + case TAT_BASE: + CPrec_NewPointerPatch(¤t->u.base.type, CPrec_GetTypePatch(act->u.base.type)); + if (act->u.base.insert_after) + CPrec_NewPointerPatch(¤t->u.base.insert_after, CPrec_GetClassListPatch(act->u.base.insert_after)); + break; + case TAT_OBJECTINIT: + CPrec_NewPointerPatch(¤t->u.objectinit.object, CPrec_GetObjectPatch(act->u.objectinit.object)); + CPrec_NewPointerPatch(¤t->u.objectinit.initexpr, CPrec_GetExpressionPatch(act->u.objectinit.initexpr)); + break; + case TAT_USINGDECL: + CPrec_NewPointerPatch(¤t->u.usingdecl.type, CPrec_GetTypeTemplDepPatch(act->u.usingdecl.type)); + break; + case TAT_OBJECTDEF: + CPrec_NewPointerPatch(¤t->u.refobj, CPrec_GetObjBasePatch(act->u.refobj)); + break; + default: + CError_FATAL(2410); + } + + if (!act->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + act = act->next; + } while (1); + + return first; +} + +static TemplateFunction *CPrec_GetTemplateFunctionPatch(TemplateFunction *tf) { + // the same cursed register swaps + AddrPatch *addrPatch; + TemplateFunction *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(tf))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(tf, first); + + do { + memclrw(&tf->deftoken, sizeof(TStreamElement)); + tf->srcfile = NULL; + tf->startoffset = 0; + tf->endoffset = 0; + + CPrec_AppendData(tf, sizeof(TemplateFunction)); + if (tf->unk4) + CPrec_NewPointerPatch(¤t->unk4, CPrec_GetTemplateFunctionPatch(tf->unk4)); + CPrec_NamePatch(¤t->name, tf->name); + if (tf->params) + CPrec_NewPointerPatch(¤t->params, CPrec_GetTemplateParamPatch(tf->params)); + if (tf->stream.firsttoken) + CPrec_NewPointerPatch(¤t->stream.firsttoken, CPrec_GetTStreamPatch(tf->stream.firsttoken, tf->stream.tokens)); + CPrec_NewPointerPatch(¤t->tfunc, CPrec_GetObjectPatch(tf->tfunc)); + if (tf->instances) + CPrec_NewPointerPatch(¤t->instances, CPrec_GetTemplFuncInstancePatch(tf->instances)); + + if (!tf->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(tf->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + tf = tf->next; + CPrec_NewAddrPatch(tf, next); + } + } while (1); + + return first; +} + +static TypeClass *CPrec_GetTypeClassPatch(TypeClass *tclass) { + TypeClass *first, *current, *next; + Boolean hasNextTempl, hasNextTemplInst; + first = current = CPrec_AppendAlign(); + + do_over: + hasNextTempl = hasNextTemplInst = 0; + CPrec_NewAddrPatch(tclass, current); + + if (tclass->flags & CLASS_IS_TEMPL) { + // template class + CPrec_AppendData(tclass, sizeof(TemplClass)); + if (TEMPL_CLASS(tclass)->next) + hasNextTempl = 1; + if (TEMPL_CLASS(tclass)->templ_parent) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->templ_parent, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->templ_parent)); + if (TEMPL_CLASS(tclass)->inst_parent) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->inst_parent, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->inst_parent)); + if (TEMPL_CLASS(tclass)->templ__params) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->templ__params, CPrec_GetTemplateParamPatch(TEMPL_CLASS(tclass)->templ__params)); + if (TEMPL_CLASS(tclass)->members) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->members, CPrec_GetTemplateMemberPatch(TEMPL_CLASS(tclass)->members)); + if (TEMPL_CLASS(tclass)->instances) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->instances, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->instances)); + if (TEMPL_CLASS(tclass)->pspec_owner) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->pspec_owner, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->pspec_owner)); + if (TEMPL_CLASS(tclass)->pspecs) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->pspecs, CPrec_GetTemplPartialSpecPatch(TEMPL_CLASS(tclass)->pspecs)); + if (TEMPL_CLASS(tclass)->actions) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->actions, CPrec_GetTemplateActionPatch(TEMPL_CLASS(tclass)->actions)); + } else if (tclass->flags & CLASS_IS_TEMPL_INST) { + // template class instance + CPrec_AppendData(tclass, sizeof(TemplClassInst)); + if (TEMPL_CLASS_INST(tclass)->next) + hasNextTemplInst = 1; + if (TEMPL_CLASS_INST(tclass)->parent) + CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->parent, CPrec_GetTypePatch((Type *) TEMPL_CLASS_INST(tclass)->parent)); + if (TEMPL_CLASS_INST(tclass)->templ) + CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->templ, CPrec_GetTypePatch((Type *) TEMPL_CLASS_INST(tclass)->templ)); + if (TEMPL_CLASS_INST(tclass)->inst_args) + CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->inst_args, CPrec_GetTemplateArgPatch(TEMPL_CLASS_INST(tclass)->inst_args)); + if (TEMPL_CLASS_INST(tclass)->oargs) + CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->oargs, CPrec_GetTemplateArgPatch(TEMPL_CLASS_INST(tclass)->oargs)); + } else { + // base + CPrec_AppendData(tclass, sizeof(TypeClass)); + } + + if (tclass->nspace) + CPrec_NewPointerPatch(¤t->nspace, CPrec_GetNameSpacePatch(tclass->nspace)); + if (tclass->classname) + CPrec_NamePatch(¤t->classname, tclass->classname); + if (tclass->bases) + CPrec_NewPointerPatch(¤t->bases, CPrec_GetClassListPatch(tclass->bases)); + if (tclass->vbases) + CPrec_NewPointerPatch(¤t->vbases, CPrec_GetVClassListPatch(tclass->vbases)); + if (tclass->ivars) + CPrec_NewPointerPatch(¤t->ivars, CPrec_GetObjMemberVarPatch(tclass->ivars)); + if (tclass->friends) + CPrec_NewPointerPatch(¤t->friends, CPrec_GetClassFriendPatch(tclass->friends)); + if (tclass->vtable) + CPrec_NewPointerPatch(¤t->vtable, CPrec_GetVTablePatch(tclass->vtable)); + if (tclass->sominfo) + CPrec_NewPointerPatch(¤t->sominfo, CPrec_GetSOMInfoPatch(tclass->sominfo)); + if (tclass->objcinfo) + CPrec_NewPointerPatch(¤t->objcinfo, CPrec_GetObjCInfoPatch(tclass->objcinfo)); + + if (hasNextTempl) { + AddrPatch *addrPatch = CPrec_FindAddrPatch(TEMPL_CLASS(tclass)->next); + if (!addrPatch) { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->next, next); + current = next; + tclass = (TypeClass *) TEMPL_CLASS(tclass)->next; + goto do_over; + } else { + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->next, addrPatch->value); + } + } + + if (hasNextTemplInst) { + AddrPatch *addrPatch = CPrec_FindAddrPatch(TEMPL_CLASS_INST(tclass)->next); + if (!addrPatch) { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->next, next); + current = next; + tclass = (TypeClass *) TEMPL_CLASS_INST(tclass)->next; + goto do_over; + } else { + CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->next, addrPatch->value); + } + } + + return first; +} + +static Type *CPrec_GetTypePatch(Type *type) { + AddrPatch *addrPatch = CPrec_FindAddrPatch(type); + if (addrPatch) + return addrPatch->value; + + switch (type->type) { + case TYPEPOINTER: + case TYPEARRAY: + return (Type *) CPrec_GetTypePointerPatch(TYPE_POINTER(type)); + case TYPEENUM: + return (Type *) CPrec_GetTypeEnumPatch(TYPE_ENUM(type)); + case TYPEBITFIELD: + return (Type *) CPrec_GetTypeBitfieldPatch(TYPE_BITFIELD(type)); + case TYPESTRUCT: + return (Type *) CPrec_GetTypeStructPatch(TYPE_STRUCT(type)); + case TYPEFUNC: + return (Type *) CPrec_GetTypeFuncPatch(TYPE_FUNC(type)); + case TYPEMEMBERPOINTER: + return (Type *) CPrec_GetTypeMemberPointerPatch(TYPE_MEMBER_POINTER(type)); + case TYPETEMPLATE: + return (Type *) CPrec_GetTypeTemplDepPatch(TYPE_TEMPLATE(type)); + case TYPECLASS: + return (Type *) CPrec_GetTypeClassPatch(TYPE_CLASS(type)); + case TYPEVOID: + case TYPEINT: + case TYPEFLOAT: + case TYPELABEL: + case TYPEOBJCID: + case TYPETEMPLDEPEXPR: + default: + CError_FATAL(2796); + return NULL; + } +} + +static ExceptionAction *CPrec_GetExceptionPatch(ExceptionAction *exc) { + ExceptionAction *first, *current, *next; + + first = current = CPrec_AppendAlign(); +repeat: + CPrec_AppendData(exc, sizeof(ExceptionAction)); + switch (exc->type) { + case EAT_DESTROYLOCAL: + CPrec_NewPointerPatch(¤t->data.destroy_local.dtor, CPrec_GetObjectPatch(exc->data.destroy_local.dtor)); + break; + case EAT_DESTROYLOCALCOND: + CPrec_NewPointerPatch(¤t->data.destroy_local_cond.dtor, CPrec_GetObjectPatch(exc->data.destroy_local_cond.dtor)); + break; + case EAT_DESTROYLOCALOFFSET: + CPrec_NewPointerPatch(¤t->data.destroy_local_offset.dtor, CPrec_GetObjectPatch(exc->data.destroy_local_offset.dtor)); + break; + case EAT_DESTROYLOCALPOINTER: + CPrec_NewPointerPatch(¤t->data.destroy_local_pointer.dtor, CPrec_GetObjectPatch(exc->data.destroy_local_pointer.dtor)); + break; + case EAT_DESTROYLOCALARRAY: + CPrec_NewPointerPatch(¤t->data.destroy_local_array.dtor, CPrec_GetObjectPatch(exc->data.destroy_local_array.dtor)); + break; + case EAT_DESTROYPARTIALARRAY: + break; + case EAT_DESTROYMEMBER: + case EAT_DESTROYBASE: + CPrec_NewPointerPatch(¤t->data.destroy_member.dtor, CPrec_GetObjectPatch(exc->data.destroy_member.dtor)); + break; + case EAT_DESTROYMEMBERCOND: + CPrec_NewPointerPatch(¤t->data.destroy_member_cond.dtor, CPrec_GetObjectPatch(exc->data.destroy_member_cond.dtor)); + break; + case EAT_DESTROYMEMBERARRAY: + CPrec_NewPointerPatch(¤t->data.destroy_member_array.dtor, CPrec_GetObjectPatch(exc->data.destroy_member_array.dtor)); + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + CPrec_NewPointerPatch(¤t->data.delete_pointer.deletefunc, CPrec_GetObjectPatch(exc->data.delete_pointer.deletefunc)); + break; + case EAT_DELETEPOINTERCOND: + CPrec_NewPointerPatch(¤t->data.delete_pointer_cond.deletefunc, CPrec_GetObjectPatch(exc->data.delete_pointer_cond.deletefunc)); + break; + case EAT_CATCHBLOCK: + if (exc->data.catch_block.catch_typeid) { + CPrec_NewPointerPatch(¤t->data.catch_block.catch_typeid, CPrec_GetObjectPatch(exc->data.catch_block.catch_typeid)); + CPrec_NewPointerPatch(¤t->data.catch_block.catch_type, CPrec_GetTypePatch(exc->data.catch_block.catch_type)); + } + break; + case EAT_ACTIVECATCHBLOCK: + break; + case EAT_SPECIFICATION: + if (exc->data.specification.unexp_id) { + int x; + char *ptrs; + ptrs = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->data.specification.unexp_id, ptrs); + CPrec_AppendData(exc->data.specification.unexp_id, sizeof(Object *) * exc->data.specification.unexp_ids); + for (x = 0; x < exc->data.specification.unexp_ids; x++) { + CPrec_NewPointerPatch(ptrs + x * sizeof(Object *), CPrec_GetObjectPatch(exc->data.specification.unexp_id[x])); + } + } + break; + case EAT_TERMINATE: + break; + default: + CError_FATAL(2905); + } + + if (exc->prev) { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->prev, next); + current = next; + exc = exc->prev; + goto repeat; + } + return first; +} + +static ENodeList *CPrec_GetExpressionListPatch(ENodeList *lst) { + ENodeList *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(lst, sizeof(ENodeList)); + CPrec_NewPointerPatch(¤t->node, CPrec_GetExpressionPatch(lst->node)); + + if (!lst->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + lst = lst->next; + } while (1); + + return first; +} + +static EMemberInfo *CPrec_GetEMemberInfoPatch(EMemberInfo *emember) { + EMemberInfo *p; + + CError_FATAL(2953); + + p = CPrec_AppendAlign(); + CPrec_AppendData(emember, sizeof(EMemberInfo)); + + if (emember->path) + CPrec_NewPointerPatch(&p->path, CPrec_GetClassAccessPatch(emember->path)); + if (emember->expr) + CPrec_NewPointerPatch(&p->expr, CPrec_GetExpressionPatch(emember->expr)); + CError_ASSERT(2968, !emember->templargs); + CPrec_NewPointerPatch(&p->list, CPrec_GetNameSpaceObjectListPatch(emember->list)); + + return p; +} + +static ENode *CPrec_GetExpressionPatch(ENode *expr) { + ENode *p; + + if (ENODE_IS(expr, ETEMPLDEP) && expr->data.templdep.subtype == TDE_SOURCEREF) + expr->data.templdep.u.sourceref.token = NULL; + + p = CPrec_AppendAlign(); + CPrec_AppendData(expr, sizeof(ENode)); + + CPrec_NewPointerPatch(&p->rtype, CPrec_GetTypePatch(expr->rtype)); + + switch (expr->type) { + ENODE_CASE_MONADIC: + CPrec_NewPointerPatch(&p->data.monadic, CPrec_GetExpressionPatch(expr->data.monadic)); + break; + ENODE_CASE_DIADIC_ALL: + CPrec_NewPointerPatch(&p->data.diadic.left, CPrec_GetExpressionPatch(expr->data.diadic.left)); + CPrec_NewPointerPatch(&p->data.diadic.right, CPrec_GetExpressionPatch(expr->data.diadic.right)); + break; + case ECOND: + CPrec_NewPointerPatch(&p->data.cond.cond, CPrec_GetExpressionPatch(expr->data.cond.cond)); + CPrec_NewPointerPatch(&p->data.cond.expr1, CPrec_GetExpressionPatch(expr->data.cond.expr1)); + CPrec_NewPointerPatch(&p->data.cond.expr2, CPrec_GetExpressionPatch(expr->data.cond.expr2)); + break; + case ESTRINGCONST: + CPrec_RawMemPatch(&p->data.string.data, expr->data.string.data, expr->data.string.size); + break; + case EOBJREF: + CPrec_NewPointerPatch(&p->data.objref, CPrec_GetObjectPatch(expr->data.objref)); + break; + case EOBJLIST: + CPrec_NewPointerPatch(&p->data.objlist.list, CPrec_GetNameSpaceObjectListPatch(expr->data.objlist.list)); + CError_ASSERT(3043, !expr->data.objlist.templargs); + if (expr->data.objlist.name) + CPrec_NamePatch(&p->data.objlist.name, expr->data.objlist.name); + break; + case EMFPOINTER: + CPrec_NewPointerPatch(&p->data.mfpointer.accessnode, CPrec_GetExpressionPatch(expr->data.mfpointer.accessnode)); + CPrec_NewPointerPatch(&p->data.mfpointer.mfpointer, CPrec_GetExpressionPatch(expr->data.mfpointer.mfpointer)); + break; + case ENULLCHECK: + CPrec_NewPointerPatch(&p->data.nullcheck.nullcheckexpr, CPrec_GetExpressionPatch(expr->data.nullcheck.nullcheckexpr)); + CPrec_NewPointerPatch(&p->data.nullcheck.condexpr, CPrec_GetExpressionPatch(expr->data.nullcheck.condexpr)); + break; + case ETEMP: + CPrec_NewPointerPatch(&p->data.temp.type, CPrec_GetTypePatch(expr->data.temp.type)); + break; + case EFUNCCALL: + case EFUNCCALLP: + CPrec_NewPointerPatch(&p->data.funccall.funcref, CPrec_GetExpressionPatch(expr->data.funccall.funcref)); + CPrec_NewPointerPatch(&p->data.funccall.functype, CPrec_GetTypePatch(TYPE(expr->data.funccall.functype))); + if (expr->data.funccall.args) + CPrec_NewPointerPatch(&p->data.funccall.args, CPrec_GetExpressionListPatch(expr->data.funccall.args)); + break; + case EMEMBER: + CPrec_NewPointerPatch(&p->data.emember, CPrec_GetEMemberInfoPatch(expr->data.emember)); + break; + case ETEMPLDEP: + switch (expr->data.templdep.subtype) { + case TDE_PARAM: + break; + case TDE_SIZEOF: + case TDE_ALIGNOF: + CPrec_NewPointerPatch(&p->data.templdep.u.typeexpr.type, CPrec_GetTypePatch(expr->data.templdep.u.typeexpr.type)); + break; + case TDE_CAST: + if (expr->data.templdep.u.cast.args) + CPrec_NewPointerPatch(&p->data.templdep.u.cast.args, CPrec_GetExpressionListPatch(expr->data.templdep.u.cast.args)); + CPrec_NewPointerPatch(&p->data.templdep.u.cast.type, CPrec_GetTypePatch(expr->data.templdep.u.cast.type)); + break; + case TDE_QUALNAME: + CPrec_NamePatch(&p->data.templdep.u.qual.name, expr->data.templdep.u.qual.name); + CPrec_NewPointerPatch(&p->data.templdep.u.qual.type, CPrec_GetTypePatch(TYPE(expr->data.templdep.u.qual.type))); + break; + case TDE_OBJ: + CPrec_NewPointerPatch(&p->data.templdep.u.obj, CPrec_GetObjectPatch(expr->data.templdep.u.obj)); + break; + case TDE_SOURCEREF: + CPrec_NewPointerPatch(&p->data.templdep.u.sourceref.expr, CPrec_GetExpressionPatch(expr->data.templdep.u.sourceref.expr)); + break; + case TDE_ADDRESS_OF: + CPrec_NewPointerPatch(&p->data.templdep.u.monadic, CPrec_GetExpressionPatch(expr->data.templdep.u.monadic)); + break; + default: + CError_FATAL(3136); + } + break; + case EINTCONST: + case EFLOATCONST: + case EPRECOMP: + case EARGOBJ: + case ELOCOBJ: + case ELABEL: + case EINSTRUCTION: + case EVECTOR128CONST: + break; + default: + CError_FATAL(3142); + } + + return p; +} + +static CI_Switch *CPrec_GetSwitchInfoPatch(CI_Switch *si) { + CI_Switch *p = CPrec_AppendAlign(); + CPrec_AppendData(si, sizeof(CI_Switch) + sizeof(CI_SwitchCase) * (si->numcases - 1)); + + CPrec_NewPointerPatch(&p->expr, CPrec_GetExpressionPatch(si->expr)); + CPrec_NewPointerPatch(&p->unkSwitch8, CPrec_GetTypePatch(si->unkSwitch8)); + return p; +} + +static InlineAsm *CPrec_GetInlineAsmPatch(InlineAsm *ia, SInt32 size) { + InlineAsm *p; + SInt32 index; + SInt32 offset; + Object *object; + + p = CPrec_AppendAlign(); + CPrec_AppendData(ia, size); + + index = 0; + while (1) { + object = InlineAsm_GetObjectOffset(ia, index, &offset); + if (!object) + break; + + object = CPrec_GetObjectPatch(object); + CPrec_NewPointerPatch((char *) p + offset, object); + index++; + } + + return p; +} + +static CI_Statement *CPrec_GetStatementPatch(CI_Statement *stmt, short count) { + short i; + CI_Statement *first, *current; + + for (i = 0; i < count; i++) { + stmt[i].sourcefilepath = NULL; + stmt[i].sourceoffset = -1; + } + + first = current = CPrec_AppendAlign(); + CPrec_AppendData(stmt, sizeof(CI_Statement) * count); + + for (i = 0; i < count; i++) { + if (stmt->dobjstack) + CPrec_NewPointerPatch(¤t->dobjstack, CPrec_GetExceptionPatch(stmt->dobjstack)); + + switch (stmt->type) { + case ST_EXPRESSION: + case ST_RETURN: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + if (stmt->u.expr) + CPrec_NewPointerPatch(¤t->u.expr, CPrec_GetExpressionPatch(stmt->u.expr)); + break; + case ST_IFGOTO: + case ST_IFNGOTO: + CPrec_NewPointerPatch(¤t->u.ifgoto.expr, CPrec_GetExpressionPatch(stmt->u.ifgoto.expr)); + break; + case ST_SWITCH: + CPrec_NewPointerPatch(¤t->u.switchdata, CPrec_GetSwitchInfoPatch(stmt->u.switchdata)); + break; + case ST_ASM: + CPrec_NewPointerPatch(¤t->u.asmdata.data, CPrec_GetInlineAsmPatch(stmt->u.asmdata.data, stmt->u.asmdata.size)); + break; + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + break; + default: + CError_FATAL(3261); + } + + current++; + stmt++; + } + + return first; +} + +static CI_Var *CPrec_GetLocObjectPatch(CI_Var *obj, short count) { + CI_Var *first, *current; + short i; + + first = current = CPrec_AppendAlign(); + CPrec_AppendData(obj, sizeof(CI_Var) * count); + + for (i = 0; i < count; i++) { + CPrec_NamePatch(¤t->name, obj->name); + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(obj->type)); + current++; + obj++; + } + + return first; +} + +static CI_FuncData *CPrec_GetInlineFuncPatch(CI_FuncData *ifunc) { + CI_FuncData *p; + + memclrw(&ifunc->fileoffset, sizeof(FileOffsetInfo)); + ifunc->symdecloffset = 0; + ifunc->functionbodyoffset = 0; + ifunc->functionbodypath = NULL; + ifunc->symdeclend = 0; + + p = CPrec_AppendAlign(); + CPrec_AppendData(ifunc, sizeof(CI_FuncData)); + + if (ifunc->numarguments) + CPrec_NewPointerPatch(&p->arguments, CPrec_GetLocObjectPatch(ifunc->arguments, ifunc->numarguments)); + if (ifunc->numlocals) + CPrec_NewPointerPatch(&p->locals, CPrec_GetLocObjectPatch(ifunc->locals, ifunc->numlocals)); + if (ifunc->numstatements) + CPrec_NewPointerPatch(&p->statements, CPrec_GetStatementPatch(ifunc->statements, ifunc->numstatements)); + + return p; +} + +static ObjEnumConst *CPrec_GetObjEnumConstPatch(ObjEnumConst *obj) { + AddrPatch *addrPatch; + ObjEnumConst *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(obj))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(obj, first); + + do { + CPrec_AppendData(obj, sizeof(ObjEnumConst)); + if (cprec_dowrite) { + CError_ASSERT(3349, obj->access != 255); + obj->access = 255; + } + CPrec_NamePatch(¤t->name, obj->name); + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch( obj->type)); + + if (!obj->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(obj->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + obj = obj->next; + CPrec_NewAddrPatch(obj, next); + } + } while (1); + + return first; +} + +static ObjType *CPrec_GetObjTypePatch(ObjType *obj) { + AddrPatch *addrPatch; + ObjType *p; + + if ((addrPatch = CPrec_FindAddrPatch(obj))) + return addrPatch->value; + + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(obj, p); + CPrec_AppendData(obj, sizeof(ObjType)); + CPrec_NewPointerPatch(&p->type, CPrec_GetTypePatch(obj->type)); + return p; +} + +static ObjTypeTag *CPrec_GetObjTypeTagPatch(ObjTypeTag *obj) { + AddrPatch *addrPatch; + ObjTypeTag *p; + + if ((addrPatch = CPrec_FindAddrPatch(obj))) + return addrPatch->value; + + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(obj, p); + CPrec_AppendData(obj, sizeof(ObjTypeTag)); + CPrec_NewPointerPatch(&p->type, CPrec_GetTypePatch(obj->type)); + return p; +} + +static ObjNameSpace *CPrec_GetObjNameSpacePatch(ObjNameSpace *obj) { + AddrPatch *addrPatch; + ObjNameSpace *p; + + if ((addrPatch = CPrec_FindAddrPatch(obj))) + return addrPatch->value; + + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(obj, p); + CPrec_AppendData(obj, sizeof(ObjNameSpace)); + CPrec_NewPointerPatch(&p->nspace, CPrec_GetNameSpacePatch(obj->nspace)); + return p; +} + +static ObjMemberVar *CPrec_GetObjMemberVarPatch(ObjMemberVar *ivar) { + AddrPatch *addrPatch; + ObjMemberVar *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(ivar))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(ivar, first); + + while (1) { + if (ivar->has_path) { + CPrec_AppendData(ivar, sizeof(ObjMemberVarPath)); + if (OBJ_MEMBER_VAR_PATH(ivar)->path) + CPrec_NewPointerPatch( + &OBJ_MEMBER_VAR_PATH(current)->path, + CPrec_GetClassAccessPatch(OBJ_MEMBER_VAR_PATH(ivar)->path)); + } else { + CPrec_AppendData(ivar, sizeof(ObjMemberVar)); + } + + if (ivar->name) + CPrec_NamePatch(¤t->name, ivar->name); + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(ivar->type)); + + if (!ivar->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(ivar->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + + current = next; + ivar = ivar->next; + CPrec_NewAddrPatch(ivar, current); + } + + return first; +} + +static DefArgCtorInfo *CPrec_GetDefArgCtorInfoPatch(DefArgCtorInfo *dac) { + DefArgCtorInfo *p = CPrec_AppendAlign(); + CPrec_AppendData(dac, sizeof(DefArgCtorInfo)); + CPrec_NewPointerPatch(&p->default_func, CPrec_GetObjectPatch(dac->default_func)); + CPrec_NewPointerPatch(&p->default_arg, CPrec_GetExpressionPatch(dac->default_arg)); + return p; +} + +static InlineXRef *CPrec_GetInlineXRefPatch(InlineXRef *ix) { + InlineXRef *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(ix, sizeof(InlineXRef) + sizeof(XRefOffset) * (ix->numxrefs - 1)); + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(ix->object)); + + if (!ix->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + ix = ix->next; + } while (1); + + return first; +} + +static Object *CPrec_GetObjectPatch(Object *obj) { + AddrPatch *addrPatch; + Object *p; + + if (CWUserBreak(cparams.context) != cwNoErr) + CError_UserBreak(); + + if ((addrPatch = CPrec_FindAddrPatch(obj))) + return addrPatch->value; + + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(obj, p); + + obj->toc = NULL; + + if ((obj->qual & Q_IS_TEMPLATED) && obj->datatype != DALIAS) { + CPrec_AppendData(obj, sizeof(ObjectTemplated)); + CPrec_NewPointerPatch(&OBJECT_TEMPL(p)->parent, CPrec_GetObjectPatch(OBJECT_TEMPL(obj)->parent)); + } else { + CPrec_AppendData(obj, sizeof(Object)); + } + + if (obj->nspace) + CPrec_NewPointerPatch(&p->nspace, CPrec_GetNameSpacePatch(obj->nspace)); + if (obj->name) + CPrec_NamePatch(&p->name, obj->name); + CPrec_NewPointerPatch(&p->type, CPrec_GetTypePatch(obj->type)); + + switch (obj->datatype) { + case DABSOLUTE: + break; + + case DLOCAL: + CError_FATAL(3580); + break; + + case DFUNC: + case DVFUNC: + if (IS_TEMPL_FUNC(obj->type)) + CPrec_NewPointerPatch(&p->u.func.u.templ, CPrec_GetTemplateFunctionPatch(obj->u.func.u.templ)); + else if ((obj->qual & Q_INLINE) && obj->u.func.u.ifuncdata) + CPrec_NewPointerPatch(&p->u.func.u.ifuncdata, CPrec_GetInlineFuncPatch(obj->u.func.u.ifuncdata)); + + if (obj->u.func.defargdata) + CPrec_NewPointerPatch(&p->u.func.defargdata, CPrec_GetDefArgCtorInfoPatch(obj->u.func.defargdata)); + if (obj->u.func.linkname) + CPrec_NamePatch(&p->u.func.linkname, obj->u.func.linkname); + if (obj->u.func.inst) + CPrec_NewPointerPatch(&p->u.func.inst, CPrec_GetTemplFuncInstancePatch(obj->u.func.inst)); + break; + + case DDATA: + CError_ASSERT(3622, !obj->u.data.info); + if (obj->qual & Q_INLINE_DATA) { + switch (obj->type->type) { + case TYPEINT: + case TYPEENUM: + case TYPEPOINTER: + break; + case TYPEFLOAT: + CPrec_RawMemPatch(&p->u.data.u.floatconst, obj->u.data.u.floatconst, sizeof(Float)); + break; + default: + CError_FATAL(3638); + } + } + if (obj->u.data.linkname) + CPrec_NamePatch(&p->u.data.linkname, obj->u.data.linkname); + break; + + case DINLINEFUNC: + CPrec_RawMemPatch(&p->u.ifunc.data, obj->u.ifunc.data, obj->u.ifunc.size); + if (obj->u.ifunc.xrefs) + CPrec_NewPointerPatch(&p->u.ifunc.xrefs, CPrec_GetInlineXRefPatch(obj->u.ifunc.xrefs)); + break; + + case DALIAS: + CPrec_NewPointerPatch(&p->u.alias.object, CPrec_GetObjectPatch(obj->u.alias.object)); + if (obj->u.alias.member) + CPrec_NewPointerPatch(&p->u.alias.member, CPrec_GetClassAccessPatch(obj->u.alias.member)); + break; + + default: + CError_FATAL(3677); + } + + if (cprec_dowrite) + obj->datatype = -1; + + return p; +} + +static ObjBase *CPrec_GetObjBasePatch(ObjBase *obj) { + switch (obj->otype) { + default: + CError_FATAL(3694); + case OT_ENUMCONST: + return (ObjBase *) CPrec_GetObjEnumConstPatch((ObjEnumConst *) obj); + case OT_TYPE: + return (ObjBase *) CPrec_GetObjTypePatch((ObjType *) obj); + case OT_TYPETAG: + return (ObjBase *) CPrec_GetObjTypeTagPatch((ObjTypeTag *) obj); + case OT_NAMESPACE: + return (ObjBase *) CPrec_GetObjNameSpacePatch((ObjNameSpace *) obj); + case OT_MEMBERVAR: + return (ObjBase *) CPrec_GetObjMemberVarPatch((ObjMemberVar *) obj); + case OT_OBJECT: + return (ObjBase *) CPrec_GetObjectPatch((Object *) obj); + } +} + +static ObjectList *CPrec_GetObjectListPatch(ObjectList *ol) { + AddrPatch *addrPatch; + ObjectList *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(ol))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(ol, first); +restart: + CPrec_AppendData(ol, sizeof(ObjectList)); + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(ol->object)); + if (ol->next) { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + ol = ol->next; + goto restart; + } + + return first; +} + +static NameSpaceObjectList *CPrec_GetNameSpaceObjectListPatch(NameSpaceObjectList *nsol) { + AddrPatch *addrPatch; + NameSpaceObjectList *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(nsol))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(nsol, first); + + do { + CPrec_AppendData(nsol, sizeof(NameSpaceObjectList)); + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjBasePatch(nsol->object)); + + if (!nsol->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(nsol->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + nsol = nsol->next; + CPrec_NewAddrPatch(nsol, next); + } + } while (1); + + return first; +} + +static NameSpaceName *CPrec_GetNameSpaceNamePatch(NameSpaceName *nsn, Boolean flag) { + AddrPatch *addrPatch; + NameSpaceName *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(nsn))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(nsn, first); + + do { + CPrec_AppendData(nsn, sizeof(NameSpaceName)); + CPrec_NamePatch(¤t->name, nsn->name); + CPrec_NewPointerPatch(¤t->first.object, CPrec_GetObjBasePatch(nsn->first.object)); + if (nsn->first.next) + CPrec_NewPointerPatch(¤t->first.next, CPrec_GetNameSpaceObjectListPatch(nsn->first.next)); + + if (!nsn->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(nsn->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + nsn = nsn->next; + CPrec_NewAddrPatch(nsn, next); + } + } while (!flag || !cprec_dowrite || CPrec_FlushBufferCheck() == noErr); + + return first; +} + +static NameSpaceList *CPrec_GetNameSpaceListPatch(NameSpaceList *nsl) { + NameSpaceList *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(nsl, sizeof(NameSpaceList)); + CPrec_NewPointerPatch(¤t->nspace, CPrec_GetNameSpacePatch(nsl->nspace)); + + if (!nsl->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + nsl = nsl->next; + } while (1); + + return first; +} + +static NameSpace *CPrec_GetNameSpacePatch(NameSpace *nspace) { + NameSpace *p; + AddrPatch *addrPatch; + + if ((addrPatch = CPrec_FindAddrPatch(nspace))) + return addrPatch->value; + + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(nspace, p); + CPrec_AppendData(nspace, sizeof(NameSpace)); + + if (nspace->parent) + CPrec_NewPointerPatch(&p->parent, CPrec_GetNameSpacePatch(nspace->parent)); + if (nspace->name) + CPrec_NamePatch(&p->name, nspace->name); + if (nspace->usings) + CPrec_NewPointerPatch(&p->usings, CPrec_GetNameSpaceListPatch(nspace->usings)); + if (nspace->theclass) + CPrec_NewPointerPatch(&p->theclass, CPrec_GetTypePatch((Type *) nspace->theclass)); + + if (nspace->is_hash) { + char *hash; + int i; + hash = CPrec_AppendAlign(); + CPrec_NewPointerPatch(&p->data.hash, hash); + CPrec_AppendData(nspace->data.hash, sizeof(NameSpaceName *) * 1024); + for (i = 0; i < 1024; i++) { + if (nspace->data.hash[i]) + CPrec_NewPointerPatch(hash + (i * sizeof(NameSpaceName *)), CPrec_GetNameSpaceNamePatch(nspace->data.hash[i], 0)); + } + } else if (nspace->data.list) { + CPrec_NewPointerPatch(&p->data.list, CPrec_GetNameSpaceNamePatch(nspace->data.list, 0)); + } + + return p; +} + +static void CPrec_DumpRootNameSpace(void) { + NameSpaceList *nslist; + NameSpaceName *nsname; + int i; + + CError_ASSERT(3905, cscope_root->is_hash); + + if (cscope_root->usings) { + nslist = CPrec_GetNameSpaceListPatch(cscope_root->usings); + if (cprec_dowrite) + cprec_header->usings = nslist; + } + + if (cprec_dowrite) + cprec_header->root_names = cscope_root->names; + + i = 0; + do { + if (cscope_root->data.hash[i]) { + nsname = CPrec_GetNameSpaceNamePatch(cscope_root->data.hash[i], 1); + if (cprec_dowrite) { + if (cprec_ioerror != noErr) + break; + cprec_header->root_nametable[i] = nsname; + } + } + } while (++i < 0x400); +} + +static CSOMStub *CPrec_GetSOMPatch(CSOMStub *stub) { + CSOMStub *first, *current, *next; + + first = current = CPrec_AppendAlign(); + while (1) { + CPrec_AppendData(stub, sizeof(CSOMStub)); + + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(stub->object)); + CPrec_NewPointerPatch(¤t->tclass, CPrec_GetTypePatch(TYPE(stub->tclass))); + + if (!stub->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + stub = stub->next; + } + + return first; +} + +static OLinkList *CPrec_GetOLinkPatch(OLinkList *olink) { + OLinkList *first, *current, *next; + + first = current = CPrec_AppendAlign(); + while (1) { + CPrec_AppendData(olink, sizeof(OLinkList)); + + CPrec_NewPointerPatch(¤t->obj, CPrec_GetObjectPatch(olink->obj)); + + if (!olink->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + olink = olink->next; + } + + return first; +} + +static StaticData *CPrec_GetStaticDataPatch(StaticData *sd) { + StaticData *current, *first, *next; + + first = current = CPrec_AppendAlign(); + while (1) { + CPrec_AppendData(sd, sizeof(StaticData)); + + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(sd->object)); + if (sd->buffer) + CPrec_RawMemPatch(¤t->buffer, sd->buffer, sd->object->type->size); + if (sd->links) + CPrec_NewPointerPatch(¤t->links, CPrec_GetOLinkPatch(sd->links)); + + if (!sd->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + sd = sd->next; + } + + return first; +} + +static CallbackAction *CPrec_GetCallbackPatch(CallbackAction *ca) { + CallbackAction *first, *current, *next; + + first = current = CPrec_AppendAlign(); + while (1) { + CPrec_AppendData(ca, sizeof(CallbackAction)); + + CPrec_NewPointerPatch(¤t->obj, CPrec_GetObjectPatch(ca->obj)); + CPrec_NewPointerPatch(¤t->tclass, CPrec_GetTypePatch(TYPE(ca->tclass))); + + if (!ca->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + ca = ca->next; + } + + return first; +} + +static ObjCSelector **CPrec_GetSelHashTablePatch(ObjCSelector **table) { + ObjCSelector **first, **current; + int i; + + first = current = CPrec_AppendAlign(); + CPrec_AppendData(table, sizeof(ObjCSelector *) * 0x400); + + for (i = 0; i < 0x400; i++) { + if (*table) + CPrec_NewPointerPatch(current, CPrec_GetObjCSelectorPatch(*table)); + table++; + current++; + } + + return first; +} + +static InitExpr *CPrec_GetIExpressionPatch(InitExpr *initexpr) { + InitExpr *first, *current, *next; + + first = current = CPrec_AppendAlign(); + while (1) { + CPrec_AppendData(initexpr, sizeof(InitExpr)); + + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(initexpr->object)); + CPrec_NewPointerPatch(¤t->expr, CPrec_GetExpressionPatch(initexpr->expr)); + + if (!initexpr->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + initexpr = initexpr->next; + } + + return first; +} + +static CI_Action *CPrec_GetInlineActionPatch(CI_Action *act) { + CI_Action *current, *first, *next; + + first = current = CPrec_AppendAlign(); + while (1) { + if (act->actiontype == CI_ActionInlineFunc) + memclrw(&act->u.inlinefunc.fileoffset, sizeof(FileOffsetInfo)); + + CPrec_AppendData(act, sizeof(CI_Action)); + + CPrec_NewPointerPatch(¤t->obj, CPrec_GetObjectPatch(act->obj)); + + switch (act->actiontype) { + case CI_ActionInlineFunc: + if (act->u.inlinefunc.stream.firsttoken) + CPrec_NewPointerPatch( + ¤t->u.inlinefunc.stream.firsttoken, + CPrec_GetTStreamPatch(act->u.inlinefunc.stream.firsttoken, act->u.inlinefunc.stream.tokens)); + if (act->u.inlinefunc.tclass) + CPrec_NewPointerPatch(¤t->u.inlinefunc.tclass, CPrec_GetTypePatch(TYPE(act->u.inlinefunc.tclass))); + break; + + case CI_ActionMemberFunc: + CPrec_NewPointerPatch(¤t->u.memberfunc.templ, CPrec_GetTypePatch(TYPE(act->u.memberfunc.templ))); + CPrec_NewPointerPatch(¤t->u.memberfunc.inst, CPrec_GetTypePatch(TYPE(act->u.memberfunc.inst))); + CPrec_NewPointerPatch(¤t->u.memberfunc.tmemb, CPrec_GetTemplateMemberPatch(act->u.memberfunc.tmemb)); + break; + + case CI_ActionTemplateFunc: + CPrec_NewPointerPatch(¤t->u.templatefunc.func, CPrec_GetTemplateFunctionPatch(act->u.templatefunc.func)); + CPrec_NewPointerPatch(¤t->u.templatefunc.inst, CPrec_GetTemplFuncInstancePatch(act->u.templatefunc.inst)); + break; + + case CI_ActionDefaultFunc: + break; + + default: + CError_FATAL(4177); + } + + if (!act->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + act = act->next; + } + + return first; +} + +static void CPrec_GenerateBuiltinPatches(void) { + int x; + int y; + Patch *scan; + + for (x = 0; x < cprec_builtins; x++) { + y = 0; + for (scan = cprec_builtin[x].patches; scan; scan = scan->next) + ++y; + + if (y) { + CPrec_AppendWord32(y); + CPrec_AppendWord32(x); + for (scan = cprec_builtin[x].patches; scan; scan = scan->next) + CPrec_AppendWord32(scan->offset); + } + } + + CPrec_AppendWord32(0); +} + +static void CPrec_GenerateTokenStreamPatches(void) { + TokenPatch *scan; + + for (scan = cprec_tokenpatches; scan; scan = scan->next) { + CPrec_AppendWord32((UInt32) scan->tokens); + CPrec_AppendWord32((UInt32) scan->count); + } + CPrec_AppendWord32(0); +} + +static OSErr CPrec_CompressWrite(const char *data, SInt32 size) { + char buf[2048 + 256]; + OSErr err; + int bufpos = 0; + int blockstart; + int c; + const char *p = data; + const char *end = data + size; + + for (;;) { + if (p < end) { + if (!*p) { + c = 224; + while (!*p && p < end && c < 256) { + c++; + p++; + } + buf[bufpos++] = c - 1; + } else { + blockstart = bufpos++; + c = 0; + while (p < end && c < 224) { + if (!p[0] && !p[1]) { + break; + } else { + buf[bufpos++] = *(p++); + c++; + } + } + buf[blockstart] = c - 1; + } + } + + if (p >= end || bufpos > 2048) { + if ((err = COS_FileWrite(cprec_refnum, buf, bufpos))) + return err; + + if (p >= end) + break; + else + bufpos = 0; + } + } + + return noErr; +} + +static OSErr CPrec_FlushRawBuffer(void) { + OSErr err; + + if (cprec_dowrite) { + CPrec_AppendAlign(); + cprec_zero_offset += cprec_glist.size; + COS_LockHandle(cprec_glist.data); + err = CPrec_CompressWrite(*cprec_glist.data, cprec_glist.size); + COS_UnlockHandle(cprec_glist.data); + cprec_glist.size = 0; + + return err; + } else { + return noErr; + } +} + +static OSErr CPrec_FlushBufferCheck(void) { + static SInt32 flushmax; + OSErr err; + + if (cprec_glist.size > flushmax) + flushmax = cprec_glist.size; + + if (cprec_glist.size > 10000) { + err = CPrec_FlushRawBuffer(); + if (err) { + cprec_ioerror = err; + return err; + } + } + + return noErr; +} + +static int CPrec_CompressPatches(void) { + Patch *scan; + int count; + SInt32 last; + + cprec_glist.size = 0; + + scan = cprec_patch_list; + last = 0; + count = 0; + while (scan) { + CError_ASSERT(4339, (scan->offset & 0x80000001) == 0); + + if ((scan->offset - last) >= -128 && (scan->offset - last) <= 126) + CPrec_AppendByte(((scan->offset - last) >> 1) | 0x80); + else + CPrec_AppendWord32(scan->offset); + + last = scan->offset; + scan = scan->next; + count++; + } + + return count; +} + +static OSErr CPrec_DumpColorSymbolTable(Boolean doWrite) { + OSErr err; + + freelheap(); + + CPrec_InitAddressHashTable(); + CPrec_InitPointerHashTable(); + + cprec_patch_list = NULL; + cprec_tokenpatches = NULL; + cprec_offset = 0; + cprec_zero_offset = 0; + cprec_dowrite = doWrite; + cprec_ioerror = noErr; + + CPrec_SetupBuiltIn(); + CPrec_AppendWord32(0); + + CPrec_DumpNameTable(); + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + + CPrec_DumpMacroTable(); + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + + CPrec_DumpRootNameSpace(); + if (doWrite) { + if (cprec_ioerror != noErr) + return cprec_ioerror; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (ctempl_templates) { + TemplClass *p = TEMPL_CLASS(CPrec_GetTypePatch(TYPE(ctempl_templates))); + if (doWrite) + cprec_header->ctempl_templates = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (ctempl_templatefuncs) { + TemplateFunction *p = CPrec_GetTemplateFunctionPatch(ctempl_templatefuncs); + if (doWrite) + cprec_header->ctempl_templatefuncs = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (csom_stubs) { + CSOMStub *p = CPrec_GetSOMPatch(csom_stubs); + if (doWrite) + cprec_header->csom_stubs = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (cprec_staticdata) { + StaticData *p = CPrec_GetStaticDataPatch(cprec_staticdata); + if (doWrite) + cprec_header->cprec_staticdata = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (callbackactions) { + CallbackAction *p = CPrec_GetCallbackPatch(callbackactions); + if (doWrite) + cprec_header->callbackactions = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (cobjc_type_class) { + Type *p = CPrec_GetTypePatch(cobjc_type_class); + if (doWrite) + cprec_header->cobjc_type_class = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (cobjc_type_id) { + Type *p = CPrec_GetTypePatch(cobjc_type_id); + if (doWrite) + cprec_header->cobjc_type_id = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (cobjc_type_sel) { + Type *p = CPrec_GetTypePatch(cobjc_type_sel); + if (doWrite) + cprec_header->cobjc_type_sel = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (cobjc_selhashtable) { + ObjCSelector **p = CPrec_GetSelHashTablePatch(cobjc_selhashtable); + if (doWrite) + cprec_header->cobjc_selhashtable = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (cobjc_classdefs) { + BClassList *p = CPrec_GetBClassListPatch(cobjc_classdefs); + if (doWrite) + cprec_header->cobjc_classdefs = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (cobjc_protocols) { + ObjCProtocol *p = CPrec_GetObjCProtocolPatch(cobjc_protocols); + if (doWrite) + cprec_header->cobjc_protocols = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (init_expressions) { + InitExpr *p = CPrec_GetIExpressionPatch(init_expressions); + if (doWrite) + cprec_header->init_expressions = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (cinline_tactionlist) { + CI_Action *p = CPrec_GetInlineActionPatch(cinline_tactionlist); + if (doWrite) + cprec_header->cinline_tactionlist = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + return noErr; +} + +static OSErr CPrec_FileAlign(short refnum, SInt32 *len) { + OSErr err; + SInt32 n; + char buf[8]; + + n = *len; + if ((n & 7) == 0) + return noErr; + + memclrw(buf, 8); + err = COS_FileWrite(refnum, buf, n = 8 - (n & 7)); + *len += n; + + return err; +} + +static OSErr CPrec_WriteFile(void) { + char str[128]; + int i; + HashNameNode *name; + OSErr err; + SInt32 offset; + + if (InitGList(&cprec_glist, 0x40000)) + CError_NoMem(); + + CompilerGetCString(10, str); + CWShowStatus(cparams.context, str, ""); + CPrep_RemoveSpecialMacros(); + + for (i = 0; i < 0x800; i++) { + for (name = name_hash_nodes[i]; name; name = name->next) + name->id = 0; + } + + if ((err = CPrec_DumpColorSymbolTable(0)) != noErr) + return err; + + CompilerGetCString(11, str); + CWShowStatus(cparams.context, str, ""); + + cprec_header = galloc(sizeof(Header)); + memclrw(cprec_header, sizeof(Header)); + + cprec_header->magic = 0xBEEFFACE; + cprec_header->version = 1047; + cprec_header->target = 2; + cprec_header->check_header_flags = copts.checkprecompflags; + cprec_header->cplusplus = copts.cplusplus; + cprec_header->uniqueID = CParser_GetUniqueID(); + cprec_header->cobjc_selrefcount = cobjc_selrefcount; + cprec_header->cobjc_classrefcount = cobjc_classrefcount; + cprec_header->cobjc_stringcount = cobjc_stringcount; + + if ((err = COS_FileWrite(cprec_refnum, cprec_header, sizeof(Header))) != noErr) + return err; + + offset = sizeof(Header); + + if ((err = CPrec_DumpColorSymbolTable(1)) != noErr) + return err; + + cprec_header->x28 = cprec_offset; + cprec_header->x30 = offset; + + if ((err = COS_FileGetPos(cprec_refnum, &offset)) != noErr) + return err; + + cprec_header->x2C = offset - cprec_header->x30; + + cprec_header->compressedPatchCount = CPrec_CompressPatches(); + cprec_header->compressedPatchSize = cprec_glist.size; + cprec_header->compressedPatchOffset = offset; + + if (cprec_header->compressedPatchCount) { + if ((err = COS_FileWrite(cprec_refnum, *cprec_glist.data, cprec_glist.size)) != noErr) + return err; + offset += cprec_glist.size; + } + + if ((err = CPrec_FileAlign(cprec_refnum, &offset)) != noErr) + return err; + + cprec_glist.size = 0; + CPrec_GenerateBuiltinPatches(); + cprec_header->builtinPatchSize = cprec_glist.size; + cprec_header->builtinPatchOffset = offset; + + if ((err = COS_FileWrite(cprec_refnum, *cprec_glist.data, cprec_glist.size)) != noErr) + return err; + offset += cprec_glist.size; + + if (cprec_tokenpatches) { + cprec_glist.size = 0; + CPrec_GenerateTokenStreamPatches(); + cprec_header->tokenStreamPatchSize = cprec_glist.size; + cprec_header->tokenStreamPatchOffset = offset; + + if ((err = COS_FileWrite(cprec_refnum, *cprec_glist.data, cprec_glist.size)) != noErr) + return err; + offset += cprec_glist.size; + } + + if ((err = COS_FileSetPos(cprec_refnum, 0)) != noErr) + return err; + + if ((err = COS_FileWrite(cprec_refnum, cprec_header, sizeof(Header))) != noErr) + return err; + + return noErr; +} + +void PrecompilerWrite(void) { + OSErr err; + short strindex; + char str[128]; + FSSpec spec; + + spec = cparamblkptr->sourcefile; + if (CWGetPrecompiledHeaderSpec(cparamblkptr->context, &spec, precomp_target_str) == cwNoErr) { + strindex = 3; + err = COS_FileNew(&spec, &cprec_refnum, copts.appltype, copts.headtype); + if (err == noErr) { + strindex = 4; + err = CPrec_WriteFile(); + } + CleanupPrecompiler(); + + if (err != noErr) { + CompilerGetCString(strindex, str); + sprintf(string, str, err); + CWReportMessage(cparamblkptr->context, NULL, string, NULL, messagetypeError, 0); + } else { + CWFileTime time = 0; + CWSetModDate(cparamblkptr->context, &spec, &time, 1); + } + } +} + +static void CPrec_ReadData(SInt32 offset, void *buffer, SInt32 size) { + if ( + COS_FileSetPos(cprec_refnum, offset) != noErr || + COS_FileRead(cprec_refnum, buffer, size) != noErr + ) + CError_ErrorTerm(CErrorStr181); +} + +static void CPrec_ReadRawBuffer(void) { + UInt8 *buffer; + UInt8 *work; + UInt8 *end; + UInt32 size; + int ch; + + if (!cprec_buffer) { + size = cprec_header->x28 + (cprec_header->x28 >> 7) + 64; + buffer = galloc(size); + cprec_rawbuffer = buffer; + + work = buffer + size - cprec_header->x2C; + CPrec_ReadData(cprec_header->x30, work, cprec_header->x2C); + } else { + buffer = galloc(cprec_header->x28); + cprec_rawbuffer = buffer; + work = (UInt8 *) cprec_buffer + cprec_header->x30; + } + + end = work + cprec_header->x2C; + + while (work < end) { + if ((ch = *(work++)) >= 0xE0) { + ch -= 0xE0; + do { + *(buffer++) = 0; + } while (--ch >= 0); + } else { + do { + *(buffer++) = *(work++); + } while (--ch >= 0); + } + } + + if (work != end || buffer != RESOLVE_RAW_BUFFER(cprec_header->x28)) + CError_ErrorTerm(CErrorStr181); +} + +static void CPrec_RelocateRawBuffer(void) { + UInt8 *patches; + UInt32 offset; + UInt8 *dest; + SInt32 count; + UInt8 *patch; + UInt32 var; + + if ((count = cprec_header->compressedPatchCount)) { + if (!cprec_buffer) { + patches = lalloc(cprec_header->compressedPatchSize); + CPrec_ReadData(cprec_header->compressedPatchOffset, patches, cprec_header->compressedPatchSize); + } else { + patches = RESOLVE_BUFFER(cprec_header->compressedPatchOffset); + } + + offset = 0; + patch = patches; + dest = cprec_rawbuffer; + do { + if (!(*patch & 0x80)) { + ((UInt8 *) &var)[0] = *(patch++); + ((UInt8 *) &var)[1] = *(patch++); + ((UInt8 *) &var)[2] = *(patch++); + ((UInt8 *) &var)[3] = *(patch++); + offset = var; + } else { + offset += (char) (*(patch++) * 2); + } + *((uintptr_t *) (dest + offset)) += (uintptr_t) dest; + } while (--count > 0); + + freelheap(); + + if (patch != (patches + cprec_header->compressedPatchSize)) + CError_ErrorTerm(CErrorStr181); + } +} + +static void CPrec_RelocateBuiltins(void) { + UInt32 *patches; + void *builtin; + UInt32 count; + UInt8 *buffer; + + if (cprec_header->builtinPatchSize) { + CPrec_SetupBuiltInArray(); + if (!cprec_buffer) { + patches = lalloc(cprec_header->builtinPatchSize); + CPrec_ReadData(cprec_header->builtinPatchOffset, patches, cprec_header->builtinPatchSize); + } else { + patches = RESOLVE_BUFFER(cprec_header->builtinPatchOffset); + } + + buffer = cprec_rawbuffer; + while (1) { + if (!(count = *(patches++))) + break; + + builtin = cprec_builtin_array[*(patches++)]; + do { + *((void **) (buffer + *(patches++))) = builtin; + } while (--count); + } + } +} + +static void CPrec_RelocateTokenStreams(void) { + UInt32 *patches; + UInt32 count; + TStreamElement *tokens; + UInt8 *buffer; + CPrepFileInfo *file; + SInt32 pos; + + if (cprec_header->tokenStreamPatchSize) { + CPrep_GetPrepPos(&file, &pos); + + if (!cprec_buffer) { + patches = lalloc(cprec_header->tokenStreamPatchSize); + CPrec_ReadData(cprec_header->tokenStreamPatchOffset, patches, cprec_header->tokenStreamPatchSize); + } else { + patches = RESOLVE_BUFFER(cprec_header->tokenStreamPatchOffset); + } + + buffer = cprec_rawbuffer; + while (1) { + if (!*patches) + break; + + tokens = (TStreamElement *) (buffer + *(patches++)); + count = *(patches++); + + while (count--) { + tokens->tokenfile = file; + tokens->tokenoffset = pos; + tokens++; + } + } + } +} + +static void CPrec_RelocateMacroTable(void) { + int i; + int j; + int count; + UInt8 *buffer; + Macro **prec_table; + Macro **table; + Macro *macro; + uintptr_t offset; + + buffer = cprec_rawbuffer; + prec_table = cprec_header->macrotable; + table = macrohashtable; + + i = 0; + do { + for (macro = *table; macro; macro = macro->next) { + macro->name = GetHashNameNodeExport(macro->name->name); + count = macro->xC & 0x7FFF; + for (j = 1; j < count; j++) + macro->names[j - 1] = GetHashNameNodeExport(macro->names[j - 1]->name); + } + + if ((offset = (uintptr_t) *prec_table)) { + if (*table) { + macro = (Macro *) (buffer + offset); + while (macro->next) + macro = macro->next; + macro->next = *table; + } + *table = (Macro *) (buffer + offset); + } + + prec_table++; + table++; + } while (++i < 0x800); +} + +static void CPrec_RelocateTable(void **table, int size, void **dest) { + int i; + void *buffer = cprec_rawbuffer; + + for (i = 0; i < size; i++) { + if (*table) + *dest = (char *) buffer + (uintptr_t) *table; + else + *dest = NULL; + table++; + dest++; + } +} + +static void CPrec_RelocateRootNameSpace(void) { + CError_ASSERT(4981, cscope_root->is_hash); + + cscope_root->names = cprec_header->root_names; + CPrec_RelocateTable( + (void **) cprec_header->root_nametable, + 0x400, + (void **) cscope_root->data.hash); +} + +static void CPrec_FixNameIds(void) { + int i; + HashNameNode *node; + + for (i = 0; i < 2048; i++) { + for (node = name_hash_nodes[i]; node; node = node->next) + node->id = -1; + } +} + +static void CPrec_DefineStaticData(void) { + StaticData *sd = cprec_staticdata; + cprec_staticdata = NULL; + + while (sd) { + CInit_DeclareData(sd->object, sd->buffer, sd->links, sd->size); + sd = sd->next; + } +} + +void PrecompilerRead(short refnum, void *buffer) { + cprec_refnum = refnum; + cprec_buffer = buffer; + + CPrep_RemoveSpecialMacros(); + + if (!CScope_IsEmptySymTable()) + CError_ErrorTerm(CErrorStr180); + + if (!cprec_buffer) { + cprec_header = galloc(sizeof(Header)); + CPrec_ReadData(0, cprec_header, sizeof(Header)); + } else { + cprec_header = cprec_buffer; + } + + if (cprec_header->magic != 0xBEEFFACE) + CError_ErrorTerm(CErrorStr181); + if (cprec_header->version != 1047) + CError_ErrorTerm(CErrorStr222); + if (cprec_header->target != 2) + CError_ErrorTerm(CErrorStr223); + + copts.checkprecompflags = cprec_header->check_header_flags; + + CPrec_ReadRawBuffer(); + CPrec_RelocateRawBuffer(); + CPrec_RelocateBuiltins(); + CPrec_RelocateTable((void **) cprec_header->nametable, 0x800, (void **) name_hash_nodes); + CPrec_FixNameIds(); + CPrec_RelocateMacroTable(); + CPrec_RelocateTokenStreams(); + CPrec_RelocateRootNameSpace(); + + if (!cprec_header->usings) + cscope_root->usings = NULL; + else + cscope_root->usings = RESOLVE_RAW_BUFFER(cprec_header->usings); + + ctempl_templates = RESOLVE_SAFE(cprec_header->ctempl_templates); + ctempl_templatefuncs = RESOLVE_SAFE(cprec_header->ctempl_templatefuncs); + csom_stubs = RESOLVE_SAFE(cprec_header->csom_stubs); + cprec_staticdata = RESOLVE_SAFE(cprec_header->cprec_staticdata); + callbackactions = RESOLVE_SAFE(cprec_header->callbackactions); + cobjc_type_class = RESOLVE_SAFE(cprec_header->cobjc_type_class); + cobjc_type_id = RESOLVE_SAFE(cprec_header->cobjc_type_id); + cobjc_type_sel = RESOLVE_SAFE(cprec_header->cobjc_type_sel); + cobjc_selhashtable = RESOLVE_SAFE(cprec_header->cobjc_selhashtable); + cobjc_classdefs = RESOLVE_SAFE(cprec_header->cobjc_classdefs); + cobjc_protocols = RESOLVE_SAFE(cprec_header->cobjc_protocols); + init_expressions = RESOLVE_SAFE(cprec_header->init_expressions); + cinline_tactionlist = RESOLVE_SAFE(cprec_header->cinline_tactionlist); + CParser_SetUniqueID(cprec_header->uniqueID); + cobjc_selrefcount = cprec_header->cobjc_selrefcount; + cobjc_classrefcount = cprec_header->cobjc_classrefcount; + cobjc_stringcount = cprec_header->cobjc_stringcount; + + cprec_refnum = 0; + + CleanupPrecompiler(); + cscope_current = cscope_root; + + if (!CParser_ReInitRuntimeObjects(1)) + CError_ErrorTerm(CErrorStr181); + + CPrep_InsertSpecialMacros(); + + if (cparamblkptr->precompile != 1) + CPrec_DefineStaticData(); +} diff --git a/compiler_and_linker/FrontEnd/C/CPrep.c b/compiler_and_linker/FrontEnd/C/CPrep.c index a2ac9e2..904e72a 100644 --- a/compiler_and_linker/FrontEnd/C/CPrep.c +++ b/compiler_and_linker/FrontEnd/C/CPrep.c @@ -14,7 +14,7 @@ #include "compiler/CodeGen.h" #include "compiler/CompilerTools.h" #include "compiler/FuncLevelAsmPPC.h" -#include "compiler/IroPointerAnalysis.h" +#include "../Optimizer/IroPointerAnalysis.h" #include "compiler/ObjGenMachO.h" #include "compiler/objects.h" #include "compiler/scopes.h" diff --git a/compiler_and_linker/FrontEnd/C/CPreprocess.c b/compiler_and_linker/FrontEnd/C/CPreprocess.c new file mode 100644 index 0000000..4e6b3c0 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CPreprocess.c @@ -0,0 +1,676 @@ +#include "compiler/CPreprocess.h" +#include "compiler/CError.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CompilerTools.h" +#include "cos.h" + +void CPrep_PreprocessDumpNewLine(void) { + if (copts.line_prepdump && pplist.data && filesp >= 0) + AppendGListData(&pplist, "\r", 1); +} + +void CPrep_PreprocessDumpFileInfo(Boolean flag) { + char linebuf[512]; + int size; + SInt16 tmp16; + SInt32 tmp32; + Str255 filename; + + if (pplist.data && filesp >= 0) { + if (nlflag && flag && pplist.size > 0) + AppendGListName(&pplist, "\r"); + + if (copts.line_prepdump) + size = sprintf(linebuf, "#line % " PRId32 "\t\"", linenumber); + else + size = sprintf(linebuf, "/* #line % " PRId32 "\t\"", linenumber); + AppendGListData(&pplist, linebuf, size); + + if (copts.fullpath_prepdump) { + if (prep_file->nameNode) { + AppendGListData(&pplist, prep_file->nameNode->name, strlen(prep_file->nameNode->name)); + } else { + COS_FileGetPathName(linebuf, &prep_file->textfile, &tmp32); + AppendGListData(&pplist, linebuf, strlen(linebuf)); + } + } else { + if (prep_file->nameNode) { + char *work = prep_file->nameNode->name + strlen(prep_file->nameNode->name); + while (work > prep_file->nameNode->name && !strchr("/\\:", work[-1])) + work--; + + AppendGListData(&pplist, work, strlen(work)); + } else { + COS_FileGetFSSpecInfo(&prep_file->textfile, &tmp16, &tmp32, filename); + AppendGListData(&pplist, &filename[1], filename[0]); + } + } + + size = sprintf(linebuf, "\"\t/* stack depth % " PRId32 " */", filesp); + AppendGListData(&pplist, linebuf, size); + + if (copts.line_prepdump && flag) + CPrep_PreprocessDumpNewLine(); + + nlflag = 1; + } +} + +static void CPrep_DumpWString(UInt16 *str, short len) { + int divisor; + int i; + + while (len--) { + if (*str < 32) { + AppendGListByte(&pplist, '\\'); + switch (*str) { + case 7: + AppendGListByte(&pplist, 'a'); + break; + case 8: + AppendGListByte(&pplist, 'b'); + break; + case 27: + AppendGListByte(&pplist, 'e'); + break; + case 12: + AppendGListByte(&pplist, 'f'); + break; + case 10: + AppendGListByte(&pplist, 'n'); + break; + case 13: + AppendGListByte(&pplist, 'r'); + break; + case 9: + AppendGListByte(&pplist, 't'); + break; + case 11: + AppendGListByte(&pplist, 'v'); + break; + default: + if (*str >= 8) + AppendGListByte(&pplist, '0' + (*str / 8)); + AppendGListByte(&pplist, '0' + (*str % 8)); + } + } else if (*str > 255) { + AppendGListByte(&pplist, '\\'); + AppendGListByte(&pplist, 'x'); + + divisor = 0x1000; + for (i = 0; i < 4; i++) { + AppendGListByte(&pplist, "0123456789ABCDEF"[(*str / divisor) % 16]); + divisor /= 16; + } + } else { + switch (*str) { + case '"': + case '\\': + AppendGListByte(&pplist, '\\'); + default: + AppendGListByte(&pplist, *str); + } + } + str++; + } +} + +static void CPrep_DumpString(UInt8 *str, short len) { + while (len--) { + if (*str < 32) { + AppendGListByte(&pplist, '\\'); + switch (*str) { + case 7: + AppendGListByte(&pplist, 'a'); + break; + case 8: + AppendGListByte(&pplist, 'b'); + break; + case 12: + AppendGListByte(&pplist, 'f'); + break; + case 10: + AppendGListByte(&pplist, 'n'); + break; + case 13: + AppendGListByte(&pplist, 'r'); + break; + case 9: + AppendGListByte(&pplist, 't'); + break; + case 11: + AppendGListByte(&pplist, 'v'); + break; + default: + if (*str >= 8) + AppendGListByte(&pplist, '0' + (*str / 8)); + AppendGListByte(&pplist, '0' + (*str % 8)); + } + } else { + switch (*str) { + case '"': + case '\\': + AppendGListByte(&pplist, '\\'); + default: + AppendGListByte(&pplist, *str); + } + } + str++; + } +} + +void CPrep_Preprocess(void) { + short innertoken; + short token; + char startToken; + char endToken; + int depth; + Boolean save_asmpoundcomment; // r16 + Boolean save_cplusplus; // r15 + char *p; + + startToken = 0; + depth = 0; + + if (InitGList(&pplist, 10000)) + CError_NoMem(); + + nlflag = 0; + spaceskip = 0; + + if ((token = lex())) { + do { + if (nlflag) { + if (!copts.line_prepdump) + AppendGListData(&pplist, "\r", 1); + } else { + if (spaceskip) + AppendGListByte(&pplist, ' '); + } + + while (1) { + switch ((innertoken = token)) { + case '(': + case ')': + case '{': + case '}': + AppendGListByte(&pplist, token); + if (cprep_nostring) { + if (innertoken == startToken) { + depth++; + } else if (innertoken == endToken) { + if (--depth == 0) { + cprep_nostring = 0; + in_assembler = 0; + copts.cplusplus = save_cplusplus; + copts.asmpoundcomment = save_asmpoundcomment; + } + } + } + break; + + case TK_INTCONST: + case TK_FLOATCONST: + if (tokenstacklevel > 0) + p = macropos; + else + p = prep_file_start + ts_current[-1].tokenoffset; + AppendGListData(&pplist, p, pos - p); + break; + + case TK_IDENTIFIER: + AppendGListData(&pplist, tkidentifier->name, strlen(tkidentifier->name)); + break; + + case TK_AUTO: + AppendGListData(&pplist, "auto", 4); + break; + case TK_REGISTER: + AppendGListData(&pplist, "register", 8); + break; + case TK_STATIC: + AppendGListData(&pplist, "static", 6); + break; + case TK_EXTERN: + AppendGListData(&pplist, "extern", 6); + break; + case TK_TYPEDEF: + AppendGListData(&pplist, "typedef", 7); + break; + case TK_INLINE: + AppendGListData(&pplist, "inline", 6); + break; + case TK_VOID: + AppendGListData(&pplist, "void", 4); + break; + case TK_CHAR: + AppendGListData(&pplist, "char", 4); + break; + case TK_SHORT: + AppendGListData(&pplist, "short", 5); + break; + case TK_INT: + AppendGListData(&pplist, "int", 3); + break; + case TK_LONG: + AppendGListData(&pplist, "long", 4); + break; + case TK_FLOAT: + AppendGListData(&pplist, "float", 5); + break; + case TK_DOUBLE: + AppendGListData(&pplist, "double", 6); + break; + case TK_SIGNED: + AppendGListData(&pplist, "signed", 6); + break; + case TK_UNSIGNED: + AppendGListData(&pplist, "unsigned", 8); + break; + case TK_STRUCT: + AppendGListData(&pplist, "struct", 6); + break; + case TK_UNION: + AppendGListData(&pplist, "union", 5); + break; + case TK_ENUM: + AppendGListData(&pplist, "enum", 4); + break; + case TK_CLASS: + AppendGListData(&pplist, "class", 5); + break; + case TK_CONST: + AppendGListData(&pplist, "const", 5); + break; + case TK_VOLATILE: + AppendGListData(&pplist, "volatile", 8); + break; + case TK_PASCAL: + AppendGListData(&pplist, "pascal", 6); + break; + case TK_UU_FAR: + AppendGListData(&pplist, "__far", 5); + break; + case TK_ONEWAY: + AppendGListData(&pplist, "oneway", 6); + break; + case TK_IN: + AppendGListData(&pplist, "in", 2); + break; + case TK_OUT: + AppendGListData(&pplist, "out", 3); + break; + case TK_INOUT: + AppendGListData(&pplist, "inout", 5); + break; + case TK_BYCOPY: + AppendGListData(&pplist, "bycopy", 6); + break; + case TK_BYREF: + AppendGListData(&pplist, "byref", 5); + break; + case TK_ASM: + AppendGListData(&pplist, "asm", 3); + endToken = 0; + startToken = 0; + AppendGListByte(&pplist, ' '); + token = lex(); + if (token == TK_VOLATILE || (token == TK_IDENTIFIER && !strcmp(tkidentifier->name, "__volatile__"))) { + AppendGListData(&pplist, "volatile", 8); + token = lex(); + } + if (token) { + if (token < ' ' || token > 255) + continue; + AppendGListByte(&pplist, token); + + if (token == '(') { + startToken = '('; + endToken = ')'; + } else if (token == '{') { + startToken = '{'; + endToken = '}'; + } else { + continue; + } + + cprep_nostring = 1; + in_assembler = 1; + depth = 1; + save_asmpoundcomment = copts.asmpoundcomment; + save_cplusplus = copts.cplusplus; + + token = lex(); + if (token == '"') { + AppendGListByte(&pplist, token); + copts.cplusplus = 0; + copts.asmpoundcomment = 1; + break; + } else if (token == 0) { + break; + } + continue; + } + break; + + case TK_CASE: + AppendGListData(&pplist, "case", 4); + break; + case TK_DEFAULT: + AppendGListData(&pplist, "default", 7); + break; + case TK_IF: + AppendGListData(&pplist, "if", 2); + break; + case TK_ELSE: + AppendGListData(&pplist, "else", 4); + break; + case TK_SWITCH: + AppendGListData(&pplist, "switch", 6); + break; + case TK_WHILE: + AppendGListData(&pplist, "while", 5); + break; + case TK_DO: + AppendGListData(&pplist, "do", 2); + break; + case TK_FOR: + AppendGListData(&pplist, "for", 3); + break; + case TK_GOTO: + AppendGListData(&pplist, "goto", 4); + break; + case TK_CONTINUE: + AppendGListData(&pplist, "continue", 8); + break; + case TK_BREAK: + AppendGListData(&pplist, "break", 5); + break; + case TK_RETURN: + AppendGListData(&pplist, "return", 6); + break; + case TK_SIZEOF: + AppendGListData(&pplist, "sizeof", 6); + break; + case TK_CATCH: + AppendGListData(&pplist, "catch", 5); + break; + case TK_DELETE: + AppendGListData(&pplist, "delete", 6); + break; + case TK_FRIEND: + AppendGListData(&pplist, "friend", 6); + break; + case TK_NEW: + AppendGListData(&pplist, "new", 3); + break; + case TK_OPERATOR: + AppendGListData(&pplist, "operator", 8); + break; + case TK_PRIVATE: + AppendGListData(&pplist, "private", 7); + break; + case TK_PROTECTED: + AppendGListData(&pplist, "protected", 9); + break; + case TK_PUBLIC: + AppendGListData(&pplist, "public", 6); + break; + case TK_TEMPLATE: + AppendGListData(&pplist, "template", 8); + break; + case TK_THIS: + AppendGListData(&pplist, "this", 4); + break; + case TK_THROW: + AppendGListData(&pplist, "throw", 5); + break; + case TK_TRY: + AppendGListData(&pplist, "try", 3); + break; + case TK_VIRTUAL: + AppendGListData(&pplist, "virtual", 7); + break; + case TK_INHERITED: + AppendGListData(&pplist, "inherited", 9); + break; + case TK_CONST_CAST: + AppendGListData(&pplist, "const_cast", 10); + break; + case TK_DYNAMIC_CAST: + AppendGListData(&pplist, "dynamic_cast", 12); + break; + case TK_EXPLICIT: + AppendGListData(&pplist, "explicit", 8); + break; + case TK_MUTABLE: + AppendGListData(&pplist, "mutable", 7); + break; + case TK_NAMESPACE: + AppendGListData(&pplist, "namespace", 9); + break; + case TK_REINTERPRET_CAST: + AppendGListData(&pplist, "reinterpret_cast", 16); + break; + case TK_STATIC_CAST: + AppendGListData(&pplist, "static_cast", 11); + break; + case TK_USING: + AppendGListData(&pplist, "using", 5); + break; + case TK_WCHAR_T: + AppendGListData(&pplist, "wchar_t", 7); + break; + case TK_TYPENAME: + AppendGListData(&pplist, "typename", 8); + break; + case TK_TRUE: + AppendGListData(&pplist, "true", 4); + break; + case TK_FALSE: + AppendGListData(&pplist, "false", 5); + break; + case TK_TYPEID: + AppendGListData(&pplist, "typeid", 6); + break; + case TK_EXPORT: + AppendGListData(&pplist, "export", 6); + break; + case TK_UU_STDCALL: + AppendGListData(&pplist, "__stdcall", 9); + break; + case TK_UU_CDECL: + AppendGListData(&pplist, "__cdecl", 7); + break; + case TK_UU_FASTCALL: + AppendGListData(&pplist, "__fastcall", 10); + break; + case TK_UU_DECLSPEC: + AppendGListData(&pplist, "__declspec", 10); + break; + case TK_MULT_ASSIGN: + AppendGListData(&pplist, "*=", 2); + break; + case TK_DIV_ASSIGN: + AppendGListData(&pplist, "/=", 2); + break; + case TK_MOD_ASSIGN: + AppendGListData(&pplist, "%=", 2); + break; + case TK_ADD_ASSIGN: + AppendGListData(&pplist, "+=", 2); + break; + case TK_SUB_ASSIGN: + AppendGListData(&pplist, "-=", 2); + break; + case TK_SHL_ASSIGN: + AppendGListData(&pplist, "<<=", 3); + break; + case TK_SHR_ASSIGN: + AppendGListData(&pplist, ">>=", 3); + break; + case TK_AND_ASSIGN: + AppendGListData(&pplist, "&=", 2); + break; + case TK_XOR_ASSIGN: + AppendGListData(&pplist, "^=", 2); + break; + case TK_OR_ASSIGN: + AppendGListData(&pplist, "|=", 2); + break; + case TK_LOGICAL_OR: + AppendGListData(&pplist, "||", 2); + break; + case TK_LOGICAL_AND: + AppendGListData(&pplist, "&&", 2); + break; + case TK_LOGICAL_EQ: + AppendGListData(&pplist, "==", 2); + break; + case TK_LOGICAL_NE: + AppendGListData(&pplist, "!=", 2); + break; + case TK_LESS_EQUAL: + AppendGListData(&pplist, "<=", 2); + break; + case TK_GREATER_EQUAL: + AppendGListData(&pplist, ">=", 2); + break; + case TK_SHL: + AppendGListData(&pplist, "<<", 2); + break; + case TK_SHR: + AppendGListData(&pplist, ">>", 2); + break; + case TK_INCREMENT: + AppendGListData(&pplist, "++", 2); + break; + case TK_DECREMENT: + AppendGListData(&pplist, "--", 2); + break; + case TK_ARROW: + AppendGListData(&pplist, "->", 2); + break; + case TK_ELLIPSIS: + AppendGListData(&pplist, "...", 3); + break; + case TK_DOT_STAR: + AppendGListData(&pplist, ".*", 2); + break; + case TK_ARROW_STAR: + AppendGListData(&pplist, "->*", 3); + break; + case TK_COLON_COLON: + AppendGListData(&pplist, "::", 2); + break; + case TK_AT_INTERFACE: + AppendGListData(&pplist, "@interface", 10); + break; + case TK_AT_IMPLEMENTATION: + AppendGListData(&pplist, "@implementation", 15); + break; + case TK_AT_PROTOCOL: + AppendGListData(&pplist, "@protocol", 9); + break; + case TK_AT_END: + AppendGListData(&pplist, "@end", 4); + break; + case TK_AT_PRIVATE: + AppendGListData(&pplist, "@private", 8); + break; + case TK_AT_PROTECTED: + AppendGListData(&pplist, "@protected", 10); + break; + case TK_AT_PUBLIC: + AppendGListData(&pplist, "@public", 7); + break; + case TK_AT_CLASS: + AppendGListData(&pplist, "@class", 6); + break; + case TK_AT_SELECTOR: + AppendGListData(&pplist, "@selector", 9); + break; + case TK_AT_ENCODE: + AppendGListData(&pplist, "@encode", 7); + break; + case TK_AT_DEFS: + AppendGListData(&pplist, "@defs", 5); + break; + case TK_SELF: + AppendGListData(&pplist, "self", 4); + break; + case TK_SUPER: + AppendGListData(&pplist, "super", 5); + break; + case TK_BOOL: + if (!copts.cplusplus && copts.c9x) + AppendGListData(&pplist, "_Bool", 5); + else + AppendGListData(&pplist, "bool", 4); + break; + case TK_RESTRICT: + if (copts.c9x) + AppendGListData(&pplist, "restrict", 8); + else + AppendGListData(&pplist, "__restrict", 10); + break; + case TK_UU_VECTOR: + AppendGListData(&pplist, "__vector", 8); + break; + case TK_UU_TYPEOF_UU: + AppendGListData(&pplist, "__typeof__", 10); + break; + case TK_UU_ATTRIBUTE_UU: + AppendGListData(&pplist, "__attribute__", 13); + break; + case TK_UU_ALIGNOF_UU: + AppendGListData(&pplist, "__alignof__", 11); + break; + case TK_UU_UUIDOF: + AppendGListData(&pplist, "__uuidof", 8); + break; + case TK_U_COMPLEX: + AppendGListData(&pplist, "_Complex", 8); + break; + case TK_U_IMAGINARY: + AppendGListData(&pplist, "_Imaginary", 10); + break; + + case TK_STRING: + if (ispascalstring) { + AppendGListData(&pplist, "\"\\p", 3); + CPrep_DumpString((UInt8 *) tkstring + 1, tksize - 1); + } else { + AppendGListByte(&pplist, '"'); + CPrep_DumpString((UInt8 *) tkstring, tksize - 1); + } + AppendGListByte(&pplist, '"'); + break; + + case TK_STRING_WIDE: + AppendGListData(&pplist, "L\"", 2); + CPrep_DumpWString((UInt16 *) tkstring, (tksize / stwchar.size) - 1); + AppendGListByte(&pplist, '"'); + break; + + default: + if (token >= 32 && token <= 255) + AppendGListByte(&pplist, token); + else + CError_FATAL(563); + } + break; + } + + CPrep_TokenStreamFlush(); + nlflag = 0; + spaceskip = 0; + } while ((token = lex())); + } + + AppendGListByte(&pplist, 0); + COS_ResizeHandle(pplist.data, pplist.size); +} diff --git a/compiler_and_linker/FrontEnd/C/CRTTI.c b/compiler_and_linker/FrontEnd/C/CRTTI.c new file mode 100644 index 0000000..3881153 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CRTTI.c @@ -0,0 +1,940 @@ +#include "compiler/CRTTI.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CInit.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CScope.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/types.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CPrep.h" + +typedef struct Offset { + struct Offset *next; + SInt32 offset; +} Offset; + +static Offset *crtti_offsets; +static OLinkList *crtti_olinks; + +// forward decls +static Object *CRTTI_ConstructTypeInfoObject(Type *type, UInt32 qual); + +typedef struct RTTISubClassList { + struct RTTISubClassList *next; + TypeClass *base; + SInt32 voffset; +} RTTISubClassList; + +typedef struct RTTIBaseList { + struct RTTIBaseList *next; + TypeClass *base; + RTTISubClassList *subclasses; + SInt32 voffset; + short numsubclasses; + Boolean x12; + Boolean x13; +} RTTIBaseList; + +static RTTIBaseList *CRTTI_CreateBaseList(TypeClass *tclass, TypeClass *tclassbase, RTTIBaseList *list, SInt32 voffset, Boolean flag) { + RTTIBaseList *scan; + ClassList *base; + Boolean flag27; + SInt32 newvoffset; + + if (tclass != tclassbase) { + flag27 = 0; + + for (scan = list; scan; scan = scan->next) { + if (scan->base == tclassbase) { + if (scan->voffset == voffset) { + if (!flag) + scan->x12 = 0; + flag27 = 0; + } else { + scan->x13 = 1; + flag27 = 1; + } + break; + } + } + + if (!scan || flag27) { + scan = lalloc(sizeof(RTTIBaseList)); + memclrw(scan, sizeof(RTTIBaseList)); + + scan->next = list; + list = scan; + scan->base = tclassbase; + scan->voffset = voffset; + scan->x12 = flag; + scan->x13 = flag27; + } + } + + for (base = tclassbase->bases; base; base = base->next) { + if (base->is_virtual) + newvoffset = CClass_VirtualBaseOffset(tclass, base->base); + else + newvoffset = voffset + base->offset; + + list = CRTTI_CreateBaseList(tclass, base->base, list, newvoffset, flag || base->access == ACCESSPRIVATE); + } + + return list; +} + +static void CRTTI_CreateSubClassList(TypeClass *tclass, RTTIBaseList *baselist, TypeClass *tclassbase, SInt32 voffset, Boolean flag) { + ClassList *base; + RTTISubClassList *scan; + SInt32 newvoffset; + + if (baselist->base != tclassbase) { + for (scan = baselist->subclasses; scan; scan = scan->next) { + if (scan->base == tclassbase && scan->voffset == voffset) + break; + } + + if (!scan) { + scan = lalloc(sizeof(RTTISubClassList)); + scan->next = baselist->subclasses; + baselist->subclasses = scan; + + scan->base = tclassbase; + scan->voffset = voffset; + baselist->numsubclasses++; + } + } + + for (base = tclassbase->bases; base; base = base->next) { + if (base->access == ACCESSPUBLIC) { + if (base->is_virtual) { + if (!flag) + continue; + newvoffset = CClass_VirtualBaseOffset(tclass, base->base); + } else { + newvoffset = voffset + base->offset; + } + + CRTTI_CreateSubClassList(tclass, baselist, base->base, newvoffset, flag); + } + } +} + +static Object *CRTTI_CreateBaseListObject(TypeClass *tclass) { + RTTIBaseList *baselist; + OLinkList *refs; + Object *object; + SInt32 *buf; + SInt32 size; + short count1; + short count2; + short total; + OLinkList *ref; + RTTIBaseList *scan; + RTTISubClassList *subclass; + SInt32 *work; + SInt32 *work2; + + baselist = CRTTI_CreateBaseList(tclass, tclass, NULL, 0, 0); + if (!baselist) + return NULL; + + count1 = 0; + count2 = 0; + total = 0; + + for (scan = baselist; scan; scan = scan->next) { + if (scan->x13 || scan->x12) { + CRTTI_CreateSubClassList(tclass, scan, scan->base, scan->voffset, scan->x13 == 0); + if (scan->numsubclasses) { + total += scan->numsubclasses; + count2++; + } + } else { + count1++; + } + } + + if (!count1 && !count2) + return NULL; + + size = (count1 + total) * 8 + count2 * 12 + 4; + buf = lalloc(size); + memclrw(buf, size); + + object = CParser_NewCompilerDefDataObject(); + object->name = CParser_GetUniqueName(); + object->type = CDecl_NewStructType(size, 4); + object->qual = Q_CONST; + object->sclass = TK_STATIC; + refs = NULL; + + work = buf; + + if (count1) { + for (scan = baselist; scan; scan = scan->next) { + if (!scan->x12 && !scan->x13) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + + ref->obj = CRTTI_ConstructTypeInfoObject(TYPE(scan->base), 0); + ref->offset = ((char *) work) - ((char *) buf); + ref->somevalue = 0; + + work[1] = CTool_EndianConvertWord32(scan->voffset); + work += 2; + } + } + } + + if (count2) { + for (scan = baselist; scan; scan = scan->next) { + if (scan->numsubclasses) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + + ref->obj = CRTTI_ConstructTypeInfoObject(TYPE(scan->base), 0); + ref->offset = ((char *) work) - ((char *) buf); + ref->somevalue = 0; + + work[1] = CTool_EndianConvertWord32(scan->voffset | 0x80000000); + work[2] = CTool_EndianConvertWord32(scan->numsubclasses); + work2 = work + 3; + + for (subclass = scan->subclasses; subclass; subclass = subclass->next) { + ref = lalloc(sizeof(OLinkList)); + ref->next = refs; + refs = ref; + + ref->obj = CRTTI_ConstructTypeInfoObject(TYPE(subclass->base), 0); + ref->offset = ((char *) work2) - ((char *) buf); + ref->somevalue = 0; + + work2[1] = CTool_EndianConvertWord32(subclass->voffset); + work2 += 2; + } + + work = work2; + } + } + } + + CInit_DeclareData(object, buf, refs, object->type->size); + return object; +} + +static Object *CRTTI_ConstructTypeInfoObject(Type *type, UInt32 qual) { + Object *baselistobj; + Object *nameobj; + HashNameNode *rttiname; + OLinkList *refs; + char *namestr; + int namelen; + Object *object; + NameSpaceObjectList *list; + TypePointer tptr_copy; + TypeMemberPointer tmemptr_copy; + UInt32 data[2]; + + switch (type->type) { + case TYPEPOINTER: + if (TPTR_QUAL(type) & (Q_CONST | Q_VOLATILE)) { + tptr_copy = *TYPE_POINTER(type); + tptr_copy.qual &= ~(Q_CONST | Q_VOLATILE); + type = TYPE(&tptr_copy); + } + break; + case TYPEMEMBERPOINTER: + if (TYPE_MEMBER_POINTER(type)->qual & (Q_CONST | Q_VOLATILE)) { + tmemptr_copy = *TYPE_MEMBER_POINTER(type); + tmemptr_copy.qual &= ~(Q_CONST | Q_VOLATILE); + type = TYPE(&tmemptr_copy); + } + break; + default: + qual = 0; + } + + if (IS_TYPE_CLASS(type) && type->size == 0) { + CDecl_CompleteType(type); + if (!(TYPE_CLASS(type)->flags & CLASS_COMPLETED)) + CError_Error(CErrorStr136, type, 0); + } + + rttiname = CMangler_RTTIObjectName(type, qual); + list = CScope_FindName(cscope_root, rttiname); + + if (!list || (object = OBJECT(list->object))->otype != OT_OBJECT || object->datatype != DDATA) { + namestr = CError_GetTypeName(type, qual, 0); + namelen = strlen(namestr) + 1; + nameobj = CInit_DeclareString(namestr, namelen, 0, 0); + + baselistobj = NULL; + if (IS_TYPE_CLASS(type)) + baselistobj = CRTTI_CreateBaseListObject(TYPE_CLASS(type)); + + memclrw(data, sizeof(data)); + + object = CParser_NewCompilerDefDataObject(); + object->name = rttiname; + object->type = CDecl_NewStructType(sizeof(data), 4); + object->qual = Q_CONST; + object->sclass = TK_STATIC; + + refs = lalloc(sizeof(OLinkList)); + refs->next = NULL; + refs->obj = nameobj; + refs->offset = 0; + refs->somevalue = 0; + + if (baselistobj) { + refs->next = lalloc(sizeof(OLinkList)); + refs->next->next = NULL; + refs->next->obj = baselistobj; + refs->next->offset = 4; + refs->next->somevalue = 0; + } + + CScope_AddGlobalObject(object); + CInit_DeclareData(object, data, refs, object->type->size); + } + + return object; +} + +static void CRTTI_ConstructVTableHeader(TypeClass *tclass1, TypeClass *tclass2, Object *typeinfoObj, char *data, SInt32 offset, SInt32 voffset) { + ClassList *base; + Offset *o; + OLinkList *olink; + SInt32 tmp; + SInt32 newoffset; + SInt32 newvoffset; + + if (tclass2->vtable->owner == tclass2) { + for (o = crtti_offsets; o; o = o->next) { + if (o->offset == voffset) + break; + } + + if (!o) { + o = lalloc(sizeof(Offset)); + o->next = crtti_offsets; + o->offset = voffset; + crtti_offsets = o; + + olink = lalloc(sizeof(OLinkList)); + olink->next = crtti_olinks; + olink->obj = typeinfoObj; + olink->offset = voffset; + olink->somevalue = 0; + crtti_olinks = olink; + + *((SInt32 *) (data + voffset + 4)) = CTool_EndianConvertWord32(-offset); + } else { + tmp = *((SInt32 *) (data + voffset + 4)); + CError_ASSERT(404, tmp == CTool_EndianConvertWord32(-offset)); + } + } + + for (base = tclass2->bases; base; base = base->next) { + if (base->base->vtable) { + if (base->is_virtual) { + newoffset = CClass_VirtualBaseOffset(tclass1, base->base); + newvoffset = CClass_VirtualBaseVTableOffset(tclass1, base->base); + } else { + newoffset = offset + base->offset; + newvoffset = voffset + base->voffset; + } + + CRTTI_ConstructVTableHeader(tclass1, base->base, typeinfoObj, data, newoffset, newvoffset); + } + } +} + +OLinkList *CRTTI_ConstructVTableHeaders(TypeClass *tclass, void *data, OLinkList *links) { + crtti_offsets = NULL; + crtti_olinks = links; + + CRTTI_ConstructVTableHeader( + tclass, tclass, + CRTTI_ConstructTypeInfoObject(TYPE(tclass), 0), + data, 0, 0); + + return crtti_olinks; +} + +static Type *CRTTI_FindTypeInfoType(void) { + NameSpace *nspace; + NameSpaceObjectList *list; + Type *type; + + if ((list = CScope_FindName(cscope_root, GetHashNameNodeExport("std"))) && list->object->otype == OT_NAMESPACE) + nspace = OBJ_NAMESPACE(list->object)->nspace; + else + nspace = cscope_root; + + type = CScope_GetLocalTagType(nspace, GetHashNameNodeExport("type_info")); + if (type && IS_TYPE_CLASS(type) && type->size) + return type; + + CError_Error(CErrorStr140, "::std::type_info"); + return TYPE(&stchar); +} + +ENode *CRTTI_ParseTypeID(void) { + ENode *expr; + Type *type; + Type *typeinfoType; + UInt32 qual; + + if (!copts.RTTI) + CError_Warning(CErrorStr257); + + typeinfoType = CRTTI_FindTypeInfoType(); + + if (lex() != '(') { + CError_Error(CErrorStr114); + return nullnode(); + } + + tk = lex(); + if ((type = CParser_ParseTypeID(&qual, NULL))) { + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + + if (IS_TYPE_REFERENCE(type)) + type = TPTR_TARGET(type); + } else { + expr = s_expression(); + + if (tk != ')') + CError_ErrorSkip(CErrorStr115); + else + tk = lex(); + + type = expr->rtype; + qual = ENODE_QUALS(expr); + + if (IS_TYPE_REFERENCE(type)) + type = TPTR_TARGET(type); + + if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->vtable) { + expr = funccallexpr( + Rgtid_func, + getnodeaddress(expr, 0), + intconstnode(TYPE(&stsignedlong), TYPE_CLASS(type)->vtable->offset), + NULL, + NULL); + expr->rtype = CDecl_NewPointerType(typeinfoType); + + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = typeinfoType; + expr->flags = ENODE_FLAG_CONST; + return expr; + } + } + + expr = create_objectrefnode(CRTTI_ConstructTypeInfoObject(type, qual)); + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = typeinfoType; + expr->flags = ENODE_FLAG_CONST; + return expr; +} + +static void CRTTI_ConstCastQualCheck(UInt32 qual1, UInt32 qual2) { + if ( + ((qual1 & Q_CONST) && !(qual2 & Q_CONST)) || + ((qual1 & Q_VOLATILE) && !(qual2 & Q_VOLATILE)) + ) + CError_Error(CErrorStr258); +} + +static void CRTTI_ConstCastCheck(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2) { + Boolean flag = 1; + if (IS_TYPE_REFERENCE(type2)) { + type2 = TPTR_TARGET(type2); + flag = 0; + } + + while (1) { + if (type1->type != type2->type) + break; + + switch (type1->type) { + case TYPEPOINTER: + if (!flag) + CRTTI_ConstCastQualCheck(TPTR_QUAL(type1), TPTR_QUAL(type2)); + type1 = TPTR_TARGET(type1); + type2 = TPTR_TARGET(type2); + flag = 0; + continue; + + case TYPEMEMBERPOINTER: + if (!flag) + CRTTI_ConstCastQualCheck(TYPE_MEMBER_POINTER(type1)->qual, TYPE_MEMBER_POINTER(type2)->qual); + type1 = TYPE_MEMBER_POINTER(type1)->ty1; + type2 = TYPE_MEMBER_POINTER(type2)->ty1; + flag = 0; + continue; + } + + break; + } + + if (!flag && !IS_TYPE_FUNC(type1) && !IS_TYPE_FUNC(type2)) + CRTTI_ConstCastQualCheck(CParser_GetCVTypeQualifiers(type1, qual1), CParser_GetCVTypeQualifiers(type2, qual2)); +} + +static ENode *CRTTI_ParseCast(DeclInfo *di) { + ENode *expr; + + if (lex() != '<') { + CError_Error(CErrorStr230); + return NULL; + } + + tk = lex(); + + memclrw(di, sizeof(DeclInfo)); + CParser_GetDeclSpecs(di, 0); + scandeclarator(di); + + if (di->name) + CError_Error(CErrorStr164); + + if (tk != '>') { + CError_Error(CErrorStr231); + return NULL; + } + + if (lex() != '(') { + CError_Error(CErrorStr114); + return NULL; + } + + tk = lex(); + expr = s_expression(); + if (!IS_TYPE_REFERENCE(di->thetype)) + expr = pointer_generation(expr); + + if (tk != ')') { + CError_Error(CErrorStr115); + return NULL; + } + + tk = lex(); + return expr; +} + +static void CRTTI_IncompleteCheck(Type *type) { + if (IS_TYPE_POINTER_ONLY(type)) + type = TPTR_TARGET(type); + + if (IS_TYPE_CLASS(type) && type->size == 0) { + CDecl_CompleteType(type); + if (!(TYPE_CLASS(type)->flags & CLASS_COMPLETED)) + CError_Error(CErrorStr136, type, 0); + } +} + +static Boolean CRTTI_IsSameType(Type *a, Type *b) { + while (1) { + if (a->type != b->type) + return 0; + + switch (a->type) { + case TYPEVOID: + return 1; + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPESTRUCT: + return a == b; + case TYPEPOINTER: + a = TPTR_TARGET(a); + b = TPTR_TARGET(b); + continue; + default: + return is_typesame(a, b); + } + } +} + +static ENode *CRTTI_UniversalCast(ENode *expr, Type *type, UInt32 qual, UInt8 mode) { + // type/qual are the target type + Boolean isSimpleCast; + Boolean needsTypcon; + Boolean failed; + + if (ENODE_IS(expr, EOBJLIST)) + return CExpr_AssignmentPromotion(expr, type, qual & (Q_CONST | Q_VOLATILE), 1); + + isSimpleCast = needsTypcon = failed = 0; + + switch (type->type) { + case TYPEINT: + case TYPEENUM: + if (mode == 2 && IS_TYPE_POINTER_ONLY(expr->rtype) && type != TYPE(&stbool)) + failed = 1; + break; + + case TYPEPOINTER: + if (TPTR_QUAL(type) & Q_REFERENCE) { + if ( + !CRTTI_IsSameType(TPTR_TARGET(type), expr->rtype) && + mode == 2 && + !( + IS_TYPE_CLASS(TPTR_TARGET(type)) && + IS_TYPE_CLASS(expr->rtype) && + ( + CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(type)), TYPE_CLASS(expr->rtype), NULL, 0, 1) || + CClass_IsBaseClass(TYPE_CLASS(expr->rtype), TYPE_CLASS(TPTR_TARGET(type)), NULL, 0, 1) + ) + ) + ) + { + failed = 1; + } + } else if (IS_TYPE_POINTER_ONLY(expr->rtype)) { + if ( + mode == 3 || + CRTTI_IsSameType(type, expr->rtype) || + IS_TYPE_VOID(TPTR_TARGET(type)) || + IS_TYPE_VOID(TPTR_TARGET(expr->rtype)) + ) + { + isSimpleCast = needsTypcon = 1; + } + else if ( + mode == 2 && + !( + IS_TYPE_CLASS(TPTR_TARGET(type)) && + IS_TYPE_CLASS(TPTR_TARGET(expr->rtype)) && + ( + CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(type)), TYPE_CLASS(TPTR_TARGET(expr->rtype)), NULL, 0, 1) || + CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(expr->rtype)), TYPE_CLASS(TPTR_TARGET(type)), NULL, 0, 1) + ) + ) + ) + { + failed = 1; + } + } else { + if (IS_TYPE_ENUM(expr->rtype)) + expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; + + if (IS_TYPE_INT(expr->rtype)) { + if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval)) { + isSimpleCast = 1; + break; + } + + if (mode != 2) + break; + } + + if (IS_TYPE_CLASS(expr->rtype)) { + if (mode == 2) + break; + } + + failed = 1; + } + break; + } + + if (failed) { + CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); + return expr; + } + + if (isSimpleCast) { + if (needsTypcon && ENODE_IS(expr, EINDIRECT) && (copts.pointercast_lvalue || !copts.ANSIstrict)) + expr = makemonadicnode(expr, ETYPCON); + + expr->rtype = type; + expr->flags = qual & ENODE_FLAG_QUALS; + return expr; + } + + if (copts.old_argmatch) + return do_typecast(expr, type, qual); + + return CExpr_Convert(expr, type, qual, 1, 1); +} + +ENode *CRTTI_Parse_dynamic_cast(void) { + Boolean isRef; + ENode *expr; + TypeClass *srcclass; + TypeClass *destclass; + ENode *typeinfo; + DeclInfo di; + + expr = CRTTI_ParseCast(&di); + if (!expr) + return nullnode(); + + if (!copts.RTTI) + CError_Warning(CErrorStr257); + + CRTTI_ConstCastCheck(expr->rtype, expr->flags, di.thetype, di.qual); + if (!IS_TYPE_POINTER_ONLY(di.thetype)) { + CError_Error(CErrorStr164); + return expr; + } + + isRef = (TPTR_QUAL(di.thetype) & Q_REFERENCE) != 0; + + if (IS_TYPE_CLASS(TPTR_TARGET(di.thetype))) { + destclass = TYPE_CLASS(TPTR_TARGET(di.thetype)); + CDecl_CompleteType(TYPE(destclass)); + if (!(destclass->flags & CLASS_COMPLETED)) { + CError_Error(CErrorStr136, destclass, 0); + return expr; + } + } else if (!IS_TYPE_VOID(TPTR_TARGET(di.thetype))) { + CError_Error(CErrorStr164); + return expr; + } else { + destclass = NULL; + } + + if (isRef) { + if (!IS_TYPE_CLASS(expr->rtype)) { + CError_Error(CErrorStr164); + return expr; + } + + srcclass = TYPE_CLASS(expr->rtype); + if (destclass) { + if (srcclass == destclass || CClass_IsBaseClass(srcclass, destclass, NULL, 0, 1)) + return do_typecast(expr, di.thetype, di.qual); + } + + expr = getnodeaddress(expr, 1); + } else { + if (!IS_TYPE_POINTER_ONLY(expr->rtype) || !IS_TYPE_CLASS(TPTR_TARGET(expr->rtype))) { + CError_Error(CErrorStr164); + return expr; + } + + srcclass = TYPE_CLASS(TPTR_TARGET(expr->rtype)); + if (destclass) { + if (srcclass == destclass || CClass_IsBaseClass(srcclass, destclass, NULL, 0, 1)) + return do_typecast(expr, di.thetype, di.qual); + } + } + + if (!(srcclass->flags & CLASS_COMPLETED)) { + CError_Error(CErrorStr136, srcclass, 0); + return expr; + } + + if (!srcclass->vtable) { + CError_Error(CErrorStr164); + return expr; + } + + if (srcclass->sominfo) { + CError_Error(CErrorStr164); + return expr; + } + + if (destclass) { + typeinfo = create_objectrefnode(CRTTI_ConstructTypeInfoObject(TYPE(destclass), 0)); + if (destclass->sominfo) { + CError_Error(CErrorStr164); + return expr; + } + } else { + typeinfo = nullnode(); + } + + expr = CExpr_FuncCallSix( + Rdync_func, + expr, + intconstnode(TYPE(&stsignedlong), srcclass->vtable->offset), + typeinfo, + create_objectrefnode(CRTTI_ConstructTypeInfoObject(TYPE(srcclass), 0)), + intconstnode(TYPE(&stsignedshort), isRef), + NULL + ); + + if (isRef) { + expr->rtype = CDecl_NewPointerType(TYPE(destclass)); + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = TYPE(destclass); + } else { + expr->rtype = di.thetype; + } + expr->flags = di.qual & ENODE_FLAG_QUALS; + return expr; +} + +ENode *CRTTI_Parse_static_cast(void) { + ENode *expr; + DeclInfo di; + + expr = CRTTI_ParseCast(&di); + if (!expr) + return nullnode(); + + CRTTI_ConstCastCheck(expr->rtype, expr->flags, di.thetype, di.qual); + + if (IS_TYPE_REFERENCE(di.thetype)) { + if (IS_TYPE_CLASS(expr->rtype) && CExpr_CanImplicitlyConvert(expr, di.thetype, di.qual)) { + expr = CExpr_Convert(expr, di.thetype, di.qual, 0, 1); + CError_ASSERT(959, IS_TYPE_POINTER_ONLY(expr->rtype)); + + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = TPTR_TARGET(di.thetype); + expr->flags = di.qual & ENODE_FLAG_QUALS; + return expr; + } + } else { + if (CExpr_CanImplicitlyConvert(expr, di.thetype, di.qual)) + return CExpr_Convert(expr, di.thetype, di.qual, 1, 1); + } + + if (!IS_TYPE_VOID(di.thetype) && !(IS_TYPE_POINTER_ONLY(expr->rtype) && IS_TYPE_VOID(TPTR_TARGET(expr->rtype)))) { + CRTTI_IncompleteCheck(di.thetype); + CRTTI_IncompleteCheck(expr->rtype); + } + + return CRTTI_UniversalCast(expr, di.thetype, di.qual, 2); +} + +ENode *CRTTI_Parse_reinterpret_cast(void) { + ENode *expr; + Type *origtype; + ENode *lvalue; + DeclInfo di; + + expr = CRTTI_ParseCast(&di); + if (!expr) + return nullnode(); + + CRTTI_ConstCastCheck(expr->rtype, expr->flags, di.thetype, di.qual); + + if (IS_TYPE_REFERENCE(di.thetype)) { + lvalue = CExpr_LValue(expr, 0, 1); + if (!ENODE_IS(lvalue, EINDIRECT)) + return lvalue; + + lvalue->data.monadic->rtype = CDecl_NewPointerType(lvalue->rtype); + expr = lvalue->data.monadic; + origtype = di.thetype; + di.thetype = CDecl_NewPointerType(TPTR_TARGET(di.thetype)); + } else { + origtype = NULL; + } + + switch (di.thetype->type) { + case TYPEINT: + switch (expr->rtype->type) { + case TYPEMEMBERPOINTER: + case TYPEPOINTER: + expr = do_typecast(expr, di.thetype, di.qual); + break; + default: + CError_Error(CErrorStr164); + } + break; + case TYPEPOINTER: + switch (expr->rtype->type) { + case TYPEINT: + case TYPEENUM: + if (origtype) + di.thetype = origtype; + expr = do_typecast(expr, di.thetype, di.qual); + break; + case TYPEPOINTER: + expr = makemonadicnode(expr, ETYPCON); + expr->rtype = di.thetype; + expr->flags = di.qual & ENODE_FLAG_QUALS; + break; + default: + CError_Error(CErrorStr164); + } + break; + case TYPEMEMBERPOINTER: + if (IS_TYPE_MEMBERPOINTER(expr->rtype)) { + if (IS_TYPE_FUNC(TYPE_MEMBER_POINTER(di.thetype)->ty1)) { + if (IS_TYPE_FUNC(TYPE_MEMBER_POINTER(expr->rtype)->ty1)) { + expr->rtype = di.thetype; + expr->flags = di.qual & ENODE_FLAG_QUALS; + break; + } + } else { + if (!IS_TYPE_FUNC(TYPE_MEMBER_POINTER(expr->rtype)->ty1)) { + expr->rtype = di.thetype; + expr->flags = di.qual & ENODE_FLAG_QUALS; + break; + } + } + } + expr = do_typecast(expr, di.thetype, di.qual); + break; + default: + CError_Error(CErrorStr164); + } + + if (origtype && IS_TYPE_POINTER_ONLY(expr->rtype)) { + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = TPTR_TARGET(di.thetype); + } + + return expr; +} + +ENode *CRTTI_Parse_const_cast(void) { + DeclInfo di; + ENode *expr; + + if (!(expr = CRTTI_ParseCast(&di))) + return nullnode(); + + if (IS_TYPE_POINTER_ONLY(di.thetype)) { + if (TPTR_QUAL(di.thetype) & Q_REFERENCE) { + if (!iscpp_typeequal(TPTR_TARGET(di.thetype), expr->rtype)) + CError_Error(CErrorStr164); + + if (ENODE_IS(expr, EINDIRECT)) { + expr->rtype = TPTR_TARGET(di.thetype); + expr->flags = di.qual & ENODE_FLAG_QUALS; + } else { + CError_Error(CErrorStr142); + } + } else { + if (!iscpp_typeequal(di.thetype, expr->rtype)) + CError_Error(CErrorStr164); + + expr = do_typecast(expr, di.thetype, di.qual); + } + } else if (IS_TYPE_MEMBERPOINTER(di.thetype)) { + if (!iscpp_typeequal(di.thetype, expr->rtype)) + CError_Error(CErrorStr164); + + expr = do_typecast(expr, di.thetype, di.qual); + } else { + if (!is_typesame(di.thetype, expr->rtype)) + CError_Error(CErrorStr164); + else + expr = do_typecast(expr, di.thetype, di.qual); + } + + return expr; +} diff --git a/compiler_and_linker/FrontEnd/C/CSOM.c b/compiler_and_linker/FrontEnd/C/CSOM.c new file mode 100644 index 0000000..7e80e32 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CSOM.c @@ -0,0 +1,2068 @@ +#include "compiler/CSOM.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CException.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInit.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/CodeGen.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/types.h" +#include "cos.h" + +// all pointers have been converted to UInt32 for the sake of maintaining 32-bit compat + +typedef struct { + SInt32 zero; + /* struct somStaticClassInfo * */ UInt32 sci; + /* void * */ UInt32 instanceDataToken; + SInt32 reserved[3]; + /* void * */ UInt32 tokens[1]; +} somClassDataStructure; + +enum { + mtVirtualMethod = 0, + mtProcedure = 1, + mtNonStatic = 2, + mtEmpty = 3, + mtDToken = 4 +}; + +enum { + pdUByte = 0, + pdSByte = 1, + pdUHalf = 2, + pdSHalf = 3, + pdULong = 4, + pdSLong = 5, + pdVLong = 6, + pdVoid = 7, + pdSFlt = 8, + pdDFlt = 9, + pdLFlt = 10, + pdVSAgg = 11, + pdNPtr = 12, + pdLPtr = 13, + pdSAgg = 14, + pdLAgg = 15 +}; + +enum { + fgShortOrChars = 1, + fgShortFloats = 2, + fgAnyFloats = 4, + fgAnyNon4Bytes = 8 +}; + +enum { + cfSharedStrings = 1, + cfTempClass = 2, + cfProxyClass = 4, + cfClassAllocate = 0x100, + cfClassDeallocate = 0x200, + cfClassInit = 0x400, + cfClassUninit = 0x800 +}; + +typedef struct { + UInt32 majorVersion; + UInt32 minorVersion; + UInt32 flags; + UInt16 dataAlignment; + UInt16 classTokenCount; + UInt16 numDirectParents; + UInt16 numMetaClasses; + UInt16 numOverriddenAncestors; + UInt16 numMigratedMethods; + UInt16 numSelectInherited; + UInt16 numUnused; + UInt16 dummy2a[4]; +} somStaticClassCounts; + +typedef UInt8 somSlotUsage; +typedef UInt8 somSignatureInfo; +typedef UInt16 somOverrideData; +typedef UInt16 somMigratedMethods; +typedef UInt16 somSelectedInherited; +typedef UInt32 somParentVersions; + +typedef struct { + /* const char * */ UInt32 className; + UInt32 instanceDataSize; + /* const somParentVersions * */ UInt32 parentVersions; + /* const somSlotUsage * */ UInt32 ttSlotUsage; + /* const somSignatureInfo * */ UInt32 signatureInfo; + /* const char * */ UInt32 methodNames; + /* const somOverrideData * */ UInt32 overrideData; + /* const somMigratedMethods * */ UInt32 migratedMethods; + /* const somSelectedInherited * */ UInt32 selectedInherited; + /* const void * */ UInt32 unused; + /* const void * */ UInt32 dummy4b[4]; +} somStaticClassDescription; + +typedef struct somStaticClassInfo { + UInt32 layoutVersion; + /* somClassDataStructure * */ UInt32 tokenTable; + /* somMethodPtr * */ UInt32 overrideMethods; + /* somClassDataStructure ** */ UInt32 specifiedAncestry; + /* somOpaque */ UInt32 DLLDesignator; + /* somMethodPtr * */ UInt32 specialProcs; + /* somRuntimeClassInfo * */ UInt32 runtimeClassInfo; + SInt32 interesting; + /* somClassDataStructure ** */ UInt32 actualAncestry; + /* void * */ UInt32 extra[4]; + /* const somStaticClassCounts * */ UInt32 classCounts; + somStaticClassDescription classDescription; +} somStaticClassInfo; + +CSOMStub *csom_stubs; +static HashNameNode *csom_initname; +static HashNameNode *csom_uninitname; +static HashNameNode *csom_envname; +static HashNameNode *csom_selfname; + +static FuncArg SOMIDT_arg1 = { + NULL, + NULL, + NULL, + TYPE(&void_ptr), + 0, + 0, + 0 +}; + +static TypeFunc SOMIDT_type = { + TYPEFUNC, + 0, + &SOMIDT_arg1, + NULL, + TYPE(&void_ptr), + 0, + 0 +}; + +void CSOM_Setup(Boolean flag) { + if (!flag) + csom_stubs = NULL; + + csom_initname = GetHashNameNodeExport("somInit"); + csom_uninitname = GetHashNameNodeExport("somUninit"); + csom_envname = GetHashNameNodeExport("Environment"); + csom_selfname = GetHashNameNodeExport("__somself"); +} + +void CSOM_Cleanup(void) { + CSOMStub *stub; + + if (cparamblkptr->precompile != 1) { + for (stub = csom_stubs; stub; stub = stub->next) { + switch (stub->x10) { + case 0: + CodeGen_SOMStub(stub->object, rt_som_glue1, stub->tclass->sominfo->classdataobject, stub->offset); + break; + case 1: + CodeGen_SOMStub(stub->object, rt_som_glue2, stub->tclass->sominfo->classdataobject, stub->offset); + break; + case 2: + CodeGen_SOMStub(stub->object, rt_som_glue3, stub->tclass->sominfo->classdataobject, stub->offset); + break; + default: + CError_FATAL(132); + } + } + } +} + +static HashNameNode *CSOM_NameTranslate(HashNameNode *name) { + if (name == constructor_name_node) + name = csom_initname; + else if (name == destructor_name_node) + name = csom_uninitname; + return name; +} + +static Type *CSOM_FindClassType(HashNameNode *name) { + Type *type; + + type = CScope_GetTagType(cscope_current, name); + if (!type) { + CPrep_ErrorName(CErrorStr281, name->name); + type = &stvoid; + } + + return type; +} + +CW_INLINE UInt16 CSOM_GetTokenTableIndex(const Object *object) { + CError_ASSERT(173, IS_TYPE_METHOD(object->type)); + return TYPE_METHOD(object->type)->vtbl_index; +} + +static SInt32 CSOM_GetTokenOffset(Object *object) { + return 24 + 4 * CSOM_GetTokenTableIndex(object); +} + +typedef struct TypeSig { + UInt8 x0; + UInt8 x1; + UInt8 x2; +} TypeSig; + +static int CSOM_GetTypeSig(TypeSig *sig, Type *type, Boolean flag) { + if (type->size > 4) + sig->x1 |= fgAnyNon4Bytes; + + switch (type->type) { + case TYPEVOID: + if (flag) + return pdVoid; + break; + case TYPEINT: + case TYPEENUM: + if (is_unsigned(type)) { + switch (type->size) { + case 1: + sig->x1 |= fgShortOrChars; + return pdUByte; + case 2: + sig->x1 |= fgShortOrChars; + return pdUHalf; + case 4: + return pdULong; + case 8: + return pdVLong; + } + } else { + switch (type->size) { + case 1: + sig->x1 |= fgShortOrChars; + return pdSByte; + case 2: + sig->x1 |= fgShortOrChars; + return pdSHalf; + case 4: + return pdSLong; + case 8: + return pdVLong; + } + } + break; + case TYPEFLOAT: + sig->x1 |= fgAnyFloats; + switch (type->size) { + case 4: + sig->x1 |= fgShortFloats; + return pdSFlt; + case 8: + return pdDFlt; + case 12: + case 16: + return pdLFlt; + } + break; + case TYPEPOINTER: + return pdNPtr; + case TYPESTRUCT: + case TYPECLASS: + if (flag) { + if (type->size <= 2) { + sig->x1 |= fgShortOrChars; + return pdVSAgg; + } else if (type->size <= 4) { + return pdSAgg; + } else { + return pdLAgg; + } + } + break; + } + + CError_Error(CErrorStr273); + return 5; +} + +static void CSOM_GetFuncSig(TypeFunc *tfunc, Boolean flag) { + FuncArg *arg; + Boolean pendingData; + UInt8 work; + TypeSig sig; + + sig.x2 = CSOM_GetTypeSig(&sig, tfunc->functype, 1); + sig.x1 = 0; + sig.x0 = 0; + + for (arg = tfunc->args; arg; arg = arg->next) { + if (arg == &elipsis || arg == &oldstyle || (++sig.x0 == 0)) { + CError_Error(CErrorStr273); + break; + } + + CSOM_GetTypeSig(&sig, arg->type, 0); + } + + if (flag) { + if ((arg = tfunc->args)) { + if (TYPE_METHOD(tfunc)->is_static == 0) + arg = arg->next; + if (arg && CMach_GetFunctionResultClass(tfunc) != 0) + arg = arg->next; + } + + AppendGListByte(&name_mangle_list, sig.x0); + AppendGListByte(&name_mangle_list, (sig.x1 << 4) | sig.x2); + if (sig.x1) { + pendingData = 0; + work = 0; + while (arg) { + work = (work << 4) | CSOM_GetTypeSig(&sig, arg->type, 0); + if (pendingData) { + AppendGListByte(&name_mangle_list, work); + pendingData = 0; + work = 0; + } else { + pendingData = 1; + } + arg = arg->next; + } + + if (pendingData) + AppendGListByte(&name_mangle_list, work << 4); + } + } +} + +void CSOM_CheckFuncType(TypeFunc *tfunc) { + CSOM_GetFuncSig(tfunc, 0); +} + +static Object *CSOM_MakeObject(char *name1, char *name2, SInt32 size) { + Object *object = CParser_NewCompilerDefDataObject(); + object->name = CParser_NameConcat(name1, name2); + object->type = CDecl_NewStructType(size, 4); + CScope_AddObject(object->nspace, object->name, OBJ_BASE(object)); + return object; +} + +void CSOM_MakeSOMClass(TypeClass *tclass) { + ClassList *base; + + for (base = tclass->bases; base; base = base->next) { + if (!base->base->sominfo) { + CError_Error(CErrorStr267); + break; + } + } + + if (!tclass->sominfo) { + SOMInfo *info = galloc(sizeof(SOMInfo)); + memclrw(info, sizeof(SOMInfo)); + tclass->sominfo = info; + + info->classdataobject = CSOM_MakeObject(tclass->classname->name, "ClassData", 28); + info->classdataobject->flags = info->classdataobject->flags | OBJECT_EXPORT; + } +} + +static Boolean CSOM_IsTokenListFunc(Object *object) { + Type *type = object->type; + if ( + IS_TYPE_FUNC(type) && + !(TYPE_FUNC(type)->flags & FUNC_FLAGS_20) && + !TYPE_METHOD(type)->is_static && + (!(object->qual & Q_INLINE) || object->datatype == DVFUNC) + ) + return 1; + + return 0; +} + +static Object **CSOM_GetLexicalOrderMethodArray(TypeClass *tclass, int *resultCount) { + Object *object; + int count; + Object **array; + CScopeObjectIterator iter; + + count = 0; + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (IS_TYPE_METHOD(object->type)) { + if (CSOM_IsTokenListFunc(object)) { + if (TYPE_METHOD(object->type)->vtbl_index > count) + count = TYPE_METHOD(object->type)->vtbl_index; + } else { + TYPE_METHOD(object->type)->vtbl_index = 0; + } + } + } + + *resultCount = ++count; + + array = lalloc(sizeof(Object *) * count); + memclrw(array, sizeof(Object *) * count); + + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (CSOM_IsTokenListFunc(object)) + array[TYPE_METHOD(object->type)->vtbl_index] = object; + } + + return array; +} + +void CSOM_ClassComplete(TypeClass *tclass) { + Object *object; + CScopeObjectIterator iter; + SInt32 counter; + SOMReleaseOrder *order; + + if (tclass->sominfo->order) { + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (CSOM_IsTokenListFunc(object)) { + HashNameNode *name; + + name = CSOM_NameTranslate(object->name); + for (order = tclass->sominfo->order, counter = 0; order; order = order->next, counter++) { + if (order->name == name) { + order->state = SOMMS_Method; + TYPE_METHOD(object->type)->vtbl_index = counter; + break; + } + } + + if (!order) + CError_Error(CErrorStr278, object); + } + } + + for (order = tclass->sominfo->order; order; order = order->next) { + if (order->state == SOMMS_Deleted) { + SOMReleaseOrder *order2; + VClassList *vbase; + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + for (order2 = vbase->base->sominfo->order; order2; order2 = order2->next) { + if (order->name == order2->name && order2->state == SOMMS_Method) { + order->state = SOMMS_Migrated; + break; + } + } + } + } + } + } else { + Object **array; + int arrayCount; + SInt32 i; + + array = CSOM_GetLexicalOrderMethodArray(tclass, &arrayCount); + for (i = counter = 0; i < arrayCount; i++) { + object = array[i]; + if (object) { + if (counter == 0 && copts.pedantic) + CError_Warning(CErrorStr291); + TYPE_METHOD(object->type)->vtbl_index = counter++; + } + } + } + + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + NameSpaceObjectList *nsol; + if (!(nsol = CScope_NextObjectIteratorObjectList(&iter))) + break; + + if (nsol->object->otype == OT_OBJECT && nsol->next && nsol->next->object->otype == OT_OBJECT) { + while (nsol) { + if ( + nsol->object->otype == OT_OBJECT && + (!(OBJECT(nsol->object)->qual & Q_INLINE) || OBJECT(nsol->object)->datatype == DVFUNC) + ) + CError_Error(CErrorStr270, nsol->object); + nsol = nsol->next; + } + } + } + + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (!(object->qual & Q_INLINE)) { + CError_ASSERT(529, IS_TYPE_FUNC(object->type)); + + TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_4; + tclass->action = CLASS_ACTION_1; + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (IS_TYPE_FUNC(object->type)) + TYPE_FUNC(object->type)->flags &= ~FUNC_FLAGS_4; + } + break; + } + } + + if (tclass->sominfo->oidl_callstyle == 0) { + Type *envType; + envType = CSOM_FindClassType(csom_envname); + + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if ( + IS_TYPE_FUNC(object->type) && + TYPE_METHOD(object->type)->is_static == 0 && + !(TYPE_FUNC(object->type)->flags & FUNC_FLAGS_20) && + !( + TYPE_FUNC(object->type)->args && + TYPE_FUNC(object->type)->args->next && + IS_TYPE_POINTER_ONLY(TYPE_FUNC(object->type)->args->next->type) && + TPTR_TARGET(TYPE_FUNC(object->type)->args->next->type) == envType + ) + ) + { + CError_Error(CErrorStr282, object); + } + } + } + + if (tclass->action == CLASS_ACTION_0) + CError_Error(CErrorStr280); +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct SOMOverride { + struct SOMOverride *next; + Object *a; + Object *b; +} SOMOverride; + +typedef struct SOMAncestor { + struct SOMAncestor *next; + TypeClass *tclass; + SOMOverride *overrides; + Boolean xC; + Boolean xD; +} SOMAncestor; + +typedef struct SOMMethod { + struct SOMMethod *next; + HashNameNode *name; + union { + Object *object; + struct { + UInt16 a; + UInt16 b; + } pair; + } u; + SOMMethodState state; +} SOMMethod; + +typedef struct SOMGenerator { + SOMMethod *methods; + SOMAncestor *ancestors; + Object *sciObj; + Object *classAncestorsObj; + Object *overrideProcsObj; + Object *dlldFunc; + Object *specialProcsObj; + somStaticClassCounts counts; + int overrideProcsCount; + Boolean hasNew; + Boolean hasDelete; +} SOMGenerator; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static SOMAncestor *CSOM_FindAddAncestor(SOMGenerator *gen, TypeClass *tclass, TypeClass *ancestorClass, UInt16 *resultIndex) { + SOMAncestor *ancestor; + SOMAncestor *scan; + UInt16 index; + + ancestor = gen->ancestors; + for (scan = ancestor, index = 0; scan; scan = scan->next, index++) { + if (scan->tclass == ancestorClass) { + if (resultIndex) + *resultIndex = index; + return scan; + } + } + + if (ancestor) { + index = 1; + while (ancestor->next) { + index++; + ancestor = ancestor->next; + } + + ancestor->next = lalloc(sizeof(SOMAncestor)); + memclrw(ancestor->next, sizeof(SOMAncestor)); + ancestor = ancestor->next; + } else { + index = 0; + ancestor = lalloc(sizeof(SOMAncestor)); + memclrw(ancestor, sizeof(SOMAncestor)); + gen->ancestors = ancestor; + } + + ancestor->tclass = ancestorClass; + if (resultIndex) + *resultIndex = index; + return ancestor; +} + +static void CSOM_GenerateOverrideIntroLists(SOMGenerator *gen, TypeClass *tclass) { + Object *object; + VClassList *vbase; + ClassList *base; + SOMMethod *method; + SOMMethod **ptr; + CScopeObjectIterator iter; + + for (base = tclass->bases; base; base = base->next) { + SOMAncestor *ancestor = CSOM_FindAddAncestor(gen, tclass, base->base, NULL); + ancestor->xD = 1; + gen->counts.numDirectParents++; + } + + if (tclass->sominfo->metaclass && tclass->sominfo->metaclass->sominfo) { + SOMAncestor *ancestor = CSOM_FindAddAncestor(gen, tclass, tclass->sominfo->metaclass, NULL); + ancestor->xC = 1; + gen->counts.numMetaClasses++; + } + + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (IS_TYPE_FUNC(object->type) && (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_20)) { + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + Object *object2; + CScopeObjectIterator iter2; + CScope_InitObjectIterator(&iter2, vbase->base->nspace); + while (1) { + if (!(object2 = OBJECT(CScope_NextObjectIteratorObject(&iter2)))) + break; + + if ( + IS_TYPE_FUNC(object2->type) && + object->name == object2->name && + object2->datatype == DVFUNC && + !(TYPE_FUNC(object2->type)->flags & FUNC_FLAGS_20) && + CClass_GetOverrideKind(TYPE_FUNC(object->type), TYPE_FUNC(object2->type), 0) != 0 + ) + { + SOMAncestor *ancestor; + SOMOverride *override; + ancestor = CSOM_FindAddAncestor(gen, tclass, vbase->base, NULL); + if (ancestor->overrides) { + override = lalloc(sizeof(SOMOverride)); + memclrw(override, sizeof(SOMOverride)); + override->next = ancestor->overrides; + ancestor->overrides = override; + } else { + override = lalloc(sizeof(SOMOverride)); + memclrw(override, sizeof(SOMOverride)); + ancestor->overrides = override; + gen->counts.numOverriddenAncestors++; + } + override->a = object; + override->b = object2; + break; + } + } + } + gen->overrideProcsCount++; + } + } + + ptr = &gen->methods; + if (tclass->sominfo->order) { + SOMReleaseOrder *order; + SOMReleaseOrder *order2; + SInt32 index; + UInt16 index2; + + for (order = tclass->sominfo->order, index = 0; order; order = order->next, index++) { + method = lalloc(sizeof(SOMMethod)); + memclrw(method, sizeof(SOMMethod)); + *ptr = method; + ptr = &method->next; + + method->name = order->name; + method->state = order->state; + switch (order->state) { + case SOMMS_Migrated: + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + for (order2 = vbase->base->sominfo->order, index2 = 0; order2; order2 = order2->next, index2++) { + if (order->name == order2->name && order2->state == SOMMS_Method) { + CSOM_FindAddAncestor(gen, tclass, vbase->base, &method->u.pair.a); + method->u.pair.b = index2; + break; + } + } + + if (order2) + break; + } + gen->counts.numMigratedMethods++; + break; + + case SOMMS_Method: + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if ( + IS_TYPE_FUNC(object->type) && + CSOM_NameTranslate(object->name) == order->name + ) + { + CError_ASSERT(733, TYPE_METHOD(object->type)->vtbl_index == index); + method->u.object = object; + break; + } + } + + CError_ASSERT(737, object != NULL); + break; + } + + gen->counts.classTokenCount++; + } + } else { + Object **array; + int arrayCount; + SInt32 i; + + array = CSOM_GetLexicalOrderMethodArray(tclass, &arrayCount); + for (i = 0; i < arrayCount; i++) { + object = array[i]; + if (object) { + method = lalloc(sizeof(SOMMethod)); + memclrw(method, sizeof(SOMMethod)); + *ptr = method; + ptr = &method->next; + + method->u.object = object; + method->name = object->name; + method->state = SOMMS_Method; + gen->counts.classTokenCount++; + } + } + } +} + +static void CSOM_GenerateClassAncestors(SOMGenerator *gen, TypeClass *tclass) { + SOMAncestor *ancestor; + Object *object; + OLinkList *relocs; + SInt32 size; + char *buf; + + if (gen->ancestors) { + object = CSOM_MakeObject(tclass->classname->name, "ClassAncestors", 4); + object->sclass = TK_STATIC; + + relocs = NULL; + size = 0; + for (ancestor = gen->ancestors; ancestor; ancestor = ancestor->next) { + OLinkList *reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = ancestor->tclass->sominfo->classdataobject; + reloc->offset = size; + reloc->somevalue = 0; + size += 4; + } + + buf = lalloc(size); + memclrw(buf, size); + object->type->size = size; + CInit_DeclareData(object, buf, relocs, object->type->size); + gen->classAncestorsObj = object; + } +} + +static void CSOM_GenerateOverrideProcs(SOMGenerator *gen, TypeClass *tclass) { + SOMOverride *override; + SOMAncestor *ancestor; + Object *object; + OLinkList *relocs; + SInt32 size; + SInt32 offset; + char *buf; + + if (gen->overrideProcsCount) { + size = gen->overrideProcsCount * 4; + object = CSOM_MakeObject(tclass->classname->name, "OverrideProcs", size); + object->sclass = TK_STATIC; + + relocs = NULL; + offset = 0; + for (ancestor = gen->ancestors; ancestor; ancestor = ancestor->next) { + if (ancestor->overrides) { + for (override = ancestor->overrides; override; override = override->next) { + OLinkList *reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = override->a; + reloc->offset = offset; + reloc->somevalue = 0; + offset += 4; + } + } + } + + buf = lalloc(size); + memclrw(buf, size); + CInit_DeclareData(object, buf, relocs, object->type->size); + gen->overrideProcsObj = object; + } +} + +static Object *CSOM_GenerateOverrideData(SOMGenerator *gen) { + SOMAncestor *ancestor; + Object *object; + short ancestorIndex; + + name_mangle_list.size = 0; + for (ancestor = gen->ancestors, ancestorIndex = 0; ancestor; ancestor = ancestor->next, ancestorIndex++) { + if (ancestor->overrides) { + SOMOverride *override; + short overrideCount; + + AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(ancestorIndex)); + + override = ancestor->overrides; + overrideCount = 0; + while (override) { + overrideCount++; + override = override->next; + } + AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(overrideCount)); + + for (override = ancestor->overrides; override; override = override->next) { + AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(CSOM_GetTokenTableIndex(override->b))); + } + } + } + + COS_LockHandle(name_mangle_list.data); + object = CInit_DeclareString(*name_mangle_list.data, name_mangle_list.size, 0, 0); + COS_UnlockHandle(name_mangle_list.data); + return object; +} + +static Object *CSOM_GenerateMigrateData(SOMGenerator *gen) { + SOMMethod *method; + Object *object; + int index; + + name_mangle_list.size = 0; + for (method = gen->methods, index = 0; method; method = method->next, index++) { + if (method->state == SOMMS_Migrated) { + AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(method->u.pair.a)); + AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(method->u.pair.b)); + AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(index)); + } + } + + COS_LockHandle(name_mangle_list.data); + object = CInit_DeclareString(*name_mangle_list.data, name_mangle_list.size, 0, 0); + COS_UnlockHandle(name_mangle_list.data); + return object; +} + +static void CSOM_GenerateDLLDFunc(SOMGenerator *gen, TypeClass *tclass) { + TypeFunc *tfunc; + Object *object; + + tfunc = galloc(sizeof(TypeFunc)); + memclrw(tfunc, sizeof(TypeFunc)); + tfunc->type = TYPEFUNC; + tfunc->functype = &stvoid; + + object = CParser_NewCompilerDefFunctionObject(); + object->type = TYPE(tfunc); + object->sclass = TK_STATIC; + object->name = CParser_NameConcat(tclass->classname->name, "DLLD"); + + if (CScope_GetLocalObject(cscope_root, object->name)) + CError_Error(CErrorStr333, object); + + gen->dlldFunc = object; + CFunc_GenerateDummyFunction(object); +} + +static void CSOM_GenerateSpecialProcs(SOMGenerator *gen, TypeClass *tclass) { + Object *newFunc; + Object *deleteFunc; + Object *object; + OLinkList *relocs; + SInt32 size; + CScopeObjectIterator iter; + char buf[16]; + + newFunc = deleteFunc = NULL; + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (IS_TYPE_FUNC(object->type)) { + if (object->name == CMangler_OperatorName(TK_NEW)) { + newFunc = object; + gen->hasNew = 1; + } else if (object->name == CMangler_OperatorName(TK_DELETE)) { + deleteFunc = object; + gen->hasDelete = 1; + } + } + } + + if (newFunc || deleteFunc) { + object = CSOM_MakeObject(tclass->classname->name, "SpecialProcs", 4); + object->sclass = TK_STATIC; + + relocs = NULL; + size = 0; + + if (newFunc) { + OLinkList *reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = newFunc; + reloc->offset = size; + reloc->somevalue = 0; + size += 4; + } + + if (deleteFunc) { + OLinkList *reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = deleteFunc; + reloc->offset = size; + reloc->somevalue = 0; + size += 4; + } + + memclrw(buf, sizeof(buf)); + object->type->size = size; + CInit_DeclareData(object, buf, relocs, object->type->size); + gen->specialProcsObj = object; + } +} + +static Object *CSOM_GenerateParentVersion(SOMGenerator *gen) { + SInt32 size; + UInt32 *buf; + SOMAncestor *ancestor; + SInt32 offset; + + size = 8 * (gen->counts.numDirectParents + gen->counts.numMetaClasses); + buf = lalloc(size); + + for (ancestor = gen->ancestors, offset = 0; ancestor; ancestor = ancestor->next) { + if (ancestor->xC || ancestor->xD) { + buf[offset++] = CTool_EndianConvertWord32(ancestor->tclass->sominfo->majorversion); + buf[offset++] = CTool_EndianConvertWord32(ancestor->tclass->sominfo->minorversion); + } + } + + return CInit_DeclareString((char *) buf, size, 0, 0); +} + +static void CSOM_SetNibble(char *buf, int offset, UInt8 value) { + int i = offset >> 1; + if (offset & 1) { + int left = buf[i] & 0xF0; + int right = value & 0xF; + buf[i] = left | right; + } else { + int left = value << 4; + int right = buf[i] & 0xF; + buf[i] = left | right; + } +} + +static Object *CSOM_GenerateSlotUsage(SOMGenerator *gen) { + SInt32 size; + SOMMethod *method; + char *buf; + int offset; + + size = (gen->counts.classTokenCount + 1) / 2; + buf = lalloc(size); + memclrw(buf, size); + + for (method = gen->methods, offset = 0; method; method = method->next, offset++) { + switch (method->state) { + case SOMMS_Deleted: + case SOMMS_Migrated: + CSOM_SetNibble(buf, offset, mtEmpty); + break; + case SOMMS_Method: + CSOM_SetNibble(buf, offset, mtVirtualMethod); + break; + default: + CError_FATAL(1048); + } + } + + return CInit_DeclareString(buf, size, 0, 0); +} + +static Object *CSOM_GenerateSignature(SOMGenerator *gen) { + Object *object; + SOMMethod *method; + + name_mangle_list.size = 0; + + for (method = gen->methods; method; method = method->next) { + if (method->state == SOMMS_Method) + CSOM_GetFuncSig(TYPE_FUNC(method->u.object->type), 1); + } + + COS_LockHandle(name_mangle_list.data); + object = CInit_DeclareString(*name_mangle_list.data, name_mangle_list.size, 0, 0); + COS_UnlockHandle(name_mangle_list.data); + return object; +} + +static Object *CSOM_GenerateMethodNames(SOMGenerator *gen) { + Object *object; + SOMMethod *method; + HashNameNode *name; + + name_mangle_list.size = 0; + + for (method = gen->methods; method; method = method->next) { + if (method->name) { + name = CSOM_NameTranslate(method->name); + AppendGListID(&name_mangle_list, name->name); + } + } + + COS_LockHandle(name_mangle_list.data); + object = CInit_DeclareString(*name_mangle_list.data, name_mangle_list.size, 0, 0); + COS_UnlockHandle(name_mangle_list.data); + return object; +} + +static void CSOM_SetupClassCounts(SOMGenerator *gen, TypeClass *tclass, somStaticClassCounts *counts) { + gen->counts.majorVersion = tclass->sominfo->majorversion; + gen->counts.minorVersion = tclass->sominfo->minorversion; + gen->counts.flags = cfSharedStrings; + if (gen->hasNew) + gen->counts.flags |= cfClassAllocate; + if (gen->hasDelete) + gen->counts.flags |= cfClassDeallocate; + + switch (tclass->align) { + case 1: + gen->counts.dataAlignment = 0; + break; + case 2: + gen->counts.dataAlignment = 1; + break; + case 4: + gen->counts.dataAlignment = 2; + break; + case 8: + gen->counts.dataAlignment = 3; + break; + default: + gen->counts.dataAlignment = 4; + break; + } + + gen->counts.numSelectInherited = 0; + + memclrw(counts, sizeof(somStaticClassCounts)); + counts->majorVersion = CTool_EndianConvertWord32(gen->counts.majorVersion); + counts->minorVersion = CTool_EndianConvertWord32(gen->counts.minorVersion); + counts->flags = CTool_EndianConvertWord32(gen->counts.flags); + counts->dataAlignment = CTool_EndianConvertWord16(gen->counts.dataAlignment); + counts->classTokenCount = CTool_EndianConvertWord16(gen->counts.classTokenCount); + counts->numDirectParents = CTool_EndianConvertWord16(gen->counts.numDirectParents); + counts->numMetaClasses = CTool_EndianConvertWord16(gen->counts.numMetaClasses); + counts->numOverriddenAncestors = CTool_EndianConvertWord16(gen->counts.numOverriddenAncestors); + counts->numMigratedMethods = CTool_EndianConvertWord16(gen->counts.numMigratedMethods); + counts->numSelectInherited = CTool_EndianConvertWord16(gen->counts.numSelectInherited); +} + +static void CSOM_GenerateSCIObject(SOMGenerator *gen, TypeClass *tclass) { + Object *object; + OLinkList *relocs; + OLinkList *reloc; + somStaticClassInfo sci; + somStaticClassCounts classCounts; + + object = CSOM_MakeObject(tclass->classname->name, "SCI", sizeof(sci)); + object->sclass = TK_STATIC; + + memclrw(&sci, sizeof(sci)); + sci.layoutVersion = CTool_EndianConvertWord32(70); + + reloc = lalloc(sizeof(OLinkList)); + reloc->next = NULL; + relocs = reloc; + reloc->obj = tclass->sominfo->classdataobject; + reloc->offset = 4; + reloc->somevalue = 0; + + if (gen->overrideProcsObj) { + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = gen->overrideProcsObj; + reloc->offset = 8; + reloc->somevalue = 0; + } + + if (gen->classAncestorsObj) { + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = gen->classAncestorsObj; + reloc->offset = 12; + reloc->somevalue = 0; + } + + if (gen->dlldFunc) { + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = gen->dlldFunc; + reloc->offset = 16; + reloc->somevalue = 0; + } + + if (gen->specialProcsObj) { + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = gen->specialProcsObj; + reloc->offset = 20; + reloc->somevalue = 0; + } + + CSOM_SetupClassCounts(gen, tclass, &classCounts); + + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = CInit_DeclareString((char *) &classCounts, sizeof(classCounts), 0, 0); + reloc->offset = 52; + reloc->somevalue = 0; + + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = CInit_DeclareString(tclass->classname->name, strlen(tclass->classname->name) + 1, 0, 0); + reloc->offset = 56; + reloc->somevalue = 0; + + sci.classDescription.instanceDataSize = CTool_EndianConvertWord32(tclass->size); + + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = CSOM_GenerateParentVersion(gen); + reloc->offset = 64; + reloc->somevalue = 0; + + if (gen->methods) { + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = CSOM_GenerateSlotUsage(gen); + reloc->offset = 68; + reloc->somevalue = 0; + + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = CSOM_GenerateSignature(gen); + reloc->offset = 72; + reloc->somevalue = 0; + + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = CSOM_GenerateMethodNames(gen); + reloc->offset = 76; + reloc->somevalue = 0; + } + + if (gen->overrideProcsObj) { + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = CSOM_GenerateOverrideData(gen); + reloc->offset = 80; + reloc->somevalue = 0; + } + + if (gen->counts.numMigratedMethods) { + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = CSOM_GenerateMigrateData(gen); + reloc->offset = 84; + reloc->somevalue = 0; + } + + sci.classDescription.selectedInherited = 0; + + CInit_DeclareData(object, &sci, relocs, object->type->size); + gen->sciObj = object; +} + +static void CSOM_GenerateClassDataObject(SOMGenerator *gen, TypeClass *tclass) { + void *buf; + OLinkList *relocs; + OLinkList *reloc; + SInt32 size; + SOMMethod *method; + + relocs = NULL; + for (size = 24, method = gen->methods; method; method = method->next) { + if (method->state == SOMMS_Method) { + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = method->u.object; + reloc->offset = size; + reloc->somevalue = 0; + } + size += 4; + } + + buf = lalloc(size); + memclrw(buf, size); + + reloc = lalloc(sizeof(OLinkList)); + reloc->next = relocs; + relocs = reloc; + reloc->obj = gen->sciObj; + reloc->offset = 4; + reloc->somevalue = 0; + + tclass->sominfo->classdataobject->type->size = size; + CInit_DeclareData(tclass->sominfo->classdataobject, buf, relocs, tclass->sominfo->classdataobject->type->size); +} + +void CSOM_GenerateClassStructures(TypeClass *tclass) { + SOMGenerator gen; + + memclrw(&gen, sizeof(gen)); + CSOM_GenerateOverrideIntroLists(&gen, tclass); + CSOM_GenerateClassAncestors(&gen, tclass); + CSOM_GenerateOverrideProcs(&gen, tclass); + CSOM_GenerateDLLDFunc(&gen, tclass); + CSOM_GenerateSpecialProcs(&gen, tclass); + CSOM_GenerateSCIObject(&gen, tclass); + CSOM_GenerateClassDataObject(&gen, tclass); +} + +static TypeClass *CSOM_GetCurrentSOMClass(void) { + if (cscope_current->theclass && cscope_current->theclass->sominfo) + return cscope_current->theclass; + + CError_Error(CErrorStr277); + return NULL; +} + +void CSOM_PragmaReleaseOrder(void) { + TypeClass *tclass; + SOMReleaseOrder *firstOrder; + SOMReleaseOrder *order; + SOMReleaseOrder **ptr; + Boolean flag; + short token; + + if (!(tclass = CSOM_GetCurrentSOMClass())) + return; + + token = CPrep_PragmaLex(0); + if (token != '(') { + if (token != TK_IDENTIFIER) { + CPrep_Error(CErrorStr114); + return; + } + + if (!strcmp(tkidentifier->name, "list")) { + token = CPrep_PragmaLex(0); + if (token != TK_IDENTIFIER) { + CPrep_Error(CErrorStr107); + return; + } + } + + flag = 1; + } else { + flag = 0; + token = CPrep_PragmaLex(0); + } + + firstOrder = NULL; + if (flag || token != ')') { + ptr = &firstOrder; + while (1) { + if (token != TK_IDENTIFIER) { + CPrep_Error(CErrorStr107); + return; + } + + for (order = firstOrder; order; order = order->next) { + if (order->name == tkidentifier) { + CError_Error(CErrorStr122, tkidentifier->name); + return; + } + } + + order = galloc(sizeof(SOMReleaseOrder)); + *ptr = order; + ptr = &order->next; + + order->next = NULL; + order->name = tkidentifier; + order->state = SOMMS_Deleted; + + if (flag) { + token = CPrep_PragmaLex(1); + if (!token) + break; + } else { + token = CPrep_PragmaLex(0); + if (token == ')') + break; + } + + if (token != ',') { + CPrep_Error(CErrorStr116); + return; + } + + token = CPrep_PragmaLex(flag); + } + } + + tclass->sominfo->order = firstOrder; +} + +void CSOM_PragmaClassVersion(void) { + Type *type; + + if (CPrep_PragmaLex(0) != '(') { + CPrep_Error(CErrorStr114); + return; + } + + if (CPrep_PragmaLex(0) != TK_IDENTIFIER) { + CPrep_Error(CErrorStr107); + return; + } + + type = CScope_GetTagType(cscope_current, tkidentifier); + if (!(type && IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo)) { + CPrep_ErrorName(CErrorStr276, tkidentifier->name); + return; + } + + if (CPrep_PragmaLex(0) != ',') { + CPrep_Error(CErrorStr116); + return; + } + + if (CPrep_PragmaLex(0) != TK_INTCONST) { + CPrep_Error(CErrorStr186); + return; + } + + TYPE_CLASS(type)->sominfo->majorversion = CInt64_GetULong(&tkintconst); + + if (CPrep_PragmaLex(0) != ',') { + CPrep_Error(CErrorStr116); + return; + } + + if (CPrep_PragmaLex(0) != TK_INTCONST) { + CPrep_Error(CErrorStr186); + return; + } + + TYPE_CLASS(type)->sominfo->minorversion = CInt64_GetULong(&tkintconst); + + if (CPrep_PragmaLex(0) != ')') { + CPrep_Error(CErrorStr115); + return; + } +} + +void CSOM_PragmaMetaClass(void) { + Type *type; + Type *type2; + + if (CPrep_PragmaLex(0) != '(') { + CPrep_Error(CErrorStr114); + return; + } + + if (CPrep_PragmaLex(0) != TK_IDENTIFIER) { + CPrep_Error(CErrorStr107); + return; + } + + type = CScope_GetTagType(cscope_current, tkidentifier); + if (!(type && IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo)) { + CPrep_ErrorName(CErrorStr276, tkidentifier->name); + return; + } + + if (CPrep_PragmaLex(0) != ',') { + CPrep_Error(CErrorStr116); + return; + } + + if (CPrep_PragmaLex(0) != TK_IDENTIFIER) { + CPrep_Error(CErrorStr107); + return; + } + + type2 = CScope_GetTagType(cscope_current, tkidentifier); + if (!(type2 && IS_TYPE_CLASS(type2) && TYPE_CLASS(type2)->sominfo)) { + CPrep_ErrorName(CErrorStr276, tkidentifier->name); + return; + } + + TYPE_CLASS(type)->sominfo->metaclass = TYPE_CLASS(type2); + + if (CPrep_PragmaLex(0) != ')') { + CPrep_Error(CErrorStr115); + return; + } +} + +void CSOM_PragmaCallStyle(void) { + TypeClass *tclass; + + if (!(tclass = CSOM_GetCurrentSOMClass())) + return; + + if (CPrep_PragmaLex(0) != TK_IDENTIFIER) { + CPrep_Error(CErrorStr107); + return; + } + + if (!strcmp(tkidentifier->name, "IDL")) { + tclass->sominfo->oidl_callstyle = 0; + return; + } + + if (!strcmp(tkidentifier->name, "OIDL")) { + tclass->sominfo->oidl_callstyle = 1; + return; + } + + CPrep_Error(CErrorStr186); +} + +void CSOM_FixNewDeleteFunctype(TypeFunc *tfunc) { + FuncArg *arg = CParser_NewFuncArg(); + arg->name = GetHashNameNodeExport("__theclass"); + arg->type = CDecl_NewPointerType(CSOM_FindClassType(GetHashNameNodeExport("SOMClass"))); + arg->next = tfunc->args; + tfunc->args = arg; +} + +static Object *CSOM_FindRTFunc(char *namestr, char *sig) { + NameSpaceObjectList *nsol; + Object *object; + FuncArg *arg; + + if ( + (nsol = CScope_GetLocalObject(cscope_root, GetHashNameNodeExport(namestr))) && + nsol->object->otype == OT_OBJECT + ) + { + object = OBJECT(nsol->object); + if ( + IS_TYPE_FUNC(object->type) && + *(sig++) == 'p' && + IS_TYPE_POINTER_ONLY(TYPE_FUNC(object->type)->functype) + ) + { + for (arg = TYPE_FUNC(object->type)->args; arg; arg = arg->next) { + switch (*(sig++)) { + case 'p': + if (IS_TYPE_POINTER_ONLY(arg->type)) + continue; + break; + case 'i': + if (arg->type == TYPE(&stsignedint)) + continue; + break; + case 'I': + if (arg->type == TYPE(&stunsignedint)) + continue; + break; + case 'l': + if (arg->type == TYPE(&stsignedlong)) + continue; + break; + case 'L': + if (arg->type == TYPE(&stunsignedlong)) + continue; + break; + } + break; + } + + if (arg == NULL && *sig == 0) + return object; + } + + CError_Error(CErrorStr275, namestr); + } else { + CError_Error(CErrorStr274, namestr); + } + + return NULL; +} + +static ENode *CSOM_MakeTempCondition(ENode *left, ENode *cond, ENode *expr1, ENode *right) { + ENode *expr; + + expr = lalloc(sizeof(ENode)); + expr->type = ECOND; + expr->cost = 0; + expr->flags = 0; + expr->rtype = &stvoid; + expr->data.cond.cond = cond; + expr->data.cond.expr1 = expr1; + expr->data.cond.expr2 = nullnode(); + expr->data.cond.expr2->rtype = &stvoid; + + if (left) + expr = makediadicnode(left, expr, ECOMMA); + + if (right) { + expr = makediadicnode(expr, right, ECOMMA); + expr->rtype = right->rtype; + } + + return expr; +} + +ENode *CSOM_New(TypeClass *tclass) { + Object *newFunc; + ENode *expr; + + if (tk == '(') { + if ((tk = lex()) == ')') { + tk = lex(); + } else { + CError_Error(CErrorStr272); + } + } + + if (!copts.som_env_check || !copts.som_call_optimize) { + newFunc = CSOM_FindRTFunc("somNewObjectInstance", "ppll"); + if (!newFunc) + return nullnode(); + } else { + newFunc = rt_som_new; + } + + expr = funccallexpr( + newFunc, + create_objectrefnode(tclass->sominfo->classdataobject), + intconstnode(TYPE(&stunsignedlong), tclass->sominfo->majorversion), + intconstnode(TYPE(&stunsignedlong), tclass->sominfo->minorversion), + NULL + ); + expr->rtype = CDecl_NewPointerType(TYPE(tclass)); + + if (copts.som_env_check && !copts.som_call_optimize) { + ENode *tempExpr; + ENode *checkExpr; + ENode *notExpr; + tempExpr = CExpr_GetETEMPCopy(expr); + checkExpr = funccallexpr(rt_som_newcheck, nullnode(), NULL, NULL, NULL); + notExpr = makemonadicnode(tempExpr, ELOGNOT); + notExpr->rtype = CParser_GetBoolType(); + expr = CSOM_MakeTempCondition(NULL, notExpr, checkExpr, tempExpr); + } + + return expr; +} + +ENode *CSOM_Delete(TypeClass *tclass, ENode *objExpr) { + Object *func; + + if ((func = CSOM_FindRTFunc("somReleaseObjectReference", "pp"))) + return funccallexpr(func, objExpr, NULL, NULL, NULL); + + return nullnode(); +} + +void CSOM_InitAutoClass(Object *object) { + Type *type; + Statement *stmt; + Object *func; + + if ((func = CSOM_FindRTFunc("somReleaseObjectReference", "pp"))) { + type = object->type; + object->type = CDecl_NewPointerType(type); + TPTR_QUAL(object->type) = Q_REFERENCE; + + stmt = CFunc_AppendStatement(ST_EXPRESSION); + stmt->expr = makediadicnode(create_objectnode2(object), CSOM_New(TYPE_CLASS(type)), EASS); + CExcept_RegisterDeleteObject(stmt, object, func); + } +} + +static void CSOM_FindIntroClassOffset(TypeClass *tclass, Object *func, TypeClass **resultClass, SInt32 *resultOffset) { + Object *scan; + VClassList *vbase; + CScopeObjectIterator iter; + + if (!(TYPE_FUNC(func->type)->flags & FUNC_FLAGS_20)) { + CScope_InitObjectIterator(&iter, tclass->nspace); + while (1) { + if (!(scan = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (scan == func) { + *resultClass = tclass; + *resultOffset = CSOM_GetTokenOffset(scan); + return; + } + } + + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + CScope_InitObjectIterator(&iter, vbase->base->nspace); + while (1) { + if (!(scan = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (scan == func) { + *resultClass = vbase->base; + *resultOffset = CSOM_GetTokenOffset(scan); + return; + } + } + } + } else { + for (vbase = tclass->vbases; vbase; vbase = vbase->next) { + CScope_InitObjectIterator(&iter, vbase->base->nspace); + while (1) { + if (!(scan = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + break; + + if (scan->name == func->name) { + if ( + IS_TYPE_FUNC(scan->type) && + scan->datatype == DVFUNC && + !(TYPE_FUNC(scan->type)->flags & FUNC_FLAGS_20) && + CClass_GetOverrideKind(TYPE_FUNC(func->type), TYPE_FUNC(scan->type), 0) + ) + { + *resultClass = vbase->base; + *resultOffset = CSOM_GetTokenOffset(scan); + return; + } + break; + } + } + } + } + + CError_FATAL(1731); +} + +static ENode *CSOM_ComputeSOMSelf(TypeClass *tclass, ENode *selfExpr) { + ENode *expr; + Object obj; + + expr = create_objectrefnode(tclass->sominfo->classdataobject); + expr = makediadicnode(expr, intconstnode(TYPE(&stsignedlong), 8), EADD); + expr->rtype = CDecl_NewPointerType(TYPE(&SOMIDT_type)); + expr = makemonadicnode(expr, EINDIRECT); + + memclrw(&obj, sizeof(Object)); + obj.otype = OT_OBJECT; + obj.type = TYPE(&SOMIDT_type); + obj.name = no_name_node; + obj.datatype = DFUNC; + selfExpr = funccallexpr(&obj, selfExpr, NULL, NULL, NULL); + + CError_ASSERT(1761, ENODE_IS(selfExpr, EFUNCCALL)); + + selfExpr->data.funccall.funcref = expr; + + return selfExpr; +} + +ENode *CSOM_SOMSelfObjectExpr(TypeClass *tclass) { + ObjectList *list; + Object *obj; + + for (list = locals; list; list = list->next) { + if (list->object->name == csom_selfname) + return create_objectnode(list->object); + } + + obj = CParser_NewLocalDataObject(NULL, 1); + obj->name = csom_selfname; + obj->type = CDecl_NewPointerType(TYPE(tclass)); + CFunc_SetupLocalVarInfo(obj); + return create_objectnode(obj); +} + +void CSOM_InitSOMSelf(TypeClass *tclass, Statement *stmt) { + ObjectList *list; + HashNameNode *name; + ENode *selfExpr; + + name = GetHashNameNodeExport("__somself"); + for (list = locals; list; list = list->next) { + if (list->object->name == name) { + selfExpr = CClass_CreateThisSelfExpr(); + CError_ASSERT(1811, selfExpr); + + selfExpr = CSOM_ComputeSOMSelf(tclass, selfExpr); + + stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); + stmt->expr = makediadicnode(create_objectnode(list->object), selfExpr, EASS); + break; + } + } +} + +ENode *CSOM_EnvCheck(ENode *funccall, ENodeList *checkArg) { + ENodeList *arg; // r26 + ENodeList *arg2; // r28 + ENode *expr26; // r26 + ENode *expr27; // r27 + ENode *expr28; // r28 + Type *returnType; // r31 + + returnType = funccall->rtype; + CError_ASSERT(1842, arg = funccall->data.funccall.args); + + if (arg == checkArg) + CError_ASSERT(1845, arg = arg->next); + + CError_ASSERT(1847, arg2 = arg->next); + + if (arg2 == checkArg) + CError_ASSERT(1850, arg2 = arg2->next); + + CError_ASSERT(1852, IS_TYPE_POINTER_ONLY(arg2->node->rtype)); + + if (!IS_TYPE_VOID(funccall->data.funccall.functype->functype)) { + if (checkArg) { + if (ENODE_IS(checkArg->node, ETEMP)) { + if (checkArg->node->data.temp.uniqueid == 0) + checkArg->node->data.temp.uniqueid = CParser_GetUniqueID(); + + expr26 = lalloc(sizeof(ENode)); + *expr26 = *checkArg->node; + expr26->data.temp.needs_dtor = 0; + } else { + expr26 = CExpr_GetETEMPCopy(checkArg->node); + } + } else { + expr26 = CExpr_GetETEMPCopy(funccall); + } + } else { + expr26 = NULL; + } + + if (!ENODE_IS(arg2->node, EOBJREF)) { + if (ENODE_IS_INDIRECT_TO(arg2->node, EOBJREF) && arg2->node->data.monadic->data.objref->datatype == DLOCAL) { + expr27 = lalloc(sizeof(ENode)); + *expr27 = *arg2->node; + } else { + expr27 = CExpr_GetETEMPCopy(arg2->node); + } + } else { + expr27 = lalloc(sizeof(ENode)); + *expr27 = *arg2->node; + } + + if (copts.som_call_optimize) { + funccall = makediadicnode(funccall, funccallexpr(rt_som_check, expr27, NULL, NULL, NULL), ECOMMA); + if (expr26) + funccall = makediadicnode(funccall, expr26, ECOMMA); + } else { + expr28 = lalloc(sizeof(ENode)); + *expr28 = *expr27; + expr28 = makemonadicnode(expr28, EINDIRECT); + expr28->rtype = TYPE(&stsignedlong); + + funccall = CSOM_MakeTempCondition( + funccall, + expr28, + funccallexpr(rt_som_check, expr27, NULL, NULL, NULL), + expr26); + } + + funccall->rtype = returnType; + return funccall; +} + +static Boolean CSOM_CanUseGlueCall(TypeFunc *tfunc) { + int gprCounter; + int fprCounter; + FuncArg *arg; + + gprCounter = 8; + fprCounter = 13; + if (CMach_GetFunctionResultClass(tfunc) != 0) + gprCounter = 7; + + for (arg = tfunc->args; arg; arg = arg->next) { + if (arg == &elipsis || arg == &oldstyle) + return 0; + + switch (arg->type->type) { + case TYPEINT: + case TYPEENUM: + case TYPEPOINTER: + if (--gprCounter < 0) + return 0; + break; + case TYPEFLOAT: + if (--fprCounter < 0) + return 0; + break; + default: + return 0; + } + } + + return 1; +} + +static char *CSOM_AppendString(char *dst, char *src) { + int ch; + while ((ch = *(src++))) + *(dst++) = ch; + return dst; +} + +static ENode *CSOM_SOMGlueCall(TypeClass *tclass, SInt32 offset, Object *object) { + UInt8 funcResultClass; + UInt32 bufsize; + char *buf; + char *ptr; + Object *stubObj; + CSOMStub *stub; + ENode *expr; + char mybuf[256]; + char numberbuf[16]; + + for (stub = csom_stubs; stub; stub = stub->next) { + if (stub->tclass == tclass && stub->offset == offset) + break; + } + + if (!stub) { + funcResultClass = CMach_GetFunctionResultClass(TYPE_FUNC(object->type)); + + bufsize = strlen(tclass->sominfo->classdataobject->name->name) + 32; + buf = (bufsize > sizeof(mybuf)) ? lalloc(bufsize) : mybuf; + + ptr = CSOM_AppendString(buf, "___glue_"); + if (tclass->sominfo->oidl_callstyle == 0) { + if (funcResultClass == 0) { + *(ptr++) = '4'; + } else { + *(ptr++) = '5'; + } + } else { + *(ptr++) = '_'; + } + *(ptr++) = '_'; + + sprintf(numberbuf, "%ld", strlen(tclass->sominfo->classdataobject->name->name)); + ptr = CSOM_AppendString(ptr, numberbuf); + ptr = CSOM_AppendString(ptr, tclass->sominfo->classdataobject->name->name); + *(ptr++) = '_'; + sprintf(numberbuf, "%" PRId32, offset); + ptr = CSOM_AppendString(ptr, numberbuf); + *ptr = 0; + + stubObj = CParser_NewCompilerDefFunctionObject(); + stubObj->nspace = cscope_root; + stubObj->name = GetHashNameNodeExport(buf); + stubObj->u.func.linkname = stubObj->name; + stubObj->type = object->type; + stubObj->qual = object->qual | Q_20000; + stubObj->flags = OBJECT_INTERNAL; + CScope_AddObject(stubObj->nspace, stubObj->name, OBJ_BASE(stubObj)); + + stub = galloc(sizeof(CSOMStub)); + stub->next = csom_stubs; + stub->object = stubObj; + stub->tclass = tclass; + stub->offset = offset; + csom_stubs = stub; + + if (tclass->sominfo->oidl_callstyle == 0) { + if (funcResultClass == 0) + stub->x10 = 0; + else + stub->x10 = 1; + } else { + stub->x10 = 2; + } + } + + expr = create_objectrefnode(stub->object); + expr->rtype = CDecl_NewPointerType(object->type); + return expr; +} + +ENode *CSOM_MemberVarAccess(BClassList *path, ObjMemberVar *ivar, ENode *thisExpr) { + if (!thisExpr) { + if ( + !cscope_currentfunc || + !cscope_currentclass || + !cscope_is_member_func || + !(thisExpr = CClass_CreateThisSelfExpr()) + ) + { + CError_Error(CErrorStr221); + return NULL; + } + } + + CError_ASSERT(2069, ENODE_IS(thisExpr, EINDIRECT)); + + thisExpr = thisExpr->data.monadic; + + if ( + path->next == NULL && + cscope_currentclass == TYPE_CLASS(path->type) && + ENODE_IS(thisExpr, EOBJREF) && + thisExpr->data.objref->name == this_name_node + ) + { + thisExpr = CSOM_SOMSelfObjectExpr(cscope_currentclass); + } + else + { + CClass_CheckPathAccess(path, NULL, ivar->access); + if (ivar->has_path) + path = OBJ_MEMBER_VAR_PATH(ivar)->path; + while (path->next) + path = path->next; + thisExpr = CSOM_ComputeSOMSelf(TYPE_CLASS(path->type), thisExpr); + } + + thisExpr = makemonadicnode(thisExpr, EINDIRECT); + thisExpr->rtype = path->type; + return CClass_AccessMember(thisExpr, ivar->type, ivar->qual, ivar->offset); +} + +ENode *CSOM_MethodAccess(BClassList *path, Object *func, Boolean flag) { + TypeClass *tclass; + TypeClass *tclass2; + TypeClass *tclass3; + ENode *expr; + SInt32 offset; + ClassList *base; + + CError_ASSERT(2107, path != NULL); + + tclass = TYPE_CLASS(path->type); + if (path->next) + path = path->next; + tclass2 = TYPE_CLASS(path->type); + + if (flag) { + SInt32 counter; + ENode *indirectExpr; + Object *resolveFunc; + + counter = 0; + if (tclass != tclass2) { + for (base = tclass->bases; base; base = base->next) { + counter++; + if (base->base == tclass2) + break; + } + + if (!base) + CError_Error(CErrorStr279); + } + + CSOM_FindIntroClassOffset(tclass2, func, &tclass3, &offset); + expr = create_objectrefnode(tclass3->sominfo->classdataobject); + expr = makediadicnode(expr, intconstnode(TYPE(&stsignedlong), offset), EADD); + indirectExpr = makemonadicnode(expr, EINDIRECT); + indirectExpr->rtype = CDecl_NewPointerType(func->type); + + resolveFunc = CSOM_FindRTFunc("somParentNumResolve", "ppip"); + if (!resolveFunc) + return nullnode(); + + expr = funccallexpr( + resolveFunc, + create_objectrefnode(tclass->sominfo->classdataobject), + intconstnode(TYPE(&stsignedint), counter), + indirectExpr, + NULL); + expr->rtype = indirectExpr->rtype; + if (copts.som_env_check && tclass3->sominfo->oidl_callstyle == 0) + expr->flags = expr->flags | ENODE_FLAG_10; + } else { + CSOM_FindIntroClassOffset(tclass2, func, &tclass3, &offset); + if (copts.som_call_optimize && CSOM_CanUseGlueCall(TYPE_FUNC(func->type))) + return CSOM_SOMGlueCall(tclass3, offset, func); + + expr = create_objectrefnode(tclass3->sominfo->classdataobject); + expr = makediadicnode(expr, intconstnode(TYPE(&stsignedlong), offset), EADD); + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = CDecl_NewPointerType(func->type); + if (copts.som_env_check && tclass3->sominfo->oidl_callstyle == 0) + expr->flags = expr->flags | ENODE_FLAG_10; + } + + return expr; +} diff --git a/compiler_and_linker/FrontEnd/C/CTemplateClass.c b/compiler_and_linker/FrontEnd/C/CTemplateClass.c new file mode 100644 index 0000000..8b3b889 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CTemplateClass.c @@ -0,0 +1,1632 @@ +#include "compiler/CTemplateClass.h" +#include "compiler/CABI.h" +#include "compiler/CBrowse.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CInline.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/CTemplateFunc.h" +#include "compiler/CTemplateNew.h" +#include "compiler/CTemplateTools.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" + +TemplClass *CTemplClass_GetMasterTemplate(TemplClass *tmclass) { + if (tmclass->inst_parent) { + tmclass = TEMPL_CLASS(tmclass->theclass.nspace->theclass); + CError_ASSERT(42, tmclass->theclass.flags & CLASS_IS_TEMPL); + } + + return tmclass; +} + +static void CTemplClass_SetupActionErrorRef(TemplateAction *action, TStreamElement **saved) { + CError_ResetErrorSkip(); + CError_LockErrorPos(&action->source_ref, saved); +} + +static void CTemplClass_RestoreActionErrorRef(TStreamElement **saved) { + CError_ResetErrorSkip(); + CError_UnlockErrorPos(saved); +} + +static void CTemplClass_AppendTemplateAction(TemplClass *tmclass, TemplateAction *action) { + TemplateAction *last; + + action->source_ref = *CPrep_CurStreamElement(); + + if ((last = tmclass->actions)) { + while (last->next) + last = last->next; + last->next = action; + } else { + tmclass->actions = action; + } +} + +static DefAction *CTemplClass_NewDefAction(TypeDeduce *deduce, TemplateAction *action) { + DefAction *defAction = lalloc(sizeof(DefAction)); + defAction->next = deduce->defActions; + defAction->action = action; + deduce->defActions = defAction; + return defAction; +} + +static void CTemplClass_InsertTemplateAction(TemplClass *tmclass, TemplateAction *action) { + action->source_ref = *CPrep_CurStreamElement(); + action->next = tmclass->actions; + tmclass->actions = action; +} + +void CTemplClass_RegisterUsingDecl(TemplClass *tmclass, TypeTemplDep *type, AccessType access) { + TemplateAction *action; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_USINGDECL; + action->u.usingdecl.type = type; + action->u.usingdecl.access = access; + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterFriend(TemplClass *tmclass, DeclInfo *di) { + TemplateFriend *tfriend; + TemplateAction *action; + + tfriend = galloc(sizeof(TemplateFriend)); + memclrw(tfriend, sizeof(TemplateFriend)); + + if (tk == '{' && IS_TYPE_FUNC(di->thetype)) { + di->qual |= Q_INLINE; + TYPE_FUNC(di->thetype)->flags |= FUNC_DEFINED | FUNC_IS_TEMPL_INSTANCE; + tfriend->fileoffset = cparser_fileoffset; + + CPrep_StreamGetBlock(&tfriend->stream, NULL, 1); + + if (lookahead() == ';') + tk = lex(); + else + tk = ';'; + } + + CDecl_PackDeclInfo(&tfriend->decl, di); + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_FRIEND; + action->u.tfriend = tfriend; + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterBaseClass(TemplClass *tmclass, Type *type, AccessType access, Boolean is_virtual) { + TemplateAction *action; + ClassList *insert_after; + + if ((insert_after = tmclass->theclass.bases)) { + while (insert_after->next) + insert_after = insert_after->next; + } + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_BASE; + action->u.base.type = type; + action->u.base.insert_after = insert_after; + action->u.base.access = access; + action->u.base.is_virtual = is_virtual; + + CTemplClass_InsertTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterEnumType(TemplClass *tmclass, TypeEnum *enumtype) { + TemplateAction *action; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_ENUMTYPE; + action->u.enumtype = enumtype; + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterEnumerator(TemplClass *tmclass, ObjEnumConst *objenumconst, ENode *initexpr) { + TemplateAction *action; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_ENUMERATOR; + action->u.enumerator.objenumconst = objenumconst; + action->u.enumerator.initexpr = initexpr ? CInline_CopyExpression(initexpr, CopyMode1) : NULL; + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterObjectInit(TemplClass *tmclass, Object *object, ENode *initexpr) { + TemplateAction *action; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_OBJECTINIT; + action->u.objectinit.object = object; + action->u.objectinit.initexpr = CInline_CopyExpression(initexpr, CopyMode1); + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_RegisterObjectDef(TemplClass *tmclass, ObjBase *refobj) { + TemplateAction *action; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_OBJECTDEF; + action->u.refobj = refobj; + + CTemplClass_AppendTemplateAction(tmclass, action); +} + +void CTemplClass_CompleteClass(TemplClass *templ, ClassLayout *de) { + templ->lex_order_count = de->lex_order_count; + if (de->has_vtable) + templ->flags |= TEMPLCLASS_HAS_VTABLE; + templ->theclass.flags |= CLASS_COMPLETED; +} + +static TemplClassInst *CTemplClass_NewInstance(TemplClass *templ, TemplArg *inst_args, TemplArg *oargs) { + TemplClassInst *inst; + ObjTypeTag *tag; + NameSpace *nspace; + HashNameNode *name; + + CError_ASSERT(288, !templ->pspec_owner); + + inst = galloc(sizeof(TemplClassInst)); + memclrw(inst, sizeof(TemplClassInst)); + + inst->next = templ->instances; + templ->instances = inst; + + if (templ->templ__params) + name = CMangler_TemplateInstanceName(templ->theclass.classname, oargs ? oargs : inst_args); + else + name = templ->theclass.classname; + + inst->inst_args = inst_args; + inst->oargs = oargs; + inst->parent = templ->inst_parent; + + nspace = CScope_NewListNameSpace(name, 1); + nspace->theclass = TYPE_CLASS(inst); + if (templ->templ_parent && templ->inst_parent) { + nspace->parent = TYPE_CLASS(templ->inst_parent)->nspace; + } else { + NameSpace *scan = templ->theclass.nspace->parent; + while (scan->is_templ) + scan = scan->parent; + nspace->parent = scan; + } + + inst->theclass.type = TYPECLASS; + inst->theclass.flags = CLASS_IS_TEMPL_INST; + inst->theclass.nspace = nspace; + inst->theclass.classname = templ->theclass.classname; + inst->theclass.mode = templ->theclass.mode; + inst->theclass.eflags = templ->theclass.eflags; + inst->templ = templ; + + tag = galloc(sizeof(ObjTypeTag)); + memclrw(tag, sizeof(ObjTypeTag)); + + tag->otype = OT_TYPETAG; + tag->access = ACCESSPUBLIC; + tag->type = TYPE(inst); + CScope_AddObject(nspace, templ->theclass.classname, OBJ_BASE(tag)); + + return inst; +} + +TemplClassInst *CTemplClass_GetInstance(TemplClass *tmclass, TemplArg *inst_args, TemplArg *oargs) { + TemplClassInst *inst; + + for (inst = tmclass->instances; inst; inst = inst->next) { + CError_ASSERT(353, !oargs); + + if (CTemplTool_EqualArgs(inst_args, inst->oargs ? inst->oargs : inst->inst_args)) + return inst; + } + + return CTemplClass_NewInstance(tmclass, inst_args, oargs); +} + +TemplateMember *CTemplClass_DefineMember(TemplClass *tmclass, Object *object, FileOffsetInfo *foi, TokenStream *stream) { + TemplateMember *member; + + for (member = tmclass->members; member; member = member->next) { + if (member->object == object) { + CError_Error(CErrorStr333, object); + return member; + } + } + + member = galloc(sizeof(TemplateMember)); + memclrw(member, sizeof(TemplateMember)); + member->next = tmclass->members; + tmclass->members = member; + + member->params = NULL; + member->object = object; + member->fileoffset = *foi; + member->stream = *stream; + + return member; +} + +static void CTemplClass_ParseBody(TemplClass *templ, short mode, SInt32 *offset) { + DeclInfo di; + + templ->align = copts.structalignment; + + memclrw(&di, sizeof(di)); + di.file = CPrep_BrowserCurrentFile(); + CPrep_BrowserFilePosition(&di.file2, &di.sourceoffset); + di.sourceoffset = *offset; + di.x28 = templ; + + CDecl_ParseClass(&di, mode, 1, 0); + + if (tk == TK_UU_ATTRIBUTE_UU) + CParser_ParseAttribute(di.thetype, NULL); + if (tk != ';') + CError_Error(CErrorStr123); + + CBrowse_NewTemplateClass(templ, di.file2, di.sourceoffset, CPrep_BrowserFileOffset() + 1); +} + +void CTemplClass_ParsePartialSpecialization(DeclFucker *what_is_this, TemplParam *params, short mode, SInt32 *offset) { + Type *type; + NameSpace *nspace; + TemplArg *args; + TemplPartialSpec *pspec; + TemplClass *templ; + TemplArg *arg; + TemplParam *param; + + nspace = what_is_this->nspace; + + if ((tk = lex()) != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + return; + } + + if (!(type = CScope_GetLocalTagType(nspace, tkidentifier))) { + CError_Error(CErrorStr140, tkidentifier->name); + return; + } + + if (!IS_TEMPL_CLASS(type)) { + CError_Error(CErrorStr132, tkidentifier->name); + return; + } + + if ((tk = lex()) != '<') + CError_FATAL(469); + + for (param = params; param; param = param->next) { + switch (param->pid.type) { + case TPT_TYPE: + if (!param->data.typeparam.type) + continue; + CError_Error(CErrorStr344); + break; + + case TPT_NONTYPE: + if (!param->data.paramdecl.defaultarg) + continue; + CError_Error(CErrorStr344); + break; + + case TPT_TEMPLATE: + if (!param->data.templparam.defaultarg) + continue; + CError_Error(CErrorStr344); + break; + + default: + CError_FATAL(501); + } + + break; + } + + args = CTempl_ParseUncheckTemplArgs(TEMPL_CLASS(type)->templ__params, 0); + tk = lex(); + + arg = args; + param = TEMPL_CLASS(type)->templ__params; + while (1) { + if (!arg) { + if (!param) + break; + CError_Error(CErrorStr344); + return; + } + if (!param) { + CError_Error(CErrorStr344); + return; + } + if (param->pid.type != arg->pid.type) { + CError_Error(CErrorStr344); + return; + } + arg = arg->next; + param = param->next; + } + + if (CTemplTool_IsSameTemplate(TEMPL_CLASS(type)->templ__params, args)) + CError_Error(CErrorStr344); + + for (pspec = TEMPL_CLASS(type)->pspecs; pspec; pspec = pspec->next) { + if (CTemplTool_EqualParams(pspec->templ->templ__params, params, 0) && CTemplTool_EqualArgs(pspec->args, args)) + break; + } + + if (!pspec) { + templ = galloc(sizeof(TemplClass)); + memclrw(templ, sizeof(TemplClass)); + + templ->templ__params = params; + CDecl_DefineClass(nspace, TEMPL_CLASS(type)->theclass.classname, TYPE_CLASS(templ), mode, 0, 0); + + templ->theclass.flags = CLASS_IS_TEMPL; + templ->pspec_owner = TEMPL_CLASS(type); + + pspec = galloc(sizeof(TemplPartialSpec)); + memclrw(pspec, sizeof(TemplPartialSpec)); + + pspec->templ = templ; + pspec->args = CTemplTool_MakeGlobalTemplArgCopy(args); + pspec->next = TEMPL_CLASS(type)->pspecs; + TEMPL_CLASS(type)->pspecs = pspec; + } else { + if ((pspec->templ->theclass.flags & CLASS_COMPLETED) && tk != ';') { + CError_Error(CErrorStr132, TEMPL_CLASS(type)->theclass.classname->name); + return; + } + + if (tk == ':' || tk == '{') + CTemplTool_EqualParams(pspec->templ->templ__params, params, 1); + } + + switch (tk) { + case ':': + case '{': + CTemplClass_ParseBody(pspec->templ, mode, offset); + break; + case ';': + break; + default: + CError_Error(CErrorStr121); + } +} + +void CTemplClass_ParseClass(DeclFucker *what_is_this, TemplParam *params, short mode, SInt32 *offset) { + TemplClass *templ; + NameSpace *nspace; + Type *type; + UInt8 classDeclSpec = 0; + + nspace = what_is_this->nspace; + if ((tk = lex()) == TK_UU_DECLSPEC) + CDecl_ParseClassDeclSpec(&classDeclSpec); + + if (tk != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + return; + } + + type = CScope_GetLocalTagType(nspace, tkidentifier); + if (!type) { + templ = galloc(sizeof(TemplClass)); + memclrw(templ, sizeof(TemplClass)); + + templ->next = ctempl_templates; + ctempl_templates = templ; + + templ->templ__params = params; + CDecl_DefineClass(nspace, tkidentifier, TYPE_CLASS(templ), mode, 0, 1); + templ->theclass.flags = CLASS_IS_TEMPL; + templ->theclass.eflags = classDeclSpec; + + tk = lex(); + if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL)) { + TemplateAction *action; + + templ->templ_parent = TEMPL_CLASS(nspace->theclass); + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_NESTEDCLASS; + action->u.tclasstype = templ; + CTemplClass_AppendTemplateAction(templ->templ_parent, action); + } + } else { + if (!IS_TEMPL_CLASS(type)) { + CError_Error(CErrorStr132, tkidentifier->name); + return; + } + + templ = TEMPL_CLASS(type); + if (!CTemplTool_EqualParams(templ->templ__params, params, 0)) { + CError_Error(CErrorStr132, templ->theclass.classname->name); + return; + } + + CTemplTool_MergeDefaultArgs(templ->templ__params, params); + templ->theclass.eflags |= classDeclSpec; + + tk = lex(); + + if ((templ->theclass.flags & CLASS_COMPLETED) && tk != ';') { + CError_Error(CErrorStr132, templ->theclass.classname->name); + return; + } + + if (tk != ';') + CTemplTool_EqualParams(templ->templ__params, params, 1); + } + + switch (tk) { + case ':': + case '{': + CTemplClass_ParseBody(templ, mode, offset); + break; + case ';': + break; + default: + CError_Error(CErrorStr121); + } +} + +static Boolean CTemplClass_TypeParamCompare(TemplArg *arg, Type *type, UInt32 qual) { + return is_typesame(type, arg->data.typeparam.type) && arg->data.typeparam.qual == qual; +} + +static TemplArg *CTemplClass_PartialTemplateArgMatch(TemplPartialSpec *pspec, TemplArg *args, Boolean flag) { + TemplArg *argA; + TemplArg *argB; + int i; + DeduceInfo info; + + if (!CTemplTool_InitDeduceInfo(&info, pspec->templ->templ__params, NULL, 1)) + return NULL; + + argA = pspec->args; + argB = args; + while (1) { + if (!argA) { + if (argB) + return NULL; + + for (i = 0; i < info.maxCount; i++) { + if (!info.args[i].is_deduced) + return NULL; + } + + if (flag) + return CTemplTool_MakeTemplArgList(&info); + else + return args; + } + + if (!argB) + return NULL; + + if (argA->pid.type != argB->pid.type) + return NULL; + + switch (argA->pid.type) { + case TPT_TYPE: + if (CTemplTool_IsTemplateArgumentDependentType(argA->data.typeparam.type)) { + if (!CTempl_DeduceType( + argA->data.typeparam.type, argA->data.typeparam.qual, + argB->data.typeparam.type, argB->data.typeparam.qual, + info.args, 0, 0 + )) + return NULL; + } else { + if ( + !is_typesame(argA->data.typeparam.type, argB->data.typeparam.type) || + argA->data.typeparam.qual != argB->data.typeparam.qual + ) + return NULL; + } + break; + + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(argA->data.paramdecl.expr)) { + i = CTempl_GetTemplateArgumentExpressionIndex(argA); + CError_ASSERT(789, i >= 0); + + if (info.args[i].is_deduced) { + if (!CTemplTool_EqualExprTypes(argB->data.paramdecl.expr, info.args[i].data.paramdecl.expr)) + return NULL; + } else { + info.args[i].data.paramdecl.expr = argB->data.paramdecl.expr; + info.args[i].pid.type = TPT_NONTYPE; + info.args[i].is_deduced = 1; + } + } else { + if (!CTemplTool_EqualExprTypes(argB->data.paramdecl.expr, argA->data.paramdecl.expr)) + return NULL; + } + break; + + case TPT_TEMPLATE: + if (CTemplTool_IsTemplateArgumentDependentType(argA->data.ttargtype)) { + if (!CTempl_DeduceType( + argA->data.ttargtype, 0, + argB->data.ttargtype, 0, + info.args, 0, 0 + )) + return NULL; + } else { + if (!is_typesame(argA->data.ttargtype, argB->data.ttargtype)) + return NULL; + } + break; + + default: + CError_FATAL(830); + } + + argA = argA->next; + argB = argB->next; + } +} + +static Boolean CTemplClass_PartialClassIsAtLeastAsSpecialized(TemplPartialSpec *pspec1, TemplPartialSpec *pspec2) { + TemplArg *argA; + TemplArg *argB; + int i; + DeduceInfo info; + + if (!CTemplTool_InitDeduceInfo(&info, pspec2->templ->templ__params, NULL, 1)) + return 0; + + argA = pspec1->args; + argB = pspec2->args; + + while (1) { + if (!argA) { + CError_ASSERT(856, !argB); + + for (i = 0; i < info.maxCount; i++) { + if (!info.args[i].is_deduced) + return 0; + } + + return 1; + } + + CError_ASSERT(865, argB); + CError_ASSERT(866, argA->pid.type == argB->pid.type); + + switch (argA->pid.type) { + case TPT_TYPE: + if (!CTempl_DeduceType( + argB->data.typeparam.type, argB->data.typeparam.qual, + argA->data.typeparam.type, argA->data.typeparam.qual, + info.args, 0, 0 + )) + return 0; + break; + + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(argB->data.paramdecl.expr)) { + i = CTempl_GetTemplateArgumentExpressionIndex(argB); + CError_ASSERT(907, i >= 0); + + if (info.args[i].is_deduced) { + if (argA->data.paramdecl.expr) { + if (!info.args[i].data.paramdecl.expr || !CTemplTool_EqualExprTypes(argA->data.paramdecl.expr, info.args[i].data.paramdecl.expr)) + return 0; + } else { + if (info.args[i].data.paramdecl.expr || argA->pid.index != info.args[i].pid.index) + return 0; + } + } else { + info.args[i].data.paramdecl.expr = argA->data.paramdecl.expr; + info.args[i].pid.index = argA->pid.index; + info.args[i].pid.type = TPT_NONTYPE; + info.args[i].is_deduced = 1; + } + } else { + if ( + !argA->data.paramdecl.expr || + !CTemplTool_EqualExprTypes(argA->data.paramdecl.expr, argB->data.paramdecl.expr) + ) + return 0; + } + break; + + case TPT_TEMPLATE: + if (!CTempl_DeduceType( + argB->data.ttargtype, 0, + argA->data.ttargtype, 0, + info.args, 0, 0 + )) + return 0; + break; + + default: + CError_FATAL(955); + } + + argA = argA->next; + argB = argB->next; + } +} + +static Boolean CTemplClass_PartialClassIsMoreSpecialized(TemplPartialSpec *pspec1, TemplPartialSpec *pspec2) { + return CTemplClass_PartialClassIsAtLeastAsSpecialized(pspec1, pspec2) && + !CTemplClass_PartialClassIsAtLeastAsSpecialized(pspec2, pspec1); +} + +typedef struct PSpecList { + struct PSpecList *next; + TemplPartialSpec *pspec; +} PSpecList; + +static PSpecList *CTemplClass_FindMostSpecializedPartialSpecializations(PSpecList *list) { + PSpecList **array; + PSpecList *scan; + int i; + int j; + int count; + + scan = list; + count = 0; + while (scan) { + scan = scan->next; + count++; + } + + array = lalloc(sizeof(PSpecList *) * count); + for (i = 0, scan = list; scan; scan = scan->next) + array[i++] = scan; + + for (i = 0; i < count; i++) { + if (array[i]) { + for (j = 0; j < count; j++) { + if (array[j] && i != j && CTemplClass_PartialClassIsMoreSpecialized(array[i]->pspec, array[j]->pspec)) + array[j] = NULL; + } + } + } + + for (i = 0, list = NULL; i < count; i++) { + if (array[i]) { + if (!list) + list = array[i]; + else + array[j]->next = array[i]; + array[i]->next = NULL; + j = i; + } + } + + return list; +} + +Boolean CTemplClass_FindPartialTemplate(TemplArg *args, TemplClass **resultTempl, TemplArg **resultArgs) { + TemplPartialSpec *pspec; + PSpecList *list; + TemplClassInst *inst; + + for (inst = (*resultTempl)->instances; inst; inst = inst->next) { + if (inst->is_instantiated || inst->is_specialized) { + if (CTemplTool_EqualArgs(args, inst->oargs ? inst->oargs : inst->inst_args)) + return 0; + } + } + + list = NULL; + for (pspec = (*resultTempl)->pspecs; pspec; pspec = pspec->next) { + if (CTemplClass_PartialTemplateArgMatch(pspec, args, 0)) { + PSpecList *entry = lalloc(sizeof(PSpecList)); + entry->next = list; + entry->pspec = pspec; + list = entry; + } + } + + if (list) { + if (list->next) { + list = CTemplClass_FindMostSpecializedPartialSpecializations(list); + if (list->next) + CError_Error(CErrorStr346); + } + + if (!list->pspec->templ->templ__params) { + *resultTempl = list->pspec->templ; + *resultArgs = NULL; + return 1; + } + + *resultTempl = list->pspec->templ; + *resultArgs = CTemplClass_PartialTemplateArgMatch(list->pspec, args, 1); + return *resultArgs != NULL; + } else { + return 0; + } +} + +TemplClass *CTemplClass_DefineNestedClass(TemplClass *parent, HashNameNode *name, short mode) { + TemplateAction *action; + TemplClass *templ; + + templ = galloc(sizeof(TemplClass)); + memclrw(templ, sizeof(TemplClass)); + + templ->next = ctempl_templates; + ctempl_templates = templ; + + templ->templ_parent = parent; + templ->templ__params = NULL; + CDecl_DefineClass(parent->theclass.nspace, name, TYPE_CLASS(templ), mode, 0, 1); + + templ->theclass.flags = CLASS_IS_TEMPL; + templ->align = copts.structalignment; + + action = galloc(sizeof(TemplateAction)); + memclrw(action, sizeof(TemplateAction)); + + action->type = TAT_NESTEDCLASS; + action->u.tclasstype = templ; + CTemplClass_AppendTemplateAction(parent, action); + + return templ; +} + +static void CTemplClass_CopyNestedClass(TypeDeduce *deduce, TemplClass *templ) { + ObjTypeTag *tag; + + tag = galloc(sizeof(ObjTypeTag)); + memclrw(tag, sizeof(ObjTypeTag)); + + tag->otype = OT_TYPETAG; + tag->access = ACCESSPUBLIC; + + if (!templ->templ__params) { + TemplClassInst *inst = CTemplClass_NewInstance(templ, NULL, NULL); + inst->parent = deduce->inst; + inst->theclass.nspace->parent = deduce->inst->theclass.nspace; + + tag->type = TYPE(inst); + } else { + TemplClass *copy = galloc(sizeof(TemplClass)); + memclrw(copy, sizeof(TemplClass)); + + copy->next = ctempl_templates; + ctempl_templates = copy; + + copy->theclass = templ->theclass; + copy->templ_parent = deduce->tmclass; + copy->inst_parent = deduce->inst; + copy->templ__params = templ->templ__params; + copy->members = NULL; + copy->instances = NULL; + copy->pspecs = NULL; + copy->actions = templ->actions; + copy->lex_order_count = templ->lex_order_count; + copy->align = templ->align; + copy->flags = templ->flags; + + tag->type = TYPE(copy); + } + + CScope_AddObject(deduce->inst->theclass.nspace, templ->theclass.classname, OBJ_BASE(tag)); +} + +static void CTemplClass_CopyBaseClasses(TypeDeduce *deduce, TemplClassInst *inst, TemplClass *templ) { + TemplateAction *action; + ClassList *newBase; + ClassList *templbase; + ClassList *instbase; + ClassList *base; + UInt32 qual = 0; + + for (base = templ->theclass.bases; base; base = base->next) { + ClassList *scan; + newBase = galloc(sizeof(ClassList)); + *newBase = *base; + newBase->next = NULL; + + if ((scan = inst->theclass.bases)) { + while (1) { + if (scan->base == newBase->base) { + CError_Error(CErrorStr131); + break; + } + if (!scan->next) { + scan->next = newBase; + break; + } + scan = scan->next; + } + } else { + inst->theclass.bases = newBase; + } + } + + for (action = deduce->tmclass->actions; action; action = action->next) { + if (action->type == TAT_BASE) { + TStreamElement *save; + + CTemplClass_SetupActionErrorRef(action, &save); + + newBase = galloc(sizeof(ClassList)); + memclrw(newBase, sizeof(ClassList)); + + newBase->base = TYPE_CLASS(CTemplTool_DeduceTypeCopy(deduce, action->u.base.type, &qual)); + newBase->access = action->u.base.access; + newBase->is_virtual = action->u.base.is_virtual; + + if (IS_TYPE_CLASS(newBase->base)) { + if (newBase->base->size == 0) { + CDecl_CompleteType(TYPE(newBase->base)); + IsCompleteType(TYPE(newBase->base)); + } + + if (CDecl_CheckNewBase(TYPE_CLASS(inst), newBase->base, newBase->is_virtual)) { + if (action->u.base.insert_after) { + templbase = templ->theclass.bases; + instbase = inst->theclass.bases; + while (1) { + CError_ASSERT(1222, templbase && instbase); + + if (templbase == action->u.base.insert_after) { + newBase->next = instbase->next; + instbase->next = newBase; + break; + } + + templbase = templbase->next; + instbase = instbase->next; + } + } else { + newBase->next = inst->theclass.bases; + inst->theclass.bases = newBase; + } + } + } else { + CError_Error(CErrorStr131); + } + + CTemplClass_RestoreActionErrorRef(&save); + } + } + + if (inst->theclass.flags & CLASS_HAS_VBASES) + CDecl_MakeVBaseList(TYPE_CLASS(inst)); +} + +static void CTemplClass_CopyEnum(TypeDeduce *deduce, TemplateAction *action) { + TypeEnum *destenum; + TypeEnum *srcenum; + ObjEnumConst **destptr; + ObjEnumConst *src; + TemplateAction *scanaction; + + srcenum = action->u.enumtype; + destenum = galloc(sizeof(TypeEnum)); + memclrw(destenum, sizeof(TypeEnum)); + + destenum->type = TYPEENUM; + destenum->size = srcenum->size; + destenum->nspace = deduce->inst->theclass.nspace; + destenum->enumtype = srcenum->enumtype; + destenum->enumname = srcenum->enumname; + + if (destenum->enumname) + CScope_DefineTypeTag(destenum->nspace, destenum->enumname, TYPE(destenum)); + + src = srcenum->enumlist; + destptr = &destenum->enumlist; + while (src) { + ObjEnumConst *dest; + + dest = galloc(sizeof(ObjEnumConst)); + *dest = *src; + + *destptr = dest; + dest->next = NULL; + dest->type = TYPE(destenum); + CScope_AddObject(deduce->inst->theclass.nspace, dest->name, OBJ_BASE(dest)); + + src = src->next; + destptr = &(*destptr)->next; + } + + for (scanaction = deduce->tmclass->actions; scanaction; scanaction = scanaction->next) { + if (scanaction->type == TAT_ENUMERATOR && scanaction->u.enumerator.objenumconst->type == TYPE(srcenum)) { + CTemplClass_NewDefAction(deduce, action)->enumtype = destenum; + return; + } + } +} + +static void CTemplClass_CompleteEnumType(TypeDeduce *deduce, TemplateAction *action, TypeEnum *destenum) { + TypeEnum *srcenum; + ObjEnumConst *dest; + TemplateAction *scanaction; + ENode *expr; + ObjEnumConst *src; + + srcenum = action->u.enumtype; + + for (scanaction = deduce->tmclass->actions; scanaction; scanaction = scanaction->next) { + if (scanaction->type == TAT_ENUMERATOR) { + src = scanaction->u.enumerator.objenumconst; + if (src->type == TYPE(srcenum)) { + TStreamElement *save; + + CTemplClass_SetupActionErrorRef(scanaction, &save); + + dest = destenum->enumlist; + while (dest) { + if (dest->name == src->name) + break; + dest = dest->next; + } + + CError_ASSERT(1332, dest); + + if (scanaction->u.enumerator.initexpr) { + expr = CTemplTool_DeduceExpr(deduce, scanaction->u.enumerator.initexpr); + if (!ENODE_IS(expr, EINTCONST)) { + CError_Error(CErrorStr124); + CTemplClass_RestoreActionErrorRef(&save); + break; + } + } else { + CError_ASSERT(1347, expr); + expr->data.intval = CInt64_Add(expr->data.intval, cint64_one); + } + + dest->val = expr->data.intval; + dest->type = expr->rtype; + CTemplClass_RestoreActionErrorRef(&save); + } + } + } + + CDecl_ComputeUnderlyingEnumType(destenum); +} + +static void CTemplClass_CopyObjMemberVarPath(TypeDeduce *deduce, ObjMemberVarPath *ivar) { + ObjMemberVarPath *copy; + + copy = galloc(sizeof(ObjMemberVarPath)); + *copy = *ivar; + + if (copy->path && copy->path->type == TYPE(deduce->tmclass)) { + copy->path = CClass_GetPathCopy(copy->path, 1); + copy->path->type = TYPE(deduce->inst); + } + + CScope_AddObject(deduce->inst->theclass.nspace, copy->name, OBJ_BASE(copy)); +} + +static void CTemplClass_CopyIVars(TypeDeduce *deduce, TemplClassInst *inst, TemplClass *templ) { + ObjMemberVar *src; + ObjMemberVar *dest; + ObjMemberVar **destptr; + TemplateAction *scanaction; + + src = templ->theclass.ivars; + destptr = &inst->theclass.ivars; + + while (src) { + CError_ASSERT(1397, !src->has_path); + + dest = galloc(sizeof(ObjMemberVar)); + *dest = *src; + + for (scanaction = deduce->tmclass->actions; scanaction; scanaction = scanaction->next) { + if (scanaction->type == TAT_OBJECTDEF && scanaction->u.refobj == OBJ_BASE(src)) { + CTemplClass_NewDefAction(deduce, scanaction)->refobj = OBJ_BASE(dest); + break; + } + } + + if (!scanaction) { + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); + if (dest->type->size == 0) { + CDecl_CompleteType(dest->type); + IsCompleteType(dest->type); + } + } + + if (dest->name && dest->name != no_name_node) + CScope_AddObject(inst->theclass.nspace, dest->name, OBJ_BASE(dest)); + + *destptr = dest; + destptr = &dest->next; + src = src->next; + } +} + +static void CTemplClass_CopyObjType(TypeDeduce *deduce, ObjType *src, HashNameNode *name) { + TemplateAction *scanaction; + NameSpaceObjectList *list; + NameSpaceObjectList *newlist; + ObjType *dest; + + for (scanaction = deduce->tmclass->actions; scanaction; scanaction = scanaction->next) { + if (scanaction->type == TAT_OBJECTDEF && scanaction->u.refobj == OBJ_BASE(src)) + break; + } + + dest = galloc(sizeof(ObjType)); + *dest = *src; + + if (scanaction) + CTemplClass_NewDefAction(deduce, scanaction)->refobj = OBJ_BASE(dest); + else + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); + + if ((list = CScope_FindName(deduce->inst->theclass.nspace, name)) && list->object->otype == OT_TYPETAG) { + CError_ASSERT(1470, list->next == NULL); + + newlist = galloc(sizeof(NameSpaceObjectList)); + newlist->object = list->object; + newlist->next = NULL; + + list->object = OBJ_BASE(dest); + list->next = newlist; + } else { + CScope_AddObject(deduce->inst->theclass.nspace, name, OBJ_BASE(dest)); + } +} + +static void CTemplClass_CopyObjTypeTag(TypeDeduce *deduce, ObjTypeTag *src, HashNameNode *name) { + UInt32 qual = 0; + ObjTypeTag *dest = galloc(sizeof(ObjTypeTag)); + + *dest = *src; + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &qual); + + CScope_AddObject(deduce->inst->theclass.nspace, name, OBJ_BASE(dest)); +} + +static void CTemplClass_CopyMemberTemplate(TypeDeduce *deduce, Object *src) { + TemplateFunction *desttempl; + Object *dest; + TemplateFunction *srctempl; + TemplateAction *action; + + srctempl = src->u.func.u.templ; + CError_ASSERT(1516, srctempl && srctempl->params); + + for (action = deduce->tmclass->actions; action; action = action->next) { + if (action->type == TAT_OBJECTDEF && action->u.refobj == OBJ_BASE(src)) + break; + } + + desttempl = galloc(sizeof(TemplateFunction)); + *desttempl = *srctempl; + + desttempl->next = ctempl_templatefuncs; + ctempl_templatefuncs = desttempl; + + desttempl->unk4 = srctempl; + + dest = galloc(sizeof(Object)); + *dest = *src; + + dest->u.func.u.templ = desttempl; + dest->nspace = deduce->inst->theclass.nspace; + + CError_ASSERT(1541, !deduce->x15); + deduce->x15 = 1; + deduce->nindex = srctempl->params->pid.nindex; + + if (action) + CTemplClass_NewDefAction(deduce, action)->refobj = OBJ_BASE(dest); + else + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); + + deduce->x15 = 0; + + CError_ASSERT(1553, IS_TYPE_FUNC(dest->type)); + + TYPE_FUNC(dest->type)->flags |= FUNC_IS_TEMPL; + + if ( + (TYPE_FUNC(dest->type)->flags & FUNC_IS_CTOR) && + deduce->x17 && + !action + ) + { + FuncArg *arg; + CError_ASSERT(1560, TYPE_FUNC(dest->type)->args); + arg = CParser_NewFuncArg(); + arg->type = TYPE(&stsignedshort); + arg->next = TYPE_FUNC(dest->type)->args->next; + TYPE_FUNC(dest->type)->args->next = arg; + } + + CScope_AddObject(deduce->inst->theclass.nspace, dest->name, OBJ_BASE(dest)); +} + +static void CTemplClass_CopyObject(TypeDeduce *deduce, Object *src) { + ObjectTemplated *dest; + TemplateAction *action; + TemplateAction *action2; + Boolean flag; + + flag = 1; + if (src->nspace != deduce->tmclass->theclass.nspace) { + CError_ASSERT(1587, src->datatype == DALIAS); + flag = 0; + } + + if (IS_TEMPL_FUNC(src->type)) { + CTemplClass_CopyMemberTemplate(deduce, src); + return; + } + + for (action = deduce->tmclass->actions; action; action = action->next) { + if (action->type == TAT_OBJECTDEF && action->u.refobj == OBJ_BASE(src)) + break; + } + + dest = galloc(sizeof(ObjectTemplated)); + dest->object = *src; + + if (action) + CTemplClass_NewDefAction(deduce, action)->refobj = OBJ_BASE(dest); + else + dest->object.type = CTemplTool_DeduceTypeCopy(deduce, dest->object.type, &dest->object.qual); + + if (flag) + dest->object.nspace = deduce->inst->theclass.nspace; + + dest->object.qual |= Q_IS_TEMPLATED; + dest->parent = src; + + if (IS_TYPE_FUNC(dest->object.type)) + TYPE_FUNC(dest->object.type)->flags &= ~FUNC_DEFINED; + + switch (dest->object.datatype) { + case DDATA: + dest->object.u.data.linkname = NULL; + for (action2 = deduce->tmclass->actions; action2; action2 = action2->next) { + if (action2->type == TAT_OBJECTINIT && action2->u.objectinit.object == src) { + CTemplClass_NewDefAction(deduce, action2)->refobj = OBJ_BASE(dest); + break; + } + } + break; + + case DABSOLUTE: + break; + + case DFUNC: + case DVFUNC: + dest->object.u.func.linkname = NULL; + CError_ASSERT(1650, IS_TYPE_FUNC(dest->object.type)); + CError_ASSERT(1651, !dest->object.u.func.u.templ && !dest->object.u.func.defargdata); + + if ( + (TYPE_FUNC(dest->object.type)->flags & FUNC_IS_CTOR) && + deduce->x17 && + !action + ) + { + FuncArg *arg; + CError_ASSERT(1657, TYPE_FUNC(dest->object.type)->args); + arg = CParser_NewFuncArg(); + arg->type = TYPE(&stsignedshort); + arg->next = TYPE_FUNC(dest->object.type)->args->next; + TYPE_FUNC(dest->object.type)->args->next = arg; + } + + if (TYPE_FUNC(dest->object.type)->flags & FUNC_CONVERSION) { + CError_ASSERT(1665, IS_TYPE_FUNC(src->type)); + if (CTemplTool_IsTemplateArgumentDependentType(TYPE_FUNC(src->type)->functype)) { + CError_ASSERT(1668, action); + return; + } + } + + break; + + case DINLINEFUNC: + break; + + case DALIAS: + if (dest->object.u.alias.member && dest->object.u.alias.member->type == TYPE(deduce->tmclass)) { + dest->object.u.alias.member = CClass_GetPathCopy(dest->object.u.alias.member, 1); + dest->object.u.alias.member->type = TYPE(deduce->inst); + } + break; + + case DLOCAL: + case DEXPR: + CError_FATAL(1688); + + default: + CError_FATAL(1691); + } + + CScope_AddObject(deduce->inst->theclass.nspace, dest->object.name, OBJ_BASE(dest)); +} + +static void CTemplClass_CompleteObject(TypeDeduce *deduce, TemplateAction *action, ObjBase *refobj) { + if (refobj->otype == OT_MEMBERVAR) { + ObjMemberVar *ivar = OBJ_MEMBER_VAR(refobj); + ivar->type = CTemplTool_DeduceTypeCopy(deduce, ivar->type, &ivar->qual); + + if (ivar->type->size == 0) { + CDecl_CompleteType(ivar->type); + if (copts.experimental) { + if (ivar->next || ivar->type->size != 0 || !IS_TYPE_ARRAY(ivar->type)) + IsCompleteType(ivar->type); + } else { + IsCompleteType(ivar->type); + } + } + } else if (refobj->otype == OT_TYPE) { + ObjType *obj = OBJ_TYPE(refobj); + obj->type = CTemplTool_DeduceTypeCopy(deduce, obj->type, &obj->qual); + } else { + Object *dest; + Object *src; + + CError_ASSERT(1737, refobj->otype == OT_OBJECT); + + dest = OBJECT(refobj); + src = OBJECT(action->u.refobj); + + if (IS_TEMPL_FUNC(src->type)) { + TemplateFunction *templ = src->u.func.u.templ; + CError_ASSERT(1747, templ); + CError_ASSERT(1748, !deduce->x15); + + deduce->x15 = 1; + deduce->nindex = templ->params->pid.nindex; + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); + deduce->x15 = 0; + + CError_ASSERT(1753, IS_TYPE_FUNC(dest->type)); + TYPE_FUNC(dest->type)->flags |= FUNC_IS_TEMPL; + } else { + dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); + dest->qual |= Q_IS_TEMPLATED; + + if (IS_TYPE_FUNC(dest->type)) + TYPE_FUNC(dest->type)->flags &= ~FUNC_DEFINED; + + switch (dest->datatype) { + case DFUNC: + case DVFUNC: + CError_ASSERT(1769, IS_TYPE_FUNC(dest->type)); + if (TYPE_FUNC(dest->type)->flags & FUNC_CONVERSION) { + CError_ASSERT(1772, IS_TYPE_FUNC(dest->type)); + if (CTemplTool_IsTemplateArgumentDependentType(TYPE_FUNC(src->type)->functype)) { + dest->name = CMangler_ConversionFuncName( + TYPE_FUNC(dest->type)->functype, TYPE_FUNC(dest->type)->qual); + CScope_AddObject(deduce->inst->theclass.nspace, dest->name, OBJ_BASE(dest)); + } + } + + if ((TYPE_FUNC(dest->type)->flags & FUNC_IS_CTOR) && deduce->x17) { + FuncArg *arg; + CError_ASSERT(1786, TYPE_FUNC(dest->type)->args); + arg = CParser_NewFuncArg(); + arg->type = TYPE(&stsignedshort); + arg->next = TYPE_FUNC(dest->type)->args->next; + TYPE_FUNC(dest->type)->args->next = arg; + } + + break; + } + } + } +} + +static void CTemplClass_CompleteObjectInit(TypeDeduce *deduce, TemplateAction *action, Object *object) { + ENode *expr = CTemplTool_DeduceExpr(deduce, action->u.objectinit.initexpr); + + if (ENODE_IS(expr, EINTCONST) && (object->qual & Q_CONST) && IS_TYPE_INT_OR_ENUM(object->type)) { + object->u.data.u.intconst = expr->data.intval; + object->qual |= Q_INLINE_DATA | Q_20000; + } else { + CError_Error(CErrorStr354, object->name->name); + } +} + +static void CTemplClass_CopyNameSpace(TypeDeduce *deduce, TemplClassInst *inst, TemplClass *templ) { + NameSpaceName *nsname; + NameSpaceObjectList *list; + + CError_ASSERT(1830, !templ->theclass.nspace->is_hash); + + for (nsname = templ->theclass.nspace->data.list; nsname; nsname = nsname->next) { + for (list = &nsname->first; list; list = list->next) { + switch (list->object->otype) { + case OT_ENUMCONST: + break; + case OT_MEMBERVAR: + if (OBJ_MEMBER_VAR(list->object)->has_path) + CTemplClass_CopyObjMemberVarPath(deduce, OBJ_MEMBER_VAR_PATH(list->object)); + break; + case OT_TYPE: + CTemplClass_CopyObjType(deduce, OBJ_TYPE(list->object), nsname->name); + break; + case OT_TYPETAG: + break; + case OT_NAMESPACE: + CError_FATAL(1854); + case OT_OBJECT: + CTemplClass_CopyObject(deduce, OBJECT(list->object)); + break; + default: + CError_FATAL(1861); + } + } + } +} + +static void CTemplClass_CopyUsingDecl(TypeDeduce *deduce, TypeTemplDep *type, AccessType access) { + TypeClass *tclass; + UInt32 qual = 0; + + CError_ASSERT(1878, IS_TYPE_TEMPLATE(type) && type->dtype == TEMPLDEP_QUALNAME); + + tclass = TYPE_CLASS(CTemplTool_DeduceTypeCopy(deduce, TYPE(type->u.qual.type), &qual)); + if (!IS_TYPE_CLASS(tclass)) { + CError_Error(CErrorStr340, type->u.qual.name->name); + return; + } + + CDecl_CompleteType(TYPE(tclass)); + CScope_AddClassUsingDeclaration(TYPE_CLASS(deduce->inst), tclass, type->u.qual.name, access); +} + +static void CTemplClass_CopyFriend(TypeDeduce *deduce, TemplateFriend *tfriend) { + TemplArg *arg; + Object *funcobj; + Boolean flag; + CScopeSave saveScope; + DeclInfo di; + + CDecl_UnpackDeclInfo(&di, &tfriend->decl); + + if (CTemplTool_IsTemplateArgumentDependentType(di.thetype)) + di.thetype = CTemplTool_DeduceTypeCopy(deduce, di.thetype, &di.qual); + + if (di.expltargs) { + di.expltargs = CTemplTool_MakeGlobalTemplArgCopy(di.expltargs); + for (arg = di.expltargs; arg; arg = arg->next) { + switch (arg->pid.type) { + case TPT_TYPE: + if (CTemplTool_IsTemplateArgumentDependentType(arg->data.typeparam.type)) + arg->data.typeparam.type = CTemplTool_DeduceTypeCopy(deduce, arg->data.typeparam.type, &arg->data.typeparam.qual); + break; + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(arg->data.paramdecl.expr)) + arg->data.paramdecl.expr = CTemplTool_DeduceExpr(deduce, arg->data.paramdecl.expr); + break; + case TPT_TEMPLATE: + default: + CError_FATAL(1930); + } + } + } + + if (IS_TYPE_FUNC(di.thetype)) { + CScope_SetNameSpaceScope(CScope_FindGlobalNS(deduce->inst->theclass.nspace), &saveScope); + funcobj = CDecl_GetFunctionObject(&di, NULL, &flag, 0); + CScope_RestoreScope(&saveScope); + + if (funcobj) { + CDecl_AddFriend(TYPE_CLASS(deduce->inst), funcobj, NULL); + if (tfriend->stream.tokens) + CInline_AddInlineFunctionAction(funcobj, TYPE_CLASS(deduce->inst), &tfriend->fileoffset, &tfriend->stream, 0); + } else { + CError_Error(CErrorStr201); + } + } else { + CError_ASSERT(1963, IS_TYPE_CLASS(di.thetype)); + CDecl_AddFriend(TYPE_CLASS(deduce->inst), NULL, TYPE_CLASS(di.thetype)); + } +} + +Boolean CTempl_InstantiateTemplateClass(TypeClass *tclass) { + TemplClassInst *inst; + ParserTryBlock *tryBlock; + TemplateAction *action; + DefAction *defAction; + UInt8 saveAlignMode; + + TypeDeduce deduce; + TemplStack stack; + CScopeSave saveScope; + ClassLayout layout; + TemplClass *templ; + TStreamElement *saveErrorRef; + TemplArg *inst_args; + + CError_ASSERT(1989, tclass->flags & CLASS_IS_TEMPL_INST); + + if (tclass->flags & CLASS_COMPLETED) + return 1; + + inst = TEMPL_CLASS_INST(tclass); + if (inst->is_specialized) + return 0; + + templ = inst->templ; + if (!(templ->flags & TEMPLCLASS_FLAGS_2)) + templ = CTemplClass_GetMasterTemplate(templ); + + if (templ->pspecs && CTemplClass_FindPartialTemplate(inst->inst_args, &templ, &inst_args)) { + CError_ASSERT(2013, !inst->oargs); + inst->templ = templ; + inst->oargs = inst->inst_args; + inst->inst_args = inst_args; + } + + if (!(templ->theclass.flags & CLASS_COMPLETED)) + return 0; + + if (inst->is_instantiated) + return 0; + + inst->is_instantiated = 1; + CScope_SetClassScope(tclass, &saveScope); + CTemplTool_PushInstance(&stack, tclass, NULL); + + tryBlock = trychain; + trychain = NULL; + + memclrw(&deduce, sizeof(deduce)); + deduce.tmclass = templ; + deduce.inst = inst; + deduce.params = templ->templ__params; + deduce.args = inst->inst_args; + + CError_ASSERT(2045, !templ->theclass.sominfo); + CError_ASSERT(2047, !templ->theclass.objcinfo); + CError_ASSERT(2049, !templ->theclass.vtable); + + inst->theclass.flags |= templ->theclass.flags & + (CLASS_ABSTRACT | CLASS_SINGLE_OBJECT | CLASS_HAS_VBASES | CLASS_IS_CONVERTIBLE | CLASS_COM_OBJECT); + + CTemplClass_CopyBaseClasses(&deduce, inst, templ); + + deduce.x17 = (inst->theclass.flags & CLASS_HAS_VBASES) && !(templ->theclass.flags & CLASS_HAS_VBASES); + + for (action = templ->actions; action; action = action->next) { + switch (action->type) { + case TAT_NESTEDCLASS: + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CopyNestedClass(&deduce, action->u.tclasstype); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + case TAT_ENUMTYPE: + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CopyEnum(&deduce, action); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + case TAT_FRIEND: + case TAT_ENUMERATOR: + case TAT_BASE: + case TAT_OBJECTINIT: + case TAT_USINGDECL: + case TAT_OBJECTDEF: + break; + default: + CError_FATAL(2094); + } + } + + CTemplClass_CopyIVars(&deduce, inst, templ); + CTemplClass_CopyNameSpace(&deduce, inst, templ); + + CError_ASSERT(2105, !templ->theclass.friends); + + for (action = templ->actions; action; action = action->next) { + switch (action->type) { + case TAT_NESTEDCLASS: + break; + case TAT_ENUMTYPE: + for (defAction = deduce.defActions; defAction; defAction = defAction->next) { + if (defAction->action == action) { + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CompleteEnumType(&deduce, action, defAction->enumtype); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + } + } + break; + case TAT_FRIEND: + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CopyFriend(&deduce, action->u.tfriend); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + case TAT_ENUMERATOR: + break; + case TAT_BASE: + break; + case TAT_OBJECTINIT: + for (defAction = deduce.defActions; ; defAction = defAction->next) { + CError_ASSERT(2136, defAction); + if (defAction->action == action) { + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CompleteObjectInit(&deduce, action, OBJECT(defAction->refobj)); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + } + } + break; + case TAT_USINGDECL: + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CopyUsingDecl(&deduce, action->u.usingdecl.type, action->u.usingdecl.access); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + case TAT_OBJECTDEF: + for (defAction = deduce.defActions; ; defAction = defAction->next) { + CError_ASSERT(2156, defAction); + if (defAction->action == action) { + CTemplClass_SetupActionErrorRef(action, &saveErrorRef); + CTemplClass_CompleteObject(&deduce, action, defAction->refobj); + CTemplClass_RestoreActionErrorRef(&saveErrorRef); + break; + } + } + break; + } + } + + memclrw(&layout, sizeof(layout)); + layout.lex_order_count = templ->lex_order_count; + layout.has_vtable = templ->flags & TEMPLCLASS_HAS_VTABLE; + + saveAlignMode = copts.structalignment; + copts.structalignment = templ->align; + CDecl_CompleteClass(&layout, TYPE_CLASS(inst)); + copts.structalignment = saveAlignMode; + + if (templ->theclass.align > inst->theclass.align) { + inst->theclass.align = templ->theclass.align; + inst->theclass.size += CABI_StructSizeAlignValue(TYPE(inst), inst->theclass.size); + } + + CTemplTool_PopInstance(&stack); + CScope_RestoreScope(&saveScope); + trychain = tryBlock; + + return 1; +} diff --git a/compiler_and_linker/FrontEnd/C/CTemplateFunc.c b/compiler_and_linker/FrontEnd/C/CTemplateFunc.c new file mode 100644 index 0000000..3c5de98 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CTemplateFunc.c @@ -0,0 +1,1383 @@ +#include "compiler/CTemplateFunc.h" +#include "compiler/CABI.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CInline.h" +#include "compiler/CInt64.h" +#include "compiler/CParser.h" +#include "compiler/CTemplateTools.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" +#include "compiler/types.h" + +static Boolean ctempl_conversion_deduction; +static UInt8 ctempl_explicitargs_nindex; +static int ctempl_explicitargs_num; +static Boolean ctempl_explicitargs_all; + +// forward decls +static Boolean CTempl_DeduceTypeTemplDep(TypeTemplDep *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray, Boolean flag); +static Boolean CTempl_DeduceType1(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray, Boolean flag); + +static void CTemplFunc_SetupTypeDeduce(TypeDeduce *deduce, TemplateFunction *templ, TemplArg *args) { + memclrw(deduce, sizeof(TypeDeduce)); + if (templ->tfunc->nspace->theclass && (templ->tfunc->nspace->theclass->flags & CLASS_IS_TEMPL)) + deduce->tmclass = TEMPL_CLASS(templ->tfunc->nspace->theclass); + deduce->params = templ->params; + deduce->args = args; +} + +Boolean CTempl_CanDeduceFunc(Object *object, TypeFunc *tfunc, TemplArg *args) { + DeduceInfo info; + int i; + + if (CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(object)->params, args, 0)) { + if (CTempl_DeduceType(object->type, 0, TYPE(tfunc), 0, info.args, 0, 0)) { + for (i = 0; i < info.maxCount; i++) { + if (!info.args[i].is_deduced) + return 0; + } + return 1; + } + } + + return 0; +} + +static TemplFuncInstance *CTempl_GetCreateFuncInstance(Object *funcobj, TemplArg *args, Object *object2) { + TemplFuncInstance *inst; + TemplateFunction *templ; + Object *instobj; + TemplParam *param; + TemplArg *arg; + TemplArg *last; + short paramCount; + short i; + TypeDeduce deduce; + + templ = CTemplTool_GetFuncTempl(funcobj); + + paramCount = 0; + param = templ->params; + while (param) { + param = param->next; + paramCount++; + } + + for (i = 1, arg = args; i < paramCount; i++, arg++) + arg->next = arg + 1; + arg->next = NULL; + + for (inst = templ->instances; inst; inst = inst->next) { + if (CTemplTool_EqualArgs(inst->args, args)) { + if (object2) + inst->object = object2; + return inst; + } + } + + inst = galloc(sizeof(TemplFuncInstance)); + memclrw(inst, sizeof(TemplFuncInstance)); + + for (i = 0, arg = NULL; i < paramCount; i++) { + if (arg) { + last->next = galloc(sizeof(TemplArg)); + last = last->next; + } else { + last = galloc(sizeof(TemplArg)); + arg = last; + } + + *last = *args; + last->next = NULL; + args++; + + if (last->pid.type == TPT_NONTYPE) { + CError_ASSERT(114, last->data.paramdecl.expr); + last->data.paramdecl.expr = CInline_CopyExpression(last->data.paramdecl.expr, CopyMode1); + } + } + + inst->args = arg; + inst->next = templ->instances; + templ->instances = inst; + + if (!object2) { + instobj = CParser_NewFunctionObject(NULL); + instobj->access = funcobj->access; + instobj->nspace = funcobj->nspace; + instobj->sclass = funcobj->sclass; + instobj->qual = funcobj->qual | Q_MANGLE_NAME; + instobj->name = templ->name; + instobj->u.func.inst = inst; + + CTemplFunc_SetupTypeDeduce(&deduce, templ, inst->args); + if (funcobj->nspace->theclass && (funcobj->nspace->theclass->flags & CLASS_IS_TEMPL_INST)) { + deduce.tmclass = TEMPL_CLASS_INST(funcobj->nspace->theclass)->templ; + deduce.inst = TEMPL_CLASS_INST(funcobj->nspace->theclass); + } + + instobj->type = CTemplTool_DeduceTypeCopy(&deduce, funcobj->type, &instobj->qual); + inst->object = instobj; + + if (IS_TYPE_FUNC(instobj->type)) { + TYPE_FUNC(instobj->type)->flags &= ~FUNC_DEFINED; + if (TYPE_FUNC(instobj->type)->flags & FUNC_IS_CTOR) { + FuncArg *funcarg; + CError_ASSERT(152, TYPE_FUNC(instobj->type)->flags & FUNC_METHOD); + CError_ASSERT(153, funcarg = TYPE_FUNC(instobj->type)->args); + + if (TYPE_METHOD(instobj->type)->theclass->flags & CLASS_HAS_VBASES) + CError_ASSERT(156, funcarg = funcarg->next); + + if (funcarg->next) + CDecl_CheckCtorIntegrity(funcarg->next, TYPE_METHOD(instobj->type)->theclass); + } + } + + if ((instobj->qual & Q_INLINE) && templ->stream.tokens) + CInline_AddTemplateFunctionAction(instobj, templ, inst); + + } else { + inst->object = object2; + } + + return inst; +} + +TemplFuncInstance *CTempl_CheckFuncInstance(Object *object1, TypeFunc *tfunc, TemplArg *args, Object *object2) { + DeduceInfo info; + int i; + + if (!CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(object1)->params, args, 1)) + return NULL; + + if (!CTempl_DeduceType(object1->type, 0, TYPE(tfunc), 0, info.args, 0, 0)) + return NULL; + + i = 0; + while (i < info.maxCount) { + if (!info.args[i++].is_deduced) + return NULL; + } + + return CTempl_GetCreateFuncInstance(object1, info.args, object2); +} + +TemplFuncInstance *CTempl_DeduceFunc(Object *object1, TypeFunc *tfunc, TemplArg *args, Object *object2, Boolean flag) { + return CTempl_CheckFuncInstance(object1, tfunc, args, object2); +} + +static Boolean CTempl_FuncIsAtLeastAsSpecialized(Object *func1, Object *func2) { + int i; + FuncArg *arg1; + FuncArg *arg2; + Type *type1; + Type *type2; + UInt32 qual1; + UInt32 qual2; + DeduceInfo info; + + arg1 = TYPE_FUNC(func2->type)->args; + if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(func2->type))) + arg1 = arg1->next; + + i = 0; + while (1) { + if (!arg1) + break; + CError_ASSERT(231, arg1->type != &stvoid); + if (arg1 == &elipsis) + break; + if (arg1 == &oldstyle) + break; + arg1 = arg1->next; + i++; + } + + if (!CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(func2)->params, NULL, 0)) + return 0; + + arg1 = TYPE_FUNC(func1->type)->args; + if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(func1->type))) + arg1 = arg1->next; + + arg2 = TYPE_FUNC(func2->type)->args; + if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(func2->type))) + arg2 = arg2->next; + + while (i > 0) { + if (!arg1) + break; + if (arg1 == &elipsis) + break; + if (arg1 == &oldstyle) + break; + + CError_ASSERT(255, arg2); + + type1 = arg1->type; + qual1 = arg1->qual & (Q_CONST | Q_VOLATILE); + qual2 = arg2->qual & (Q_CONST | Q_VOLATILE); + type2 = arg2->type; + + if (!CTemplTool_IsTemplateArgumentDependentType(type2)) { + if (IS_TYPE_REFERENCE(type1)) + type1 = TPTR_TARGET(type1); + type1 = CParser_RemoveTopMostQualifiers(type1, &qual1); + + if (IS_TYPE_REFERENCE(type2)) + type2 = TPTR_TARGET(type2); + type2 = CParser_RemoveTopMostQualifiers(type2, &qual2); + + if (!is_typesame(type1, type2) || qual1 != qual2) + return 0; + } else { + if (!CTempl_DeduceType(type2, qual2, type1, qual1, info.args, 0, 0)) + return 0; + } + + arg1 = arg1->next; + arg2 = arg2->next; + i--; + } + + return 1; +} + +Boolean CTempl_FuncIsMoreSpecialized(Object *object1, Object *object2) { + return CTempl_FuncIsAtLeastAsSpecialized(object1, object2) && !CTempl_FuncIsAtLeastAsSpecialized(object2, object1); +} + +Object *CTempl_PartialOrdering(Object *object, ObjectList *list, int count) { + int i; + int j; + Object **array; + ObjectList *scan; + Object *arrayBuffer[16]; + + for (count = 1, scan = list; scan; scan = scan->next) { + if (IS_TEMPL_FUNC(scan->object->type)) + count++; + } + + if (count > 16) + array = lalloc(sizeof(Object *) * count); + else + array = arrayBuffer; + + array[0] = object; + for (i = 1, scan = list; scan; scan = scan->next) { + if (IS_TEMPL_FUNC(scan->object->type)) + array[i++] = scan->object; + } + + for (i = 0; i < count; i++) { + if (array[i]) { + for (j = 0; j < count; j++) { + if (array[j] && i != j && CTempl_FuncIsMoreSpecialized(array[i], array[j])) + array[j] = NULL; + } + } + } + + object = NULL; + + for (i = 0; i < count; i++) { + if (array[i]) { + if (object) + return NULL; + object = array[i]; + } + } + + return object; +} + +int CTempl_GetTemplateArgumentExpressionIndex(TemplArg *arg) { + CError_ASSERT(529, arg->data.paramdecl.expr); + + if (ENODE_IS(arg->data.paramdecl.expr, ETEMPLDEP) && arg->data.paramdecl.expr->data.templdep.subtype == TDE_PARAM) + return arg->data.paramdecl.expr->data.templdep.u.pid.index; + + return -1; +} + +static Type *CTempl_GetSpecifiedType(TemplateFunction *templ, Type *type, UInt32 qual, TemplArg *args, UInt32 *resultQual) { + TypeDeduce deduce; + + CTemplFunc_SetupTypeDeduce(&deduce, templ, args); + *resultQual = qual; + return CTemplTool_DeduceTypeCopy(&deduce, type, resultQual); +} + +static Boolean CTempl_DeduceTemplateArgs(TemplArg *args1, TemplArg *args2, TemplArg *argArray) { + int index; + + while (1) { + if (!args1) + return !args2; + if (!args2) + return 0; + + if (args1->pid.type != args2->pid.type) + return 0; + + switch (args1->pid.type) { + case TPT_TYPE: + if (!CTempl_DeduceType1( + args1->data.typeparam.type, args1->data.typeparam.qual, + args2->data.typeparam.type, args2->data.typeparam.qual, + argArray, 1 + )) + return 0; + break; + + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(args1->data.paramdecl.expr)) { + index = CTempl_GetTemplateArgumentExpressionIndex(args1); + if (index < 0) + return 1; + + if (argArray[index].is_deduced) { + if (!CTemplTool_EqualExprTypes(args2->data.paramdecl.expr, argArray[index].data.paramdecl.expr)) + return 0; + } else { + argArray[index].data.paramdecl.expr = args2->data.paramdecl.expr; + argArray[index].pid.type = TPT_NONTYPE; + argArray[index].is_deduced = 1; + } + } else { + if (!CTemplTool_EqualExprTypes(args2->data.paramdecl.expr, args1->data.paramdecl.expr)) + return 0; + } + break; + + case TPT_TEMPLATE: + if (!IS_TEMPL_CLASS(args2->data.ttargtype)) + return 0; + + index = args1->pid.index; + if (argArray[index].is_deduced) { + if (args2->data.ttargtype != argArray[index].data.ttargtype) + return 0; + } else { + argArray[index].data.ttargtype = args2->data.ttargtype; + argArray[index].pid.type = TPT_TEMPLATE; + argArray[index].is_deduced = 1; + } + break; + + default: + CError_FATAL(640); + } + + args1 = args1->next; + args2 = args2->next; + } +} + +static Boolean CTempl_DeduceTemplDepTemplate(TemplClass *templ1, TemplArg *args1, TemplClass *templ2, TemplArg *args2, TemplArg *argArray) { + if (templ1 != templ2) + return 0; + + return CTempl_DeduceTemplateArgs(args2, args1, argArray); +} + +static Boolean CTempl_DeduceTemplateType(TemplClass *templ, TemplArg *args, TemplClassInst *inst, TemplArg *argArray) { + TemplClassInst *scan; + + for (scan = templ->instances; scan; scan = scan->next) { + if (scan == inst) + return CTempl_DeduceTemplateArgs(args, scan->oargs ? scan->oargs : scan->inst_args, argArray); + } + + return 0; +} + +static Boolean CTempl_DeduceTemplateTypeBase(TemplClass *templ, TemplArg *args, TemplClassInst *inst, TemplArg *argArray, Boolean flag) { + ClassList *base; + + if (CTempl_DeduceTemplateType(templ, args, inst, argArray)) + return 1; + + if (flag) { + for (base = inst->theclass.bases; base; base = base->next) { + if (CTempl_DeduceTemplateType(templ, args, TEMPL_CLASS_INST(base->base), argArray)) { + ctempl_conversion_deduction = 1; + return 1; + } + } + + for (base = inst->theclass.bases; base; base = base->next) { + if (CTempl_DeduceTemplateTypeBase(templ, args, TEMPL_CLASS_INST(base->base), argArray, 1)) { + ctempl_conversion_deduction = 1; + return 1; + } + } + } + + return 0; +} + +static Boolean CTempl_DeduceQualTemplate(TypeTemplDep *type1, TemplArg *args1, Type *type2, TemplArg *argArray) { + int index; + + if (type1->dtype == TEMPLDEP_ARGUMENT && type1->u.pid.type == TPT_TEMPLATE) { + index = type1->u.pid.index; + if (IS_TEMPL_CLASS_INST(type2)) { + if (argArray[index].is_deduced) { + if (argArray[index].data.ttargtype != TYPE(TEMPL_CLASS_INST(type2)->templ)) + return 0; + } else { + argArray[index].data.ttargtype = TYPE(TEMPL_CLASS_INST(type2)->templ); + argArray[index].pid.type = TPT_TEMPLATE; + argArray[index].is_deduced = 1; + } + + return CTempl_DeduceTemplateArgs(args1, TEMPL_CLASS_INST(type2)->inst_args, argArray); + } + + if (IS_TYPE_TEMPLATE(type2)) { + if (TYPE_TEMPLATE(type2)->dtype == TEMPLDEP_TEMPLATE) { + if (argArray[index].is_deduced) { + if (argArray[index].data.ttargtype != TYPE(TYPE_TEMPLATE(type2)->u.templ.templ)) + return 0; + } else { + argArray[index].data.ttargtype = TYPE(TYPE_TEMPLATE(type2)->u.templ.templ); + argArray[index].pid.type = TPT_TEMPLATE; + argArray[index].is_deduced = 1; + } + + return CTempl_DeduceTemplateArgs(args1, TYPE_TEMPLATE(type2)->u.templ.args, argArray); + } + + if (TYPE_TEMPLATE(type2)->dtype == TEMPLDEP_QUALTEMPL) { + return + CTempl_DeduceTypeTemplDep(type1, 0, TYPE(TYPE_TEMPLATE(type2)->u.qualtempl.type), 0, argArray, 1) && + CTempl_DeduceTemplateArgs(args1, TYPE_TEMPLATE(type2)->u.qualtempl.args, argArray); + } + } + } + + return 0; +} + +static Boolean CTempl_DeduceTypeTemplDep(TypeTemplDep *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray, Boolean flag) { + Type *tmptype; + UInt32 tmpqual; + short index; + Boolean f; + UInt32 modqual; + + switch (type1->dtype) { + case TEMPLDEP_ARGUMENT: + index = type1->u.pid.index; + tmptype = type2; + if (type1->u.pid.type == TPT_TEMPLATE) { + if (argArray[index].is_deduced) { + if (!is_typesame(tmptype, argArray[index].data.ttargtype)) + return 0; + } else { + argArray[index].data.ttargtype = type2; + argArray[index].pid.type = TPT_TEMPLATE; + argArray[index].is_deduced = 1; + } + return 1; + } + + switch (type2->type) { + case TYPEPOINTER: + tmpqual = qual2; + f = 0; + qual2 = TPTR_QUAL(type2); + modqual = qual2; + + if ((modqual & Q_CONST) && (qual1 & Q_CONST)) { + modqual &= ~Q_CONST; + f = 1; + } + if ((modqual & Q_VOLATILE) && (qual1 & Q_VOLATILE)) { + modqual &= ~Q_VOLATILE; + f = 1; + } + + if (f) { + tmptype = galloc(sizeof(TypePointer)); + *TYPE_POINTER(tmptype) = *TYPE_POINTER(type2); + TPTR_QUAL(tmptype) = modqual; + } + + if (flag && (qual2 | modqual) != (qual1 | modqual)) + return 0; + + break; + + case TYPEMEMBERPOINTER: + tmpqual = qual2; + f = 0; + qual2 = TYPE_MEMBER_POINTER(type2)->qual; + modqual = qual2; + + if ((modqual & Q_CONST) && (qual1 & Q_CONST)) { + modqual &= ~Q_CONST; + f = 1; + } + if ((modqual & Q_VOLATILE) && (qual1 & Q_VOLATILE)) { + modqual &= ~Q_VOLATILE; + f = 1; + } + + if (f) { + tmptype = galloc(sizeof(TypeMemberPointer)); + *TYPE_MEMBER_POINTER(tmptype) = *TYPE_MEMBER_POINTER(type2); + TYPE_MEMBER_POINTER(tmptype)->qual = modqual; + } + + if (flag && (qual2 | modqual) != (qual1 | modqual)) + return 0; + + break; + + default: + tmpqual = 0; + if ((qual2 & Q_CONST) && !(qual1 & Q_CONST)) + tmpqual |= Q_CONST; + if ((qual2 & Q_VOLATILE) && !(qual1 & Q_VOLATILE)) + tmpqual |= Q_VOLATILE; + + if (flag && (qual2 | tmpqual) != (qual1 | tmpqual)) + return 0; + } + + if (argArray[index].is_deduced) { + if (!is_typesame(tmptype, argArray[index].data.typeparam.type) || tmpqual != argArray[index].data.typeparam.qual) + return 0; + } else { + argArray[index].data.typeparam.type = tmptype; + argArray[index].data.typeparam.qual = tmpqual; + argArray[index].pid.type = TPT_TYPE; + argArray[index].is_deduced = 1; + } + return 1; + + case TEMPLDEP_QUALNAME: + return 1; + + case TEMPLDEP_TEMPLATE: + if (IS_TYPE_CLASS(type2)) + return CTempl_DeduceTemplateTypeBase( + type1->u.templ.templ, type1->u.templ.args, + TEMPL_CLASS_INST(type2), argArray, 0); + + if (IS_TYPE_TEMPLATE(type2) && TYPE_TEMPLATE(type2)->dtype == TEMPLDEP_TEMPLATE) + return CTempl_DeduceTemplDepTemplate( + TYPE_TEMPLATE(type2)->u.templ.templ, TYPE_TEMPLATE(type2)->u.templ.args, + type1->u.templ.templ, type1->u.templ.args, + argArray + ); + + return 0; + + case TEMPLDEP_ARRAY: + if (IS_TYPE_ARRAY(type2)) { + SInt32 elements; + + if (!CTempl_DeduceType1(type1->u.array.type, qual1, TPTR_TARGET(type2), qual2, argArray, flag)) + return 0; + + if (ENODE_IS(type1->u.array.index, EINTCONST)) { + CError_ASSERT(961, TPTR_TARGET(type2)->size); + return (type2->size / TPTR_TARGET(type2)->size) == CInt64_GetULong(&type1->u.array.index->data.intval); + } + + if (!ENODE_IS(type1->u.array.index, ETEMPLDEP) || type1->u.array.index->data.templdep.subtype != TDE_PARAM) + return 1; + + CError_ASSERT(970, TPTR_TARGET(type2)->size); + + elements = type2->size / TPTR_TARGET(type2)->size; + index = type1->u.array.index->data.templdep.u.pid.index; + if (argArray[index].is_deduced) { + CError_ASSERT(976, ENODE_IS(argArray[index].data.paramdecl.expr, EINTCONST)); + return elements == CInt64_GetULong(&argArray[index].data.paramdecl.expr->data.intval); + } else { + argArray[index].data.paramdecl.expr = intconstnode(CABI_GetPtrDiffTType(), elements); + argArray[index].pid.type = TPT_NONTYPE; + argArray[index].is_deduced = 1; + return 1; + } + } else if (IS_TYPE_TEMPLATE(type2) && TYPE_TEMPLATE(type2)->dtype == TEMPLDEP_ARRAY) { + if (!CTempl_DeduceType1(type1->u.array.type, qual1, TYPE_TEMPLATE(type2)->u.array.type, qual2, argArray, flag)) + return 0; + + if (ENODE_IS(type1->u.array.index, EINTCONST)) { + return ENODE_IS(TYPE_TEMPLATE(type2)->u.array.index, EINTCONST) && + CInt64_Equal(type1->u.array.index->data.intval, TYPE_TEMPLATE(type2)->u.array.index->data.intval); + } + + if (!ENODE_IS(type1->u.array.index, ETEMPLDEP) || type1->u.array.index->data.templdep.subtype != TDE_PARAM) + return 1; + + index = type1->u.array.index->data.templdep.u.pid.index; + if (argArray[index].is_deduced) { + return CTemplTool_EqualExprTypes(TYPE_TEMPLATE(type2)->u.array.index, argArray[index].data.paramdecl.expr); + } else { + argArray[index].data.paramdecl.expr = TYPE_TEMPLATE(type2)->u.array.index; + argArray[index].pid.type = TPT_NONTYPE; + argArray[index].is_deduced = 1; + return 1; + } + } + + return 0; + + case TEMPLDEP_QUALTEMPL: + return CTempl_DeduceQualTemplate(type1->u.qualtempl.type, type1->u.qualtempl.args, type2, argArray); + + case TEMPLDEP_BITFIELD: + default: + CError_FATAL(1022); + return 1; + } +} + +static Boolean CTempl_DeduceFuncType(TypeFunc *tfunc1, TypeFunc *tfunc2, TemplArg *argArray) { + FuncArg *arg1; + FuncArg *arg2; + Type *type2; + Type *type1; + UInt32 qual2; + UInt32 qual1; + + arg1 = tfunc1->args; + arg2 = tfunc2->args; + + if (IS_TYPEFUNC_NONSTATIC_METHOD(tfunc1) && !IS_TYPEFUNC_METHOD(tfunc2)) { + CError_ASSERT(1045, arg1); + arg1 = arg1->next; + } + + while (1) { + if (arg1 == NULL) + return !arg2; + if (arg1 == &oldstyle) + return arg2 == &oldstyle; + if (arg1 == &elipsis) + return arg2 == &elipsis; + + if (arg2 == NULL || arg2 == &oldstyle || arg2 == &elipsis) + return 0; + + qual2 = arg2->qual; + type2 = CParser_RemoveTopMostQualifiers(arg2->type, &qual2); + + qual1 = arg1->qual; + type1 = CParser_RemoveTopMostQualifiers(arg1->type, &qual1); + + if (!CTempl_DeduceType1(type1, qual1, type2, qual2, argArray, 1)) + return 0; + + arg1 = arg1->next; + arg2 = arg2->next; + } +} + +static Boolean CTempl_DeduceType1(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray, Boolean flag) { + while (1) { + switch (type1->type) { + case TYPETEMPLATE: + return CTempl_DeduceTypeTemplDep(TYPE_TEMPLATE(type1), qual1, type2, qual2, argArray, flag); + + case TYPEVOID: + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPESTRUCT: + case TYPECLASS: + return type1 == type2; + + case TYPEMEMBERPOINTER: + if (type1->type != type2->type || TYPE_MEMBER_POINTER(type1)->qual != TYPE_MEMBER_POINTER(type2)->qual) + return 0; + if (!CTempl_DeduceType1(TYPE_MEMBER_POINTER(type1)->ty1, qual1, TYPE_MEMBER_POINTER(type2)->ty1, qual2, argArray, flag)) + return 0; + type1 = TYPE_MEMBER_POINTER(type1)->ty2; + type2 = TYPE_MEMBER_POINTER(type2)->ty2; + continue; + + case TYPEARRAY: + if (type2->type != TYPEARRAY) + return 0; + type1 = TPTR_TARGET(type1); + type2 = TPTR_TARGET(type2); + continue; + + case TYPEPOINTER: + if (type2->type != TYPEPOINTER || TPTR_QUAL(type1) != TPTR_QUAL(type2)) + return 0; + type1 = TPTR_TARGET(type1); + type2 = TPTR_TARGET(type2); + continue; + + case TYPEFUNC: + if (type1->type != type2->type) + return 0; + + if (CTempl_DeduceType1(TYPE_FUNC(type1)->functype, TYPE_FUNC(type1)->qual, TYPE_FUNC(type2)->functype, TYPE_FUNC(type2)->qual, argArray, flag)) + return CTempl_DeduceFuncType(TYPE_FUNC(type1), TYPE_FUNC(type2), argArray); + + return 0; + + default: + CError_FATAL(1124); + } + } +} + +static Boolean CTempl_DeduceType2(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray) { + while (1) { + switch (type1->type) { + case TYPEPOINTER: + if (type2->type != TYPEPOINTER) + return 0; + if (!CParser_IsSameOrMoreCVQualified(TPTR_QUAL(type2), TPTR_QUAL(type1))) + return 0; + type1 = TPTR_TARGET(type1); + type2 = TPTR_TARGET(type2); + continue; + + case TYPEMEMBERPOINTER: + if (type2->type != TYPEMEMBERPOINTER) + return 0; + if (!CParser_IsSameOrMoreCVQualified(TYPE_MEMBER_POINTER(type2)->qual, TYPE_MEMBER_POINTER(type1)->qual)) + return 0; + if (!CTempl_DeduceType2(TYPE_MEMBER_POINTER(type1)->ty1, qual1, TYPE_MEMBER_POINTER(type2)->ty1, qual2, argArray)) + return 0; + type1 = TYPE_MEMBER_POINTER(type1)->ty2; + type2 = TYPE_MEMBER_POINTER(type2)->ty2; + continue; + + default: + if (CParser_IsSameOrMoreCVQualified(qual2, qual1)) + return CTempl_DeduceType1(type1, qual2, type2, qual2, argArray, 0); + return 0; + } + } +} + +static Boolean CTempl_DeduceType3(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray) { + Boolean flag = 0; + + while (1) { + switch (type1->type) { + case TYPEPOINTER: + flag = 1; + if (type2->type != TYPEPOINTER) + return 0; + if (!CParser_IsSameOrMoreCVQualified(TPTR_QUAL(type2), TPTR_QUAL(type1))) + return 0; + type1 = TPTR_TARGET(type1); + type2 = TPTR_TARGET(type2); + continue; + + case TYPEMEMBERPOINTER: + flag = 1; + if (type2->type != TYPEMEMBERPOINTER) + return 0; + if (!CParser_IsSameOrMoreCVQualified(TYPE_MEMBER_POINTER(type2)->qual, TYPE_MEMBER_POINTER(type1)->qual)) + return 0; + if (!CTempl_DeduceType2(TYPE_MEMBER_POINTER(type1)->ty1, qual1, TYPE_MEMBER_POINTER(type2)->ty1, qual2, argArray)) + return 0; + type1 = TYPE_MEMBER_POINTER(type1)->ty2; + type2 = TYPE_MEMBER_POINTER(type2)->ty2; + continue; + + default: + if (!flag) + return 0; + if (CParser_IsSameOrMoreCVQualified(qual2, qual1)) + return CTempl_DeduceType1(type1, qual2, type2, qual2, argArray, 0); + return 0; + } + } +} + +static Boolean CTempl_DeduceType4(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray) { + if (IS_TYPE_POINTER_ONLY(type1)) { + if (!IS_TYPE_POINTER_ONLY(type2)) + return 0; + + if (!CParser_IsSameOrMoreCVQualified(TPTR_QUAL(type1), TPTR_QUAL(type2))) + return 0; + + type1 = TPTR_TARGET(type1); + type2 = TPTR_TARGET(type2); + } + + if (IS_TYPE_TEMPLATE(type1) && TYPE_TEMPLATE(type1)->dtype == TEMPLDEP_TEMPLATE && IS_TYPE_CLASS(type2)) { + if (CParser_IsSameOrMoreCVQualified(qual1, qual2)) + return CTempl_DeduceTemplateTypeBase( + TYPE_TEMPLATE(type1)->u.templ.templ, + TYPE_TEMPLATE(type1)->u.templ.args, + TEMPL_CLASS_INST(type2), + argArray, + 1); + else + return 0; + } + + return 0; +} + +Boolean CTempl_DeduceType(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray, Boolean flag1, Boolean flag2) { + Boolean flag31; + Boolean flag8; + + flag31 = 0; + flag8 = 1; + + if (flag1 || flag2) { + if (IS_TYPE_REFERENCE(type1)) { + type1 = TPTR_TARGET(type1); + flag31 = 1; + } else { + switch (type2->type) { + case TYPEFUNC: + type2 = CDecl_NewPointerType(type2); + break; + case TYPEARRAY: + type2 = CDecl_NewPointerType(TPTR_TARGET(type2)); + break; + } + + type1 = CParser_RemoveTopMostQualifiers(type1, &qual1); + type2 = CParser_RemoveTopMostQualifiers(type2, &qual2); + } + flag8 = 0; + } + + if (CTempl_DeduceType1(type1, qual1, type2, qual2, argArray, flag8)) + return 1; + + if (flag1 || flag2) { + if (flag31 && CTempl_DeduceType2(type1, qual1, type2, qual2, argArray)) + return 1; + if (CTempl_DeduceType3(type1, qual1, type2, qual2, argArray)) + return 1; + if (flag1 && CTempl_DeduceType4(type1, qual1, type2, qual2, argArray)) + return 1; + } + + return 0; +} + +static Boolean CTempl_TypeNeedsDeduction(Type *type) { + FuncArg *arg; + Boolean result; + + while (1) { + switch (type->type) { + case TYPETEMPLATE: + switch (TYPE_TEMPLATE(type)->dtype) { + case TEMPLDEP_ARGUMENT: + if ( + TYPE_TEMPLATE(type)->u.pid.index >= ctempl_explicitargs_num || + TYPE_TEMPLATE(type)->u.pid.nindex != ctempl_explicitargs_nindex + ) + ctempl_explicitargs_all = 0; + return 1; + + case TEMPLDEP_QUALNAME: + CTempl_TypeNeedsDeduction(TYPE(TYPE_TEMPLATE(type)->u.qual.type)); + return 1; + + case TEMPLDEP_TEMPLATE: + ctempl_explicitargs_all = 0; + return 1; + + case TEMPLDEP_ARRAY: + CTempl_TypeNeedsDeduction(TYPE_TEMPLATE(type)->u.array.type); + ctempl_explicitargs_all = 0; + return 1; + + case TEMPLDEP_QUALTEMPL: + CTempl_TypeNeedsDeduction(TYPE(TYPE_TEMPLATE(type)->u.qualtempl.type)); + ctempl_explicitargs_all = 0; + return 1; + + case TEMPLDEP_BITFIELD: + default: + CError_FATAL(1357); + } + + case TYPEVOID: + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPESTRUCT: + case TYPECLASS: + return 0; + + case TYPEMEMBERPOINTER: + result = 0; + if (CTempl_TypeNeedsDeduction(TYPE_MEMBER_POINTER(type)->ty1)) + result = 1; + if (CTempl_TypeNeedsDeduction(TYPE_MEMBER_POINTER(type)->ty2)) + result = 1; + return result; + + case TYPEPOINTER: + case TYPEARRAY: + type = TPTR_TARGET(type); + continue; + + case TYPEFUNC: + result = 0; + for (arg = TYPE_FUNC(type)->args; arg && arg != &elipsis; arg = arg->next) { + if (CTempl_TypeNeedsDeduction(arg->type)) + result = 1; + } + + if (CTempl_TypeNeedsDeduction(TYPE_FUNC(type)->functype)) + result = 1; + return result; + + default: + CError_FATAL(1389); + } + } +} + +static Boolean CTempl_MatchTemplFunc(Object *object, DeduceInfo *info, FuncArg *args, ENodeList *exprs, Match13 *match13ptr) { + Match13 match13; + int i; + + memclrw(&match13, sizeof(match13)); + + while (1) { + if (!args || args->type == &stvoid) { + if (!exprs) + break; + return 0; + } + + if (args == &elipsis) + break; + if (args == &oldstyle) + break; + + if (!exprs) { + if (args->dexpr) + break; + return 0; + } + + ctempl_explicitargs_nindex = info->x12C; + ctempl_explicitargs_num = info->count; + ctempl_explicitargs_all = 1; + + if (CTempl_TypeNeedsDeduction(args->type)) { + if (!ctempl_explicitargs_all) { + UInt32 cv2; + UInt32 cv1; + Type *type2; + Type *type1; + UInt32 qual2; + UInt32 qual1; + + type1 = args->type; + qual1 = args->qual & (Q_CONST | Q_VOLATILE); + + type2 = exprs->node->rtype; + qual2 = ENODE_QUALS(exprs->node); + + if (IS_TYPE_REFERENCE(type1)) { + type1 = TPTR_TARGET(type1); + cv1 = CParser_GetCVTypeQualifiers(type1, qual1); + cv2 = CParser_GetCVTypeQualifiers(type2, qual2); + if ( + (!(cv1 & Q_CONST) && (cv2 & Q_CONST)) || + (!(cv1 & Q_VOLATILE) && (cv2 & Q_VOLATILE)) + ) + return 0; + + if (!(cv1 & Q_CONST) && !CExpr_IsLValue(exprs->node)) + return 0; + } + + type1 = CParser_RemoveTopMostQualifiers(type1, &qual1); + type2 = CParser_RemoveTopMostQualifiers(type2, &qual2); + + if (ENODE_IS(exprs->node, EOBJREF) && IS_TEMPL_FUNC(exprs->node->data.objref->type)) + return 0; + + if (ENODE_IS(exprs->node, EOBJLIST)) { + NameSpaceObjectList *list; + + for (list = exprs->node->data.objlist.list; list; list = list->next) { + if (list->object->otype == OT_OBJECT && IS_TEMPL_FUNC(OBJECT(list->object)->type)) + break; + } + + if (list) + return 0; + + if (IS_TYPE_FUNC(type2)) + type2 = CDecl_NewPointerType(type2); + } + + ctempl_conversion_deduction = 0; + if (!CTempl_DeduceType(type1, qual1, type2, qual2, info->args, 1, 0)) + return 0; + + if (ctempl_conversion_deduction) + match13.anotherm5.x4++; + else + match13.anotherm5.x0++; + + if (IS_TYPE_POINTER_ONLY(args->type)) + CExpr_MatchCV(type2, qual2, args->type, args->qual, &match13); + + } else { + Type *type; + UInt32 qual; + + type = CTempl_GetSpecifiedType(CTemplTool_GetFuncTempl(object), args->type, args->qual, info->args, &qual); + if (type && !CExpr_MatchAssign(type, qual, exprs->node, &match13)) + return 0; + } + } else { + if (copts.old_argmatch && !CExpr_MatchAssign(args->type, args->qual, exprs->node, &match13)) + return 0; + } + + exprs = exprs->next; + args = args->next; + } + + for (i = 0; i < info->maxCount; i++) { + if (!info->args[i].is_deduced) + return 0; + info->args[i].next = &info->args[i + 1]; + } + info->args[info->maxCount].next = NULL; + + return CExpr_MatchCompare(object, match13ptr, &match13); +} + +void CTempl_FuncMatch(NameSpaceObjectList *list, TemplArg *args, ENodeList *argexprs, Match13 *match13ptr, ENode *expr) { + Object *obj; + Object *success; + Object *object1; + FuncMatchArgs funcMatchArgs; + DeduceInfo info; + DeduceInfo info2; + + object1 = match13ptr->obj; + success = NULL; + while (list) { + obj = OBJECT(list->object); + if ( + obj->otype == OT_OBJECT && + IS_TEMPL_FUNC(obj->type) && + CExpr_GetFuncMatchArgs(obj, argexprs, expr, &funcMatchArgs) && + CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(obj)->params, args, 0) && + CTempl_MatchTemplFunc(obj, &info, funcMatchArgs.args, funcMatchArgs.exprs, match13ptr) + ) + { + info2 = info; + if (info.args == info.argBuffer) + info2.args = info2.argBuffer; + success = obj; + } + list = list->next; + } + + if (success) { + if (match13ptr->list) { + ENodeList *argexpr = argexprs; + int argexprcount = 0; + while (argexpr) { + argexpr = argexpr->next; + argexprcount++; + } + + obj = CTempl_PartialOrdering(match13ptr->obj, match13ptr->list, argexprcount); + if (!obj) { + CError_OverloadedFunctionError(match13ptr->obj, match13ptr->list); + match13ptr->list = NULL; + if (object1) + match13ptr->obj = object1; + else + match13ptr->obj = CTempl_GetCreateFuncInstance(success, info2.args, NULL)->object; + } else { + NameSpaceObjectList mylist; + mylist.next = NULL; + mylist.object = OBJ_BASE(obj); + memclrw(match13ptr, sizeof(Match13)); + CTempl_FuncMatch(&mylist, args, argexprs, match13ptr, expr); + } + } else { + match13ptr->obj = CTempl_GetCreateFuncInstance(success, info2.args, NULL)->object; + } + } else { + match13ptr->obj = object1; + } +} + +static Boolean CExpr_DeduceFromObjList(FuncArg *arg, NameSpaceObjectList *list, DeduceInfo *info) { + TemplArg *savebuf; + NameSpaceObjectList *scan; + SInt32 size; + + for (scan = list; scan; scan = scan->next) { + if (scan->object->otype == OT_OBJECT && IS_TEMPL_FUNC(OBJECT(scan->object)->type)) + return 0; + } + + size = sizeof(TemplArg) * info->maxCount; + savebuf = lalloc(size); + + for (scan = list; scan; scan = scan->next) { + if (scan->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(scan->object)->type)) { + Object *obj; + + memcpy(savebuf, info->args, size); + + obj = OBJECT(scan->object); + if (CTempl_DeduceType( + arg->type, arg->qual & (Q_CONST | Q_VOLATILE), + obj->type, obj->qual, + savebuf, 1, 0 + )) + { + memcpy(info->args, savebuf, size); + return 1; + } + } + } + + return 0; +} + +Object *CTempl_DeduceFromFunctionCall(Object *funcobj, TemplArg *templargs, ENodeList *argexprs) { + DeduceInfo info; + FuncArg *arg; + int i; + + CError_ASSERT(1655, IS_TEMPL_FUNC(funcobj->type)); + + if (CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(funcobj)->params, templargs, 0)) { + arg = TYPE_FUNC(funcobj->type)->args; + if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(funcobj->type))) { + CError_ASSERT(1664, arg); + arg = arg->next; + } + + while (1) { + if (!arg || arg->type == &stvoid) { + if (argexprs) + return NULL; + break; + } + + if (arg == &elipsis) + break; + if (arg == &oldstyle) + break; + + if (!argexprs) { + if (arg->dexpr) + break; + return NULL; + } + + ctempl_explicitargs_nindex = info.x12C; + ctempl_explicitargs_num = info.count; + ctempl_explicitargs_all = 1; + + if (CTempl_TypeNeedsDeduction(arg->type) && !ctempl_explicitargs_all) { + ENode *node = argexprs->node; + + if (ENODE_IS(node, EOBJREF) && IS_TEMPL_FUNC(node->data.objref->type)) + return NULL; + + if (ENODE_IS(node, EOBJLIST)) { + if (!CExpr_DeduceFromObjList(arg, node->data.objlist.list, &info)) + return NULL; + } else { + if (!CTempl_DeduceType( + arg->type, arg->qual & (Q_CONST | Q_VOLATILE), + node->rtype, ENODE_QUALS(node), + info.args, 1, 0)) + return NULL; + } + } + + argexprs = argexprs->next; + arg = arg->next; + } + + for (i = 0; i < info.maxCount; i++) { + if (!info.args[i].is_deduced) + return 0; + info.args[i].next = &info.args[i + 1]; + } + info.args[info.maxCount].next = NULL; + + return CTempl_GetCreateFuncInstance(funcobj, info.args, NULL)->object; + } else { + return NULL; + } +} + +Object *CTempl_DeduceFromConversion(Object *funcobj, Type *type, UInt32 qual) { + DeduceInfo info; + int i; + + CError_ASSERT(1745, IS_TEMPL_FUNC(funcobj->type)); + + if (!CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(funcobj)->params, NULL, 0)) + return NULL; + + ctempl_explicitargs_nindex = info.x12C; + ctempl_explicitargs_num = info.count; + ctempl_explicitargs_all = 1; + + if (!CTempl_TypeNeedsDeduction(TYPE_FUNC(funcobj->type)->functype)) + return NULL; + + if (!CTempl_DeduceType(TYPE_FUNC(funcobj->type)->functype, TYPE_FUNC(funcobj->type)->qual, type, qual, info.args, 0, 1)) + return NULL; + + for (i = 0; i < info.maxCount; i++) { + if (!info.args[i].is_deduced) + return 0; + info.args[i].next = &info.args[i + 1]; + } + info.args[info.maxCount].next = NULL; + + return CTempl_GetCreateFuncInstance(funcobj, info.args, NULL)->object; +} + +static int CTemplFunc_TemplateNestLevel(NameSpace *nspace) { + int level = 0; + + while (nspace) { + if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL_ANY)) + level++; + nspace = nspace->parent; + } + + return level; +} + +static Boolean CTemplFunc_SameFuncType(TypeFunc *a, TypeFunc *b) { + FuncArg *arg1; + FuncArg *arg2; + + CError_ASSERT(1800, IS_TYPE_FUNC(a) && IS_TYPE_FUNC(b)); + + if (!is_typesame(a->functype, b->functype)) + return 0; + + if (a->qual != b->qual) + return 0; + + if ((a->flags & FUNC_CALL_CONV_MASK) != (b->flags & FUNC_CALL_CONV_MASK)) + return 0; + + arg1 = a->args; + if ((a->flags & FUNC_METHOD) && !TYPE_METHOD(a)->is_static) { + CError_ASSERT(1808, arg1); + arg1 = arg1->next; + } + + arg2 = b->args; + if ((b->flags & FUNC_METHOD) && !TYPE_METHOD(b)->is_static) { + CError_ASSERT(1814, arg2); + arg2 = arg2->next; + } + + return is_arglistsame(arg1, arg2); +} + +Object *CTempl_TemplateFunctionCheck(DeclInfo *di, NameSpaceObjectList *nsol) { + TemplArg *arg; + TemplFuncInstance *inst; + Object *object; + + for (arg = di->expltargs; arg; arg = arg->next) { + switch (arg->pid.type) { + case TPT_TYPE: + if (CTemplTool_IsTemplateArgumentDependentType(arg->data.typeparam.type)) + break; + continue; + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(arg->data.paramdecl.expr)) + break; + continue; + default: + CError_FATAL(1844); + } + + break; + } + + if (arg) { + while (nsol) { + object = OBJECT(nsol->object); + if ( + object->otype == OT_OBJECT && + IS_TEMPL_FUNC(object->type) && + CTemplTool_IsSameTemplate(CTemplTool_GetFuncTempl(object)->params, di->expltargs) && + CTemplFunc_SameFuncType(TYPE_FUNC(OBJECT(nsol->object)->type), TYPE_FUNC(di->thetype)) + ) + return OBJECT(nsol->object); + + nsol = nsol->next; + } + } else { + while (nsol) { + object = OBJECT(nsol->object); + if ( + object->otype == OT_OBJECT && + IS_TEMPL_FUNC(object->type) && + (inst = CTempl_DeduceFunc(object, TYPE_FUNC(di->thetype), di->expltargs, NULL, 1)) + ) + { + if (di->x3C) { + if (!(di->qual & Q_INLINE)) { + if (!inst->is_specialized) + inst->object->qual &= ~Q_INLINE; + } else { + inst->object->qual |= Q_INLINE; + } + + if (!inst->is_specialized && inst->is_instantiated) + CError_Error(CErrorStr335); + + if (di->x3C != (CTemplFunc_TemplateNestLevel(inst->object->nspace) + 1)) + CError_Warning(CErrorStr335); + + inst->is_specialized = 1; + di->x3C = 0; + } + + CTemplTool_MergeArgNames(TYPE_FUNC(di->thetype), TYPE_FUNC(inst->object->type)); + di->x38 = CTemplTool_GetFuncTempl(OBJECT(nsol->object)); + return inst->object; + } + nsol = nsol->next; + } + } + + CError_ResetErrorSkip(); + CError_Error(CErrorStr335); + di->x3C = 0; + return NULL; +} diff --git a/compiler_and_linker/FrontEnd/C/CTemplateNew.c b/compiler_and_linker/FrontEnd/C/CTemplateNew.c new file mode 100644 index 0000000..c33534a --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CTemplateNew.c @@ -0,0 +1,1880 @@ +#include "compiler/CTemplateNew.h" +#include "compiler/CBrowse.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInit.h" +#include "compiler/CInline.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/CTemplateClass.h" +#include "compiler/CTemplateTools.h" +#include "compiler/CompilerTools.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" + +TemplClass *ctempl_templates; +TemplateFunction *ctempl_templatefuncs; +TemplStack *ctempl_curinstance; +static jmp_buf ctempl_parseparse; +static Boolean ctempl_scanfuncparams; + +// forward decls +static TemplParam *CTempl_ParseParamList(NameSpace *nspace, UInt8 nindex); +static Boolean CTempl_GenClassInstance(TemplClassInst *inst, Boolean flag); + +void CTempl_Setup(void) { + ctempl_curinstance = NULL; + ctempl_templates = NULL; + ctempl_templatefuncs = NULL; + ctempl_instdepth = 0; + ctempl_scanfuncparams = 0; +} + +void CTempl_Cleanup(void) { +} + +static short CTempl_MemberParseLex(void) { + switch ((tk = lex())) { + case ';': + case '=': + case '{': + case '}': + longjmp(ctempl_parseparse, 1); + } + + return tk; +} + +static void CTempl_MemberParseTemplArgList(void) { + struct { + char ch; + char flag; + } stack[256]; + int pos; + + stack[0].ch = '>'; + stack[0].flag = 1; + pos = 0; + while (1) { + switch (CTempl_MemberParseLex()) { + case '<': + if (stack[pos].flag) { + if (pos >= 255) + longjmp(ctempl_parseparse, 1); + stack[++pos].ch = '>'; + stack[pos].flag = 1; + } + continue; + case '(': + if (pos >= 255) + longjmp(ctempl_parseparse, 1); + stack[++pos].ch = ')'; + stack[pos].flag = 0; + continue; + case '[': + if (pos >= 255) + longjmp(ctempl_parseparse, 1); + stack[++pos].ch = ']'; + stack[pos].flag = 0; + continue; + case '>': + if (!(stack[pos].flag)) + continue; + case ')': + case ']': + break; + default: + continue; + } + + if (tk != stack[pos].ch) + longjmp(ctempl_parseparse, 1); + if (--pos < 0) + break; + } +} + +static Type *CTempl_MemberParseTempl(HashNameNode *name) { + Type *type; + + type = CScope_GetTagType(cscope_current, name); + if (!type || !IS_TEMPL_CLASS(type)) + longjmp(ctempl_parseparse, 1); + + CTempl_MemberParseTemplArgList(); + if (lookahead() != TK_COLON_COLON) + return NULL; + CTempl_MemberParseLex(); + + while (1) { + switch (CTempl_MemberParseLex()) { + case TK_IDENTIFIER: + switch (lookahead()) { + case '(': + case ')': + case ';': + case '=': + case '[': + return type; + case TK_COLON_COLON: + CTempl_MemberParseLex(); + continue; + default: + return NULL; + } + break; + case '~': + case TK_OPERATOR: + return type; + default: + return NULL; + } + } +} + +static Boolean CTempl_ParseTemplateMember(void) { + HashNameNode *name; + SInt32 state; + + CPrep_UnLex(); + CPrep_TokenStreamGetState(&state); + + if (setjmp(ctempl_parseparse) == 0) { + while (1) { + switch (CTempl_MemberParseLex()) { + case TK_IDENTIFIER: + name = tkidentifier; + switch (lookahead()) { + case '<': + CTempl_MemberParseLex(); + if (CTempl_MemberParseTempl(name)) { + CError_FATAL(228); + return 1; + } + break; + case TK_COLON_COLON: + CTempl_MemberParseLex(); + while (1) { + if (CTempl_MemberParseLex() != TK_IDENTIFIER) + break; + if (lookahead() != TK_COLON_COLON) + break; + CTempl_MemberParseLex(); + } + break; + } + break; + case 0: + return 0; + default: + continue; + } + break; + } + + while (1) { + switch (CTempl_MemberParseLex()) { + case TK_IDENTIFIER: + name = tkidentifier; + if (CTempl_MemberParseLex() == '<') { + if (CTempl_MemberParseTempl(name)) { + CError_FATAL(265); + return 1; + } + } + break; + case 0: + return 0; + default: + continue; + } + break; + } + } + + CPrep_TokenStreamSetState(&state); + tk = lex(); + return 0; +} + +static Type *CTempl_ParseTemplArgType(UInt32 *resultQual) { + DeclInfo di; + + memclrw(&di, sizeof(di)); + CParser_GetDeclSpecs(&di, 0); + + if (di.storageclass) + CError_Error(CErrorStr177); + if (di.x48) + CError_Error(CErrorStr121); + + CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_REFERENCE | Q_ALIGNED_MASK)); + + scandeclarator(&di); + if (di.name) + CError_Error(CErrorStr121); + + CTemplTool_CheckTemplArgType(di.thetype); + + *resultQual = di.qual; + return di.thetype; +} + +static ENode *CTempl_ParseTemplArgExpr(Type *type, UInt32 qual) { + ENode *expr; + ENode *copy; + + disallowgreaterthan = 1; + if (copts.old_argmatch) + expr = conv_assignment_expression(); + else + expr = assignment_expression(); + disallowgreaterthan = 0; + + if (type && !CTemplTool_IsTemplateArgumentDependentType(type) && !IS_TYPE_TEMPLDEPEXPR(expr->rtype)) { + expr = argumentpromotion(expr, type, qual, 1); + if (IS_TYPE_POINTER_ONLY(type)) { + if (ENODE_IS(expr, ETYPCON) && ENODE_IS(expr->data.monadic, EINTCONST)) + expr = expr->data.monadic; + if (ENODE_IS(expr, EINTCONST)) + expr->rtype = type; + } + } + + if (!IS_TYPE_TEMPLDEPEXPR(expr->rtype)) { + if (!copts.old_argmatch) + expr = pointer_generation(expr); + + switch (expr->type) { + case EINTCONST: + break; + case EOBJREF: + if (CParser_HasInternalLinkage2(expr->data.objref)) + CError_Error(CErrorStr357); + break; + case EOBJLIST: + CError_Error(CErrorStr199); + expr = nullnode(); + break; + default: + CError_Error(CErrorStr371); + expr = nullnode(); + } + + copy = galloc(sizeof(ENode)); + *copy = *expr; + return copy; + } else { + return CInline_CopyExpression(expr, CopyMode1); + } +} + +static Type *CTempl_ParseTemplArgTempl(TemplParam *params) { + NameResult pr; + + if ( + (tk != TK_IDENTIFIER && tk != TK_COLON_COLON) || + !CScope_ParseDeclName(&pr) || + !pr.type + ) + { + CError_Error(CErrorStr121); + tk = lex(); + return NULL; + } + + if (IS_TEMPL_CLASS(pr.type)) { + if (params && !CTemplTool_EqualParams(params->data.templparam.plist, TEMPL_CLASS(pr.type)->templ__params, 0)) { + CError_Error(CErrorStr235); + tk = lex(); + return NULL; + } + } else { + if (!CTemplTool_IsTemplateArgumentDependentType(pr.type)) + CError_Error(CErrorStr146); + } + + tk = lex(); + return pr.type; +} + +static UInt8 CTempl_GetTemplateNestIndex(NameSpace *nspace) { + UInt8 count = 0; + + while (nspace) { + if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL_ANY)) + count++; + nspace = nspace->parent; + } + + return count; +} + +static TemplParam *CTempl_ParseParam(NameSpace *nspace, TemplParam *param, UInt16 index, UInt8 nindex) { + DeclInfo di; + SInt32 savedState; + short startToken; + + param = galloc(sizeof(TemplParam)); + memclrw(param, sizeof(TemplParam)); + + param->pid.index = index; + param->pid.nindex = nindex; + + CPrep_TokenStreamGetState(&savedState); + + switch ((startToken = tk)) { + case TK_CLASS: + case TK_TYPENAME: + if ((tk = lex()) == TK_IDENTIFIER) { + param->name = tkidentifier; + tk = lex(); + } + + switch (tk) { + case ',': + case '>': + break; + case '=': + tk = lex(); + param->data.typeparam.type = CTempl_ParseTemplArgType(¶m->data.typeparam.qual); + break; + default: + param->name = NULL; + CPrep_TokenStreamSetState(&savedState); + tk = startToken; + goto defaultProc; + } + + param->pid.type = TPT_TYPE; + break; + + case TK_TEMPLATE: + if ((tk = lex()) != '<') { + CError_Error(CErrorStr230); + return NULL; + } + + tk = lex(); + param->data.templparam.plist = CTempl_ParseParamList(nspace, 0); + + if (tk == '>') + tk = lex(); + else + CError_Error(CErrorStr231); + + if (tk == TK_CLASS) + tk = lex(); + else + CError_Error(CErrorStr121); + + if (tk == TK_IDENTIFIER) { + param->name = tkidentifier; + tk = lex(); + } + + if (tk == '=') { + tk = lex(); + param->data.templparam.defaultarg = CTempl_ParseTemplArgTempl(param); + } + + param->pid.type = TPT_TEMPLATE; + break; + + default: + defaultProc: + memclrw(&di, sizeof(di)); + CParser_GetDeclSpecs(&di, 0); + + if (di.storageclass) + CError_Error(CErrorStr177); + + CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_REFERENCE | Q_ALIGNED_MASK)); + + scandeclarator(&di); + + switch (di.thetype->type) { + case TYPEARRAY: + di.thetype = CDecl_NewPointerType(TPTR_TARGET(di.thetype)); + break; + case TYPEFUNC: + di.thetype = CDecl_NewPointerType(di.thetype); + break; + case TYPEMEMBERPOINTER: + CError_Error(CErrorStr190); + di.thetype = TYPE(&stsignedint); + break; + case TYPEINT: + case TYPEENUM: + case TYPETEMPLATE: + case TYPEPOINTER: + break; + default: + CError_Error(CErrorStr229); + di.thetype = TYPE(&stsignedint); + } + + di.thetype = CParser_RemoveTopMostQualifiers(di.thetype, &di.qual); + param->name = di.name; + param->data.paramdecl.type = di.thetype; + param->data.paramdecl.qual = di.qual; + if (tk == '=') { + tk = lex(); + param->data.paramdecl.defaultarg = CTempl_ParseTemplArgExpr(di.thetype, di.qual); + } + + param->pid.type = TPT_NONTYPE; + break; + } + + if (param->name) + CTemplTool_InsertTemplateParameter(nspace, param); + + return param; +} + +static TemplParam *CTempl_ParseParamList(NameSpace *nspace, UInt8 nindex) { + TemplParam *params; + TemplParam **ptr; + TemplParam *param; + TemplParam *scan; + UInt16 index; + + params = NULL; + index = 0; + ptr = ¶ms; + + while (1) { + param = CTempl_ParseParam(nspace, params, index, nindex); + if (!param) + break; + + if (param->name) { + for (scan = params; scan; scan = scan->next) { + if (scan->name == param->name) + CError_Error(CErrorStr122, param->name->name); + } + } + + *ptr = param; + ptr = ¶m->next; + + if (tk != ',') + break; + + tk = lex(); + index++; + } + + if (!params) + CError_Error(CErrorStr229); + + return params; +} + +TemplArg *CTempl_ParseUncheckTemplArgs(TemplParam *params, Boolean is_global) { + TemplArg *args; + TemplArg *last; + UInt16 index; + + if (tk != '<') { + CError_Error(CErrorStr230); + return NULL; + } + + if ((tk = lex()) == '>') + return NULL; + + args = NULL; + index = 0; + while (1) { + if (is_global) { + if (args) { + last->next = galloc(sizeof(TemplArg)); + last = last->next; + } else { + last = galloc(sizeof(TemplArg)); + args = last; + } + } else { + if (args) { + last->next = lalloc(sizeof(TemplArg)); + last = last->next; + } else { + last = galloc(sizeof(TemplArg)); + args = last; + } + } + + last->next = NULL; + + if (!params) { + Type *type; + UInt32 qual; + Boolean flag; + + last->pid.index = index; + last->pid.nindex = 0; + + if ((type = CParser_ParseTypeID(&qual, &flag))) { + if (flag) { + last->data.ttargtype = type; + last->pid.type = TPT_TEMPLATE; + } else { + last->data.typeparam.type = type; + last->data.typeparam.qual = qual; + last->pid.type = TPT_TYPE; + } + } else { + last->data.paramdecl.expr = CTempl_ParseTemplArgExpr(NULL, 0); + last->pid.type = TPT_NONTYPE; + } + } else { + last->pid = params->pid; + switch (last->pid.type) { + case TPT_TYPE: + last->data.typeparam.type = CTempl_ParseTemplArgType(&last->data.typeparam.qual); + break; + case TPT_NONTYPE: + last->data.paramdecl.expr = CTempl_ParseTemplArgExpr(NULL, 0); + break; + case TPT_TEMPLATE: + if (!(last->data.ttargtype = CTempl_ParseTemplArgTempl(params))) + return NULL; + break; + default: + CError_FATAL(674); + } + params = params->next; + } + + if (tk == '>') + return args; + + if (tk != ',') { + CError_Error(CErrorStr116); + return NULL; + } + + tk = lex(); + index++; + } +} + +static TemplArg *CTempl_ParseTemplArgs(TemplClass **resultTempl, TemplArg **resultArgs) { + TemplParam *param; + TemplParam *params; + TemplArg *args; + TemplArg **ptr; + TemplArg *arg; + + params = (*resultTempl)->templ__params; + *resultArgs = NULL; + + if (tk != '<') { + CError_Error(CErrorStr230); + return NULL; + } + + tk = lex(); + + param = params; + args = NULL; + ptr = &args; + + while (param) { + arg = galloc(sizeof(TemplArg)); + memclrw(arg, sizeof(TemplArg)); + + *ptr = arg; + ptr = &arg->next; + + arg->pid = param->pid; + + if (tk != '>') { + switch (arg->pid.type) { + case TPT_TYPE: + arg->data.typeparam.type = CTempl_ParseTemplArgType(&arg->data.typeparam.qual); + break; + + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentType(param->data.paramdecl.type)) { + Type *type; + UInt32 qual; + + type = CTemplTool_DeduceArgDepType(args, param->data.paramdecl.type, param->data.paramdecl.qual, &qual); + arg->data.paramdecl.expr = CTempl_ParseTemplArgExpr(type, qual); + } else { + arg->data.paramdecl.expr = CTempl_ParseTemplArgExpr(param->data.paramdecl.type, param->data.paramdecl.qual); + } + break; + + case TPT_TEMPLATE: + if (!(arg->data.ttargtype = CTempl_ParseTemplArgTempl(param))) + return NULL; + break; + + default: + CError_FATAL(742); + } + + if (tk != '>') { + if (tk != ',') { + CError_Error(CErrorStr232); + return NULL; + } + + if ((tk = lex()) == '>') { + CError_Error(CErrorStr232); + return NULL; + } + } + } else { + switch (arg->pid.type) { + case TPT_TYPE: + if (!param->data.typeparam.type) { + CError_Error(CErrorStr232); + return NULL; + } + + arg->data.typeparam.type = param->data.typeparam.type; + arg->data.typeparam.qual = param->data.typeparam.qual; + + if (CTemplTool_IsTemplateArgumentDependentType(param->data.typeparam.type)) { + TypeDeduce deduce; + memclrw(&deduce, sizeof(deduce)); + deduce.tmclass = *resultTempl; + deduce.inst = NULL; + deduce.params = params; + deduce.args = args; + + arg->data.typeparam.qual = param->data.typeparam.qual; + arg->data.typeparam.type = CTemplTool_DeduceTypeCopy(&deduce, arg->data.typeparam.type, &arg->data.typeparam.qual); + } + break; + + case TPT_NONTYPE: + if (!param->data.paramdecl.defaultarg) { + CError_Error(CErrorStr232); + return NULL; + } + + if (IS_TYPE_TEMPLDEPEXPR(param->data.paramdecl.defaultarg->rtype)) { + TypeDeduce deduce; + memclrw(&deduce, sizeof(deduce)); + deduce.tmclass = *resultTempl; + deduce.inst = NULL; + deduce.params = params; + deduce.args = args; + + arg->data.paramdecl.expr = CInline_CopyExpression( + CTemplTool_DeduceExpr(&deduce, param->data.paramdecl.defaultarg), CopyMode1); + } else { + arg->data.paramdecl.expr = param->data.paramdecl.defaultarg; + } + break; + + case TPT_TEMPLATE: + if (!param->data.templparam.defaultarg) { + CError_Error(CErrorStr232); + return NULL; + } + + if (IS_TEMPL_CLASS(param->data.templparam.defaultarg)) { + arg->data.ttargtype = param->data.templparam.defaultarg; + break; + } + + if (CTemplTool_IsTemplateArgumentDependentType(param->data.templparam.defaultarg)) { + CError_Error(CErrorStr190); + return NULL; + } + + CError_FATAL(817); + + default: + CError_FATAL(820); + } + } + + param = param->next; + } + + if (tk != '>') { + CError_Error(CErrorStr231); + return NULL; + } + + if ((*resultTempl)->pspecs) + return args; + + return args; +} + +Type *CTempl_ParseTemplTemplParam(TypeTemplDep *type) { + TemplArg *args; + Type *newType; + + tk = lex(); + if (!(args = CTempl_ParseUncheckTemplArgs(NULL, 1))) { + CError_Error(CErrorStr121); + return TYPE(&stsignedint); + } + + newType = CDecl_NewTemplDepType(TEMPLDEP_QUALTEMPL); + TYPE_TEMPLATE(newType)->u.qualtempl.type = type; + TYPE_TEMPLATE(newType)->u.qualtempl.args = args; + return newType; +} + +Type *CTempl_ClassGetType(TemplClass *templ) { + TemplClass *owner; + TemplArg *ownerArgs; + TemplArg *args; + Type *type; + + owner = templ; + if (templ->pspec_owner) + owner = templ->pspec_owner; + + if (!(args = CTempl_ParseTemplArgs(&owner, &ownerArgs))) + return &stvoid; + + if ((type = CTemplTool_IsDependentTemplate(owner, args))) + return type; + + return TYPE(CTemplClass_GetInstance(owner, args, ownerArgs)); +} + +static void CTempl_SetupClassParamNameSpace(DeclFucker *what_is_this, TypeClass *tclass) { + cscope_current = tclass->nspace; +} + +Boolean CTempl_IsQualifiedMember(DeclInfo *di, Type *type, NameSpace **resultnspace) { + if ( + TYPE_TEMPLATE(type)->dtype == TEMPLDEP_QUALNAME && + (type = CTemplTool_GetSelfRefTemplate(TYPE(TYPE_TEMPLATE(type)->u.qual.type))) + ) + { + *resultnspace = TYPE_CLASS(type)->nspace; + CError_ASSERT(948, di->fucker34 && (*resultnspace)->theclass); + + CTempl_SetupClassParamNameSpace(di->fucker34, (*resultnspace)->theclass); + di->fucker34 = NULL; + return 1; + } + + return 0; +} + +static void *CTempl_ParseMemberFunction(int unk1, int unk2, int unk3, Object *func) { + // no idea what should've been here, it's not called + + CError_ASSERT(974, TYPE_FUNC(func->type)->flags & FUNC_METHOD); + + return NULL; +} + +static void CTempl_ParseMember(TemplParam *params, TemplClass *templ, DeclInfo *di, SInt32 *startOffset) { + Object *object; + NameSpaceObjectList *nsol; + TokenStream stream; + CPrepFileInfo *file; + SInt32 offset; + Boolean saveForceLoc; + TemplateMember *member; + + if (templ->theclass.flags & CLASS_IS_TEMPL) + di->thetype = CTemplTool_ResolveMemberSelfRefs(templ, di->thetype, &di->qual); + + if (IS_TYPE_FUNC(di->thetype)) { + Boolean flag; + if (!(object = CDecl_GetFunctionObject(di, NULL, &flag, 0))) { + CError_Error(CErrorStr140, di->name->name); + return; + } + + if (tk != '{' && tk != TK_TRY && tk != ':') { + if (tk != ';') + CError_Error(CErrorStr123); + else + tk = lex(); + return; + } + + if ( + (TYPE_FUNC(object->type)->flags & FUNC_DEFINED) && + (!(TYPE_FUNC(object->type)->flags & FUNC_IS_TEMPL) || object->u.func.u.templ->instances) + ) + CError_Error(CErrorStr333, object); + + TYPE_FUNC(object->type)->flags |= FUNC_IS_TEMPL_INSTANCE | FUNC_DEFINED; + + CPrep_StreamGetBlock(&stream, NULL, 1); + saveForceLoc = gForceSourceLoc; + gForceSourceLoc = 1; + CPrep_BrowserFilePosition(&file, &offset); + gForceSourceLoc = saveForceLoc; + + if (file && file->recordbrowseinfo && *startOffset >= 0 && offset > *startOffset) + CBrowse_NewFunction(object, file, file, *startOffset, offset + 1); + } else { + if (!(nsol = CScope_GetLocalObject(templ->theclass.nspace, di->name))) { + CError_Error(CErrorStr140, di->name->name); + return; + } + + object = OBJECT(nsol->object); + if (object->otype != OT_OBJECT) { + CError_Error(CErrorStr122, di->name->name); + return; + } + + if ( + !is_typesame(di->thetype, object->type) || + (object->qual & (Q_CONST | Q_VOLATILE | Q_PASCAL)) != (di->qual & (Q_CONST | Q_VOLATILE | Q_PASCAL)) + ) + { + CError_Error(CErrorStr249, CError_GetObjectName(object), object->type, object->qual, di->thetype, di->qual); + return; + } + + CError_ASSERT(1070, object->datatype == DDATA); + + CPrep_StreamGetSemicolon(&stream, NULL); + } + + if (stream.tokens) { + if (IS_TEMPL_FUNC(object->type) != 0) { + if (!CTemplTool_EqualParams(object->u.func.u.templ->params, params, 0)) + CError_Error(CErrorStr235); + + object->u.func.u.templ->stream = stream; + } else { + if (!(templ->theclass.flags & CLASS_IS_TEMPL)) { + CError_Error(CErrorStr190); + return; + } + + member = CTemplClass_DefineMember(templ, object, &cparser_fileoffset, &stream); + if (templ->templ__params) { + if (!CTemplTool_EqualParams(templ->templ__params, params, 0)) { + CError_Error(CErrorStr235); + return; + } + + member->params = params; + } + } + } +} + +static TemplateFunction *CTempl_DeclareTemplateFunction(DeclInfo *di, TemplParam *params, TypeClass *tclass, AccessType access, Boolean flag) { + TemplateFunction *templ; + Object *object; + + if (tclass) { + CError_ASSERT(1122, cscope_current->theclass); + di->thetype = TYPE(CDecl_MakeTypeMemberFunc(TYPE_FUNC(di->thetype), cscope_current->theclass, flag)); + } else { + access = ACCESSPUBLIC; + } + + templ = galloc(sizeof(TemplateFunction)); + memclrw(templ, sizeof(TemplateFunction)); + + templ->next = ctempl_templatefuncs; + ctempl_templatefuncs = templ; + + templ->params = params; + templ->name = di->name; + templ->deftoken = symdecltoken; + + object = CParser_NewFunctionObject(NULL); + object->access = access; + object->name = di->name; + object->u.func.linkname = CParser_GetUniqueName(); + object->type = di->thetype; + object->qual = di->qual | Q_MANGLE_NAME; + object->sclass = di->storageclass; + TYPE_FUNC(object->type)->flags |= FUNC_IS_TEMPL; + object->u.func.u.templ = templ; + + if (di->qual & Q_INLINE) + object->sclass = TK_STATIC; + + templ->tfunc = object; + CScope_AddObject(cscope_current, di->name, OBJ_BASE(object)); + + return templ; +} + +static void CTempl_ParseTemplateFunction(TemplateFunction *templ, TypeClass *tclass, SInt32 *startOffset) { + Object *object; + CPrepFileInfo *file; + SInt32 offset; + Boolean saveForceLoc; + + object = templ->tfunc; + + if (tk == '{' || tk == ':' || tk == TK_TRY) { + if (tclass) { + object->qual |= Q_INLINE; + object->sclass = TK_STATIC; + } + + if (TYPE_FUNC(object->type)->flags & FUNC_DEFINED) + CError_Error(CErrorStr333, object); + + TYPE_FUNC(object->type)->flags |= FUNC_DEFINED | FUNC_IS_TEMPL_INSTANCE; + + CPrep_StreamGetBlock(&templ->stream, NULL, 0); + + if (lookahead() == ';') + tk = lex(); + else + tk = ';'; + + saveForceLoc = gForceSourceLoc; + gForceSourceLoc = 1; + CPrep_BrowserFilePosition(&file, &offset); + gForceSourceLoc = saveForceLoc; + + if (file && *startOffset >= 0 && offset > *startOffset) { + templ->srcfile = file; + templ->startoffset = *startOffset; + templ->endoffset = offset + 1; + if (cparamblkptr->browseoptions.recordTemplates && file->recordbrowseinfo) + CBrowse_NewTemplateFunc(templ); + } + + } else { + if (tk != ';') + CError_Error(CErrorStr121); + } +} + +static HashNameNode *CTempl_FindConversionFuncName(TypeClass *tclass, Type *type, UInt32 qual) { + Object *object; + CScopeObjectIterator iter; + + CScope_InitObjectIterator(&iter, tclass->nspace); + do { + if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) + return NULL; + } while ( + !IS_TYPE_FUNC(object->type) || + !(TYPE_FUNC(object->type)->flags & FUNC_CONVERSION) || + (TYPE_FUNC(object->type)->qual & (Q_CONST | Q_VOLATILE)) != (qual & (Q_CONST | Q_VOLATILE)) || + !is_typesame(TYPE_FUNC(object->type)->functype, type) + ); + + return object->name; +} + +static void CTempl_ParseConversionFunctionTemplate(DeclInfo *di, DeclFucker *what_is_this, TemplParam *params, TypeClass *tclass, SInt32 *startOffset, AccessType access) { + tk = lex(); + if (!tclass) { + CError_Error(CErrorStr121); + return; + } + + tclass->flags = tclass->flags | CLASS_IS_CONVERTIBLE; + CError_QualifierCheck(di->qual & ~Q_INLINE); + + conversion_type_name(di); + CDecl_NewConvFuncType(di); + + if (cscope_current->is_templ) { + CError_ASSERT(1260, cscope_current == what_is_this->nspace); + cscope_current = what_is_this->nspace->parent; + } + + CTempl_ParseTemplateFunction(CTempl_DeclareTemplateFunction(di, params, tclass, access, 0), tclass, startOffset); +} + +static void CTempl_ParseFunctionOrMemberTemplate(DeclFucker *what_is_this, TemplParam *params, TypeClass *tclass, SInt32 *startOffset, AccessType access, Boolean mysteryFlag) { + NameSpaceObjectList *nsol; + Object *object; + TemplParam *param; + TemplateFunction *templfunc; + Boolean disallowCVFlag; + TypeClass *tclass2; + Type *type; + UInt32 qual; + DeclInfo di; + + for (param = params; param; param = param->next) { + switch (param->pid.type) { + case TPT_TYPE: + if (param->data.typeparam.type) { + CError_Error(CErrorStr378); + param->data.typeparam.type = NULL; + } + break; + case TPT_NONTYPE: + if (param->data.paramdecl.defaultarg) { + CError_Error(CErrorStr378); + param->data.paramdecl.defaultarg = NULL; + } + break; + case TPT_TEMPLATE: + if (param->data.templparam.defaultarg) { + CError_Error(CErrorStr378); + param->data.templparam.defaultarg = NULL; + } + break; + default: + CError_FATAL(1317); + } + } + + disallowCVFlag = 0; + ctempl_scanfuncparams = 1; + + memclrw(&di, sizeof(di)); + di.x51 = mysteryFlag; + + if (tk == TK_OPERATOR) { + CTempl_ParseConversionFunctionTemplate(&di, what_is_this, params, tclass, startOffset, access); + return; + } + + CParser_GetDeclSpecs(&di, 1); + if (tk == ';' && IS_TEMPL_CLASS(di.thetype)) + return; + + if (di.x10 || di.x14) { + TypeFunc *tfunc; + + if (di.x14) { + di.x10 = OBJECT(di.x14->object); + CError_ASSERT(1342, di.x10->otype == OT_OBJECT); + } + + CError_ASSERT(1344, IS_TYPE_FUNC(di.x10->type)); + + tfunc = TYPE_FUNC(di.x10->type); + if (tfunc->flags & FUNC_CONVERSION) { + di.thetype = tfunc->functype; + di.qual |= tfunc->qual; + di.nspace = di.x10->nspace; + di.name = di.x10->name; + } else if (tfunc->flags & FUNC_IS_CTOR) { + di.thetype = TYPE(&void_ptr); + di.nspace = di.x10->nspace; + di.name = di.x10->name; + } else { + CError_Error(CErrorStr121); + return; + } + + if ((tk = lex()) == '(') { + tk = lex(); + CDecl_ParseDirectFuncDecl(&di); + if (IS_TYPE_FUNC(di.thetype)) + goto skipPastStuff; + } else { + CError_Error(CErrorStr114); + } + } + + if (di.storageclass) { + if (tclass) { + if (di.storageclass == TK_STATIC) + disallowCVFlag = 1; + else + CError_Error(CErrorStr177); + di.storageclass = 0; + } else { + if (di.storageclass != TK_STATIC && di.storageclass != TK_EXTERN) { + CError_Error(CErrorStr177); + di.storageclass = 0; + } + } + } + + CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_ASM | Q_PASCAL | Q_INLINE | Q_EXPLICIT | Q_20000 | Q_WEAK | Q_ALIGNED_MASK)); + + if (tk == TK_OPERATOR && di.x4A) { + CTempl_ParseConversionFunctionTemplate(&di, what_is_this, params, tclass, startOffset, access); + return; + } + + if (!di.x53) { + if (tclass && IS_TYPE_CLASS(di.thetype) && TYPE_CLASS(di.thetype) == tclass && tk == '(') { + CError_ASSERT(1418, cscope_current == tclass->nspace); + CError_QualifierCheck(di.qual & ~(Q_INLINE | Q_EXPLICIT)); + + di.thetype = TYPE(&void_ptr); + di.x4B = 1; + + tk = lex(); + CDecl_ParseDirectFuncDecl(&di); + + if (IS_TYPE_FUNC(di.thetype)) { + if (TYPE_FUNC(di.thetype)->args && !TYPE_FUNC(di.thetype)->args->next && TYPE_FUNC(di.thetype)->args->type == TYPE(tclass)) { + CError_Error(CErrorStr239); + TYPE_FUNC(di.thetype)->args = NULL; + } + + if (tclass->flags & CLASS_HAS_VBASES) + CDecl_AddArgument(TYPE_FUNC(di.thetype), TYPE(&stsignedshort)); + + TYPE_FUNC(di.thetype)->flags |= FUNC_IS_CTOR; + di.name = constructor_name_node; + + what_is_this->nspace->tparams = NULL; + + CTempl_ParseTemplateFunction( + CTempl_DeclareTemplateFunction(&di, params, tclass, access, disallowCVFlag), + tclass, startOffset); + + return; + } else { + CError_Error(CErrorStr241); + } + } + + if (IS_TYPE_TEMPLATE(di.thetype)) { + if ( + tk == '(' && + TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_QUALNAME && + (tclass2 = TYPE_CLASS(CTemplTool_GetSelfRefTemplate(TYPE(TYPE_TEMPLATE(di.thetype)->u.qual.type)))) && + TYPE_TEMPLATE(di.thetype)->u.qual.name == tclass2->classname + ) + { + if (tclass) + CError_Error(CErrorStr229); + + di.thetype = TYPE(&void_ptr); + di.x4B = 1; + + CTempl_SetupClassParamNameSpace(what_is_this, tclass2); + + tk = lex(); + CDecl_ParseDirectFuncDecl(&di); + + if (IS_TYPE_FUNC(di.thetype)) { + di.name = constructor_name_node; + if (tclass2->flags & CLASS_HAS_VBASES) + CDecl_AddArgument(TYPE_FUNC(di.thetype), TYPE(&stsignedshort)); + + TYPE_FUNC(di.thetype)->flags |= FUNC_IS_CTOR; + CTempl_ParseMember(params, TEMPL_CLASS(tclass2), &di, startOffset); + } else { + CError_Error(CErrorStr241); + } + + return; + } + + if ( + tk == TK_COLON_COLON && + TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_TEMPLATE && + (tclass2 = TYPE_CLASS(CTemplTool_GetSelfRefTemplate(di.thetype))) + ) + { + if (tclass) + CError_Error(CErrorStr229); + + if ((tk = lex()) == '~') { + if ( + (tk = lex()) != TK_IDENTIFIER || + tkidentifier != tclass2->classname || + (tk = lex()) != '(' + ) + { + if (tk == '<') { + DeclInfo di2; + + CPrep_UnLex(); + tk = TK_IDENTIFIER; + tkidentifier = tclass2->classname; + + memclrw(&di2, sizeof(di2)); + CParser_GetDeclSpecs(&di2, 0); + if (tk != '(') + CError_Error(CErrorStr241); + + if (di2.thetype != TYPE(tclass2) && (!IS_TYPE_TEMPLATE(di2.thetype) || CTemplTool_IsTemplate( + TYPE_TEMPLATE(di2.thetype)) != TEMPL_CLASS(tclass2))) + { + CError_Error(CErrorStr241); + } + } else { + CError_Error(CErrorStr241); + } + } + + di.thetype = TYPE(&void_ptr); + + CTempl_SetupClassParamNameSpace(what_is_this, tclass2); + tk = lex(); + CDecl_ParseDirectFuncDecl(&di); + + if (IS_TYPE_FUNC(di.thetype)) { + if (tclass2->sominfo) + di.qual |= Q_VIRTUAL; + else + CDecl_AddArgument(TYPE_FUNC(di.thetype), TYPE(&stsignedshort)); + + di.name = destructor_name_node; + TYPE_FUNC(di.thetype)->flags |= FUNC_IS_DTOR; + CTempl_ParseMember(params, TEMPL_CLASS(tclass2), &di, startOffset); + } else { + CError_Error(CErrorStr241); + } + } else if (tk == TK_OPERATOR) { + CTempl_SetupClassParamNameSpace(what_is_this, tclass2); + if (CMangler_OperatorName((tk = lex()))) { + CError_Error(CErrorStr349); + return; + } + + CError_QualifierCheck(di.qual & ~(Q_INLINE | Q_VIRTUAL)); + conversion_type_name(&di); + + type = di.thetype; + qual = di.qual; + CDecl_NewConvFuncType(&di); + + if (CTemplTool_IsTemplateArgumentDependentType(type)) { + di.name = CTempl_FindConversionFuncName(tclass2, type, qual); + if (!di.name) { + CError_Error(CErrorStr150, "conversion function"); + return; + } + } + CTempl_ParseMember(params, TEMPL_CLASS(tclass2), &di, startOffset); + } else { + CError_Error(CErrorStr121); + } + + return; + } + + if (TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_QUALNAME && !di.x49) + CError_Warning(CErrorStr355); + } + } + + di.x30 = params; + di.fucker34 = what_is_this; + scandeclarator(&di); + ctempl_scanfuncparams = 0; + +skipPastStuff: + if (cscope_current->is_templ) { + CError_ASSERT(1589, cscope_current == what_is_this->nspace); + what_is_this->nspace->tparams = NULL; + } + + if (!di.name) { + CError_Error(CErrorStr229); + return; + } + + if (di.nspace) { + if (di.nspace->theclass) { + if (tclass) + CError_Error(CErrorStr229); + CTempl_ParseMember(params, TEMPL_CLASS(di.nspace->theclass), &di, startOffset); + return; + } + + if (!IS_TYPE_FUNC(di.thetype)) { + CError_Error(CErrorStr229); + return; + } + + CScope_FindName(di.nspace, di.name); + } else { + if (!IS_TYPE_FUNC(di.thetype)) { + CError_Error(CErrorStr229); + return; + } + + CScope_FindName(cscope_current, di.name); + } + + nsol = CScope_FindName(di.nspace ? di.nspace : cscope_current, di.name); + while (nsol) { + object = OBJECT(nsol->object); + if (object->otype == OT_OBJECT && IS_TEMPL_FUNC(object->type)) { + templfunc = CTemplTool_GetFuncTempl(object); + if (CTemplTool_EqualParams(templfunc->params, params, 0) && is_typesame(object->type, di.thetype)) { + if (tk != ';' && templfunc->stream.tokens) + CError_Error(CErrorStr234); + + if (tk == '{' || tk == ':' || tk == TK_TRY) + CError_ASSERT(1654, CTemplTool_EqualParams(templfunc->params, params, 1)); + + if (di.qual & Q_INLINE) + object->qual |= Q_INLINE; + TYPE_FUNC(object->type)->args = TYPE_FUNC(di.thetype)->args; + break; + } + } + nsol = nsol->next; + } + + if (!nsol) { + if (di.nspace) + CError_Error(CErrorStr229); + templfunc = CTempl_DeclareTemplateFunction(&di, params, tclass, access, disallowCVFlag); + } + + CTempl_ParseTemplateFunction(templfunc, tclass, startOffset); +} + +static void CTempl_ExplicitInstantiation(void) { + Boolean flag; + short saveToken; + Object *object; + DeclInfo di; + + memclrw(&di, sizeof(di)); + di.x51 = 1; + flag = 1; + + if (tk == TK_IDENTIFIER && !strcmp(tkidentifier->name, "__dont_instantiate")) { + flag = 0; + tk = lex(); + } + + switch (tk) { + case TK_STRUCT: + case TK_UNION: + case TK_CLASS: + memclrw(&di, sizeof(di)); + CParser_GetDeclSpecs(&di, 0); + if (tk == ';') { + if (IS_TEMPL_CLASS_INST(di.thetype)) { + CTempl_InstantiateTemplateClass(TYPE_CLASS(di.thetype)); + if ((TYPE_CLASS(di.thetype)->flags & CLASS_COMPLETED) && !(TYPE_CLASS(di.thetype)->eflags & CLASS_EFLAGS_IMPORT)) { + if (flag) + CTempl_GenClassInstance(TEMPL_CLASS_INST(di.thetype), 1); + else + TEMPL_CLASS_INST(di.thetype)->is_extern = 1; + } else { + CError_Error(CErrorStr136, TYPE_CLASS(di.thetype), 0); + } + } else { + CError_Error(CErrorStr238); + } + return; + } + break; + default: + memclrw(&di, sizeof(di)); + CParser_GetDeclSpecs(&di, 0); + } + + di.x51 = 1; + + scandeclarator(&di); + + saveToken = tk; + + di.x38 = NULL; + if ( + di.name && + IS_TYPE_FUNC(di.thetype) && + (object = CDecl_GetFunctionObject(&di, di.nspace, NULL, 1)) && + IS_TYPE_FUNC(object->type) && + object->u.func.inst && + di.x38 + ) + { + if (!flag) + object->u.func.inst->is_extern = 1; + else + CTempl_GenFuncInstance(di.x38, object->u.func.inst, 1); + } else { + CError_Error(CErrorStr238); + } + + if (saveToken != ';') + CError_Error(CErrorStr123); +} + +static void CTempl_ExplicitSpecialization(void) { + Boolean flag; + TemplParam *params; + int counter; + DeclFucker what_is_this; + DeclInfo di; + + flag = 0; + counter = 1; + while (tk == TK_TEMPLATE) { + if ((tk = lex()) != '<') { + CError_Error(CErrorStr230); + break; + } + + if ((tk = lex()) != '>') { + if (!flag) { + what_is_this.nspace = cscope_current; + what_is_this.mystery4 = NULL; + cscope_current->tparams = NULL; + flag = 1; + } + + params = CTempl_ParseParamList(what_is_this.nspace, counter); + if (tk != '>') + CError_Error(CErrorStr231); + } else { + if (flag) + CError_Error(CErrorStr335); + } + + counter++; + tk = lex(); + } + + if (flag) { + SInt32 startOffset = -1; + CTempl_ParseFunctionOrMemberTemplate(&what_is_this, params, NULL, &startOffset, ACCESSPUBLIC, 1); + return; + } + + memclrw(&di, sizeof(di)); + di.x3C = counter; + di.x51 = 1; + CParser_GetDeclSpecs(&di, 1); + + if (tk == ';') { + if (IS_TEMPL_CLASS_INST(di.thetype)) + TEMPL_CLASS_INST(di.thetype)->is_specialized = 1; + else + CError_Error(CErrorStr335); + } else { + scandeclaratorlist(&di); + if ((tk != ';' && tk != '}') || di.x3C) + CError_Error(CErrorStr335); + } + + if (flag) + what_is_this.nspace->tparams = NULL; +} + +void CTempl_Parse(TemplClass *templ, AccessType access) { + TemplParam *params; + UInt8 i; + short mode; + Boolean flag; + UInt8 classDeclSpec; + SInt32 startOffset; + SInt32 savedState; + CScopeSave savedScope; + DeclFucker what_is_this; + + startOffset = CPrep_BrowserFileOffset(); + CScope_GetScope(&savedScope); + + if ((tk = lex()) != '<') { + if (templ) + CError_Error(CErrorStr238); + CTempl_ExplicitInstantiation(); + CScope_RestoreScope(&savedScope); + return; + } + + if ((tk = lex()) == '>') { + if (templ) + CError_Error(CErrorStr335); + tk = lex(); + CTempl_ExplicitSpecialization(); + CScope_RestoreScope(&savedScope); + return; + } + + what_is_this.nspace = cscope_current; + what_is_this.mystery4 = NULL; + cscope_current->tparams = NULL; + i = CTempl_GetTemplateNestIndex(what_is_this.nspace); + + while (1) { + params = CTempl_ParseParamList(what_is_this.nspace, i); + if (tk != '>') + CError_Error(CErrorStr231); + + if ((tk = lex()) != TK_TEMPLATE) + break; + + if (templ) + CError_Error(CErrorStr121); + + if ((tk = lex()) != '<') + CError_Error(CErrorStr230); + else + tk = lex(); + + i++; + } + + switch (tk) { + case TK_CLASS: + mode = CLASS_MODE_CLASS; + break; + case TK_UNION: + mode = CLASS_MODE_UNION; + break; + case TK_STRUCT: + mode = CLASS_MODE_STRUCT; + break; + default: + mode = -1; + } + + if (mode >= 0) { + classDeclSpec = 0; + flag = 0; + + CPrep_TokenStreamGetState(&savedState); + if ((tk = lex()) == TK_UU_DECLSPEC) + CDecl_ParseClassDeclSpec(&classDeclSpec); + + if (tk == TK_IDENTIFIER) { + if ((tk = lex()) == '<') { + if (setjmp(ctempl_parseparse) == 0) { + CTempl_MemberParseTemplArgList(); + flag = 1; + tk = lex(); + } + } + + switch (tk) { + case ':': + case ';': + case '{': + CPrep_TokenStreamSetCurState(&savedState); + if (flag) + CTemplClass_ParsePartialSpecialization(&what_is_this, params, mode, &startOffset); + else + CTemplClass_ParseClass(&what_is_this, params, mode, &startOffset); + goto done; + } + } + + CPrep_TokenStreamSetCurState(&savedState); + } + + CTempl_ParseFunctionOrMemberTemplate(&what_is_this, params, TYPE_CLASS(templ), &startOffset, access, 0); + +done: + what_is_this.nspace->tparams = NULL; + CScope_RestoreScope(&savedScope); +} + +void CTempl_ParseInstanceScopeFunction(Object *funcobj, TemplClassInst *inst, TypeClass *tclass) { + TemplParam *params; + NameSpace *nspace; + TemplateMember *member; + Object *parent; + DeclInfo di; + CScopeSave savedScope; + TemplStack stack; + + params = inst->templ->templ__params; + if (funcobj->qual & Q_IS_TEMPLATED) { + for (member = CTemplClass_GetMasterTemplate(inst->templ)->members, parent = OBJECT_TEMPL(funcobj)->parent; member; member = member->next) { + if (member->object == parent) { + if (member->params) + params = member->params; + break; + } + } + } + + CTemplTool_PushInstance(&stack, NULL, funcobj); + nspace = CTemplTool_InsertTemplateArgumentNameSpace(params, inst, &savedScope); + if (tclass) + cscope_current = tclass->nspace; + + memclrw(&di, sizeof(di)); + CFunc_ParseFuncDef(funcobj, &di, NULL, 0, 0, tclass ? cscope_current : NULL); + + CTemplTool_RemoveTemplateArgumentNameSpace(nspace, inst, &savedScope); + CTemplTool_PopInstance(&stack); +} + +Boolean CTempl_GenFuncInstance(TemplateFunction *templ, TemplFuncInstance *inst, Boolean flag) { + Boolean saveDebugInfo; + NameSpace *nspace; + SInt32 streamState; + TemplStack stack; + DeclInfo di; + + if (!flag && copts.no_implicit_templates && inst->object->sclass != TK_STATIC) + return 0; + + if (inst->is_extern && !flag) + return 0; + + while (1) { + if (templ->stream.tokens) + break; + if (!templ->unk4) + break; + templ = templ->unk4; + } + + if (!templ->stream.tokens) { + if (flag) { + CError_SetErrorToken(&templ->deftoken); + CError_Error(CErrorStr233, inst->object); + } + return 0; + } + + inst->is_instantiated = 1; + + CPrep_StreamInsert(&templ->stream, &streamState); + + saveDebugInfo = copts.filesyminfo; + if (copts.nosyminline || !templ->deftoken.tokenfile) + copts.filesyminfo = 0; + + CError_ASSERT(2112, (tk = lex()) == '{' || tk == ':' || tk == TK_TRY); + + symdecltoken = *CPrep_CurStreamElement(); + + if (copts.filesyminfo) { + CPrep_NewFileOffsetInfo(&cparser_fileoffset, &templ->deftoken); + symdecloffset = cparser_fileoffset.tokenline; + } + + if (inst->object->sclass != TK_STATIC) + inst->object->qual |= Q_WEAK; + + memclrw(&di, sizeof(di)); + di.file2 = templ->srcfile; + di.file = CPrep_BrowserCurrentFile(); + di.sourceoffset = templ->startoffset; + + CTemplTool_PushInstance(&stack, NULL, inst->object); + CTemplTool_MergeArgNames(TYPE_FUNC(templ->tfunc->type), TYPE_FUNC(inst->object->type)); + + nspace = CTemplTool_SetupTemplateArgumentNameSpace(templ->params, inst->args, 0); + nspace->parent = inst->object->nspace; + inst->object->nspace = nspace; + + CTemplTool_SetupOuterTemplateArgumentNameSpace(nspace); + CFunc_ParseFuncDef(inst->object, &di, NULL, 0, 0, nspace); + CTemplTool_RemoveOuterTemplateArgumentNameSpace(nspace); + + inst->object->nspace = nspace->parent; + + CTemplTool_PopInstance(&stack); + + CPrep_StreamRemove(&templ->stream, &streamState); + copts.filesyminfo = saveDebugInfo; + + if (di.file->recordbrowseinfo) + CBrowse_NewFunction(inst->object, di.file, di.file2, di.sourceoffset, templ->endoffset); + + return 1; +} + +void CTempl_InstantiateMember(TemplClass *templ, TemplClassInst *inst, TemplateMember *tmemb, Object *object, Boolean flag) { + Boolean saveDebugInfo; + NameSpace *nspace; + Boolean saveSourceLoc; + + DeclInfo di; + CScopeSave savedScope; + TemplStack stack; + SInt32 savedState; + + if (!flag && copts.no_implicit_templates) + return; + + CTemplTool_PushInstance(&stack, NULL, object); + nspace = CTemplTool_InsertTemplateArgumentNameSpace( + tmemb->params ? tmemb->params : templ->templ__params, inst, &savedScope); + CPrep_StreamInsert(&tmemb->stream, &savedState); + + saveSourceLoc = gForceSourceLoc; + gForceSourceLoc = 1; + symdecltoken.tokenoffset = tmemb->startoffset; + tk = lex(); + + symdecltoken = *CPrep_CurStreamElement(); + + saveDebugInfo = copts.filesyminfo; + if (copts.filesyminfo) { + CPrep_NewFileOffsetInfo(&cparser_fileoffset, &symdecltoken); + symdecloffset = cparser_fileoffset.tokenline; + } + + if (object->sclass != TK_STATIC) + object->qual |= Q_WEAK; + + memclrw(&di, sizeof(di)); + di.file2 = tmemb->srcfile; + di.file = CPrep_BrowserCurrentFile(); + di.sourceoffset = tmemb->startoffset; + + switch (object->datatype) { + case DFUNC: + case DVFUNC: + CTemplTool_MergeArgNames(TYPE_FUNC(tmemb->object->type), TYPE_FUNC(object->type)); + CFunc_ParseFuncDef(object, &di, TYPE_CLASS(inst), 0, 0, NULL); + break; + + case DDATA: + CDecl_CompleteType(object->type); + CInit_InitializeData(object); + break; + + default: + CError_FATAL(2227); + } + + CTemplTool_PopInstance(&stack); + CTemplTool_RemoveTemplateArgumentNameSpace(nspace, inst, &savedScope); + CPrep_StreamRemove(&tmemb->stream, &savedState); + copts.filesyminfo = saveDebugInfo; + gForceSourceLoc = saveSourceLoc; +} + +static Boolean CTempl_GenMemberInstance(TemplClassInst *inst, ObjectTemplated *objtempl, Boolean flag) { + TemplateMember *member; + Object *parent = objtempl->parent; + + for (member = CTemplClass_GetMasterTemplate(inst->templ)->members; member; member = member->next) { + if (member->object == parent) { + CTempl_InstantiateMember(inst->templ, inst, member, OBJECT(objtempl), flag); + return 1; + } + } + + if (flag) + CError_Warning(CErrorStr233, objtempl); + return 0; +} + +static Boolean CTempl_GenClassInstance(TemplClassInst *inst, Boolean flag) { + Object *object; + Boolean result; + CScopeObjectIterator iter; + + result = 0; + + if (!flag && copts.no_implicit_templates) + return 0; + if (!flag && inst->is_extern) + return 0; + + CScope_InitObjectIterator(&iter, inst->theclass.nspace); + while ((object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) { + if (IS_TYPE_FUNC(object->type) && object->datatype != DALIAS) { + if ( + (flag || (object->flags & OBJECT_FLAGS_2)) && + !(TYPE_FUNC(object->type)->flags & (FUNC_DEFINED | FUNC_AUTO_GENERATED)) && + CTempl_GenMemberInstance(inst, OBJECT_TEMPL(object), flag) && + (TYPE_FUNC(object->type)->flags & FUNC_DEFINED) + ) + result = 1; + } else { + if ( + !inst->static_instantiated && + object->datatype == DDATA && + !(object->qual & Q_INLINE_DATA) && + !(object->flags & OBJECT_DEFINED) && + CTempl_GenMemberInstance(inst, OBJECT_TEMPL(object), flag) + ) + result = 1; + } + } + + inst->static_instantiated = 1; + return result; +} + +Boolean CTempl_Instantiate(void) { + Boolean result = 0; + TemplClass *templ; + TemplClassInst *inst; + TemplPartialSpec *pspec; + TemplFuncInstance *instf; + TemplateFunction *templf; + + for (templ = ctempl_templates; templ; templ = templ->next) { + for (inst = templ->instances; inst; inst = inst->next) { + if ( + (inst->theclass.flags & CLASS_IS_TEMPL_INST) && + !inst->is_specialized && + CTempl_GenClassInstance(inst, 0) + ) + result = 1; + } + + for (pspec = templ->pspecs; pspec; pspec = pspec->next) { + for (inst = pspec->templ->instances; inst; inst = inst->next) { + if ( + (inst->theclass.flags & CLASS_IS_TEMPL_INST) && + !inst->is_specialized && + CTempl_GenClassInstance(inst, 0) + ) + result = 1; + } + } + } + + for (templf = ctempl_templatefuncs; templf; templf = templf->next) { + for (instf = templf->instances; instf; instf = instf->next) { + if ( + !instf->is_instantiated && + !instf->is_specialized && + (instf->object->flags & OBJECT_FLAGS_2) && + !(TYPE_FUNC(instf->object->type)->flags & FUNC_DEFINED) + ) + { + instf->is_instantiated = 1; + if (CTempl_GenFuncInstance(templf, instf, 0)) + result = 1; + } + } + } + + return result; +} + +Boolean CTempl_InlineFunctionCheck(Object *funcobj) { + TemplClassInst *inst; + TemplateMember *member; + Object *parent; + + CError_ASSERT(2422, IS_TYPE_FUNC(funcobj->type) && (funcobj->qual & Q_IS_TEMPLATED)); + + if (!(TYPE_FUNC(funcobj->type)->flags & FUNC_DEFINED)) { + inst = TEMPL_CLASS_INST(TYPE_METHOD(funcobj->type)->theclass); + if (!inst->is_specialized) { + parent = OBJECT_TEMPL(funcobj)->parent; + if (parent->qual & Q_INLINE) { + for (member = CTemplClass_GetMasterTemplate(inst->templ)->members; member; member = member->next) { + funcobj->qual |= Q_INLINE; + if (member->object == parent) { + CTemplTool_MergeArgNames(TYPE_FUNC(member->object->type), TYPE_FUNC(funcobj->type)); + CInline_AddInlineFunctionAction(funcobj, TYPE_CLASS(inst), &member->fileoffset, &member->stream, 0); + return 1; + } + } + } + } + } + + return 0; +} diff --git a/compiler_and_linker/FrontEnd/C/CTemplateTools.c b/compiler_and_linker/FrontEnd/C/CTemplateTools.c new file mode 100644 index 0000000..0e77e74 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CTemplateTools.c @@ -0,0 +1,1962 @@ +#include "compiler/CTemplateTools.h" +#include "compiler/CABI.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInline.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CScope.h" +#include "compiler/CTemplateClass.h" +#include "compiler/CTemplateNew.h" +#include "compiler/CompilerTools.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/templates.h" +#include "compiler/types.h" + +short ctempl_instdepth; + +void CTemplTool_PushInstance(TemplStack *stack, TypeClass *tmclass, Object *func) { + if (tmclass) { + stack->u.theclass = tmclass; + stack->is_func = 0; + } else { + stack->u.func = func; + stack->is_func = 1; + } + stack->next = ctempl_curinstance; + ctempl_curinstance = stack; + + if (++ctempl_instdepth >= 64) + CError_ErrorTerm(CErrorStr314); +} + +void CTemplTool_PopInstance(TemplStack *stack) { + CError_ASSERT(53, ctempl_curinstance == stack); + + ctempl_curinstance = stack->next; + if (--ctempl_instdepth < 0) + ctempl_instdepth = 0; +} + +ENode *CTempTool_GetPTMTemplArgExpr(ENode *expr, Type *type) { + NameSpaceObjectList *list; + + CError_ASSERT(69, ENODE_IS(expr, EMEMBER)); + CError_ASSERT(70, IS_TYPE_MEMBERPOINTER(type)); + + if (!copts.cpp_extensions) { + if (!expr->data.emember->x11 || !expr->data.emember->pr_1D) + CError_Warning(CErrorStr331); + } + + type = TYPE_MEMBER_POINTER(type)->ty1; + for (list = expr->data.emember->list; list; list = list->next) { + if (list->object->otype == OT_MEMBERVAR) { + if (!is_typeequal(OBJ_MEMBER_VAR(list->object)->type, type)) + CError_Error(CErrorStr146); + return expr; + } + + if (list->object->otype == OT_OBJECT && is_memberpointerequal(OBJECT(list->object)->type, type)) { + if (expr->data.emember->list != list || list->next) { + // rewrite the EMEMBER to contain just one node + expr->data.emember->list = galloc(sizeof(NameSpaceObjectList)); + *expr->data.emember->list = *list; + expr->data.emember->list->next = NULL; + } + break; + } + } + + if (!list) + CError_Error(CErrorStr146); + + return expr; +} + +Boolean CTemplTool_InitDeduceInfo(DeduceInfo *info, TemplParam *params, TemplArg *args, Boolean flag) { + int i; + TemplArg *buffer; + TemplParam *param; + + if (!params) { + info->args = info->argBuffer; + info->maxCount = 0; + info->x12C = 0xFF; + return 1; + } + + memclrw(info, sizeof(DeduceInfo)); + + i = 0; + param = params; + while (param) { + param = param->next; + i++; + } + + if (i > 16) { + buffer = lalloc(i * sizeof(TemplArg)); + memclrw(buffer, i * sizeof(TemplArg)); + } else { + buffer = info->argBuffer; + } + info->args = buffer; + info->maxCount = i; + info->x12C = params->pid.nindex; + + for (param = params, i = 0; param; param = param->next, i++) + buffer[i].pid = param->pid; + + i = 0; + param = params; + while (args) { + if (!param || param->pid.type != args->pid.type) + return 0; + + buffer[i].data = args->data; + if (i > 0) + buffer[i - 1].next = &buffer[i]; + buffer[i].next = NULL; + buffer[i].is_deduced = 1; + info->count++; + + if (param->pid.type == TPT_NONTYPE && !CTemplTool_IsTemplateArgumentDependentType(param->data.paramdecl.type)) { + if (CExpr_CanImplicitlyConvert(buffer[i].data.paramdecl.expr, param->data.paramdecl.type, param->data.paramdecl.qual)) { + buffer[i].data.paramdecl.expr = CExpr_AssignmentPromotion( + buffer[i].data.paramdecl.expr, param->data.paramdecl.type, param->data.paramdecl.qual, 0); + } else { + return 0; + } + } + + args = args->next; + param = param->next; + i++; + } + + if (flag) { + for (param = params, i = 0; param; param = param->next, i++) { + if (!buffer[i].is_deduced && !param->name) { + switch (param->pid.type) { + case TPT_TYPE: + buffer[i].data.typeparam.type = &stvoid; + break; + case TPT_NONTYPE: + buffer[i].data.paramdecl.expr = nullnode(); + break; + case TPT_TEMPLATE: + default: + CError_FATAL(208); + } + buffer[i].is_deduced = 1; + } + } + } + + return 1; +} + +void CTemplTool_InsertTemplateParameter(NameSpace *nspace, TemplParam *param) { + Type *type; + ObjType *obj; + NameSpaceName *nsn; + + type = CDecl_NewTemplDepType(TEMPLDEP_ARGUMENT); + TYPE_TEMPLATE(type)->u.pid = param->pid; + + obj = galloc(sizeof(ObjType)); + memclrw(obj, sizeof(ObjType)); + obj->otype = OT_TYPE; + obj->access = ACCESSPUBLIC; + obj->type = type; + + for (nsn = nspace->tparams; nsn; nsn = nsn->next) { + if (nsn->name == param->name) { + CError_Error(CErrorStr122, param->name->name); + return; + } + } + + nsn = galloc(sizeof(NameSpaceName)); + memclrw(nsn, sizeof(NameSpaceName)); + + nsn->name = param->name; + nsn->first.object = OBJ_BASE(obj); + + nsn->next = nspace->tparams; + nspace->tparams = nsn; +} + +TemplArg *CTemplTool_MakeTemplArgList(DeduceInfo *info) { + TemplArg *args; + TemplArg *last; + int i; + + for (i = 0; i < info->maxCount; i++) { + if (i) { + last->next = galloc(sizeof(TemplArg)); + last = last->next; + } else { + args = last = galloc(sizeof(TemplArg)); + } + + *last = info->args[i]; + } + + last->next = NULL; + return args; +} + +Boolean CTemplTool_IsIdenticalTemplArgList(TemplArg *args, TemplParam *params) { + while (args) { + if (!params) + return 0; + + CError_ASSERT(297, params->pid.type == args->pid.type); + + switch (args->pid.type) { + case TPT_TYPE: + if ( + !IS_TYPE_TEMPLATE(args->data.typeparam.type) || + TYPE_TEMPLATE(args->data.typeparam.type)->dtype != TEMPLDEP_ARGUMENT || + TYPE_TEMPLATE(args->data.typeparam.type)->u.pid.index != params->pid.index || + TYPE_TEMPLATE(args->data.typeparam.type)->u.pid.nindex != params->pid.nindex + ) + return 0; + break; + case TPT_NONTYPE: + if ( + !ENODE_IS(args->data.paramdecl.expr, ETEMPLDEP) || + args->data.paramdecl.expr->data.templdep.subtype != TDE_PARAM || + args->data.paramdecl.expr->data.templdep.u.pid.index != params->pid.index || + args->data.paramdecl.expr->data.templdep.u.pid.nindex != params->pid.nindex + ) + return 0; + break; + case TPT_TEMPLATE: + if ( + !IS_TYPE_TEMPLATE(args->data.ttargtype) || + TYPE_TEMPLATE(args->data.ttargtype)->dtype != TEMPLDEP_ARGUMENT || + TYPE_TEMPLATE(args->data.ttargtype)->u.pid.index != params->pid.index || + TYPE_TEMPLATE(args->data.ttargtype)->u.pid.nindex != params->pid.nindex + ) + return 0; + break; + default: + CError_FATAL(331); + } + + args = args->next; + params = params->next; + } + + return !params; +} + +Type *CTemplTool_GetSelfRefTemplate(Type *type) { + TemplClass *templ; + TemplArg *args; + + CError_ASSERT(347, IS_TYPE_TEMPLATE(type)); + + if (TYPE_TEMPLATE(type)->dtype == TEMPLDEP_TEMPLATE) { + if (CTemplTool_IsIdenticalTemplArgList( + TYPE_TEMPLATE(type)->u.templ.args, + TYPE_TEMPLATE(type)->u.templ.templ->templ__params)) + return TYPE(TYPE_TEMPLATE(type)->u.templ.templ); + + if (TYPE_TEMPLATE(type)->u.templ.templ->pspecs) { + templ = TYPE_TEMPLATE(type)->u.templ.templ; + if ( + CTemplClass_FindPartialTemplate(TYPE_TEMPLATE(type)->u.templ.args, &templ, &args) && + CTemplTool_IsIdenticalTemplArgList(args, templ->templ__params) + ) + return TYPE(templ); + } + + return NULL; + } + + if (TYPE_TEMPLATE(type)->dtype == TEMPLDEP_QUALNAME) { + Type *t = CTemplTool_GetSelfRefTemplate(TYPE(TYPE_TEMPLATE(type)->u.qual.type)); + if ( + t && + (t = CScope_GetLocalTagType(TYPE_CLASS(t)->nspace, TYPE_TEMPLATE(type)->u.qual.name)) && + IS_TEMPL_CLASS(t) && + !TEMPL_CLASS(t)->templ__params + ) + return t; + + return NULL; + } + + if (TYPE_TEMPLATE(type)->dtype == TEMPLDEP_QUALTEMPL) { + Type *t; + + CError_ASSERT(389, TYPE_TEMPLATE(TYPE_TEMPLATE(type)->u.qualtempl.type)->dtype == TEMPLDEP_QUALNAME); + + t = CTemplTool_GetSelfRefTemplate(TYPE(TYPE_TEMPLATE(TYPE_TEMPLATE(type)->u.qualtempl.type)->u.qual.type)); + if ( + t && + (t = CScope_GetLocalTagType(TYPE_CLASS(t)->nspace, TYPE_TEMPLATE(TYPE_TEMPLATE(type)->u.qualtempl.type)->u.qual.name)) && + IS_TEMPL_CLASS(t) + ) + { + TemplClass *tm = TEMPL_CLASS(t); + if (CTemplTool_IsIdenticalTemplArgList(TYPE_TEMPLATE(type)->u.qualtempl.args, tm->templ__params)) + return TYPE(tm); + } + } + + return NULL; +} + +TemplateFunction *CTemplTool_GetFuncTempl(Object *object) { + while (object->datatype == DALIAS) + object = object->u.alias.object; + + CError_ASSERT(416, IS_TEMPL_FUNC(object->type)); + return object->u.func.u.templ; +} + +Boolean CTemplTool_ParamHasDefaultArg(TemplParam *param) { + switch (param->pid.type) { + case TPT_TYPE: + return param->data.typeparam.type != NULL; + case TPT_NONTYPE: + return param->data.paramdecl.defaultarg != NULL; + case TPT_TEMPLATE: + default: + CError_FATAL(438); + return 0; + } +} + +void CTemplTool_MergeDefaultArgs(TemplParam *dest, TemplParam *src) { + while (1) { + if (!dest) { + CError_ASSERT(455, !src); + return; + } + + CError_ASSERT(458, src); + CError_ASSERT(459, dest->pid.type == src->pid.type); + + switch (dest->pid.type) { + case TPT_TYPE: + if (!dest->data.typeparam.type && src->data.typeparam.type) + dest->data = src->data; + break; + case TPT_NONTYPE: + if (!dest->data.paramdecl.defaultarg && src->data.paramdecl.defaultarg) + dest->data = src->data; + break; + case TPT_TEMPLATE: + if (!dest->data.templparam.defaultarg && src->data.templparam.defaultarg) + dest->data = src->data; + break; + default: + CError_FATAL(484); + } + + dest = dest->next; + src = src->next; + } +} + +static FuncArg *CTemplTool_GetFirstRealArg(TypeFunc *tfunc) { + FuncArg *arg = tfunc->args; + + if (IS_TYPEFUNC_NONSTATIC_METHOD(tfunc)) { + CError_ASSERT(502, arg); + arg = arg->next; + if ((tfunc->flags & FUNC_IS_CTOR) && (TYPE_METHOD(tfunc)->theclass->flags & CLASS_HAS_VBASES)) { + CError_ASSERT(507, arg); + arg = arg->next; + } + } + + return arg; +} + +void CTemplTool_MergeArgNames(TypeFunc *src, TypeFunc *dest) { + FuncArg *destArg; + FuncArg *srcArg; + + CError_ASSERT(524, IS_TYPE_FUNC(dest) && IS_TYPE_FUNC(src)); + + srcArg = CTemplTool_GetFirstRealArg(src); + destArg = CTemplTool_GetFirstRealArg(dest); + + while (1) { + if (!srcArg || !destArg || srcArg == &elipsis || destArg == &elipsis) { + CError_ASSERT(531, srcArg == destArg); + break; + } + + destArg->name = srcArg->name; + srcArg = srcArg->next; + destArg = destArg->next; + } + + if (IS_TYPEFUNC_NONSTATIC_METHOD(dest)) { + CError_ASSERT(538, destArg = dest->args); + if (!destArg->name) + destArg->name = this_name_node; + } +} + +Boolean CTemplTool_EqualParams(TemplParam *a, TemplParam *b, Boolean copyNames) { + while (1) { + if (!a) + return !b; + if (!b) + return 0; + + if (a->pid.type != b->pid.type) + return 0; + + if (copyNames) + a->name = b->name; + + switch (a->pid.type) { + case TPT_TYPE: + break; + case TPT_NONTYPE: + if ( + !is_typesame(a->data.paramdecl.type, b->data.paramdecl.type) || + a->data.paramdecl.qual != b->data.paramdecl.qual + ) + return 0; + break; + case TPT_TEMPLATE: + break; + default: + CError_FATAL(576); + } + + a = a->next; + b = b->next; + } +} + +NameSpace *CTemplTool_SetupTemplateArgumentNameSpace(TemplParam *params, TemplArg *args, Boolean is_global) { + NameSpace *nspace; + Boolean clear_global; + ObjType *objType; + Object *object; + + clear_global = 0; + if (!is_global && trychain) { + clear_global = 1; + is_global = 1; + } + + nspace = CScope_NewListNameSpace(NULL, is_global); + nspace->is_templ = 1; + + if (clear_global) + nspace->is_global = 0; + + if (!params) + return nspace; + + while (params) { + CError_ASSERT(607, args); + + if (params->name) { + switch (args->pid.type) { + case TPT_TYPE: + if (is_global) { + objType = galloc(sizeof(ObjType)); + memclrw(objType, sizeof(ObjType)); + } else { + objType = lalloc(sizeof(ObjType)); + memclrw(objType, sizeof(ObjType)); + } + objType->otype = OT_TYPE; + objType->access = ACCESSPUBLIC; + objType->type = args->data.typeparam.type; + objType->qual = args->data.typeparam.qual; + CScope_AddObject(nspace, params->name, OBJ_BASE(objType)); + break; + case TPT_NONTYPE: + if (is_global) { + object = galloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + } else { + object = lalloc(sizeof(Object)); + memclrw(object, sizeof(Object)); + } + object->otype = OT_OBJECT; + object->access = ACCESSPUBLIC; + object->nspace = nspace; + object->name = params->name; + object->type = args->data.paramdecl.expr->rtype; + object->qual = ENODE_QUALS(args->data.paramdecl.expr); + object->datatype = DEXPR; + object->u.expr = args->data.paramdecl.expr; + if (IS_TYPE_REFERENCE(params->data.paramdecl.type)) { + CError_ASSERT(652, IS_TYPE_POINTER_ONLY(object->u.expr->rtype)); + object->u.expr = makemonadicnode(object->u.expr, EINDIRECT); + object->u.expr->rtype = TPTR_TARGET(params->data.paramdecl.type); + } + if (is_global) + object->u.expr = CInline_CopyExpression(object->u.expr, CopyMode1); + CScope_AddObject(nspace, params->name, OBJ_BASE(object)); + break; + case TPT_TEMPLATE: + if (is_global) { + objType = galloc(sizeof(ObjType)); + memclrw(objType, sizeof(ObjType)); + } else { + objType = lalloc(sizeof(ObjType)); + memclrw(objType, sizeof(ObjType)); + } + objType->otype = OT_TYPE; + objType->access = ACCESSPUBLIC; + objType->type = args->data.ttargtype; + objType->qual = 0; + CScope_AddObject(nspace, params->name, OBJ_BASE(objType)); + break; + default: + CError_FATAL(681); + } + } + + params = params->next; + args = args->next; + } + + CError_ASSERT(685, !args); + + return nspace; +} + +void CTemplTool_SetupOuterTemplateArgumentNameSpace(NameSpace *nspace) { + NameSpace *newns; + + while (nspace) { + if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL_INST)) { + newns = CTemplTool_SetupTemplateArgumentNameSpace( + TEMPL_CLASS_INST(nspace->theclass)->templ->templ__params, + TEMPL_CLASS_INST(nspace->theclass)->inst_args, + 0); + newns->parent = nspace->parent; + nspace->parent = newns; + } + + nspace = nspace->parent; + } +} + +NameSpace *CTemplTool_InsertTemplateArgumentNameSpace(TemplParam *params, TemplClassInst *inst, CScopeSave *save) { + NameSpace *nspace = CTemplTool_SetupTemplateArgumentNameSpace(params, inst->inst_args, 0); + + nspace->parent = inst->theclass.nspace->parent; + inst->theclass.nspace->parent = nspace; + + CTemplTool_SetupOuterTemplateArgumentNameSpace(nspace); + CScope_SetNameSpaceScope(inst->theclass.nspace, save); + + return nspace; +} + +void CTemplTool_RemoveOuterTemplateArgumentNameSpace(NameSpace *nspace) { + while (nspace->parent) { + if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL_INST) && nspace->parent->is_templ) + nspace->parent = nspace->parent->parent; + nspace = nspace->parent; + } +} + +void CTemplTool_RemoveTemplateArgumentNameSpace(NameSpace *nspace, TemplClassInst *inst, CScopeSave *save) { + CTemplTool_RemoveOuterTemplateArgumentNameSpace(inst->theclass.nspace); + CScope_RestoreScope(save); +} + +Boolean CTemplTool_IsTemplateArgumentDependentType(Type *type) { + FuncArg *arg; + + while (1) { + switch (type->type) { + case TYPETEMPLATE: + return 1; + case TYPEVOID: + case TYPEINT: + case TYPEFLOAT: + case TYPEENUM: + case TYPESTRUCT: + return 0; + case TYPECLASS: + return (TYPE_CLASS(type)->flags & CLASS_IS_TEMPL) ? 1 : 0; + case TYPEMEMBERPOINTER: + if (CTemplTool_IsTemplateArgumentDependentType(TYPE_MEMBER_POINTER(type)->ty1)) + return 1; + type = TYPE_MEMBER_POINTER(type)->ty2; + continue; + case TYPEPOINTER: + case TYPEARRAY: + type = TPTR_TARGET(type); + continue; + case TYPEFUNC: + for (arg = TYPE_FUNC(type)->args; arg && arg != &elipsis && arg != &oldstyle; arg = arg->next) { + if (CTemplTool_IsTemplateArgumentDependentType(arg->type)) + return 1; + } + type = TYPE_FUNC(type)->functype; + continue; + case TYPEBITFIELD: + type = TYPE_BITFIELD(type)->bitfieldtype; + continue; + case TYPETEMPLDEPEXPR: + return 1; + default: + CError_FATAL(822); + } + } +} + +Boolean CTemplTool_IsTemplateArgumentDependentExpression(ENode *expr) { + if (!expr) + return 0; + + if (IS_TYPE_TEMPLDEPEXPR(expr->rtype)) + return 1; + + return 0; +} + +Boolean CTemplTool_IsSameTemplate(TemplParam *params, TemplArg *args) { + while (1) { + if (!args) { + CError_ASSERT(850, !params); + return 1; + } + + CError_ASSERT(853, params && args->pid.type == params->pid.type); + + switch (args->pid.type) { + case TPT_TYPE: + if ( + !IS_TYPE_TEMPLATE(args->data.typeparam.type) || + TYPE_TEMPLATE(args->data.typeparam.type)->dtype != TEMPLDEP_ARGUMENT || + TYPE_TEMPLATE(args->data.typeparam.type)->u.pid.nindex != params->pid.nindex || + TYPE_TEMPLATE(args->data.typeparam.type)->u.pid.index != params->pid.index || + args->data.typeparam.qual != 0 + ) + return 0; + break; + case TPT_NONTYPE: + if ( + !ENODE_IS(args->data.paramdecl.expr, ETEMPLDEP) || + args->data.paramdecl.expr->data.templdep.subtype != TDE_PARAM || + args->data.paramdecl.expr->data.templdep.u.pid.nindex != params->pid.nindex || + args->data.paramdecl.expr->data.templdep.u.pid.index != params->pid.index + ) + return 0; + break; + case TPT_TEMPLATE: + if (!IS_TYPE_TEMPLATE(args->data.ttargtype)) + return 0; + break; + default: + CError_FATAL(886); + } + + args = args->next; + params = params->next; + } +} + +TemplClass *CTemplTool_IsTemplate(TypeTemplDep *ttd) { + if (ttd->dtype == TEMPLDEP_QUALNAME && ttd->u.qual.type->dtype == TEMPLDEP_TEMPLATE) + ttd = ttd->u.qual.type; + else if (ttd->dtype != TEMPLDEP_TEMPLATE) + return NULL; + + if (CTemplTool_IsSameTemplate(ttd->u.templ.templ->templ__params, ttd->u.templ.args)) + return ttd->u.templ.templ; + else + return NULL; +} + +Type *CTemplTool_IsDependentTemplate(TemplClass *tmclass, TemplArg *args) { + TemplParam *param; + TemplArg *arg; + Type *type; + + if (!tmclass->templ_parent || tmclass->inst_parent) { + arg = args; + param = tmclass->templ__params; + while (1) { + if (!arg) { + CError_ASSERT(988, !param); + return NULL; + } + + CError_ASSERT(991, param && arg->pid.type == param->pid.type); + + switch (arg->pid.type) { + case TPT_TYPE: + if (CTemplTool_IsTemplateArgumentDependentType(arg->data.typeparam.type)) + goto done; + break; + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(arg->data.paramdecl.expr)) + goto done; + break; + case TPT_TEMPLATE: + if (!IS_TYPE_CLASS(arg->data.ttargtype) && CTemplTool_IsTemplateArgumentDependentType(arg->data.ttargtype)) + goto done; + break; + default: + CError_FATAL(1008); + goto done; + } + + arg = arg->next; + param = param->next; + } + } +done: + if (cscope_current->theclass == TYPE_CLASS(tmclass) && CTemplTool_IsSameTemplate(tmclass->templ__params, args)) + return TYPE(tmclass); + + type = CDecl_NewTemplDepType(TEMPLDEP_TEMPLATE); + TYPE_TEMPLATE(type)->u.templ.templ = tmclass; + TYPE_TEMPLATE(type)->u.templ.args = args; + return type; +} + +Boolean CTemplTool_EqualExprTypes(ENode *a, ENode *b) { + Object *objA; + Object *objB; + + if (!a || !b) + return 0; + if (a->type != b->type) + return 0; + + switch (a->type) { + case EINTCONST: + return CInt64_Equal(a->data.intval, b->data.intval); + case EOBJREF: + objA = a->data.objref; + while (objA->datatype == DALIAS) + objA = objA->u.alias.object; + objB = b->data.objref; + while (objB->datatype == DALIAS) + objB = objB->u.alias.object; + return objA == objB; + case EMEMBER: + return a->data.emember->list == b->data.emember->list; + case ETEMPLDEP: + if (a->data.templdep.subtype != b->data.templdep.subtype) + return 0; + + switch (a->data.templdep.subtype) { + case TDE_PARAM: + return a->data.templdep.u.pid.nindex == b->data.templdep.u.pid.nindex && + a->data.templdep.u.pid.index == b->data.templdep.u.pid.index; + case TDE_SIZEOF: + case TDE_ALIGNOF: + return is_typesame(a->data.templdep.u.typeexpr.type, b->data.templdep.u.typeexpr.type); + case TDE_CAST: + return is_typesame(a->data.templdep.u.cast.type, b->data.templdep.u.cast.type) && + a->data.templdep.u.cast.qual == b->data.templdep.u.cast.qual; + case TDE_QUALNAME: + return is_typesame(TYPE(a->data.templdep.u.qual.type), TYPE(b->data.templdep.u.qual.type)) && + a->data.templdep.u.qual.name == b->data.templdep.u.qual.name; + case TDE_OBJ: + return a->data.templdep.u.obj == b->data.templdep.u.obj; + case TDE_ADDRESS_OF: + return CTemplTool_EqualExprTypes(a->data.templdep.u.monadic, b->data.templdep.u.monadic); + default: + CError_FATAL(1086); + } + case EMUL: + case EDIV: + case EMODULO: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case EROTL: + case EROTR: + return CTemplTool_EqualExprTypes(a->data.diadic.left, b->data.diadic.left) && + CTemplTool_EqualExprTypes(a->data.diadic.right, b->data.diadic.right); + case EMONMIN: + case EBINNOT: + case ELOGNOT: + return CTemplTool_EqualExprTypes(a->data.monadic, b->data.monadic); + case ECOND: + return CTemplTool_EqualExprTypes(a->data.cond.cond, b->data.cond.cond) && + CTemplTool_EqualExprTypes(a->data.cond.expr1, b->data.cond.expr1) && + CTemplTool_EqualExprTypes(a->data.cond.expr2, b->data.cond.expr2); + default: + CError_FATAL(1122); + return 0; + } +} + +ENode *CTempl_MakeTemplDepExpr(ENode *left, ENodeType nt, ENode *right) { + if (!IS_TYPE_TEMPLDEPEXPR(right->rtype)) { + right = pointer_generation(right); + if (!ENODE_IS(right, EINTCONST)) { + CError_Error(CErrorStr348); + right = nullnode(); + } + } + + if (left) { + if (!IS_TYPE_TEMPLDEPEXPR(left->rtype)) { + left = pointer_generation(left); + if (!ENODE_IS(left, EINTCONST)) { + CError_Error(CErrorStr348); + left = nullnode(); + } + } + + left = makediadicnode(left, right, nt); + } else { + left = makemonadicnode(right, nt); + } + + left->rtype = &sttemplexpr; + return left; +} + +void CTemplTool_CheckTemplArgType(Type *type) { + while (IS_TYPE_POINTER_ONLY(type)) + type = TPTR_TARGET(type); + + if (IS_TYPE_CLASS(type)) { + if (IsTempName(TYPE_CLASS(type)->classname) || CScope_IsInLocalNameSpace(TYPE_CLASS(type)->nspace)) + CError_Error(CErrorStr232); + } +} + +Boolean CTemplTool_EqualArgs(TemplArg *a, TemplArg *b) { + while (a) { + if (!b || a->pid.type != b->pid.type) + return 0; + + switch (a->pid.type) { + case TPT_TYPE: + if ( + !is_typesame(a->data.typeparam.type, b->data.typeparam.type) || + a->data.typeparam.qual != b->data.typeparam.qual + ) + return 0; + break; + case TPT_NONTYPE: + if (!CTemplTool_EqualExprTypes(a->data.paramdecl.expr, b->data.paramdecl.expr)) + return 0; + break; + case TPT_TEMPLATE: + if (!is_typesame(a->data.ttargtype, b->data.ttargtype)) + return 0; + break; + default: + CError_FATAL(1215); + } + + a = a->next; + b = b->next; + } + + if (b) + return 0; + + return 1; +} + +TemplArg *CTemplTool_MakeGlobalTemplArgCopy(TemplArg *args) { + TemplArg *firstCopy; + TemplArg *copy; + + firstCopy = NULL; + while (args) { + if (firstCopy) { + copy->next = galloc(sizeof(TemplArg)); + copy = copy->next; + } else { + copy = galloc(sizeof(TemplArg)); + firstCopy = copy; + } + + *copy = *args; + if (copy->pid.type == TPT_NONTYPE && copy->data.paramdecl.expr) + copy->data.paramdecl.expr = CInline_CopyExpression(copy->data.paramdecl.expr, CopyMode1); + + args = args->next; + } + + return firstCopy; +} + +Boolean CTemplTool_TemplDepTypeCompare(TypeTemplDep *a, TypeTemplDep *b) { + if (a == b) + return 1; + if (a->dtype != b->dtype) + return 0; + + switch (a->dtype) { + case TEMPLDEP_ARGUMENT: + return a->u.pid.nindex == b->u.pid.nindex && + a->u.pid.index == b->u.pid.index; + case TEMPLDEP_QUALNAME: + return CTemplTool_TemplDepTypeCompare(a->u.qual.type, b->u.qual.type) && + a->u.qual.name == b->u.qual.name; + case TEMPLDEP_TEMPLATE: + return a->u.templ.templ == b->u.templ.templ && + CTemplTool_EqualArgs(a->u.templ.args, b->u.templ.args); + case TEMPLDEP_ARRAY: + return is_typesame(a->u.array.type, b->u.array.type) && + CTemplTool_EqualExprTypes(a->u.array.index, b->u.array.index); + case TEMPLDEP_QUALTEMPL: + return CTemplTool_TemplDepTypeCompare(a->u.qualtempl.type, b->u.qualtempl.type) && + CTemplTool_EqualArgs(a->u.qualtempl.args, b->u.qualtempl.args); + case TEMPLDEP_BITFIELD: + return is_typesame(a->u.bitfield.type, b->u.bitfield.type) && + CTemplTool_EqualExprTypes(a->u.bitfield.size, b->u.bitfield.size); + default: + CError_FATAL(1286); + return 0; + } +} + +Type *CTemplTool_DeduceArgDepType(TemplArg *args, Type *type, UInt32 qual, UInt32 *resultQual) { + TemplArg *arg; + + *resultQual = qual; + + if (IS_TYPE_TEMPLATE(type) && TYPE_TEMPLATE(type)->dtype == TEMPLDEP_ARGUMENT) { + arg = args; + while (1) { + if (!arg) + return NULL; + + if ( + arg->pid.index == TYPE_TEMPLATE(type)->u.pid.index && + arg->pid.nindex == TYPE_TEMPLATE(type)->u.pid.nindex + ) + break; + + arg = arg->next; + } + + CError_ASSERT(1314, arg->pid.type == TPT_TYPE); + *resultQual |= arg->data.typeparam.qual; + return arg->data.typeparam.type; + } + + return NULL; +} + +static TemplClassInst *CTemplTool_FindNestedClassInstance(TemplClass *a, TemplClass *b, TemplClassInst *c) { + TemplClass *array[32]; + TemplClassInst *inst; + int i; + + array[0] = a; + i = 0; + while (1) { + CError_ASSERT(1338, i < 32); + CError_ASSERT(1339, a = a->templ_parent); + + if (a == b) + break; + + CError_ASSERT(1341, a->templ__params == NULL); + + array[++i] = a; + } + + while (1) { + inst = array[i--]->instances; + while (1) { + CError_ASSERT(1350, inst); + if (inst->parent == c) + break; + inst = inst->next; + } + + c = inst; + if (i < 0) + break; + + if ((inst->theclass.flags & (CLASS_COMPLETED | CLASS_IS_TEMPL_INST)) == CLASS_IS_TEMPL_INST) + CTempl_InstantiateTemplateClass(TYPE_CLASS(inst)); + } + + return inst; +} + +static TemplClassInst *CTemplTool_FindNestedClass(TemplClass *a, TemplClassInst *b, TemplClass *c) { + TemplClass *scan; + + while (1) { + for (scan = c->templ_parent; scan; scan = scan->templ_parent) { + if (scan == a) + return CTemplTool_FindNestedClassInstance(c, a, b); + } + + a = a->templ_parent; + if (!a) + break; + + b = b->parent; + CError_ASSERT(1377, b); + } + + return NULL; +} + +static Type *CTemplTool_FindTemplateInstance(TypeDeduce *deduce, TemplClass *templ) { + TemplClass *scantempl; + TemplClass *dtempl; + TemplClassInst *scaninst; + TemplClassInst *dinst; + + dtempl = deduce->tmclass; + CError_ASSERT(1393, dtempl); + + dinst = deduce->inst; + if (!dinst) { + if (!dtempl->templ_parent || !dtempl->inst_parent) + return TYPE(templ); + + dtempl = dtempl->templ_parent; + dinst = deduce->tmclass->inst_parent; + } + + scantempl = dtempl; + scaninst = dinst; + while (1) { + if (scantempl == templ) + return TYPE(scaninst); + + if (!scantempl->templ_parent && scantempl->pspec_owner) + scantempl = scantempl->pspec_owner; + + scantempl = scantempl->templ_parent; + if (!scantempl) + break; + + CError_ASSERT(1416, scaninst = scaninst->parent); + } + + if (dtempl->flags & TEMPLCLASS_FLAGS_2) { + scantempl = TEMPL_CLASS(dtempl->theclass.nspace->theclass); + CError_ASSERT(1422, scantempl->theclass.flags & CLASS_IS_TEMPL); + scaninst = dinst; + + while (1) { + if (scantempl == templ) + return TYPE(scaninst); + + scantempl = scantempl->templ_parent; + if (!scantempl) + break; + + CError_ASSERT(1430, scaninst = scaninst->parent); + } + } + + if (!templ->templ__params && (scaninst = CTemplTool_FindNestedClass(dtempl, dinst, templ))) + return TYPE(scaninst); + + CError_FATAL(1477); + return NULL; +} + +static ENode *CTemplTool_DeduceExprCheck(ENode *expr) { + if (expr->type != EINTCONST) { + CError_Error(CErrorStr348); + expr = nullnode(); + } + + return expr; +} + +static ENodeList *CTemplTool_DeduceExprList(TypeDeduce *deduce, ENodeList *list) { + ENodeList *resultList; + ENodeList *last; + + resultList = NULL; + while (list) { + if (resultList) { + last->next = lalloc(sizeof(ENodeList)); + last = last->next; + } else { + last = lalloc(sizeof(ENodeList)); + resultList = last; + } + + *last = *list; + last->node = CTemplTool_DeduceExpr(deduce, last->node); + + list = list->next; + } + + return resultList; +} + +ENode *CTemplTool_DeduceExpr(TypeDeduce *deduce, ENode *expr) { + TemplArg *arg; + TemplClassInst *inst; + ENode *newExpr; + NameSpaceObjectList *nsObjectList; + TStreamElement *saved; + NameResult pr; + Type *type; + UInt32 qual; + + if (!CTemplTool_IsTemplateArgumentDependentExpression(expr)) { + newExpr = lalloc(sizeof(ENode)); + *newExpr = *expr; + return newExpr; + } + + switch (expr->type) { + case ETEMPLDEP: + switch (expr->data.templdep.subtype) { + case TDE_PARAM: + if (deduce->x15 && expr->data.templdep.u.pid.nindex == deduce->nindex) { + newExpr = lalloc(sizeof(ENode)); + *newExpr = *expr; + return newExpr; + } + + for (arg = deduce->args; arg; arg = arg->next) { + if ( + arg->pid.index == expr->data.templdep.u.pid.index && + arg->pid.nindex == expr->data.templdep.u.pid.nindex + ) + { + CError_ASSERT(1562, arg->pid.type == TPT_NONTYPE && arg->data.paramdecl.expr); + newExpr = lalloc(sizeof(ENode)); + *newExpr = *arg->data.paramdecl.expr; + return newExpr; + } + } + + for (inst = deduce->inst; inst; inst = inst->parent) { + for (arg = inst->inst_args; arg; arg = arg->next) { + if ( + arg->pid.index == expr->data.templdep.u.pid.index && + arg->pid.nindex == expr->data.templdep.u.pid.nindex + ) + { + CError_ASSERT(1575, arg->pid.type == TPT_NONTYPE && arg->data.paramdecl.expr); + newExpr = lalloc(sizeof(ENode)); + *newExpr = *arg->data.paramdecl.expr; + return newExpr; + } + } + } + + CError_FATAL(1582); + + case TDE_SIZEOF: + qual = 0; + type = CTemplTool_DeduceTypeCopy(deduce, TYPE(expr->data.templdep.u.typeexpr.type), &qual); + CDecl_CompleteType(type); + + if (CTemplTool_IsTemplateArgumentDependentType(type)) { + newExpr = lalloc(sizeof(ENode)); + *newExpr = *expr; + newExpr->data.templdep.u.typeexpr.type = type; + return newExpr; + } + + return intconstnode(CABI_GetSizeTType(), type->size); + + case TDE_ALIGNOF: + qual = 0; + type = CTemplTool_DeduceTypeCopy(deduce, TYPE(expr->data.templdep.u.typeexpr.type), &qual); + CDecl_CompleteType(type); + + if (CTemplTool_IsTemplateArgumentDependentType(type)) { + newExpr = lalloc(sizeof(ENode)); + *newExpr = *expr; + newExpr->data.templdep.u.typeexpr.type = type; + return newExpr; + } + + return intconstnode(CABI_GetSizeTType(), CMach_GetTypeAlign(type)); + + case TDE_CAST: + qual = expr->data.templdep.u.cast.qual; + type = CTemplTool_DeduceTypeCopy(deduce, expr->data.templdep.u.cast.type, &qual); + return CExpr_DoExplicitConversion(type, qual, CTemplTool_DeduceExprList(deduce, expr->data.templdep.u.cast.args)); + + case TDE_QUALNAME: + qual = 0; + type = CTemplTool_DeduceTypeCopy(deduce, TYPE(expr->data.templdep.u.qual.type), &qual); + + if (IS_TYPE_CLASS(type)) { + CDecl_CompleteType(type); + if (CScope_FindQualifiedClassMember(&pr, TYPE_CLASS(type), expr->data.templdep.u.qual.name)) + return pointer_generation(CExpr_MakeNameLookupResultExpr(&pr)); + + CError_Error(CErrorStr150, expr->data.templdep.u.qual.name->name); + } else if (IS_TYPE_TEMPLATE(type) && !deduce->inst) { + newExpr = lalloc(sizeof(ENode)); + *newExpr = *expr; + newExpr->data.templdep.u.qual.type = TYPE_TEMPLATE(type); + return newExpr; + } else { + CError_Error(CErrorStr340, expr->data.templdep.u.qual.name->name); + } + + return nullnode(); + + case TDE_OBJ: + type = CTemplTool_FindTemplateInstance(deduce, TEMPL_CLASS(expr->data.templdep.u.obj->nspace->theclass)); + CError_ASSERT(1651, type && IS_TYPE_CLASS(type)); + + nsObjectList = CScope_GetLocalObject(TYPE_CLASS(type)->nspace, expr->data.templdep.u.obj->name); + CError_ASSERT(1654, nsObjectList); + + memclrw(&pr, sizeof(pr)); + pr.obj_10 = nsObjectList->object; + return pointer_generation(CExpr_MakeNameLookupResultExpr(&pr)); + + case TDE_SOURCEREF: + CError_LockErrorPos(expr->data.templdep.u.sourceref.token, &saved); + newExpr = CTemplTool_DeduceExpr(deduce, expr->data.templdep.u.sourceref.expr); + CError_UnlockErrorPos(&saved); + return newExpr; + + case TDE_ADDRESS_OF: + return getnodeaddress(CTemplTool_DeduceExpr(deduce, expr->data.templdep.u.monadic), 1); + + default: + CError_FATAL(1671); + } + case EFUNCCALL: + newExpr = CExpr_PointerGeneration(CTemplTool_DeduceExpr(deduce, expr->data.funccall.funcref)); + return CExpr_MakeFunctionCall(newExpr, CTemplTool_DeduceExprList(deduce, expr->data.funccall.args)); + case ELOGNOT: + return CExpr_New_ELOGNOT_Node(CTemplTool_DeduceExpr(deduce, expr->data.monadic)); + case EMONMIN: + return CExpr_New_EMONMIN_Node(CTemplTool_DeduceExpr(deduce, expr->data.monadic)); + case EBINNOT: + return CExpr_New_EBINNOT_Node(CTemplTool_DeduceExpr(deduce, expr->data.monadic)); + case EMUL: + case EDIV: + case EMODULO: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case EROTL: + case EROTR: + return CExpr_NewDyadicNode( + CTemplTool_DeduceExpr(deduce, expr->data.diadic.left), + expr->type, + CTemplTool_DeduceExpr(deduce, expr->data.diadic.right)); + case ECOND: + return CExpr_New_ECOND_Node( + CTemplTool_DeduceExpr(deduce, expr->data.cond.cond), + CTemplTool_DeduceExpr(deduce, expr->data.cond.expr1), + CTemplTool_DeduceExpr(deduce, expr->data.cond.expr2)); + default: + CError_FATAL(1727); + case EINTCONST: + newExpr = lalloc(sizeof(ENode)); + *newExpr = *expr; + return newExpr; + } +} + +ENode *CTemplTool_DeduceDefaultArg(Object *func, ENode *expr) { + TypeDeduce deduce; + + memclrw(&deduce, sizeof(deduce)); + CError_ASSERT(1747, IS_TYPE_FUNC(func->type)); + + if (func->u.func.inst) + deduce.args = func->u.func.inst->args; + + if ((TYPE_FUNC(func->type)->flags & FUNC_METHOD) && (TYPE_METHOD(func->type)->theclass->flags & CLASS_IS_TEMPL_INST)) { + deduce.inst = TEMPL_CLASS_INST(TYPE_METHOD(func->type)->theclass); + deduce.tmclass = TEMPL_CLASS_INST(TYPE_METHOD(func->type)->theclass)->templ; + } + + return CTemplTool_DeduceExpr(&deduce, expr); +} + +static TemplClass *CTemplTool_FindNestedTemplateInstance(TypeDeduce *deduce, TemplClass *templ) { + TemplClass *dtempl; + TemplClassInst *dinst; + Type *type; + + if (templ->inst_parent) + return templ; + + CError_ASSERT(1776, (dtempl = deduce->tmclass) && (dinst = deduce->inst)); + + while (1) { + if ( + templ->templ_parent == dtempl && + (type = CScope_GetLocalTagType(dinst->theclass.nspace, templ->theclass.classname)) && + IS_TEMPL_CLASS(type) && + TEMPL_CLASS(type)->templ_parent == templ->templ_parent + ) + return TEMPL_CLASS(type); + + dtempl = dtempl->templ_parent; + if (!dtempl) + break; + + dinst = dinst->parent; + CError_ASSERT(1790, dinst); + } + + return templ; +} + +static Type *CTemplTool_DeduceClassInstanceCopy(TypeDeduce *deduce, TemplClass *templ, TemplArg *args) { + TemplArg *arg; + TemplArg *deducedArgs; + TemplArg *last; + TemplParam *param; + UInt32 qual; + Type *type; + + if (templ->templ_parent) + templ = CTemplTool_FindNestedTemplateInstance(deduce, templ); + + arg = args; + deducedArgs = NULL; + param = templ->templ__params; + + while (arg) { + if (deducedArgs) { + last->next = galloc(sizeof(TemplArg)); + last = last->next; + } else { + last = galloc(sizeof(TemplArg)); + deducedArgs = last; + } + + *last = *arg; + + if (!param || param->pid.type != last->pid.type) { + CError_Error(CErrorStr374); + return &stvoid; + } + + last->pid = param->pid; + param = param->next; + + switch (last->pid.type) { + case TPT_TYPE: + last->data.typeparam.type = CTemplTool_DeduceTypeCopy(deduce, last->data.typeparam.type, &last->data.typeparam.qual); + break; + + case TPT_NONTYPE: + if (!last->data.paramdecl.expr) { + CError_FATAL(1873); + } else if (CTemplTool_IsTemplateArgumentDependentExpression(last->data.paramdecl.expr)) { + last->data.paramdecl.expr = pointer_generation(CTemplTool_DeduceExpr(deduce, last->data.paramdecl.expr)); + last->data.paramdecl.expr = CInline_CopyExpression(last->data.paramdecl.expr, CopyMode1); + } + break; + + case TPT_TEMPLATE: + qual = 0; + last->data.ttargtype = CTemplTool_DeduceTypeCopy(deduce, last->data.ttargtype, &qual); + break; + + default: + CError_FATAL(1891); + } + + arg = arg->next; + } + + for (arg = deducedArgs; arg; arg = arg->next) { + switch (arg->pid.type) { + case TPT_TYPE: + if (CTemplTool_IsTemplateArgumentDependentType(arg->data.typeparam.type)) + break; + continue; + + case TPT_NONTYPE: + if (CTemplTool_IsTemplateArgumentDependentExpression(arg->data.paramdecl.expr)) + break; + + switch (arg->data.paramdecl.expr->type) { + case EINTCONST: + case EOBJLIST: + case EMEMBER: + break; + case EOBJREF: + if (CParser_HasInternalLinkage2(arg->data.paramdecl.expr->data.objref)) + CError_Error(CErrorStr357); + break; + default: + CError_Error(CErrorStr371); + arg->data.paramdecl.expr = nullnode(); + break; + } + continue; + + case TPT_TEMPLATE: + if (!IS_TYPE_CLASS(arg->data.ttargtype) && CTemplTool_IsTemplateArgumentDependentType(arg->data.ttargtype)) + break; + continue; + + default: + CError_FATAL(1937); + } + + break; + } + + if (arg) { + type = CDecl_NewTemplDepType(TEMPLDEP_TEMPLATE); + TYPE_TEMPLATE(type)->u.templ.templ = templ; + TYPE_TEMPLATE(type)->u.templ.args = deducedArgs; + return type; + } + + if ((type = CTemplTool_IsDependentTemplate(templ, deducedArgs))) + return type; + + return TYPE(CTemplClass_GetInstance(templ, deducedArgs, NULL)); +} + +static TemplArg *CTemplTool_FindTemplArg(TemplArg *args, TemplParamID pid) { + while (args) { + if (args->pid.index == pid.index && args->pid.nindex == pid.nindex) { + CError_ASSERT(1984, pid.type == args->pid.type); + return args; + } + args = args->next; + } + + return NULL; +} + +static TemplArg *CTemplTool_DeduceTemplArg(TypeDeduce *deduce, TemplParamID pid) { + TemplClass *tmclass; + TemplClassInst *inst; + TemplArg *arg; + + if ((arg = CTemplTool_FindTemplArg(deduce->args, pid))) + return arg; + + tmclass = deduce->tmclass; + CError_ASSERT(2008, tmclass); + + inst = deduce->inst; + if (!inst) { + CError_ASSERT(2011, tmclass->templ_parent && tmclass->inst_parent); + inst = deduce->tmclass->inst_parent; + } + + while (1) { + if ((arg = CTemplTool_FindTemplArg(inst->inst_args, pid))) + return arg; + + inst = inst->parent; + CError_ASSERT(2022, inst); + } +} + +static Type *CTemplTool_DeduceArrayCopy(TypeDeduce *deduce, Type *type, ENode *index, UInt32 *resultQual) { + if (CTemplTool_IsTemplateArgumentDependentType(type)) + type = CTemplTool_DeduceTypeCopy(deduce, type, resultQual); + + index = CTemplTool_DeduceExpr(deduce, index); + + if (ENODE_IS(index, EINTCONST)) { + if (CInt64_IsNegative(&index->data.intval)) { + CError_Error(CErrorStr124); + index->data.intval = cint64_one; + } + + if (!CDecl_CheckArrayIntegr(type)) + type = TYPE(&stsignedchar); + + type = CDecl_NewArrayType(type, type->size * CInt64_GetULong(&index->data.intval)); + } else { + if (!deduce->x16) + CError_Error(CErrorStr124); + } + + return type; +} + +static Type *CTemplTool_DeduceBitfieldCopy(TypeDeduce *deduce, Type *type, ENode *size, UInt32 *resultQual) { + TypeBitfield *tbitfield; + short sizeval; + short maxsize; + + if (CTemplTool_IsTemplateArgumentDependentType(type)) { + UInt32 qual = 0; + type = CTemplTool_DeduceTypeCopy(deduce, type, &qual); + } + + if (!IS_TYPE_INT_OR_ENUM(type)) { + CError_Error(CErrorStr138); + type = TYPE(&stunsignedint); + } + + switch (type->size) { + case 1: + maxsize = 8; + break; + case 2: + maxsize = 16; + break; + case 4: + maxsize = 32; + break; + default: + CError_Error(CErrorStr138); + return type; + } + + if (!ENODE_IS(size, EINTCONST)) { + size = CTemplTool_DeduceExpr(deduce, size); + if (!ENODE_IS(size, EINTCONST)) { + CError_Error(CErrorStr124); + return type; + } + } + + sizeval = CInt64_GetULong(&size->data.intval); + if (sizeval > maxsize || CInt64_IsNegative(&size->data.intval)) { + CError_Error(CErrorStr138); + sizeval = 1; + } + + tbitfield = galloc(sizeof(TypeBitfield)); + memclrw(tbitfield, sizeof(TypeBitfield)); + + tbitfield->type = TYPEBITFIELD; + tbitfield->size = type->size; + tbitfield->bitfieldtype = type; + tbitfield->bitlength = sizeval; + + return TYPE(tbitfield); +} + +static Type *CTemplTool_DeduceTemplDepType(TypeDeduce *deduce, TypeTemplDep *tdt, UInt32 *resultQual) { + Type *type; + UInt32 qual; + TemplArg *arg; + + qual = 0; + + if (deduce->x14) { + type = CTemplTool_GetSelfRefTemplate(TYPE(tdt)); + if (type && type == TYPE(deduce->tmclass)) + return type; + + switch (tdt->dtype) { + case TEMPLDEP_ARGUMENT: + return TYPE(tdt); + + case TEMPLDEP_QUALNAME: + type = CTemplTool_DeduceTypeCopy(deduce, TYPE(tdt->u.qual.type), &qual); + if (type == TYPE(tdt->u.qual.type)) + return TYPE(tdt); + + if (!IS_TYPE_CLASS(type)) { + TypeTemplDep *tdtCopy; + CError_ASSERT(2157, IS_TYPE_TEMPLATE(type)); + tdtCopy = galloc(sizeof(TypeTemplDep)); + *tdtCopy = *tdt; + tdtCopy->u.qual.type = TYPE_TEMPLATE(type); + return TYPE(tdtCopy); + } else if ((type = CScope_GetType(TYPE_CLASS(type)->nspace, tdt->u.qual.name, resultQual))) { + return type; + } else { + CError_Error(CErrorStr150, tdt->u.qual.name->name); + return TYPE(tdt); + } + + case TEMPLDEP_TEMPLATE: + for (arg = tdt->u.templ.args; arg; arg = arg->next) { + if (arg->pid.type == TPT_TYPE) + arg->data.typeparam.type = CTemplTool_DeduceTypeCopy(deduce, arg->data.typeparam.type, &arg->data.typeparam.qual); + } + return TYPE(tdt); + + case TEMPLDEP_ARRAY: + tdt->u.array.type = CTemplTool_DeduceTypeCopy(deduce, tdt->u.array.type, &qual); + return TYPE(tdt); + + case TEMPLDEP_QUALTEMPL: + tdt->u.qualtempl.type = TYPE_TEMPLATE(CTemplTool_DeduceTemplDepType(deduce, tdt->u.qualtempl.type, &qual)); + for (arg = tdt->u.qualtempl.args; arg; arg = arg->next) { + if (arg->pid.type == TPT_TYPE) + arg->data.typeparam.type = CTemplTool_DeduceTypeCopy(deduce, arg->data.typeparam.type, &arg->data.typeparam.qual); + } + return TYPE(tdt); + + case TEMPLDEP_BITFIELD: + tdt->u.bitfield.type = CTemplTool_DeduceTypeCopy(deduce, tdt->u.bitfield.type, &qual); + return TYPE(tdt); + } + } else { + switch (tdt->dtype) { + case TEMPLDEP_ARGUMENT: + if (deduce->x15 && tdt->u.pid.nindex == deduce->nindex) + return TYPE(tdt); + + arg = CTemplTool_DeduceTemplArg(deduce, tdt->u.pid); + if (arg->pid.type == TPT_TEMPLATE) { + CError_ASSERT(2222, IS_TEMPL_CLASS(arg->data.typeparam.type)); + *resultQual = arg->data.typeparam.qual; + return arg->data.typeparam.type; + } + + CError_ASSERT(2226, arg->pid.type == TPT_TYPE); + *resultQual = arg->data.typeparam.qual; + return arg->data.typeparam.type; + + case TEMPLDEP_QUALNAME: + type = CTemplTool_DeduceTypeCopy(deduce, TYPE(tdt->u.qual.type), &qual); + if (IS_TYPE_CLASS(type)) { + CDecl_CompleteType(type); + if ((type = CScope_GetType(TYPE_CLASS(type)->nspace, tdt->u.qual.name, resultQual))) { + return type; + } else { + CError_Error(CErrorStr150, tdt->u.qual.name->name); + } + } else { + if ((deduce->x15 || !deduce->inst) && IS_TYPE_TEMPLATE(type)) { + TypeTemplDep *tdtCopy = galloc(sizeof(TypeTemplDep)); + *tdtCopy = *tdt; + tdtCopy->u.qual.type = TYPE_TEMPLATE(type); + return TYPE(tdtCopy); + } else { + CError_Error(CErrorStr340, tdt->u.qual.name->name); + } + } + return TYPE(&stsignedint); + + case TEMPLDEP_TEMPLATE: + return CTemplTool_DeduceClassInstanceCopy(deduce, tdt->u.templ.templ, tdt->u.templ.args); + + case TEMPLDEP_ARRAY: + return CTemplTool_DeduceArrayCopy(deduce, tdt->u.array.type, tdt->u.array.index, resultQual); + + case TEMPLDEP_QUALTEMPL: + type = CTemplTool_DeduceTypeCopy(deduce, TYPE(tdt->u.qualtempl.type), &qual); + if (!IS_TEMPL_CLASS(type)) { + CError_Error(CErrorStr121); + return TYPE(&stsignedint); + } + return CTemplTool_DeduceClassInstanceCopy(deduce, TEMPL_CLASS(type), tdt->u.qualtempl.args); + + case TEMPLDEP_BITFIELD: + return CTemplTool_DeduceBitfieldCopy(deduce, tdt->u.bitfield.type, tdt->u.bitfield.size, resultQual); + } + } + + CError_FATAL(2275); + return NULL; +} + +static Type *CTemplTool_DeduceTypeQualCopy(TypeDeduce *deduce, Type *type, UInt32 *resultQual) { + Type *innerType; + UInt32 qual; + UInt32 innerQual; + TypePointer *newPtr; + + qual = *resultQual; + + if (IS_TYPE_POINTER_ONLY(type) && IS_TYPE_TEMPLATE(TPTR_TARGET(type))) { + innerQual = 0; + innerType = CTemplTool_DeduceTemplDepType(deduce, TYPE_TEMPLATE(TPTR_TARGET(type)), &innerQual); + + newPtr = galloc(sizeof(TypePointer)); + *newPtr = *TYPE_POINTER(type); + + if (IS_TYPE_POINTER_ONLY(innerType)) { + newPtr->target = galloc(sizeof(TypePointer)); + *TYPE_POINTER(newPtr->target) = *TYPE_POINTER(innerType); + *resultQual = innerQual & (Q_CONST | Q_VOLATILE); + TPTR_QUAL(newPtr->target) |= qual & (Q_CONST | Q_VOLATILE); + } else if (IS_TYPE_MEMBERPOINTER(innerType)) { + newPtr->target = galloc(sizeof(TypeMemberPointer)); + *TYPE_MEMBER_POINTER(newPtr->target) = *TYPE_MEMBER_POINTER(innerType); + *resultQual = innerQual & (Q_CONST | Q_VOLATILE); + TYPE_MEMBER_POINTER(newPtr->target)->qual |= qual & (Q_CONST | Q_VOLATILE); + } else { + newPtr->target = innerType; + *resultQual = (qual | innerQual) & (Q_CONST | Q_VOLATILE); + } + + return TYPE(newPtr); + } + + return CTemplTool_DeduceTypeCopy(deduce, type, resultQual); +} + +FuncArg *CTemplTool_DeduceArgCopy(TypeDeduce *deduce, FuncArg *args) { + FuncArg *resultArgs; + FuncArg *last; + + if (args == &oldstyle || args == &elipsis) + return args; + + resultArgs = NULL; + + while (args) { + if (args == &elipsis) { + last->next = args; + break; + } + + if (resultArgs) { + last->next = galloc(sizeof(FuncArg)); + last = last->next; + } else { + last = galloc(sizeof(FuncArg)); + resultArgs = last; + } + + *last = *args; + last->type = CTemplTool_DeduceTypeQualCopy(deduce, last->type, &last->qual); + CanCreateObject(last->type); + + args = args->next; + } + + return resultArgs; +} + +static ExceptSpecList *CTemplTool_DeduceExSpecCopy(TypeDeduce *deduce, ExceptSpecList *exspec) { + ExceptSpecList *copy; + + copy = galloc(sizeof(ExceptSpecList)); + *copy = *exspec; + + if (copy->type && CTemplTool_IsTemplateArgumentDependentType(copy->type)) + copy->type = CTemplTool_DeduceTypeCopy(deduce, copy->type, ©->qual); + + if (copy->next) + copy->next = CTemplTool_DeduceExSpecCopy(deduce, copy->next); + + return copy; +} + +Type *CTemplTool_DeduceTypeCopy(TypeDeduce *deduce, Type *type, UInt32 *resultQual) { + TemplClassInst *inst; + Type *deduced; + UInt32 qual2; + UInt32 qual; + + switch (type->type) { + case TYPETEMPLATE: + qual = 0; + deduced = CTemplTool_DeduceTemplDepType(deduce, TYPE_TEMPLATE(type), &qual); + if (*resultQual & (Q_CONST | Q_VOLATILE)) { + if (IS_TYPE_POINTER_ONLY(deduced)) { + TypePointer *newPtr = galloc(sizeof(TypePointer)); + *newPtr = *TYPE_POINTER(deduced); + newPtr->qual |= *resultQual & (Q_CONST | Q_VOLATILE); + *resultQual &= ~(Q_CONST | Q_VOLATILE); + deduced = TYPE(newPtr); + } else if (IS_TYPE_MEMBERPOINTER(deduced)) { + TypeMemberPointer *newPtr = galloc(sizeof(TypeMemberPointer)); + *newPtr = *TYPE_MEMBER_POINTER(deduced); + newPtr->qual |= *resultQual & (Q_CONST | Q_VOLATILE); + *resultQual &= ~(Q_CONST | Q_VOLATILE); + deduced = TYPE(newPtr); + } + } + *resultQual |= qual; + return deduced; + + case TYPEVOID: + case TYPEINT: + case TYPEFLOAT: + case TYPESTRUCT: + return type; + + case TYPEENUM: + if ( + TYPE_ENUM(type)->nspace->theclass && + (TYPE_ENUM(type)->nspace->theclass->flags & CLASS_IS_TEMPL) && + !deduce->x14 + ) + { + CError_ASSERT(2471, TYPE_ENUM(type)->enumname); + inst = TEMPL_CLASS_INST(CTemplTool_FindTemplateInstance(deduce, TEMPL_CLASS(TYPE_ENUM(type)->nspace->theclass))); + CError_ASSERT(2473, inst && inst->theclass.type == TYPECLASS); + + CDecl_CompleteType(TYPE(inst)); + type = CScope_GetLocalTagType(inst->theclass.nspace, TYPE_ENUM(type)->enumname); + CError_ASSERT(2477, type); + return type; + } + return type; + + case TYPECLASS: + if (!deduce->x14) { + if (TYPE_CLASS(type)->flags & CLASS_IS_TEMPL) + return CTemplTool_FindTemplateInstance(deduce, TEMPL_CLASS(type)); + + if (TYPE_CLASS(type)->nspace->theclass && (TYPE_CLASS(type)->nspace->theclass->flags & CLASS_IS_TEMPL)) { + CError_ASSERT(2492, deduce->inst); + CError_ASSERT(2493, TYPE_CLASS(type)->classname); + + type = CScope_GetLocalTagType(deduce->inst->theclass.nspace, TYPE_CLASS(type)->classname); + CError_ASSERT(2496, type); + return type; + } + } + + return type; + + case TYPEARRAY: { + SInt32 elements; + + elements = TPTR_TARGET(type)->size; + if (elements > 0) + elements = type->size / elements; + + deduced = galloc(sizeof(TypePointer)); + *TYPE_POINTER(deduced) = *TYPE_POINTER(type); + TPTR_TARGET(deduced) = CTemplTool_DeduceTypeCopy(deduce, TPTR_TARGET(type), resultQual); + + do { + type = TPTR_TARGET(type); + } while (IS_TYPE_ARRAY(type)); + + if (IS_TYPE_TEMPLATE(type)) { + CDecl_CompleteType(TPTR_TARGET(deduced)); + deduced->size = TPTR_TARGET(deduced)->size * elements; + } + + return deduced; + } + + case TYPEPOINTER: + deduced = galloc(sizeof(TypePointer)); + *TYPE_POINTER(deduced) = *TYPE_POINTER(type); + TPTR_TARGET(deduced) = CTemplTool_DeduceTypeCopy(deduce, TPTR_TARGET(type), resultQual); + return deduced; + + case TYPEBITFIELD: + deduced = galloc(sizeof(TypeBitfield)); + *TYPE_BITFIELD(deduced) = *TYPE_BITFIELD(type); + TYPE_BITFIELD(deduced)->bitfieldtype = CTemplTool_DeduceTypeCopy(deduce, TYPE_BITFIELD(type)->bitfieldtype, resultQual); + return deduced; + + case TYPEMEMBERPOINTER: + deduced = galloc(sizeof(TypeMemberPointer)); + *TYPE_MEMBER_POINTER(deduced) = *TYPE_MEMBER_POINTER(type); + TYPE_MEMBER_POINTER(deduced)->ty1 = CTemplTool_DeduceTypeCopy(deduce, TYPE_MEMBER_POINTER(type)->ty1, resultQual); + qual2 = 0; + TYPE_MEMBER_POINTER(deduced)->ty2 = CTemplTool_DeduceTypeCopy(deduce, TYPE_MEMBER_POINTER(type)->ty2, &qual2); + + if ( + !IS_TYPE_CLASS(TYPE_MEMBER_POINTER(deduced)->ty2) && + !deduce->x14 && + !deduce->x15 && + !deduce->x16 + ) + { + CError_Error(CErrorStr232); + return TYPE_MEMBER_POINTER(deduced)->ty1; + } + return deduced; + + case TYPEFUNC: + if (TYPE_FUNC(type)->flags & FUNC_METHOD) { + qual2 = 0; + deduced = galloc(sizeof(TypeMemberFunc)); + *TYPE_METHOD(deduced) = *TYPE_METHOD(type); + TYPE_METHOD(deduced)->funcid = 0; + TYPE_METHOD(deduced)->theclass = TYPE_CLASS(CTemplTool_DeduceTypeQualCopy(deduce, TYPE(TYPE_METHOD(type)->theclass), &qual2)); + CError_ASSERT(2556, IS_TYPE_CLASS(TYPE_METHOD(deduced)->theclass)); + } else { + deduced = galloc(sizeof(TypeFunc)); + *TYPE_FUNC(deduced) = *TYPE_FUNC(type); + } + + TYPE_FUNC(deduced)->flags &= ~FUNC_IS_TEMPL; + + qual2 = TYPE_FUNC(type)->qual; + TYPE_FUNC(deduced)->functype = CTemplTool_DeduceTypeQualCopy(deduce, TYPE_FUNC(type)->functype, &qual2); + TYPE_FUNC(deduced)->qual = qual2; + + TYPE_FUNC(deduced)->args = CTemplTool_DeduceArgCopy(deduce, TYPE_FUNC(type)->args); + if (TYPE_FUNC(type)->exspecs) + TYPE_FUNC(deduced)->exspecs = CTemplTool_DeduceExSpecCopy(deduce, TYPE_FUNC(type)->exspecs); + + CDecl_SetResultReg(TYPE_FUNC(deduced)); + return deduced; + + case TYPETEMPLDEPEXPR: + CError_Error(CErrorStr190); + return &stvoid; + + default: + CError_FATAL(2580); + return NULL; + } +} + +Type *CTemplTool_ResolveMemberSelfRefs(TemplClass *templ, Type *type, UInt32 *resultQual) { + TypeDeduce deduce; + + memclrw(&deduce, sizeof(deduce)); + deduce.tmclass = templ; + deduce.x14 = 1; + + if (IS_TYPE_FUNC(type)) { + TYPE_FUNC(type)->functype = CTemplTool_DeduceTypeCopy(&deduce, TYPE_FUNC(type)->functype, &TYPE_FUNC(type)->qual); + TYPE_FUNC(type)->args = CTemplTool_DeduceArgCopy(&deduce, TYPE_FUNC(type)->args); + CDecl_SetResultReg(TYPE_FUNC(type)); + } else { + type = CTemplTool_DeduceTypeCopy(&deduce, type, resultQual); + } + + return type; +} + +Boolean CTemplTool_IsSameTemplateType(Type *a, Type *b) { + return CTemplTool_GetSelfRefTemplate(b) == a; +} diff --git a/compiler_and_linker/FrontEnd/Common/CIRTransform.c b/compiler_and_linker/FrontEnd/Common/CIRTransform.c new file mode 100644 index 0000000..b91f6af --- /dev/null +++ b/compiler_and_linker/FrontEnd/Common/CIRTransform.c @@ -0,0 +1,534 @@ +#include "compiler/CIRTransform.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInit.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/objects.h" +#include "compiler/types.h" +#include "compiler/CompilerTools.h" +#include "compiler/CDecl.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct CIRTransTemp { + struct CIRTransTemp *next; + Object *object; + Boolean flag; +} CIRTransTemp; + +typedef struct MultiAccessOperand { + Object *object; + Object *tempobj; + ENode *ass; + Type *type; + Type *bitfieldType; +} MultiAccessOperand; + +// no idea what this is for... +typedef struct StrangeRuntimeFunction { + Object *object; + short unk; + char name[1]; +} StrangeRuntimeFunction; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static TypeFunc cirtrans_rtfunc8 = { + TYPEFUNC, 0, NULL, NULL, TYPE(&void_ptr), 0, 0 +}; +static TypeFunc cirtrans_rtfunc4 = { + TYPEFUNC, 0, NULL, NULL, TYPE(&stunsignedlong), 0, 0 +}; +static TypeFunc cirtrans_rtfunc2 = { + TYPEFUNC, 0, NULL, NULL, TYPE(&stsignedshort), 0, 0 +}; + +static CIRTransTemp *cirtrans_temps; +Boolean modulo_generated; +Boolean bigswitch_generated; +Boolean alloca_called; + +// forward decls +static ENode *CIRTrans_TransExpr(ENode *expr, Boolean flag); + +void CIRTrans_Setup(void) { +} + +void CIRTrans_Cleanup(void) { +} + +static Object *CIRTrans_GetRuntimeFunction(StrangeRuntimeFunction *rtfunc, Type *type) { + Object *object; + + object = rtfunc->object; + if (!object) { + object = CParser_NewFunctionObject(NULL); + rtfunc->object = object; + + object->nspace = cscope_root; + object->name = GetHashNameNodeExport(rtfunc->name); + object->flags = OBJECT_INTERNAL; + + if (type) { + switch (type->size) { + case 2: + object->type = TYPE(&cirtrans_rtfunc2); + break; + case 4: + object->type = TYPE(&cirtrans_rtfunc4); + break; + case 8: + object->type = TYPE(&cirtrans_rtfunc8); + break; + default: + CError_FATAL(427); + } + } else { + object->type = TYPE(&cirtrans_rtfunc8); + } + } + + return object; +} + +static Object *CIRTrans_GetTemporary(Type *type) { + CIRTransTemp *temp; + + for (temp = cirtrans_temps; temp; temp = temp->next) { + if (temp->object->type->size == type->size && !temp->flag) { + temp->flag = 1; + return temp->object; + } + } + + temp = oalloc(sizeof(CIRTransTemp)); + temp->next = cirtrans_temps; + cirtrans_temps = temp; + + temp->object = create_temp_object(type); + temp->flag = 1; + return temp->object; +} + +static ENode *CIRTrans_CheckRuntimeAssign(ENode *expr) { + ENode *inner; + + if (ENODE_IS(expr->data.diadic.right, EINDIRECT)) { + inner = expr->data.diadic.right->data.monadic; + if ( + ENODE_IS(inner, EFUNCCALL) && + (inner->flags & ENODE_FLAG_80) && + inner->data.funccall.args && + ENODE_IS(inner->data.funccall.args->node, EOBJREF) + ) + { + CError_ASSERT(502, ENODE_IS(expr->data.diadic.left, EINDIRECT)); + inner->data.funccall.args->node = expr->data.diadic.left->data.monadic; + inner->flags &= ~ENODE_FLAG_80; + return expr->data.diadic.right; + } + } + + return expr; +} + +static void CIRTrans_SetupMultiAccessOperand(MultiAccessOperand *mop, ENode *expr) { + memclrw(mop, sizeof(MultiAccessOperand)); + + mop->type = expr->rtype; + + CError_ASSERT(522, ENODE_IS(expr, EINDIRECT)); + expr = expr->data.monadic; + + if (ENODE_IS(expr, EOBJREF)) { + mop->object = expr->data.objref; + } else { + if (ENODE_IS(expr, EBITFIELD)) { + mop->bitfieldType = expr->rtype; + expr = expr->data.monadic; + } + expr->rtype = CDecl_NewPointerType(mop->type); + mop->tempobj = create_temp_object(expr->rtype); + mop->ass = makediadicnode(create_objectnode(mop->tempobj), expr, EASS); + } +} + +static ENode *CIRTrans_GetMultiAccessOperand(MultiAccessOperand *mop) { + ENode *expr; + + if (mop->object == NULL) { + expr = create_objectnode(mop->tempobj); + if (mop->bitfieldType) { + expr = makemonadicnode(expr, EBITFIELD); + expr->rtype = mop->bitfieldType; + } + expr = makemonadicnode(expr, EINDIRECT); + } else { + expr = create_objectnode(mop->object); + } + + expr->rtype = mop->type; + return expr; +} + +static ENode *CIRTrans_InitMultiAccessExpression(MultiAccessOperand *mop, ENode *expr) { + if (mop->ass) { + expr = makediadicnode(mop->ass, expr, ECOMMA); + expr->rtype = expr->data.diadic.right->rtype; + } + return expr; +} + +ENode *CIRTrans_TransformOpAss(ENode *expr) { + ENodeType nt; + ENode *expr2; + MultiAccessOperand mop; + + if (!ENODE_IS(expr->data.diadic.left, EINDIRECT)) { + CError_Error(CErrorStr142); + return nullnode(); + } + + CIRTrans_SetupMultiAccessOperand(&mop, expr->data.diadic.left); + + switch (expr->type) { + case EMULASS: + nt = EMUL; + break; + case EDIVASS: + nt = EDIV; + break; + case EMODASS: + nt = EMODULO; + break; + case EADDASS: + nt = EADD; + break; + case ESUBASS: + nt = ESUB; + break; + case ESHLASS: + nt = ESHL; + break; + case ESHRASS: + nt = ESHR; + break; + case EANDASS: + nt = EAND; + break; + case EXORASS: + nt = EXOR; + break; + case EORASS: + nt = EOR; + break; + default: + CError_FATAL(622); + } + + expr2 = CIRTrans_GetMultiAccessOperand(&mop); + + if (!IS_TYPE_POINTER_ONLY(expr2->rtype)) { + expr2 = CExpr_NewDyadicNode(expr2, nt, expr->data.diadic.right); + if (expr2->rtype != expr->data.diadic.left->rtype) { + expr2 = makemonadicnode(expr2, ETYPCON); + expr2->rtype = expr->data.diadic.left->rtype; + } + } else { + expr2 = makediadicnode(expr2, expr->data.diadic.right, nt); + } + + if (IS_TYPE_FLOAT(expr2->rtype)) + expr2 = CExpr_BinaryFloatExpression(expr2); + + expr2 = makediadicnode(CIRTrans_GetMultiAccessOperand(&mop), expr2, EASS); + return CIRTrans_InitMultiAccessExpression(&mop, expr2); +} + +static void CIRTrans_TransIncDec() { + // empty, never called +} + +static ENode *CIRTrans_TransIntConst(ENode *expr) { + Object *obj; + UInt8 data[16]; + + CMach_InitIntMem(expr->rtype, expr->data.intval, data); + + obj = CParser_NewGlobalDataObject(NULL); + obj->name = CParser_GetUniqueName(); + obj->type = expr->rtype; + obj->sclass = TK_STATIC; + obj->datatype = DDATA; + CScope_AddGlobalObject(obj); + CInit_DeclareData(obj, data, NULL, obj->type->size); + return create_objectnode(obj); +} + +static ENode *CIRTrans_TransFloatConst(ENode *expr) { + Object *obj; + UInt8 data[16]; + + CMach_InitFloatMem(expr->rtype, expr->data.floatval, data); + + obj = CParser_NewGlobalDataObject(NULL); + obj->name = CParser_GetUniqueName(); + obj->type = expr->rtype; + obj->sclass = TK_STATIC; + obj->datatype = DDATA; + CScope_AddGlobalObject(obj); + CInit_DeclareData(obj, data, NULL, obj->type->size); + return create_objectnode(obj); +} + +static ENode *CIRTrans_TransUnary(ENode *expr, Type *type, StrangeRuntimeFunction *rtfunc) { + if (type->size > 4) { + expr = funccallexpr( + CIRTrans_GetRuntimeFunction(rtfunc, type), + create_objectrefnode(CIRTrans_GetTemporary(type)), + expr, + NULL, + NULL); + expr->flags |= ENODE_FLAG_80; + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = type; + return expr; + } else { + expr = funccallexpr( + CIRTrans_GetRuntimeFunction(rtfunc, type), + expr, + NULL, + NULL, + NULL); + expr->rtype = type; + return expr; + } +} + +static ENode *CIRTrans_TransBinary(ENode *expr, StrangeRuntimeFunction *rtfunc) { + ENode *expr2; + + if (expr->rtype->size > 4) { + expr2 = funccallexpr( + CIRTrans_GetRuntimeFunction(rtfunc, expr->rtype), + create_objectrefnode(CIRTrans_GetTemporary(expr->rtype)), + expr->data.diadic.left, + expr->data.diadic.right, + NULL); + expr2->flags |= ENODE_FLAG_80; + expr2 = makemonadicnode(expr2, EINDIRECT); + expr2->rtype = expr->rtype; + return expr2; + } else { + expr2 = funccallexpr( + CIRTrans_GetRuntimeFunction(rtfunc, expr->rtype), + expr->data.diadic.left, + expr->data.diadic.right, + NULL, + NULL); + expr2->rtype = expr->rtype; + return expr2; + } +} + +static ENodeList *CIRTrans_TransExprList(ENodeList *list) { + ENodeList *scan; + + for (scan = list; scan; scan = scan->next) + scan->node = CIRTrans_TransExpr(scan->node, 1); + + return list; +} + +static ENode *CIRTrans_TransExpr(ENode *expr, Boolean flag) { + switch (expr->type) { + case EINDIRECT: + case EFORCELOAD: + case EBITFIELD: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); + break; + case EPOSTINC: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, 1); + break; + case EPOSTDEC: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, 1); + break; + case EPREINC: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, 1); + break; + case EPREDEC: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, 1); + break; + case ETYPCON: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); + if (!flag) + return expr->data.monadic; + break; + case EBINNOT: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); + break; + case ELOGNOT: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); + break; + case EMONMIN: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); + break; + case EADD: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case ESUB: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EMUL: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + case EDIV: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EMODULO: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case ESHL: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case ESHR: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EROTL: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EROTR: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EAND: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EXOR: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EOR: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + if (!flag) { + expr->type = ECOMMA; + expr->rtype = expr->data.diadic.right->rtype; + return expr; + } + break; + case ELAND: + case ELOR: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 1); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EMULV: + case EADDV: + case ESUBV: + case EPMODULO: + case EBCLR: + case EBTST: + case EBSET: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EASS: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 1); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, 1); + break; + case EMULASS: + case EDIVASS: + case EADDASS: + case ESUBASS: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 1); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, 1); + break; + case EMODASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 1); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, 1); + break; + case ECOMMA: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 0); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case ECOND: + expr->data.cond.cond = CIRTrans_TransExpr(expr->data.cond.cond, 1); + expr->data.cond.expr1 = CIRTrans_TransExpr(expr->data.cond.expr1, 1); + expr->data.cond.expr2 = CIRTrans_TransExpr(expr->data.cond.expr2, 1); + break; + case EMFPOINTER: + expr->data.mfpointer.accessnode = CIRTrans_TransExpr(expr->data.mfpointer.accessnode, flag); + expr->data.mfpointer.mfpointer = CIRTrans_TransExpr(expr->data.mfpointer.mfpointer, flag); + break; + case EFUNCCALL: + case EFUNCCALLP: + if ( + ENODE_IS(expr->data.funccall.funcref, EOBJREF) && + !strcmp(expr->data.funccall.funcref->data.objref->name->name, "__alloca") + ) + alloca_called = 1; + expr->data.funccall.funcref = CIRTrans_TransExpr(expr->data.funccall.funcref, 1); + expr->data.funccall.args = CIRTrans_TransExprList(expr->data.funccall.args); + break; + case ENULLCHECK: + expr->data.nullcheck.nullcheckexpr = CIRTrans_TransExpr(expr->data.nullcheck.nullcheckexpr, 1); + expr->data.nullcheck.condexpr = CIRTrans_TransExpr(expr->data.nullcheck.condexpr, 1); + break; + case ENEWEXCEPTION: + case ENEWEXCEPTIONARRAY: + expr->data.newexception.initexpr = CIRTrans_TransExpr(expr->data.newexception.initexpr, 1); + expr->data.newexception.tryexpr = CIRTrans_TransExpr(expr->data.newexception.tryexpr, 1); + break; + case EINITTRYCATCH: + expr->data.itc.initexpr = CIRTrans_TransExpr(expr->data.itc.initexpr, 1); + expr->data.itc.tryexpr = CIRTrans_TransExpr(expr->data.itc.tryexpr, 1); + expr->data.itc.catchexpr = CIRTrans_TransExpr(expr->data.itc.catchexpr, 1); + expr->data.itc.result = CIRTrans_TransExpr(expr->data.itc.result, 1); + break; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ETEMP: + case ELABEL: + case EMEMBER: + case EINSTRUCTION: + case EVECTOR128CONST: + break; + default: + CError_FATAL(1947); + } + + return expr; +} + +void CIRTrans_Transform(void) { + cirtrans_temps = NULL; +} diff --git a/compiler_and_linker/FrontEnd/Common/COptimizer.c b/compiler_and_linker/FrontEnd/Common/COptimizer.c new file mode 100644 index 0000000..3c83ae6 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Common/COptimizer.c @@ -0,0 +1,1831 @@ +#include "compiler/COptimizer.h" +#include "compiler/CompilerTools.h" +#include "compiler/CClass.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/InlineAsm.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/CodeGen.h" +#include "compiler/Switch.h" +#include "compiler/Exceptions.h" +#include "../Optimizer/IrOptimizer.h" +#include "cos.h" + +COptBlock *basicblocks; +Boolean copt_isleaffunction; +static Boolean stmtchanged; +static COptBlock *currentblock; +static ENode *mexpr; +static short setbytes; +static COptCSE *csenodes[MAXEXPR]; +static COptCSEList *cselist; +static short extravars; +static Boolean cse_found; +static Boolean cse_invals; +static Boolean static_for_inlines; +static short replaces; +static ENode *objrefnode; +static int objrefnodes; + +static short bitmasks[] = { + 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, + 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000 +}; + +// forward decls +static COptCSE *cse_expression(ENode *expr); + +static COptCSE *cse_new(ENode *expr) { + COptCSE *cse = oalloc(sizeof(COptCSE)); + cse->expr = expr; + cse->replaced = NULL; + cse->block = currentblock; + cse->mexpr = mexpr; + cse->left = NULL; + cse->right = NULL; + cse->x1C = 1; + return cse; +} + +static COptCSE *cse_append(COptCSE *cse, ENode *expr) { + COptCSEList *list = oalloc(sizeof(COptCSEList)); + list->next = cselist; + cselist = list; + list->cse = cse; + list->expr = expr; + return cse; +} + +static void cse_cleanup(void) { + COptCSEList *scanlist; + COptCSEList *prevlist; + COptCSE *scan; + COptCSE *prev; + short op; + + scanlist = cselist; + while (scanlist && !scanlist->cse) + scanlist = scanlist->next; + cselist = scanlist; + + if (scanlist) { + do { + prevlist = scanlist; + do { + scanlist = scanlist->next; + } while (scanlist && !scanlist->cse); + prevlist->next = scanlist; + } while (scanlist); + } + + for (op = 0; op < MAXEXPR; op++) { + scan = csenodes[op]; + while (scan && scan->x1C < 0) + scan = scan->next; + csenodes[op] = scan; + + if (scan) { + do { + prev = scan; + do { + scan = scan->next; + } while (scan && scan->x1C < 0); + prev->next = scan; + } while (scan); + } + } +} + +static void cse_inval(COptCSE *cse) { + COptCSEList *scanlist; + COptCSE *scan; + short op; + + if (cse) { + for (scanlist = cselist; scanlist; scanlist = scanlist->next) { + if (scanlist->cse == cse) { + scanlist->cse = NULL; + scanlist->expr = NULL; + } + } + + cse->x1C = -1; + cse->left = NULL; + cse->right = NULL; + + for (op = 0; op < MAXEXPR; op++) { + for (scan = csenodes[op]; scan; scan = scan->next) { + if (scan->left == cse || scan->right == cse) + cse_inval(scan); + } + } + } +} + +static void cse_update_usages(COptCSE *cse, short amount) { + cse->x1C /= amount; + if (cse->left) + cse_update_usages(cse->left, amount); + if (cse->right) + cse_update_usages(cse->right, amount); +} + +static void cse_replace(ENode *expr, COptCSE *cse) { + COptCSEList *list; + + for (list = cselist; list; list = list->next) { + if (list->cse == cse) { + *list->expr = *expr; + replaces++; + list->cse = NULL; + list->expr = NULL; + } + } +} + +static short cse_objectcost(Object *obj) { + if (obj->datatype == DLOCAL && !obj->u.var.info->noregister) + return 0; + return 1; +} + +static void cse_treereplacemexpr(COptCSE *cse, ENode *from, ENode *to) { + if (cse->mexpr == from) + cse->mexpr = to; + if (cse->left) + cse_treereplacemexpr(cse->left, from, to); + if (cse->right) + cse_treereplacemexpr(cse->right, from, to); +} + +static Boolean cse_issubcse(COptCSE *a, COptCSE *b) { + if (a == b) + return 1; + if (b->left && cse_issubcse(a, b->left)) + return 1; + if (b->right && cse_issubcse(a, b->right)) + return 1; + + return 0; +} + +static short cse_cost(COptCSE *cse) { + short cost; + + if (cse) { + while (ENODE_IS(cse->expr, ETYPCON) && cse->expr->rtype->type == cse->expr->data.monadic->rtype->type && cse->expr->rtype->size == cse->expr->data.monadic->rtype->size) + cse = cse->left; + + if (ENODE_IS_INDIRECT_TO(cse->expr, EOBJREF)) + return cse_objectcost(cse->expr->data.monadic->data.objref); + + cost = 1; + if (!copts.optimizesize) { + if (ENODE_IS3(cse->expr, EMUL, EDIV, EMODULO)) + cost = 2; + } + return cse_cost(cse->left) + cse_cost(cse->right) + cost; + } + + return 0; +} + +static void cse_remove(void) { + short op; // r27 + COptCSE *cse; // r25 + COptCSE *best_cse; // r28 + int best_cost; // r30 + Object *obj; // r31 + Boolean did_replacement; // r24 + VarInfo *vi; // r27 + ObjectList *objlist; + ENode *expr1; + ENode *expr2; + ENode *expr3; + ENode *expr4; + ENode *mexprsave; + COptCSEList *list; + short cost; + + while (1) { + op = 0; + best_cse = NULL; + best_cost = 0; + did_replacement = 0; + + for (; op < MAXEXPR; op++) { + switch (op) { + case EINTCONST: + case EFLOATCONST: + case EOBJREF: + case EVECTOR128CONST: + break; + default: + for (cse = csenodes[op]; cse; cse = cse->next) { + if (cse->x1C > 1 && (cost = cse_cost(cse)) > 4) { + if (cse->replaced) { + replaces = 0; + cse_replace(cse->replaced, cse); + CError_ASSERT(348, replaces >= 1); + cse_found = 1; + did_replacement = 1; + cse_update_usages(cse, cse->x1C); + } else { + if ((cse->x1C * cost) > best_cost) { + best_cse = cse; + best_cost = cse->x1C * cost; + } + } + } + } + break; + } + } + + if (did_replacement) + continue; + if (!best_cse || extravars >= 256) + return; + + obj = lalloc(sizeof(Object)); + memclrw(obj, sizeof(Object)); + obj->name = CParser_GetUniqueName(); + obj->type = cse->expr->rtype; + obj->datatype = DLOCAL; + vi = CodeGen_GetNewVarInfo(); + obj->u.var.info = vi; + + objlist = lalloc(sizeof(ObjectList)); + objlist->object = obj; + objlist->next = locals; + locals = objlist; + + vi->used = 1; + vi->usage = cse->x1C + 1; + + expr1 = lalloc(sizeof(ENode)); + expr1->type = EOBJREF; + expr1->cost = 0; + expr1->flags = 0; + expr1->data.objref = obj; + expr1->rtype = CDecl_NewPointerType(obj->type); + + expr2 = lalloc(sizeof(ENode)); + expr2->type = EINDIRECT; + expr2->cost = 1; + expr2->flags = 0; + expr2->data.monadic = expr1; + expr2->rtype = obj->type; + + expr3 = lalloc(sizeof(ENode)); + expr3->type = EASS; + expr3->cost = -1; + expr3->flags = 0; + expr3->rtype = obj->type; + expr3->data.diadic.left = expr2; + expr3->data.diadic.right = lalloc(sizeof(ENode)); + + *expr3->data.diadic.right = *cse->expr; + cse->expr = expr3->data.diadic.right; + + replaces = 0; + cse_replace(expr2, cse); + cse->replaced = expr2; + + if (replaces < 2) + CError_FATAL(390); + else + cse_found = 1; + + expr4 = lalloc(sizeof(ENode)); + *expr4 = *cse->mexpr; + + cse->mexpr->type = ECOMMA; + cse->mexpr->data.diadic.left = expr3; + cse->mexpr->data.diadic.right = expr4; + + cse_update_usages(cse, cse->x1C); + extravars++; + + mexprsave = cse->mexpr; + if (mexpr == mexprsave) + mexpr = expr4; + + for (list = cselist; list; list = list->next) { + if (list->cse && !cse_issubcse(list->cse, cse)) { + if (list->cse->mexpr == mexprsave) + list->cse->mexpr = expr4; + if (list->cse->expr == mexprsave) + list->cse->expr = expr4; + if (list->expr == mexprsave) + list->expr = expr4; + } + } + } +} + +static COptCSE *cse_intconst(ENode *expr) { + COptCSE *cse = csenodes[EINTCONST]; + + for (; cse; cse = cse->next) { + if (expr->rtype == cse->expr->rtype) + if (CInt64_Equal(cse->expr->data.intval, expr->data.intval)) + return cse; + } + + cse = cse_new(expr); + cse->next = csenodes[EINTCONST]; + csenodes[EINTCONST] = cse; + return cse; +} + +static COptCSE *cse_floatconst(ENode *expr) { + COptCSE *cse = csenodes[EFLOATCONST]; + Float val = expr->data.floatval; + + for (; cse; cse = cse->next) { + if (CMach_CalcFloatDiadicBool(cse->expr->rtype, cse->expr->data.floatval, TK_LOGICAL_EQ, val)) + if (expr->rtype == cse->expr->rtype) + return cse; + } + + cse = cse_new(expr); + cse->next = csenodes[EFLOATCONST]; + csenodes[EFLOATCONST] = cse; + return cse; +} + +static COptCSE *cse_vectorconst(ENode *expr) { + COptCSE *cse = csenodes[EVECTOR128CONST]; + MWVector128 val = expr->data.vector128val; + + for (; cse; cse = cse->next) { + if (CMach_CalcVectorDiadicBool(cse->expr->rtype, &cse->expr->data.vector128val, TK_LOGICAL_EQ, &val)) + if (expr->rtype == cse->expr->rtype) + return cse; + } + + cse = cse_new(expr); + cse->next = csenodes[EVECTOR128CONST]; + csenodes[EVECTOR128CONST] = cse; + return cse; +} + +static COptCSE *cse_objref(ENode *expr) { + COptCSE *cse = csenodes[EOBJREF]; + Object *obj = expr->data.objref; + + for (; cse; cse = cse->next) { + if (cse->expr->data.objref == obj) + return cse; + } + + cse = cse_new(expr); + cse->next = csenodes[EOBJREF]; + csenodes[EOBJREF] = cse; + return cse; +} + +static COptCSE *cse_add_monadic_node(ENode *outer, COptCSE *innercse) { + COptCSE *cse; + + if (!innercse) + return NULL; + + for (cse = csenodes[outer->type]; cse; cse = cse->next) { + if (cse->left == innercse && cse->expr->rtype == outer->rtype) { + CError_ASSERT(524, cse->expr != outer); + cse->x1C++; + return cse; + } + } + + cse = cse_new(outer); + cse->next = csenodes[outer->type]; + csenodes[outer->type] = cse; + cse->left = innercse; + return cse; +} + +static COptCSE *cse_add_typecon_node(ENode *outer, COptCSE *innercse) { + COptCSE *cse; + + if (!innercse) + return NULL; + + for (cse = csenodes[outer->type]; cse; cse = cse->next) { + if (cse->left == innercse && cse->expr->rtype == outer->rtype) { + CError_ASSERT(552, cse->expr != outer); + cse->x1C++; + return cse; + } + } + + cse = cse_new(outer); + cse->next = csenodes[outer->type]; + csenodes[outer->type] = cse; + cse->left = innercse; + return cse; +} + +static COptCSE *cse_add_diadic_node(ENode *outer, COptCSE *leftcse, COptCSE *rightcse) { + COptCSE *cse; + + if (!leftcse || !rightcse) + return NULL; + + for (cse = csenodes[outer->type]; cse; cse = cse->next) { + if (cse->left == leftcse && cse->right == rightcse) { + CError_ASSERT(581, cse->expr != outer); + cse->x1C++; + return cse; + } + } + + cse = cse_new(outer); + cse->next = csenodes[outer->type]; + csenodes[outer->type] = cse; + cse->left = leftcse; + cse->right = rightcse; + return cse; +} + +static COptCSE *cse_add_commdiadic_node(ENode *outer, COptCSE *leftcse, COptCSE *rightcse) { + COptCSE *cse; + + if (!leftcse || !rightcse) + return NULL; + + for (cse = csenodes[outer->type]; cse; cse = cse->next) { + if ((cse->left == leftcse && cse->right == rightcse) || (cse->left == rightcse && cse->right == leftcse)) { + CError_ASSERT(612, cse->expr != outer); + cse->x1C++; + return cse; + } + } + + cse = cse_new(outer); + cse->next = csenodes[outer->type]; + csenodes[outer->type] = cse; + cse->left = leftcse; + cse->right = rightcse; + return cse; +} + +static void sfind_objref(ENode *expr) { + while (1) { + switch (expr->type) { + case ETYPCON: + expr = expr->data.monadic; + break; + case EOBJREF: + objrefnode = expr; + objrefnodes++; + return; + case EADD: + case ESUB: + sfind_objref(expr->data.diadic.left); + expr = expr->data.diadic.right; + break; + default: + return; + } + } +} + +static ENode *find_objref_node(ENode *expr) { + objrefnode = NULL; + objrefnodes = 0; + sfind_objref(expr); + if (objrefnodes == 1) + return objrefnode; + else + return NULL; +} + +static void cse_mem_modify(void) { + COptCSE *cse; + + for (cse = csenodes[EINDIRECT]; cse; cse = cse->next) { + if (ENODE_IS(cse->expr->data.monadic, EOBJREF)) { + Object *obj = cse->expr->data.monadic->data.objref; + CError_ASSERT(672, obj->datatype != DALIAS); + if (obj->datatype == DLOCAL && !obj->u.var.info->noregister) + continue; + } + + cse_inval(cse); + } +} + +static void cse_modify_expression(ENode *expr) { + if (!expr) { + short op; + + cse_remove(); + for (op = 0; op < MAXEXPR; op++) + csenodes[op] = NULL; + + cselist = NULL; + freeoheap(); + } else { + ENode *objnode; + Object *obj; + COptCSE *cse; + + cse_invals = 1; + if (ENODE_IS(expr, EINDIRECT) && (objnode = find_objref_node(expr->data.monadic))) { + do { + obj = objnode->data.objref; + cse_remove(); + for (cse = csenodes[EINDIRECT]; cse; cse = cse->next) { + if ((objnode = find_objref_node(cse->expr->data.monadic)) && obj == objnode->data.objref) + cse_inval(cse); + } + + objnode = find_objref_node(expr->data.monadic); + if (!objnode) { + cse_mem_modify(); + break; + } + } while (obj != objnode->data.objref); + } else { + cse_remove(); + cse_mem_modify(); + } + } +} + +static void cse_pascalcall(ENode *expr) { + ENodeList *list; + + for (list = expr->data.funccall.args; list; list = list->next) + cse_expression(list->node); + + if (ENODE_IS(expr, EFUNCCALLP)) + cse_expression(expr->data.funccall.funcref); + + cse_remove(); + cse_mem_modify(); +} + +static Boolean cse_pusharg(ENodeList *exprs, FuncArg *args) { + Boolean result; + + if (!exprs) + return 1; + + if (args && args != &elipsis && args != &oldstyle) + args = args->next; + if (exprs->next) + result = cse_pusharg(exprs->next, args); + + cse_expression(exprs->node); + return result; +} + +static void cse_ccall(ENode *expr) { + if (cse_pusharg(expr->data.funccall.args, expr->data.funccall.functype->args)) { + if (ENODE_IS(expr, EFUNCCALL)) + cse_expression(expr->data.funccall.funcref); + + cse_remove(); + cse_mem_modify(); + } else { + cse_modify_expression(NULL); + } +} + +static COptCSE *cse_expression(ENode *expr) { + ENode *save; + COptCSE *tmp; + ENodeType nt = expr->type; + + switch (nt) { + case EFUNCCALL: + cse_ccall(expr); + return NULL; + case EFUNCCALLP: + cse_pascalcall(expr); + return NULL; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + save = mexpr; + mexpr = expr; + CError_ASSERT(816, ENODE_IS(expr->data.monadic, EINDIRECT)); + + cse_expression(expr->data.monadic->data.monadic); + cse_modify_expression(expr->data.monadic); + mexpr = save; + return NULL; + + case EINDIRECT: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + return cse_append(cse_add_monadic_node(expr, cse_expression(expr->data.monadic)), expr); + + case ETYPCON: + return cse_append(cse_add_typecon_node(expr, cse_expression(expr->data.monadic)), expr); + + case EMUL: + case EMULV: + case EADDV: + case EADD: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + tmp = cse_expression(expr->data.diadic.left); + if (expr->type == nt) + return cse_append(cse_add_commdiadic_node(expr, tmp, cse_expression(expr->data.diadic.right)), expr); + else + return NULL; + + case EDIV: + case EMODULO: + case ESUBV: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EPMODULO: + case EROTL: + case EROTR: + case EBTST: + tmp = cse_expression(expr->data.diadic.left); + if (expr->type == nt) + return cse_append(cse_add_diadic_node(expr, tmp, cse_expression(expr->data.diadic.right)), expr); + else + return NULL; + + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + CError_ASSERT(887, ENODE_IS(expr->data.diadic.left, EINDIRECT)); + save = mexpr; + mexpr = expr; + cse_expression(expr->data.diadic.right); + if (expr->type == nt) { + cse_expression(expr->data.diadic.left->data.monadic); + cse_modify_expression(expr->data.diadic.left); + mexpr = save; + return NULL; + } else { + cse_modify_expression(NULL); + return NULL; + } + + case ECOMMA: + cse_expression(expr->data.diadic.left); + save = mexpr; + mexpr = expr->data.diadic.right; + tmp = cse_expression(expr->data.diadic.right); + mexpr = save; + return tmp; + + case EINTCONST: + return cse_intconst(expr); + case EFLOATCONST: + return cse_floatconst(expr); + case EVECTOR128CONST: + return cse_vectorconst(expr); + case EOBJREF: + return cse_objref(expr); + + case EBITFIELD: + cse_modify_expression(NULL); + return NULL; + + case ECOND: + cse_expression(expr->data.cond.cond); + cse_modify_expression(NULL); + return NULL; + + case ENULLCHECK: + cse_expression(expr->data.nullcheck.nullcheckexpr); + cse_modify_expression(NULL); + return NULL; + + case ELAND: + case ELOR: + cse_expression(expr->data.diadic.left); + cse_modify_expression(NULL); + return NULL; + + case ESTRINGCONST: + case ELABEL: + return NULL; + + case EPRECOMP: + CError_FATAL(948); + + default: + CError_FATAL(951); + return NULL; + } +} + +static void cse_block(COptBlock *block) { + Statement *stmt; + COptBlock *check; + COptBlockList *scan; + COptBlock *best; + short i; + SInt32 counter; + UInt32 starttime; + + starttime = COS_GetTicks(); + counter = 0; + + while (1) { + cse_invals = 0; + currentblock = block; + block->x1E = 1; + + for (stmt = block->stmt, i = block->x1C; i > 0; stmt = stmt->next, i--) { + switch (stmt->type) { + case ST_EXPRESSION: + case ST_SWITCH: + case ST_IFGOTO: + case ST_IFNGOTO: + mexpr = stmt->expr; + cse_expression(mexpr); + break; + case ST_RETURN: + mexpr = stmt->expr; + if (mexpr) + cse_expression(mexpr); + break; + } + } + + i = 0; + for (scan = block->blocks2; scan; scan = scan->next) { + check = scan->block; + if (!check->x1E && check->blocks && !check->blocks->next && check->blocks->block == block) { + best = check; + i++; + } + } + + if (i != 1) + break; + + block = best; + if (COS_GetTicks() > (starttime + 60)) { + if (counter++ & 1) { + if (CWDisplayLines(cparamblkptr->context, lines)) + CError_UserBreak(); + } else { + if (CWDisplayLines(cparamblkptr->context, lines + 1)) + CError_UserBreak(); + } + starttime = COS_GetTicks(); + } + + if (cse_invals) + cse_cleanup(); + } + + cse_remove(); +} + +static void CSE(void) { + COptBlock *block; + + for (block = basicblocks->next; block; block = block->next) + block->x1E = 0; + + for (block = basicblocks->next; block; block = block->next) { + if (!block->x1E) { + short op; + + for (op = 0; op < MAXEXPR; op++) + csenodes[op] = NULL; + + cselist = NULL; + cse_found = 0; + cse_block(block); + freeoheap(); + } + } +} + +static short TestSetBit(short *set, short bit) { + return set[bit >> 4] & bitmasks[bit & 15]; +} + +static void SetSetBit(short *set, short bit) { + set[bit >> 4] |= bitmasks[bit & 15]; +} + +UInt32 RegAllocMask(short var) { + COptBlock *block; + UInt32 mask = 0; + + for (block = basicblocks; block; block = block->next) { + if (TestSetBit(block->set1, var) || TestSetBit(block->set2, var)) + mask |= block->allocmask; + } + + return mask; +} + +void MarkRegAllocMask(short var, short bit, Boolean flag) { + COptBlock *block; + UInt32 mask = 1 << bit; + + if (flag) { + for (block = basicblocks; block; block = block->next) { + if (TestSetBit(block->set1, var) || TestSetBit(block->set2, var)) + block->allocmask |= mask; + } + } else { + for (block = basicblocks; block; block = block->next) { + block->allocmask |= mask; + } + } +} + +static COptBlock *newblock(void) { + COptBlock *block; + short i; + short max; + + block = lalloc(sizeof(COptBlock) + (setbytes * 2)); + block->x1E = 0; + block->next = NULL; + block->blocks = NULL; + block->blocks2 = NULL; + block->allocmask = 0; + block->set1 = (short *) (((long) block) + sizeof(COptBlock)); + block->set2 = (short *) (((long) block) + setbytes + sizeof(COptBlock)); + + for (i = 0, max = setbytes / 2; i < max; i++) { + block->set1[i] = 0; + block->set2[i] = 0; + } + + return block; +} + +static void MarkFollow(COptBlock *block) { + COptBlockList *list; + +restart: + block->x1E = 1; + if ((list = block->blocks2)) { + while (1) { + if (!list->block->x1E) { + if (!list->next) { + block = list->block; + goto restart; + } + MarkFollow(list->block); + list = list->next; + } else { + list = list->next; + if (!list) + break; + } + } + } +} + +static Boolean CheckInit(short var) { + Boolean result; + COptBlock *block; + + result = 1; + for (block = basicblocks; block; block = block->next) { + if (!block->x1E && TestSetBit(block->set2, var)) + MarkFollow(block); + } + + for (block = basicblocks; block; block = block->next) { + if (!block->x1E) { + if (TestSetBit(block->set1, var)) + result = 0; + } else { + block->x1E = 0; + } + } + + return result; +} + +static void CheckVarInit(void) { + COptBlock *block; + VarInfo *vi; + ObjectList *list; + + for (block = basicblocks; block; block = block->next) + block->x1E = 0; + + for (list = locals; list; list = list->next) { + if (list->object->datatype == DLOCAL && !IsTempName(list->object->name) && !is_volatile_object(list->object)) { + vi = list->object->u.var.info; + if (vi->used && !CheckInit(vi->varnumber)) { + if (!IS_TYPE_CLASS(list->object->type) || !CClass_IsEmpty(TYPE_CLASS(list->object->type))) { + CError_SetErrorToken(&vi->deftoken); + CError_Warning(CErrorStr185, list->object->name->name); + } + } + } + } +} + +static void AddVar(Object *obj, Boolean whichSet) { + VarInfo *vi; + + if (obj->datatype == DLOCAL) { + vi = obj->u.var.info; + if (!whichSet) { + SetSetBit(currentblock->set1, vi->varnumber); + } else { + if (!TestSetBit(currentblock->set1, vi->varnumber)) + SetSetBit(currentblock->set2, vi->varnumber); + } + } +} + +static void CheckExpr(ENode *expr) { + ENodeList *list; + + while (1) { + switch (expr->type) { + case EINDIRECT: + if (ENODE_IS(expr->data.monadic, EOBJREF)) { + AddVar(expr->data.monadic->data.objref, 0); + return; + } + expr = expr->data.monadic; + break; + case EOBJREF: + AddVar(expr->data.objref, 1); + return; + case EFUNCCALL: + case EFUNCCALLP: + CheckExpr(expr->data.funccall.funcref); + for (list = expr->data.funccall.args; list; list = list->next) + CheckExpr(list->node); + return; + case ECOND: + CheckExpr(expr->data.cond.cond); + CheckExpr(expr->data.cond.expr1); + CheckExpr(expr->data.cond.expr2); + return; + case EASS: + if (ENODE_IS_INDIRECT_TO(expr->data.diadic.left, EOBJREF)) { + CheckExpr(expr->data.diadic.right); + AddVar(expr->data.diadic.left->data.monadic->data.objref, 1); + return; + } + case EMUL: + case EMULV: + case EDIV: + case EMODULO: + case EADDV: + case ESUBV: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBCLR: + case EBTST: + case EBSET: + CheckExpr(expr->data.diadic.left); + expr = expr->data.diadic.right; + break; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + expr = expr->data.monadic; + break; + case ENULLCHECK: + CheckExpr(expr->data.nullcheck.nullcheckexpr); + expr = expr->data.nullcheck.condexpr; + break; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EPRECOMP: + case ELABEL: + case EVECTOR128CONST: + return; + default: + CError_FATAL(1332); + } + } +} + +static short CheckPath(COptBlock *block, short var) { + COptBlockList *list; + + if (block->x1E) + return TestSetBit(block->set1, var); + + block->x1E = 1; + if (TestSetBit(block->set1, var)) + return -1; + if (TestSetBit(block->set2, var)) + return 0; + + for (list = block->blocks2; list; list = list->next) { + if (CheckPath(list->block, var)) { + SetSetBit(block->set1, var); + return -1; + } + } + + return 0; +} + +static void MarkPre(COptBlock *block, short var) { + COptBlockList *list; + +restart: + block->x1E = 1; + for (list = block->blocks; list; list = list->next) { + if (!list->block->x1E) { + if (!TestSetBit(list->block->set2, var)) { + SetSetBit(list->block->set1, var); + if (!list->next) { + block = list->block; + goto restart; + } + MarkPre(list->block, var); + } else { + list->block->x1E = 1; + } + } + } +} + +static void CheckVarUsage(void) { + short local; + COptBlock *block; + short counter; + + for (currentblock = basicblocks; currentblock; currentblock = currentblock->next) { + Statement *stmt = currentblock->stmt; + if (currentblock->x1C > 0 && stmt->type == ST_LABEL && (stmt->flags & StmtFlag_1)) { + short i; + for (i = 0; i < localcount; i++) + SetSetBit(currentblock->set2, i); + } + + for (counter = currentblock->x1C; counter > 0; counter--) { + if (stmt->type >= ST_EXPRESSION && stmt->type <= ST_GOTOEXPR && stmt->expr) + CheckExpr(stmt->expr); + stmt = stmt->next; + } + } + + for (local = 0; local < localcount; local++) { + for (block = basicblocks; block; block = block->next) { + if (!block->x1E && TestSetBit(block->set1, local)) + MarkPre(block, local); + } + for (block = basicblocks; block; block = block->next) { + block->x1E = 0; + } + } +} + +static void SplitCommaExpressions(void) { + COptBlock *block; + Statement *stmt; + ENode *expr; + Statement *stmtcopy; + short counter; + Boolean flag; + + block = basicblocks->next; + while (block) { + stmt = block->stmt; + counter = block->x1C; + flag = 1; + while (counter > 0) { + if (stmt->type >= ST_EXPRESSION && stmt->type <= ST_GOTOEXPR) { + if ((expr = stmt->expr) && ENODE_IS(expr, ECOMMA)) { + stmtcopy = lalloc(sizeof(Statement)); + *stmtcopy = *stmt; + stmt->next = stmtcopy; + stmt->type = ST_EXPRESSION; + stmt->expr = expr->data.diadic.left; + stmtcopy->expr = expr->data.diadic.right; + block->x1C++; + flag = 0; + break; + } + } + + stmt = stmt->next; + counter--; + } + + if (flag) + block = block->next; + } +} + +static void BasicBlockAnalyze(Statement *stmt) { + COptBlock *block; + ObjectList *objlist; + COptBlockList *scan; + COptBlockList *list; + CLabel *label; + COptBlock *iblock; + COptBlock *oblock; + SwitchCase *swcase; + + setbytes = 2 * ((localcount - 1) / 16) + 2; + if (copts.globaloptimizer) { + setbytes += 32; + extravars = 0; + } + + block = newblock(); + basicblocks = block; + block->stmt = NULL; + block->x1C = 0; + + if (stmt) { + list = lalloc(sizeof(COptBlockList)); + list->next = NULL; + block->blocks2 = list; + list->block = (COptBlock *) stmt; + } + + for (objlist = arguments; objlist; objlist = objlist->next) { + SetSetBit(block->set2, objlist->object->u.var.info->varnumber); + } + + while (stmt) { + int counter; + + block->next = newblock(); + block = block->next; + block->stmt = stmt; + counter = 1; + + innerLoop: + switch (stmt->type) { + case ST_ASM: + label = InlineAsm_GetReferencedLabel(stmt); + if (!label) + goto jumpahead; + list = lalloc(sizeof(COptBlockList)); + list->next = block->blocks2; + block->blocks2 = list; + list->block = (COptBlock *) label->stmt; + if (stmt->next) { + list = lalloc(sizeof(COptBlockList)); + list->next = block->blocks2; + block->blocks2 = list; + list->block = (COptBlock *) stmt->next; + } + stmt = stmt->next; + block->x1C = counter; + continue; + case ST_NOP: + case ST_LABEL: + case ST_ENTRY: + if (stmt->next && stmt->next->type != ST_LABEL) { + stmt = stmt->next; + counter++; + goto innerLoop; + } + break; + case ST_EXPRESSION: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + jumpahead: + if (stmt->next && stmt->next->type == ST_GOTO) { + stmt = stmt->next; + counter++; + goto innerLoop; + } + break; + } + + switch (stmt->type) { + case ST_SWITCH: + label = ((SwitchInfo *) stmt->label)->defaultlabel; + if (label != cleanreturnlabel) { + list = lalloc(sizeof(COptBlockList)); + list->next = block->blocks2; + block->blocks2 = list; + list->block = (COptBlock *) label->stmt; + } + for (swcase = ((SwitchInfo *) stmt->label)->cases; swcase; swcase = swcase->next) { + label = swcase->label; + if (label != cleanreturnlabel) { + list = lalloc(sizeof(COptBlockList)); + list->next = block->blocks2; + block->blocks2 = list; + list->block = (COptBlock *) label->stmt; + } + } + break; + case ST_RETURN: + case ST_EXIT: + case ST_GOTOEXPR: + break; + case ST_GOTO: + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_OVF: + label = stmt->label; + if (label != cleanreturnlabel) { + list = lalloc(sizeof(COptBlockList)); + list->next = block->blocks2; + block->blocks2 = list; + list->block = (COptBlock *) label->stmt; + } + if (stmt->type == ST_GOTO) + break; + default: + if (stmt->next) { + list = lalloc(sizeof(COptBlockList)); + list->next = block->blocks2; + block->blocks2 = list; + list->block = (COptBlock *) stmt->next; + } + break; + } + + stmt = stmt->next; + block->x1C = counter; + } + + for (oblock = basicblocks; oblock; oblock = oblock->next) { + for (scan = oblock->blocks2; scan; scan = scan->next) { + stmt = (Statement *) scan->block; + for (iblock = basicblocks->next; iblock; iblock = iblock->next) { + if (iblock->stmt == stmt) { + scan->block = iblock; + list = lalloc(sizeof(COptBlockList)); + list->next = iblock->blocks; + iblock->blocks = list; + list->block = oblock; + break; + } + } + + CError_ASSERT(1602, iblock); + } + } + + SplitCommaExpressions(); + CheckVarUsage(); +} + +static CLabel *finallabel(CLabel *label, Statement *stmt) { + Statement *scan; + + for (scan = label->stmt; scan; scan = scan->next) { + if (scan->type > ST_LABEL) { + if (scan == stmt) + return label; + if (scan->type == ST_GOTO) { + if (scan->label != label) + stmtchanged = 1; + return scan->label; + } + return label; + } + } + + return label; +} + +static void optimizegoto(Statement *stmt) { + Statement *scan; + + for (scan = stmt->next; scan; scan = scan->next) { + if (stmt->label->stmt == scan) { + stmt->type = ST_NOP; + stmtchanged = 1; + return; + } + if (scan->type > ST_LABEL) + break; + } + + stmt->label = finallabel(stmt->label, stmt); +} + +static void removeif(Statement *stmt, Boolean flag) { + if (((stmt->type == ST_IFGOTO) && flag) || ((stmt->type == ST_IFNGOTO) && !flag)) { + Statement *copy = lalloc(sizeof(Statement)); + *copy = *stmt; + copy->type = ST_GOTO; + stmt->next = copy; + } + stmt->type = ST_EXPRESSION; + stmtchanged = 1; +} + +static void optimizeif(Statement *stmt) { + Statement *scan; + Statement *scan2; + Boolean flag; + + if (iszero(stmt->expr)) { + removeif(stmt, 0); + return; + } + if (isnotzero(stmt->expr)) { + removeif(stmt, 1); + return; + } + + for (scan = stmt->next, flag = 0; scan; scan = scan->next) { + if (scan->type > ST_LABEL) { + if (scan->type == ST_GOTO) { + if (scan->label == stmt->label) { + stmt->type = ST_EXPRESSION; + stmtchanged = 1; + return; + } + + if (!flag) { + for (scan2 = scan->next; scan2; scan2 = scan2->next) { + if (scan2->type > ST_LABEL) + break; + if (stmt->label->stmt == scan2) { + stmt->label = scan->label; + scan->type = ST_NOP; + if (stmt->type == ST_IFGOTO) + stmt->type = ST_IFNGOTO; + else + stmt->type = ST_IFGOTO; + stmtchanged = 1; + stmt->label = finallabel(stmt->label, stmt); + return; + } + } + } + } else if (scan->type == ST_RETURN && !scan->expr && !static_for_inlines && !flag) { + for (scan2 = scan->next; scan2; scan2 = scan2->next) { + if (scan2->type > ST_LABEL) + break; + if (stmt->label->stmt == scan2) { + stmt->label = cleanreturnlabel; + needs_cleanup = 1; + scan->type = ST_NOP; + if (stmt->type == ST_IFGOTO) + stmt->type = ST_IFNGOTO; + else + stmt->type = ST_IFGOTO; + stmtchanged = 1; + return; + } + } + } + break; + } + + if (scan->type == ST_LABEL) + flag = 1; + + if (stmt->label->stmt == scan) { + stmt->type = ST_EXPRESSION; + stmtchanged = 1; + return; + } + } + + stmt->label = finallabel(stmt->label, stmt); +} + +static void optimizeswitch(Statement *stmt) { + SwitchInfo *info; + SwitchCase *swcase; + + info = (SwitchInfo *) stmt->label; + CError_ASSERT(1746, info && info->cases && info->defaultlabel); + + info->defaultlabel = finallabel(info->defaultlabel, stmt); + for (swcase = info->cases; swcase; swcase = swcase->next) + swcase->label = finallabel(swcase->label, stmt); + + if (ENODE_IS(stmt->expr, EINTCONST)) { + for (swcase = info->cases; swcase; swcase = swcase->next) { + if (CInt64_GreaterEqual(swcase->min, stmt->expr->data.intval) && CInt64_LessEqual(swcase->max, stmt->expr->data.intval)) + break; + } + + stmt->type = ST_GOTO; + stmt->label = swcase ? swcase->label : info->defaultlabel; + } +} + +static void removeunusedlabels(Statement *stmt) { + Statement *scan; + CLabel *label; + SwitchCase *swcase; + ExceptionAction *action; + + for (scan = stmt; scan; scan = scan->next) + scan->marked = 0; + + for (scan = stmt; scan; scan = scan->next) { + switch (scan->type) { + case ST_GOTO: + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_OVF: + if (scan->label->stmt) + scan->label->stmt->marked = 1; + break; + case ST_SWITCH: + ((SwitchInfo *) scan->label)->defaultlabel->stmt->marked = 1; + for (swcase = ((SwitchInfo *) scan->label)->cases; swcase; swcase = swcase->next) + swcase->label->stmt->marked = 1; + break; + case ST_ASM: + if ((label = InlineAsm_GetReferencedLabel(scan))) + label->stmt->marked = 1; + if ((label = InlineAsm_GetReferencedLabel2(scan))) + label->stmt->marked = 1; + break; + case ST_BEGINLOOP: + ((LoopInfo *) scan->expr)->stmt->marked = 1; + break; + case ST_ENDLOOP: + if (scan->next->type == ST_GOTO && scan->next->next->type == ST_LABEL) + scan->next->next->marked = 1; + break; + default: + for (action = scan->dobjstack; action; action = action->prev) { + if (action->type == EAT_CATCHBLOCK) { + action->data.catch_block.catch_label->stmt->marked = 1; + action->data.catch_block.catch_label->stmt->flags = action->data.catch_block.catch_label->stmt->flags | StmtFlag_1; + } else if (action->type == EAT_SPECIFICATION) { + action->data.specification.unexp_label->stmt->marked = 1; + action->data.specification.unexp_label->stmt->flags = action->data.specification.unexp_label->stmt->flags | StmtFlag_1; + } + } + } + } + + for (scan = stmt; scan; scan = scan->next) { + if (scan->type == ST_LABEL && !scan->marked && !(scan->flags & StmtFlag_1)) { + scan->type = ST_NOP; + stmtchanged = 1; + } + } +} + +static void optimizebranches(Statement *stmt) { + removeunusedlabels(stmt); + while (stmt) { + switch (stmt->type) { + case ST_GOTO: + optimizegoto(stmt); + break; + case ST_IFGOTO: + case ST_IFNGOTO: + optimizeif(stmt); + break; + case ST_SWITCH: + optimizeswitch(stmt); + break; + } + stmt = stmt->next; + } +} + +void SetVarUsage(Object *obj, Boolean noregister) { + VarInfo *vi; + CError_ASSERT(1875, obj->datatype != DALIAS); + + if (obj->datatype == DLOCAL || obj->datatype == DNONLAZYPTR) { + vi = obj->u.var.info; + vi->used = 1; + if (!copts.globaloptimizer) { + if (copts.optimizesize) + vi->usage++; + else + vi->usage += curstmtvalue; + } + + if (noregister) + vi->noregister = 1; + } +} + +static void checkexpression(ENode *expr) { + ENodeList *list; + + while (1) { + switch (expr->type) { + case EOBJREF: + SetVarUsage(expr->data.objref, 1); + return; + case EINDIRECT: + if (ENODE_IS(expr->data.monadic, EOBJREF)) { + SetVarUsage(expr->data.monadic->data.objref, 0); + return; + } + expr = expr->data.monadic; + break; + case EFUNCCALL: + case EFUNCCALLP: + copt_isleaffunction = 0; + checkexpression(expr->data.funccall.funcref); + for (list = expr->data.funccall.args; list; list = list->next) + checkexpression(list->node); + return; + case ECOND: + case ECONDASS: + checkexpression(expr->data.cond.cond); + checkexpression(expr->data.cond.expr1); + checkexpression(expr->data.cond.expr2); + return; + case EMUL: + case EMULV: + case EDIV: + case EMODULO: + case EADDV: + case ESUBV: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + case EASS: + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBCLR: + case EBTST: + case EBSET: + checkexpression(expr->data.diadic.left); + expr = expr->data.diadic.right; + break; + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EMONMIN: + case EBINNOT: + case ELOGNOT: + case EFORCELOAD: + case ETYPCON: + case EBITFIELD: + expr = expr->data.monadic; + break; + case ENULLCHECK: + checkexpression(expr->data.nullcheck.nullcheckexpr); + expr = expr->data.nullcheck.condexpr; + break; + case EINTCONST: + case EFLOATCONST: + case EPRECOMP: + case ELABEL: + case EVECTOR128CONST: + return; + case ESTRINGCONST: + return; + default: + CError_FATAL(1998); + } + } +} + +static void checklocalusage(Statement *stmt) { + Statement *scan; + + for (scan = stmt; scan; scan = scan->next) { + if (scan->type >= ST_EXPRESSION && scan->type <= ST_GOTOEXPR && scan->expr) { + curstmtvalue = scan->value; + checkexpression(scan->expr); + } else if (scan->type == ST_ASM) { + curstmtvalue = scan->value; + InlineAsm_CheckLocalUsage(scan); + } + } +} + +static void colorcode(Statement *stmt) { + CLabel *label; + SwitchCase *swcase; + + while (stmt && !stmt->marked) { + stmt->marked = 1; + switch (stmt->type) { + case ST_GOTOEXPR: + return; + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_OVF: + colorcode(stmt->label->stmt); + break; + case ST_GOTO: + case ST_EXIT: + stmt = stmt->label->stmt; + continue; + case ST_RETURN: + return; + case ST_SWITCH: + for (swcase = ((SwitchInfo *) stmt->label)->cases; swcase; swcase = swcase->next) + colorcode(swcase->label->stmt); + stmt = ((SwitchInfo *) stmt->label)->defaultlabel->stmt; + continue; + case ST_ASM: + if ((label = InlineAsm_GetReferencedLabel(stmt))) + colorcode(label->stmt); + if ((label = InlineAsm_GetReferencedLabel2(stmt))) + colorcode(label->stmt); + break; + case ST_ENDLOOP: + if (stmt->next && stmt->next->type == ST_GOTO) { + stmt = stmt->next; + stmt->marked = 1; + } + break; + case ST_NOP: + case ST_LABEL: + case ST_EXPRESSION: + case ST_ENTRY: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + case ST_BEGINLOOP: + break; + default: + CError_FATAL(2096); + } + stmt = stmt->next; + } +} + +static void removeunusedcode(Statement *stmt) { + Statement *scan; + + for (scan = stmt; scan; scan = scan->next) + scan->marked = 0; + + colorcode(stmt); + for (scan = stmt; scan; scan = scan->next) { + if (!scan->marked && (scan->flags & StmtFlag_1)) + colorcode(scan); + } + + for (scan = stmt; scan; scan = scan->next) { + if (!scan->marked && scan->type != ST_NOP) { + scan->type = ST_NOP; + stmtchanged = 1; + } + } +} + +static void COpt_ReturnCheck(Object *obj, Statement *stmt) { + if ((copts.pedantic || copts.cplusplus) && obj && TYPE_FUNC(obj->type)->functype != &stvoid) { + while (stmt) { + if (!stmt->next && stmt->type != ST_GOTO && stmt->type != ST_RETURN) { + CError_Warning(CErrorStr184); + break; + } + + if (stmt->type == ST_RETURN && !stmt->expr && !(stmt->flags & StmtFlag_8)) { + CError_Warning(CErrorStr184); + break; + } + + stmt = stmt->next; + } + } +} + +static void COpt_Optimize(Object *obj, Statement *stmt) { + Statement **ptr; + + do { + stmtchanged = 0; + optimizebranches(stmt->next); + removeunusedcode(stmt->next); + } while (stmtchanged); + + ptr = &stmt->next; + while (*ptr) { + if ((*ptr)->type == ST_NOP) + *ptr = (*ptr)->next; + else + ptr = &(*ptr)->next; + } +} + +static void COpt_ELABELCallBack(ENode *expr) { + CError_ASSERT(2195, expr->data.label->stmt && expr->data.label->stmt->type == ST_LABEL); + expr->data.label->stmt->flags = expr->data.label->stmt->flags | StmtFlag_1; +} + +void COpt_SimpleOptimizer(Object *obj, Statement *stmt) { + Statement *scan; + + for (scan = stmt; scan; scan = scan->next) { + if ((scan->type >= ST_EXPRESSION && scan->type <= ST_GOTOEXPR) && scan->expr) + CExpr_SearchExprTree(scan->expr, COpt_ELABELCallBack, 1, ELABEL); + } + + static_for_inlines = 1; + cleanreturnlabel = NULL; + COpt_Optimize(obj, stmt); + COpt_ReturnCheck(obj, stmt); +} + +Statement *COpt_Optimizer(Object *obj, Statement *stmt) { + copt_isleaffunction = 1; + if (copts.globaloptimizer) + stmt = IRO_Optimizer(obj, stmt); + + static_for_inlines = 0; + COpt_Optimize(obj, stmt); + + if (obj && !(obj->qual & Q_INLINE)) + COpt_ReturnCheck(obj, stmt); + + checklocalusage(stmt->next); + return stmt; +} diff --git a/compiler_and_linker/FrontEnd/Optimizer/BitVector.h b/compiler_and_linker/FrontEnd/Optimizer/BitVector.h new file mode 100644 index 0000000..a6830d6 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/BitVector.h @@ -0,0 +1,36 @@ +#ifndef COMPILER_IROBITVECT_H +#define COMPILER_IROBITVECT_H + +#include "compiler/common.h" +#include "compiler/CError.h" + +typedef struct BitVector { + UInt32 size; + UInt32 data[0]; +} BitVector; + +extern void Bv_AllocVector(BitVector **bv, UInt32 size); +extern void Bv_AllocVectorLocal(BitVector **bv, UInt32 size); +extern void Bv_ClearBit(UInt32 bit, BitVector *bv); +extern void Bv_And(const BitVector *a, BitVector *b); +extern void Bv_Or(const BitVector *a, BitVector *b); +extern Boolean Bv_BitsInCommon(const BitVector *a, const BitVector *b); +extern Boolean Bv_Compare(const BitVector *a, const BitVector *b); +extern void Bv_Minus(const BitVector *a, BitVector *b); +extern void Bv_Copy(const BitVector *src, BitVector *dst); +extern void Bv_Clear(BitVector *bv); +extern void Bv_Set(BitVector *bv); +extern Boolean Bv_IsSubset(const BitVector *a, const BitVector *b); +extern Boolean Bv_IsEmpty(const BitVector *bv); + +CW_INLINE void Bv_SetBit(UInt32 bit, BitVector *bv) { + if ((bit / 32) < bv->size) { + bv->data[bit / 32] |= 1 << (bit & 31); + } else { + CError_FATAL(56); + } +} + +#define Bv_IsBitSet(_bit, _bv) ( (((_bit) >> 5) < (_bv)->size) && ((_bv)->data[(_bit) >> 5] & (1 << ((_bit) & 31))) ) + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IROUseDef.c b/compiler_and_linker/FrontEnd/Optimizer/IROUseDef.c new file mode 100644 index 0000000..ba3f817 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IROUseDef.c @@ -0,0 +1,1432 @@ +#include "IROUseDef.h" +#include "IroDump.h" +#include "IroVars.h" +#include "IroFlowgraph.h" +#include "IroLinearForm.h" +#include "IroMalloc.h" +#include "IroPointerAnalysis.h" +#include "IroTransform.h" +#include "IroUtil.h" +#include "compiler/CompilerTools.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/objects.h" +#include "compiler/types.h" +#include "compiler/InlineAsm.h" +#include "compiler/InlineAsmPPC.h" + +ENodeType IRO_NonAssignmentOp[MAXEXPR]; +typedef CInt64 (*AssignmentFoldingFunc)(CInt64, CInt64); +static AssignmentFoldingFunc AssignmentFoldingFunction[MAXEXPR]; +static SInt32 NumDefs; +static IRODef *FirstDef; +static IRODef *LastDef; +static SInt32 NumUses; +static BitVector *Reaches; +static BitVector *MightReachAnyUse; +static BitVector *alldefs; +static BitVector *alluses; +static BitVector *defset; +static BitVector *useset; +IROUse *IRO_FirstVarUse; +IROUse *IRO_LastVarUse; + +// forward decls +static void AddDefToRange(IRODef *def); + +static void MakeDef(VarRecord *var, IROLinear *linear, IRONode *node, Boolean flag) { + IRODef *def = oalloc(sizeof(IRODef)); + + def->index = NumDefs++; + def->node = node; + def->linear = linear; + def->var = var; + def->globalnext = NULL; + def->x18 = 0; + def->x1A = Inline_IsObjectData(var->object); + def->x1B = var->xB; + def->x1C = flag; + def->x1D = 0; + + if (FirstDef) + LastDef->globalnext = def; + else + FirstDef = def; + LastDef = def; + + def->varnext = var->defs; + var->defs = def; +} + +static void MakeUse(VarRecord *var, IROLinear *linear, IRONode *node) { + IROUse *use = oalloc(sizeof(IROUse)); + + use->index = NumUses++; + use->node = node; + use->linear = linear; + use->var = var; + use->globalnext = NULL; + use->x1C = 0; + + if (IRO_FirstVarUse) + IRO_LastVarUse->globalnext = use; + else + IRO_FirstVarUse = use; + IRO_LastVarUse = use; + + use->varnext = var->uses; + var->uses = use; +} + +static void FindDefsAndUses(void) { + VarRecord *var; + IROLinear *linear; + IRONode *node; + + NumDefs = 0; + NumUses = 0; + IRO_FirstVarUse = NULL; + FirstDef = NULL; + + for (var = IRO_FirstVar; var; var = var->next) { + var->defs = NULL; + var->uses = NULL; + var->xC = 0; + } + + for (node = IRO_FirstNode; node; node = node->nextnode) { + for (linear = node->first; linear; linear = linear->next) { + if (IS_LINEAR_ENODE(linear, EOBJREF)) { + Object *obj = linear->u.node->data.objref; + if ((linear->flags & IROLF_Ind) && (!(linear->flags & IROLF_Assigned) || (linear->flags & IROLF_Used))) { + if ((var = IRO_FindVar(obj, 0, 1))) + MakeUse(var, linear, node); + } + } + + if (IRO_IsAssignment(linear) && (var = IRO_FindAssigned(linear))) { + MakeDef( + var, + linear, + node, + (linear->rtype->size == var->object->type->size) && !IRO_IsBitField + ); + } + + if (linear->type == IROLinearAsm) { + IAEffects effects; + int i; + CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); + + for (i = 0; i < effects.numoperands; i++) { + var = IRO_FindVar(effects.operands[i].object, 0, 1); + switch (effects.operands[i].type) { + case IAEffect_0: + MakeUse(var, linear, node); + break; + case IAEffect_1: + MakeDef( + var, + linear, + node, + (effects.operands[i].offset == 0) && (effects.operands[i].size == var->object->type->size) + ); + break; + case IAEffect_2: + MakeDef(var, linear, node, 0); + break; + case IAEffect_4: + MakeUse(var, linear, node); + MakeDef( + var, + linear, + node, + (effects.operands[i].offset == 0) && (effects.operands[i].size == var->object->type->size) + ); + break; + } + } + } + + if (linear == node->last) + break; + } + } + + for (var = IRO_FirstVar; var; var = var->next) + MakeDef(var, NULL, NULL, 1); +} + +static void MarkUses(Object *obj) { + VarRecord *var; + IRODef *def; + + if ((var = IRO_FindVar(obj, 0, 1))) { + for (def = var->defs; def; def = def->varnext) { + if (Bv_IsBitSet(def->index, Reaches)) { + Bv_SetBit(def->index, MightReachAnyUse); + def->x18++; + } + } + + var->xC = 1; + } +} + +static Boolean IsIncOrDec(IROLinear *linear) { + switch (linear->type) { + case IROLinearOp1Arg: + if (linear->nodetype == EPOSTINC || linear->nodetype == EPOSTDEC || linear->nodetype == EPREINC || linear->nodetype == EPREDEC) { + if (!(linear->u.monadic->flags & IROLF_BitfieldIndirect)) + return 1; + } + break; + case IROLinearOp2Arg: + if (linear->nodetype == EADDASS || linear->nodetype == ESUBASS) { + if (IRO_IsIntConstant(linear->u.diadic.right) && !(linear->u.diadic.left->flags & IROLF_BitfieldIndirect)) + return 1; + } + break; + } + + return 0; +} + +static Boolean IsOtherSelfAssignment(IROLinear *linear) { + switch (linear->type) { + case IROLinearOp2Arg: + switch (linear->nodetype) { + case EMULASS: + case EDIVASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + if (IRO_IsIntConstant(linear->u.diadic.right)) + return 1; + break; + } + break; + } + + return 0; +} + +CInt64 IRO_GetSelfAssignmentVal(IROLinear *linear) { + CInt64 result; + + if (linear->type == IROLinearOp1Arg) { + switch (linear->nodetype) { + case EPOSTINC: + case EPREINC: + CInt64_SetLong(&result, 1); + break; + case EPOSTDEC: + case EPREDEC: + CInt64_SetLong(&result, -1); + break; + default: + CError_FATAL(445); + } + + if (IS_TYPE_POINTER_ONLY(linear->rtype)) { + CInt64 mul; + CInt64_SetLong(&mul, TPTR_TARGET(linear->rtype)->size); + result = CInt64_Mul(result, mul); + } + } else if (linear->type == IROLinearOp2Arg) { + switch (linear->nodetype) { + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + result = linear->u.diadic.right->u.node->data.intval; + break; + case ESUBASS: + result = linear->u.diadic.right->u.node->data.intval; + result = CInt64_Neg(result); + break; + default: + CError_FATAL(491); + } + } else { + CError_FATAL(496); + } + + return result; +} + +static void UpdateUse(IROLinear *linear, CInt64 val, Type *type) { + IROLinear *father; + IROLinear *repl; + IROLinear *newdiadic; + + if ((father = IRO_LocateFather(linear))) { + switch (father->type) { + case IROLinearOp1Arg: + switch (father->nodetype) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + val = CInt64_Add(val, IRO_GetSelfAssignmentVal(father)); + father->nodetype = EADDASS; + father->type = IROLinearOp2Arg; + repl = IRO_NewIntConst(val, type); + father->u.diadic.right = repl; + IRO_PasteAfter(repl, repl, linear); + return; + } + break; + case IROLinearOp2Arg: + if (IRO_IsIntConstant(father->u.diadic.right)) { + switch (father->nodetype) { + case EADD: + case EADDASS: + father->u.diadic.right->u.node->data.intval = CInt64_Add( + father->u.diadic.right->u.node->data.intval, val); + return; + case ESUB: + case ESUBASS: + father->u.diadic.right->u.node->data.intval = CInt64_Sub( + father->u.diadic.right->u.node->data.intval, val); + return; + } + } + break; + } + } + + repl = IRO_NewIntConst(val, type); + newdiadic = IRO_NewLinear(IROLinearOp2Arg); + newdiadic->index = ++IRO_NumLinear; + newdiadic->nodetype = EADD; + newdiadic->u.diadic.left = linear; + newdiadic->u.diadic.right = repl; + newdiadic->rtype = linear->rtype; + repl->next = newdiadic; + IRO_LocateFather_Cut_And_Paste_Without_Nopping(linear, newdiadic); + IRO_PasteAfter(repl, newdiadic, linear); +} + +void IRO_InitializeNonAssignmentOpArray(void) { + int i; + + for (i = 0; i < MAXEXPR; i++) + IRO_NonAssignmentOp[i] = MAXEXPR; + + IRO_NonAssignmentOp[EPOSTINC] = MAXEXPR; + IRO_NonAssignmentOp[EPOSTDEC] = MAXEXPR; + IRO_NonAssignmentOp[EPREINC] = MAXEXPR; + IRO_NonAssignmentOp[EPREDEC] = MAXEXPR; + IRO_NonAssignmentOp[EINDIRECT] = MAXEXPR; + IRO_NonAssignmentOp[EMONMIN] = MAXEXPR; + IRO_NonAssignmentOp[EBINNOT] = MAXEXPR; + IRO_NonAssignmentOp[ELOGNOT] = MAXEXPR; + IRO_NonAssignmentOp[EFORCELOAD] = MAXEXPR; + IRO_NonAssignmentOp[EMUL] = MAXEXPR; + IRO_NonAssignmentOp[EMULV] = MAXEXPR; + IRO_NonAssignmentOp[EDIV] = MAXEXPR; + IRO_NonAssignmentOp[EMODULO] = MAXEXPR; + IRO_NonAssignmentOp[EADDV] = MAXEXPR; + IRO_NonAssignmentOp[ESUBV] = MAXEXPR; + IRO_NonAssignmentOp[EADD] = MAXEXPR; + IRO_NonAssignmentOp[ESUB] = MAXEXPR; + IRO_NonAssignmentOp[ESHL] = MAXEXPR; + IRO_NonAssignmentOp[ESHR] = MAXEXPR; + IRO_NonAssignmentOp[ELESS] = MAXEXPR; + IRO_NonAssignmentOp[EGREATER] = MAXEXPR; + IRO_NonAssignmentOp[ELESSEQU] = MAXEXPR; + IRO_NonAssignmentOp[EGREATEREQU] = MAXEXPR; + IRO_NonAssignmentOp[EEQU] = MAXEXPR; + IRO_NonAssignmentOp[ENOTEQU] = MAXEXPR; + IRO_NonAssignmentOp[EAND] = MAXEXPR; + IRO_NonAssignmentOp[EXOR] = MAXEXPR; + IRO_NonAssignmentOp[EOR] = MAXEXPR; + IRO_NonAssignmentOp[ELAND] = MAXEXPR; + IRO_NonAssignmentOp[ELOR] = MAXEXPR; + IRO_NonAssignmentOp[EASS] = MAXEXPR; + IRO_NonAssignmentOp[EMULASS] = EMUL; + IRO_NonAssignmentOp[EDIVASS] = EDIV; + IRO_NonAssignmentOp[EMODASS] = EMODULO; + IRO_NonAssignmentOp[EADDASS] = EADD; + IRO_NonAssignmentOp[ESUBASS] = ESUB; + IRO_NonAssignmentOp[ESHLASS] = ESHL; + IRO_NonAssignmentOp[ESHRASS] = ESHR; + IRO_NonAssignmentOp[EANDASS] = EAND; + IRO_NonAssignmentOp[EXORASS] = EXOR; + IRO_NonAssignmentOp[EORASS] = EOR; + IRO_NonAssignmentOp[ECOMMA] = MAXEXPR; + IRO_NonAssignmentOp[EPMODULO] = MAXEXPR; + IRO_NonAssignmentOp[EROTL] = MAXEXPR; + IRO_NonAssignmentOp[EROTR] = MAXEXPR; + IRO_NonAssignmentOp[EBCLR] = MAXEXPR; + IRO_NonAssignmentOp[EBTST] = MAXEXPR; + IRO_NonAssignmentOp[EBSET] = MAXEXPR; + IRO_NonAssignmentOp[ETYPCON] = MAXEXPR; + IRO_NonAssignmentOp[EBITFIELD] = MAXEXPR; + IRO_NonAssignmentOp[EINTCONST] = MAXEXPR; + IRO_NonAssignmentOp[EFLOATCONST] = MAXEXPR; + IRO_NonAssignmentOp[ESTRINGCONST] = MAXEXPR; + IRO_NonAssignmentOp[ECOND] = MAXEXPR; + IRO_NonAssignmentOp[EFUNCCALL] = MAXEXPR; + IRO_NonAssignmentOp[EFUNCCALLP] = MAXEXPR; + IRO_NonAssignmentOp[EOBJREF] = MAXEXPR; + IRO_NonAssignmentOp[EMFPOINTER] = MAXEXPR; + IRO_NonAssignmentOp[ENULLCHECK] = MAXEXPR; + IRO_NonAssignmentOp[EPRECOMP] = MAXEXPR; + IRO_NonAssignmentOp[ETEMP] = MAXEXPR; + IRO_NonAssignmentOp[EARGOBJ] = MAXEXPR; + IRO_NonAssignmentOp[ELOCOBJ] = MAXEXPR; + IRO_NonAssignmentOp[ELABEL] = MAXEXPR; + IRO_NonAssignmentOp[ESETCONST] = MAXEXPR; + IRO_NonAssignmentOp[ENEWEXCEPTION] = MAXEXPR; + IRO_NonAssignmentOp[ENEWEXCEPTIONARRAY] = MAXEXPR; + IRO_NonAssignmentOp[EOBJLIST] = MAXEXPR; + IRO_NonAssignmentOp[EMEMBER] = MAXEXPR; + IRO_NonAssignmentOp[ETEMPLDEP] = MAXEXPR; + IRO_NonAssignmentOp[EINSTRUCTION] = MAXEXPR; + IRO_NonAssignmentOp[EDEFINE] = MAXEXPR; + IRO_NonAssignmentOp[EREUSE] = MAXEXPR; + IRO_NonAssignmentOp[EASSBLK] = MAXEXPR; + IRO_NonAssignmentOp[EVECTOR128CONST] = MAXEXPR; + IRO_NonAssignmentOp[ECONDASS] = MAXEXPR; +} + +void IRO_InitializeAssignmentFoldingFunctionArray(void) { + int i; + + for (i = 0; i < MAXEXPR; i++) + AssignmentFoldingFunction[i] = NULL; + + AssignmentFoldingFunction[EPOSTINC] = NULL; + AssignmentFoldingFunction[EPOSTDEC] = NULL; + AssignmentFoldingFunction[EPREINC] = NULL; + AssignmentFoldingFunction[EPREDEC] = NULL; + AssignmentFoldingFunction[EINDIRECT] = NULL; + AssignmentFoldingFunction[EMONMIN] = NULL; + AssignmentFoldingFunction[EBINNOT] = NULL; + AssignmentFoldingFunction[ELOGNOT] = NULL; + AssignmentFoldingFunction[EFORCELOAD] = NULL; + AssignmentFoldingFunction[EMUL] = NULL; + AssignmentFoldingFunction[EMULV] = NULL; + AssignmentFoldingFunction[EDIV] = NULL; + AssignmentFoldingFunction[EMODULO] = NULL; + AssignmentFoldingFunction[EADDV] = NULL; + AssignmentFoldingFunction[ESUBV] = NULL; + AssignmentFoldingFunction[EADD] = NULL; + AssignmentFoldingFunction[ESUB] = NULL; + AssignmentFoldingFunction[ESHL] = NULL; + AssignmentFoldingFunction[ESHR] = NULL; + AssignmentFoldingFunction[ELESS] = NULL; + AssignmentFoldingFunction[EGREATER] = NULL; + AssignmentFoldingFunction[ELESSEQU] = NULL; + AssignmentFoldingFunction[EGREATEREQU] = NULL; + AssignmentFoldingFunction[EEQU] = NULL; + AssignmentFoldingFunction[ENOTEQU] = NULL; + AssignmentFoldingFunction[EAND] = NULL; + AssignmentFoldingFunction[EXOR] = NULL; + AssignmentFoldingFunction[EOR] = NULL; + AssignmentFoldingFunction[ELAND] = NULL; + AssignmentFoldingFunction[ELOR] = NULL; + AssignmentFoldingFunction[EASS] = NULL; + AssignmentFoldingFunction[EMULASS] = CInt64_Mul; + AssignmentFoldingFunction[EDIVASS] = CInt64_Mul; + AssignmentFoldingFunction[EMODASS] = NULL; + AssignmentFoldingFunction[EADDASS] = CInt64_Add; + AssignmentFoldingFunction[ESUBASS] = CInt64_Add; + AssignmentFoldingFunction[ESHLASS] = CInt64_Add; + AssignmentFoldingFunction[ESHRASS] = CInt64_Add; + AssignmentFoldingFunction[EANDASS] = CInt64_And; + AssignmentFoldingFunction[EXORASS] = CInt64_Xor; + AssignmentFoldingFunction[EORASS] = CInt64_Or; + AssignmentFoldingFunction[ECOMMA] = NULL; + AssignmentFoldingFunction[EPMODULO] = NULL; + AssignmentFoldingFunction[EROTL] = NULL; + AssignmentFoldingFunction[EROTR] = NULL; + AssignmentFoldingFunction[EBCLR] = NULL; + AssignmentFoldingFunction[EBTST] = NULL; + AssignmentFoldingFunction[EBSET] = NULL; + AssignmentFoldingFunction[ETYPCON] = NULL; + AssignmentFoldingFunction[EBITFIELD] = NULL; + AssignmentFoldingFunction[EINTCONST] = NULL; + AssignmentFoldingFunction[EFLOATCONST] = NULL; + AssignmentFoldingFunction[ESTRINGCONST] = NULL; + AssignmentFoldingFunction[ECOND] = NULL; + AssignmentFoldingFunction[EFUNCCALL] = NULL; + AssignmentFoldingFunction[EFUNCCALLP] = NULL; + AssignmentFoldingFunction[EOBJREF] = NULL; + AssignmentFoldingFunction[EMFPOINTER] = NULL; + AssignmentFoldingFunction[ENULLCHECK] = NULL; + AssignmentFoldingFunction[EPRECOMP] = NULL; + AssignmentFoldingFunction[ETEMP] = NULL; + AssignmentFoldingFunction[EARGOBJ] = NULL; + AssignmentFoldingFunction[ELOCOBJ] = NULL; + AssignmentFoldingFunction[ELABEL] = NULL; + AssignmentFoldingFunction[ESETCONST] = NULL; + AssignmentFoldingFunction[ENEWEXCEPTION] = NULL; + AssignmentFoldingFunction[ENEWEXCEPTIONARRAY] = NULL; + AssignmentFoldingFunction[EOBJLIST] = NULL; + AssignmentFoldingFunction[EMEMBER] = NULL; + AssignmentFoldingFunction[ETEMPLDEP] = NULL; + AssignmentFoldingFunction[EINSTRUCTION] = NULL; + AssignmentFoldingFunction[EDEFINE] = NULL; + AssignmentFoldingFunction[EREUSE] = NULL; + AssignmentFoldingFunction[EASSBLK] = NULL; + AssignmentFoldingFunction[EVECTOR128CONST] = NULL; + AssignmentFoldingFunction[ECONDASS] = NULL; +} + +static void UpdateUseForOtherSelfAssignment(IROLinear *a, IROLinear *b, Type *type) { + CInt64 val; + IROLinear *father; + IROLinear *repl; + IROLinear *newdiadic; + + val = IRO_GetSelfAssignmentVal(b); + if ((father = IRO_LocateFather(a)) && father->type == IROLinearOp2Arg && IRO_IsIntConstant(father->u.diadic.right)) { + CInt64 var_30 = father->u.diadic.right->u.node->data.intval; + if (AssignmentFoldingFunction[b->nodetype] && ((father->nodetype == b->nodetype) || (father->nodetype == IRO_NonAssignmentOp[b->nodetype]))) { + CInt64 v; + CInt64 folded; + CInt64_SetLong(&v, b->rtype->size * 8); + folded = AssignmentFoldingFunction[b->nodetype](var_30, val); + if (b->nodetype == ESHRASS && !is_unsigned(b->rtype)) { + if (CInt64_LessU(var_30, v) && CInt64_LessU(val, v)) { + if (CInt64_GreaterEqualU(folded, v)) + folded = CInt64_Sub(v, cint64_one); + father->u.diadic.right->u.node->data.intval = folded; + return; + } + } else { + father->u.diadic.right->u.node->data.intval = folded; + return; + } + } else { + switch (b->nodetype) { + case EMULASS: + if (father->nodetype == ESHL || father->nodetype == ESHLASS) { + SInt32 powvalue; + if (IRO_IsPow2(b->u.diadic.right, &powvalue)) { + if (powvalue > 0) { + CInt64 v; + CInt64_SetLong(&v, powvalue); + father->u.diadic.right->u.node->data.intval = CInt64_Add(v, var_30); + } + } else { + father->nodetype = (father->nodetype == ESHL) ? EMUL : EMULASS; + var_30 = CInt64_Shl(cint64_one, var_30); + father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val); + } + return; + } + break; + case EDIVASS: + if ((father->nodetype == ESHR || father->nodetype == ESHRASS) && is_unsigned(father->rtype)) { + SInt32 powvalue; + if (IRO_IsPow2(b->u.diadic.right, &powvalue)) { + if (powvalue > 0) { + CInt64 v; + CInt64_SetLong(&v, powvalue); + father->u.diadic.right->u.node->data.intval = CInt64_Add(v, var_30); + } + } else { + father->nodetype = (father->nodetype == ESHR) ? EDIV : EDIVASS; + var_30 = CInt64_Shl(cint64_one, var_30); + father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val); + } + return; + } + break; + case ESHLASS: + if (father->nodetype == EMUL || father->nodetype == EMULASS) { + SInt32 powvalue; + if (IRO_IsPow2(father->u.diadic.right, &powvalue)) { + if (powvalue > 0) { + CInt64 v; + father->nodetype = (father->nodetype == EMUL) ? ESHL : ESHLASS; + CInt64_SetLong(&v, powvalue); + father->u.diadic.right->u.node->data.intval = CInt64_Add(v, val); + } + } else { + val = CInt64_Shl(cint64_one, val); + father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val); + } + return; + } else if (father->nodetype == ESHR || father->nodetype == ESHRASS) { + if (CInt64_Equal(var_30, val) && is_unsigned(father->rtype)) { + father->nodetype = (father->nodetype == ESHR) ? EAND : EANDASS; + if (father->rtype->size < 8) { + CInt64 v; + CInt64_SetLong(&v, 64 - (father->rtype->size * 8)); + val = CInt64_Add(val, v); + } + father->u.diadic.right->u.node->data.intval = CInt64_ShrU(cint64_negone, val); + return; + } + } + break; + case ESHRASS: + if ((father->nodetype == EDIV || father->nodetype == EDIVASS) && is_unsigned(father->rtype)) { + SInt32 powvalue; + if (IRO_IsPow2(father->u.diadic.right, &powvalue)) { + if (powvalue > 0) { + CInt64 v; + father->nodetype = (father->nodetype == EDIV) ? ESHR : ESHRASS; + CInt64_SetLong(&v, powvalue); + father->u.diadic.right->u.node->data.intval = CInt64_Add(v, val); + } + } else { + val = CInt64_Shl(cint64_one, val); + father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val); + } + return; + } else if (father->nodetype == ESHL || father->nodetype == ESHLASS) { + if (CInt64_Equal(var_30, val)) { + father->nodetype = (father->nodetype == ESHL) ? EAND : EANDASS; + father->u.diadic.right->u.node->data.intval = CInt64_Shl(cint64_negone, val); + return; + } + } + break; + } + } + } + + repl = IRO_NewIntConst(val, type); + newdiadic = IRO_NewLinear(IROLinearOp2Arg); + newdiadic->index = ++IRO_NumLinear; + newdiadic->nodetype = IRO_NonAssignmentOp[b->nodetype]; + newdiadic->u.diadic.left = a; + newdiadic->u.diadic.right = repl; + newdiadic->rtype = a->rtype; + repl->next = newdiadic; + IRO_LocateFather_Cut_And_Paste_Without_Nopping(a, newdiadic); + IRO_PasteAfter(repl, newdiadic, a); +} + +static Boolean PropagateIncsAndDecs(void) { + IRODef *def; + Boolean result; + + result = 0; + def = FirstDef; + while (def) { + if ( + def->linear && + def->x1C && + IsIncOrDec(def->linear) && + !(def->linear->flags & IROLF_Reffed) && + (IS_TYPE_INT_OR_ENUM(def->linear->rtype) || IS_TYPE_POINTER_ONLY(def->linear->rtype)) && + IRO_TypesEqual(def->linear->rtype, def->var->object->type) && + !is_volatile_object(def->var->object) + ) { + IROUse *use; + IROUse *use2; + IROLinear *father; + CInt64 val; + SInt32 i; + Type *type; + + for (use = def->var->uses, i = 0; use; use = use->varnext) { + if (Bv_IsBitSet(def->index, use->x18)) { + if ( + use->x1C == 1 && + use->linear->type == IROLinearOperand && + (father = IRO_LocateFather(use->linear)) && + IRO_IsVariable(father) && + IRO_TypesEqual(def->linear->rtype, father->rtype) + ) { + if (use->linear->flags & IROLF_Assigned) { + if (!((father = IRO_LocateFather(father)) && IsIncOrDec(father) && !(father->flags & IROLF_Reffed))) + goto nextDef; + } + i++; + } else { + goto nextDef; + } + } + } + + if (i == def->x18) { + for (use = def->var->uses; use; use = use->varnext) { + if (Bv_IsBitSet(def->index, use->x18)) { + IRO_Dump("Propagating inc/dec from %d to %d\n", def->linear->index, use->linear->index); + father = IRO_LocateFather(use->linear); + val = IRO_GetSelfAssignmentVal(def->linear); + type = def->linear->rtype; + if (IS_TYPE_POINTER_ONLY(def->linear->rtype)) + type = TYPE(&stunsignedlong); + UpdateUse(father, val, type); + + result = 1; + for (use2 = def->var->uses; use2; use2 = use2->varnext) { + if (use2->linear == def->linear->u.monadic->u.diadic.left) { + use->x1C = use2->x1C; + Bv_Copy(use2->x18, use->x18); + break; + } + } + } + } + def->x18 = 0; + IRO_NopNonSideEffects(def->linear, -1); + def->linear->type = IROLinearNop; + IRO_Dump("Removing deadddd assignment %d\n", def->linear->index); + } + } + nextDef: + def = def->globalnext; + } + + return result; +} + +static Boolean PropagateOtherSelfAssignments(void) { + IRODef *def; + Boolean result; + + result = 0; + + def = FirstDef; + while (def) { + if ( + def->linear && + def->x1C && + IsOtherSelfAssignment(def->linear) && + !(def->linear->flags & IROLF_Reffed) && + IS_TYPE_INT_OR_ENUM(def->linear->rtype) && + IRO_TypesEqual(def->linear->rtype, def->var->object->type) && + !is_volatile_object(def->var->object) + ) + { + IROUse *use; + IROUse *use2; + IROLinear *father; + SInt32 i; + Type *type; + + for (use = def->var->uses, i = 0; use; use = use->varnext) { + if (Bv_IsBitSet(def->index, use->x18)) { + if ( + use->x1C == 1 && + use->linear->type == IROLinearOperand && + (father = IRO_LocateFather(use->linear)) && + IRO_IsVariable(father) && + IRO_TypesEqual(def->linear->rtype, father->rtype) + ) { + if (use->linear->flags & IROLF_Assigned) { + if (!((father = IRO_LocateFather(father)) && IsOtherSelfAssignment(father) && (father->nodetype == def->linear->nodetype) && !(father->flags & IROLF_Reffed))) + goto nextDef; + } + i++; + } else { + goto nextDef; + } + } + } + + if (i == def->x18) { + for (use = def->var->uses; use; use = use->varnext) { + if (Bv_IsBitSet(def->index, use->x18)) { + IRO_Dump("Propagating self assignment from %d to %d\n", def->linear->index, use->linear->index); + father = IRO_LocateFather(use->linear); + UpdateUseForOtherSelfAssignment(father, def->linear, def->linear->rtype); + + result = 1; + for (use2 = def->var->uses; use2; use2 = use2->varnext) { + if (use2->linear == def->linear->u.monadic->u.diadic.left) { + use->x1C = use2->x1C; + Bv_Copy(use2->x18, use->x18); + break; + } + } + } + } + def->x18 = 0; + IRO_NopNonSideEffects(def->linear, -1); + def->linear->type = IROLinearNop; + IRO_Dump("Removing deadddd assignment %d\n", def->linear->index); + } + } + nextDef: + def = def->globalnext; + } + + return result; +} + +static void MarkUsesByIndirect(IROLinear *linear, BitVector *a, BitVector *b) { + IROListNode *list; + IROLinear *nd; + Object *obj; + VarRecord *var; + Boolean foundObjRef; + IROListNode *scan; + IRODef *def; + Boolean found; + + found = 0; + + if (linear && copts.opt_pointer_analysis && linear->pointsToFunction && FunctionName) { + IROListNode *resultList; + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, linear, &resultList); + if ((list = resultList)) { + for (scan = list; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + found = 1; + break; + } + + foundObjRef = 0; + for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + foundObjRef = 1; + break; + } + } + + if (!foundObjRef) { + found = 1; + break; + } + } + + if (!found) { + while (list) { + for (nd = list->list.head; nd != list->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + obj = nd->u.node->data.objref; + CError_ASSERT(1422, obj != NULL); + var = IRO_FindVar(obj, 1, 1); + CError_ASSERT(1424, var != NULL); + + for (def = var->defs; def; def = def->varnext) { + if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) { + def->x18++; + Bv_SetBit(def->index, MightReachAnyUse); + } + } + } + } + list = list->nextList; + } + } + + while (resultList) { + IROListNode *next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + found = 1; + } + } else { + found = 1; + } + + if (found) { + Bv_Copy(Reaches, a); + Bv_And(b, a); + Bv_Or(a, MightReachAnyUse); + for (def = FirstDef; def; def = def->globalnext) { + if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) + def->x18++; + } + } +} + +static void MarkUsesByFunctionCall(IROLinear *linear, BitVector *a, BitVector *b) { + ObjectList *olist; + IROLinear *funcnd; + IROListNode *list; + IROLinear *nd; + Object *obj; + VarRecord *var; + Boolean foundObjRef; + IROListNode *scan; + IRODef *def; + Boolean found; + + found = 0; + + if ((funcnd = linear->u.funccall.linear8) && copts.opt_pointer_analysis && funcnd->pointsToFunction && FunctionName) { + IROListNode *resultList; + ObjectList *depsList; + + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, funcnd, &resultList); + if (resultList) { + for (scan = resultList; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + found = 1; + break; + } + + foundObjRef = 0; + for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + foundObjRef = 1; + obj = nd->u.node->data.objref; + CError_ASSERT(1522, obj != NULL); + + depsList = NULL; + PointerAnalysis_GetFunctionDependencies(obj, linear, &depsList); + for (olist = depsList; olist; olist = olist->next) { + if (!olist->object) { + found = 1; + break; + } + } + + while (depsList) { + olist = depsList->next; + IRO_free(depsList); + depsList = olist; + } + + if (found) + break; + } + } + + if (!foundObjRef) + found = 1; + if (found) + break; + } + + if (!found) { + for (list = resultList; list; list = list->nextList) { + for (nd = list->list.head; nd != list->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + obj = nd->u.node->data.objref; + depsList = NULL; + PointerAnalysis_GetFunctionDependencies(obj, linear, &depsList); + + for (olist = depsList; olist; olist = olist->next) { + var = IRO_FindVar(olist->object, 1, 1); + CError_ASSERT(1573, var != NULL); + + for (def = var->defs; def; def = def->varnext) { + if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) { + def->x18++; + Bv_SetBit(def->index, MightReachAnyUse); + } + } + } + + while (depsList) { + olist = depsList->next; + IRO_free(depsList); + depsList = olist; + } + } + } + } + } + + while (resultList) { + IROListNode *next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + found = 1; + } + } else { + found = 1; + } + + if (found) { + Bv_Copy(Reaches, a); + Bv_And(b, a); + Bv_Or(a, MightReachAnyUse); + for (def = FirstDef; def; def = def->globalnext) { + if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) + def->x18++; + } + } + + if (linear->stmt && IRO_FunctionCallMightThrowException(linear)) + IRO_WalkExcActions(linear->stmt->dobjstack, MarkUses); +} + +static Boolean UseOfVarIsInsideASimpleDefOfVar(IROUse *use) { + VarRecord *var; + VarRecord *varAss; + IROLinear *nd; + IROLinear *nd2; + + if ((var = use->var)) { + if ((nd = use->linear) && (nd->flags & IROLF_4000)) + return 0; + + while (nd && (nd->flags & IROLF_Reffed)) + nd = nd->next; + + if ( + nd && + IRO_IsAssignment(nd) && + (varAss = IRO_FindAssigned(nd)) && + varAss == var && + !IRO_HasSideEffect((nd->type == IROLinearOp1Arg) ? nd->u.monadic : nd->u.diadic.left) && + (!(nd2 = (nd->type == IROLinearOp1Arg) ? NULL : nd->u.diadic.right) || !IRO_HasSideEffect(nd2)) + ) { + return 1; + } + } + + return 0; +} + +static Boolean AllLoopDefUsesAreInSimpleLoopDefs(IRODef *def) { + VarRecord *var; + IRODef *scan; + IROUse *use; + + if ((var = def->var)) { + for (scan = var->defs; scan; scan = scan->varnext) { + if (scan->node && scan->node->loopdepth) { + for (use = var->uses; use; use = use->varnext) { + if (Bv_IsBitSet(scan->index, use->x18)) { + if (!use->node || !use->node->loopdepth || !UseOfVarIsInsideASimpleDefOfVar(use)) + return 0; + } + } + } + } + return 1; + } else { + return 0; + } +} + +static void MarkRemovableLoopDefs(void) { + IRODef *def; + IRODef *scan; + + for (def = FirstDef; def; def = def->globalnext) { + if (!def->x1A && !def->x1B && def->node && def->node->loopdepth && !def->x1D && + AllLoopDefUsesAreInSimpleLoopDefs(def) && def->var) { + for (scan = def->var->defs; scan; scan = scan->varnext) { + if (scan->node && scan->node->loopdepth) + scan->x1D = 1; + } + } + } +} + +static Boolean EliminateReffedDeadStore(IRODef *def) { + Boolean isPostIncOrDec; + IROLinear *nd; + Boolean result; + + nd = def->linear; + isPostIncOrDec = (nd->type == IROLinearOp1Arg) && (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC); + + result = IRO_LocateFather(nd) != NULL; + if (result && IRO_IsAssignment(nd) && IRO_IsModifyOp[nd->nodetype]) + result = IRO_TransformSelfAssignmentToAssignment(nd); + result = result && (nd->type == IROLinearOp2Arg) && (nd->nodetype == EASS); + + if (result) { + def->x18 = 0; + IRO_Dump("Removing referenced dead assignment %d\n", nd->index); + + if (isPostIncOrDec) { + IRO_NopNonSideEffects(nd->u.diadic.right, 0); + nd->type = IROLinearNop; + IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, nd->u.diadic.left); + } else { + IRO_NopNonSideEffects(nd->u.diadic.left, 0); + nd->type = IROLinearNop; + IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, nd->u.diadic.right); + } + } + + return result; +} + +Boolean IRO_UseDef(Boolean optDeadAssignments, Boolean optPropagation) { + Boolean result; + IRODef *gdef; + IROUse *guse; + IRODef *def; + IROUse *use; + IRONode *node; + IROLinear *nd; + VarRecord *var; + Boolean flag; + BitVector *bv3; + BitVector *bv2; + BitVector *bv; + int i; + + FindDefsAndUses(); + + IRO_CheckForUserBreak(); + + for (use = IRO_FirstVarUse; use; use = use->globalnext) + Bv_AllocVector(&use->x18, NumDefs); + Bv_AllocVector(&MightReachAnyUse, NumDefs); + Bv_AllocVector(&bv, NumDefs); + + IRO_CheckForUserBreak(); + + for (def = FirstDef; def; def = def->globalnext) { + if (def->x1A || def->x1B) + Bv_SetBit(def->index, bv); + } + + Bv_AllocVector(&bv2, NumDefs); + gdef = FirstDef; + for (node = IRO_FirstNode; node; node = node->nextnode) { + Bv_AllocVector(&node->x16, NumDefs); + Bv_AllocVector(&node->x1E, NumDefs); + Bv_AllocVector(&node->x22, NumDefs); + Bv_AllocVector(&node->x1A, NumDefs); + + for (nd = node->first; nd; nd = nd->next) { + while (gdef && gdef->linear == nd) { + Bv_SetBit(gdef->index, node->x1E); + if (gdef->x1C) { + for (def = gdef->var->defs; def; def = def->varnext) { + if (def != gdef) { + Bv_SetBit(def->index, node->x22); + Bv_ClearBit(def->index, node->x1E); + } + } + } + gdef = gdef->globalnext; + } + if (nd == node->last) + break; + } + + if (node->numpred) + Bv_Set(node->x16); + Bv_Copy(node->x1E, node->x1A); + IRO_CheckForUserBreak(); + } + + Bv_AllocVector(&bv3, NumDefs); + + do { + flag = 0; + for (node = IRO_FirstNode; node; node = node->nextnode) { + Bv_Clear(node->x16); + if (node->numpred) { + for (i = 0; i < node->numpred; i++) + Bv_Or(IRO_NodeTable[node->pred[i]]->x1A, node->x16); + } else if (node == IRO_FirstNode) { + for (var = IRO_FirstVar; var; var = var->next) + Bv_SetBit(var->defs->index, node->x16); + } + Bv_Copy(node->x16, bv3); + Bv_Minus(node->x22, bv3); + Bv_Or(node->x1E, bv3); + if (!Bv_Compare(bv3, node->x1A)) { + Bv_Copy(bv3, node->x1A); + flag = 1; + } + } + + IRO_CheckForUserBreak(); + } while (flag); + + gdef = FirstDef; + guse = IRO_FirstVarUse; + Bv_AllocVector(&Reaches, NumDefs); + + for (node = IRO_FirstNode; node; node = node->nextnode) { + Bv_Copy(node->x16, Reaches); + nd = node->first; + while (1) { + while (guse && guse->linear == nd) { + for (def = guse->var->defs; def; def = def->varnext) { + if (Bv_IsBitSet(def->index, Reaches)) { + Bv_SetBit(def->index, guse->x18); + Bv_SetBit(def->index, MightReachAnyUse); + def->x18++; + guse->x1C++; + } + } + guse = guse->globalnext; + } + + if (nd->type == IROLinearFunccall) { + MarkUsesByFunctionCall(nd, bv2, bv); + } else if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT && !IRO_IsVariable(nd)) { + MarkUsesByIndirect(nd, bv2, bv); + } else if ((nd->type == IROLinearFunccall) || + (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT && !IRO_IsVariable(nd))) { + Bv_Copy(Reaches, bv2); + Bv_And(bv, bv2); + Bv_Or(bv2, MightReachAnyUse); + for (def = FirstDef; def; def = def->globalnext) { + if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) + def->x18++; + } + if (nd->type == IROLinearFunccall && nd->stmt && IRO_FunctionCallMightThrowException(nd)) + IRO_WalkExcActions(nd->stmt->dobjstack, MarkUses); + } + + if (nd->type == IROLinearAsm) { + IAEffects effects; + CodeGen_GetAsmEffects(nd->u.asm_stmt, &effects); + if (effects.x2) { + Bv_Copy(Reaches, bv2); + Bv_And(bv, bv2); + Bv_Or(bv2, MightReachAnyUse); + } + } + + if (nd->type == IROLinearReturn || nd->type == IROLinearEnd) { + for (def = FirstDef; def; def = def->globalnext) { + if (def->x1A && Bv_IsBitSet(def->index, Reaches)) { + Bv_SetBit(def->index, MightReachAnyUse); + def->x18++; + } + } + } + + while (gdef && gdef->linear == nd) { + if (gdef->x1C) { + for (def = gdef->var->defs; def; def = def->varnext) + Bv_ClearBit(def->index, Reaches); + } + Bv_SetBit(gdef->index, Reaches); + gdef = gdef->globalnext; + } + + if (nd == node->last) + break; + nd = nd->next; + } + } + + IRO_CheckForUserBreak(); + + result = 0; + + if (optDeadAssignments) { + MarkRemovableLoopDefs(); + for (def = FirstDef; def; def = def->globalnext) { + if (def->linear && + (!Bv_IsBitSet(def->index, MightReachAnyUse) || def->x1D) && + (copts.opt_pointer_analysis || !def->x1B) && + def->linear->type != IROLinearAsm && + (!def->linear->rtype || !CParser_IsVolatile(def->linear->rtype, def->linear->nodeflags & ENODE_FLAG_QUALS)) && + !is_volatile_object(def->var->object) + ) { + if (!(def->linear->flags & IROLF_Reffed)) { + def->x18 = 0; + IRO_NopNonSideEffects(def->linear, -1); + def->linear->type = IROLinearNop; + IRO_Dump("Removing dead assignment %d\n", def->linear->index); + result = 1; + } else { + result = EliminateReffedDeadStore(def); + } + } + } + } + + IRO_CheckForUserBreak(); + + if (optPropagation) { + while (1) { + if (PropagateIncsAndDecs() || PropagateOtherSelfAssignments()) + result = 1; + else + break; + } + } + + IRO_CheckForUserBreak(); + + return result; +} + +static IROLinear *GetOperand(IROLinear *nd) { + IROLinear *inner; + + if (nd->type == IROLinearOperand) + return nd; + + if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD) { + inner = GetOperand(nd->u.diadic.left); + if (!inner) + inner = GetOperand(nd->u.diadic.right); + return inner; + } + + return NULL; +} + +static IROLinear *GetAssigned(IROLinear *nd) { + if (!nd) + return NULL; + + if (nd->type == IROLinearOp2Arg) + nd = nd->u.diadic.left; + else if (nd->type == IROLinearOp1Arg) + nd = nd->u.monadic; + else + CError_FATAL(2338); + + if (nd->type != IROLinearOp1Arg || nd->nodetype != EINDIRECT) + CError_FATAL(2351); + + nd = nd->u.monadic; + + if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD) + nd = GetOperand(nd); + + return nd; +} + +static void AddUseToRange(IROUse *use) { + IRODef *def; + + Bv_SetBit(use->index, useset); + Bv_ClearBit(use->index, alluses); + + for (def = use->var->defs; def; def = def->varnext) { + if (Bv_IsBitSet(def->index, alldefs) && (Bv_IsBitSet(def->index, use->x18) || GetAssigned(def->linear) == use->linear)) + AddDefToRange(def); + } +} + +static void AddDefToRange(IRODef *def) { + IROUse *use; + IROLinear *assigned; + + Bv_SetBit(def->index, defset); + Bv_ClearBit(def->index, alldefs); + + for (use = def->var->uses, assigned = GetAssigned(def->linear); use; use = use->varnext) { + if (Bv_IsBitSet(use->index, alluses) && (Bv_IsBitSet(def->index, use->x18) || assigned == use->linear)) + AddUseToRange(use); + } +} + +static void ReplaceAssigned(IROLinear *nd, Object *from, Object *to) { + IROLinear *assigned; + + if ( + !(assigned = GetAssigned(nd)) || + assigned->type != IROLinearOperand || + assigned->u.node->type != EOBJREF || + assigned->u.node->data.objref != from + ) + CError_FATAL(2459); + + assigned->u.node->data.objref = to; +} + +static void ReplaceUsed(IROLinear *nd, Object *from, Object *to) { + CError_ASSERT(2482, nd->type == IROLinearOperand && nd->u.node->type == EOBJREF); + + if (nd->u.node->data.objref == from) + nd->u.node->data.objref = to; + else if (nd->u.node->data.objref != to) + CError_FATAL(2494); +} + +static void SplitOffRange(VarRecord *var) { + Object *newObj; + IRODef *def; + IROUse *use; + + IRO_Dump("Splitting range for variable: %d\n", var->index); + IRO_DumpBits("Def set: ", defset); + IRO_DumpBits("Use set: ", useset); + IRO_DumpBits("All defs: ", alldefs); + IRO_DumpBits("All uses: ", alluses); + + newObj = create_temp_object(var->object->type); + IRO_FindVar(newObj, 1, 1); + + for (def = var->defs; def; def = def->varnext) { + if (Bv_IsBitSet(def->index, defset) && def->linear) + ReplaceAssigned(def->linear, var->object, newObj); + } + + for (use = var->uses; use; use = use->varnext) { + if (Bv_IsBitSet(use->index, useset)) + ReplaceUsed(use->linear, var->object, newObj); + } +} + +void IRO_SplitLifetimes(void) { + VarRecord *var; + SInt32 numVars; + IRODef *def; + IROUse *use; + Boolean flag; + + Bv_AllocVector(&alldefs, NumDefs); + Bv_AllocVector(&alluses, NumUses); + Bv_AllocVector(&defset, NumDefs); + Bv_AllocVector(&useset, NumUses); + + var = IRO_FirstVar; + numVars = IRO_NumVars; + + while (var && var->index <= numVars) { + if (var->object->datatype == DLOCAL && !is_volatile_object(var->object) && !var->xC && !var->xB && !var->x1E) { + Bv_Clear(alldefs); + Bv_Clear(alluses); + + for (def = var->defs; def; def = def->varnext) { + if (def->linear && def->linear->type == IROLinearAsm) + goto skipThisVar; + Bv_SetBit(def->index, alldefs); + } + + for (use = var->uses; use; use = use->varnext) { + if (use->linear && use->linear->type == IROLinearAsm) + goto skipThisVar; + Bv_SetBit(use->index, alluses); + } + + flag = 1; + while (1) { + Bv_Clear(defset); + Bv_Clear(useset); + + def = var->defs; + while (def && !Bv_IsBitSet(def->index, alldefs)) + def = def->varnext; + + if (!def) + break; + + AddDefToRange(def); + if (Bv_IsEmpty(alldefs)) + break; + + if (!flag) + SplitOffRange(var); + flag = 0; + } + } + + skipThisVar: + var = var->next; + } + + IRO_CheckForUserBreak(); +} diff --git a/compiler_and_linker/FrontEnd/Optimizer/IROUseDef.h b/compiler_and_linker/FrontEnd/Optimizer/IROUseDef.h new file mode 100644 index 0000000..03d3f9b --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IROUseDef.h @@ -0,0 +1,48 @@ +#ifndef COMPILER_IROUSEDEF_H +#define COMPILER_IROUSEDEF_H + +#include "IrOptimizer.h" +#include "BitVector.h" +#include "compiler/enode.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +struct IROUse { + SInt32 index; + IRONode *node; + IROLinear *linear; + VarRecord *var; + IROUse *globalnext; + IROUse *varnext; + BitVector *x18; + UInt16 x1C; +}; +struct IRODef { + SInt32 index; + IRONode *node; + IROLinear *linear; + VarRecord *var; + IRODef *globalnext; + IRODef *varnext; + UInt16 x18; + Boolean x1A; + Boolean x1B; + Boolean x1C; + Boolean x1D; +}; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +extern ENodeType IRO_NonAssignmentOp[MAXEXPR]; +extern IROUse *IRO_FirstVarUse; +extern IROUse *IRO_LastVarUse; + +extern CInt64 IRO_GetSelfAssignmentVal(IROLinear *linear); +extern void IRO_InitializeNonAssignmentOpArray(void); +extern void IRO_InitializeAssignmentFoldingFunctionArray(void); +extern Boolean IRO_UseDef(Boolean optDeadAssignments, Boolean optPropagation); +extern void IRO_SplitLifetimes(void); + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.c b/compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.c new file mode 100644 index 0000000..59bb368 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.c @@ -0,0 +1,400 @@ +#include "IrOptimizer.h" +#include "compiler/CError.h" +#include "compiler/CParser.h" +#include "compiler/InlineAsmPPC.h" +#include "IroCSE.h" +#include "IroDump.h" +#include "IroEval.h" +#include "IroFlowgraph.h" +#include "IroLinearForm.h" +#include "IroSubable.h" +#include "IroTransform.h" +#include "IROUseDef.h" +#include "IroUtil.h" +#include "IroVars.h" +#include "compiler/objects.h" +#include "IroPropagate.h" +#include "IroPointerAnalysis.h" +#include "IroJump.h" +#include "IroRangePropagation.h" +#include "IroEmptyLoop.h" +#include "IroUnrollLoop.h" +#include "IroLoop.h" +#include "IroExprRegeneration.h" + +Boolean DoScalarize; +Boolean DoLinearize; +Boolean EarlyReturn; +Boolean IRO_CPFirstTime; +Boolean VectorPhaseCalledFromUnroll; +Boolean IRO_Log; +static Boolean stIsSetup; + +static void CountRefToObject(Object *object, int depth) { + static unsigned short LoopUsage[] = {1, 4, 16, 64}; + + if (depth > 3) + depth = 3; + + object->u.var.info->usage += LoopUsage[depth]; + object->u.var.info->used = 1; +} + +static void CountARef(IROLinear *node, int depth) { + Object *object; + + object = node->u.node->data.objref; + CError_ASSERT(78, object->datatype != DALIAS); + + if (object->datatype == DLOCAL && object->u.var.info) { + CountRefToObject(object, depth); + if ((node->flags & IROLF_Used) && (node->flags & IROLF_Assigned)) + CountRefToObject(object, depth); + + if (!(node->flags & IROLF_Immind) && !object->u.var.info->noregister) + object->u.var.info->noregister = 2; + } +} + +static void CountDoubleInd(IROLinear *node, int depth) { + if (IRO_IsVariable(node)) { + CountARef(node->u.monadic, depth); + } else if (node->type == IROLinearOp2Arg) { + if (node->nodetype == EADD) { + CountDoubleInd(node->u.diadic.left, depth); + CountDoubleInd(node->u.diadic.right, depth); + } else if (IRO_IsAddressMultiply(node)) { + if (IRO_IsVariable(node->u.diadic.left)) + CountARef(node->u.diadic.left->u.monadic, depth); + } + } +} + +static void CountUsage(void) { + IRONode *fnode = IRO_FirstNode; + IROLinear *node; + + if (IRO_FirstNode) { + for (; fnode; fnode = fnode->nextnode) { + for (node = fnode->first; node; node = node->next) { + if (IS_LINEAR_ENODE(node, EOBJREF)) + CountARef(node, fnode->loopdepth); + else if (IS_LINEAR_MONADIC(node, EINDIRECT)) + CountDoubleInd(node->u.monadic, fnode->loopdepth); + + if (node->type == IROLinearAsm) { + IAEffects effects; + int i; + + CodeGen_GetAsmEffects(node->u.asm_stmt, &effects); + for (i = 0; i < effects.numoperands; i++) { + Object *object = effects.operands[i].object; + if (object->datatype == DLOCAL && object->u.var.info) { + CountRefToObject(object, fnode->loopdepth); + if (effects.operands[i].type == IAOpnd_3 && !object->u.var.info->noregister) + object->u.var.info->noregister = 2; + } + } + } + + if (node == fnode->last) + break; + } + } + } else { + for (node = IRO_FirstLinear; node; node = node->next) { + if (IS_LINEAR_ENODE(node, EOBJREF)) + CountARef(node, 0); + else if (IS_LINEAR_MONADIC(node, EINDIRECT)) + CountDoubleInd(node->u.monadic, 0); + } + } + + IRO_CheckForUserBreak(); +} + +Statement *IRO_Optimizer(Object *func, Statement *statements) { + Boolean changed; + int pass; + int passCount; + + CError_ASSERT(234, stIsSetup); + +#ifdef CW_ENABLE_IRO_DEBUG + if (copts.debuglisting) + IRO_Log = 1; +#endif + + DisableDueToAsm = 0; + FunctionName = func; + DoScalarize = 1; + DoLinearize = 1; + EarlyReturn = 0; + IRO_Depends = NULL; + LoopOptimizerRun = 0; + IRO_IsLeafFunction = 1; + IRO_FunctionHasReturn = 0; + + IRO_SetupForUserBreakChecking(); + + IRO_Dump("Starting function %s\n", func ? func->name->name : "Init-code"); + IRO_Dump("--------------------------------------------------------------------------------\n"); + + if (DoLinearize) + IRO_PreLinearize(statements); + if (copts.optimizationlevel > 0) + IRO_TransformTree(statements); + + VectorPhaseCalledFromUnroll = 0; + + IRO_Linearize(statements); + + CurStat = NULL; + + IRO_FirstExpr = NULL; + IRO_LastExpr = NULL; + IRO_FirstAssign = NULL; + IRO_LastAssign = NULL; + IRO_FirstVarUse = NULL; + IRO_LastVarUse = NULL; + IRO_FirstNode = NULL; + IRO_LastNode = NULL; + + if (copts.optimizationlevel > 0) + IRO_DoTransformations(); + + IRO_BuildFlowgraph(IRO_FirstLinear); + IRO_DumpAfterPhase("IRO_BuildflowGraph", 0); + + IRO_FindAllVars(); + IRO_CheckInit(); + + if (!DisableDueToAsm && copts.optimizationlevel > 0 && copts.opt_pointer_analysis && func) { + IRO_AnalyzePointers(func); + if (copts.propagation && IRO_EvaluateDefinitePointers(func)) { + IRO_UpdateFlagsOnInts(); + IRO_UpdateVars(); + IRO_DumpAfterPhase("IRO_EvaluateDefinitePointers", 0); + } + } + + if (copts.optimizationlevel > 0) { + changed = IRO_EvaluateConditionals(); + + if (!DisableDueToAsm) { + changed |= IRO_RemoveUnreachable(); + IRO_DumpAfterPhase("IRO_RemoveUnreachable", 0); + } + + changed |= IRO_RemoveRedundantJumps(); + IRO_DumpAfterPhase("IRO_RemoveRedundantJumps", 0); + + if (!DisableDueToAsm) { + changed |= IRO_RemoveLabels(); + IRO_DumpAfterPhase("IRO_RemoveLabels()", 0); + } + + if (changed) { + IRO_BuildFlowgraph(IRO_FirstLinear); + IRO_DumpAfterPhase("IRO_BuildflowGraph--1", 0); + } + } + + if (!DisableDueToAsm && copts.optimizationlevel > 0) { + passCount = copts.multiplepasses ? 2 : 1; + IRO_CPFirstTime = 1; + for (pass = 0; pass < passCount; pass++) { + IRO_Dump("*****************\n"); + IRO_Dump("Dumps for pass=%d\n", pass); + IRO_Dump("*****************\n"); + + if (DoScalarize) + IRO_ScalarizeClassDataMembers(); + IRO_DumpAfterPhase("IRO_ScalarizeClassDataMembers", 0); + + if (copts.propagation) { + IRO_CopyAndConstantPropagation(); + IRO_CPFirstTime = 0; + IRO_ExpressionPropagation(); + IRO_DumpAfterPhase("Copy and constant propagation", 0); + + IRO_RangePropagateInFNode(); + IRO_DumpAfterPhase("IRO_RangePropagateInFNode", 0); + IRO_UpdateFlagsOnInts(); + } + + IRO_DumpAfterPhase("IRO_ExpressionPropagation", 0); + + if (copts.deadstore || copts.propagation) + IRO_UseDef(copts.deadstore, copts.propagation); + IRO_DumpAfterPhase("after IRO_UseDef", 0); + + IRO_UpdateVars(); + IRO_ConstantFolding(); + IRO_DumpAfterPhase("IRO_ConstantFolding", 0); + + IRO_EvaluateConditionals(); + IRO_RemoveUnreachable(); + IRO_SimplifyConditionals(); + + if (pass == 1 && copts.optimizationlevel > 2) { + IRO_RenumberInts(); + IRO_DumpAfterPhase("Before IRO_FindEmptyLoops", 0); + IRO_FindEmptyLoops(); + IRO_DumpAfterPhase("After IRO_FindEmptyLoops", 0); + IRO_RenumberInts(); + } + + if (copts.unrolling && !copts.optimizesize && pass == 0) { + IRO_DumpAfterPhase("Before IRO_LoopUnroller", 0); + IRO_LoopUnroller(); + IRO_DumpAfterPhase("After IRO_LoopUnroller", 0); + IRO_RenumberInts(); + } + + VectorPhaseCalledFromUnroll = 0; + + if (pass == 0 && (copts.loopinvariants || copts.strengthreduction)) { + IRO_DumpAfterPhase("Before IRO_FindLoops", 0); + IRO_FindLoops(); + LoopOptimizerRun = 1; + IRO_SetLoopDepth(); + } + IRO_DumpAfterPhase("After IRO_FindLoops", 0); + + if (copts.propagation) { + IRO_CopyAndConstantPropagation(); + IRO_ConstantFolding(); + IRO_EvaluateConditionals(); + } + + IRO_DumpAfterPhase("Second pass:IRO_CopyAndConstantPropagation, IRO_ConstantFolding, IRO_EvaluateConditionals", 0); + + if (copts.commonsubs) + IRO_FindExpressions(NULL, 0); + + if (copts.commonsubs) { + IRO_ComputeAvail(); + IRO_CommonSubs(); + } + IRO_DumpAfterPhase("IRO_CommonSubs", 0); + + IRO_UpdateFlagsOnInts(); + IRO_UpdateVars(); + IRO_DoTransformations(); + IRO_ConstantFolding(); + + do { + IRO_UpdateFlagsOnInts(); + + if (copts.deadcode) + IRO_RemoveUnreachable(); + IRO_DumpAfterPhase("IRO_RemoveUnreachable", 0); + + changed = IRO_RemoveRedundantJumps(); + IRO_DumpAfterPhase("IRO_RemoveRedundantJumps", 0); + + changed |= IRO_RemoveLabels(); + IRO_DumpAfterPhase("IRO_RemoveLabels", 0); + + changed |= IRO_DoJumpChaining(); + IRO_DumpAfterPhase("IRO_DoJumpChaining", 0); + + if (copts.propagation) { + IRO_RenumberInts(); + IRO_DumpAfterPhase("Before IRO_CopyAndConstantPropagation", 0); + changed |= IRO_CopyAndConstantPropagation(); + IRO_DumpAfterPhase("After IRO_CopyAndConstantPropagation", 0); + IRO_ConstantFolding(); + } + + if (copts.deadstore || copts.propagation) + changed |= IRO_UseDef(copts.deadstore, copts.propagation); + IRO_DumpAfterPhase("IRO_UseDef", 0); + + changed |= IRO_EvaluateConditionals(); + IRO_DumpAfterPhase("IRO_EvaluateConditionals", 0); + } while (changed); + } + + if (copts.lifetimes) { + IRO_UseDef(0, 0); + IRO_SplitLifetimes(); + } + + IRO_DoTransformations(); + IRO_DumpAfterPhase("Before RebuildCondExpressions", 0); + } + + IRO_RenumberInts(); + IRO_DumpAfterPhase("before IRO_RewriteBitFieldTemps", 0); + IRO_RewriteBitFieldTemps(); + IRO_DumpAfterPhase("After IRO_RewriteBitFieldTemps", 0); + + CountUsage(); + + if (!DisableDueToAsm) { + IRO_RegenerateExpressions(); + IRO_DumpAfterPhase("IRO_RegenerateExpressions", 0); + } + + IRO_DumpAfterPhase("After IRO_Optimizer", 0); + + statements = IRO_Delinearize(IRO_FirstNode, NULL); + + IRO_ZapVarPtrs(); + freeoheap(); + return statements; +} + +void IRO_Setup(void) { + static Boolean ENodeArraysHaveBeenInitialized; + + if (!stIsSetup) { + IRO_Log = 0; + IRO_SetupDump(); + if (!ENodeArraysHaveBeenInitialized) { + IRO_InitializeNodeNamesArray(); + IRO_InitializeIsAssociativeENodeTypeArray(); + IRO_InitializeIsSubableOpArray(); + IRO_InitializeAssignmentOpArray(); + IRO_InitializeComplementaryOpArray(); + IRO_InitializeComplementaryOpLogicalArray(); + IRO_InitializeNonAssignmentOpArray(); + IRO_InitializeAssignmentFoldingFunctionArray(); + IRO_InitializeIRO_IsModifyOpArray(); + IRO_InitializeIRO_IsAssignOpArray(); + ENodeArraysHaveBeenInitialized = 1; + } + stIsSetup = 1; + } +} + +void IRO_Cleanup(void) { + if (stIsSetup) { + IRO_CleanupDump(); + stIsSetup = 0; + } +} + +void CodeGen_UpdateOptimizerOptions(void) { + Boolean flag; + + flag = copts.optimizationlevel >= 1; + copts.deadcode = flag; + + flag = copts.optimizationlevel >= 2; + copts.propagation = flag; + copts.commonsubs = flag; + + flag = copts.optimizationlevel >= 3; + copts.vectorizeloops = flag; + copts.unrolling = flag; + copts.deadstore = flag; + copts.lifetimes = flag; + copts.strengthreduction = flag; + copts.loopinvariants = flag; + + flag = copts.optimizationlevel >= 4; + copts.multiplepasses = flag; +} diff --git a/compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.h b/compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.h new file mode 100644 index 0000000..287e279 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IrOptimizer.h @@ -0,0 +1,30 @@ +#ifndef COMPILER_IROPTIMIZER_H +#define COMPILER_IROPTIMIZER_H + +#include "compiler/common.h" + +typedef struct IROAddrRecord IROAddrRecord; +typedef struct IROAssign IROAssign; +typedef struct IRODef IRODef; +typedef struct IROElmList IROElmList; +typedef struct IROExpr IROExpr; +typedef struct IROLinear IROLinear; +typedef struct IROList IROList; +typedef struct IROListNode IROListNode; +typedef struct IROLoop IROLoop; +typedef struct IRONode IRONode; +typedef struct IROUse IROUse; + +extern Boolean DoScalarize; +extern Boolean DoLinearize; +extern Boolean EarlyReturn; +extern Boolean IRO_CPFirstTime; +extern Boolean VectorPhaseCalledFromUnroll; +extern Boolean IRO_Log; + +extern Statement *IRO_Optimizer(Object *func, Statement *statements); +extern void IRO_Setup(void); +extern void IRO_Cleanup(void); +extern void CodeGen_UpdateOptimizerOptions(void); + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroBitVect.c b/compiler_and_linker/FrontEnd/Optimizer/IroBitVect.c new file mode 100644 index 0000000..873b1ca --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroBitVect.c @@ -0,0 +1,112 @@ +#include "BitVector.h" +#include "compiler/CompilerTools.h" + +void Bv_AllocVector(BitVector **bv, UInt32 size) { + UInt32 long_size = (size / 32) + 1; + *bv = oalloc(sizeof(BitVector) + sizeof(UInt32) * long_size); + (*bv)->size = long_size; + Bv_Clear(*bv); +} + +void Bv_AllocVectorLocal(BitVector **bv, UInt32 size) { + UInt32 long_size = (size / 32) + 1; + *bv = lalloc(sizeof(BitVector) + sizeof(UInt32) * long_size); + (*bv)->size = long_size; + Bv_Clear(*bv); +} + +void Bv_ClearBit(UInt32 bit, BitVector *bv) { + if ((bit / 32) < bv->size) + bv->data[bit / 32] &= ~(1 << (bit & 31)); + else + CError_FATAL(73); +} + +void Bv_And(const BitVector *a, BitVector *b) { + UInt32 i; + for (i = 0; i < b->size; i++) + b->data[i] &= a->data[i]; +} + +void Bv_Or(const BitVector *a, BitVector *b) { + UInt32 i, len; + + len = a->size; + if (b->size < len) + len = b->size; + + for (i = 0; i < len; i++) { + b->data[i] |= a->data[i]; + } +} + +Boolean Bv_BitsInCommon(const BitVector *a, const BitVector *b) { + UInt32 len; + UInt32 i; + + len = a->size; + if (b->size < len) + len = b->size; + + for (i = 0; i < len; i++) { + if (a->data[i] & b->data[i]) + return 1; + } + + return 0; +} + +Boolean Bv_Compare(const BitVector *a, const BitVector *b) { + UInt32 i; + for (i = 0; i < a->size; i++) { + if (a->data[i] != b->data[i]) + return 0; + } + + return 1; +} + +void Bv_Minus(const BitVector *a, BitVector *b) { + UInt32 i; + for (i = 0; i < b->size; i++) + b->data[i] &= ~a->data[i]; +} + +void Bv_Copy(const BitVector *src, BitVector *dst) { + memcpy(dst->data, src->data, sizeof(UInt32) * dst->size); +} + +void Bv_Clear(BitVector *bv) { + memset(bv->data, 0, sizeof(UInt32) * bv->size); +} + +void Bv_Set(BitVector *bv) { + memset(bv->data, 0xFF, sizeof(UInt32) * bv->size); +} + +Boolean Bv_IsSubset(const BitVector *a, const BitVector *b) { + UInt32 i; + + for (i = 0; i < a->size; i++) { + if (b->size < i) { + if (a->data[i]) + return 0; + } else { + if (a->data[i] & ~(b->data[i])) + return 0; + } + } + + return 1; +} + +Boolean Bv_IsEmpty(const BitVector *bv) { + UInt32 i; + + for (i = 0; i < bv->size; i++) { + if (bv->data[i]) + return 0; + } + + return 1; +} diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroCSE.c b/compiler_and_linker/FrontEnd/Optimizer/IroCSE.c new file mode 100644 index 0000000..7bc4866 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroCSE.c @@ -0,0 +1,1038 @@ +#include "IroCSE.h" +#include "IroDump.h" +#include "IroFlowgraph.h" +#include "IroLinearForm.h" +#include "IroMalloc.h" +#include "IroPointerAnalysis.h" +#include "IroSubable.h" +#include "IROUseDef.h" +#include "IroUtil.h" +#include "IroVars.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CInt64.h" +#include "compiler/CParser.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" + +BitVector *IRO_Depends; +Boolean IRO_NotSubable; +Boolean IRO_IsVolatile; +Boolean IRO_CouldError; +IROExpr *IRO_FirstExpr; +IROExpr *IRO_LastExpr; +SInt32 IRO_NumExprs; +static Boolean HasVectorOperand; + +// forward decls +static void IRO_DependsOnForDataFlow(IROLinear *linear, Boolean flag); + +static void GetDependsOfIndirect(IROLinear *nd) { + IROListNode *resultList; + IROListNode *next; + IROListNode *list; + IROListNode *scan; + IROLinear *scannd; + Object *obj; + VarRecord *var; + int index; + Boolean result; + Boolean foundObjRef; + + result = 0; + + if (nd && copts.opt_pointer_analysis && nd->pointsToFunction && FunctionName) { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, nd, &resultList); + if ((list = resultList)) { + for (scan = list; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + result = 1; + break; + } + + foundObjRef = 0; + for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + foundObjRef = 1; + break; + } + } + + if (!foundObjRef) { + result = 1; + break; + } + } + + if (!result) { + while (list) { + for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + obj = scannd->u.node->data.objref; + CError_ASSERT(119, obj != NULL); + var = IRO_FindVar(obj, 1, 1); + CError_ASSERT(121, var != NULL); + index = var->index; + CError_ASSERT(123, index != 0); + + if (is_volatile_object(obj)) { + IRO_IsVolatile = 1; + IRO_NotSubable = 1; + } + Bv_SetBit(index, IRO_Depends); + } + } + list = list->nextList; + } + } + + while (resultList) { + next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + result = 1; + } + } else { + result = 1; + } + + if (result) { + nd = nd->u.monadic; + if (nd->type == IROLinearOp1Arg && nd->nodetype == EBITFIELD) + nd = nd->u.monadic; + + if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD) { + IRO_BaseTerms = 0; + IRO_VarTerms = 0; + IRO_DecomposeAddressExpression_Cheap(nd); + if (IRO_BaseTerms != 1) { + IRO_CouldError = 1; + Bv_SetBit(0, IRO_Depends); + Bv_Or(IRO_FuncKills, IRO_Depends); + } + if (IRO_VarTerms) + IRO_CouldError = 1; + } else { + IRO_CouldError = 1; + Bv_SetBit(0, IRO_Depends); + Bv_Or(IRO_FuncKills, IRO_Depends); + } + } +} + +static void GetDependsOfFunctionCallForDataFlow(IROLinear *nd) { + IROLinear *innernd; + IROListNode *resultList; + IROListNode *next; + IROListNode *list; + IROListNode *scan; + IROLinear *scannd; + Object *obj; + VarRecord *var; + int index; + Boolean result; + Boolean foundObjRef; + ObjectList *olist; + ObjectList *depsList; + + result = 0; + innernd = nd->u.funccall.linear8; + + if (innernd && copts.opt_pointer_analysis && innernd->pointsToFunction && FunctionName) { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, innernd, &resultList); + if ((list = resultList)) { + for (scan = list; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + result = 1; + break; + } + + foundObjRef = 0; + for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + foundObjRef = 1; + obj = scannd->u.node->data.objref; + CError_ASSERT(234, obj != NULL); + + depsList = NULL; + PointerAnalysis_GetFunctionDependencies(obj, nd, &depsList); + + for (olist = depsList; olist; olist = olist->next) { + if (!olist->object) { + result = 1; + break; + } + } + + while (depsList) { + olist = depsList->next; + IRO_free(depsList); + depsList = olist; + } + + if (result) + break; + } + } + + if (!foundObjRef) + result = 1; + if (result) + break; + } + + if (!result) { + for (list = resultList; list; list = list->nextList) { + for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + obj = scannd->u.node->data.objref; + + depsList = NULL; + PointerAnalysis_GetFunctionDependencies(obj, nd, &depsList); + + for (olist = depsList; olist; olist = olist->next) { + var = IRO_FindVar(olist->object, 1, 1); + CError_ASSERT(285, var != NULL); + index = var->index; + CError_ASSERT(287, index != 0); + + if (is_volatile_object(olist->object)) { + IRO_IsVolatile = 1; + IRO_NotSubable = 1; + } + Bv_SetBit(index, IRO_Depends); + } + + while (depsList) { + olist = depsList->next; + IRO_free(depsList); + depsList = olist; + } + } + } + } + } + + while (resultList) { + next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + result = 1; + } + } else { + result = 1; + } + + if (result) { + IRO_DependsOnForDataFlow(nd->u.funccall.linear8, 0); + Bv_Or(IRO_FuncKills, IRO_Depends); + + for (index = nd->u.funccall.argCount - 1; index >= 0; index--) + IRO_DependsOnForDataFlow(nd->u.funccall.args[index], 0); + } +} + +static void IRO_DependsOn(IROLinear *linear, Boolean flag) { + VarRecord *var; + IROLinear *inner; + + if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) { + IRO_IsVolatile = 1; + IRO_NotSubable = 1; + } + + if (!IRO_NotSubable) { + switch (linear->type) { + case IROLinearOperand: + if (flag && linear->u.node->type == EOBJREF) { + if ((var = IRO_FindVar(linear->u.node->data.objref, 0, 1))) { + if (is_volatile_object(var->object)) { + IRO_IsVolatile = 1; + IRO_NotSubable = 1; + } + Bv_SetBit(var->index, IRO_Depends); + } else { + IRO_NotSubable = 1; + } + } + break; + case IROLinearOp1Arg: + if (IRO_IsAssignOp[linear->nodetype]) { + IRO_NotSubable = 1; + } else { + inner = linear->u.monadic; + if (linear->nodetype == EINDIRECT) { + if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD) + inner = inner->u.monadic; + if (inner->type != IROLinearOperand || inner->u.node->type != EOBJREF) + GetDependsOfIndirect(linear); + } + + IRO_DependsOn(inner, linear->nodetype == EINDIRECT); + } + break; + case IROLinearOp2Arg: + if (IRO_IsAssignOp[linear->nodetype]) { + IRO_NotSubable = 1; + } else { + if (linear->nodetype == EDIV || linear->nodetype == EMODULO) { + if (IRO_IsIntConstant(linear->u.diadic.right)) { + if (CInt64_Equal(linear->u.diadic.right->u.node->data.intval, cint64_zero)) + IRO_CouldError = 1; + } else { + IRO_CouldError = 1; + } + } + + IRO_DependsOn(linear->u.diadic.left, flag); + IRO_DependsOn(linear->u.diadic.right, flag); + } + break; + case IROLinearOp3Arg: + if (IRO_IsAssignOp[linear->nodetype]) { + IRO_NotSubable = 1; + } else { + IRO_DependsOn(linear->u.args3.a, flag); + IRO_DependsOn(linear->u.args3.b, flag); + IRO_DependsOn(linear->u.args3.c, flag); + } + break; + case IROLinearFunccall: + IRO_NotSubable = 1; + break; + default: + CError_FATAL(479); + } + } +} + +static void IRO_DependsOnForDataFlow(IROLinear *linear, Boolean flag) { + VarRecord *var; + IROLinear *inner; + + if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) { + IRO_IsVolatile = 1; + IRO_NotSubable = 1; + } + + switch (linear->type) { + case IROLinearOperand: + if (flag && linear->u.node->type == EOBJREF) { + if ((var = IRO_FindVar(linear->u.node->data.objref, 0, 1))) { + if (is_volatile_object(var->object)) { + IRO_IsVolatile = 1; + IRO_NotSubable = 1; + } + Bv_SetBit(var->index, IRO_Depends); + } else { + IRO_NotSubable = 1; + } + } + break; + case IROLinearOp1Arg: + if (IRO_IsAssignOp[linear->nodetype]) + IRO_NotSubable = 1; + + inner = linear->u.monadic; + if (linear->nodetype == EINDIRECT) { + if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD) + inner = inner->u.monadic; + if (inner->type != IROLinearOperand || inner->u.node->type != EOBJREF) + GetDependsOfIndirect(linear); + } + + IRO_DependsOnForDataFlow(inner, linear->nodetype == EINDIRECT); + break; + case IROLinearOp2Arg: + if (IRO_IsAssignOp[linear->nodetype]) + IRO_NotSubable = 1; + + if (linear->nodetype == EDIV || linear->nodetype == EMODULO) { + if (IRO_IsIntConstant(linear->u.diadic.right)) { + if (CInt64_Equal(linear->u.diadic.right->u.node->data.intval, cint64_zero)) + IRO_CouldError = 1; + } else { + IRO_CouldError = 1; + } + } + + IRO_DependsOnForDataFlow(linear->u.diadic.left, flag); + IRO_DependsOnForDataFlow(linear->u.diadic.right, flag); + break; + case IROLinearOp3Arg: + if (IRO_IsAssignOp[linear->nodetype]) + IRO_NotSubable = 1; + + IRO_DependsOnForDataFlow(linear->u.args3.a, flag); + IRO_DependsOnForDataFlow(linear->u.args3.b, flag); + IRO_DependsOnForDataFlow(linear->u.args3.c, flag); + break; + case IROLinearFunccall: + IRO_NotSubable = 1; + GetDependsOfFunctionCallForDataFlow(linear); + break; + default: + CError_FATAL(650); + } +} + +void IRO_FindDepends_NoAlloc(IROLinear *linear) { + Bv_Clear(IRO_Depends); + IRO_CouldError = 0; + IRO_NotSubable = 0; + IRO_IsVolatile = 0; + IRO_DependsOnForDataFlow(linear, 0); +} + +void IRO_FindDepends(IROLinear *linear) { + Bv_AllocVector(&IRO_Depends, IRO_NumVars + 1); + IRO_CouldError = 0; + IRO_NotSubable = 0; + IRO_DependsOn(linear, 0); +} + +static void VecAct(IROLinear *linear, Boolean isFirst) { + if (!isFirst && (linear->flags & IROLF_VecOpBase)) + HasVectorOperand = 1; +} + +static Boolean IRO_DoesNotHaveVectorOperand(IROLinear *linear) { + HasVectorOperand = 0; + IRO_WalkTree(linear, VecAct); + return HasVectorOperand == 0; +} + +static void IRO_AddExpression(IROLinear *linear, IRONode *node, Boolean flag) { + IROExpr *expr; + + if ((linear->flags & IROLF_Reffed) && IRO_IsSubableExpression(linear) && IRO_DoesNotHaveVectorOperand(linear)) { + expr = oalloc(sizeof(IROExpr)); + expr->x0 = 0; + expr->index = ++IRO_NumExprs; + expr->linear = linear; + expr->x8 = NULL; + expr->node = node; + IRO_FindDepends(linear); + expr->depends = IRO_Depends; + expr->notSubable = IRO_NotSubable; + expr->couldError = IRO_CouldError; + expr->next = NULL; + expr->x14 = NULL; + if (IRO_FirstExpr) + IRO_LastExpr->next = expr; + else + IRO_FirstExpr = expr; + IRO_LastExpr = expr; + linear->expr = expr; + } +} + +void IRO_FindExpressions(BitVector *bv, Boolean flag) { + IROLinear *nd; + IRONode *fnode; + + IRO_FirstExpr = IRO_LastExpr = NULL; + IRO_NumExprs = 0; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (!bv || Bv_IsBitSet(fnode->index, bv)) { + for (nd = fnode->first; nd; nd = nd->next) { + nd->expr = NULL; + IRO_AddExpression(nd, fnode, flag); + if (nd == fnode->last) + break; + } + } else { + for (nd = fnode->first; nd; nd = nd->next) { + nd->expr = NULL; + if (nd == fnode->last) + break; + } + } + } + + IRO_CheckForUserBreak(); +} + +void IRO_RemoveExpr(IROExpr *expr) { + IROExpr *prev; + IROExpr *scan; + + scan = IRO_FirstExpr; + prev = NULL; + while (scan != expr) { + prev = scan; + scan = scan->next; + CError_ASSERT(809, scan); + } + + expr->linear->expr = NULL; + if (prev) + prev->next = expr->next; + else + IRO_FirstExpr = expr->next; +} + +static void GetExprKillsByIndirectAssignment(IROLinear *linear) { + IROLinear *inner; + IROListNode *resultList; + IROListNode *next; + IROListNode *list; + IROListNode *scan; + IROLinear *scannd; + Object *obj; + VarRecord *var; + int index; + Boolean result; + Boolean foundObjRef; + IROExpr *expr; + + result = 0; + if (linear->type == IROLinearOp2Arg) + linear = linear->u.diadic.left; + else + linear = linear->u.monadic; + + if ( + linear && + linear->type == IROLinearOp1Arg && + linear->nodetype == EINDIRECT && + (inner = linear->u.monadic) && + copts.opt_pointer_analysis && + inner->pointsToFunction && + FunctionName + ) { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList); + if ((list = resultList)) { + for (scan = list; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + result = 1; + break; + } + + foundObjRef = 0; + for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + foundObjRef = 1; + break; + } + } + + if (!foundObjRef) { + result = 1; + break; + } + } + + if (!result) { + while (list) { + for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + obj = scannd->u.node->data.objref; + CError_ASSERT(893, obj != NULL); + var = IRO_FindVar(obj, 1, 1); + CError_ASSERT(895, var != NULL); + index = var->index; + + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if (Bv_IsBitSet(index, expr->depends)) + Bv_SetBit(expr->index, IRO_ExprKills); + } + } + } + list = list->nextList; + } + } + + while (resultList) { + next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + result = 1; + } + } else { + result = 1; + } + + if (result) { + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if (Bv_BitsInCommon(expr->depends, IRO_FuncKills)) + Bv_SetBit(expr->index, IRO_ExprKills); + } + } +} + +static void GetExprKillsByFunctionCall(IROLinear *funccall) { + IROLinear *innernd; + IROListNode *resultList; + IROListNode *next; + IROListNode *list; + IROListNode *scan; + IROLinear *scannd; + Object *obj; + VarRecord *var; + int index; + Boolean result; + Boolean foundObjRef; + ObjectList *olist; + ObjectList *depsList; + IROExpr *expr; + + result = 0; + innernd = funccall->u.funccall.linear8; + + if (innernd && copts.opt_pointer_analysis && innernd->pointsToFunction && FunctionName) { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, innernd, &resultList); + if ((list = resultList)) { + for (scan = list; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + result = 1; + break; + } + + foundObjRef = 0; + for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + foundObjRef = 1; + obj = scannd->u.node->data.objref; + CError_ASSERT(991, obj != NULL); + + depsList = NULL; + PointerAnalysis_GetFunctionKills(obj, funccall, &depsList); + + for (olist = depsList; olist; olist = olist->next) { + if (!olist->object) { + result = 1; + break; + } + } + + while (depsList) { + olist = depsList->next; + IRO_free(depsList); + depsList = olist; + } + + if (result) + break; + } + } + + if (!foundObjRef) + result = 1; + if (result) + break; + } + + if (!result) { + for (list = resultList; list; list = list->nextList) { + for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + obj = scannd->u.node->data.objref; + + depsList = NULL; + PointerAnalysis_GetFunctionKills(obj, funccall, &depsList); + + for (olist = depsList; olist; olist = olist->next) { + var = IRO_FindVar(olist->object, 1, 1); + CError_ASSERT(1042, var != NULL); + index = var->index; + CError_ASSERT(1044, index != 0); + + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if (Bv_IsBitSet(index, expr->depends)) + Bv_SetBit(expr->index, IRO_ExprKills); + } + } + + while (depsList) { + olist = depsList->next; + IRO_free(depsList); + depsList = olist; + } + } + } + } + } + + while (resultList) { + next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + result = 1; + } + } else { + result = 1; + } + + if (result) { + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if (Bv_BitsInCommon(expr->depends, IRO_FuncKills)) + Bv_SetBit(expr->index, IRO_ExprKills); + } + } +} + +static void IRO_GetExprKills(IROLinear *linear) { + Bv_Clear(IRO_ExprKills); + switch (linear->type) { + case IROLinearOp1Arg: + case IROLinearOp2Arg: + if (IRO_IsAssignOp[linear->nodetype]) { + VarRecord *var; + int index; + + var = IRO_FindAssigned(linear); + index = 0; + if (var) + index = var->index; + if (!index) { + GetExprKillsByIndirectAssignment(linear); + } else { + IROExpr *expr; + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if (Bv_IsBitSet(index, expr->depends)) + Bv_SetBit(expr->index, IRO_ExprKills); + } + } + } + break; + case IROLinearAsm: { + IROExpr *expr; + IRO_GetKills(linear); + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if (Bv_BitsInCommon(expr->depends, IRO_VarKills)) + Bv_SetBit(expr->index, IRO_ExprKills); + } + break; + } + case IROLinearFunccall: + GetExprKillsByFunctionCall(linear); + break; + } +} + +void IRO_ComputeAvail(void) { + IRONode *node; + IROLinear *linear; + SInt32 counter; + BitVector *bv; + Boolean flag; + + counter = 0; + node = IRO_FirstNode; + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + Bv_AllocVector(&IRO_ExprKills, IRO_NumExprs + 1); + + while (node) { + Bv_AllocVector(&node->x16, IRO_NumExprs); + if (node->numpred) + Bv_Set(node->x16); + Bv_AllocVector(&node->x22, IRO_NumExprs); + Bv_AllocVector(&node->x1E, IRO_NumExprs); + Bv_AllocVector(&node->x1A, IRO_NumExprs); + + for (linear = node->first; linear; linear = linear->next) { + if (linear->expr) + Bv_SetBit(linear->expr->index, node->x1E); + IRO_GetExprKills(linear); + Bv_Or(IRO_ExprKills, node->x22); + Bv_Minus(IRO_ExprKills, node->x1E); + if (linear == node->last) + break; + + if (counter > 250) { + IRO_CheckForUserBreak(); + counter = 0; + } else { + counter++; + } + } + + Bv_Copy(node->x16, node->x1A); + Bv_Minus(node->x22, node->x1A); + Bv_Or(node->x1E, node->x1A); + node = node->nextnode; + } + + IRO_CheckForUserBreak(); + + Bv_AllocVector(&bv, IRO_NumExprs); + do { + flag = 0; + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (!node->numpred) { + Bv_Clear(bv); + } else { + UInt16 i; + Bv_Set(bv); + for (i = 0; i < node->numpred; i++) + Bv_And(IRO_NodeTable[node->pred[i]]->x1A, bv); + } + + if (!Bv_Compare(bv, node->x16)) { + flag = 1; + Bv_Copy(bv, node->x16); + } + + Bv_Copy(node->x16, node->x1A); + Bv_Minus(node->x22, node->x1A); + Bv_Or(node->x1E, node->x1A); + } + IRO_CheckForUserBreak(); + } while (flag); +} + +static void IRO_MakeReplacementEmbedded(IROExpr *expr) { + IROLinear *opnd; + IROLinear *ind; + IROLinear *ass; + + IRO_GetTemp(expr); + + opnd = IRO_NewLinear(IROLinearOperand); + opnd->u.node = create_objectrefnode(expr->x8); + opnd->rtype = opnd->u.node->data.objref->type; + opnd->index = ++IRO_NumLinear; + opnd->flags |= IROLF_Reffed | IROLF_Assigned | IROLF_Ind; + + ind = IRO_NewLinear(IROLinearOp1Arg); + ind->nodetype = EINDIRECT; + ind->rtype = expr->linear->rtype; + ind->u.monadic = opnd; + ind->index = ++IRO_NumLinear; + ind->flags |= IROLF_Reffed | IROLF_Assigned; + + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->nodetype = EASS; + ass->u.diadic.left = ind; + ass->u.diadic.right = expr->linear; + ass->rtype = expr->linear->rtype; + ass->index = ++IRO_NumLinear; + + opnd->next = ind; + ind->next = ass; + IRO_ReplaceReferenceWithNode(expr->linear, ass); + IRO_PasteAfter(opnd, ass, expr->linear); +} + +static void IRO_ActUnmarkSubExpressions(IROLinear *linear, Boolean isFirst) { + if (isFirst) + linear->flags &= ~IROLF_8; +} + +static void CheckCommonSub(IROLinear *linear) { + IROExpr *expr; + + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if (expr->linear != linear && !expr->x14) { + if (Bv_IsBitSet(expr->index, IRO_Avail) && !expr->notSubable && IRO_ExprsSame(linear, expr->linear)) { + IRO_WalkTree(linear, IRO_ActUnmarkSubExpressions); + linear->flags |= IROLF_8; + linear->expr->x14 = expr; + break; + } + } + } +} + +static void MoveCommonSub(IROExpr *expr) { + SInt32 best; + SInt32 sz1; + SInt32 sz2; + SInt32 i1; + SInt32 i2; + IROLinear *scan; + IROLinear *array1[64]; + IROLinear *array2[64]; + IROExpr *scanexpr; + + sz1 = 0; + scan = expr->linear; + do { + scan = IRO_LocateFather(scan); + if (scan) { + if (sz1 == 64) + return; + array1[sz1++] = scan; + } + } while (scan); + + best = -1; + for (scanexpr = IRO_FirstExpr; scanexpr; scanexpr = scanexpr->next) { + if (scanexpr->x14 == expr) { + sz2 = 0; + scan = scanexpr->linear; + do { + scan = IRO_LocateFather(scan); + if (scan) { + if (sz2 == 64) + return; + array2[sz2++] = scan; + } + } while (scan); + + i1 = sz1; + i2 = sz2; + while (i1 && i2 && array1[i1 - 1] == array2[i2 - 1]) { + i1--; + i2--; + } + + if (i1 != sz1 && i1 > best) + best = i1; + } + } + + if (best < 0) { + IRO_MakeReplacementEmbedded(expr); + } else { + IROLinear *start; + IROLinear *comma; + IRO_Dump("Moving common sub from node %d to %d\n", expr->linear->index, array1[best]->index); + start = IRO_FindStart(array1[best]); + IRO_GetTemp(expr); + IRO_ReplaceReference(expr->linear, expr->x8, expr->linear); + IRO_MoveExpression(expr, start); + + comma = IRO_NewLinear(IROLinearOp2Arg); + comma->nodetype = ECOMMA; + comma->rtype = array1[best]->rtype; + comma->u.diadic.left = IRO_AssignToTemp(expr); + comma->u.diadic.right = array1[best]; + comma->stmt = array1[best]->stmt; + IRO_ReplaceReferenceWithNode(array1[best], comma); + IRO_PasteAfter(comma, comma, array1[best]); + } +} + +static void ReplaceCommonSub(IROLinear *linear) { + IROExpr *expr = linear->expr->x14; + if (!expr->x8) { + MoveCommonSub(expr); + if (!expr->x8) + return; + } + + IRO_Dump("Replacing common sub at %d with %d\n", linear->index, expr->linear->index); + IRO_ReplaceReference(linear, expr->x8, linear); + IRO_RemoveExpr(linear->expr); + IRO_NopOut(linear); +} + +void IRO_CommonSubs(void) { + IRONode *node; + IROLinear *linear; + SInt32 counter; + + counter = 0; + for (node = IRO_FirstNode; node; node = node->nextnode) { + IRO_Avail = node->x16; + linear = node->first; + while (1) { + if (!linear) + break; + if (linear->expr && !linear->expr->notSubable) + CheckCommonSub(linear); + if (linear->expr) + Bv_SetBit(linear->expr->index, IRO_Avail); + IRO_GetExprKills(linear); + Bv_Minus(IRO_ExprKills, IRO_Avail); + if (linear == node->last) + break; + if (counter > 250) { + IRO_CheckForUserBreak(); + counter = 0; + } else { + counter++; + } + linear = linear->next; + } + } + + for (node = IRO_FirstNode; node; node = node->nextnode) { + for (linear = node->first; linear; linear = linear->next) { + if (linear->expr && (linear->flags & IROLF_8) && !IRO_HasSideEffect(linear)) + ReplaceCommonSub(linear); + if (linear == node->last) + break; + if (counter > 250) { + IRO_CheckForUserBreak(); + counter = 0; + } else { + counter++; + } + } + } + + IRO_CheckForUserBreak(); +} + +static Boolean CountThisSubableOperandUse(IROUse *use) { + return use->x1C != 0; +} + +static int GetSubableOperandUseCount(VarRecord *var) { + int count = 0; + IROUse *use; + + if (var->uses) { + for (use = var->uses; use; use = use->varnext) { + if (CountThisSubableOperandUse(use)) + count++; + } + } + + return count; +} + +static void IRO_MakeTopLevelExprForSubableOperand(IROLinear *linear) { + IROLinear *copy = IRO_NewLinear(IROLinearOperand); + memcpy(copy, linear, sizeof(IROLinear)); + copy->index = ++IRO_NumLinear; + + if (IRO_FirstLinear && IRO_FirstLinear->type == IROLinearNop) + IRO_PasteAfter(copy, copy, IRO_FirstLinear); + else + IRO_Paste(copy, copy, IRO_FirstLinear); +} + +void IRO_GenerateTopLevelExprsForSubableOperands(void) { + IROLinear *nd; + IRONode *fnode; + VarRecord *var; + BitVector *bv; + + Bv_AllocVector(&bv, IRO_NumVars + 1); + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + for (nd = fnode->first; nd; nd = nd->next) { + nd->expr = NULL; + if ((nd->flags & IROLF_Reffed) && IRO_IsSubableExpression(nd) && IRO_DoesNotHaveVectorOperand(nd)) { + if (nd->type == IROLinearOperand && nd->u.node && nd->u.node->type == EOBJREF) { + if ((var = IRO_FindVar(nd->u.node->data.objref, 0, 1))) { + if (!Bv_IsBitSet(var->index, bv)) { + IRO_MakeTopLevelExprForSubableOperand(nd); + Bv_SetBit(var->index, bv); + } + } + } + } + + if (nd == fnode->last) + break; + } + } +} diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroCSE.h b/compiler_and_linker/FrontEnd/Optimizer/IroCSE.h new file mode 100644 index 0000000..c1e166c --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroCSE.h @@ -0,0 +1,45 @@ +#ifndef COMPILER_IROCSE_H +#define COMPILER_IROCSE_H + +#include "IrOptimizer.h" +#include "BitVector.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +struct IROExpr { + Boolean x0; + UInt16 index; + IROLinear *linear; + Object *x8; + IRONode *node; + BitVector *depends; + IROExpr *x14; + Boolean couldError; + Boolean notSubable; + IROLinear *x1A; + VarRecord *x1E; + IROLinear *x22; + IROExpr *next; +}; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +extern BitVector *IRO_Depends; +extern Boolean IRO_NotSubable; +extern Boolean IRO_IsVolatile; +extern Boolean IRO_CouldError; +extern IROExpr *IRO_FirstExpr; +extern IROExpr *IRO_LastExpr; +extern SInt32 IRO_NumExprs; + +extern void IRO_FindDepends_NoAlloc(IROLinear *linear); +extern void IRO_FindDepends(IROLinear *linear); +extern void IRO_FindExpressions(BitVector *bv, Boolean flag); +extern void IRO_RemoveExpr(IROExpr *expr); +extern void IRO_ComputeAvail(void); +extern void IRO_CommonSubs(void); +extern void IRO_GenerateTopLevelExprsForSubableOperands(void); + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroDump.c b/compiler_and_linker/FrontEnd/Optimizer/IroDump.c new file mode 100644 index 0000000..d21496f --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroDump.c @@ -0,0 +1,660 @@ +#include "IroDump.h" +#include "IroCSE.h" +#include "IroFlowgraph.h" +#include "IroLinearForm.h" +#include "IroPropagate.h" +#include "IroUtil.h" +#include "IroVars.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CParser.h" +#include "compiler/objects.h" + +static FILE *DumpFile; +static char *nodenames[MAXEXPR]; + +char *IRO_NodeName(ENodeType nodetype) { + return nodenames[nodetype]; +} + +void IRO_InitializeNodeNamesArray(void) { + int i; + for (i = 0; i < MAXEXPR; i++) + nodenames[i] = ""; + + nodenames[EPOSTINC] = "EPOSTINC"; + nodenames[EPOSTDEC] = "EPOSTDEC"; + nodenames[EPREINC] = "EPREINC"; + nodenames[EPREDEC] = "EPREDEC"; + nodenames[EINDIRECT] = "EINDIRECT"; + nodenames[EMONMIN] = "EMONMIN"; + nodenames[EBINNOT] = "EBINNOT"; + nodenames[ELOGNOT] = "ELOGNOT"; + nodenames[EFORCELOAD] = "EFORCELOAD"; + nodenames[EMUL] = "EMUL"; + nodenames[EMULV] = "EMULV"; + nodenames[EDIV] = "EDIV"; + nodenames[EMODULO] = "EMODULO"; + nodenames[EADDV] = "EADDV"; + nodenames[ESUBV] = "ESUBV"; + nodenames[EADD] = "EADD"; + nodenames[ESUB] = "ESUB"; + nodenames[ESHL] = "ESHL"; + nodenames[ESHR] = "ESHR"; + nodenames[ELESS] = "ELESS"; + nodenames[EGREATER] = "EGREATER"; + nodenames[ELESSEQU] = "ELESSEQU"; + nodenames[EGREATEREQU] = "EGREATEREQU"; + nodenames[EEQU] = "EEQU"; + nodenames[ENOTEQU] = "ENOTEQU"; + nodenames[EAND] = "EAND"; + nodenames[EXOR] = "EXOR"; + nodenames[EOR] = "EOR"; + nodenames[ELAND] = "ELAND"; + nodenames[ELOR] = "ELOR"; + nodenames[EASS] = "EASS"; + nodenames[EMULASS] = "EMULASS"; + nodenames[EDIVASS] = "EDIVASS"; + nodenames[EMODASS] = "EMODASS"; + nodenames[EADDASS] = "EADDASS"; + nodenames[ESUBASS] = "ESUBASS"; + nodenames[ESHLASS] = "ESHLASS"; + nodenames[ESHRASS] = "ESHRASS"; + nodenames[EANDASS] = "EANDASS"; + nodenames[EXORASS] = "EXORASS"; + nodenames[EORASS] = "EORASS"; + nodenames[ECOMMA] = "ECOMMA"; + nodenames[EPMODULO] = "EPMODULO"; + nodenames[EROTL] = "EROTL"; + nodenames[EROTR] = "EROTR"; + nodenames[EBCLR] = "EBCLR"; + nodenames[EBTST] = "EBTST"; + nodenames[EBSET] = "EBSET"; + nodenames[ETYPCON] = "ETYPCON"; + nodenames[EBITFIELD] = "EBITFIELD"; + nodenames[EINTCONST] = "EINTCONST"; + nodenames[EFLOATCONST] = "EFLOATCONST"; + nodenames[ESTRINGCONST] = "ESTRINGCONST"; + nodenames[ECOND] = "ECOND"; + nodenames[EFUNCCALL] = "EFUNCCALL"; + nodenames[EFUNCCALLP] = "EFUNCCALLP"; + nodenames[EOBJREF] = "EOBJREF"; + nodenames[EMFPOINTER] = "EMFPOINTER"; + nodenames[ENULLCHECK] = "ENULLCHECK"; + nodenames[EPRECOMP] = "EPRECOMP"; + nodenames[ETEMP] = "ETEMP"; + nodenames[EARGOBJ] = "EARGOBJ"; + nodenames[ELOCOBJ] = "ELOCOBJ"; + nodenames[ELABEL] = "ELABEL"; + nodenames[ESETCONST] = "ESETCONST"; + nodenames[ENEWEXCEPTION] = "ENEWEXCEPTION"; + nodenames[ENEWEXCEPTIONARRAY] = "ENEWEXCEPTIONARRAY"; + nodenames[EOBJLIST] = "EOBJLIST"; + nodenames[EMEMBER] = "EMEMBER"; + nodenames[ETEMPLDEP] = "ETEMPLDEP"; + nodenames[EINSTRUCTION] = "EINSTRUCTION"; + nodenames[EDEFINE] = "EDEFINE"; + nodenames[EREUSE] = "EREUSE"; + nodenames[EASSBLK] = "EASSBLK"; + nodenames[EVECTOR128CONST] = "EVECTOR128CONST"; + nodenames[ECONDASS] = "ECONDASS"; +} + +static void DumpENode(ENode *enode) { + char buf[64]; + + if (IRO_Log) { + switch (enode->type) { + case EOBJREF: + fprintf(DumpFile, "%s", enode->data.objref->name->name); + break; + case EINTCONST: + CInt64_PrintDec(buf, enode->data.intval); + fprintf(DumpFile, "%s", buf); + break; + case EFLOATCONST: + fprintf(DumpFile, "%g", enode->data.floatval.value); + break; + case EVECTOR128CONST: + fprintf(DumpFile, "%.8lX%.8lX%.8lX%.8lX", + enode->data.vector128val.ul[0], + enode->data.vector128val.ul[1], + enode->data.vector128val.ul[2], + enode->data.vector128val.ul[3] + ); + break; + } + } +} + +static void DumpLinearNode(IROLinear *linear) { + int i; + + if (IRO_Log) { + fprintf(DumpFile, "%4d: ", linear->index); + switch (linear->type) { + case IROLinearNop: + fprintf(DumpFile, "Nop"); + break; + case IROLinearOperand: + fprintf(DumpFile, "Operand "); + DumpENode(linear->u.node); + break; + case IROLinearOp1Arg: + fprintf(DumpFile, "%s %d", nodenames[linear->nodetype], linear->u.monadic->index); + break; + case IROLinearOp2Arg: + fprintf(DumpFile, "%s %d %d", nodenames[linear->nodetype], linear->u.diadic.left->index, linear->u.diadic.right->index); + break; + case IROLinearGoto: + fprintf(DumpFile, "Goto %s", linear->u.label.label->name->name); + break; + case IROLinearIf: + fprintf(DumpFile, "If %d %s", linear->u.label.x4->index, linear->u.label.label->name->name); + break; + case IROLinearIfNot: + fprintf(DumpFile, "IfNot %d %s", linear->u.label.x4->index, linear->u.label.label->name->name); + break; + case IROLinearReturn: + fprintf(DumpFile, "Return "); + if (linear->u.monadic) + fprintf(DumpFile, "%d", linear->u.monadic->index); + break; + case IROLinearLabel: + fprintf(DumpFile, "Label %s", linear->u.label.label->name->name); + break; + case IROLinearSwitch: + fprintf(DumpFile, "Switch %d", linear->u.swtch.x4->index); + break; + case IROLinearOp3Arg: + fprintf(DumpFile, "%s %d %d %d", + nodenames[linear->nodetype], + linear->u.args3.a->index, + linear->u.args3.b->index, + linear->u.args3.c->index); + break; + case IROLinearFunccall: + fprintf(DumpFile, "Funccall %d(", linear->u.funccall.linear8->index); + for (i = 0; i < linear->u.funccall.argCount; i++) { + fprintf(DumpFile, "%d", linear->u.funccall.args[i]->index); + if (i < (linear->u.funccall.argCount - 1)) + fprintf(DumpFile, ","); + } + fprintf(DumpFile, ")"); + break; + case IROLinearBeginCatch: + fprintf(DumpFile, "BeginCatch %d", linear->u.ctch.linear->index); + break; + case IROLinearEndCatch: + fprintf(DumpFile, "EndCatch %d", linear->u.monadic->index); + break; + case IROLinearEndCatchDtor: + fprintf(DumpFile, "EndCatchDtor %d", linear->u.monadic->index); + break; + case IROLinearEnd: + fprintf(DumpFile, "End"); + break; + } + + if (linear->flags & IROLF_Assigned) fprintf(DumpFile, " "); + if (linear->flags & IROLF_Used) fprintf(DumpFile, " "); + if (linear->flags & IROLF_Ind) fprintf(DumpFile, " "); + if (linear->flags & IROLF_Subs) fprintf(DumpFile, " "); + if (linear->flags & IROLF_LoopInvariant) fprintf(DumpFile, " "); + if (linear->flags & IROLF_BeginLoop) fprintf(DumpFile, " "); + if (linear->flags & IROLF_EndLoop) fprintf(DumpFile, " "); + if (linear->flags & IROLF_Ris) fprintf(DumpFile, " "); + if (linear->flags & IROLF_Immind) fprintf(DumpFile, " "); + if (linear->flags & IROLF_Reffed) fprintf(DumpFile, " "); + if (linear->flags & IROLF_VecOp) fprintf(DumpFile, " "); + if (linear->flags & IROLF_VecOpBase) fprintf(DumpFile, " "); + if (linear->flags & IROLF_CounterLoop) fprintf(DumpFile, " "); + if (linear->flags & IROLF_BitfieldIndirect) fprintf(DumpFile, " "); + if (linear->flags & IROLF_CouldError) fprintf(DumpFile, " "); + + if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) + fprintf(DumpFile, " "); + + if (IS_LINEAR_ENODE(linear, EOBJREF)) { + VarRecord *var = IRO_FindVar(linear->u.node->data.objref, 0, 1); + if (var && is_volatile_object(var->object)) + fprintf(DumpFile, " "); + } + + fprintf(DumpFile, "\n"); + } +} + +static void DumpAct(IROLinear *linear, Boolean isFirst) { + if (!isFirst) + DumpLinearNode(linear); +} + +void IRO_DumpIntTree(IROLinear *linear) { + IRO_WalkTree(linear, DumpAct); +} + +void IRO_DumpLinearList(IROLinear *linear) { + if (!IRO_Log) + return; + + while (linear) { + DumpLinearNode(linear); + linear = linear->next; + } + fprintf(DumpFile, "\n"); +} + +static void DumpList(int num, UInt16 *list) { + int i; + + if (IRO_Log) { + for (i = 0; i < num; i++) + fprintf(DumpFile, "%d ", list[i]); + fprintf(DumpFile, "\n"); + } +} + +void IRO_DumpBits(char *name, BitVector *bv) { + SInt32 i; + SInt32 rangeStart; + Boolean inRange = 0; + Boolean isFirst = 1; + + if (!IRO_Log) + return; + + fprintf(DumpFile, name); + if (!bv) { + fprintf(DumpFile, "NULL"); + } else { + for (i = 0; i < (bv->size * 32); i++) { + if (Bv_IsBitSet(i, bv)) { + if (!inRange) { + if (!isFirst) + fputc(',', DumpFile); + isFirst = 0; + fprintf(DumpFile, "%d", i); + inRange = 1; + rangeStart = i; + } + } else { + if (inRange) { + inRange = 0; + if (i != (rangeStart + 1)) + fprintf(DumpFile, "-%d", i - 1); + } + } + } + + if (inRange && i != (rangeStart + 1)) + fprintf(DumpFile, "-%d", i - 1); + } + + fprintf(DumpFile, "\n"); +} + +void IRO_DumpAfterPhase(char *str, Boolean flag) { +#ifdef CW_ENABLE_IRO_DEBUG + if (copts.debuglisting) + flag = 1; +#endif + if (flag) { + IRO_Dump("Dumping function %s after %s \n", FunctionName ? FunctionName->name->name : "Init-code", str); + IRO_Dump("--------------------------------------------------------------------------------\n"); + IRO_DumpFlowgraph(); + } +} + +void IRO_LogForFunction(char *name) { + if (FunctionName) { + if (!strcmp(FunctionName->name->name, name)) + IRO_Log = 1; + else + IRO_Log = 0; + } +} + +void IRO_DumpFlowgraph(void) { + IRONode *node; + IROLinear *linear; + + if (IRO_Log && DumpFile) { + fprintf(DumpFile, "\nFlowgraph\n"); + for (node = IRO_FirstNode; node; node = node->nextnode) { + fprintf(DumpFile, "Flowgraph node %d First=%d, Last=%d\n", node->index, node->first->index, node->last->index); + + fprintf(DumpFile, "Succ = "); + DumpList(node->numsucc, node->succ); + fprintf(DumpFile, "Pred = "); + DumpList(node->numpred, node->pred); + + fprintf(DumpFile, "MustReach = %d, MustReach1=%d\n", node->mustreach, node->mustreach1); + fprintf(DumpFile, "LoopDepth = %d\n", node->loopdepth); + + IRO_DumpBits("Dom: ", node->dom); + if ((linear = node->first)) { + while (1) { + DumpLinearNode(linear); + if (linear == node->last) + break; + linear = linear->next; + } + } + + fprintf(DumpFile, "\n\n"); + } + fprintf(DumpFile, "\n"); + fflush(DumpFile); + } +} + +void IRO_DumpNode(IRONode *node) { + IROLinear *linear; + + if (IRO_Log) { + if (!DumpFile) + return; + + while (node) { + fprintf(DumpFile, "Flowgraph node %d First=%d, Last=%d\n", node->index, node->first->index, + node->last->index); + + fprintf(DumpFile, "Succ = "); + DumpList(node->numsucc, node->succ); + fprintf(DumpFile, "Pred = "); + DumpList(node->numpred, node->pred); + + fprintf(DumpFile, "MustReach = %d MustReach1 = %d\n", node->mustreach, node->mustreach1); + fprintf(DumpFile, "LoopDepth = %d\n", node->loopdepth); + + IRO_DumpBits("Dom: ", node->dom); + if ((linear = node->first)) { + while (1) { + DumpLinearNode(linear); + if (linear == node->last) + break; + linear = linear->next; + } + } + + fprintf(DumpFile, "\n\n"); + node = node->nextnode; + } + + fprintf(DumpFile, "\n"); + fflush(DumpFile); + } +} + +void IRO_DumpAssignments(void) { + IROAssign *assign; + + if (IRO_Log) { + fprintf(DumpFile, "\nAssignments\n\n"); + for (assign = IRO_FirstAssign; assign; assign = assign->next) { + fprintf(DumpFile, "%5d ", assign->index); + DumpLinearNode(assign->linear); + fprintf(DumpFile, "\n"); + } + fprintf(DumpFile, "\n"); + } +} + +void IRO_DumpVars(void) { + VarRecord *var; + + if (IRO_Log) { + fprintf(DumpFile, "\nVariables\n"); + for (var = IRO_FirstVar; var; var = var->next) { + fprintf(DumpFile, "%5d %s %s\n", var->index, var->object->name->name, var->xB ? "" : ""); + } + fprintf(DumpFile, "\n"); + } +} + +void IRO_DumpDf(void) { + IRONode *node; + + if (IRO_Log) { + for (node = IRO_FirstNode; node; node = node->nextnode) { + fprintf(DumpFile, "Node %d\n", node->index); + if (node->x16) IRO_DumpBits("In: ", node->x16); + if (node->x1E) IRO_DumpBits("Gen: ", node->x1E); + if (node->x22) IRO_DumpBits("Kill: ", node->x22); + if (node->x1A) IRO_DumpBits("Out: ", node->x1A); + if (node->x2A) IRO_DumpBits("AA: ", node->x2A); + fprintf(DumpFile, "\n"); + } + fprintf(DumpFile, "\n"); + } +} + +void IRO_DumpExprs(void) { + IROExpr *expr; + + if (IRO_Log) { + fprintf(DumpFile, "Expressions\n\n"); + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + fprintf(DumpFile, "%4d: %d FN:%d CE:%d NS:%d ", expr->index, expr->linear->index, expr->node->index, expr->couldError, expr->notSubable); + IRO_DumpBits("Depends: ", expr->depends); + fprintf(DumpFile, "\n"); + } + fprintf(DumpFile, "\n"); + } +} + +void IRO_SetupDump(void) { +#ifdef CW_ENABLE_IRO_DEBUG + IRO_Log = 1; +#endif + + if (IRO_Log) { + if ((DumpFile = fopen("OPT.LOG", "wt")) == NULL) + IRO_Log = 0; + } +} + +void IRO_CleanupDump(void) { + if (DumpFile) + fclose(DumpFile); +} + +void IRO_Dump(char *format, ...) { + va_list va; + if (IRO_Log) { + va_start(va, format); + vfprintf(DumpFile, format, va); + va_end(va); + } +} + +void IRO_DumpAddr(IROAddrRecord *rec) { + IROElmList *list; + + if (IRO_Log && DumpFile) { + fprintf(DumpFile, "\n"); + fprintf(DumpFile, "Address :\n"); + IRO_DumpIntTree(rec->linear); + fprintf(DumpFile, "\n"); + fprintf(DumpFile, "BaseTerms:\n"); + for (list = rec->objRefs; list; list = list->next) { + IRO_DumpIntTree(list->element); + fprintf(DumpFile, "\n"); + } + fprintf(DumpFile, "VarTerms:\n"); + for (list = rec->misc; list; list = list->next) { + IRO_DumpIntTree(list->element); + fprintf(DumpFile, "\n"); + } + fprintf(DumpFile, "ConstTerms:\n"); + for (list = rec->ints; list; list = list->next) { + IRO_DumpIntTree(list->element); + fprintf(DumpFile, "\n"); + } + } +} + +static void IRO_DumpType(Type *type) { + char buf[256]; + IRO_SpellType(type, buf); + fprintf(DumpFile, " (%s)", buf); +} + +void IRO_SpellType(Type *type, char *buf) { + char mybuf[256]; + char mybuf2[256]; + + switch (type->type) { + case TYPEVOID: + strcpy(buf, "void"); + break; + case TYPEINT: + switch (TYPE_INTEGRAL(type)->integral) { + case IT_BOOL: + strcpy(buf, "bool"); + break; + case IT_CHAR: + strcpy(buf, "char"); + break; + case IT_WCHAR_T: + strcpy(buf, "wchar_t"); + break; + case IT_SCHAR: + strcpy(buf, "signed char"); + break; + case IT_UCHAR: + strcpy(buf, "unsigned char"); + break; + case IT_SHORT: + strcpy(buf, "short"); + break; + case IT_USHORT: + strcpy(buf, "unsigned short"); + break; + case IT_INT: + strcpy(buf, "int"); + break; + case IT_UINT: + strcpy(buf, "unsigned int"); + break; + case IT_LONG: + strcpy(buf, "long"); + break; + case IT_ULONG: + strcpy(buf, "unsigned long"); + break; + case IT_LONGLONG: + strcpy(buf, "long long"); + break; + case IT_ULONGLONG: + strcpy(buf, "unsigned long long"); + break; + } + break; + case TYPEFLOAT: + switch (TYPE_INTEGRAL(type)->integral) { + case IT_FLOAT: + strcpy(buf, "float"); + break; + case IT_SHORTDOUBLE: + strcpy(buf, "short double"); + break; + case IT_DOUBLE: + strcpy(buf, "double"); + break; + case IT_LONGDOUBLE: + strcpy(buf, "long double"); + break; + } + break; + case TYPEENUM: + strcpy(buf, "enum "); + if (TYPE_ENUM(type)->enumname) + strcat(buf, TYPE_ENUM(type)->enumname->name); + break; + case TYPESTRUCT: + if (IS_TYPESTRUCT_VECTOR(TYPE_STRUCT(type))) { + switch (TYPE_STRUCT(type)->stype) { + case STRUCT_VECTOR_UCHAR: + strcpy(buf, "vector unsigned char "); + break; + case STRUCT_VECTOR_SCHAR: + strcpy(buf, "vector signed char "); + break; + case STRUCT_VECTOR_BCHAR: + strcpy(buf, "vector bool char "); + break; + case STRUCT_VECTOR_USHORT: + strcpy(buf, "vector unsigned short "); + break; + case STRUCT_VECTOR_SSHORT: + strcpy(buf, "vector signed short "); + break; + case STRUCT_VECTOR_BSHORT: + strcpy(buf, "vector bool short "); + break; + case STRUCT_VECTOR_UINT: + strcpy(buf, "vector unsigned long "); + break; + case STRUCT_VECTOR_SINT: + strcpy(buf, "vector signed long "); + break; + case STRUCT_VECTOR_BINT: + strcpy(buf, "vector bool long "); + break; + case STRUCT_VECTOR_FLOAT: + strcpy(buf, "vector float "); + break; + case STRUCT_VECTOR_PIXEL: + strcpy(buf, "vector pixel "); + break; + } + } else { + strcpy(buf, "struct "); + } + if (TYPE_STRUCT(type)->name) + strcat(buf, TYPE_STRUCT(type)->name->name); + break; + case TYPECLASS: + strcpy(buf, "class "); + if (TYPE_CLASS(type)->classname) + strcat(buf, TYPE_CLASS(type)->classname->name); + break; + case TYPEFUNC: + IRO_SpellType(TYPE_FUNC(type)->functype, mybuf); + strcpy(buf, "freturns("); + strcat(buf, mybuf); + strcat(buf, ")"); + break; + case TYPEBITFIELD: + IRO_SpellType(TYPE_BITFIELD(type)->bitfieldtype, mybuf); + sprintf(buf, "bitfield(%s){%d:%d}", mybuf, TYPE_BITFIELD(type)->offset, TYPE_BITFIELD(type)->bitlength); + break; + case TYPELABEL: + strcpy(buf, "label"); + break; + case TYPEPOINTER: + IRO_SpellType(TPTR_TARGET(type), mybuf); + strcpy(buf, "pointer("); + strcat(buf, mybuf); + strcat(buf, ")"); + break; + case TYPEARRAY: + IRO_SpellType(TPTR_TARGET(type), mybuf); + strcpy(buf, "array("); + strcat(buf, mybuf); + strcat(buf, ")"); + break; + case TYPEMEMBERPOINTER: + IRO_SpellType(TYPE_MEMBER_POINTER(type)->ty2, mybuf); + IRO_SpellType(TYPE_MEMBER_POINTER(type)->ty1, mybuf2); + strcpy(buf, "memberpointer("); + strcat(buf, mybuf); + strcat(buf, ","); + strcat(buf, mybuf2); + strcat(buf, ")"); + break; + } +} + diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroDump.h b/compiler_and_linker/FrontEnd/Optimizer/IroDump.h new file mode 100644 index 0000000..ad8c039 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroDump.h @@ -0,0 +1,27 @@ +#ifndef COMPILER_IRODUMP_H +#define COMPILER_IRODUMP_H + +#include "IrOptimizer.h" +#include "BitVector.h" +#include "compiler/enode.h" + +extern char *IRO_NodeName(ENodeType nodetype); +extern void IRO_InitializeNodeNamesArray(void); +extern void IRO_DumpIntTree(IROLinear *linear); +extern void IRO_DumpLinearList(IROLinear *linear); +extern void IRO_DumpBits(char *name, BitVector *bv); +extern void IRO_DumpAfterPhase(char *str, Boolean flag); +extern void IRO_LogForFunction(char *name); +extern void IRO_DumpFlowgraph(void); +extern void IRO_DumpNode(IRONode *node); +extern void IRO_DumpAssignments(void); +extern void IRO_DumpVars(void); +extern void IRO_DumpDf(void); +extern void IRO_DumpExprs(void); +extern void IRO_SetupDump(void); +extern void IRO_CleanupDump(void); +extern void IRO_Dump(char *format, ...); +extern void IRO_DumpAddr(IROAddrRecord *rec); +extern void IRO_SpellType(Type *type, char *buf); + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroEmptyLoop.c b/compiler_and_linker/FrontEnd/Optimizer/IroEmptyLoop.c new file mode 100644 index 0000000..23d5d4a --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroEmptyLoop.c @@ -0,0 +1,560 @@ +#include "IroEmptyLoop.h" +#include "IroDump.h" +#include "IroFlowgraph.h" +#include "IroLinearForm.h" +#include "IroLoop.h" +#include "IroUtil.h" +#include "IroVars.h" +#include "compiler/CInt64.h" + +// forward decls +static Boolean EmptyLoop(IRONode *fnode); +static int CanRemoveRedundantLoop(IROLoop *loop); +static int CanRemoveRedundantLoop1(IROLoop *loop); +static int RedundantLoopCheck(IROLoop *loop); +static int CheckStepOverFlow1_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2); +static int CheckStepOverFlow2_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2); + +void IRO_FindEmptyLoops(void) { + IRONode *fnode; + IRONode *pred; + UInt16 i; + UInt16 x; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + x = 0; + for (i = 0; i < fnode->numpred; i++) { + pred = IRO_NodeTable[fnode->pred[i]]; + if (Bv_IsBitSet(fnode->index, pred->dom)) { + if (!x) { + Bv_AllocVector(&InLoop, IRO_NumNodes + 1); + Bv_Clear(InLoop); + Bv_SetBit(fnode->index, InLoop); + } + x = 1; + Bv_SetBit(pred->index, InLoop); + if (pred != fnode) + AddPreds(pred); + } + } + + if (x) { + IRO_Dump("IRO_FindEmptyLoops:Found loop with header %d\n", fnode->index); + IRO_DumpBits("Loop includes: ", InLoop); + EmptyLoop(fnode); + IRO_UpdateFlagsOnInts(); + } + } + + IRO_CheckForUserBreak(); +} + +static Boolean EmptyLoop(IRONode *fnode) { + VarRecord *var; + IRONode *bestpred; + IRONode *pred; + UInt16 i; + int flag2; + IRONode *r24; + Boolean flag; + int counter; + int j; + IRONode *succ; + IRONode *bestsucc; + int counter2; + UInt32 counter3; + IROLoop *loop; + IRONode *r21; + IRONode *r20; + IROLinear *constnd; + Type *type20; + ENode *enode; + IROLinear *save; + + flag = 0; + counter = 0; + LoopNode = fnode; + FindMustReach(); + + for (var = IRO_FirstVar; var; var = var->next) + var->xA = 1; + + ComputeLoopKills(); + ComputeLoopInvariance(); + ComputeLoopInduction(); + + LoopNode = fnode; + ConditionalHeaderAtBottom = 0; + + bestpred = NULL; + flag2 = 0; + for (i = 0; i < LoopNode->numpred; i++) { + pred = IRO_NodeTable[LoopNode->pred[i]]; + if (!Bv_IsBitSet(pred->index, InLoop)) { + flag2 = 1; + if (pred->nextnode == fnode) { + CError_ASSERT(173, !bestpred || pred == bestpred); + bestpred = pred; + } + } + } + + if (!flag2) { + IRO_Dump("No predecessor outside the loop\n"); + return 0; + } + + bestsucc = NULL; + for (i = 0; i < LoopNode->numsucc; i++) { + succ = IRO_NodeTable[LoopNode->succ[i]]; + if (Bv_IsBitSet(succ->index, InLoop)) { + bestsucc = succ; + counter++; + } + } + + if (LoopNode == bestsucc && counter == 1) + flag = 1; + + if (LoopNode->last->type != IROLinearIf || LoopNode->last->type != IROLinearIfNot || flag) { + counter2 = 0; + for (j = 0; j < LoopNode->numpred; j++) { + if (Bv_IsBitSet(IRO_NodeTable[LoopNode->pred[j]]->index, InLoop)) { + r21 = IRO_NodeTable[LoopNode->pred[j]]; + counter2++; + } + } + + r24 = NULL; + counter3 = 0; + for (j = 0; j < LoopNode->numpred; j++) { + if (!Bv_IsBitSet(IRO_NodeTable[LoopNode->pred[j]]->index, InLoop)) { + r24 = IRO_NodeTable[LoopNode->pred[j]]; + counter3++; + } + } + + if (counter2 == 1 && counter3 == 1) { + if (r21->last->type == IROLinearIf) { + if ((Bv_IsBitSet(LoopNode->nextnode->index, InLoop) && !Bv_IsBitSet(r21->nextnode->index, InLoop)) || flag) { + IRO_Dump("Standard while loop layout\n"); + loop = ExtractLoopInfo(r21); + if (flag) + loop->flags |= LoopFlags_20000; + FindAssignmenttoInductionVar(loop, r24); + r20 = r24; + while (r20 && !loop->nd14 && r20->numpred == 1 && IRO_NodeTable[r20->pred[0]]->numsucc == 1) { + FindAssignmenttoInductionVar(loop, IRO_NodeTable[r20->pred[0]]); + r20 = IRO_NodeTable[r20->pred[0]]; + } + + if (CanRemoveRedundantLoop(loop)) { + IRO_Dump("EmptyLoop: # of iterations =%" PRId32 ", FinalStoreVal=%" PRId32 "\n", CInt64_GetULong(&loop->x28), CInt64_GetULong(&loop->x30)); + IRO_NopOut(r21->last->u.label.x4); + r21->last->type = IROLinearNop; + type20 = loop->induction->nd->rtype; + constnd = IRO_NewLinear(IROLinearOperand); + constnd->index = ++IRO_NumLinear; + enode = IRO_NewENode(EINTCONST); + enode->rtype = type20; + enode->data.intval = loop->x30; + constnd->u.node = enode; + constnd->rtype = type20; + + if (loop->induction->nd->type == IROLinearOp1Arg) { + save = loop->induction->nd->u.monadic; + loop->induction->nd->type = IROLinearOp2Arg; + loop->induction->nd->nodetype = EASS; + loop->induction->nd->u.diadic.left = save; + loop->induction->nd->u.diadic.right = constnd; + IRO_Paste(constnd, constnd, loop->induction->nd); + } else if (loop->induction->nd->type == IROLinearOp2Arg) { + loop->induction->nd->nodetype = EASS; + IRO_NopOut(loop->induction->nd->u.diadic.right); + loop->induction->nd->u.diadic.right = constnd; + IRO_Paste(constnd, constnd, loop->induction->nd); + } + } else if (CanRemoveRedundantLoop1(loop)) { + IRO_Dump("EmptyLoop: self recursive dowhile(--n ) loop\n"); + + r21->last->type = IROLinearNop; + type20 = loop->induction->nd->rtype; + constnd = IRO_NewLinear(IROLinearOperand); + constnd->index = ++IRO_NumLinear; + enode = IRO_NewENode(EINTCONST); + enode->rtype = type20; + enode->data.intval = cint64_zero; + constnd->u.node = enode; + constnd->rtype = type20; + + save = loop->induction->nd->u.monadic; + loop->induction->nd->type = IROLinearOp2Arg; + loop->induction->nd->nodetype = EASS; + loop->induction->nd->u.diadic.left = save; + loop->induction->nd->u.diadic.right = constnd; + IRO_Paste(constnd, constnd, loop->induction->nd); + } + } else { + IRO_Dump("NonStandard while loop layout\n"); + } + } else { + IRO_Dump("NonStandard while loop layout\n"); + } + } else { + IRO_Dump("Cannot handle Do While Loop with multiple tails\n"); + } + } + + return 0; +} + +static int CanRemoveRedundantLoop(IROLoop *loop) { + IROLinear *inner; + + if (loop->flags & LoopFlags_10000) { + IRO_Dump("CanRemoveRedundantLoop:No because detection of dowhile(n--) loop not supported\n"); + return 0; + } + + if (loop->flags & LP_LOOP_HAS_ASM) { + IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_ASM \n"); + return 0; + } + + if (loop->flags & LP_IFEXPR_NON_CANONICAL) { + IRO_Dump("CanRemoveRedundantLoop:No due to LP_IFEXPR_NON_CANONICAL \n"); + return 0; + } + + if (loop->flags & LP_LOOP_HAS_CALLS) { + IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_CALLS \n"); + return 0; + } + + if (loop->flags & LP_LOOP_HAS_CNTRLFLOW) { + IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_CNTRLFLOW \n"); + return 0; + } + + if (loop->flags & LP_INDUCTION_NOT_FOUND) { + IRO_Dump("CanRemoveRedundantLoop:No due to LP_INDUCTION_NOT_FOUND \n"); + return 0; + } + + if (loop->flags & LP_HAS_MULTIPLE_INDUCTIONS) { + IRO_Dump("CanRemoveRedundantLoop:No due to LP_HAS_MULTIPLE_INDUCTIONS \n"); + return 0; + } + + if (loop->flags & LP_LOOP_HDR_HAS_SIDEEFFECTS) { + IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HDR_HAS_SIDEEFFECTS \n"); + return 0; + } + + if (!(loop->flags & LoopFlags_200)) { + IRO_Dump("CanRemoveRedundantLoop:No because header does not follow induction update \n"); + return 0; + } + + if (!(loop->flags & LoopFlags_10000)) { + inner = loop->nd18->u.diadic.right; + if (!IRO_IsIntConstant(inner) && !(inner->flags & IROLF_LoopInvariant)) { + IRO_Dump("CanRemoveRedundantLoop:No because Loop Upper Bound is Variant in the loop\n"); + return 0; + } + + if (!loop->nd14) { + IRO_Dump("CanRemoveRedundantLoop:No because there is no initialization of loop index in PreHeader\n"); + return 0; + } + + if (!IRO_IsVariable(loop->nd14->u.diadic.left)) { + IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction stored thru pointer\n"); + return 0; + } + + if (!IRO_IsUnsignedType(loop->nd14->rtype)) { + if (IRO_IsIntConstant(loop->nd14->u.diadic.right)) { + if (!CInt64_GreaterEqual(loop->nd14->u.diadic.right->u.node->data.intval, cint64_zero)) { + IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction is signed but < 0\n"); + return 0; + } + } else { + IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction is signed and not constant\n"); + return 0; + } + } + + if (!(loop->flags & LP_LOOP_STEP_ISPOS) && !(loop->flags & LP_LOOP_STEP_ISNEG)) { + IRO_Dump("CanRemoveRedundantLoop:No because LP_LOOP_STEP_ISPOS/LP_LOOP_STEP_ISNEG is not set\n"); + return 0; + } + + if ((loop->flags & LP_LOOP_STEP_ISPOS) && CheckStepOverFlow1_EmptyLoop(loop, &loop->x28, &loop->x30)) { + IRO_Dump("CanRemoveRedundantLoop:No because Final Value of indution will overflow\n"); + return 0; + } + + if ((loop->flags & LP_LOOP_STEP_ISNEG) && CheckStepOverFlow2_EmptyLoop(loop, &loop->x28, &loop->x30)) { + IRO_Dump("CanRemoveRedundantLoop:No because Final Value of indution will overflow\n"); + return 0; + } + } + + return RedundantLoopCheck(loop) != 0; +} + +static int CanRemoveRedundantLoop1(IROLoop *loop) { + if ((loop->flags & LoopFlags_10000) && (loop->flags & LoopFlags_20000)) { + if (loop->flags & LP_LOOP_HAS_ASM) { + IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_ASM \n"); + return 0; + } + + if (loop->flags & LP_IFEXPR_NON_CANONICAL) { + IRO_Dump("CanRemoveRedundantLoop1:No due to LP_IFEXPR_NON_CANONICAL \n"); + return 0; + } + + if (loop->flags & LP_LOOP_HAS_CALLS) { + IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_CALLS \n"); + return 0; + } + + if (loop->flags & LP_LOOP_HAS_CNTRLFLOW) { + IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_CNTRLFLOW \n"); + return 0; + } + + if (loop->flags & LP_INDUCTION_NOT_FOUND) { + IRO_Dump("CanRemoveRedundantLoop1:No due to LP_INDUCTION_NOT_FOUND \n"); + return 0; + } + + if (loop->flags & LP_HAS_MULTIPLE_INDUCTIONS) { + IRO_Dump("CanRemoveRedundantLoop1:No due to LP_HAS_MULTIPLE_INDUCTIONS \n"); + return 0; + } + + if (loop->flags & LP_LOOP_HDR_HAS_SIDEEFFECTS) { + IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HDR_HAS_SIDEEFFECTS \n"); + return 0; + } + + if (!(loop->flags & LoopFlags_200)) { + IRO_Dump("CanRemoveRedundantLoop1:No because header does not follow induction update \n"); + return 0; + } + + if (loop->induction->nd->type == IROLinearOp1Arg && loop->induction->nd->nodetype == EPREDEC) { + if (IRO_IsUnsignedType(loop->induction->nd->rtype)) + return 1; + IRO_Dump("CanRemoveRedundantLoop1:No because induction not of the right type \n"); + return 0; + } + + IRO_Dump("CanRemoveRedundantLoop1:No because induction operator not a predec \n"); + return 0; + } else { + return 0; + } +} + +static int RedundantLoopCheck(IROLoop *loop) { + IRONode *fnode; + IROLinear *nd; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (Bv_IsBitSet(fnode->index, InLoop) && fnode != loop->fnode && (nd = fnode->first)) { + while (1) { + if ((nd->index < loop->index20 || nd->index > loop->index24) && nd->type != IROLinearNop && nd->type != IROLinearLabel) { + if (IS_LINEAR_DIADIC(nd, EASS)) { + if (!(nd->flags & IROLF_Reffed)) { + if (IS_LINEAR_MONADIC(nd->u.diadic.left, EINDIRECT)) { + if (nd->u.diadic.left->rtype && CParser_IsVolatile(nd->u.diadic.left->rtype, nd->u.diadic.left->nodeflags & ENODE_FLAG_QUALS)) { + IRO_Dump(" EASS at %d fail as store to volatile memory \n", nd->index); + return 0; + } + + if ((nd->u.diadic.left->u.monadic->flags & IROLF_LoopInvariant) && (nd->u.diadic.right->flags & IROLF_LoopInvariant)) { + IRO_Dump(" EASS at %d pass\n", nd->index); + } else { + IRO_Dump(" EASS at %d fail, either LHS address or RHS is variant \n", nd->index); + return 0; + } + } else { + IRO_Dump("Found EASS nodes whose lhs root is not a EINDIRECT node\n"); + return 0; + } + } else { + IRO_Dump("Found EASS node that is referenced i.e embedded assignment\n"); + return 0; + } + } else { + if (!(nd->flags & IROLF_Reffed)) { + IRO_Dump("Found non EASS top level node in the loop\n"); + return 0; + } + } + } + + if (nd == fnode->last) + break; + nd = nd->next; + } + } + } + + return 1; +} + +static int CheckStepOverFlow1_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2) { + Boolean isUnsigned; + IROLinear *nd2; + IROLinear *nd1; + CInt64 nd2value; + CInt64 nd1value; + CInt64 addConst; + CInt64 work; + CInt64 neg1; + + nd2 = loop->nd14->u.diadic.right; + nd1 = loop->nd18->u.diadic.right; + isUnsigned = IRO_IsUnsignedType(loop->nd18->u.diadic.right->rtype); + + if (IRO_IsIntConstant(nd2) && IRO_IsIntConstant(nd1)) { + nd2value = nd2->u.node->data.intval; + nd1value = nd1->u.node->data.intval; + if (isUnsigned) { + if (CInt64_LessEqualU(nd1value, nd2value)) + return 1; + } else { + if (CInt64_LessEqual(nd1value, nd2value)) + return 1; + } + + CInt64_SetLong(&addConst, loop->induction->addConst); + CInt64_SetLong(&neg1, -1); + *val1 = CInt64_Sub(nd1value, nd2value); + *val1 = CInt64_Add(*val1, addConst); + if (IS_LINEAR_DIADIC(loop->nd18, ELESS)) + *val1 = CInt64_Add(*val1, neg1); + + CError_ASSERT(855, !CInt64_IsZero(&addConst)); + + if (isUnsigned) + *val1 = CInt64_DivU(*val1, addConst); + else + *val1 = CInt64_Div(*val1, addConst); + + if (CInt64_Equal(*val1, cint64_zero)) + return 1; + + if (isUnsigned) { + if (CInt64_LessEqualU(*val1, cint64_zero)) + CError_FATAL(877); + } else { + if (CInt64_LessEqual(*val1, cint64_zero)) + CError_FATAL(886); + } + + if (isUnsigned) { + *val2 = CInt64_MulU(*val1, addConst); + *val2 = CInt64_Add(*val2, nd2value); + } else { + *val2 = CInt64_Mul(*val1, addConst); + *val2 = CInt64_Add(*val2, nd2value); + } + } else { + return 1; + } + + CInt64_SetLong(&addConst, loop->induction->addConst); + work = CInt64_Add(nd1value, addConst); + + if (isUnsigned) { + if (CInt64_LessU(work, nd1value)) + return 1; + } else { + if (CInt64_Less(work, nd1value)) + return 1; + } + + return 0; +} + +static int CheckStepOverFlow2_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2) { + Boolean isUnsigned; + IROLinear *nd2; + IROLinear *nd1; + CInt64 nd2value; + CInt64 nd1value; + CInt64 addConst; + CInt64 work; + CInt64 neg1; + + nd1 = loop->nd14->u.diadic.right; + nd2 = loop->nd18->u.diadic.right; + isUnsigned = IRO_IsUnsignedType(loop->nd18->u.diadic.right->rtype); + + if (IRO_IsIntConstant(nd2) && IRO_IsIntConstant(nd1)) { + nd2value = nd2->u.node->data.intval; + nd1value = nd1->u.node->data.intval; + if (isUnsigned) { + if (CInt64_LessEqualU(nd1value, nd2value)) + return 1; + } else { + if (CInt64_LessEqual(nd1value, nd2value)) + return 1; + } + + CInt64_SetLong(&addConst, loop->induction->addConst); + CInt64_SetLong(&neg1, -1); + *val1 = CInt64_Sub(nd1value, nd2value); + *val1 = CInt64_Add(*val1, addConst); + if (IS_LINEAR_DIADIC(loop->nd18, EGREATER)) + *val1 = CInt64_Add(*val1, neg1); + + CError_ASSERT(995, !CInt64_IsZero(&addConst)); + + if (isUnsigned) + *val1 = CInt64_DivU(*val1, addConst); + else + *val1 = CInt64_Div(*val1, addConst); + + if (CInt64_Equal(*val1, cint64_zero)) + return 1; + + if (isUnsigned) { + if (CInt64_LessEqualU(*val1, cint64_zero)) + return 0; + } else { + if (CInt64_LessEqual(*val1, cint64_zero)) + return 0; + } + + if (isUnsigned) { + *val2 = CInt64_MulU(*val1, addConst); + *val2 = CInt64_Sub(nd1value, *val2); + } else { + *val2 = CInt64_Mul(*val1, addConst); + *val2 = CInt64_Sub(nd1value, *val2); + } + } else { + return 1; + } + + CInt64_SetLong(&addConst, loop->induction->addConst); + work = CInt64_Sub(nd2value, addConst); + + if (isUnsigned) { + if (CInt64_GreaterU(work, nd2value)) + return 1; + } else { + if (CInt64_Greater(work, nd1value)) + return 1; + } + + return 0; +} + diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroEmptyLoop.h b/compiler_and_linker/FrontEnd/Optimizer/IroEmptyLoop.h new file mode 100644 index 0000000..c5597e6 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroEmptyLoop.h @@ -0,0 +1,8 @@ +#ifndef COMPILER_IROEMPTYLOOP_H +#define COMPILER_IROEMPTYLOOP_H + +#include "IrOptimizer.h" + +extern void IRO_FindEmptyLoops(void); + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroEval.c b/compiler_and_linker/FrontEnd/Optimizer/IroEval.c new file mode 100644 index 0000000..aba64e1 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroEval.c @@ -0,0 +1,914 @@ +#include "IroEval.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "IroFlowgraph.h" +#include "IroLinearForm.h" +#include "IroMalloc.h" +#include "IroPointerAnalysis.h" +#include "IroUtil.h" +#include "IroVars.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +static Boolean IsAssociativeENodeType[MAXEXPR]; + +void IRO_InitializeIsAssociativeENodeTypeArray(void) { + int i; + + for (i = 0; i < MAXEXPR; i++) + IsAssociativeENodeType[i] = 0; + + IsAssociativeENodeType[EPOSTINC] = 0; + IsAssociativeENodeType[EPOSTDEC] = 0; + IsAssociativeENodeType[EPREINC] = 0; + IsAssociativeENodeType[EPREDEC] = 0; + IsAssociativeENodeType[EINDIRECT] = 0; + IsAssociativeENodeType[EMONMIN] = 0; + IsAssociativeENodeType[EBINNOT] = 0; + IsAssociativeENodeType[ELOGNOT] = 0; + IsAssociativeENodeType[EFORCELOAD] = 0; + IsAssociativeENodeType[EMUL] = 1; + IsAssociativeENodeType[EMULV] = 1; + IsAssociativeENodeType[EDIV] = 0; + IsAssociativeENodeType[EMODULO] = 0; + IsAssociativeENodeType[EADDV] = 1; + IsAssociativeENodeType[ESUBV] = 0; + IsAssociativeENodeType[EADD] = 1; + IsAssociativeENodeType[ESUB] = 0; + IsAssociativeENodeType[ESHL] = 0; + IsAssociativeENodeType[ESHR] = 0; + IsAssociativeENodeType[ELESS] = 0; + IsAssociativeENodeType[EGREATER] = 0; + IsAssociativeENodeType[ELESSEQU] = 0; + IsAssociativeENodeType[EGREATEREQU] = 0; + IsAssociativeENodeType[EEQU] = 0; + IsAssociativeENodeType[ENOTEQU] = 0; + IsAssociativeENodeType[EAND] = 1; + IsAssociativeENodeType[EXOR] = 1; + IsAssociativeENodeType[EOR] = 1; + IsAssociativeENodeType[ELAND] = 0; + IsAssociativeENodeType[ELOR] = 0; + IsAssociativeENodeType[EASS] = 0; + IsAssociativeENodeType[EMULASS] = 0; + IsAssociativeENodeType[EDIVASS] = 0; + IsAssociativeENodeType[EMODASS] = 0; + IsAssociativeENodeType[EADDASS] = 0; + IsAssociativeENodeType[ESUBASS] = 0; + IsAssociativeENodeType[ESHLASS] = 0; + IsAssociativeENodeType[ESHRASS] = 0; + IsAssociativeENodeType[EANDASS] = 0; + IsAssociativeENodeType[EXORASS] = 0; + IsAssociativeENodeType[EORASS] = 0; + IsAssociativeENodeType[ECOMMA] = 0; + IsAssociativeENodeType[EPMODULO] = 0; + IsAssociativeENodeType[EROTL] = 0; + IsAssociativeENodeType[EROTR] = 0; + IsAssociativeENodeType[EBCLR] = 0; + IsAssociativeENodeType[EBTST] = 0; + IsAssociativeENodeType[EBSET] = 0; + IsAssociativeENodeType[ETYPCON] = 0; + IsAssociativeENodeType[EBITFIELD] = 0; + IsAssociativeENodeType[EINTCONST] = 0; + IsAssociativeENodeType[EFLOATCONST] = 0; + IsAssociativeENodeType[ESTRINGCONST] = 0; + IsAssociativeENodeType[ECOND] = 0; + IsAssociativeENodeType[EFUNCCALL] = 0; + IsAssociativeENodeType[EFUNCCALLP] = 0; + IsAssociativeENodeType[EOBJREF] = 0; + IsAssociativeENodeType[EMFPOINTER] = 0; + IsAssociativeENodeType[ENULLCHECK] = 0; + IsAssociativeENodeType[EPRECOMP] = 0; + IsAssociativeENodeType[ETEMP] = 0; + IsAssociativeENodeType[EARGOBJ] = 0; + IsAssociativeENodeType[ELOCOBJ] = 0; + IsAssociativeENodeType[ELABEL] = 0; + IsAssociativeENodeType[ESETCONST] = 0; + IsAssociativeENodeType[ENEWEXCEPTION] = 0; + IsAssociativeENodeType[ENEWEXCEPTIONARRAY] = 0; + IsAssociativeENodeType[EOBJLIST] = 0; + IsAssociativeENodeType[EMEMBER] = 0; + IsAssociativeENodeType[ETEMPLDEP] = 0; + IsAssociativeENodeType[EINSTRUCTION] = 0; + IsAssociativeENodeType[EDEFINE] = 0; + IsAssociativeENodeType[EREUSE] = 0; + IsAssociativeENodeType[EASSBLK] = 0; + IsAssociativeENodeType[EVECTOR128CONST] = 0; + IsAssociativeENodeType[ECONDASS] = 0; +} + +void IRO_TruncateValueToType(CInt64 *val, Type *type) { + if (IRO_IsUnsignedType(type)) { + switch (type->size) { + case 1: + CInt64_ConvertUInt8(val); + break; + case 2: + CInt64_ConvertUInt16(val); + break; + case 4: + CInt64_ConvertUInt32(val); + break; + } + } else { + switch (type->size) { + case 1: + CInt64_ConvertInt8(val); + break; + case 2: + CInt64_ConvertInt16(val); + break; + case 4: + CInt64_ConvertInt32(val); + break; + } + } +} + +void IRO_TruncateBitfieldValueToType(CInt64 *val, Type *type, Type *type2) { + UInt32 limit; + UInt32 i; + UInt32 j; + CInt64 work; + + work = cint64_zero; + limit = TYPE_BITFIELD(type2)->bitlength; + for (i = 0; i < limit; i++) + work = CInt64_Or(work, CInt64_Shl(cint64_one, IRO_MakeULong(i))); + *val = CInt64_And(*val, work); + + if (!IRO_IsUnsignedType(type)) { + work = cint64_zero; + for (j = 0; j <= (i - 1); j++) { + if (j == (i - 1)) + work = CInt64_Or(work, CInt64_Shl(cint64_one, IRO_MakeULong(j))); + } + if (CInt64_NotEqual(CInt64_And(work, *val), cint64_zero)) { + for (j = i - 1; j < 64; j++) + *val = CInt64_Or(*val, CInt64_Shl(cint64_one, IRO_MakeULong(j))); + } + } + + IRO_TruncateValueToType(val, type); +} + +void IRO_ConstantFolding(void) { + IROLinear *nd; + ENode *expr; + int isCompare; + int flag; + CInt64 val; + + for (nd = IRO_FirstLinear; nd; nd = nd->next) { + switch (nd->type) { + case IROLinearOp1Arg: + if (IRO_IsIntConstant(nd->u.monadic)) { + expr = NULL; + flag = 0; + val = nd->u.monadic->u.node->data.intval; + if (nd->nodetype == ETYPCON && IS_TYPE_FLOAT(nd->rtype)) { + expr = IRO_NewENode(EFLOATCONST); + if (!IRO_IsUnsignedType(nd->u.monadic->rtype)) + expr->data.floatval.value = CInt64_ConvertToLongDouble(&val); + else + expr->data.floatval.value = CInt64_ConvertUToLongDouble(&val); + expr->rtype = nd->rtype; + } else { + switch (nd->nodetype) { + case ETYPCON: + flag = 1; + break; + case ELOGNOT: + val = CInt64_Not(val); + flag = 1; + break; + case EBINNOT: + val = CInt64_Inv(val); + flag = 1; + break; + case EMONMIN: + val = CInt64_Neg(val); + flag = 1; + break; + } + + if (flag) { + IRO_TruncateValueToType(&val, nd->rtype); + expr = IRO_NewENode(EINTCONST); + expr->rtype = nd->rtype; + expr->data.intval = val; + } + } + + if (expr) { + nd->u.monadic->type = IROLinearNop; + nd->type = IROLinearOperand; + nd->u.node = expr; + } + } + break; + + case IROLinearOp2Arg: + if (IRO_IsIntConstant(nd->u.diadic.left) && !IRO_IsIntConstant(nd->u.diadic.right) && IsAssociativeENodeType[nd->nodetype]) { + IROLinear *tmp = nd->u.diadic.right; + nd->u.diadic.right = nd->u.diadic.left; + nd->u.diadic.left = tmp; + } + + if (IRO_IsIntConstant(nd->u.diadic.right) && nd->nodetype == ESUB) { + nd->nodetype = EADD; + if (IRO_IsIntConstant(nd->u.diadic.right)) { + CInt64 v; + v = CInt64_Neg(nd->u.diadic.right->u.node->data.intval); + nd->u.diadic.right->u.node->data.intval = v; + } else { + Float f; + f = CMach_CalcFloatMonadic( + nd->u.diadic.right->rtype, + '-', + nd->u.diadic.right->u.node->data.floatval); + nd->u.diadic.right->u.node->data.floatval = f; + } + } + + if ( + IRO_IsIntConstant(nd->u.diadic.right) && + IsAssociativeENodeType[nd->nodetype] && + nd->u.diadic.left->type == IROLinearOp2Arg && + nd->u.diadic.left->nodetype == nd->nodetype && + nd->u.diadic.left->rtype == nd->rtype && + IRO_IsIntConstant(nd->u.diadic.left->u.diadic.right) && + nd->u.diadic.left->u.diadic.right->rtype == nd->u.diadic.right->rtype + ) + { + IROLinear *tmp = nd->u.diadic.left; + nd->u.diadic.left = tmp->u.diadic.left; + tmp->u.diadic.left = tmp->u.diadic.right; + tmp->u.diadic.right = nd->u.diadic.right; + tmp->rtype = tmp->u.diadic.left->rtype; + nd->u.diadic.right = tmp; + nd = tmp; + } + + if (IRO_IsIntConstant(nd->u.diadic.left) && IRO_IsIntConstant(nd->u.diadic.right)) { + CInt64 val1 = nd->u.diadic.left->u.node->data.intval; + CInt64 val2 = nd->u.diadic.right->u.node->data.intval; + flag = 0; + switch (nd->nodetype) { + case EADD: + val = CInt64_Add(val1, val2); + flag = 1; + break; + case ESUB: + val = CInt64_Sub(val1, val2); + flag = 1; + break; + case EMUL: + if (IRO_IsUnsignedType(nd->rtype)) + val = CInt64_MulU(val1, val2); + else + val = CInt64_Mul(val1, val2); + flag = 1; + break; + case EDIV: + if (!CInt64_IsZero(&val2)) { + if (IRO_IsUnsignedType(nd->rtype)) + val = CInt64_DivU(val1, val2); + else + val = CInt64_Div(val1, val2); + flag = 1; + } + break; + case EMODULO: + if (!CInt64_IsZero(&val2)) { + if (IRO_IsUnsignedType(nd->rtype)) + val = CInt64_ModU(val1, val2); + else + val = CInt64_Mod(val1, val2); + flag = 1; + } + break; + case ESHL: + val = CInt64_Shl(val1, val2); + flag = 1; + break; + case ESHR: + if (IRO_IsUnsignedType(nd->rtype)) + val = CInt64_ShrU(val1, val2); + else + val = CInt64_Shr(val1, val2); + flag = 1; + break; + case EAND: + val = CInt64_And(val1, val2); + flag = 1; + break; + case EOR: + val = CInt64_Or(val1, val2); + flag = 1; + break; + case EXOR: + val = CInt64_Xor(val1, val2); + flag = 1; + break; + case ELESS: + if (IRO_IsUnsignedType(nd->u.diadic.left->rtype)) + CInt64_SetULong(&val, CInt64_LessU(val1, val2)); + else + CInt64_SetULong(&val, CInt64_Less(val1, val2)); + flag = 1; + break; + case EGREATER: + if (IRO_IsUnsignedType(nd->u.diadic.left->rtype)) + CInt64_SetULong(&val, CInt64_GreaterU(val1, val2)); + else + CInt64_SetULong(&val, CInt64_Greater(val1, val2)); + flag = 1; + break; + case ELESSEQU: + if (IRO_IsUnsignedType(nd->u.diadic.left->rtype)) + CInt64_SetULong(&val, CInt64_LessEqualU(val1, val2)); + else + CInt64_SetULong(&val, CInt64_LessEqual(val1, val2)); + flag = 1; + break; + case EGREATEREQU: + if (IRO_IsUnsignedType(nd->u.diadic.left->rtype)) + CInt64_SetULong(&val, CInt64_GreaterEqualU(val1, val2)); + else + CInt64_SetULong(&val, CInt64_GreaterEqual(val1, val2)); + flag = 1; + break; + case EEQU: + CInt64_SetULong(&val, CInt64_Equal(val1, val2)); + flag = 1; + break; + case ENOTEQU: + CInt64_SetULong(&val, CInt64_NotEqual(val1, val2)); + flag = 1; + break; + } + + if (flag) { + IRO_TruncateValueToType(&val, nd->rtype); + expr = IRO_NewENode(EINTCONST); + expr->rtype = nd->rtype; + expr->data.intval = val; + nd->u.diadic.left->type = IROLinearNop; + nd->u.diadic.right->type = IROLinearNop; + nd->type = IROLinearOperand; + nd->u.node = expr; + } + } + + if (IRO_IsFloatConstant(nd->u.diadic.left) && IRO_IsFloatConstant(nd->u.diadic.right)) { + Float fval1 = nd->u.diadic.left->u.node->data.floatval; + Float fval2 = nd->u.diadic.right->u.node->data.floatval; + Float fval; + flag = 0; + isCompare = 0; + switch (nd->nodetype) { + case EADD: + fval = CMach_CalcFloatDiadic(nd->rtype, fval1, '+', fval2); + flag = 1; + break; + case ESUB: + fval = CMach_CalcFloatDiadic(nd->rtype, fval1, '-', fval2); + flag = 1; + break; + case EMUL: + fval = CMach_CalcFloatDiadic(nd->rtype, fval1, '*', fval2); + flag = 1; + break; + case EDIV: + fval = CMach_CalcFloatDiadic(nd->rtype, fval1, '/', fval2); + flag = 1; + break; + case ELESS: + CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, '<', fval2)); + flag = 1; + isCompare = 1; + break; + case EGREATER: + CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, '>', fval2)); + flag = 1; + isCompare = 1; + break; + case ELESSEQU: + CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, TK_LESS_EQUAL, fval2)); + flag = 1; + isCompare = 1; + break; + case EGREATEREQU: + CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, TK_GREATER_EQUAL, fval2)); + flag = 1; + isCompare = 1; + break; + case EEQU: + CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, TK_LOGICAL_EQ, fval2)); + flag = 1; + isCompare = 1; + break; + case ENOTEQU: + CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, TK_LOGICAL_NE, fval2)); + flag = 1; + isCompare = 1; + break; + } + + if (flag) { + if (isCompare) { + IRO_TruncateValueToType(&val, nd->rtype); + expr = IRO_NewENode(EINTCONST); + expr->rtype = nd->rtype; + expr->data.intval = val; + nd->u.diadic.left->type = IROLinearNop; + nd->u.diadic.right->type = IROLinearNop; + nd->type = IROLinearOperand; + nd->u.node = expr; + } else { + expr = IRO_NewENode(EFLOATCONST); + expr->rtype = nd->rtype; + expr->data.floatval = fval; + nd->u.diadic.left->type = IROLinearNop; + nd->u.diadic.right->type = IROLinearNop; + nd->type = IROLinearOperand; + nd->u.node = expr; + } + } + } + + break; + } + } + + IRO_CheckForUserBreak(); +} + +Boolean IRO_EvaluateConditionals(void) { + IRONode *fnode; + IROLinear *nd; + Boolean changed = 0; + SwitchInfo *switchInfo; + SwitchCase *swcase; + char found; + CInt64 val; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + nd = fnode->last; + switch (nd->type) { + case IROLinearIf: + case IROLinearIfNot: + if (IRO_IsIntConstant(nd->u.label.x4)) { + Boolean isZero = CInt64_IsZero(&nd->u.label.x4->u.node->data.intval); + IRO_NopOut(nd->u.label.x4); + if ((isZero == 0) == (nd->type == IROLinearIf)) + nd->type = IROLinearGoto; + else + nd->type = IROLinearNop; + changed = 1; + } + break; + + case IROLinearSwitch: + if (IRO_IsIntConstant(nd->u.swtch.x4)) { + val = nd->u.swtch.x4->u.node->data.intval; + switchInfo = nd->u.swtch.info; + swcase = switchInfo->cases; + + IRO_NopOut(nd->u.swtch.x4); + nd->type = IROLinearGoto; + + found = 0; + while (swcase) { + if (CInt64_GreaterEqual(val, swcase->min) && CInt64_LessEqual(val, swcase->max)) { + found = 1; + nd->u.label.label = swcase->label; + break; + } + swcase = swcase->next; + } + + if (!found) + nd->u.label.label = switchInfo->defaultlabel; + changed = 1; + } + break; + } + } + + if (changed) { + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + } + IRO_CheckForUserBreak(); + + return changed; +} + +static int EEquConst(IROLinear *nd) { + return nd && (nd->nodetype == EEQU) && IRO_IsIntConstant(nd->u.diadic.right); +} + +static Object *VEquConst(IROLinear *nd) { + if (EEquConst(nd)) + return IRO_IsVariable(nd->u.diadic.left); + else + return NULL; +} + +static int IsConsecutive(CInt64 a, CInt64 b) { + CInt64 diff; + + if (!CInt64_Equal(a, cint64_min) && !CInt64_Equal(b, cint64_min)) { + diff = CInt64_Sub(b, a); + return CInt64_Equal(diff, cint64_one) || CInt64_Equal(diff, cint64_negone); + } + + return 0; +} + +static IROLinear *findLabel(CLabel *label) { + IROLinear *nd; + + for (nd = IRO_FirstLinear; nd; nd = nd->next) { + if (nd->type == IROLinearLabel && nd->u.label.label == label) + break; + } + + return nd; +} + +static IROLinear *leftLeaveOf(IROLinear *nd) { + switch (nd->type) { + case IROLinearOp1Arg: + return leftLeaveOf(nd->u.monadic); + case IROLinearOp2Arg: + return leftLeaveOf(nd->u.diadic.left); + case IROLinearOperand: + return nd; + default: + return NULL; + } +} + +static int checkNode(IRONode *fnode) { + IROLinear *nd; + + if (fnode->numpred <= 1) { + nd = fnode->first; + while (nd != fnode->last && (nd->type == IROLinearNop || nd->type == IROLinearLabel)) + nd = nd->next; + + if (nd == leftLeaveOf(fnode->last->u.label.x4)) + return 1; + } + + return 0; +} + +static int checkLabel(CLabel *label, IRONode *fnode) { + switch (fnode->last->type) { + case IROLinearIf: + if (label == fnode->last->u.label.label) + return 1; + break; + } + + return 0; +} + +static Object *checkExpr(Object *a, IROLinear *nd) { + Object *b = VEquConst(nd); + + if ((!a || a == b) && !IRO_HasSideEffect(nd)) + return b; + + return NULL; +} + +static int checkStruct(IRONode *fnode1, IRONode *fnode2) { + CLabel *label; + Object *var; + + if (fnode1 == fnode2) + return (int) checkExpr(NULL, fnode1->last->u.label.x4); + + label = fnode1->last->u.label.label; + var = IRO_IsVariable(fnode1->last->u.label.x4->u.monadic); + return checkNode(fnode2) && checkLabel(label, fnode2) && checkExpr(var, fnode2->last->u.label.x4); +} + +typedef struct ReduceInfo { + int x0; + int x4; + Object *x8; + IRONode *fnode; + struct ReduceInfo *next; + CInt64 val; +} ReduceInfo; + +static int MarkPattern1(ReduceInfo *info1, ReduceInfo *info2, CInt64 *val) { + ReduceInfo *scan; + + if (!info2) + return 0; + + if (info2->x0) + return MarkPattern1(info1, info2->next, val); + + for (scan = info1; scan; scan = scan->next) { + if (scan->x0 == 2) { + if (CInt64_Equal(info2->val, scan->val)) { + IRO_NopOut(scan->fnode->last); + IRO_NopOut(scan->fnode->last->u.label.x4); // right union? + scan->x0 = -1; + return MarkPattern1(info1, info2->next, val); + } + + if (IsConsecutive(info2->val, scan->val)) { + info2->x0 = 2; + if (CInt64_Greater(*val, scan->val)) + *val = scan->val; + if (CInt64_Greater(*val, info2->val)) + *val = info2->val; + MarkPattern1(scan->next, info2, val); + MarkPattern1(info1, info1->next, val); + return 1; + } + } + } + + return MarkPattern1(info1, info2->next, val); +} + +static int DoReducible1(ReduceInfo *info, CInt64 val) { + ReduceInfo *last; + ReduceInfo *scan; + IROLinear *right; + IROLinear *left; + IROLinear *typconRight; + IROLinear *typconLeft; + IROLinear *cond; + int count; + + count = 0; + for (scan = info; scan; scan = scan->next) { + if (scan->x0 == 2) { + last = scan; + count++; + } + } + + if (!count) + return 0; + + for (scan = info; scan != last; scan = scan->next) { + if (scan->x0 == 2) { + scan->x0 = -1; + IRO_NopOut(scan->fnode->last); + IRO_NopOut(scan->fnode->last->u.label.x4); + } + } + + last->x0 = -1; + + cond = last->fnode->last; + cond->u.label.x4->nodetype = ELESSEQU; + CInt64_SetULong(&cond->u.label.x4->u.diadic.right->u.node->data.intval, count - 1); + + typconLeft = IRO_NewLinear(IROLinearOp1Arg); + typconLeft->nodetype = ETYPCON; + typconLeft->rtype = IRO_UnsignedType(cond->u.label.x4->u.diadic.left->rtype); + typconLeft->index = ++IRO_NumLinear; + + typconRight = IRO_NewLinear(IROLinearOp1Arg); + *typconRight = *typconLeft; + typconRight->index = ++IRO_NumLinear; + + left = IRO_NewLinear(IROLinearOp2Arg); + left->nodetype = EADD; + left->rtype = cond->u.label.x4->u.diadic.left->rtype; + left->index = ++IRO_NumLinear; + + right = IRO_NewLinear(IROLinearOperand); + right->nodetype = EINTCONST; + right->rtype = cond->u.label.x4->u.diadic.left->rtype; + right->index = ++IRO_NumLinear; + right->u.node = IRO_NewENode(EINTCONST); + right->u.node->data.intval = CInt64_Neg(val); + right->u.node->rtype = right->rtype; + + typconLeft->next = cond->u.label.x4->u.diadic.left->next; + cond->u.label.x4->u.diadic.left->next = right; + right->next = left; + left->next = typconLeft; + + typconRight->next = cond->u.label.x4->u.diadic.right->next; + cond->u.label.x4->u.diadic.right->next = typconRight; + + typconLeft->u.monadic = left; + left->u.diadic.left = cond->u.label.x4->u.diadic.left; + left->u.diadic.right = right; + cond->u.label.x4->u.diadic.left = typconLeft; + typconRight->u.monadic = cond->u.label.x4->u.diadic.right; + cond->u.label.x4->u.diadic.right = typconRight; + + return count; +}; + +static int ReducePattern1(IRONode *startnode, IRONode *endnode) { + ReduceInfo *infos; + ReduceInfo *info; + int changed = 0; + int count; + IRONode *fnode; + int i; + int j; + CInt64 val; + + if (startnode == endnode) + return 0; + + count = 0; + for (fnode = startnode; fnode != endnode; fnode = fnode->nextnode) + count++; + + infos = oalloc(sizeof(ReduceInfo) * ++count); + + fnode = startnode; + for (i = 0; i < count; i++) { + infos[i].x0 = 0; + infos[i].x4 = 0; + infos[i].fnode = fnode; + infos[i].next = NULL; + infos[i].x8 = VEquConst(fnode->last->u.label.x4); + if (infos[i].x8) { + infos[i].val = fnode->last->u.label.x4->u.diadic.right->u.node->data.intval; + infos[i].x4 = 1; + } + fnode = fnode->nextnode; + } + + for (j = 0; j < count; j++) { + if (infos[j].x4 == 1 && infos[j].x8) { + infos[j].x4 = -1; + info = &infos[j]; + for (i = j + 1; i < count; i++) { + if (infos[j].x8 == infos[i].x8) { + info->next = &infos[i]; + info = &infos[i]; + infos[i].x4 = 0; + } + } + } + } + + for (j = 0; j < count; j++) { + if (infos[j].x4 == -1) { + for (info = &infos[j]; info; info = info->next) { + if (info->x0 == 0) { + info->x0 = 2; + val = info->val; + if (MarkPattern1(&infos[j], info->next, &val)) { + changed = 1; + DoReducible1(&infos[j], val); + } else { + info->x0 = -1; + } + } + } + } + } + + return changed; +} + +static int ReduceConsecutiveIf(IRONode *startnode, IRONode *endnode) { + IRONode *node31; + IRONode *node30; + int changed = 0; + + while (startnode != endnode) { + if (checkStruct(startnode, startnode)) + break; + startnode = startnode->nextnode; + } + + node31 = startnode; + if (startnode != endnode) { + node30 = startnode; + node31 = startnode->nextnode; + while (node31 != endnode) { + if (checkStruct(startnode, node31)) { + node30 = node31; + node31 = node31->nextnode; + } else { + node31 = node30; + break; + } + } + + if (node31 == endnode && !checkStruct(startnode, node31)) + node31 = node30; + + if (startnode != node31 && ReducePattern1(startnode, node31)) + changed = 1; + + if (node31 != endnode) + node31 = node31->nextnode; + } + + if (node31 != endnode && ReduceConsecutiveIf(node31, endnode)) + changed = 1; + + return changed; +} + +int IRO_SimplifyConditionals(void) { + IRONode *fnode; + IRONode *start; + IRONode *end; + int changed = 0; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (fnode->last->type == IROLinearIf) { + start = end = fnode; + while (fnode->nextnode && fnode->nextnode->last->type == IROLinearIf) { + end = fnode = fnode->nextnode; + } + if (start != end && ReduceConsecutiveIf(start, end)) + changed = 1; + } + } + + if (changed) { + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + } + IRO_CheckForUserBreak(); + return changed; +} + +Boolean IRO_EvaluateDefinitePointers(Object *func) { + IROLinear *nd; + Boolean result; // r29 + Boolean changed; // r28 + Boolean changed2; // r26 + IROLinear *nd2; // r25 + IROListNode *scan; // r25 + IROListNode *list; + + if (!copts.opt_pointer_analysis) + return 0; + + result = 0; + + do { + changed = 0; + + for (nd = IRO_FirstLinear; nd; nd = nd->next) { + if ( + nd->type == IROLinearOp1Arg && + nd->nodetype == EINDIRECT && + !(nd->flags & IROLF_Assigned) && + nd->pointsToFunction && + !IRO_HasSideEffect(nd) && + PointerAnalysis_IsLinearNodePointerExprDefinite(func, nd) + ) + { + list = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(func, nd, &list); + if (list) { + if (list->list.head && list->list.tail && !list->nextList) { + changed2 = IRO_LocateFather_Cut_And_Paste(nd, list->list.tail) != NULL; + if (changed2) { + IRO_PasteAfter(list->list.head, list->list.tail, nd); + for (nd2 = list->list.head; nd2 != list->list.tail->next; nd2 = nd2->next) { + if (nd2->type == IROLinearOperand && nd2->u.node->type == EOBJREF) { + if (nd2->u.node->data.objref->datatype == DDATA || nd2->u.node->data.objref->datatype == DLOCAL) + IRO_FindVar(nd2->u.node->data.objref, 1, 1); + else + nd2->u.node->data.objref->varptr = NULL; + } + } + } + changed |= changed2; + } + + while (list) { + scan = list->nextList; + IRO_free(list); + list = scan; + } + } + } + } + + result |= changed; + IRO_CheckForUserBreak(); + } while (changed); + + return result; +} diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroEval.h b/compiler_and_linker/FrontEnd/Optimizer/IroEval.h new file mode 100644 index 0000000..3b91f21 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroEval.h @@ -0,0 +1,14 @@ +#ifndef COMPILER_IROEVAL_H +#define COMPILER_IROEVAL_H + +#include "IrOptimizer.h" + +extern void IRO_InitializeIsAssociativeENodeTypeArray(void); +extern void IRO_TruncateValueToType(CInt64 *val, Type *type); +extern void IRO_TruncateBitfieldValueToType(CInt64 *val, Type *type, Type *type2); +extern void IRO_ConstantFolding(void); +extern Boolean IRO_EvaluateConditionals(void); +extern int IRO_SimplifyConditionals(void); +extern Boolean IRO_EvaluateDefinitePointers(Object *func); + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroExprRegeneration.c b/compiler_and_linker/FrontEnd/Optimizer/IroExprRegeneration.c new file mode 100644 index 0000000..c56beae --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroExprRegeneration.c @@ -0,0 +1,1531 @@ +#include "IroExprRegeneration.h" +#include "IroCSE.h" +#include "IroDump.h" +#include "IroFlowgraph.h" +#include "IroLinearForm.h" +#include "IroSubable.h" +#include "IroTransform.h" +#include "IROUseDef.h" +#include "IroUtil.h" +#include "IroVars.h" +#include "compiler/CDecl.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/objects.h" + +// forward decls +static void GetExprUses(IROLinear *linear, Boolean isEntry); +static void RebuildPossibleCondExpression(IRONode *fnode); +static void AddNodeAndSuccessorsRecursively(IRONodes *nodes, IRONode *fnode1, IRONode *fnode2); + +static Boolean FindFlowgraphNodeThatStartsWithLabel(CLabel *label, IRONode **result1, IRONode **result2) { + IRONode *prev; + IRONode *iter; + + prev = IRO_FirstNode; + if (prev != NULL) + iter = prev->nextnode; + + while (iter) { + if (iter->first->type == IROLinearLabel && iter->first->u.label.label == label) { + *result1 = iter; + *result2 = prev; + return 1; + } + + prev = iter; + iter = iter->nextnode; + } + + return 0; +} + +static IROLinear *FindLastDiadicTopLevelAssignmentInFlowgraphNode(IRONode *fnode) { + IROLinear *scan; + IROLinear *result; + + result = NULL; + + for (scan = fnode->first; scan != fnode->last->next; scan = scan->next) { + if (scan->type == IROLinearOp2Arg && scan->nodetype == EASS && !(scan->flags & IROLF_Reffed)) + result = scan; + } + + return result; +} + +static Boolean RewriteUse(IROUse *use, ENode *enode, IROLinear *nd, Boolean flag) { + IROLinear *father; + IROLinear *father2; + + if ( + use && + use->x1C && + use->linear && + use->linear->type == IROLinearOperand && + use->linear->u.node->type == EOBJREF && + use->linear->u.node->data.objref == enode->data.objref && + (father = IRO_LocateFather(use->linear)) && + father->type == IROLinearOp1Arg && + father->nodetype == EINDIRECT && + father->rtype == nd->rtype && + (father2 = IRO_LocateFather(father)) && + ((father2->type != IROLinearOp1Arg && father2->type != IROLinearOp2Arg) || !IRO_IsModifyOp[father2->nodetype]) + ) { + if (flag) + IRO_LocateFather_Cut_And_Paste(father, nd); + return 1; + } + + return 0; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +static struct { + jmp_buf buf; + UInt16 index; + Boolean flag; +} scuai; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void StatementContainsUseAction(IROLinear *linear, Boolean isFirst) { + if (isFirst && linear->index == scuai.index) { + scuai.flag = 1; + longjmp(scuai.buf, 1); + } +} + +static Boolean StatementContainsUse(IROLinear *a, IROLinear *b) { + memset(&scuai, 0, sizeof(scuai)); + scuai.index = b->index; + scuai.flag = 0; + + if (!setjmp(scuai.buf)) + IRO_WalkInts(a, a, StatementContainsUseAction); + + return scuai.flag; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +static struct { + jmp_buf buf; + Boolean flag; +} scseai; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void StatementContainsSideEffectAction(IROLinear *linear, Boolean isFirst) { + if (isFirst) { + switch (linear->type) { + case IROLinearOperand: + case IROLinearOp1Arg: + case IROLinearOp2Arg: + case IROLinearOp3Arg: + case IROLinearFunccall: + case IROLinearAsm: + if (IRO_HasSideEffect(linear)) { + scseai.flag = 1; + longjmp(scseai.buf, 1); + } + break; + } + } +} + +static Boolean StatementContainsSideEffect(IROLinear *linear) { + memset(&scseai, 0, sizeof(scseai)); + scseai.flag = 0; + + if (!setjmp(scseai.buf)) + IRO_WalkInts(linear, linear, StatementContainsSideEffectAction); + + return scseai.flag; +} + +static Boolean HasSideEffectsBeforeUse(IRONode *fnode1, IRONode *fnode2, IRONode *fnode3, IROLinear *nd, Boolean flag) { + IRONode *fnode; + IROLinear *scannd; + UInt16 i; + + if (fnode1 != fnode3) { + if (flag) { + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) + fnode->x3C = 0; + } else if (fnode1->x3C) { + return 0; + } + fnode1->x3C = 1; + } + + for (scannd = fnode1->first; scannd && scannd != fnode1->last->next; scannd = scannd->next) { + if (!(scannd->flags & IROLF_Reffed)) { + if (StatementContainsUse(scannd, nd)) + return 0; + if (StatementContainsSideEffect(scannd)) + return 1; + } + } + + if (fnode1 != fnode3) { + for (i = 0; i < fnode1->numsucc; i++) { + if (HasSideEffectsBeforeUse(IRO_NodeTable[fnode1->succ[i]], fnode2, fnode3, nd, 0)) + return 1; + } + } + + return 0; +} + +static Boolean UsesAKilledVarBeforeUse(IRONode *fnode1, IRONode *fnode2, IRONode *fnode3, IROLinear *nd, BitVector *bv, Boolean flag) { + IRONode *fnode; + UInt16 i; + IROLinear *scannd; + + if (fnode1 != fnode3) { + if (flag) { + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) + fnode->x3C = 0; + } else if (fnode1->x3C) { + return 0; + } + fnode1->x3C = 1; + } + + for (scannd = fnode1->first; scannd && scannd != fnode1->last->next; scannd = scannd->next) { + if (!(scannd->flags & IROLF_Reffed)) { + if (StatementContainsUse(scannd, nd)) + return 0; + Bv_Clear(IRO_VarKills); + IRO_WalkInts(scannd, scannd, GetExprUses); + if (Bv_BitsInCommon(bv, IRO_VarKills)) + return 1; + } + } + + if (fnode1 != fnode3) { + for (i = 0; i < fnode1->numsucc; i++) { + if (UsesAKilledVarBeforeUse(IRO_NodeTable[fnode1->succ[i]], fnode2, fnode3, nd, bv, 0)) + return 1; + } + } + + return 0; +} + +static void GetExprUses(IROLinear *linear, Boolean isEntry) { + Object *obj; + VarRecord *var; + + if (isEntry) { + if (linear->type == IROLinearOperand && linear->u.node->type == EOBJREF) { + obj = linear->u.node->data.objref; + if ((linear->flags & IROLF_Ind) && (!(linear->flags & IROLF_Assigned) || (linear->flags & IROLF_Used))) { + if ((var = IRO_FindVar(obj, 0, 1))) + Bv_SetBit(var->index, IRO_VarKills); + } + } + } +} + +static void GetExprKills(IROLinear *linear, Boolean isEntry) { + if (isEntry) + IRO_GetKills(linear); +} + +static void CheckUnorderedRegionForSideEffectsAndUses(IROLinear *nd, BitVector *bv1, BitVector *bv2, Boolean *result) { + if (IRO_HasSideEffect(nd)) { + *result = 1; + } else { + Bv_Clear(bv2); + Bv_Clear(IRO_VarKills); + IRO_WalkTree(nd, GetExprUses); + Bv_Or(IRO_VarKills, bv2); + + if (Bv_BitsInCommon(bv1, bv2)) + *result = 1; + } +} + +static void CheckUnorderedRegionsForSideEffectsAndUses(IROLinear *nd1, IROLinear *nd2, BitVector *bv1, BitVector *bv2, Boolean *result) { + int i; + + switch (nd1->type) { + case IROLinearOp2Arg: + if (nd1->nodetype != ELAND && nd1->nodetype != ELOR && nd1->nodetype != ECOMMA) { + if (nd1->u.diadic.left != nd2) + CheckUnorderedRegionForSideEffectsAndUses(nd1->u.diadic.left, bv1, bv2, result); + if (nd1->u.diadic.right != nd2) + CheckUnorderedRegionForSideEffectsAndUses(nd1->u.diadic.right, bv1, bv2, result); + } + break; + case IROLinearFunccall: + if (nd1->u.funccall.linear8 != nd2) + CheckUnorderedRegionForSideEffectsAndUses(nd1->u.funccall.linear8, bv1, bv2, result); + for (i = 0; !*result && i < nd1->u.funccall.argCount; i++) { + if (nd1->u.funccall.args[i] != nd2) + CheckUnorderedRegionForSideEffectsAndUses(nd1->u.funccall.args[i], bv1, bv2, result); + } + break; + } +} + +static Boolean CheckThenOrElseBranch(IRONode *fnode1, IRONode *fnode2, IROLinear *nd, Boolean flag) { + IRONode *fnode; + IROLinear *scannd; + IRONodes nodes; + Boolean result; + + IROFlowgraph_sub_4C2140(&nodes); + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) + fnode->x3C = 0; + AddNodeAndSuccessorsRecursively(&nodes, fnode1, fnode2); + + while (IROFlowgraph_sub_4C2040(&nodes)) { + fnode = IRO_NodeTable[IROFlowgraph_sub_4C2100(&nodes)]; + if (fnode) { + if (!Bv_IsBitSet(fnode1->index, fnode->dom)) { + result = 0; + goto done; + } + + for (scannd = fnode->first; scannd && scannd != fnode->last->next; scannd = scannd->next) { + if (!nd || scannd != nd) { + if (!flag || (scannd->type != IROLinearReturn)) { + if (fnode->numpred == 2 && scannd->type == IROLinearLabel) + RebuildPossibleCondExpression(fnode); + + if (scannd->type != IROLinearNop && + scannd->type != IROLinearLabel && + scannd->type != IROLinearGoto && + !(scannd->flags & IROLF_Reffed)) { + result = 0; + goto done; + } + } + } + } + } + } + + result = 1; +done: + IROFlowgraph_sub_4C20E0(&nodes); + return result; +} + +static void RebuildPossibleCondExpression(IRONode *fnode) { + IRONode *pred1; + IRONode *pred2; + IRONode *r30; + IROLinear *leftAss; + IROLinear *rightAss; + IROLinear *r27; + IROLinear *r13; + IROLinear *var_58; + IRONode *left; + IRONode *right; + IRONode *r24; + ENode *r23; + IRODef *r22; + IRODef *r21; + IRODef *def; + IROUse *use; + UInt32 r20; + UInt32 r19; + Boolean r18; + Boolean r17; + UInt32 i; + Boolean compareType; + Type *var_60; + IROLinear copy1; + IROLinear copy2; + IROLinear copy3; + + if ( + !fnode || + fnode->numpred != 2 || + !fnode->first || + fnode->first->type != IROLinearLabel + ) + return; + + pred1 = IRO_NodeTable[fnode->pred[0]]; + pred2 = IRO_NodeTable[fnode->pred[1]]; + if ( + !pred1 || !pred2 || + pred1->numsucc != 1 || pred2->numsucc != 1 + ) + return; + + r24 = NULL; + for (i = 0; i < IRO_NumNodes; i++) { + if ( + Bv_IsBitSet(i, fnode->dom) && + (r24 = IRO_NodeTable[i]) && + r24->last && + (r24->last->type == IROLinearIf || r24->last->type == IROLinearIfNot) && + r24->last->u.label.label && + r24->numsucc == 2 + ) { + if (Bv_IsBitSet(r24->succ[0], pred1->dom) && + !Bv_IsBitSet(r24->succ[0], pred2->dom) && + Bv_IsBitSet(r24->succ[1], pred2->dom) && + !Bv_IsBitSet(r24->succ[1], pred1->dom)) + break; + + if (Bv_IsBitSet(r24->succ[0], pred2->dom) && + !Bv_IsBitSet(r24->succ[0], pred1->dom) && + Bv_IsBitSet(r24->succ[1], pred1->dom) && + !Bv_IsBitSet(r24->succ[1], pred2->dom)) + break; + } + } + + if (i >= IRO_NumNodes) + return; + + /*if ( + (r30 = IRO_NodeTable[r24->succ[0]]) && + r30->numpred == 1 && + r30->first && + r30->first->type == IROLinearLabel && + r30->first->u.label.label == r24->last->u.label.label + ) { + goto ok; + } else if ( + (r30 = IRO_NodeTable[r24->succ[1]]) && + r30->numpred == 1 && + r30->first && + r30->first->type == IROLinearLabel && + r30->first->u.label.label == r24->last->u.label.label + ) { + goto ok; + } else { + return; + }*/ + /*if ( + (!(r30 = IRO_NodeTable[r24->succ[0]]) || + r30->numpred != 1 || + !r30->first || + r30->first->type != IROLinearLabel || + r30->first->u.label.label != r24->last->u.label.label) + && + (!(r30 = IRO_NodeTable[r24->succ[1]]) || + r30->numpred != 1 || + !r30->first || + r30->first->type != IROLinearLabel || + r30->first->u.label.label != r24->last->u.label.label) + ) + return;*/ + r30 = IRO_NodeTable[r24->succ[0]]; + if ( + r30 && + r30->numpred == 1 && + r30->first && + r30->first->type == IROLinearLabel && + r30->first->u.label.label == r24->last->u.label.label + ) { + (void)0; + } else { + r30 = IRO_NodeTable[r24->succ[1]]; + if ( + r30 && + r30->numpred == 1 && + r30->first && + r30->first->type == IROLinearLabel && + r30->first->u.label.label == r24->last->u.label.label + ) { + } else { + return; + } + } + +ok: + if (Bv_IsBitSet(r30->index, pred1->dom)) { + left = pred2; + right = pred1; + } else { + left = pred1; + right = pred2; + } + + leftAss = FindLastDiadicTopLevelAssignmentInFlowgraphNode(left); + if ( + !leftAss || + leftAss->type != IROLinearOp2Arg || + !leftAss->u.diadic.left || + leftAss->u.diadic.left->type != IROLinearOp1Arg || + leftAss->u.diadic.left->nodetype != EINDIRECT || + !leftAss->u.diadic.left->u.monadic || + leftAss->u.diadic.left->u.monadic->type != IROLinearOperand || + !(r23 = leftAss->u.diadic.left->u.monadic->u.node) || + !r23->rtype || + !IS_TYPE_POINTER_ONLY(r23->rtype) || + !r23->data.objref || + is_volatile_object(r23->data.objref) || + r23->data.objref->datatype != DLOCAL + ) + r23 = NULL; + + if (r23) { + rightAss = FindLastDiadicTopLevelAssignmentInFlowgraphNode(right); + if ( + !rightAss || + rightAss->type != IROLinearOp2Arg || + !rightAss->u.diadic.left || + rightAss->u.diadic.left->type != IROLinearOp1Arg || + rightAss->u.diadic.left->nodetype != EINDIRECT || + !rightAss->u.diadic.left->u.monadic || + rightAss->u.diadic.left->u.monadic->type != IROLinearOperand || + !rightAss->u.diadic.left->u.monadic->u.node || + !rightAss->u.diadic.left->u.monadic->u.node->rtype || + !IS_TYPE_POINTER_ONLY(rightAss->u.diadic.left->u.monadic->u.node->rtype) || + rightAss->u.diadic.left->u.monadic->u.node->type != EOBJREF || + rightAss->u.diadic.left->u.monadic->u.node->data.objref != r23->data.objref || + rightAss->rtype != leftAss->rtype + ) + r23 = NULL; + } + + if (r23) { + if (!CheckThenOrElseBranch(r24->nextnode, left, leftAss, 0) || !CheckThenOrElseBranch(r30, right, rightAss, 0)) + return; + + r19 = 0; + r20 = 0; + r18 = 0; + r17 = 0; + if (!r23->data.objref->varptr || !r23->data.objref->varptr->uses || !r23->data.objref->varptr->defs) { + r23 = NULL; + } else { + r21 = NULL; + r22 = NULL; + for (def = r23->data.objref->varptr->defs; def && (!r22 || !r21); def = def->varnext) { + if (def->x18 && def->linear == leftAss) + r22 = def; + else if (def->x18 && def->linear == rightAss) + r21 = def; + } + + if (!r22 || !r21) { + r23 = NULL; + } else { + for (use = r23->data.objref->varptr->uses; r23 && use; use = use->varnext) { + if (use->x1C) { + r20++; + if (Bv_IsBitSet(r22->index, use->x18) && Bv_IsBitSet(r21->index, use->x18)) { + for (i = 0; r23 && i < use->x18->size; i++) { + if (i != r22->index && i != r21->index && Bv_IsBitSet(i, use->x18)) + r23 = NULL; + } + + if (r23 && !Bv_IsBitSet(fnode->index, use->node->dom)) + r23 = NULL; + + if (r23) { + if (RewriteUse(use, r23, rightAss, 0)) + r19++; + else + r23 = NULL; + } + + if (r23 && !r17) + r17 = HasSideEffectsBeforeUse(fnode, fnode, use->node, use->linear, 1); + + if (r23 && !r18 && (IRO_HasSideEffect(r24->last->u.label.x4) || IRO_HasSideEffect(leftAss->u.label.x4) || + IRO_HasSideEffect(rightAss->u.label.x4))) + r18 = 1; + } else if (Bv_IsBitSet(r22->index, use->x18) || Bv_IsBitSet(r21->index, use->x18)) { + r23 = NULL; + } + } + } + } + } + } + + if (!r23) + return; + + compareType = r24->last->type == IROLinearIf; + r27 = r24->last->u.label.x4; + r13 = leftAss->u.label.x4; + var_58 = rightAss->u.label.x4; + var_60 = rightAss->rtype; + memcpy(©1, r13, sizeof(IROLinear)); + memcpy(©2, rightAss, sizeof(IROLinear)); + + r24->last->type = IROLinearNop; + r24->last->expr = NULL; + r30->first->type = IROLinearNop; + r30->first->expr = NULL; + fnode->first->type = IROLinearNop; + fnode->first->expr = NULL; + if (left->last->type == IROLinearGoto) { + left->last->type = IROLinearNop; + left->last->expr = NULL; + } + if (right->last->type == IROLinearGoto) { + right->last->type = IROLinearNop; + right->last->expr = NULL; + } + + if (r23) { + IRO_NopOut(leftAss->u.diadic.left); + leftAss->type = IROLinearNop; + leftAss->expr = NULL; + } + + memcpy(rightAss, ©1, sizeof(IROLinear)); + rightAss->type = IROLinearOp3Arg; + rightAss->nodetype = ECOND; + rightAss->index = copy2.index; + rightAss->u.args3.a = r27; + rightAss->rtype = var_60; + rightAss->next = copy2.next; + if (compareType) { + rightAss->u.args3.b = var_58; + rightAss->u.args3.c = r13; + } else { + rightAss->u.args3.b = r13; + rightAss->u.args3.c = var_58; + } + rightAss->flags |= IROLF_Reffed; + + if (r19 == 1 && !r17 && !r18 && !r23->data.objref->varptr->xB) { + for (use = r23->data.objref->varptr->uses; use; use = use->varnext) { + if (use->x1C && Bv_IsBitSet(r22->index, use->x18) && Bv_IsBitSet(r21->index, use->x18)) { + RewriteUse(use, r23, rightAss, 1); + if ((r18 = (use->linear->flags & IROLF_4000) && IRO_HasSideEffect(r27))) { + IROLinear *tmp; + Object *obj; + + tmp = IRO_NewLinear(IROLinearOperand); + memcpy(tmp, copy2.u.diadic.left->u.monadic, sizeof(IROLinear)); + tmp->index = IRO_NumLinear++; + tmp->rtype = r27->rtype; + if (r20 == 1) { + tmp->u.node->data.objref->type = r27->rtype; + tmp->u.node->rtype = CDecl_NewPointerType(r27->rtype); + } else { + obj = create_temp_object(tmp->rtype); + IRO_FindVar(obj, 1, 1); + tmp->u.node = create_objectrefnode(obj); + } + IRO_PasteAfter(tmp, tmp, r27); + + tmp = IRO_NewLinear(IROLinearOp1Arg); + memcpy(tmp, copy2.u.diadic.left, sizeof(IROLinear)); + tmp->index = IRO_NumLinear++; + tmp->u.monadic = r27->next; + tmp->rtype = r27->rtype; + IRO_PasteAfter(tmp, tmp, r27->next); + + tmp = IRO_NewLinear(IROLinearOp2Arg); + memcpy(tmp, ©2, sizeof(IROLinear)); + tmp->index = IRO_NumLinear++; + tmp->u.diadic.right = r27; + tmp->u.diadic.left = r27->next->next; + tmp->rtype = r27->rtype; + IRO_PasteAfter(tmp, tmp, r27->next->next); + + if (r20 != 1) { + tmp = copy2.u.diadic.left->u.monadic; + tmp->u.node = create_objectrefnode(obj); + } + + rightAss->u.args3.a = copy2.u.diadic.left; + rightAss->u.args3.a->rtype = r27->rtype; + + if (r20 == 1) { + r21->linear = r27->next->next; + if (Bv_IsBitSet(r21->index, right->x1A)) { + Bv_ClearBit(r21->index, right->x1A); + Bv_SetBit(r21->index, r24->x1A); + } + if (Bv_IsBitSet(r21->index, right->x1E)) { + Bv_ClearBit(r21->index, right->x1E); + Bv_SetBit(r21->index, r24->x1E); + } + if (Bv_IsBitSet(r21->index, right->x22)) { + Bv_ClearBit(r21->index, right->x22); + Bv_SetBit(r21->index, r24->x22); + } + } + } + } + } + + if (!r18) { + if (r20 == 1 && r23->data.objref->u.var.info) { + r23->data.objref->u.var.info->usage = 0; + r23->data.objref->u.var.info->used = 0; + } + r22->x18 = 0; + IRO_NopOut(copy2.u.diadic.left); + r21->x18 = 0; + } + } else { + memcpy(©3, fnode->first, sizeof(IROLinear)); + memcpy(fnode->first, ©2, sizeof(IROLinear)); + + fnode->first->index = copy3.index; + fnode->first->u.diadic.right = rightAss; + fnode->first->next = copy3.next; + r22->x18 = 0; + r21->linear = fnode->first; + if (Bv_IsBitSet(r21->index, right->x1A)) { + Bv_ClearBit(r21->index, right->x1A); + Bv_SetBit(r21->index, fnode->x1A); + } + if (Bv_IsBitSet(r21->index, right->x1E)) { + Bv_ClearBit(r21->index, right->x1E); + Bv_SetBit(r21->index, fnode->x1E); + } + if (Bv_IsBitSet(r21->index, right->x22)) { + Bv_ClearBit(r21->index, right->x22); + Bv_SetBit(r21->index, fnode->x22); + } + } +} + +static void RebuildPossibleReturnCondExpression(IRONode *fnode) { + IRONode *succ1; + IRONode *succ2; + IROLinear *node1; + IROLinear *node2; + IROLinear *node3; + IRONode *r27; + Boolean isIf; + Type *type; + IROList list; + + if ( + !fnode || + fnode->numsucc != 2 || + !fnode->last || + (fnode->last->type != IROLinearIf && fnode->last->type != IROLinearIfNot) + ) + return; + + succ1 = IRO_NodeTable[fnode->succ[0]]; + succ2 = IRO_NodeTable[fnode->succ[1]]; + if ( + !succ1 || !succ2 || + succ1->numsucc != 0 || succ1->numpred != 1 || + succ2->numsucc != 0 || succ2->numpred != 1 + ) + return; + + if (succ1->first && succ1->first->type == IROLinearLabel && succ1->first->u.label.label == fnode->last->u.label.label) { + r27 = succ1; + } else if (succ2->first && succ2->first->type == IROLinearLabel && succ2->first->u.label.label == fnode->last->u.label.label) { + r27 = succ2; + } else { + return; + } + + if (r27->numpred != 1) + return; + + if (!CheckThenOrElseBranch(fnode->nextnode, fnode->nextnode, NULL, 1) || !CheckThenOrElseBranch(r27, r27, NULL, 1)) + return; + + if ( + !fnode->nextnode->last || + fnode->nextnode->last->type != IROLinearReturn || + !fnode->nextnode->last->u.monadic || + !r27->last || + r27->last->type != IROLinearReturn || + !r27->last->u.monadic || + !IRO_TypesEqual(fnode->nextnode->last->u.monadic->rtype, r27->last->u.monadic->rtype) + ) + return; + + isIf = fnode->last->type == IROLinearIf; + node1 = fnode->last->u.diadic.right; + node2 = fnode->nextnode->last->u.diadic.left; + node3 = r27->last->u.diadic.left; + type = node2->rtype; + + fnode->last->type = IROLinearNop; + fnode->last->expr = NULL; + r27->last->type = IROLinearNop; + r27->last->expr = NULL; + r27->first->type = IROLinearNop; + r27->first->expr = NULL; + + if (IRO_IsIntConstant(node2) && IRO_IsIntConstant(node3) && + ((IRO_IsConstantOne(node2) && IRO_IsConstantZero(node3)) || + (IRO_IsConstantZero(node2) && IRO_IsConstantOne(node3)))) { + if (!(node1->type == IROLinearOp1Arg && node1->nodetype == ELOGNOT && node1->rtype == type)) { + IROLinear *tmp1; + IROLinear *tmp2; + + tmp1 = IRO_NewLinear(IROLinearOp1Arg); + memcpy(tmp1, node2, sizeof(IROLinear)); + tmp1->type = IROLinearOp1Arg; + tmp1->nodetype = ELOGNOT; + tmp1->index = IRO_NumLinear++; + tmp1->u.monadic = node1; + + tmp1->next = tmp2 = IRO_NewLinear(IROLinearOp1Arg); + memcpy(tmp2, node2, sizeof(IROLinear)); + tmp2->type = IROLinearOp1Arg; + tmp2->nodetype = ELOGNOT; + tmp2->index = IRO_NumLinear++; + tmp2->u.monadic = tmp1; + + IRO_PasteAfter(tmp1, tmp2, node1); + node1 = tmp2; + } + + if ((IRO_IsConstantZero(node2) && !isIf) || (IRO_IsConstantOne(node2) && isIf)) { + if (node1->type == IROLinearOp1Arg && node1->nodetype == ELOGNOT && node1->rtype == node1->u.monadic->rtype) { + IROLinear *tmp = node1; + node1 = node1->u.monadic; + tmp->type = IROLinearNop; + tmp->expr = NULL; + } else { + IROLinear *tmp = IRO_NewLinear(IROLinearOp1Arg); + memcpy(tmp, node2, sizeof(IROLinear)); + tmp->type = IROLinearOp1Arg; + tmp->nodetype = ELOGNOT; + tmp->index = IRO_NumLinear++; + tmp->u.monadic = node1; + IRO_PasteAfter(tmp, tmp, node1); + node1 = tmp; + } + } + + node2->type = IROLinearNop; + node2->expr = NULL; + node3->type = IROLinearNop; + node3->expr = NULL; + fnode->nextnode->last->u.monadic = node1; + } else { + IROLinear *tmp1; + IROLinear *tmp2; + + IRO_InitList(&list); + tmp1 = IRO_DuplicateExpr(node3, &list); + IRO_NopOut(node3); + IRO_Paste(list.head, list.tail, fnode->nextnode->last); + + tmp2 = IRO_NewLinear(IROLinearOp3Arg); + memcpy(tmp2, node2, sizeof(IROLinear)); + tmp2->type = IROLinearOp3Arg; + tmp2->nodetype = ECOND; + tmp2->index = IRO_NumLinear++; + tmp2->u.args3.a = node1; + tmp2->rtype = type; + IRO_Paste(tmp2, tmp2, fnode->nextnode->last); + + if (isIf) { + tmp2->u.args3.b = tmp1; + tmp2->u.args3.c = node2; + } else { + tmp2->u.args3.b = node2; + tmp2->u.args3.c = tmp1; + } + + fnode->nextnode->last->u.monadic = tmp2; + } +} + +static void RebuildCondExpressions(void) { + IRONode *fnode; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (fnode->numpred == 2) { + if (fnode->first && fnode->first->type == IROLinearLabel) + RebuildPossibleCondExpression(fnode); + } else if (fnode->numsucc == 2) { + if (fnode->last && (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot)) + RebuildPossibleReturnCondExpression(fnode); + } + } + + IRO_CheckForUserBreak(); +} + +static Boolean IsLogicalExpressionAssign(IROLinear *nd) { + IROLinear *right; + IROLinear *left; + + return ( + nd->type == IROLinearOp2Arg && + nd->nodetype == EASS && + (left = nd->u.diadic.left) && + (right = nd->u.diadic.right) && + right->type == IROLinearOperand && + right->u.node && + right->u.node->type == EINTCONST && + (CInt64_Equal(right->u.node->data.intval, cint64_one) || CInt64_Equal(right->u.node->data.intval, cint64_zero)) && + left->type == IROLinearOp1Arg && + left->nodetype == EINDIRECT && + left->u.monadic && + IS_TYPE_POINTER_ONLY(left->u.monadic->rtype) && + left->u.monadic->type == IROLinearOperand && + left->u.monadic->u.node && + left->u.monadic->u.node->type == EOBJREF && + left->u.monadic->u.node->data.objref && + left->u.monadic->u.node->data.objref->datatype == DLOCAL); +} + +static Boolean IsPossibleLogicalExpressionStart(IRONode *fnode, IROLinear *nd) { + return + fnode->numsucc == 2 && + fnode->last && + (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot) && + IsLogicalExpressionAssign(nd); +} + +static Boolean CheckForTopLevelExpressions(IRONode *fnode1, IRONode *fnode2, IRONode *fnode3, IROLinear *nd1, IROLinear *nd2, Boolean flag) { + IRONode *fnode; + IROLinear *nd; + UInt16 i; + + if (fnode1 != fnode3) { + if (!Bv_IsBitSet(fnode2->index, fnode1->dom)) + return 0; + + if (flag) { + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) + fnode->x3C = 0; + } else if (fnode1->x3C) { + return 1; + } + fnode1->x3C = 1; + + for (i = 0; i < fnode1->numsucc; i++) { + fnode = IRO_NodeTable[fnode1->succ[i]]; + if (!CheckForTopLevelExpressions(fnode, fnode2, fnode3, fnode->first, nd2, 0)) + return 0; + } + } + + for (nd = nd1; nd && nd != fnode1->last->next; nd = nd->next) { + if (nd == nd2) + return 1; + + if (nd->type != IROLinearNop && nd->type != IROLinearLabel && !(nd->flags & IROLF_Reffed)) + return 0; + } + + return 1; +} + +static void AddNodeAndSuccessorsRecursively(IRONodes *nodes, IRONode *fnode1, IRONode *fnode2) { + UInt16 i; + + if (fnode1 && !fnode1->x3C) { + fnode1->x3C = 1; + IROFlowgraph_sub_4C3880(nodes, fnode1->index); + if (fnode1 != fnode2) { + for (i = 0; i < fnode1->numsucc; i++) + AddNodeAndSuccessorsRecursively(nodes, IRO_NodeTable[fnode1->succ[i]], fnode2); + } + } +} + +static Boolean RebuildPossibleLogicalExpression(IRONode *fnode, IROLinear *nd) { + IROUse *use; + IROLinear *nd2; + IROLinear *left; + IROLinear *right; + IRONode *r25; + IRONode *r24; + ENode *objnode; + IRODef *def1; + IRODef *def2; + UInt32 useCount; + UInt32 rewrittenUseCount; + Boolean sideEffectFlag; + IROLinearType compareType; + CLabel *somelab; + IRONode *var_68; + IRONode *var_6C; + CInt64 compareVal; + Boolean killedFlag; + BitVector *bv1; + BitVector *bv2; + + IROLinear *father; + IROLinear *iter; + IRODef *def; + UInt32 i; + IROLinear *newlin; + + objnode = nd->u.diadic.left->u.monadic->u.node; + if (!objnode->data.objref->varptr) + return 0; + + if (CInt64_Equal(nd->u.diadic.right->u.node->data.intval, cint64_zero)) { + compareType = IROLinearIfNot; + compareVal = cint64_one; + } else { + compareType = IROLinearIf; + compareVal = cint64_zero; + } + + var_68 = NULL; + def1 = NULL; + for (def = objnode->data.objref->varptr->defs; def && !def1; def = def->varnext) { + if (def->x18 && def->linear == nd) + def1 = def; + } + + if (def1) { + for (use = objnode->data.objref->varptr->uses; use; use = use->varnext) { + if (use->x1C == 2 && Bv_IsBitSet(def1->index, use->x18)) { + if (!var_68) { + var_68 = use->node; + } else if (Bv_IsBitSet(use->node->index, var_68->dom)) { + var_68 = use->node; + } + } + } + + if (var_68) { + for (use = objnode->data.objref->varptr->uses; use; use = use->varnext) { + if (use->node != var_68 && use->x1C == 2 && Bv_IsBitSet(def1->index, use->x18) && !Bv_IsBitSet(var_68->index, use->node->dom)) { + var_68 = NULL; + break; + } + } + } + } + + if ( + !var_68 || + !var_68->first || + var_68->first->type != IROLinearLabel || + !(somelab = var_68->first->u.label.label) || + var_68->numpred != 3 + ) + return 0; + + r25 = IRO_NodeTable[var_68->pred[0]]; + if (Bv_IsBitSet(IRO_NodeTable[var_68->pred[1]]->index, r25->dom)) { + r25 = IRO_NodeTable[var_68->pred[1]]; + } else if (!Bv_IsBitSet(r25->index, IRO_NodeTable[var_68->pred[1]]->dom)) { + return 0; + } + + if (Bv_IsBitSet(IRO_NodeTable[var_68->pred[2]]->index, r25->dom)) { + r25 = IRO_NodeTable[var_68->pred[2]]; + } else if (!Bv_IsBitSet(r25->index, IRO_NodeTable[var_68->pred[2]]->dom)) { + return 0; + } + + if ( + !r25 || + !(left = r25->last) || + left->type != compareType || + left->u.label.label != somelab + ) + return 0; + + if ( + !FindFlowgraphNodeThatStartsWithLabel(left->u.label.label, &var_68, &var_6C) || + !var_6C || + var_6C->numpred != 1 || + !(r24 = IRO_NodeTable[var_6C->pred[0]]) || + !(right = r24->last) || + right->type != compareType || + right->u.label.label != left->u.label.label || + !(nd2 = FindLastDiadicTopLevelAssignmentInFlowgraphNode(var_6C)) || + !IsLogicalExpressionAssign(nd2) || + nd2->u.diadic.left->u.monadic->u.node->data.objref != objnode->data.objref || + !CInt64_Equal(compareVal, nd2->u.diadic.right->u.node->data.intval) || + nd2->rtype != nd->rtype + ) + return 0; + + if ( + !CheckForTopLevelExpressions(fnode, fnode, r25, nd->next, left, 1) || + !CheckForTopLevelExpressions(r25->nextnode, r25->nextnode, r24, r25->nextnode->first, right, 1) || + !CheckForTopLevelExpressions(r24->nextnode, r24->nextnode, var_6C, right->next, nd2, 1) || + !CheckForTopLevelExpressions(var_6C, var_6C, var_6C, nd2->next, var_68->first, 1) + ) + return 0; + + rewrittenUseCount = 0; + useCount = 0; + killedFlag = 0; + sideEffectFlag = 0; + if (!objnode->data.objref->varptr || !(objnode->data.objref->varptr->uses) || !(objnode->data.objref->varptr->defs)) { + objnode = NULL; + } else { + def1 = def2 = NULL; + for (def = objnode->data.objref->varptr->defs; def && (!def1 || !def2); def = def->varnext) { + if (def->x18 && def->linear == nd) + def1 = def; + else if (def->x18 && def->linear == nd2) + def2 = def; + } + + if (!def1 || !def2) { + objnode = NULL; + } else { + for (use = objnode->data.objref->varptr->uses; objnode && use; use = use->varnext) { + if (use->x1C) { + useCount++; + if (Bv_IsBitSet(def1->index, use->x18) && Bv_IsBitSet(def2->index, use->x18)) { + for (i = 0; objnode && i < use->x18->size; i++) { + if (i != def1->index && i != def2->index && Bv_IsBitSet(i, use->x18)) + objnode = NULL; + } + + if (objnode && !Bv_IsBitSet(var_68->index, use->node->dom)) + objnode = NULL; + + if (objnode) { + if (RewriteUse(use, objnode, nd2, 0)) + rewrittenUseCount++; + else + objnode = NULL; + } + + if (objnode) { + if (!sideEffectFlag) + sideEffectFlag = HasSideEffectsBeforeUse(var_68, var_68, use->node, use->linear, 1); + + if (!killedFlag && (IRO_HasSideEffect(left->u.label.x4) || IRO_HasSideEffect(right->u.label.x4))) { + iter = use->linear; + if ((father = IRO_LocateFather(use->linear))) { + Bv_AllocVector(&bv1, IRO_NumVars + 1); + Bv_AllocVector(&bv2, IRO_NumVars + 1); + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + IRO_WalkTree(left->u.label.x4, GetExprKills); + IRO_WalkTree(right->u.label.x4, GetExprKills); + Bv_Or(IRO_VarKills, bv1); + while (father && !killedFlag) { + CheckUnorderedRegionsForSideEffectsAndUses(father, iter, bv1, bv2, &killedFlag); + iter = father; + father = IRO_LocateFather(father); + } + } + + if (!killedFlag) + killedFlag = UsesAKilledVarBeforeUse(var_68, var_68, use->node, use->linear, bv1, 1); + } + } + } else if (Bv_IsBitSet(def1->index, use->x18) || Bv_IsBitSet(def2->index, use->x18)) + objnode = NULL; + } + } + } + } + + if (!objnode) + return 0; + + left->type = right->type = IROLinearNop; + left->expr = right->expr = NULL; + + IRO_NopOut(nd); + + newlin = IRO_NewLinear(IROLinearOp2Arg); + memcpy(newlin, nd2, sizeof(IROLinear)); + newlin->nodetype = (compareType == IROLinearIf) ? ELOR : ELAND; + newlin->index = IRO_NumLinear++; + newlin->u.diadic.left = left->u.label.x4; + newlin->u.diadic.right = right->u.label.x4; + newlin->flags |= IROLF_Reffed; + IRO_Paste(newlin, newlin, nd2); + + if (rewrittenUseCount == 1 && !sideEffectFlag && !killedFlag && !objnode->data.objref->varptr->xB) { + for (use = objnode->data.objref->varptr->uses; use; use = use->varnext) { + if (use->x1C && Bv_IsBitSet(def1->index, use->x18) && Bv_IsBitSet(def2->index, use->x18)) + RewriteUse(use, objnode, newlin, 1); + } + + if (useCount == 1 && objnode->data.objref->u.var.info) { + objnode->data.objref->u.var.info->usage = 0; + objnode->data.objref->u.var.info->used = 0; + } + IRO_NopOut(nd2); + def1->x18 = 0; + def2->x18 = 0; + } else { + IRO_NopOut(nd2->u.label.x4); + nd2->u.label.x4 = newlin; + def1->x18 = 0; + } + + if (r24->numpred == 1 && IRO_NodeTable[r24->pred[0]] == r25 && IRO_MergeFlowGraphNodes(r25, r24)) + r24 = r25; + if (var_6C->numpred == 1 && IRO_NodeTable[var_6C->pred[0]] == r24 && IRO_MergeFlowGraphNodes(r24, var_6C)) + var_6C = r24; + if (var_68->numpred == 1 && r24 == r25 && var_6C == r24) + IRO_MergeFlowGraphNodes(var_6C, var_68); + return 1; +} + +static void RebuildLogicalExpressions(void) { + IRONode *fnode; + IROLinear *nd; + Boolean flag; + + flag = 1; + while (flag) { + flag = 0; + for (fnode = IRO_FirstNode; fnode && fnode->last; fnode = fnode->nextnode) { + for (nd = fnode->first; nd && nd != fnode->last->next; nd = nd->next) { + if (IsPossibleLogicalExpressionStart(fnode, nd) && RebuildPossibleLogicalExpression(fnode, nd)) + flag = 1; + } + } + } + + IRO_CheckForUserBreak(); +} + +static Boolean IsPossibleCondAssStart(IRONode *fnode) { + return (fnode->numsucc == 2) && fnode->last && (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot); +} + +static Type *logicalType(void) { + if (copts.cplusplus && copts.booltruefalse) + return TYPE(&stbool); + else + return TYPE(&stsignedint); +} + +static Boolean GeneratePossibleCondAss(IRONode *fnode) { + IROLinear *r31; + IRONode *node2; + IRONode *r29; + Boolean r28; + IRONode *node1; + IROLinear *r24; + Boolean r23; + IROLinear *r19; + Boolean r18; + IROLinear *r20; + Boolean r19flag; + IROLinear *r18nd; + IROLinear *ass; + IROLinear *cond; + IROLinear *r16; + IROLinear *r15; + BitVector *saveVarKills; + IROList list; + Object *obj; + IROLinear *r14; + + if (!fnode || fnode->numsucc != 2 || !fnode->last || (fnode->last->type != IROLinearIf && fnode->last->type != IROLinearIfNot)) + return 0; + + if (IRO_NodeTable[fnode->succ[0]] && + IRO_NodeTable[fnode->succ[0]]->first && + IRO_NodeTable[fnode->succ[0]]->first->type == IROLinearLabel && + IRO_NodeTable[fnode->succ[0]]->first->u.label.label == fnode->last->u.label.label) { + node1 = IRO_NodeTable[fnode->succ[0]]; + node2 = IRO_NodeTable[fnode->succ[1]]; + } else { + node1 = IRO_NodeTable[fnode->succ[1]]; + if (node1 && node1->first && node1->first->type == IROLinearLabel && node1->first->u.label.label == fnode->last->u.label.label) { + node2 = IRO_NodeTable[fnode->succ[0]]; + } else { + return 0; + } + } + + if (!node2 || node2->numpred != 1 || node2->numsucc != 1 || node2->last->next != node1->first) + return 0; + + if (IRO_NodeTable[node2->succ[0]] == node1 && Bv_IsBitSet(fnode->index, node1->dom)) { + r28 = 0; + } else if ( + node1->numpred == 1 && node1->numsucc == 1 && + node2->succ[0] == node1->succ[0] && + (r29 = IRO_NodeTable[node2->succ[0]]) && + Bv_IsBitSet(fnode->index, r29->dom) && + node1->last->next == r29->first + ) { + r28 = 1; + } else { + return 0; + } + + r24 = NULL; + if (node2->last) { + for (r19 = node2->first; r19 && r19 != node2->last->next; r19 = r19->next) { + if (IRO_IsAssignment(r19) && !(r19->flags & IROLF_Reffed) && !r24) { + r24 = r19; + } else if (r19->type != IROLinearNop && r19->type != IROLinearLabel && r19->type != IROLinearGoto && !(r19->flags & IROLF_Reffed)) { + return 0; + } + } + } + + if ( + !r24 || + (r24->nodetype != EASS && !IRO_TransformSelfAssignmentToAssignment(r24)) || + !r24->u.diadic.left || + r24->u.diadic.left->type != IROLinearOp1Arg || + r24->u.diadic.left->nodetype != EINDIRECT || + !r24->u.diadic.left->u.monadic || + r24->u.diadic.left->u.monadic->type != IROLinearOperand || + !r24->u.diadic.left->u.monadic->u.node || + !r24->u.diadic.left->u.monadic->u.node->rtype || + !IS_TYPE_POINTER_ONLY(r24->u.diadic.left->u.monadic->u.node->rtype) || + !r24->u.diadic.left->u.monadic->u.node->data.monadic + ) + return 0; + + if (r28) { + r31 = NULL; + if (node1->last) { + for (r19 = node1->first; r19 && r19 != node1->last->next; r19 = r19->next) { + if (IRO_IsAssignment(r19) && !(r19->flags & IROLF_Reffed) && !r31) { + r31 = r19; + } else if (r19->type != IROLinearNop && r19->type != IROLinearLabel && r19->type != IROLinearGoto && !(r19->flags & IROLF_Reffed)) { + return 0; + } + } + } + + if ( + !r31 || + (r31->nodetype != EASS && !IRO_TransformSelfAssignmentToAssignment(r31)) || + !r31->u.diadic.left || + r31->u.diadic.left->type != IROLinearOp1Arg || + r31->u.diadic.left->nodetype != EINDIRECT || + !r31->u.diadic.left->u.monadic || + r31->u.diadic.left->u.monadic->type != IROLinearOperand || + !r31->u.diadic.left->u.monadic->u.node || + !r31->u.diadic.left->u.monadic->u.node->rtype || + !IS_TYPE_POINTER_ONLY(r31->u.diadic.left->u.monadic->u.node->rtype) || + !r31->u.diadic.left->u.monadic->u.node->data.monadic + ) + return 0; + + r18 = IRO_ExprsSame(r24->u.diadic.left, r31->u.diadic.left); + } + + r23 = fnode->last->type == IROLinearIf; + r20 = fnode->last->u.diadic.right; + r19flag = 0; + if (r28 && copts.commonsubs && IRO_IsSubableExpression(r20)) + r19flag = 1; + + if (r19flag) { + IRO_FindDepends(r20); + r19flag = !IRO_NotSubable; + } + + if (r28) { + if (r18) { + r19flag = 0; + } else if (IRO_HasSideEffect(r20)) { + r19flag = 1; + } else { + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + IRO_WalkTree(r20, GetExprUses); + saveVarKills = IRO_VarKills; + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + IRO_WalkTree(r20, GetExprKills); + if (Bv_BitsInCommon(IRO_VarKills, saveVarKills)) + r19flag = 1; + } + + if (r19flag && !copts.commonsubs) + return 0; + } + + if (r19flag) { + IRO_InitList(&list); + obj = create_temp_object(r20->rtype); + IRO_FindVar(obj, 1, 1); + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->u.diadic.left = IRO_TempReference(obj, &list); + ass->rtype = r20->rtype; + ass->nodetype = EASS; + ass->index = ++IRO_NumLinear; + ass->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned; + ass->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned; + ass->u.diadic.right = r20; + IRO_AddToList(ass, &list); + IRO_PasteAfter(list.head, list.tail, r20); + } + + r16 = r24->u.diadic.left; + r15 = r24->u.diadic.right; + fnode->last->type = IROLinearNop; + fnode->last->expr = NULL; + if (node2->last->type == IROLinearGoto) { + node2->last->type = IROLinearNop; + node2->last->expr = NULL; + } + if (r28 || node1->numpred == 2) { + node1->first->type = IROLinearNop; + node1->first->expr = NULL; + } + + if (r28 && r18) { + if (node1->last->type == IROLinearGoto) { + node1->last->type = IROLinearNop; + node1->last->expr = NULL; + } + if (r29->numpred == 2) { + r29->first->type = IROLinearNop; + r29->first->expr = NULL; + } + + cond = IRO_NewLinear(IROLinearOp3Arg); + memcpy(cond, r24, sizeof(IROLinear)); + cond->type = IROLinearOp3Arg; + cond->nodetype = ECOND; + cond->index = ++IRO_NumLinear; + cond->rtype = r16->rtype; + cond->flags |= IROLF_Reffed; + if (r19flag) { + IRO_InitList(&list); + r14 = IRO_TempReference(obj, &list); + IRO_Paste(list.head, list.tail, r31); + } else { + r14 = r20; + } + cond->u.args3.a = r14; + + if (r23) { + cond->u.args3.b = r31->u.diadic.right; + cond->u.args3.c = r15; + } else { + cond->u.args3.b = r15; + cond->u.args3.c = r31->u.diadic.right; + } + + r24->type = IROLinearNop; + r24->expr = NULL; + IRO_NopOut(r24->u.diadic.left); + IRO_Paste(cond, cond, r31); + r31->u.diadic.right = cond; + } else { + r24->type = IROLinearOp3Arg; + r24->nodetype = ECONDASS; + if (r19flag) { + IRO_InitList(&list); + r20 = IRO_TempReference(obj, &list); + IRO_Paste(list.head, list.tail, r24); + } + cond = r20; + if (r23) { + r18nd = IRO_NewLinear(IROLinearOp1Arg); + memcpy(r18nd, r20, sizeof(IROLinear)); + r18nd->type = IROLinearOp1Arg; + r18nd->nodetype = ELOGNOT; + r18nd->index = ++IRO_NumLinear; + r18nd->rtype = logicalType(); + r18nd->u.monadic = r20; + r18nd->flags |= IROLF_Reffed; + IRO_Paste(r18nd, r18nd, r24); + r20 = r18nd; + } + r24->u.args3.a = r20; + r24->u.args3.b = r16; + r24->u.args3.c = r15; + if (r28) { + r15 = r31->u.diadic.left; + r16 = r31->u.diadic.right; + if (node1->last->type == IROLinearGoto) { + node1->last->type = IROLinearNop; + node1->last->expr = NULL; + } + if (r29->numpred == 2) { + r29->first->type = IROLinearNop; + r29->first->expr = NULL; + } + r31->type = IROLinearOp3Arg; + r31->nodetype = ECONDASS; + if (r19flag) { + IRO_InitList(&list); + cond = IRO_TempReference(obj, &list); + IRO_Paste(list.head, list.tail, r31); + } else { + IRO_InitList(&list); + cond = IRO_DuplicateExpr(cond, &list); + IRO_Paste(list.head, list.tail, r31); + } + if (!r23) { + r14 = IRO_NewLinear(IROLinearOp1Arg); + memcpy(r14, cond, sizeof(IROLinear)); + r14->type = IROLinearOp1Arg; + r14->nodetype = ELOGNOT; + r14->index = ++IRO_NumLinear; + r14->rtype = logicalType(); + r14->u.monadic = cond; + r14->flags |= IROLF_Reffed; + IRO_Paste(r14, r14, r31); + cond = r14; + } + r31->u.args3.a = cond; + r31->u.args3.b = r15; + r31->u.args3.c = r16; + } + } + + if (IRO_MergeFlowGraphNodes(fnode, node2)) + node2 = fnode; + if ((r28 || node1->numpred == 1) && IRO_MergeFlowGraphNodes(node2, node1)) + node1 = node2; + if (r28 && r29->numpred == 1) + IRO_MergeFlowGraphNodes(node1, r29); + return 1; +} + +static void GenerateCondAssignments(void) { + IRONode *fnode; + + fnode = IRO_FirstNode; + while (fnode && fnode->last) { + if (IsPossibleCondAssStart(fnode)) { + if (!GeneratePossibleCondAss(fnode)) + fnode = fnode->nextnode; + } else { + fnode = fnode->nextnode; + } + } + + IRO_CheckForUserBreak(); +} + +void IRO_RegenerateExpressions(void) { + IRO_UpdateFlagsOnInts(); + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + IRO_UseDef(0, 0); + + if (copts.optimizationlevel > 0) { + IRO_Dump("Rebuilding ELORs and ELANDs\n"); + RebuildLogicalExpressions(); + IRO_DumpAfterPhase("RebuildLogicalExpressions", 0); + } + + if (copts.optimizationlevel > 0) { + IRO_Dump("Rebuilding ECONDs\n"); + RebuildCondExpressions(); + IRO_DumpAfterPhase("RebuildCondExpressions", 0); + } + + if (copts.optimizationlevel > 0) { + IRO_Dump("Generating ECONDASSes\n"); + GenerateCondAssignments(); + IRO_DumpAfterPhase("GenerateCondAssignments", 0); + } +} diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroExprRegeneration.h b/compiler_and_linker/FrontEnd/Optimizer/IroExprRegeneration.h new file mode 100644 index 0000000..c74f95f --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroExprRegeneration.h @@ -0,0 +1,8 @@ +#ifndef COMPILER_IROEXPRREGENERATION_H +#define COMPILER_IROEXPRREGENERATION_H + +#include "IrOptimizer.h" + +extern void IRO_RegenerateExpressions(void); + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroFlowgraph.c b/compiler_and_linker/FrontEnd/Optimizer/IroFlowgraph.c new file mode 100644 index 0000000..2fa9875 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroFlowgraph.c @@ -0,0 +1,439 @@ +#include "IroFlowgraph.h" +#include "IroCSE.h" +#include "IroLinearForm.h" +#include "IroPropagate.h" +#include "IROUseDef.h" +#include "IroUtil.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CompilerTools.h" +#include "compiler/Exceptions.h" +#include "compiler/InlineAsmPPC.h" + +UInt16 IRO_NumNodes; +IRONode *IRO_FirstNode; +IRONode *IRO_LastNode; +IRONode *IRO_EndNode; +IRONode **IRO_NodeTable; +BitVector *IRO_VarKills; +BitVector *IRO_Avail; +BitVector *IRO_FuncKills; +BitVector *IRO_ExprKills; + +static IRONode *StartNode(IROLinear *linear) { + IRONode *node = oalloc(sizeof(IRONode)); + + node->index = IRO_NumNodes; + node->numsucc = 0; + node->succ = NULL; + node->numpred = 0; + node->pred = NULL; + node->first = linear; + node->last = linear; + node->x16 = NULL; + node->x1A = NULL; + node->x1E = NULL; + node->x22 = NULL; + node->x26 = 0; + node->x2A = NULL; + node->dom = NULL; + node->nextnode = NULL; + node->x36 = 0; + node->x37 = 0; + node->mustreach = 0; + node->x39 = 0; + node->loopdepth = 0; + node->x3C = 0; + node->addressed = NULL; + + IRO_NumNodes++; + if (!IRO_FirstNode) + IRO_FirstNode = node; + else + IRO_LastNode->nextnode = node; + IRO_LastNode = node; + return node; +} + +static void AddSucc(IRONode *a, IRONode *b) { + a->succ[a->numsucc++] = b->index; + b->numpred++; +} + +static void AddLabelSucc(IRONode *node, CLabel *label) { + IRONode *targetnode = (IRONode *) label->stmt; + if (targetnode) { + AddSucc(node, targetnode); + targetnode->x39 = 1; + } else { + CError_FATAL(126); + } +} + +static void AddSwitchSucc(IRONode *node) { + SwitchInfo *info = node->last->u.swtch.info; + SwitchCase *curcase = info->cases; + SInt32 i = 1; + + while (curcase) { + curcase = curcase->next; + i++; + } + + node->succ = oalloc(sizeof(UInt16) * i); + for (curcase = info->cases; curcase; curcase = curcase->next) + AddLabelSucc(node, curcase->label); + AddLabelSucc(node, info->defaultlabel); +} + +static void AddPred(UInt32 a, UInt16 b) { + IRONode *node = IRO_NodeTable[a]; + node->pred[node->numpred++] = b; +} + +void IRO_ComputeSuccPred(void) { + CLabel *label; + IRONode *node; + SInt32 count; + IROLinear *linear; + ExceptionAction *action; + IAEffects effects; + UInt16 i; + + for (label = Labels; label; label = label->next) + label->stmt = NULL; + + for (node = IRO_FirstNode; node; node = node->nextnode) { + node->x39 = 0; + node->numsucc = 0; + node->numpred = 0; + node->x36 = 0; + node->x37 = 0; + if (node->first && node->first->type == IROLinearLabel) + node->first->u.label.label->stmt = (Statement *) node; + } + + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (!node->first) { + if (node->nextnode) { + node->succ = oalloc(sizeof(UInt16)); + AddSucc(node, node->nextnode); + } + } else { + linear = node->last; + next_linear: + switch (linear->type) { + case IROLinearReturn: + case IROLinearEnd: + break; + case IROLinearGoto: + node->succ = oalloc(sizeof(UInt16)); + AddLabelSucc(node, linear->u.label.label); + break; + case IROLinearIf: + case IROLinearIfNot: + node->succ = oalloc(sizeof(UInt16) * 2); + AddSucc(node, node->nextnode); + AddLabelSucc(node, linear->u.label.label); + break; + case IROLinearSwitch: + AddSwitchSucc(node); + break; + case IROLinearFunccall: + count = 1; + if (IRO_FunctionCallMightThrowException(linear)) { + for (action = linear->stmt->dobjstack; action; action = action->prev) { + if (action->type == EAT_CATCHBLOCK || action->type == EAT_SPECIFICATION) + count++; + } + } + node->succ = oalloc(sizeof(UInt16) * count); + AddSucc(node, node->nextnode); + if (IRO_FunctionCallMightThrowException(linear)) { + for (action = linear->stmt->dobjstack; action; action = action->prev) { + if (action->type == EAT_CATCHBLOCK) + AddLabelSucc(node, action->data.catch_block.catch_label); + else if (action->type == EAT_SPECIFICATION) + AddLabelSucc(node, action->data.specification.unexp_label); + } + } + break; + case IROLinearAsm: + CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); + node->succ = oalloc(sizeof(UInt16) * (!effects.x5 + effects.numlabels)); + if (!effects.x5) + AddSucc(node, node->nextnode); + for (i = 0; i < effects.numlabels; i++) + AddLabelSucc(node, effects.labels[i]); + break; + case IROLinearOp2Arg: + if (linear->nodetype == ECOMMA) { + linear = linear->u.diadic.right; + goto next_linear; + } + default: + if (node->nextnode) { + node->succ = oalloc(sizeof(UInt16)); + AddSucc(node, node->nextnode); + } + } + } + } + + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->numpred) + node->pred = oalloc(sizeof(UInt16) * node->numpred); + else + node->pred = NULL; + node->numpred = 0; + } + + for (node = IRO_FirstNode; node; node = node->nextnode) { + for (i = 0; i < node->numsucc; i++) + AddPred(node->succ[i], node->index); + } + + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->first && node->first->type == IROLinearLabel) { + IROLinear *linear = node->first; + do { + if (linear->type == IROLinearBeginCatch || linear->type == IROLinearEndCatch || linear->type == IROLinearEndCatchDtor) { + node->x39 = 1; + break; + } + } while (linear != node->last && (linear = linear->next)); + } + } +} + +void IRO_ComputeDom(void) { + IRONode *node; + BitVector *bv; + SInt32 i; + int repeat; + + Bv_AllocVector(&IRO_FirstNode->dom, IRO_NumNodes); + Bv_SetBit(IRO_FirstNode->index, IRO_FirstNode->dom); + for (node = IRO_FirstNode->nextnode; node; node = node->nextnode) { + Bv_AllocVector(&node->dom, IRO_NumNodes); + Bv_Set(node->dom); + } + + Bv_AllocVector(&bv, IRO_NumNodes); + + do { + repeat = 0; + for (node = IRO_FirstNode->nextnode; node; node = node->nextnode) { + if (node->numpred) { + Bv_Set(bv); + for (i = 0; i < node->numpred; i++) { + Bv_And(IRO_NodeTable[node->pred[i]]->dom, bv); + } + Bv_SetBit(node->index, bv); + } else { + Bv_Clear(bv); + Bv_SetBit(node->index, bv); + } + + if (!Bv_Compare(bv, node->dom)) { + Bv_Copy(bv, node->dom); + repeat = 1; + } + } + } while (repeat); +} + +void IRO_BuildFlowgraph(IROLinear *linear) { + IROLinear *scan; + CLabel *label; + ExceptionAction *action; + IAEffects effects; + IRONode *node; + SInt32 i; + int flag; + + for (label = Labels; label; label = label->next) + label->stmt = NULL; + + scan = linear; + IRO_NumNodes = 0; + IRO_FirstNode = IRO_LastNode = IRO_EndNode = NULL; + while (scan) { + StartNode(scan); + if (scan->type == IROLinearLabel) + scan->u.label.label->stmt = (Statement *) IRO_LastNode; + + flag = 0; + while (!flag && scan->next && !(scan->next->flags & IROLF_1)) { + switch (scan->type) { + case IROLinearGoto: + case IROLinearReturn: + case IROLinearEntry: + case IROLinearExit: + case IROLinearEnd: + flag = 1; + break; + case IROLinearIf: + case IROLinearIfNot: + case IROLinearSwitch: + flag = 1; + skip: + if (scan->next->type == IROLinearLabel) { + IROLinear *nw = IRO_NewLinear(IROLinearNop); + nw->index = ++IRO_NumLinear; + nw->next = scan->next; + scan->next = nw; + } + break; + case IROLinearFunccall: + if (IRO_FunctionCallMightThrowException(scan)) { + for (action = scan->stmt->dobjstack; action; action = action->prev) { + if (action->type == EAT_CATCHBLOCK || action->type == EAT_SPECIFICATION) { + flag = 1; + goto skip; + } + } + } + break; + case IROLinearAsm: + CodeGen_GetAsmEffects(scan->u.asm_stmt, &effects); + if (effects.numlabels) + flag = 1; + break; + } + if (!flag) + scan = scan->next; + } + + if (scan->type == IROLinearEnd) + IRO_EndNode = IRO_LastNode; + IRO_LastNode->last = scan; + scan = scan->next; + } + + IRO_NodeTable = oalloc(IRO_NumNodes * sizeof(IRONode *)); + memset(IRO_NodeTable, 0, IRO_NumNodes * sizeof(IRONode *)); + for (node = IRO_FirstNode, i = 0; node; node = node->nextnode) + IRO_NodeTable[i++] = node; + + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + IRO_CheckForUserBreak(); +} + +IRONode *IRO_NewFlowGraphNode(void) { + IRONode *node = oalloc(sizeof(IRONode)); + memset(node, 0, sizeof(IRONode)); + node->index = IRO_NumNodes; + IRO_NumNodes++; + node->nextnode = NULL; + return node; +} + +IRONode *IRO_MergeFlowGraphNodes(IRONode *a, IRONode *b) { + IRONode *succ; + Boolean found; + UInt32 i; + UInt32 j; + UInt32 k; + + if (a->nextnode == b && a->last && b->first && a->last->next == b->first) { + if (b->first->type == IROLinearLabel) + IRO_NopOut(b->first); + + a->nextnode = b->nextnode; + a->last = b->last; + + for (i = 0; i < a->numsucc; i++) { + if (b->index == a->succ[i]) { + for (j = i; j < a->numsucc; j++) { + if ((j + 1) < a->numsucc) + a->succ[j] = a->succ[j + 1]; + else + a->succ[j] = 0; + } + a->numsucc--; + break; + } + } + + for (i = 0; i < b->numsucc; i++) { + succ = IRO_NodeTable[b->succ[i]]; + for (j = 0; j < a->numsucc; j++) { + if (b->succ[i] == a->succ[j]) + break; + } + + if (j == a->numsucc) { + AddSucc(a, IRO_NodeTable[b->succ[i]]); + succ->numpred--; + } + + found = 0; + for (j = 0; j < succ->numpred; j++) { + if (a->index == succ->pred[j]) { + found = 1; + break; + } + } + + for (j = 0; j < succ->numpred; j++) { + if (b->index == succ->pred[j]) { + if (!found) { + succ->pred[j] = a->index; + } else { + for (k = j; k < succ->numpred; k++) { + if ((k + 1) < succ->numpred) + succ->pred[k] = succ->pred[k + 1]; + else + succ->pred[k] = 0; + } + succ->numpred--; + } + break; + } + } + } + + b->numsucc = b->numpred = 0; + b->first = b->last = NULL; + b->nextnode = NULL; + b->x36 = 0; + b->x37 = 0; + b->mustreach = 0; + b->x39 = 0; + b->loopdepth = 0; + + if (IRO_LastNode == b) + IRO_LastNode = a; + + if (IRO_FirstExpr && IRO_LastExpr) { + IROExpr *expr; + for (expr = IRO_FirstExpr; expr && expr != IRO_LastExpr->next; expr = expr->next) { + if (expr->node == b) + expr->node = a; + } + } + + if (IRO_FirstAssign && IRO_LastAssign) { + IROAssign *assign; + for (assign = IRO_FirstAssign; assign && assign != IRO_LastAssign->next; assign = assign->next) { + if (assign->node == b) + assign->node = a; + } + } + + if (IRO_FirstVarUse && IRO_LastVarUse) { + IROUse *use; + for (use = IRO_FirstVarUse; use && use != IRO_LastVarUse->globalnext; use = use->globalnext) { + if (use->node == b) + use->node = a; + } + } + + IRO_NodeTable[b->index] = NULL; + return a; + } + + return NULL; +} diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroFlowgraph.h b/compiler_and_linker/FrontEnd/Optimizer/IroFlowgraph.h new file mode 100644 index 0000000..13ddce9 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroFlowgraph.h @@ -0,0 +1,97 @@ +#ifndef COMPILER_IROFLOWGRAPH_H +#define COMPILER_IROFLOWGRAPH_H + +#include "IrOptimizer.h" +#include "BitVector.h" +#include "compiler/CError.h" +#include "compiler/CompilerTools.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +struct IRONode { + UInt16 index; + UInt16 numsucc; + UInt16 *succ; + UInt16 numpred; + UInt16 *pred; + IROLinear *first; + IROLinear *last; + BitVector *x16; // In + BitVector *x1A; // Out + BitVector *x1E; // Gen + BitVector *x22; // Kill + UInt32 x26; + BitVector *x2A; // AA + BitVector *dom; + IRONode *nextnode; + Boolean x36; + Boolean x37; + Boolean mustreach; + Boolean x39; + UInt16 loopdepth; + Boolean x3C; + struct ObjectSet *addressed; + Boolean mustreach1; +}; + +typedef struct IRONodes { + UInt16 *indices; + UInt16 num; + UInt16 base; +} IRONodes; + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +extern UInt16 IRO_NumNodes; +extern IRONode *IRO_FirstNode; +extern IRONode *IRO_LastNode; +extern IRONode *IRO_EndNode; +extern IRONode **IRO_NodeTable; +extern BitVector *IRO_VarKills; +extern BitVector *IRO_Avail; +extern BitVector *IRO_FuncKills; +extern BitVector *IRO_ExprKills; + +extern void IRO_ComputeSuccPred(void); +extern void IRO_ComputeDom(void); +extern void IRO_BuildFlowgraph(IROLinear *linear); +extern IRONode *IRO_NewFlowGraphNode(void); +extern IRONode *IRO_MergeFlowGraphNodes(IRONode *a, IRONode *b); + +CW_INLINE void IROFlowgraph_sub_4C2140(IRONodes *nodes) { + nodes->indices = oalloc(sizeof(UInt16) * IRO_NumNodes); + nodes->num = 0; + nodes->base = 0; +} + +CW_INLINE void IROFlowgraph_sub_4C20E0(IRONodes *nodes) { +} + +CW_INLINE UInt16 IROFlowgraph_sub_4C2040(IRONodes *nodes) { + return nodes->num; +} + +CW_INLINE UInt16 IROFlowgraph_sub_4C2100(IRONodes *nodes) { + UInt16 result = -1; + if (nodes->num) { + result = nodes->indices[nodes->base]; + nodes->base = (nodes->base + 1) % IRO_NumNodes; + nodes->num--; + } + return result; +} + +CW_INLINE void IROFlowgraph_sub_4C3880(IRONodes *nodes, UInt16 index) { + if (nodes->num < IRO_NumNodes) { + nodes->indices[(nodes->base + nodes->num) % IRO_NumNodes] = index; + nodes->num++; + } else { + CError_FATAL(93); + } +} + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroJump.c b/compiler_and_linker/FrontEnd/Optimizer/IroJump.c new file mode 100644 index 0000000..9af248e --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroJump.c @@ -0,0 +1,267 @@ +#include "IroJump.h" +#include "IroDump.h" +#include "IroFlowgraph.h" +#include "IroLinearForm.h" +#include "IroUtil.h" +#include "compiler/CFunc.h" +#include "compiler/Exceptions.h" + +static Boolean CheckChain(CLabel **labelptr) { + IRONode *node; + + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->first && node->first->type == IROLinearLabel && node->first->u.label.label == *labelptr) { + IROLinear *linear; + CLabel *lab; + for (linear = node->first->next, lab = NULL; linear && (linear->type == IROLinearLabel || linear->type == IROLinearNop); linear = linear->next) { + if (linear->type == IROLinearLabel) + lab = linear->u.label.label; + } + + if (linear->type == IROLinearGoto && *labelptr != linear->u.label.label) { + *labelptr = linear->u.label.label; + IRO_Dump("Chaining goto at %d\n", linear->index); + return 1; + } + + if (lab && *labelptr != lab) + *labelptr = lab; + return 0; + } + } + + return 0; +} + +Boolean IRO_DoJumpChaining(void) { + IRONode *node; + IROLinear *linear; + Boolean flag; + SwitchInfo *info; + SwitchCase *curcase; + Boolean result; + + result = 0; + do { + flag = 0; + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->first) { + linear = node->last; + switch (linear->type) { + case IROLinearGoto: + if (CheckChain(&linear->u.label.label)) + flag = 1; + break; + case IROLinearIf: + case IROLinearIfNot: + if (CheckChain(&linear->u.label.label)) + flag = 1; + break; + case IROLinearSwitch: + info = linear->u.swtch.info; + for (curcase = info->cases; curcase; curcase = curcase->next) { + if (CheckChain(&curcase->label)) + flag = 1; + } + if (CheckChain(&info->defaultlabel)) + flag = 1; + break; + } + } + } + result |= flag; + IRO_CheckForUserBreak(); + } while (flag); + + return result; +} + +void IRO_MakeReachable(IRONode *node) { + UInt16 i; + Boolean flag; + + node->x36 = 1; + do { + flag = 0; + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->x36 && !node->x37) { + for (i = 0; i < node->numsucc; i++) { + if (!IRO_NodeTable[node->succ[i]]->x36) { + flag = 1; + IRO_NodeTable[node->succ[i]]->x36 = 1; + } + } + node->x37 = 1; + } + } + } while (flag); +} + +Boolean IRO_RemoveUnreachable(void) { + IRONode *node2; + IRONode *node1; + IROLinear *scan; + IROLinear *linear; + Boolean result; + ExceptionAction **actptr; + ExceptionAction *act; + + result = 0; + IRO_ComputeSuccPred(); + IRO_MakeReachable(IRO_FirstNode); + node1 = IRO_FirstNode; + for (node2 = IRO_FirstNode->nextnode; node2; node2 = node2->nextnode) { + if (node2->first && !node2->x36) { + IRO_Dump("Removing unreachable code at: %d\n", node2->index); + node1->nextnode = node2->nextnode; + node1->last->next = node2->last->next; + result = 1; + for (linear = node2->first; linear && linear->type == IROLinearLabel && linear != node2->last->next; linear = linear->next) { + for (scan = IRO_FirstLinear; scan; scan = scan->next) { + if (scan->stmt) + scan->stmt->marked = 0; + } + + for (scan = IRO_FirstLinear; scan; scan = scan->next) { + if (scan->stmt && !scan->stmt->marked) { + scan->stmt->marked = 1; + for (actptr = &scan->stmt->dobjstack; (act = *actptr); actptr = &act->prev) { + if ( + (act->type == EAT_CATCHBLOCK && act->data.catch_block.catch_label == linear->u.label.label) || + (act->type == EAT_SPECIFICATION && act->data.specification.unexp_label == linear->u.label.label)) { + *actptr = act->prev; + } + } + } + } + } + if (node2 == IRO_LastNode) + IRO_LastNode = node1; + } else { + node1 = node2; + } + } + + if (result) { + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + } + + IRO_CheckForUserBreak(); + return result; +} + +Boolean IRO_RemoveRedundantJumps(void) { + IRONode *node; + IROLinear *linear; + IROLinear *scan; + IROLinear *scan2; + SwitchInfo *info; + SwitchCase *curcase; + Boolean result; + + result = 0; + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->first) { + linear = node->last; + switch (linear->type) { + case IROLinearGoto: + scan = linear->next; + while (scan && ((scan->type == IROLinearNop) || (scan->type == IROLinearLabel && scan->u.label.label != linear->u.label.label))) + scan = scan->next; + while (1) { + if (!scan) break; + if (scan->type != IROLinearLabel) break; + if (scan->u.label.label == linear->u.label.label) { + IRO_Dump("Removing goto next at %d\n", linear->index); + linear->type = IROLinearNop; + result = 1; + break; + } + scan = scan->next; + } + break; + + case IROLinearIf: + case IROLinearIfNot: + scan = linear->next; + while (scan && scan->type == IROLinearNop) + scan = scan->next; + if (scan && scan->type == IROLinearGoto) { + scan2 = scan->next; + while (scan2 && ((scan2->type == IROLinearNop) || (scan2->type == IROLinearLabel && scan2->u.label.label != linear->u.label.label))) + scan2 = scan2->next; + + if (scan2 && scan2->type == IROLinearLabel && scan2->u.label.label == linear->u.label.label) { + if (linear->type == IROLinearIf) + linear->type = IROLinearIfNot; + else + linear->type = IROLinearIf; + + linear->u.label.label = scan->u.label.label; + scan->type = IROLinearNop; + IRO_Dump("Removing branch around goto at %d\n", linear->index); + result = 1; + } + } + + scan2 = linear->next; + while (scan2 && ((scan2->type == IROLinearNop) || (scan2->type == IROLinearLabel && scan2->u.label.label != linear->u.label.label))) + scan2 = scan2->next; + while (1) { + if (!scan2) break; + if (scan2->type != IROLinearLabel) break; + if (scan2->u.label.label == linear->u.label.label) { + IRO_Dump("Removing If/IfNot_Goto next at %d\n", linear->index); + linear->type = IROLinearNop; + IRO_CheckSideEffect(linear->u.label.x4); + result = 1; + break; + } + scan2 = scan2->next; + } + break; + + case IROLinearSwitch: + info = linear->u.swtch.info; + curcase = info->cases; + while (curcase && curcase->label == info->defaultlabel) + curcase = curcase->next; + if (!curcase) { + IRO_Dump("Removing Switch next at %d\n", linear->index); + IRO_CheckSideEffect(linear->u.swtch.x4); + linear->type = IROLinearGoto; + linear->u.label.label = info->defaultlabel; + result = 1; + } + break; + } + } + } + + if (result) { + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + } + + IRO_CheckForUserBreak(); + return result; +} + +Boolean IRO_RemoveLabels(void) { + Boolean result; + IRONode *node; + + result = 0; + IRO_ComputeSuccPred(); + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->first && node->first->type == IROLinearLabel && !node->x39) { + node->first->type = IROLinearNop; + node->first->flags &= ~IROLF_1; + result = 1; + } + } + + IRO_CheckForUserBreak(); + return result; +} diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroJump.h b/compiler_and_linker/FrontEnd/Optimizer/IroJump.h new file mode 100644 index 0000000..62b7be6 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroJump.h @@ -0,0 +1,12 @@ +#ifndef COMPILER_IROJUMP_H +#define COMPILER_IROJUMP_H + +#include "IrOptimizer.h" + +extern Boolean IRO_DoJumpChaining(void); +extern void IRO_MakeReachable(IRONode *node); +extern Boolean IRO_RemoveUnreachable(void); +extern Boolean IRO_RemoveRedundantJumps(void); +extern Boolean IRO_RemoveLabels(void); + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.c b/compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.c new file mode 100644 index 0000000..8c5b0d8 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.c @@ -0,0 +1,1797 @@ +#include "IroLinearForm.h" +#include "IroDump.h" +#include "IroFlowgraph.h" +#include "IroUtil.h" +#include "IroVars.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CParser.h" +#include "compiler/CompilerTools.h" +#include "compiler/InlineAsm.h" +#include "compiler/InlineAsmPPC.h" +#include "compiler/types.h" + +typedef struct NullCheckListNode { + SInt32 precompid; + Object *tempobj; + struct NullCheckListNode *next; +} NullCheckListNode; + +IROLinear *IRO_FirstLinear; +IROLinear *IRO_LastLinear; +UInt32 IRO_NumLinear; +Statement *CurStat; +static NullCheckListNode *NullCheckList; +static Statement *CurrStmt; +static Statement *PrevStmt; + +static void LinkLinear(IROLinear *linear) { + linear->index = IRO_NumLinear++; + if (IRO_FirstLinear) + IRO_LastLinear->next = linear; + else + IRO_FirstLinear = linear; + IRO_LastLinear = linear; +} + +IROLinear *IRO_NewLinear(IROLinearType type) { + IROLinear *linear = oalloc(sizeof(IROLinear)); + memset(linear, 0, sizeof(IROLinear)); + linear->stmt = CurStat; + linear->nodetype = EPOSTINC; + linear->next = NULL; + linear->type = type; + linear->rtype = NULL; + linear->flags = 0; + linear->nodeflags = 0; + linear->expr = NULL; + linear->x16 = 0; + return linear; +} + +static void MarkAssigned(IROLinear *linear, Boolean flag) { + IROLinear *inner; + IROAddrRecord *rec; + + if (IS_LINEAR_MONADIC(linear, EINDIRECT) && IS_LINEAR_MONADIC(linear->u.monadic, EBITFIELD)) { + linear->flags |= IROLF_Assigned; + inner = linear->u.monadic->u.monadic; + if (inner->type == IROLinearOperand) { + inner->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + inner->flags |= IROLF_Used; + } + } + + if (IS_LINEAR_DIADIC(inner, EADD)) { + if (IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) { + if (IS_LINEAR_ENODE(inner->u.diadic.right, EINTCONST)) + inner->u.diadic.left->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + inner->u.diadic.left->flags |= IROLF_Used; + } + } + + rec = IRO_InitAddrRecordPointer(inner); + IRO_DecomposeAddressExpression(inner, rec); + if (rec->numObjRefs == 1 && IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) { + ((IROLinear *) rec->objRefs->element)->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + ((IROLinear *) rec->objRefs->element)->flags |= IROLF_Used; + } + } + } + } + + if (IS_LINEAR_MONADIC(linear, EINDIRECT)) { + linear->flags |= IROLF_Assigned; + if (linear->u.monadic->type == IROLinearOperand) { + linear->u.monadic->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + linear->u.monadic->flags |= IROLF_Used; + } + } + } + + if (IS_LINEAR_MONADIC(linear, EINDIRECT)) { + linear->flags |= IROLF_Assigned; + inner = linear->u.monadic; + + if (IS_LINEAR_DIADIC(inner, EADD)) { + if (IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) { + if (IS_LINEAR_ENODE(inner->u.diadic.right, EINTCONST)) + inner->u.diadic.left->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + inner->u.diadic.left->flags |= IROLF_Used; + } + } + + rec = IRO_InitAddrRecordPointer(inner); + IRO_DecomposeAddressExpression(inner, rec); + if (rec->numObjRefs == 1 && IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) { + ((IROLinear *) rec->objRefs->element)->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + ((IROLinear *) rec->objRefs->element)->flags |= IROLF_Used; + } + } + } + } +} + +static void MarkSubscript(IROLinear *linear) { + linear->flags |= IROLF_Subs; + if (IS_LINEAR_DIADIC(linear, EADD)) { + if (IRO_IsAddressMultiply(linear->u.diadic.left) || IS_LINEAR_MONADIC(linear->u.diadic.left, EINDIRECT)) + linear->u.diadic.left->flags |= IROLF_Subs; + if (IRO_IsAddressMultiply(linear->u.diadic.right) || IS_LINEAR_MONADIC(linear->u.diadic.right, EINDIRECT)) + linear->u.diadic.right->flags |= IROLF_Subs; + + if (IS_LINEAR_DIADIC(linear->u.diadic.left, EADD)) + MarkSubscript(linear->u.diadic.left); + if (IS_LINEAR_DIADIC(linear->u.diadic.right, EADD)) + MarkSubscript(linear->u.diadic.right); + } +} + +static void MarkArgs(IROLinear *linear) { + int i; + linear->flags |= IROLF_4000; + + switch (linear->type) { + case IROLinearEnd: + break; + case IROLinearOp1Arg: + case IROLinearBeginCatch: + case IROLinearEndCatch: + case IROLinearEndCatchDtor: + MarkArgs(linear->u.monadic); + break; + case IROLinearOp2Arg: + MarkArgs(linear->u.diadic.left); + MarkArgs(linear->u.diadic.right); + break; + case IROLinearIf: + case IROLinearIfNot: + MarkArgs(linear->u.label.x4); + break; + case IROLinearReturn: + if (linear->u.monadic) + MarkArgs(linear->u.monadic); + break; + case IROLinearSwitch: + MarkArgs(linear->u.swtch.x4); + break; + case IROLinearOp3Arg: + MarkArgs(linear->u.args3.a); + MarkArgs(linear->u.args3.b); + MarkArgs(linear->u.args3.c); + break; + case IROLinearFunccall: + MarkArgs(linear->u.funccall.linear8); + for (i = 0; i < linear->u.funccall.argCount; i++) + MarkArgs(linear->u.funccall.args[i]); + break; + } +} + +// assumed name, position +CW_INLINE void MarkSubExpr(IROLinear *linear) { + int i; + + switch (linear->type) { + case IROLinearNop: + case IROLinearOperand: + case IROLinearGoto: + case IROLinearLabel: + case IROLinearEntry: + case IROLinearExit: + case IROLinearAsm: + case IROLinearEnd: + break; + case IROLinearOp1Arg: + case IROLinearBeginCatch: + case IROLinearEndCatch: + case IROLinearEndCatchDtor: + linear->u.monadic->flags |= IROLF_Reffed; + break; + case IROLinearOp2Arg: + linear->u.diadic.left->flags |= IROLF_Reffed; + linear->u.diadic.right->flags |= IROLF_Reffed; + break; + case IROLinearIf: + case IROLinearIfNot: + linear->u.label.x4->flags |= IROLF_Reffed; + break; + case IROLinearReturn: + if (linear->u.monadic) + linear->u.monadic->flags |= IROLF_Reffed; + break; + case IROLinearSwitch: + linear->u.swtch.x4->flags |= IROLF_Reffed; + break; + case IROLinearOp3Arg: + linear->u.args3.a->flags |= IROLF_Reffed; + linear->u.args3.b->flags |= IROLF_Reffed; + linear->u.args3.c->flags |= IROLF_Reffed; + break; + case IROLinearFunccall: + linear->u.funccall.linear8->flags |= IROLF_Reffed; + for (i = 0; i < linear->u.funccall.argCount; i++) + linear->u.funccall.args[i]->flags |= IROLF_Reffed; + break; + default: + CError_FATAL(368); + } +} + +static void MarkSubs1(IROLinear *linear) { + IROAddrRecord *rec; + + if (IS_LINEAR_MONADIC(linear, EBITFIELD)) { + linear = linear->u.monadic; + if (IS_LINEAR_ENODE(linear, EOBJREF)) + linear->flags |= IROLF_Ind; + } + + if (IS_LINEAR_DIADIC(linear, EADD)) { + if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF) && IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) + linear->u.diadic.left->flags |= IROLF_Ind; + + rec = IRO_InitAddrRecordPointer(linear); + IRO_DecomposeAddressExpression(linear, rec); + if (rec->numObjRefs == 1 && IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF)) + ((IROLinear *) rec->objRefs->element)->flags |= IROLF_Ind; + } +} + +static void MakeLeftChildAsAssignment(ENode *enode) { + Statement *stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = enode->data.diadic.left; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void AssignCommaRToTemp(ENode *enode, Boolean flag) { + Statement *stmt; + + if (!IS_TYPE_VOID(enode->rtype) && !flag) { + Object *obj = create_temp_object(enode->rtype); + ENode *indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(obj); + + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + CError_FATAL(548); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.diadic.right; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + enode->type = EINDIRECT; + enode->data.monadic = create_objectrefnode(obj); + CError_ASSERT(580, !IS_TYPE_VOID(enode->rtype)); + } else { + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = enode->data.diadic.right; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + enode->type = EINTCONST; + enode->data.intval = cint64_zero; + } +} + +static void AssignDangerousArgumentToTemp(ENode *enode) { + Statement *stmt; + Object *obj; + ENode *indnode; + ENode *rightnode; + + obj = create_temp_object(enode->rtype); + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(obj); + + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + CError_FATAL(627); + + rightnode = IRO_NewENode(enode->type); + memcpy(rightnode, enode, sizeof(ENode)); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = rightnode; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + enode->type = EINDIRECT; + enode->data.monadic = create_objectrefnode(obj); +} + +static void CreateTempAssignmentToZero(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + ENode *rightnode; + + *objptr = create_temp_object(enode->rtype); + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + CError_FATAL(678); + + rightnode = IRO_NewENode(EINTCONST); + rightnode->data.intval = cint64_zero; + rightnode->rtype = enode->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = rightnode; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void CreateTempAssignmentToOne(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + ENode *rightnode; + + *objptr = create_temp_object(enode->rtype); + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + CError_FATAL(720); + + rightnode = IRO_NewENode(EINTCONST); + rightnode->data.intval = cint64_one; + rightnode->rtype = enode->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = rightnode; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateCondExpression(ENode *enode, CLabel **label) { + Statement *stmt; + + *label = IRO_NewLabel(); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFNGOTO; + stmt->expr = enode->data.cond.cond; + stmt->label = *label; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateGoToStmt(ENode *enode, CLabel **label) { + Statement *stmt; + + *label = IRO_NewLabel(); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_GOTO; + stmt->label = *label; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void PutTempOnNullCheckList(ENode *expr, Object *obj) { + NullCheckListNode *n = lalloc(sizeof(NullCheckListNode)); + n->precompid = expr->data.nullcheck.precompid; + n->tempobj = obj; + n->next = NULL; + if (NullCheckList) { + n->next = NullCheckList; + NullCheckList = n; + } else { + NullCheckList = n; + } +} + +static Object *GetTempFromtheList(ENode *expr) { + NullCheckListNode *n; + + for (n = NullCheckList; n; n = n->next) { + if (n->precompid == expr->data.precompid) + break; + } + + CError_ASSERT(839, n); + return n->tempobj; +} + +static void GenerateNullcheckExprTempAssignment(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + + if (!IS_TYPE_VOID(enode->rtype)) + *objptr = create_temp_object(enode->rtype); + else + *objptr = create_temp_object(enode->data.nullcheck.nullcheckexpr->rtype); + + PutTempOnNullCheckList(enode, *objptr); + + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + indnode->rtype = enode->data.nullcheck.nullcheckexpr->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.nullcheck.nullcheckexpr; + if (!IS_TYPE_VOID(enode->rtype)) + stmt->expr->rtype = enode->rtype; + else + stmt->expr->rtype = enode->data.nullcheck.nullcheckexpr->rtype; + + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateExpr1TempAssignment(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + + if (!IS_TYPE_VOID(enode->rtype)) { + *objptr = create_temp_object(enode->rtype); + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + indnode->rtype = enode->rtype; + CError_ASSERT(905, !IS_TYPE_VOID(enode->rtype)); + } + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + if (!IS_TYPE_VOID(enode->rtype)) { + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.cond.expr1; + stmt->expr->rtype = enode->rtype; + } else { + stmt->expr = enode->data.cond.expr1; + } + + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateExpr2TempAssignment(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + + if (!IS_TYPE_VOID(enode->rtype)) { + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + indnode->rtype = enode->rtype; + CError_ASSERT(953, !IS_TYPE_VOID(enode->rtype)); + } + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + if (!IS_TYPE_VOID(enode->rtype)) { + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.cond.expr2; + stmt->expr->rtype = enode->rtype; + } else { + stmt->expr = enode->data.cond.expr2; + } + + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateForceLoadTempAssignment(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + + if (!IS_TYPE_VOID(enode->rtype)) { + *objptr = create_temp_object(enode->rtype); + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + indnode->rtype = enode->rtype; + CError_ASSERT(1003, !IS_TYPE_VOID(enode->rtype)); + } + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + if (!IS_TYPE_VOID(enode->rtype)) { + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.monadic; + stmt->expr->rtype = enode->rtype; + } else { + stmt->expr = enode->data.monadic; + } + + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateLabel(CLabel **labelptr) { + Statement *stmt; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_LABEL; + stmt->label = *labelptr; + stmt->label->stmt = stmt; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateIfNotTemp(ENode *enode, Object **objptr, CLabel **labelptr) { + Statement *stmt; + ENode *indnode; + + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + indnode->rtype = enode->data.monadic->rtype; + + *labelptr = IRO_NewLabel(); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFNGOTO; + stmt->expr = indnode; + stmt->label = *labelptr; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateNullcheckCondExpr(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + indnode->rtype = enode->data.nullcheck.nullcheckexpr->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.nullcheck.condexpr; + if (!IS_TYPE_VOID(enode->rtype)) + stmt->expr->rtype = enode->rtype; + else + stmt->expr->rtype = enode->data.nullcheck.nullcheckexpr->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void TransformLogicalAndLHS(ENode *enode, Object **objptr, CLabel **labelptr) { + Statement *stmt; + + *labelptr = IRO_NewLabel(); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFNGOTO; + stmt->expr = enode->data.diadic.left; + stmt->label = *labelptr; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void TransformLogicalAndRHS(ENode *enode, Object **objptr, CLabel **labelptr) { + Statement *stmt; + ENode *indnode; + ENode *rightnode; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFNGOTO; + stmt->expr = enode->data.diadic.right; + stmt->label = *labelptr; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + CError_FATAL(1225); + + rightnode = IRO_NewENode(EINTCONST); + rightnode->data.intval = cint64_one; + rightnode->rtype = enode->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = rightnode; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_LABEL; + stmt->label = *labelptr; + stmt->label->stmt = stmt; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + enode->type = EINDIRECT; + enode->data.monadic = create_objectrefnode(*objptr); + CError_ASSERT(1276, !IS_TYPE_VOID(enode->rtype)); +} + +static void TransformLogicalOrLHS(ENode *enode, Object **objptr, CLabel **labelptr) { + Statement *stmt; + + *labelptr = IRO_NewLabel(); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFGOTO; + stmt->expr = enode->data.diadic.left; + stmt->label = *labelptr; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void TransformLogicalOrRHS(ENode *enode, Object **objptr, CLabel **labelptr) { + Statement *stmt; + ENode *indnode; + ENode *rightnode; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFGOTO; + stmt->expr = enode->data.diadic.right; + stmt->label = *labelptr; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + CError_FATAL(1354); + + rightnode = IRO_NewENode(EINTCONST); + rightnode->data.intval = cint64_zero; + rightnode->rtype = enode->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = rightnode; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_LABEL; + stmt->label = *labelptr; + stmt->label->stmt = stmt; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + enode->type = EINDIRECT; + enode->data.monadic = create_objectrefnode(*objptr); + CError_ASSERT(1405, !IS_TYPE_VOID(enode->rtype)); +} + +static void LinearizeExpr1(ENode *a, ENode *b, Boolean flag, Boolean flag2) { + switch (a->type) { + ENODE_CASE_MONADIC: + LinearizeExpr1(a->data.monadic, a, 0, 0); + if (a->type == EFORCELOAD) { + Object *obj; + GenerateForceLoadTempAssignment(a, &obj); + a->type = EINDIRECT; + a->data.monadic = create_objectrefnode(obj); + CError_ASSERT(1428, !IS_TYPE_VOID(a->rtype)); + } + break; + ENODE_CASE_DIADIC_1: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBTST: + if (a->type == ECOMMA) { + LinearizeExpr1(a->data.diadic.left, a, 1, 0); + MakeLeftChildAsAssignment(a); + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + AssignCommaRToTemp(a, flag); + } else if (a->data.diadic.right->cost >= a->data.diadic.left->cost) { + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + LinearizeExpr1(a->data.diadic.left, a, 0, 0); + } else { + LinearizeExpr1(a->data.diadic.left, a, 0, 0); + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + } + break; + ENODE_CASE_ASSIGN: + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + LinearizeExpr1(a->data.diadic.left, a, 0, 0); + break; + case ELAND: + case ELOR: + if (a->type == ELAND) { + CLabel *label; + Object *obj; + CreateTempAssignmentToZero(a, &obj); + LinearizeExpr1(a->data.diadic.left, a, 0, 0); + TransformLogicalAndLHS(a, &obj, &label); + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + TransformLogicalAndRHS(a, &obj, &label); + } else if (a->type == ELOR) { + CLabel *label; + Object *obj; + CreateTempAssignmentToOne(a, &obj); + LinearizeExpr1(a->data.diadic.left, a, 0, 0); + TransformLogicalOrLHS(a, &obj, &label); + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + TransformLogicalOrRHS(a, &obj, &label); + } + break; + case ECOND: { + CLabel *label1, *label2; + Object *obj; + LinearizeExpr1(a->data.cond.cond, a, 0, 0); + GenerateCondExpression(a, &label1); + LinearizeExpr1(a->data.cond.expr1, a, 0, 0); + GenerateExpr1TempAssignment(a, &obj); + GenerateGoToStmt(a, &label2); + GenerateLabel(&label1); + LinearizeExpr1(a->data.cond.expr2, a, 0, 0); + GenerateExpr2TempAssignment(a, &obj); + GenerateLabel(&label2); + if (!IS_TYPE_VOID(a->rtype)) { + a->type = EINDIRECT; + a->data.monadic = create_objectrefnode(obj); + CError_ASSERT(1596, !IS_TYPE_VOID(a->rtype)); + } else { + a->type = EINTCONST; + a->data.intval = cint64_zero; + } + break; + } + case EPRECOMP: { + Object *temp = GetTempFromtheList(a); + a->type = EINDIRECT; + a->data.monadic = create_objectrefnode(temp); + CError_ASSERT(1614, !IS_TYPE_VOID(a->rtype)); + break; + } + case ENULLCHECK: { + CLabel *label; + Object *obj; + LinearizeExpr1(a->data.nullcheck.nullcheckexpr, a, 0, 0); + GenerateNullcheckExprTempAssignment(a, &obj); + GenerateIfNotTemp(a, &obj, &label); + LinearizeExpr1(a->data.nullcheck.condexpr, a, 0, 0); + GenerateNullcheckCondExpr(a, &obj); + GenerateLabel(&label); + if (!IS_TYPE_VOID(a->rtype)) { + a->type = EINDIRECT; + a->data.monadic = create_objectrefnode(obj); + CError_ASSERT(1639, !IS_TYPE_VOID(a->rtype)); + } else { + a->type = EINTCONST; + a->data.intval = cint64_zero; + } + break; + } + case EFUNCCALL: + case EFUNCCALLP: { + SInt32 count; + SInt32 i; + ENodeList *list; + ENode **arr; + SInt16 *arr2; + + IRO_IsLeafFunction = 0; + + list = a->data.funccall.args; + count = 0; + while (list) { + list = list->next; + count++; + } + + if (count) { + arr = oalloc(sizeof(ENode *) * count); + list = a->data.funccall.args; + count = 0; + while (list) { + arr[count] = list->node; + list = list->next; + count++; + } + + arr2 = oalloc(sizeof(SInt16) * count); + for (i = 0; i < count; i++) + arr2[i] = count - i - 1; + + for (i = 0; i < count; i++) + LinearizeExpr1(arr[arr2[i]], a, 0, 0); + } + + LinearizeExpr1(a->data.funccall.funcref, a, 0, 0); + break; + } + + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case ESETCONST: + case EVECTOR128CONST: + break; + + default: + CError_FATAL(1723); + } +} + +static IROLinear *LinearizeExpr(ENode *enode) { + IROLinear *linear = NULL; + + switch (enode->type) { + ENODE_CASE_MONADIC: + linear = IRO_NewLinear(IROLinearOp1Arg); + linear->u.monadic = LinearizeExpr(enode->data.monadic); + linear->nodetype = enode->type; + linear->rtype = enode->rtype; + linear->nodeflags = enode->flags; + if (IRO_IsAssignOp[linear->nodetype]) + MarkAssigned(linear->u.monadic, 1); + if (linear->nodetype == EINDIRECT) { + MarkSubs1(linear->u.monadic); + linear->u.monadic->flags |= IROLF_Immind | IROLF_Ind; + if (IS_LINEAR_DIADIC(linear->u.monadic, EADD)) + MarkSubscript(linear->u.monadic); + } + break; + ENODE_CASE_DIADIC_1: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBTST: + linear = IRO_NewLinear(IROLinearOp2Arg); + linear->nodeflags = enode->flags; + if (!ENODE_IS(enode, ECOMMA) && enode->data.diadic.right->cost >= enode->data.diadic.left->cost) { + linear->u.diadic.right = LinearizeExpr(enode->data.diadic.right); + linear->u.diadic.left = LinearizeExpr(enode->data.diadic.left); + linear->flags |= IROLF_8000; + } else { + linear->u.diadic.left = LinearizeExpr(enode->data.diadic.left); + linear->u.diadic.right = LinearizeExpr(enode->data.diadic.right); + } + linear->nodetype = enode->type; + linear->rtype = enode->rtype; + if (IRO_IsAssignOp[linear->nodetype]) + MarkAssigned(linear->u.diadic.left, IRO_IsModifyOp[linear->nodetype]); + break; + ENODE_CASE_ASSIGN: + linear = IRO_NewLinear(IROLinearOp2Arg); + linear->nodeflags = enode->flags; + linear->u.diadic.right = LinearizeExpr(enode->data.diadic.right); + linear->u.diadic.left = LinearizeExpr(enode->data.diadic.left); + linear->flags |= IROLF_8000; + linear->nodetype = enode->type; + linear->rtype = enode->rtype; + MarkAssigned(linear->u.diadic.left, IRO_IsModifyOp[linear->nodetype]); + break; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EVECTOR128CONST: + linear = IRO_NewLinear(IROLinearOperand); + linear->nodeflags = enode->flags; + linear->u.node = enode; + linear->rtype = enode->rtype; + break; + case EFUNCCALL: + case EFUNCCALLP: { + SInt32 count; + SInt32 i; + ENodeList *list; + ENode **arr; + SInt16 *arr2; + + linear = IRO_NewLinear(IROLinearFunccall); + linear->nodeflags = enode->flags; + linear->u.funccall.ispascal = enode->type == EFUNCCALLP; + + list = enode->data.funccall.args; + count = 0; + while (list) { + list = list->next; + count++; + } + + arr = NULL; + if (count) { + arr = oalloc(sizeof(ENode *) * count); + list = enode->data.funccall.args; + count = 0; + while (list) { + arr[count] = list->node; + list = list->next; + count++; + } + + arr2 = oalloc(sizeof(SInt16) * count); + for (i = 0; i < count; i++) + arr2[i] = count - i - 1; + + for (i = 0; i < count; i++) { + arr[arr2[i]] = (ENode *) LinearizeExpr(arr[arr2[i]]); + MarkArgs((IROLinear *) arr[arr2[i]]); + } + } + + linear->u.funccall.argCount = count; + linear->u.funccall.args = (IROLinear **) arr; + linear->u.funccall.linear8 = LinearizeExpr(enode->data.funccall.funcref); + linear->u.funccall.functype = enode->data.funccall.functype; + linear->rtype = enode->rtype; + break; + } + default: + CError_FATAL(1943); + } + + if (linear) + LinkLinear(linear); + return linear; +} + +void IRO_PreLinearize(Statement *stmt) { + IRO_FirstLinear = IRO_LastLinear = NULL; + IRO_NumLinear = 0; + CurrStmt = PrevStmt = NULL; + + while (stmt) { + CurStat = stmt; + CurrStmt = stmt; + NullCheckList = NULL; + + switch (stmt->type) { + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + break; + case ST_OVF: + CError_FATAL(1989); + case ST_EXPRESSION: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_SWITCH: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_IFGOTO: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_IFNGOTO: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_RETURN: + if (stmt->expr) + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_BEGINCATCH: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_ENDCATCH: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_ENDCATCHDTOR: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + + case ST_EXIT: + case ST_ENTRY: + case ST_ASM: + break; + + default: + CError_FATAL(2038); + } + + PrevStmt = stmt; + stmt = stmt->next; + } + + IRO_CheckForUserBreak(); +} + +static void MarkAllSubExprs(IROLinear *linear) { + IROLinear *scan; + int i; + + for (scan = linear; scan; scan = scan->next) + scan->flags &= ~IROLF_Reffed; + + for (scan = linear; scan; scan = scan->next) + MarkSubExpr(scan); +} + +void IRO_Linearize(Statement *stmt) { + IROLinear *linear; + + IRO_FirstLinear = IRO_LastLinear = NULL; + IRO_NumLinear = 0; + + while (stmt) { + CurStat = stmt; + linear = NULL; + + switch (stmt->type) { + case ST_NOP: + linear = IRO_NewLinear(IROLinearNop); + break; + case ST_LABEL: + linear = IRO_NewLinear(IROLinearLabel); + linear->u.label.label = stmt->label; + linear->flags |= IROLF_1; + break; + case ST_GOTO: + linear = IRO_NewLinear(IROLinearGoto); + linear->u.label.label = stmt->label; + break; + case ST_EXPRESSION: + LinearizeExpr(stmt->expr); + break; + case ST_SWITCH: + linear = IRO_NewLinear(IROLinearSwitch); + linear->u.swtch.x4 = LinearizeExpr(stmt->expr); + linear->u.swtch.info = (SwitchInfo *) stmt->label; + break; + case ST_IFGOTO: + linear = IRO_NewLinear(IROLinearIf); + linear->u.label.x4 = LinearizeExpr(stmt->expr); + linear->u.label.label = stmt->label; + break; + case ST_IFNGOTO: + linear = IRO_NewLinear(IROLinearIfNot); + linear->u.label.x4 = LinearizeExpr(stmt->expr); + linear->u.label.label = stmt->label; + break; + case ST_RETURN: + IRO_FunctionHasReturn = 1; + linear = IRO_NewLinear(IROLinearReturn); + if (stmt->expr) + linear->u.monadic = LinearizeExpr(stmt->expr); + else + linear->u.monadic = NULL; + break; + case ST_OVF: + CError_FATAL(2143); + break; + case ST_EXIT: + linear = IRO_NewLinear(IROLinearExit); + linear->u.label.label = stmt->label; + break; + case ST_ENTRY: + linear = IRO_NewLinear(IROLinearEntry); + linear->u.label.label = stmt->label; + linear->flags |= IROLF_1; + break; + case ST_BEGINCATCH: + linear = IRO_NewLinear(IROLinearBeginCatch); + linear->u.ctch.linear = LinearizeExpr(stmt->expr); + linear->u.ctch.x4 = 0; + linear->u.ctch.x8 = 0; + break; + case ST_ENDCATCH: + linear = IRO_NewLinear(IROLinearEndCatch); + linear->u.monadic = LinearizeExpr(stmt->expr); + break; + case ST_ENDCATCHDTOR: + linear = IRO_NewLinear(IROLinearEndCatchDtor); + linear->u.monadic = LinearizeExpr(stmt->expr); + break; + case ST_ASM: + linear = IRO_NewLinear(IROLinearAsm); + linear->u.asm_stmt = stmt; + if (copts.optimizewithasm) { + IAEffects effects; + CodeGen_GetAsmEffects(stmt, &effects); + if (effects.x0 || effects.x3) + DisableDueToAsm = 1; + } else { + DisableDueToAsm = 1; + } + break; + default: + CError_FATAL(2194); + } + + if (linear) + LinkLinear(linear); + stmt = stmt->next; + } + + linear = IRO_NewLinear(IROLinearEnd); + linear->flags |= IROLF_1; + LinkLinear(linear); + + MarkAllSubExprs(IRO_FirstLinear); + IRO_CheckForUserBreak(); +} + +static Statement *NewStatement(IROLinear *linear, StatementType sttype) { + Statement *stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = sttype; + stmt->value = 1; + if (linear->stmt) { + stmt->dobjstack = linear->stmt->dobjstack; + stmt->sourceoffset = linear->stmt->sourceoffset; + stmt->sourcefilepath = linear->stmt->sourcefilepath; + stmt->value = linear->stmt->value; + stmt->flags = linear->stmt->flags; + } else { + stmt->sourceoffset = -1; + stmt->sourcefilepath = NULL; + } + return stmt; +} + +ENode *IRO_NewENode(ENodeType nodetype) { + ENode *enode = lalloc(sizeof(ENode)); + memset(enode, 0, sizeof(ENode)); + enode->type = nodetype; + return enode; +} + +static ENode *BuildExpr(IROLinear *linear) { + ENode *enode; + + switch (linear->type) { + case IROLinearOperand: + enode = IRO_NewENode(linear->u.node->type); + enode->flags = linear->nodeflags; + *enode = *linear->u.node; + break; + case IROLinearOp1Arg: + enode = IRO_NewENode(linear->nodetype); + enode->flags = linear->nodeflags; + enode->data.monadic = BuildExpr(linear->u.monadic); + enode->rtype = linear->rtype; + enode->cost = enode->data.monadic->cost; + if (!enode->cost) + enode->cost = 1; + break; + case IROLinearOp2Arg: + enode = IRO_NewENode(linear->nodetype); + enode->flags = linear->nodeflags; + enode->data.diadic.left = BuildExpr(linear->u.diadic.left); + enode->data.diadic.right = BuildExpr(linear->u.diadic.right); + + enode->cost = enode->data.diadic.left->cost; + if (enode->data.diadic.right->cost > enode->cost) + enode->cost = enode->data.diadic.right->cost; + else if (enode->data.diadic.right->cost == enode->cost) + enode->cost += 1; + + if (ENODE_IS4(enode, ESHL, ESHR, EDIV, EMODULO)) + enode->cost += 2; + if (enode->cost > 200) + enode->cost = 200; + + enode->rtype = linear->rtype; + break; + case IROLinearOp3Arg: + enode = IRO_NewENode(linear->nodetype); + enode->flags = linear->nodeflags; + enode->data.cond.cond = BuildExpr(linear->u.args3.a); + enode->data.cond.expr1 = BuildExpr(linear->u.args3.b); + enode->data.cond.expr2 = BuildExpr(linear->u.args3.c); + enode->rtype = linear->rtype; + + enode->cost = enode->data.cond.cond->cost; + if (enode->data.cond.expr1->cost > enode->cost) + enode->cost = enode->data.cond.expr1->cost; + if (enode->data.cond.expr2->cost > enode->cost) + enode->cost = enode->data.cond.expr2->cost; + enode->cost += 1; + + if (enode->cost > 200) + enode->cost = 200; + + break; + + case IROLinearFunccall: { + int i; + enode = IRO_NewENode(linear->u.funccall.ispascal ? EFUNCCALLP : EFUNCCALL); + enode->flags = linear->nodeflags; + enode->data.funccall.funcref = BuildExpr(linear->u.funccall.linear8); + enode->data.funccall.functype = linear->u.funccall.functype; + enode->data.funccall.args = NULL; + enode->cost = 200; + for (i = linear->u.funccall.argCount - 1; i >= 0; i--) { + ENodeList *list = lalloc(sizeof(ENodeList)); + list->node = BuildExpr(linear->u.funccall.args[i]); + list->next = enode->data.funccall.args; + enode->data.funccall.args = list; + } + enode->rtype = linear->rtype; + break; + } + + default: + IRO_Dump("Oh, oh, bad expression type in BuildExpr at: %d\n", linear->index); + CError_FATAL(2390); + } + + enode->pointsTo = linear->pointsToFunction; + return enode; +} + +Statement *IRO_Delinearize(IRONode *node, IROLinear *linear) { + IROLinear *scanlin; + Statement *firstStmt; + Statement *lastStmt; + IRONode *scan; + Statement *stmt; + IRONode mynode; + + firstStmt = lastStmt = NULL; + + if (node) { + scan = node; + MarkAllSubExprs(IRO_FirstLinear); + } else { + memset(&mynode, 0, sizeof(IRONode)); + mynode.first = linear; + scan = &mynode; + MarkAllSubExprs(linear); + } + + while (scan) { + for (scanlin = scan->first; scanlin; scanlin = scanlin->next) { + stmt = NULL; + if (!(scanlin->flags & IROLF_Reffed)) { + switch (scanlin->type) { + case IROLinearNop: + if (scan == node) + stmt = NewStatement(scanlin, ST_NOP); + else + stmt = NULL; + break; + case IROLinearOperand: + case IROLinearOp1Arg: + case IROLinearOp2Arg: + case IROLinearOp3Arg: + case IROLinearFunccall: + stmt = NewStatement(scanlin, ST_EXPRESSION); + stmt->expr = BuildExpr(scanlin); + break; + case IROLinearGoto: + stmt = NewStatement(scanlin, ST_GOTO); + stmt->label = scanlin->u.label.label; + break; + case IROLinearExit: + stmt = NewStatement(scanlin, ST_EXIT); + stmt->label = scanlin->u.label.label; + break; + case IROLinearIf: + case IROLinearIfNot: + stmt = NewStatement(scanlin, (scanlin->type == IROLinearIf) ? ST_IFGOTO : ST_IFNGOTO); + stmt->label = scanlin->u.label.label; + stmt->expr = BuildExpr(scanlin->u.label.x4); + break; + case IROLinearReturn: + stmt = NewStatement(scanlin, ST_RETURN); + if (scanlin->u.monadic) + stmt->expr = BuildExpr(scanlin->u.monadic); + break; + case IROLinearLabel: + stmt = NewStatement(scanlin, ST_LABEL); + stmt->label = scanlin->u.label.label; + stmt->label->stmt = stmt; + break; + case IROLinearEntry: + stmt = NewStatement(scanlin, ST_ENTRY); + stmt->label = scanlin->u.label.label; + stmt->label->stmt = stmt; + break; + case IROLinearSwitch: + stmt = NewStatement(scanlin, ST_SWITCH); + stmt->expr = BuildExpr(scanlin->u.swtch.x4); + stmt->label = (CLabel *) scanlin->u.swtch.info; + break; + case IROLinearBeginCatch: + stmt = NewStatement(scanlin, ST_BEGINCATCH); + stmt->expr = BuildExpr(scanlin->u.ctch.linear); + break; + case IROLinearEndCatch: + stmt = NewStatement(scanlin, ST_ENDCATCH); + stmt->expr = BuildExpr(scanlin->u.monadic); + break; + case IROLinearEndCatchDtor: + stmt = NewStatement(scanlin, ST_ENDCATCHDTOR); + stmt->expr = BuildExpr(scanlin->u.monadic); + break; + case IROLinearAsm: + stmt = scanlin->u.asm_stmt; + break; + case IROLinearEnd: + stmt = NULL; + break; + default: + CError_FATAL(2685); + } + + if (stmt) { + if (LoopOptimizerRun) { + SInt32 i; + SInt32 value = 1; + for (i = 0; i < scan->loopdepth; i++) { + value = (value < 4096) ? (value * 8) : (value + 1); + } + stmt->value = value; + } + if (firstStmt) + lastStmt->next = stmt; + else + firstStmt = stmt; + lastStmt = stmt; + } + } + if (scanlin == scan->last) + break; + } + scan = scan->nextnode; + } + + return firstStmt; +} + +void IRO_RenumberInts(void) { + IROLinear *linear = IRO_FirstLinear; + IRO_NumLinear = 0; + while (linear) { + linear->index = IRO_NumLinear++; + linear = linear->next; + } +} + +static void TravExprToUpdateFlags(IROLinear *linear) { + int i; + + linear->flags &= ~(IROLF_Assigned | IROLF_8 | IROLF_Used | IROLF_Ind | IROLF_Subs | IROLF_LoopInvariant | IROLF_Ris | IROLF_Immind | IROLF_CouldError); + switch (linear->type) { + case IROLinearNop: + case IROLinearOperand: + break; + case IROLinearOp1Arg: + TravExprToUpdateFlags(linear->u.monadic); + if (IRO_IsAssignOp[linear->nodetype]) + MarkAssigned(linear->u.monadic, 1); + if (linear->nodetype == EINDIRECT) { + MarkSubs1(linear->u.monadic); + linear->u.monadic->flags |= IROLF_Immind | IROLF_Ind; + if (IS_LINEAR_DIADIC(linear->u.monadic, EADD)) + MarkSubscript(linear->u.monadic); + } + break; + case IROLinearOp2Arg: + TravExprToUpdateFlags(linear->u.diadic.left); + TravExprToUpdateFlags(linear->u.diadic.right); + if (IRO_IsAssignOp[linear->nodetype]) + MarkAssigned(linear->u.diadic.left, IRO_IsModifyOp[linear->nodetype]); + break; + case IROLinearOp3Arg: + TravExprToUpdateFlags(linear->u.args3.a); + TravExprToUpdateFlags(linear->u.args3.b); + TravExprToUpdateFlags(linear->u.args3.c); + break; + case IROLinearFunccall: + TravExprToUpdateFlags(linear->u.funccall.linear8); + for (i = linear->u.funccall.argCount - 1; i >= 0; i--) + TravExprToUpdateFlags(linear->u.funccall.args[i]); + break; + default: + IRO_Dump("Oh, oh, bad expression type in TravExprToUpdateFlags at: %d\n", linear->index); + CError_FATAL(2853); + } +} + +void IRO_UpdateFlagsOnInts(void) { + IROLinear *linear; + IRONode *node; + + MarkAllSubExprs(IRO_FirstLinear); + + for (node = IRO_FirstNode; node; node = node->nextnode) { + for (linear = node->first; linear; linear = linear->next) { + if (!(linear->flags & IROLF_Reffed)) { + switch (linear->type) { + case IROLinearOperand: + case IROLinearOp1Arg: + case IROLinearOp2Arg: + case IROLinearOp3Arg: + case IROLinearFunccall: + TravExprToUpdateFlags(linear); + break; + case IROLinearIf: + case IROLinearIfNot: + TravExprToUpdateFlags(linear->u.label.x4); + break; + case IROLinearReturn: + if (linear->u.monadic) + TravExprToUpdateFlags(linear->u.monadic); + break; + case IROLinearSwitch: + TravExprToUpdateFlags(linear->u.swtch.x4); + break; + case IROLinearBeginCatch: + TravExprToUpdateFlags(linear->u.ctch.linear); + break; + case IROLinearEndCatch: + TravExprToUpdateFlags(linear->u.monadic); + break; + case IROLinearEndCatchDtor: + TravExprToUpdateFlags(linear->u.monadic); + break; + case IROLinearNop: + case IROLinearGoto: + case IROLinearLabel: + case IROLinearEntry: + case IROLinearExit: + case IROLinearAsm: + case IROLinearEnd: + break; + default: + CError_FATAL(2931); + } + } + if (linear == node->last) + break; + } + } +} + +void IRO_SaveLinearIR(IROLinearIRSave *save) { + save->firstLinear = IRO_FirstLinear; + save->lastLinear = IRO_LastLinear; + save->numLinear = IRO_NumLinear; + save->curStat = CurStat; + save->disableDueToAsm = DisableDueToAsm; + save->isLeafFunction = IRO_IsLeafFunction; + save->functionHasReturn = IRO_FunctionHasReturn; + save->nullCheckList = NullCheckList; + save->currStmt = CurrStmt; + save->prevStmt = PrevStmt; +} + +void IRO_RestoreLinearIR(IROLinearIRSave *save) { + IRO_FirstLinear = save->firstLinear; + IRO_LastLinear = save->lastLinear; + IRO_NumLinear = save->numLinear; + CurStat = save->curStat; + DisableDueToAsm = save->disableDueToAsm; + IRO_IsLeafFunction = save->isLeafFunction; + IRO_FunctionHasReturn = save->functionHasReturn; + NullCheckList = save->nullCheckList; + CurrStmt = save->currStmt; + PrevStmt = save->prevStmt; +} + diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.h b/compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.h new file mode 100644 index 0000000..c0b2d17 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.h @@ -0,0 +1,165 @@ +#ifndef COMPILER_IROLINEARFORM_H +#define COMPILER_IROLINEARFORM_H + +#include "IrOptimizer.h" +#include "compiler/Switch.h" +#include "compiler/enode.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif + +typedef struct IROLinearIRSave { + IROLinear *firstLinear; + IROLinear *lastLinear; + UInt32 numLinear; + Statement *curStat; + Boolean disableDueToAsm; + Boolean isLeafFunction; + Boolean functionHasReturn; + void *nullCheckList; + Statement *currStmt; + Statement *prevStmt; +} IROLinearIRSave; + +typedef enum IROLinearType { + IROLinearNop, + IROLinearOperand, + IROLinearOp1Arg, + IROLinearOp2Arg, + IROLinearGoto, + IROLinearIf, + IROLinearIfNot, + IROLinearReturn, + IROLinearLabel, + IROLinearSwitch, + IROLinearOp3Arg, + IROLinearFunccall, + IROLinearEntry, + IROLinearExit, + IROLinearBeginCatch, + IROLinearEndCatch, + IROLinearEndCatchDtor, + IROLinearAsm, + IROLinear18, + IROLinear19, + IROLinearEnd +} IROLinearType; + +enum { + IROLF_1 = 0x1, + IROLF_Reffed = 0x2, + IROLF_Assigned = 0x4, + IROLF_8 = 0x8, + IROLF_Used = 0x10, + IROLF_Ind = 0x20, + IROLF_Subs = 0x40, + IROLF_80 = 0x80, + IROLF_LoopInvariant = 0x100, + IROLF_BeginLoop = 0x200, + IROLF_EndLoop = 0x400, + IROLF_Ris = 0x800, + IROLF_Immind = 0x1000, + IROLF_VecOp = 0x2000, + IROLF_4000 = 0x4000, + IROLF_8000 = 0x8000, + IROLF_VecOpBase = 0x10000, + IROLF_20000 = 0x20000, + IROLF_CounterLoop = 0x40000, + IROLF_BitfieldIndirect = 0x80000, + IROLF_CouldError = 0x100000 +}; + +// actual name is LinearNode as per mwccppc v8 +struct IROLinear { + IROLinearType type; + ENodeType nodetype; + SInt32 flags; + UInt16 nodeflags; + unsigned short index; + Statement *stmt; + Type *rtype; + IROExpr *expr; + struct ERange *x16; + PointsToFunction *pointsToFunction; + Boolean x1E; + union { + struct { + void *data1; + void *data2; + void *data3; + void *data4; + void *data5; + } idk; + // Operand + ENode *node; + // Op1Arg + IROLinear *monadic; + // Op2Arg + struct { + IROLinear *left; + IROLinear *right; + } diadic; + // Op3Arg + struct { + IROLinear *a; + IROLinear *b; + IROLinear *c; + } args3; + // Funccall + struct { + char ispascal; + short argCount; + IROLinear **args; + IROLinear *linear8; // funcref + TypeFunc *functype; + struct LocationSetSet *returnedLocs; + } funccall; + // Asm + Statement *asm_stmt; + // If, IfNot, Goto, Label + struct { + CLabel *label; + IROLinear *x4; // if,ifnot only?? + } label; + struct { + SwitchInfo *info; + IROLinear *x4; + } swtch; + // BeginCatch, EndCatch, EndCatchDtor + struct { + IROLinear *linear; + int x4; + int x8; + } ctch; + } u; + IROLinear *next; +}; + +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +extern IROLinear *IRO_FirstLinear; +extern IROLinear *IRO_LastLinear; +extern UInt32 IRO_NumLinear; +extern Statement *CurStat; + +extern IROLinear *IRO_NewLinear(IROLinearType type); +extern void IRO_PreLinearize(Statement *stmt); +extern void IRO_Linearize(Statement *stmt); +extern ENode *IRO_NewENode(ENodeType nodetype); +extern Statement *IRO_Delinearize(IRONode *node, IROLinear *linear); +extern void IRO_RenumberInts(void); +extern void IRO_UpdateFlagsOnInts(void); +extern void IRO_SaveLinearIR(IROLinearIRSave *save); +extern void IRO_RestoreLinearIR(IROLinearIRSave *save); + +#define IS_LINEAR_ENODE(_linear, _nodetype) ( ((_linear)->type == IROLinearOperand) && ((_linear)->u.node->type) == (_nodetype) ) +#define IS_LINEAR_MONADIC(_linear, _nodetype) ( ((_linear)->type == IROLinearOp1Arg) && ((_linear)->nodetype) == (_nodetype) ) +#define IS_LINEAR_MONADIC_2(_linear, _nodetype1, _nodetype2) ( ((_linear)->type == IROLinearOp1Arg) && (((_linear)->nodetype) == (_nodetype1) || ((_linear)->nodetype) == (_nodetype2)) ) +#define IS_LINEAR_DIADIC(_linear, _nodetype) ( ((_linear)->type == IROLinearOp2Arg) && ((_linear)->nodetype) == (_nodetype) ) +#define IS_LINEAR_DIADIC_2(_linear, _nodetype1, _nodetype2) ( ((_linear)->type == IROLinearOp2Arg) && (((_linear)->nodetype) == (_nodetype1) || ((_linear)->nodetype) == (_nodetype2)) ) +#define IS_LINEAR_DIADIC_3(_linear, _nodetype1, _nodetype2, _nodetype3) ( ((_linear)->type == IROLinearOp2Arg) && (((_linear)->nodetype) == (_nodetype1) || ((_linear)->nodetype) == (_nodetype2) || ((_linear)->nodetype) == (_nodetype3)) ) + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroLoop.c b/compiler_and_linker/FrontEnd/Optimizer/IroLoop.c new file mode 100644 index 0000000..850146d --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroLoop.c @@ -0,0 +1,2324 @@ +#include "IroLoop.h" +#include "IroCSE.h" +#include "IroDump.h" +#include "IroFlowgraph.h" +#include "IroLinearForm.h" +#include "IroPropagate.h" +#include "IroSubable.h" +#include "IroUtil.h" +#include "IroVars.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +IRONode *LoopNode; +Boolean ConditionalHeaderAtBottom; +IROLoopInd *FirstInd; +BitVector *InLoop; +IROList IRO_InitLList; +BitVector *InLoop_Exits; +BitVector *InLoop_Tails; +UInt32 LoopExitNumber; +UInt32 LoopTailNum; +IRONode *LoopExitSuccessor; +IRONode *LoopTail; +IROLoopMemRef *IRO_LoopMemRefFirst; +IROLoopMemRef *IRO_LoopMemRefCurrent; +static IROExpr *RisList; +static BitVector *AllKills; +static Boolean KnownBounds; +static SInt32 Times; +static IROLinear *PredInt; +static IROElmList *FirstAddendLinear; +static IROElmList *LastAddendLinear; +static int NoSubableSubs; + +// forward decls +static void MyHandleLoop_Vector(IRONode *fnode); +static void MyHandleLoop_Motion(IRONode *fnode); +static void CheckAllLoopAddresses(IRONode *fnode, BitVector *bv, Boolean *resultFlag); +static void MakeLoopEntry(IROLinear *nd, IROAddrRecord *rec, Boolean mustreach1, Boolean flag2); +static void MoveInvarianceInAddressExpr(void); +static IROLinear *RearrangeInvarianceInAddressExpr(IROLinear *nd, IROList *list); +static UInt32 IsAssignmentReductionCandidate(IROLinear *nd); + +void FindMustReach(void) { + IRONode *fnode; + IRONode *fnode2; + IRONode *pred; + int i; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + fnode->mustreach = 0; + if (Bv_IsBitSet(fnode->index, InLoop)) { + fnode->mustreach = 1; + + for (i = 0; i < LoopNode->numpred; i++) { + pred = IRO_NodeTable[LoopNode->pred[i]]; + if (Bv_IsBitSet(pred->index, InLoop) && !Bv_IsBitSet(fnode->index, pred->dom)) { + fnode->mustreach = 0; + break; + } + } + + for (fnode2 = IRO_FirstNode; fnode2; fnode2 = fnode2->nextnode) { + if (Bv_IsBitSet(fnode2->index, InLoop)) { + for (i = 0; i < fnode2->numsucc; i++) { + if (!Bv_IsBitSet(fnode2->succ[i], InLoop) && !Bv_IsBitSet(fnode->index, fnode2->dom)) { + fnode->mustreach = 0; + break; + } + } + + if (!fnode->mustreach) + break; + } + } + } + } +} + +void FindMustReach1(IRONode *checkfnode) { + IRONode *fnode; + IRONode *fnode2; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (Bv_IsBitSet(fnode->index, InLoop)) { + fnode->mustreach1 = 1; + for (fnode2 = IRO_FirstNode; fnode2; fnode2 = fnode2->nextnode) { + if (Bv_IsBitSet(fnode2->index, InLoop)) { + if (Bv_IsBitSet(fnode2->index, InLoop_Tails) && !Bv_IsBitSet(fnode->index, fnode2->dom)) + fnode->mustreach1 = 0; + + if (Bv_IsBitSet(fnode2->index, InLoop_Exits) && fnode2 != checkfnode && !Bv_IsBitSet(fnode->index, fnode2->dom)) + fnode->mustreach1 = 0; + + if (!fnode->mustreach1) + break; + } + } + } + } +} + +static void IRO_FindLoopTailsAndExits(IRONode *fnode) { + IRONode *scan; + IRONode *succ; + int i; + + for (scan = IRO_FirstNode; scan; scan = scan->nextnode) { + if (Bv_IsBitSet(scan->index, InLoop)) { + for (i = 0; i < scan->numsucc; i++) { + succ = IRO_NodeTable[scan->succ[i]]; + if (succ == fnode) { + Bv_SetBit(scan->index, InLoop_Tails); + LoopTail = scan; + LoopTailNum++; + } + if (!Bv_IsBitSet(succ->index, InLoop)) { + LoopExitNumber++; + LoopExitSuccessor = succ; + Bv_SetBit(scan->index, InLoop_Exits); + } + } + } + } + + IRO_Dump("IRO_FindLoopTailsAndExits:For header %d, Loop exits and loop tails are \n", fnode->index); + IRO_DumpBits("Loop Exits: ", InLoop_Exits); + IRO_DumpBits("Loop Tails: ", InLoop_Tails); + IRO_Dump("LoopExitNum=%d: \n", LoopExitNumber); + if (LoopExitSuccessor) + IRO_Dump("LoopExitSuccessor node =%d: \n", LoopExitSuccessor->index); +} + +static int IsSafeTypcon(IROLinear *nd) { + Type *srcType; + Type *destType; + SInt32 srcSize; + SInt32 destSize; + Boolean srcUnsigned; + Boolean destUnsigned; + + srcType = nd->u.monadic->rtype; + destType = nd->rtype; + if (!IS_TYPE_INT(srcType) || !IS_TYPE_INT(destType)) + return 0; + + srcSize = srcType->size; + destSize = destType->size; + srcUnsigned = IRO_IsUnsignedType(srcType); + destUnsigned = IRO_IsUnsignedType(destType); + + if (srcUnsigned == destUnsigned && destSize >= srcSize) + return 1; + if (srcUnsigned == 1 && destUnsigned == 0 && destSize > srcSize) + return 1; + return 0; +} + +static int Reducable(IROLinear *nd, IROLinear **resultNd1, IROLinear **resultNd2, VarRecord **resultVar) { + IROLinear *indirect; + IROLinear *left; + IROLinear *right; + Boolean leftInvariant; + Boolean rightInvariant; + Boolean leftTypcon; + Boolean rightTypcon; + Object *obj; + ENode *enode; + IROLoopInd *ind; + CInt64 val64; + SInt32 val; + SInt32 div; + + leftInvariant = 0; + rightInvariant = 0; + leftTypcon = 0; + rightTypcon = 0; + + if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD && (IS_TYPE_INT(nd->rtype) || IS_TYPE_POINTER_ONLY(nd->rtype))) { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + if (left->type == IROLinearOp1Arg && left->nodetype == ETYPCON) { + leftTypcon = 1; + leftInvariant = (left->flags & IROLF_LoopInvariant) != 0; + left = left->u.monadic; + } + if (right->type == IROLinearOp1Arg && right->nodetype == ETYPCON) { + rightTypcon = 1; + rightInvariant = (right->flags & IROLF_LoopInvariant) != 0; + right = right->u.monadic; + } + + if (((left->flags & IROLF_LoopInvariant) || leftInvariant) && IRO_IsVariable(right)) { + if (leftInvariant || ((!(obj = IRO_IsVariable(left)) || !IRO_IsRegable(obj)) && !IRO_IsConstant(left))) { + if ( + left->type == IROLinearOp2Arg && + left->nodetype == EADD && + (obj = IRO_IsVariable(left->u.diadic.left)) && + IRO_IsRegable(obj) && + IRO_IsConstant(left->u.diadic.right) + ) + return 0; + + if (rightTypcon) { + if (!IsSafeTypcon(nd->u.diadic.right)) + return 0; + *resultNd2 = nd->u.diadic.right; + } else { + *resultNd2 = right; + } + + indirect = right; + *resultNd1 = IRO_NewLinear(IROLinearOperand); + + enode = IRO_NewENode(EINTCONST); + enode->data.intval = cint64_one; + enode->rtype = nd->u.diadic.right->rtype; + (*resultNd1)->rtype = nd->u.diadic.right->rtype; + (*resultNd1)->u.node = enode; + } else { + return 0; + } + } else if ( + ((left->flags & IROLF_LoopInvariant) || leftInvariant) && + right->type == IROLinearOp2Arg && + !rightTypcon && + (right->nodetype == EMUL || right->nodetype == ESHL) + ) { + if (IRO_IsConstant(right->u.diadic.right)) { + if (right->nodetype == ESHL) { + right->nodetype = EMUL; + right->u.diadic.right->u.node->data.intval = CInt64_Shl(cint64_one, right->u.diadic.right->u.node->data.intval); + } + if (right->u.diadic.left->type == IROLinearOp1Arg) { + if (IRO_IsVariable(right->u.diadic.left)) { + *resultNd2 = right->u.diadic.left; + indirect = right->u.diadic.left; + *resultNd1 = right->u.diadic.right; + } else if (right->u.diadic.left->nodetype == ETYPCON && IRO_IsVariable(right->u.diadic.left->u.monadic)) { + if (!IsSafeTypcon(right->u.diadic.left)) + return 0; + *resultNd2 = right->u.diadic.left; + indirect = right->u.diadic.left->u.monadic; + *resultNd1 = right->u.diadic.right; + } else { + return 0; + } + } else { + return 0; + } + } else { + return 0; + } + } else if ( + ((right->flags & IROLF_LoopInvariant) || rightInvariant) && + left->type == IROLinearOp2Arg && + !leftTypcon && + (left->nodetype == EMUL || left->nodetype == ESHL) + ) { + if (IRO_IsConstant(left->u.diadic.right)) { + if (left->nodetype == ESHL) { + left->nodetype = EMUL; + left->u.diadic.right->u.node->data.intval = CInt64_Shl(cint64_one, left->u.diadic.right->u.node->data.intval); + } + if (left->u.diadic.left->type == IROLinearOp1Arg) { + if (IRO_IsVariable(left->u.diadic.left)) { + *resultNd2 = left->u.diadic.left; + indirect = left->u.diadic.left; + *resultNd1 = left->u.diadic.right; + } else if (left->u.diadic.left->nodetype == ETYPCON && IRO_IsVariable(left->u.diadic.left->u.monadic)) { + if (!IsSafeTypcon(left->u.diadic.left)) + return 0; + *resultNd2 = left->u.diadic.left; + indirect = left->u.diadic.left->u.monadic; + *resultNd1 = left->u.diadic.right; + } else { + return 0; + } + } else { + return 0; + } + } else { + return 0; + } + } else if ( + ((right->flags & IROLF_LoopInvariant) || rightInvariant) && + IRO_IsVariable(left) + ) { + if (rightInvariant || ((!(obj = IRO_IsVariable(right)) || !IRO_IsRegable(obj)) && !IRO_IsConstant(right))) { + if ( + right->type == IROLinearOp2Arg && + right->nodetype == EADD && + (obj = IRO_IsVariable(right->u.diadic.left)) && + IRO_IsRegable(obj) && + IRO_IsConstant(right->u.diadic.right) + ) + return 0; + + if (leftTypcon) { + if (!IsSafeTypcon(nd->u.diadic.left)) + return 0; + *resultNd2 = nd->u.diadic.left; + } else { + *resultNd2 = left; + } + + indirect = left; + *resultNd1 = IRO_NewLinear(IROLinearOperand); + + enode = IRO_NewENode(EINTCONST); + enode->data.intval = cint64_one; + enode->rtype = nd->u.diadic.left->rtype; + (*resultNd1)->rtype = nd->u.diadic.left->rtype; + (*resultNd1)->u.node = enode; + } else { + return 0; + } + } else { + return 0; + } + } else if (nd->type == IROLinearOp2Arg && (nd->nodetype == EMUL || nd->nodetype == ESHL) && nd->rtype->size <= 4 && (IS_TYPE_INT(nd->rtype) || IS_TYPE_POINTER_ONLY(nd->rtype))) { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + + if (IRO_IsConstant(right) && IRO_IsVariable(left)) { + *resultNd2 = left; + indirect = left; + *resultNd1 = right; + } else if (IRO_IsConstant(nd->u.diadic.right) && left->type == IROLinearOp1Arg && left->nodetype == ETYPCON && + IRO_IsVariable(left->u.monadic)) { + if (!IsSafeTypcon(left)) + return 0; + *resultNd2 = left; + indirect = left->u.monadic; + *resultNd1 = right; + } else { + if (nd->type == IROLinearOp2Arg && nd->nodetype == ESHL) + return 0; + + if (nd->u.diadic.right->flags & IROLF_LoopInvariant) { + if (IRO_IsVariable(left)) { + *resultNd2 = left; + indirect = left; + *resultNd1 = right; + } else if (left->type == IROLinearOp1Arg && left->nodetype == ETYPCON && IRO_IsVariable(left->u.monadic)) { + if (!IsSafeTypcon(left)) + return 0; + *resultNd2 = left; + indirect = left->u.monadic; + *resultNd1 = right; + } else { + return 0; + } + } else if (nd->u.diadic.left->flags & IROLF_LoopInvariant) { + if (IRO_IsVariable(right)) { + *resultNd2 = right; + indirect = right; + *resultNd1 = left; + } else if (right->type == IROLinearOp1Arg && right->nodetype == ETYPCON && IRO_IsVariable(right->u.monadic) && nd->type == IROLinearOp2Arg && nd->nodetype == EMUL) { + if (!IsSafeTypcon(right)) + return 0; + *resultNd2 = right; + indirect = right->u.monadic; + *resultNd1 = left; + } else { + return 0; + } + } else { + return 0; + } + } + } else if (nd->type == IROLinearOp2Arg && (nd->nodetype == EDIV || nd->nodetype == ESHR) && nd->rtype->size <= 4 && IS_TYPE_INT(nd->rtype)) { + if (IRO_IsVariable(nd->u.diadic.left) && IRO_IsConstant(nd->u.diadic.right)) { + val64 = nd->u.diadic.right->u.node->data.intval; + if (nd->type == IROLinearOp2Arg && nd->nodetype == ESHR) { + CInt64_GetULong(&val64); + if (CInt64_GetULong(&val64) > 32 || CTool_EndianReadWord32(&val64.hi)) + return 0; + val64 = CInt64_Shl(cint64_one, val64); + } + *resultNd2 = nd->u.diadic.left; + indirect = nd->u.diadic.left; + } else { + return 0; + } + } else { + return 0; + } + + if ( + nd->type == IROLinearOp2Arg && + nd->nodetype == ESHL && + ( + !IRO_IsConstant(*resultNd1) || + (SInt32) CInt64_GetULong(&(*resultNd1)->u.node->data.intval) < 0 || + (SInt32) CInt64_GetULong(&(*resultNd1)->u.node->data.intval) > 32 || + CTool_EndianReadWord32(&(*resultNd1)->u.node->data.intval.hi) + ) + ) + return 0; + + CError_ASSERT(802, indirect->u.monadic->u.node != NULL); + *resultVar = IRO_FindVar(indirect->u.monadic->u.node->data.objref, 0, 1); + if (!*resultVar || (*resultVar)->xA != 2) + return 0; + + if (copts.ANSIstrict || copts.strengthreductionstrict) { + Type *type = (*resultVar)->object->type; + if (IRO_IsUnsignedType(type) && type->size < stunsignedlong.size) + return 0; + } + + if (nd->type == IROLinearOp2Arg && (nd->nodetype == ESHR || nd->nodetype == EDIV)) { + ind = FirstInd; + while (ind && ind->var != *resultVar) + ind = ind->next; + + CError_ASSERT(845, ind != NULL); + + if (ind->addNode == NULL) { + if (ind->addConst < (val = CInt64_GetULong(&val64))) + return 0; + if ((div = ind->addConst / val) <= 0) + return 0; + + *resultNd1 = IRO_NewLinear(IROLinearOperand); + enode = IRO_NewENode(EINTCONST); + CInt64_SetULong(&enode->data.intval, div); + enode->rtype = nd->u.diadic.left->rtype; + (*resultNd1)->rtype = nd->u.diadic.left->rtype; + (*resultNd1)->u.node = enode; + } else { + return 0; + } + } + + return 1; +} + +static void IRO_RemoveExpr_Action(IROLinear *linear, Boolean isFirst) { + if (isFirst && linear->expr) + IRO_RemoveExpr(linear->expr); +} + +static void IRO_ActUnmarkRISCandidate(IROLinear *linear, Boolean isFirst) { + if (isFirst && linear->expr) + linear->flags &= ~IROLF_Ris; +} + +static IROExpr *CreateRIS(IROExpr *expr, IROLinear *nd1, IROLinear *nd2, IROLoopInd *induction, int unk) { + Object *tempObj; + Type *type; + Boolean flag23; + Object *tempObj2; + IROLinear *firstnode; + IROLinear *fourthnode; + IROLinear *fifthnode; + IROLinear *secondnode; + IROLinear *thirdnode; + IROLinear *tmp; + ENode *enode; + IROList list1; + IROList list2; + + flag23 = 0; + type = expr->linear->rtype; + tempObj = create_temp_object(type); + IRO_FindVar(tempObj, 1, 1); + IRO_InitList(&list1); + + if (IS_LINEAR_DIADIC(expr->linear, EADD)) { + firstnode = IRO_DuplicateExpr(expr->linear, &list1); + } else if (IS_LINEAR_DIADIC_2(expr->linear, EDIV, ESHR)) { + firstnode = IRO_DuplicateExpr(expr->linear, &list1); + } else { + firstnode = IRO_NewLinear(IROLinearOp2Arg); + firstnode->index = ++IRO_NumLinear; + firstnode->rtype = type; + firstnode->nodetype = EMUL; + firstnode->u.diadic.left = IRO_DuplicateExpr(nd1, &list1); + if (unk) + firstnode->u.diadic.right = IRO_DuplicateExpr(nd1, &list1); + else + firstnode->u.diadic.right = IRO_DuplicateExpr(nd2, &list1); + IRO_AddToList(firstnode, &list1); + } + + secondnode = IRO_NewLinear(IROLinearOp2Arg); + secondnode->index = ++IRO_NumLinear; + secondnode->rtype = type; + secondnode->nodetype = EASS; + secondnode->u.diadic.left = IRO_TempReference(tempObj, &list1); + secondnode->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned; + secondnode->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned; + secondnode->u.diadic.right = firstnode; + IRO_AddToList(secondnode, &list1); + IRO_Paste(list1.head, list1.tail, PredInt); + if ( + !IS_LINEAR_DIADIC_2(expr->linear, EDIV, ESHR) && + induction->addConst != 1 && + (induction->addNode || !IRO_IsConstant(nd2)) + ) { + flag23 = 1; + IRO_InitList(&list1); + thirdnode = IRO_NewLinear(IROLinearOp2Arg); + thirdnode->index = ++IRO_NumLinear; + thirdnode->rtype = nd2->rtype; + thirdnode->nodetype = EMUL; + + if (!induction->addNode) { + thirdnode->u.diadic.left = IRO_DuplicateExpr(nd2, &list1); + thirdnode->u.diadic.right = IRO_NewLinear(IROLinearOperand); + thirdnode->u.diadic.right->index = ++IRO_NumLinear; + enode = IRO_NewENode(EINTCONST); + enode->rtype = nd2->rtype; + thirdnode->u.diadic.right->rtype = nd2->rtype; + CInt64_SetLong(&enode->data.intval, induction->addConst); + thirdnode->u.diadic.right->u.node = enode; + IRO_AddToList(thirdnode->u.diadic.right, &list1); + } else { + thirdnode->u.diadic.left = IRO_DuplicateExpr(nd2, &list1); + thirdnode->u.diadic.right = IRO_DuplicateExpr(induction->addNode, &list1); + if (nd2->rtype != induction->addNode->rtype) { + tmp = IRO_NewLinear(IROLinearOp1Arg); + tmp->nodetype = ETYPCON; + tmp->index = ++IRO_NumLinear; + tmp->rtype = nd2->rtype; + tmp->u.monadic = thirdnode->u.diadic.right; + IRO_AddToList(tmp, &list1); + thirdnode->u.diadic.right = tmp; + } + } + IRO_AddToList(thirdnode, &list1); + + tempObj2 = create_temp_object(nd2->rtype); + + fourthnode = IRO_NewLinear(IROLinearOp2Arg); + fourthnode->index = ++IRO_NumLinear; + fourthnode->rtype = nd2->rtype; + fourthnode->nodetype = EASS; + fourthnode->u.diadic.left = IRO_TempReference(tempObj2, &list1); + fourthnode->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned; + fourthnode->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned; + fourthnode->u.diadic.right = thirdnode; + IRO_AddToList(fourthnode, &list1); + IRO_Paste(list1.head, list1.tail, PredInt); + } + + IRO_InitList(&list2); + fifthnode = IRO_NewLinear(IROLinearOp2Arg); + fifthnode->index = ++IRO_NumLinear; + fifthnode->rtype = type; + if (induction->nd->type == IROLinearOp2Arg) { + if (induction->nd->nodetype == EASS && IS_LINEAR_DIADIC(induction->nd->u.diadic.right, EADD)) + fifthnode->nodetype = EADDASS; + else if (induction->nd->nodetype == EASS && IS_LINEAR_DIADIC(induction->nd->u.diadic.right, ESUB)) + fifthnode->nodetype = ESUBASS; + else + fifthnode->nodetype = induction->nd->nodetype; + } else { + if (induction->nd->nodetype == EPREINC || induction->nd->nodetype == EPOSTINC) + fifthnode->nodetype = EADDASS; + else + fifthnode->nodetype = ESUBASS; + } + + fifthnode->u.diadic.left = IRO_TempReference(tempObj, &list2); + fifthnode->u.diadic.left->flags |= IROLF_Ind | IROLF_Used | IROLF_Assigned; + fifthnode->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Used | IROLF_Assigned; + if (!unk) { + if (!flag23) { + if (induction->addConst == 1 || IS_LINEAR_DIADIC_2(expr->linear, EDIV, ESHR)) { + fifthnode->u.diadic.right = IRO_DuplicateExpr(nd2, &list2); + } else { + fifthnode->u.diadic.right = IRO_NewLinear(IROLinearOperand); + fifthnode->u.diadic.right->index = ++IRO_NumLinear; + enode = IRO_NewENode(EINTCONST); + enode->rtype = nd2->rtype; + fifthnode->u.diadic.right->rtype = nd2->rtype; + CInt64_SetLong(&enode->data.intval, induction->addConst * CInt64_GetULong(&nd2->u.node->data.intval)); + fifthnode->u.diadic.right->u.node = enode; + IRO_AddToList(fifthnode->u.diadic.right, &list2); + } + } else { + fifthnode->u.diadic.right = IRO_TempReference(tempObj2, &list2); + fifthnode->u.diadic.right->flags |= IROLF_Used; + } + } + + fifthnode->index = ++IRO_NumLinear; + IRO_AddToList(fifthnode, &list2); + IRO_Paste(list2.head, list2.tail, IRO_FindStart(induction->nd)); + IRO_WalkTree(expr->linear, IRO_RemoveExpr_Action); + expr->x8 = tempObj; + expr->next = RisList; + RisList = expr; + return expr; +} + +static IRONode *CreatePreHeader(IRONode *fnode1, IRONode *fnode2) { + IROLinear *labelnode; + IRONode *newfnode; + IRONode *iter; + CLabel *oldlabel; + CLabel *newlabel; + SwitchInfo *swinfo; + SwitchCase *swcase; + + newfnode = oalloc(sizeof(IRONode)); + memset(newfnode, 0, sizeof(IRONode)); + newfnode->index = IRO_NumNodes; + IRO_NumNodes++; + + labelnode = IRO_NewLinear(IROLinearLabel); + labelnode->index = IRO_NumLinear++; + labelnode->next = NULL; + labelnode->u.label.label = IRO_NewLabel(); + labelnode->flags |= IROLF_1; + labelnode->u.label.label->stmt = (Statement *) newfnode; + newfnode->first = labelnode; + newfnode->last = labelnode; + + if (fnode2) { + fnode2->last->next = labelnode; + labelnode->next = IRO_NewLinear(IROLinearNop); + labelnode->next->next = fnode1->first; + fnode2->nextnode = newfnode; + newfnode->nextnode = fnode1; + } else { + CError_ASSERT(1254, fnode1->first->type == IROLinearLabel); + labelnode->next = IRO_NewLinear(IROLinearGoto); + labelnode->next->u.label.label = fnode1->first->u.label.label; + IRO_LastNode->last->next = labelnode; + IRO_LastNode->nextnode = newfnode; + IRO_LastNode = newfnode; + IRO_LastLinear = labelnode->next; + } + + newfnode->last = labelnode->next; + + IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes); + memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes); + for (iter = IRO_FirstNode; iter; iter = iter->nextnode) + IRO_NodeTable[iter->index] = iter; + + if (fnode1->first->type == IROLinearLabel) { + oldlabel = fnode1->first->u.label.label; + newlabel = newfnode->first->u.label.label; + for (iter = IRO_FirstNode; iter; iter = iter->nextnode) { + if (!Bv_IsBitSet(iter->index, InLoop) && iter != newfnode) { + switch (iter->last->type) { + case IROLinearGoto: + if (iter->last->u.label.label == oldlabel) + iter->last->u.label.label = newlabel; + break; + case IROLinearIf: + case IROLinearIfNot: + if (iter->last->u.label.label == oldlabel) + iter->last->u.label.label = newlabel; + break; + case IROLinearSwitch: + swinfo = iter->last->u.swtch.info; + for (swcase = swinfo->cases; swcase; swcase = swcase->next) { + if (swcase->label == oldlabel) + swcase->label = newlabel; + } + if (swinfo->defaultlabel == oldlabel) + swinfo->defaultlabel = newlabel; + break; + } + } + } + } + + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + return newfnode; +} + +static IRONode *CreateNewLoopExitSuccessor(IRONode *fnode1) { + IROLinear *labelnode; + IRONode *fnode2; + IRONode *newfnode; + Boolean flag; + IRONode *iter; + CLabel *oldlabel; + CLabel *newlabel; + SwitchInfo *swinfo; + SwitchCase *swcase; + UInt16 i; + + CError_ASSERT(1355, fnode1 != NULL && LoopExitNumber == 1); + + fnode2 = NULL; + flag = 0; + + for (i = 0; i < fnode1->numpred; i++) { + iter = IRO_NodeTable[fnode1->pred[i]]; + if (Bv_IsBitSet(iter->index, InLoop_Exits)) { + CError_ASSERT(1366, fnode2 == NULL); + fnode2 = iter; + if (!flag) { + if ( + !iter->last || + !fnode1->first || + fnode1->first->type != IROLinearLabel || + ( + (iter->last->type == IROLinearIf || iter->last->type == IROLinearIfNot) && + iter->last->u.label.label != fnode1->first->u.label.label + )) + flag = 1; + } + } + } + + CError_ASSERT(1382, fnode2 != NULL); + + newfnode = oalloc(sizeof(IRONode)); + memset(newfnode, 0, sizeof(IRONode)); + newfnode->index = IRO_NumNodes; + IRO_NumNodes++; + + labelnode = IRO_NewLinear(IROLinearLabel); + labelnode->index = IRO_NumLinear++; + labelnode->next = NULL; + labelnode->u.label.label = IRO_NewLabel(); + labelnode->flags |= IROLF_1; + labelnode->u.label.label->stmt = (Statement *) newfnode; + newfnode->first = labelnode; + newfnode->last = labelnode; + + if (flag) { + fnode2->last->next = labelnode; + labelnode->next = IRO_NewLinear(IROLinearNop); + labelnode->next->next = fnode1->first; + fnode2->nextnode = newfnode; + newfnode->nextnode = fnode1; + } else { + CError_ASSERT(1422, fnode1->first->type == IROLinearLabel); + labelnode->next = IRO_NewLinear(IROLinearGoto); + labelnode->next->u.label.label = fnode1->first->u.label.label; + IRO_LastNode->last->next = labelnode; + IRO_LastNode->nextnode = newfnode; + IRO_LastNode = newfnode; + IRO_LastLinear = labelnode->next; + } + + newfnode->last = labelnode->next; + + IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes); + memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes); + for (iter = IRO_FirstNode; iter; iter = iter->nextnode) + IRO_NodeTable[iter->index] = iter; + + if (fnode1->first->type == IROLinearLabel) { + oldlabel = fnode1->first->u.label.label; + newlabel = newfnode->first->u.label.label; + switch (fnode2->last->type) { + case IROLinearGoto: + if (fnode2->last->u.label.label == oldlabel) + fnode2->last->u.label.label = newlabel; + break; + case IROLinearIf: + case IROLinearIfNot: + if (fnode2->last->u.label.label == oldlabel) + fnode2->last->u.label.label = newlabel; + break; + case IROLinearSwitch: + swinfo = fnode2->last->u.swtch.info; + for (swcase = swinfo->cases; swcase; swcase = swcase->next) { + if (swcase->label == oldlabel) + swcase->label = newlabel; + } + if (swinfo->defaultlabel == oldlabel) + swinfo->defaultlabel = newlabel; + break; + } + } + + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + return newfnode; +} + +void AddPreds(IRONode *fnode) { + IRONode *pred; + int i; + + for (i = 0; i < fnode->numpred; i++) { + pred = IRO_NodeTable[fnode->pred[i]]; + if (!Bv_IsBitSet(pred->index, InLoop)) { + Bv_SetBit(pred->index, InLoop); + AddPreds(pred); + } + } +} + +static void RemoveNoopsFromExprList(void) { + IROExpr *expr; + IROExpr *prev; + + expr = IRO_FirstExpr; + prev = NULL; + while (expr) { + if (expr->linear->type == IROLinearNop) { + if (prev) + prev->next = expr->next; + else + IRO_FirstExpr = expr->next; + expr = expr->next; + } else { + prev = expr; + expr = expr->next; + } + } +} + +void IncLoopDepth(void) { + IRONode *fnode; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (Bv_IsBitSet(fnode->index, InLoop)) + fnode->loopdepth++; + } +} + +void IRO_SetLoopDepth(void) { + IRONode *fnode; + IRONode *pred; + UInt16 i; + UInt16 flag; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) + fnode->loopdepth = 0; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + flag = 0; + + for (i = 0; i < fnode->numpred; i++) { + pred = IRO_NodeTable[fnode->pred[i]]; + if (Bv_IsBitSet(fnode->index, pred->dom)) { + if (!flag) { + Bv_AllocVector(&InLoop, IRO_NumNodes + 1); + Bv_Clear(InLoop); + Bv_SetBit(fnode->index, InLoop); + } + flag = 1; + Bv_SetBit(pred->index, InLoop); + if (pred != fnode) + AddPreds(pred); + } + } + + if (flag) + IncLoopDepth(); + } + + IRO_CheckForUserBreak(); +} + +static void InsertBranchAroundLoopPreheaders(void) { + IRONode *fnode; + CLabel *label; + IRONode *iter; + IROLinear *endnode; + IROLinear *labelnode; + + if (IRO_EndNode && IRO_EndNode->last && IRO_EndNode->last->type == IROLinearEnd) { + label = IRO_NewLabel(); + fnode = IRO_NewFlowGraphNode(); + IRO_LastNode->nextnode = fnode; + label->stmt = (Statement *) fnode; + + IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes); + memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes); + for (iter = IRO_FirstNode; iter; iter = iter->nextnode) + IRO_NodeTable[iter->index] = iter; + + labelnode = IRO_NewLinear(IROLinearLabel); + labelnode->index = ++IRO_NumLinear; + labelnode->u.label.label = label; + labelnode->flags |= IROLF_1; + fnode->first = labelnode; + IRO_LastLinear->next = labelnode; + + endnode = IRO_NewLinear(IROLinearEnd); + memcpy(endnode, IRO_EndNode->last, sizeof(IROLinear)); + endnode->index = ++IRO_NumLinear; + endnode->next = NULL; + fnode->last = endnode; + labelnode->next = endnode; + IRO_LastLinear = endnode; + + IRO_EndNode->last->type = IROLinearGoto; + IRO_EndNode->last->u.label.label = label; + IRO_LastNode = fnode; + IRO_EndNode = fnode; + + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + } +} + +void IRO_FindLoops(void) { + IRONode *fnode; + IRONode *pred; + UInt16 i; + UInt16 flag; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + flag = 0; + + for (i = 0; i < fnode->numpred; i++) { + pred = IRO_NodeTable[fnode->pred[i]]; + if (Bv_IsBitSet(fnode->index, pred->dom)) { + if (!flag) { + Bv_AllocVector(&InLoop, IRO_NumNodes + 1); + Bv_Clear(InLoop); + Bv_SetBit(fnode->index, InLoop); + } + flag = 1; + Bv_SetBit(pred->index, InLoop); + if (pred != fnode) + AddPreds(pred); + } + } + + if (flag) { + IncLoopDepth(); + IRO_Dump("IRO_FindLoops:Found loop with header %d\n", fnode->index); + IRO_DumpBits("Loop includes: ", InLoop); + MyHandleLoop_Motion(fnode); + IRO_UpdateFlagsOnInts(); + MyHandleLoop_Vector(fnode); + RemoveNoopsFromExprList(); + IRO_UpdateFlagsOnInts(); + IRO_UpdateVars(); + } + } + + if (!IRO_FunctionHasReturn && IRO_EndNode != IRO_LastNode) + InsertBranchAroundLoopPreheaders(); +} + +static void CheckSubableSub(IROLinear *linear, Boolean isFirst) { + if (isFirst && IRO_IsSubableExpression(linear)) { + IRO_Dump("Subable Expression is %d\n", linear->index); + NoSubableSubs = 0; + } +} + +static int NoSubableSubExprs(IROLinear *nd) { + NoSubableSubs = 1; + IRO_WalkTree(nd, CheckSubableSub); + return NoSubableSubs; +} + +void ComputeLoopKills(void) { + IRONode *fnode; + IROLinear *nd; + + Bv_AllocVector(&AllKills, IRO_NumVars + 1); + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) { + Bv_AllocVector(&fnode->x16, IRO_NumVars + 1); + Bv_AllocVector(&fnode->x1E, IRO_NumVars + 1); + while (1) { + Bv_Clear(IRO_VarKills); + IRO_GetKills(nd); + Bv_Or(IRO_VarKills, AllKills); + if (nd == fnode->last) + break; + nd = nd->next; + } + } + } +} + +void ComputeLoopInvariance(void) { + IRONode *fnode; + IROLinear *nd; + + IRO_Depends = IRO_VarKills; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) { + nd->flags &= ~IROLF_LoopInvariant; + while (1) { + if ((nd->flags & IROLF_Reffed) && nd->type != IROLinearNop) { + IRO_FindDepends_NoAlloc(nd); + if (!IRO_IsVolatile && !Bv_BitsInCommon(IRO_Depends, AllKills)) + nd->flags |= IROLF_LoopInvariant; + + if (IRO_CouldError) + nd->flags |= IROLF_CouldError; + else + nd->flags &= ~IROLF_CouldError; + } + + if (nd == fnode->last) + break; + nd = nd->next; + } + } + } +} + +void ComputeLoopInduction(void) { + IRONode *fnode; + IROLinear *nd; + Boolean flag; + Object *obj; + Object *obj2; + Object *obj3; + VarRecord *var; + IROLinear *tmpnd; + IROLoopInd *ind; + Boolean isUnsigned; + + Bv_AllocVector(&AllKills, IRO_NumVars + 1); + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) { + while (1) { + Bv_Clear(IRO_VarKills); + IRO_GetKills(nd); + Bv_Or(IRO_VarKills, AllKills); + flag = 0; + if ( + ( + nd->type == IROLinearOp2Arg && + nd->rtype->size <= 4 && + (nd->nodetype == EADDASS || nd->nodetype == ESUBASS) && + (obj = IRO_IsVariable(nd->u.diadic.left)) && + obj->type->size == nd->rtype->size && + IS_TYPE_INT(obj->type) && + ( + (IRO_IsIntConstant(nd->u.diadic.right) && CInt64_GetULong(&nd->u.diadic.right->u.node->data.intval)) + || + (nd->u.diadic.right->flags & IROLF_LoopInvariant) + ) + ) + || + ( + nd->type == IROLinearOp1Arg && + nd->rtype->size <= 4 && + (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC || nd->nodetype == EPREINC || nd->nodetype == EPREDEC) && + (obj = IRO_IsVariable(nd->u.monadic)) && + obj->type->size == nd->rtype->size && + IS_TYPE_INT(obj->type) + ) + ) + { + flag = 1; + } + else if ( + nd->type == IROLinearOp2Arg && + nd->rtype->size <= 4 && + nd->nodetype == EASS && + (obj = IRO_IsVariable(nd->u.diadic.left)) && + obj->type->size == nd->rtype->size && + IS_TYPE_INT(obj->type) && + nd->u.diadic.right->type == IROLinearOp2Arg && + (nd->u.diadic.right->nodetype == EADD || nd->u.diadic.right->nodetype == ESUB) + ) + { + if (nd->u.diadic.right->nodetype == EADD) { + obj2 = IRO_IsVariable(nd->u.diadic.right->u.diadic.left); + obj3 = IRO_IsVariable(nd->u.diadic.right->u.diadic.right); + if (obj2 == obj && obj3 != obj && (nd->u.diadic.right->u.diadic.right->flags & IROLF_LoopInvariant)) + flag = 1; + + if (obj3 == obj && obj2 != obj && (nd->u.diadic.right->u.diadic.left->flags & IROLF_LoopInvariant)) { + flag = 1; + tmpnd = nd->u.diadic.right->u.diadic.left; + nd->u.diadic.right->u.diadic.left = nd->u.diadic.right->u.diadic.right; + nd->u.diadic.right->u.diadic.right = tmpnd; + } + } else { + obj2 = IRO_IsVariable(nd->u.diadic.right->u.diadic.left); + obj3 = IRO_IsVariable(nd->u.diadic.right->u.diadic.right); + if (obj2 == obj && obj3 != obj && (nd->u.diadic.right->u.diadic.right->flags & IROLF_LoopInvariant)) + flag = 1; + } + } + + if (flag) { + if ((var = IRO_FindAssigned(nd))) { + if (var->xA == 2) + var->xA = 0; + else if (var->xA == 1) + var->xA = 2; + } + } else { + for (var = IRO_FirstVar; var; var = var->next) { + if (Bv_IsBitSet(var->index, IRO_VarKills)) + var->xA = 0; + } + } + + if (nd == fnode->last) + break; + nd = nd->next; + } + } + } + + IRO_DumpBits("Killed in loop: ", AllKills); + + for (fnode = IRO_FirstNode, FirstInd = NULL; fnode; fnode = fnode->nextnode) { + if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) { + while (1) { + if ( + ( + nd->type == IROLinearOp2Arg && + (nd->nodetype == EADDASS || nd->nodetype == ESUBASS || nd->nodetype == EASS) + ) + || + ( + nd->type == IROLinearOp1Arg && + (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC || nd->nodetype == EPREINC || nd->nodetype == EPREDEC) + ) + ) { + if ((var = IRO_FindAssigned(nd)) && var->xA == 2 && var->object->type->size <= 4) { + ind = oalloc(sizeof(IROLoopInd)); + ind->fnode = fnode; + ind->var = var; + ind->nd = nd; + ind->next = FirstInd; + ind->addNode = NULL; + ind->addConst = 0; + ind->flags = 0; + + if (nd->type == IROLinearOp2Arg) { + isUnsigned = IRO_IsUnsignedType(nd->rtype); + if (IRO_IsIntConstant(nd->u.diadic.right)) { + CInt64 val = nd->u.diadic.right->u.node->data.intval; + if (IS_LINEAR_DIADIC(nd, EADDASS) && CInt64_Less(val, cint64_zero)) { + nd->nodetype = ESUBASS; + nd->u.diadic.right->u.node->data.intval = CInt64_Neg(val); + } + if (isUnsigned) { + CInt64_ConvertUInt32(&nd->u.diadic.right->u.node->data.intval); + ind->addConst = CInt64_GetULong(&nd->u.diadic.right->u.node->data.intval); + } else { + CInt64_ConvertInt32(&nd->u.diadic.right->u.node->data.intval); + ind->addConst = CInt64_GetULong(&nd->u.diadic.right->u.node->data.intval); + } + ind->addNode = NULL; + } else if (nd->nodetype == EADDASS || nd->nodetype == ESUBASS) { + ind->addNode = nd->u.diadic.right; + } else if (nd->nodetype == EASS) { + ind->addNode = nd->u.diadic.right->u.diadic.right; + } + } else { + if (IS_TYPE_POINTER_ONLY(nd->rtype)) + ind->addConst = TPTR_TARGET(nd->rtype)->size; + else + ind->addConst = 1; + ind->addNode = NULL; + } + + FirstInd = ind; + + if (IS_LINEAR_DIADIC_2(nd, EADDASS, ESUBASS)) { + if (nd->u.diadic.right->flags & IROLF_LoopInvariant) + IRO_Dump("Found induction variable the new way: %s\n", var->object->name->name); + else + IRO_Dump("Found induction variable the old way: %s\n", var->object->name->name); + } else if (nd->type == IROLinearOp2Arg && (nd->u.diadic.right->nodetype == EADD || nd->u.diadic.right->nodetype == ESUB)) { + IRO_Dump("Found induction variable the new way: %s\n", var->object->name->name); + } else { + IRO_Dump("Found induction variable the old way: %s\n", var->object->name->name); + } + } + } + + if (nd == fnode->last) + break; + nd = nd->next; + } + } + } +} + +static void IRO_ActUnmarkLoopInvariance(IROLinear *linear, Boolean isFirst) { + if (isFirst) + linear->flags &= ~IROLF_LoopInvariant; +} + +static void UnmarkSubexpressionsOfInvariantExpressions(void) { + IROExpr *expr; + + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if ( + Bv_IsBitSet(expr->node->index, InLoop) && + !expr->notSubable && + (!expr->couldError || expr->node->mustreach) && + (expr->linear->flags & IROLF_LoopInvariant) + ) { + IRO_WalkTree(expr->linear, IRO_ActUnmarkLoopInvariance); + expr->linear->flags |= IROLF_LoopInvariant; + } + } +} + +static void MyHandleLoop_Vector(IRONode *fnode) { + IRONode *pred; + UInt16 i; + IROExpr *expr; + IROExpr *removedExprs; + IROExpr *exprnext; + IROLoopInd *induction; + IROExpr *exprinner; + Boolean flag24; + IRONode *v2; + IRONode *node22; + int flag21; + IRONode *iter; + IROExpr *searchris; + IROLinear *reduceNd1; + VarRecord *var; + IROLinear *reduceNd2; + + IRO_FirstExpr = NULL; + LoopNode = fnode; + FindMustReach(); + + for (var = IRO_FirstVar; var; var = var->next) + var->xA = 1; + + ComputeLoopKills(); + ComputeLoopInvariance(); + ComputeLoopInduction(); + LoopNode = fnode; + ConditionalHeaderAtBottom = 0; + + v2 = NULL; + flag21 = 0; + node22 = NULL; + for (i = 0; i < LoopNode->numpred; i++) { + pred = IRO_NodeTable[LoopNode->pred[i]]; + if (!Bv_IsBitSet(pred->index, InLoop)) { + if (flag21) + node22 = NULL; + else + node22 = pred; + flag21 = 1; + if (pred->nextnode == fnode) { + CError_ASSERT(2880, v2 == NULL || pred == v2); + v2 = pred; + } + } + } + + if (!flag21) { + IRO_Dump("No predecessor outside the loop\n"); + return; + } + + if (!node22 || node22->last->type != IROLinearGoto) + node22 = CreatePreHeader(fnode, v2); + PredInt = node22->last; + + if (PredInt->type == IROLinearGoto && PredInt->u.label.label != LoopNode->first->u.label.label) { + if (!KnownBounds || !Times) { + for (iter = IRO_FirstNode; iter; iter = iter->nextnode) + iter->mustreach = 0; + } else { + PredInt->u.label.label = LoopNode->first->u.label.label; + IRO_ComputeSuccPred(); + } + } + + if (copts.loopinvariants || copts.strengthreduction) { + MoveInvarianceInAddressExpr(); + IRO_DumpAfterPhase("MoveInvarianceInAddressExpr", 0); + IRO_FindExpressions(InLoop, 1); + IRO_DumpExprs(); + } + + if (copts.loopinvariants) + UnmarkSubexpressionsOfInvariantExpressions(); + + if (!copts.optimizesize && copts.strengthreduction) { + for (expr = IRO_FirstExpr; expr; expr = expr->next) { + if ( + !(expr->x0 & 4) && + Bv_IsBitSet(expr->node->index, InLoop) && + !expr->notSubable && + (!expr->couldError || expr->node->mustreach) && + Reducable(expr->linear, &reduceNd1, &reduceNd2, &var) + ) { + IRO_WalkTree(expr->linear, IRO_ActUnmarkRISCandidate); + expr->linear->flags |= IROLF_Ris; + expr->x1A = reduceNd1; + expr->x1E = var; + expr->x22 = reduceNd2; + } + } + } + + if (!copts.optimizesize && copts.strengthreduction) { + RisList = NULL; + for (expr = IRO_FirstExpr; expr; expr = exprnext) { + exprnext = expr->next; + if (!(expr->x0 & 4) && (expr->linear->flags & IROLF_Ris)) { + reduceNd1 = expr->x1A; + var = expr->x1E; + reduceNd2 = expr->x22; + + induction = FirstInd; + while (induction && induction->var != var) + induction = induction->next; + CError_ASSERT(3529, induction != NULL); + + IRO_FindDepends(reduceNd1); + if (!Bv_BitsInCommon(IRO_Depends, AllKills)) { + IRO_Dump("Found reduction in strength: %d\n", expr->linear->index); + if (IS_LINEAR_DIADIC(expr->linear, ESHL)) { + expr->linear->nodetype = EMUL; + CInt64_SetULong(&reduceNd1->u.node->data.intval, 1 << CInt64_GetULong(&reduceNd1->u.node->data.intval)); + reduceNd1->u.node->rtype = expr->linear->rtype; + } + + searchris = RisList; + while (1) { + if (!searchris) + break; + if (IRO_ExprsSame(expr->linear, searchris->linear)) + break; + searchris = searchris->next; + } + + if (searchris) { + IRO_Dump("Using existing RIS: %d\n", searchris->linear->index); + IRO_WalkTree(expr->linear, IRO_RemoveExpr_Action); + } else { + searchris = CreateRIS(expr, reduceNd2, reduceNd1, induction, 0); + } + IRO_ReplaceReference(expr->linear, searchris->x8, expr->linear); + IRO_ClipExpr(expr); + } + } + } + } + + RisList = NULL; + + expr = IRO_FirstExpr; + removedExprs = NULL; + if (copts.loopinvariants) { + while (expr) { + exprnext = expr->next; + flag24 = 0; + + if ( + Bv_IsBitSet(expr->node->index, InLoop) && + !expr->notSubable && + (!expr->couldError || expr->node->mustreach) && + (expr->linear->flags & IROLF_LoopInvariant) && + !(expr->x0 & 4) + ) { + IRO_Dump("Found loop invariant: %d\n", expr->linear->index); + + for (exprinner = removedExprs; exprinner; exprinner = exprinner->next) { + if (IRO_ExprsSame(exprinner->linear, expr->linear)) { + IRO_ReplaceReference(expr->linear, exprinner->x8, expr->linear); + IRO_NopOut(expr->linear); + IRO_Dump("Using already removed expr: %d\n", exprinner->linear->index); + IRO_RemoveExpr(expr); + flag24 = 1; + } + } + + if (!flag24 && !expr->x8) { + IRO_GetTemp(expr); + IRO_ReplaceReference(expr->linear, expr->x8, expr->linear); + IRO_MoveExpression(expr, PredInt); + IRO_AssignToTemp(expr); + IRO_RemoveExpr(expr); + expr->next = removedExprs; + removedExprs = expr; + } + } + + expr = exprnext; + } + } +} + +static void MyHandleLoop_Motion(IRONode *fnode) { + IROLoopMemRef *memref; + IRONode *pred; + UInt16 i; + IRONode *v2; + IRONode *node21; + Object *tempobj; + int flag20; + IRONode *iter; + IROLinear *ass; + VarRecord *var; + Boolean checkflag; + IROLoop *loop; + IROList list; + IROElmList *refiter; + + IRO_FirstExpr = NULL; + LoopNode = fnode; + FindMustReach(); + + for (var = IRO_FirstVar; var; var = var->next) + var->xA = 1; + + ComputeLoopKills(); + ComputeLoopInvariance(); + ComputeLoopInduction(); + LoopNode = fnode; + ConditionalHeaderAtBottom = 0; + + v2 = NULL; + flag20 = 0; + node21 = NULL; + for (i = 0; i < LoopNode->numpred; i++) { + pred = IRO_NodeTable[LoopNode->pred[i]]; + if (!Bv_IsBitSet(pred->index, InLoop)) { + if (flag20) + node21 = NULL; + else + node21 = pred; + flag20 = 1; + if (pred->nextnode == fnode) { + CError_ASSERT(3880, v2 == NULL || pred == v2); + v2 = pred; + } + } + } + + if (!flag20) { + IRO_Dump("No predecessor outside the loop\n"); + return; + } + + if (!node21 || node21->last->type != IROLinearGoto) + node21 = CreatePreHeader(fnode, v2); + PredInt = node21->last; + + if (PredInt->type == IROLinearGoto && PredInt->u.label.label != LoopNode->first->u.label.label) { + if (!KnownBounds || !Times) { + for (iter = IRO_FirstNode; iter; iter = iter->nextnode) + iter->mustreach = 0; + } else { + PredInt->u.label.label = LoopNode->first->u.label.label; + IRO_ComputeSuccPred(); + } + } + + if (copts.loopinvariants || copts.strengthreduction) { + MoveInvarianceInAddressExpr(); + IRO_DumpAfterPhase("MoveInvarianceInAddressExpr", 0); + IRO_FindExpressions(InLoop, 0); + IRO_DumpExprs(); + } + + if (copts.loopinvariants) + UnmarkSubexpressionsOfInvariantExpressions(); + + checkflag = 1; + Bv_AllocVector(&InLoop_Exits, IRO_NumNodes + 1); + Bv_AllocVector(&InLoop_Tails, IRO_NumNodes + 1); + LoopExitNumber = 0; + LoopExitSuccessor = NULL; + LoopTailNum = 0; + LoopTail = NULL; + IRO_FindLoopTailsAndExits(fnode); + FindMustReach1(fnode); + + loop = NULL; + if (LoopTailNum == 1) { + if (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot) + loop = ExtractLoopInfo(fnode); + else if (LoopTail->last->type == IROLinearIf || LoopTail->last->type == IROLinearIfNot) + loop = ExtractLoopInfo(LoopTail); + } + + if (loop && !(loop->flags & LP_IFEXPR_NON_CANONICAL) && LoopExitNumber == 1) { + IRO_LoopMemRefFirst = NULL; + IRO_LoopMemRefCurrent = NULL; + CheckAllLoopAddresses(IRO_FirstNode, InLoop, &checkflag); + CheckAllLoopAddresses(IRO_FirstNode, InLoop, &checkflag); + if (checkflag) { + for (memref = IRO_LoopMemRefFirst; memref; memref = memref->next) { + if (memref->flags & LoopMemRef_10) + memref->flags |= LoopMemRef_8; + } + + for (memref = IRO_LoopMemRefFirst; memref; memref = memref->next) { + IRO_Dump("Loop Motion Candidate:: Int= %d", memref->nd->index); + if (memref->flags & LoopMemRef_8) + IRO_Dump(""); + if (memref->flags & LoopMemRef_1) + IRO_Dump(""); + if (memref->flags & LoopMemRef_2) + IRO_Dump(""); + IRO_Dump("\n"); + + if (!(memref->flags & LoopMemRef_8)) { + tempobj = create_temp_object(memref->nd->rtype); + IRO_FindVar(tempobj, 1, 1); + if (IRO_FindVar(((IROLinear *) memref->rec->objRefs->element)->u.node->data.objref, 0, 1)) { + IRO_InitList(&list); + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->index = ++IRO_NumLinear; + ass->rtype = memref->nd->rtype; + ass->nodetype = EASS; + ass->u.diadic.left = IRO_TempReference(tempobj, &list); + ass->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned; + ass->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned; + ass->u.diadic.right = IRO_DuplicateExpr(memref->nd, &list); + IRO_AddToList(ass, &list); + IRO_Paste(list.head, list.tail, PredInt); + } else { + CError_FATAL(4123); + } + + if (LoopExitSuccessor->numpred != 1) + LoopExitSuccessor = CreateNewLoopExitSuccessor(LoopExitSuccessor); + + IRO_InitList(&list); + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->index = ++IRO_NumLinear; + ass->rtype = memref->nd->rtype; + ass->nodetype = EASS; + ass->u.diadic.left = IRO_DuplicateExpr(memref->nd, &list); + ass->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned; + ass->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned; + ass->u.diadic.right = IRO_TempReference(tempobj, &list); + IRO_AddToList(ass, &list); + + if (LoopExitSuccessor->first->type == IROLinearLabel) + IRO_PasteAfter(list.head, list.tail, LoopExitSuccessor->first); + else + IRO_Paste(list.head, list.tail, LoopExitSuccessor->first); + + for (refiter = memref->list; refiter; refiter = refiter->next) { + IRO_Dump("Loop Motion Candidate Reference at Int= %d\n", ((IROLinear *) refiter->element)->index); + IRO_InitList(&list); + IRO_TempReference(tempobj, &list); + IRO_Paste(list.head, list.tail, refiter->element); + IRO_LocateFather_Cut_And_Paste(refiter->element, list.tail); + } + } + } + } + } + + IRO_DumpAfterPhase("After Motion", 0); +} + +static Boolean CheckLoopAddress(IROLinear *nd, Boolean mustreach1) { + IROLoopMemRef *memref; + IROAddrRecord *rec; + IROAddrRecord *otherrec; + IROLinear *inner; + IROElmList *list; + Boolean flag; + + inner = nd->u.monadic; + rec = IRO_InitAddrRecordPointer(inner); + if (IS_LINEAR_ENODE(inner, EOBJREF)) { + rec->numObjRefs++; + IRO_AddElmToList(inner, &rec->objRefs); + } else if (IS_LINEAR_DIADIC(inner, EADD)) { + IRO_DecomposeAddressExpression(inner, rec); + } else { + return 0; + } + + if (rec->numObjRefs != 1) + return 0; + + flag = (nd->flags & IROLF_CouldError) || !(nd->flags & IROLF_Reffed); + if (!IRO_LoopMemRefFirst) { + MakeLoopEntry(nd, rec, mustreach1, flag); + } else { + for (memref = IRO_LoopMemRefFirst; memref; memref = memref->next) { + otherrec = memref->rec; + if (((IROLinear *) rec->objRefs->element)->u.node->data.objref == ((IROLinear *) otherrec->objRefs->element)->u.node->data.objref) { + if (IRO_ExprsSame(inner, otherrec->linear)) { + list = oalloc(sizeof(IROElmList)); + list->element = nd; + list->next = NULL; + if (!memref->list) { + memref->list = list; + } else { + list->next = memref->list; + memref->list = list; + } + } else { + memref->flags |= LoopMemRef_8; + } + + if (!mustreach1 && flag) + memref->flags |= LoopMemRef_8; + if (mustreach1 || flag) + memref->flags &= ~LoopMemRef_10; + break; + } + } + + if (!memref) + MakeLoopEntry(nd, rec, mustreach1, flag); + } + + return 1; +} + +static void CheckAllLoopAddresses(IRONode *fnode, BitVector *bv, Boolean *resultFlag) { + IROLinear *nd; + Boolean flag; + + flag = *resultFlag; + while (fnode) { + if (Bv_IsBitSet(fnode->index, bv) && (nd = fnode->first)) { + while (flag) { + if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT) + flag = CheckLoopAddress(nd, fnode->mustreach1); + else if (nd->type == IROLinearFunccall) + flag = 0; + + if (nd == fnode->last) + break; + nd = nd->next; + } + + if (!flag) + break; + } + fnode = fnode->nextnode; + } + *resultFlag = flag; +} + +static void MakeLoopEntry(IROLinear *nd, IROAddrRecord *rec, Boolean mustreach1, Boolean flag2) { + IROElmList *list; + + if (!IRO_IsRegable(((IROLinear *) rec->objRefs->element)->u.node->data.objref) && + (nd->u.monadic->flags & IROLF_LoopInvariant) && + !IRO_HasSideEffect(nd)) { + if (!IRO_LoopMemRefFirst) { + IRO_LoopMemRefCurrent = IRO_LoopMemRefFirst = oalloc(sizeof(IROLoopMemRef)); + } else { + IRO_LoopMemRefCurrent->next = oalloc(sizeof(IROLoopMemRef)); + IRO_LoopMemRefCurrent = IRO_LoopMemRefCurrent->next; + } + IRO_LoopMemRefCurrent->flags = LoopMemRef_10; + IRO_LoopMemRefCurrent->nd = nd; + IRO_LoopMemRefCurrent->rec = rec; + IRO_LoopMemRefCurrent->next = NULL; + IRO_LoopMemRefCurrent->list = NULL; + + list = oalloc(sizeof(IROElmList)); + list->element = nd; + list->next = NULL; + if (!IRO_LoopMemRefCurrent->list) { + IRO_LoopMemRefCurrent->list = list; + } else { + list->next = IRO_LoopMemRefCurrent->list; + IRO_LoopMemRefCurrent->list = list; + } + + if (((IROLinear *) rec->objRefs->element)->flags & IROLF_Assigned) { + IRO_LoopMemRefCurrent->flags |= LoopMemRef_2; + if (((IROLinear *) rec->objRefs->element)->flags & IROLF_Used) + IRO_LoopMemRefCurrent->flags |= LoopMemRef_1; + } else { + IRO_LoopMemRefCurrent->flags |= LoopMemRef_1; + } + + if (!mustreach1 && flag2) + IRO_LoopMemRefCurrent->flags |= LoopMemRef_8; + + if (mustreach1 || flag2) + IRO_LoopMemRefCurrent->flags &= ~LoopMemRef_10; + } +} + +void FindAssignmenttoInductionVar(IROLoop *loop, IRONode *fnode) { + IROLinear *nd; + UInt32 index; + + if (!loop->induction) { + loop->nd14 = NULL; + } else { + index = loop->induction->var->index; + for (nd = fnode->first; nd; nd = nd->next) { + Bv_Clear(IRO_VarKills); + IRO_GetKills(nd); + if (Bv_IsBitSet(index, IRO_VarKills)) + loop->nd14 = nd; + + if (nd == fnode->last) + break; + } + + if (loop->nd14 && loop->nd14->type != IROLinearOp2Arg) + loop->nd14 = NULL; + } +} + +static void ComputeIntWeight(IROLoop *loop, IROLinear *Int) { + loop->sizeBySomeMeasurement++; +} + +static IROLinear *IsTypconVar(IROLinear *nd) { + if (IS_LINEAR_MONADIC(nd, ETYPCON) && IRO_IsVariable(nd->u.monadic)) + return nd->u.monadic; + else + return NULL; +} + +IROLoop *ExtractLoopInfo(IRONode *fnode) { + Boolean flag30; + Boolean flag29; + Boolean flag28; + UInt32 counter27; + IROLoopInd *ind23; + Object *obj; + IROLinear *nd21; + IRONode *scanfnode; + IROLinear *left19; + IROLinear *right18; + IROLinear *tmp18; + IROLinear *scannd; + IROLinear *tmp; + VarRecord *var; + IROLoopInd *scanind; + IROLinear *left; + IROLinear *right; + UInt32 counter2; + UInt32 i; + IROLoop *loop; + + flag30 = 0; + flag29 = 0; + flag28 = 0; + counter27 = 0; + LoopNode = fnode; + + loop = oalloc(sizeof(IROLoop)); + loop->fnode = fnode; + nd21 = LoopNode->last->u.label.x4; + loop->nd18 = nd21; + loop->flags = 0; + loop->x8 = 0; + loop->nd14 = NULL; + loop->induction = NULL; + loop->index20 = -1; + loop->index24 = -1; + loop->sizeBySomeMeasurement = 0; + + if (nd21->type == IROLinearOp2Arg && IS_TYPE_INT(nd21->rtype)) { + ind23 = NULL; + left19 = nd21->u.diadic.left; + right18 = nd21->u.diadic.right; + if (IRO_IsVariable(left19) || (left19 = IsTypconVar(left19))) { + if ((var = IRO_FindVar(left19->u.monadic->u.node->data.objref, 0, 1))) { + scanind = FirstInd; + while (scanind && scanind->var != var) + scanind = scanind->next; + if (scanind) { + ind23 = scanind; + loop->flags |= LoopFlags_1; + loop->induction = scanind; + } + } + } + + if (IRO_IsVariable(right18) || (right18 = IsTypconVar(right18))) { + if ((var = IRO_FindVar(right18->u.monadic->u.node->data.objref, 0, 1))) { + scanind = FirstInd; + while (scanind && scanind->var != var) + scanind = scanind->next; + if (scanind) { + ind23 = scanind; + loop->flags &= ~LoopFlags_1; + loop->induction = scanind; + } + } + } + + if (ind23 && ind23->addConst > 0) { + if (loop->flags & LoopFlags_1) { + if ( + loop->nd18->type != IROLinearOp2Arg || + !(loop->nd18->nodetype == ELESS || loop->nd18->nodetype == EGREATER || loop->nd18->nodetype == ELESSEQU || loop->nd18->nodetype == EGREATEREQU) || + !loop->nd18->u.diadic.left || + !loop->nd18->u.diadic.left->rtype || + !IS_TYPE_INT(loop->nd18->u.diadic.left->rtype) || + !loop->nd18->u.diadic.right || + !loop->nd18->u.diadic.right->rtype || + !IS_TYPE_INT(loop->nd18->u.diadic.right->rtype) + ) { + loop->flags |= LP_IFEXPR_NON_CANONICAL; + return loop; + } + } else { + if ( + loop->nd18->type == IROLinearOp2Arg && + (loop->nd18->nodetype == EGREATER || loop->nd18->nodetype == EGREATEREQU) && + (left = loop->nd18->u.diadic.left) && + left->rtype && + IS_TYPE_INT(left->rtype) && + (right = loop->nd18->u.diadic.right) && + right->rtype && + IS_TYPE_INT(right->rtype) + ) { + loop->nd18->u.diadic.left = right; + loop->nd18->u.diadic.right = left; + if (loop->nd18->nodetype == EGREATER) + loop->nd18->nodetype = ELESS; + else if (loop->nd18->nodetype == EGREATEREQU) + loop->nd18->nodetype = ELESSEQU; + loop->flags |= LoopFlags_1; + } else if ( + loop->nd18->type == IROLinearOp2Arg && + (loop->nd18->nodetype == ELESS || loop->nd18->nodetype == ELESSEQU) && + (left = loop->nd18->u.diadic.left) && + left->rtype && + IS_TYPE_INT(left->rtype) && + (right = loop->nd18->u.diadic.right) && + right->rtype && + IS_TYPE_INT(right->rtype) + ) { + loop->nd18->u.diadic.left = right; + loop->nd18->u.diadic.right = left; + if (loop->nd18->nodetype == ELESS) + loop->nd18->nodetype = EGREATER; + else if (loop->nd18->nodetype == ELESSEQU) + loop->nd18->nodetype = EGREATEREQU; + loop->flags |= LoopFlags_1; + } else { + loop->flags |= LP_IFEXPR_NON_CANONICAL; + return loop; + } + } + } else { + loop->flags |= LP_INDUCTION_NOT_FOUND; + return loop; + } + } else if (nd21->type == IROLinearOp1Arg && IS_TYPE_INT(nd21->rtype)) { + if (nd21->nodetype == EPREINC || nd21->nodetype == EPOSTINC || nd21->nodetype == EPREDEC || nd21->nodetype == EPOSTDEC) { + if (IRO_IsVariable(nd21->u.monadic)) { + if ((var = IRO_FindVar(nd21->u.monadic->u.monadic->u.node->data.objref, 0, 1))) { + scanind = FirstInd; + while (scanind && scanind->var != var) + scanind = scanind->next; + if (scanind) { + ind23 = scanind; + loop->flags |= LoopFlags_10000; + loop->induction = scanind; + } else { + loop->flags |= LP_INDUCTION_NOT_FOUND; + return loop; + } + } else { + loop->flags |= LP_INDUCTION_NOT_FOUND; + return loop; + } + } else { + loop->flags |= LP_INDUCTION_NOT_FOUND; + return loop; + } + } else { + loop->flags |= LP_INDUCTION_NOT_FOUND; + return loop; + } + } else { + loop->flags |= LP_IFEXPR_NON_CANONICAL; + return loop; + } + + counter2 = 0; + scanind = FirstInd; + while (scanind) { + scanind = scanind->next; + counter2++; + } + + if (counter2 > 1) + loop->flags |= LP_HAS_MULTIPLE_INDUCTIONS; + + if ((scanind = loop->induction)) { + nd21 = scanind->nd; + if (nd21->type == IROLinearOp2Arg) { + if (IS_LINEAR_DIADIC_2(loop->nd18, ELESS, ELESSEQU)) { + if (nd21->nodetype == EADDASS) { + if (scanind->addConst == 1) + loop->flags |= LP_LOOP_STEP_ISADD; + if (scanind->addConst > 0) + loop->flags |= LP_LOOP_STEP_ISPOS; + } else if (nd21->nodetype == EASS && + IS_LINEAR_DIADIC(nd21->u.diadic.right, EADD) && + IRO_IsIntConstant(tmp18 = nd21->u.diadic.right->u.diadic.right) && + CTool_EndianReadWord32(&tmp18->u.node->data.intval.hi) == 0) { + if (CInt64_GetULong(&tmp18->u.node->data.intval) == 1) + loop->flags |= LP_LOOP_STEP_ISADD; + if (CInt64_GetULong(&tmp18->u.node->data.intval) > 0) + loop->flags |= LP_LOOP_STEP_ISPOS; + } + } + } else if (nd21->type == IROLinearOp1Arg) { + if (nd21->nodetype == EPREINC || nd21->nodetype == EPOSTINC) { + if (scanind->addConst == 1) + loop->flags |= LP_LOOP_STEP_ISADD; + if (scanind->addConst > 0) + loop->flags |= LP_LOOP_STEP_ISPOS; + } + if (nd21->nodetype == EPREDEC || nd21->nodetype == EPOSTDEC) { + if (scanind->addConst == 1) + loop->flags |= LoopFlags_2000; + if (scanind->addConst > 0) + loop->flags |= LP_LOOP_STEP_ISNEG; + } + } + loop->index24 = nd21->index; + loop->index20 = IRO_FindStart(nd21)->index; + } + + if (ind23) { + tmp = IRO_FindStart(fnode->last->u.diadic.right); + loop->flags |= LoopFlags_200; + if (loop->flags & LoopFlags_10000) { + for (scannd = loop->fnode->first; scannd && scannd != tmp; scannd = scannd->next) { + if (scannd->type != IROLinearLabel && scannd->type != IROLinearNop) + loop->flags &= ~LoopFlags_200; + } + } else { + for (scannd = ind23->nd->next; scannd && scannd != tmp; scannd = scannd->next){ + if (scannd->type != IROLinearLabel && scannd->type != IROLinearNop) + loop->flags &= ~LoopFlags_200; + } + for (scannd = loop->fnode->first; scannd && scannd != tmp; scannd = scannd->next){ + if ((scannd->index < loop->index20 || scannd->index > loop->index24) && scannd->type != IROLinearLabel && scannd->type != IROLinearNop) + loop->flags &= ~LoopFlags_200; + } + } + } + + for (scanfnode = IRO_FirstNode; scanfnode; scanfnode = scanfnode->nextnode) { + if (Bv_IsBitSet(scanfnode->index, InLoop) && scanfnode != fnode && (scannd = scanfnode->first)) { + while (1) { + if (scannd->type == IROLinearFunccall) + flag30 = 1; + if (scannd->type == IROLinearGoto) + flag28++; + if (flag28 >= 1) + flag29 = 1; + if (scannd->type == IROLinearIf || scannd->type == IROLinearIfNot || scannd->type == IROLinearSwitch || scannd->type == IROLinearReturn) + flag29 = 1; + + if (scannd->type == IROLinearAsm) + loop->flags |= LP_LOOP_HAS_ASM; + + if (!(scannd->flags & IROLF_Reffed) && scannd->type != IROLinearNop && scannd->type != IROLinearLabel) { + if (!IRO_IsAssignOp[scannd->nodetype]) { + loop->flags |= LoopFlags_8; + } else if (scannd->index < loop->index20 || scannd->index > loop->index24) { + counter27++; + if (IsAssignmentReductionCandidate(scannd) && counter27 == 1) + loop->flags |= LoopFlags_40000; + if (counter27 > 1) + loop->flags &= ~LoopFlags_40000; + } + } + + if (scannd->index < loop->index20 || scannd->index > loop->index24) { + if (IS_LINEAR_ENODE(scannd, EOBJREF)) { + obj = scannd->u.node->data.objref; + if ((scannd->flags & IROLF_Ind) && obj && obj == loop->induction->var->object) { + if (!(scannd->flags & IROLF_Assigned) && (scannd->flags & IROLF_Used)) { + IRO_Dump("Induction Used in loop\n"); + loop->flags |= LoopFlags_800; + } + } + } + + if (IS_LINEAR_DIADIC(scannd, ESHR) && + (obj = IRO_IsVariable(scannd->u.diadic.left)) && + IRO_IsIntConstant(scannd->u.diadic.right)) { + for (scanind = FirstInd; scanind; scanind = scanind->next) { + if (scanind->var->object == obj) { + IRO_Dump("Induction has DIV: %s\n", obj->name->name); + scanind->flags |= LoopInd_HasDiv; + } + } + } + + if (IS_LINEAR_DIADIC(scannd, EAND) && + (obj = IRO_IsVariable(scannd->u.diadic.left)) && + IRO_IsIntConstant(scannd->u.diadic.right)) { + for (scanind = FirstInd; scanind && obj; scanind = scanind->next) { + if (scanind->var->object == obj) { + IRO_Dump("Induction has MOD: %s\n", obj->name->name); + scanind->flags |= LoopInd_HasMod; + } + } + } + } + + ComputeIntWeight(loop, scannd); + if (scannd == scanfnode->last) + break; + scannd = scannd->next; + } + } + + if (flag30) + loop->flags |= LP_LOOP_HAS_CALLS; + if (flag29) + loop->flags |= LP_LOOP_HAS_CNTRLFLOW; + + for (i = 0; i < scanfnode->numsucc && scanfnode != fnode; i++) { + if (Bv_IsBitSet(scanfnode->index, InLoop) && !Bv_IsBitSet(scanfnode->succ[i], InLoop)) { + IRO_Dump("Node %d has an out of loop successor %d\n", scanfnode->index, scanfnode->succ[i]); + IRO_DumpBits("Loop includes: ", InLoop); + IRO_Dump("loop has multiple exits\n"); + loop->flags |= LoopFlags_1000; + } + } + } + + return loop; +} + +CLabel *BuildLabel(IROList *list) { + IROLinear *nd; + + nd = IRO_NewLinear(IROLinearLabel); + nd->index = IRO_NumLinear++; + nd->u.label.label = IRO_NewLabel(); + nd->flags |= IROLF_1; + IRO_AddToList(nd, list); + return nd->u.label.label; +} + +static void MoveInvarianceInAddressExpr(void) { + IRONode *fnode; + IROLinear *nd; + IROLinear *start; + IROList list; + + IRO_FirstExpr = IRO_LastExpr = NULL; + IRO_NumExprs = 0; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (Bv_IsBitSet(fnode->index, InLoop)) { + for (nd = fnode->first; nd; nd = nd->next) { + if (nd->type == IROLinearOp1Arg && + (nd->nodetype == EINDIRECT || nd->nodetype == EINDIRECT) && + IS_LINEAR_DIADIC(nd->u.monadic, EADD)) { + RearrangeInvarianceInAddressExpr(nd->u.monadic, &list); + start = IRO_FindStart(nd->u.monadic); + IRO_LocateFather_Cut_And_Paste(nd->u.monadic, list.tail); + IRO_Paste(list.head, list.tail, start); + } + + if (nd == fnode->last) + break; + } + } + } + + IRO_UpdateFlagsOnInts(); +} + +static void AddAddendLinear(IROLinear *nd) { + IROElmList *list; + + if (IS_LINEAR_DIADIC(nd, EADD)) { + AddAddendLinear(nd->u.diadic.left); + AddAddendLinear(nd->u.diadic.right); + } else { + list = oalloc(sizeof(IROElmList)); + list->element = nd; + list->next = NULL; + if (FirstAddendLinear) + LastAddendLinear->next = list; + else + FirstAddendLinear = list; + LastAddendLinear = list; + } +} + +static IROLinear *RearrangeInvarianceInAddressExpr(IROLinear *nd, IROList *list) { + IROLinear *result; + IROElmList *scanlist; + IROElmList *elist; + IROLinear *scannd; + + IRO_InitList(list); + FirstAddendLinear = LastAddendLinear = NULL; + AddAddendLinear(nd->u.diadic.left); + AddAddendLinear(nd->u.diadic.right); + + elist = NULL; + result = NULL; + for (scanlist = FirstAddendLinear; scanlist; scanlist = scanlist->next) { + scannd = scanlist->element; + if (!IRO_IsIntConstant(scannd) && (scannd->flags & IROLF_LoopInvariant)) { + if (result) { + IROLinear *tmp = IRO_NewLinear(IROLinearOp2Arg); + tmp->index = ++IRO_NumLinear; + tmp->nodetype = EADD; + tmp->u.diadic.left = result; + tmp->u.diadic.right = IRO_DuplicateExpr(scannd, list); + IRO_AddToList(tmp, list); + tmp->flags |= IROLF_LoopInvariant; + tmp->flags |= IROLF_Reffed; + tmp->rtype = result->rtype; + result = tmp; + } else { + result = IRO_DuplicateExpr(scannd, list); + } + + if (elist) + elist->next = scanlist->next; + else + FirstAddendLinear = scanlist->next; + } else { + elist = scanlist; + } + } + + for (scanlist = FirstAddendLinear, elist = NULL; scanlist; scanlist = scanlist->next) { + scannd = scanlist->element; + if (!IRO_IsIntConstant(scannd)) { + if (result) { + IROLinear *tmp = IRO_NewLinear(IROLinearOp2Arg); + tmp->index = ++IRO_NumLinear; + tmp->nodetype = EADD; + tmp->u.diadic.left = result; + tmp->u.diadic.right = IRO_DuplicateExpr(scannd, list); + IRO_AddToList(tmp, list); + tmp->flags |= IROLF_Reffed; + tmp->rtype = result->rtype; + result = tmp; + } else { + result = IRO_DuplicateExpr(scannd, list); + } + + if (elist) + elist->next = scanlist->next; + else + FirstAddendLinear = scanlist->next; + } else { + elist = scanlist; + } + } + + for (scanlist = FirstAddendLinear; scanlist; scanlist = scanlist->next) { + scannd = scanlist->element; + if (result) { + IROLinear *tmp = IRO_NewLinear(IROLinearOp2Arg); + tmp->index = ++IRO_NumLinear; + tmp->nodetype = EADD; + tmp->u.diadic.left = result; + tmp->u.diadic.right = scannd; + tmp->u.diadic.right = IRO_DuplicateExpr(scannd, list); + IRO_AddToList(tmp, list); + tmp->flags |= IROLF_Reffed; + tmp->rtype = result->rtype; + result = tmp; + } else { + result = IRO_DuplicateExpr(scannd, list); + } + } + + return result; +} + +static IROLinear *FindAddendForReductionPattern(IROLinear *a, IROLinear *b, Boolean *resultFlag) { + IROLinear *left; + IROLinear *right; + IROLinear *node28; + Boolean subflag; + + left = b->u.diadic.left; + right = b->u.diadic.right; + if (b->nodetype == EADD || b->nodetype == ESUB) { + node28 = left; + while (IS_LINEAR_MONADIC(node28, ETYPCON)) + node28 = node28->u.monadic; + + if (IS_LINEAR_MONADIC(node28, EINDIRECT) && (node28->u.monadic->flags & IROLF_LoopInvariant) && IRO_ExprsSame(a, node28)) { + *resultFlag = 1; + return left; + } + + if (IS_LINEAR_DIADIC_2(node28, EADD, ESUB)) { + if ((node28 = FindAddendForReductionPattern(a, node28, &subflag))) { + *resultFlag = 1; + return node28; + } + } + } + + *resultFlag = 0; + if (b->nodetype == EADD) { + node28 = right; + while (IS_LINEAR_MONADIC(node28, ETYPCON)) + node28 = node28->u.monadic; + + if (IS_LINEAR_MONADIC(node28, EINDIRECT) && (node28->u.monadic->flags & IROLF_LoopInvariant) && IRO_ExprsSame(a, node28)) { + return right; + } + + if (IS_LINEAR_DIADIC_2(node28, EADD, ESUB)) { + if ((node28 = FindAddendForReductionPattern(a, node28, &subflag))) { + return node28; + } + } + } + + return NULL; +} + +static void ReorderOperandsForReductionPattern(IROLinear *a, IROLinear *b) { + IROLinear *left; + IROLinear *right; + IROLinear *addend; + IROLinear *tmp; + Boolean flag; + + left = b->u.diadic.left; + right = b->u.diadic.right; + + if (b->nodetype == EADD && (addend = FindAddendForReductionPattern(a, b, &flag)) && addend != left) { + if (flag && IS_LINEAR_DIADIC_2(left, EADD, ESUB) && addend->rtype == right->rtype) { + tmp = left; + b->u.diadic.left = right; + left = right; + b->u.diadic.right = tmp; + right = tmp; + flag = 0; + } + + if (!flag && IS_LINEAR_DIADIC_2(right, EADD, ESUB) && addend->rtype == left->rtype) { + if (IRO_LocateFather_Cut_And_Paste_Without_Nopping(addend, left)) + b->u.diadic.left = addend; + } + } +} + +static UInt32 IsAssignmentReductionCandidate(IROLinear *nd) { + IROLinear *left; + IROLinear *right; + IROLinear *tmp; + + if (nd->type == IROLinearOp2Arg) { + if (nd->nodetype == EASS) { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + if (IS_LINEAR_MONADIC(left, EINDIRECT) && (left->u.monadic->flags & IROLF_LoopInvariant)) { + if (IS_LINEAR_MONADIC(right, ETYPCON) && + right->rtype->type == right->u.monadic->rtype->type && + IS_TYPE_INT(right->rtype) && + right->rtype->size < right->u.monadic->rtype->size) + right = right->u.monadic; + + if (IS_LINEAR_DIADIC_2(right, EADD, ESUB)) { + ReorderOperandsForReductionPattern(left, right); + tmp = right->u.diadic.left; + if (IS_LINEAR_MONADIC(tmp, ETYPCON)) + tmp = tmp->u.monadic; + if (IS_LINEAR_MONADIC(tmp, EINDIRECT) && + (tmp->u.monadic->flags & IROLF_LoopInvariant) && + IRO_ExprsSame(left, tmp) && + right->u.diadic.right->type == IROLinearOp2Arg) { + if (right->u.diadic.right->nodetype == EADD) + return 1; + if (right->u.diadic.right->nodetype == ESUB) + return 1; + if (right->u.diadic.right->nodetype == EMUL) + return 1; + if (right->u.diadic.right->nodetype == EDIV) + return 1; + } + } + } + } else if (nd->nodetype == EADDASS || nd->nodetype == ESUBASS) { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + + if (IS_LINEAR_MONADIC(right, ETYPCON) && + right->rtype->type == right->u.monadic->rtype->type && + IS_TYPE_INT(right->rtype) && + right->rtype->size < right->u.monadic->rtype->size) + right = right->u.monadic; + + if (IS_LINEAR_MONADIC(left, EINDIRECT) && + (left->u.monadic->flags & IROLF_LoopInvariant) && + right->type == IROLinearOp2Arg) { + if (right->nodetype == EADD) + return 1; + if (right->nodetype == ESUB) + return 1; + if (right->nodetype == EMUL) + return 1; + if (right->nodetype == EDIV) + return 1; + } + } + } + + return 0; +} + diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroLoop.h b/compiler_and_linker/FrontEnd/Optimizer/IroLoop.h new file mode 100644 index 0000000..2d968ad --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroLoop.h @@ -0,0 +1,111 @@ +#ifndef COMPILER_IROLOOP_H +#define COMPILER_IROLOOP_H + +#include "IrOptimizer.h" +#include "BitVector.h" + +typedef enum IROLoopIndFlags { + LoopInd_HasMod = 1, + LoopInd_HasDiv = 2, + LoopInd_4 = 4, + LoopInd_8 = 8 +} IROLoopIndFlags; + +typedef enum IROLoopFlags { + LoopFlags_1 = 1, // LP_INDUCTION_AT_LEFT + LP_LOOP_HAS_CALLS = 2, + LP_LOOP_HAS_CNTRLFLOW = 4, + LoopFlags_8 = 8, // LP_HAS_NONASSIGN + LP_INDUCTION_NOT_FOUND = 0x10, + LP_IFEXPR_NON_CANONICAL = 0x20, + LP_HAS_MULTIPLE_INDUCTIONS = 0x40, + LP_LOOP_HDR_HAS_SIDEEFFECTS = 0x80, + LP_LOOP_STEP_ISADD = 0x100, + LoopFlags_200 = 0x200, // LP_HEADER_FOLLOWS_UPDATE? + LP_LOOP_STEP_ISPOS = 0x400, + LoopFlags_800 = 0x800, // LP_IND_USED_IN_LOOP + LoopFlags_1000 = 0x1000, // LP_HAS_MULTIPLE_EXITS + LoopFlags_2000 = 0x2000, // inverse of LP_LOOP_STEP_ISADD? + LP_LOOP_STEP_ISNEG = 0x4000, + LP_LOOP_HAS_ASM = 0x8000, + LoopFlags_10000 = 0x10000, // LP_WHILE_LOOP + LoopFlags_20000 = 0x20000, // maybe LP_RECURSIVE_LOOP? + LoopFlags_40000 = 0x40000 // LP_IS_REDUCTION_CAND +} IROLoopFlags; + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct IROLoopInd { + IROLoopIndFlags flags; + VarRecord *var; + IRONode *fnode; + IROLinear *nd; + SInt32 addConst; + IROLinear *addNode; + struct IROLoopInd *next; +} IROLoopInd; + +struct IROLoop { + SInt32 flags; + IRONode *fnode; + int x8; + IRONode *xC; + IRONode *x10; + IROLinear *nd14; // assignment expression that sets the initial value of induction + IROLinear *nd18; // ifexpr? + IROLoopInd *induction; + int index20; + int index24; + CInt64 x28; + CInt64 x30; + int sizeBySomeMeasurement; +}; + +typedef enum IROLoopMemRefFlags { + LoopMemRef_1 = 1, + LoopMemRef_2 = 2, + LoopMemRef_4 = 4, + LoopMemRef_8 = 8, + LoopMemRef_10 = 0x10 +} IROLoopMemRefFlags; + +typedef struct IROLoopMemRef { + IROLoopMemRefFlags flags; + IROLinear *nd; + IROElmList *list; + IROAddrRecord *rec; + struct IROLoopMemRef *next; +} IROLoopMemRef; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +extern IRONode *LoopNode; +extern Boolean ConditionalHeaderAtBottom; +extern IROLoopInd *FirstInd; +extern BitVector *InLoop; +extern IROList IRO_InitLList; +extern BitVector *InLoop_Exits; +extern BitVector *InLoop_Tails; +extern UInt32 LoopExitNumber; +extern UInt32 LoopTailNum; +extern IRONode *LoopExitSuccessor; +extern IRONode *LoopTail; +extern IROLoopMemRef *IRO_LoopMemRefFirst; +extern IROLoopMemRef *IRO_LoopMemRefCurrent; + +extern void FindMustReach(void); +extern void FindMustReach1(IRONode *checkfnode); +extern void AddPreds(IRONode *fnode); +extern void IncLoopDepth(void); +extern void IRO_SetLoopDepth(void); +extern void IRO_FindLoops(void); +extern void ComputeLoopKills(void); +extern void ComputeLoopInvariance(void); +extern void ComputeLoopInduction(void); +extern void FindAssignmenttoInductionVar(IROLoop *loop, IRONode *fnode); +extern IROLoop *ExtractLoopInfo(IRONode *fnode); +extern CLabel *BuildLabel(IROList *list); + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroMalloc.c b/compiler_and_linker/FrontEnd/Optimizer/IroMalloc.c new file mode 100644 index 0000000..1f15cad --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroMalloc.c @@ -0,0 +1,564 @@ +#include "IroMalloc.h" +#include "compiler/CompilerTools.h" + +#define FLAGMASK 0xF + +typedef struct Block { + struct Block *prev; + struct Block *next; + void *x8; + void *xC; + size_t remain; + size_t x14; +} Block; + +typedef struct SubBlockBase { + size_t x0; + Block *block; +} SubBlockBase; + +typedef struct SubBlock { + size_t x0; + Block *block; + struct SubBlock *x8; + struct SubBlock *xC; +} SubBlock; + +typedef struct SubBlockTail { + size_t x0copy; +} SubBlockTail; + +typedef struct BlockTail { + size_t x14copy; + SubBlock *unk; +} BlockTail; + +typedef struct FixStart { + struct FixBlock *a; + struct FixSubBlock *b; + long count; +} FixStart; + +typedef struct FixBlock { + struct FixBlock *prev; + struct FixBlock *next; + size_t entrysize; +} FixBlock; + +typedef struct FixSubBlockBase { + FixBlock *fixblock; +} FixSubBlockBase; + +typedef struct FixSubBlock { + FixBlock *fixblock; + struct FixSubBlock *next; +} FixSubBlock; + +static const size_t fix_pool_sizes[] = {0xC, 0x1C, 0x2C, 0x4C}; +static Block *start_; +static FixStart fix_start[4]; +static int initialized; + +// forward decls +static void Block_link(Block *block, SubBlock *subblock); +static void Block_unlink(Block *block, SubBlock *subblock); +static void SubBlock_construct(SubBlock *subblock, size_t size, Block *block, int flag1, int flag2); +static SubBlock *SubBlock_split(SubBlock *subblock, size_t pos); +static SubBlock *SubBlock_merge_prev(SubBlock *subblock, SubBlock **sbptr); +static void SubBlock_merge_next(SubBlock *subblock, SubBlock **sbptr); + +#define BLOCK_TAIL(block) ((BlockTail *) ((long) (block) + ((block)->x14 & ~FLAGMASK) - sizeof(BlockTail))) + +#define BUF_LOCATOR(buf) (*((size_t *) ((long) (buf) - sizeof(size_t)))) +#define SBB_BLOCK(sbb) ((Block *) ((long) ((sbb)->block) & ~1)) + +#define BUF_IS_VAR(buf) (BUF_LOCATOR(buf) & 1) +#define VARBUF_SBB(buf) ((SubBlockBase *) ((long) (buf) - sizeof(SubBlockBase))) +#define VARBUF_SB(buf) ((SubBlock *) ((long) (buf) - sizeof(SubBlockBase))) +#define VARBUF_BLOCKSIZE(buf) (VARBUF_SBB(buf)->x0 & ~FLAGMASK) +#define VARBUF_SIZE(buf) (((VARBUF_SBB(buf)->x0 & ~FLAGMASK) - sizeof(SubBlockBase))) +#define VARBUF_BLOCK(buf) SBB_BLOCK(VARBUF_SBB(buf)) +#define FIXBUF_SIZE(buf) (((FixBlock *) BUF_LOCATOR(buf))->entrysize) + +#define BUF_SIZE(buf) BUF_IS_VAR(buf) ? VARBUF_SIZE(buf) : FIXBUF_SIZE(buf) + +static void Block_construct(Block *block, size_t size) { + SubBlock *subblock; + + block->x14 = size | 3; + ((BlockTail *) ((long) block + size - sizeof(BlockTail)))->x14copy = block->x14; + + subblock = (SubBlock *) (block + 1); + SubBlock_construct(subblock, size - sizeof(Block) - sizeof(BlockTail), block, 0, 0); + + block->remain = size - sizeof(Block) - sizeof(BlockTail); + BLOCK_TAIL(block)->unk = NULL; + + Block_link(block, subblock); +} + +static SubBlock *Block_subBlock(Block *block, size_t size) { + SubBlock *subblock; + size_t check; + size_t best; + + if (!BLOCK_TAIL(block)->unk) + return NULL; + + subblock = BLOCK_TAIL(block)->unk; + best = subblock->x0 & ~FLAGMASK; + check = subblock->x0 & ~FLAGMASK; + while (check < size) { + subblock = subblock->xC; + check = subblock->x0 & ~FLAGMASK; + if (best < check) + best = check; + if (subblock == BLOCK_TAIL(block)->unk) { + block->remain = best; + return NULL; + } + } + + if ((check - size) >= 0x60) + SubBlock_split(subblock, size); + + BLOCK_TAIL(block)->unk = subblock->xC; + Block_unlink(block, subblock); + return subblock; +} + +static void Block_link(Block *block, SubBlock *subblock) { + size_t size; + SubBlock **sbptr; + + size = subblock->x0 & ~FLAGMASK; + subblock->x0 &= ~2; + ((SubBlock *) ((long) subblock + size))->x0 &= ~4; + ((SubBlockTail *) ((long) subblock + size - sizeof(SubBlockTail)))->x0copy = size; + + sbptr = &BLOCK_TAIL(block)->unk; + if (*sbptr) { + subblock->x8 = (*sbptr)->x8; + subblock->x8->xC = subblock; + subblock->xC = *sbptr; + (*sbptr)->x8 = subblock; + *sbptr = subblock; + *sbptr = SubBlock_merge_prev(*sbptr, sbptr); + SubBlock_merge_next(*sbptr, sbptr); + } else { + *sbptr = subblock; + subblock->x8 = subblock; + subblock->xC = subblock; + } + + if (block->remain < ((*sbptr)->x0 & ~FLAGMASK)) + block->remain = (*sbptr)->x0 & ~FLAGMASK; +} + +static void Block_unlink(Block *block, SubBlock *subblock) { + size_t size; + SubBlock **sbptr; + + size = subblock->x0 & ~FLAGMASK; + subblock->x0 |= 2; + ((SubBlock *) ((long) subblock + size))->x0 |= 4; + + sbptr = &BLOCK_TAIL(block)->unk; + if (*sbptr == subblock) + *sbptr = subblock->xC; + + if (*sbptr == subblock) { + *sbptr = NULL; + block->remain = 0; + } else { + subblock->xC->x8 = subblock->x8; + subblock->x8->xC = subblock->xC; + } +} + +static void SubBlock_construct(SubBlock *subblock, size_t size, Block *block, int flag1, int flag2) { + subblock->block = (Block *) ((long) block | 1); + subblock->x0 = size; + if (flag1) + subblock->x0 |= 4; + if (flag2) { + subblock->x0 |= 2; + ((SubBlock *) (((long) subblock) + size))->x0 |= 4; + } else { + ((SubBlockTail *) (((long) subblock) + size - sizeof(SubBlockTail)))->x0copy = size; + } +} + +static SubBlock *SubBlock_split(SubBlock *subblock, size_t pos) { + size_t oldsize; + int flag; + SubBlock *splitright; + Block *block; + + oldsize = subblock->x0 & ~FLAGMASK; + flag = !(subblock->x0 & 2); + splitright = (SubBlock *) ((long) subblock + pos); + block = (Block *) ((long) subblock->block & ~1); + SubBlock_construct(subblock, pos, block, subblock->x0 & 4, !flag); + SubBlock_construct(splitright, oldsize - pos, block, !flag, !flag); + if (flag) { + splitright->xC = subblock->xC; + splitright->xC->x8 = splitright; + splitright->x8 = subblock; + subblock->xC = splitright; + } + + return splitright; +} + +static SubBlock *SubBlock_merge_prev(SubBlock *subblock, SubBlock **sbptr) { + size_t prevsize; + SubBlock *prevblock; + + if (!(subblock->x0 & 4)) { + prevsize = ((SubBlockTail *) ((long) subblock - sizeof(SubBlockTail)))->x0copy; + if (prevsize & 2) + return subblock; + + prevblock = (SubBlock *) ((long) subblock - prevsize); + prevblock->x0 = prevblock->x0 & FLAGMASK; + prevblock->x0 |= (prevsize + (subblock->x0 & ~FLAGMASK)) & ~FLAGMASK; + if (!(prevblock->x0 & 2)) + ((SubBlockTail *) ((long) prevblock + prevsize + (subblock->x0 & ~FLAGMASK) - sizeof(SubBlockTail)))->x0copy = prevsize + (subblock->x0 & ~FLAGMASK); + + if (*sbptr == subblock) + *sbptr = (*sbptr)->xC; + + subblock->xC->x8 = subblock->x8; + subblock->xC->x8->xC = subblock->xC; + return prevblock; + } + + return subblock; +} + +static void SubBlock_merge_next(SubBlock *subblock, SubBlock **sbptr) { + SubBlock *nextblock; + size_t nextsize; + + nextblock = (SubBlock *) ((long) subblock + (subblock->x0 & ~FLAGMASK)); + if (!(nextblock->x0 & 2)) { + nextsize = (subblock->x0 & ~FLAGMASK) + (nextblock->x0 & ~FLAGMASK); + subblock->x0 = subblock->x0 & FLAGMASK; + subblock->x0 |= nextsize & ~FLAGMASK; + + if (!(subblock->x0 & 2)) + ((SubBlockTail *) ((long) subblock + nextsize - sizeof(SubBlockTail)))->x0copy = nextsize; + + if (!(subblock->x0 & 2)) + ((SubBlock *) ((long) subblock + nextsize))->x0 &= ~4; + else + ((SubBlock *) ((long) subblock + nextsize))->x0 |= 4; + + if (*sbptr == nextblock) + *sbptr = (*sbptr)->xC; + if (*sbptr == nextblock) + *sbptr = NULL; + + nextblock->xC->x8 = nextblock->x8; + nextblock->x8->xC = nextblock->xC; + } +} + +static void link_block(Block *block) { + if (start_) { + block->prev = start_->prev; + block->prev->next = block; + block->next = start_; + + start_->prev = block; + start_ = block; + } else { + start_ = block; + block->prev = block; + block->next = block; + } +} + +static Block *unlink_block(Block *block) { + Block *newblock; + + newblock = block->next; + if (newblock == block) + newblock = NULL; + + if (start_ == block) + start_ = newblock; + + if (newblock) { + newblock->prev = block->prev; + newblock->prev->next = newblock; + } + + block->prev = block->next = NULL; + return newblock; +} + +static Block *link_new_block(size_t size) { + Block *block; + + size = (size + 0x1000 + sizeof(Block) + sizeof(BlockTail) - 1) & ~0xFFF; + if (size < 0x10000) + size = 0x10000; + + if (!(block = galloc(size))) + return NULL; + + Block_construct(block, size); + link_block(block); + return block; +} + +static void *allocate_from_var_pools(size_t size) { + Block *block; + SubBlock *subblock; + + size = (size + sizeof(Block) - 1) & ~0xF; + if (size < 0x60) + size = 0x60; + + block = start_ ? start_ : link_new_block(size); + if (!block) + return NULL; + + do { + if (size <= block->remain) { + if ((subblock = Block_subBlock(block, size))) { + start_ = block; + goto allocated; + } + } + } while ((block = block->next) != start_); + + block = link_new_block(size); + if (!block) + return NULL; + subblock = Block_subBlock(block, size); +allocated: + return (SubBlockBase *) subblock + 1; +} + +static void deallocate_from_var_pools(void *buf) { + Block *block; + SubBlock *subblock; + int flag; + + subblock = (SubBlock *) ((long) buf - sizeof(SubBlockBase)); + block = (Block *) ((long) subblock->block & ~1); + Block_link(block, subblock); + + flag = 0; + subblock = (SubBlock *) (block + 1); + if (!(subblock->x0 & 2)) { + if ((subblock->x0 & ~FLAGMASK) == ((block->x14 & ~FLAGMASK) - sizeof(Block) - sizeof(BlockTail))) + flag = 1; + } + + if (flag) + unlink_block(block); +} + +static void FixBlock_construct(FixBlock *fixblock, FixBlock *prev, FixBlock *next, int poolIndex, void *buffer, size_t buffersize) { + size_t entrysize; + size_t entrycount; + size_t i; + FixSubBlock *fsb; + FixSubBlock *fsbnext; + + fixblock->prev = prev; + fixblock->next = next; + fixblock->entrysize = fix_pool_sizes[poolIndex]; + + entrysize = fix_pool_sizes[poolIndex] + sizeof(void *); + entrycount = (buffersize / entrysize); + fsb = buffer; + for (i = 0; i < (entrycount - 1); i++) { + fsbnext = (FixSubBlock *) ((long) fsb + entrysize); + fsb->fixblock = fixblock; + fsb->next = fsbnext; + fsb = fsbnext; + } + + fsb->fixblock = fixblock; + fsb->next = fix_start[poolIndex].b; + fix_start[poolIndex].b = buffer; +} + +static void *allocate_from_fixed_pools(size_t size) { + int poolIndex; + FixSubBlock *fsb; + + poolIndex = 0; + while (size > fix_pool_sizes[poolIndex]) + poolIndex++; + + if (!fix_start[poolIndex].b) { + void *buf; + size_t bufsize; + + buf = allocate_from_var_pools(4000); + if (!buf) + return NULL; + + bufsize = !BUF_IS_VAR(buf) ? FIXBUF_SIZE(buf) : VARBUF_SIZE(buf); + FixBlock_construct( + buf, NULL, fix_start[poolIndex].a, poolIndex, + ((FixBlock *) buf) + 1, + bufsize - sizeof(FixBlock) + ); + fix_start[poolIndex].a = buf; + } + + fsb = fix_start[poolIndex].b; + fix_start[poolIndex].b = fsb->next; + fix_start[poolIndex].count++; + return ((FixSubBlockBase *) fsb) + 1; +} + +static void deallocate_from_fixed_pools(void *buf, size_t size) { + int poolIndex; + FixBlock *fixblock; + FixBlock *nextfb; + FixSubBlock *fsb; + + poolIndex = 0; + while (size > fix_pool_sizes[poolIndex]) + poolIndex++; + + fsb = (FixSubBlock *) ((long) buf - sizeof(FixSubBlockBase)); + fsb->next = fix_start[poolIndex].b; + fix_start[poolIndex].b = fsb; + if (--fix_start[poolIndex].count == 0) { + fixblock = fix_start[poolIndex].a; + while (fixblock) { + nextfb = fixblock->next; + deallocate_from_var_pools(fixblock); + fixblock = nextfb; + } + fix_start[poolIndex].a = NULL; + fix_start[poolIndex].b = NULL; + } +} + +size_t IRO_msize(void *buf) { + return BUF_SIZE(buf); +} + +void *IRO_malloc(size_t size) { + if (!size) + return NULL; + + if (size <= 0x4C) + return allocate_from_fixed_pools(size); + else + return allocate_from_var_pools(size); +} + +void IRO_free(void *buf) { + if (buf) { + size_t size = !BUF_IS_VAR(buf) ? FIXBUF_SIZE(buf) : VARBUF_SIZE(buf); + + if (size <= 0x4C) + deallocate_from_fixed_pools(buf, size); + else + deallocate_from_var_pools(buf); + } +} + +void *IRO_realloc(void *buf, size_t newsize) { + size_t oldsize; + size_t newblocksize; + void *newbuf; + + if (!buf) + return IRO_malloc(newsize); + + if (!newsize) { + IRO_free(buf); + return NULL; + } + + oldsize = !BUF_IS_VAR(buf) ? FIXBUF_SIZE(buf) : VARBUF_SIZE(buf); + if (newsize > oldsize) { + if (BUF_IS_VAR(buf)) { + newblocksize = (newsize + sizeof(Block) - 1) & ~FLAGMASK; + if (newblocksize < 0x60) + newblocksize = 0x60; + SubBlock_merge_next(VARBUF_SB(buf), &BLOCK_TAIL(VARBUF_BLOCK(buf))->unk); + if (VARBUF_BLOCKSIZE(buf) >= newblocksize) { + if ((VARBUF_BLOCKSIZE(buf) - newblocksize) >= 0x60) { + Block_link(VARBUF_BLOCK(buf), SubBlock_split(VARBUF_SB(buf), newblocksize)); + } + return buf; + } + } + + newbuf = IRO_malloc(newsize); + if (!newbuf) + return NULL; + + memcpy(newbuf, buf, oldsize); + IRO_free(buf); + return newbuf; + } + + if (BUF_IS_VAR(buf)) { + newsize = (newsize + sizeof(Block) - 1) & ~FLAGMASK; + if (newsize < 0x60) + newsize = 0x60; + if ((VARBUF_BLOCKSIZE(buf) - newsize) >= 0x60) { + Block_link(VARBUF_BLOCK(buf), SubBlock_split(VARBUF_SB(buf), newsize)); + } + } + + return buf; +} + +void *IRO_calloc(size_t a, size_t b) { + void *buf; + size_t len = b * a; + buf = IRO_malloc(len); + if (buf) + memset(buf, 0, len); + return buf; +} + +void IRO_pool_free_all(void) { + int i; + Block *block; + if ((block = start_)) { + do { + block = block->next; + } while (block != start_); + start_ = NULL; + + for (i = 0; i < 4; i++) { + fix_start[i].a = NULL; + fix_start[i].b = NULL; + fix_start[i].count = 0; + } + } +} + +void IRO_InitializeAllocator(void) { + if (!initialized) { + int i; + for (i = 0; i < 4; i++) { + fix_start[i].a = NULL; + fix_start[i].b = NULL; + fix_start[i].count = 0; + } + start_ = NULL; + initialized = 1; + } +} + +void IRO_TerminateAllocator(void) { + initialized = 0; +} + diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroMalloc.h b/compiler_and_linker/FrontEnd/Optimizer/IroMalloc.h new file mode 100644 index 0000000..7700280 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroMalloc.h @@ -0,0 +1,15 @@ +#ifndef COMPILER_IROMALLOC_H +#define COMPILER_IROMALLOC_H + +#include "IrOptimizer.h" + +extern size_t IRO_msize(void *buf); +extern void *IRO_malloc(size_t size); +extern void IRO_free(void *buf); +extern void *IRO_realloc(void *buf, size_t newsize); +extern void *IRO_calloc(size_t a, size_t b); +extern void IRO_pool_free_all(void); +extern void IRO_InitializeAllocator(void); +extern void IRO_TerminateAllocator(void); + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.c b/compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.c new file mode 100644 index 0000000..3f8989f --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.c @@ -0,0 +1,5734 @@ +#include "IroPointerAnalysis.h" +#include "IroEval.h" +#include "IroFlowgraph.h" +#include "IroLinearForm.h" +#include "IroMalloc.h" +#include "IroUtil.h" +#include "IroVars.h" +#include "compiler/CDecl.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CScope.h" +#include "compiler/InlineAsmPPC.h" +#include "compiler/CompilerTools.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "IroPointerAnalysisADTs.c" + +// forward decls +static Object *GetLocalObject(PALocalVar *local, Object *proc, Boolean flag); +static Boolean GetActualLocsOfExtendedParam(LocationSetSet *set, LocationSet *ls, Object *var, Stack **stackPtr, ParamMappingFunction *map, Boolean flag); +static int ExpandLocationSetSetToActuals(Stack **stackPtr, ParamMappingFunction *map, LocationSetSet *thingsPointedTo); +static Boolean Lookup(LocationSetSet *set, Stack **stackPtr, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf, LocationSet *dst, PointsToFunction *pointsToFunc, Boolean unk, Type *indRtype); +static ExtendedParam *CreateExtendedParam(Stack **stackPtr, ParamMappingFunction *map, Object *var, Boolean *result); +static Boolean Assign(PartialTransferFunction *ptf, LocationSet *dst, LocationSetSet *srcs, Object *proc, IROLinear *nd, IRONode *fnode); +static ObjectList *FunctionArguments(Object *proc); +static IRONode **FunctionNodeTable(Object *proc); +static Boolean ApplySummary(PartialTransferFunction *tgtPTF, ParamMappingFunction *tgtMap, Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf, ParamMappingFunction *map, Boolean flag); +static PartialTransferFunction *GetPTF(ParamMappingFunction *map, Object *proc, IROLinear *nd, PartialTransferFunction *ptf, Boolean *needVisit); +static Boolean ObjectIsAFunctionArgument(Object *proc, Object *obj); +static Boolean ObjectIsARealFunctionArgument(Object *proc, Object *obj); +static void EvalProc(Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf); +static void FindGlobalObjectAction(Object *object, void *refcon); + +static Boolean ObjectIsRestrictQualified(Object *obj) { + return (CParser_GetTypeQualifiers(obj->type, obj->qual) & Q_RESTRICT) != 0; +} + +static Boolean LocationIsVolatile(LocationSet *loc, Object *proc) { + Boolean result; + Type *rtype; + + IRO_ASSERT(932, loc != NULL); + IRO_ASSERT(933, proc != NULL); + + result = 0; + + if ((rtype = LocationSet_rtype(loc))) { + UInt32 qual; + switch (rtype->type) { + case TYPEARRAY: + qual = TYPE_POINTER(rtype)->qual; + break; + case TYPEPOINTER: + qual = TYPE_POINTER(rtype)->qual; + break; + case TYPEMEMBERPOINTER: + qual = TYPE_MEMBER_POINTER(rtype)->qual; + break; + default: + qual = 0; + } + if (qual & Q_VOLATILE) + result = 1; + } + + if (!result && !LocationSet_IsUnknown(loc)) { + Object *obj = NULL; + PAMemoryBlock *block = LocationSet_block(loc); + + switch (PAMemoryBlock_kind(block)) { + case PAMEMORYBLOCKKIND_LOCALVAR: { + PALocalVar *local = PAMemoryBlock_thing(block); + if (local) + obj = GetLocalObject(local, proc, 0); + break; + } + case PAMEMORYBLOCKKIND_EXTENDEDPARAM: { + ExtendedParam *ep = PAMemoryBlock_thing(block); + if (ep) { + ObjectSet *objSet = ExtendedParam_objectSet(ep); + if (objSet) { + if (ObjectSet_Count(objSet) == 1) + obj = ObjectSet_FindFirst(objSet); + else + ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); + } + } + break; + } + } + + if (obj && is_volatile_object(obj)) + result = 1; + } + + return result; +} + +static Object *GetLocalObject(PALocalVar *local, Object *proc, Boolean flag) { + ObjectList *list; + Object *arg; + Object *obj; + char *name; + + IRO_ASSERT(999, local != NULL); + IRO_ASSERT(1000, proc != NULL); + + obj = PALocalVar_Get0_sub_4847E0(local); + name = PALocalVar_Get4_sub_4847D0(local); + + if (proc != &stUnknown && !obj && name && name[0] && flag) { + for (list = FunctionArguments(proc); list && !obj; list = list->next) { + arg = list->object; + if (arg && arg != &stUnknown && arg->name && arg->name->name) { + if (!strcmp(arg->name->name, name)) + obj = arg; + } + } + } + + if (obj) + PALocalVar_SetSth_sub_4847C0(local, obj); + + return obj; +} + +static Boolean ObjectIsAnExtendedParamCandidate(Object *obj) { + IRO_ASSERT(1042, obj != NULL); + + return Inline_IsObjectData(obj) || + obj->datatype == DABSOLUTE || + obj->datatype == DFUNC || + obj->datatype == DVFUNC || + obj->datatype == DINLINEFUNC; +} + +static Boolean ObjectIsAFunction(Object *obj) { + IRO_ASSERT(1054, obj != NULL); + + return obj->datatype == DFUNC || + obj->datatype == DVFUNC || + obj->datatype == DINLINEFUNC; +} + +static Boolean LocationSetRepresentsSingleLocation(LocationSet *ls, Object *proc, PointsToFunction *pointsToFunc) { + Boolean result; + PAMemoryBlock *mb; + PAMemoryBlockKind kind; + ExtendedParam *ep; + ObjectSet *objSet; + + IRO_ASSERT(1073, ls != NULL); + IRO_ASSERT(1074, proc == NULL || proc != NULL); + IRO_ASSERT(1075, pointsToFunc == NULL || pointsToFunc != NULL); + + result = 1; + if (LocationSet_IsUnknown(ls) || LocationSet_stride(ls)) { + result = 0; + } else { + mb = LocationSet_block(ls); + IRO_ASSERT(1084, mb != NULL); + + kind = PAMemoryBlock_kind(mb); + if (kind == PAMEMORYBLOCKKIND_HEAPBLOCK) { + result = 0; + } else if (kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + ep = PAMemoryBlock_thing(mb); + if (!ep) { + result = 0; + } else { + if ((objSet = ExtendedParam_objectSet(ep)) && ObjectSet_Count(objSet) > 1) { + Object *obj = NULL; + ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); + + if (!obj) { + LocationSetSet *lss; + LocationSet *tmp; + ExtendedParam *ep; + ObjectSet *objSet; + + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + GetActualLocsOfExtendedParam(lss, ls, NULL, &stCallingContextStack, NULL, 0); + if ( + LocationSetSet_Count(lss) != 1 || + !(tmp = LocationSetSet_FindFirst(lss)) || + LocationSet_IsUnknown(tmp) || + (!((mb = LocationSet_block(tmp)) && (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) && (ep = PAMemoryBlock_thing(mb)) && (objSet = ExtendedParam_objectSet(ep)) && (ObjectSet_Count(objSet) == 1) && + ObjectIsAnExtendedParamCandidate(ObjectSet_FindFirst(objSet))) && + !LocationSetRepresentsSingleLocation(tmp, proc, pointsToFunc)) + ) + result = 0; + + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + } + } + } + } + } + + return result; +} + +static void EvalExprAction(LocationSet *ls, void *refcon) { + CInt64 value; + UInt32 stride; + PAMemoryBlock *mb; + + IRO_ASSERT(1151, ls != NULL); + IRO_ASSERT(1152, !LocationSet_IsUnknown(ls)); + IRO_ASSERT(1153, refcon != NULL); + + value = *((CInt64 *) refcon); + stride = LocationSet_stride(ls); + mb = LocationSet_block(ls); + + if (mb && PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT) { + Type *rtype = LocationSet_rtype(ls); + LocationSet_Term(ls); + value = CInt64_Add(value, *((CInt64 *) PAMemoryBlock_thing(mb))); + mb = PAMemoryBlock_New(); + PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value); + LocationSet_InitKnown(ls, mb, cint64_zero, stride, rtype); + } else { + value = CInt64_Add(value, LocationSet_field(ls)); + if (stride) { + CInt64 strideval; + CInt64_SetLong(&strideval, stride); + value = CInt64_Mod(value, strideval); + } + SetsLocationSetField_sub_4851B0(ls, value); + } +} + +static void EvalExprAction2(LocationSet *ls, void *refcon) { + UInt32 value; + + IRO_ASSERT(1188, ls != NULL); + IRO_ASSERT(1189, !LocationSet_IsUnknown(ls)); + IRO_ASSERT(1190, refcon != NULL); + + value = CInt64_GetULong((CInt64 *) refcon); + if (value) { + SetsLocationSetField_sub_4851B0(ls, CInt64_Mod(LocationSet_field(ls), *((CInt64 *) refcon))); + } + SetsLocationSetStride_sub_4852D0(ls, value); +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct EvalExprAction3Params { + LocationSetSet *set; + Stack **stackPtr; + Object *proc; + ParamMappingFunction *map; + PartialTransferFunction *ptf; + PointsToFunction *pointsToFunc; + Type *indRtype; + Boolean x1C; +} EvalExprAction3Params; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void EvalExprAction3(LocationSet *ls, void *refcon) { + EvalExprAction3Params *params; + + IRO_ASSERT(1219, ls != NULL); + IRO_ASSERT(1220, refcon != NULL); + + params = refcon; + + params->x1C |= Lookup( + params->set, + params->stackPtr, + params->proc, + params->map, + params->ptf, + ls, + params->pointsToFunc, + 1, + params->indRtype + ); +} + +static void EvalExprAction4(LocationSet *ls, void *refcon) { + Type *type; + PAMemoryBlock *mb; + + IRO_ASSERT(1235, ls != NULL); + IRO_ASSERT(1236, refcon != NULL); + + type = refcon; + + if (LocationSet_IsUnknown(ls)) { + LocationSet_SetRtype(ls, type); + } else if ((mb = LocationSet_block(ls))) { + if (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT) { + CInt64 value; + CInt64 field; + UInt32 stride; + + value = *((CInt64 *) PAMemoryBlock_thing(mb)); + IRO_TruncateValueToType(&value, type); + field = LocationSet_field(ls); + IRO_TruncateValueToType(&field, type); + stride = LocationSet_stride(ls); + LocationSet_Term(ls); + + mb = PAMemoryBlock_New(); + PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value); + + LocationSet_InitKnown(ls, mb, field, stride, type); + } + LocationSet_SetRtype(ls, type); + } +} + +static Boolean EvalExpr(LocationSetSet *set, Object *proc, IROLinear *Int, Stack **stackPtr, ParamMappingFunction *map, PartialTransferFunction *ptf) { + Boolean result; + LocationSetSet *lss; + LocationSetSet *lss2; + IROLinear *indirect; + EvalExprAction3Params params; + IROLinear *originalInt; + + IRO_ASSERT(1284, set == NULL || set != NULL); + IRO_ASSERT(1285, proc != NULL); + IRO_ASSERT(1286, Int != NULL); + IRO_ASSERT(1287, map == NULL || map != NULL); + IRO_ASSERT(1288, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); + + result = 0; + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + + originalInt = Int; + while (Int && Int->type == IROLinearOp1Arg && Int->nodetype == ETYPCON) + Int = Int->u.monadic; + + IRO_ASSERT(1302, Int != NULL); + + if (IRO_IsAssignment(Int)) { + if (Int->type == IROLinearOp1Arg) + indirect = Int->u.monadic; + else + indirect = Int->u.diadic.left; + IRO_ASSERT(1310, indirect->type == IROLinearOp1Arg && indirect->nodetype == EINDIRECT); + + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + result |= EvalExpr(lss2, proc, indirect->u.monadic, stackPtr, map, ptf); + + memset(¶ms, 0, sizeof(params)); + params.set = lss; + params.stackPtr = stackPtr; + params.proc = proc; + params.map = map; + params.ptf = ptf; + if (Int->nodetype == EPOSTINC || Int->nodetype == EPOSTDEC) + params.pointsToFunc = indirect->pointsToFunction; + else + params.pointsToFunc = Int->pointsToFunction; + params.indRtype = indirect->rtype; + params.x1C = 0; + LocationSetSet_ForEach(lss2, EvalExprAction3, ¶ms); + result |= params.x1C; + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } else if (Int->type == IROLinearFunccall) { + IRO_ASSERT(1338, Int->u.funccall.returnedLocs != NULL); + LocationSetSet_AddSet(lss, Int->u.funccall.returnedLocs); + } else if (Int->type == IROLinearOp1Arg && Int->nodetype == EINDIRECT) { + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + result |= EvalExpr(lss2, proc, Int->u.monadic, stackPtr, map, ptf); + + memset(¶ms, 0, sizeof(params)); + params.set = lss; + params.stackPtr = stackPtr; + params.proc = proc; + params.map = map; + params.ptf = ptf; + params.pointsToFunc = Int->pointsToFunction; + params.indRtype = Int->rtype; + params.x1C = 0; + LocationSetSet_ForEach(lss2, EvalExprAction3, ¶ms); + result |= params.x1C; + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } else if (Int->type == IROLinearOp2Arg && Int->nodetype == EADD) { + IROAddrRecord *addr = IRO_InitAddrRecordPointer(Int); + IRO_DecomposeAddressExpression(Int, addr); + if (addr->numObjRefs > 1) { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } else { + CInt64 value; + CInt64 max; + CInt64 work; + Boolean flag1; + Boolean flag2; + + CInt64_SetLong(&value, 0); + flag1 = 0; + flag2 = 0; + if (addr->numObjRefs == 1) { + Object *obj; + IRO_ASSERT(1383, addr->objRefs->element->type == IROLinearOperand); + IRO_ASSERT(1384, addr->objRefs->element->u.node->type == EOBJREF); + obj = ((IROLinear *) addr->objRefs->element)->u.node->data.objref; + IRO_ASSERT(1387, obj != NULL); + result |= EvalExpr(lss, proc, addr->objRefs->element, stackPtr, map, ptf); + flag2 = 1; + } + + if (addr->numMisc != 0) { + IROElmList *list; + IROLinear *nd; + max = cint64_max; + + for (list = addr->misc; list; list = list->next) { + nd = list->element; + while (nd && nd->type == IROLinearOp1Arg && nd->nodetype == ETYPCON) + nd = nd->u.monadic; + + if (nd) { + if (nd->type == IROLinearOp2Arg && nd->nodetype == EMUL) { + if (IRO_IsIntConstant(nd->u.diadic.left) && IRO_IsIntConstant(nd->u.diadic.right)) { + if (IRO_IsUnsignedType(nd->rtype)) + work = CInt64_MulU(nd->u.diadic.left->u.node->data.intval, nd->u.diadic.right->u.node->data.intval); + else + work = CInt64_Mul(nd->u.diadic.left->u.node->data.intval, nd->u.diadic.right->u.node->data.intval); + IRO_TruncateValueToType(&work, ((IROLinear *) list->element)->rtype); + value = CInt64_Add(value, work); + } else if (IRO_IsIntConstant(nd->u.diadic.left)) { + work = nd->u.diadic.left->u.node->data.intval; + if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) + max = work; + } else if (IRO_IsIntConstant(nd->u.diadic.right)) { + work = nd->u.diadic.right->u.node->data.intval; + if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) + max = work; + } else { + max = cint64_one; + } + } else if (nd->type == IROLinearOp2Arg && nd->nodetype == ESHL) { + if (IRO_IsIntConstant(nd->u.diadic.left) && IRO_IsIntConstant(nd->u.diadic.right)) { + work = CInt64_Shl(nd->u.diadic.left->u.node->data.intval, nd->u.diadic.right->u.node->data.intval); + IRO_TruncateValueToType(&work, ((IROLinear *) list->element)->rtype); + value = CInt64_Add(value, work); + } else if (IRO_IsIntConstant(nd->u.diadic.right)) { + work = CInt64_Shl(cint64_one, nd->u.diadic.right->u.node->data.intval); + IRO_TruncateValueToType(&work, ((IROLinear *) list->element)->rtype); + if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) + max = work; + } else { + max = cint64_one; + } + } else { + LocationSet *tmp; + PAMemoryBlock *mb; + + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + result |= EvalExpr(lss2, proc, nd, stackPtr, map, ptf); + + if (LocationSetSet_FindUnknown(lss2)) { + max = cint64_one; + } else if ( + LocationSetSet_Count(lss2) == 1 && + (tmp = LocationSetSet_FindFirst(lss2)) && + (LocationSet_stride(tmp) == 0) && + (mb = LocationSet_block(tmp)) && + (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT) + ) { + value = CInt64_Add(value, *((CInt64 *) PAMemoryBlock_thing(mb))); + } else if (!flag2 && (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype))) { + if (flag1) { + LocationSetSet_RemoveAll(lss); + max = cint64_one; + } + LocationSetSet_AddSet(lss, lss2); + flag2 = 1; + } else if (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype)) { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } else if (!flag1) { + LocationSetSet_AddSet(lss, lss2); + flag1 = 1; + } else { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } + } + } + + if (IS_TYPE_POINTER(Int->rtype)) + CInt64_SetLong(&work, TYPE_POINTER(Int->rtype)->target->size); + else if (IS_TYPE_MEMBERPOINTER(Int->rtype)) + CInt64_SetLong(&work, TYPE_MEMBER_POINTER(Int->rtype)->ty1->size); + else + work = cint64_zero; + + if (CInt64_GreaterU(work, max)) + max = work; + } + + if (addr->numInts != 0) { + IROElmList *list; + IROLinear *addend; + + for (list = addr->ints; list; list = list->next) { + addend = list->element; + + if (addend) { + IRO_ASSERT(1536, IRO_IsIntConstant(addend)); + + value = CInt64_Add(value, addend->u.node->data.intval); + } + } + } + + IRO_TruncateValueToType(&value, Int->rtype); + + if (LocationSetSet_Count(lss) == 0) { + if (CInt64_Equal(max, cint64_max)) { + PAMemoryBlock *mb; + LocationSet *ls; + + mb = PAMemoryBlock_New(); + PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value); + + ls = LocationSet_New(); + LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype); + LocationSetSet_Add(lss, ls); + LocationSet_Term(ls); + LocationSet_Delete(ls); + } else { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } + } else { + if (!LocationSetSet_FindUnknown(lss) && !CInt64_IsZero(&value)) + LocationSetSet_ForEach(lss, EvalExprAction, &value); + } + + if (!LocationSetSet_FindUnknown(lss) && addr->numMisc && !CInt64_Equal(max, cint64_max)) + LocationSetSet_ForEach(lss, EvalExprAction2, &max); + } + } else if (Int->type == IROLinearOperand) { + Object *obj; + void *thing; + PAMemoryBlockKind kind; + + thing = NULL; + if (IRO_IsIntConstant(Int)) { + kind = PAMEMORYBLOCKKIND_INT; + thing = &Int->u.node->data.intval; + } else if (Int->u.node->type == ESTRINGCONST) { + kind = PAMEMORYBLOCKKIND_6; + thing = Int->u.node; + } else if (Int->u.node->type == EOBJREF) { + obj = Int->u.node->data.objref; + IRO_ASSERT(1597, obj != NULL); + if (ObjectIsAnExtendedParamCandidate(obj)) { + kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM; + thing = CreateExtendedParam(stackPtr, map, obj, &result); + } else { + kind = PAMEMORYBLOCKKIND_LOCALVAR; + thing = PALocalVar_New(); + if (obj->name && obj->name->name && ObjectIsARealFunctionArgument(proc, obj)) + PALocalVar_InitByName(thing, obj->name->name); + else + PALocalVar_InitByObject(thing, obj); + } + } + + if (thing) { + PAMemoryBlock *mb; + LocationSet *ls; + + mb = PAMemoryBlock_New(); + PAMemoryBlock_Init(mb, kind, thing); + + ls = LocationSet_New(); + LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype); + LocationSetSet_Add(lss, ls); + LocationSet_Term(ls); + LocationSet_Delete(ls); + } + } else if (Int->type == IROLinearOp1Arg && Int->nodetype == EBITFIELD) { + LocationSet *ls; + + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + result |= EvalExpr(lss2, proc, Int->u.monadic, stackPtr, map, ptf); + + if (LocationSetSet_Count(lss2) == 1 && (ls = LocationSetSet_FindFirst(lss2))) + LocationSetSet_AddUnknown(lss, NULL, NULL, ls); + else + CError_FATAL(1643); + + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } else { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } + + LocationSetSet_ForEach(lss, EvalExprAction4, originalInt->rtype); + + if (set && lss) + LocationSetSet_AddSet(set, lss); + + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + + return result; +} + +static IROAddrRecord *IRO_InitENodeAddrRecordPointer(ENode *enode) { + IROAddrRecord *addr = IRO_malloc(sizeof(IROAddrRecord)); + + addr->numObjRefs = 0; + addr->objRefs = NULL; + addr->numMisc = 0; + addr->misc = NULL; + addr->numInts = 0; + addr->ints = NULL; + addr->x16 = 0; + addr->linear = (IROLinear *) enode; + + return addr; +} + +static void IRO_AddENodeElmToList(ENode *linear, IROElmList **list) { + IROElmList *elmlist = IRO_malloc(sizeof(IROElmList)); + elmlist->element = linear; + elmlist->next = NULL; + if (!*list) { + *list = elmlist; + } else { + elmlist->next = *list; + *list = elmlist; + } +} + +static void IRO_DecomposeENodeAddressExpression(ENode *node, IROAddrRecord *addr) { + if (node->data.diadic.left->type == EADD) { + IRO_DecomposeENodeAddressExpression(node->data.diadic.left, addr); + } else if (node->data.diadic.left->type == EINTCONST) { + addr->numInts++; + IRO_AddENodeElmToList(node->data.diadic.left, &addr->ints); + } else if (node->data.diadic.left->type == EOBJREF) { + addr->numObjRefs++; + IRO_AddENodeElmToList(node->data.diadic.left, &addr->objRefs); + } else { + addr->numMisc++; + IRO_AddENodeElmToList(node->data.diadic.left, &addr->misc); + } + + if (node->data.diadic.right->type == EADD) { + IRO_DecomposeENodeAddressExpression(node->data.diadic.right, addr); + } else if (node->data.diadic.right->type == EINTCONST) { + addr->numInts++; + IRO_AddENodeElmToList(node->data.diadic.right, &addr->ints); + } else if (node->data.diadic.right->type == EOBJREF) { + addr->numObjRefs++; + IRO_AddENodeElmToList(node->data.diadic.right, &addr->objRefs); + } else { + addr->numMisc++; + IRO_AddENodeElmToList(node->data.diadic.right, &addr->misc); + } +} + +static Boolean EvalENodeExpr(LocationSetSet *set, Object *proc, ENode *Int, Stack **stackPtr, ParamMappingFunction *map, PartialTransferFunction *ptf) { + Boolean result; + LocationSetSet *lss; + LocationSetSet *lss2; + ENode *indirect; + EvalExprAction3Params params; + ENode *originalInt; + + IRO_ASSERT(0, set == NULL || set != NULL); + IRO_ASSERT(0, proc != NULL); + IRO_ASSERT(0, Int != NULL); + IRO_ASSERT(0, map == NULL || map != NULL); + IRO_ASSERT(0, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); + + result = 0; + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + + originalInt = Int; + while (Int && Int->type == ETYPCON) + Int = Int->data.monadic; + + IRO_ASSERT(0, Int != NULL); + + if (IRO_IsAssignOp[Int->type]) { + if (Int->type == EPOSTINC || Int->type == EPOSTDEC || Int->type == EPREINC || Int->type == EPREDEC) + indirect = Int->data.monadic; + else + indirect = Int->data.diadic.left; + IRO_ASSERT(0, indirect->type == EINDIRECT); + + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + result |= EvalENodeExpr(lss2, proc, indirect->data.monadic, stackPtr, map, ptf); + + memset(¶ms, 0, sizeof(params)); + params.set = lss; + params.stackPtr = stackPtr; + params.proc = proc; + params.map = map; + params.ptf = ptf; + if (Int->type == EPOSTINC || Int->type == EPOSTDEC) + params.pointsToFunc = indirect->pointsTo; + else + params.pointsToFunc = Int->pointsTo; + params.indRtype = indirect->rtype; + params.x1C = 0; + LocationSetSet_ForEach(lss2, EvalExprAction3, ¶ms); + result |= params.x1C; + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } else if (Int->type == EINDIRECT) { + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + result |= EvalENodeExpr(lss2, proc, Int->data.monadic, stackPtr, map, ptf); + + memset(¶ms, 0, sizeof(params)); + params.set = lss; + params.stackPtr = stackPtr; + params.proc = proc; + params.map = map; + params.ptf = ptf; + params.pointsToFunc = Int->pointsTo; + params.indRtype = Int->rtype; + params.x1C = 0; + LocationSetSet_ForEach(lss2, EvalExprAction3, ¶ms); + result |= params.x1C; + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } else if (Int->type == EADD) { + IROAddrRecord *addr = IRO_InitENodeAddrRecordPointer(Int); + IRO_DecomposeENodeAddressExpression(Int, addr); + if (addr->numObjRefs > 1) { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } else { + CInt64 value; + CInt64 max; + CInt64 work; + Boolean flag1; + Boolean flag2; + + CInt64_SetLong(&value, 0); + flag1 = 0; + flag2 = 0; + if (addr->numObjRefs == 1) { + Object *obj; + // IRO_ASSERT(addr->objRefs->element->type == IROLinearOperand); + // IRO_ASSERT(addr->objRefs->element->u.node->type == EOBJREF); + obj = ((ENode *) addr->objRefs->element)->data.objref; + IRO_ASSERT(0, obj != NULL); + result |= EvalENodeExpr(lss, proc, addr->objRefs->element, stackPtr, map, ptf); + flag2 = 1; + } + + if (addr->numMisc != 0) { + IROElmList *list; + ENode *nd; + max = cint64_max; + + for (list = addr->misc; list; list = list->next) { + nd = list->element; + while (nd && nd->type == ETYPCON) + nd = nd->data.monadic; + + if (nd) { + if (nd->type == EMUL) { + if (nd->data.diadic.left->type == EINTCONST && nd->data.diadic.right->type == EINTCONST) { + if (IRO_IsUnsignedType(nd->rtype)) + work = CInt64_MulU(nd->data.diadic.left->data.intval, + nd->data.diadic.right->data.intval); + else + work = CInt64_Mul(nd->data.diadic.left->data.intval, + nd->data.diadic.right->data.intval); + IRO_TruncateValueToType(&work, ((ENode *) list->element)->rtype); + value = CInt64_Add(value, work); + } else if (nd->data.diadic.left->type == EINTCONST) { + work = nd->data.diadic.left->data.intval; + if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) + max = work; + } else if (nd->data.diadic.right->type == EINTCONST) { + work = nd->data.diadic.right->data.intval; + if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) + max = work; + } else { + max = cint64_one; + } + } else if (nd->type == ESHL) { + if (nd->data.diadic.left->type == EINTCONST && nd->data.diadic.right->type == EINTCONST) { + work = CInt64_Shl(nd->data.diadic.left->data.intval, + nd->data.diadic.right->data.intval); + IRO_TruncateValueToType(&work, ((ENode *) list->element)->rtype); + value = CInt64_Add(value, work); + } else if (nd->data.diadic.right->type == EINTCONST) { + work = CInt64_Shl(cint64_one, nd->data.diadic.right->data.intval); + IRO_TruncateValueToType(&work, ((ENode *) list->element)->rtype); + if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) + max = work; + } else { + max = cint64_one; + } + } else { + LocationSet *tmp; + PAMemoryBlock *mb; + + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + result |= EvalENodeExpr(lss2, proc, nd, stackPtr, map, ptf); + + if (LocationSetSet_FindUnknown(lss2)) { + max = cint64_one; + } else if ( + LocationSetSet_Count(lss2) == 1 && + (tmp = LocationSetSet_FindFirst(lss2)) && + (LocationSet_stride(tmp) == 0) && + (mb = LocationSet_block(tmp)) && + (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT) + ) { + value = CInt64_Add(value, *((CInt64 *) PAMemoryBlock_thing(mb))); + } else if (!flag2 && (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype))) { + if (flag1) { + LocationSetSet_RemoveAll(lss); + max = cint64_one; + } + LocationSetSet_AddSet(lss, lss2); + flag2 = 1; + } else if (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype)) { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } else if (!flag1) { + LocationSetSet_AddSet(lss, lss2); + flag1 = 1; + } else { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } + } + } + + if (IS_TYPE_POINTER(Int->rtype)) + CInt64_SetLong(&work, TYPE_POINTER(Int->rtype)->target->size); + else if (IS_TYPE_MEMBERPOINTER(Int->rtype)) + CInt64_SetLong(&work, TYPE_MEMBER_POINTER(Int->rtype)->ty1->size); + else + work = cint64_zero; + + if (CInt64_GreaterU(work, max)) + max = work; + } + + if (addr->numInts != 0) { + IROElmList *list; + ENode *addend; + + for (list = addr->ints; list; list = list->next) { + addend = list->element; + + if (addend) { + IRO_ASSERT(0, addend->type == EINTCONST); + + value = CInt64_Add(value, addend->data.intval); + } + } + } + + IRO_TruncateValueToType(&value, Int->rtype); + + if (LocationSetSet_Count(lss) == 0) { + if (CInt64_Equal(max, cint64_max)) { + PAMemoryBlock *mb; + LocationSet *ls; + + mb = PAMemoryBlock_New(); + PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value); + + ls = LocationSet_New(); + LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype); + LocationSetSet_Add(lss, ls); + LocationSet_Term(ls); + LocationSet_Delete(ls); + } else { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } + } else { + if (!LocationSetSet_FindUnknown(lss) && !CInt64_IsZero(&value)) + LocationSetSet_ForEach(lss, EvalExprAction, &value); + } + + if (!LocationSetSet_FindUnknown(lss) && addr->numMisc && !CInt64_Equal(max, cint64_max)) + LocationSetSet_ForEach(lss, EvalExprAction2, &max); + } + } else if (Int->type == EOBJREF || Int->type == EINTCONST || Int->type == ESTRINGCONST) { + Object *obj; + void *thing; + PAMemoryBlockKind kind; + + thing = NULL; + if (Int->type == EINTCONST) { + kind = PAMEMORYBLOCKKIND_INT; + thing = &Int->data.intval; + } else if (Int->type == ESTRINGCONST) { + kind = PAMEMORYBLOCKKIND_6; + thing = Int; + } else if (Int->type == EOBJREF) { + obj = Int->data.objref; + IRO_ASSERT(0, obj != NULL); + if (ObjectIsAnExtendedParamCandidate(obj)) { + kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM; + thing = CreateExtendedParam(stackPtr, map, obj, &result); + } else { + kind = PAMEMORYBLOCKKIND_LOCALVAR; + thing = PALocalVar_New(); + if (obj->name && obj->name->name && ObjectIsARealFunctionArgument(proc, obj)) + PALocalVar_InitByName(thing, obj->name->name); + else + PALocalVar_InitByObject(thing, obj); + } + } + + if (thing) { + PAMemoryBlock *mb; + LocationSet *ls; + + mb = PAMemoryBlock_New(); + PAMemoryBlock_Init(mb, kind, thing); + + ls = LocationSet_New(); + LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype); + LocationSetSet_Add(lss, ls); + LocationSet_Term(ls); + LocationSet_Delete(ls); + } + } else if (Int->type == EBITFIELD) { + LocationSet *ls; + + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + result |= EvalENodeExpr(lss2, proc, Int->data.monadic, stackPtr, map, ptf); + + if (LocationSetSet_Count(lss2) == 1 && (ls = LocationSetSet_FindFirst(lss2))) + LocationSetSet_AddUnknown(lss, NULL, NULL, ls); + else + CError_FATAL(2146); + + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } else { + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + } + + LocationSetSet_ForEach(lss, EvalExprAction4, originalInt->rtype); + + if (set && lss) + LocationSetSet_AddSet(set, lss); + + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + + return result; +} + +static Boolean EvalVarAddr(LocationSetSet *set, Object *proc, VarRecord *var, Stack **stackPtr, ParamMappingFunction *map) { + Boolean result; + PAMemoryBlockKind kind; + void *thing; + Object *obj; + PAMemoryBlock *block; + LocationSet *loc; + + result = 0; + obj = var->object; + + if (ObjectIsAnExtendedParamCandidate(obj)) { + kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM; + thing = CreateExtendedParam(stackPtr, map, obj, &result); + } else { + kind = PAMEMORYBLOCKKIND_LOCALVAR; + thing = PALocalVar_New(); + if (obj->name && obj->name->name && ObjectIsAFunctionArgument(proc, obj)) + PALocalVar_InitByName(thing, obj->name->name); + else + PALocalVar_InitByObject(thing, obj); + } + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, kind, thing); + + loc = LocationSet_New(); + LocationSet_InitKnown(loc, block, cint64_zero, 0, CDecl_NewPointerType(obj->type)); + LocationSetSet_Add(set, loc); + LocationSet_Term(loc); + LocationSet_Delete(loc); + + return result; +} + +static Boolean EvalVariable(LocationSetSet *set, Object *proc, VarRecord *var, PointsToFunction *pointsToFunc, Stack **stackPtr, ParamMappingFunction *map, PartialTransferFunction *ptf) { + LocationSetSet *locs; + Boolean result; + EvalExprAction3Params params; + + locs = LocationSetSet_New(); + LocationSetSet_Init(locs); + result = EvalVarAddr(locs, proc, var, stackPtr, map); + + memset(¶ms, 0, sizeof(params)); + params.set = set; + params.stackPtr = stackPtr; + params.proc = proc; + params.map = map; + params.ptf = ptf; + params.pointsToFunc = pointsToFunc; + params.indRtype = var->object->type; + params.x1C = 0; + LocationSetSet_ForEach(locs, EvalExprAction3, ¶ms); + + result |= params.x1C; + LocationSetSet_Term(locs); + LocationSetSet_Delete(locs); + + return result; +} + +static void StoreReturnedLocationsAction(LocationSet *loc, void *refcon) { + IRO_ASSERT(2275, loc != NULL); + IRO_ASSERT(2276, refcon != NULL); + + if (!LocationSet_IsUnknown(loc)) { + if (PAMemoryBlock_kind(LocationSet_block(loc)) == PAMEMORYBLOCKKIND_HEAPBLOCK) { + PAHeapBlock *hb; + PAMemoryBlock *mb; + CInt64 field; + UInt32 stride; + Type *rtype; + + hb = CreateUniqueHeapAlloc_sub_486420(); + InitUniqueHeapAlloc_sub_486410(hb, refcon); + + mb = PAMemoryBlock_New(); + PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_HEAPBLOCK, hb); + + field = LocationSet_field(loc); + stride = LocationSet_stride(loc); + rtype = LocationSet_rtype(loc); + LocationSet_Term(loc); + LocationSet_InitKnown(loc, mb, field, stride, rtype); + } + } +} + +static void StoreReturnedLocations(IROLinear *nd, PartialTransferFunction *ptf, ParamMappingFunction *map) { + LocationSet *retLoc; + LocationSetSet *retLocs; + + IRO_ASSERT(2307, nd != NULL); + IRO_ASSERT(2308, nd->type == IROLinearFunccall); + IRO_ASSERT(2309, ptf != NULL); + IRO_ASSERT(2310, map != NULL); + + retLoc = PartialTransferFunction_returnLocation(ptf); + retLocs = nd->u.funccall.returnedLocs; + if (!retLocs) { + LocationSetSet_Init(retLocs = nd->u.funccall.returnedLocs = LocationSetSet_New()); + } else { + LocationSetSet_RemoveAll(retLocs); + } + + Lookup(retLocs, NULL, NULL, NULL, NULL, retLoc, PartialTransferFunction_finalPointsToFn(ptf), 0, NULL); + ExpandLocationSetSetToActuals(&stCallingContextStack, map, retLocs); + LocationSetSet_ForEach(retLocs, StoreReturnedLocationsAction, nd); +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct EPParams { + ParamMappingFunction *map; + ExtendedParam *ep; + Object *proc; + Object *var; + unsigned char x10; + unsigned char x11; +} EPParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void FillInAppropriateMappingsWithExtParamAction(Object *obj, void *refcon) { + EPParams *params; + ParamMapping *mapping; + + IRO_ASSERT(2352, obj != NULL); + IRO_ASSERT(2353, refcon != NULL); + + params = refcon; + + IRO_ASSERT(2357, params->map != NULL); + IRO_ASSERT(2358, params->ep != NULL); + IRO_ASSERT(2359, params->proc == NULL || params->proc != NULL); + IRO_ASSERT(2360, params->proc != &stUnknown); + IRO_ASSERT(2361, params->var == NULL || params->var != NULL); + IRO_ASSERT(2362, params->var != &stUnknown); + + mapping = ParamMappingFunction_FindMappingByFormal(params->map, obj); + if (!mapping) { + if (ObjectIsAnExtendedParamCandidate(obj) || !params->proc || ObjectIsAFunctionArgument(params->proc, obj)) { + mapping = ParamMapping_New(); + ParamMapping_Init_PROBABLY(mapping, NULL, obj, params->ep); + Pmf_Add_sub_486610(params->map, mapping); + ParamMapping_Term(mapping); + ParamMapping_Delete(mapping); + params->x11 = 1; + } + } else { + if (ParamMapping_extended(mapping) != params->ep) { + ParamMapping_SetExtended(mapping, params->ep); + params->x11 = 1; + } + } + + if (obj == params->var) + params->x10 = 1; +} + +static Boolean FillInAppropriateMappingsWithExtParam(ParamMappingFunction *map, Object *var, ExtendedParam *ep, Object *proc) { + EPParams params; + ObjectSet *objSet; + + IRO_ASSERT(2398, map != NULL); + IRO_ASSERT(2399, var == NULL || var != NULL); + IRO_ASSERT(2400, var != &stUnknown); + IRO_ASSERT(2401, ep != NULL); + IRO_ASSERT(2402, proc == NULL || proc != NULL); + IRO_ASSERT(2403, proc != &stUnknown); + + memset(¶ms, 0, sizeof(params)); + params.map = map; + params.ep = ep; + params.proc = proc; + params.var = var; + params.x10 = 0; + params.x11 = 0; + + if ((objSet = ExtendedParam_objectSet(ep))) + ObjectSet_ForEach(objSet, FillInAppropriateMappingsWithExtParamAction, ¶ms); + + if (var && !params.x10) { + ExtendedParam_sub_4867B0(ep, var); + FillInAppropriateMappingsWithExtParamAction(var, ¶ms); + } + + return params.x11; +} + +static void MatchPTFHelper(LocationSet *loc, LocationSetSet *locs, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf) { + PointsToFunction *initial; + PAMemoryBlock *block; + PAMemoryBlockKind kind; + Object *obj; + + IRO_ASSERT(2448, loc != NULL); + IRO_ASSERT(2449, !LocationSet_IsUnknown(loc)); + IRO_ASSERT(2450, locs != NULL); + IRO_ASSERT(2451, proc != NULL); + IRO_ASSERT(2452, map != NULL); + IRO_ASSERT(2453, ptf != NULL); + + initial = PartialTransferFunction_initialPointsToFn(ptf); + IRO_ASSERT(2456, initial != NULL); + + IRO_ASSERT(2458, !LocationSet_IsUnknown(loc)); + + block = LocationSet_block(loc); + IRO_ASSERT(2460, block != NULL); + + kind = PAMemoryBlock_kind(block); + + if (kind == PAMEMORYBLOCKKIND_LOCALVAR) { + PALocalVar *local; + + local = PAMemoryBlock_thing(block); + IRO_ASSERT(2466, local != NULL); + + obj = GetLocalObject(local, proc, 1); + if (obj && ObjectIsAFunctionArgument(proc, obj)) { + if (LocationSetSet_Count(locs) == 1) { + LocationSet *ls; + ls = LocationSetSet_FindFirst(locs); + if (ls && !LocationSet_IsUnknown(ls)) { + if ((block = LocationSet_block(ls))) { + if (PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + ExtendedParam *ep; + if ((ep = PAMemoryBlock_thing(block))) { + ExtendedParam_sub_4867B0(ep, obj); + if (stExtParamSet) + ExtParamSet_sub_487630(stExtParamSet, ep); + FillInAppropriateMappingsWithExtParam(map, obj, ep, proc); + } + } + } + } + } + } + } else if (kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + void *ep = PAMemoryBlock_thing(block); + IRO_ASSERT(2489, ep != NULL); + + obj = NULL; + ObjectSet_ForEach(ExtendedParam_objectSet(ep), FindGlobalObjectAction, &obj); + if (obj && obj != &stUnknown) + FillInAppropriateMappingsWithExtParam(map, obj, ep, proc); + } else { + CError_FATAL(2500); + } + + if (!PointsToFunction_FindByLookupCompatibleLocationSet(initial, loc)) { + PointsToEntry *pte = PointsToEntry_New(); + PointsToEntry_Init(pte, loc, locs); + PointsToFunction_AddWithoutChecking(initial, pte); + PointsToEntry_Term(pte); + PointsToEntry_Delete(pte); + } +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct MatchPTFActionParams { + Object *proc; + PartialTransferFunction *ptfCopy; + ParamMappingFunction *mapCopy; + Stack **stackPtr; +} MatchPTFActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void MatchPTFAction1(PointsToEntry *tgtPTE, void *refcon) { + MatchPTFActionParams *params; + LocationSet *loc; + LocationSetSet *locs; + PAMemoryBlock *block; + PAMemoryBlockKind kind; + + IRO_ASSERT(2525, tgtPTE != NULL); + IRO_ASSERT(2526, refcon != NULL); + + params = refcon; + + IRO_ASSERT(2530, params->proc != NULL); + IRO_ASSERT(2531, params->ptfCopy != NULL); + IRO_ASSERT(2532, params->mapCopy != NULL); + + if ((loc = PointsToEntry_loc(tgtPTE)) && (locs = PointsToEntry_locs(tgtPTE))) { + if ((block = LocationSet_block(loc))) { + kind = PAMemoryBlock_kind(block); + if (kind == PAMEMORYBLOCKKIND_LOCALVAR) { + MatchPTFHelper(loc, locs, params->proc, params->mapCopy, params->ptfCopy); + } else if (kind != PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + CError_FATAL(2547); + } + } + } +} + +static void MatchPTFAction2(PointsToEntry *tgtPTE, void *refcon) { + MatchPTFActionParams *params; + LocationSet *loc; + LocationSetSet *locs; + PAMemoryBlock *block; + PAMemoryBlockKind kind; + + IRO_ASSERT(2561, tgtPTE != NULL); + IRO_ASSERT(2562, refcon != NULL); + + params = refcon; + + IRO_ASSERT(2566, params->proc != NULL); + IRO_ASSERT(2567, params->ptfCopy != NULL); + IRO_ASSERT(2568, params->mapCopy != NULL); + + if ((loc = PointsToEntry_loc(tgtPTE)) && (locs = PointsToEntry_locs(tgtPTE))) { + if ((block = LocationSet_block(loc))) { + kind = PAMemoryBlock_kind(block); + if (kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + MatchPTFHelper(loc, locs, params->proc, params->mapCopy, params->ptfCopy); + } + } + } +} + +static Boolean MatchPTF(PartialTransferFunction *tgtPTF, Object *proc, ParamMappingFunction *map, IROLinear *nd, PartialTransferFunction *ptf) { + Boolean result; + PartialTransferFunction *ptfCopy; + ParamMappingFunction *mapCopy; + PointsToFunction *initial; + MatchPTFActionParams params; + + IRO_ASSERT(2593, tgtPTF != NULL); + IRO_ASSERT(2594, proc != NULL); + IRO_ASSERT(2595, map != NULL); + IRO_ASSERT(2596, nd != NULL); + IRO_ASSERT(2597, ptf != NULL); + + ptfCopy = PartialTransferFunction_New(); + PartialTransferFunction_Copy(ptfCopy, ptf); + + mapCopy = ParamMappingFunction_New(); + ParamMappingFunction_Copy(mapCopy, map); + + initial = PartialTransferFunction_initialPointsToFn(tgtPTF); + PointsToFunction_SortByExtendedParamNum(initial); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.ptfCopy = ptfCopy; + params.mapCopy = mapCopy; + params.stackPtr = &stCallingContextStack; + + PointsToFunction_ForEach(initial, MatchPTFAction1, ¶ms); + PointsToFunction_ForEach(initial, MatchPTFAction2, ¶ms); + + result = PointsToFunctions_Match(initial, PartialTransferFunction_initialPointsToFn(ptfCopy)); + if (result) { + PartialTransferFunction_Term(ptf); + PartialTransferFunction_Copy(ptf, ptfCopy); + + ParamMappingFunction_Term(map); + ParamMappingFunction_Copy(map, mapCopy); + } + + PartialTransferFunction_Term(ptfCopy); + PartialTransferFunction_Delete(ptfCopy); + + ParamMappingFunction_Term(mapCopy); + ParamMappingFunction_Delete(mapCopy); + + return result; +} + +static void FindCallTargetsAction2(Object *obj, void *refcon) { + ObjectSet *procList; + + IRO_ASSERT(2650, obj != NULL); + IRO_ASSERT(2651, refcon != NULL); + + procList = refcon; + + if (obj == &stUnknown || ObjectIsAFunction(obj)) + ObjectSet_sub_4867D0(procList, obj); +} + +static void FindCallTargetsAction(LocationSet *ls, void *refcon) { + ObjectSet *procList; + + IRO_ASSERT(2669, ls != NULL); + IRO_ASSERT(2670, refcon != NULL); + + procList = refcon; + + if (!LocationSet_IsUnknown(ls)) { + PAMemoryBlock *mb = LocationSet_block(ls); + if (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + ExtendedParam *ep = PAMemoryBlock_thing(mb); + ObjectSet *objSet = ExtendedParam_objectSet(ep); + ObjectSet_ForEach(objSet, FindCallTargetsAction2, procList); + } + } else { + FindCallTargetsAction2(&stUnknown, procList); + } +} + +static int FindCallTargets(ObjectSet *procList, Object *proc, IROLinear *nd, ParamMappingFunction *map, PartialTransferFunction *ptf) { + LocationSetSet *set; + int evalResult; + int result; + + IRO_ASSERT(2696, procList != NULL); + IRO_ASSERT(2697, proc != NULL); + IRO_ASSERT(2698, nd != NULL); + IRO_ASSERT(2699, nd->type == IROLinearFunccall); + IRO_ASSERT(2700, map != NULL); + IRO_ASSERT(2701, ptf != NULL); + + set = LocationSetSet_New(); + LocationSetSet_Init(set); + evalResult = EvalExpr(set, proc, nd->u.funccall.linear8, &stCallingContextStack, map, ptf); + result = evalResult | ExpandLocationSetSetToActuals(&stCallingContextStack, map, set); + LocationSetSet_ForEach(set, FindCallTargetsAction, procList); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + + return result; +} + +static int LookupParam(LocationSetSet *set, LocationSet *ls, Object *var, Stack **stackPtr, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf, Boolean unkflag) { + Boolean result; + ExtendedParam *ep; + + IRO_ASSERT(2728, set == NULL || set != NULL); + IRO_ASSERT(2729, ls != NULL); + IRO_ASSERT(2730, var != NULL); + IRO_ASSERT(2731, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); + IRO_ASSERT(2732, proc != NULL); + IRO_ASSERT(2733, map == NULL || map != NULL); + IRO_ASSERT(2734, ptf == NULL || ptf != NULL); + + result = 0; + + ep = ExtendedParam_FindByObject(var); + if (!ep) + ep = CreateExtendedParam(stackPtr, map, var, &result); + + IRO_ASSERT(2741, ep != NULL); + + if (ep) { + PAMemoryBlock *block; + LocationSet *newLS; + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, ep); + + newLS = LocationSet_New(); + LocationSet_InitKnown(newLS, block, LocationSet_field(ls), LocationSet_stride(ls), LocationSet_rtype(ls)); + if (set) + LocationSetSet_Add(set, newLS); + + if (unkflag) { + if (map) + result |= FillInAppropriateMappingsWithExtParam(map, var, ep, proc); + + if (ptf) { + PointsToFunction *initial; + + initial = PartialTransferFunction_initialPointsToFn(ptf); + if (initial && !PointsToFunction_FindByLookupCompatibleLocationSet(initial, ls)) { + LocationSet_Term(newLS); + LocationSet_InitKnown(newLS, LocationSet_block(ls), cint64_zero, 0, LocationSet_rtype(ls)); + if (!PointsToFunction_FindByLookupCompatibleLocationSet(initial, newLS)) { + LocationSet *newLS2; + LocationSetSet *newSet; + PointsToEntry *newPTE; + + newLS2 = LocationSet_New(); + LocationSet_InitKnown(newLS2, block, cint64_zero, 0, LocationSet_rtype(ls)); + + newSet = LocationSetSet_New(); + LocationSetSet_Init(newSet); + LocationSetSet_Add(newSet, newLS2); + + newPTE = PointsToEntry_New(); + PointsToEntry_Init(newPTE, newLS, newSet); + result |= PointsToFunction_Add(initial, newPTE); + PointsToEntry_Term(newPTE); + PointsToEntry_Delete(newPTE); + + LocationSetSet_Term(newSet); + LocationSetSet_Delete(newSet); + + LocationSet_Term(newLS2); + LocationSet_Delete(newLS2); + } + } + } + } + + LocationSet_Term(newLS); + LocationSet_Delete(newLS); + } + + return result; +} + +static Boolean GetActualLocsOfExtendedParam(LocationSetSet *set, LocationSet *ls, Object *var, Stack **stackPtr, ParamMappingFunction *map, Boolean flag) { + Boolean result; + PAMemoryBlock *block; + IROLinear *nd; + ExtendedParam *ep; + ParamMapping *mapping; + Type *savedRtype; + CInt64 savedField; + UInt32 savedStride; + LocationSetSet *newSet; + + IRO_ASSERT(2821, set == NULL || set != NULL); + IRO_ASSERT(2822, (ls != NULL && var == NULL) || (ls == NULL && var != NULL)); + IRO_ASSERT(2823, ls == NULL || !LocationSet_IsUnknown(ls)); + IRO_ASSERT(2824, var != &stUnknown); + IRO_ASSERT(2825, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); + IRO_ASSERT(2826, map == NULL || map != NULL); + + result = 0; + block = NULL; + nd = 0; + ep = NULL; + mapping = NULL; + + if (ls) { + block = LocationSet_block(ls); + IRO_ASSERT(2838, block != NULL); + IRO_ASSERT(2839, PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM); + + ep = PAMemoryBlock_thing(block); + IRO_ASSERT(2842, ep != NULL); + + savedField = LocationSet_field(ls); + savedStride = LocationSet_stride(ls); + savedRtype = LocationSet_rtype(ls); + } + + IRO_ASSERT(2848, ep == NULL || ep != NULL); + + if (stackPtr && *stackPtr) { + StackElement *element = Stack_Top(stackPtr); + if (element && !map) + map = StackElement_map(element); + } + + IRO_ASSERT(2859, map == NULL || map != NULL); + + if (ep) { + IRO_ASSERT(2863, var == NULL); + ObjectSet_ForEach(ExtendedParam_objectSet(ep), FindGlobalObjectAction, &var); + if (!var) + var = ObjectSet_FindFirst(ExtendedParam_objectSet(ep)); + if (!var) + var = &stUnknown; + } + + IRO_ASSERT(2870, var != NULL); + + if (map && var != &stUnknown) { + if (flag) + result |= FillInAppropriateMappingsWithExtParam(map, var, ep, NULL); + mapping = ParamMappingFunction_FindMappingByFormal(map, var); + } + + newSet = LocationSetSet_New(); + LocationSetSet_Init(newSet); + + IRO_ASSERT(2884, mapping == NULL || mapping != NULL); + + if (mapping) + nd = ParamMapping_actual(mapping); + + if (!nd) { + if (!ls) { + IRO_ASSERT(2893, var != NULL); + IRO_ASSERT(2894, ep == NULL); + + if (var != &stUnknown) { + ep = CreateExtendedParam(stackPtr, NULL, var, &result); + if (flag && mapping && ParamMapping_extended(mapping) != ep) { + ParamMapping_SetExtended(mapping, ep); + result = 1; + } + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, ep); + savedField = cint64_zero; + savedStride = 0; + savedRtype = CDecl_NewPointerType(var->type); + } else { + block = LocationSet_block(stUnknownLs); + savedRtype = NULL; + } + } else if (var == &stUnknown || !ObjectIsAnExtendedParamCandidate(var)) { + block = LocationSet_block(stUnknownLs); + savedRtype = NULL; + } + + IRO_ASSERT(2925, block != NULL); + + if (block == LocationSet_block(stUnknownLs)) { + LocationSetSet_AddUnknown(newSet, savedRtype, NULL, NULL); + } else { + LocationSet *tmp = LocationSet_New(); + LocationSet_InitKnown(tmp, block, savedField, savedStride, savedRtype); + LocationSetSet_Add(newSet, tmp); + LocationSet_Term(tmp); + LocationSet_Delete(tmp); + } + } else { + Stack *next; + StackElement *element; + if (stackPtr && *stackPtr && (next = Stack_Next(stackPtr)) && (element = Stack_Top(&next))) { + if (ls) { + if (!savedStride && !CInt64_IsZero(&savedField)) { + IROLinear *ic; + IROLinear *d; + ic = IRO_NewIntConst(savedField, TYPE(&stunsignedlong)); + d = IRO_NewLinear(IROLinearOp2Arg); + d->index = ++IRO_NumLinear; + d->rtype = nd->rtype; + d->u.diadic.left = nd; + d->u.diadic.right = ic; + nd = d; + } + if (savedStride) { + IROLinear *call; + IROLinear *d; + call = IRO_NewLinear(IROLinearFunccall); + call->u.funccall.returnedLocs = LocationSetSet_New(); + LocationSetSet_Init(call->u.funccall.returnedLocs); + LocationSetSet_AddUnknown(call->u.funccall.returnedLocs, NULL, NULL, NULL); + d = IRO_NewLinear(IROLinearOp2Arg); + d->index = ++IRO_NumLinear; + d->rtype = nd->rtype; + d->u.diadic.left = nd; + d->u.diadic.right = call; + nd = d; + } + } + EvalExpr(newSet, StackElement_proc(element), nd, &next, StackElement_map(element), StackElement_ptf(element)); + } else { + LocationSetSet_AddUnknown(newSet, NULL, NULL, NULL); + } + } + + if (set) + LocationSetSet_AddSet(set, newSet); + + LocationSetSet_Term(newSet); + LocationSetSet_Delete(newSet); + + return result; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct ExpandLocationSetSetActionParams { + LocationSetSet *toBeRemoved; + LocationSetSet *toBeAdded; + Stack **stackPtr; + ParamMappingFunction *map; + Boolean x10; +} ExpandLocationSetSetActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void ExpandLocationSetSetToActualsAction(LocationSet *ls, void *refcon) { + ExpandLocationSetSetActionParams *params; + + IRO_ASSERT(3021, ls != NULL); + IRO_ASSERT(3022, refcon != NULL); + + params = refcon; + + IRO_ASSERT(3026, params->toBeRemoved != NULL); + IRO_ASSERT(3027, params->toBeAdded != NULL); + IRO_ASSERT(3028, params->stackPtr == NULL || *params->stackPtr == NULL || *params->stackPtr != NULL); + IRO_ASSERT(3029, params->map == NULL || params->map != NULL); + + if (!LocationSet_IsUnknown(ls)) { + PAMemoryBlock *block = LocationSet_block(ls); + if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + ExtendedParam *ep = PAMemoryBlock_thing(block); + if (ep) { + ObjectSet *objSet = ExtendedParam_objectSet(ep); + Object *obj = NULL; + ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); + if (!obj) { + LocationSetSet_Add(params->toBeRemoved, ls); + params->x10 |= GetActualLocsOfExtendedParam(params->toBeAdded, ls, NULL, params->stackPtr, params->map, 0); + } + } + } + } +} + +static int ExpandLocationSetSetToActuals(Stack **stackPtr, ParamMappingFunction *map, LocationSetSet *thingsPointedTo) { + LocationSetSet *toBeRemoved; + LocationSetSet *toBeAdded; + ExpandLocationSetSetActionParams params; + Boolean result; + + IRO_ASSERT(3063, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); + IRO_ASSERT(3064, map == NULL || map != NULL); + IRO_ASSERT(3065, thingsPointedTo != NULL); + + toBeRemoved = LocationSetSet_New(); + LocationSetSet_Init(toBeRemoved); + + toBeAdded = LocationSetSet_New(); + LocationSetSet_Init(toBeAdded); + + memset(¶ms, 0, sizeof(params)); + params.toBeRemoved = toBeRemoved; + params.toBeAdded = toBeAdded; + params.stackPtr = stackPtr; + params.map = map; + params.x10 = 0; + + LocationSetSet_ForEach(thingsPointedTo, ExpandLocationSetSetToActualsAction, ¶ms); + + result = params.x10; + LocationSetSet_sub_488700(thingsPointedTo, toBeRemoved); + LocationSetSet_AddSet(thingsPointedTo, toBeAdded); + + LocationSetSet_Term(toBeRemoved); + LocationSetSet_Delete(toBeRemoved); + + LocationSetSet_Term(toBeAdded); + LocationSetSet_Delete(toBeAdded); + + return result; +} + +static void EvaluatePartialAbsolute(LocationSetSet *set, LocationSetSet *thingsPointedTo, LocationSet *dst, Type *indRtype) { + LocationSet *absLoc; + Type *absLocRtype; + PAMemoryBlock *block; + + IRO_ASSERT(3108, set != NULL); + IRO_ASSERT(3109, thingsPointedTo != NULL); + IRO_ASSERT(3110, dst != NULL); + IRO_ASSERT(3111, indRtype != NULL); + + absLoc = LocationSetSet_FindFirst(thingsPointedTo); + IRO_ASSERT(3114, absLoc != NULL); + + if (!LocationSet_IsUnknown(absLoc)) + absLocRtype = LocationSet_rtype(absLoc); + + if (!LocationSet_IsUnknown(absLoc) && indRtype->size == absLocRtype->size) { + LocationSetSet_AddSet(set, thingsPointedTo); + } else if ( + !LocationSet_IsUnknown(absLoc) && + !LocationSet_stride(absLoc) && + LocationSetSet_Count(thingsPointedTo) == 1 && + (block = LocationSet_block(absLoc)) && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_INT && + absLocRtype->size <= stsignedlonglong.size && + indRtype->size < absLocRtype->size + ) { + CInt64 val2; + CInt64 val8; + CInt64 val4; + CInt64 val5; + CInt64 val1; + CInt64 val3; + CInt64 val7; + CInt64 val6; + LocationSet *ls; + + val1 = LocationSet_field(absLoc); + val2 = *((CInt64 *) PAMemoryBlock_thing(block)); + CInt64_SetLong(&val3, 8); + val4 = cint64_zero; + CInt64_SetLong(&val5, stsignedlonglong.size - absLocRtype->size); + val6 = CInt64_Sub(LocationSet_field(dst), val1); + CInt64_SetLong(&val7, absLocRtype->size - indRtype->size); + val5 = CInt64_Add(val5, val6); + val4 = CInt64_Add(val4, val7); + val4 = CInt64_Sub(val4, val6); + val5 = CInt64_MulU(val5, val3); + val4 = CInt64_MulU(val4, val3); + val8 = cint64_negone; + val8 = CInt64_Shl(val8, val5); + val8 = CInt64_ShrU(val8, val5); + val2 = CInt64_And(val2, val8); + val2 = CInt64_ShrU(val2, val4); + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_INT, &val2); + + ls = LocationSet_New(); + LocationSet_InitKnown(ls, block, cint64_zero, 0, indRtype); + LocationSetSet_Add(set, ls); + LocationSet_Term(ls); + LocationSet_Delete(ls); + } else { + LocationSetSet_AddUnknown(set, indRtype, NULL, NULL); + } +} + +static Boolean AddToInitialPointsToFunc(Boolean flag, PartialTransferFunction *ptf, LocationSet *dst, LocationSetSet *set) { + Boolean result; + LocationSet *ls; + PointsToFunction *initial; + PointsToEntry *pte; + + IRO_ASSERT(3192, ptf == NULL || ptf != NULL); + IRO_ASSERT(3193, dst != NULL); + IRO_ASSERT(3194, set != NULL); + + result = 0; + + if (flag && ptf) { + ls = LocationSetSet_FindUnknown(set); + if (!ls || LocationSet_rtype(ls)) { + initial = PartialTransferFunction_initialPointsToFn(ptf); + if (initial && !PointsToFunction_FindByLookupCompatibleLocationSet(initial, dst)) { + IRO_ASSERT(3208, dst != NULL); + + pte = PointsToEntry_New(); + PointsToEntry_Init(pte, dst, set); + result = PointsToFunction_AddWithoutChecking(initial, pte); + PointsToEntry_Term(pte); + PointsToEntry_Delete(pte); + } + } + } + + return result; +} + +static Boolean Lookup(LocationSetSet *set, Stack **stackPtr, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf, LocationSet *dst, PointsToFunction *pointsToFunc, Boolean unk, Type *indRtype) { + Boolean result; + LocationSetSet *mySet; + LocationSetSet *set2; + PAMemoryBlock *block; + ExtendedParam *ep; + PALocalVar *local; + ObjectSet *objSet; + Object *obj; + + IRO_ASSERT(3245, set == NULL || set != NULL); + IRO_ASSERT(3246, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); + IRO_ASSERT(3247, proc == NULL || proc != NULL); + IRO_ASSERT(3248, map == NULL || map != NULL); + IRO_ASSERT(3249, ptf == NULL || ptf != NULL); + IRO_ASSERT(3250, dst != NULL); + IRO_ASSERT(3251, pointsToFunc == NULL || pointsToFunc != NULL); + IRO_ASSERT(3252, indRtype == NULL || indRtype != NULL); + + result = 0; + + set2 = NULL; + + mySet = LocationSetSet_New(); + LocationSetSet_Init(mySet); + + if (proc) { + if (LocationIsVolatile(dst, proc)) + LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL); + } + + if (pointsToFunc && !LocationSet_IsUnknown(dst)) { + PointsToEntry *pte = PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, dst); + if (pte) { + set2 = PointsToEntry_locs(pte); + } else if (indRtype) { + pte = PointsToFunction_FindContainingLocationSet(pointsToFunc, dst, indRtype); + if (pte) + set2 = PointsToEntry_locs(pte); + } + } + + if (set2) { + if (indRtype) + EvaluatePartialAbsolute(mySet, set2, dst, indRtype); + else + LocationSetSet_AddSet(mySet, set2); + } else if (!set2) { + block = NULL; + if (!LocationSet_IsUnknown(dst)) + block = LocationSet_block(dst); + + if (!LocationSet_IsUnknown(dst) && LocationSet_stride(dst)) { + LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL); + } else if ( + block && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM && + (ep = PAMemoryBlock_thing(block)) && + (objSet = ExtendedParam_objectSet(ep)) + ) { + obj = NULL; + ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); + if (!obj) { + LocationSetSet *lss3; + LocationSet *tmp; + // Boolean result1; + EvalExprAction3Params params; + + lss3 = LocationSetSet_New(); + LocationSetSet_Init(lss3); + result = GetActualLocsOfExtendedParam(lss3, dst, NULL, stackPtr, map, unk); + + memset(¶ms, 0, sizeof(params)); + params.set = mySet; + params.stackPtr = stackPtr; + params.proc = proc; + params.map = map; + params.ptf = ptf; + params.pointsToFunc = pointsToFunc; + params.indRtype = indRtype; + params.x1C = 0; + LocationSetSet_ForEach(lss3, EvalExprAction3, ¶ms); + result |= params.x1C; + + LocationSetSet_Term(lss3); + LocationSetSet_Delete(lss3); + + if ((tmp = LocationSetSet_FindUnknown(mySet))) { + if (!LocationSet_restriction(tmp) && ObjectSet_Count(objSet) == 1) { + if ((obj = ObjectSet_FindFirst(objSet))) { + if (ObjectIsRestrictQualified(obj)) { + LocationSet_Term(tmp); + LocationSet_InitUnknown(tmp, indRtype, block, NULL); + } + } + } + } + + result |= AddToInitialPointsToFunc(unk, ptf, dst, mySet); + } else { + // Boolean result1; + Stack *next; + StackElement *element; + + result = GetActualLocsOfExtendedParam(NULL, dst, NULL, stackPtr, map, unk); + if (stackPtr && *stackPtr && (next = Stack_Next(stackPtr)) && (element = Stack_Top(&next))) { + result |= Lookup(mySet, &next, StackElement_proc(element), StackElement_map(element), + StackElement_ptf(element), dst, StackElement_funcCall(element)->pointsToFunction, unk, indRtype); + } else { + LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL); + } + + result |= AddToInitialPointsToFunc(unk, ptf, dst, mySet); + } + } else if ( + block && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR && + (local = PAMemoryBlock_thing(block)) && + proc && + (obj = GetLocalObject(local, proc, 1)) && + ObjectIsAFunctionArgument(proc, obj) + ) { + result = LookupParam(mySet, dst, obj, stackPtr, proc, map, ptf, unk); + } else { + LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL); + } + } + + if (set) + LocationSetSet_AddSet(set, mySet); + + LocationSetSet_Term(mySet); + LocationSetSet_Delete(mySet); + + return result; +} + +static Boolean InputsHaveNewPointerValues(PartialTransferFunction *tgtPTF, PartialTransferFunction *ptf) { + IRO_ASSERT(3393, tgtPTF != NULL); + IRO_ASSERT(3394, ptf != NULL); + + return 0; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct CreateEPActionParams { + ParamMapping *last; + ParamMapping *lowest; +} CreateEPActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void CreateExtendedParamAction(ParamMapping *mapping, void *refcon) { + CreateEPActionParams *params; + ExtendedParam *ep; + uint32 value; + ExtendedParam *lowestEP; + uint32 lowestValue; + ExtendedParam *lastEP; + uint32 lastValue; + + IRO_ASSERT(3417, mapping != NULL); + IRO_ASSERT(3418, refcon != NULL); + + params = refcon; + + IRO_ASSERT(3422, params->last == NULL || params->last != NULL); + IRO_ASSERT(3423, params->lowest == NULL || params->lowest != NULL); + + if ((ep = ParamMapping_extended(mapping))) { + value = ExtendedParam_sub_489110(ep); + + if (params->lowest) { + lowestEP = ParamMapping_extended(params->lowest); + lowestValue = ExtendedParam_sub_489110(lowestEP); + if (params->last) { + lastEP = ParamMapping_extended(params->last); + lastValue = ExtendedParam_sub_489110(lastEP); + if (value > lastValue && value < lowestValue) + params->lowest = mapping; + } else if (value < lowestValue) { + params->lowest = mapping; + } + } else if (params->last) { + lastEP = ParamMapping_extended(params->last); + lastValue = ExtendedParam_sub_489110(lastEP); + if (value > lastValue) + params->lowest = mapping; + } else { + params->lowest = mapping; + } + } +} + +static ExtendedParam *FindMatchingExtendedParam(Stack **stackPtr, ParamMappingFunction *map, LocationSetSet *lss, ParamMapping *lowest, Boolean *result) { + ExtendedParam *ep; + ExtendedParam *lowestEP; + + IRO_ASSERT(3473, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); + IRO_ASSERT(3474, map == NULL || map != NULL); + IRO_ASSERT(3475, lss != NULL); + IRO_ASSERT(3476, lowest != NULL); + + ep = NULL; + if ((lowestEP = ParamMapping_extended(lowest))) { + PAMemoryBlock *block; + LocationSet *lowestLS; + LocationSetSet *lowestLSS; + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, lowestEP); + + lowestLS = LocationSet_New(); + LocationSet_InitKnown(lowestLS, block, cint64_zero, 0, TYPE(&void_ptr)); + + lowestLSS = LocationSetSet_New(); + LocationSetSet_Init(lowestLSS); + + *result |= GetActualLocsOfExtendedParam(lowestLSS, lowestLS, NULL, stackPtr, map, 0); + if (LocationSetSets_Equal(lowestLSS, lss)) + ep = lowestEP; + + LocationSetSet_Term(lowestLSS); + LocationSetSet_Delete(lowestLSS); + + LocationSet_Term(lowestLS); + LocationSet_Delete(lowestLS); + } + + return ep; +} + +static ExtendedParam *CreateExtendedParam(Stack **stackPtr, ParamMappingFunction *map, Object *var, Boolean *result) { + ExtendedParam *ep; + ParamMapping *mapping; + LocationSetSet *lss; + CreateEPActionParams params; + + IRO_ASSERT(3518, map == NULL || map != NULL); + IRO_ASSERT(3519, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); + IRO_ASSERT(3520, var != NULL); + + mapping = NULL; + if (map) + mapping = ParamMappingFunction_FindMappingByFormal(map, var); + + ep = ExtendedParam_FindByObject(var); + if (ep) { + if (mapping) + IRO_ASSERT(3535, ep == ParamMapping_extended(mapping) || ParamMapping_extended(mapping) == NULL); + } else if (map && !ObjectIsRestrictQualified(var)) { + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + *result |= GetActualLocsOfExtendedParam(lss, NULL, var, stackPtr, map, 0); + + memset(¶ms, 0, sizeof(params)); + params.last = NULL; + do { + params.lowest = NULL; + pmf_sub_487C70(map, CreateExtendedParamAction, ¶ms); + if (params.lowest && params.lowest != mapping) + ep = FindMatchingExtendedParam(stackPtr, map, lss, params.lowest, result); + params.last = params.lowest; + } while (params.lowest && !ep); + + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + } + + if (!ep) + ep = ExtendedParam_FindByObject(var); + + if (!ep) { + ep = ExtendedParam_New(); + ExtendedParam_Init(ep, var); + } else { + ExtendedParam_sub_4867B0(ep, var); + } + + if (stExtParamSet) + ExtParamSet_sub_487630(stExtParamSet, ep); + + IRO_ASSERT(3583, ep != NULL); + + return ep; +} + +#ifdef IRO_DEBUG +void __assertion_failed(char *expr, char *filename, int line) { + CError_ASSERT(3605, filename); + CError_Internal(filename, line); +} +#endif + +static void RecordActuals(IROLinear *nd, Object *proc, ParamMappingFunction *map) { + IRO_ASSERT(3628, nd != NULL); + IRO_ASSERT(3629, nd->type == IROLinearFunccall); + IRO_ASSERT(3630, proc != NULL); + IRO_ASSERT(3631, map != NULL); + + if (proc != &stUnknown) { + int i; + ObjectList *args; + Object *arg; + + args = FunctionArguments(proc); + if (args) + arg = args->object; + else + arg = &stUnknown; + + for (i = 0; i < nd->u.funccall.argCount; i++) { + IRO_ASSERT(3643, arg != NULL); + + if (arg != &stUnknown) { + ParamMapping *mapping = ParamMapping_New(); + ParamMapping_Init_PROBABLY(mapping, nd->u.funccall.args[i], arg, NULL); + Pmf_Add_sub_486610(map, mapping); + ParamMapping_Term(mapping); + ParamMapping_Delete(mapping); + } + + if (args) { + args = args->next; + if (args) + arg = args->object; + else + arg = &stUnknown; + } + } + } +} + +static Boolean IsAddressableLocation(LocationSet *loc, Object *proc, IRONode *fnode, IROLinear *nd) { + IRO_ASSERT(3676, loc != NULL); + IRO_ASSERT(3677, fnode != NULL); + IRO_ASSERT(3678, nd != NULL); + + if (!LocationSet_IsUnknown(loc)) { + PAMemoryBlock *block; + PALocalVar *local; + Object *obj; + ExtendedParam *ep; + ObjectSet *objSet; + + block = LocationSet_block(loc); + if ( + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR && + (local = PAMemoryBlock_thing(block)) && + (obj = GetLocalObject(local, proc, 0)) && + fnode->addressed && + !ObjectSet_sub_485020(fnode->addressed, obj) + ) { + return 0; + } + + if ( + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM && + (ep = PAMemoryBlock_thing(block)) && + (objSet = ExtendedParam_objectSet(ep)) && + ObjectSet_Count(objSet) == 1 && + (obj = ObjectSet_FindFirst(objSet)) && + ObjectIsAFunctionArgument(proc, obj) && + ObjectIsRestrictQualified(obj) + ) { + return 0; + } + } + + return 1; +} + +static Boolean LocationSetsAlias(LocationSet *ls1, LocationSet *ls2) { + IRO_ASSERT(3719, ls1 != NULL); + IRO_ASSERT(3720, ls2 != NULL); + + return + (ls1 == ls2) || + LocationSet_IsUnknown(ls1) || + LocationSet_IsUnknown(ls2) || + ( + (LocationSet_stride(ls1) || + LocationSet_stride(ls2) || + CInt64_Equal(LocationSet_field(ls1), LocationSet_field(ls2))) && + MemoryBlocks_Equal(LocationSet_block(ls1), LocationSet_block(ls2)) + ); +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct FindAliasingParams { + LocationSetSet *x0; + LocationSet *x4; + Boolean x8; +} FindAliasingParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void FindAliasingAction2(LocationSet *ls, void *refcon) { + FindAliasingParams *params; + + params = refcon; + + if (!params->x8) { + if (LocationSetsAlias(params->x4, ls)) + params->x8 = 1; + } +} + +static void FindAliasingAction(LocationSet *ls, void *refcon) { + FindAliasingParams *params; + + IRO_ASSERT(3751, ls != NULL); + IRO_ASSERT(3752, refcon != NULL); + + params = refcon; + + if (!params->x8) { + params->x4 = ls; + LocationSetSet_ForEach(params->x0, FindAliasingAction2, params); + } +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct KillLocationParams { + Object *proc; + IRONode *fnode; + IROLinear *nd; + PartialTransferFunction *ptf; + PointsToFunction *toBeKilled; + LocationSet *dst; + Boolean x18; +} KillLocationParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void KillAllAddressableLocationsAction(PointsToEntry *pte, void *refcon) { + KillLocationParams *params; + LocationSet *loc; + + IRO_ASSERT(3779, pte != NULL); + IRO_ASSERT(3780, refcon != NULL); + + params = refcon; + + IRO_ASSERT(3784, params->proc != NULL); + IRO_ASSERT(3785, params->fnode != NULL); + IRO_ASSERT(3786, params->nd != NULL); + IRO_ASSERT(3787, params->ptf != NULL); + IRO_ASSERT(3788, params->toBeKilled != NULL); + IRO_ASSERT(3789, params->dst == NULL); + + loc = PointsToEntry_loc(pte); + IRO_ASSERT(3793, loc != NULL); + IRO_ASSERT(3794, !LocationSet_IsUnknown(loc)); + + if (IsAddressableLocation(loc, params->proc, params->fnode, params->nd)) + PointsToFunction_Add(params->toBeKilled, pte); +} + +static void KillAllAliasingExtParamLocsAction(PointsToEntry *pte, void *refcon) { + KillLocationParams *params; + LocationSet *loc; + + IRO_ASSERT(3813, pte != NULL); + IRO_ASSERT(3814, refcon != NULL); + + params = refcon; + + IRO_ASSERT(3818, params->proc != NULL); + IRO_ASSERT(3819, params->fnode != NULL); + IRO_ASSERT(3820, params->nd != NULL); + IRO_ASSERT(3821, params->ptf != NULL); + IRO_ASSERT(3822, params->toBeKilled != NULL); + IRO_ASSERT(3823, params->dst != NULL); + IRO_ASSERT(3824, LocationSet_block(params->dst) != NULL); + IRO_ASSERT(3825, PAMemoryBlock_kind(LocationSet_block(params->dst)) == PAMEMORYBLOCKKIND_EXTENDEDPARAM); + + loc = PointsToEntry_loc(pte); + IRO_ASSERT(3829, loc != NULL); + IRO_ASSERT(3830, !LocationSet_IsUnknown(loc)); + + if (loc != params->dst) { + if (LocationSetsAlias(loc, params->dst)) { + PointsToFunction_Add(params->toBeKilled, pte); + } else { + ExtendedParam *ep; + ObjectSet *objSet; + Object *obj; + PAMemoryBlock *block; + + if ( + (ep = PAMemoryBlock_thing(LocationSet_block(params->dst))) && + (objSet = ExtendedParam_objectSet(ep)) && + (ObjectSet_Count(objSet) != 1 || !(obj = ObjectSet_FindFirst(objSet)) || !ObjectIsRestrictQualified(obj)) && + (block = LocationSet_block(loc)) && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM && + (ep = PAMemoryBlock_thing(block)) && + (objSet = ExtendedParam_objectSet(ep)) && + (ObjectSet_Count(objSet) != 1 || !(obj = ObjectSet_FindFirst(objSet)) || !ObjectIsRestrictQualified(obj)) + ) { + LocationSetSet *lss1; + LocationSetSet *lss2; + Boolean changed; + FindAliasingParams aparams; + + lss1 = LocationSetSet_New(); + LocationSetSet_Init(lss1); + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + + changed = GetActualLocsOfExtendedParam(lss1, loc, NULL, &stCallingContextStack, NULL, 0); + changed |= GetActualLocsOfExtendedParam(lss2, params->dst, NULL, &stCallingContextStack, NULL, 0); + + memset(&aparams, 0, sizeof(aparams)); + aparams.x8 = 0; + aparams.x0 = lss2; + LocationSetSet_ForEach(lss1, FindAliasingAction, &aparams); + if (aparams.x8) + PointsToFunction_Add(params->toBeKilled, pte); + + LocationSetSet_Term(lss1); + LocationSetSet_Delete(lss1); + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + } + } + } +} + +static void KillLocationsAction(PointsToEntry *pte, void *refcon) { + KillLocationParams *params; + LocationSet *loc; + LocationSetSet *lss; + + IRO_ASSERT(3886, pte != NULL); + IRO_ASSERT(3887, refcon != NULL); + + params = refcon; + + IRO_ASSERT(3891, params->proc != NULL); + IRO_ASSERT(3892, params->fnode != NULL); + IRO_ASSERT(3893, params->nd != NULL); + IRO_ASSERT(3894, params->ptf != NULL); + IRO_ASSERT(3895, params->toBeKilled != NULL); + IRO_ASSERT(3896, params->dst == NULL); + + loc = PointsToEntry_loc(pte); + IRO_ASSERT(3900, loc != NULL); + IRO_ASSERT(3901, !LocationSet_IsUnknown(loc)); + + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + + params->x18 |= Assign(params->ptf, loc, lss, params->proc, params->nd, params->fnode); + + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); +} + +static Boolean KillAllAddressableLocations(Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf) { + Boolean result; + PointsToFunction *pointsToFunc; + PointsToFunction *pointsToFuncCopy; + PointsToFunction *toBeKilled; + KillLocationParams params; + + IRO_ASSERT(3921, proc != NULL); + IRO_ASSERT(3922, fnode == NULL || fnode != NULL); + IRO_ASSERT(3923, nd == NULL || nd != NULL); + IRO_ASSERT(3924, ptf != NULL); + + if (nd && nd->pointsToFunction) + pointsToFunc = nd->pointsToFunction; + else + pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf); + + pointsToFuncCopy = PointsToFunction_New(); + PointsToFunction_Copy(pointsToFuncCopy, pointsToFunc); + + toBeKilled = PointsToFunction_New(); + PointsToFunction_Init(toBeKilled); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.fnode = fnode; + params.nd = nd; + params.ptf = ptf; + params.toBeKilled = toBeKilled; + params.dst = NULL; + params.x18 = 0; + + if (pointsToFunc) { + PointsToFunction_ForEach(pointsToFunc, KillAllAddressableLocationsAction, ¶ms); + PointsToFunction_ForEach(params.toBeKilled, KillLocationsAction, ¶ms); + } + + PointsToFunction_Term(toBeKilled); + PointsToFunction_Delete(toBeKilled); + + if (params.x18) + result = !PointsToFunctions_Equal(pointsToFuncCopy, pointsToFunc); + else + result = 0; + + PointsToFunction_Term(pointsToFuncCopy); + PointsToFunction_Delete(pointsToFuncCopy); + + return result; +} + +static void KillAllAliasingExtParamLocs(Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf, LocationSet *dst) { + PointsToFunction *pointsToFunc; + PointsToFunction *toBeKilled; + KillLocationParams params; + + IRO_ASSERT(3974, proc != NULL); + IRO_ASSERT(3975, fnode == NULL || fnode != NULL); + IRO_ASSERT(3976, nd == NULL || nd != NULL); + IRO_ASSERT(3977, ptf != NULL); + IRO_ASSERT(3978, dst != NULL); + + if (!LocationSet_IsUnknown(dst) && LocationSet_block(dst)) { + if (PAMemoryBlock_kind(LocationSet_block(dst)) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + + if (nd && nd->pointsToFunction) + pointsToFunc = nd->pointsToFunction; + else + pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf); + + toBeKilled = PointsToFunction_New(); + PointsToFunction_Init(toBeKilled); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.fnode = fnode; + params.nd = nd; + params.ptf = ptf; + params.toBeKilled = toBeKilled; + params.dst = dst; + params.x18 = 0; + + if (pointsToFunc) { + PointsToFunction_ForEach(pointsToFunc, KillAllAliasingExtParamLocsAction, ¶ms); + PointsToFunction_ForEach(params.toBeKilled, KillLocationsAction, ¶ms); + } + + PointsToFunction_Term(toBeKilled); + PointsToFunction_Delete(toBeKilled); + } + } +} + +static Boolean Assign(PartialTransferFunction *ptf, LocationSet *dst, LocationSetSet *srcs, Object *proc, IROLinear *nd, IRONode *fnode) { + PointsToFunction *pointsToFunc; + Boolean result; + PointsToEntry *pte; + LocationSet *loc; + LocationSetSet *locs; + LocationSet *bitfieldOf; + LocationSetSet *lss; + + IRO_ASSERT(4027, ptf != NULL); + IRO_ASSERT(4028, dst != NULL); + IRO_ASSERT(4029, srcs != NULL); + IRO_ASSERT(4030, proc != NULL); + IRO_ASSERT(4031, nd == NULL || nd != NULL); + IRO_ASSERT(4032, fnode == NULL || fnode != NULL); + + if (nd) { + if (!nd->pointsToFunction) { + nd->pointsToFunction = PointsToFunction_New(); + PointsToFunction_Init(nd->pointsToFunction); + } + pointsToFunc = nd->pointsToFunction; + } else { + pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf); + } + + pte = PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, dst); + if (pte) { + loc = PointsToEntry_loc(pte); + locs = PointsToEntry_locs(pte); + IRO_ASSERT(4056, !LocationSet_IsUnknown(dst)); + IRO_ASSERT(4057, LocationSet_stride(dst) == 0 || LocationSet_stride(loc) != 0); + + result = !LocationSetSets_Equal(srcs, locs) || LocationSet_stride(dst) != LocationSet_stride(loc); + + if (result) { + pte = PointsToEntry_New(); + PointsToEntry_Init(pte, dst, srcs); + PointsToFunction_RemoveByLocationSet(pointsToFunc, loc); + PointsToFunction_AddWithoutChecking(pointsToFunc, pte); + PointsToEntry_Term(pte); + PointsToEntry_Delete(pte); + } + } else if (!LocationSet_IsUnknown(dst)) { + KillAllAliasingExtParamLocs(proc, fnode, nd, ptf, dst); + + pte = PointsToEntry_New(); + PointsToEntry_Init(pte, dst, srcs); + result = PointsToFunction_AddWithoutChecking(pointsToFunc, pte); + PointsToEntry_Term(pte); + PointsToEntry_Delete(pte); + } else if ((bitfieldOf = LocationSet_bitfieldOf(dst))) { + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); + result = Assign(ptf, bitfieldOf, lss, proc, nd, fnode); + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + } else if (!LocationSet_restriction(dst)) { + result = KillAllAddressableLocations(proc, fnode, nd, ptf); + } + + return result; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct EvalMeetActionParams { + Object *proc; + IRONode *fnode; + IRONode *pred; + IROLinear *nd; + PartialTransferFunction *ptf; + Boolean x14; + Boolean x15; +} EvalMeetActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void EvalMeetAction(PointsToEntry *pte, void *refcon) { + EvalMeetActionParams *params; + LocationSet *loc; + LocationSetSet *set; + UInt16 i; + + IRO_ASSERT(4123, pte != NULL); + IRO_ASSERT(4124, refcon != NULL); + + params = refcon; + + IRO_ASSERT(4128, params->proc != NULL); + IRO_ASSERT(4129, params->fnode != NULL); + IRO_ASSERT(4130, params->pred != NULL); + IRO_ASSERT(4131, params->nd != NULL); + IRO_ASSERT(4132, params->ptf != NULL); + + loc = PointsToEntry_loc(pte); + + set = LocationSetSet_New(); + LocationSetSet_Init(set); + LocationSetSet_AddSet(set, PointsToEntry_locs(pte)); + + for (i = 0; i < params->fnode->numpred; i++) { + IRONode *pred = FunctionNodeTable(params->proc)[params->fnode->pred[i]]; + if (pred->x3C && pred != params->pred) { + params->x14 |= Lookup(set, &stCallingContextStack, params->proc, NULL, params->ptf, loc, pred->last->pointsToFunction, 0, NULL); + } + } + + params->x15 |= Assign(params->ptf, loc, set, params->proc, params->nd, params->fnode); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); +} + +static Boolean EvalMeet(Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf) { + PointsToFunction *pointsToFunc; + EvalMeetActionParams params; + int i; + + IRO_ASSERT(4163, proc != NULL); + IRO_ASSERT(4164, fnode != NULL); + IRO_ASSERT(4165, nd != NULL); + IRO_ASSERT(4166, ptf != NULL); + + pointsToFunc = PointsToFunction_New(); + if (nd->pointsToFunction) + PointsToFunction_Copy(pointsToFunc, nd->pointsToFunction); + else + PointsToFunction_Init(pointsToFunc); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.fnode = fnode; + params.nd = nd; + params.ptf = ptf; + params.x14 = 0; + params.x15 = 0; + + for (i = 0; i < fnode->numpred; i++) { + IRONode *pred = FunctionNodeTable(proc)[fnode->pred[i]]; + params.pred = pred; + if (pred->x3C && pred->last->pointsToFunction) { + PointsToFunction_ForEach(pred->last->pointsToFunction, EvalMeetAction, ¶ms); + } + } + + if (!params.x14 && params.x15) { + if (nd->pointsToFunction) + params.x14 = !PointsToFunctions_Equal(pointsToFunc, nd->pointsToFunction); + else + params.x14 = PointsToFunction_FindFirst(pointsToFunc) != NULL; + } + + PointsToFunction_Term(pointsToFunc); + PointsToFunction_Delete(pointsToFunc); + + return params.x14; +} + +static PartialTransferFunction *AllocatePTF(Object *proc, IROLinear *nd, PartialTransferFunction *ptf) { + PartialTransferFunction *newPTF; + + IRO_ASSERT(4210, proc != NULL); + IRO_ASSERT(4211, proc->u.func.ptfList != NULL); + IRO_ASSERT(4212, nd == NULL || nd != NULL); + IRO_ASSERT(4213, ptf == NULL || ptf != NULL); + + newPTF = PartialTransferFunction_New(); + PartialTransferFunction_Init(newPTF, nd, ptf); + PTFList_sub_48A050(proc->u.func.ptfList, newPTF); + return newPTF; +} + +static Object *FindMainEntryPoint(Object *function) { + IRO_ASSERT(4229, function != NULL); + + return function; +} + +static ObjectList *FunctionArguments(Object *proc) { + Object *search; + ObjectList *scan; + ObjectList *list; + ObjectList *prev; + ExtendedParam *ep; + char *name; + VarInfo *vi; + Object *obj; + FuncArg *args; + Boolean notFound; + + IRO_ASSERT(4252, proc != NULL); + + if (proc == stCurrentProc) { + for (list = arguments; list; list = list->next) { + if ((obj = list->object) && obj->name && (name = obj->name->name) && name[0]) { + prev = NULL; + for (scan = proc->u.func.argList; scan; scan = scan->next) { + prev = scan; + if ((search = scan->object) && search->name && search->name->name) { + if (!strcmp(name, search->name->name)) + break; + } + } + + if (!scan) + search = NULL; + + notFound = !search; + + if (!search) { + search = IRO_malloc(sizeof(Object)); + ep = NULL; + search->u.var.info = IRO_malloc(sizeof(VarInfo)); + memset(search->u.var.info, 0, sizeof(VarInfo)); + search->u.var.info->func = proc; + } else { + ep = search->extParam; + } + + vi = search->u.var.info; + memcpy(search, obj, sizeof(Object)); + search->extParam = ep; + search->u.var.info = vi; + search->u.var.realObj = obj; + + if (notFound) { + scan = IRO_malloc(sizeof(ObjectList)); + scan->next = NULL; + scan->object = search; + if (!prev) + proc->u.func.argList = scan; + else + prev->next = scan; + } + } + } + } else if (proc->type) { + for (args = TYPE_FUNC(proc->type)->args; args; args = args->next) { + if (args->name && (name = args->name->name) && name[0]) { + prev = NULL; + for (scan = proc->u.func.argList; scan; scan = scan->next) { + prev = scan; + if ((search = scan->object) && search->name && search->name->name) { + if (!strcmp(name, search->name->name)) + break; + } + } + + if (!scan) + search = NULL; + + if (!search) { + search = IRO_malloc(sizeof(Object)); + memset(search, 0, sizeof(Object)); + search->datatype = DLOCAL; + search->extParam = NULL; + search->name = GetHashNameNodeExport(name); + search->type = args->type; + search->qual = args->qual; + search->u.var.info = IRO_malloc(sizeof(VarInfo)); + memset(search->u.var.info, 0, sizeof(VarInfo)); + search->u.var.info->func = proc; + + scan = IRO_malloc(sizeof(ObjectList)); + scan->next = NULL; + scan->object = search; + if (!prev) + proc->u.func.argList = scan; + else + prev->next = scan; + } + } + } + } + + return proc->u.func.argList; +} + +static IRONode **FunctionNodeTable(Object *proc) { + IRO_ASSERT(4383, proc != NULL); + + IRO_ASSERT(4391, proc == stCurrentProc); + + return IRO_NodeTable; +} + +static IRONode *FunctionFirstNode(Object *proc) { + IRO_ASSERT(4401, proc != NULL); + + IRO_ASSERT(4409, proc == stCurrentProc); + + return IRO_FirstNode; +} + +static void UpdatePTFDomain() { + // no idea what this would've done +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct EvalCallActionParams { + Object *proc; + IRONode *fnode; + IROLinear *nd; + PartialTransferFunction *ptf; + ParamMappingFunction *map; + int x14; + Boolean x18; + Boolean x19; + Boolean x1A; +} EvalCallActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void EvalCallAction(Object *proc, void *refcon) { + EvalCallActionParams *params; + ParamMappingFunction *pmf; + PartialTransferFunction *tgtPTF; + Boolean flag; + Boolean flag2; + + IRO_ASSERT(4458, proc != NULL); + IRO_ASSERT(4459, refcon != NULL); + + params = refcon; + + IRO_ASSERT(4463, params->proc != NULL); + IRO_ASSERT(4464, params->fnode != NULL); + IRO_ASSERT(4465, params->nd != NULL); + IRO_ASSERT(4466, params->ptf != NULL); + IRO_ASSERT(4467, params->map == NULL || params->map != NULL); + + if (!params->x18) { + pmf = ParamMappingFunction_New(); + ParamMappingFunction_Init(pmf); + RecordActuals(params->nd, proc, pmf); + + flag = 0; + if (!Stack_sub_48A710(&stCallingContextStack, proc)) { + StackElement *element; + + flag2 = 0; + tgtPTF = GetPTF(pmf, proc, params->nd, params->ptf, &flag2); + + element = StackElement_New(); + StackElement_Init(element, proc, tgtPTF, pmf, params->nd); + Stack_sub_48A660(&stCallingContextStack, element); + StackElement_Term(element); + StackElement_Delete(element); + + IRO_ASSERT(4490, tgtPTF != NULL); + + flag = 1; + + if (stPTFList) + PTFList_sub_48A050(stPTFList, tgtPTF); + PartialTransferFunction_sub_48A610(tgtPTF, 0); + + if (flag2 || params->x1A) { + if (params->x1A) { + params->x1A = 0; + EvalProc(proc, pmf, tgtPTF); + } else { + tgtPTF = stUnknownPTF; + } + } + } else { + tgtPTF = stUnknownPTF; + } + + if (params->map) + params->x19 |= ApplySummary(tgtPTF, pmf, params->proc, params->fnode, params->nd, params->ptf, params->map, params->x14 == 1); + + if (flag) { + StackElement *element = Stack_sub_48A5B0(&stCallingContextStack); + StackElement_Term(element); + StackElement_Delete(element); + } + + ParamMappingFunction_Term(pmf); + ParamMappingFunction_Delete(pmf); + } +} + +static Boolean EvalCall(Object *proc, IRONode *fnode, IROLinear *nd, ParamMappingFunction *map, PartialTransferFunction *ptf) { + EvalCallActionParams params; + ObjectSet *objSet; + + IRO_ASSERT(4548, proc != NULL); + IRO_ASSERT(4549, fnode != NULL); + IRO_ASSERT(4550, nd != NULL); + IRO_ASSERT(4551, map != NULL); + IRO_ASSERT(4552, ptf != NULL); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.fnode = fnode; + params.nd = nd; + params.ptf = ptf; + params.map = map; + params.x18 = 0; + params.x19 = 0; + params.x1A = 0; + + objSet = ObjectSet_New(); + ObjectSet_Init(objSet); + + params.x19 |= FindCallTargets(objSet, proc, nd, map, ptf); + params.x14 = ObjectSet_Count(objSet); + ObjectSet_ForEach(objSet, EvalCallAction, ¶ms); + + ObjectSet_Term(objSet); + ObjectSet_Delete(objSet); + + return params.x19; +} + +static void AdjustTypesForVolatilityAction(LocationSet *ls, void *refcon) { + Type *type; + Type *newtype; + UInt32 qual; + + type = LocationSet_rtype(ls); + switch (type->type) { + case TYPEARRAY: + qual = TYPE_POINTER(type)->qual; + break; + case TYPEPOINTER: + qual = TYPE_POINTER(type)->qual; + break; + case TYPEMEMBERPOINTER: + qual = TYPE_MEMBER_POINTER(type)->qual; + break; + default: + CError_FATAL(4604); + } + + if (!(qual & Q_VOLATILE)) { + switch (type->type) { + case TYPEARRAY: + newtype = CDecl_NewArrayType(TYPE_POINTER(type)->target, type->size); + TYPE_POINTER(newtype)->qual |= Q_VOLATILE; + break; + case TYPEPOINTER: + newtype = CDecl_NewPointerType(TYPE_POINTER(type)->target); + TYPE_POINTER(newtype)->qual |= Q_VOLATILE; + break; + case TYPEMEMBERPOINTER: + newtype = galloc(sizeof(TypeMemberPointer)); + memcpy(newtype, type, sizeof(TypeMemberPointer)); + TYPE_MEMBER_POINTER(newtype)->qual |= Q_VOLATILE; + break; + } + + LocationSet_SetRtype(ls, newtype); + } +} + +static void AdjustTypesForVolatility(LocationSetSet *set, Object *proc, IROLinear *nd) { + if (nd->rtype && CParser_IsVolatile(nd->rtype, nd->nodeflags & ENODE_FLAG_QUALS)) + LocationSetSet_ForEach(set, AdjustTypesForVolatilityAction, NULL); +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct EvalAssignAction2Params { + CInt64 x0; + IROLinear *nd; + Boolean xC; +} EvalAssignAction2Params; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void EvalAssignAction2(LocationSet *ls, void *refcon) { + EvalAssignAction2Params *params; + CInt64 value; + IROLinear *nd; + ENodeType oper; + UInt32 stride; + Type *rtype; + PAMemoryBlock *block; + + IRO_ASSERT(4657, ls != NULL); + IRO_ASSERT(4658, refcon != NULL); + + params = refcon; + + if (!params->xC && !LocationSet_IsUnknown(ls)) { + value = params->x0; + nd = params->nd; + IRO_ASSERT(4665, nd != NULL); + oper = nd->nodetype; + + stride = LocationSet_stride(ls); + rtype = LocationSet_rtype(ls); + block = LocationSet_block(ls); + + if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_INT) { + LocationSet_Term(ls); + + switch (oper) { + case EPOSTINC: + case EPREINC: + case EADDASS: + value = CInt64_Add(*((CInt64 *) PAMemoryBlock_thing(block)), value); + break; + case EPOSTDEC: + case EPREDEC: + case ESUBASS: + value = CInt64_Sub(*((CInt64 *) PAMemoryBlock_thing(block)), value); + break; + case EMULASS: + if (IRO_IsUnsignedType(nd->rtype)) + value = CInt64_MulU(*((CInt64 *) PAMemoryBlock_thing(block)), value); + else + value = CInt64_Mul(*((CInt64 *) PAMemoryBlock_thing(block)), value); + break; + case EDIVASS: + if (CInt64_IsZero(&value)) { + if (nd->stmt->sourceoffset) { + TStreamElement *e = CPrep_CurStreamElement(); + e->tokenoffset = nd->stmt->sourceoffset; + CError_SetErrorToken(e); + } + CError_Warning(CErrorStr139); + params->xC = 1; + } else { + if (IRO_IsUnsignedType(nd->rtype)) + value = CInt64_DivU(*((CInt64 *) PAMemoryBlock_thing(block)), value); + else + value = CInt64_Div(*((CInt64 *) PAMemoryBlock_thing(block)), value); + } + break; + case EMODASS: + if (CInt64_IsZero(&value)) { + if (nd->stmt->sourceoffset) { + TStreamElement *e = CPrep_CurStreamElement(); + e->tokenoffset = nd->stmt->sourceoffset; + CError_SetErrorToken(e); + } + CError_Warning(CErrorStr139); + params->xC = 1; + } else { + if (IRO_IsUnsignedType(nd->rtype)) + value = CInt64_ModU(*((CInt64 *) PAMemoryBlock_thing(block)), value); + else + value = CInt64_Mod(*((CInt64 *) PAMemoryBlock_thing(block)), value); + } + break; + case ESHLASS: + value = CInt64_Shl(*((CInt64 *) PAMemoryBlock_thing(block)), value); + break; + case ESHRASS: + if (IRO_IsUnsignedType(nd->rtype)) + value = CInt64_ShrU(*((CInt64 *) PAMemoryBlock_thing(block)), value); + else + value = CInt64_Shr(*((CInt64 *) PAMemoryBlock_thing(block)), value); + break; + case EANDASS: + value = CInt64_And(*((CInt64 *) PAMemoryBlock_thing(block)), value); + break; + case EXORASS: + value = CInt64_Xor(*((CInt64 *) PAMemoryBlock_thing(block)), value); + break; + case EORASS: + value = CInt64_Or(*((CInt64 *) PAMemoryBlock_thing(block)), value); + break; + default: + CError_FATAL(4746); + } + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_INT, &value); + LocationSet_InitKnown(ls, block, cint64_zero, stride, rtype); + } else { + if (oper == EPOSTDEC || oper == EPREDEC || oper == ESUBASS) + value = CInt64_Neg(value); + + switch (oper) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + case EADDASS: + case ESUBASS: + value = CInt64_Add(LocationSet_field(ls), value); + if (stride) { + CInt64 tmp; + CInt64_SetLong(&tmp, stride); + value = CInt64_Mod(value, tmp); + } + SetsLocationSetField_sub_4851B0(ls, value); + break; + default: + params->xC = 1; + break; + } + } + } +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct EvalAssignActionParams { + Object *proc; + PartialTransferFunction *ptf; + IROLinear *nd; + IRONode *fnode; + LocationSetSet *srcs; + Boolean x14; + Boolean x15; + Boolean x16; +} EvalAssignActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void EvalAssignAction(LocationSet *dst, void *refcon) { + EvalAssignActionParams *params; + LocationSetSet *srcs; + + IRO_ASSERT(4797, dst != NULL); + IRO_ASSERT(4798, refcon != NULL); + + params = refcon; + + IRO_ASSERT(4802, params->proc != NULL); + IRO_ASSERT(4802, params->ptf != NULL); + IRO_ASSERT(4803, params->nd != NULL); + IRO_ASSERT(4804, params->fnode != NULL); + IRO_ASSERT(4805, params->srcs != NULL); + + srcs = params->srcs; + if ( + !params->x14 || + !LocationSetRepresentsSingleLocation(dst, params->proc, params->nd->pointsToFunction) || + LocationIsVolatile(dst, params->proc) || + LocationSet_sub_48AF30(dst) + ) { + LocationSetSet *set = LocationSetSet_New(); + LocationSetSet_Init(set); + params->x15 |= Lookup(set, &stCallingContextStack, params->proc, NULL, params->ptf, dst, params->nd->pointsToFunction, 0, params->nd->rtype); + LocationSetSet_AddSet(srcs, set); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + } + + params->x16 |= Assign(params->ptf, dst, srcs, params->proc, params->nd, params->fnode); +} + +static Boolean EvalAssign(Object *proc, IROLinear *nd, IRONode *fnode, ParamMappingFunction *map, PartialTransferFunction *ptf) { + EvalAssignActionParams params; + EvalAssignAction2Params params2; + LocationSetSet *set; + LocationSet *tmp; + PAMemoryBlock *block; + Type *type; + + IRO_ASSERT(4840, proc != NULL); + IRO_ASSERT(4841, nd != NULL); + IRO_ASSERT(4842, fnode != NULL); + IRO_ASSERT(4843, map != NULL); + IRO_ASSERT(4844, ptf != NULL); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.ptf = ptf; + params.nd = nd; + params.fnode = fnode; + params.x15 = 0; + params.x16 = 0; + + set = LocationSetSet_New(); + params.srcs = LocationSetSet_New(); + LocationSetSet_Init(set); + LocationSetSet_Init(params.srcs); + + if (nd->type == IROLinearOp2Arg) { + IRO_ASSERT(4861, nd->u.diadic.left->type == IROLinearOp1Arg && nd->u.diadic.left->nodetype == EINDIRECT); + + params.x15 |= EvalExpr(set, proc, nd->u.diadic.left->u.monadic, &stCallingContextStack, map, ptf); + AdjustTypesForVolatility(set, proc, nd->u.diadic.left); + params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.right, &stCallingContextStack, map, ptf); + + if (nd->nodetype != EASS) { + switch (nd->nodetype) { + case EMULASS: + case EDIVASS: + case EMODASS: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + if ( + LocationSetSet_Count(params.srcs) == 1 && + (tmp = LocationSetSet_FindFirst(params.srcs)) && + !LocationSet_IsUnknown(tmp) && + !LocationSet_stride(tmp) && + (block = LocationSet_block(tmp)) && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_INT + ) { + LocationSetSet_Term(params.srcs); + LocationSetSet_Init(params.srcs); + params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.left, &stCallingContextStack, map, ptf); + + memset(¶ms2, 0, sizeof(params2)); + params2.x0 = *((CInt64 *) PAMemoryBlock_thing(block)); + IRO_TruncateValueToType(¶ms2.x0, nd->u.diadic.right->rtype); + params2.nd = nd; + params2.xC = 0; + + if (!CInt64_IsZero(¶ms2.x0)) { + LocationSetSet_ForEach(params.srcs, EvalAssignAction2, ¶ms2); + if (params2.xC) { + LocationSetSet_Term(params.srcs); + LocationSetSet_Init(params.srcs); + params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.left, &stCallingContextStack, map, ptf); + if (!LocationSetSet_FindUnknown(params.srcs)) + LocationSetSet_ForEach(params.srcs, EvalExprAction2, (void *) &cint64_one); + } + } + } else { + LocationSetSet_Term(params.srcs); + LocationSetSet_Init(params.srcs); + params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.left, &stCallingContextStack, map, ptf); + if (!LocationSetSet_FindUnknown(params.srcs)) + LocationSetSet_ForEach(params.srcs, EvalExprAction2, (void *) &cint64_one); + } + break; + default: + LocationSetSet_Term(params.srcs); + LocationSetSet_Init(params.srcs); + LocationSetSet_AddUnknown(params.srcs, nd->rtype, NULL, NULL); + break; + } + } + } else if (nd->type == IROLinearOp1Arg) { + IRO_ASSERT(4958, nd->u.monadic.left->type == IROLinearOp1Arg && nd->u.monadic->nodetype == EINDIRECT); + + params.x15 |= EvalExpr(set, proc, nd->u.monadic->u.monadic, &stCallingContextStack, map, ptf); + AdjustTypesForVolatility(set, proc, nd->u.monadic); + params.x15 |= EvalExpr(params.srcs, proc, nd->u.monadic, &stCallingContextStack, map, ptf); + + switch (nd->nodetype) { + case EPOSTINC: + case EPOSTDEC: + case EPREINC: + case EPREDEC: + memset(¶ms2, 0, sizeof(params2)); + params2.x0 = cint64_one; + params2.nd = nd; + params2.xC = 0; + + type = NULL; + if (IS_TYPE_POINTER(nd->rtype)) + type = TPTR_TARGET(nd->rtype); + else if (IS_TYPE_MEMBERPOINTER(nd->rtype)) + type = TYPE_MEMBER_POINTER(nd->rtype)->ty1; + + if (type) + CInt64_SetLong(¶ms2.x0, type->size); + + if (!CInt64_IsZero(¶ms2.x0)) { + LocationSetSet_ForEach(params.srcs, EvalAssignAction2, ¶ms2); + if (params2.xC) { + LocationSetSet_Term(params.srcs); + LocationSetSet_Init(params.srcs); + params.x15 |= EvalExpr(params.srcs, proc, nd->u.monadic, &stCallingContextStack, map, ptf); + if (!LocationSetSet_FindUnknown(params.srcs)) + LocationSetSet_ForEach(params.srcs, EvalExprAction2, (void *) &cint64_one); + } + } + break; + + default: + LocationSetSet_Term(params.srcs); + LocationSetSet_Init(params.srcs); + LocationSetSet_AddUnknown(params.srcs, nd->rtype, NULL, NULL); + break; + } + } else { + CError_FATAL(5006); + } + + if (LocationSetSet_Count(params.srcs) != 0) { + PointsToFunction *pointsToFunc; + + pointsToFunc = PointsToFunction_New(); + if (nd->pointsToFunction) + PointsToFunction_Copy(pointsToFunc, nd->pointsToFunction); + else + PointsToFunction_Init(pointsToFunc); + + params.x14 = LocationSetSet_Count(set) == 1; + LocationSetSet_ForEach(set, EvalAssignAction, ¶ms); + + if (!params.x15 && params.x16) { + if (nd->pointsToFunction) + params.x15 = !PointsToFunctions_Equal(pointsToFunc, nd->pointsToFunction); + else + params.x15 = PointsToFunction_FindFirst(pointsToFunc) != NULL; + } + + PointsToFunction_Term(pointsToFunc); + PointsToFunction_Delete(pointsToFunc); + } + + LocationSetSet_Term(set); + LocationSetSet_Term(params.srcs); + LocationSetSet_Delete(set); + LocationSetSet_Delete(params.srcs); + + return params.x15; +} + +static Boolean EvalReturn(Object *proc, IROLinear *nd, IRONode *fnode, ParamMappingFunction *map, PartialTransferFunction *ptf) { + EvalAssignActionParams params; + LocationSet *loc; + + IRO_ASSERT(5046, proc != NULL); + IRO_ASSERT(5047, nd != NULL); + IRO_ASSERT(5048, nd->type == IROLinearReturn); + IRO_ASSERT(5049, fnode != NULL); + IRO_ASSERT(5050, map != NULL); + IRO_ASSERT(5051, ptf != NULL); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.ptf = ptf; + params.nd = nd; + params.fnode = fnode; + params.x15 = 0; + params.x16 = 0; + + if (nd->u.monadic) { + params.srcs = LocationSetSet_New(); + LocationSetSet_Init(params.srcs); + + loc = PartialTransferFunction_returnLocation(ptf); + params.x15 |= EvalExpr(params.srcs, proc, nd->u.monadic, &stCallingContextStack, map, ptf); + + if (LocationSetSet_Count(params.srcs) != 0) { + params.x14 = 1; + EvalAssignAction(loc, ¶ms); + params.x15 |= params.x16; + } + + LocationSetSet_Term(params.srcs); + LocationSetSet_Delete(params.srcs); + } + + return params.x15; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct ApplySummaryActionParams { + ParamMappingFunction *tgtMap; + Object *proc; + IRONode *fnode; + IROLinear *nd; + PartialTransferFunction *ptf; + ParamMappingFunction *map; + LocationSet *loc; + LocationSetSet *locs; + Boolean x20; + Boolean x21; + Boolean x22; +} ApplySummaryActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void ApplySummaryAction2(ParamMapping *mapping, void *refcon) { + ApplySummaryActionParams *params; + PAMemoryBlock *block; + ExtendedParam *ep; + IROLinear *nd; + LocationSetSet *set; + EvalAssignActionParams assignParams; + + IRO_ASSERT(5108, mapping != NULL); + IRO_ASSERT(5109, refcon != NULL); + + params = refcon; + + IRO_ASSERT(5113, params->tgtMap != NULL); + IRO_ASSERT(5114, params->proc != NULL); + IRO_ASSERT(5115, params->fnode != NULL); + IRO_ASSERT(5116, params->nd != NULL); + IRO_ASSERT(5117, params->nd->type == IROLinearFunccall); + IRO_ASSERT(5118, params->ptf != NULL); + IRO_ASSERT(5119, params->map != NULL); + IRO_ASSERT(5120, params->loc != NULL); + IRO_ASSERT(5121, params->locs != NULL); + + block = LocationSet_block(params->loc); + + IRO_ASSERT(5124, block != NULL); + IRO_ASSERT(5125, PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM); + + ep = PAMemoryBlock_thing(block); + + IRO_ASSERT(5127, ep != NULL); + + if (ParamMapping_extended(mapping) == ep && (nd = ParamMapping_actual(mapping))) { + set = LocationSetSet_New(); + LocationSetSet_Init(set); + params->x21 |= EvalExpr(set, params->proc, nd, &stCallingContextStack, params->map, params->ptf); + + if (!LocationSetSet_FindUnknown(set)) { + CInt64 stride64; + CInt64 value; + + value = LocationSet_field(params->loc); + LocationSetSet_ForEach(set, EvalExprAction, &value); + + CInt64_SetULong(&stride64, LocationSet_stride(params->loc)); + LocationSetSet_ForEach(set, EvalExprAction2, &stride64); + } + + memset(&assignParams, 0, sizeof(assignParams)); + assignParams.proc = params->proc; + assignParams.ptf = params->ptf; + assignParams.nd = params->nd; + assignParams.fnode = params->fnode; + assignParams.srcs = params->locs; + assignParams.x14 = params->x20 && (LocationSetSet_Count(set) == 1); + assignParams.x15 = 0; + assignParams.x16 = 0; + LocationSetSet_ForEach(set, EvalAssignAction, &assignParams); + + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + + params->x21 |= assignParams.x15; + params->x22 |= assignParams.x16; + } +} + +static void ApplySummaryAction(PointsToEntry *pte, void *refcon) { + ApplySummaryActionParams *params; + LocationSet *loc; + PAMemoryBlock *block; + + IRO_ASSERT(5175, pte != NULL); + IRO_ASSERT(5176, refcon != NULL); + + params = refcon; + + IRO_ASSERT(5180, params->tgtMap != NULL); + IRO_ASSERT(5181, params->proc != NULL); + IRO_ASSERT(5182, params->fnode != NULL); + IRO_ASSERT(5183, params->nd != NULL); + IRO_ASSERT(5184, params->nd->type == IROLinearFunccall); + IRO_ASSERT(5185, params->ptf != NULL); + IRO_ASSERT(5186, params->map != NULL); + + loc = PointsToEntry_loc(pte); + + IRO_ASSERT(5189, loc != NULL); + IRO_ASSERT(5190, !LocationSet_IsUnknown(loc)); + + block = LocationSet_block(loc); + if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + params->loc = loc; + params->locs = PointsToEntry_locs(pte); + pmf_sub_487C70(params->tgtMap, ApplySummaryAction2, params); + } +} + +static Boolean ApplySummary(PartialTransferFunction *tgtPTF, ParamMappingFunction *tgtMap, Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf, ParamMappingFunction *map, Boolean flag) { + Boolean result; + ApplySummaryActionParams params; + PointsToFunction *pointsToFunc; + + IRO_ASSERT(5208, tgtPTF != NULL); + IRO_ASSERT(5209, tgtMap != NULL); + IRO_ASSERT(5210, proc != NULL); + IRO_ASSERT(5211, fnode != NULL); + IRO_ASSERT(5212, nd != NULL); + IRO_ASSERT(5213, nd->type == IROLinearFunccall); + IRO_ASSERT(5214, ptf != NULL); + IRO_ASSERT(5215, map != NULL); + + StoreReturnedLocations(nd, tgtPTF, tgtMap); + if (tgtPTF == stUnknownPTF) { + result = KillAllAddressableLocations(proc, fnode, nd, ptf); + } else { + pointsToFunc = PointsToFunction_New(); + if (nd->pointsToFunction) + PointsToFunction_Copy(pointsToFunc, nd->pointsToFunction); + else + PointsToFunction_Init(pointsToFunc); + + memset(¶ms, 0, sizeof(params)); + params.tgtMap = tgtMap; + params.proc = proc; + params.fnode = fnode; + params.nd = nd; + params.ptf = ptf; + params.map = map; + params.loc = NULL; + params.locs = NULL; + params.x20 = flag; + params.x21 = 0; + params.x22 = 0; + + PointsToFunction_ForEach(PartialTransferFunction_finalPointsToFn(tgtPTF), ApplySummaryAction, ¶ms); + + result = params.x21; + if (!params.x21 && params.x22) { + if (nd->pointsToFunction) + result = !PointsToFunctions_Equal(pointsToFunc, nd->pointsToFunction); + else + result = PointsToFunction_FindFirst(pointsToFunc) != NULL; + } + } + + return result; +} + +static void GetPTFAction2(ParamMapping *mapping, void *refcon) { + IRO_ASSERT(5331, mapping != NULL); + + if (ParamMapping_extended(mapping)) + ParamMapping_SetExtended(mapping, NULL); +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct GetPTFActionParams { + ParamMappingFunction *map; + Object *proc; + IROLinear *nd; + PartialTransferFunction *ptf; + Boolean *needVisit; + PartialTransferFunction *x14; + PartialTransferFunction *x18; +} GetPTFActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void GetPTFAction(PartialTransferFunction *tgtPTF, void *refcon) { + GetPTFActionParams *params; + + IRO_ASSERT(5359, tgtPTF != NULL); + IRO_ASSERT(5360, refcon != NULL); + + params = refcon; + + IRO_ASSERT(5364, params->map != NULL); + IRO_ASSERT(5365, params->proc != NULL); + IRO_ASSERT(5366, params->proc != &stUnknown); + IRO_ASSERT(5367, params->nd != NULL); + IRO_ASSERT(5368, params->ptf != NULL); + IRO_ASSERT(5369, params->needVisit != NULL); + + if (!params->x18) { + if (MatchPTF(tgtPTF, params->proc, params->map, params->nd, params->ptf)) { + if (InputsHaveNewPointerValues(tgtPTF, params->ptf)) + *params->needVisit = 1; + params->x18 = tgtPTF; + } else { + pmf_sub_487C70(params->map, GetPTFAction2, NULL); + if (PTF_sub_48B980(tgtPTF) == params->nd && PTF_sub_48B970(tgtPTF) == params->ptf) + params->x14 = tgtPTF; + } + } +} + +static PartialTransferFunction *GetPTF(ParamMappingFunction *map, Object *proc, IROLinear *nd, PartialTransferFunction *ptf, Boolean *needVisit) { + PartialTransferFunction *found; + PartialTransferFunction *result; + GetPTFActionParams params; + + IRO_ASSERT(5396, map != NULL); + IRO_ASSERT(5397, proc != NULL); + IRO_ASSERT(5398, nd != NULL); + IRO_ASSERT(5399, ptf != NULL); + IRO_ASSERT(5400, needVisit != NULL); + + if (proc == &stUnknown) { + result = stUnknownPTF; + } else { + memset(¶ms, 0, sizeof(params)); + params.map = map; + params.proc = proc; + params.nd = nd; + params.ptf = PartialTransferFunction_New(); + PartialTransferFunction_Init(params.ptf, nd, ptf); + params.needVisit = needVisit; + params.x14 = NULL; + params.x18 = NULL; + + if (!proc->u.func.ptfList) { + proc->u.func.ptfList = PTFList_New(); + PTFList_Init(proc->u.func.ptfList); + } + + PTFList_ForEach(proc->u.func.ptfList, GetPTFAction, ¶ms); + + found = params.x18; + if (found && !*needVisit) { + PartialTransferFunction_Copy(result = PartialTransferFunction_New(), found); + } else { + result = stUnknownPTF; + } + + PartialTransferFunction_Term(params.ptf); + PartialTransferFunction_Delete(params.ptf); + } + + return result; +} + +static Boolean IsMeetNode(IRONode *fnode, IROLinear *nd) { + return (fnode->numpred > 1) && (fnode->first == nd); +} + +static Boolean IsExitNode(Object *proc, IRONode *fnode) { + IRO_ASSERT(5467, proc != NULL); + IRO_ASSERT(5468, fnode != NULL); + + return (fnode->numsucc == 0) && Bv_IsBitSet(FunctionFirstNode(proc)->index, fnode->dom); +} + +static Boolean SomePredecessorHasBeenVisited(Object *proc, IRONode *fnode) { + UInt16 i; + + IRO_ASSERT(5479, proc != NULL); + IRO_ASSERT(5480, fnode != NULL); + + for (i = 0; i < fnode->numpred; i++) { + if (FunctionNodeTable(proc)[fnode->pred[i]]->x3C) + return 1; + } + + return 0; +} + +static Boolean AllPredecessorsHaveBeenVisited(Object *proc, IRONode *fnode) { + UInt16 i; + + IRO_ASSERT(0, proc != NULL); + IRO_ASSERT(0, fnode != NULL); + + for (i = 0; i < fnode->numpred; i++) { + if (!FunctionNodeTable(proc)[fnode->pred[i]]->x3C) + return 0; + } + + return 1; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct EvalProcActionParams { + Object *proc; + IRONode *fnode; + PartialTransferFunction *ptf; +} EvalProcActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void EvalProcAction2(PointsToEntry *pte, void *refcon) { + EvalProcActionParams *params; + LocationSet *dst; + PAMemoryBlock *block; + LocationSetSet *set; + IRONode *node; + + IRO_ASSERT(5525, pte != NULL); + IRO_ASSERT(5526, refcon != NULL); + + params = refcon; + + IRO_ASSERT(5530, params->proc != NULL); + IRO_ASSERT(5531, params->fnode != NULL); + IRO_ASSERT(5532, params->ptf != NULL); + + dst = PointsToEntry_loc(pte); + + IRO_ASSERT(5535, dst != NULL); + IRO_ASSERT(5536, !LocationSet_IsUnknown(dst)); + + block = LocationSet_block(dst); + + if (block && (LocationSet_sub_48AF30(dst) || PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM)) { + set = LocationSetSet_New(); + LocationSetSet_Init(set); + LocationSetSet_AddSet(set, PointsToEntry_locs(pte)); + + for (node = FunctionFirstNode(params->proc); node; node = node->nextnode) { + if (node->x3C && node != params->fnode && IsExitNode(params->proc, node)) { + if (node->last->pointsToFunction) + Lookup(set, &stCallingContextStack, params->proc, NULL, params->ptf, dst, node->last->pointsToFunction, 0, NULL); + } + } + + Assign(params->ptf, dst, set, params->proc, NULL, NULL); + + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + } +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct AssignEachInPointsToFunctionActionParams { + Object *proc; + IROLinear *nd; + IRONode *fnode; + PartialTransferFunction *ptf; + Boolean x10; +} AssignEachInPointsToFunctionActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void AssignEachInPointsToFunctionAction(PointsToEntry *pte, void *refcon) { + AssignEachInPointsToFunctionActionParams *params; + LocationSet *dst; + LocationSetSet *srcs; + + IRO_ASSERT(5577, pte != NULL); + IRO_ASSERT(5578, refcon != NULL); + + params = refcon; + + IRO_ASSERT(5582, params->proc != NULL); + IRO_ASSERT(5583, params->nd != NULL); + IRO_ASSERT(5584, params->fnode != NULL); + IRO_ASSERT(5585, params->ptf != NULL); + + dst = PointsToEntry_loc(pte); + + srcs = LocationSetSet_New(); + LocationSetSet_Init(srcs); + LocationSetSet_AddSet(srcs, PointsToEntry_locs(pte)); + params->x10 |= Assign(params->ptf, dst, srcs, params->proc, params->nd, params->fnode); + LocationSetSet_Term(srcs); + LocationSetSet_Delete(srcs); +} + +static void AssignEachInPointsToFunction(PointsToFunction *pointsTo, void *refcon) { + AssignEachInPointsToFunctionActionParams *params; + PointsToFunction *pointsToFunc; + + IRO_ASSERT(5602, pointsTo != NULL); + IRO_ASSERT(5603, refcon != NULL); + + params = refcon; + + IRO_ASSERT(5607, params->nd != NULL); + + pointsToFunc = PointsToFunction_New(); + if (params->nd->pointsToFunction) + PointsToFunction_Copy(pointsToFunc, params->nd->pointsToFunction); + else + PointsToFunction_Init(pointsToFunc); + + if (PointsToFunction_FindFirst(pointsToFunc)) { + PointsToFunction_ForEach(pointsTo, AssignEachInPointsToFunctionAction, params); + } else { + if (!params->nd->pointsToFunction) + params->nd->pointsToFunction = PointsToFunction_New(); + else + PointsToFunction_Term(params->nd->pointsToFunction); + + PointsToFunction_Copy(params->nd->pointsToFunction, pointsTo); + params->x10 = 1; + } + + if (params->x10) { + if (params->nd->pointsToFunction) + params->x10 = !PointsToFunctions_Equal(pointsToFunc, params->nd->pointsToFunction); + else + params->x10 = PointsToFunction_FindFirst(pointsToFunc) != NULL; + } + + PointsToFunction_Term(pointsToFunc); + PointsToFunction_Delete(pointsToFunc); +} + +static Boolean ObjectIsAFunctionArgument(Object *proc, Object *obj) { + ObjectList *list; + + IRO_ASSERT(5643, proc != NULL); + IRO_ASSERT(5644, proc != &stUnknown); + IRO_ASSERT(5645, obj != NULL); + + if (obj->datatype == DLOCAL) { + for (list = FunctionArguments(proc); list; list = list->next) { + if (obj == list->object) + return 1; + } + } + + return 0; +} + +static Boolean ObjectIsARealFunctionArgument(Object *proc, Object *obj) { + ObjectList *list; + + IRO_ASSERT(5661, proc != NULL); + IRO_ASSERT(5662, proc != &stUnknown); + IRO_ASSERT(5663, obj != NULL); + + if (obj->datatype == DLOCAL && proc == cscope_currentfunc) { + for (list = arguments; list; list = list->next) { + if (obj == list->object) + return 1; + } + } + + return 0; +} + +static void AddLocalVarsAddressedByExceptionUses(Object *var) { + IRO_ASSERT(5699, var != NULL); + IRO_ASSERT(5700, stExceptionFNode != NULL); + IRO_ASSERT(5701, stExceptionFNode->addressed != NULL); + + if (var->datatype == DLOCAL) + ObjectSet_sub_4867D0(stExceptionFNode->addressed, var); +} + +static Boolean LinearNodeIsInFlowgraphNode(IROLinear *nd, IRONode *fnode) { + IROLinear *first; + IROLinear *last; + IROLinear *scan; + + if (fnode && (first = fnode->first) && (last = fnode->last)) { + for (scan = first; scan && scan != last->next; scan = scan->next) { + if (scan == nd) + return 1; + } + } + + return 0; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +static struct { + Object *proc; + IRONode *fnode; + ParamMappingFunction *map; + PartialTransferFunction *ptf; + PointsToFunction *pointsToFunc; + Boolean *changed; + Boolean x18; + Boolean x19; +} stEvalProcActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void EvalProcAction(IROLinear *Int, Boolean flag) { + Boolean *changed; + Boolean result; + Object *proc; + PartialTransferFunction *ptf; + Boolean x18; + Boolean x19; + IRONode *fnode; + PointsToFunction *pointsToFunc; + ParamMappingFunction *map; + Object *obj; + AssignEachInPointsToFunctionActionParams params; + + static int userBreakCounter; + + if (!flag && !Int->x1E) { + IRO_ASSERT(5748, Int != NULL); + IRO_ASSERT(5749, stEvalProcActionParams.changed != NULL); + + proc = stEvalProcActionParams.proc; + fnode = stEvalProcActionParams.fnode; + map = stEvalProcActionParams.map; + ptf = stEvalProcActionParams.ptf; + pointsToFunc = stEvalProcActionParams.pointsToFunc; + changed = stEvalProcActionParams.changed; + x18 = stEvalProcActionParams.x18; + x19 = stEvalProcActionParams.x19; + + IRO_ASSERT(5760, proc != NULL); + IRO_ASSERT(5761, fnode != NULL); + IRO_ASSERT(5762, map != NULL); + IRO_ASSERT(5763, ptf != NULL); + + if (++userBreakCounter > 40) { + IRO_CheckForUserBreak(); + userBreakCounter = 0; + } + + result = 0; + + if (x19 && Int->pointsToFunction) { + PointsToFunction_Term(Int->pointsToFunction); + PointsToFunction_Delete(Int->pointsToFunction); + Int->pointsToFunction = NULL; + } + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.nd = Int; + params.fnode = fnode; + params.ptf = ptf; + params.x10 = 0; + + if (x18) { + PointsToFunction *initial = PartialTransferFunction_initialPointsToFn(ptf); + if (fnode == FunctionFirstNode(proc) && initial) { + AssignEachInPointsToFunction(initial, ¶ms); + result |= params.x10; + } + result |= EvalMeet(proc, fnode, Int, ptf); + pointsToFunc = Int->pointsToFunction; + x18 = 0; + } else if (!Int->pointsToFunction) { + if (pointsToFunc) + AssignEachInPointsToFunction(pointsToFunc, ¶ms); + result |= params.x10; + pointsToFunc = Int->pointsToFunction; + } + + if (IRO_IsAssignment(Int)) { + if (Int->flags & IROLF_4000) + longjmp(stAbortPointerAnalysis, 1); + result |= EvalAssign(proc, Int, fnode, map, ptf); + pointsToFunc = Int->pointsToFunction; + } else if (Int->type == IROLinearReturn) { + result |= EvalReturn(proc, Int, fnode, map, ptf); + pointsToFunc = Int->pointsToFunction; + } else if (Int->type == IROLinearFunccall) { + if (Int->flags & IROLF_4000) + longjmp(stAbortPointerAnalysis, 1); + if (Int->stmt && IRO_FunctionCallMightThrowException(Int)) { + stExceptionFNode = fnode; + IRO_WalkExcActions(Int->stmt->dobjstack, AddLocalVarsAddressedByExceptionUses); + } + result |= EvalCall(proc, fnode, Int, map, ptf); + pointsToFunc = Int->pointsToFunction; + } else if (Int->type == IROLinearOp1Arg && Int->nodetype == EINDIRECT && (!(Int->flags & IROLF_Assigned) || (Int->flags & IROLF_Used))) { + result |= EvalExpr(NULL, proc, Int, &stCallingContextStack, map, ptf); + } else if (Int->type == IROLinearOperand && !(Int->flags & IROLF_Ind) && Int->u.node->type == EOBJREF && (obj = Int->u.node->data.objref) && obj->datatype == DLOCAL) { + ObjectSet_sub_4867D0(fnode->addressed, obj); + } else if (Int->type == IROLinearAsm) { + IAEffects effects; + int i; + CodeGen_GetAsmEffects(Int->u.asm_stmt, &effects); + for (i = 0; i < effects.numoperands; i++) { + obj = effects.operands[i].object; + if (obj && obj->datatype == DLOCAL && effects.operands[i].type == IAEffect_3) { + ObjectSet_sub_4867D0(fnode->addressed, obj); + } + } + } + + if (result && Int != fnode->last && fnode->last->pointsToFunction) { + PointsToFunction_Term(fnode->last->pointsToFunction); + PointsToFunction_Delete(fnode->last->pointsToFunction); + fnode->last->pointsToFunction = NULL; + } + + *changed |= result; + x19 |= result; + + stEvalProcActionParams.pointsToFunc = pointsToFunc; + stEvalProcActionParams.x18 = x18; + stEvalProcActionParams.x19 = x19; + + Int->x1E = 1; + + if (Int->type != IROLinearReturn) { + IROLinear *father = IRO_LocateFather(Int); + if (father && father->type == IROLinearReturn) { + if (LinearNodeIsInFlowgraphNode(father, fnode)) + EvalProcAction(father, 0); + else + longjmp(stAbortPointerAnalysis, 1); + } + } + } +} + +static void EvalProc(Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf) { + IRONode *fnode; + IRONode *pred; + IROLinear *nd; + UInt32 passCount; + Boolean changed; + UInt16 i; + AssignEachInPointsToFunctionActionParams assignParams; + EvalProcActionParams params; + + IRO_ASSERT(5964, proc != NULL); + IRO_ASSERT(5965, map != NULL); + IRO_ASSERT(5966, ptf != NULL); + + for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) + fnode->x3C = 0; + + passCount = 0; + do { + clock(); + changed = 0; + for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) { + if (fnode->last && ((fnode->numpred == 0) || SomePredecessorHasBeenVisited(proc, fnode))) { + clock(); + if (!fnode->addressed) { + fnode->addressed = ObjectSet_New(); + ObjectSet_Init(fnode->addressed); + } + + for (i = 0; i < fnode->numpred; i++) { + pred = FunctionNodeTable(proc)[fnode->pred[i]]; + if (pred->addressed) + ObjectSet_sub_48C590(fnode->addressed, pred->addressed); + } + + memset(&stEvalProcActionParams, 0, sizeof(stEvalProcActionParams)); + stEvalProcActionParams.proc = proc; + stEvalProcActionParams.fnode = fnode; + stEvalProcActionParams.map = map; + stEvalProcActionParams.ptf = ptf; + stEvalProcActionParams.pointsToFunc = NULL; + stEvalProcActionParams.changed = &changed; + stEvalProcActionParams.x18 = 1; + stEvalProcActionParams.x19 = 0; + + for (nd = fnode->first; nd && nd != fnode->last->next; nd = nd->next) + nd->x1E = 0; + IRO_WalkInts(fnode->first, fnode->last, EvalProcAction); + + if (stEvalProcActionParams.x18 || !fnode->last->pointsToFunction) { + memset(&assignParams, 0, sizeof(assignParams)); + assignParams.proc = proc; + assignParams.nd = fnode->last; + assignParams.fnode = fnode; + assignParams.ptf = ptf; + assignParams.x10 = 0; + if (stEvalProcActionParams.x18) { + PointsToFunction *initial = PartialTransferFunction_initialPointsToFn(ptf); + if (fnode == FunctionFirstNode(proc) && initial) { + AssignEachInPointsToFunction(initial, &assignParams); + changed |= assignParams.x10; + } + changed |= EvalMeet(proc, fnode, fnode->last, ptf); + stEvalProcActionParams.x18 = 0; + } else { + if (stEvalProcActionParams.pointsToFunc) + AssignEachInPointsToFunction(stEvalProcActionParams.pointsToFunc, &assignParams); + changed |= assignParams.x10; + } + } + + fnode->x3C = 1; + clock(); + } + } + + clock(); + if (++passCount > 32) + CError_FATAL(6072); + } while (changed); + + if (passCount > stMaxPassCount) + stMaxPassCount = passCount; + + PartialTransferFunction_sub_48A610(ptf, 1); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.ptf = ptf; + for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) { + if (fnode->x3C && IsExitNode(proc, fnode) && fnode->last->pointsToFunction) { + params.fnode = fnode; + PointsToFunction_ForEach(fnode->last->pointsToFunction, EvalProcAction2, ¶ms); + } + } +} + +static void PointerAnalysis_Init(void) { + stCallingContextStack = Stack_New(); + Stack_Init(stCallingContextStack); + + stUnknownPTF = PartialTransferFunction_New(); + PartialTransferFunction_Init(stUnknownPTF, NULL, NULL); + + stExtParamSet = AllocsExtParamSet_sub_4876C0(); + InitsExtParamSet_sub_4876A0(stExtParamSet); + + stPTFList = PTFList_New(); + PTFList_Init(stPTFList); +} + +static void CleanseLocationSet(LocationSet *loc, void *refcon) { + PAMemoryBlock *block; + PALocalVar *local; + + IRO_ASSERT(6161, loc != NULL); + IRO_ASSERT(6162, refcon == NULL); + + if ( + !LocationSet_IsUnknown(loc) && + (block = LocationSet_block(loc)) && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR && + (local = PAMemoryBlock_thing(block)) + ) { + PALocalVar_SetSth_sub_4847C0(local, NULL); + } +} + +static void CleansePointsToEntry(PointsToEntry *pte, void *refcon) { + IRO_ASSERT(6177, pte != NULL); + IRO_ASSERT(6178, refcon == NULL); + + CleanseLocationSet(PointsToEntry_loc(pte), NULL); + LocationSetSet_ForEach(PointsToEntry_locs(pte), CleanseLocationSet, NULL); +} + +static void PointerAnalysis_TermAction4(PartialTransferFunction *ptf, void *refcon) { + IRO_ASSERT(6187, ptf != NULL); + IRO_ASSERT(6188, refcon == NULL); + + if (ptf != stUnknownPTF) { + PointsToFunction_ForEach(PartialTransferFunction_initialPointsToFn(ptf), CleansePointsToEntry, NULL); + PointsToFunction_ForEach(PartialTransferFunction_finalPointsToFn(ptf), CleansePointsToEntry, NULL); + } +} + +static void PointerAnalysis_TermAction3(ExtendedParam *ep) { + ExtendedParam_Term(ep); + ExtendedParam_Delete(ep); +} + +static void PointerAnalysis_TermAction2(Object *obj, void *refcon) { + ObjectSet *objSet; + Object *proc; + ObjectList *list; + + objSet = refcon; + + if (!ObjectIsAnExtendedParamCandidate(obj)) { + if ( + obj->datatype == DLOCAL && + obj->u.var.info && + (proc = obj->u.var.info->func) && + ObjectIsAFunction(proc) && + proc->u.func.argList + ) { + for (list = proc->u.func.argList; list; list = list->next) { + if (obj == list->object) + break; + } + + if (!list) + ObjectSet_sub_4867D0(objSet, obj); + } else { + ObjectSet_sub_4867D0(objSet, obj); + } + } +} + +static void PointerAnalysis_TermAction1(ExtendedParam *ep, void *refcon) { + ObjectSet *objSet; + ObjectSet *epObjSet; + Object *obj; + + objSet = ObjectSet_New(); + ObjectSet_Init(objSet); + + epObjSet = ExtendedParam_objectSet(ep); + obj = NULL; + ObjectSet_ForEach(epObjSet, FindGlobalObjectAction, &obj); + if (obj) { + ObjectSet_ForEach(epObjSet, PointerAnalysis_TermAction2, objSet); + if (ObjectSet_FindFirst(objSet)) + EP_sub_48C850(ep, objSet); + } + + ObjectSet_Term(objSet); + ObjectSet_Delete(objSet); +} + +static void PointerAnalysis_Term(void) { + if (stExtParamSet) { + MaybeWalkExtParamSet_sub_48CBE0(stExtParamSet, PointerAnalysis_TermAction1, NULL); + TermsExtParamSet_sub_48CB00(stExtParamSet); + FreesExtParamSet_sub_48CAE0(stExtParamSet); + stExtParamSet = NULL; + } + + if (stPTFList) { + PTFList_ForEach(stPTFList, PointerAnalysis_TermAction4, NULL); + PTFList_Term(stPTFList); + PTFList_Delete(stPTFList); + stPTFList = NULL; + } + + PartialTransferFunction_Term(stUnknownPTF); + PartialTransferFunction_Delete(stUnknownPTF); + stUnknownPTF = NULL; + + Stack_Term(&stCallingContextStack); + Stack_Delete(stCallingContextStack); + stCallingContextStack = NULL; +} + +static void InvalidatePointsToFunctions(Object *proc) { + IRONode *fnode; + IROLinear *nd; + + IRO_ASSERT(6302, proc != NULL); + + for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) { + if (fnode->last) { + if (fnode->addressed) { + ObjectSet_Term(fnode->addressed); + ObjectSet_Delete(fnode->addressed); + fnode->addressed = NULL; + } + + for (nd = fnode->first; nd && nd != fnode->last->next; nd = nd->next) { + if (nd->pointsToFunction) { + PointsToFunction_Term(nd->pointsToFunction); + PointsToFunction_Delete(nd->pointsToFunction); + nd->pointsToFunction = NULL; + } + } + } + } +} + +static void InitialSetup(void) { +} + +static void PointerAnalysis_HeapErrorProc(void) { + longjmp(stAbortPointerAnalysis, 2); +} + +void PointerAnalysis_Setup(void) { + IRO_InitializeAllocator(); + stExtendedParamNum = 0; + stParamObjs = NULL; + stMaxPassCount = 0; +} + +void PointerAnalysis_Cleanup(void) { + ObjectList *list; + ObjectList *next; + + for (list = stParamObjs; list; list = next) { + IRO_free(list->object); + next = list->next; + IRO_free(list); + } + stParamObjs = NULL; + IRO_TerminateAllocator(); +} + +void IRO_AnalyzePointers(Object *function) { + EvalCallActionParams params; + IROLinear nd; + IRONode fnode; + int code; + volatile heaperror_t saveheaperror; + + IRO_ASSERT(6393, function != NULL); + + PointerAnalysis_Init(); + + memset(¶ms, 0, sizeof(params)); + memset(&nd, 0, sizeof(nd)); + nd.type = IROLinearFunccall; + memset(&fnode, 0, sizeof(fnode)); + params.proc = &stUnknown; + params.fnode = &fnode; + params.nd = &nd; + params.ptf = stUnknownPTF; + params.map = NULL; + params.x18 = 0; + params.x19 = 0; + params.x1A = 1; + + stCurrentProc = FindMainEntryPoint(function); + + if ((code = setjmp(stAbortPointerAnalysis)) == 0) { + saveheaperror = getheaperror(); + setheaperror(PointerAnalysis_HeapErrorProc); + InitialSetup(); + EvalCallAction(stCurrentProc, ¶ms); + PointerAnalysis_Term(); + stCurrentProc = NULL; + setheaperror(saveheaperror); + } else { + setheaperror(saveheaperror); + InvalidatePointsToFunctions(stCurrentProc); + PointerAnalysis_Term(); + stCurrentProc = NULL; + if (code == 2 && saveheaperror) + saveheaperror(); + } +} + +static void RemoveRestrictedExtendedParamsAction(LocationSet *ls, void *refcon) { + LocationSetSet *locs; + PAMemoryBlock *block; + ExtendedParam *ep; + ObjectSet *objSet; + Object *obj; + + locs = refcon; + + if ( + !LocationSet_IsUnknown(ls) && + (block = LocationSet_block(ls)) && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM && + (ep = PAMemoryBlock_thing(block)) + ) { + objSet = ExtendedParam_objectSet(ep); + if ( + ObjectSet_Count(objSet) == 1 && + (obj = ObjectSet_FindFirst(objSet)) && + ObjectIsRestrictQualified(obj) + ) { + LocationSetSet_Add(locs, ls); + } + } +} + +static void RemoveRestrictedExtendedParams(LocationSetSet *locs) { + LocationSetSet *set; + + set = LocationSetSet_New(); + LocationSetSet_Init(set); + LocationSetSet_ForEach(locs, RemoveRestrictedExtendedParamsAction, set); + LocationSetSet_sub_488700(locs, set); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); +} + +Boolean PointerAnalysis_TwoLinearNodePointerExprsMightAlias(Object *proc, IROLinear *nd1, IROLinear *nd2) { + LocationSetSet *lss1; + LocationSetSet *lss2; + PointsToFunction *pointsTo1; + PointsToFunction *pointsTo2; + PointsToFunction *savePointsTo1; + PointsToFunction *savePointsTo2; + FindAliasingParams params; + + pointsTo1 = nd1->pointsToFunction; + pointsTo2 = nd2->pointsToFunction; + if (!pointsTo1) + pointsTo1 = pointsTo2; + if (!pointsTo2) + pointsTo2 = pointsTo1; + + if (copts.opt_pointer_analysis_mode == 2 && !is_typeequal(nd1->rtype, nd2->rtype)) + return 0; + if (!pointsTo1 || !pointsTo2) + return 1; + + lss1 = LocationSetSet_New(); + LocationSetSet_Init(lss1); + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + + savePointsTo1 = nd1->pointsToFunction; + nd1->pointsToFunction = pointsTo1; + EvalExpr(lss1, proc, nd1, NULL, NULL, NULL); + nd1->pointsToFunction = savePointsTo1; + + savePointsTo2 = nd2->pointsToFunction; + nd2->pointsToFunction = pointsTo2; + EvalExpr(lss2, proc, nd2, NULL, NULL, NULL); + nd2->pointsToFunction = savePointsTo2; + + memset(¶ms, 0, sizeof(params)); + params.x8 = 0; + params.x0 = lss2; + LocationSetSet_ForEach(lss1, FindAliasingAction, ¶ms); + + if (!params.x8) { + params.x0 = lss1; + LocationSetSet_ForEach(lss2, FindAliasingAction, ¶ms); + + if (!params.x8) { + RemoveRestrictedExtendedParams(lss1); + RemoveRestrictedExtendedParams(lss2); + ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss1); + ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss2); + + params.x0 = lss2; + LocationSetSet_ForEach(lss1, FindAliasingAction, ¶ms); + + if (!params.x8) { + params.x0 = lss1; + LocationSetSet_ForEach(lss2, FindAliasingAction, ¶ms); + } + } + } + + LocationSetSet_Term(lss1); + LocationSetSet_Delete(lss1); + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + + return params.x8; +} + +Boolean PointerAnalysis_TwoENodePointerExprsMightAlias(Object *proc, ENode *nd1, ENode *nd2) { + LocationSetSet *lss1; + LocationSetSet *lss2; + PointsToFunction *pointsTo1; + PointsToFunction *pointsTo2; + PointsToFunction *savePointsTo1; + PointsToFunction *savePointsTo2; + FindAliasingParams params; + + pointsTo1 = nd1->pointsTo; + pointsTo2 = nd2->pointsTo; + if (!pointsTo1) + pointsTo1 = pointsTo2; + if (!pointsTo2) + pointsTo2 = pointsTo1; + + if (copts.opt_pointer_analysis_mode == 2 && !is_typeequal(nd1->rtype, nd2->rtype)) + return 0; + if (!pointsTo1 || !pointsTo2) + return 1; + + lss1 = LocationSetSet_New(); + LocationSetSet_Init(lss1); + lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + + savePointsTo1 = nd1->pointsTo; + nd1->pointsTo = pointsTo1; + EvalENodeExpr(lss1, proc, nd1, NULL, NULL, NULL); + nd1->pointsTo = savePointsTo1; + + savePointsTo2 = nd2->pointsTo; + nd2->pointsTo = pointsTo2; + EvalENodeExpr(lss2, proc, nd2, NULL, NULL, NULL); + nd2->pointsTo = savePointsTo2; + + memset(¶ms, 0, sizeof(params)); + params.x8 = 0; + params.x0 = lss2; + LocationSetSet_ForEach(lss1, FindAliasingAction, ¶ms); + + if (!params.x8) { + params.x0 = lss1; + LocationSetSet_ForEach(lss2, FindAliasingAction, ¶ms); + + if (!params.x8) { + RemoveRestrictedExtendedParams(lss1); + RemoveRestrictedExtendedParams(lss2); + ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss1); + ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss2); + + params.x0 = lss2; + LocationSetSet_ForEach(lss1, FindAliasingAction, ¶ms); + + if (!params.x8) { + params.x0 = lss1; + LocationSetSet_ForEach(lss2, FindAliasingAction, ¶ms); + } + } + } + + LocationSetSet_Term(lss1); + LocationSetSet_Delete(lss1); + LocationSetSet_Term(lss2); + LocationSetSet_Delete(lss2); + + return params.x8; +} + +Boolean PointerAnalysis_IsLinearNodePointerExprDefinite(Object *proc, IROLinear *nd) { + LocationSetSet *lss; + LocationSet *loc; + Boolean result; + + if (!nd->pointsToFunction) + return 0; + + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + EvalExpr(lss, proc, nd, NULL, NULL, NULL); + + result = + (LocationSetSet_Count(lss) == 1) && + (loc = LocationSetSet_FindFirst(lss)) && + LocationSetRepresentsSingleLocation(loc, NULL, NULL); + + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + + return result; +} + +Boolean PointerAnalysis_IsENodePointerExprDefinite(Object *proc, ENode *nd) { + LocationSetSet *lss; + LocationSet *loc; + Boolean result; + + if (!nd->pointsTo) + return 0; + + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + EvalENodeExpr(lss, proc, nd, NULL, NULL, NULL); + + result = + (LocationSetSet_Count(lss) == 1) && + (loc = LocationSetSet_FindFirst(lss)) && + LocationSetRepresentsSingleLocation(loc, NULL, NULL); + + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + + return result; +} + +Boolean PointerAnalysis_IsVariableValueDefinite(Object *proc, VarRecord *var, PointsToFunction *pointsTo) { + LocationSetSet *lss; + LocationSet *loc; + Boolean result; + + if (!pointsTo) + return 0; + + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + EvalVariable(lss, proc, var, pointsTo, NULL, NULL, NULL); + + result = + (LocationSetSet_Count(lss) == 1) && + (loc = LocationSetSet_FindFirst(lss)) && + LocationSetRepresentsSingleLocation(loc, NULL, NULL); + + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + + return result; +} + +static void FindGlobalObjectAction(Object *object, void *refcon) { + if (ObjectIsAnExtendedParamCandidate(object)) { + Object **ptr = refcon; + *ptr = object; + } +} + +static void GetDefiniteObjectOfExtendedParamLoc(LocationSet *loc, Object **resultObj, CInt64 *resultField) { + Object *obj; + CInt64 field; + PAMemoryBlock *block; + ExtendedParam *ep; + ObjectSet *objSet; + LocationSetSet *locs; + LocationSet *tmp; + PALocalVar *local; + + IRO_ASSERT(6763, loc != NULL); + IRO_ASSERT(6764, resultObj != NULL); + IRO_ASSERT(6765, resultField != NULL); + + obj = NULL; + field = LocationSet_field(loc); + block = LocationSet_block(loc); + + if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + if ((ep = PAMemoryBlock_thing(block)) && (objSet = ExtendedParam_objectSet(ep))) { + IRO_ASSERT(6777, obj == NULL); + ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); + } + } + + if (!obj) { + locs = LocationSetSet_New(); + LocationSetSet_Init(locs); + GetActualLocsOfExtendedParam(locs, loc, NULL, &stCallingContextStack, NULL, 0); + + if ( + LocationSetSet_Count(locs) == 1 && + (tmp = LocationSetSet_FindFirst(locs)) && + !LocationSet_IsUnknown(tmp)) + { + field = CInt64_Add(field, LocationSet_field(tmp)); + if ( + (block = LocationSet_block(tmp)) && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM && + (ep = PAMemoryBlock_thing(block)) && + (objSet = ExtendedParam_objectSet(ep)) + ) + { + IRO_ASSERT(6801, obj == NULL); + ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); + } else if ( + (block = LocationSet_block(tmp)) && + PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR && + (local = PAMemoryBlock_thing(block)) + ) + { + obj = GetLocalObject(local, &stUnknown, 0); + } + } + + LocationSetSet_Term(locs); + LocationSetSet_Delete(locs); + } + + *resultObj = obj; + *resultField = field; +} + +static void CreateExpressionForLocationSet(LocationSet *loc, IROList *list, Type *rtype, Object *proc) { + CInt64 field; + PAMemoryBlock *block; + PAMemoryBlockKind kind; + void *thing; + IROLinear *nd; + Object *obj; + + IRO_ASSERT(6833, loc != NULL); + IRO_ASSERT(6834, !LocationSet_IsUnknown(loc)); + IRO_ASSERT(6835, LocationSet_stride(loc) == 0); + IRO_ASSERT(6836, list != NULL); + IRO_ASSERT(6837, rtype != NULL); + IRO_ASSERT(6838, proc != NULL); + + field = LocationSet_field(loc); + block = LocationSet_block(loc); + kind = PAMemoryBlock_kind(block); + thing = PAMemoryBlock_thing(block); + nd = NULL; + + switch (kind) { + case PAMEMORYBLOCKKIND_EXTENDEDPARAM: + GetDefiniteObjectOfExtendedParamLoc(loc, &obj, &field); + if (obj) { + nd = IRO_NewLinear(IROLinearOperand); + nd->u.node = create_objectrefnode(obj); + nd->rtype = rtype; + nd->index = ++IRO_NumLinear; + IRO_AddToList(nd, list); + } + break; + case PAMEMORYBLOCKKIND_LOCALVAR: + obj = GetLocalObject(thing, proc, 0); + if (obj) { + if (ObjectIsAFunctionArgument(proc, obj) && obj->u.var.realObj) + obj = obj->u.var.realObj; + nd = IRO_NewLinear(IROLinearOperand); + nd->u.node = create_objectrefnode(obj); + nd->rtype = rtype; + nd->index = ++IRO_NumLinear; + IRO_AddToList(nd, list); + } + break; + case PAMEMORYBLOCKKIND_INT: + if (IS_TYPE_INT(rtype)) { + nd = IRO_NewIntConst(*((CInt64 *) thing), rtype); + IRO_AddToList(nd, list); + } + break; + case PAMEMORYBLOCKKIND_6: + break; + default: + CError_FATAL(6894); + } + + if (nd && !CInt64_IsZero(&field)) { + IROLinear *nd2; + IROLinear *nd3; + + nd2 = IRO_NewIntConst(field, TYPE(&stunsignedlong)); + IRO_AddToList(nd2, list); + + nd3 = IRO_NewLinear(IROLinearOp2Arg); + nd3->nodetype = EADD; + nd3->index = ++IRO_NumLinear; + nd3->rtype = rtype; + nd3->u.diadic.left = nd; + nd3->u.diadic.right = nd2; + IRO_AddToList(nd3, list); + } +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct LookupLinearExprActionParams { + Object *proc; + Type *indirectType; + IROListNode **list; +} LookupLinearExprActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void LookupLinearExprAction(LocationSet *loc, void *refcon) { + LookupLinearExprActionParams *params; + IROListNode *list; + + IRO_ASSERT(6926, loc != NULL); + IRO_ASSERT(6927, refcon != NULL); + + params = refcon; + + IRO_ASSERT(6931, params->proc != NULL); + IRO_ASSERT(6932, params->indirectType != NULL); + IRO_ASSERT(6933, params->list != NULL); + + list = *params->list = IRO_malloc(sizeof(IROListNode)); + IRO_InitList(&list->list); + list->nextList = NULL; + + if (!LocationSet_IsUnknown(loc) && LocationSetRepresentsSingleLocation(loc, NULL, NULL)) + CreateExpressionForLocationSet(loc, &list->list, params->indirectType, params->proc); + + params->list = &list->nextList; +} + +void PointerAnalysis_LookupLinearNodePointerExpr(Object *proc, IROLinear *indirect, IROListNode **list) { + LocationSetSet *set; + LookupLinearExprActionParams params; + + IRO_ASSERT(6957, indirect != NULL); + + if (indirect->pointsToFunction) { + set = LocationSetSet_New(); + LocationSetSet_Init(set); + EvalExpr(set, proc, indirect, NULL, NULL, NULL); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.indirectType = indirect->rtype; + params.list = list; + + LocationSetSet_ForEach(set, LookupLinearExprAction, ¶ms); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + } +} + +static void CreateENodeForLocationSet(LocationSet *loc, ENode **resultNode, Type *rtype, Object *proc) { + CInt64 field; + PAMemoryBlock *block; + PAMemoryBlockKind kind; + void *thing; + ENode *nd; + Object *obj; + + IRO_ASSERT(0, loc != NULL); + IRO_ASSERT(0, !LocationSet_IsUnknown(loc)); + IRO_ASSERT(0, LocationSet_stride(loc) == 0); + IRO_ASSERT(0, resultNode != NULL); + IRO_ASSERT(0, rtype != NULL); + IRO_ASSERT(0, proc != NULL); + + field = LocationSet_field(loc); + block = LocationSet_block(loc); + kind = PAMemoryBlock_kind(block); + thing = PAMemoryBlock_thing(block); + nd = NULL; + + switch (kind) { + case PAMEMORYBLOCKKIND_EXTENDEDPARAM: + GetDefiniteObjectOfExtendedParamLoc(loc, &obj, &field); + if (obj) { + nd = create_objectrefnode(obj); + nd->rtype = rtype; + } + break; + case PAMEMORYBLOCKKIND_LOCALVAR: + obj = GetLocalObject(thing, proc, 0); + if (obj) { + if (ObjectIsAFunctionArgument(proc, obj) && obj->u.var.realObj) + obj = obj->u.var.realObj; + nd = create_objectrefnode(obj); + nd->rtype = rtype; + } + break; + case PAMEMORYBLOCKKIND_INT: + if (IS_TYPE_INT(rtype)) { + nd = IRO_NewENode(EINTCONST); + nd->data.intval = *((CInt64 *) thing); + nd->rtype = rtype; + } + break; + case PAMEMORYBLOCKKIND_6: + break; + default: + CError_FATAL(7040); + } + + if (nd && !CInt64_IsZero(&field)) { + ENode *nd2; + ENode *nd3; + + nd2 = IRO_NewENode(EINTCONST); + nd2->data.intval = field; + nd2->rtype = TYPE(&stunsignedlong); + + nd3 = IRO_NewENode(EADD); + nd3->data.diadic.left = nd; + nd3->data.diadic.right = nd2; + nd3->rtype = rtype; + + *resultNode = nd3; + } else { + *resultNode = nd; + } +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct LookupENodeExprActionParams { + Object *proc; + Type *indirectType; + ENodeList **list; +} LookupENodeExprActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void LookupENodeExprAction(LocationSet *loc, void *refcon) { + LookupENodeExprActionParams *params; + ENodeList *list; + + IRO_ASSERT(0, loc != NULL); + IRO_ASSERT(0, refcon != NULL); + + params = refcon; + + IRO_ASSERT(0, params->proc != NULL); + IRO_ASSERT(0, params->indirectType != NULL); + IRO_ASSERT(0, params->list != NULL); + + list = *params->list = IRO_malloc(sizeof(ENodeList)); + list->node = NULL; + list->next = NULL; + + if (!LocationSet_IsUnknown(loc) && LocationSetRepresentsSingleLocation(loc, NULL, NULL)) + CreateENodeForLocationSet(loc, &list->node, params->indirectType, params->proc); + + params->list = &list->next; +} + +void PointerAnalysis_LookupENodePointerExpr(Object *proc, ENode *indirect, ENodeList **list) { + LocationSetSet *set; + LookupENodeExprActionParams params; + + IRO_ASSERT(0, indirect != NULL); + + if (indirect->pointsTo) { + set = LocationSetSet_New(); + LocationSetSet_Init(set); + EvalENodeExpr(set, proc, indirect, NULL, NULL, NULL); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.indirectType = indirect->rtype; + params.list = list; + + LocationSetSet_ForEach(set, LookupENodeExprAction, ¶ms); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + } +} + +void PointerAnalysis_LookupVariableIntoLinearNodeExprs(Object *proc, VarRecord *var, PointsToFunction *pointsTo, IROListNode **list) { + LocationSetSet *set; + LookupLinearExprActionParams params; + + if (pointsTo) { + set = LocationSetSet_New(); + LocationSetSet_Init(set); + EvalVariable(set, proc, var, pointsTo, NULL, NULL, NULL); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.indirectType = var->object->type; + params.list = list; + + LocationSetSet_ForEach(set, LookupLinearExprAction, ¶ms); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + } +} + +void PointerAnalysis_LookupVariableIntoENodeExprs(Object *proc, VarRecord *var, PointsToFunction *pointsTo, ENodeList **list) { + LocationSetSet *set; + LookupENodeExprActionParams params; + + if (pointsTo) { + set = LocationSetSet_New(); + LocationSetSet_Init(set); + EvalVariable(set, proc, var, pointsTo, NULL, NULL, NULL); + + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.indirectType = var->object->type; + params.list = list; + + LocationSetSet_ForEach(set, LookupENodeExprAction, ¶ms); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + } +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct GetFunctionDepsOrKillsActionParams { + Object *proc; + PartialTransferFunction *ptf; + IROLinear *funccall; + ParamMappingFunction *map; + ObjectList **list; +} GetFunctionDepsOrKillsActionParams; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void GetFunctionDepsOrKillsAction(LocationSet *ls, void *refcon) { + GetFunctionDepsOrKillsActionParams *params; + ObjectList *list; + PAMemoryBlock *block; + ExtendedParam *ep; + ObjectSet *objSet; + PALocalVar *local; + Object *obj; + + IRO_ASSERT(7204, ls != NULL); + IRO_ASSERT(7205, refcon != NULL); + + params = refcon; + + IRO_ASSERT(7209, params->proc != NULL); + IRO_ASSERT(7210, params->ptf != NULL); + IRO_ASSERT(7211, params->funccall != NULL); + IRO_ASSERT(7212, params->map == NULL || params->map != NULL); + IRO_ASSERT(7213, params->list != NULL); + + list = *params->list = IRO_malloc(sizeof(ObjectList)); + list->object = NULL; + list->next = NULL; + + if (!LocationSet_IsUnknown(ls) && (block = LocationSet_block(ls))) { + obj = NULL; + switch (PAMemoryBlock_kind(block)) { + case PAMEMORYBLOCKKIND_EXTENDEDPARAM: + if ((ep = PAMemoryBlock_thing(block)) && (objSet = ExtendedParam_objectSet(ep))) { + IRO_ASSERT(7232, obj == NULL); + ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); + } + break; + case PAMEMORYBLOCKKIND_LOCALVAR: + if ((local = PAMemoryBlock_thing(block))) { + obj = GetLocalObject(local, &stUnknown, 0); + if (ObjectIsAFunctionArgument(FunctionName, obj) && obj->u.var.realObj) + obj = obj->u.var.realObj; + } + break; + } + + list->object = obj; + } + + params->list = &list->next; +} + +static void GetFunctionDepsOrKillsAction2(PointsToEntry *pte, void *refcon) { + GetFunctionDepsOrKillsActionParams *params; + LocationSet *loc; + PAMemoryBlock *block; + LocationSetSet *set; + + IRO_ASSERT(7264, pte != NULL); + IRO_ASSERT(7265, refcon != NULL); + + params = refcon; + + IRO_ASSERT(7269, params->proc != NULL); + IRO_ASSERT(7270, params->ptf != NULL); + IRO_ASSERT(7271, params->funccall != NULL); + IRO_ASSERT(7272, params->map != NULL); + IRO_ASSERT(7273, params->list != NULL); + + loc = PointsToEntry_loc(pte); + + IRO_ASSERT(7277, !LocationSet_IsUnknown(loc)); + + if ((block = LocationSet_block(loc)) && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { + set = LocationSetSet_New(); + LocationSetSet_Init(set); + GetActualLocsOfExtendedParam(set, loc, NULL, &stCallingContextStack, params->map, 0); + LocationSetSet_ForEach(set, GetFunctionDepsOrKillsAction, params); + LocationSetSet_Term(set); + LocationSetSet_Delete(set); + } +} + +static void CreateFalseContext(Object *proc, IROLinear *funccall, PartialTransferFunction **resultPTF, ParamMappingFunction **resultMap) { + IROLinear myFunccall; + Boolean needVisit; + ParamMappingFunction *map; + PartialTransferFunction *ptf; + StackElement *stackElement; + ParamMappingFunction *map2; + PartialTransferFunction *ptf2; + StackElement *stackElement2; + + PointerAnalysis_Init(); + memset(&myFunccall, 0, sizeof(myFunccall)); + myFunccall.type = IROLinearFunccall; + + map = ParamMappingFunction_New(); + ParamMappingFunction_Init(map); + RecordActuals(&myFunccall, FunctionName, map); + + needVisit = 0; + ptf = GetPTF(map, FunctionName, &myFunccall, stUnknownPTF, &needVisit); + + stackElement = StackElement_New(); + StackElement_Init(stackElement, FunctionName, ptf, map, &myFunccall); + Stack_sub_48A660(&stCallingContextStack, stackElement); + StackElement_Term(stackElement); + StackElement_Delete(stackElement); + + map2 = ParamMappingFunction_New(); + ParamMappingFunction_Init(map2); + RecordActuals(funccall, proc, map2); + + if (FunctionName != proc) { + needVisit = 0; + ptf2 = GetPTF(map2, proc, funccall, ptf, &needVisit); + + stackElement2 = StackElement_New(); + StackElement_Init(stackElement2, proc, ptf2, map2, funccall); + Stack_sub_48A660(&stCallingContextStack, stackElement2); + StackElement_Term(stackElement2); + StackElement_Delete(stackElement2); + } else { + ptf2 = stUnknownPTF; + } + + *resultPTF = ptf2; + *resultMap = map2; +} + +static void DestroyFalseContext(Object *proc, PartialTransferFunction *ptf, ParamMappingFunction *map) { + StackElement *element; + + if (FunctionName != proc) { + element = Stack_sub_48A5B0(&stCallingContextStack); + StackElement_Term(element); + StackElement_Delete(element); + } + + ParamMappingFunction_Term(map); + ParamMappingFunction_Delete(map); + + element = Stack_sub_48A5B0(&stCallingContextStack); + map = StackElement_map(element); + ParamMappingFunction_Term(map); + ParamMappingFunction_Delete(map); + StackElement_Term(element); + StackElement_Delete(element); + + PointerAnalysis_Term(); +} + +void PointerAnalysis_GetFunctionKills(Object *proc, IROLinear *funccall, ObjectList **list) { + Boolean fail; + PartialTransferFunction *ptf; + LocationSetSet *set; + GetFunctionDepsOrKillsActionParams params; + + IRO_ASSERT(7398, proc != NULL); + IRO_ASSERT(7399, funccall != NULL); + IRO_ASSERT(7400, funccall->type == IROLinearFunccall); + + if (!ObjectIsAFunction(proc)) + return; + + fail = !proc->u.func.ptfList || !(ptf = PTFList_FindFirst(proc->u.func.ptfList)); + if (!fail) { + fail = !(set = PTF_sub_48D750(ptf)); + if (!fail) { + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.ptf = ptf; + params.funccall = funccall; + params.map = NULL; + params.list = list; + LocationSetSet_ForEach(set, GetFunctionDepsOrKillsAction, ¶ms); + } + } + + if (fail) { + *list = IRO_malloc(sizeof(ObjectList)); + (*list)->object = NULL; + (*list)->next = NULL; + } +} + +void PointerAnalysis_GetFunctionDependencies(Object *proc, IROLinear *funccall, ObjectList **list) { + Boolean fail; + PartialTransferFunction *ptf; + ParamMappingFunction *map; + PointsToFunction *finalPointsTo; + GetFunctionDepsOrKillsActionParams params; + + IRO_ASSERT(7446, proc != NULL); + IRO_ASSERT(7447, funccall != NULL); + IRO_ASSERT(7448, funccall->type == IROLinearFunccall); + + if (!ObjectIsAFunction(proc)) + return; + + fail = !proc->u.func.ptfList || !PTFList_FindFirst(proc->u.func.ptfList); + if (!fail) { + CreateFalseContext(proc, funccall, &ptf, &map); + fail = !ptf || !map || !(finalPointsTo = PartialTransferFunction_finalPointsToFn(ptf)); + if (!fail) { + memset(¶ms, 0, sizeof(params)); + params.proc = proc; + params.ptf = ptf; + params.funccall = funccall; + params.map = map; + params.list = list; + PointsToFunction_ForEach(finalPointsTo, GetFunctionDepsOrKillsAction2, ¶ms); + } + DestroyFalseContext(proc, ptf, map); + } + + if (fail) { + *list = IRO_malloc(sizeof(ObjectList)); + (*list)->object = NULL; + (*list)->next = NULL; + } +} + +void PointerAnalysis_PragmaMode(void) { + if (cparamblkptr->preprocess) { + skipendofline(); + return; + } + + if (notendofline()) { + if (plex() == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "addr")) { + copts.opt_pointer_analysis_mode = 0; + return; + } + if (!strcmp(tkidentifier->name, "ansi")) { + copts.opt_pointer_analysis_mode = 1; + return; + } + if (!strcmp(tkidentifier->name, "type")) { + copts.opt_pointer_analysis_mode = 2; + return; + } + } + + CPrep_Warning(CErrorStr105); + skipendofline(); + return; + } + + if (copts.warn_illpragma) + CPrep_Warning(CErrorStr186); + skipendofline(); +} + +typedef enum CreateNewParamObjects { + CREATE_NEW_PARAM_OBJECTS_FALSE, + CREATE_NEW_PARAM_OBJECTS_TRUE +} CreateNewParamObjects; + +static void ParseLocationSet(LocationSet *loc, Type *rtype, Object *proc, CreateNewParamObjects createNewParamObjects, Boolean arg5, int arg6, Boolean *arg7, Boolean *resultFailed) { + CInt64 field; + UInt32 stride; + PAMemoryBlock *block; + PAMemoryBlock *restriction; + Boolean failed; + Boolean flag37; + Boolean epFlag; + Boolean anotherFlag; + Boolean isUnknown; + + IRO_ASSERT(7552, loc != NULL); + IRO_ASSERT(7553, rtype == NULL || rtype != NULL); + IRO_ASSERT(7554, proc != NULL); + IRO_ASSERT(7555, createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_FALSE || createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_TRUE); + IRO_ASSERT(7556, resultFailed != NULL); + IRO_ASSERT(7557, *resultFailed == false); + IRO_ASSERT(7558, proc != NULL); + IRO_ASSERT(7559, proc == NULL || ObjectIsAFunction(proc)); + + failed = 0; + isUnknown = 0; + anotherFlag = 0; + field = cint64_zero; + stride = 0; + + tk = lex(); + if (tk == TK_IDENTIFIER) { + if (!strcmp(tkidentifier->name, "__unknown")) { + flag37 = 0; + isUnknown = 1; + tk = lookahead(); + if (tk == '(') { + lex(); + tk = lex(); + if (tk != TK_IDENTIFIER) { + CError_Error(CErrorStr107); + failed = 1; + } + if (!failed) { + PALocalVar *local; + local = PALocalVar_New(); + PALocalVar_InitByName(local, tkidentifier->name); + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_LOCALVAR, local); + + tk = lex(); + if (tk != ')') { + CError_Error(CErrorStr115); + failed = 1; + } + if (!failed) { + rtype = NULL; + restriction = block; + } + } + } else { + rtype = NULL; + restriction = NULL; + } + } else if (arg5 && !strcmp(tkidentifier->name, "__return_value")) { + flag37 = 0; + anotherFlag = 1; + } else if (!strcmp(tkidentifier->name, "__unique_heap_allocation")) { + PAHeapBlock *hb; + + flag37 = 0; + hb = CreateUniqueHeapAlloc_sub_486420(); + InitUniqueHeapAlloc_sub_486410(hb, NULL); + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_HEAPBLOCK, hb); + } else if (!strcmp(tkidentifier->name, "__parameter_representative")) { + flag37 = 1; + tk = lex(); + + if (tk == '(') { + tk = lex(); + if (tk != TK_INTCONST) { + CError_Error(CErrorStr121); + failed = 1; + } + if (!failed) { + Object *obj; + ObjectList *list; + ExtendedParam *ep; + obj = NULL; + for (list = stParamObjs; list; list = list->next) { + if ((obj = list->object) && (obj->u.var.uid == CInt64_GetULong(&tkintconst))) + break; + } + if (!list) + obj = NULL; + + if (!obj) { + if (createNewParamObjects) { + obj = IRO_malloc(sizeof(Object)); + memset(obj, 0, sizeof(Object)); + obj->datatype = DLOCAL; + obj->extParam = NULL; + obj->name = CParser_GetUniqueName(); + obj->type = TYPE(&stunsignedlong); + obj->qual = 0; + obj->u.var.info = NULL; + obj->u.var.uid = CInt64_GetULong(&tkintconst); + + list = IRO_malloc(sizeof(ObjectList)); + list->next = stParamObjs; + list->object = obj; + stParamObjs = list; + + ep = CreateExtendedParam(NULL, NULL, obj, &epFlag); + } else { + char buf[64]; + sprintf(buf, "__parameter_representative(%" PRId32 ")", obj->u.var.uid); + CError_Error(CErrorStr140, buf); + failed = 1; + } + } else { + ep = obj->extParam; + IRO_ASSERT(7687, ep != NULL); + } + + if (!failed) { + tk = lex(); + if (tk != ')') { + CError_Error(CErrorStr115); + failed = 1; + } + } + if (!failed) { + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, ep); + } + } + } + } else { + Object *obj; + NameSpace *nspace; + + obj = NULL; + for (nspace = cscope_current; nspace; nspace = nspace->parent) { + NameSpaceObjectList *chk; + if ((chk = CScope_GetLocalObject(nspace, tkidentifier)) && chk->object->otype == OT_OBJECT) { + if (notendofline()) { + obj = OBJECT(chk->object); + break; + } + } + } + + if (!obj) { + ObjectList *chk; + for (chk = FunctionArguments(proc); chk; chk = chk->next) { + if (chk->object && chk->object->name && chk->object->name->name && !strcmp(tkidentifier->name, chk->object->name->name)) { + obj = chk->object; + } + } + } + + if (obj) { + PAMemoryBlockKind kind; + void *thing; + + if (ObjectIsAnExtendedParamCandidate(obj)) { + kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM; + thing = CreateExtendedParam(NULL, NULL, obj, &epFlag); + } else { + kind = PAMEMORYBLOCKKIND_LOCALVAR; + thing = PALocalVar_New(); + if (obj->name && obj->name->name && ObjectIsAFunctionArgument(proc, obj)) + PALocalVar_InitByName(thing, obj->name->name); + else + PALocalVar_InitByObject(thing, obj); + } + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, kind, thing); + rtype = CDecl_NewPointerType(obj->type); + } else { + CError_Error(CErrorStr140, tkidentifier->name); + failed = 1; + } + } + } else if (tk == TK_INTCONST) { + flag37 = 0; + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_INT, &tkintconst); + } else if (tk == '(') { + ParseLocationSet(loc, rtype, proc, createNewParamObjects, arg5, 1, &anotherFlag, &failed); + if (!failed) { + tk = plex(); + if (tk != ')') + CError_Error(CErrorStr115); + failed = 1; + } + } else { + CError_Error(CErrorStr121); + failed = 1; + } + + if (!failed && flag37) { + tk = lookahead(); + if (tk == '[') { + lex(); + if (rtype && IS_TYPE_POINTER(rtype) && IS_TYPE_POINTER(TPTR_TARGET(rtype))) { + tk = lex(); + if (tk == ']') { + if ((stride = rtype->size)) { + CInt64 tmp; + CInt64_SetLong(&tmp, stride); + field = CInt64_Mod(field, tmp); + } + rtype = TPTR_TARGET(rtype); + } else { + CError_Error(CErrorStr125); + } + } else { + CError_Error(CErrorStr148); + } + } else if (tk == '.') { + lex(); + if (rtype && IS_TYPE_POINTER(rtype) && IS_TYPE_STRUCT(TPTR_TARGET(rtype))) { + if (TPTR_TARGET(rtype)->size) { + tk = lex(); + if (tk == TK_IDENTIFIER) { + StructMember *member; + if ((member = ismember(TYPE_STRUCT(TPTR_TARGET(rtype)), tkidentifier))) { + CInt64_SetLong(&field, member->offset); + rtype = CDecl_NewPointerType(member->type); + } else { + CError_Error(CErrorStr150, tkidentifier); + } + } else { + CError_Error(CErrorStr107); + } + } else { + CError_Error(CErrorStr136, TPTR_TARGET(rtype), 0); + } + } else { + CError_Error(CErrorStr149); + } + } + } + + if (!failed && !anotherFlag) { + LocationSet_Term(loc); + if (!isUnknown) + LocationSet_InitKnown(loc, block, field, stride, rtype); + else + LocationSet_InitUnknown(loc, rtype, restriction, NULL); + } + + *arg7 = anotherFlag; + *resultFailed = failed; +} + +static void ParseLocationSetSet(LocationSetSet *locs, Type *rtype, Object *proc, CreateNewParamObjects createNewParamObjects, Boolean *resultFailed) { + Boolean failed; + + IRO_ASSERT(7892, locs != NULL); + IRO_ASSERT(7893, rtype == NULL || rtype != NULL); + IRO_ASSERT(7894, proc != NULL); + IRO_ASSERT(7895, createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_FALSE || createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_TRUE); + IRO_ASSERT(7896, resultFailed != NULL); + IRO_ASSERT(7897, *resultFailed == false); + IRO_ASSERT(7898, proc != NULL); + IRO_ASSERT(7899, proc == NULL || ObjectIsAFunction(proc)); + + failed = 0; + + tk = lex(); + if (tk != '(') { + CError_Error(CErrorStr114); + failed = 1; + } + + if (!failed) { + Boolean anotherFlag; + + LocationSet *ls; + ls = LocationSet_New(); + LocationSet_InitUnknown(ls, NULL, NULL, NULL); + + tk = lookahead(); + while (!failed && tk != ')') { + ParseLocationSet(ls, rtype, proc, createNewParamObjects, 0, 0, &anotherFlag, &failed); + if (!failed) + LocationSetSet_Add(locs, ls); + + if (!failed) { + tk = lookahead(); + if (tk == ',') { + lex(); + tk = lookahead(); + } else if (tk != ')') { + lex(); + CError_Error(CErrorStr121); + failed = 1; + } + } + } + + if (!failed) + lex(); + + LocationSet_Term(ls); + LocationSet_Delete(ls); + } + + *resultFailed = failed; +} + +static Object *GetFunctionObjectFromDeclInfo(DeclInfo *di) { + Object *proc; + + IRO_ASSERT(7953, di != NULL); + + if (di->storageclass != TK_TYPEDEF && IS_TYPE_FUNC(di->thetype)) { + Boolean flag; + proc = CDecl_GetFunctionObject(di, NULL, &flag, 1); + if (flag) + di->x64 = 1; + } else { + proc = NULL; + } + + return proc; +} + +void PointerAnalysis_ParseEntryPointsToSpecifier(DeclInfo *di) { + Object *proc; + Boolean failed; + Boolean anotherFlag; + + IRO_ASSERT(7982, di != NULL); + + proc = GetFunctionObjectFromDeclInfo(di); + if (proc) { + IRO_ASSERT(7987, proc == NULL || ObjectIsAFunction(proc)); + + tk = lex(); + IRO_ASSERT(7996, tk == TK_IDENTIFIER && strcmp(tkidentifier->name,"entry_points_to") == 0); + + failed = 0; + + tk = lex(); + if (tk != '(') { + CError_Error(CErrorStr114); + failed = 1; + } + + if (!failed) { + LocationSet *ls; + ls = LocationSet_New(); + LocationSet_InitUnknown(ls, NULL, NULL, NULL); + ParseLocationSet(ls, NULL, proc, CREATE_NEW_PARAM_OBJECTS_FALSE, 0, 0, &anotherFlag, &failed); + if (!failed) { + if ((tk = lex()) != ',') { + CError_Error(CErrorStr116); + failed = 1; + } + } + if (!failed) { + Type *type; + Type *innerType; + LocationSetSet *lss; + + type = LocationSet_rtype(ls); + if (type && IS_TYPE_POINTER(type)) + innerType = TPTR_TARGET(type); + else + innerType = NULL; + + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + ParseLocationSetSet(lss, innerType, proc, CREATE_NEW_PARAM_OBJECTS_TRUE, &failed); + if (!failed) { + if ((tk = lex()) != ')') { + CError_Error(CErrorStr115); + failed = 1; + } + } + if (!failed) { + PartialTransferFunction *ptf; + PointsToFunction *pointsToFunc; + PointsToEntry *pte; + + if (!proc->u.func.ptfList) { + proc->u.func.ptfList = PTFList_New(); + PTFList_Init(proc->u.func.ptfList); + } + ptf = PTFList_FindFirst(proc->u.func.ptfList); + if (!ptf) + ptf = AllocatePTF(proc, NULL, NULL); + + pointsToFunc = PartialTransferFunction_initialPointsToFn(ptf); + pte = PointsToEntry_New(); + PointsToEntry_Init(pte, ls, lss); + PointsToFunction_Add(pointsToFunc, pte); + PointsToEntry_Term(pte); + PointsToEntry_Delete(pte); + } + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + } + LocationSet_Term(ls); + LocationSet_Delete(ls); + } + } +} + +void PointerAnalysis_ParseExitPointsToSpecifier(DeclInfo *di) { + Object *proc; + Boolean failed; + Boolean anotherFlag; + + IRO_ASSERT(8097, di != NULL); + + proc = GetFunctionObjectFromDeclInfo(di); + if (proc) { + IRO_ASSERT(8102, proc == NULL || ObjectIsAFunction(proc)); + + tk = lex(); + IRO_ASSERT(8111, tk == TK_IDENTIFIER && strcmp(tkidentifier->name,"exit_points_to") == 0); + + failed = 0; + + tk = lex(); + if (tk != '(') { + CError_Error(CErrorStr114); + failed = 1; + } + + if (!failed) { + LocationSet *ls; + ls = LocationSet_New(); + LocationSet_InitUnknown(ls, NULL, NULL, NULL); + ParseLocationSet(ls, NULL, proc, CREATE_NEW_PARAM_OBJECTS_FALSE, 1, 0, &anotherFlag, &failed); + if (!failed) { + if ((tk = lex()) != ',') { + CError_Error(CErrorStr116); + failed = 1; + } + } + if (!failed) { + Type *type; + Type *innerType; + LocationSetSet *lss; + + type = LocationSet_rtype(ls); + if (type && IS_TYPE_POINTER(type)) + innerType = TPTR_TARGET(type); + else + innerType = NULL; + + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + ParseLocationSetSet(lss, innerType, proc, CREATE_NEW_PARAM_OBJECTS_FALSE, &failed); + if (!failed) { + if ((tk = lex()) != ')') { + CError_Error(CErrorStr115); + failed = 1; + } + } + if (!failed) { + PartialTransferFunction *ptf; + PointsToFunction *pointsToFunc; + PointsToEntry *pte; + + if (!proc->u.func.ptfList) { + proc->u.func.ptfList = PTFList_New(); + PTFList_Init(proc->u.func.ptfList); + } + ptf = PTFList_FindFirst(proc->u.func.ptfList); + if (!ptf) + ptf = AllocatePTF(proc, NULL, NULL); + + pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf); + pte = PointsToEntry_New(); + if (anotherFlag) + PointsToEntry_Init(pte, PartialTransferFunction_returnLocation(ptf), lss); + else + PointsToEntry_Init(pte, ls, lss); + PointsToFunction_Add(pointsToFunc, pte); + PointsToEntry_Term(pte); + PointsToEntry_Delete(pte); + } + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + } + LocationSet_Term(ls); + LocationSet_Delete(ls); + } + } +} + +void PointerAnalysis_ParseFunctionModifiesSpecifier(DeclInfo *di) { + Object *proc; + Boolean failed; + LocationSetSet *lss; + PartialTransferFunction *ptf; + LocationSetSet *ptfLSS; + + IRO_ASSERT(8211, di != NULL); + + proc = GetFunctionObjectFromDeclInfo(di); + if (proc) { + IRO_ASSERT(8216, proc == NULL || ObjectIsAFunction(proc)); + + tk = lex(); + IRO_ASSERT(8225, tk == TK_IDENTIFIER && strcmp(tkidentifier->name,"function_modifies") == 0); + + failed = 0; + lss = LocationSetSet_New(); + LocationSetSet_Init(lss); + ParseLocationSetSet(lss, NULL, proc, CREATE_NEW_PARAM_OBJECTS_FALSE, &failed); + if (!failed) { + if (!proc->u.func.ptfList) { + proc->u.func.ptfList = PTFList_New(); + PTFList_Init(proc->u.func.ptfList); + } + ptf = PTFList_FindFirst(proc->u.func.ptfList); + if (!ptf) + ptf = AllocatePTF(proc, NULL, NULL); + ptfLSS = PTF_sub_48D750(ptf); + LocationSetSet_RemoveAll(ptfLSS); + LocationSetSet_AddSet(ptfLSS, lss); + } + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + } +} + diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.h b/compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.h new file mode 100644 index 0000000..ec50eba --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysis.h @@ -0,0 +1,25 @@ +#ifndef COMPILER_IROPOINTERANALYSIS_H +#define COMPILER_IROPOINTERANALYSIS_H + +#include "IrOptimizer.h" + +extern void PointerAnalysis_Setup(void); +extern void PointerAnalysis_Cleanup(void); +extern void IRO_AnalyzePointers(Object *function); +extern Boolean PointerAnalysis_TwoLinearNodePointerExprsMightAlias(Object *proc, IROLinear *nd1, IROLinear *nd2); +extern Boolean PointerAnalysis_TwoENodePointerExprsMightAlias(Object *proc, ENode *nd1, ENode *nd2); +extern Boolean PointerAnalysis_IsLinearNodePointerExprDefinite(Object *proc, IROLinear *nd); +extern Boolean PointerAnalysis_IsENodePointerExprDefinite(Object *proc, ENode *nd); +extern Boolean PointerAnalysis_IsVariableValueDefinite(Object *proc, VarRecord *var, PointsToFunction *pointsTo); +extern void PointerAnalysis_LookupLinearNodePointerExpr(Object *proc, IROLinear *indirect, IROListNode **list); +extern void PointerAnalysis_LookupENodePointerExpr(Object *proc, ENode *indirect, ENodeList **list); +extern void PointerAnalysis_LookupVariableIntoLinearNodeExprs(Object *proc, VarRecord *var, PointsToFunction *pointsTo, IROListNode **list); +extern void PointerAnalysis_LookupVariableIntoENodeExprs(Object *proc, VarRecord *var, PointsToFunction *pointsTo, ENodeList **list); +extern void PointerAnalysis_GetFunctionKills(Object *proc, IROLinear *funccall, ObjectList **list); +extern void PointerAnalysis_GetFunctionDependencies(Object *proc, IROLinear *funccall, ObjectList **list); +extern void PointerAnalysis_PragmaMode(void); +extern void PointerAnalysis_ParseEntryPointsToSpecifier(DeclInfo *di); +extern void PointerAnalysis_ParseExitPointsToSpecifier(DeclInfo *di); +extern void PointerAnalysis_ParseFunctionModifiesSpecifier(DeclInfo *di); + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysisADTs.c b/compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysisADTs.c new file mode 100644 index 0000000..dad9501 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroPointerAnalysisADTs.c @@ -0,0 +1,2736 @@ +#include "IroPointerAnalysis.h" +#include "IroMalloc.h" +#include "compiler/CError.h" +#include "compiler/CInt64.h" +#include "compiler/CParser.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +// TODO: this should really be elsewhere (but where?) +CW_INLINE UInt32 gcd(UInt32 a, UInt32 b) { + UInt32 chk; + + if (!a) + return b; + if (!b) + return a; + + while (1) { + chk = a % b; + if (!chk) + return b; + a = b; + b = chk; + } +} + +// #define IRO_DEBUG + +typedef struct ExtendedParamSet ExtendedParamSet; +typedef struct LocationSet LocationSet; +typedef struct LocationSetSet LocationSetSet; +typedef struct ObjectSet ObjectSet; +typedef struct PAHeapBlock PAHeapBlock; +typedef struct PALocalVar PALocalVar; +typedef struct PAMemoryBlock PAMemoryBlock; +typedef struct ParamMapping ParamMapping; +typedef struct ParamMappingFunction ParamMappingFunction; +typedef struct PartialTransferFunction PartialTransferFunction; +typedef struct PointsToEntry PointsToEntry; +// typedef struct PointsToFunction PointsToFunction; +typedef struct Stack Stack; +typedef struct StackElement StackElement; + +typedef UInt32 uint32; + +void __assertion_failed(char *expr, char *filename, int line); + +#ifdef IRO_DEBUG +#define IRO_ASSERT(line, expr) \ + do { \ + if (!(expr)) { \ + __assertion_failed(#expr, __FILE__, line); \ + } \ + } while (0); + +#define IRO_DEBUG_CLEAR(obj, type) \ + memset((obj), 0xFF, sizeof(type)) +#else +#define IRO_ASSERT(line, expr) ((void) 0) +#define IRO_DEBUG_CLEAR(obj, type) ((void) 0) +#endif + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +struct StackElement { + Object *proc; + PartialTransferFunction *ptf; + ParamMappingFunction *map; + IROLinear *funcCall; +}; + +struct Stack { + StackElement *top; + Stack *next; +}; + +struct ObjectSet { + Object *proc; + ObjectSet *otherProcs; +}; + +struct ExtendedParam { + ObjectSet *objectSet; + uint32 x4; +}; + +struct ExtendedParamSet { + ExtendedParam *ep; + ExtendedParamSet *otherEps; +}; + +struct PAHeapBlock { + IROLinear *x0; +}; + +struct PALocalVar { + Object *x0; + char *x4; +}; + +typedef enum { + PAMEMORYBLOCKKIND_INVALID, + PAMEMORYBLOCKKIND_1, + PAMEMORYBLOCKKIND_EXTENDEDPARAM, + PAMEMORYBLOCKKIND_LOCALVAR, + PAMEMORYBLOCKKIND_HEAPBLOCK, + PAMEMORYBLOCKKIND_INT, + PAMEMORYBLOCKKIND_6 +} PAMemoryBlockKind; + +struct PAMemoryBlock { + PAMemoryBlockKind kind; + union { + ExtendedParam *ep; + PALocalVar *localvar; + PAHeapBlock *heapblock; + CInt64 intval; + void *x6; + } u; +}; + +struct LocationSet { + PAMemoryBlock *block; + Type *rtype; + union { + struct { + CInt64 field; + UInt32 stride; + } known; + struct { + PAMemoryBlock *restriction; + LocationSet *bitfieldOf; + } unknown; + } u; +}; + +struct LocationSetSet { + LocationSet *loc; + LocationSetSet *otherLocs; + UInt8 count; +}; + +struct ParamMapping { + IROLinear *actual; + Object *formal; + ExtendedParam *extended; +}; + +struct ParamMappingFunction { + ParamMapping *mapping; + ParamMappingFunction *otherMappings; +}; + +struct PointsToEntry { + LocationSet *loc; + LocationSetSet *locs; +}; + +struct PointsToFunction { + PointsToEntry *pte; + PointsToFunction *otherPtes; +}; + +struct PartialTransferFunction { + PointsToFunction *initialPointsToFn; + PointsToFunction *finalPointsToFn; + LocationSetSet *funcModifies; + LocationSet *returnLocation; + Boolean x10; + struct { + IROLinear *nd; + PartialTransferFunction *ptf; + } context; +}; + +struct PTFList { + PartialTransferFunction *ptf; + PTFList *otherPTFs; +}; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +// TODO: how many of these are actually in IroPointerAnalysis.c? +static uint32 stExtendedParamNum; +static PartialTransferFunction *stUnknownPTF; +static uint32 stIndentationLevel; +static UInt8 stTabs[0x2C]; // unused mystery object +static Stack *stCallingContextStack; +static ObjectList *stParamObjs; +static jmp_buf stAbortPointerAnalysis; +static Object stUnknown; +static Object *stCurrentProc; +static ExtendedParamSet *stExtParamSet; +static PTFList *stPTFList; +static uint32 stMaxPassCount; +// TODO: stEvalProcActionParams +static IRONode *stExceptionFNode; + +static PAMemoryBlock stDummyMemoryBlock = { + PAMEMORYBLOCKKIND_1 +}; +static PAMemoryBlock *stUnknownMb = &stDummyMemoryBlock; + +static LocationSet stDummyLocationSet = { + &stDummyMemoryBlock +}; + +static LocationSet *stUnknownLs = &stDummyLocationSet; + +// forward decls +CW_INLINE StackElement *Stack_sub_48A5B0(Stack **stackPtr); +CW_INLINE void ObjectSet_RemoveAll(ObjectSet *procList); +CW_INLINE void ExtendedParamSet_RemoveAll(ExtendedParamSet *epList); +CW_INLINE void LocationSet_Copy(LocationSet *dest, LocationSet *src); +CW_INLINE Boolean LocationSet_IsUnknown(LocationSet *ls); +CW_INLINE void LocationSetSet_RemoveAll(LocationSetSet *lss); +CW_INLINE void LocationSetSet_AddSet(LocationSetSet *dest, LocationSetSet *src); +CW_INLINE void ParamMappingFunction_RemoveAll(ParamMappingFunction *pmf); +CW_INLINE void ParamMappingFunction_AddAllMaybe_sub_487C50(ParamMappingFunction *dest, ParamMappingFunction *src); +CW_INLINE void PointsToFunction_RemoveAll(PointsToFunction *pointsToFunc); +CW_INLINE void PointsToFunction_AddAllIGuess_sub_487D80(PointsToFunction *dest, PointsToFunction *src); +CW_INLINE void PTFList_RemoveAll(PTFList *ptfList); + +CW_INLINE StackElement *StackElement_New(void) { + StackElement *stackElement = IRO_malloc(sizeof(StackElement)); + IRO_ASSERT(103, stackElement != NULL); +#ifdef IRO_DEBUG + stackElement->proc = NULL; + stackElement->ptf = NULL; + stackElement->map = NULL; + stackElement->funcCall = NULL; +#endif + return stackElement; +} + +CW_INLINE void StackElement_Delete(StackElement *stackElement) { + IRO_ASSERT(117, stackElement != NULL); + IRO_ASSERT(118, stackElement->proc == NULL); + IRO_ASSERT(119, stackElement->ptf == NULL); + IRO_ASSERT(120, stackElement->map == NULL); + IRO_ASSERT(121, stackElement->funcCall == NULL); + IRO_DEBUG_CLEAR(stackElement, sizeof(StackElement)); + IRO_free(stackElement); +} + +CW_INLINE void StackElement_Init(StackElement *stackElement, Object *proc, PartialTransferFunction *ptf, ParamMappingFunction *map, IROLinear *funcCall) { + IRO_ASSERT(131, stackElement != NULL); + IRO_ASSERT(132, proc != NULL); + IRO_ASSERT(133, ptf != NULL); + IRO_ASSERT(134, map != NULL); + IRO_ASSERT(135, funcCall != NULL); + stackElement->proc = proc; + stackElement->ptf = ptf; + stackElement->map = map; + stackElement->funcCall = funcCall; +} + +CW_INLINE void StackElement_Copy(StackElement *dest, StackElement *src) { + IRO_ASSERT(145, dest != NULL); + IRO_ASSERT(146, src != NULL); + StackElement_Init(dest, src->proc, src->ptf, src->map, src->funcCall); +} + +CW_INLINE void StackElement_Term(StackElement *stackElement) { + IRO_ASSERT(156, stackElement != NULL); +#ifdef IRO_DEBUG + stackElement->proc = NULL; + stackElement->ptf = NULL; + stackElement->map = NULL; + stackElement->funcCall = NULL; +#endif +} + +CW_INLINE void *StackElement_sub_48A780(StackElement *stackElement) { + IRO_ASSERT(213, stackElement != NULL); + return stackElement->proc; +} + +CW_INLINE Boolean StackRelated_sub_48A760(void *key1, void *key2) { + IRO_ASSERT(220, key1 != NULL); + IRO_ASSERT(221, key2 != NULL); + return key1 == key2; +} + +CW_INLINE Object *StackElement_proc(StackElement *stackElement) { + IRO_ASSERT(228, stackElement != NULL); + return stackElement->proc; +} + +CW_INLINE PartialTransferFunction *StackElement_ptf(StackElement *stackElement) { + IRO_ASSERT(235, stackElement != NULL); + return stackElement->ptf; +} + +CW_INLINE ParamMappingFunction *StackElement_map(StackElement *stackElement) { + IRO_ASSERT(242, stackElement != NULL); + return stackElement->map; +} + +CW_INLINE IROLinear *StackElement_funcCall(StackElement *stackElement) { + IRO_ASSERT(249, stackElement != NULL); + return stackElement->funcCall; +} + +CW_INLINE Stack *Stack_New(void) { + Stack *stack = IRO_malloc(sizeof(Stack)); + IRO_ASSERT(265, stack != NULL); +#ifdef IRO_DEBUG + stack->top = NULL; + stack->next = NULL; +#endif + return stack; +} + +CW_INLINE void Stack_Delete(Stack *stack) { + IRO_ASSERT(277, stack != NULL); + IRO_ASSERT(278, stack->top == NULL); + IRO_ASSERT(279, stack->next == NULL); + IRO_DEBUG_CLEAR(stack, sizeof(Stack)); + IRO_free(stack); +} + +CW_INLINE void Stack_Init(Stack *stack) { + IRO_ASSERT(289, stack != NULL); + stack->top = NULL; + stack->next = NULL; +} + +CW_INLINE void Stack_Term(Stack **stackPtr) { + StackElement *stackElement; + + IRO_ASSERT(299, stackPtr != NULL); + IRO_ASSERT(300, *stackPtr != NULL); + + while ((*stackPtr)->top) { + stackElement = Stack_sub_48A5B0(stackPtr); + StackElement_Term(stackElement); + StackElement_Delete(stackElement); + } +} + +CW_INLINE void Stack_sub_48A660(Stack **stackPtr, StackElement *stackElement) { + StackElement *newElement; + Stack *newStack; + + IRO_ASSERT(315, stackPtr != NULL); + IRO_ASSERT(316, *stackPtr != NULL); + + newElement = StackElement_New(); + StackElement_Copy(newElement, stackElement); + + newStack = Stack_New(); + newStack->top = newElement; + newStack->next = *stackPtr; + *stackPtr = newStack; +} + +CW_INLINE StackElement *Stack_Top(Stack **stackPtr) { + IRO_ASSERT(331, stackPtr != NULL); + IRO_ASSERT(332, *stackPtr != NULL); + + return (*stackPtr)->top; +} + +CW_INLINE Stack *Stack_Next(Stack **stackPtr) { + IRO_ASSERT(343, stackPtr != NULL); + IRO_ASSERT(344, *stackPtr != NULL); + + return (*stackPtr)->next; +} + +CW_INLINE StackElement *Stack_sub_48A5B0(Stack **stackPtr) { + StackElement *stackElement; + + IRO_ASSERT(357, stackPtr != NULL); + IRO_ASSERT(358, *stackPtr != NULL); + + stackElement = (*stackPtr)->top; + if (stackElement) { + Stack *next = (*stackPtr)->next; + (*stackPtr)->top = NULL; + (*stackPtr)->next = NULL; + Stack_Delete(*stackPtr); + *stackPtr = next; + } + + return stackElement; +} + +CW_INLINE StackElement *Stack_sub_48A710(Stack **stackPtr, void *key) { + Stack *stack; + + IRO_ASSERT(379, stackPtr != NULL); + IRO_ASSERT(380, key != NULL); + + for (stack = *stackPtr; stack; stack = stack->next) { + if (stack->top) { + if (StackRelated_sub_48A760(StackElement_sub_48A780(stack->top), key)) + return stack->top; + } + } + + return NULL; +} + +CW_INLINE ObjectSet *ObjectSet_New(void) { + ObjectSet *procList; + + procList = IRO_malloc(sizeof(ObjectSet)); + IRO_ASSERT(439, procList != NULL); +#ifdef IRO_DEBUG + procList->proc = NULL; + procList->otherProcs = NULL; +#endif + return procList; +} + +CW_INLINE void ObjectSet_Delete(ObjectSet *procList) { + IRO_ASSERT(451, procList != NULL); + IRO_ASSERT(452, procList->proc == NULL); + IRO_ASSERT(453, procList->otherProcs == NULL); + IRO_DEBUG_CLEAR(procList, sizeof(ObjectSet)); + IRO_free(procList); +} + +CW_INLINE void ObjectSet_Init(ObjectSet *procList) { + IRO_ASSERT(463, procList != NULL); + procList->proc = NULL; + procList->otherProcs = NULL; +} + +CW_INLINE void ObjectSet_Term(ObjectSet *procList) { + IRO_ASSERT(481, procList != NULL); + ObjectSet_RemoveAll(procList); +#ifdef IRO_DEBUG + procList->proc = NULL; + procList->otherProcs = NULL; +#endif +} + +CW_INLINE void ObjectSet_ForEach(ObjectSet *procList, void (*action)(Object *, void *), void *refcon) { + IRO_ASSERT(528, procList != NULL); + IRO_ASSERT(529, action != NULL); + IRO_ASSERT(530, refcon == NULL || refcon != NULL); + + while (procList && procList->proc) { + action(procList->proc, refcon); + procList = procList->otherProcs; + } +} + +CW_INLINE Object *ObjectSet_sub_485020(ObjectSet *procList, Object *proc) { + IRO_ASSERT(540, procList != NULL); + IRO_ASSERT(541, proc != NULL); + while (procList && procList->proc) { + if (procList->proc == proc) + return procList->proc; + procList = procList->otherProcs; + } + return NULL; +} + +CW_INLINE Object *ObjectSet_FindFirst(ObjectSet *procList) { + IRO_ASSERT(552, procList != NULL); + return procList->proc; +} + +CW_INLINE int ObjectSet_Count(ObjectSet *procList) { + int count; + + IRO_ASSERT(561, procList != NULL); + + count = 0; + while (procList && procList->proc) { + count++; + procList = procList->otherProcs; + } + + return count; +} + +CW_INLINE void ObjectSet_sub_486800(ObjectSet *procList, Object *proc) { + ObjectSet *newProcList; + + IRO_ASSERT(574, procList != NULL); + IRO_ASSERT(575, proc != NULL); + + if (procList->proc) { + newProcList = ObjectSet_New(); + ObjectSet_Init(newProcList); + newProcList->proc = procList->proc; + newProcList->otherProcs = procList->otherProcs; + procList->otherProcs = newProcList; + } + + procList->proc = proc; +} + +CW_INLINE void ObjectSet_sub_4867D0(ObjectSet *procList, Object *proc) { + IRO_ASSERT(592, procList != NULL); + IRO_ASSERT(593, proc != NULL); + + if (!ObjectSet_sub_485020(procList, proc)) + ObjectSet_sub_486800(procList, proc); +} + +CW_INLINE void ObjectSet_Remove(ObjectSet *procList, Object *proc) { + ObjectSet *prev; + ObjectSet *tmp; + + IRO_ASSERT(605, procList != NULL); + IRO_ASSERT(606, proc != NULL); + + prev = NULL; + while (procList && procList->proc) { + if (procList->proc == proc) { + if (!prev) { + if (procList->otherProcs == NULL) { + procList->proc = NULL; + } else { + tmp = procList->otherProcs; + procList->proc = procList->otherProcs->proc; + procList->otherProcs = procList->otherProcs->otherProcs; + tmp->proc = NULL; + tmp->otherProcs = NULL; + ObjectSet_Term(tmp); + ObjectSet_Delete(tmp); + } + } else { + prev->otherProcs = procList->otherProcs; + procList->proc = NULL; + procList->otherProcs = NULL; + ObjectSet_Term(procList); + ObjectSet_Delete(procList); + } + return; + } + prev = procList; + procList = procList->otherProcs; + } +} + +CW_INLINE void ObjectSet_RemoveAll(ObjectSet *procList) { + IRO_ASSERT(645, procList != NULL); + + while (procList && procList->proc) + ObjectSet_Remove(procList, procList->proc); +} + +CW_INLINE void ObjectSet_AddSetAction(Object *proc, void *refcon) { + IRO_ASSERT(655, proc != NULL); + IRO_ASSERT(656, refcon != NULL); + + ObjectSet_sub_4867D0(refcon, proc); +} + +CW_INLINE void ObjectSet_SimpleAddSetAction(Object *proc, void *refcon) { + IRO_ASSERT(663, proc != NULL); + IRO_ASSERT(664, refcon != NULL); + + ObjectSet_sub_486800(refcon, proc); +} + +CW_INLINE void ObjectSet_sub_48C590(ObjectSet *dest, ObjectSet *src) { + IRO_ASSERT(671, dest != NULL); + IRO_ASSERT(672, src != NULL); + + if (dest->proc) + ObjectSet_ForEach(src, ObjectSet_AddSetAction, dest); + else + ObjectSet_ForEach(src, ObjectSet_SimpleAddSetAction, dest); +} + +CW_INLINE void ObjectSet_RemoveSetAction(Object *proc, void *refcon) { + IRO_ASSERT(682, proc != NULL); + IRO_ASSERT(683, refcon != NULL); + + ObjectSet_Remove(refcon, proc); +} + +CW_INLINE void ObjectSet_removeiter_sub_48C890(ObjectSet *dest, ObjectSet *src) { + IRO_ASSERT(690, dest != NULL); + IRO_ASSERT(691, src != NULL); + + ObjectSet_ForEach(src, ObjectSet_RemoveSetAction, dest); +} + +CW_INLINE Boolean ObjectSet_sub_484FA0(ObjectSet *os1, ObjectSet *os2) { + ObjectSet *scan; + + IRO_ASSERT(700, os1 != NULL); + IRO_ASSERT(701, os2 != NULL); + + if (os1 == os2) + return 1; + + for (scan = os1; scan && scan->proc; scan = scan->otherProcs) { + if (!ObjectSet_sub_485020(os2, scan->proc)) + return 0; + } + + for (scan = os2; scan && scan->proc; scan = scan->otherProcs) { + if (!ObjectSet_sub_485020(os1, scan->proc)) + return 0; + } + + return 1; +} + +CW_INLINE ExtendedParam *ExtendedParam_New(void) { + ExtendedParam *ep = IRO_malloc(sizeof(ExtendedParam)); + + IRO_ASSERT(755, ep != NULL); +#ifdef IRO_DEBUG + ep->objectSet = NULL; +#endif + return ep; +} + +CW_INLINE void ExtendedParam_Delete(ExtendedParam *ep) { + IRO_ASSERT(762, ep != NULL); + IRO_ASSERT(763, ep->objectSet == NULL); + IRO_DEBUG_CLEAR(ep, sizeof(ExtendedParam)); + IRO_free(ep); +} + +CW_INLINE void ExtendedParam_Init(ExtendedParam *ep, Object *obj) { + IRO_ASSERT(777, ep != NULL); + IRO_ASSERT(778, obj != NULL); + IRO_ASSERT(779, obj->extParam == NULL); + IRO_ASSERT(780, stExtendedParamNum < ((uint32) -1) / 2 - 1); + + ep->objectSet = ObjectSet_New(); + ObjectSet_Init(ep->objectSet); + ObjectSet_sub_4867D0(ep->objectSet, obj); + obj->extParam = ep; + + ep->x4 = stExtendedParamNum++; +} + +CW_INLINE void ExtendedParam_TermAction(Object *obj, void *refcon) { + obj->extParam = NULL; +} + +CW_INLINE void ExtendedParam_Term(ExtendedParam *ep) { + IRO_ASSERT(800, ep != NULL); + + ObjectSet_ForEach(ep->objectSet, ExtendedParam_TermAction, NULL); + ObjectSet_Term(ep->objectSet); + ObjectSet_Delete(ep->objectSet); +#ifdef IRO_DEBUG + ep->objectSet = NULL; +#endif +} + +CW_INLINE Boolean ExtendedParams_Equal(ExtendedParam *ep1, ExtendedParam *ep2) { + IRO_ASSERT(841, ep1 != NULL); + IRO_ASSERT(842, ep2 != NULL); + IRO_ASSERT(843, ep1->objectSet != NULL); + IRO_ASSERT(844, ep2->objectSet != NULL); + + if (ep1 == ep2) + return 1; + + return ep1->x4 == ep2->x4 && ObjectSet_sub_484FA0(ep1->objectSet, ep2->objectSet); +} + +CW_INLINE ExtendedParam *ExtendedParam_FindByObject(Object *obj) { + IRO_ASSERT(856, obj != NULL); + + return obj->extParam; +} + +CW_INLINE void ExtendedParam_sub_4867B0(ExtendedParam *ep, Object *obj) { + IRO_ASSERT(863, ep != NULL); + IRO_ASSERT(864, ep->objectSet != NULL); + IRO_ASSERT(865, obj != NULL); + + ObjectSet_sub_4867D0(ep->objectSet, obj); + obj->extParam = ep; +} + +CW_INLINE void ExtendedParam_RemoveObjectSetAction(Object *object, void *refcon) { + object->extParam = NULL; +} + +CW_INLINE void EP_sub_48C850(ExtendedParam *ep, ObjectSet *objSet) { + IRO_ASSERT(888, ep != NULL); + IRO_ASSERT(889, ep->objectSet != NULL); + IRO_ASSERT(890, objSet != NULL); + + ObjectSet_removeiter_sub_48C890(ep->objectSet, objSet); + ObjectSet_ForEach(objSet, ExtendedParam_RemoveObjectSetAction, NULL); +} + +CW_INLINE ObjectSet *ExtendedParam_objectSet(ExtendedParam *ep) { + IRO_ASSERT(898, ep != NULL); + + return ep->objectSet; +} + +CW_INLINE uint32 ExtendedParam_sub_489110(ExtendedParam *ep) { + IRO_ASSERT(905, ep != NULL); + + return ep->x4; +} + +CW_INLINE ExtendedParamSet *AllocsExtParamSet_sub_4876C0(void) { + ExtendedParamSet *epList = IRO_malloc(sizeof(ExtendedParamSet)); + + IRO_ASSERT(924, epList != NULL); +#ifdef IRO_DEBUG + epList->ep = NULL; + epList->otherEps = NULL; +#endif + return epList; +} + +CW_INLINE void FreesExtParamSet_sub_48CAE0(ExtendedParamSet *epList) { + IRO_ASSERT(936, epList != NULL); + IRO_ASSERT(937, epList->ep == NULL); + IRO_ASSERT(938, epList->otherEps == NULL); + IRO_DEBUG_CLEAR(epList, sizeof(ExtendedParamSet)); + IRO_free(epList); +} + +CW_INLINE void InitsExtParamSet_sub_4876A0(ExtendedParamSet *epList) { + IRO_ASSERT(948, epList != NULL); + epList->ep = NULL; + epList->otherEps = NULL; +} + +CW_INLINE void TermsExtParamSet_sub_48CB00(ExtendedParamSet *epList) { + IRO_ASSERT(966, epList != NULL); + ExtendedParamSet_RemoveAll(epList); +#ifdef IRO_DEBUG + epList->ep = NULL; + epList->otherEps = NULL; +#endif +} + +CW_INLINE void MaybeWalkExtParamSet_sub_48CBE0(ExtendedParamSet *epList, void (*action)(ExtendedParam *, void *), void *refcon) { + IRO_ASSERT(1010, epList != NULL); + IRO_ASSERT(1011, action != NULL); + + while (epList && epList->ep) { + action(epList->ep, refcon); + epList = epList->otherEps; + } +} + +CW_INLINE ExtendedParam *ExtParamSet_sub_4876D0(ExtendedParamSet *epList, ExtendedParam *ep) { + IRO_ASSERT(1022, epList != NULL); + IRO_ASSERT(1023, ep != NULL); + + while (epList && epList->ep) { + if (epList->ep == ep) + return epList->ep; + epList = epList->otherEps; + } + + return NULL; +} + +CW_INLINE void ExtParamSet_sub_487660(ExtendedParamSet *epList, ExtendedParam *ep) { + IRO_ASSERT(1056, epList != NULL); + IRO_ASSERT(1057, ep != NULL); + + if (epList->ep) { + ExtendedParamSet *newSet = AllocsExtParamSet_sub_4876C0(); + InitsExtParamSet_sub_4876A0(newSet); + newSet->ep = epList->ep; + newSet->otherEps = epList->otherEps; + epList->otherEps = newSet; + } + + epList->ep = ep; +} + +CW_INLINE void ExtParamSet_sub_487630(ExtendedParamSet *epList, ExtendedParam *ep) { + IRO_ASSERT(1076, epList != NULL); + IRO_ASSERT(1077, ep != NULL); + + if (!ExtParamSet_sub_4876D0(epList, ep)) + ExtParamSet_sub_487660(epList, ep); +} + +CW_INLINE void ExtendedParamSet_Remove(ExtendedParamSet *epList, ExtendedParam *ep) { + ExtendedParamSet *prev; + ExtendedParamSet *tmp; + + IRO_ASSERT(1089, epList != NULL); + IRO_ASSERT(1090, ep != NULL); + + prev = NULL; + while (epList && epList->ep) { + if (epList->ep == ep) { + if (!prev) { + if (epList->otherEps == NULL) { + epList->ep = NULL; + } else { + tmp = epList->otherEps; + epList->ep = epList->otherEps->ep; + epList->otherEps = epList->otherEps->otherEps; + tmp->ep = NULL; + tmp->otherEps = NULL; + TermsExtParamSet_sub_48CB00(tmp); + FreesExtParamSet_sub_48CAE0(tmp); + } + } else { + prev->otherEps = epList->otherEps; + epList->ep = NULL; + epList->otherEps = NULL; + TermsExtParamSet_sub_48CB00(epList); + FreesExtParamSet_sub_48CAE0(epList); + } + return; + } + prev = epList; + epList = epList->otherEps; + } +} + +CW_INLINE void ExtendedParamSet_RemoveAll(ExtendedParamSet *epList) { + IRO_ASSERT(1129, epList != NULL); + + while (epList && epList->ep) + ExtendedParamSet_Remove(epList, epList->ep); +} + +CW_INLINE PAHeapBlock *CreateUniqueHeapAlloc_sub_486420(void) { + PAHeapBlock *hb = IRO_malloc(sizeof(PAHeapBlock)); + + IRO_ASSERT(1225, hb != NULL); +#ifdef IRO_DEBUG + hb->parent = NULL; +#endif + return hb; +} + +CW_INLINE void InitUniqueHeapAlloc_sub_486410(PAHeapBlock *hb, IROLinear *nd) { + IRO_ASSERT(1247, hb != NULL); + + hb->x0 = nd; +} + +CW_INLINE Boolean PAHeapBlocks_Equal(PAHeapBlock *hb1, PAHeapBlock *hb2) { + IRO_ASSERT(1296, hb1 != NULL); + IRO_ASSERT(1297, hb2 != NULL); + + return (hb1 == hb2) || (hb1->x0 == hb2->x0); +} + +CW_INLINE PALocalVar *PALocalVar_New(void) { + PALocalVar *local = IRO_malloc(sizeof(PALocalVar)); + + IRO_ASSERT(1333, local != NULL); +#ifdef IRO_DEBUG + local->parent = NULL; + local->nextSibling = NULL; +#endif + return local; +} + +CW_INLINE void PALocalVar_InitByObject(PALocalVar *local, Object *obj) { + IRO_ASSERT(1357, local != NULL); + IRO_ASSERT(1358, obj != NULL); + + local->x0 = obj; + if (obj->name && obj->name->name) { + local->x4 = IRO_malloc(strlen(obj->name->name) + 1); + strcpy(local->x4, obj->name->name); + } else { + local->x4 = NULL; + } +} + +CW_INLINE void PALocalVar_InitByName(PALocalVar *local, char *name) { + IRO_ASSERT(1372, local != NULL); + IRO_ASSERT(1373, name != NULL); + + local->x0 = NULL; + local->x4 = IRO_malloc(strlen(name) + 1); + strcpy(local->x4, name); +} + +CW_INLINE Boolean PALocalVars_Equal(PALocalVar *local1, PALocalVar *local2) { + IRO_ASSERT(1419, local1 == NULL || local1 != NULL); + IRO_ASSERT(1420, local2 == NULL || local2 != NULL); + + if (local1 == local2) + return 1; + if (!local1 || !local2) + return 0; + + if (!local1->x0 || !local2->x0) { + if (local1->x4) + return local2->x4 && !strcmp(local1->x4, local2->x4); + } + + return local1->x0 == local2->x0; +} + +CW_INLINE void PALocalVar_SetSth_sub_4847C0(PALocalVar *local, Object *obj) { + IRO_ASSERT(1436, local != NULL); + IRO_ASSERT(1437, obj == NULL || obj != NULL); + + local->x0 = obj; +} + +CW_INLINE Object *PALocalVar_Get0_sub_4847E0(PALocalVar *local) { + IRO_ASSERT(1444, local != NULL); + return local->x0; +} + +CW_INLINE char *PALocalVar_Get4_sub_4847D0(PALocalVar *local) { + IRO_ASSERT(1451, local != NULL); + return local->x4; +} + +CW_INLINE PAMemoryBlock *PAMemoryBlock_New(void) { + PAMemoryBlock *mb = IRO_malloc(sizeof(PAMemoryBlock)); + + IRO_ASSERT(1491, mb != NULL); +#ifdef IRO_DEBUG + mb->kind = PAMEMORYBLOCKKIND_INVALID; +#endif + return mb; +} + +CW_INLINE void PAMemoryBlock_Delete(PAMemoryBlock *mb) { + IRO_ASSERT(1502, mb != NULL); + IRO_ASSERT(1503, mb->kind == PAMEMORYBLOCKKIND_INVALID); + IRO_free(mb); +} + +CW_INLINE void PAMemoryBlock_Init(PAMemoryBlock *mb, PAMemoryBlockKind kind, void *thing) { + IRO_ASSERT(1513, mb != NULL); + IRO_ASSERT(1514, thing == NULL || thing != NULL); + + mb->kind = kind; + switch (mb->kind) { + case PAMEMORYBLOCKKIND_EXTENDEDPARAM: + mb->u.ep = (ExtendedParam *) thing; + break; + case PAMEMORYBLOCKKIND_LOCALVAR: + mb->u.localvar = (PALocalVar *) thing; + break; + case PAMEMORYBLOCKKIND_HEAPBLOCK: + mb->u.heapblock = (PAHeapBlock *) thing; + break; + case PAMEMORYBLOCKKIND_INT: + mb->u.intval = *((CInt64 *) thing); + break; + case PAMEMORYBLOCKKIND_6: + mb->u.x6 = (void *) thing; + break; + default: + CError_FATAL(1535); + } +} + +CW_INLINE void PAMemoryBlock_Term(PAMemoryBlock *mb) { + IRO_ASSERT(1552, mb != NULL); + +#ifdef IRO_DEBUG + mb->kind = PAMEMORYBLOCKKIND_INVALID; +#endif +} + +CW_INLINE Boolean MemoryBlocks_Equal(PAMemoryBlock *mb1, PAMemoryBlock *mb2) { + IRO_ASSERT(1657, mb1 == NULL || mb1 != NULL); + IRO_ASSERT(1658, mb2 == NULL || mb2 != NULL); + + if (mb1 == mb2) + return 1; + + if (!mb1 || !mb2 || mb1->kind != mb2->kind) + return 0; + + switch (mb1->kind) { + case PAMEMORYBLOCKKIND_EXTENDEDPARAM: + return ExtendedParams_Equal(mb1->u.ep, mb2->u.ep); + case PAMEMORYBLOCKKIND_LOCALVAR: + return PALocalVars_Equal(mb1->u.localvar, mb2->u.localvar); + case PAMEMORYBLOCKKIND_HEAPBLOCK: + return PAHeapBlocks_Equal(mb1->u.heapblock, mb2->u.heapblock); + case PAMEMORYBLOCKKIND_INT: + return CInt64_Equal(mb1->u.intval, mb2->u.intval); + case PAMEMORYBLOCKKIND_6: + return mb1->u.x6 == mb2->u.x6; + default: + CError_FATAL(1684); + return 0; + } +} + +CW_INLINE PAMemoryBlockKind PAMemoryBlock_kind(PAMemoryBlock *mb) { + IRO_ASSERT(1692, mb != NULL); + + return mb->kind; +} + +CW_INLINE void *PAMemoryBlock_thing(PAMemoryBlock *mb) { + IRO_ASSERT(1699, mb != NULL); + + switch (mb->kind) { + case PAMEMORYBLOCKKIND_EXTENDEDPARAM: + return mb->u.ep; + case PAMEMORYBLOCKKIND_LOCALVAR: + return mb->u.localvar; + case PAMEMORYBLOCKKIND_HEAPBLOCK: + return mb->u.heapblock; + case PAMEMORYBLOCKKIND_INT: + return &mb->u.intval; + case PAMEMORYBLOCKKIND_6: + return mb->u.x6; + default: + CError_FATAL(1719); + return NULL; + } +} + +CW_INLINE LocationSet *LocationSet_New(void) { + LocationSet *ls = IRO_malloc(sizeof(LocationSet)); + + IRO_ASSERT(1767, ls != NULL); +#ifdef IRO_DEBUG + ls->block = NULL; + ls->rtype = NULL; + ls->u.known.field = cint64_zero; + ls->u.known.stride = 0; +#endif + return ls; +} + +CW_INLINE void LocationSet_Delete(LocationSet *ls) { + IRO_ASSERT(1781, ls != NULL); + IRO_ASSERT(1782, ls != stUnknownLs); + IRO_ASSERT(1783, ls->block == NULL); + IRO_ASSERT(1784, CInt64_IsZero(&ls->u.known.field)); + IRO_ASSERT(1785, ls->u.known.stride == 0); + IRO_ASSERT(1786, ls->rtype == NULL); + IRO_DEBUG_CLEAR(ls, sizeof(LocationSet)); + IRO_free(ls); +} + +CW_INLINE void LocationSet_InitKnown(LocationSet *ls, PAMemoryBlock *block, CInt64 field, UInt32 stride, Type *rtype) { + IRO_ASSERT(1796, ls != NULL); + IRO_ASSERT(1797, ls != stUnknownLs); + IRO_ASSERT(1798, block != NULL); + IRO_ASSERT(1799, rtype == NULL || rtype != NULL); + ls->block = block; + ls->rtype = rtype; + ls->u.known.field = field; + ls->u.known.stride = stride; +} + +CW_INLINE void LocationSet_InitUnknown(LocationSet *ls, Type *rtype, PAMemoryBlock *restriction, LocationSet *bitfieldOf) { + IRO_ASSERT(1809, ls != NULL); + IRO_ASSERT(1810, ls != stUnknownLs); + IRO_ASSERT(1811, rtype == NULL || rtype != NULL); + IRO_ASSERT(1812, restriction == NULL || restriction != NULL); + IRO_ASSERT(1813, bitfieldOf == NULL || bitfieldOf != NULL); + + LocationSet_Copy(ls, stUnknownLs); + ls->rtype = rtype; + ls->u.unknown.restriction = restriction; + if (bitfieldOf) { + ls->u.unknown.bitfieldOf = LocationSet_New(); + LocationSet_Copy(ls->u.unknown.bitfieldOf, bitfieldOf); + } else { + ls->u.unknown.bitfieldOf = NULL; + } +} + +CW_INLINE void LocationSet_Copy(LocationSet *dest, LocationSet *src) { + IRO_ASSERT(1829, src != NULL); + IRO_ASSERT(1830, dest != NULL); + + dest->block = src->block; + dest->rtype = src->rtype; + + if (!LocationSet_IsUnknown(src)) { + dest->u.known.field = src->u.known.field; + dest->u.known.stride = src->u.known.stride; + } else { + dest->u.unknown.restriction = src->u.unknown.restriction; + if (src->u.unknown.bitfieldOf != NULL) { + dest->u.unknown.bitfieldOf = LocationSet_New(); + LocationSet_Copy(dest->u.unknown.bitfieldOf, src->u.unknown.bitfieldOf); + } else { + dest->u.unknown.bitfieldOf = NULL; + } + } +} + +CW_INLINE void LocationSet_Term(LocationSet *ls) { + IRO_ASSERT(1857, ls != NULL); + IRO_ASSERT(1858, ls != stUnknownLs); + +#ifdef IRO_DEBUG + if (LocationSet_IsUnknown(ls) && ls->u.unknown.bitfieldOf) { + LocationSet_Term(ls->u.unknown.bitfieldOf); + LocationSet_Delete(ls->u.unknown.bitfieldOf); + } + ls->block = NULL; + ls->rtype = NULL; + ls->u.known.field = cint64_zero; + ls->u.known.stride = 0; +#endif +} + +CW_INLINE Boolean LocationSets_Overlap(LocationSet *ls1, Type *rtype1, LocationSet *ls2, Type *rtype2) { + Boolean isUnknown1, isUnknown2; + PAMemoryBlock *restriction1, *restriction2; + + IRO_ASSERT(1974, ls1 != NULL); + IRO_ASSERT(1975, rtype1 == NULL || rtype1 != NULL); + IRO_ASSERT(1976, ls2 != NULL); + IRO_ASSERT(1977, rtype2 == NULL || rtype2 != NULL); + + if (ls1 == ls2) + return 1; + + isUnknown1 = LocationSet_IsUnknown(ls1); + if (isUnknown1) + restriction1 = ls1->u.unknown.restriction; + else + restriction1 = NULL; + + isUnknown2 = LocationSet_IsUnknown(ls2); + if (isUnknown2) + restriction2 = ls2->u.unknown.restriction; + else + restriction2 = NULL; + + if ( + (isUnknown1 && !restriction1) || + (isUnknown2 && !restriction2) || + (isUnknown1 && isUnknown2 && MemoryBlocks_Equal(restriction1, restriction2)) + ) + return 1; + + if (isUnknown1 || isUnknown2) + return 0; + + if (MemoryBlocks_Equal(ls1->block, ls2->block)) { + UInt32 size1; + UInt32 size2; + UInt32 i; + CInt64 work; + CInt64 longgcd; + + if (rtype1) + size1 = rtype1->size; + else + size1 = -1; + + if (rtype2) + size2 = rtype2->size; + else + size2 = -1; + + if (ls1->u.known.stride == ls2->u.known.stride) { + CInt64 longsize1; + CInt64 longsize2; + CInt64_SetULong(&longsize1, size1); + CInt64_SetULong(&longsize2, size2); + + return CInt64_Equal(ls1->u.known.field, ls2->u.known.field) || + (CInt64_Less(ls1->u.known.field, ls2->u.known.field) && CInt64_Greater(CInt64_Add(ls1->u.known.field, longsize1), ls2->u.known.field)) || + (CInt64_Less(ls2->u.known.field, ls1->u.known.field) && CInt64_Greater(CInt64_Add(ls2->u.known.field, longsize2), ls1->u.known.field)); + } else { + work = CInt64_Sub(ls1->u.known.field, ls2->u.known.field); + if (CInt64_IsNegative(&work)) + work = CInt64_Neg(work); + + CInt64_SetULong(&longgcd, gcd(ls1->u.known.stride, ls2->u.known.stride)); + if (CInt64_Equal(CInt64_ModU(work, longgcd), cint64_zero)) + return 1; + + if (size1 == -1) + return 1; + + for (i = 1; i < size1; i++) { + CInt64_SetLong(&work, i); + work = CInt64_Add(work, ls1->u.known.field); + work = CInt64_Sub(work, ls2->u.known.field); + if (CInt64_IsNegative(&work)) + work = CInt64_Neg(work); + if (CInt64_Equal(CInt64_ModU(work, longgcd), cint64_zero)) + return 1; + } + + if (size2 == -1) + return 1; + + for (i = 1; i < size2; i++) { + CInt64_SetLong(&work, i); + work = CInt64_Add(work, ls2->u.known.field); + work = CInt64_Sub(work, ls1->u.known.field); + if (CInt64_IsNegative(&work)) + work = CInt64_Neg(work); + if (CInt64_Equal(CInt64_ModU(work, longgcd), cint64_zero)) + return 1; + } + + return 0; + } + } + + return 0; +} + +CW_INLINE Boolean LocationSets_Equal(LocationSet *ls1, LocationSet *ls2) { + IRO_ASSERT(2080, ls1 != NULL); + IRO_ASSERT(2081, ls2 != NULL); + + return + (ls1 == ls2) || + ( + (LocationSet_IsUnknown(ls1) && LocationSet_IsUnknown(ls2)) && + (MemoryBlocks_Equal(ls1->u.unknown.restriction, ls2->u.unknown.restriction)) && + ((ls1->u.unknown.bitfieldOf == ls2->u.unknown.bitfieldOf) || + (ls1->u.unknown.bitfieldOf && ls2->u.unknown.bitfieldOf && LocationSets_Equal(ls1->u.unknown.bitfieldOf, ls2->u.unknown.bitfieldOf))) && + ((ls1->rtype == ls2->rtype) || (ls1->rtype && ls2->rtype && ls1->rtype->size == ls2->rtype->size)) + ) || + ( + (!LocationSet_IsUnknown(ls1) && !LocationSet_IsUnknown(ls2)) && + (ls1->u.known.stride == ls2->u.known.stride) && + ((ls1->rtype == ls2->rtype) || (ls1->rtype && ls2->rtype && ls1->rtype->size == ls2->rtype->size)) && + CInt64_Equal(ls1->u.known.field, ls2->u.known.field) && + MemoryBlocks_Equal(ls1->block, ls2->block) + ); +} + +CW_INLINE Boolean LocationSets_LookupCompatible(LocationSet *ls1, LocationSet *ls2) { + IRO_ASSERT(2119, ls1 != NULL); + IRO_ASSERT(2120, ls2 != NULL); + + if ( + (ls1 == ls2) || + ( + LocationSet_IsUnknown(ls1) && + LocationSet_IsUnknown(ls2) && + MemoryBlocks_Equal(ls1->u.unknown.restriction, ls2->u.unknown.restriction) && + (ls1->rtype == ls2->rtype || (ls1->rtype && ls2->rtype && ls1->rtype->size == ls2->rtype->size)) + )) + return 1; + + if ( + (!LocationSet_IsUnknown(ls1) && !LocationSet_IsUnknown(ls2)) && + (ls1->rtype == ls2->rtype || (ls1->rtype && ls2->rtype && ls1->rtype->size == ls2->rtype->size)) && + MemoryBlocks_Equal(ls1->block, ls2->block) + ) { + CInt64 work; + CInt64 longgcd; + + if (ls1->u.known.stride == ls2->u.known.stride) + return CInt64_Equal(ls1->u.known.field, ls2->u.known.field); + + work = CInt64_Sub(ls1->u.known.field, ls2->u.known.field); + if (CInt64_IsNegative(&work)) + work = CInt64_Neg(work); + + CInt64_SetULong(&longgcd, gcd(ls1->u.known.stride, ls2->u.known.stride)); + return CInt64_Equal(CInt64_ModU(work, longgcd), cint64_zero); + } + + return 0; +} + +CW_INLINE Boolean LocationSet_Contains(LocationSet *ls1, Type *rtype1, LocationSet *ls2, Type *rtype2) { + Boolean unknown1; + Boolean unknown2; + PAMemoryBlock *restriction2; + PAMemoryBlock *restriction1; + CInt64 longsize1; + CInt64 longsize2; + + IRO_ASSERT(2168, ls1 != NULL); + IRO_ASSERT(2169, ls2 != NULL); + IRO_ASSERT(2170, rtype1 != NULL); + IRO_ASSERT(2171, rtype2 != NULL); + + if (ls1 == ls2) + return 1; + + unknown1 = LocationSet_IsUnknown(ls1); + if (unknown1) + restriction1 = ls1->u.unknown.restriction; + else + restriction1 = NULL; + + unknown2 = LocationSet_IsUnknown(ls2); + if (unknown2) + restriction2 = ls2->u.unknown.restriction; + else + restriction2 = NULL; + + if (unknown1) + return !restriction1 || (unknown2 && MemoryBlocks_Equal(restriction2, restriction1)); + + CInt64_SetULong(&longsize1, rtype1->size); + CInt64_SetULong(&longsize2, rtype2->size); + + return + !LocationSet_IsUnknown(ls2) && + (ls1->u.known.stride == 0) && + (ls2->u.known.stride == 0) && + rtype1->size >= rtype2->size && + CInt64_LessEqual(ls1->u.known.field, ls2->u.known.field) && + CInt64_GreaterEqual(CInt64_Add(ls1->u.known.field, longsize1), CInt64_Add(ls2->u.known.field, longsize2)) && + MemoryBlocks_Equal(ls1->block, ls2->block); +} + +CW_INLINE Boolean LocationSet_IsUnknown(LocationSet *ls) { + IRO_ASSERT(2233, ls != NULL); + + return (ls == stUnknownLs) || (ls->block == stUnknownMb); +} + +CW_INLINE Boolean LocationSet_sub_48AF30(LocationSet *ls) { + return + !LocationSet_IsUnknown(ls) && + (ls->u.known.stride == 0) && + CInt64_IsZero(&ls->u.known.field) && + PAMemoryBlock_kind(ls->block) == PAMEMORYBLOCKKIND_LOCALVAR && + !PAMemoryBlock_thing(ls->block); +} + +CW_INLINE void LocationSet_SetRtype(LocationSet *ls, Type *rtype) { + IRO_ASSERT(2263, ls != NULL); + IRO_ASSERT(2264, ls != stUnknownLs); + IRO_ASSERT(2265, rtype != NULL); + + ls->rtype = rtype; +} + +CW_INLINE void SetsLocationSetField_sub_4851B0(LocationSet *ls, CInt64 field) { + IRO_ASSERT(2272, ls != NULL); + IRO_ASSERT(2273, !LocationSet_IsUnknown(ls)); + + ls->u.known.field = field; +} + +CW_INLINE void SetsLocationSetStride_sub_4852D0(LocationSet *ls, SInt32 stride) { + IRO_ASSERT(2280, ls != NULL); + IRO_ASSERT(2281, !LocationSet_IsUnknown(ls)); + + ls->u.known.stride = stride; +} + +CW_INLINE PAMemoryBlock *LocationSet_block(LocationSet *ls) { + IRO_ASSERT(2298, ls != NULL); + + return ls->block; +} + +CW_INLINE Type *LocationSet_rtype(LocationSet *ls) { + IRO_ASSERT(2306, ls != NULL); + IRO_ASSERT(2307, ls != stUnknownLs); + + return ls->rtype; +} + +CW_INLINE CInt64 LocationSet_field(LocationSet *ls) { + IRO_ASSERT(2314, ls != NULL); + IRO_ASSERT(2315, !LocationSet_IsUnknown(ls)); + + return ls->u.known.field; +} + +CW_INLINE UInt32 LocationSet_stride(LocationSet *ls) { + IRO_ASSERT(2322, ls != NULL); + IRO_ASSERT(2323, !LocationSet_IsUnknown(ls)); + + return ls->u.known.stride; +} + +CW_INLINE PAMemoryBlock *LocationSet_restriction(LocationSet *ls) { + IRO_ASSERT(2330, ls != NULL); + IRO_ASSERT(2331, LocationSet_IsUnknown(ls)); + + return ls->u.unknown.restriction; +} + +CW_INLINE LocationSet *LocationSet_bitfieldOf(LocationSet *ls) { + IRO_ASSERT(2338, ls != NULL); + IRO_ASSERT(2339, LocationSet_IsUnknown(ls)); + + return ls->u.unknown.bitfieldOf; +} + +CW_INLINE LocationSetSet *LocationSetSet_New(void) { + LocationSetSet *lss = IRO_malloc(sizeof(LocationSetSet)); + + IRO_ASSERT(2356, lss != NULL); +#ifdef IRO_DEBUG + lss->loc = NULL; + lss->otherLocs = NULL; + lss->count = 0; +#endif + return lss; +} + +CW_INLINE void LocationSetSet_Delete(LocationSetSet *lss) { + IRO_ASSERT(2369, lss != NULL); + IRO_ASSERT(2370, lss->loc == NULL); + IRO_ASSERT(2371, lss->otherLocs == NULL); + IRO_ASSERT(2372, lss->count == 0); + IRO_DEBUG_CLEAR(lss, sizeof(LocationSetSet)); + IRO_free(lss); +} + +CW_INLINE void LocationSetSet_Init(LocationSetSet *lss) { + IRO_ASSERT(2382, lss != NULL); + + lss->loc = NULL; + lss->otherLocs = NULL; + lss->count = 0; +} + +CW_INLINE void LocationSetSet_Copy(LocationSetSet *dest, LocationSetSet *src) { + IRO_ASSERT(2391, dest != NULL); + IRO_ASSERT(2392, src != NULL); + + dest->loc = NULL; + dest->otherLocs = NULL; + dest->count = 0; + LocationSetSet_AddSet(dest, src); +} + +CW_INLINE void LocationSetSet_Term(LocationSetSet *lss) { + IRO_ASSERT(2402, lss != NULL); + + LocationSetSet_RemoveAll(lss); + +#ifdef IRO_DEBUG + lss->loc = NULL; + lss->otherLocs = NULL; + lss->count = 0; +#endif +} + +CW_INLINE void LocationSetSet_ForEach(LocationSetSet *lss, void (*action)(LocationSet *, void *), void *refcon) { + IRO_ASSERT(2446, lss != NULL); + IRO_ASSERT(2447, action != NULL); + IRO_ASSERT(2448, refcon == NULL || refcon != NULL); + + while (lss && lss->loc) { + action(lss->loc, refcon); + lss = lss->otherLocs; + } +} + +CW_INLINE LocationSet *LocationSetSet_Find(LocationSetSet *lss, LocationSet *ls) { + IRO_ASSERT(2458, lss != NULL); + IRO_ASSERT(2459, ls != NULL); + + while (lss && lss->loc) { + if (LocationSets_Equal(lss->loc, ls)) + return lss->loc; + lss = lss->otherLocs; + } + + return NULL; +} + +CW_INLINE LocationSet *LocationSetSet_FindUnknown(LocationSetSet *lss) { + IRO_ASSERT(2470, lss != NULL); + + if (!lss->loc) + return stUnknownLs; + + while (lss && lss->loc) { + if (LocationSet_IsUnknown(lss->loc)) + return lss->loc; + lss = lss->otherLocs; + } + + return NULL; +} + +CW_INLINE LocationSet *LocationSetSet_FindFirst(LocationSetSet *lss) { + IRO_ASSERT(2498, lss != NULL); + + return lss->loc; +} + +CW_INLINE int LocationSetSet_Count(LocationSetSet *lss) { + IRO_ASSERT(2505, lss != NULL); + + return lss->count; +} + +CW_INLINE void LocationSetSet_RemoveAllWithMemoryBlock(LocationSetSet *lss, PAMemoryBlock *block) { + LocationSetSet *first; + LocationSetSet *prev; + LocationSetSet *next; + LocationSetSet *tmp; + + IRO_ASSERT(2514, lss != NULL); + IRO_ASSERT(2515, block != NULL); + + first = lss; + prev = NULL; + while (lss && lss->loc) { + next = lss->otherLocs; + if (MemoryBlocks_Equal(block, lss->loc->block)) { + if (lss->loc != stUnknownLs) { + LocationSet_Term(lss->loc); + LocationSet_Delete(lss->loc); + } + if (!prev) { + if (lss->otherLocs == NULL) { + lss->loc = NULL; + prev = lss; + } else { + tmp = lss->otherLocs; + lss->loc = lss->otherLocs->loc; + lss->otherLocs = lss->otherLocs->otherLocs; + tmp->loc = NULL; + tmp->otherLocs = NULL; + LocationSetSet_Term(tmp); + LocationSetSet_Delete(tmp); + prev = NULL; + next = lss; + } + } else { + prev->otherLocs = lss->otherLocs; + lss->loc = NULL; + lss->otherLocs = NULL; + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + prev = lss; + } + first->count--; + } + lss = next; + } +} + +CW_INLINE void LocationSetSet_SimpleAdd(LocationSetSet *lss, LocationSet *ls) { + IRO_ASSERT(2572, lss != NULL); + IRO_ASSERT(2573, ls != NULL); + + if (!LocationSet_IsUnknown(ls) && lss->count < 4) { + LocationSet *ls2; + + if (ls == stUnknownLs) { + ls2 = stUnknownLs; + } else { + ls2 = LocationSet_New(); + LocationSet_Copy(ls2, ls); + } + + if (lss->loc) { + LocationSetSet *lss2 = LocationSetSet_New(); + LocationSetSet_Init(lss2); + lss2->loc = lss->loc; + lss2->otherLocs = lss->otherLocs; + lss->otherLocs = lss2; + } + + lss->loc = ls2; + lss->count++; + } else { + LocationSet *ls2; + + LocationSetSet_RemoveAll(lss); + ls2 = LocationSet_New(); + if (LocationSet_IsUnknown(ls)) { + LocationSet_Copy(ls2, ls); + } else { + LocationSet_Copy(ls2, stUnknownLs); + if (ls->rtype) + LocationSet_SetRtype(ls2, ls->rtype); + } + + lss->loc = ls2; + lss->count = 1; + } +} + +CW_INLINE void LocationSetSet_Add(LocationSetSet *lss, LocationSet *ls) { + IRO_ASSERT(2622, lss != NULL); + IRO_ASSERT(2623, ls != NULL); + + if (!lss->loc || (!LocationSet_IsUnknown(lss->loc) && !LocationSetSet_Find(lss, ls))) { + if (!LocationSet_IsUnknown(ls) && ls->u.known.stride) + LocationSetSet_RemoveAllWithMemoryBlock(lss, ls->block); + LocationSetSet_SimpleAdd(lss, ls); + } +} + +CW_INLINE void LocationSetSet_AddUnknown(LocationSetSet *lss, Type *rtype, PAMemoryBlock *restriction, LocationSet *bitfieldOf) { + LocationSet *ls; + + IRO_ASSERT(2643, lss != NULL); + IRO_ASSERT(2644, rtype == NULL || rtype != NULL); + IRO_ASSERT(2645, restriction == NULL || restriction != NULL); + IRO_ASSERT(2646, bitfieldOf == NULL || bitfieldOf != NULL); + + ls = LocationSet_New(); + LocationSet_InitUnknown(ls, rtype, restriction, bitfieldOf); + LocationSetSet_Add(lss, ls); + LocationSet_Term(ls); + LocationSet_Delete(ls); +} + +CW_INLINE void LocationSetSet_Remove(LocationSetSet *lss, LocationSet *ls) { + LocationSetSet *prev; + LocationSetSet *first; + LocationSetSet *tmp; + + IRO_ASSERT(2659, lss != NULL); + IRO_ASSERT(2660, ls != NULL); + + first = lss; + prev = NULL; + while (lss && lss->loc) { + if (LocationSets_Equal(lss->loc, ls)) { + if (lss->loc != stUnknownLs) { + LocationSet_Term(lss->loc); + LocationSet_Delete(lss->loc); + } + if (!prev) { + if (lss->otherLocs == NULL) { + lss->loc = NULL; + } else { + tmp = lss->otherLocs; + lss->loc = lss->otherLocs->loc; + lss->otherLocs = lss->otherLocs->otherLocs; + tmp->loc = NULL; + tmp->otherLocs = NULL; + LocationSetSet_Term(tmp); + LocationSetSet_Delete(tmp); + } + } else { + prev->otherLocs = lss->otherLocs; + lss->loc = NULL; + lss->otherLocs = NULL; + LocationSetSet_Term(lss); + LocationSetSet_Delete(lss); + } + first->count--; + return; + } + + prev = lss; + lss = lss->otherLocs; + } +} + +CW_INLINE void LocationSetSet_RemoveAll(LocationSetSet *lss) { + IRO_ASSERT(2707, lss != NULL); + + while (lss && lss->loc) + LocationSetSet_Remove(lss, lss->loc); +} + +CW_INLINE void LocationSetSet_AddSetAction(LocationSet *ls, void *refcon) { + IRO_ASSERT(2717, ls != NULL); + IRO_ASSERT(2718, refcon != NULL); + + LocationSetSet_Add((LocationSetSet *) refcon, ls); +} + +CW_INLINE void LocationSetSet_SimpleAddSetAction(LocationSet *ls, void *refcon) { + IRO_ASSERT(2725, ls != NULL); + IRO_ASSERT(2726, refcon != NULL); + + LocationSetSet_SimpleAdd((LocationSetSet *) refcon, ls); +} + +CW_INLINE void LocationSetSet_AddSet(LocationSetSet *dest, LocationSetSet *src) { + IRO_ASSERT(2733, dest != NULL); + IRO_ASSERT(2734, src != NULL); + + if (dest->count) + LocationSetSet_ForEach(src, LocationSetSet_AddSetAction, dest); + else + LocationSetSet_ForEach(src, LocationSetSet_SimpleAddSetAction, dest); +} + +CW_INLINE void LocationSetSet_RemoveSetAction(LocationSet *ls, void *refcon) { + IRO_ASSERT(2744, ls != NULL); + IRO_ASSERT(2745, refcon != NULL); + + LocationSetSet_Remove((LocationSetSet *) refcon, ls); +} + +CW_INLINE void LocationSetSet_sub_488700(LocationSetSet *dest, LocationSetSet *src) { + IRO_ASSERT(2752, dest != NULL); + IRO_ASSERT(2753, src != NULL); + + LocationSetSet_ForEach(src, LocationSetSet_RemoveSetAction, dest); +} + +CW_INLINE Boolean LocationSetSets_Equal(LocationSetSet *lss1, LocationSetSet *lss2) { + IRO_ASSERT(2826, lss1 != NULL); + IRO_ASSERT(2827, lss2 != NULL); + + if (lss1 == lss2) + return 1; + if (LocationSetSet_Count(lss1) != LocationSetSet_Count(lss2)) + return 0; + + while (lss1 && lss1->loc) { + if (!LocationSetSet_Find(lss2, lss1->loc)) + return 0; + lss1 = lss1->otherLocs; + } + + return 1; +} + +CW_INLINE ParamMapping *ParamMapping_New(void) { + ParamMapping *pm = IRO_malloc(sizeof(ParamMapping)); + + IRO_ASSERT(2885, pm != NULL); +#ifdef IRO_DEBUG + pm->actual = NULL; + pm->formal = NULL; + pm->extended = NULL; +#endif + return pm; +} + +CW_INLINE void ParamMapping_Delete(ParamMapping *pm) { + IRO_ASSERT(2898, pm != NULL); + IRO_ASSERT(2899, pm->actual == NULL); + IRO_ASSERT(2900, pm->formal == NULL); + IRO_ASSERT(2901, pm->extended == NULL); + IRO_DEBUG_CLEAR(pm, sizeof(ParamMapping)); + IRO_free(pm); +} + +CW_INLINE void ParamMapping_Init_PROBABLY(ParamMapping *pm, IROLinear *actual, Object *formal, ExtendedParam *extended) { + IRO_ASSERT(2911, pm != NULL); + + pm->actual = actual; + pm->formal = formal; + pm->extended = extended; +} + +CW_INLINE void ParamMapping_Copy(ParamMapping *dest, ParamMapping *src) { + IRO_ASSERT(2920, src != NULL); + IRO_ASSERT(2921, dest != NULL); + + dest->actual = src->actual; + dest->formal = src->formal; + dest->extended = src->extended; +} + +CW_INLINE void ParamMapping_Term(ParamMapping *pm) { + IRO_ASSERT(2933, pm != NULL); + +#ifdef IRO_DEBUG + pm->actual = NULL; + pm->formal = NULL; + pm->extended = NULL; +#endif +} + +CW_INLINE void ParamMapping_SetExtended(ParamMapping *pm, ExtendedParam *ep) { + IRO_ASSERT(2992, pm != NULL); + + pm->extended = ep; +} + +CW_INLINE IROLinear *ParamMapping_actual(ParamMapping *pm) { + IRO_ASSERT(2999, pm != NULL); + + return pm->actual; +} + +CW_INLINE ExtendedParam *ParamMapping_extended(ParamMapping *pm) { + IRO_ASSERT(3011, pm != NULL); + + return pm->extended; +} + +CW_INLINE ParamMappingFunction *ParamMappingFunction_New(void) { + ParamMappingFunction *pmf = IRO_malloc(sizeof(ParamMappingFunction)); + + IRO_ASSERT(3026, pmf != NULL); +#ifdef IRO_DEBUG + pmf->mapping = NULL; + pmf->otherMappings = NULL; +#endif + return pmf; +} + +CW_INLINE void ParamMappingFunction_Delete(ParamMappingFunction *pmf) { + IRO_ASSERT(3039, pmf != NULL); + IRO_ASSERT(3040, pmf->mapping == NULL); + IRO_ASSERT(3041, pmf->otherMappings == NULL); + IRO_DEBUG_CLEAR(pmf, sizeof(ParamMappingFunction)); + IRO_free(pmf); +} + +CW_INLINE void ParamMappingFunction_Init(ParamMappingFunction *pmf) { + IRO_ASSERT(3050, pmf != NULL); + + pmf->mapping = NULL; + pmf->otherMappings = NULL; +} + +CW_INLINE void ParamMappingFunction_Copy(ParamMappingFunction *dest, ParamMappingFunction *src) { + IRO_ASSERT(3058, src != NULL); + IRO_ASSERT(3059, dest != NULL); + + dest->mapping = NULL; + dest->otherMappings = NULL; + ParamMappingFunction_AddAllMaybe_sub_487C50(dest, src); +} + +CW_INLINE void ParamMappingFunction_Term(ParamMappingFunction *pmf) { + IRO_ASSERT(3068, pmf != NULL); + + ParamMappingFunction_RemoveAll(pmf); + +#ifdef IRO_DEBUG + pmf->mapping = NULL; + pmf->otherMappings = NULL; +#endif +} + +CW_INLINE void pmf_sub_487C70(ParamMappingFunction *pmf, void (*action)(ParamMapping *, void *), void *refcon) { + IRO_ASSERT(3111, pmf != NULL); + IRO_ASSERT(3112, action != NULL); + IRO_ASSERT(3113, refcon == NULL || refcon != NULL); + + while (pmf && pmf->mapping) { + action(pmf->mapping, refcon); + pmf = pmf->otherMappings; + } +} + +CW_INLINE ParamMapping *ParamMappingFunction_FindMappingByFormal(ParamMappingFunction *pmf, Object *formal) { + IRO_ASSERT(3123, pmf != NULL); + IRO_ASSERT(3124, formal != NULL); + + while (pmf && pmf->mapping) { + if (pmf->mapping->formal == formal) + return pmf->mapping; + pmf = pmf->otherMappings; + } + + return NULL; +} + +CW_INLINE void Pmf_Add_sub_486610(ParamMappingFunction *pmf, ParamMapping *mapping) { + ParamMapping *existing; + + IRO_ASSERT(3138, pmf != NULL); + IRO_ASSERT(3139, mapping != NULL); + + existing = ParamMappingFunction_FindMappingByFormal(pmf, mapping->formal); + if (!existing) { + existing = ParamMapping_New(); + ParamMapping_Copy(existing, mapping); + if (pmf->mapping) { + ParamMappingFunction *newPMF = ParamMappingFunction_New(); + ParamMappingFunction_Init(newPMF); + newPMF->mapping = pmf->mapping; + newPMF->otherMappings = pmf->otherMappings; + pmf->otherMappings = newPMF; + } + pmf->mapping = existing; + } else { + existing->actual = mapping->actual; + existing->extended = mapping->extended; + } +} + +CW_INLINE void ParamMappingFunction_Remove(ParamMappingFunction *pmf, ParamMapping *mapping) { + ParamMappingFunction *prev; + ParamMappingFunction *tmp; + + IRO_ASSERT(3170, pmf != NULL); + IRO_ASSERT(3171, mapping != NULL); + + prev = NULL; + while (pmf && pmf->mapping) { + if (pmf->mapping->formal == mapping->formal) { + ParamMapping_Term(pmf->mapping); + ParamMapping_Delete(pmf->mapping); + if (!prev) { + if (pmf->otherMappings == NULL) { + pmf->mapping = NULL; + } else { + tmp = pmf->otherMappings; + pmf->mapping = pmf->otherMappings->mapping; + pmf->otherMappings = pmf->otherMappings->otherMappings; + tmp->mapping = NULL; + tmp->otherMappings = NULL; + ParamMappingFunction_Term(tmp); + ParamMappingFunction_Delete(tmp); + } + } else { + prev->otherMappings = pmf->otherMappings; + pmf->mapping = NULL; + pmf->otherMappings = NULL; + ParamMappingFunction_Term(pmf); + ParamMappingFunction_Delete(pmf); + } + return; + } + + prev = pmf; + pmf = pmf->otherMappings; + } +} + +CW_INLINE void ParamMappingFunction_RemoveAll(ParamMappingFunction *pmf) { + IRO_ASSERT(3213, pmf != NULL); + + while (pmf && pmf->mapping) + ParamMappingFunction_Remove(pmf, pmf->mapping); +} + +CW_INLINE void ParamMappingFunction_AddFunctionAction(ParamMapping *mapping, void *refcon) { + IRO_ASSERT(3223, mapping != NULL); + IRO_ASSERT(3224, refcon != NULL); + + Pmf_Add_sub_486610((ParamMappingFunction *) refcon, mapping); +} + +CW_INLINE void ParamMappingFunction_AddAllMaybe_sub_487C50(ParamMappingFunction *dest, ParamMappingFunction *src) { + IRO_ASSERT(3231, dest != NULL); + IRO_ASSERT(3232, src != NULL); + + pmf_sub_487C70(src, ParamMappingFunction_AddFunctionAction, dest); +} + +CW_INLINE PointsToEntry *PointsToEntry_New(void) { + PointsToEntry *pte = IRO_malloc(sizeof(PointsToEntry)); + + IRO_ASSERT(3288, pte != NULL); +#ifdef IRO_DEBUG + pte->loc = NULL; + pte->locs = NULL; +#endif + return pte; +} + +CW_INLINE void PointsToEntry_Delete(PointsToEntry *pte) { + IRO_ASSERT(3300, pte != NULL); + IRO_ASSERT(3301, pte->loc == NULL); + IRO_ASSERT(3302, pte->locs == NULL); + IRO_DEBUG_CLEAR(pte, sizeof(PointsToEntry)); + IRO_free(pte); +} + +CW_INLINE void PointsToEntry_Init(PointsToEntry *pte, LocationSet *loc, LocationSetSet *locs) { + IRO_ASSERT(3312, pte != NULL); + IRO_ASSERT(3313, loc != NULL); + IRO_ASSERT(3314, !LocationSet_IsUnknown(loc)); + IRO_ASSERT(3315, locs != NULL); + + pte->loc = LocationSet_New(); + LocationSet_Copy(pte->loc, loc); + + pte->locs = LocationSetSet_New(); + LocationSetSet_Copy(pte->locs, locs); +} + +CW_INLINE void PointsToEntry_Copy(PointsToEntry *dest, PointsToEntry *src) { + IRO_ASSERT(3325, src != NULL); + IRO_ASSERT(3326, dest != NULL); + + PointsToEntry_Init(dest, src->loc, src->locs); +} + +CW_INLINE void PointsToEntry_Term(PointsToEntry *pte) { + IRO_ASSERT(3333, pte != NULL); + + LocationSet_Term(pte->loc); + LocationSet_Delete(pte->loc); + LocationSetSet_Term(pte->locs); + LocationSetSet_Delete(pte->locs); + +#ifdef IRO_DEBUG + pte->loc = NULL; + pte->locs = NULL; +#endif +} + +CW_INLINE Boolean PointsToEntries_Equal(PointsToEntry *pte1, PointsToEntry *pte2) { + IRO_ASSERT(3381, pte1 != NULL); + IRO_ASSERT(3382, pte2 != NULL); + + if (pte1 == pte2) + return 1; + + return LocationSets_Equal(pte1->loc, pte2->loc) && LocationSetSets_Equal(pte1->locs, pte2->locs); +} + +CW_INLINE LocationSet *PointsToEntry_loc(PointsToEntry *pte) { + IRO_ASSERT(3407, pte != NULL); + + return pte->loc; +} + +CW_INLINE LocationSetSet *PointsToEntry_locs(PointsToEntry *pte) { + IRO_ASSERT(3414, pte != NULL); + + return pte->locs; +} + +CW_INLINE PointsToFunction *PointsToFunction_New(void) { + PointsToFunction *pointsToFunc = IRO_malloc(sizeof(PointsToFunction)); + + IRO_ASSERT(3430, pointsToFunc != NULL); +#ifdef IRO_DEBUG + pointsToFunc->pte = NULL; + pointsToFunc->otherPtes = NULL; +#endif + return pointsToFunc; +} + +CW_INLINE void PointsToFunction_Delete(PointsToFunction *pointsToFunc) { + IRO_ASSERT(3442, pointsToFunc != NULL); + IRO_ASSERT(3443, pointsToFunc->pte == NULL); + IRO_ASSERT(3444, pointsToFunc->otherPtes == NULL); + IRO_DEBUG_CLEAR(pointsToFunc, sizeof(PointsToFunction)); + IRO_free(pointsToFunc); +} + +CW_INLINE void PointsToFunction_Init(PointsToFunction *pointsToFunc) { + IRO_ASSERT(3454, pointsToFunc != NULL); + + pointsToFunc->pte = NULL; + pointsToFunc->otherPtes = NULL; +} + +CW_INLINE void PointsToFunction_Copy(PointsToFunction *dest, PointsToFunction *src) { + IRO_ASSERT(3462, src != NULL); + IRO_ASSERT(3463, dest != NULL); + + dest->pte = NULL; + dest->otherPtes = NULL; + PointsToFunction_AddAllIGuess_sub_487D80(dest, src); +} + +CW_INLINE void PointsToFunction_Term(PointsToFunction *pointsToFunc) { + IRO_ASSERT(3472, pointsToFunc != NULL); + + PointsToFunction_RemoveAll(pointsToFunc); + +#ifdef IRO_DEBUG + pointsToFunc->pte = NULL; + pointsToFunc->otherPtes = NULL; +#endif +} + +CW_INLINE void PointsToFunction_ForEach(PointsToFunction *pointsToFunc, void (*action)(PointsToEntry *, void *), void *refcon) { + IRO_ASSERT(3515, pointsToFunc != NULL); + IRO_ASSERT(3516, action != NULL); + IRO_ASSERT(3517, refcon == NULL || refcon != NULL); + + while (pointsToFunc && pointsToFunc->pte) { + action(pointsToFunc->pte, refcon); + pointsToFunc = pointsToFunc->otherPtes; + } +} + +CW_INLINE PointsToEntry *PointsToFunction_FindByLocationSet(PointsToFunction *pointsToFunc, LocationSet *ls) { + IRO_ASSERT(3527, pointsToFunc != NULL); + IRO_ASSERT(3528, ls != NULL); + + while (pointsToFunc && pointsToFunc->pte) { + if (LocationSets_Equal(pointsToFunc->pte->loc, ls)) + return pointsToFunc->pte; + pointsToFunc = pointsToFunc->otherPtes; + } + + return NULL; +} + +CW_INLINE PointsToEntry *PointsToFunction_FindFirst(PointsToFunction *pointsToFunc) { + IRO_ASSERT(3539, pointsToFunc != NULL); + + return pointsToFunc->pte; +} + +CW_INLINE PointsToEntry *PointsToFunction_FindByLookupCompatibleLocationSet(PointsToFunction *pointsToFunc, LocationSet *ls) { + IRO_ASSERT(3546, pointsToFunc != NULL); + IRO_ASSERT(3547, ls != NULL); + + while (pointsToFunc && pointsToFunc->pte) { + if (ls->u.known.stride) { + if (LocationSets_Equal(pointsToFunc->pte->loc, ls)) + return pointsToFunc->pte; + } else if (LocationSets_LookupCompatible(pointsToFunc->pte->loc, ls)) { + return pointsToFunc->pte; + } + pointsToFunc = pointsToFunc->otherPtes; + } + + return NULL; +} + +CW_INLINE PointsToEntry *PointsToFunction_FindContainingLocationSet(PointsToFunction *pointsToFunc, LocationSet *ls, Type *rtype) { + IRO_ASSERT(3565, pointsToFunc != NULL); + IRO_ASSERT(3566, ls != NULL); + IRO_ASSERT(3567, rtype != NULL); + + while (pointsToFunc && pointsToFunc->pte) { + if (pointsToFunc->pte->locs->loc && !LocationSet_IsUnknown(pointsToFunc->pte->locs->loc)) { + if (!pointsToFunc->pte->locs->otherLocs && LocationSet_Contains(pointsToFunc->pte->loc, pointsToFunc->pte->locs->loc->rtype, ls, rtype)) + return pointsToFunc->pte; + } + pointsToFunc = pointsToFunc->otherPtes; + } + + return NULL; +} + +CW_INLINE void PointsToFunction_RemoveOverlappingLocations(PointsToFunction *pointsToFunc, PointsToEntry *pte) { + Type *rtype1; + Type *rtype2; + LocationSet *ls; + PointsToFunction *prev; + PointsToFunction *next; + PointsToFunction *tmp; + + IRO_ASSERT(3601, pointsToFunc != NULL); + IRO_ASSERT(3602, pte != NULL); + IRO_ASSERT(3603, pte->locs != NULL); + + if (pte->locs->loc && pte->locs->loc != stUnknownLs) + rtype1 = pte->locs->loc->rtype; + else + rtype1 = NULL; + ls = pte->loc; + IRO_ASSERT(3614, ls != NULL); + + prev = NULL; + while (pointsToFunc && pointsToFunc->pte) { + next = pointsToFunc->otherPtes; + if (pointsToFunc->pte->locs->loc && pointsToFunc->pte->locs->loc != stUnknownLs) + rtype2 = pointsToFunc->pte->locs->loc->rtype; + else + rtype2 = NULL; + + if (LocationSets_Overlap(ls, rtype1, pointsToFunc->pte->loc, rtype2)) { + PointsToEntry_Term(pointsToFunc->pte); + PointsToEntry_Delete(pointsToFunc->pte); + if (!prev) { + if (pointsToFunc->otherPtes == NULL) { + pointsToFunc->pte = NULL; + prev = pointsToFunc; + } else { + tmp = pointsToFunc->otherPtes; + pointsToFunc->pte = pointsToFunc->otherPtes->pte; + pointsToFunc->otherPtes = pointsToFunc->otherPtes->otherPtes; + tmp->pte = NULL; + tmp->otherPtes = NULL; + PointsToFunction_Term(tmp); + PointsToFunction_Delete(tmp); + prev = NULL; + next = pointsToFunc; + } + } else { + prev->otherPtes = pointsToFunc->otherPtes; + pointsToFunc->pte = NULL; + pointsToFunc->otherPtes = NULL; + PointsToFunction_Term(pointsToFunc); + PointsToFunction_Delete(pointsToFunc); + prev = pointsToFunc; + } + } + + pointsToFunc = next; + } +} + +CW_INLINE Boolean ShouldAddNewPointsToEntryToFunction(PointsToFunction *pointsToFunc, PointsToEntry *pte) { + Boolean flag; + Boolean isKnown; + SInt32 stride; + PointsToFunction *next; + LocationSet *loc; + LocationSet *loc2; + Type *rtype1; + Type *rtype2; + LocationSetSet *locs2; + LocationSet *tmp; + LocationSet *unknown; + Boolean flag2; + Boolean flag3; + + IRO_ASSERT(3675, pointsToFunc != NULL); + IRO_ASSERT(3676, pte != NULL); + IRO_ASSERT(3677, pte->locs != NULL); + IRO_ASSERT(3678, PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, pte->loc) == NULL); + IRO_ASSERT(3679, (unknown = LocationSetSet_FindFirst(pte->locs)) != NULL); + IRO_ASSERT(3680, LocationSet_IsUnknown(unknown)); + IRO_ASSERT(3681, LocationSet_bitfieldOf(unknown) == NULL); + IRO_ASSERT(3682, LocationSet_restriction(unknown) == NULL); + + if (pte->locs->loc && pte->locs->loc != stUnknownLs) + rtype1 = pte->locs->loc->rtype; + else + rtype1 = NULL; + + loc = pte->loc; + IRO_ASSERT(3693, loc != NULL); + + isKnown = !LocationSet_IsUnknown(loc); + if (isKnown) + stride = LocationSet_stride(loc); + + flag = 0; + while (pointsToFunc && pointsToFunc->pte) { + next = pointsToFunc->otherPtes; + + locs2 = pointsToFunc->pte->locs; + + if (locs2->loc && locs2->loc != stUnknownLs) + rtype2 = locs2->loc->rtype; + else + rtype2 = NULL; + + loc2 = pointsToFunc->pte->loc; + + flag2 = !(tmp = LocationSetSet_FindFirst(locs2)) || + !LocationSet_IsUnknown(tmp) || + LocationSet_bitfieldOf(tmp) || + LocationSet_restriction(tmp); + + flag3 = LocationSets_Overlap(loc, rtype1, loc2, rtype2); + + if (!flag && flag3) + flag = 1; + + if (flag3 && (flag2 || (isKnown && stride && LocationSet_stride(loc2) == 0))) + return 1; + + pointsToFunc = next; + } + + return !flag; +} + +CW_INLINE Boolean PointsToFunction_SimpleAdd(PointsToFunction *pointsToFunc, PointsToEntry *pte) { + PointsToEntry *newPTE; + + IRO_ASSERT(3741, pointsToFunc != NULL); + IRO_ASSERT(3742, pte != NULL); + + newPTE = PointsToEntry_New(); + PointsToEntry_Copy(newPTE, pte); + if (pointsToFunc->pte) { + PointsToFunction *newPointsToFunc = PointsToFunction_New(); + PointsToFunction_Init(newPointsToFunc); + newPointsToFunc->pte = pointsToFunc->pte; + newPointsToFunc->otherPtes = pointsToFunc->otherPtes; + pointsToFunc->otherPtes = newPointsToFunc; + } + pointsToFunc->pte = newPTE; + return 1; +} + +CW_INLINE Boolean PointsToFunction_Add(PointsToFunction *pointsToFunc, PointsToEntry *pte) { + IRO_ASSERT(3766, pointsToFunc != NULL); + IRO_ASSERT(3767, pte != NULL); + + if (!PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, pte->loc)) { + LocationSet *ls; + if (!(ls = LocationSetSet_FindFirst(pte->locs)) || !LocationSet_IsUnknown(ls) || LocationSet_bitfieldOf(ls) || + LocationSet_restriction(ls) || ShouldAddNewPointsToEntryToFunction(pointsToFunc, pte)) { + PointsToFunction_RemoveOverlappingLocations(pointsToFunc, pte); + if (!LocationSet_IsUnknown(pte->loc) || pte->loc->rtype) + PointsToFunction_SimpleAdd(pointsToFunc, pte); + return 1; + } + } + + return 0; +} + +CW_INLINE Boolean PointsToFunction_AddWithoutChecking(PointsToFunction *pointsToFunc, PointsToEntry *pte) { + LocationSet *ls; + + IRO_ASSERT(3793, pointsToFunc != NULL); + IRO_ASSERT(3794, pte != NULL); + + if (!(ls = LocationSetSet_FindFirst(pte->locs)) || !LocationSet_IsUnknown(ls) || LocationSet_bitfieldOf(ls) || + LocationSet_restriction(ls) || ShouldAddNewPointsToEntryToFunction(pointsToFunc, pte)) { + PointsToFunction_RemoveOverlappingLocations(pointsToFunc, pte); + if (!LocationSet_IsUnknown(pte->loc) || pte->loc->rtype) + PointsToFunction_SimpleAdd(pointsToFunc, pte); + return 1; + } + + return 0; +} + +CW_INLINE void PointsToFunction_RemoveByLocationSet(PointsToFunction *pointsToFunc, LocationSet *ls) { + PointsToFunction *prev; + PointsToFunction *tmp; + + IRO_ASSERT(3818, pointsToFunc != NULL); + IRO_ASSERT(3819, ls != NULL); + IRO_ASSERT(3820, !LocationSet_IsUnknown(ls)); + + prev = NULL; + while (pointsToFunc && pointsToFunc->pte) { + if (LocationSets_Equal(pointsToFunc->pte->loc, ls)) { + PointsToEntry_Term(pointsToFunc->pte); + PointsToEntry_Delete(pointsToFunc->pte); + if (!prev) { + if (pointsToFunc->otherPtes == NULL) { + pointsToFunc->pte = NULL; + } else { + tmp = pointsToFunc->otherPtes; + pointsToFunc->pte = pointsToFunc->otherPtes->pte; + pointsToFunc->otherPtes = pointsToFunc->otherPtes->otherPtes; + tmp->pte = NULL; + tmp->otherPtes = NULL; + PointsToFunction_Term(tmp); + PointsToFunction_Delete(tmp); + } + } else { + prev->otherPtes = pointsToFunc->otherPtes; + pointsToFunc->pte = NULL; + pointsToFunc->otherPtes = NULL; + PointsToFunction_Term(pointsToFunc); + PointsToFunction_Delete(pointsToFunc); + } + return; + } + + prev = pointsToFunc; + pointsToFunc = pointsToFunc->otherPtes; + } +} + +CW_INLINE void PointsToFunction_RemoveAll(PointsToFunction *pointsToFunc) { + IRO_ASSERT(3862, pointsToFunc != NULL); + + while (pointsToFunc && pointsToFunc->pte) + PointsToFunction_RemoveByLocationSet(pointsToFunc, pointsToFunc->pte->loc); +} + +CW_INLINE void PointsToFunction_AddFunctionAction(PointsToEntry *pte, void *refcon) { + IRO_ASSERT(3872, pte != NULL); + IRO_ASSERT(3873, refcon != NULL); + + PointsToFunction_Add((PointsToFunction *) refcon, pte); +} + +CW_INLINE void PointsToFunction_SimpleAddFunctionAction(PointsToEntry *pte, void *refcon) { + IRO_ASSERT(3880, pte != NULL); + IRO_ASSERT(3881, refcon != NULL); + + PointsToFunction_SimpleAdd((PointsToFunction *) refcon, pte); +} + +CW_INLINE void PointsToFunction_AddAllIGuess_sub_487D80(PointsToFunction *dest, PointsToFunction *src) { + IRO_ASSERT(3888, dest != NULL); + IRO_ASSERT(3889, src != NULL); + + if (dest->pte) + PointsToFunction_ForEach(src, PointsToFunction_AddFunctionAction, dest); + else + PointsToFunction_ForEach(src, PointsToFunction_SimpleAddFunctionAction, dest); +} + +CW_INLINE void PointsToFunction_SortByExtendedParamNum(PointsToFunction *pointsToFunc) { + UInt32 value1; + UInt32 value2; + PointsToFunction *scan; + + while (pointsToFunc && pointsToFunc->pte) { + value1 = 0; + if (pointsToFunc->pte->loc && pointsToFunc->pte->loc->block) { + PAMemoryBlock *block = pointsToFunc->pte->loc->block; + if (block->kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM && block->u.ep) { + value1 = 2 * (block->u.ep->x4) + 1; + } else if (block->kind == PAMEMORYBLOCKKIND_LOCALVAR && block->u.localvar) { + if (block->u.localvar->x0 && block->u.localvar->x0->extParam) + value1 = 2 * block->u.localvar->x0->extParam->x4; + } + } + + for (scan = pointsToFunc->otherPtes; scan && scan->pte; scan = scan->otherPtes) { + value2 = 0; + if (scan->pte->loc && scan->pte->loc->block) { + PAMemoryBlock *block = scan->pte->loc->block; + if (block->kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM && block->u.ep) { + value2 = 2 * (block->u.ep->x4) + 1; + } else if (block->kind == PAMEMORYBLOCKKIND_LOCALVAR && block->u.localvar) { + if (block->u.localvar->x0 && block->u.localvar->x0->extParam) + value2 = 2 * block->u.localvar->x0->extParam->x4; + } + } + + if (value2 < value1) { + LocationSet *saveloc; + LocationSetSet *savelocs; + saveloc = pointsToFunc->pte->loc; + savelocs = pointsToFunc->pte->locs; + pointsToFunc->pte->loc = scan->pte->loc; + pointsToFunc->pte->locs = scan->pte->locs; + scan->pte->loc = saveloc; + scan->pte->locs = savelocs; + } + } + + pointsToFunc = pointsToFunc->otherPtes; + } +} + +CW_INLINE Boolean PointsToFunctions_Equal(PointsToFunction *pointsToFunc1, PointsToFunction *pointsToFunc2) { + PointsToFunction *scan; + PointsToEntry *pte; + + IRO_ASSERT(3968, pointsToFunc1 != NULL); + IRO_ASSERT(3969, pointsToFunc2 != NULL); + + if (pointsToFunc1 == pointsToFunc2) + return 1; + + for (scan = pointsToFunc1; scan && scan->pte; scan = scan->otherPtes) { + pte = PointsToFunction_FindByLocationSet(pointsToFunc2, scan->pte->loc); + if (!pte || !PointsToEntries_Equal(pte, scan->pte)) + return 0; + } + + for (scan = pointsToFunc2; scan && scan->pte; scan = scan->otherPtes) { + pte = PointsToFunction_FindByLocationSet(pointsToFunc1, scan->pte->loc); + if (!pte || !PointsToEntries_Equal(pte, scan->pte)) + return 0; + } + + return 1; +} + +CW_INLINE Boolean PointsToFunctions_Match(PointsToFunction *pointsToFunc1, PointsToFunction *pointsToFunc2) { + return 1; +} + +CW_INLINE PartialTransferFunction *PartialTransferFunction_New(void) { + PartialTransferFunction *ptf = IRO_malloc(sizeof(PartialTransferFunction)); + + IRO_ASSERT(4110, ptf != NULL); +#ifdef IRO_DEBUG + ptf->initialPointsToFn = NULL; + ptf->finalPointsToFn = NULL; + ptf->funcModifies = NULL; + ptf->context.nd = NULL; + ptf->context.ptf = NULL; + ptf->returnLocation = NULL; +#endif + return ptf; +} + +CW_INLINE void PartialTransferFunction_Delete(PartialTransferFunction *ptf) { + IRO_ASSERT(4126, ptf != NULL); + IRO_ASSERT(4127, ptf->initialPointsToFn == NULL); + IRO_ASSERT(4128, ptf->finalPointsToFn == NULL); + IRO_ASSERT(4129, ptf->funcModifies == NULL); + IRO_ASSERT(4130, ptf->context.nd == NULL); + IRO_ASSERT(4131, ptf->context.ptf == NULL); + IRO_ASSERT(4132, ptf->returnLocation == NULL); + IRO_DEBUG_CLEAR(ptf, sizeof(PartialTransferFunction)); + IRO_free(ptf); +} + +CW_INLINE void PartialTransferFunction_Init(PartialTransferFunction *ptf, IROLinear *contextNd, PartialTransferFunction *contextPTF) { + IRO_ASSERT(4142, ptf != NULL); + IRO_ASSERT(4143, contextNd != NULL); + IRO_ASSERT(4144, contextPTF != NULL); + + ptf->initialPointsToFn = PointsToFunction_New(); + PointsToFunction_Init(ptf->initialPointsToFn); + ptf->finalPointsToFn = PointsToFunction_New(); + PointsToFunction_Init(ptf->finalPointsToFn); + + ptf->funcModifies = LocationSetSet_New(); + LocationSetSet_Init(ptf->funcModifies); + LocationSetSet_AddUnknown(ptf->funcModifies, NULL, NULL, NULL); + + ptf->returnLocation = NULL; + ptf->x10 = 0; + + ptf->context.nd = contextNd; + ptf->context.ptf = contextPTF; +} + +CW_INLINE void PartialTransferFunction_Copy(PartialTransferFunction *dest, PartialTransferFunction *src) { + IRO_ASSERT(4164, src != NULL); + IRO_ASSERT(4165, dest != NULL); + + dest->initialPointsToFn = PointsToFunction_New(); + PointsToFunction_Copy(dest->initialPointsToFn, src->initialPointsToFn); + dest->finalPointsToFn = PointsToFunction_New(); + PointsToFunction_Copy(dest->finalPointsToFn, src->finalPointsToFn); + + dest->funcModifies = LocationSetSet_New(); + LocationSetSet_Copy(dest->funcModifies, src->funcModifies); + + if (src->returnLocation) { + dest->returnLocation = LocationSet_New(); + LocationSet_Copy(dest->returnLocation, src->returnLocation); + } else { + dest->returnLocation = NULL; + } + + dest->x10 = src->x10; + dest->context = src->context; +} + +CW_INLINE void PartialTransferFunction_Term(PartialTransferFunction *ptf) { + IRO_ASSERT(4190, ptf != NULL); + + PointsToFunction_Term(ptf->initialPointsToFn); + PointsToFunction_Delete(ptf->initialPointsToFn); + PointsToFunction_Term(ptf->finalPointsToFn); + PointsToFunction_Delete(ptf->finalPointsToFn); + LocationSetSet_Term(ptf->funcModifies); + LocationSetSet_Delete(ptf->funcModifies); + + if (ptf->returnLocation) { + PAMemoryBlock_Term(ptf->returnLocation->block); + PAMemoryBlock_Delete(ptf->returnLocation->block); + LocationSet_Term(ptf->returnLocation); + LocationSet_Delete(ptf->returnLocation); + ptf->returnLocation = NULL; + } + +#ifdef IRO_DEBUG + ptf->initialPointsToFn = NULL; + ptf->finalPointsToFn = NULL; + ptf->funcModifies = NULL; + ptf->context.nd = NULL; + ptf->context.ptf = NULL; +#endif +} + +CW_INLINE PointsToFunction *PartialTransferFunction_initialPointsToFn(PartialTransferFunction *ptf) { + IRO_ASSERT(4221, ptf != NULL); + + return ptf->initialPointsToFn; +} + +CW_INLINE PointsToFunction *PartialTransferFunction_finalPointsToFn(PartialTransferFunction *ptf) { + IRO_ASSERT(4227, ptf != NULL); + + return ptf->finalPointsToFn; +} + +CW_INLINE LocationSetSet *PTF_sub_48D750(PartialTransferFunction *ptf) { + IRO_ASSERT(4233, ptf != NULL); + + return ptf->funcModifies; +} + +CW_INLINE LocationSet *PartialTransferFunction_returnLocation(PartialTransferFunction *ptf) { + IRO_ASSERT(4249, ptf != NULL); + + if (!ptf->returnLocation) { + PAMemoryBlock *block; + LocationSet *ls; + + block = PAMemoryBlock_New(); + PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_LOCALVAR, NULL); + ls = LocationSet_New(); + LocationSet_InitKnown(ls, block, cint64_zero, 0, TYPE(&void_ptr)); + ptf->returnLocation = ls; + } + + return ptf->returnLocation; +} + +CW_INLINE IROLinear *PTF_sub_48B980(PartialTransferFunction *ptf) { + IRO_ASSERT(4265, ptf != NULL); + + return ptf->context.nd; +} + +CW_INLINE PartialTransferFunction *PTF_sub_48B970(PartialTransferFunction *ptf) { + IRO_ASSERT(4271, ptf != NULL); + + return ptf->context.ptf; +} + +CW_INLINE void PartialTransferFunction_sub_48A610(PartialTransferFunction *ptf, Boolean value) { + IRO_ASSERT(4298, ptf != NULL); + + ptf->x10 = (value != 0) ? 1 : 0; +} + +CW_INLINE PTFList *PTFList_New(void) { + PTFList *ptfList = IRO_malloc(sizeof(PTFList)); + + IRO_ASSERT(4393, ptfList != NULL); +#ifdef IRO_DEBUG + ptfList->ptf = NULL; + ptfList->otherPTFs = NULL; +#endif + return ptfList; +} + +CW_INLINE void PTFList_Delete(PTFList *ptfList) { + IRO_ASSERT(4405, ptfList != NULL); + IRO_ASSERT(4406, ptfList->ptf == NULL); + IRO_ASSERT(4407, ptfList->otherPTFs == NULL); + IRO_DEBUG_CLEAR(ptfList, sizeof(PTFList)); + IRO_free(ptfList); +} + +CW_INLINE void PTFList_Init(PTFList *ptfList) { + IRO_ASSERT(4417, ptfList != NULL); + + ptfList->ptf = NULL; + ptfList->otherPTFs = NULL; +} + +CW_INLINE void PTFList_Term(PTFList *ptfList) { + IRO_ASSERT(4435, ptfList != NULL); + + PTFList_RemoveAll(ptfList); + +#ifdef IRO_DEBUG + ptfList->ptf = NULL; + ptfList->otherPTFs = NULL; +#endif +} + +CW_INLINE void PTFList_ForEach(PTFList *ptfList, void (*action)(PartialTransferFunction *, void *), void *refcon) { + IRO_ASSERT(4478, ptfList != NULL); + IRO_ASSERT(4479, action != NULL); + IRO_ASSERT(4480, refcon == NULL || refcon != NULL); + + while (ptfList && ptfList->ptf) { + action(ptfList->ptf, refcon); + ptfList = ptfList->otherPTFs; + } +} + +CW_INLINE PartialTransferFunction *PTFList_sub_48A0F0(PTFList *ptfList, PartialTransferFunction *ptf) { + IRO_ASSERT(4490, ptfList != NULL); + IRO_ASSERT(4491, ptf != NULL); + + while (ptfList && ptfList->ptf) { + if (ptfList->ptf == ptf) + return ptfList->ptf; + + ptfList = ptfList->otherPTFs; + } + + return NULL; +} + +CW_INLINE PartialTransferFunction *PTFList_FindFirst(PTFList *ptfList) { + IRO_ASSERT(4502, ptfList != NULL); + + return ptfList->ptf; +} + +CW_INLINE void PTFList_sub_48A080(PTFList *ptfList, PartialTransferFunction *ptf) { + IRO_ASSERT(4511, ptfList != NULL); + IRO_ASSERT(4512, ptf != NULL); + + if (ptfList->ptf) { + PTFList *newList = PTFList_New(); + PTFList_Init(newList); + newList->ptf = ptfList->ptf; + newList->otherPTFs = ptfList->otherPTFs; + ptfList->otherPTFs = newList; + } + + ptfList->ptf = ptf; +} + +CW_INLINE void PTFList_sub_48A050(PTFList *ptfList, PartialTransferFunction *ptf) { + IRO_ASSERT(4529, ptfList != NULL); + IRO_ASSERT(4530, ptf != NULL); + + if (!PTFList_sub_48A0F0(ptfList, ptf)) + PTFList_sub_48A080(ptfList, ptf); +} + +CW_INLINE void PTFList_Remove(PTFList *ptfList, PartialTransferFunction *ptf) { + PTFList *prev; + PTFList *tmp; + + IRO_ASSERT(4542, ptfList != NULL); + IRO_ASSERT(4543, ptf != NULL); + + prev = NULL; + while (ptfList && ptfList->ptf) { + if (ptfList->ptf == ptf) { + if (!prev) { + if (ptfList->otherPTFs == NULL) { + ptfList->ptf = NULL; + } else { + tmp = ptfList->otherPTFs; + ptfList->ptf = ptfList->otherPTFs->ptf; + ptfList->otherPTFs = ptfList->otherPTFs->otherPTFs; + tmp->ptf = NULL; + tmp->otherPTFs = NULL; + PTFList_Term(tmp); + PTFList_Delete(tmp); + } + } else { + prev->otherPTFs = ptfList->otherPTFs; + ptfList->ptf = NULL; + ptfList->otherPTFs = NULL; + PTFList_Term(ptfList); + PTFList_Delete(ptfList); + } + return; + } + + prev = ptfList; + ptfList = ptfList->otherPTFs; + } +} + +CW_INLINE void PTFList_RemoveAll(PTFList *ptfList) { + IRO_ASSERT(4582, ptfList != NULL); + + while (ptfList && ptfList->ptf) + PTFList_Remove(ptfList, ptfList->ptf); +} diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroPropagate.c b/compiler_and_linker/FrontEnd/Optimizer/IroPropagate.c new file mode 100644 index 0000000..c5ad708 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroPropagate.c @@ -0,0 +1,593 @@ +#include "IroPropagate.h" +#include "IroCSE.h" +#include "IroDump.h" +#include "IroEval.h" +#include "IroFlowgraph.h" +#include "IroLinearForm.h" +#include "IROUseDef.h" +#include "IroUtil.h" +#include "IroVars.h" +#include "compiler/objects.h" +#include "compiler/CExpr.h" +#include "compiler/CompilerTools.h" +#include "compiler/CParser.h" +#include "compiler/InlineAsm.h" +#include "compiler/InlineAsmPPC.h" + +IROAssign *IRO_FirstAssign; +IROAssign *IRO_LastAssign; +SInt32 IRO_NumAssign; + +static Boolean VarIsUsedInOtherFNodes(VarRecord *var, IRONode *node) { + if (var->defs && var->uses) { + IROUse *use; + IRODef *def = NULL; + for (use = var->uses; use; use = use->varnext) { + if (!def && use->node == node && use->linear && !(use->linear->flags & IROLF_Assigned)) { + for (def = var->defs; def; def = def->varnext) { + if (Bv_IsBitSet(def->index, use->x18)) + break; + } + } + } + + if (def) { + for (use = var->uses; use; use = use->varnext) { + if (use->node != node && use->linear && !(use->linear->flags & IROLF_Assigned)) { + if (Bv_IsBitSet(def->index, use->x18)) + return 1; + } + } + } + } else { + IROLinear *linear; + IRONode *scan; + for (scan = IRO_FirstNode; scan; scan = scan->nextnode) { + if (scan != node) { + linear = scan->first; + while (1) { + if (!linear) + break; + + if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) { + if (IRO_FindVar(linear->u.diadic.left->u.node->data.objref, 0, 1) == var) + return 1; + } + + if (linear == scan->last) + break; + linear = linear->next; + } + } + } + IRO_CheckForUserBreak(); + } + + return 0; +} + +static void GetExprUses(IROLinear *linear, Boolean isFirst) { + if (isFirst && IS_LINEAR_ENODE(linear, EOBJREF)) { + Object *obj = linear->u.node->data.objref; + if ((linear->flags & IROLF_Ind) && (!(linear->flags & IROLF_Assigned) || (linear->flags & IROLF_Used))) { + VarRecord *var = IRO_FindVar(obj, 0, 1); + if (var) + Bv_SetBit(var->index, IRO_VarKills); + } + } +} + +static void GetExprKills(IROLinear *linear, Boolean isFirst) { + if (isFirst) + IRO_GetKills(linear); +} + +static void CheckUnorderedRegionForDefs(IROLinear *linear, BitVector *a, BitVector *b, Boolean *flag) { + Bv_Clear(a); + Bv_Clear(IRO_VarKills); + IRO_WalkTree(linear, GetExprKills); + Bv_Or(IRO_VarKills, a); + if (Bv_BitsInCommon(a, b)) + *flag = 1; +} + +static void CheckUnorderedRegionsForDefs(IROLinear *linear1, IROLinear *linear2, BitVector *a, BitVector *b, Boolean *flag) { + int i; + + switch (linear1->type) { + case IROLinearOp2Arg: + if (linear1->nodetype == ELAND) break; + if (linear1->nodetype == ELOR) break; + if (linear1->nodetype == ECOMMA) break; + if (linear1->u.diadic.left != linear2) + CheckUnorderedRegionForDefs(linear1->u.diadic.left, a, b, flag); + if (linear1->u.diadic.right != linear2) + CheckUnorderedRegionForDefs(linear1->u.diadic.right, a, b, flag); + break; + case IROLinearFunccall: + if (linear1->u.funccall.linear8 != linear2) + CheckUnorderedRegionForDefs(linear1->u.funccall.linear8, a, b, flag); + for (i = 0; !*flag && i < linear1->u.funccall.argCount; i++) { + if (linear1->u.funccall.args[i] != linear2) + CheckUnorderedRegionForDefs(linear1->u.funccall.args[i], a, b, flag); + } + break; + } +} + +static Boolean PropagationHasDefsInUnorderedRegions(IROLinear *a, IROLinear *b) { + Boolean flag; + IROLinear *father; + BitVector *bv1; + BitVector *bv2; + VarRecord *var; + + flag = 0; + if ((father = IRO_LocateFather(a))) { + Bv_AllocVector(&bv1, IRO_NumVars + 1); + Bv_AllocVector(&bv2, IRO_NumVars + 1); + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + IRO_WalkTree(b, GetExprUses); + Bv_Or(IRO_VarKills, bv2); + var = IRO_FindVar(a->u.diadic.left->u.node->data.objref, 0, 1); + Bv_SetBit(var->index, bv2); + while (father && !flag) { + CheckUnorderedRegionsForDefs(father, a, bv1, bv2, &flag); + a = father; + father = IRO_LocateFather(father); + } + } + + return flag; +} + +int IRO_IsRegable(Object *obj) { + if (obj->datatype == DLOCAL && obj->u.var.info) + return obj->u.var.info->noregister == 0; + return 0; +} + +static Boolean IsPropagatable(IROLinear *linear) { + Object *obj; + Object *obj2; + + if (IS_LINEAR_DIADIC(linear, EASS) && (obj = IRO_IsVariable(linear->u.diadic.left)) && obj->type == linear->rtype && !is_volatile_object(obj)) { + if (linear->u.diadic.left->flags & IROLF_BitfieldIndirect) { + if (!IRO_IsConstant(linear->u.diadic.right)) + return 0; + else + return 1; + } + + if (IRO_IsConstant(linear->u.diadic.right)) + return 1; + + if ((obj2 = IRO_IsVariable(linear->u.diadic.right)) && !is_volatile_object(obj2) && IRO_TypesEqual(obj->type, linear->rtype)) { + if (!Inline_IsObjectData(linear->u.diadic.right->u.monadic->u.node->data.objref)) { + if (IRO_IsRegable(obj) && !IRO_IsRegable(obj2)) + return 0; + return 1; + } + } + } + + return 0; +} + +static Boolean IsIntGenKillCandidate(IROLinear *linear) { + if (linear->type == IROLinearFunccall) + return 1; + + if (IRO_IsAssignOp[linear->nodetype] && (linear->type == IROLinearOp1Arg || linear->type == IROLinearOp2Arg)) + return 1; + + if (linear->type == IROLinearAsm) + return 1; + + return 0; +} + +static Boolean IsPropagatableExpr(IROLinear *linear, IROList *list) { + Object *obj; + if (IS_LINEAR_DIADIC(linear, EASS) && !(linear->flags & IROLF_Reffed)) { + if ((obj = IRO_IsVariable(linear->u.diadic.left)) && !is_volatile_object(obj) && !(linear->u.diadic.left->flags & IROLF_BitfieldIndirect)) { + if (!IRO_IsRegable(obj)) + return 0; + if (IS_LINEAR_ENODE(linear->u.diadic.right, ESTRINGCONST)) + return 0; + + IRO_FindDepends(linear->u.diadic.right); + if (!IRO_NotSubable) + return 1; + } + } + + return 0; +} + +static void ClearAvailibilityOnNode(IRONode *node, UInt32 bit) { + IRONode *scan; + + for (scan = node->nextnode; scan; scan = scan->nextnode) + Bv_ClearBit(bit, scan->x16); +} + +Boolean IRO_CopyAndConstantPropagation(void) { + IROAssign *ass2; + IROAssign *ass; + IROLinear *linear; + IRONode *node; + VarRecord *var; + BitVector *bv; + Boolean flag; + Boolean result; + + IRO_FirstAssign = NULL; + IRO_NumAssign = 0; + result = 0; + + for (node = IRO_FirstNode; node; node = node->nextnode) { + linear = node->first; + while (1) { + if (!linear) + break; + + if (IsPropagatable(linear) && (var = IRO_FindAssigned(linear))) { + IROAssign *newass; + IRO_Dump("Found propagatable assignment at: %d\n", linear->index); + newass = oalloc(sizeof(IROAssign)); + newass->linear = linear; + newass->next = NULL; + newass->index = ++IRO_NumAssign; + newass->varIndex = var->index; + newass->linear2 = linear->u.diadic.right; + newass->var = NULL; + newass->varObj = IRO_IsVariable(linear->u.diadic.right); + newass->node = node; + if (newass->varObj) + newass->var = IRO_FindVar(newass->varObj, 0, 1); + if (!IRO_FirstAssign) + IRO_FirstAssign = newass; + else + IRO_LastAssign->next = newass; + IRO_LastAssign = newass; + } + + if (linear == node->last) + break; + linear = linear->next; + } + } + + IRO_CheckForUserBreak(); + + node = IRO_FirstNode; + ass = IRO_FirstAssign; + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + while (node) { + Bv_AllocVector(&node->x16, IRO_NumAssign); + if (node != IRO_FirstNode) + Bv_Set(node->x16); + Bv_AllocVector(&node->x22, IRO_NumAssign); + Bv_AllocVector(&node->x1E, IRO_NumAssign); + Bv_AllocVector(&node->x2A, IRO_NumAssign); + node->x1A = NULL; + + linear = node->first; + while (1) { + if (!linear) + break; + + if (IsIntGenKillCandidate(linear)) { + //IROAssign *ass2; + Bv_Clear(IRO_VarKills); + IRO_GetKills(linear); + + for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) { + if (Bv_IsBitSet(ass2->varIndex, IRO_VarKills)) { + Bv_SetBit(ass2->index, node->x22); + Bv_ClearBit(ass2->index, node->x1E); + } + if (ass2->var && Bv_IsBitSet(ass2->var->index, IRO_VarKills)) { + Bv_SetBit(ass2->index, node->x22); + Bv_ClearBit(ass2->index, node->x1E); + } + } + } + + while (ass && ass->linear == linear) { + Bv_SetBit(ass->index, node->x1E); + ass = ass->next; + } + + if (linear == node->last) + break; + linear = linear->next; + } + + Bv_Copy(node->x16, node->x2A); + Bv_Minus(node->x22, node->x2A); + Bv_Or(node->x1E, node->x2A); + node = node->nextnode; + } + + IRO_CheckForUserBreak(); + + Bv_AllocVector(&bv, IRO_NumAssign); + do { + flag = 0; + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node == IRO_FirstNode) { + Bv_Clear(bv); + } else { + UInt16 i; + Bv_Set(bv); + for (i = 0; i < node->numpred; i++) + Bv_And(IRO_NodeTable[node->pred[i]]->x2A, bv); + } + + if (!Bv_Compare(bv, node->x16)) { + flag = 1; + Bv_Copy(bv, node->x16); + } + + Bv_Copy(node->x16, node->x2A); + Bv_Minus(node->x22, node->x2A); + Bv_Or(node->x1E, node->x2A); + } + } while (flag); + + IRO_CheckForUserBreak(); + + node = IRO_FirstNode; + ass = IRO_FirstAssign; + while (node) { + IRO_Avail = node->x16; + linear = node->first; + while (1) { + if (!linear) + break; + + if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) { + if ((var = IRO_FindVar(linear->u.diadic.left->u.node->data.objref, 0, 1))) { + //IROAssign *ass2; + for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) { + if ( + ass2->varIndex == var->index && + Bv_IsBitSet(ass2->index, IRO_Avail) && + (IRO_IsConstant(ass2->linear2) || node->loopdepth <= ass2->node->loopdepth) && + !PropagationHasDefsInUnorderedRegions(linear, ass2->linear2) + ) { + if (ass2->linear2->type == IROLinearOperand && IRO_is_CPtypeequal(linear->rtype, ass2->linear->u.diadic.left->rtype)) { + ENode *enode = IRO_NewENode(ass2->linear2->u.node->type); + *enode = *ass2->linear2->u.node; + if (enode->type == EINTCONST) { + if (linear->flags & IROLF_BitfieldIndirect) { + IRO_TruncateBitfieldValueToType(&enode->data.intval, linear->rtype, var->x1A); + enode->rtype = linear->rtype; + result = 1; + } else { + IRO_TruncateValueToType(&enode->data.intval, linear->rtype); + enode->rtype = linear->rtype; + } + } + linear->u.monadic->type = IROLinearNop; + linear->type = IROLinearOperand; + linear->u.node = enode; + } else if (ass2->varObj && IRO_is_CPtypeequal(linear->rtype, ass2->linear->rtype)) { + linear->u.diadic.left->u.node = create_objectrefnode(ass2->varObj); + if (ass2->linear2->flags & IROLF_BitfieldIndirect) + linear->flags |= IROLF_BitfieldIndirect; + } + IRO_Dump("Found propagation at %d from %d\n", linear->index, ass2->linear->index); + break; + } + } + } + } else if (linear->type == IROLinearAsm) { + IAEffects effects; + int i; + CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); + + for (i = 0; i < effects.numoperands; i++) { + if (effects.operands[i].type == IAEffect_0 && effects.operands[i].offset == 0 && effects.operands[i].object->type->size == effects.operands[i].size) { + if ((var = IRO_FindVar(effects.operands[i].object, 0, 1))) { + //IROAssign *ass2; + for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) { + if (ass2->varIndex == var->index && Bv_IsBitSet(ass2->index, IRO_Avail) && ass2->linear->rtype->size == effects.operands[i].size) { + ENode *enode; + if (ass2->varObj) + enode = create_objectrefnode(ass2->varObj); + else if (ass2->linear2->type == IROLinearOperand) + enode = ass2->linear2->u.node; + else + CError_FATAL(768); + CodeGen_PropagateIntoAsm(linear->u.asm_stmt, effects.operands[i].object, enode); + break; + } + } + } + } + } + } + + if (IsIntGenKillCandidate(linear)) { + //IROAssign *ass2; + Bv_Clear(IRO_VarKills); + IRO_GetKills(linear); + + for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) { + if (Bv_IsBitSet(ass2->varIndex, IRO_VarKills)) { + Bv_ClearBit(ass2->index, IRO_Avail); + } + if (ass2->var && Bv_IsBitSet(ass2->var->index, IRO_VarKills)) { + Bv_ClearBit(ass2->index, IRO_Avail); + } + } + + while (ass && ass->linear == linear) { + Bv_SetBit(ass->index, IRO_Avail); + ass = ass->next; + } + } + + if (linear == node->last) + break; + linear = linear->next; + } + node = node->nextnode; + } + + IRO_CheckForUserBreak(); + + return result; +} + +void IRO_ExpressionPropagation(void) { + IRONode *node; + IROLinear *linear; + Object *obj; + VarRecord *var; + IROAssign *ass; + + for (node = IRO_FirstNode; node; node = node->nextnode) { + IRO_FirstAssign = NULL; + IRO_LastAssign = NULL; + IRO_NumAssign = 0; + + linear = node->first; + while (1) { + IROList list; + if (!linear) + break; + + IRO_InitList(&list); + if (IsPropagatableExpr(linear, &list)) { + if ((var = IRO_FindAssigned(linear))) { + IRO_Dump("Found propagatable expression assignment at: %d\n", linear->index); + ass = oalloc(sizeof(IROAssign)); + ass->linear = linear; + ass->next = NULL; + ass->index = ++IRO_NumAssign; + ass->varIndex = var->index; + ass->linear2 = linear->u.diadic.right; + ass->x20 = 0; + ass->node = node; + IRO_FindDepends(linear->u.diadic.right); + ass->depends = IRO_Depends; + if (!IRO_FirstAssign) { + IRO_FirstAssign = ass; + ass->prev = NULL; + } else { + IRO_LastAssign->next = ass; + ass->prev = IRO_LastAssign; + } + IRO_LastAssign = ass; + } + } + + if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) { + if ((var = IRO_FindVar(linear->u.monadic->u.node->data.objref, 0, 1))) { + for (ass = IRO_LastAssign; ass; ass = ass->prev) { + if (ass->varIndex == var->index) + ass->x20++; + } + } + } + + if (linear == node->last) + break; + linear = linear->next; + } + + Bv_AllocVector(&IRO_Avail, IRO_NumAssign); + + linear = node->first; + while (1) { + if (!linear) + break; + + if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) { + if ((var = IRO_FindVar(linear->u.monadic->u.node->data.objref, 0, 1))) { + for (ass = IRO_FirstAssign; ass; ass = ass->next) { + if (ass->varIndex == var->index && Bv_IsBitSet(ass->index, IRO_Avail) && !PropagationHasDefsInUnorderedRegions(linear, ass->linear2)) { + if (ass->linear2->type == IROLinearOperand && IRO_is_CPtypeequal(linear->rtype, ass->linear->u.diadic.left->rtype)) { + ENode *enode = IRO_NewENode(ass->linear2->u.node->type); + *enode = *ass->linear2->u.node; + if (enode->type == EINTCONST) { + IRO_TruncateValueToType(&enode->data.intval, linear->rtype); + enode->rtype = linear->rtype; + } else if (enode->type == EOBJREF) { + IROLinear *tmp = IRO_LocateFather(linear); + if (tmp && (tmp->flags & IROLF_Assigned)) + linear->flags |= IROLF_Assigned; + } + linear->u.monadic->type = IROLinearNop; + linear->type = IROLinearOperand; + linear->u.node = enode; + } else if (IRO_IsVariable(ass->linear2) && IRO_is_CPtypeequal(linear->rtype, ass->linear->rtype)) { + linear->u.monadic->u.node = create_objectrefnode(ass->linear2->u.monadic->u.node->data.objref); + if (ass->linear2->flags & IROLF_BitfieldIndirect) + linear->flags |= IROLF_BitfieldIndirect; + } else if (IRO_is_CPtypeequal(linear->rtype, ass->linear->rtype) && ass->x20 == 1 && !VarIsUsedInOtherFNodes(var, node)) { + IROList list; + IRO_InitList(&list); + IRO_DuplicateExpr(ass->linear->u.diadic.right, &list); + if (IS_TYPE_FLOAT(ass->linear->rtype)) { + IROLinear *tmp = IRO_NewLinear(IROLinearOp1Arg); + tmp->index = ++IRO_NumLinear; + tmp->rtype = ass->linear->rtype; + tmp->nodetype = ETYPCON; + tmp->nodeflags = ENODE_FLAG_80; + tmp->u.monadic = list.tail; + IRO_AddToList(tmp, &list); + } + IRO_PasteAfter(list.head, list.tail, linear); + IRO_LocateFather_Cut_And_Paste(linear, list.tail); + linear = list.tail; + } + IRO_Dump("Found expression propagation at %d from %d\n", linear->index, ass->linear->index); + break; + } + } + } + } + + if (linear->type != IROLinearNop && IsIntGenKillCandidate(linear)) { + Bv_Clear(IRO_VarKills); + IRO_GetKills(linear); + for (ass = IRO_FirstAssign; ass; ass = ass->next) { + if (Bv_IsBitSet(ass->varIndex, IRO_VarKills)) + Bv_ClearBit(ass->index, IRO_Avail); + if ((obj = IRO_IsVariable(ass->linear->u.diadic.right))) { + if ((var = IRO_FindVar(obj, 0, 1))) { + if (Bv_IsBitSet(var->index, IRO_VarKills)) + Bv_ClearBit(ass->index, IRO_Avail); + } + } else { + IROList list; + IRO_InitList(&list); + IRO_Depends = ass->depends; + IRO_FindDepends_NoAlloc(ass->linear->u.diadic.right); + if (Bv_BitsInCommon(IRO_VarKills, ass->depends)) + Bv_ClearBit(ass->index, IRO_Avail); + } + } + + for (ass = IRO_FirstAssign; ass; ass = ass->next) { + IRO_Depends = ass->depends; + IRO_FindDepends_NoAlloc(ass->linear->u.diadic.right); + if (ass->linear == linear && !Bv_IsBitSet(ass->varIndex, ass->depends)) + Bv_SetBit(ass->index, IRO_Avail); + } + } + + if (linear == node->last) + break; + linear = linear->next; + } + } + + IRO_CheckForUserBreak(); +} + diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroPropagate.h b/compiler_and_linker/FrontEnd/Optimizer/IroPropagate.h new file mode 100644 index 0000000..ff9fadb --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroPropagate.h @@ -0,0 +1,35 @@ +#ifndef COMPILER_IROPROPAGATE_H +#define COMPILER_IROPROPAGATE_H + +#include "IrOptimizer.h" +#include "BitVector.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +struct IROAssign { + IROLinear *linear; + UInt16 index; + UInt16 varIndex; + IROLinear *linear2; + BitVector *depends; + Object *varObj; + VarRecord *var; + IROAssign *next; + IROAssign *prev; + UInt16 x20; + IRONode *node; +}; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +extern IROAssign *IRO_FirstAssign; +extern IROAssign *IRO_LastAssign; +extern SInt32 IRO_NumAssign; + +extern int IRO_IsRegable(Object *obj); +extern Boolean IRO_CopyAndConstantPropagation(void); +extern void IRO_ExpressionPropagation(void); + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroRangePropagation.c b/compiler_and_linker/FrontEnd/Optimizer/IroRangePropagation.c new file mode 100644 index 0000000..737035f --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroRangePropagation.c @@ -0,0 +1,774 @@ +#include "IroRangePropagation.h" +#include "IroDump.h" +#include "IroFlowgraph.h" +#include "IroLinearForm.h" +#include "IroMalloc.h" +#include "IroPointerAnalysis.h" +#include "IroUtil.h" +#include "IroVars.h" +#include "compiler/CInt64.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef enum ERangeType { + ERangeType0, + ERangeType1, + ERangeType2, + ERangeType3 +} ERangeType; + +typedef struct ERange { + ERangeType type; + CInt64 upper; + CInt64 lower; +} ERange; + +typedef struct ERecord { + Object *object; + ERange *range; + struct ERecord *next; +} ERecord; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static ERecord *ERangeFirst; +static ERecord *ERangeLast; + +static ERange *ERnewERange(ERangeType type) { + ERange *range; + + range = oalloc(sizeof(ERange)); + range->type = type; + return range; +} + +static ERecord *ERnewRecord(Object *object, ERange *range) { + ERecord *record; + + record = oalloc(sizeof(ERecord)); + record->object = object; + record->range = range; + record->next = ERangeFirst; + ERangeFirst = record; + if (!ERangeLast) + ERangeLast = record; + return record; +} + +static ERecord *ERecordFound(Object *obj) { + ERecord *scan; + + scan = ERangeFirst; + while (scan && obj != scan->object) + scan = scan->next; + + return scan; +} + +static Boolean EREandHasNoUse(ERange *range, CInt64 val) { + UInt16 i; + CInt64 v11; + CInt64 work; + + i = 0; + work = range->upper; + while (CInt64_NotEqual(work = CInt64_ShrU(work, cint64_one), cint64_zero)) + i++; + + if (CInt64_NotEqual(range->upper, cint64_zero)) + i++; + + CInt64_SetULong(&work, i); + v11 = CInt64_Sub(CInt64_Shl(cint64_one, work), cint64_one); + if (CInt64_NotEqual(cint64_zero, CInt64_And(CInt64_Inv(val), v11))) + return 0; + else + return 1; +} + +static void ERcheckOverflow(ERange *range, Type *type) { + CInt64 typeSize; + CInt64 work; + CInt64 work2; + CInt64 value3; + + if (!range) + return; + + if (!IS_TYPE_INT(type)) { + range->type = ERangeType3; + return; + } + + CInt64_SetLong(&typeSize, type->size); + CInt64_SetLong(&value3, 3); + + if (IRO_IsUnsignedType(type)) { + if (type->size < 8) { + work = CInt64_Sub(CInt64_Shl(cint64_one, CInt64_Shl(typeSize, value3)), cint64_one); + if (CInt64_GreaterU(range->upper, work)) + range->type = ERangeType3; + } else { + range->type = ERangeType3; + } + } else { + if (type->size < 8) { + work = CInt64_Sub(CInt64_Shl(cint64_one, CInt64_Sub(CInt64_Shl(typeSize, value3), cint64_one)), cint64_one); + work2 = CInt64_Shl(cint64_negone, CInt64_Sub(CInt64_Shl(typeSize, value3), cint64_one)); + if (CInt64_Greater(range->upper, work) || CInt64_Less(range->lower, work2)) + range->type = ERangeType3; + } else { + range->type = ERangeType3; + } + } +} + +static void ERinvalidAll(void) { + ERecord *record; + + for (record = ERangeFirst; record; record = record->next) + record->range->type = ERangeType3; +} + +static void SetRangesForKillsByIndirectAssignment(IROLinear *nd) { + IROListNode *list; + IROListNode *scan; + IROLinear *inner; + Boolean failed; + IROListNode *resultList; + IROLinear *scannd; + Boolean foundObjRef; + ERecord *record; + ERange *range; + IROListNode *next; + Object *obj; + IROLinear *analysend; + Object *proc; + + failed = 0; + if (nd->type == IROLinearOp2Arg) + inner = nd->u.diadic.left; + else + inner = nd->u.monadic; + + if ( + inner && + inner->type == IROLinearOp1Arg && + inner->nodetype == EINDIRECT && + (analysend = inner->u.monadic) && + copts.opt_pointer_analysis && + analysend->pointsToFunction && + (proc = FunctionName) + ) { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(proc, analysend, &resultList); + + if ((list = resultList)) { + for (scan = list; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + failed = 1; + break; + } + + foundObjRef = 0; + for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + foundObjRef = 1; + break; + } + } + + if (!foundObjRef) { + failed = 1; + break; + } + } + + if (!failed) { + for (; list; list = list->nextList) { + for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + obj = scannd->u.node->data.objref; + CError_ASSERT(302, obj != NULL); + + range = nd->x16; + if (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC) + range = inner->x16; + + record = ERecordFound(obj); + if (!record) + ERnewRecord(obj, range); + else + record->range = range; + } + } + } + } + + while (resultList) { + next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + failed = 1; + } + } else { + failed = 1; + } + + if (failed) { + ERinvalidAll(); + nd->x16 = ERnewERange(ERangeType3); + } +} + +static void InvalidateRangesForKillsByFunctionCall(IROLinear *nd) { + IROListNode *scan; + IROLinear *scannd; + Boolean failed; + Boolean foundObjRef; + IROListNode *list; + IROListNode *resultList; + ERecord *record; + IROListNode *next; + Object *obj; + IROLinear *analysend; + Object *proc; + ObjectList *olist; + ObjectList *killList; + + failed = 0; + + if ( + (analysend = nd->u.funccall.linear8) && + copts.opt_pointer_analysis && + analysend->pointsToFunction && + (proc = FunctionName) + ) { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(proc, analysend, &resultList); + + if (resultList) { + for (scan = resultList; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + failed = 1; + break; + } + + foundObjRef = 0; + for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + foundObjRef = 1; + obj = scannd->u.node->data.objref; + CError_ASSERT(385, obj != NULL); + + killList = NULL; + PointerAnalysis_GetFunctionKills(obj, nd, &killList); + + for (olist = killList; olist; olist = olist->next) { + if (!olist->object) { + failed = 1; + break; + } + } + + while (killList) { + olist = killList->next; + IRO_free(killList); + killList = olist; + } + + if (failed) + break; + } + } + + if (!foundObjRef) + failed = 1; + if (failed) + break; + } + + if (!failed) { + for (list = resultList; list; list = list->nextList) { + for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { + if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { + obj = scannd->u.node->data.objref; + killList = NULL; + PointerAnalysis_GetFunctionKills(obj, nd, &killList); + + for (olist = killList; olist; olist = olist->next) { + if ((record = ERecordFound(olist->object))) + record->range->type = ERangeType3; + } + + while (killList) { + olist = killList->next; + IRO_free(killList); + killList = olist; + } + } + } + } + } + + while (resultList) { + next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + failed = 1; + } + } else { + failed = 1; + } + + if (failed) + ERinvalidAll(); +} + +static void ERfoldOperand(IROLinear *nd) { + switch (nd->u.node->type) { + case EOBJREF: + nd->x16 = NULL; + break; + case EINTCONST: + nd->x16 = ERnewERange(ERangeType0); + nd->x16->upper = nd->x16->lower = nd->u.node->data.intval; + break; + case EFLOATCONST: + case ESTRINGCONST: + nd->x16 = ERnewERange(ERangeType0); + break; + } +} + +static Boolean ERfoldExpr(IROLinear *nd) { + ERecord *record; + ERange *range; + IROLinear *tmp; + IROLinear *inner; + Object *obj; + + switch (nd->nodetype) { + case EINDIRECT: + inner = nd->u.monadic; + if (IS_TYPE_INT(nd->rtype)) { + if (inner->type == IROLinearOperand && inner->u.node->type == EOBJREF) { + if (!inner->x16 && (obj = inner->u.node->data.objref)) { + if ((record = ERecordFound(obj))) { + inner->x16 = ERnewERange(ERangeType3); + *inner->x16 = *record->range; + } else { + inner->x16 = ERnewERange(ERangeType3); + inner->x16->upper = cint64_max; + inner->x16->lower = cint64_min; + ERnewRecord(obj, inner->x16); + } + } + nd->x16 = inner->x16; + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } else { + if (inner->type == IROLinearOperand && inner->u.node->type == EOBJREF && !inner->x16) + inner->x16 = ERnewERange(ERangeType3); + nd->x16 = ERnewERange(ERangeType3); + } + break; + case EAND: + case EANDASS: + if (IRO_IsIntConstant(nd->u.diadic.right)) { + CInt64 val = nd->u.diadic.right->u.node->data.intval; + nd->x16 = ERnewERange(ERangeType1); + nd->x16->upper = val; + nd->x16->lower = cint64_zero; + if ( + (range = nd->u.diadic.left->x16) && + range->type != ERangeType3 && + CInt64_LessEqualU(range->upper, val) && + CInt64_LessEqualU(range->lower, val) && + EREandHasNoUse(range, val) && + !IRO_HasSideEffect(nd->u.diadic.left) + ) { + IRO_Dump("eliminating redundant EAND %" PRId32 "; upperBound==0x%x, lowerBound==0x%x, Constant==0x%x\n", + nd->index, + CInt64_GetULong(&range->upper), + CInt64_GetULong(&range->upper), + CInt64_GetULong(&val) + ); + IRO_NopOut(nd->u.diadic.right); + nd->type = IROLinearNop; + nd->expr = NULL; + tmp = nd->u.diadic.left; + nd->u.diadic.left = nd->u.diadic.right; + if (!IRO_LocateFather_Cut_And_Paste(nd, tmp)) { + tmp->flags &= ~IROLF_Reffed; + if (IRO_IsVariable(tmp)) + IRO_NopOut(tmp); + } + } + } else { + if (nd->u.diadic.right->x16) { + nd->x16 = ERnewERange(ERangeType3); + *nd->x16 = *nd->u.diadic.right->x16; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case ELOGNOT: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case ELAND: + case ELOR: + nd->x16 = ERnewERange(ERangeType1); + nd->x16->upper = cint64_one; + nd->x16->lower = cint64_zero; + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EBINNOT: + case EFORCELOAD: + case EXOR: + case EOR: + case EXORASS: + case EORASS: + case ECOMMA: + case ETYPCON: + case EBITFIELD: + case ECOND: + case ENULLCHECK: + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + break; + case EASS: + if (IS_TYPE_INT(nd->rtype)) + nd->x16 = nd->u.diadic.right->x16; + break; + case EMUL: + case EMULV: + case EMULASS: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && + nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + if (IRO_IsUnsignedType(nd->rtype)) { + nd->x16->upper = CInt64_MulU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper); + nd->x16->lower = CInt64_MulU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower); + } else { + nd->x16->upper = CInt64_Mul(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper); + nd->x16->lower = CInt64_Mul(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower); + } + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EDIV: + case EDIVASS: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && + nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + if (!CInt64_IsZero(&nd->u.diadic.right->x16->lower) && !CInt64_IsZero(&nd->u.diadic.right->x16->upper)) { + if (IRO_IsUnsignedType(nd->rtype)) { + nd->x16->upper = CInt64_DivU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); + nd->x16->lower = CInt64_DivU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); + } else { + nd->x16->upper = CInt64_Div(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); + nd->x16->lower = CInt64_Div(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); + } + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EMODULO: + case EMODASS: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && + nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + if (!CInt64_IsZero(&nd->u.diadic.right->x16->lower) && !CInt64_IsZero(&nd->u.diadic.right->x16->upper)) { + if (IRO_IsUnsignedType(nd->rtype)) { + nd->x16->upper = CInt64_ModU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); + nd->x16->lower = CInt64_ModU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); + } else { + nd->x16->upper = CInt64_Mod(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); + nd->x16->lower = CInt64_Mod(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); + } + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EADDV: + case EADD: + case EADDASS: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && + nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + nd->x16->upper = CInt64_Add(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper); + nd->x16->lower = CInt64_Add(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower); + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case ESUBV: + case ESUB: + case ESUBASS: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && + nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + nd->x16->upper = CInt64_Sub(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); + nd->x16->lower = CInt64_Sub(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case ESHL: + case ESHLASS: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && + nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + nd->x16->upper = CInt64_Shl(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper); + nd->x16->lower = CInt64_Shl(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower); + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case ESHR: + case ESHRASS: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && + nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + if (IRO_IsUnsignedType(nd->rtype)) { + nd->x16->upper = CInt64_ShrU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); + nd->x16->lower = CInt64_ShrU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); + } else { + nd->x16->upper = CInt64_Shr(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); + nd->x16->lower = CInt64_Shr(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); + } + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EPOSTINC: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + range = nd->u.monadic->x16; + *nd->x16 = *range; + range->upper = CInt64_Add(range->upper, cint64_one); + range->lower = CInt64_Add(range->lower, cint64_one); + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EPOSTDEC: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + range = nd->u.monadic->x16; + *nd->x16 = *range; + range->upper = CInt64_Sub(range->upper, cint64_one); + range->lower = CInt64_Sub(range->lower, cint64_one); + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EPREINC: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + range = nd->u.monadic->x16; + nd->x16->upper = CInt64_Add(range->upper, cint64_one); + nd->x16->lower = CInt64_Add(range->lower, cint64_one); + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EPREDEC: + if (IS_TYPE_INT(nd->rtype)) { + if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) { + nd->x16 = ERnewERange(ERangeType2); + range = nd->u.monadic->x16; + nd->x16->upper = CInt64_Sub(range->upper, cint64_one); + nd->x16->lower = CInt64_Sub(range->lower, cint64_one); + } else { + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + } + } + ERcheckOverflow(nd->x16, nd->rtype); + break; + case EMONMIN: + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + break; + case EPMODULO: + case EROTL: + case EROTR: + case EBCLR: + case EBTST: + case EBSET: + nd->x16 = ERnewERange(ERangeType3); + nd->x16->upper = cint64_max; + nd->x16->lower = cint64_min; + break; + default: + ERcheckOverflow(nd->x16, nd->rtype); + break; + } + + if ( + (nd->type == IROLinearOp1Arg || nd->type == IROLinearOp2Arg) && + IRO_IsAssignOp[nd->nodetype] && + nd->x16 && + IS_TYPE_INT(nd->rtype) + ) { + IROLinear *x = NULL; + if (nd->type == IROLinearOp2Arg) + x = nd->u.diadic.left; + else if (nd->type == IROLinearOp1Arg) + x = nd->u.monadic; + + if (x->type == IROLinearOp1Arg && + x->nodetype == EINDIRECT && + (x->u.monadic->nodetype == EINDIRECT || x->u.monadic->nodetype == EADD)) { + SetRangesForKillsByIndirectAssignment(nd); + } else { + obj = NULL; + if (x) + obj = IRO_IsVariable(x); + if (!obj) + return 0; + + range = nd->x16; + if (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC) + range = x->x16; + + record = ERecordFound(obj); + if (!record) + ERnewRecord(obj, range); + else + record->range = range; + } + } + + return nd->x16 != NULL; +} + +static Boolean ERfoldLinear(IROLinear *nd) { + nd->x16 = 0; + + switch (nd->type) { + case IROLinearNop: + case IROLinearEnd: + break; + case IROLinearOperand: + ERfoldOperand(nd); + break; + case IROLinearOp1Arg: + case IROLinearOp2Arg: + ERfoldExpr(nd); + break; + case IROLinearFunccall: + InvalidateRangesForKillsByFunctionCall(nd); + break; + case IROLinearAsm: + ERinvalidAll(); + break; + } + + return 0; +} + +Boolean IRO_RangePropagateInFNode(void) { + IRONode *fnode; + IROLinear *nd; + Boolean result; + + result = 0; + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + ERangeFirst = ERangeLast = NULL; + for (nd = fnode->first; nd != fnode->last; nd = nd->next) + ERfoldLinear(nd); + if (ERfoldLinear(nd)) + result = 1; + } + + if (result) { + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + } + + IRO_CheckForUserBreak(); + return result; +} diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroRangePropagation.h b/compiler_and_linker/FrontEnd/Optimizer/IroRangePropagation.h new file mode 100644 index 0000000..96888ac --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroRangePropagation.h @@ -0,0 +1,8 @@ +#ifndef COMPILER_IRORANGEPROPAGATION_H +#define COMPILER_IRORANGEPROPAGATION_H + +#include "IrOptimizer.h" + +extern Boolean IRO_RangePropagateInFNode(void); + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroSubable.c b/compiler_and_linker/FrontEnd/Optimizer/IroSubable.c new file mode 100644 index 0000000..513ac6c --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroSubable.c @@ -0,0 +1,160 @@ +#include "IroSubable.h" +#include "IroLinearForm.h" +#include "IroPropagate.h" +#include "IroUtil.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +static Boolean IsSubableOp[MAXEXPR]; + +void IRO_InitializeIsSubableOpArray(void) { + int i; + + for (i = 0; i < MAXEXPR; i++) + IsSubableOp[i] = 0; + + IsSubableOp[EPOSTINC] = 0; + IsSubableOp[EPOSTDEC] = 0; + IsSubableOp[EPREINC] = 0; + IsSubableOp[EPREDEC] = 0; + IsSubableOp[EINDIRECT] = 0; + IsSubableOp[EMONMIN] = 1; + IsSubableOp[EBINNOT] = 1; + IsSubableOp[ELOGNOT] = 1; + IsSubableOp[EFORCELOAD] = 0; + IsSubableOp[EMUL] = 1; + IsSubableOp[EMULV] = 1; + IsSubableOp[EDIV] = 1; + IsSubableOp[EMODULO] = 1; + IsSubableOp[EADDV] = 1; + IsSubableOp[ESUBV] = 1; + IsSubableOp[EADD] = 1; + IsSubableOp[ESUB] = 1; + IsSubableOp[ESHL] = 1; + IsSubableOp[ESHR] = 1; + IsSubableOp[ELESS] = 0; + IsSubableOp[EGREATER] = 0; + IsSubableOp[ELESSEQU] = 0; + IsSubableOp[EGREATEREQU] = 0; + IsSubableOp[EEQU] = 0; + IsSubableOp[ENOTEQU] = 0; + IsSubableOp[EAND] = 1; + IsSubableOp[EXOR] = 1; + IsSubableOp[EOR] = 1; + IsSubableOp[ELAND] = 0; + IsSubableOp[ELOR] = 0; + IsSubableOp[EASS] = 0; + IsSubableOp[EMULASS] = 0; + IsSubableOp[EDIVASS] = 0; + IsSubableOp[EMODASS] = 0; + IsSubableOp[EADDASS] = 0; + IsSubableOp[ESUBASS] = 0; + IsSubableOp[ESHLASS] = 0; + IsSubableOp[ESHRASS] = 0; + IsSubableOp[EANDASS] = 0; + IsSubableOp[EXORASS] = 0; + IsSubableOp[EORASS] = 0; + IsSubableOp[ECOMMA] = 0; + IsSubableOp[EPMODULO] = 0; + IsSubableOp[EROTL] = 0; + IsSubableOp[EROTR] = 0; + IsSubableOp[EBCLR] = 0; + IsSubableOp[EBTST] = 0; + IsSubableOp[EBSET] = 0; + IsSubableOp[ETYPCON] = 0; + IsSubableOp[EBITFIELD] = 0; + IsSubableOp[EINTCONST] = 0; + IsSubableOp[EFLOATCONST] = 0; + IsSubableOp[ESTRINGCONST] = 0; + IsSubableOp[ECOND] = 0; + IsSubableOp[EFUNCCALL] = 0; + IsSubableOp[EFUNCCALLP] = 0; + IsSubableOp[EOBJREF] = 0; + IsSubableOp[EMFPOINTER] = 0; + IsSubableOp[ENULLCHECK] = 0; + IsSubableOp[EPRECOMP] = 0; + IsSubableOp[ETEMP] = 0; + IsSubableOp[EARGOBJ] = 0; + IsSubableOp[ELOCOBJ] = 0; + IsSubableOp[ELABEL] = 0; + IsSubableOp[ESETCONST] = 0; + IsSubableOp[ENEWEXCEPTION] = 0; + IsSubableOp[ENEWEXCEPTIONARRAY] = 0; + IsSubableOp[EOBJLIST] = 0; + IsSubableOp[EMEMBER] = 0; + IsSubableOp[ETEMPLDEP] = 0; + IsSubableOp[EINSTRUCTION] = 0; + IsSubableOp[EDEFINE] = 0; + IsSubableOp[EREUSE] = 0; + IsSubableOp[EASSBLK] = 0; + IsSubableOp[EVECTOR128CONST] = 0; + IsSubableOp[ECONDASS] = 0; +} + +static int IsSubscript(IROLinear *nd) { + return 0; +} + +Boolean IRO_IsSubableExpression(IROLinear *nd) { + Object *varobj; + Boolean result; + + switch (nd->type) { + case IROLinearOp2Arg: + if (nd->nodetype == EADD || nd->nodetype == ESUB) { + if ( + IRO_IsConstant(nd->u.diadic.right) && + (varobj = IRO_IsVariable(nd->u.diadic.left)) && + varobj->datatype == DLOCAL && + varobj->u.var.info && + !varobj->u.var.info->noregister) + return 0; + + } + result = IsSubableOp[nd->nodetype] && !IsSubscript(nd); + return result; + case IROLinearOp1Arg: + if (IsSubableOp[nd->nodetype] && !IsSubscript(nd)) + return 1; + + if (nd->nodetype == EINDIRECT && !(nd->flags & IROLF_Assigned)) { + if (nd->flags & IROLF_Ind) { + nd = nd->u.monadic; + if (nd->type == IROLinearOperand && + nd->u.node->type == EOBJREF && + nd->u.node->data.objref->datatype == DLOCAL && + nd->u.node->data.objref->u.var.info && + !nd->u.node->data.objref->u.var.info->noregister + ) + return 0; + return 1; + } + + if (IRO_IsVariable(nd) && IRO_IsRegable(nd->u.monadic->u.node->data.objref)) + return 0; + return 1; + } else if (nd->nodetype == ETYPCON && IS_TYPE_INT(nd->rtype) && nd->rtype->size >= nd->u.monadic->rtype->size) { + return 1; + } else { + return 0; + } + case IROLinearOperand: + default: + return 0; + } +} + +Boolean IRO_IsVectorTempCandidate(IROLinear *nd) { + return + ( + nd->type == IROLinearOp1Arg || + nd->type == IROLinearOp2Arg || + nd->type == IROLinearOp3Arg || + nd->type == IROLinearOperand || + nd->type == IROLinearFunccall + ) && ( + (nd->flags & IROLF_LoopInvariant) && + !(nd->flags & IROLF_Ind) + ); +} diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroSubable.h b/compiler_and_linker/FrontEnd/Optimizer/IroSubable.h new file mode 100644 index 0000000..db5f860 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroSubable.h @@ -0,0 +1,10 @@ +#ifndef COMPILER_IROSUBABLE_H +#define COMPILER_IROSUBABLE_H + +#include "IrOptimizer.h" + +extern void IRO_InitializeIsSubableOpArray(void); +extern Boolean IRO_IsSubableExpression(IROLinear *nd); +extern Boolean IRO_IsVectorTempCandidate(IROLinear *nd); + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroTransform.c b/compiler_and_linker/FrontEnd/Optimizer/IroTransform.c new file mode 100644 index 0000000..8a4af16 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroTransform.c @@ -0,0 +1,2794 @@ +#include "IroTransform.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CIRTransform.h" +#include "compiler/CMachine.h" +#include "compiler/CPrep.h" +#include "compiler/CompilerTools.h" +#include "IroDump.h" +#include "IroLinearForm.h" +#include "IroMalloc.h" +#include "IroPointerAnalysis.h" +#include "IROUseDef.h" +#include "IroUtil.h" +#include "IroVars.h" +#include "compiler/enode.h" +#include "compiler/types.h" + +ENodeType ExprType; +ENode *IndirectRef; +Boolean FirstTime; +CInt64 OperandConst; +Object *OperandObject; +ENodeList *FirstAddend; +ENodeList *LastAddend; +static ENodeType AssignmentOp[MAXEXPR]; +static ENodeType ComplementaryOpLogical[MAXEXPR]; +static ENodeType ComplementaryOp[MAXEXPR]; + +// forward decls +static void DoDiadic(IROLinear *nd); + +static int GetTypeSize(Type *type) { + if (type->size == 1) + return 0; + if (type->size == 2) + return 1; + if (type->size == 4) + return 2; + if (type->size == 8) + return 3; + return -1; +} + +void IRO_InitializeAssignmentOpArray(void) { + int i; + + for (i = 0; i < MAXEXPR; i++) + AssignmentOp[i] = MAXEXPR; + + AssignmentOp[EPOSTINC] = MAXEXPR; + AssignmentOp[EPOSTDEC] = MAXEXPR; + AssignmentOp[EPREINC] = MAXEXPR; + AssignmentOp[EPREDEC] = MAXEXPR; + AssignmentOp[EINDIRECT] = MAXEXPR; + AssignmentOp[EMONMIN] = MAXEXPR; + AssignmentOp[EBINNOT] = MAXEXPR; + AssignmentOp[ELOGNOT] = MAXEXPR; + AssignmentOp[EFORCELOAD] = MAXEXPR; + AssignmentOp[EMUL] = EMULASS; + AssignmentOp[EMULV] = MAXEXPR; + AssignmentOp[EDIV] = EDIVASS; + AssignmentOp[EMODULO] = EMODASS; + AssignmentOp[EADDV] = MAXEXPR; + AssignmentOp[ESUBV] = MAXEXPR; + AssignmentOp[EADD] = EADDASS; + AssignmentOp[ESUB] = ESUBASS; + AssignmentOp[ESHL] = ESHLASS; + AssignmentOp[ESHR] = ESHRASS; + AssignmentOp[ELESS] = MAXEXPR; + AssignmentOp[EGREATER] = MAXEXPR; + AssignmentOp[ELESSEQU] = MAXEXPR; + AssignmentOp[EGREATEREQU] = MAXEXPR; + AssignmentOp[EEQU] = MAXEXPR; + AssignmentOp[ENOTEQU] = MAXEXPR; + AssignmentOp[EAND] = EANDASS; + AssignmentOp[EXOR] = EXORASS; + AssignmentOp[EOR] = EORASS; + AssignmentOp[ELAND] = MAXEXPR; + AssignmentOp[ELOR] = MAXEXPR; + AssignmentOp[EASS] = MAXEXPR; + AssignmentOp[EMULASS] = MAXEXPR; + AssignmentOp[EDIVASS] = MAXEXPR; + AssignmentOp[EMODASS] = MAXEXPR; + AssignmentOp[EADDASS] = MAXEXPR; + AssignmentOp[ESUBASS] = MAXEXPR; + AssignmentOp[ESHLASS] = MAXEXPR; + AssignmentOp[ESHRASS] = MAXEXPR; + AssignmentOp[EANDASS] = MAXEXPR; + AssignmentOp[EXORASS] = MAXEXPR; + AssignmentOp[EORASS] = MAXEXPR; + AssignmentOp[ECOMMA] = MAXEXPR; + AssignmentOp[EPMODULO] = MAXEXPR; + AssignmentOp[EROTL] = MAXEXPR; + AssignmentOp[EROTR] = MAXEXPR; + AssignmentOp[EBCLR] = MAXEXPR; + AssignmentOp[EBTST] = MAXEXPR; + AssignmentOp[EBSET] = MAXEXPR; + AssignmentOp[ETYPCON] = MAXEXPR; + AssignmentOp[EBITFIELD] = MAXEXPR; + AssignmentOp[EINTCONST] = MAXEXPR; + AssignmentOp[EFLOATCONST] = MAXEXPR; + AssignmentOp[ESTRINGCONST] = MAXEXPR; + AssignmentOp[ECOND] = MAXEXPR; + AssignmentOp[EFUNCCALL] = MAXEXPR; + AssignmentOp[EFUNCCALLP] = MAXEXPR; + AssignmentOp[EOBJREF] = MAXEXPR; + AssignmentOp[EMFPOINTER] = MAXEXPR; + AssignmentOp[ENULLCHECK] = MAXEXPR; + AssignmentOp[EPRECOMP] = MAXEXPR; + AssignmentOp[ETEMP] = MAXEXPR; + AssignmentOp[EARGOBJ] = MAXEXPR; + AssignmentOp[ELOCOBJ] = MAXEXPR; + AssignmentOp[ELABEL] = MAXEXPR; + AssignmentOp[ESETCONST] = MAXEXPR; + AssignmentOp[ENEWEXCEPTION] = MAXEXPR; + AssignmentOp[ENEWEXCEPTIONARRAY] = MAXEXPR; + AssignmentOp[EOBJLIST] = MAXEXPR; + AssignmentOp[EMEMBER] = MAXEXPR; + AssignmentOp[ETEMPLDEP] = MAXEXPR; + AssignmentOp[EINSTRUCTION] = MAXEXPR; + AssignmentOp[EDEFINE] = MAXEXPR; + AssignmentOp[EREUSE] = MAXEXPR; + AssignmentOp[EASSBLK] = MAXEXPR; + AssignmentOp[EVECTOR128CONST] = MAXEXPR; + AssignmentOp[ECONDASS] = MAXEXPR; +} + +void IRO_InitializeComplementaryOpArray(void) { + int i; + + for (i = 0; i < MAXEXPR; i++) + ComplementaryOp[i] = MAXEXPR; + + ComplementaryOp[EPOSTINC] = EPOSTDEC; + ComplementaryOp[EPOSTDEC] = EPOSTINC; + ComplementaryOp[EPREINC] = EPREDEC; + ComplementaryOp[EPREDEC] = EPREINC; + ComplementaryOp[EINDIRECT] = MAXEXPR; + ComplementaryOp[EMONMIN] = EMONMIN; + ComplementaryOp[EBINNOT] = EBINNOT; + ComplementaryOp[ELOGNOT] = ELOGNOT; + ComplementaryOp[EFORCELOAD] = MAXEXPR; + ComplementaryOp[EMUL] = EDIV; + ComplementaryOp[EMULV] = MAXEXPR; + ComplementaryOp[EDIV] = EMUL; + ComplementaryOp[EMODULO] = MAXEXPR; + ComplementaryOp[EADDV] = ESUBV; + ComplementaryOp[ESUBV] = EADDV; + ComplementaryOp[EADD] = ESUB; + ComplementaryOp[ESUB] = EADD; + ComplementaryOp[ESHL] = ESHR; + ComplementaryOp[ESHR] = ESHL; + ComplementaryOp[ELESS] = EGREATER; + ComplementaryOp[EGREATER] = ELESS; + ComplementaryOp[ELESSEQU] = EGREATEREQU; + ComplementaryOp[EGREATEREQU] = ELESSEQU; + ComplementaryOp[EEQU] = ENOTEQU; + ComplementaryOp[ENOTEQU] = EEQU; + ComplementaryOp[EAND] = EOR; + ComplementaryOp[EXOR] = MAXEXPR; + ComplementaryOp[EOR] = EAND; + ComplementaryOp[ELAND] = ELOR; + ComplementaryOp[ELOR] = ELAND; + ComplementaryOp[EASS] = MAXEXPR; + ComplementaryOp[EMULASS] = EDIVASS; + ComplementaryOp[EDIVASS] = EMULASS; + ComplementaryOp[EMODASS] = MAXEXPR; + ComplementaryOp[EADDASS] = ESUBASS; + ComplementaryOp[ESUBASS] = EADDASS; + ComplementaryOp[ESHLASS] = ESHRASS; + ComplementaryOp[ESHRASS] = ESHLASS; + ComplementaryOp[EANDASS] = EORASS; + ComplementaryOp[EXORASS] = MAXEXPR; + ComplementaryOp[EORASS] = EANDASS; + ComplementaryOp[ECOMMA] = MAXEXPR; + ComplementaryOp[EPMODULO] = MAXEXPR; + ComplementaryOp[EROTL] = EROTR; + ComplementaryOp[EROTR] = EROTL; + ComplementaryOp[EBCLR] = MAXEXPR; + ComplementaryOp[EBTST] = MAXEXPR; + ComplementaryOp[EBSET] = MAXEXPR; + ComplementaryOp[ETYPCON] = MAXEXPR; + ComplementaryOp[EBITFIELD] = MAXEXPR; + ComplementaryOp[EINTCONST] = MAXEXPR; + ComplementaryOp[EFLOATCONST] = MAXEXPR; + ComplementaryOp[ESTRINGCONST] = MAXEXPR; + ComplementaryOp[ECOND] = MAXEXPR; + ComplementaryOp[EFUNCCALL] = MAXEXPR; + ComplementaryOp[EFUNCCALLP] = MAXEXPR; + ComplementaryOp[EOBJREF] = MAXEXPR; + ComplementaryOp[EMFPOINTER] = MAXEXPR; + ComplementaryOp[ENULLCHECK] = MAXEXPR; + ComplementaryOp[EPRECOMP] = MAXEXPR; + ComplementaryOp[ETEMP] = MAXEXPR; + ComplementaryOp[EARGOBJ] = MAXEXPR; + ComplementaryOp[ELOCOBJ] = MAXEXPR; + ComplementaryOp[ELABEL] = MAXEXPR; + ComplementaryOp[ESETCONST] = MAXEXPR; + ComplementaryOp[ENEWEXCEPTION] = MAXEXPR; + ComplementaryOp[ENEWEXCEPTIONARRAY] = MAXEXPR; + ComplementaryOp[EOBJLIST] = MAXEXPR; + ComplementaryOp[EMEMBER] = MAXEXPR; + ComplementaryOp[ETEMPLDEP] = MAXEXPR; + ComplementaryOp[EINSTRUCTION] = MAXEXPR; + ComplementaryOp[EDEFINE] = MAXEXPR; + ComplementaryOp[EREUSE] = MAXEXPR; + ComplementaryOp[EASSBLK] = MAXEXPR; + ComplementaryOp[EVECTOR128CONST] = MAXEXPR; + ComplementaryOp[ECONDASS] = MAXEXPR; +} + +void IRO_InitializeComplementaryOpLogicalArray(void) { + int i; + + for (i = 0; i < MAXEXPR; i++) + ComplementaryOpLogical[i] = MAXEXPR; + + ComplementaryOpLogical[EPOSTINC] = MAXEXPR; + ComplementaryOpLogical[EPOSTDEC] = MAXEXPR; + ComplementaryOpLogical[EPREINC] = MAXEXPR; + ComplementaryOpLogical[EPREDEC] = MAXEXPR; + ComplementaryOpLogical[EINDIRECT] = MAXEXPR; + ComplementaryOpLogical[EMONMIN] = MAXEXPR; + ComplementaryOpLogical[EBINNOT] = MAXEXPR; + ComplementaryOpLogical[ELOGNOT] = ELOGNOT; + ComplementaryOpLogical[EFORCELOAD] = MAXEXPR; + ComplementaryOpLogical[EMUL] = MAXEXPR; + ComplementaryOpLogical[EMULV] = MAXEXPR; + ComplementaryOpLogical[EDIV] = MAXEXPR; + ComplementaryOpLogical[EMODULO] = MAXEXPR; + ComplementaryOpLogical[EADDV] = MAXEXPR; + ComplementaryOpLogical[ESUBV] = MAXEXPR; + ComplementaryOpLogical[EADD] = MAXEXPR; + ComplementaryOpLogical[ESUB] = MAXEXPR; + ComplementaryOpLogical[ESHL] = MAXEXPR; + ComplementaryOpLogical[ESHR] = MAXEXPR; + ComplementaryOpLogical[ELESS] = EGREATEREQU; + ComplementaryOpLogical[EGREATER] = ELESSEQU; + ComplementaryOpLogical[ELESSEQU] = EGREATER; + ComplementaryOpLogical[EGREATEREQU] = ELESS; + ComplementaryOpLogical[EEQU] = ENOTEQU; + ComplementaryOpLogical[ENOTEQU] = EEQU; + ComplementaryOpLogical[EAND] = MAXEXPR; + ComplementaryOpLogical[EXOR] = MAXEXPR; + ComplementaryOpLogical[EOR] = MAXEXPR; + ComplementaryOpLogical[ELAND] = ELOR; + ComplementaryOpLogical[ELOR] = ELAND; + ComplementaryOpLogical[EASS] = MAXEXPR; + ComplementaryOpLogical[EMULASS] = MAXEXPR; + ComplementaryOpLogical[EDIVASS] = MAXEXPR; + ComplementaryOpLogical[EMODASS] = MAXEXPR; + ComplementaryOpLogical[EADDASS] = MAXEXPR; + ComplementaryOpLogical[ESUBASS] = MAXEXPR; + ComplementaryOpLogical[ESHLASS] = MAXEXPR; + ComplementaryOpLogical[ESHRASS] = MAXEXPR; + ComplementaryOpLogical[EANDASS] = MAXEXPR; + ComplementaryOpLogical[EXORASS] = MAXEXPR; + ComplementaryOpLogical[EORASS] = MAXEXPR; + ComplementaryOpLogical[ECOMMA] = MAXEXPR; + ComplementaryOpLogical[EPMODULO] = MAXEXPR; + ComplementaryOpLogical[EROTL] = MAXEXPR; + ComplementaryOpLogical[EROTR] = MAXEXPR; + ComplementaryOpLogical[EBCLR] = MAXEXPR; + ComplementaryOpLogical[EBTST] = MAXEXPR; + ComplementaryOpLogical[EBSET] = MAXEXPR; + ComplementaryOpLogical[ETYPCON] = MAXEXPR; + ComplementaryOpLogical[EBITFIELD] = MAXEXPR; + ComplementaryOpLogical[EINTCONST] = MAXEXPR; + ComplementaryOpLogical[EFLOATCONST] = MAXEXPR; + ComplementaryOpLogical[ESTRINGCONST] = MAXEXPR; + ComplementaryOpLogical[ECOND] = MAXEXPR; + ComplementaryOpLogical[EFUNCCALL] = MAXEXPR; + ComplementaryOpLogical[EFUNCCALLP] = MAXEXPR; + ComplementaryOpLogical[EOBJREF] = MAXEXPR; + ComplementaryOpLogical[EMFPOINTER] = MAXEXPR; + ComplementaryOpLogical[ENULLCHECK] = MAXEXPR; + ComplementaryOpLogical[EPRECOMP] = MAXEXPR; + ComplementaryOpLogical[ETEMP] = MAXEXPR; + ComplementaryOpLogical[EARGOBJ] = MAXEXPR; + ComplementaryOpLogical[ELOCOBJ] = MAXEXPR; + ComplementaryOpLogical[ELABEL] = MAXEXPR; + ComplementaryOpLogical[ESETCONST] = MAXEXPR; + ComplementaryOpLogical[ENEWEXCEPTION] = MAXEXPR; + ComplementaryOpLogical[ENEWEXCEPTIONARRAY] = MAXEXPR; + ComplementaryOpLogical[EOBJLIST] = MAXEXPR; + ComplementaryOpLogical[EMEMBER] = MAXEXPR; + ComplementaryOpLogical[ETEMPLDEP] = MAXEXPR; + ComplementaryOpLogical[EINSTRUCTION] = MAXEXPR; + ComplementaryOpLogical[EDEFINE] = MAXEXPR; + ComplementaryOpLogical[EREUSE] = MAXEXPR; + ComplementaryOpLogical[EASSBLK] = MAXEXPR; + ComplementaryOpLogical[EVECTOR128CONST] = MAXEXPR; + ComplementaryOpLogical[ECONDASS] = MAXEXPR; +} + +static void DoTransformations(IROLinear *nd) { + IROLinear *nd2; + IROLinear *nd3; + IROLinear *nd4; + IROLinear *nd5; + Type *newtype; + SInt32 value; + + if (nd->type == IROLinearOp2Arg) { + switch (nd->nodetype) { + case EASS: + nd2 = nd->u.diadic.right; + if ( + nd2->type == IROLinearOp2Arg && + AssignmentOp[nd2->nodetype] < MAXEXPR && + IRO_TypesEqual(nd->rtype, nd2->rtype) && + IRO_IsVariable(nd3 = nd->u.diadic.left) && + !(nd3->flags & IROLF_BitfieldIndirect) && + IRO_ExprsSame(nd3, nd2->u.diadic.left) + ) + { + nd->nodetype = AssignmentOp[nd2->nodetype]; + nd->u.diadic.right = nd2->u.diadic.right; + IRO_NopOut(nd2->u.diadic.left); + nd2->type = IROLinearNop; + + nd3->flags |= IROLF_Used; + nd3->u.diadic.left->flags |= IROLF_Used; + } + break; + + case EMUL: + if ( + IS_TYPE_INT(nd->rtype) && + IRO_IsPow2(nd->u.diadic.right, &value) + ) + { + nd->nodetype = ESHL; + CInt64_SetLong(&nd->u.diadic.right->u.node->data.intval, value); + } + break; + + case EDIV: + if ( + IS_TYPE_INT(nd->rtype) && + IRO_IsPow2(nd->u.diadic.right, &value) + ) + { + if (IRO_IsUnsignedType(nd->rtype)) { + nd->nodetype = ESHR; + CInt64_SetLong(&nd->u.diadic.right->u.node->data.intval, value); + } else if ( + !IRO_IsUnsignedType(nd->rtype) && + TYPE_INTEGRAL(nd->rtype)->integral != IT_BOOL && + nd->u.diadic.left->nodetype == ETYPCON && + IS_TYPE_INT(nd->u.diadic.left->u.monadic->rtype) && + IRO_IsUnsignedType(nd->u.diadic.left->u.monadic->rtype) && + nd->u.diadic.left->u.monadic->rtype->size < nd->u.diadic.left->rtype->size + ) + { + nd->nodetype = ESHR; + CInt64_SetLong(&nd->u.diadic.right->u.node->data.intval, value); + if (nd->flags & IROLF_Reffed) { + IROLinear *copy = IRO_NewLinear(IROLinearOp1Arg); + memcpy(copy, nd, sizeof(IROLinear)); + copy->type = IROLinearOp1Arg; + copy->nodetype = ETYPCON; + copy->index = IRO_NumLinear++; + copy->rtype = nd->rtype; + IRO_PasteAfter(copy, copy, nd); + IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, copy); + copy->u.monadic = nd; + nd->flags |= IROLF_Reffed; + } + nd->rtype = IRO_UnsignedType(nd->rtype); + newtype = IRO_UnsignedType(nd->u.diadic.right->rtype); + nd->u.diadic.right->u.node->rtype = newtype; + nd->u.diadic.right->rtype = newtype; + nd->u.diadic.left->rtype = IRO_UnsignedType(nd->u.diadic.left->rtype); + } + } + break; + + case EMODULO: + if ( + IS_TYPE_INT(nd->rtype) && + IRO_IsUnsignedType(nd->rtype) && + IRO_IsPow2(nd->u.diadic.right, &value) + ) + { + nd->nodetype = EAND; + nd->u.diadic.right->u.node->data.intval = CInt64_Sub(nd->u.diadic.right->u.node->data.intval, cint64_one); + } + break; + + case EEQU: + if ( + (nd2 = IRO_LocateFather(nd)) && + nd2->nodetype == ETYPCON && + IS_TYPE_INT(nd2->rtype) && + (nd3 = IRO_LocateFather(nd2)) && + nd3->nodetype == ELOGNOT && + (nd4 = IRO_LocateFather(nd3)) && + nd4->nodetype == ETYPCON && + IS_TYPE_INT(nd4->rtype) && + ( + ((nd5 = IRO_LocateFather(nd4)) && nd5->type == IROLinearIf) || + nd5->type == IROLinearIfNot + ) + ) + { + IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd4, nd); + nd->nodetype = ENOTEQU; + nd2->type = IROLinearNop; + nd3->type = IROLinearNop; + nd4->type = IROLinearNop; + } + break; + } + } +} + +static void IRO_SwitchChildren(IROLinear *nd) { + IROLinear *tmp = nd->u.diadic.left; + nd->u.diadic.left = nd->u.diadic.right; + nd->u.diadic.right = tmp; +} + +static void ReplaceExprWithConst(IROLinear *nd, CInt64 val) { + IRO_NopOut(nd); + nd->type = IROLinearOperand; + nd->nodetype = EINTCONST; + nd->u.node = IRO_NewENode(EINTCONST); + nd->u.node->data.intval = val; + nd->u.node->flags = nd->nodeflags; + nd->u.node->rtype = nd->rtype; + + if (IS_TYPE_FLOAT(nd->rtype)) { + nd->u.node->type = EFLOATCONST; + nd->nodetype = EFLOATCONST; + nd->u.node->data.floatval = CMach_CalcFloatConvertFromInt(TYPE(&stsignedlong), val); + } +} + +static void ReplaceExprWithLeftChild(IROLinear *nd) { + IROLinear *left = nd->u.diadic.left; + IROLinear *right = nd->u.diadic.right; + + if (left->rtype == nd->rtype) { + IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, left); + left->flags = nd->flags; + left->nodeflags = nd->nodeflags; + nd->type = IROLinearNop; + IRO_NopOut(right); + } else { + nd->type = IROLinearOp1Arg; + nd->nodetype = ETYPCON; + nd->u.monadic = left; + IRO_NopOut(right); + } +} + +static void ReplaceExprWithRightChild(IROLinear *nd) { + IROLinear *left = nd->u.diadic.left; + IROLinear *right = nd->u.diadic.right; + + if (right->rtype == nd->rtype) { + IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, right); + right->flags = nd->flags; + right->nodeflags = nd->nodeflags; + nd->type = IROLinearNop; + IRO_NopOut(left); + } else { + nd->type = IROLinearOp1Arg; + nd->nodetype = ETYPCON; + nd->u.monadic = right; + IRO_NopOut(left); + } +} + +static void ReplaceExprWithMonaminRight(IROLinear *nd) { + IROLinear *left = nd->u.diadic.left; + IROLinear *right = nd->u.diadic.right; + + if (right->rtype == nd->rtype) { + nd->type = IROLinearOp1Arg; + nd->nodetype = EMONMIN; + nd->u.monadic = right; + IRO_NopOut(left); + } else { + IRO_NopOut(left); + left->type = IROLinearOp1Arg; + left->nodetype = ETYPCON; + left->expr = right->expr; + left->rtype = nd->rtype; + left->u.monadic = right; + nd->type = IROLinearOp1Arg; + nd->nodetype = EMONMIN; + nd->u.monadic = left; + } +} + +static void ReplaceExprWithMonaminLeft(IROLinear *nd) { + IROLinear *left = nd->u.diadic.left; + IROLinear *right = nd->u.diadic.right; + + if (left->rtype == nd->rtype) { + nd->type = IROLinearOp1Arg; + nd->nodetype = EMONMIN; + nd->u.monadic = left; + IRO_NopOut(right); + } else { + IRO_NopOut(right); + right->type = IROLinearOp1Arg; + right->nodetype = ETYPCON; + right->expr = left->expr; + right->rtype = nd->rtype; + right->u.monadic = left; + nd->type = IROLinearOp1Arg; + nd->nodetype = EMONMIN; + nd->u.monadic = right; + } +} + +static void switchFatherLeftMonadic(IROLinear *nd) { + IROLinear *inner = nd->u.monadic; + IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, inner); + nd->u.monadic = inner->u.monadic; + inner->u.monadic = nd; + inner->rtype = nd->rtype; + inner->flags = nd->flags; + inner->nodeflags = nd->nodeflags; + IRO_CutAndPasteAfter(inner, inner, nd); +} + +static void switchFatherLeft(IROLinear *nd, int isRight) { + IROLinear *a; + IROLinear *b; + + a = nd->u.diadic.left; + IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, a); + + if (isRight) { + nd->u.diadic.left = a->u.diadic.left; + a->u.diadic.left = nd; + b = a->u.diadic.right; + } else { + nd->u.diadic.left = a->u.diadic.right; + a->u.diadic.right = nd; + b = a->u.diadic.left; + } + + a->rtype = nd->rtype; + a->flags = nd->flags; + a->nodeflags = nd->nodeflags; + IRO_CutAndPasteAfter(a, a, nd); + IRO_CutAndPasteAfter(IRO_FindFirst(b), b, nd); +} + +static void PickCommonsubAtLeftLeft(IROLinear *nd) { + switchFatherLeft(nd, 0); + ReplaceExprWithRightChild(nd->u.diadic.right); +} + +static void PickCommonsubAtRightLeft(IROLinear *nd) { + switchFatherLeft(nd, 1); + ReplaceExprWithRightChild(nd->u.diadic.right); +} + +static void PickCommonsubAtLeftRight(IROLinear *nd) { + switchFatherLeft(nd, 0); + ReplaceExprWithLeftChild(nd->u.diadic.right); +} + +static void PickCommonsubAtRightRight(IROLinear *nd) { + switchFatherLeft(nd, 1); + ReplaceExprWithLeftChild(nd->u.diadic.right); +} + +static void DoTransformations11(IROLinear *nd) { + IROLinear *left; + IROLinear *right; + int changed; + int compare; + Type *type; + SInt32 tmp1; + SInt32 tmp2; + CInt64 val; + + if (nd->type == IROLinearOp2Arg) { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + if (IS_TYPE_FLOAT(nd->rtype) || IS_TYPE_FLOAT(left->rtype) || IS_TYPE_FLOAT(right->rtype)) + return; + + changed = 0; + if (!IRO_HasSideEffect(left) && !IRO_HasSideEffect(right)) { + if (IRO_IsIntConstant(right) || IRO_IsFloatConstant(right)) { + if (IRO_IsConstantZero(right)) { + switch (nd->nodetype) { + case EADDV: + case ESUBV: + case EADD: + case ESUB: + case ESHL: + case ESHR: + case EXOR: + case EOR: + case ELOR: + case EADDASS: + case ESUBASS: + case ESHLASS: + case ESHRASS: + case EXORASS: + case EORASS: + ReplaceExprWithLeftChild(nd); + changed = 1; + break; + case EMUL: + case EAND: + case ELAND: + ReplaceExprWithConst(nd, cint64_zero); + changed = 1; + break; + case EMULASS: + case EANDASS: + nd->nodetype = EASS; + nd->u.diadic.right->rtype = nd->rtype; + nd->u.diadic.right->u.node->rtype = nd->rtype; + changed = 1; + break; + case EDIV: + case EMODULO: + case EDIVASS: + case EMODASS: + if (nd->stmt->sourceoffset) { + TStreamElement *token = CPrep_CurStreamElement(); + token->tokenoffset = nd->stmt->sourceoffset; + CError_SetErrorToken(token); + } + CError_Warning(CErrorStr139); + break; + } + } else if (nd->nodetype == ELAND) { + ReplaceExprWithLeftChild(nd); + changed = 1; + } else if (nd->nodetype == ELOR) { + ReplaceExprWithConst(nd, cint64_one); + changed = 1; + } else if (nd->nodetype == ESHL || nd->nodetype == ESHR || nd->nodetype == ESHLASS || nd->nodetype == ESHRASS) { + type = nd->rtype; + tmp1 = type->size * 8; + if (left->type == IROLinearOp1Arg && left->nodetype == ETYPCON) { + type = left->u.monadic->rtype; + if ( + left->u.monadic->type == IROLinearOp1Arg && + left->u.monadic->nodetype == EINDIRECT && + left->u.monadic->u.monadic->type == IROLinearOp1Arg && + left->u.monadic->u.monadic->nodetype == EBITFIELD && + IS_TYPE_BITFIELD(left->u.monadic->u.monadic->rtype) + ) + tmp2 = TYPE_BITFIELD(left->u.monadic->u.monadic->rtype)->bitlength; + else + tmp2 = type->size * 8; + } else { + tmp2 = tmp1; + } + + switch (nd->nodetype) { + case ESHL: + case ESHLASS: + CInt64_SetLong(&val, tmp1); + if (IRO_IsUnsignedType(type)) + compare = CInt64_GreaterEqualU(right->u.node->data.intval, val); + else + compare = CInt64_GreaterEqual(right->u.node->data.intval, val); + break; + case ESHR: + case ESHRASS: + CInt64_SetLong(&val, tmp2); + compare = IRO_IsUnsignedType(type) && CInt64_GreaterEqualU(right->u.node->data.intval, val); + break; + } + + if (compare) { + switch (nd->nodetype) { + case ESHL: + case ESHR: + ReplaceExprWithConst(nd, cint64_zero); + break; + case ESHLASS: + case ESHRASS: + nd->nodetype = EASS; + ReplaceExprWithConst(right, cint64_zero); + break; + } + changed = 1; + } + } else if (IRO_IsConstantOne(right)) { + switch (nd->nodetype) { + case EMUL: + case EMULV: + case EDIV: + case EMULASS: + case EDIVASS: + ReplaceExprWithLeftChild(nd); + changed = 1; + break; + case EMODULO: + ReplaceExprWithConst(nd, cint64_zero); + changed = 1; + break; + case EMODASS: + nd->nodetype = EASS; + ReplaceExprWithConst(right, cint64_zero); + nd->u.diadic.right->rtype = nd->rtype; + nd->u.diadic.right->u.node->rtype = nd->rtype; + changed = 1; + break; + } + } else if (IRO_IsConstantNegativeOne(right)) { + switch (nd->nodetype) { + case EMUL: + case EMULV: + case EDIV: + ReplaceExprWithMonaminLeft(nd); + changed = 1; + break; + case EMODULO: + ReplaceExprWithConst(nd, cint64_zero); + changed = 1; + break; + case EMODASS: + nd->nodetype = EASS; + ReplaceExprWithConst(right, cint64_zero); + nd->u.diadic.right->rtype = nd->rtype; + nd->u.diadic.right->u.node->rtype = nd->rtype; + changed = 1; + break; + } + } + } + + if (!changed && (IRO_IsIntConstant(left) || IRO_IsFloatConstant(left))) { + if (IRO_IsConstantZero(left)) { + switch (nd->nodetype) { + case EADDV: + case EADD: + case EXOR: + case EOR: + case ELOR: + ReplaceExprWithRightChild(nd); + break; + case EMUL: + case ESHL: + case ESHR: + case EAND: + case ELAND: + ReplaceExprWithConst(nd, cint64_zero); + break; + case ESUBV: + case ESUB: + ReplaceExprWithMonaminRight(nd); + break; + } + } else if (nd->nodetype == ELAND) { + ReplaceExprWithRightChild(nd); + } else if (nd->nodetype == ELOR) { + ReplaceExprWithConst(nd, cint64_one); + } else if (IRO_IsConstantOne(left)) { + switch (nd->nodetype) { + case EMUL: + case EMULV: + ReplaceExprWithRightChild(nd); + break; + } + } else if (IRO_IsConstantNegativeOne(left)) { + switch (nd->nodetype) { + case EMUL: + case EMULV: + ReplaceExprWithMonaminRight(nd); + break; + } + } + } + } + } +} + +static void DoTransformations12(IROLinear *nd) { + IROLinear *left; + IROLinear *right; + + if (nd->type == IROLinearOp2Arg) { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + if (IS_TYPE_FLOAT(nd->rtype) || IS_TYPE_FLOAT(left->rtype) || IS_TYPE_FLOAT(right->rtype)) + return; + + if (IRO_ExprsSameSemantically(left, right) && !IRO_HasSideEffect(left)) { + switch (nd->nodetype) { + case ESUBV: + case ESUB: + case ELESS: + case EGREATER: + case ENOTEQU: + case EXOR: + ReplaceExprWithConst(nd, cint64_zero); + break; + case ELESSEQU: + case EGREATEREQU: + case EEQU: + ReplaceExprWithConst(nd, cint64_one); + break; + case EAND: + case EOR: + case ELAND: + case ELOR: + case EASS: + case EANDASS: + case EORASS: + ReplaceExprWithLeftChild(nd); + break; + case ESUBASS: + case EXORASS: + nd->nodetype = EASS; + ReplaceExprWithConst(right, cint64_zero); + break; + } + } + } +} + +static void DoTransformations13(IROLinear *nd) { + IROLinear *left; + IROLinear *right; + IROLinear *left2; + IROLinear *right2; + IROListNode *tmp; + IROListNode *leftlist; + IROListNode *rightlist; + + if (nd->type == IROLinearOp2Arg) { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + + if ( + !IRO_HasSideEffect(left) && + !IRO_HasSideEffect(right) && + (nd->nodetype == EEQU || nd->nodetype == ENOTEQU) && + PointerAnalysis_IsLinearNodePointerExprDefinite(FunctionName, left) && + PointerAnalysis_IsLinearNodePointerExprDefinite(FunctionName, right) + ) + { + leftlist = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, left, &leftlist); + if (leftlist) { + if (leftlist->list.head && leftlist->list.tail && !leftlist->nextList) { + rightlist = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, right, &rightlist); + if (rightlist) { + if (rightlist->list.head && rightlist->list.tail && !rightlist->nextList) { + left2 = leftlist->list.tail; + right2 = rightlist->list.tail; + if (IRO_ExprsSameSemantically(left2, right2)) { + ReplaceExprWithConst(nd, (nd->nodetype == EEQU) ? cint64_one : cint64_zero); + } else if (left2->type == right2->type && IRO_TypesEqual(left2->rtype, right2->rtype)) { + ReplaceExprWithConst(nd, (nd->nodetype == EEQU) ? cint64_zero : cint64_one); + } + } + + while (rightlist) { + tmp = rightlist->nextList; + IRO_free(rightlist); + rightlist = tmp; + } + } + } + + while (leftlist) { + tmp = leftlist->nextList; + IRO_free(leftlist); + leftlist = tmp; + } + } + } + } +} + +static void DoTransformations21(IROLinear *nd) { + IROLinear *left; + IROLinear *right; + Boolean changed; + + if (nd->type == IROLinearOp2Arg) { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + + if (left->type == IROLinearOp1Arg && right->type == IROLinearOp1Arg && left->nodetype == right->nodetype) { + switch (left->nodetype) { + case EMONMIN: + case EBINNOT: + case ELOGNOT: + changed = 0; + switch (nd->nodetype) { + case EXOR: + if (left->nodetype == EBINNOT) + goto collapse; + break; + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + if (left->nodetype == EMONMIN) { + nd->nodetype = ComplementaryOp[nd->nodetype]; + goto collapse; + } + break; + case EMUL: + case EDIV: + if (left->nodetype == EMONMIN) + goto collapse; + break; + case EEQU: + case ENOTEQU: + if (left->nodetype != ELOGNOT) { + collapse: + nd->u.diadic.left = left->u.monadic; + nd->u.diadic.right = right->u.monadic; + left->type = right->type = IROLinearNop; + changed = 1; + } + break; + case ELAND: + case ELOR: + if (left->nodetype == ELOGNOT) { + nd->nodetype = ComplementaryOp[nd->nodetype]; + goto switchfather; + } + break; + case EAND: + case EOR: + if ( + !IS_TYPE_FLOAT(nd->rtype) && + !IS_TYPE_FLOAT(left->rtype) && + !IS_TYPE_FLOAT(right->rtype) && + left->nodetype != EMONMIN + ) + { + nd->nodetype = ComplementaryOp[nd->nodetype]; + goto switchfather; + } + break; + case EADD: + case ESUB: + if ( + !IS_TYPE_FLOAT(nd->rtype) && + !IS_TYPE_FLOAT(left->rtype) && + !IS_TYPE_FLOAT(right->rtype) && + left->nodetype == EMONMIN + ) + { + switchfather: + switchFatherLeftMonadic(nd); + nd->u.diadic.right = right->u.monadic; + right->type = IROLinearNop; + changed = 1; + } + break; + } + + if (changed) { + DoTransformations(nd); + DoTransformations11(nd); + DoTransformations12(nd); + DoTransformations13(nd); + } + break; + } + } + } +} + +static void DoTransformations22(IROLinear *nd) { + IROLinear *left; + IROLinear *right; + IROLinear *ndtmp; + + if (nd->type == IROLinearOp2Arg) { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + if (IS_TYPE_FLOAT(nd->rtype) || IS_TYPE_FLOAT(left->rtype) || IS_TYPE_FLOAT(right->rtype)) + return; + + if (!IRO_HasSideEffect(left) && !IRO_HasSideEffect(right)) { + if (left->type == IROLinearOp1Arg && left->nodetype == EMONMIN) { + switch (nd->nodetype) { + case ESUB: + case ESUBV: + nd->nodetype = ComplementaryOp[nd->nodetype]; + switchFatherLeftMonadic(nd); + break; + + case EADD: + case EADDV: + nd->nodetype = ComplementaryOp[nd->nodetype]; + nd->u.diadic.left = right; + nd->u.diadic.right = left->u.monadic; + left->type = IROLinearNop; + DoTransformations(nd); + DoTransformations12(nd); + DoTransformations21(nd); + break; + + case EDIV: + if (IRO_ExprsSameSemantically(left->u.monadic, right)) + ReplaceExprWithConst(nd, cint64_negone); + break; + } + } else { + ndtmp = NULL; + if (left->type == IROLinearOp1Arg && IRO_ExprsSameSemantically(left->u.monadic, right)) + ndtmp = left; + else if (right->type == IROLinearOp1Arg && IRO_ExprsSameSemantically(left, right->u.monadic)) + ndtmp = right; + + if (ndtmp) { + switch (nd->nodetype) { + case EAND: + if (ndtmp->nodetype == EBINNOT || ndtmp->nodetype == ELOGNOT) + ReplaceExprWithConst(nd, cint64_zero); + break; + + case EANDASS: + if (ndtmp->nodetype == EBINNOT || ndtmp->nodetype == ELOGNOT) { + nd->nodetype = EASS; + ReplaceExprWithConst(right, cint64_zero); + nd->u.diadic.right->rtype = nd->rtype; + nd->u.diadic.right->u.node->rtype = nd->rtype; + } + break; + + case EXOR: + case EOR: + if (ndtmp->nodetype == EBINNOT) { + ReplaceExprWithConst(nd, cint64_zero); + nd->u.node->data.intval = CInt64_Inv(nd->u.node->data.intval); + } + break; + + case EXORASS: + case EORASS: + if (ndtmp->nodetype == EBINNOT) { + nd->nodetype = EASS; + ReplaceExprWithConst(right, cint64_zero); + right->u.node->data.intval = CInt64_Inv(right->u.node->data.intval); + nd->u.diadic.right->rtype = nd->rtype; + nd->u.diadic.right->u.node->rtype = nd->rtype; + } + break; + + case ELOR: + if (ndtmp->nodetype == EBINNOT || ndtmp->nodetype == ELOGNOT) + ReplaceExprWithConst(nd, cint64_one); + break; + + case ELAND: + if (ndtmp->nodetype == ELOGNOT) + ReplaceExprWithConst(nd, cint64_zero); + break; + + case EDIV: + if (ndtmp->nodetype == EMONMIN) + ReplaceExprWithConst(nd, cint64_negone); + break; + + case EDIVASS: + if (ndtmp->nodetype == EMONMIN) { + nd->nodetype = EASS; + ReplaceExprWithConst(right, cint64_negone); + nd->u.diadic.right->rtype = nd->rtype; + nd->u.diadic.right->u.node->rtype = nd->rtype; + } + break; + } + } + } + } + } +} + +static void DoTransformations23(IROLinear *nd) { + Boolean changed; + Boolean isCompare; + UInt8 which; + IROLinear *left; + IROLinear *right; + CInt64 size; + CInt64 val; + + if (nd->type == IROLinearOp2Arg && !IRO_HasSideEffect(nd)) { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + if (IS_TYPE_FLOAT(nd->rtype) || IS_TYPE_FLOAT(left->rtype) || IS_TYPE_FLOAT(right->rtype)) + return; + + isCompare = 0; + changed = 0; + which = 0; + + switch (nd->nodetype) { + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + isCompare = 1; + case EADDV: + case EADD: + case EEQU: + case ENOTEQU: + case EAND: + case EOR: + if (left->type == IROLinearOp2Arg) { + if (IRO_ExprsSameSemantically(right, left->u.diadic.left)) + which = 1; + else if (IRO_ExprsSameSemantically(right, left->u.diadic.right)) + which = 2; + + if (which) { + if (isCompare) + nd->nodetype = ComplementaryOp[nd->nodetype]; + IRO_SwitchChildren(nd); + left = nd->u.diadic.left; + right = nd->u.diadic.right; + break; + } + } + case ESUBV: + case ESUB: + case EADDASS: + case ESUBASS: + case EANDASS: + case EORASS: + if (right->type == IROLinearOp2Arg) { + if (IRO_ExprsSameSemantically(left, right->u.diadic.left)) + which = 1; + else if (IRO_ExprsSameSemantically(left, right->u.diadic.right)) + which = 2; + } + break; + + default: + goto done; + } + + if (which) { + switch (right->nodetype) { + case EAND: + case EOR: + if (which == 2) + IRO_SwitchChildren(right); + + if ( + nd->nodetype == right->nodetype || + (nd->nodetype == EANDASS && right->nodetype == EAND) || + (nd->nodetype == EORASS && right->nodetype == EOR) + ) + { + ReplaceExprWithRightChild(right); + changed = 1; + } + else if ( + nd->nodetype == ComplementaryOp[right->nodetype] || + (nd->nodetype == EANDASS && right->nodetype == EOR) || + (nd->nodetype == EORASS && right->nodetype == EAND) + ) + { + ReplaceExprWithLeftChild(nd); + } + break; + + case EADD: + if (which == 2) + IRO_SwitchChildren(right); + + switch (nd->nodetype) { + case EEQU: + case ENOTEQU: + ReplaceExprWithConst(left, cint64_zero); + ReplaceExprWithRightChild(right); + IRO_SwitchChildren(nd); + if (isCompare) + nd->nodetype = ComplementaryOp[nd->nodetype]; + changed = 1; + break; + + case ESUB: + case ESUBV: + ReplaceExprWithRightChild(right); + ReplaceExprWithMonaminRight(nd); + changed = 1; + break; + + case ESUBASS: + ReplaceExprWithRightChild(right); + changed = 1; + break; + } + break; + + case ESUB: + switch (nd->nodetype) { + case EEQU: + case ENOTEQU: + if (which == 1) { + ReplaceExprWithConst(left, cint64_zero); + ReplaceExprWithRightChild(right); + IRO_SwitchChildren(nd); + } + break; + case EADD: + case EADDV: + if (which == 2) { + ReplaceExprWithLeftChild(right); + ReplaceExprWithRightChild(nd); + } + break; + case ESUB: + case ESUBV: + if (which == 1) { + ReplaceExprWithRightChild(right); + ReplaceExprWithRightChild(nd); + } + break; + case EADDASS: + if (which == 2) { + nd->nodetype = EASS; + ReplaceExprWithLeftChild(right); + changed = 1; + } + break; + case ESUBASS: + if (which == 1) { + nd->nodetype = EASS; + ReplaceExprWithRightChild(right); + changed = 1; + } + break; + } + break; + } + } + + done: + if (!changed) { + switch (nd->nodetype) { + case ESUB: + case ESUBV: + which = 0; + if (left->type == IROLinearOp2Arg) { + if (IRO_ExprsSameSemantically(right, left->u.diadic.left)) + which = 1; + else if (IRO_ExprsSameSemantically(right, left->u.diadic.right)) + which = 2; + } + + if (which == 1) { + if (left->nodetype == ESUB) { + ReplaceExprWithMonaminRight(left); + ReplaceExprWithLeftChild(nd); + } else if (left->nodetype == EADD) { + ReplaceExprWithRightChild(left); + ReplaceExprWithLeftChild(nd); + } + } else if (which == 2) { + if (left->nodetype == EADD) { + ReplaceExprWithLeftChild(left); + ReplaceExprWithLeftChild(nd); + } + } + break; + } + + switch (nd->nodetype) { + case ESHL: + case ESHR: + case ESHLASS: + case ESHRASS: + which = 0; + if (left->type == IROLinearOp2Arg) { + if (left->nodetype == ComplementaryOp[nd->nodetype] || left->nodetype == AssignmentOp[ComplementaryOp[nd->nodetype]]) { + if (IRO_IsIntConstant(right) && IRO_ExprsSameSemantically(right, left->u.diadic.right)) + which = 2; + } + } + + if (which == 2) { + val = right->u.node->data.intval; + if (left->nodetype == ESHR || left->nodetype == ESHRASS) { + ReplaceExprWithLeftChild(left); + nd->nodetype = (nd->nodetype == ESHL) ? EAND : EANDASS; + right->u.node->data.intval = CInt64_Shl(cint64_negone, val); + changed = 1; + } else if (IRO_IsUnsignedType(nd->rtype)) { + ReplaceExprWithLeftChild(left); + nd->nodetype = (nd->nodetype == ESHR) ? EAND : EANDASS; + if (nd->rtype->size < 8) { + CInt64_SetLong(&size, 64 - 8 * nd->rtype->size); + val = CInt64_Add(val, size); + } + right->u.node->data.intval = CInt64_ShrU(cint64_negone, val); + changed = 1; + } + } + break; + } + } + + if (changed) { + DoTransformations(nd); + DoTransformations11(nd); + DoTransformations12(nd); + DoTransformations13(nd); + DoTransformations21(nd); + DoTransformations22(nd); + DoTransformations23(nd); + } + } +} + +static void DoTransformations24(IROLinear *nd) { + IROLinear *left; + IROLinear *right; + UInt8 changed; + + if (nd->type == IROLinearOp2Arg) { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + if (IS_TYPE_FLOAT(nd->rtype) || IS_TYPE_FLOAT(left->rtype) || IS_TYPE_FLOAT(right->rtype)) + return; + + if (left->type == IROLinearOp2Arg && right->type == IROLinearOp2Arg && !IRO_HasSideEffect(nd)) { + changed = 0; + + if (IRO_ExprsSameSemantically(left->u.diadic.left, right->u.diadic.left)) { + if (left->nodetype == right->nodetype) { + switch (left->nodetype) { + case EADD: + if (nd->nodetype == ComplementaryOp[left->nodetype]) { + ReplaceExprWithRightChild(left); + ReplaceExprWithRightChild(right); + changed = 1; + } + break; + case ESUB: + if (nd->nodetype == ESUB || nd->nodetype == ESUBV) { + ReplaceExprWithRightChild(left); + ReplaceExprWithRightChild(right); + IRO_SwitchChildren(nd); + changed = 1; + } + break; + case EMUL: + switch (nd->nodetype) { + case EADD: + case ESUB: + PickCommonsubAtLeftLeft(nd); + changed = 3; + break; + } + break; + case EAND: + if (nd->nodetype == EXOR) { + PickCommonsubAtLeftLeft(nd); + changed = 3; + break; + } + case EOR: + if (nd->nodetype == left->nodetype) { + ReplaceExprWithRightChild(left); + changed = 1; + } else if (nd->nodetype == ComplementaryOp[left->nodetype]) { + PickCommonsubAtLeftLeft(nd); + changed = 3; + } + break; + } + } else if (left->nodetype == ComplementaryOp[right->nodetype]) { + switch (nd->nodetype) { + case ESUB: + case ESUBV: + switch (left->nodetype) { + case EADD: + nd->nodetype = ComplementaryOp[nd->nodetype]; + ReplaceExprWithRightChild(left); + ReplaceExprWithRightChild(right); + changed = 1; + break; + case ESUB: + ReplaceExprWithMonaminRight(left); + ReplaceExprWithRightChild(right); + changed = 1; + break; + } + break; + + case EAND: + case EOR: + if (left->nodetype == nd->nodetype) + ReplaceExprWithLeftChild(nd); + else if (right->nodetype == nd->nodetype) + ReplaceExprWithRightChild(nd); + break; + } + } + } else if (IRO_ExprsSameSemantically(left->u.diadic.right, right->u.diadic.left)) { + if (left->nodetype == right->nodetype) { + switch (left->nodetype) { + case EADD: + if (nd->nodetype == ComplementaryOp[left->nodetype]) { + ReplaceExprWithLeftChild(left); + ReplaceExprWithRightChild(right); + changed = 1; + } + break; + case EMUL: + switch (nd->nodetype) { + case EADD: + case ESUB: + PickCommonsubAtRightLeft(nd); + changed = 3; + break; + } + break; + case EAND: + if (nd->nodetype == EXOR) { + PickCommonsubAtRightLeft(nd); + changed = 3; + break; + } + case EOR: + if (nd->nodetype == left->nodetype) { + ReplaceExprWithLeftChild(left); + changed = 1; + } else if (nd->nodetype == ComplementaryOp[left->nodetype]) { + PickCommonsubAtRightLeft(nd); + changed = 3; + } + break; + } + } else if (left->nodetype == ComplementaryOp[right->nodetype]) { + switch (nd->nodetype) { + case ESUB: + case ESUBV: + if (left->nodetype == EADD) { + nd->nodetype = ComplementaryOp[nd->nodetype]; + ReplaceExprWithLeftChild(left); + ReplaceExprWithRightChild(right); + changed = 1; + } + break; + + case EADD: + case EADDV: + if (left->nodetype == ESUB) { + ReplaceExprWithLeftChild(left); + ReplaceExprWithRightChild(right); + changed = 1; + } + break; + + case EAND: + case EOR: + if (left->nodetype == nd->nodetype) + ReplaceExprWithLeftChild(nd); + else if (right->nodetype == nd->nodetype) + ReplaceExprWithRightChild(nd); + break; + } + } + } else if (IRO_ExprsSameSemantically(left->u.diadic.left, right->u.diadic.right)) { + if (left->nodetype == right->nodetype) { + switch (left->nodetype) { + case EADD: + if (nd->nodetype == ComplementaryOp[left->nodetype]) { + ReplaceExprWithRightChild(left); + ReplaceExprWithLeftChild(right); + changed = 1; + } + break; + case ESUB: + switch (nd->nodetype) { + case EADDV: + case EADD: + nd->nodetype = ComplementaryOp[nd->nodetype]; + ReplaceExprWithRightChild(left); + ReplaceExprWithLeftChild(right); + IRO_SwitchChildren(nd); + changed = 1; + break; + } + break; + case EMUL: + switch (nd->nodetype) { + case EADD: + case ESUB: + PickCommonsubAtLeftRight(nd); + changed = 2; + break; + } + break; + case EAND: + if (nd->nodetype == EXOR) { + PickCommonsubAtLeftRight(nd); + changed = 2; + break; + } + case EOR: + if (nd->nodetype == left->nodetype) { + ReplaceExprWithRightChild(left); + changed = 1; + } else if (nd->nodetype == ComplementaryOp[left->nodetype]) { + PickCommonsubAtLeftRight(nd); + changed = 2; + } + break; + } + } else if (left->nodetype == ComplementaryOp[right->nodetype]) { + switch (nd->nodetype) { + case EADD: + case EADDV: + if (left->nodetype == EADD) { + ReplaceExprWithRightChild(left); + ReplaceExprWithLeftChild(right); + changed = 1; + } + break; + + case ESUB: + case ESUBV: + if (left->nodetype == ESUB) { + ReplaceExprWithMonaminRight(left); + ReplaceExprWithRightChild(right); + changed = 1; + } + break; + + case EAND: + case EOR: + if (left->nodetype == nd->nodetype) + ReplaceExprWithLeftChild(nd); + else if (right->nodetype == nd->nodetype) + ReplaceExprWithRightChild(nd); + break; + } + } + } else if (IRO_ExprsSameSemantically(left->u.diadic.right, right->u.diadic.right)) { + if (left->nodetype == right->nodetype) { + switch (nd->nodetype) { + case ESUB: + switch (left->nodetype) { + case EADD: + case ESUB: + ReplaceExprWithLeftChild(left); + ReplaceExprWithLeftChild(right); + changed = 1; + } + case EADD: + switch (left->nodetype) { + case EMUL: + case ESHL: + PickCommonsubAtRightRight(nd); + changed = 2; + break; + } + break; + case EXOR: + switch (left->nodetype) { + case ESHL: + case ESHR: + case EAND: + PickCommonsubAtRightRight(nd); + changed = 2; + break; + } + break; + case EAND: + case EOR: + if (left->nodetype == nd->nodetype) { + ReplaceExprWithLeftChild(right); + changed = 1; + } else if ( + left->nodetype == ComplementaryOp[nd->nodetype] || + left->nodetype == ESHR || + left->nodetype == ESHL + ) + { + PickCommonsubAtRightRight(nd); + changed = 2; + } + break; + } + } else if (left->nodetype == ComplementaryOp[right->nodetype]) { + switch (nd->nodetype) { + case EADD: + case EADDV: + switch (left->nodetype) { + case EADD: + case ESUB: + ReplaceExprWithLeftChild(left); + ReplaceExprWithLeftChild(right); + changed = 1; + break; + } + break; + + case EAND: + case EOR: + if (left->nodetype == nd->nodetype) + ReplaceExprWithLeftChild(nd); + else if (right->nodetype == nd->nodetype) + ReplaceExprWithRightChild(nd); + break; + } + } + } + + if (changed) { + DoDiadic(nd); + if (changed == 2) + DoDiadic(nd->u.diadic.left); + else if (changed == 3) + DoDiadic(nd->u.diadic.right); + IRO_Dump("remove common op at: %d\n", nd->index); + } + } + } +} + +static void DoTransformations25(IROLinear *nd) { + int changed = 0; + IROLinear *left; + IROLinear *right; + + if (nd->type == IROLinearOp2Arg) { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + + if ( + (left->type == IROLinearOp2Arg && (IS_TYPE_FLOAT(left->u.diadic.left->rtype) || IS_TYPE_FLOAT(left->u.diadic.right->rtype))) || + (right->type == IROLinearOp2Arg && (IS_TYPE_FLOAT(right->u.diadic.left->rtype) || IS_TYPE_FLOAT(right->u.diadic.right->rtype))) + ) + return; + + switch (left->nodetype) { + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + switch (nd->nodetype) { + case EEQU: + if (IRO_IsConstantOne(right)) { + ReplaceExprWithLeftChild(nd); + changed = 1; + } else if (IRO_IsConstantZero(right)) { + left->nodetype = ComplementaryOpLogical[left->nodetype]; + ReplaceExprWithLeftChild(nd); + changed = 1; + } + break; + case ENOTEQU: + if (IRO_IsConstantOne(right)) { + left->nodetype = ComplementaryOpLogical[left->nodetype]; + ReplaceExprWithLeftChild(nd); + changed = 1; + } else if (IRO_IsConstantZero(right)) { + ReplaceExprWithLeftChild(nd); + changed = 1; + } + break; + } + break; + case ELAND: + case ELOR: + switch (nd->nodetype) { + case EEQU: + if (IRO_IsConstantOne(right)) { + ReplaceExprWithLeftChild(nd); + changed = 1; + } + break; + case ENOTEQU: + if (IRO_IsConstantZero(right)) { + ReplaceExprWithLeftChild(nd); + changed = 1; + } + break; + } + break; + } + + if (!changed) { + switch (right->nodetype) { + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + switch (nd->nodetype) { + case EEQU: + if (IRO_IsConstantOne(left)) { + ReplaceExprWithRightChild(nd); + } else if (IRO_IsConstantZero(left)) { + right->nodetype = ComplementaryOpLogical[right->nodetype]; + ReplaceExprWithRightChild(nd); + } + break; + case ENOTEQU: + if (IRO_IsConstantOne(left)) { + right->nodetype = ComplementaryOpLogical[right->nodetype]; + ReplaceExprWithRightChild(nd); + } else if (IRO_IsConstantZero(left)) { + ReplaceExprWithRightChild(nd); + } + break; + } + break; + case ELAND: + case ELOR: + switch (nd->nodetype) { + case EEQU: + if (IRO_IsConstantOne(left)) { + ReplaceExprWithRightChild(nd); + } + break; + case ENOTEQU: + if (IRO_IsConstantZero(left)) { + ReplaceExprWithRightChild(nd); + } + break; + } + break; + } + } + } +} + +static Boolean isOrderingOperator(ENodeType op) { + switch (op) { + case ELAND: + case ELOR: + case ECOMMA: + case ECOND: + case ECONDASS: + return 1; + default: + return 0; + } +} + +static void RemoveUnreffed(IROLinear *nd) { + if (!(nd->flags & IROLF_Reffed)) { + switch (nd->type) { + case IROLinearOperand: + IRO_NopNonSideEffects(nd, 0); + break; + case IROLinearOp1Arg: + case IROLinearOp2Arg: + case IROLinearOp3Arg: + case IROLinearFunccall: + if (!isOrderingOperator(nd->nodetype)) + IRO_NopNonSideEffects(nd, 0); + break; + } + } +} + +static void RemoveRedundantMonadicOp(IROLinear *nd) { + IROLinear *nd2; + IROLinear *nd3; + + if (nd->type == IROLinearOp1Arg && (nd2 = IRO_LocateFather(nd)) && nd2->nodetype == nd->nodetype) { + switch (nd->nodetype) { + case ELOGNOT: + if ((nd3 = IRO_LocateFather(nd2))) { + if ( + nd3->rtype && + TYPE_INTEGRAL(nd3->rtype)->integral == IT_BOOL && + nd->u.monadic->rtype && + TYPE_INTEGRAL(nd->u.monadic->rtype)->integral == IT_BOOL + ) + goto remove; + + if (nd3->type == IROLinearIf) + goto remove; + if (nd3->type == IROLinearIfNot) + goto remove; + if (nd3->type == IROLinearOp3Arg && nd == nd3->u.args3.a) + goto remove; + + switch (nd3->nodetype) { + case ELOGNOT: + case ELAND: + case ELOR: + goto remove; + } + } + + if (nd->u.monadic->type == IROLinearOp1Arg || nd->u.monadic->type == IROLinearOp2Arg) { + switch (nd->u.monadic->nodetype) { + case ELOGNOT: + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + case ELAND: + case ELOR: + goto remove; + } + } + break; + + case EMONMIN: + case EBINNOT: + remove: + IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd2, nd->u.monadic); + nd2->type = IROLinearNop; + nd->type = IROLinearNop; + break; + + case ETYPCON: + if (TYPE_INTEGRAL(nd->rtype)->integral == IT_FLOAT) { + switch (TYPE_INTEGRAL(nd2->rtype)->integral) { + case IT_DOUBLE: + case IT_LONGDOUBLE: + switch (TYPE_INTEGRAL(nd->u.monadic->rtype)->integral) { + case IT_BOOL: + case IT_CHAR: + case IT_SCHAR: + case IT_UCHAR: + case IT_SHORT: + case IT_USHORT: + nd->type = IROLinearNop; + nd2->u.monadic = nd->u.monadic; + break; + } + break; + } + } + break; + } + } +} + +static void ReverseOpForMonmin(IROLinear *nd) { + IROLinear *father; + + if ( + nd->type == IROLinearOp1Arg && + nd->nodetype == EMONMIN && + (father = IRO_LocateFather(nd)) && + father->type == IROLinearOp2Arg && + father->u.diadic.right == nd + ) + { + switch (father->nodetype) { + case EADDV: + case ESUBV: + case EADD: + case ESUB: + case EADDASS: + case ESUBASS: + father->nodetype = ComplementaryOp[father->nodetype]; + nd->type = IROLinearNop; + father->u.diadic.right = nd->u.monadic; + break; + } + } +} + +static void DoDiadic(IROLinear *nd) { + RemoveUnreffed(nd); + DoTransformations(nd); + DoTransformations11(nd); + DoTransformations12(nd); + DoTransformations13(nd); + DoTransformations21(nd); + DoTransformations22(nd); + DoTransformations23(nd); + DoTransformations24(nd); + DoTransformations25(nd); +} + +void IRO_DoTransformations(void) { + IROLinear *nd; + + for (nd = IRO_FirstLinear; nd; nd = nd->next) { + switch (nd->type) { + case IROLinearOp2Arg: + DoDiadic(nd); + break; + case IROLinearOp1Arg: + RemoveUnreffed(nd); + RemoveRedundantMonadicOp(nd); + ReverseOpForMonmin(nd); + break; + case IROLinearOperand: + RemoveUnreffed(nd); + break; + } + } + + IRO_CheckForUserBreak(); +} + +static Boolean ReconcileAssignments(IROLinear *nd1, IROLinear *nd2, IROList *list) { + IROLinear *copy; + Boolean result = 0; + int argCount; + int i; + IROLinear *tmp; + + if ( + (nd2->type == IROLinearOp1Arg && nd2->nodetype == ETYPCON) && + !(nd1->type == IROLinearOp1Arg && nd1->nodetype == ETYPCON) && + ReconcileAssignments(nd1, nd2->u.monadic, list) + ) + { + result = 1; + } + + if ( + (nd1->type == IROLinearOp1Arg && nd1->nodetype == ETYPCON) && + !(nd2->type == IROLinearOp1Arg && nd2->nodetype == ETYPCON) && + ReconcileAssignments(nd1->u.monadic, nd2, list) + ) + { + copy = IRO_NewLinear(IROLinearOp1Arg); + *copy = *nd2; + copy->index = IRO_NumLinear++; + copy->type = IROLinearOp1Arg; + copy->nodetype = ETYPCON; + copy->rtype = nd1->rtype; + copy->next = NULL; + copy->u.monadic = list->tail; + IRO_AddToList(copy, list); + result = 1; + } + + if (nd1->type == nd2->type && nd1->nodetype == nd2->nodetype) { + copy = IRO_NewLinear(IROLinearNop); + *copy = *nd2; + copy->index = IRO_NumLinear++; + copy->rtype = nd1->rtype; + copy->next = NULL; + switch (nd1->type) { + case IROLinearOperand: + if (nd1->u.node->type == nd2->u.node->type) { + if (!(nd1->u.node->type == EOBJREF && nd1->u.node->data.objref != nd2->u.node->data.objref)) + result = 1; + } + break; + + case IROLinearOp1Arg: + if (ReconcileAssignments(nd1->u.monadic, nd2->u.monadic, list)) { + copy->u.monadic = list->tail; + result = 1; + } + break; + + case IROLinearOp2Arg: + tmp = list->tail; + if (ReconcileAssignments(nd1->u.diadic.left, nd2->u.diadic.left, list)) { + copy->u.diadic.left = list->tail; + if (ReconcileAssignments(nd1->u.diadic.right, nd2->u.diadic.right, list)) { + copy->u.diadic.right = list->tail; + result = 1; + } + } + + if (!result && !IRO_HasSideEffect(nd1) && !IRO_HasSideEffect(nd2)) { + if (nd1->nodetype == EMUL || nd1->nodetype == EADD || nd1->nodetype == EAND || nd1->nodetype == EXOR || nd1->nodetype == EOR) { + list->tail = tmp; + if (ReconcileAssignments(nd1->u.diadic.left, nd2->u.diadic.right, list)) { + copy->u.diadic.right = list->tail; + if (ReconcileAssignments(nd1->u.diadic.right, nd2->u.diadic.left, list)) { + copy->u.diadic.left = list->tail; + result = 1; + } + } + } + } + break; + + case IROLinearOp3Arg: + if (ReconcileAssignments(nd1->u.args3.c, nd2->u.args3.c, list)) { + copy->u.args3.c = list->tail; + if (ReconcileAssignments(nd1->u.args3.b, nd2->u.args3.b, list)) { + copy->u.args3.b = list->tail; + if (ReconcileAssignments(nd1->u.args3.a, nd2->u.args3.a, list)) { + copy->u.args3.a = list->tail; + result = 1; + } + } + } + break; + + case IROLinearFunccall: + argCount = nd1->u.funccall.argCount; + if (argCount == nd2->u.funccall.argCount) { + result = 1; + copy->u.funccall.args = oalloc(sizeof(IROLinear *) * argCount); + for (i = argCount - 1; i >= 0; i--) { + if (!ReconcileAssignments(nd1->u.funccall.args[i], nd2->u.funccall.args[i], list)) { + result = 0; + break; + } + copy->u.funccall.args[i] = list->tail; + } + + if (result) { + if (!ReconcileAssignments(nd1->u.funccall.linear8, nd2->u.funccall.linear8, list)) { + result = 0; + break; + } + copy->u.funccall.linear8 = list->tail; + } + } + break; + } + + if (result) + IRO_AddToList(copy, list); + } + + return result; +} + +static IROLinear *FrontendTransformSelfAssignmentToAssignment(IROLinear *nd) { + Statement *stmt; + IROList list; + IROLinearIRSave save; + + IRO_SaveLinearIR(&save); + + IRO_InitList(&list); + IRO_DuplicateExpr(nd, &list); + + stmt = IRO_Delinearize(NULL, list.head); + CError_ASSERT(3550, stmt); + CError_ASSERT(3552, stmt->expr); + stmt->expr = CIRTrans_TransformOpAss(stmt->expr); + CError_ASSERT(3557, stmt->expr); + + if (DoLinearize) + IRO_PreLinearize(stmt); + IRO_Linearize(stmt); + + IRO_InitList(&list); + list.head = IRO_FirstLinear; + list.tail = IRO_LastLinear; + + IRO_RestoreLinearIR(&save); + + for (nd = list.head; nd; nd = nd->next) { + if (!(nd->flags & IROLF_Reffed) && IRO_IsAssignment(nd)) + break; + } + + return nd; +} + +static Type *PromotedIntegralType(Type *type) { + CError_ASSERT(3586, IS_TYPE_ENUM(type) || IS_TYPE_INT(type)); + + if (IS_TYPE_ENUM(type)) + type = TYPE_ENUM(type)->enumtype; + + if (TYPE_INTEGRAL(type)->integral < IT_INT) { + if (IRO_IsUnsignedType(type)) + return TYPE(&stunsignedint); + else + return TYPE(&stsignedint); + } else { + return type; + } +} + +static Boolean TransformMonadicSelfAssignmentToDiadicSelfAssignment(IROLinear *nd) { + ENodeType t; + ENodeType newtype; + IROLinear *incExpr; + IROLinear *varExpr; + + t = nd->nodetype; + + if (IRO_IsAssignment(nd) && IRO_IsModifyOp[t]) { + incExpr = NULL; + varExpr = NULL; + newtype = MAXEXPR; + + if ( + nd->type == IROLinearOp1Arg && + (t == EPOSTINC || t == EPOSTDEC || t == EPREINC || t == EPREDEC) && + (!(nd->flags & IROLF_Reffed) || t == EPREINC || t == EPREDEC) + ) + { + Type *type = nd->rtype; + TypeType typetype = type->type; + varExpr = nd->u.monadic; + if (typetype == TYPEINT || typetype == TYPEENUM) { + incExpr = IRO_NewIntConst(cint64_one, PromotedIntegralType(type)); + } else if (typetype == TYPEPOINTER || typetype == TYPEARRAY || typetype == TYPEMEMBERPOINTER) { + Type *inner = NULL; + CInt64 val = cint64_zero; + + if (typetype == TYPEPOINTER || typetype == TYPEARRAY) + inner = TPTR_TARGET(type); + else if (typetype == TYPEMEMBERPOINTER) + inner = TYPE_MEMBER_POINTER(type)->ty1; + + if (inner) + CInt64_SetLong(&val, inner->size); + + if (!CInt64_IsZero(&val)) { + incExpr = IRO_NewIntConst(val, TYPE(&stsignedlong)); + } else { + return 0; + } + } else if (typetype == TYPEFLOAT) { + Float fval; + fval = CMach_CalcFloatConvertFromInt(type, cint64_one); + incExpr = IRO_NewFloatConst(fval, nd->rtype); + } else { + return 0; + } + + if (t == EPOSTINC || t == EPREINC) + newtype = EADDASS; + else + newtype = ESUBASS; + } + + if ( + varExpr && + incExpr && + newtype != MAXEXPR && + varExpr->u.diadic.left && + varExpr->u.diadic.left->type == IROLinearOperand && + varExpr->u.diadic.left->u.node && + varExpr->u.diadic.left->u.node->type == EOBJREF && + !IRO_HasSideEffect(varExpr) + ) + { + incExpr->flags |= IROLF_Reffed; + nd->nodetype = newtype; + nd->u.diadic.right = incExpr; + nd->type = IROLinearOp2Arg; + IRO_Paste(incExpr, incExpr, nd); + return 1; + } + } + + return 0; +} + +Boolean IRO_TransformSelfAssignmentToAssignment(IROLinear *nd) { + ENodeType nonAssOp; + IROLinear *left; + IROLinear *right; + ENodeType nodetype; + IROLinear *nonAss; + IROLinear *dupLeft; + IROLinear *last; + IROList list1; + IROList list2; + + nodetype = nd->nodetype; + if ( + IRO_IsAssignment(nd) && + IRO_IsModifyOp[nodetype] && + nd->type == IROLinearOp1Arg && + TransformMonadicSelfAssignmentToDiadicSelfAssignment(nd) + ) + nodetype = nd->nodetype; + + if ( + IRO_IsAssignment(nd) && + IRO_IsModifyOp[nodetype] && + nd->type == IROLinearOp2Arg && + IRO_NonAssignmentOp[nodetype] != MAXEXPR + ) + { + left = nd->u.diadic.left; + right = nd->u.diadic.right; + nonAssOp = IRO_NonAssignmentOp[nodetype]; + if ( + left && + right && + nonAssOp != MAXEXPR && + left->u.monadic && + left->u.monadic->type == IROLinearOperand && + left->u.monadic->u.node && + left->u.monadic->u.node->type == EOBJREF && + !IRO_HasSideEffect(left) + ) + { + IRO_InitList(&list1); + dupLeft = IRO_DuplicateExpr(left, &list1); + + if (left->rtype != right->rtype) { + IROLinear *tmp = IRO_NewLinear(IROLinearOp1Arg); + tmp->nodetype = ETYPCON; + tmp->flags |= IROLF_Reffed; + tmp->rtype = right->rtype; + tmp->index = ++IRO_NumLinear; + tmp->u.monadic = dupLeft; + IRO_AddToList(tmp, &list1); + dupLeft = tmp; + } + + nonAss = IRO_NewLinear(IROLinearOp2Arg); + nonAss->nodetype = nonAssOp; + nonAss->flags |= IROLF_Reffed; + nonAss->rtype = dupLeft->rtype; + nonAss->index = ++IRO_NumLinear; + nonAss->u.diadic.left = dupLeft; + nonAss->u.diadic.right = right; + IRO_AddToList(nonAss, &list1); + + if (left->rtype != right->rtype) { + IROLinear *tmp = IRO_NewLinear(IROLinearOp1Arg); + tmp->nodetype = ETYPCON; + tmp->flags |= IROLF_Reffed; + tmp->rtype = left->rtype; + tmp->index = ++IRO_NumLinear; + tmp->u.monadic = nonAss; + IRO_AddToList(tmp, &list1); + nonAss = tmp; + } + + IRO_InitList(&list2); + last = FrontendTransformSelfAssignmentToAssignment(nd); + if ( + last && + last->type == IROLinearOp2Arg && + ReconcileAssignments(last->u.diadic.right, nonAss, &list2) + ) + { + IRO_NopOut(nd->u.diadic.right); + nd->nodetype = EASS; + nd->u.diadic.right = list2.tail; + nd->type = IROLinearOp2Arg; + IRO_Paste(list2.head, list2.tail, nd); + return 1; + } + } + } + + return 0; +} + +static void AddAddend(ENode *expr) { + if (expr->type == EADD) { + AddAddend(expr->data.diadic.left); + AddAddend(expr->data.diadic.right); + } else { + ENodeList *list = oalloc(sizeof(ENodeList)); + list->node = expr; + list->next = NULL; + + if (FirstAddend) + LastAddend->next = list; + else + FirstAddend = list; + LastAddend = list; + } +} + +static ENode *CombineConstants(ENode *expr) { + ENode *addend; + ENodeList *el; + ENode *result; + ENode *var; + Type *type; + ENode *tmp; + ENodeList *prev; + CInt64 val; + + FirstAddend = LastAddend = NULL; + AddAddend(expr->data.diadic.left); + AddAddend(expr->data.diadic.right); + + // these variable names are courtesy of the resource fork in abort_exit.c + el = FirstAddend; + prev = NULL; + var = NULL; + while (el) { + addend = el->node; + if (addend->type == EOBJREF) { + var = addend; + if (prev) + prev->next = el->next; + else + FirstAddend = el->next; + break; + } + prev = el; + el = el->next; + } + + if (!var) { + el = FirstAddend; + prev = NULL; + while (el) { + addend = el->node; + if (addend->type == EINDIRECT) { + var = addend; + if (prev) + prev->next = el->next; + else + FirstAddend = el->next; + break; + } + prev = el; + el = el->next; + } + } + + prev = NULL; + CInt64_SetLong(&val, 0); + type = NULL; + + for (el = FirstAddend; el; el = el->next) { + addend = el->node; + if (addend->type == EINTCONST && addend->rtype) { + if (!type || type->size < addend->rtype->size) + type = addend->rtype; + val = CInt64_Add(val, addend->data.intval); + if (prev) + prev->next = el->next; + else + FirstAddend = el->next; + } else if (addend->type == EMUL && addend->data.diadic.right->type == EINTCONST && addend->rtype) { + if (!type || type->size < addend->rtype->size) + type = addend->rtype; + + tmp = addend->data.diadic.left; + if (tmp->type == EADD && tmp->data.diadic.right->type == EINTCONST) { + val = CInt64_Add(val, CInt64_MulU(tmp->data.diadic.right->data.intval, addend->data.diadic.right->data.intval)); + addend->data.diadic.left = tmp->data.diadic.left; + } + prev = el; + } else { + prev = el; + } + } + + result = NULL; + if (var) { + result = var; + if (!CInt64_IsZero(&val)) { + result = IRO_NewENode(EADD); + result->data.diadic.left = var; + result->data.diadic.right = IRO_NewENode(EINTCONST); + result->data.diadic.right->data.intval = val; + result->data.diadic.right->rtype = type; + result->rtype = var->rtype; + result->cost = 1; + CInt64_SetLong(&val, 0); + } + } + + for (el = FirstAddend; el; el = el->next) { + addend = el->node; + if (result) { + tmp = IRO_NewENode(EADD); + tmp->data.diadic.left = result; + tmp->data.diadic.right = addend; + tmp->cost = result->cost + 1; + tmp->rtype = result->rtype; + result = tmp; + } else { + result = addend; + } + } + + if (!CInt64_IsZero(&val)) { + tmp = IRO_NewENode(EADD); + tmp->data.diadic.left = result; + tmp->data.diadic.right = IRO_NewENode(EINTCONST); + tmp->data.diadic.right->data.intval = val; + tmp->data.diadic.right->rtype = type; + tmp->cost = result->cost + 1; + tmp->rtype = result->rtype; + result = tmp; + } + + return result; +} + +static ENode *TransformExprNode(ENode *expr) { + ENode *left; + ENode *right; + + switch (expr->type) { + case EINDIRECT: + if (ENODE_IS(expr->data.monadic, EADD)) + expr->data.monadic = CombineConstants(expr->data.monadic); + break; + + case EMUL: + case EADD: + case EAND: + case EXOR: + case EOR: + if ( + IS_TYPE_INT(expr->rtype) && + !ENODE_IS(right = expr->data.diadic.right, EINTCONST) && + ENODE_IS(left = expr->data.diadic.left, EINTCONST) + ) + { + expr->data.diadic.left = right; + expr->data.diadic.right = left; + } + break; + + case EEQU: + case ENOTEQU: + if ( + IS_TYPE_INT(expr->rtype) && + !ENODE_IS(left = expr->data.diadic.right, EINTCONST) && + ENODE_IS(right = expr->data.diadic.left, EINTCONST) + ) + { + expr->data.diadic.left = left; + expr->data.diadic.right = right; + } + + if ( + ENODE_IS(expr->data.diadic.right, EINTCONST) && + ENODE_IS(left = expr->data.diadic.left, EBINNOT) + ) + { + expr->data.diadic.left = left->data.monadic; + left->data.monadic = expr->data.diadic.right; + expr->data.diadic.right = left; + } + + break; + } + + return expr; +} + +static ENode *TransformExprTree(ENode *expr) { + ENodeList *list; + + switch (expr->type) { + ENODE_CASE_MONADIC: + expr->data.monadic = TransformExprTree(expr->data.monadic); + break; + + ENODE_CASE_DIADIC_ALL: + expr->data.diadic.left = TransformExprTree(expr->data.diadic.left); + expr->data.diadic.right = TransformExprTree(expr->data.diadic.right); + break; + + case EFUNCCALL: + case EFUNCCALLP: + TransformExprTree(expr->data.funccall.funcref); + for (list = expr->data.funccall.args; list; list = list->next) + TransformExprTree(list->node); + break; + + case ECOND: + TransformExprTree(expr->data.cond.cond); + TransformExprTree(expr->data.cond.expr1); + TransformExprTree(expr->data.cond.expr2); + break; + + case ENULLCHECK: + TransformExprTree(expr->data.nullcheck.nullcheckexpr); + TransformExprTree(expr->data.nullcheck.condexpr); + break; + } + + return TransformExprNode(expr); +} + +static void FoldConstantsinAssociativeExprs(ENode *expr) { + short nodetype1; + short nodetype2; + short nodetype3; + Boolean changed; + short op; + CInt64 val1; + CInt64 val2; + CInt64 tmpval; + + if ( + ( + expr->type == EADD || + expr->type == EMUL || + expr->type == EAND || + expr->type == EXOR || + expr->type == EOR || + expr->type == ESHL || + expr->type == ESHR + ) && + IS_TYPE_INT(expr->rtype) && + expr->data.diadic.right->type == EINTCONST + ) + { + do { + changed = 0; + + if ( + expr->data.diadic.left->type == expr->type && + expr->data.diadic.left->data.diadic.right->type == EINTCONST + ) + { + val1 = expr->data.diadic.right->data.intval; + val2 = expr->data.diadic.left->data.diadic.right->data.intval; + switch (expr->type) { + case EADD: + case ESHL: + op = '+'; + break; + case ESHR: + op = '+'; + if (!IRO_IsUnsignedType(expr->rtype)) { + CInt64_SetLong(&tmpval, expr->rtype->size * 8); + if (CInt64_GreaterEqualU(val1, tmpval) || CInt64_GreaterEqualU(val2, tmpval)) + return; + + if (CInt64_GreaterEqualU(CMach_CalcIntDiadic(expr->rtype, val1, '+', val2), tmpval)) { + val1 = CInt64_Sub(tmpval, cint64_one); + val2 = cint64_zero; + } + } + break; + case EMUL: + op = '*'; + break; + case EAND: + op = '&'; + break; + case EOR: + op = '|'; + break; + case EXOR: + op = '^'; + break; + default: + return; + } + + expr->data.diadic.right->data.intval = CMach_CalcIntDiadic(expr->rtype, val1, op, val2); + expr->data.diadic.left = expr->data.diadic.left->data.diadic.left; + changed = 1; + } else if ( + ((nodetype1 = expr->type) == EAND || nodetype1 == EOR) && + ((nodetype2 = expr->data.diadic.left->type) == EAND || nodetype2 == EOR) && + ((nodetype3 = expr->data.diadic.left->data.diadic.left->type) == EAND || nodetype3 == EOR) && + expr->data.diadic.left->data.diadic.left->data.diadic.right->type == EINTCONST + ) + { + val1 = expr->data.diadic.right->data.intval; + if (CInt64_Equal(val1, expr->data.diadic.left->data.diadic.left->data.diadic.right->data.intval)) { + if (nodetype1 == nodetype3) { + expr->data.diadic.left->data.diadic.left = expr->data.diadic.left->data.diadic.left->data.diadic.left; + changed = 1; + } else if (nodetype2 == nodetype3) { + *expr = *expr->data.diadic.right; + changed = 1; + } else { + expr->data.diadic.left = expr->data.diadic.left->data.diadic.right; + changed = 1; + } + } + } + } while (changed); + } +} + +static void TransformExprTree1(ENode *expr) { + ENodeList *list; + + switch (expr->type) { + ENODE_CASE_MONADIC: + TransformExprTree1(expr->data.monadic); + break; + + ENODE_CASE_DIADIC_ALL: + TransformExprTree1(expr->data.diadic.left); + TransformExprTree1(expr->data.diadic.right); + break; + + case EFUNCCALL: + case EFUNCCALLP: + TransformExprTree1(expr->data.funccall.funcref); + for (list = expr->data.funccall.args; list; list = list->next) + TransformExprTree1(list->node); + break; + + case ECOND: + TransformExprTree1(expr->data.cond.cond); + TransformExprTree1(expr->data.cond.expr1); + TransformExprTree1(expr->data.cond.expr2); + break; + + case ENULLCHECK: + TransformExprTree1(expr->data.nullcheck.nullcheckexpr); + TransformExprTree1(expr->data.nullcheck.condexpr); + break; + } + + FoldConstantsinAssociativeExprs(expr); +} + +static int RemoveRedundantBitOperations(ENode *expr) { + Boolean a; + Boolean b; + + if (expr->type == ExprType) { + a = RemoveRedundantBitOperations(expr->data.diadic.left); + b = RemoveRedundantBitOperations(expr->data.diadic.right); + return a & b; + } + + if (expr->type == EINDIRECT) { + if (expr->data.monadic->type == EOBJREF) { + if (!OperandObject) { + OperandObject = expr->data.monadic->data.objref; + IndirectRef = expr; + return 1; + } else { + return expr->data.monadic->data.objref == OperandObject; + } + } else { + return 0; + } + } + + if (expr->type == EINTCONST) { + if (FirstTime) { + OperandConst = expr->data.intval; + FirstTime = 0; + } else if (ExprType == EAND) { + OperandConst = CInt64_And(expr->data.intval, OperandConst); + } else if (ExprType == EOR) { + OperandConst = CInt64_Or(expr->data.intval, OperandConst); + } else if (ExprType == EXOR) { + OperandConst = CInt64_Xor(expr->data.intval, OperandConst); + } + return 1; + } + + return 0; +} + +static void TransformExprTree2(ENode *expr) { + ENodeList *list; + + switch (expr->type) { + ENODE_CASE_MONADIC: + TransformExprTree2(expr->data.monadic); + break; + + ENODE_CASE_DIADIC_ALL: + TransformExprTree2(expr->data.diadic.left); + TransformExprTree2(expr->data.diadic.right); + break; + + case EFUNCCALL: + case EFUNCCALLP: + TransformExprTree2(expr->data.funccall.funcref); + for (list = expr->data.funccall.args; list; list = list->next) + TransformExprTree2(list->node); + break; + + case ECOND: + TransformExprTree2(expr->data.cond.cond); + TransformExprTree2(expr->data.cond.expr1); + TransformExprTree2(expr->data.cond.expr2); + break; + + case ENULLCHECK: + TransformExprTree2(expr->data.nullcheck.nullcheckexpr); + TransformExprTree2(expr->data.nullcheck.condexpr); + break; + } + + if ( + ENODE_IS3(expr, EAND, EOR, EXOR) && + (expr->type == expr->data.diadic.left->type || expr->type == expr->data.diadic.right->type) + ) + { + OperandObject = NULL; + ExprType = expr->type; + FirstTime = 1; + IndirectRef = NULL; + + if (RemoveRedundantBitOperations(expr)) { + expr->data.diadic.left = IndirectRef; + expr->data.diadic.right->type = EINTCONST; + expr->data.diadic.right->data.intval = OperandConst; + } + } +} + +static void PullOutPostOps(Statement *stmt, ENode **pExpr) { + ENode *ind; + ENode *inner; + Statement *newStmt; + + switch ((*pExpr)->type) { + ENODE_CASE_MONADIC: + if ((*pExpr)->type != EFORCELOAD) + PullOutPostOps(stmt, &(*pExpr)->data.monadic); + + if (ENODE_IS2(*pExpr, EPOSTINC, EPOSTDEC)) { + inner = (*pExpr)->data.monadic; + if ( + ENODE_IS(inner, EINDIRECT) && + inner->rtype && + !CParser_IsVolatile(inner->rtype, ENODE_QUALS(inner)) && + ENODE_IS(inner->data.monadic, EOBJREF) && + !is_volatile_object(inner->data.monadic->data.objref) + ) + { + newStmt = lalloc(sizeof(Statement)); + memset(newStmt, 0, sizeof(Statement)); + newStmt->type = ST_EXPRESSION; + newStmt->expr = *pExpr; + newStmt->dobjstack = stmt->dobjstack; + newStmt->sourceoffset = stmt->sourceoffset; + newStmt->sourcefilepath = stmt->sourcefilepath; + newStmt->value = stmt->value; + newStmt->flags = stmt->flags; + newStmt->next = stmt->next; + stmt->next = newStmt; + + ind = IRO_NewENode(EINDIRECT); + *ind = *inner; + ind->data.monadic = IRO_NewENode(EOBJREF); + *ind->data.monadic = *inner->data.monadic; + *pExpr = ind; + } + } + break; + + ENODE_CASE_DIADIC_ALL: + if (ENODE_IS(*pExpr, ECOND)) + break; + if (ENODE_IS(*pExpr, ECOMMA)) + break; + if (ENODE_IS(*pExpr, ELOR)) + break; + if (ENODE_IS(*pExpr, ELAND)) + break; + if (ENODE_IS(*pExpr, ENULLCHECK)) + break; + PullOutPostOps(stmt, &(*pExpr)->data.diadic.left); + PullOutPostOps(stmt, &(*pExpr)->data.diadic.right); + break; + } +} + +void IRO_TransformTree(Statement *statements) { + Statement *stmt; + Statement *next; + + for (stmt = statements; stmt; stmt = next) { + next = stmt->next; + switch (stmt->type) { + case ST_EXPRESSION: + case ST_SWITCH: + case ST_IFGOTO: + case ST_IFNGOTO: + case ST_RETURN: + if (stmt->expr) { + stmt->expr = TransformExprTree(stmt->expr); + TransformExprTree2(stmt->expr); + TransformExprTree1(stmt->expr); + } + break; + } + } + + IRO_CheckForUserBreak(); +} diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroTransform.h b/compiler_and_linker/FrontEnd/Optimizer/IroTransform.h new file mode 100644 index 0000000..104657f --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroTransform.h @@ -0,0 +1,13 @@ +#ifndef COMPILER_IROTRANSFORM_H +#define COMPILER_IROTRANSFORM_H + +#include "IrOptimizer.h" + +extern void IRO_InitializeAssignmentOpArray(void); +extern void IRO_InitializeComplementaryOpArray(void); +extern void IRO_InitializeComplementaryOpLogicalArray(void); +extern void IRO_DoTransformations(void); +extern Boolean IRO_TransformSelfAssignmentToAssignment(IROLinear *nd); +extern void IRO_TransformTree(Statement *statements); + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroUnrollLoop.c b/compiler_and_linker/FrontEnd/Optimizer/IroUnrollLoop.c new file mode 100644 index 0000000..cf3f1bf --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroUnrollLoop.c @@ -0,0 +1,2305 @@ +#include "IroUnrollLoop.h" +#include "compiler/CError.h" +#include "IroFlowgraph.h" +#include "IroLinearForm.h" +#include "IroUtil.h" +#include "compiler/LoopDetection.h" +#include "IroLoop.h" +#include "IroDump.h" +#include "IroVars.h" +#include "compiler/CFunc.h" +#include "compiler/CMachine.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct LoopList { + UInt8 flags; + BitVector *bv; + struct LoopList *next; + IRONode *fnode; + int xE; +} LoopList; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +// forward decls +static void IRO_FindLoops_Unroll(void); +static void LoopUnroll(int count, IRONode *fnode); +static int IsLoopUnrollable(IROLoop *loop); +static int IsDifferenceOfTermsConstant(IROAddrRecord *lowerRec, IROAddrRecord *upperRec, int isUnsigned, CInt64 *pval); +static IROLinear *BuildOrigIterationCount_DoWhile(IROList *list, IROLoop *loop); +static IROLinear *BuildPreAlignTemp(IROLoopInd *ind, UInt32 unrollFactor, IROList *list); +static IROLinear *BuildNewFinalvalue_DoWhile(IROLinear *iterCount, UInt32 unrollFactor, IROList *list, IROLoop *loop); +static IROLinear *BuildUnrolledFinalvalue_DoWhile(IROLinear *iterCount, UInt32 unrollFactor, IROList *list, IROLoop *loop); + +void IRO_LoopUnroller(void) { + VectorPhaseCalledFromUnroll = 1; + IRO_FindLoops_Unroll(); + IRO_CheckForUserBreak(); +} + +static void IRO_FindLoops_Unroll(void) { + IRONode *fnode; + IRONode *pred; + UInt16 i; + UInt16 flag; + LoopList *list; + LoopList *list2; + + fnode = IRO_FirstNode; + LoopList_First = NULL; + + while (fnode) { + flag = 0; + for (i = 0; i < fnode->numpred; i++) { + pred = IRO_NodeTable[fnode->pred[i]]; + if (Bv_IsBitSet(fnode->index, pred->dom)) { + if (!flag) { + Bv_AllocVector(&InLoop, IRO_NumNodes + 1); + Bv_Clear(InLoop); + Bv_SetBit(fnode->index, InLoop); + } + flag = 1; + Bv_SetBit(pred->index, InLoop); + if (pred != fnode) + AddPreds(pred); + } + } + + if (flag) { + if (!LoopList_First) { + list = oalloc(sizeof(LoopList)); + list->next = NULL; + } else { + list = oalloc(sizeof(LoopList)); + list->next = LoopList_First; + } + LoopList_First = list; + + Bv_AllocVector(&list->bv, IRO_NumNodes + 1); + list->flags |= 1; + Bv_Copy(InLoop, list->bv); + list->fnode = fnode; + list->xE = 0; + } + + fnode = fnode->nextnode; + } + + list = LoopList_First; + Bv_AllocVector(&LoopTemp, IRO_NumNodes + 1); + while (list) { + for (list2 = LoopList_First; list2; list2 = list2->next) { + if (list2 != list) { + IRO_Dump(" header = %d \n", list2->fnode->index); + IRO_Dump(" l1 bit vector=\n"); + IRO_DumpBits("", list2->bv); + IRO_Dump(" l bit vector=\n"); + IRO_DumpBits("", list->bv); + if (Bv_IsSubset(list->bv, list2->bv)) + list2->flags &= ~1; + } + } + list = list->next; + } + + for (list = LoopList_First; list; list = list->next) { + if (list->flags & 1) { + IRONode *listfnode; + Bv_Copy(list->bv, InLoop); + listfnode = list->fnode; + IRO_Dump("IRO_FindLoops_Unroll:Found loop with header %d\n", listfnode->index); + IRO_DumpBits("Loop includes: ", InLoop); + LoopUnroll(copts.unrollfactor, listfnode); + IRO_UpdateFlagsOnInts(); + } + } +} + +static int CheckConstant(CInt64 a, CInt64 b, CInt64 *result) { + CInt64 shl = cint64_zero; + CInt64 work = cint64_zero; + CInt64 and = cint64_zero; + CInt64 i; + + for (i = cint64_zero; CInt64_Less(i, a); i = CInt64_Add(i, cint64_one)) { + shl = CInt64_Shl(b, i); + and = CInt64_And(shl, work); + if (CInt64_NotEqual(and, cint64_zero)) + return 0; + work = CInt64_Or(shl, work); + } + + *result = work; + return 1; +} + +typedef struct LoopPattern { + IROLinear *nd0; + IROLinear *nd4; + Type *type; + IROLinear *ndC; + IROLinear *nd10; + CInt64 val14; + CInt64 val1C; +} LoopPattern; + +static void UnrollWhileLoopBody(IRONode *header, IRONode *fnode2, IRONode *fnode3, IROLoop *loop, LoopPattern *pattern, UInt32 unrollFactor) { + IRONode *scan; + int pass; + IROLinear *firstnode; + IROLinear *lastnd; + IROLinear *nd; + IROLinear *nd1; + IROLinear *nd2; + IROLinear *nd3; + IROLinear *nd4; + IROLinear *nd5; + IROLinear *nd6; + IROLinear *nd8; + IROLinear *nd7; + ENode *expr; + IROList list; + CInt64 zero; + CInt64 shiftval; + + CInt64_SetLong(&zero, 0); + + pass = 0; + + do { + firstnode = NULL; + for (scan = fnode3; scan && scan != header; scan = scan->nextnode) { + IRO_InitList(&list); + lastnd = scan->last; + nd = scan->first; + while (1) { + if (nd->stmt) + nd->stmt->flags |= StmtFlag_10; + + if ( + (nd->index < loop->index20 || nd->index > loop->index24) && + nd->type != IROLinearLabel && + nd->type != IROLinearNop && + !(nd->flags & IROLF_Reffed) + ) + { + CError_ASSERT(345, nd->nodetype == EORASS || nd->nodetype == EANDASS || nd->nodetype == EXORASS); + + IRO_DuplicateExpr(pattern->nd0, &list); + nd1 = list.tail; + + shiftval = cint64_one; + shiftval = CInt64_Shl(shiftval, pattern->val1C); + + nd2 = IRO_NewLinear(IROLinearOperand); + nd2->index = ++IRO_NumLinear; + nd2->rtype = pattern->nd0->rtype; + expr = IRO_NewENode(EINTCONST); + expr->rtype = pattern->nd0->rtype; + CInt64_SetLong(&expr->data.intval, pass * CInt64_GetULong(&shiftval)); + nd2->u.node = expr; + IRO_AddToList(nd2, &list); + + IRO_DuplicateExpr(pattern->nd4, &list); + + nd3 = IRO_NewLinear(IROLinearOp2Arg); + nd3->index = ++IRO_NumLinear; + nd3->nodetype = EADD; + nd3->rtype = pattern->type; + nd3->u.diadic.left = list.tail; + nd3->u.diadic.right = nd2; + IRO_AddToList(nd3, &list); + + nd4 = IRO_NewLinear(IROLinearOp2Arg); + nd4->index = ++IRO_NumLinear; + nd4->nodetype = EADD; + nd4->rtype = pattern->type; + nd4->u.diadic.left = nd3; + nd4->u.diadic.right = nd1; + IRO_AddToList(nd4, &list); + + nd5 = IRO_NewLinear(IROLinearOp1Arg); + nd5->index = ++IRO_NumLinear; + nd5->nodetype = EINDIRECT; + nd5->rtype = nd->rtype; + nd5->u.monadic = nd4; + IRO_AddToList(nd5, &list); + + nd6 = IRO_NewLinear(IROLinearOp2Arg); + *nd6 = *nd; + nd6->index = ++IRO_NumLinear; + nd6->u.diadic.left = list.tail; + nd6->next = NULL; + + nd7 = IRO_NewLinear(IROLinearOperand); + nd7->index = ++IRO_NumLinear; + nd7->rtype = pattern->ndC->rtype; + expr = IRO_NewENode(EINTCONST); + expr->rtype = pattern->ndC->rtype; + nd7->u.node = expr; + nd7->next = NULL; + expr->data.intval = pattern->val14; + + if ( + IS_LINEAR_DIADIC(nd, EANDASS) && + CInt64_Equal(pattern->val14, cint64_zero) + ) + { + nd6->nodetype = EASS; + } else if ( + IS_LINEAR_DIADIC(nd, EORASS) && + !CTool_EndianReadWord32(&pattern->val14.hi) + ) + { + UInt32 tmp = CInt64_GetULong(&pattern->val14); + if ( + (nd->rtype->size == 1 && tmp == 0xFF) || + (nd->rtype->size == 2 && tmp == 0xFFFF) || + (nd->rtype->size == 4 && tmp == 0xFFFFFFFF) + ) + { + nd6->nodetype = EASS; + } + } + + IRO_AddToList(nd7, &list); + + if (IS_LINEAR_MONADIC(pattern->nd10, ETYPCON)) { + nd8 = IRO_NewLinear(IROLinearOp1Arg); + *nd8 = *pattern->nd10; + nd8->index = ++IRO_NumLinear; + nd8->u.monadic = nd7; + nd8->next = NULL; + IRO_AddToList(nd8, &list); + } else { + nd8 = nd7; + } + nd6->u.diadic.right = nd8; + IRO_AddToList(nd6, &list); + + if (!firstnode) + firstnode = list.head; + } + + if (nd == lastnd) + break; + nd = nd->next; + } + + if (list.head && list.tail) + IRO_Paste(list.head, list.tail, fnode2->last); + } + } while (++pass < 8); +} + +static int PatternMatchLoop(IRONode *fnode, IROLoop *loop, IROLoopInd *ind, UInt32 *unrollFactor, SInt32 *result1, SInt32 *result2, LoopPattern *pattern) { + IROLinear *scan; + IROLinear *varnode; + IROLinear *nd1; + IROLinear *nd2; + IROLinear *left1; + IROLinear *left2; + IROLinear *right1; + IROLinear *right2; + Object *obj1; + Object *obj2; + CInt64 shl; + CInt64 val; + + *result1 = 0; + *result2 = 0; + + if ((scan = fnode->first)) { + while (1) { + if ( + (scan->index < loop->index20 || scan->index > loop->index24) && + !(scan->flags & IROLF_Reffed) && + scan->type != IROLinearNop && + scan->type != IROLinearLabel + ) + { + if (IS_LINEAR_DIADIC_3(scan, EORASS, EXORASS, EANDASS)) { + (*result2)++; + if (IS_LINEAR_MONADIC(scan->u.diadic.left, EINDIRECT)) { + varnode = scan->u.diadic.left->u.monadic; + if (IS_LINEAR_DIADIC(varnode, EADD)) { + pattern->nd4 = varnode->u.diadic.left; + pattern->type = varnode->rtype; + if (IRO_IsVariable(varnode->u.diadic.left)) { + pattern->nd0 = varnode->u.diadic.right; + if ( + IS_LINEAR_DIADIC(pattern->nd0, ESHL) && + IRO_IsConstant(pattern->nd0->u.diadic.right) + ) + { + pattern->val1C = pattern->nd0->u.diadic.right->u.node->data.intval; + nd1 = pattern->nd0->u.diadic.left; + } else { + return 0; + } + } else { + return 0; + } + } else { + return 0; + } + } else { + return 0; + } + + pattern->nd10 = scan->u.diadic.right; + + if (IS_LINEAR_MONADIC(pattern->nd10, ETYPCON)) { + if (IS_LINEAR_DIADIC(scan, EANDASS)) { + if (IS_LINEAR_MONADIC(pattern->nd10->u.monadic, EBINNOT)) { + pattern->ndC = pattern->nd10->u.monadic->u.monadic; + } else { + return 0; + } + } else { + pattern->ndC = pattern->nd10->u.monadic; + } + + if (IS_LINEAR_DIADIC(pattern->ndC, ESHL) && IRO_IsConstant(pattern->ndC->u.diadic.left)) { + val = pattern->ndC->u.diadic.left->u.node->data.intval; + nd2 = pattern->ndC->u.diadic.right; + } else { + return 0; + } + } else if (IS_LINEAR_DIADIC(pattern->nd10, ESHL) && IS_LINEAR_DIADIC_2(scan, EORASS, EXORASS)) { + pattern->ndC = pattern->nd10; + if (IRO_IsConstant(pattern->ndC->u.diadic.left)) { + val = pattern->ndC->u.diadic.left->u.node->data.intval; + nd2 = pattern->ndC->u.diadic.right; + } else { + return 0; + } + } else if (IS_LINEAR_MONADIC(pattern->nd10, EBINNOT) && IS_LINEAR_DIADIC(scan, EANDASS)) { + pattern->ndC = pattern->nd10->u.monadic; + if (IS_LINEAR_DIADIC(pattern->ndC, ESHL) && IRO_IsConstant(pattern->ndC->u.diadic.left)) { + val = pattern->ndC->u.diadic.left->u.node->data.intval; + nd2 = pattern->ndC->u.diadic.right; + } else { + return 0; + } + } else { + return 0; + } + + if (IS_LINEAR_DIADIC(nd2, EAND) && IS_LINEAR_DIADIC(nd1, ESHR)) { + left1 = nd1->u.diadic.left; + left2 = nd2->u.diadic.left; + obj1 = IRO_IsVariable(left1); + obj2 = IRO_IsVariable(left2); + if (obj1 == obj2 && obj1 == ind->var->object) { + right1 = nd1->u.diadic.right; + right2 = nd2->u.diadic.right; + if (IRO_IsConstant(right1) && IRO_IsConstant(right2)) { + shl = cint64_one; + shl = CInt64_Shl(shl, right1->u.node->data.intval); + shl = CInt64_Sub(shl, cint64_one); + if (CInt64_Equal(shl, right2->u.node->data.intval)) { + if (CTool_EndianReadWord32(&shl.hi) == 0) { + *unrollFactor = CInt64_GetULong(&shl) + 1; + if (CheckConstant(CInt64_Add(shl, cint64_one), val, &pattern->val14)) { + (*result1)++; + if (IS_LINEAR_DIADIC(scan, EANDASS)) + pattern->val14 = CInt64_Not(pattern->val14); + } + } else { + return 0; + } + } else { + return 0; + } + } else { + return 0; + } + } else { + return 0; + } + } else { + return 0; + } + } else { + return 0; + } + } + + if (scan == fnode->last) + break; + scan = scan->next; + } + } + + return 1; +} + +static UInt32 UnrollWhileLoop(IRONode *header, IRONode *fnode2, IRONode *fnode3, IROLoop *loop, UInt32 unrollFactor) { + IROLoopInd *ind; + IRONode *scan; + CLabel *lastlabel; + IROLinear *lastlabelnode; + IROLinear *earlyLoopExitTest; + CLabel *earlyLoopExitTestLabel; + IROLinear *origIterationCount; + IROLinear *unrolledFinalValue; + IROLinear *preAlignTemp; + IROLinear *newFinalValue; + IROLinear *savedHead60; + IROLinear *unrolledBodyEntryTest; + CLabel *label; + IROLinear *savedHead2; + IROLinear *loophead25; + IROLinear *loopend; + IROLinear *loopscan; + IROLinear *indvar; + IROLinear *less; + IROLinear *loopExitTest; + IROLinear *saveTail; + CLabel *label2; + IROLinear *gotond; + CLabel *label3; + IROLinear *savedHead3; + IROLinear *updIndInc; + IROLinear *label2nd; + IROLinear *less2; + IROLinear *saveTail2; + IROLinear *less3; + IROLinear *wtf; + IROLinear *constnd; + IROLinear *ass; + IROLinear *nd18; + IRONode *fn19; + IRONode *newfnode1; + IRONode *newfnode2; + IRONode *newfnode3; + IRONode *newfnode4; + IRONode *newfnode5; + IRONode *newfnode6; + IRONode *newfnode7; + IRONode *newfnode8; + IROLinear *lastnd; + ENode *expr; + SInt32 result1; + SInt32 result2; + LoopPattern pattern; + IROList list; + + IRO_Dump("while(n--) loop \n"); + + if (loop->flags & LoopFlags_800) { + IRO_Dump("loop not unrolled because induction used in loop \n"); + return 0; + } + if (loop->flags & LoopFlags_1000) { + IRO_Dump("loop not unrolled because loop has multiple exits \n"); + return 0; + } + + if (!(loop->flags & LP_HAS_MULTIPLE_INDUCTIONS)) + return 0; + + for (ind = FirstInd; ind; ind = ind->next) { + if ((ind->flags & LoopInd_HasMod) && (ind->flags & LoopInd_HasDiv)) + break; + } + + if (!ind) { + IRO_Dump("Could not find loop with and induction with MOD and DIV operation\n"); + return 0; + } + + if (!IRO_IsUnsignedType(ind->nd->rtype)) + return 0; + + if (ind->nd->type == IROLinearOp2Arg) { + if (ind->nd->nodetype == EADDASS && IRO_IsConstant(ind->nd->u.diadic.right)) { + if (ind->addConst != 1) + return 0; + } else if (ind->nd->nodetype == EASS) { + if ( + ind->nd->u.diadic.right->type != IROLinearOp2Arg || + ind->nd->u.diadic.right->nodetype != EADD || + !IRO_IsConstant(ind->nd->u.diadic.right->u.diadic.right) + ) + return 0; + + if (ind->addConst != 1) + return 0; + } else { + return 0; + } + } else if (ind->nd->type == IROLinearOp1Arg && ind->nd->nodetype != EPREINC && ind->nd->nodetype != EPOSTINC) { + return 0; + } + + loop->induction = ind; + loop->index24 = ind->nd->index; + loop->index20 = IRO_FindStart(ind->nd)->index; + + scan = IRO_FirstNode; + memset(&pattern, 0, sizeof(pattern)); + while (scan) { + if (Bv_IsBitSet(scan->index, InLoop) && scan != header) { + if (!PatternMatchLoop(scan, loop, ind, &unrollFactor, &result1, &result2, &pattern)) + return 0; + } + scan = scan->nextnode; + } + + if (result1 > 1 || result2 > 1) + return 0; + + lastlabel = fnode2->last->u.label.label; + lastlabelnode = IRO_FindLabelNode(fnode2->last->u.label.label, fnode2->last); + + IRO_InitList(&list); + IRO_DuplicateExprRange(lastlabelnode->next, LoopNode->last->u.label.x4->u.diadic.left, &list); + IRO_DuplicateExpr(LoopNode->last->u.label.x4, &list); + IRO_Paste(list.head, list.tail, fnode2->last); + lastlabelnode = list.tail; + + IRO_InitList(&list); + earlyLoopExitTest = BuildEarlyLoopExitTest(LoopNode->last->type, &list); + earlyLoopExitTestLabel = IRO_NewLabel(); + earlyLoopExitTest->u.label.label = earlyLoopExitTestLabel; + earlyLoopExitTest->u.label.x4 = lastlabelnode; + earlyLoopExitTest->u.label.x4->flags |= IROLF_Reffed; + earlyLoopExitTest->rtype = LoopNode->last->rtype; + IRO_Paste(list.head, list.tail, fnode2->last); + + IRO_InitList(&list); + origIterationCount = BuildOrigIterationCount_DoWhile(&list, loop); + IRO_Paste(list.head, list.tail, fnode2->last); + savedHead60 = list.head; + + IRO_InitList(&list); + preAlignTemp = BuildPreAlignTemp(ind, unrollFactor, &list); + IRO_Paste(list.head, list.tail, fnode2->last); + + IRO_InitList(&list); + unrolledFinalValue = BuildUnrolledFinalvalue_DoWhile(origIterationCount, unrollFactor, &list, loop); + IRO_Paste(list.head, list.tail, fnode2->last); + + IRO_InitList(&list); + newFinalValue = BuildNewFinalvalue_DoWhile(origIterationCount, unrollFactor, &list, loop); + IRO_Paste(list.head, list.tail, fnode2->last); + + IRO_InitList(&list); + BuildUnrolledBodyEntryTest(&list, origIterationCount, unrollFactor, lastlabel); + IRO_Paste(list.head, list.tail, fnode2->last); + unrolledBodyEntryTest = list.tail; + + IRO_InitList(&list); + label = BuildLabel(&list); + IRO_Paste(list.head, list.tail, fnode2->last); + + savedHead2 = list.head; + loophead25 = NULL; + for (scan = fnode3; scan && scan != header; scan = scan->nextnode) { + IRO_InitList(&list); + loopend = scan->last; + loopscan = scan->first; + while (1) { + if (loopscan->stmt) + loopscan->stmt->flags |= StmtFlag_10; + if (loopscan->type != IROLinearLabel && !(loopscan->flags & IROLF_Reffed)) { + IRO_DuplicateExpr(loopscan, &list); + if (!loophead25) + loophead25 = list.head; + } + if (loopscan == loopend) + break; + loopscan = loopscan->next; + } + + if (list.head && list.tail) + IRO_Paste(list.head, list.tail, fnode2->last); + } + + IRO_InitList(&list); + + if (ind->nd->type == IROLinearOp1Arg) + IRO_DuplicateExpr(ind->nd->u.monadic, &list); + else + IRO_DuplicateExpr(ind->nd->u.diadic.left, &list); + list.tail->flags &= ~IROLF_Assigned; + indvar = list.tail; + + IRO_DuplicateExpr(preAlignTemp, &list); + list.tail->flags &= ~IROLF_Assigned; + + less = IRO_NewLinear(IROLinearOp2Arg); + less->nodetype = ELESS; + less->rtype = TYPE(&stbool); + less->index = ++IRO_NumLinear; + less->next = NULL; + less->u.diadic.left = indvar; + less->u.diadic.right = list.tail; + IRO_AddToList(less, &list); + less->flags |= IROLF_Reffed; + + loopExitTest = BuildLoopExitTest(LoopNode->last->type, &list); + loopExitTest->u.label.label = label; + loopExitTest->u.label.x4 = less; + loopExitTest->u.label.x4->flags |= IROLF_Reffed; + loopExitTest->rtype = LoopNode->last->rtype; + IRO_Paste(list.head, list.tail, fnode2->last); + saveTail = list.tail; + + IRO_InitList(&list); + label2 = IRO_NewLabel(); + gotond = IRO_NewLinear(IROLinearOp1Arg); + gotond->index = ++IRO_NumLinear; + gotond->type = IROLinearGoto; + gotond->u.label.label = label2; + IRO_AddToList(gotond, &list); + IRO_Paste(list.head, list.tail, fnode2->last); + + IRO_InitList(&list); + label3 = BuildLabel(&list); + IRO_Paste(list.head, list.tail, fnode2->last); + savedHead3 = list.head; + + UnrollWhileLoopBody(header, fnode2, fnode3, loop, &pattern, unrollFactor); + updIndInc = UpdateInductionIncrement(loop, 8 * unrollFactor, fnode2->last); + + IRO_InitList(&list); + label2nd = IRO_NewLinear(IROLinearLabel); + label2nd->index = IRO_NumLinear++; + label2nd->u.label.label = label2; + label2nd->flags |= IROLF_1; + IRO_AddToList(label2nd, &list); + IRO_Paste(list.head, list.tail, fnode2->last); + + IRO_InitList(&list); + + if (ind->nd->type == IROLinearOp1Arg) + IRO_DuplicateExpr(ind->nd->u.monadic, &list); + else + IRO_DuplicateExpr(ind->nd->u.diadic.left, &list); + list.tail->flags &= ~IROLF_Assigned; + indvar = list.tail; + + IRO_DuplicateExpr(unrolledFinalValue, &list); + list.tail->flags &= ~IROLF_Assigned; + + less2 = IRO_NewLinear(IROLinearOp2Arg); + less2->nodetype = ELESS; + less2->rtype = TYPE(&stbool); + less2->index = ++IRO_NumLinear; + less2->next = NULL; + less2->u.diadic.left = indvar; + less2->u.diadic.right = list.tail; + IRO_AddToList(less2, &list); + less2->flags |= IROLF_Reffed; + + loopExitTest = BuildLoopExitTest(LoopNode->last->type, &list); + loopExitTest->u.label.label = label3; + loopExitTest->u.label.x4 = less2; + loopExitTest->u.label.x4->flags |= IROLF_Reffed; + loopExitTest->rtype = LoopNode->last->rtype; + IRO_Paste(list.head, list.tail, fnode2->last); + saveTail2 = list.tail; + + IRO_InitList(&list); + + if (ind->nd->type == IROLinearOp1Arg) + IRO_DuplicateExpr(ind->nd->u.monadic, &list); + else + IRO_DuplicateExpr(ind->nd->u.diadic.left, &list); + list.tail->flags &= ~IROLF_Assigned; + indvar = list.tail; + + IRO_DuplicateExpr(newFinalValue, &list); + list.tail->flags &= ~IROLF_Assigned; + + less3 = IRO_NewLinear(IROLinearOp2Arg); + less3->nodetype = ELESS; + less3->rtype = TYPE(&stbool); + less3->index = ++IRO_NumLinear; + less3->next = NULL; + less3->u.diadic.left = indvar; + less3->u.diadic.right = list.tail; + IRO_AddToList(less3, &list); + less3->flags |= IROLF_Reffed; + + wtf = LoopNode->last->u.label.x4; + IRO_Paste(list.head, list.tail, LoopNode->last); + LoopNode->last->u.label.x4 = list.tail; + + IRO_InitList(&list); + + constnd = IRO_NewLinear(IROLinearOperand); + constnd->index = ++IRO_NumLinear; + expr = IRO_NewENode(EINTCONST); + expr->rtype = wtf->u.diadic.left->rtype; + expr->data.intval = cint64_zero; + constnd->u.node = expr; + constnd->rtype = expr->rtype; + IRO_AddToList(constnd, &list); + constnd->flags |= IROLF_Reffed; + + IRO_DuplicateExpr(wtf->u.diadic.left, &list); + + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->nodetype = EASS; + ass->rtype = list.tail->rtype; + ass->index = ++IRO_NumLinear; + ass->next = NULL; + ass->u.diadic.left = list.tail; + ass->u.diadic.right = constnd; + IRO_AddToList(ass, &list); + ass->flags |= IROLF_Assigned; + + IRO_NopOut(wtf); + + fn19 = fnode2->nextnode; + nd18 = fnode2->last; + fnode2->last = earlyLoopExitTest; + + newfnode1 = IRO_NewFlowGraphNode(); + newfnode1->first = savedHead60; + newfnode1->last = unrolledBodyEntryTest; + fnode2->nextnode = newfnode1; + + newfnode2 = IRO_NewFlowGraphNode(); + newfnode2->first = savedHead2; + newfnode2->last = saveTail; + savedHead2->u.label.label->stmt = (Statement *) newfnode2; + newfnode1->nextnode = newfnode2; + + newfnode3 = IRO_NewFlowGraphNode(); + newfnode3->first = gotond; + newfnode3->last = gotond; + newfnode2->nextnode = newfnode3; + + newfnode4 = IRO_NewFlowGraphNode(); + newfnode4->first = savedHead3; + newfnode4->last = updIndInc; + savedHead3->u.label.label->stmt = (Statement *) newfnode4; + newfnode3->nextnode = newfnode4; + + newfnode5 = IRO_NewFlowGraphNode(); + newfnode5->first = label2nd; + newfnode5->last = saveTail2; + label2nd->u.label.label->stmt = (Statement *) newfnode5; + newfnode4->nextnode = newfnode5; + + newfnode6 = IRO_NewFlowGraphNode(); + newfnode6->first = nd18; + newfnode6->last = nd18; + newfnode5->nextnode = newfnode6; + newfnode6->nextnode = fn19; + + newfnode7 = oalloc(sizeof(IRONode)); + memset(newfnode7, 0, sizeof(IRONode)); + newfnode7->index = IRO_NumNodes; + IRO_NumNodes++; + + newfnode7->first = list.head; + newfnode7->last = list.tail; + + list.tail->next = LoopNode->last->next; + LoopNode->last->next = list.head; + + newfnode7->nextnode = LoopNode->nextnode; + LoopNode->nextnode = newfnode7; + + newfnode8 = oalloc(sizeof(IRONode)); + memset(newfnode8, 0, sizeof(IRONode)); + newfnode8->index = IRO_NumNodes; + IRO_NumNodes++; + + lastnd = IRO_NewLinear(IROLinearLabel); + lastnd->index = IRO_NumLinear++; + lastnd->next = NULL; + lastnd->u.label.label = earlyLoopExitTestLabel; + lastnd->flags |= IROLF_1; + earlyLoopExitTestLabel->stmt = (Statement *) newfnode8; + + newfnode8->first = lastnd; + newfnode8->last = lastnd; + + lastnd->next = newfnode7->last->next; + newfnode7->last->next = lastnd; + + newfnode8->nextnode = newfnode7->nextnode; + newfnode7->nextnode = newfnode8; + + return 1; +} + +void IRO_IterateForLoopBody(IRONode *start, IRONode *end, IROLoop *loop, IROLinear *destnode, SInt32 addConst, CInt64 *val, Boolean funkyFlag) { + IROLinear *first = NULL; + IROLinear *last = NULL; + IRONode *fnode; + IROLinear *lastnd; + IROLinear *nd; + IROList list; + + for (fnode = start; fnode && fnode != end; fnode = fnode->nextnode) { + IRO_InitList(&list); + + lastnd = fnode->last; + nd = fnode->first; + while (1) { + if (nd->stmt) + nd->stmt->flags |= StmtFlag_10; + + if ( + (nd->index < loop->index20 || nd->index > loop->index24) && + nd->type != IROLinearLabel && + !(nd->flags & IROLF_Reffed) + ) + { + IRO_DuplicateExpr(nd, &list); + if (!first) + first = list.head; + last = list.tail; + } + + if (nd == lastnd) + break; + nd = nd->next; + } + + if (list.head && list.tail) + IRO_Paste(list.head, list.tail, destnode); + } + + if (funkyFlag) { + *val = CInt64_Add(*val, IRO_MakeLong(loop->induction->addConst)); + ChangeInductionReference(first, last, *val, loop); + } +} + +void IRO_LinearizeForLoopPostLoop(IRONode *fnode1, IRONode *fnode2, IROLoop *loop, IRONode *fnode3, UInt32 unrollFactor) { + IRONode *newfnode; + IROLinear *newnd; + SInt32 i; + CInt64 val; + + newfnode = oalloc(sizeof(IRONode)); + memset(newfnode, 0, sizeof(IRONode)); + newfnode->index = IRO_NumNodes; + IRO_NumNodes++; + + newnd = IRO_NewLinear(IROLinearNop); + newnd->index = IRO_NumLinear++; + newnd->next = NULL; + newnd->flags |= IROLF_1; + + newfnode->first = newfnode->last = newnd; + + newfnode->nextnode = fnode3->nextnode; + fnode3->nextnode = newfnode; + + newnd->next = fnode3->last->next; + fnode3->last->next = newnd; + + val = cint64_zero; + for (i = 0; i < unrollFactor; i++) + IRO_IterateForLoopBody(fnode2, fnode1, loop, newfnode->last, loop->induction->addConst, &val, i > 0); + UpdateInductionIncrement(loop, unrollFactor, newfnode->last); +} + +static UInt32 UnrollForLoop(IRONode *header, IRONode *fnode2, IRONode *fnode3, IROLoop *loop, UInt32 unrollFactor) { + IROLinear *lastlabelnode; + IROLinear *earlyLoopExitTest; + IROLinear *origIterationCount; + IROLinear *saveHead1; + IROLinear *newFinalValue; + IROLinear *unrolledBodyEntryTest; + IROLinear *gotoNd; + IROLinear *saveHead2; + IROLinear *updIndInc; + IROLinear *labelNd; + IROLinear *saveTail2; + IROLinear *ndCopy; + IROLinear *saveTail3; + IROLinear *loopExitTest; + IROLinear *lastnd; + IROLinear *labelNd2; + IROLinear *saveTail4; + IROLinear *labelNd3; + IROLinear *scan; + IRONode *nd18; + IRONode *newfnode1; + IRONode *newfnode2; + IRONode *newfnode3; + IRONode *newfnode4; + IRONode *newfnode5; + IRONode *newfnode6; + CLabel *lastlabel; + CLabel *earlyLoopExitTestLabel; + CLabel *label; + CLabel *label2; + SInt32 i; + + IROList list; + CInt64 iterCount; + int isConstant; + UInt32 needOrigLoop = 0; + UInt32 needUnrollBodyTest = 0; + UInt32 resetUnrolledFinalValue = 0; + SInt32 leftOver; + CInt64 val; + + lastlabelnode = IRO_FindLabelNode(fnode2->last->u.label.label, fnode2->last); + lastlabel = IRO_NewLabel(); + + IRO_InitList(&list); + IRO_DuplicateExprRange(lastlabelnode->next, LoopNode->last->u.label.x4, &list); + IRO_DuplicateExpr(LoopNode->last->u.label.x4, &list); + IRO_Paste(list.head, list.tail, fnode2->last); + lastlabelnode = list.tail; + + IRO_InitList(&list); + earlyLoopExitTest = BuildEarlyLoopExitTest(LoopNode->last->type, &list); + earlyLoopExitTestLabel = IRO_NewLabel(); + earlyLoopExitTest->u.label.label = earlyLoopExitTestLabel; + earlyLoopExitTest->u.label.x4 = lastlabelnode; + earlyLoopExitTest->u.label.x4->flags |= IROLF_Reffed; + earlyLoopExitTest->rtype = LoopNode->last->rtype; + IRO_Paste(list.head, list.tail, fnode2->last); + + isConstant = IsIterationCountConstant(loop, &iterCount); + needOrigLoop = 1; + needUnrollBodyTest = 1; + resetUnrolledFinalValue = 0; + if (isConstant) + IRO_TestConstantIterationCount(loop, &iterCount, 1, &unrollFactor, &leftOver, &needOrigLoop, &needUnrollBodyTest, &resetUnrolledFinalValue); + + IRO_InitList(&list); + origIterationCount = BuildOrigIterationCount(&list, loop); + IRO_Paste(list.head, list.tail, fnode2->last); + saveHead1 = list.head; + + IRO_InitList(&list); + newFinalValue = BuildNewFinalvalue(origIterationCount, unrollFactor, &list, loop); + IRO_Paste(list.head, list.tail, fnode2->last); + + IRO_InitList(&list); + BuildUnrolledBodyEntryTest(&list, origIterationCount, unrollFactor, lastlabel); + IRO_Paste(list.head, list.tail, fnode2->last); + unrolledBodyEntryTest = list.tail; + + label = IRO_NewLabel(); + IRO_InitList(&list); + gotoNd = IRO_NewLinear(IROLinearOp1Arg); + gotoNd->index = ++IRO_NumLinear; + gotoNd->type = IROLinearGoto; + gotoNd->u.label.label = label; + IRO_AddToList(gotoNd, &list); + IRO_Paste(list.head, list.tail, fnode2->last); + + IRO_InitList(&list); + label2 = BuildLabel(&list); + IRO_Paste(list.head, list.tail, fnode2->last); + saveHead2 = list.head; + + val = cint64_zero; + for (i = 0; i < unrollFactor; i++) + IRO_IterateForLoopBody(fnode3, header, loop, fnode2->last, loop->induction->addConst, &val, i > 0); + updIndInc = UpdateInductionIncrement(loop, unrollFactor, fnode2->last); + + IRO_InitList(&list); + labelNd = IRO_NewLinear(IROLinearLabel); + labelNd->index = IRO_NumLinear++; + labelNd->u.label.label = label; + labelNd->flags |= IROLF_1; + IRO_AddToList(labelNd, &list); + IRO_Paste(list.head, list.tail, fnode2->last); + + IRO_InitList(&list); + + IRO_DuplicateExpr(LoopNode->last->u.label.x4->u.diadic.left, &list); + saveTail2 = list.tail; + + if (resetUnrolledFinalValue) + IRO_DuplicateExpr(loop->nd18->u.diadic.right, &list); + else + IRO_DuplicateExpr(newFinalValue, &list); + + ndCopy = IRO_NewLinear(LoopNode->last->u.label.x4->type); + *ndCopy = *LoopNode->last->u.label.x4; + ndCopy->index = ++IRO_NumLinear; + ndCopy->next = NULL; + ndCopy->expr = NULL; + ndCopy->u.diadic.left = saveTail2; + ndCopy->u.diadic.right = list.tail; + IRO_AddToList(ndCopy, &list); + + IRO_Paste(list.head, list.tail, fnode2->last); + saveTail3 = list.tail; + + IRO_InitList(&list); + loopExitTest = BuildLoopExitTest(LoopNode->last->type, &list); + loopExitTest->u.label.label = label2; + loopExitTest->u.label.x4 = saveTail3; + loopExitTest->u.label.x4->flags |= IROLF_Reffed; + loopExitTest->rtype = LoopNode->last->rtype; + IRO_Paste(list.head, list.tail, fnode2->last); + saveTail4 = list.tail; + + IRO_InitList(&list); + labelNd2 = IRO_NewLinear(IROLinearLabel); + labelNd2->index = IRO_NumLinear++; + labelNd2->u.label.label = lastlabel; + labelNd2->flags |= IROLF_1; + IRO_AddToList(labelNd2, &list); + IRO_Paste(list.head, list.tail, fnode2->last); + + lastnd = fnode2->last; + nd18 = fnode2->nextnode; + fnode2->last = earlyLoopExitTest; + + newfnode1 = IRO_NewFlowGraphNode(); + newfnode1->first = saveHead1; + newfnode1->last = unrolledBodyEntryTest; + fnode2->nextnode = newfnode1; + + newfnode2 = IRO_NewFlowGraphNode(); + newfnode2->first = gotoNd; + newfnode2->last = gotoNd; + newfnode1->nextnode = newfnode2; + + newfnode3 = IRO_NewFlowGraphNode(); + newfnode3->first = saveHead2; + newfnode3->last = updIndInc; + + saveHead2->u.label.label->stmt = (Statement *) newfnode3; + if (newfnode2) + newfnode2->nextnode = newfnode3; + else + newfnode1->nextnode = newfnode3; + + newfnode4 = IRO_NewFlowGraphNode(); + newfnode4->first = labelNd; + newfnode4->last = saveTail4; + labelNd->u.label.label->stmt = (Statement *) newfnode4; + newfnode3->nextnode = newfnode4; + + newfnode5 = IRO_NewFlowGraphNode(); + newfnode5->first = labelNd2; + newfnode5->last = lastnd; + newfnode4->nextnode = newfnode5; + newfnode5->nextnode = nd18; + + newfnode6 = oalloc(sizeof(IRONode)); + memset(newfnode6, 0, sizeof(IRONode)); + newfnode6->index = IRO_NumNodes; + IRO_NumNodes++; + + labelNd3 = IRO_NewLinear(IROLinearLabel); + labelNd3->index = IRO_NumLinear++; + labelNd3->next = NULL; + labelNd3->u.label.label = earlyLoopExitTestLabel; + labelNd3->flags |= IROLF_1; + earlyLoopExitTestLabel->stmt = (Statement *) newfnode6; + + newfnode6->first = labelNd3; + newfnode6->last = labelNd3; + + labelNd3->next = LoopNode->last->next; + LoopNode->last->next = labelNd3; + + newfnode6->nextnode = LoopNode->nextnode; + LoopNode->nextnode = newfnode6; + + if (!needOrigLoop) { + NoOpBlock(newfnode5); + NoOpBlock(header); + NoOpBlock(fnode3); + NoOpBlock(loop->induction->fnode); + IRO_NopOut(newfnode1->last->u.label.x4); + newfnode1->last->type = IROLinearNop; + } + + if (!needUnrollBodyTest) { + IRO_NopOut(earlyLoopExitTest->u.label.x4); + earlyLoopExitTest->type = IROLinearNop; + + IRO_NopOut(newfnode4->last->u.label.x4); + newfnode4->last->type = IROLinearNop; + + if (newfnode2) + newfnode2->last->type = IROLinearNop; + + for (scan = newfnode1->first; scan; scan = scan->next) { + if (!(scan->flags & IROLF_Reffed)) + IRO_NopOut(scan); + if (scan == newfnode1->last) + break; + } + } + + return 1; +} + +static UInt32 UnrollStandardLoop(IRONode *header, IRONode *fnode2, IRONode *fnode3, int count) { + IROLoop *loop; + + ConditionalHeaderAtBottom = 1; + loop = ExtractLoopInfo(header); + loop->xC = fnode2; + loop->x10 = fnode3; + FindAssignmenttoInductionVar(loop, fnode2); + + if (!IsLoopUnrollable(loop)) { + IRO_Dump("LoopUnroll:loop with header %d not unrolled because IsLoopUnrollable failed\n", header->index); + return 0; + } + + if (loop->flags & LoopFlags_10000) + return UnrollWhileLoop(header, fnode2, fnode3, loop, count); + else + return UnrollForLoop(header, fnode2, fnode3, loop, count); +} + +static void LoopUnroll(int count, IRONode *header) { + VarRecord *var; + IRONode *tmp; + UInt16 i; + UInt16 j; + IRONode *prevpred; + IRONode *prevsucc; + int foundpred; + UInt32 predcount; + UInt32 success = 0; + + LoopNode = header; + FindMustReach(); + + for (var = IRO_FirstVar; var; var = var->next) + var->xA = 1; + + ComputeLoopKills(); + ComputeLoopInvariance(); + ComputeLoopInduction(); + + LoopNode = header; + ConditionalHeaderAtBottom = 0; + + prevpred = NULL; + foundpred = 0; + for (i = 0; i < LoopNode->numpred; i++) { + tmp = IRO_NodeTable[LoopNode->pred[i]]; + if (!Bv_IsBitSet(tmp->index, InLoop)) { + foundpred = 1; + if (tmp->nextnode == header) { + CError_ASSERT(2101, !prevpred || tmp == prevpred); + prevpred = tmp; + } + } + } + + if (!foundpred) { + IRO_Dump("No predecessor outside the loop\n"); + return; + } + + if (LoopNode->last->type == IROLinearIf || LoopNode->last->type == IROLinearIfNot) { + if (LoopNode->nextnode && !Bv_IsBitSet(LoopNode->nextnode->index, InLoop)) { + prevsucc = NULL; + for (i = 0; i < LoopNode->numsucc; i++) { + tmp = IRO_NodeTable[LoopNode->succ[i]]; + if (Bv_IsBitSet(tmp->index, InLoop)) { + CError_ASSERT(2159, !prevsucc); + prevsucc = tmp; + } + } + + prevpred = NULL; + predcount = 0; + for (j = 0; j < LoopNode->numpred; j++) { + tmp = IRO_NodeTable[LoopNode->pred[j]]; + if (!Bv_IsBitSet(tmp->index, InLoop)) { + prevpred = tmp; + predcount++; + } + } + + if ( + predcount == 1 && + prevpred->last->type == IROLinearGoto && + prevpred->nextnode == prevsucc && + prevsucc != LoopNode + ) + { + success = UnrollStandardLoop(header, prevpred, prevsucc, count); + } + } + } else { + IRO_Dump(" LoopUnroll:Loop with header = %d is not a conditional loop\n", header->index); + } + + if (!success) + return; + + IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes); + memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes); + for (tmp = IRO_FirstNode; tmp; tmp = tmp->nextnode) + IRO_NodeTable[tmp->index] = tmp; + IRO_ComputeSuccPred(); + IRO_ComputeDom(); + if (success) + IRO_Dump(" LoopUnroll:Loop with header = %d Unrolled\n", header->index); +} + +static int IsLoopUnrollable(IROLoop *loop) { + CInt64 tmp; + + if (loop->flags & LP_LOOP_HAS_ASM) { + IRO_Dump("IsLoopUnrollable:No due to LP_LOOP_HAS_ASM \n"); + return 0; + } + if (loop->flags & LP_IFEXPR_NON_CANONICAL) { + IRO_Dump("IsLoopUnrollable:No due to LP_IFEXPR_NON_CANONICAL \n"); + return 0; + } + if (loop->flags & LP_LOOP_HAS_CALLS) { + IRO_Dump("IsLoopUnrollable:No due to LP_LOOP_HAS_CALLS \n"); + return 0; + } + if (loop->flags & LP_LOOP_HAS_CNTRLFLOW) { + IRO_Dump("IsLoopUnrollable:No due to LP_LOOP_HAS_CNTRLFLOW \n"); + return 0; + } + if (loop->flags & LP_INDUCTION_NOT_FOUND) { + IRO_Dump("IsLoopUnrollable:No due to LP_INDUCTION_NOT_FOUND \n"); + return 0; + } + if (loop->flags & LP_LOOP_HDR_HAS_SIDEEFFECTS) { + IRO_Dump("IsLoopUnrollable:No due to LP_LOOP_HDR_HAS_SIDEEFFECTS \n"); + return 0; + } + if (!(loop->flags & LoopFlags_200)) { + IRO_Dump("IsLoopUnrollable:No because header does not follow induction update \n"); + return 0; + } + + if (!(loop->flags & LoopFlags_10000)) { + IROLinear *upperBound = loop->nd18->u.diadic.right; + if (!IRO_IsIntConstant(upperBound) && !(upperBound->flags & IROLF_LoopInvariant)) { + IRO_Dump("IsLoopUnrollable:No because Loop Upper Bound is Variant in the loop\n"); + return 0; + } + if (!loop->nd14) { + IRO_Dump("IsLoopUnrollable:No because there is no initialization of loop index in PreHeader\n"); + return 0; + } + if (!IRO_IsVariable(loop->nd14->u.diadic.left)) { + IRO_Dump("IsLoopUnrollable:No because initial value of induction stored thru pointer\n"); + return 0; + } + + if (!IRO_IsUnsignedType(loop->nd14->rtype)) { + if (IRO_IsIntConstant(loop->nd14->u.diadic.right)) { + if (!CInt64_GreaterEqual(loop->nd14->u.diadic.right->u.node->data.intval, cint64_zero)) { + IRO_Dump("IsLoopUnrollable:No because initial value of induction is signed but init < 0\n"); + return 0; + } + } else if (IsIterationCountConstant(loop, &tmp)) { + IRO_Dump("IsLoopUnrollable:Yes, the limits substract out to be constants\n"); + } else { + IRO_Dump("IsLoopUnrollable:No because initial value of induction is signed and not constant\n"); + return 0; + } + } + + if (!(loop->flags & LP_LOOP_STEP_ISADD)) { + IRO_Dump("IsLoopUnrollable:No because LP_LOOP_STEP_ISADD is not set i.e induciton is not updated by 1\n"); + return 0; + } + + } else { + if (!IRO_IsUnsignedType(loop->nd18->u.diadic.left->rtype)) { + IRO_Dump("IsLoopUnrollable:No because the while loop induction is signed\n"); + return 0; + } + if (!(loop->flags & LoopFlags_2000)) { + IRO_Dump("IsLoopUnrollable:No because the while loop operator is not of decrement form\n"); + return 0; + } + } + + if (loop->sizeBySomeMeasurement > copts.unrollinstrfactor) { + IRO_Dump("IsLoopUnrollable:No because loop size greater than threshold\n"); + return 0; + } + + return 1; +} + +IROLinear *BuildEarlyLoopExitTest(IROLinearType type, IROList *list) { + IROLinear *nd = IRO_NewLinear(IROLinearOp1Arg); + nd->index = ++IRO_NumLinear; + if (type == IROLinearIf) + nd->type = IROLinearIfNot; + else + nd->type = IROLinearIf; + IRO_AddToList(nd, list); + return nd; +} + +IROLinear *BuildLoopExitTest(IROLinearType type, IROList *list) { + IROLinear *nd = IRO_NewLinear(IROLinearOp1Arg); + nd->index = ++IRO_NumLinear; + nd->type = type; + IRO_AddToList(nd, list); + return nd; +} + +int IsIterationCountConstant(IROLoop *loop, CInt64 *pval) { + IROLinear *lowerBound; + IROLinear *upperBound; + Type *type; + int isUnsigned; + IROAddrRecord *lowerRec; + IROAddrRecord *upperRec; + CInt64 lowerval; + CInt64 upperval; + CInt64 incval; + CInt64 negOne; + + lowerBound = loop->nd14->u.diadic.right; + if (loop->flags & LoopFlags_1) { + upperBound = loop->nd18->u.diadic.right; + type = loop->nd18->u.diadic.right->rtype; + } else { + upperBound = loop->nd18->u.diadic.left; + type = loop->nd18->u.diadic.left->rtype; + } + + isUnsigned = IRO_IsUnsignedType(type); + + if (IRO_IsIntConstant(lowerBound) && IRO_IsIntConstant(upperBound)) { + lowerval = lowerBound->u.node->data.intval; + upperval = upperBound->u.node->data.intval; + if (isUnsigned) { + if (CInt64_LessEqualU(upperval, lowerval)) + return 0; + } else { + if (CInt64_LessEqual(upperval, lowerval)) + return 0; + } + + CInt64_SetLong(&incval, loop->induction->addConst); + CInt64_SetLong(&negOne, -1); + *pval = CInt64_Sub(upperval, lowerval); + *pval = CInt64_Add(*pval, incval); + + if (IS_LINEAR_DIADIC(loop->nd18, ELESS)) + *pval = CInt64_Add(*pval, negOne); + + CError_ASSERT(2486, !CInt64_IsZero(&incval)); + + if (isUnsigned) + *pval = CInt64_DivU(*pval, incval); + else + *pval = CInt64_Div(*pval, incval); + + if (CInt64_Equal(*pval, cint64_zero)) + return 0; + + if (isUnsigned) { + CError_ASSERT(2508, !CInt64_LessEqualU(*pval, cint64_zero)); + } else { + CError_ASSERT(2517, !CInt64_LessEqual(*pval, cint64_zero)); + } + + return 1; + } + + lowerRec = IRO_InitAddrRecordPointer(lowerBound); + upperRec = IRO_InitAddrRecordPointer(upperBound); + + if (IS_LINEAR_DIADIC(lowerBound, EADD)) { + IRO_DecomposeAddressExpression(lowerBound, lowerRec); + } else if (IRO_IsIntConstant(lowerBound)) { + lowerRec->numInts++; + IRO_AddElmToList(lowerBound, &lowerRec->ints); + lowerRec->numObjRefs = 0; + lowerRec->numMisc = 0; + } else { + lowerRec->numMisc++; + IRO_AddElmToList(lowerBound, &lowerRec->misc); + lowerRec->numObjRefs = 0; + lowerRec->numInts = 0; + } + + if (IS_LINEAR_DIADIC(upperBound, EADD)) { + IRO_DecomposeAddressExpression(upperBound, upperRec); + } else if (IRO_IsIntConstant(upperBound)) { + upperRec->numInts++; + IRO_AddElmToList(upperBound, &upperRec->ints); + upperRec->numObjRefs = 0; + upperRec->numMisc = 0; + } else { + upperRec->numMisc++; + IRO_AddElmToList(upperBound, &upperRec->misc); + upperRec->numObjRefs = 0; + upperRec->numInts = 0; + } + + if (IsDifferenceOfTermsConstant(lowerRec, upperRec, isUnsigned, pval)) { + if (IS_LINEAR_DIADIC(loop->nd18, ELESSEQU)) + *pval = CInt64_Add(*pval, cint64_one); + return 1; + } + + return 0; +} + +static int IsDifferenceOfTermsConstant(IROAddrRecord *lowerRec, IROAddrRecord *upperRec, int isUnsigned, CInt64 *pval) { + UInt32 i; + CInt64 upperval; + CInt64 lowerval; + IROElmList *el; + IROLinear *nd; + + if (upperRec->numObjRefs == lowerRec->numObjRefs && upperRec->numObjRefs != 0) + return 0; + else if (upperRec->numObjRefs != lowerRec->numObjRefs) + return 0; + + if (upperRec->numMisc == lowerRec->numMisc && upperRec->numMisc != 0) { + for (i = 0; i < upperRec->numMisc; i++) { + // bug? surely this should index on i...? + if (!IRO_ExprsSame(lowerRec->misc->element, upperRec->misc->element)) + return 0; + } + } else if (upperRec->numMisc != lowerRec->numMisc) { + return 0; + } + + upperval = cint64_zero; + for (el = upperRec->ints; el; el = el->next) { + nd = el->element; + upperval = CMach_CalcIntDiadic(nd->rtype, upperval, '+', nd->u.node->data.intval); + } + + lowerval = cint64_zero; + for (el = lowerRec->ints; el; el = el->next) { + nd = el->element; + lowerval = CMach_CalcIntDiadic(nd->rtype, lowerval, '+', nd->u.node->data.intval); + } + + if (CInt64_Equal(upperval, lowerval)) + return 0; + + if (CInt64_Greater(upperval, lowerval)) { + *pval = CInt64_Sub(upperval, lowerval); + return 1; + } else { + return 0; + } +} + +void NoOpBlock(IRONode *fnode) { + IROLinear *last, *scan; + + for (scan = fnode->first, last = fnode->last; scan; scan = scan->next) { + scan->type = IROLinearNop; + if (scan == last) + break; + } +} + +void IRO_TestConstantIterationCount(IROLoop *loop, CInt64 *iterCount, SInt32 vectorStride, UInt32 *unrollFactor, SInt32 *leftOver, UInt32 *needOrigLoop, UInt32 *needUnrollBodyTest, UInt32 *resetUnrolledFinalValue) { + UInt32 isUnsigned; + CInt64 val; + CInt64 val3; + CInt64 mod; + CInt64 val2; + CInt64 loopvar3; + CInt64 loopvar1; + CInt64 loopvar2; + CInt64 strideVal; + + CError_ASSERT(2737, *unrollFactor); + + isUnsigned = IRO_IsUnsignedType( + (loop->flags & LoopFlags_1) ? loop->nd18->u.diadic.right->rtype :loop->nd18->u.diadic.left->rtype); + + CError_ASSERT(2756, vectorStride); + + strideVal = IRO_MakeLong(vectorStride); + if (isUnsigned ? CInt64_LessU(*iterCount, strideVal) : CInt64_Less(*iterCount, strideVal)) { + *needOrigLoop = 1; + *needUnrollBodyTest = 0; + *unrollFactor = 0; + *leftOver = CInt64_GetULong(iterCount); + } else { + switch (vectorStride) { + case 1: + val = *iterCount; + break; + case 2: + val = CInt64_ShrU(*iterCount, cint64_one); + break; + case 4: + val = CInt64_ShrU(*iterCount, IRO_MakeLong(2)); + break; + case 8: + val = CInt64_ShrU(*iterCount, IRO_MakeLong(3)); + break; + case 16: + val = CInt64_ShrU(*iterCount, IRO_MakeLong(4)); + break; + default: + val = CInt64_Div(*iterCount, strideVal); + } + + if (CInt64_LessU(val, IRO_MakeLong(*unrollFactor))) + *unrollFactor = CInt64_GetULong(&val); + + CInt64_SetLong(&val2, *unrollFactor); + switch (vectorStride) { + case 1: + val3 = cint64_zero; + break; + case 2: + val3 = CInt64_And(*iterCount, cint64_one); + break; + case 4: + val3 = CInt64_And(*iterCount, IRO_MakeLong(3)); + break; + case 8: + val3 = CInt64_And(*iterCount, IRO_MakeLong(7)); + break; + case 16: + val3 = CInt64_And(*iterCount, IRO_MakeLong(15)); + break; + default: + val3 = CInt64_Mod(*iterCount, strideVal); + } + + if (CInt64_LessEqualU(val, IRO_MakeLong(8))) { + *needUnrollBodyTest = vectorStride > 1; + *unrollFactor = CInt64_GetULong(&val); + *leftOver = CInt64_GetULong(&val3); + *needOrigLoop = *leftOver != 0; + *resetUnrolledFinalValue = !(*needOrigLoop && *needUnrollBodyTest); + } else { + loopvar1 = IRO_MakeLong(0x7FFFFFFF); + loopvar2 = IRO_MakeLong(0x7FFFFFFF); + do { + mod = CInt64_Mod(val, val2); + loopvar3 = CInt64_Add(CInt64_Mul(mod, strideVal), val3); + if (CInt64_Less(loopvar3, loopvar2)) { + loopvar2 = loopvar3; + loopvar1 = val2; + } + if (vectorStride > 1) + break; + val2 = CInt64_Add(val2, cint64_negone); + } while (CInt64_GreaterEqualU(CInt64_Mul(val2, val2), val)); + + *unrollFactor = CInt64_GetULong(&loopvar1); + *leftOver = CInt64_GetULong(&loopvar2); + *needOrigLoop = *leftOver != 0; + *needUnrollBodyTest = CInt64_Less(loopvar1, val) || vectorStride > 1; + *resetUnrolledFinalValue = !(*needOrigLoop && *needUnrollBodyTest); + } + } + + IRO_Dump( + "---- IterCount = %d, VectorStride = %d, UnrollFactor = %d, LeftOver = %d,\n" + "\tNeedOrigLoop = %d, NeedUnrollBodyTest = %d, ResetUnrolledFinalValue = %d\n", + CInt64_GetULong(iterCount), vectorStride, *unrollFactor, *leftOver, + *needOrigLoop, *needUnrollBodyTest, *resetUnrolledFinalValue + ); +} + +IROLinear *BuildOrigIterationCount(IROList *list, IROLoop *loop) { + IROLinear *upperBound; + IROLinear *nd29b; + IROLinear *lowerBound; + IROLinear *finalCount; + IROLinear *divisor; + Type *type; + IROLinear *nd25; + IROLinear *tmp; + Boolean isZeroBase; + Object *tempobj; + IROLinear *iterCount; + IROLinear *negone; + IROLinear *ass; + ENode *expr; + SInt32 powval; + + isZeroBase = 0; + lowerBound = loop->nd14->u.diadic.right; + if (IRO_IsIntConstant(lowerBound) && CInt64_Equal(lowerBound->u.node->data.intval, cint64_zero)) + isZeroBase = 1; + + if (!isZeroBase) + lowerBound = IRO_DuplicateExpr(lowerBound, list); + + if (loop->flags & LoopFlags_1) { + upperBound = IRO_DuplicateExpr(loop->nd18->u.diadic.right, list); + type = loop->nd18->u.diadic.right->rtype; + } else { + upperBound = IRO_DuplicateExpr(loop->nd18->u.diadic.left, list); + type = loop->nd18->u.diadic.left->rtype; + } + + CError_ASSERT(2924, loop->induction); + CError_ASSERT(2929, loop->induction->addConst); + + divisor = IRO_NewLinear(IROLinearOperand); + divisor->index = ++IRO_NumLinear; + divisor->rtype = type; + expr = IRO_NewENode(EINTCONST); + expr->rtype = type; + CInt64_SetLong(&expr->data.intval, loop->induction->addConst); + divisor->u.node = expr; + + if (isZeroBase) { + iterCount = upperBound; + } else { + iterCount = IRO_NewLinear(IROLinearOp2Arg); + iterCount->index = ++IRO_NumLinear; + iterCount->nodetype = ESUB; + iterCount->u.diadic.left = upperBound; + iterCount->u.diadic.right = lowerBound; + iterCount->rtype = type; + IRO_AddToList(iterCount, list); + } + + nd25 = IRO_DuplicateExpr(divisor, list); + + nd29b = IRO_NewLinear(IROLinearOp2Arg); + nd29b->index = ++IRO_NumLinear; + nd29b->nodetype = EADD; + nd29b->u.diadic.left = iterCount; + nd29b->u.diadic.right = nd25; + nd29b->rtype = type; + IRO_AddToList(nd29b, list); + + if (loop->nd18->type == IROLinearOp2Arg && loop->nd18->nodetype == ELESS) { + tmp = nd29b; + + negone = IRO_NewLinear(IROLinearOperand); + negone->index = ++IRO_NumLinear; + negone->rtype = type; + expr = IRO_NewENode(EINTCONST); + expr->rtype = type; + CInt64_SetLong(&expr->data.intval, -1); + negone->u.node = expr; + IRO_AddToList(negone, list); + + nd29b = IRO_NewLinear(IROLinearOp2Arg); + nd29b->index = ++IRO_NumLinear; + nd29b->nodetype = EADD; + nd29b->u.diadic.left = tmp; + nd29b->u.diadic.right = negone; + nd29b->rtype = type; + IRO_AddToList(nd29b, list); + } + + if (CInt64_Equal(divisor->u.node->data.intval, cint64_one)) { + finalCount = nd29b; + } else { + if (divisor->rtype->size <= 4 && IS_TYPE_INT(divisor->rtype) && IRO_IsPow2(divisor, &powval)) { + finalCount = IRO_NewLinear(IROLinearOp2Arg); + finalCount->index = ++IRO_NumLinear; + finalCount->nodetype = ESHL; + finalCount->u.diadic.left = nd29b; + finalCount->u.diadic.right = divisor; + CInt64_SetLong(&divisor->u.node->data.intval, powval); + finalCount->rtype = type; + IRO_AddToList(divisor, list); + IRO_AddToList(finalCount, list); + } else { + finalCount = IRO_NewLinear(IROLinearOp2Arg); + finalCount->index = ++IRO_NumLinear; + finalCount->nodetype = EDIV; + finalCount->u.diadic.left = nd29b; + finalCount->u.diadic.right = divisor; + finalCount->rtype = type; + IRO_AddToList(divisor, list); + IRO_AddToList(finalCount, list); + } + } + + tempobj = create_temp_object(type); + IRO_FindVar(tempobj, 1, 1); + + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->index = ++IRO_NumLinear; + ass->nodetype = EASS; + ass->u.diadic.left = IRO_TempReference(tempobj, list); + ass->u.diadic.left->flags |= IROLF_Assigned | IROLF_Ind; + ass->u.diadic.left->u.monadic->flags |= IROLF_Assigned | IROLF_Ind; + ass->u.diadic.right = finalCount; + ass->u.diadic.right->flags |= IROLF_Reffed; + ass->rtype = type; + IRO_AddToList(ass, list); + + return ass->u.diadic.left; +} + +static IROLinear *BuildOrigIterationCount_DoWhile(IROList *list, IROLoop *loop) { + IROLinear *finalCount; + IROLinear *count; + IROLinear *ass; + Type *type; + Object *tempobj; + ENode *expr; + + type = loop->nd18->u.diadic.left->rtype; + + count = IRO_NewLinear(IROLinearOperand); + count->index = ++IRO_NumLinear; + expr = IRO_NewENode(EINTCONST); + expr->rtype = type; + expr->data.intval = cint64_one; + count->u.node = expr; + count->rtype = type; + IRO_AddToList(count, list); + count->flags |= IROLF_Reffed; + + finalCount = IRO_NewLinear(IROLinearOp2Arg); + finalCount->index = ++IRO_NumLinear; + finalCount->nodetype = EADD; + finalCount->rtype = type; + finalCount->u.diadic.left = IRO_DuplicateExpr(loop->nd18->u.diadic.left, list); + finalCount->u.diadic.left->flags |= IROLF_Reffed; + finalCount->u.diadic.left->flags &= ~IROLF_Assigned; + finalCount->u.diadic.left->u.monadic->flags &= ~IROLF_Assigned; + finalCount->u.diadic.right = count; + IRO_AddToList(finalCount, list); + + tempobj = create_temp_object(type); + IRO_FindVar(tempobj, 1, 1); + + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->index = ++IRO_NumLinear; + ass->nodetype = EASS; + ass->u.diadic.left = IRO_TempReference(tempobj, list); + ass->u.diadic.left->flags |= IROLF_Assigned | IROLF_Ind; + ass->u.diadic.left->u.monadic->flags |= IROLF_Assigned | IROLF_Ind; + ass->u.diadic.right = finalCount; + ass->rtype = type; + IRO_AddToList(ass, list); + + return ass->u.diadic.left; +} + +IROLinear *BuildNewFinalvalue(IROLinear *iterCount, UInt32 unrollFactor, IROList *list, IROLoop *loop) { + IROLinear *sub; + IROLinear *addvalue; + Type *type; + IROLinear *ass; + IROLinear *dupbound; + Object *tempobj; + ENode *expr; + + type = iterCount->rtype; + + addvalue = IRO_NewLinear(IROLinearOperand); + addvalue->index = ++IRO_NumLinear; + addvalue->rtype = type; + expr = IRO_NewENode(EINTCONST); + expr->rtype = type; + CInt64_SetLong(&expr->data.intval, loop->induction->addConst * unrollFactor); + addvalue->u.node = expr; + IRO_AddToList(addvalue, list); + + if (loop->flags & LoopFlags_1) + dupbound = IRO_DuplicateExpr(loop->nd18->u.diadic.right, list); + else + dupbound = IRO_DuplicateExpr(loop->nd18->u.diadic.left, list); + + sub = IRO_NewLinear(IROLinearOp2Arg); + sub->index = ++IRO_NumLinear; + sub->nodetype = ESUB; + sub->u.diadic.left = dupbound; + sub->u.diadic.right = addvalue; + sub->rtype = type; + IRO_AddToList(sub, list); + + tempobj = create_temp_object(type); + IRO_FindVar(tempobj, 1, 1); + + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->index = ++IRO_NumLinear; + ass->nodetype = EASS; + ass->u.diadic.left = IRO_TempReference(tempobj, list); + ass->u.diadic.left->flags |= IROLF_Assigned | IROLF_Ind; + ass->u.diadic.left->u.monadic->flags |= IROLF_Assigned | IROLF_Ind; + ass->u.diadic.right = sub; + ass->u.diadic.right->flags |= IROLF_Reffed; + ass->rtype = type; + IRO_AddToList(ass, list); + + return ass->u.diadic.left; +} + +static IROLinear *BuildPreAlignTemp(IROLoopInd *ind, UInt32 unrollFactor, IROList *list) { + Type *type; + IROLinear *indnd; + IROLinear *factornd; + IROLinear *div; + IROLinear *constnd; + IROLinear *add; + IROLinear *mul; + IROLinear *ass; + Object *tempobj; + ENode *expr; + + indnd = ind->nd; + type = indnd->rtype; + + factornd = IRO_NewLinear(IROLinearOperand); + factornd->index = ++IRO_NumLinear; + factornd->rtype = type; + expr = IRO_NewENode(EINTCONST); + expr->rtype = type; + CInt64_SetLong(&expr->data.intval, unrollFactor); + factornd->u.node = expr; + IRO_AddToList(factornd, list); + + if (indnd->type == IROLinearOp1Arg) + IRO_DuplicateExpr(indnd->u.monadic, list); + else + IRO_DuplicateExpr(indnd->u.diadic.left, list); + + list->tail->flags &= ~IROLF_Assigned; + list->tail->u.monadic->flags &= ~IROLF_Assigned; + + div = IRO_NewLinear(IROLinearOp2Arg); + div->index = ++IRO_NumLinear; + div->nodetype = EDIV; + div->u.diadic.left = list->tail; + div->u.diadic.right = factornd; + div->rtype = type; + IRO_AddToList(div, list); + div->flags |= IROLF_Reffed; + + constnd = IRO_NewLinear(IROLinearOperand); + constnd->index = ++IRO_NumLinear; + expr = IRO_NewENode(EINTCONST); + expr->rtype = type; + expr->data.intval = cint64_one; + constnd->u.node = expr; + constnd->rtype = type; + IRO_AddToList(constnd, list); + constnd->flags |= IROLF_Reffed; + + add = IRO_NewLinear(IROLinearOp2Arg); + add->index = ++IRO_NumLinear; + add->nodetype = EADD; + add->u.diadic.left = div; + add->u.diadic.right = constnd; + add->rtype = type; + IRO_AddToList(add, list); + add->flags |= IROLF_Reffed; + + IRO_DuplicateExpr(factornd, list); + + mul = IRO_NewLinear(IROLinearOp2Arg); + mul->index = ++IRO_NumLinear; + mul->nodetype = EMUL; + mul->u.diadic.left = add; + mul->u.diadic.right = list->tail; + mul->rtype = type; + IRO_AddToList(mul, list); + mul->flags |= IROLF_Reffed; + + tempobj = create_temp_object(type); + IRO_FindVar(tempobj, 1, 1); + + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->index = ++IRO_NumLinear; + ass->nodetype = EASS; + ass->u.diadic.left = IRO_TempReference(tempobj, list); + ass->u.diadic.left->flags |= IROLF_Assigned | IROLF_Ind; + ass->u.diadic.left->u.monadic->flags |= IROLF_Assigned | IROLF_Ind; + ass->u.diadic.right = mul; + ass->u.diadic.right->flags |= IROLF_Reffed; + ass->rtype = type; + IRO_AddToList(ass, list); + + return ass->u.diadic.left; +} + +static IROLinear *BuildNewFinalvalue_DoWhile(IROLinear *iterCount, UInt32 unrollFactor, IROList *list, IROLoop *loop) { + IROLinear *addvalue; + IROLinear *add; + IROLinear *mul; + IROLinear *ass; + Type *type; + Object *tempobj; + ENode *expr; + + type = iterCount->rtype; + + addvalue = IRO_NewLinear(IROLinearOperand); + addvalue->index = ++IRO_NumLinear; + addvalue->rtype = type; + expr = IRO_NewENode(EINTCONST); + expr->rtype = type; + CInt64_SetLong(&expr->data.intval, loop->induction->addConst); + addvalue->u.node = expr; + IRO_AddToList(addvalue, list); + addvalue->flags |= IROLF_Reffed; + + mul = IRO_NewLinear(IROLinearOp2Arg); + mul->index = ++IRO_NumLinear; + mul->nodetype = EMUL; + mul->u.diadic.left = IRO_DuplicateExpr(iterCount, list); + mul->u.diadic.right = addvalue; + mul->rtype = type; + IRO_AddToList(mul, list); + mul->flags |= IROLF_Reffed; + mul->u.diadic.left->flags &= ~IROLF_Assigned; + mul->u.diadic.left->u.diadic.left->flags &= ~IROLF_Assigned; + + if (loop->induction->nd->type == IROLinearOp1Arg) + IRO_DuplicateExpr(loop->induction->nd->u.monadic, list); + else + IRO_DuplicateExpr(loop->induction->nd->u.diadic.left, list); + list->tail->flags &= ~IROLF_Assigned; + list->tail->u.diadic.left->flags &= ~IROLF_Assigned; + + add = IRO_NewLinear(IROLinearOp2Arg); + add->index = ++IRO_NumLinear; + add->nodetype = EADD; + add->u.diadic.left = mul; + add->u.diadic.right = list->tail; + add->rtype = type; + IRO_AddToList(add, list); + add->flags |= IROLF_Reffed; + + tempobj = create_temp_object(type); + IRO_FindVar(tempobj, 1, 1); + + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->index = ++IRO_NumLinear; + ass->nodetype = EASS; + ass->u.diadic.left = IRO_TempReference(tempobj, list); + ass->u.diadic.left->flags |= IROLF_Assigned | IROLF_Ind; + ass->u.diadic.left->u.monadic->flags |= IROLF_Assigned | IROLF_Ind; + ass->u.diadic.right = add; + ass->u.diadic.right->flags |= IROLF_Reffed; + ass->rtype = type; + IRO_AddToList(ass, list); + + return ass->u.diadic.left; +} + +static IROLinear *BuildUnrolledFinalvalue_DoWhile(IROLinear *iterCount, UInt32 unrollFactor, IROList *list, IROLoop *loop) { + IROLinear *addvalue_mult; + IROLinear *addvalue; + IROLinear *mul; + IROLinear *sub; + IROLinear *add; + IROLinear *ass; + Type *type; + Object *tempobj; + ENode *expr; + + type = iterCount->rtype; + + addvalue_mult = IRO_NewLinear(IROLinearOperand); + addvalue_mult->index = ++IRO_NumLinear; + addvalue_mult->rtype = type; + expr = IRO_NewENode(EINTCONST); + expr->rtype = type; + CInt64_SetLong(&expr->data.intval, loop->induction->addConst * unrollFactor); + addvalue_mult->u.node = expr; + IRO_AddToList(addvalue_mult, list); + addvalue_mult->flags |= IROLF_Reffed; + + addvalue = IRO_NewLinear(IROLinearOperand); + addvalue->index = ++IRO_NumLinear; + addvalue->rtype = type; + expr = IRO_NewENode(EINTCONST); + expr->rtype = type; + CInt64_SetLong(&expr->data.intval, loop->induction->addConst); + addvalue->u.node = expr; + IRO_AddToList(addvalue, list); + addvalue->flags |= IROLF_Reffed; + + mul = IRO_NewLinear(IROLinearOp2Arg); + mul->index = ++IRO_NumLinear; + mul->nodetype = EMUL; + mul->u.diadic.left = IRO_DuplicateExpr(iterCount, list); + mul->u.diadic.right = addvalue; + mul->rtype = type; + IRO_AddToList(mul, list); + mul->flags |= IROLF_Reffed; + mul->u.diadic.left->flags &= ~IROLF_Assigned; + mul->u.diadic.left->u.diadic.left->flags &= ~IROLF_Assigned; + + sub = IRO_NewLinear(IROLinearOp2Arg); + sub->index = ++IRO_NumLinear; + sub->nodetype = ESUB; + sub->u.diadic.left = mul; + sub->u.diadic.right = addvalue_mult; + sub->rtype = type; + IRO_AddToList(sub, list); + sub->flags |= IROLF_Reffed; + + if (loop->induction->nd->type == IROLinearOp1Arg) + IRO_DuplicateExpr(loop->induction->nd->u.monadic, list); + else + IRO_DuplicateExpr(loop->induction->nd->u.diadic.left, list); + list->tail->flags &= ~IROLF_Assigned; + list->tail->u.diadic.left->flags &= ~IROLF_Assigned; + + add = IRO_NewLinear(IROLinearOp2Arg); + add->index = ++IRO_NumLinear; + add->nodetype = EADD; + add->u.diadic.left = sub; + add->u.diadic.right = list->tail; + add->rtype = type; + IRO_AddToList(add, list); + add->flags |= IROLF_Reffed; + + tempobj = create_temp_object(type); + IRO_FindVar(tempobj, 1, 1); + + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->index = ++IRO_NumLinear; + ass->nodetype = EASS; + ass->u.diadic.left = IRO_TempReference(tempobj, list); + ass->u.diadic.left->flags |= IROLF_Assigned | IROLF_Ind; + ass->u.diadic.left->u.monadic->flags |= IROLF_Assigned | IROLF_Ind; + ass->u.diadic.right = add; + ass->u.diadic.right->flags |= IROLF_Reffed; + ass->rtype = type; + IRO_AddToList(ass, list); + + return ass->u.diadic.left; +} + +void BuildUnrolledBodyEntryTest(IROList *list, IROLinear *iterCount, UInt32 unrollFactor, CLabel *label) { + Type *type; + IROLinear *ifnot; + IROLinear *comp; + IROLinear *var; + IROLinear *value; + ENode *expr; + + type = iterCount->rtype; + + value = IRO_NewLinear(IROLinearOperand); + value->index = ++IRO_NumLinear; + value->rtype = type; + expr = IRO_NewENode(EINTCONST); + expr->rtype = type; + CInt64_SetLong(&expr->data.intval, unrollFactor); + value->u.node = expr; + IRO_AddToList(value, list); + + var = IRO_DuplicateExpr(iterCount, list); + + comp = IRO_NewLinear(IROLinearOp2Arg); + comp->index = ++IRO_NumLinear; + comp->nodetype = EGREATER; + comp->u.diadic.left = var; + comp->u.diadic.right = value; + comp->u.diadic.right->flags |= IROLF_Reffed; + comp->rtype = type; + IRO_AddToList(comp, list); + + ifnot = IRO_NewLinear(IROLinearOp1Arg); + ifnot->index = ++IRO_NumLinear; + ifnot->type = IROLinearIfNot; + ifnot->u.label.x4 = comp; + ifnot->u.label.x4->flags |= IROLF_Reffed; + ifnot->rtype = type; + ifnot->u.label.label = label; + IRO_AddToList(ifnot, list); +} + +void ChangeInductionReference(IROLinear *first, IROLinear *last, CInt64 val, IROLoop *loop) { + IROLinear *nd; + IROLinear *value; + IROLinear *add; + UInt32 isUnsigned; + IROLinear *father; + Boolean flag; + IROLinear *father2; + IROLinear *father3; + Type *tmp; + UInt32 flag2; + Object *varobj; + IROLinear *next; + ENode *expr; + Type *type; + + CInt64 val2; + CInt64 val1; + IROList list; + + type = loop->induction->nd->rtype; + isUnsigned = IRO_IsUnsignedType(type); + + for (nd = first; nd; nd = next) { + next = nd->next; + + varobj = IRO_IsVariable(nd); + if (varobj && loop->induction->var->object == varobj) { + value = IRO_NewLinear(IROLinearOperand); + value->index = ++IRO_NumLinear; + value->rtype = type; + expr = IRO_NewENode(EINTCONST); + expr->rtype = type; + expr->data.intval = val; + value->u.node = expr; + + add = IRO_NewLinear(IROLinearOp2Arg); + add->index = ++IRO_NumLinear; + add->nodetype = EADD; + add->rtype = type; + + father = IRO_LocateFather(nd); + flag = 1; + if (father && IS_LINEAR_MONADIC(father, ETYPCON)) { + tmp = father->rtype; + father = IRO_LocateFather(father); + if (tmp->type != nd->rtype->type || tmp->size < nd->rtype->size) + flag = 0; + } + + flag2 = 0; + if ( + flag && + father && + IS_LINEAR_DIADIC_2(father, ESHL, EMUL) && + IRO_IsIntConstant(father->u.diadic.right) && + (father2 = IRO_LocateFather(father)) && + IS_LINEAR_DIADIC(father2, EADD) && + father2->u.diadic.right == father && + (father3 = IRO_LocateFather(father2)) + ) + { + IRO_InitList(&list); + val2 = father->u.diadic.right->u.node->data.intval; + if (father->nodetype == ESHL) + val2 = CInt64_Shl(cint64_one, val2); + + val1 = value->u.node->data.intval; + if (isUnsigned) + val1 = CInt64_MulU(val2, val1); + else + val1 = CInt64_Mul(val2, val1); + value->u.node->data.intval = val1; + + IRO_AddToList(value, &list); + IRO_AddToList(add, &list); + add->u.diadic.right = value; + IRO_Paste(list.head, list.tail, father3); + IRO_LocateFather_Cut_And_Paste_Without_Nopping(father2, add); + add->u.diadic.left = father2; + add->rtype = father2->rtype; + flag2 = 1; + } + + if (!flag2) { + add->u.diadic.right = value; + add->u.diadic.right->flags |= IROLF_Reffed; + value->next = add; + + add->u.diadic.left = nd; + IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, add); + add->flags |= IROLF_Reffed; + + nd->next = value; + add->next = next; + } + } + + if (nd == last) + break; + } +} + +IROLinear *UpdateInductionIncrement(IROLoop *loop, SInt32 value, IROLinear *before) { + IROLinear *ind_nd; + IROLinear *addvalue; + IROLinear *ass; + Type *type; + ENode *expr; + IROList list; + + IRO_InitList(&list); + ind_nd = loop->induction->nd; + type = ind_nd->rtype; + + addvalue = IRO_NewLinear(IROLinearOperand); + addvalue->index = ++IRO_NumLinear; + addvalue->rtype = type; + expr = IRO_NewENode(EINTCONST); + expr->rtype = type; + CInt64_SetLong(&expr->data.intval, value * loop->induction->addConst); + addvalue->u.node = expr; + IRO_AddToList(addvalue, &list); + + if (IS_LINEAR_MONADIC_2(ind_nd, EPREINC, EPOSTINC)) { + ind_nd = IRO_DuplicateExpr(ind_nd->u.monadic, &list); + + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->index = ++IRO_NumLinear; + ass->nodetype = EADDASS; + ass->u.diadic.left = ind_nd; + ass->u.diadic.right = addvalue; + ass->rtype = type; + IRO_AddToList(ass, &list); + } else if (IS_LINEAR_MONADIC_2(ind_nd, EPREDEC, EPOSTDEC)) { + ind_nd = IRO_DuplicateExpr(ind_nd->u.monadic, &list); + + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->index = ++IRO_NumLinear; + ass->nodetype = ESUBASS; + ass->u.diadic.left = ind_nd; + ass->u.diadic.right = addvalue; + ass->rtype = type; + IRO_AddToList(ass, &list); + } else if (IS_LINEAR_DIADIC(ind_nd, EADDASS)) { + ind_nd = IRO_DuplicateExpr(ind_nd->u.monadic, &list); + + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->index = ++IRO_NumLinear; + ass->nodetype = EADDASS; + ass->u.diadic.left = ind_nd; + ass->u.diadic.right = addvalue; + ass->rtype = type; + IRO_AddToList(ass, &list); + } + + IRO_Paste(list.head, list.tail, before); + return list.tail; +} + +void GenInitialAssignment(IROLoop *loop, Object *var, IROList *list) { + Type *type; + IROLinear *nd; + + CError_ASSERT(3924, loop->nd14 && loop->nd14->type == IROLinearOp2Arg); + + type = loop->induction->nd->rtype; + + nd = IRO_NewLinear(IROLinearOp2Arg); + nd->index = ++IRO_NumLinear; + nd->nodetype = EASS; + nd->u.diadic.left = IRO_TempReference(var, list); + nd->u.diadic.right = IRO_DuplicateExpr(loop->nd14->u.diadic.right, list); + nd->rtype = type; + IRO_AddToList(nd, list); +} + +void GenNewInduction(void) { + CError_FATAL(3941); +} diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroUnrollLoop.h b/compiler_and_linker/FrontEnd/Optimizer/IroUnrollLoop.h new file mode 100644 index 0000000..fd4972b --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroUnrollLoop.h @@ -0,0 +1,23 @@ +#ifndef COMPILER_IROUNROLLLOOP_H +#define COMPILER_IROUNROLLLOOP_H + +#include "IrOptimizer.h" +#include "IroLinearForm.h" + +extern void IRO_LoopUnroller(void); +extern void IRO_IterateForLoopBody(IRONode *start, IRONode *end, IROLoop *loop, IROLinear *destnode, SInt32 addConst, CInt64 *val, Boolean funkyFlag); +extern void IRO_LinearizeForLoopPostLoop(IRONode *fnode1, IRONode *fnode2, IROLoop *loop, IRONode *fnode3, UInt32 unrollFactor); +extern IROLinear *BuildEarlyLoopExitTest(IROLinearType type, IROList *list); +extern IROLinear *BuildLoopExitTest(IROLinearType type, IROList *list); +extern int IsIterationCountConstant(IROLoop *loop, CInt64 *pval); +extern void NoOpBlock(IRONode *fnode); +extern void IRO_TestConstantIterationCount(IROLoop *loop, CInt64 *iterCount, SInt32 vectorStride, UInt32 *unrollFactor, SInt32 *leftOver, UInt32 *needOrigLoop, UInt32 *needUnrollBodyTest, UInt32 *resetUnrolledFinalValue); +extern IROLinear *BuildOrigIterationCount(IROList *list, IROLoop *loop); +extern IROLinear *BuildNewFinalvalue(IROLinear *iterCount, UInt32 unrollFactor, IROList *list, IROLoop *loop); +extern void BuildUnrolledBodyEntryTest(IROList *list, IROLinear *iterCount, UInt32 unrollFactor, CLabel *label); +extern void ChangeInductionReference(IROLinear *first, IROLinear *last, CInt64 val, IROLoop *loop); +extern IROLinear *UpdateInductionIncrement(IROLoop *loop, SInt32 value, IROLinear *before); +extern void GenInitialAssignment(IROLoop *loop, Object *var, IROList *list); +extern void GenNewInduction(void); + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroUtil.c b/compiler_and_linker/FrontEnd/Optimizer/IroUtil.c new file mode 100644 index 0000000..7e6321d --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroUtil.c @@ -0,0 +1,1262 @@ +#include "IroUtil.h" +#include "IroCSE.h" +#include "IroDump.h" +#include "IroFlowgraph.h" +#include "IroLinearForm.h" +#include "IroLoop.h" +#include "IroVars.h" +#include "compiler/InlineAsmPPC.h" +#include "compiler/CompilerTools.h" +#include "compiler/CCompiler.h" +#include "compiler/CError.h" +#include "compiler/CException.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/Exceptions.h" +#include "compiler/objects.h" +#include "compiler/types.h" +#include "cos.h" + +static UInt32 IRO_LastUserBreakTick; +static IROLinear *ExprStart; +static IROLinear *ExprEnd; +static IRONode *IRO_Node; +static SInt32 FuncLevel; +Object *FunctionName; +Boolean IRO_IsLeafFunction; +Boolean IRO_FunctionHasReturn; +Boolean DisableDueToAsm; +Boolean LoopOptimizerRun; + +Object *IRO_IsVariable(IROLinear *linear) { + if (linear->type == IROLinearOp1Arg && + linear->nodetype == EINDIRECT && + linear->u.monadic->type == IROLinearOperand && + linear->u.monadic->u.node->type == EOBJREF) + return linear->u.monadic->u.node->data.objref; + + return NULL; +} + +Boolean IRO_IsConstant(IROLinear *linear) { + if (linear->type == IROLinearOperand && ENODE_IS3(linear->u.node, EINTCONST, EVECTOR128CONST, EFLOATCONST)) + return 1; + return 0; +} + +Boolean IRO_IsPow2(IROLinear *linear, SInt32 *powvalue) { + UInt32 desired; + UInt32 value; + SInt32 i; + + *powvalue = -1; + if (linear->type == IROLinearOperand && linear->u.node->type == EINTCONST) { + if (CTool_EndianReadWord32(&linear->u.node->data.intval.hi)) + return 0; + + desired = CInt64_GetULong(&linear->u.node->data.intval); + value = 1; + for (i = 0; i < 31; i++) { + if (value == desired) { + *powvalue = i; + return 1; + } + value += value; + } + } + + return 0; +} + +Boolean IRO_IsIntConstant(IROLinear *linear) { + if (linear->type == IROLinearOperand && ENODE_IS(linear->u.node, EINTCONST)) + return 1; + return 0; +} + +Boolean IRO_IsFloatConstant(IROLinear *linear) { + if (linear->type == IROLinearOperand && ENODE_IS(linear->u.node, EFLOATCONST)) + return 1; + return 0; +} + +Boolean IRO_IsVector128Constant(IROLinear *linear) { + if (linear->type == IROLinearOperand && ENODE_IS(linear->u.node, EVECTOR128CONST)) + return 1; + return 0; +} + +Boolean IRO_IsAssignment(IROLinear *linear) { + if (linear->type == IROLinearOp1Arg || linear->type == IROLinearOp2Arg) { + if (IRO_IsAssignOp[linear->nodetype]) + return 1; + } + return 0; +} + +static Boolean IRO_OperandsSame(ENode *a, ENode *b) { + if (a->type == b->type) { + switch (a->type) { + case EINTCONST: + return CInt64_Equal(a->data.intval, b->data.intval); + case ESTRINGCONST: + return 0; + case EFLOATCONST: + return a->data.floatval.value == b->data.floatval.value; + case EVECTOR128CONST: + return (a->data.vector128val.ul[0] == b->data.vector128val.ul[0]) && + (a->data.vector128val.ul[1] == b->data.vector128val.ul[1]) && + (a->data.vector128val.ul[2] == b->data.vector128val.ul[2]) && + (a->data.vector128val.ul[3] == b->data.vector128val.ul[3]); + case EOBJREF: + return a->data.objref == b->data.objref; + } + } + + return 0; +} + +Boolean IRO_TypesEqual(Type *a, Type *b) { + if (IS_TYPE_BITFIELD(a)) { + if (IS_TYPE_BITFIELD(b)) { + if ( + (TYPE_BITFIELD(a)->bitfieldtype == TYPE_BITFIELD(b)->bitfieldtype) && + (TYPE_BITFIELD(a)->offset == TYPE_BITFIELD(b)->offset) && + (TYPE_BITFIELD(a)->bitlength == TYPE_BITFIELD(b)->bitlength)) + return 1; + } + return 0; + } + + if (IS_TYPE_POINTER_ONLY(a) && IS_TYPE_POINTER_ONLY(b)) + return 1; + + return is_typeequal(a, b) != 0; +} + +Type *IRO_UnsignedType(Type *type) { + if (IS_TYPE_ENUM(type) || IS_TYPE_POINTER_ONLY(type)) { + if (type->size == stunsignedchar.size) + return TYPE(&stunsignedchar); + if (type->size == stunsignedint.size) + return TYPE(&stunsignedint); + if (type->size == stunsignedshort.size) + return TYPE(&stunsignedshort); + if (type->size == stunsignedlong.size) + return TYPE(&stunsignedlong); + if (type->size == stunsignedlonglong.size) + return TYPE(&stunsignedlonglong); + CError_FATAL(281); + return NULL; + } + + if (!IS_TYPE_INT(type)) { + CError_FATAL(287); + return NULL; + } + + if (type == TYPE(&stbool) || type == TYPE(&stwchar)) + return type; + + if (type == TYPE(&stchar) || type == TYPE(&stsignedchar) || type == TYPE(&stunsignedchar)) + return TYPE(&stunsignedchar); + if (type == TYPE(&stsignedshort) || type == TYPE(&stunsignedshort)) + return TYPE(&stunsignedshort); + if (type == TYPE(&stsignedint) || type == TYPE(&stunsignedint)) + return TYPE(&stunsignedint); + if (type == TYPE(&stsignedlong) || type == TYPE(&stunsignedlong)) + return TYPE(&stunsignedlong); + if (type == TYPE(&stsignedlonglong) || type == TYPE(&stunsignedlonglong)) + return TYPE(&stunsignedlonglong); + + CError_FATAL(319); + return NULL; +} + +Type *IRO_SignedType(Type *type) { + if (IS_TYPE_ENUM(type) || IS_TYPE_POINTER_ONLY(type)) { + if (type->size == stsignedchar.size) + return TYPE(&stsignedchar); + if (type->size == stsignedint.size) + return TYPE(&stsignedint); + if (type->size == stsignedshort.size) + return TYPE(&stsignedshort); + if (type->size == stsignedlong.size) + return TYPE(&stsignedlong); + if (type->size == stsignedlonglong.size) + return TYPE(&stsignedlonglong); + CError_FATAL(357); + return NULL; + } + + if (!IS_TYPE_INT(type)) { + CError_FATAL(363); + return NULL; + } + + if (type == TYPE(&stbool) && type->size == stsignedchar.size) + return TYPE(&stsignedchar); + + if (type == TYPE(&stwchar) && type->size == stsignedshort.size) + return TYPE(&stsignedshort); + + if (type == TYPE(&stchar) || type == TYPE(&stsignedchar) || type == TYPE(&stunsignedchar)) + return TYPE(&stsignedchar); + if (type == TYPE(&stsignedshort) || type == TYPE(&stunsignedshort)) + return TYPE(&stsignedshort); + if (type == TYPE(&stsignedint) || type == TYPE(&stunsignedint)) + return TYPE(&stsignedint); + if (type == TYPE(&stsignedlong) || type == TYPE(&stunsignedlong)) + return TYPE(&stsignedlong); + if (type == TYPE(&stsignedlonglong) || type == TYPE(&stunsignedlonglong)) + return TYPE(&stsignedlonglong); + + CError_FATAL(399); + return NULL; +} + +Boolean IRO_is_CPtypeequal(Type *a, Type *b) { + if (IS_TYPE_POINTER_ONLY(a) && IS_TYPE_POINTER_ONLY(b)) + return 1; + + return is_typeequal(a, b) != 0; +} + +Boolean IRO_ExprsSame(IROLinear *a, IROLinear *b) { + if (a->type == b->type && IRO_TypesEqual(a->rtype, b->rtype)) { + switch (a->type) { + case IROLinearOperand: + return IRO_OperandsSame(a->u.node, b->u.node); + case IROLinearOp1Arg: + if (a->nodetype == b->nodetype) + return IRO_ExprsSame(a->u.monadic, b->u.monadic); + return 0; + case IROLinearOp2Arg: + if (a->nodetype == b->nodetype) + return IRO_ExprsSame(a->u.diadic.left, b->u.diadic.left) && + IRO_ExprsSame(a->u.diadic.right, b->u.diadic.right); + return 0; + case IROLinearOp3Arg: + if (a->nodetype == b->nodetype) + return IRO_ExprsSame(a->u.args3.a, b->u.args3.a) && + IRO_ExprsSame(a->u.args3.b, b->u.args3.b) && + IRO_ExprsSame(a->u.args3.c, b->u.args3.c); + return 0; + case IROLinearFunccall: + return 0; + default: + return 0; + } + } + + return 0; +} + +CLabel *IRO_NewLabel(void) { + CLabel *label = newlabel(); + label->next = Labels; + Labels = label; + return label; +} + +Boolean IRO_ExprsSameSemantically(IROLinear *a, IROLinear *b) { + if (a->type == b->type && IRO_TypesEqual(a->rtype, b->rtype)) { + Boolean flag = 0; + + switch (a->type) { + case IROLinearOperand: + return IRO_OperandsSame(a->u.node, b->u.node); + case IROLinearOp1Arg: + if (a->nodetype == b->nodetype) + return IRO_ExprsSameSemantically(a->u.monadic, b->u.monadic); + return 0; + case IROLinearOp2Arg: + if (a->nodetype == b->nodetype) { + switch (a->nodetype) { + case EMUL: + case EADD: + case EAND: + case EXOR: + case EOR: + case ELAND: + case ELOR: + if (!IRO_HasSideEffect(a)) { + flag = IRO_ExprsSameSemantically(a->u.diadic.left, b->u.diadic.right) && + IRO_ExprsSameSemantically(a->u.diadic.right, b->u.diadic.left); + } + } + + return flag || (IRO_ExprsSameSemantically(a->u.diadic.left, b->u.diadic.left) && + IRO_ExprsSameSemantically(a->u.diadic.right, b->u.diadic.right)); + } + return 0; + case IROLinearOp3Arg: + if (a->nodetype == b->nodetype) + return IRO_ExprsSameSemantically(a->u.args3.a, b->u.args3.a) && + IRO_ExprsSameSemantically(a->u.args3.b, b->u.args3.b) && + IRO_ExprsSameSemantically(a->u.args3.c, b->u.args3.c); + return 0; + case IROLinearFunccall: + return 0; + default: + return 0; + } + } + + return 0; +} + +IROLinear *IRO_FindPrecedAfter(IROLinear *a, IROLinear *iter) { + IROLinear *prev = iter; + while (iter && iter != a) { + prev = iter; + iter = iter->next; + } + + if (iter) + return prev; + return iter; +} + +IROLinear *IRO_FindPreced(IROLinear *a) { + IROLinear *iter; + IROLinear *prev; + + prev = iter = IRO_FirstLinear; + while (iter && iter != a) { + prev = iter; + iter = iter->next; + } + + if (iter) + return prev; + return iter; +} + +IROLinear *IRO_FindFirst(IROLinear *linear) { + short i; + + switch (linear->type) { + case IROLinearOperand: + return linear; + case IROLinearOp1Arg: + return IRO_FindFirst(linear->u.monadic); + case IROLinearOp2Arg: + if (linear->u.diadic.right->index < linear->u.diadic.left->index) + return IRO_FindFirst(linear->u.diadic.right); + else + return IRO_FindFirst(linear->u.diadic.left); + case IROLinearOp3Arg: + if (linear->u.args3.a->index < linear->u.args3.b->index) { + if (linear->u.args3.b->index < linear->u.args3.c->index) + return IRO_FindFirst(linear->u.args3.a); + else + return IRO_FindFirst(linear->u.args3.c); + } else { + if (linear->u.args3.b->index < linear->u.args3.c->index) + return IRO_FindFirst(linear->u.args3.b); + else + return IRO_FindFirst(linear->u.args3.c); + } + case IROLinearFunccall: + i = linear->u.funccall.argCount - 1; + return IRO_FindFirst(linear->u.funccall.args[i]); + default: + CError_FATAL(641); + return NULL; + } +} + +void IRO_CutAndPasteAfter(IROLinear *a, IROLinear *b, IROLinear *c) { + IROLinear *preced = IRO_FindPreced(a); + preced->next = b->next; + b->next = c->next; + c->next = a; +} + +Boolean IRO_IsConstantZero(IROLinear *linear) { + return (IRO_IsIntConstant(linear) && CInt64_IsZero(&linear->u.node->data.intval)) || + (IRO_IsFloatConstant(linear) && CMach_FloatIsZero(linear->u.node->data.floatval)); +} + +Boolean IRO_IsConstantOne(IROLinear *linear) { + return (IRO_IsIntConstant(linear) && CInt64_IsOne(&linear->u.node->data.intval)) || + (IRO_IsFloatConstant(linear) && CMach_FloatIsOne(linear->u.node->data.floatval)); +} + +Boolean IRO_IsConstantNegativeOne(IROLinear *linear) { + CInt64 neg = CInt64_Neg(linear->u.node->data.intval); + return (IRO_IsIntConstant(linear) && CInt64_IsOne(&neg)) || + (IRO_IsFloatConstant(linear) && CMach_FloatIsNegOne(linear->u.node->data.floatval)); +} + +static void ActNop(IROLinear *linear, Boolean isEntry) { + if (!isEntry) { + linear->type = IROLinearNop; + linear->expr = NULL; + } +} + +void IRO_NopOut(IROLinear *linear) { + IRO_WalkTree(linear, ActNop); +} + +static Boolean NotNoppable(IROLinear *linear) { + return ( + (linear->type == IROLinearFunccall) || + IRO_IsAssignment(linear) || + ((linear->type == IROLinearOperand) && ENODE_IS(linear->u.node, EINSTRUCTION)) || + (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) || + ((linear->type == IROLinearOperand) && ENODE_IS(linear->u.node, EOBJREF) && is_volatile_object(linear->u.node->data.objref)) + ); +} + +static void ActNopNonSideEffects(IROLinear *linear, Boolean isEntry) { + if (isEntry) { + if (NotNoppable(linear)) { + if (!FuncLevel) + linear->flags &= ~IROLF_Reffed; + FuncLevel++; + } + } else { + if (NotNoppable(linear)) { + FuncLevel--; + } else if (!FuncLevel) { + linear->type = IROLinearNop; + } + } +} + +void IRO_NopNonSideEffects(IROLinear *linear, SInt32 level) { + FuncLevel = level; + IRO_WalkTree(linear, ActNopNonSideEffects); +} + +void IRO_BuildList(IROLinear *linear, Boolean isEntry) { + if (!isEntry) { + linear->next = NULL; + IRO_AddToList(linear, &IRO_InitLList); + } +} + +void IRO_WalkTree(IROLinear *linear, IROWalkTreeFunc func) { + int i; + + func(linear, 1); + switch (linear->type) { + case IROLinearOperand: + break; + case IROLinearOp1Arg: + IRO_WalkTree(linear->u.monadic, func); + break; + case IROLinearOp2Arg: + IRO_WalkTree(linear->u.diadic.left, func); + IRO_WalkTree(linear->u.diadic.right, func); + break; + case IROLinearOp3Arg: + IRO_WalkTree(linear->u.args3.a, func); + IRO_WalkTree(linear->u.args3.b, func); + IRO_WalkTree(linear->u.args3.c, func); + break; + case IROLinearFunccall: + IRO_WalkTree(linear->u.funccall.linear8, func); + for (i = 0; i < linear->u.funccall.argCount; i++) + IRO_WalkTree(linear->u.funccall.args[i], func); + break; + } + func(linear, 0); +} + +void IRO_WalkTreeToPropagateFlags(IROLinear *linear, IROWalkTreeFunc func) { + int i; + + switch (linear->type) { + case IROLinearOperand: + break; + case IROLinearOp1Arg: + IRO_WalkTreeToPropagateFlags(linear->u.monadic, func); + break; + case IROLinearOp2Arg: + IRO_WalkTreeToPropagateFlags(linear->u.diadic.left, func); + IRO_WalkTreeToPropagateFlags(linear->u.diadic.right, func); + break; + case IROLinearOp3Arg: + IRO_WalkTreeToPropagateFlags(linear->u.args3.a, func); + IRO_WalkTreeToPropagateFlags(linear->u.args3.b, func); + IRO_WalkTreeToPropagateFlags(linear->u.args3.c, func); + break; + case IROLinearFunccall: + IRO_WalkTreeToPropagateFlags(linear->u.funccall.linear8, func); + for (i = 0; i < linear->u.funccall.argCount; i++) + IRO_WalkTreeToPropagateFlags(linear->u.funccall.args[i], func); + break; + } + func(linear, 0); +} + +void IRO_WalkInts(IROLinear *a, IROLinear *b, IROWalkTreeFunc func) { + IROLinear *scan; + + for (scan = a; scan; scan = scan->next) { + switch (scan->type) { + case IROLinearBeginCatch: + case IROLinearEndCatch: + case IROLinearEndCatchDtor: + IRO_WalkTree(scan->u.ctch.linear, func); + break; + case IROLinearOperand: + case IROLinearOp1Arg: + case IROLinearOp2Arg: + case IROLinearOp3Arg: + case IROLinearFunccall: + IRO_WalkTree(scan, func); + break; + case IROLinearIf: + case IROLinearIfNot: + IRO_WalkTree(scan->u.label.x4, func); + break; + case IROLinearReturn: + if (scan->u.monadic) + IRO_WalkTree(scan->u.monadic, func); + break; + case IROLinearSwitch: + IRO_WalkTree(scan->u.swtch.x4, func); + break; + case IROLinearAsm: + func(scan, 1); + func(scan, 0); + break; + case IROLinearEnd: + break; + } + + if (scan == b) + break; + } +} + +void IRO_Cut(IROLinear *a, IROLinear *b) { + IROLinear *scan; + IROLinear *prev; + IRONode *node; + + scan = a; + while (1) { + scan->stmt = NULL; + if (scan == b) + break; + scan = scan->next; + } + + prev = NULL; + for (scan = IRO_FirstLinear; scan && scan != a; scan = scan->next) + prev = scan; + + CError_ASSERT(951, scan); + + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->first == a) { + if (node->last == b) { + node->first = node->last = NULL; + break; + } else { + node->first = b->next; + break; + } + } else if (node->last == b) { + node->last = prev; + break; + } + } + + if (prev) + prev->next = b->next; + else + IRO_FirstLinear = b->next; +} + +void IRO_Paste(IROLinear *a, IROLinear *b, IROLinear *c) { + IROLinear *prev; + IROLinear *scan; + IRONode *node; + + CError_ASSERT(1002, c && c->type != IROLinearLabel); + + prev = NULL; + for (scan = IRO_FirstLinear; scan && scan != c; scan = scan->next) + prev = scan; + + CError_ASSERT(1016, scan); + + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->first == c) { + node->first = a; + break; + } + } + + b->next = c; + if (prev) + prev->next = a; + else + IRO_FirstLinear = a; +} + +void IRO_PasteAfter(IROLinear *a, IROLinear *b, IROLinear *c) { + IRONode *node; + + switch (c->type) { + case IROLinearGoto: + case IROLinearIf: + case IROLinearIfNot: + case IROLinearSwitch: + CError_FATAL(1060); + } + + for (node = IRO_FirstNode; node; node = node->nextnode) { + if (node->last == c) { + node->last = b; + break; + } + } + + b->next = c->next; + c->next = a; +} + +static void FindStart(IROLinear *linear, Boolean isEntry) { + IROLinear *scan; + if (isEntry) { + scan = linear; + do { + if (scan == ExprStart) { + ExprStart = linear; + return; + } + if (scan == ExprEnd) + return; + } while ((scan = scan->next)); + } +} + +void IRO_ClipExpr(IROExpr *expr) { + ExprStart = ExprEnd = expr->linear; + IRO_WalkTree(expr->linear, FindStart); + IRO_Cut(ExprStart, ExprEnd); +} + +void IRO_ClipExprTree(IROLinear *linear) { + ExprStart = ExprEnd = linear; + IRO_WalkTree(linear, FindStart); + IRO_Cut(ExprStart, ExprEnd); +} + +static void SetNodeNumInExprList(IROLinear *linear, Boolean isEntry) { + if (isEntry && linear->expr) + linear->expr->node = IRO_Node; +} + +void IRO_MoveExpression(IROExpr *expr, IROLinear *linear) { + IRONode *node; + IROLinear *scan; + + ExprStart = ExprEnd = expr->linear; + IRO_WalkTree(expr->linear, FindStart); + + if (ExprStart != linear) { + IRO_Cut(ExprStart, ExprEnd); + IRO_Paste(ExprStart, ExprEnd, linear); + for (node = IRO_FirstNode; node; node = node->nextnode) { + for (scan = node->first; scan; scan = scan->next) { + if (scan == expr->linear) { + expr->node = node; + break; + } + if (scan == node->last) + break; + } + } + + IRO_Node = expr->node; + IRO_WalkTree(expr->linear, SetNodeNumInExprList); + } +} + +void IRO_InitList(IROList *list) { + list->head = list->tail = NULL; +} + +void IRO_AddToList(IROLinear *linear, IROList *list) { + if (list->head) + list->tail->next = linear; + else + list->head = linear; + + list->tail = linear; + while (list->tail->next) + list->tail = list->tail->next; +} + +IROLinear *IRO_FindLabelNode(CLabel *label, IROLinear *linear) { + IROLinear *scan; + + for (scan = linear; scan; scan = scan->next) { + if (scan->type == IROLinearLabel && scan->u.label.label == label) + break; + } + + CError_ASSERT(1244, scan); + return scan; +} + +void IRO_DuplicateExprRange(IROLinear *start, IROLinear *end, IROList *list) { + IROLinear *scan; + + for (scan = start; scan; scan = scan->next) { + if (scan->type != IROLinearNop && !(scan->flags & IROLF_Reffed)) + IRO_DuplicateExpr(scan, list); + if (scan == end) + break; + } +} + +IROLinear *IRO_DuplicateExpr(IROLinear *linear, IROList *list) { + IROLinear *copy; + ENode *copynode; + int i; + + copy = IRO_NewLinear(linear->type); + *copy = *linear; + + copy->index = ++IRO_NumLinear; + copy->next = NULL; + copy->expr = NULL; + + switch (copy->type) { + case IROLinearOperand: + copynode = lalloc(sizeof(ENode)); + *copynode = *linear->u.node; + copy->u.node = copynode; + break; + case IROLinearOp1Arg: + copy->u.monadic = IRO_DuplicateExpr(copy->u.monadic, list); + break; + case IROLinearOp2Arg: + if (linear->flags & IROLF_8000) { + copy->u.diadic.right = IRO_DuplicateExpr(copy->u.diadic.right, list); + copy->u.diadic.left = IRO_DuplicateExpr(copy->u.diadic.left, list); + } else { + copy->u.diadic.left = IRO_DuplicateExpr(copy->u.diadic.left, list); + copy->u.diadic.right = IRO_DuplicateExpr(copy->u.diadic.right, list); + } + break; + case IROLinearOp3Arg: + copy->u.args3.a = IRO_DuplicateExpr(copy->u.args3.a, list); + copy->u.args3.b = IRO_DuplicateExpr(copy->u.args3.b, list); + copy->u.args3.c = IRO_DuplicateExpr(copy->u.args3.c, list); + break; + case IROLinearFunccall: + copy->u.funccall.linear8 = IRO_DuplicateExpr(copy->u.funccall.linear8, list); + copy->u.funccall.args = oalloc(sizeof(IROLinear *) * copy->u.funccall.argCount); + for (i = 0; i < copy->u.funccall.argCount; i++) { + copy->u.funccall.args[i] = IRO_DuplicateExpr(linear->u.funccall.args[i], list); + } + break; + case IROLinearAsm: + copy->u.asm_stmt = CodeGen_CopyAsmStat(linear->u.asm_stmt); + break; + } + + IRO_AddToList(copy, list); + return copy; +} + +IROLinear *IRO_TempReference(Object *obj, IROList *list) { + IROLinear *op; + IROLinear *ind; + + op = IRO_NewLinear(IROLinearOperand); + op->u.node = create_objectrefnode(obj); + op->rtype = op->u.node->data.objref->type; + op->index = ++IRO_NumLinear; + op->flags |= IROLF_Reffed | IROLF_Ind; + IRO_AddToList(op, list); + + ind = IRO_NewLinear(IROLinearOp1Arg); + ind->nodetype = EINDIRECT; + ind->rtype = obj->type; + ind->u.monadic = op; + ind->index = ++IRO_NumLinear; + ind->next = NULL; + IRO_AddToList(ind, list); + + return ind; +} + +CW_INLINE IROLinear *LocateFatherHelper(IROLinear *linear, Boolean a, IROLinear ***b) { + IROLinear *scan; + SInt32 index; + int i; + + for (scan = linear->next, index = 0; index < (a ? 2 : 1); index++) { + while (scan) { + switch (scan->type) { + case IROLinearIf: + case IROLinearIfNot: + if (scan->u.label.x4 == linear) { + if (b) + *b = &scan->u.label.x4; + return scan; + } + break; + case IROLinearReturn: + if (scan->u.monadic == linear) { + if (b) + *b = &scan->u.monadic; + return scan; + } + break; + case IROLinearOp1Arg: + if (scan->u.monadic == linear) { + if (b) + *b = &scan->u.monadic; + return scan; + } + break; + case IROLinearSwitch: + if (scan->u.swtch.x4 == linear) { + if (b) + *b = &scan->u.swtch.x4; + return scan; + } + break; + case IROLinearOp2Arg: + if (scan->u.diadic.left == linear) { + if (b) + *b = &scan->u.diadic.left; + return scan; + } + if (scan->u.diadic.right == linear) { + if (b) + *b = &scan->u.diadic.right; + return scan; + } + break; + case IROLinearOp3Arg: + if (scan->u.args3.a == linear) { + if (b) + *b = &scan->u.args3.a; + return scan; + } + if (scan->u.args3.b == linear) { + if (b) + *b = &scan->u.args3.b; + return scan; + } + if (scan->u.args3.c == linear) { + if (b) + *b = &scan->u.args3.c; + return scan; + } + break; + case IROLinearFunccall: + if (scan->u.funccall.linear8 == linear) { + if (b) + *b = &scan->u.funccall.linear8; + return scan; + } + for (i = 0; i < scan->u.funccall.argCount; i++) { + if (scan->u.funccall.args[i] == linear) { + if (b) + *b = &scan->u.funccall.args[i]; + return scan; + } + } + break; + case IROLinearNop: + case IROLinearOperand: + case IROLinearGoto: + case IROLinearLabel: + case IROLinearEntry: + case IROLinearExit: + case IROLinearBeginCatch: + case IROLinearEndCatch: + case IROLinearEndCatchDtor: + case IROLinearAsm: + case IROLinearEnd: + break; + default: + CError_FATAL(1536); + } + scan = scan->next; + } + + scan = IRO_FirstLinear; + } + + if (b) + *b = NULL; + return NULL; +} + +IROLinear *IRO_LocateFather(IROLinear *linear) { + return LocateFatherHelper(linear, 0, NULL); +} + +IROLinear *IRO_LocateFather_Cut_And_Paste(IROLinear *a, IROLinear *b) { + IROLinear **p; + IROLinear *l = LocateFatherHelper(a, 0, &p); + if (l) { + CError_ASSERT(1568, p && *p); + IRO_NopOut(a); + *p = b; + } + return l; +} + +IROLinear *IRO_LocateFather_Cut_And_Paste_Without_Nopping(IROLinear *a, IROLinear *b) { + IROLinear **p; + IROLinear *l = LocateFatherHelper(a, 0, &p); + if (l) { + CError_ASSERT(1585, p && *p); + *p = b; + } + return l; +} + +void IRO_ReplaceReference(IROLinear *a, Object *obj, IROLinear *b) { + IROLinear **ptr; + IROList list; + + if (LocateFatherHelper(a, 1, &ptr)) { + CError_ASSERT(1605, ptr && *ptr); + IRO_InitList(&list); + *ptr = IRO_TempReference(obj, &list); + IRO_PasteAfter(list.head, list.tail, b); + if (a->flags & IROLF_LoopInvariant) + list.tail->flags |= IROLF_LoopInvariant; + } else { + IRO_Dump("Oh, oh, did not find reference to replace\n"); + } +} + +void IRO_ReplaceReferenceWithNode(IROLinear *a, IROLinear *b) { + IROLinear **ptr; + IROList list; + + if (LocateFatherHelper(a, 1, &ptr)) { + CError_ASSERT(1664, ptr && *ptr); + *ptr = b; + b->flags |= IROLF_Reffed; + } else { + IRO_Dump("Oh, oh, did not find reference to replace\n"); + } +} + +VarRecord *IRO_GetTemp(IROExpr *expr) { + expr->x8 = create_temp_object(expr->linear->rtype); + return IRO_FindVar(expr->x8, 1, 1); +} + +IROLinear *IRO_AssignToTemp(IROExpr *expr) { + IROLinear *objref; + IROLinear *ind; + IROLinear *ass; + + objref = IRO_NewLinear(IROLinearOperand); + objref->u.node = create_objectrefnode(expr->x8); + objref->rtype = objref->u.node->data.objref->type; + objref->index = ++IRO_NumLinear; + objref->flags |= IROLF_Reffed | IROLF_Assigned | IROLF_Ind; + + ind = IRO_NewLinear(IROLinearOp1Arg); + ind->nodetype = EINDIRECT; + ind->rtype = expr->linear->rtype; + ind->u.monadic = objref; + ind->index = ++IRO_NumLinear; + ind->flags |= IROLF_Reffed | IROLF_Assigned; + + ass = IRO_NewLinear(IROLinearOp2Arg); + ass->nodetype = EASS; + ass->u.diadic.left = ind; + ass->u.diadic.right = expr->linear; + ass->rtype = expr->linear->rtype; + ass->index = ++IRO_NumLinear; + + objref->next = ind; + ind->next = ass; + IRO_PasteAfter(objref, ass, expr->linear); + return ass; +} + +IROLinear *IRO_FindStart(IROLinear *linear) { + ExprStart = ExprEnd = linear; + IRO_WalkTree(linear, FindStart); + return ExprStart; +} + +void IRO_DeleteCommaNode(IROLinear *linear, IROExpr *expr) { + IROLinear *scan; + for (scan = linear; scan; scan = scan->next) { + if (scan->nodetype == ECOMMA) { + if (scan != expr->linear) { + IRO_NopOut(scan->u.diadic.left); + IRO_LocateFather_Cut_And_Paste(scan, scan->u.diadic.right); + } else { + IRO_NopOut(scan->u.diadic.left); + expr->linear = scan->u.diadic.right; + } + } + } +} + +void IRO_RemoveCommaNodeFromIR(void) { + IRONode *node; + IROLinear *linear; + + for (node = IRO_FirstNode; node; node = node->nextnode) { + linear = node->first; + do { + if (!linear) + break; + if (linear->nodetype == ECOMMA) { + linear->u.diadic.left->flags = linear->u.diadic.left->flags & ~IROLF_Reffed; + IRO_LocateFather_Cut_And_Paste_Without_Nopping(linear, linear->u.diadic.right); + linear->type = IROLinearNop; + } + linear = linear->next; + } while (linear != node->last); + } +} + +IROAddrRecord *IRO_InitAddrRecordPointer(IROLinear *linear) { + IROAddrRecord *rec = oalloc(sizeof(IROAddrRecord)); + rec->numObjRefs = 0; + rec->objRefs = NULL; + rec->numMisc = 0; + rec->misc = NULL; + rec->numInts = 0; + rec->ints = NULL; + rec->x16 = 0; + rec->linear = linear; + return rec; +} + +IROLinear *IRO_HasSideEffect(IROLinear *linear) { + IROLinear *tmp; + + if (!linear) + return linear; + + if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) + return linear; + + switch (linear->type) { + case IROLinearAsm: + return linear; + case IROLinearOperand: + if (ENODE_IS(linear->u.node, EOBJREF) && is_volatile_object(linear->u.node->data.objref)) + return linear; + return NULL; + case IROLinearOp1Arg: + if (IRO_IsAssignOp[linear->nodetype]) + return linear; + else + return IRO_HasSideEffect(linear->u.monadic); + case IROLinearOp2Arg: + if (IRO_IsAssignOp[linear->nodetype]) + return linear; + else if ((tmp = IRO_HasSideEffect(linear->u.diadic.left))) + return tmp; + else + return IRO_HasSideEffect(linear->u.diadic.right); + case IROLinearOp3Arg: + if ((tmp = IRO_HasSideEffect(linear->u.args3.a))) + return tmp; + else if ((tmp = IRO_HasSideEffect(linear->u.args3.b))) + return tmp; + else + return IRO_HasSideEffect(linear->u.args3.c); + case IROLinearFunccall: + return linear; + default: + return linear; + } +} + +IROLinear *IRO_CheckSideEffect(IROLinear *linear) { + IROLinear *result; + IROLinear *tmp; + IROLinear *tmp2; + IROLinear *tmp3; + + if (!linear) + return linear; + + if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) { + linear->flags &= ~IROLF_Reffed; + return linear; + } + + result = NULL; + switch (linear->type) { + case IROLinearAsm: + linear->flags &= ~IROLF_Reffed; + return linear; + case IROLinearOperand: + if (ENODE_IS(linear->u.node, EOBJREF) && is_volatile_object(linear->u.node->data.objref)) { + linear->flags &= ~IROLF_Reffed; + return linear; + } + break; + case IROLinearOp1Arg: + if (IRO_IsAssignOp[linear->nodetype]) { + linear->flags &= ~IROLF_Reffed; + return linear; + } + if ((result = IRO_CheckSideEffect(linear->u.monadic))) { + if (linear->nodetype == EINDIRECT && linear->u.monadic->type == IROLinearOperand) { + linear->flags &= ~IROLF_Reffed; + return linear; + } + } + break; + case IROLinearOp2Arg: + if (IRO_IsAssignOp[linear->nodetype]) { + linear->flags &= ~IROLF_Reffed; + return linear; + } + tmp = IRO_CheckSideEffect(linear->u.diadic.left); + tmp2 = IRO_CheckSideEffect(linear->u.diadic.right); + if (tmp) + result = tmp; + else + result = tmp2; + break; + case IROLinearOp3Arg: + tmp = IRO_CheckSideEffect(linear->u.args3.a); + tmp2 = IRO_CheckSideEffect(linear->u.args3.b); + tmp3 = IRO_CheckSideEffect(linear->u.args3.c); + result = tmp ? tmp : tmp2 ? tmp2 : tmp3; + break; + case IROLinearFunccall: + linear->flags &= ~IROLF_Reffed; + return linear; + default: + return linear; + } + + linear->type = IROLinearNop; + IRO_Dump("Nop out with side-effects checking at: %d\n", linear->index); + return result; +} + +void IRO_WalkExcActions(ExceptionAction *action, WalkObjFunc func) { + while (action) { + switch (action->type) { + case EAT_DESTROYLOCAL: + func(action->data.destroy_local.local); + break; + case EAT_DESTROYLOCALCOND: + func(action->data.destroy_local_cond.local); + func(action->data.destroy_local_cond.cond); + break; + case EAT_DESTROYLOCALOFFSET: + func(action->data.destroy_local_offset.local); + break; + case EAT_DESTROYLOCALPOINTER: + func(action->data.destroy_local_pointer.pointer); + break; + case EAT_DESTROYLOCALARRAY: + func(action->data.destroy_local_array.localarray); + break; + case EAT_DESTROYPARTIALARRAY: + func(action->data.destroy_partial_array.arraypointer); + func(action->data.destroy_partial_array.arraycounter); + func(action->data.destroy_partial_array.element_size); + break; + case EAT_DESTROYBASE: + func(action->data.destroy_member.objectptr); // wrong union? + break; + case EAT_DESTROYMEMBER: + func(action->data.destroy_member.objectptr); + break; + case EAT_DESTROYMEMBERCOND: + func(action->data.destroy_member_cond.objectptr); + func(action->data.destroy_member_cond.cond); + break; + case EAT_DESTROYMEMBERARRAY: + func(action->data.destroy_member_array.objectptr); + break; + case EAT_DELETEPOINTER: + func(action->data.delete_pointer.pointerobject); + break; + case EAT_DELETEPOINTERCOND: + func(action->data.delete_pointer_cond.pointerobject); + func(action->data.delete_pointer_cond.cond); + break; + } + action = action->prev; + } +} + +Boolean IRO_FunctionCallMightThrowException(IROLinear *linear) { + Object *obj; + if (linear->type == IROLinearFunccall) { + obj = NULL; + if (linear->u.funccall.linear8->type == IROLinearOperand && ENODE_IS(linear->u.funccall.linear8->u.node, EOBJREF)) + obj = linear->u.funccall.linear8->u.node->data.objref; + if (!obj || CExcept_CanThrowException(obj, obj->datatype == DVFUNC && !(linear->nodeflags & ENODE_FLAG_80))) + return 1; + } + return 0; +} + +IROLinear *IRO_NewIntConst(CInt64 val, Type *type) { + ENode *node; + IROLinear *linear; + + node = IRO_NewENode(EINTCONST); + node->data.intval = val; + node->rtype = type; + + linear = IRO_NewLinear(IROLinearOperand); + linear->index = ++IRO_NumLinear; + linear->rtype = type; + linear->u.node = node; + return linear; +} + +IROLinear *IRO_NewFloatConst(const Float val, Type *type) { + ENode *node; + IROLinear *linear; + + node = IRO_NewENode(EFLOATCONST); + node->data.floatval = val; + node->rtype = type; + + linear = IRO_NewLinear(IROLinearOperand); + linear->index = ++IRO_NumLinear; + linear->rtype = type; + linear->u.node = node; + return linear; +} + +Boolean IRO_IsAddressMultiply(IROLinear *linear) { + return 0; +} + +void IRO_SetupForUserBreakChecking(void) { + IRO_LastUserBreakTick = 0; +} + +void IRO_CheckForUserBreak(void) { + if (IRO_LastUserBreakTick + 8 < COS_GetTicks()) { + if (CWUserBreak(cparams.context)) + CError_UserBreak(); + IRO_LastUserBreakTick = COS_GetTicks(); + } +} diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroUtil.h b/compiler_and_linker/FrontEnd/Optimizer/IroUtil.h new file mode 100644 index 0000000..2661985 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroUtil.h @@ -0,0 +1,127 @@ +#ifndef COMPILER_IROUTIL_H +#define COMPILER_IROUTIL_H + +#include "IrOptimizer.h" +#include "compiler/CInt64.h" +#include "compiler/CParser.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +struct IROList { + IROLinear *head; + IROLinear *tail; +}; + +struct IROListNode { + IROList list; + IROListNode *nextList; +}; + +struct IROElmList { + void *element; + IROElmList *next; +}; + +struct IROAddrRecord { + IROLinear *linear; + unsigned short numObjRefs; + IROElmList *objRefs; + unsigned short numMisc; + IROElmList *misc; + unsigned short numInts; + IROElmList *ints; + int x16; +}; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +extern Object *FunctionName; +extern Boolean IRO_IsLeafFunction; +extern Boolean IRO_FunctionHasReturn; +extern Boolean DisableDueToAsm; +extern Boolean LoopOptimizerRun; + +extern Object *IRO_IsVariable(IROLinear *linear); +extern Boolean IRO_IsConstant(IROLinear *linear); +extern Boolean IRO_IsPow2(IROLinear *linear, SInt32 *powvalue); +extern Boolean IRO_IsIntConstant(IROLinear *linear); +extern Boolean IRO_IsFloatConstant(IROLinear *linear); +extern Boolean IRO_IsVector128Constant(IROLinear *linear); +extern Boolean IRO_IsAssignment(IROLinear *linear); +extern Boolean IRO_TypesEqual(Type *a, Type *b); +extern Type *IRO_UnsignedType(Type *type); +extern Type *IRO_SignedType(Type *type); +extern Boolean IRO_is_CPtypeequal(Type *a, Type *b); +extern Boolean IRO_ExprsSame(IROLinear *a, IROLinear *b); +extern CLabel *IRO_NewLabel(void); +extern Boolean IRO_ExprsSameSemantically(IROLinear *a, IROLinear *b); +extern IROLinear *IRO_FindPrecedAfter(IROLinear *a, IROLinear *iter); +extern IROLinear *IRO_FindPreced(IROLinear *a); +extern IROLinear *IRO_FindFirst(IROLinear *linear); +extern void IRO_CutAndPasteAfter(IROLinear *a, IROLinear *b, IROLinear *c); +extern Boolean IRO_IsConstantZero(IROLinear *linear); +extern Boolean IRO_IsConstantOne(IROLinear *linear); +extern Boolean IRO_IsConstantNegativeOne(IROLinear *linear); +extern void IRO_NopOut(IROLinear *linear); +extern void IRO_NopNonSideEffects(IROLinear *linear, SInt32 level); +extern void IRO_BuildList(IROLinear *linear, Boolean isEntry); +typedef void (*IROWalkTreeFunc)(IROLinear *linear, Boolean isEntry); +extern void IRO_WalkTree(IROLinear *linear, IROWalkTreeFunc func); +extern void IRO_WalkTreeToPropagateFlags(IROLinear *linear, IROWalkTreeFunc func); +extern void IRO_WalkInts(IROLinear *a, IROLinear *b, IROWalkTreeFunc func); +extern void IRO_Cut(IROLinear *a, IROLinear *b); +extern void IRO_Paste(IROLinear *a, IROLinear *b, IROLinear *c); +extern void IRO_PasteAfter(IROLinear *a, IROLinear *b, IROLinear *c); +extern void IRO_ClipExpr(IROExpr *expr); +extern void IRO_ClipExprTree(IROLinear *linear); +extern void IRO_MoveExpression(IROExpr *expr, IROLinear *linear); +extern void IRO_InitList(IROList *list); +extern void IRO_AddToList(IROLinear *linear, IROList *list); +extern IROLinear *IRO_FindLabelNode(CLabel *label, IROLinear *linear); +extern void IRO_DuplicateExprRange(IROLinear *start, IROLinear *end, IROList *list); +extern IROLinear *IRO_DuplicateExpr(IROLinear *linear, IROList *list); +extern IROLinear *IRO_TempReference(Object *obj, IROList *list); +extern IROLinear *IRO_LocateFather(IROLinear *linear); +extern IROLinear *IRO_LocateFather_Cut_And_Paste(IROLinear *a, IROLinear *b); +extern IROLinear *IRO_LocateFather_Cut_And_Paste_Without_Nopping(IROLinear *a, IROLinear *b); +extern void IRO_ReplaceReference(IROLinear *a, Object *obj, IROLinear *b); +extern void IRO_ReplaceReferenceWithNode(IROLinear *a, IROLinear *b); +extern VarRecord *IRO_GetTemp(IROExpr *expr); +extern IROLinear *IRO_AssignToTemp(IROExpr *expr); +extern IROLinear *IRO_FindStart(IROLinear *linear); +extern void IRO_DeleteCommaNode(IROLinear *linear, IROExpr *expr); +extern void IRO_RemoveCommaNodeFromIR(void); +extern IROAddrRecord *IRO_InitAddrRecordPointer(IROLinear *linear); +extern IROLinear *IRO_HasSideEffect(IROLinear *linear); +extern IROLinear *IRO_CheckSideEffect(IROLinear *linear); +typedef void (*WalkObjFunc)(Object *obj); +extern void IRO_WalkExcActions(ExceptionAction *action, WalkObjFunc func); +extern Boolean IRO_FunctionCallMightThrowException(IROLinear *linear); +extern IROLinear *IRO_NewIntConst(CInt64 val, Type *type); +extern IROLinear *IRO_NewFloatConst(const Float val, Type *type); +extern Boolean IRO_IsAddressMultiply(IROLinear *linear); +extern void IRO_SetupForUserBreakChecking(void); +extern void IRO_CheckForUserBreak(void); + +// TODO is this elsewhere? +CW_INLINE Boolean IRO_IsUnsignedType(Type *type) { + return is_unsigned(type); +} + +// 4B4D40 +CW_INLINE CInt64 IRO_MakeULong(UInt32 i) { + CInt64 val; + CInt64_SetULong(&val, i); + return val; +} + +// 4BAAA0 +CW_INLINE CInt64 IRO_MakeLong(SInt32 i) { + CInt64 val; + CInt64_SetLong(&val, i); + return val; +} + +#endif diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroVars.c b/compiler_and_linker/FrontEnd/Optimizer/IroVars.c new file mode 100644 index 0000000..b72ba89 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroVars.c @@ -0,0 +1,1430 @@ +#include "IroVars.h" +#include "IroDump.h" +#include "IroFlowgraph.h" +#include "IroJump.h" +#include "IroLinearForm.h" +#include "IroMalloc.h" +#include "IroPointerAnalysis.h" +#include "IroUtil.h" +#include "IROUseDef.h" +#include "compiler/CClass.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CParser.h" +#include "compiler/CompilerTools.h" +#include "compiler/Exceptions.h" +#include "compiler/objects.h" +#include "compiler/InlineAsm.h" +#include "compiler/InlineAsmPPC.h" +#include "BitVector.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct IndirectRecordMatch { + IROLinear *nd; + struct IndirectRecordMatch *otherMatches; +} IndirectRecordMatch; + +typedef struct IndirectRecord { + IROLinear *linear; + unsigned char flags; + VarRecord *var; + SInt32 addend; + SInt32 size; + int startbit; + int endbit; + Type *type; + struct IndirectRecord *next; + IndirectRecordMatch *matches; + IROLinear *x26; +} IndirectRecord; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static IndirectRecord *IRO_FirstIndirectRecord; +static IndirectRecord *IRO_LastIndirectRecord; +static IROLinear *TheBaseTerm; +VarRecord *IRO_FirstVar; +VarRecord *IRO_LastVar; +SInt32 IRO_NumVars; +Boolean IRO_IsBitField; +SInt32 IRO_BaseTerms; +SInt32 IRO_VarTerms; +Boolean IRO_IsModifyOp[MAXEXPR]; +Boolean IRO_IsAssignOp[MAXEXPR]; + +// forward decls +static Boolean CheckAddress(IROLinear *nd, Boolean *resultFlag); +static Boolean CheckAddressConsistency(IROLinear *nd, VarRecord *var, SInt32 addend, Type *type); +static void DisableEntries(IndirectRecord *irec); +static void DisableAddressedEntries(void); +static UInt32 ObjectIsArg(Object *obj); + +void IRO_InitializeIRO_IsModifyOpArray(void) { + int i; + + for (i = 0; i < MAXEXPR; i++) + IRO_IsModifyOp[i] = 0; + + IRO_IsModifyOp[EPOSTINC] = 1; + IRO_IsModifyOp[EPOSTDEC] = 1; + IRO_IsModifyOp[EPREINC] = 1; + IRO_IsModifyOp[EPREDEC] = 1; + IRO_IsModifyOp[EINDIRECT] = 0; + IRO_IsModifyOp[EMONMIN] = 0; + IRO_IsModifyOp[EBINNOT] = 0; + IRO_IsModifyOp[ELOGNOT] = 0; + IRO_IsModifyOp[EFORCELOAD] = 0; + IRO_IsModifyOp[EMUL] = 0; + IRO_IsModifyOp[EMULV] = 0; + IRO_IsModifyOp[EDIV] = 0; + IRO_IsModifyOp[EMODULO] = 0; + IRO_IsModifyOp[EADDV] = 0; + IRO_IsModifyOp[ESUBV] = 0; + IRO_IsModifyOp[EADD] = 0; + IRO_IsModifyOp[ESUB] = 0; + IRO_IsModifyOp[ESHL] = 0; + IRO_IsModifyOp[ESHR] = 0; + IRO_IsModifyOp[ELESS] = 0; + IRO_IsModifyOp[EGREATER] = 0; + IRO_IsModifyOp[ELESSEQU] = 0; + IRO_IsModifyOp[EGREATEREQU] = 0; + IRO_IsModifyOp[EEQU] = 0; + IRO_IsModifyOp[ENOTEQU] = 0; + IRO_IsModifyOp[EAND] = 0; + IRO_IsModifyOp[EXOR] = 0; + IRO_IsModifyOp[EOR] = 0; + IRO_IsModifyOp[ELAND] = 0; + IRO_IsModifyOp[ELOR] = 0; + IRO_IsModifyOp[EASS] = 0; + IRO_IsModifyOp[EMULASS] = 1; + IRO_IsModifyOp[EDIVASS] = 1; + IRO_IsModifyOp[EMODASS] = 1; + IRO_IsModifyOp[EADDASS] = 1; + IRO_IsModifyOp[ESUBASS] = 1; + IRO_IsModifyOp[ESHLASS] = 1; + IRO_IsModifyOp[ESHRASS] = 1; + IRO_IsModifyOp[EANDASS] = 1; + IRO_IsModifyOp[EXORASS] = 1; + IRO_IsModifyOp[EORASS] = 1; + IRO_IsModifyOp[ECOMMA] = 0; + IRO_IsModifyOp[EPMODULO] = 1; + IRO_IsModifyOp[EROTL] = 1; + IRO_IsModifyOp[EROTR] = 1; + IRO_IsModifyOp[EBCLR] = 1; + IRO_IsModifyOp[EBTST] = 1; + IRO_IsModifyOp[EBSET] = 1; + IRO_IsModifyOp[ETYPCON] = 0; + IRO_IsModifyOp[EBITFIELD] = 0; + IRO_IsModifyOp[EINTCONST] = 0; + IRO_IsModifyOp[EFLOATCONST] = 0; + IRO_IsModifyOp[ESTRINGCONST] = 0; + IRO_IsModifyOp[ECOND] = 0; + IRO_IsModifyOp[EFUNCCALL] = 0; + IRO_IsModifyOp[EFUNCCALLP] = 0; + IRO_IsModifyOp[EOBJREF] = 0; + IRO_IsModifyOp[EMFPOINTER] = 0; + IRO_IsModifyOp[ENULLCHECK] = 0; + IRO_IsModifyOp[EPRECOMP] = 0; + IRO_IsModifyOp[ETEMP] = 0; + IRO_IsModifyOp[EARGOBJ] = 0; + IRO_IsModifyOp[ELOCOBJ] = 0; + IRO_IsModifyOp[ELABEL] = 0; + IRO_IsModifyOp[ESETCONST] = 0; + IRO_IsModifyOp[ENEWEXCEPTION] = 0; + IRO_IsModifyOp[ENEWEXCEPTIONARRAY] = 0; + IRO_IsModifyOp[EOBJLIST] = 0; + IRO_IsModifyOp[EMEMBER] = 0; + IRO_IsModifyOp[ETEMPLDEP] = 0; + IRO_IsModifyOp[EINSTRUCTION] = 0; + IRO_IsModifyOp[EDEFINE] = 0; + IRO_IsModifyOp[EREUSE] = 0; + IRO_IsModifyOp[EASSBLK] = 0; + IRO_IsModifyOp[EVECTOR128CONST] = 0; + IRO_IsModifyOp[ECONDASS] = 1; +} + +void IRO_InitializeIRO_IsAssignOpArray(void) { + int i; + + for (i = 0; i < MAXEXPR; i++) + IRO_IsAssignOp[i] = 0; + + IRO_IsAssignOp[EPOSTINC] = 1; + IRO_IsAssignOp[EPOSTDEC] = 1; + IRO_IsAssignOp[EPREINC] = 1; + IRO_IsAssignOp[EPREDEC] = 1; + IRO_IsAssignOp[EINDIRECT] = 0; + IRO_IsAssignOp[EMONMIN] = 0; + IRO_IsAssignOp[EBINNOT] = 0; + IRO_IsAssignOp[ELOGNOT] = 0; + IRO_IsAssignOp[EFORCELOAD] = 0; + IRO_IsAssignOp[EMUL] = 0; + IRO_IsAssignOp[EMULV] = 0; + IRO_IsAssignOp[EDIV] = 0; + IRO_IsAssignOp[EMODULO] = 0; + IRO_IsAssignOp[EADDV] = 0; + IRO_IsAssignOp[ESUBV] = 0; + IRO_IsAssignOp[EADD] = 0; + IRO_IsAssignOp[ESUB] = 0; + IRO_IsAssignOp[ESHL] = 0; + IRO_IsAssignOp[ESHR] = 0; + IRO_IsAssignOp[ELESS] = 0; + IRO_IsAssignOp[EGREATER] = 0; + IRO_IsAssignOp[ELESSEQU] = 0; + IRO_IsAssignOp[EGREATEREQU] = 0; + IRO_IsAssignOp[EEQU] = 0; + IRO_IsAssignOp[ENOTEQU] = 0; + IRO_IsAssignOp[EAND] = 0; + IRO_IsAssignOp[EXOR] = 0; + IRO_IsAssignOp[EOR] = 0; + IRO_IsAssignOp[ELAND] = 0; + IRO_IsAssignOp[ELOR] = 0; + IRO_IsAssignOp[EASS] = 1; + IRO_IsAssignOp[EMULASS] = 1; + IRO_IsAssignOp[EDIVASS] = 1; + IRO_IsAssignOp[EMODASS] = 1; + IRO_IsAssignOp[EADDASS] = 1; + IRO_IsAssignOp[ESUBASS] = 1; + IRO_IsAssignOp[ESHLASS] = 1; + IRO_IsAssignOp[ESHRASS] = 1; + IRO_IsAssignOp[EANDASS] = 1; + IRO_IsAssignOp[EXORASS] = 1; + IRO_IsAssignOp[EORASS] = 1; + IRO_IsAssignOp[ECOMMA] = 0; + IRO_IsAssignOp[EPMODULO] = 1; + IRO_IsAssignOp[EROTL] = 1; + IRO_IsAssignOp[EROTR] = 1; + IRO_IsAssignOp[EBCLR] = 1; + IRO_IsAssignOp[EBTST] = 1; + IRO_IsAssignOp[EBSET] = 1; + IRO_IsAssignOp[ETYPCON] = 0; + IRO_IsAssignOp[EBITFIELD] = 0; + IRO_IsAssignOp[EINTCONST] = 0; + IRO_IsAssignOp[EFLOATCONST] = 0; + IRO_IsAssignOp[ESTRINGCONST] = 0; + IRO_IsAssignOp[ECOND] = 0; + IRO_IsAssignOp[EFUNCCALL] = 0; + IRO_IsAssignOp[EFUNCCALLP] = 0; + IRO_IsAssignOp[EOBJREF] = 0; + IRO_IsAssignOp[EMFPOINTER] = 0; + IRO_IsAssignOp[ENULLCHECK] = 0; + IRO_IsAssignOp[EPRECOMP] = 0; + IRO_IsAssignOp[ETEMP] = 0; + IRO_IsAssignOp[EARGOBJ] = 0; + IRO_IsAssignOp[ELOCOBJ] = 0; + IRO_IsAssignOp[ELABEL] = 0; + IRO_IsAssignOp[ESETCONST] = 0; + IRO_IsAssignOp[ENEWEXCEPTION] = 0; + IRO_IsAssignOp[ENEWEXCEPTIONARRAY] = 0; + IRO_IsAssignOp[EOBJLIST] = 0; + IRO_IsAssignOp[EMEMBER] = 0; + IRO_IsAssignOp[ETEMPLDEP] = 0; + IRO_IsAssignOp[EINSTRUCTION] = 0; + IRO_IsAssignOp[EDEFINE] = 0; + IRO_IsAssignOp[EREUSE] = 0; + IRO_IsAssignOp[EASSBLK] = 0; + IRO_IsAssignOp[EVECTOR128CONST] = 0; + IRO_IsAssignOp[ECONDASS] = 1; +} + +VarRecord *IRO_FindVar(Object *object, Boolean flag1, Boolean flag2) { + VarRecord *var; + VarInfo *vi; + + var = object->varptr; + if (!var && flag1) { + vi = NULL; + if (object->datatype == DLOCAL) + vi = object->u.var.info; + if (vi) + vi->usage = 0; + var = oalloc(sizeof(VarRecord)); + var->object = object; + var->index = ++IRO_NumVars; + var->x6 = 0; + var->xA = 0; + var->next = NULL; + var->defs = NULL; + var->uses = NULL; + var->x1A = NULL; + var->x1E = NULL; + var->xB = 0; + if (IRO_FirstVar) + IRO_LastVar->next = var; + else + IRO_FirstVar = var; + IRO_LastVar = var; + object->varptr = var; + } + + if (var && !flag2) { + var->xB = 1; + if (object->datatype == DLOCAL && object->u.var.info && object->u.var.info->noregister == 0) + object->u.var.info->noregister = 2; + } + + return var; +} + +static void ResetVars(void) { + VarRecord *var; + + for (var = IRO_FirstVar; var; var = var->next) { + var->xB = 0; + if (var->object && var->object->datatype == DLOCAL && var->object->u.var.info) { + if (var->object->u.var.info->noregister == 2) + var->object->u.var.info->noregister = 0; + } + } +} + +static void IRO_HandleExceptionActions(IROLinear *linear) { + ExceptionAction *action; + + for (action = linear->stmt->dobjstack; action; action = action->prev) { + switch (action->type) { + case EAT_DESTROYLOCAL: + IRO_FindVar(action->data.destroy_local.local, 1, 0); + break; + case EAT_DESTROYLOCALCOND: + IRO_FindVar(action->data.destroy_local_cond.local, 1, 0); + break; + case EAT_DESTROYLOCALOFFSET: + IRO_FindVar(action->data.destroy_local_offset.local, 1, 0); + break; + case EAT_DESTROYLOCALARRAY: + IRO_FindVar(action->data.destroy_local_array.localarray, 1, 0); + break; + case EAT_DESTROYMEMBER: + case EAT_DESTROYBASE: + IRO_FindVar(action->data.destroy_member.objectptr, 1, 0); + break; + case EAT_DESTROYMEMBERCOND: + IRO_FindVar(action->data.destroy_member_cond.objectptr, 1, 0); + break; + case EAT_DESTROYMEMBERARRAY: + IRO_FindVar(action->data.destroy_member_array.objectptr, 1, 0); + break; + case EAT_CATCHBLOCK: + if (action->data.catch_block.catch_object) + IRO_FindVar(action->data.catch_block.catch_object, 1, 0); + IRO_FindVar(action->data.catch_block.catch_info_object, 1, 0); + break; + case EAT_ACTIVECATCHBLOCK: + IRO_FindVar(action->data.active_catch_block.catch_info_object, 1, 0); + break; + } + } +} + +void IRO_FindAllVars(void) { + IROLinear *linear; + VarRecord *var; + + linear = IRO_FirstLinear; + IRO_NumVars = 0; + IRO_FirstVar = IRO_LastVar = NULL; + + while (linear) { + if (IS_LINEAR_ENODE(linear, EOBJREF)) { + if (Inline_IsObjectData(linear->u.node->data.objref) || linear->u.node->data.objref->datatype == DLOCAL) + IRO_FindVar(linear->u.node->data.objref, 1, (linear->flags & IROLF_Ind) != 0); + else + linear->u.node->data.objref->varptr = NULL; + } else if (linear->type == IROLinearFunccall) { + if (linear->stmt && IRO_FunctionCallMightThrowException(linear)) + IRO_HandleExceptionActions(linear); + } else if (linear->type == IROLinearAsm) { + IAEffects effects; + int i; + CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); + for (i = 0; i < effects.numoperands; i++) + IRO_FindVar(effects.operands[i].object, 1, effects.operands[i].type != IAEffect_3); + } + linear = linear->next; + } + + var = IRO_FirstVar; + Bv_AllocVector(&IRO_FuncKills, IRO_NumVars + 1); + Bv_SetBit(0, IRO_FuncKills); + while (var) { + if (Inline_IsObjectData(var->object) || var->xB) + Bv_SetBit(var->index, IRO_FuncKills); + var = var->next; + } + + IRO_CheckForUserBreak(); +} + +void IRO_ZapVarPtrs(void) { + VarRecord *var; + + for (var = IRO_FirstVar; var; var = var->next) + var->object->varptr = NULL; +} + +void IRO_UpdateVars(void) { + IROLinear *linear; + VarRecord *var; + + ResetVars(); + + for (linear = IRO_FirstLinear; linear; linear = linear->next) { + if (IS_LINEAR_ENODE(linear, EOBJREF)) { + if (Inline_IsObjectData(linear->u.node->data.objref) || linear->u.node->data.objref->datatype == DLOCAL) + IRO_FindVar(linear->u.node->data.objref, 0, (linear->flags & IROLF_Ind) || !(linear->flags & IROLF_Reffed)); + } else if (linear->type == IROLinearFunccall) { + if (linear->stmt && IRO_FunctionCallMightThrowException(linear)) + IRO_HandleExceptionActions(linear); + } else if (linear->type == IROLinearAsm) { + IAEffects effects; + int i; + CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); + for (i = 0; i < effects.numoperands; i++) + IRO_FindVar(effects.operands[i].object, 0, effects.operands[i].type != IAEffect_3); + } + } + + var = IRO_FirstVar; + Bv_AllocVector(&IRO_FuncKills, IRO_NumVars + 1); + Bv_SetBit(0, IRO_FuncKills); + while (var) { + if (Inline_IsObjectData(var->object) || var->xB) + Bv_SetBit(var->index, IRO_FuncKills); + var = var->next; + } +} + +void IRO_AddElmToList(IROLinear *linear, IROElmList **list) { + IROElmList *l = oalloc(sizeof(IROElmList)); + l->element = linear; + l->next = NULL; + if (!*list) { + *list = l; + } else { + l->next = *list; + *list = l; + } +} + +void IRO_DecomposeAddressExpression(IROLinear *linear, IROAddrRecord *rec) { + if (IS_LINEAR_DIADIC(linear->u.diadic.left, EADD)) { + IRO_DecomposeAddressExpression(linear->u.diadic.left, rec); + } else if (IS_LINEAR_ENODE(linear->u.diadic.left, EINTCONST)) { + rec->numInts++; + IRO_AddElmToList(linear->u.diadic.left, &rec->ints); + } else if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF)) { + rec->numObjRefs++; + IRO_AddElmToList(linear->u.diadic.left, &rec->objRefs); + } else { + rec->numMisc++; + IRO_AddElmToList(linear->u.diadic.left, &rec->misc); + } + + if (IS_LINEAR_DIADIC(linear->u.diadic.right, EADD)) { + IRO_DecomposeAddressExpression(linear->u.diadic.right, rec); + } else if (IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) { + rec->numInts++; + IRO_AddElmToList(linear->u.diadic.right, &rec->ints); + } else if (IS_LINEAR_ENODE(linear->u.diadic.right, EOBJREF)) { + rec->numObjRefs++; + IRO_AddElmToList(linear->u.diadic.right, &rec->objRefs); + } else { + rec->numMisc++; + IRO_AddElmToList(linear->u.diadic.right, &rec->misc); + } +} + +void IRO_DecomposeAddressExpression_Cheap(IROLinear *linear) { + if (IS_LINEAR_DIADIC(linear->u.diadic.left, EADD)) { + IRO_DecomposeAddressExpression_Cheap(linear->u.diadic.left); + } else if (!IS_LINEAR_ENODE(linear->u.diadic.left, EINTCONST)) { + if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF)) { + IRO_BaseTerms++; + TheBaseTerm = linear->u.diadic.left; + } else { + IRO_VarTerms++; + } + } + + if (IS_LINEAR_DIADIC(linear->u.diadic.right, EADD)) { + IRO_DecomposeAddressExpression_Cheap(linear->u.diadic.right); + } else if (!IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) { + if (IS_LINEAR_ENODE(linear->u.diadic.right, EOBJREF)) { + IRO_BaseTerms++; + TheBaseTerm = linear->u.diadic.right; + } else { + IRO_VarTerms++; + } + } +} + +VarRecord *IRO_FindAssigned(IROLinear *linear) { + VarRecord *rec; + + IRO_IsBitField = 0; + if (linear->type == IROLinearOp2Arg) + linear = linear->u.diadic.left; + else if (linear->type == IROLinearOp1Arg) + linear = linear->u.monadic; + else + CError_FATAL(818); + + if (IS_LINEAR_MONADIC(linear, EINDIRECT)) + linear = linear->u.monadic; + + if (IS_LINEAR_MONADIC(linear, EBITFIELD)) { + IRO_IsBitField = 1; + linear = linear->u.monadic; + } + + if (IS_LINEAR_DIADIC(linear, EADD)) { + if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF) && IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) { + linear = linear->u.diadic.left; + } else { + IRO_BaseTerms = 0; + IRO_DecomposeAddressExpression_Cheap(linear); + if (IRO_BaseTerms == 1) + linear = TheBaseTerm; + } + } + + if (!IS_LINEAR_ENODE(linear, EOBJREF)) + return NULL; + + if ((rec = IRO_FindVar(linear->u.node->data.objref, 0, 1))) + return rec; + else + return NULL; +} + +static void GetKillsByIndirectAssignment(IROLinear *linear) { + IROListNode *resultList; + IROLinear *nd; + IROListNode *list; + IROListNode *scan; + IROLinear *inner; + Boolean result; + Boolean foundLinear; + + result = 0; + + if (linear->type == IROLinearOp2Arg) + linear = linear->u.diadic.left; + else + linear = linear->u.monadic; + + if ( + linear && + linear->type == IROLinearOp1Arg && + linear->nodetype == EINDIRECT && + (inner = linear->u.monadic) && + copts.opt_pointer_analysis && + inner->pointsToFunction && + FunctionName + ) + { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList); + if ((list = resultList)) { + for (scan = list; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + result = 1; + break; + } + + foundLinear = 0; + for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + foundLinear = 1; + break; + } + } + if (!foundLinear) { + result = 1; + break; + } + } + + if (!result) { + while (list) { + for (nd = list->list.head; nd != list->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + Object *obj; + VarRecord *var; + int index; + + obj = nd->u.node->data.objref; + CError_ASSERT(952, obj != NULL); + + var = IRO_FindVar(obj, 1, 1); + CError_ASSERT(954, var != NULL); + + index = var->index; + CError_ASSERT(956, index != 0); + + Bv_SetBit(index, IRO_VarKills); + } + } + + list = list->nextList; + } + } + + while (resultList) { + IROListNode *next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + result = 1; + } + } else { + result = 1; + } + + if (result) + Bv_Or(IRO_FuncKills, IRO_VarKills); +} + +static void GetKillsByFunctionCall(IROLinear *linear) { + IROListNode *resultList; + IROLinear *nd; + IROListNode *list; + IROListNode *scan; + IROLinear *inner; + Boolean result; + Boolean foundLinear; + Object *obj; + ObjectList *killList; + ObjectList *olist; + + result = 0; + + if ( + (inner = linear->u.funccall.linear8) && + copts.opt_pointer_analysis && + inner->pointsToFunction && + FunctionName + ) + { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList); + if (resultList) { + for (scan = resultList; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + result = 1; + break; + } + + foundLinear = 0; + for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + foundLinear = 1; + obj = nd->u.node->data.objref; + CError_ASSERT(1028, obj != NULL); + + killList = NULL; + PointerAnalysis_GetFunctionKills(obj, linear, &killList); + + for (olist = killList; olist; olist = olist->next) { + if (!olist->object) { + result = 1; + break; + } + } + + while (killList) { + ObjectList *next = killList->next; + IRO_free(killList); + killList = next; + } + + if (result) + break; + } + } + + if (!foundLinear) + result = 1; + if (result) + break; + } + + if (!result) { + for (scan = resultList; scan; scan = scan->nextList) { + for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + obj = nd->u.node->data.objref; + killList = NULL; + PointerAnalysis_GetFunctionKills(obj, linear, &killList); + + for (olist = killList; olist; olist = olist->next) { + VarRecord *var; + int index; + + var = IRO_FindVar(olist->object, 1, 1); + CError_ASSERT(1079, var != NULL); + + index = var->index; + CError_ASSERT(1081, index != 0); + + Bv_SetBit(index, IRO_VarKills); + } + + while (killList) { + ObjectList *next = killList->next; + IRO_free(killList); + killList = next; + } + } + } + } + } + + while (resultList) { + IROListNode *next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + result = 1; + } + } else { + result = 1; + } + + if (result) + Bv_Or(IRO_FuncKills, IRO_VarKills); +} + +void IRO_GetKills(IROLinear *linear) { + VarRecord *var; + + switch (linear->type) { + case IROLinearOp1Arg: + case IROLinearOp2Arg: + if (IRO_IsAssignOp[linear->nodetype]) { + IROLinear *assigned; + int index; + + var = IRO_FindAssigned(linear); + index = 0; + if (var) index = var->index; + Bv_SetBit(index, IRO_VarKills); + + if (!index) + GetKillsByIndirectAssignment(linear); + } + break; + case IROLinearFunccall: + GetKillsByFunctionCall(linear); + break; + case IROLinearAsm: { + IAEffects effects; + int i; + + CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); + for (i = 0; i < effects.numoperands; i++) { + switch (effects.operands[i].type) { + case IAEffect_1: + case IAEffect_2: + case IAEffect_4: + if ((var = IRO_FindVar(effects.operands[i].object, 0, 1))) + Bv_SetBit(var->index, IRO_VarKills); + break; + } + } + + if (effects.x1 || effects.x4) + Bv_Or(IRO_FuncKills, IRO_VarKills); + break; + } + } +} + +void IRO_CheckInit(void) { + IRONode *fnode; + IROLinear *nd; + VarRecord *var; + ObjectList *olist; + int flag; + int i; + BitVector *bv; + + IRO_MakeReachable(IRO_FirstNode); + fnode = IRO_FirstNode; + Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); + + while (fnode) { + Bv_AllocVector(&fnode->x16, IRO_NumVars + 1); + Bv_AllocVector(&fnode->x1E, IRO_NumVars + 1); + + for (nd = fnode->first; nd; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + if (nd->flags & IROLF_Ind) { + if (!(nd->flags & IROLF_Assigned) || (nd->flags & IROLF_Used)) { + if ((var = IRO_FindVar(nd->u.node->data.objref, 0, 1))) { + if (!Bv_IsBitSet(var->index, fnode->x1E)) + Bv_SetBit(var->index, fnode->x16); + } + } + } else { + if ((var = IRO_FindVar(nd->u.node->data.objref, 0, 0))) { + Bv_SetBit(var->index, fnode->x1E); + } + } + } else if (nd->type == IROLinearOp2Arg && nd->nodetype == EASS) { + if ((var = IRO_FindAssigned(nd))) + Bv_SetBit(var->index, fnode->x1E); + } else if (nd->type == IROLinearAsm) { + IAEffects effects; + + CodeGen_GetAsmEffects(nd->u.asm_stmt, &effects); + for (i = 0; i < effects.numoperands; i++) { + var = IRO_FindVar(effects.operands[i].object, 0, 1); + switch (effects.operands[i].type) { + case IAEffect_1: + case IAEffect_2: + case IAEffect_4: + Bv_SetBit(var->index, fnode->x1E); + break; + } + } + } + + if (nd == fnode->last) + break; + } + + fnode = fnode->nextnode; + } + + Bv_AllocVector(&bv, IRO_NumVars + 1); + + do { + flag = 0; + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + Bv_Copy(fnode->x1E, bv); + for (i = 0; i < fnode->numpred; i++) + Bv_Or(IRO_NodeTable[fnode->pred[i]]->x1E, bv); + if (!Bv_Compare(bv, fnode->x1E)) { + Bv_Copy(bv, fnode->x1E); + flag = 1; + } + } + } while (flag); + + Bv_Clear(IRO_VarKills); + + for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { + if (fnode->x36) { + Bv_Copy(fnode->x16, bv); + for (i = 0; i < fnode->numpred; i++) + Bv_Minus(IRO_NodeTable[fnode->pred[i]]->x1E, bv); + Bv_Or(bv, IRO_VarKills); + } + } + + for (olist = locals; olist; olist = olist->next) { + if ((var = IRO_FindVar(olist->object, 0, 1)) && Bv_IsBitSet(var->index, IRO_VarKills)) { + VarInfo *vi = olist->object->u.var.info; + if (!IsTempName(olist->object->name) && !is_volatile_object(olist->object)) { + if (!IS_TYPE_CLASS(olist->object->type) || !CClass_IsEmpty(TYPE_CLASS(olist->object->type))) { + CError_SetErrorToken(&vi->deftoken); + CError_Warning(CErrorStr185, olist->object->name->name); + } + } + } + } + + IRO_CheckForUserBreak(); +} + +static void RewriteIndDec(void) { + IROLinear *add; + IROLinear *indirect; + IROLinear *Int; + IROLinear *nd; + CInt64 value; + IROList list; + + for (nd = IRO_FirstLinear; nd; nd = nd->next) { + if ( + nd->type == IROLinearOp1Arg && + (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC) && + !(nd->flags & IROLF_Reffed) + ) { + indirect = nd->u.monadic; + if ( + indirect->type == IROLinearOp1Arg && + indirect->nodetype == EINDIRECT && + indirect->u.monadic->type == IROLinearOp1Arg && + indirect->u.monadic->nodetype == EBITFIELD + ) { + value = IRO_GetSelfAssignmentVal(nd); + IRO_InitList(&list); + + nd->type = IROLinearOp2Arg; + nd->nodetype = EASS; + nd->u.diadic.left = indirect; + IRO_DuplicateExpr(indirect, &list); + + Int = IRO_NewIntConst(value, indirect->rtype); + Int->flags |= IROLF_Used | IROLF_Reffed; + + add = IRO_NewLinear(IROLinearOp2Arg); + add->nodetype = EADD; + add->u.diadic.left = list.tail; + add->u.diadic.left->flags = 0; + add->u.diadic.left->flags |= IROLF_Used | IROLF_Reffed; + add->u.diadic.right = Int; + add->rtype = indirect->rtype; + add->flags = 0; + add->flags |= IROLF_Used | IROLF_Reffed; + + nd->u.diadic.right = add; + + IRO_AddToList(Int, &list); + IRO_AddToList(add, &list); + IRO_PasteAfter(list.head, list.tail, indirect); + } + } + } +} + +void IRO_RewriteBitFieldTemps(void) { + IROLinear *nd; + IROLinear *expr2; + Object *obj; + VarRecord *var; + IROList list; + + for (nd = IRO_FirstLinear; nd; nd = nd->next) { + if ((obj = IRO_IsVariable(nd)) && (nd->flags & IROLF_BitfieldIndirect)) { + var = IRO_FindVar(obj, 0, 1); + CError_ASSERT(1526, var != NULL); + + expr2 = var->x1E; + CError_ASSERT(1532, expr2 != NULL); + + IRO_InitList(&list); + IRO_DuplicateExpr(expr2, &list); + IRO_NopOut(nd->u.monadic); + nd->u.monadic = list.tail; + IRO_Paste(list.head, list.tail, nd); + } + } +} + +static Boolean FunctionCallMightUseOrKillAnyAddressedVar(IROLinear *funccall) { + IROLinear *funcnd; + IROLinear *nd; + IROListNode *scan; + IROListNode *resultList; + ObjectList *olist; + ObjectList *killList; + VarRecord *var; + Boolean result; + Boolean foundObjRef; + Object *obj; + + result = 0; + + funcnd = funccall->u.funccall.linear8; + if (funcnd && copts.opt_pointer_analysis && funcnd->pointsToFunction && FunctionName) { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, funcnd, &resultList); + + if (resultList) { + for (scan = resultList; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + result = 1; + break; + } + + foundObjRef = 0; + for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + foundObjRef = 1; + obj = nd->u.node->data.objref; + CError_ASSERT(1592, obj != NULL); + + killList = NULL; + PointerAnalysis_GetFunctionKills(obj, funccall, &killList); + for (olist = killList; olist; olist = olist->next) { + if (!olist->object) { + result = 1; + } else { + var = IRO_FindVar(olist->object, 1, 1); + CError_ASSERT(1604, var != NULL); + if (var->xB) + result = 1; + } + + if (result) + break; + } + + while (killList) { + ObjectList *next = killList->next; + IRO_free(killList); + killList = next; + } + + if (!result) { + killList = NULL; + PointerAnalysis_GetFunctionDependencies(obj, funccall, &killList); + for (olist = killList; olist; olist = olist->next) { + if (!olist->object) { + result = 1; + } else { + var = IRO_FindVar(olist->object, 1, 1); + CError_ASSERT(1632, var != NULL); + if (var->xB) + result = 1; + } + + if (result) + break; + } + + while (killList) { + ObjectList *next = killList->next; + IRO_free(killList); + killList = next; + } + } + + if (result) + break; + } + } + + if (!foundObjRef) + result = 1; + if (result) + break; + } + + while (resultList) { + IROListNode *next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + result = 1; + } + } else { + result = 1; + } + + return result; +} + +static Boolean IndirectMightUseOrKillAnyAddressedVar(IROLinear *indirect) { + Boolean result; + IROLinear *inner; + IROLinear *nd; + IROListNode *scan; + IROListNode *resultList; + Boolean foundObjRef; + Object *obj; + VarRecord *var; + + result = 0; + + if ( + indirect && + indirect->type == IROLinearOp1Arg && + indirect->nodetype == EINDIRECT && + (inner = indirect->u.monadic) && + copts.opt_pointer_analysis && + inner->pointsToFunction && + FunctionName + ) { + resultList = NULL; + PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList); + if (resultList) { + for (scan = resultList; scan; scan = scan->nextList) { + if (!scan->list.head || !scan->list.tail) { + result = 1; + break; + } + + foundObjRef = 0; + for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { + if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { + foundObjRef = 1; + obj = nd->u.node->data.objref; + CError_ASSERT(1723, obj != NULL); + var = IRO_FindVar(obj, 1, 1); + CError_ASSERT(1725, var != NULL); + + if (var->xB) + result = 1; + } + } + + if (!foundObjRef) + result = 1; + if (result) + break; + } + + while (resultList) { + IROListNode *next = resultList->nextList; + IRO_free(resultList); + resultList = next; + } + } else { + result = 1; + } + } else { + result = 1; + } + + return result; +} + +void IRO_ScalarizeClassDataMembers(void) { + IROLinear *nd; + VarRecord *var; + Boolean flag; + Object *obj; + IndirectRecord *irec; + IndirectRecordMatch *match; + IROLinear *tmp; + + nd = IRO_FirstLinear; + IRO_FirstIndirectRecord = NULL; + IRO_LastIndirectRecord = NULL; + RewriteIndDec(); + IRO_DumpAfterPhase("RewriteIndDec", 0); + flag = 0; + + while (nd) { + if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT) { + CheckAddress(nd, &flag); + } + if (nd->type == IROLinearAsm) { + IAEffects effects; + SInt32 i; + CodeGen_GetAsmEffects(nd->u.asm_stmt, &effects); + for (i = 0; i < effects.numoperands; i++) { + if ((var = IRO_FindVar(effects.operands[i].object, 0, 1))) + CheckAddressConsistency(nd, var, -1, &stvoid); + else + CError_FATAL(1823); + } + } + if (nd->type == IROLinearFunccall && !flag) + flag = FunctionCallMightUseOrKillAnyAddressedVar(nd); + + nd = nd->next; + } + + if (flag) + DisableAddressedEntries(); + + for (irec = IRO_FirstIndirectRecord; irec; irec = irec->next) { + if (!(irec->flags & 1)) { + IROList list1; + IROList list2; + + obj = create_temp_object(irec->type); + var = IRO_FindVar(obj, 1, 1); + for (match = irec->matches; match; match = match->otherMatches) { + IRO_InitList(&list1); + IRO_InitList(&list2); + IRO_DuplicateExpr(match->nd, &list1); + IRO_DuplicateExpr(match->nd, &list2); + if (match->nd->type == IROLinearOperand && match->nd->u.node->type == EOBJREF) { + tmp = IRO_LocateFather(match->nd); + if (irec->flags & 2) { + tmp->flags |= IROLF_BitfieldIndirect; + var->x1A = match->nd->rtype; + var->x1E = list2.tail; + } + match->nd->u.node = create_objectrefnode(obj); + irec->x26 = list2.tail; + } else { + tmp = IRO_LocateFather(match->nd); + if (irec->flags & 2) { + tmp->flags |= IROLF_BitfieldIndirect; + var->x1A = match->nd->rtype; + var->x1E = list2.tail; + } + irec->x26 = list2.tail; + + IRO_NopOut(tmp->u.monadic); + tmp->u.monadic = IRO_NewLinear(IROLinearOperand); + tmp->u.monadic->u.node = create_objectrefnode(obj); + tmp->u.monadic->rtype = match->nd->rtype; + tmp->u.monadic->index = ++IRO_NumLinear; + tmp->u.monadic->flags |= IROLF_Ind | IROLF_Reffed; + IRO_NopOut(match->nd); + IRO_PasteAfter(tmp->u.monadic, tmp->u.monadic, match->nd); + } + } + + if (ObjectIsArg(irec->var->object)) { + IROLinear *op1; + IROLinear *op2; + IROLinear *op3; + IROLinear *op4; + IROLinear *op5; + + op1 = IRO_NewLinear(IROLinearOperand); + op1->u.node = create_objectrefnode(obj); + op1->rtype = op1->u.node->data.objref->type; + op1->index = ++IRO_NumLinear; + op1->flags |= IROLF_Ind | IROLF_Assigned; + + op2 = list1.tail; + + op3 = IRO_NewLinear(IROLinearOp1Arg); + op3->nodetype = EINDIRECT; + op3->rtype = irec->type; + op3->u.monadic = op1; + op3->index = ++IRO_NumLinear; + op3->flags |= IROLF_Assigned; + + op4 = IRO_NewLinear(IROLinearOp1Arg); + op4->nodetype = EINDIRECT; + op4->rtype = irec->type; + op4->u.monadic = op2; + op4->index = ++IRO_NumLinear; + op4->flags |= IROLF_Reffed; + + op5 = IRO_NewLinear(IROLinearOp2Arg); + op5->nodetype = EASS; + op5->u.diadic.left = op3; + op5->u.diadic.right = op4; + op5->rtype = irec->type; + op5->index = ++IRO_NumLinear; + + op2->next = op4; + op4->next = op1; + op1->next = op3; + op3->next = op5; + + IRO_PasteAfter(list1.head, op5, IRO_FirstLinear); + } + } + } + + IRO_CheckForUserBreak(); +} + +static Boolean CheckAddress(IROLinear *nd, Boolean *resultFlag) { + IROLinear *inner; + VarRecord *var; + Boolean result; + + inner = nd->u.monadic; + if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD) + inner = inner->u.monadic; + + result = 0; + + if (inner->type == IROLinearOperand && inner->u.node->type == EOBJREF) { + if (IS_TYPE_CLASS(inner->u.node->data.objref->type) || IS_TYPE_STRUCT(inner->u.node->data.objref->type) || + IS_TYPE_ARRAY(inner->u.node->data.objref->type)) { + if (inner->u.node->data.objref->datatype == DLOCAL) { + var = IRO_FindVar(inner->u.node->data.objref, 0, 1); + CError_ASSERT(2240, var != NULL); + CheckAddressConsistency(nd, var, 0, nd->rtype); + result = 1; + } + } + } else if ( + inner->type == IROLinearOp2Arg && + inner->nodetype == EADD && + inner->u.diadic.left->type == IROLinearOperand && + inner->u.diadic.left->u.node->type == EOBJREF) { + if ( + inner->u.diadic.right->type == IROLinearOperand && + inner->u.diadic.right->u.node->type == EINTCONST && + inner->u.diadic.right->u.node->data.intval.hi == 0) { + if ( + IS_TYPE_CLASS(inner->u.diadic.left->u.node->data.objref->type) || + IS_TYPE_STRUCT(inner->u.diadic.left->u.node->data.objref->type) || + IS_TYPE_ARRAY(inner->u.diadic.left->u.node->data.objref->type) + ) { + if (inner->u.diadic.left->u.node->data.objref->datatype == DLOCAL) { + var = IRO_FindVar(inner->u.diadic.left->u.node->data.objref, 0, 1); + CError_ASSERT(2267, var != NULL); + CheckAddressConsistency(nd, var, inner->u.diadic.right->u.node->data.intval.lo, nd->rtype); + result = 1; + } + } + } else { + if ( + IS_TYPE_CLASS(inner->u.diadic.left->u.node->data.objref->type) || + IS_TYPE_STRUCT(inner->u.diadic.left->u.node->data.objref->type) || + IS_TYPE_ARRAY(inner->u.diadic.left->u.node->data.objref->type) + ) { + if (inner->u.diadic.left->u.node->data.objref->datatype == DLOCAL) { + var = IRO_FindVar(inner->u.diadic.left->u.node->data.objref, 0, 1); + CheckAddressConsistency(nd, var, -1, nd->rtype); + result = 1; + } + } + } + } + + if (!result && !*resultFlag) { + *resultFlag = IndirectMightUseOrKillAnyAddressedVar(nd); + } + + return 0; +} + +static Boolean CheckAddressConsistency(IROLinear *nd, VarRecord *var, SInt32 addend, Type *type) { + IndirectRecord *rp; + IndirectRecordMatch *match; + UInt32 flag; + IROLinear *inner; + UInt32 start_bit; + UInt32 end_bit; + + flag = 0; + inner = nd->u.monadic; + if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD) { + start_bit = TYPE_BITFIELD(inner->rtype)->offset + 8 * addend; + end_bit = start_bit + TYPE_BITFIELD(inner->rtype)->bitlength - 1; + } else { + start_bit = 8 * addend; + end_bit = start_bit + 8 * type->size - 1; + } + + if (var->xB && !copts.opt_pointer_analysis) + return 0; + + if (nd->rtype && CParser_IsVolatile(nd->rtype, nd->nodeflags & ENODE_FLAG_QUALS)) + addend = -1; + if (is_volatile_object(var->object)) + addend = -1; + + for (rp = IRO_FirstIndirectRecord; rp; rp = rp->next) { + if (rp->var->index == var->index) { + if (rp->flags & 1) + return 0; + + if (addend == -1) { + flag = 1; + break; + } + + if (IRO_TypesEqual(rp->type, type) && rp->startbit == start_bit && rp->endbit == end_bit) { + match = oalloc(sizeof(IndirectRecordMatch)); + match->nd = inner; + match->otherMatches = NULL; + if (!rp->matches) { + rp->matches = match; + } else { + match->otherMatches = rp->matches; + rp->matches = match; + } + + IRO_Dump("Exact Match of Type and bits at %d and %d\n", rp->linear->index, nd->index); + IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit); + return 1; + } + + if (rp->startbit == start_bit && rp->endbit == end_bit && !IRO_TypesEqual(rp->type, type)) { + IRO_Dump("match on bits but mismatch on type %d and %d\n", rp->linear->index, nd->index); + IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit); + flag = 1; + break; + } + + if (rp->startbit >= start_bit && end_bit >= rp->startbit) { + IRO_Dump("Overlap detected --1 %d and %d\n", rp->linear->index, nd->index); + IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit); + flag = 1; + break; + } + + if (rp->startbit < start_bit && rp->endbit >= start_bit) { + IRO_Dump("Overlap detected --2 %d and %d\n", rp->linear->index, nd->index); + IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit); + flag = 1; + break; + } + } + } + + if (flag) { + DisableEntries(rp); + if (addend >= 0) + return 0; + } + + IRO_Dump("Create Entry at %d\n", nd->index); + IRO_Dump("start_bit=%d,end_bit=%d\n", start_bit, end_bit); + + rp = oalloc(sizeof(IndirectRecord)); + rp->linear = nd; + rp->flags = 0; + rp->var = var; + rp->addend = addend; + rp->size = type->size; + rp->type = type; + rp->next = NULL; + rp->matches = oalloc(sizeof(IndirectRecordMatch)); + rp->matches->nd = inner; + rp->matches->otherMatches = NULL; + rp->startbit = start_bit; + rp->endbit = end_bit; + + if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT && + nd->u.monadic->type == IROLinearOp1Arg && nd->u.monadic->nodetype == EBITFIELD) + rp->flags |= 2; + + if (!(IS_TYPE_FLOAT(type) || IS_TYPE_INT(type) || IS_TYPE_POINTER_ONLY(type)) || + addend == -1 || ((inner->flags & IROLF_4000) && ObjectIsArg(var->object))) + rp->flags |= 1; + + if (IRO_FirstIndirectRecord) + IRO_LastIndirectRecord->next = rp; + else + IRO_FirstIndirectRecord = rp; + IRO_LastIndirectRecord = rp; + return 1; +} + +static void DisableEntries(IndirectRecord *irec) { + IndirectRecord *scan; + + for (scan = IRO_FirstIndirectRecord; scan; scan = scan->next) { + if (irec->var->index == scan->var->index) + scan->flags |= 1; + } +} + +static void DisableAddressedEntries(void) { + IndirectRecord *scan; + + for (scan = IRO_FirstIndirectRecord; scan; scan = scan->next) { + if (scan->var->xB) + scan->flags |= 1; + } +} + +static UInt32 ObjectIsArg(Object *obj) { + ObjectList *scan; + + for (scan = arguments; scan; scan = scan->next) { + if (scan->object == obj) + return 1; + } + + return 0; +} + diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroVars.h b/compiler_and_linker/FrontEnd/Optimizer/IroVars.h new file mode 100644 index 0000000..2af5b4d --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroVars.h @@ -0,0 +1,51 @@ +#ifndef COMPILER_IROVARS_H +#define COMPILER_IROVARS_H + +#include "IrOptimizer.h" +#include "compiler/enode.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +struct VarRecord { + UInt16 index; + Object *object; + int x6; + Boolean xA; + Boolean xB; + Boolean xC; + VarRecord *next; + IRODef *defs; + IROUse *uses; + Type *x1A; // bitfield-related + IROLinear *x1E; +}; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +extern VarRecord *IRO_FirstVar; +extern VarRecord *IRO_LastVar; +extern SInt32 IRO_NumVars; +extern Boolean IRO_IsBitField; +extern SInt32 IRO_BaseTerms; +extern SInt32 IRO_VarTerms; +extern Boolean IRO_IsModifyOp[MAXEXPR]; +extern Boolean IRO_IsAssignOp[MAXEXPR]; + +extern void IRO_InitializeIRO_IsModifyOpArray(void); +extern void IRO_InitializeIRO_IsAssignOpArray(void); +extern VarRecord *IRO_FindVar(Object *object, Boolean flag1, Boolean flag2); +extern void IRO_FindAllVars(void); +extern void IRO_ZapVarPtrs(void); +extern void IRO_UpdateVars(void); +extern void IRO_AddElmToList(IROLinear *linear, IROElmList **list); +extern void IRO_DecomposeAddressExpression(IROLinear *linear, IROAddrRecord *rec); +extern void IRO_DecomposeAddressExpression_Cheap(IROLinear *linear); +extern VarRecord *IRO_FindAssigned(IROLinear *linear); +extern void IRO_GetKills(IROLinear *linear); +extern void IRO_CheckInit(void); +extern void IRO_RewriteBitFieldTemps(void); +extern void IRO_ScalarizeClassDataMembers(void); + +#endif diff --git a/compiler_and_linker/unsorted/Alias.c b/compiler_and_linker/unsorted/Alias.c deleted file mode 100644 index 8223bf4..0000000 --- a/compiler_and_linker/unsorted/Alias.c +++ /dev/null @@ -1,747 +0,0 @@ -#include "compiler/Alias.h" -#include "compiler/CClass.h" -#include "compiler/CError.h" -#include "compiler/CParser.h" -#include "compiler/CMachine.h" -#include "compiler/CodeGen.h" -#include "compiler/CopyPropagation.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" -#include "compiler/RegisterInfo.h" -#include "compiler/UseDefChains.h" -#include "compiler/ValueNumbering.h" -#include "compiler/BitVectors.h" -#include "compiler/CompilerTools.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -static Alias *aliases; -static int n_aliases; -static int n_gathered_aliases; -static Alias *alias_hash[997]; -Alias *worst_case; -Object worst_case_obj; - -static TypePointer worst_case_memory_type = { - TYPEARRAY, - 0xFFFFFF, - TYPE(&stchar) -}; - -static Boolean is_safe_const(Object *obj) { - Type *type; - - type = obj->type; - while (IS_TYPE_ARRAY(type)) - type = TPTR_TARGET(type); - - if (TYPE_FITS_IN_REGISTER(type) || IS_TYPE_VECTOR(type) || IS_TYPE_FLOAT(type) || IS_TYPE_STRUCT(type)) - return is_const_object(obj); - - if (IS_TYPE_CLASS(type)) - return is_const_object(obj) && CClass_IsPODClass(TYPE_CLASS(type)); - - return 0; -} - -void initialize_aliases(void) { - int i; - - memclrw(&worst_case_obj, sizeof(Object)); - worst_case_obj.otype = OT_OBJECT; - worst_case_obj.type = TYPE(&worst_case_memory_type); - worst_case_obj.datatype = DDATA; - worst_case_obj.name = GetHashNameNodeExport("@worst_case@"); - - aliases = NULL; - n_aliases = 0; - n_gathered_aliases = 0; - for (i = 0; i < 997; i++) - alias_hash[i] = NULL; - - worst_case = make_alias_set(); - add_alias_member(worst_case, make_alias(&worst_case_obj, 0, 0)); -} - -static UInt32 hash_alias(Object *object, SInt32 offset, SInt32 size) { - return (UInt32) (object->name->hashval * offset * size) % 997; -} - -static Alias *create_alias(AliasType type, Object *object, SInt32 offset, SInt32 size, Boolean addToHash) { - Alias *alias; - UInt32 hash; - - alias = lalloc(sizeof(Alias)); - memclrw(alias, sizeof(Alias)); - alias->type = type; - alias->index = n_aliases++; - alias->next = aliases; - aliases = alias; - alias->object = object; - alias->offset = offset; - alias->size = size; - - if (addToHash) { - hash = hash_alias(object, offset, size); - alias->hashNext = alias_hash[hash]; - alias_hash[hash] = alias; - } - - return alias; -} - -static Alias *lookup_alias(Object *object, SInt32 offset, SInt32 size) { - Alias *scan; - - for (scan = alias_hash[hash_alias(object, offset, size)]; scan; scan = scan->hashNext) { - if (scan->object == object && scan->offset == offset && scan->size == size) - return scan; - } - - return NULL; -} - -Alias *make_alias(Object *object, SInt32 offset, SInt32 size) { - Alias *alias; - Alias *alias2; - - if (!offset && !size) - size = object->type->size; - - alias = lookup_alias(object, offset, size); - if (!alias) { - if (offset > 0 || size != object->type->size) { - alias2 = make_alias(object, 0, object->type->size); - alias = create_alias(AliasType1, object, offset, size, 1); - add_alias_member(alias2, alias); - } else { - alias = create_alias(AliasType0, object, offset, size, 1); - } - - switch (object->datatype) { - case DLOCAL: - case DNONLAZYPTR: - break; - default: - if (!is_safe_const(object)) - add_alias_member(worst_case, make_alias(object, 0, 0)); - } - } - - if (offset > object->type->size) - return NULL; - else - return alias; -} - -Alias *make_alias_set(void) { - return create_alias(AliasType2, NULL, 0, 0, 0); -} - -void add_alias_member(Alias *parent, Alias *child) { - AliasMember *member; - - if (child->type == AliasType2) { - for (member = child->parents; member; member = member->nextParent) - add_alias_member(parent, member->child); - } else { - if (parent == worst_case && child->type == AliasType1) - child = make_alias(child->object, 0, 0); - - for (member = parent->parents; member; member = member->nextParent) { - if (member->child == child) - return; - } - - member = lalloc(sizeof(AliasMember)); - member->parent = parent; - member->child = child; - member->nextParent = parent->parents; - parent->parents = member; - member->nextChild = child->children; - child->children = member; - } -} - -Alias *make_alias_set_from_IR(void) { - CError_FATAL(333); - return NULL; -} - -static Boolean aliases_overlap(Alias *a, Alias *b) { - return ( - a->offset == b->offset || - (a->offset > b->offset && a->offset < (b->offset + b->size)) || - (b->offset > a->offset && b->offset < (a->offset + a->size)) - ); -} - -static int is_address_load(PCode *pcode) { - Object *obj; - - switch (pcode->op) { - case PC_LWZ: - if (pcode->args[2].kind == PCOp_MEMORY && pcode->args[2].data.mem.obj->datatype == DNONLAZYPTR) - return 1; - break; - case PC_LBZU: - case PC_LBZUX: - case PC_LHZU: - case PC_LHZUX: - case PC_LHAU: - case PC_LHAUX: - case PC_LWZU: - case PC_LWZUX: - case PC_STBU: - case PC_STBUX: - case PC_STHU: - case PC_STHUX: - case PC_STWU: - case PC_STWUX: - return 1; - case PC_ADDI: - case PC_ADDIS: - if (pcode->args[0].data.reg.reg < n_real_registers[RegClass_GPR]) { - if (pcode->args[2].kind == PCOp_MEMORY) { - obj = pcode->args[2].data.mem.obj; - if (obj->datatype == DLOCAL && !is_safe_const(obj)) - add_alias_member(worst_case, make_alias(obj, 0, 0)); - return 0; - } - } else { - return 1; - } - break; - case PC_ADD: - return 1; - } - - return 0; -} - -static int addresspropagatestouse(int candidateID, int useID) { - PCode *candidate_pcode; // r30 - PCode *use_pcode; // r29 - int reg; // r28 - short reg2; - Object *object; // r27 - SInt32 offset; // r26 - Alias *alias; // r25 - Boolean flag24; // r24 - SInt32 size; // r23 - Alias *aliasSet; // r22 - int i; - PCode *scan; - PCodeArg *op; - - candidate_pcode = Candidates[candidateID].pcode; - use_pcode = Uses[useID].pcode; - flag24 = 0; - size = 1; - reg = candidate_pcode->args[0].data.reg.reg; - - if (candidate_pcode->alias && (candidate_pcode->alias->type == AliasType0 || candidate_pcode->alias->type == AliasType1)) { - object = candidate_pcode->alias->object; - offset = candidate_pcode->alias->offset; - if (offset == 0 && candidate_pcode->alias->size == object->type->size) - flag24 = 1; - } else if (candidate_pcode->args[2].kind == PCOp_MEMORY) { - object = candidate_pcode->args[2].data.mem.obj; - if (candidate_pcode->op == PC_ADDIS) - offset = candidate_pcode->args[2].data.mem.offset << 16; - else - offset = candidate_pcode->args[2].data.mem.offset; - } else { - return 0; - } - - CError_ASSERT(478, object->otype == OT_OBJECT); - - if ((candidate_pcode->flags & (fIsRead | fIsWrite)) && (candidate_pcode->flags & fUpdatesPtr)) { - reg = candidate_pcode->args[1].data.reg.reg; - offset = 0; - flag24 = 1; - } else if (candidate_pcode->op == PC_LWZ) { - if (object->datatype != DNONLAZYPTR) - return 0; - - object = object->u.var.realObj; - CError_ASSERT(495, object->otype == OT_OBJECT); - offset = 0; - } else if (candidate_pcode->op == PC_ADDI) { - if (!candidate_pcode->alias && object) - candidate_pcode->alias = make_alias(object, offset, 1); - } else if (candidate_pcode->op == PC_ADDIS) { - if (!candidate_pcode->alias && object) - candidate_pcode->alias = make_alias(object, offset, 1); - } else if (candidate_pcode->op == PC_ADD) { - offset = 0; - flag24 = 1; - } else { - CError_FATAL(509); - } - - if ( - !(use_pcode->flags & (fIsRead | fIsWrite)) && - use_pcode->op != PC_ADDI && - use_pcode->op != PC_ADD && - use_pcode->op != PC_ADDIS - ) { - if (object->datatype == DLOCAL && !is_safe_const(object)) - add_alias_member(worst_case, make_alias(object, 0, 0)); - return 1; - } - - if ( - (use_pcode->flags & (fIsWrite | fPCodeFlag40000)) && - use_pcode->args[0].kind == PCOp_REGISTER && - use_pcode->args[0].arg == RegClass_GPR && - use_pcode->args[0].data.reg.reg == reg && - object->datatype == DLOCAL && - !is_safe_const(object) - ) - add_alias_member(worst_case, make_alias(object, 0, 0)); - - if (use_pcode->argCount < 3) - return 1; - - CError_ASSERT(543, use_pcode->args[1].kind == PCOp_REGISTER); - - if (candidate_pcode->block == use_pcode->block && precedes(candidate_pcode, use_pcode)) { - for (scan = candidate_pcode->nextPCode; scan && scan != use_pcode; scan = scan->nextPCode) { - for (op = scan->args, i = scan->argCount; i--; op++) { - if (op->kind == PCOp_REGISTER && - op->arg == RegClass_GPR && - (op->data.reg.effect & EffectWrite) && - op->data.reg.reg == reg) - return 1; - } - } - } else { - if (!bitvectorgetbit(candidateID, propinfo[use_pcode->block->blockIndex].vec8)) { - if (bitvectorgetbit(candidate_pcode->defID, usedefinfo[use_pcode->block->blockIndex].defvec8)) { - for (scan = use_pcode->block->firstPCode; scan && scan != use_pcode; scan = scan->nextPCode) { - for (op = scan->args, i = scan->argCount; i--; op++) { - if (op->kind == PCOp_REGISTER && - op->arg == RegClass_GPR && - (op->data.reg.effect & EffectWrite) && - op->data.reg.reg == reg) - return 1; - } - } - } else { - return 1; - } - } - - for (scan = use_pcode->block->firstPCode; scan; scan = scan->nextPCode) { - if (scan == use_pcode) - break; - for (op = scan->args, i = scan->argCount; i--; op++) { - if (op->kind == PCOp_REGISTER && - op->arg == RegClass_GPR && - (op->data.reg.effect & EffectWrite) && - op->data.reg.reg == reg) - return 1; - } - } - } - - CError_ASSERT(598, object != NULL); - - if (use_pcode->op == PC_ADDI || use_pcode->op == PC_ADD || use_pcode->op == PC_ADDIS) { - if (use_pcode->args[0].data.reg.reg < n_real_registers[RegClass_GPR] && !is_safe_const(object)) - add_alias_member(worst_case, make_alias(object, 0, 0)); - } - - if (use_pcode->flags & (fIsRead | fIsWrite)) - size = nbytes_loaded_or_stored_by(use_pcode); - - if (use_pcode->args[2].kind == PCOp_REGISTER) { - if (use_pcode->args[1].data.reg.reg == 0) { - if (use_pcode->args[2].data.reg.reg == reg) - alias = make_alias(object, offset, size); - } else { - if (use_pcode->args[1].data.reg.reg == reg) - reg2 = use_pcode->args[2].data.reg.reg; - else if (use_pcode->args[2].data.reg.reg == reg) - reg2 = use_pcode->args[1].data.reg.reg; - else - return 1; - - for (scan = use_pcode->prevPCode; scan; scan = scan->prevPCode) { - if (scan->op == PC_LI && scan->args[0].data.reg.reg == reg2) - break; - - for (i = 0; i < scan->argCount; i++) { - if (scan->args[i].kind == PCOp_REGISTER && - scan->args[i].arg == RegClass_GPR && - scan->args[i].data.reg.reg == reg2 && - (scan->args[i].data.reg.effect & EffectWrite)) { - scan = NULL; - break; - } - } - - if (!scan) - break; - } - - if (scan) { - offset += scan->args[1].data.mem.offset; - alias = make_alias(object, offset, size); - } else { - alias = make_alias(object, 0, 0); - } - } - } else { - if (use_pcode->args[1].kind != PCOp_REGISTER || - use_pcode->args[1].arg != RegClass_GPR || - use_pcode->args[1].data.reg.reg != reg) - return 1; - - if (use_pcode->args[1].data.reg.effect & EffectWrite) { - alias = make_alias(object, 0, 0); - } else if (use_pcode->args[2].kind == PCOp_IMMEDIATE) { - if (use_pcode->op == PC_ADDIS) { - offset += use_pcode->args[2].data.imm.value << 16; - alias = make_alias(object, offset, 1); - } else { - offset += use_pcode->args[2].data.imm.value; - alias = make_alias(object, offset, size); - } - } else { - return 1; - } - } - - if (flag24) - alias = make_alias(object, 0, 0); - - if (!alias) - return 1; - - if (!use_pcode->alias) { - if ( - use_pcode->op == PC_ADDI || - use_pcode->op == PC_ADD || - use_pcode->op == PC_ADDIS || - ((candidate_pcode->flags & (fIsRead | fIsWrite)) && (candidate_pcode->flags & fUpdatesPtr)) - ) - recursive_propagation = 1; - } - - if (use_pcode->alias) { - if (use_pcode->alias == worst_case) { - add_alias_member(worst_case, make_alias(object, 0, 0)); - } else if (use_pcode->alias == alias) { - return 1; - } else if (use_pcode->alias->type == AliasType0 || use_pcode->alias->type == AliasType1) { - if (object == use_pcode->alias->object) { - use_pcode->alias = make_alias(object, 0, 0); - } else { - aliasSet = make_alias_set(); - if ( - use_pcode->op == PC_ADDI || - use_pcode->op == PC_ADD || - use_pcode->op == PC_ADDIS || - ((use_pcode->flags & (fIsRead | fIsWrite)) && (use_pcode->flags & fUpdatesPtr)) - ) { - if (alias->type == AliasType2) - add_alias_member(worst_case, alias); - else - add_alias_member(worst_case, make_alias(use_pcode->alias->object, 0, 0)); - } - add_alias_member(aliasSet, use_pcode->alias); - add_alias_member(aliasSet, alias); - use_pcode->alias = aliasSet; - } - } else { - add_alias_member(use_pcode->alias, alias); - } - } else { - use_pcode->alias = alias; - } - - propagated_instructions = 1; - return 1; -} - -static void finishpropagatealiases(int id) { - propagated_instructions = 1; -} - -static Propagation alias_prop = { - &is_address_load, - &addresspropagatestouse, - &finishpropagatealiases, - "ALIAS", - "ALIASES", - "A%" PRId32, - 1 -}; - -static void propagatealiasinfo(Object *proc) { - propagateinstructions(proc, &alias_prop, (copts.optimizationlevel >= 4) ? 4 : 1, 1); -} - -void gather_alias_info(void) { - UInt32 *myvec; // r31 - Alias *alias; // r22 - AliasMember *member; - AliasMember *member2; - PCodeBlock *block; // r21 - PCode *pcode; // r20 - PCodeArg *op; // r19 - RegUseOrDef *list; // r18 - int i; // r17 - Alias *alias_choice; // r16 - int aliases_idx; // r15 (helper in r23) - PCode *defpcode; // r14 - Alias *alias_array[3]; - UseOrDef *def; - int defID; - - if (coloring) { - propagatealiasinfo(gFunction); - myvec = oalloc(4 * ((number_of_Defs + 31) >> 5)); - - for (block = pcbasicblocks; block; block = block->nextBlock) { - bitvectorcopy(myvec, usedefinfo[block->blockIndex].defvec8, number_of_Defs); - - for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { - if (pcode->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) { - if (!pcode->alias) { - pcode->alias = worst_case; - } else { - if ((pcode->alias->type == AliasType0 || pcode->alias->type == AliasType1) && - pcode->alias->size == nbytes_loaded_or_stored_by(pcode)) { - pcode->flags &= ~fIsPtrOp; - } else { - pcode->flags |= fIsPtrOp; - } - - if (pcode->alias != worst_case) { - aliases_idx = 0; - alias_choice = NULL; - op = pcode->args; - for (i = 0; i < pcode->argCount; i++, op++) { - if ( - (!(pcode->flags & (fIsWrite | fPCodeFlag40000)) || op != pcode->args) && - op->kind == PCOp_REGISTER && - op->arg == RegClass_GPR && - (op->data.reg.effect & EffectRead) - ) { - alias_array[aliases_idx] = NULL; - if (aliases_idx >= 2) { - alias_choice = worst_case; - break; - } - alias_array[aliases_idx] = pcode->alias; - - for (list = reg_Defs[RegClass_GPR][op->data.reg.reg]; list; list = list->next) { - if (bitvectorgetbit(list->id, myvec)) { - defpcode = Defs[list->id].pcode; - if (!defpcode->alias || !is_address_load(defpcode) || defpcode->alias == worst_case) { - alias_array[aliases_idx] = worst_case; - break; - } - } - } - - aliases_idx++; - } - } - - if (!alias_choice) { - if (aliases_idx > 0) { - alias_choice = alias_array[0]; - if (aliases_idx == 2) { - if (alias_array[0] != worst_case) { - if (alias_array[1] != worst_case) - alias_choice = worst_case; - } else if (alias_array[1] != worst_case) { - alias_choice = alias_array[1]; - } - } - } - - if (alias_choice == worst_case) { - pcode->flags |= fIsPtrOp; - if (pcode->alias->type == AliasType2) - add_alias_member(worst_case, pcode->alias); - else - add_alias_member(worst_case, make_alias(pcode->alias->object, 0, 0)); - } - - if (alias_choice) - pcode->alias = alias_choice; - } - } - } - } else { - if ((pcode->flags & fIsCall) && !pcode->alias) - pcode->alias = worst_case; - } - - for (def = &Defs[defID = pcode->defID]; defID < number_of_Defs && def->pcode == pcode; defID++, def++) { - if (def->v.kind == PCOp_REGISTER && def->v.arg == RegClass_GPR) { - for (list = reg_Defs[RegClass_GPR][def->v.u.reg]; list; list = list->next) - bitvectorclearbit(list->id, myvec); - } - bitvectorsetbit(defID, myvec); - } - } - } - - freeoheap(); - } else { - for (block = pcbasicblocks; block; block = block->nextBlock) { - for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { - if ((pcode->flags & (fIsRead | fIsWrite | fIsCall | fPCodeFlag20000 | fPCodeFlag40000)) && !pcode->alias) - pcode->alias = worst_case; - } - } - } - - if (n_gathered_aliases != n_aliases) { - for (alias = aliases; alias; alias = alias->next) { - if (alias->type == AliasType2) { - alias->vec24 = lalloc(4 * ((n_aliases + 31) >> 5)); - bitvectorinitialize(alias->vec24, n_aliases, 0); - for (member = alias->parents; member; member = member->nextParent) { - bitvectorsetbit(member->child->index, alias->vec24); - for (member2 = member->child->parents; member2; member2 = member2->nextParent) - bitvectorsetbit(member2->child->index, alias->vec24); - } - } - } - n_gathered_aliases = n_aliases; - } -} - -static Boolean may_alias_alias(Alias *a, Alias *b) { - switch ((a->type * 3) + b->type) { - case (AliasType0 * 3) + AliasType0: - return a == b; - case (AliasType0 * 3) + AliasType1: - case (AliasType1 * 3) + AliasType0: - return a->object == b->object; - case (AliasType1 * 3) + AliasType1: - return (a->object == b->object) && aliases_overlap(a, b); - case (AliasType0 * 3) + AliasType2: - case (AliasType1 * 3) + AliasType2: - return bitvectorgetbit(a->index, b->vec24) != 0; - case (AliasType2 * 3) + AliasType0: - case (AliasType2 * 3) + AliasType1: - return bitvectorgetbit(b->index, a->vec24) != 0; - case (AliasType2 * 3) + AliasType2: - return (a == b) || !bitvectorintersectionisempty(a->vec24, b->vec24, n_aliases); - default: - CError_FATAL(1054); - return 1; - } -} - -Boolean may_alias(PCode *a, PCode *b) { - return may_alias_alias(a->alias, b->alias); -} - -Boolean uniquely_aliases(PCode *a, PCode *b) { - if (may_alias_alias(a->alias, b->alias)) { - if ( - a->alias->type != AliasType2 && - b->alias->type != AliasType2 && - a->alias && - b->alias && - a->alias->size == nbytes_loaded_or_stored_by(a) && - b->alias->size == nbytes_loaded_or_stored_by(b) - ) - return 1; - } - - return 0; -} - -Boolean may_alias_worst_case(PCode *pcode) { - return may_alias_alias(pcode->alias, worst_case); -} - -Boolean may_alias_object(PCode *pcode, Object *object) { - return may_alias_alias(pcode->alias, make_alias(object, 0, 0)); -} - -void initialize_alias_values(void) { - Alias *alias; - - for (alias = aliases; alias; alias = alias->next) { - alias->valuenumber = nextvaluenumber++; - alias->valuepcode = NULL; - } -} - -void update_alias_value(Alias *alias, PCode *pcode) { - AliasMember *member; - AliasMember *member2; - AliasMember *member3; - - switch (alias->type) { - case AliasType0: - killmemory(alias, pcode); - for (member = alias->children; member; member = member->nextChild) { - CError_ASSERT(1152, member->parent->type == AliasType2); - killmemory(member->parent, NULL); - } - for (member = alias->parents; member; member = member->nextParent) { - CError_ASSERT(1157, member->child->type == AliasType1); - killmemory(member->child, NULL); - for (member2 = member->child->children; member2; member2 = member2->nextChild) { - if (member2->parent != alias) { - CError_ASSERT(1163, member2->parent->type == AliasType2); - killmemory(member2->parent, NULL); - } - } - } - break; - - case AliasType1: - killmemory(alias, pcode); - for (member = alias->children; member; member = member->nextChild) { - killmemory(member->parent, NULL); - if (member->parent->type == AliasType0) { - for (member2 = member->parent->parents; member2; member2 = member2->nextParent) { - if (member2->child != alias && aliases_overlap(alias, member2->child)) { - killmemory(member2->child, NULL); - } - } - } - } - break; - - case AliasType2: - killmemory(alias, NULL); - for (member = alias->parents; member; member = member->nextParent) { - killmemory(member->child, NULL); - for (member2 = member->child->children; member2; member2 = member2->nextChild) { - if (member2->parent != alias) - killmemory(member2->parent, NULL); - } - for (member3 = member->child->parents; member3; member3 = member3->nextParent) { - killmemory(member3->child, NULL); - for (member2 = member3->child->children; member2; member2 = member2->nextChild) { - if (member2->parent != member->child) - killmemory(member2->parent, NULL); - } - } - } - break; - } -} - -void update_all_alias_values(void) { - Alias *alias; - - for (alias = aliases; alias; alias = alias->next) - killmemory(alias, NULL); -} - diff --git a/compiler_and_linker/unsorted/CABI.c b/compiler_and_linker/unsorted/CABI.c deleted file mode 100644 index 2a88de1..0000000 --- a/compiler_and_linker/unsorted/CABI.c +++ /dev/null @@ -1,2033 +0,0 @@ -#include "compiler/CABI.h" -#include "compiler/CClass.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CException.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInit.h" -#include "compiler/CInline.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CParser.h" -#include "compiler/CScope.h" -#include "compiler/CSOM.h" -#include "compiler/CompilerTools.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/types.h" - -typedef struct OffsetList { - struct OffsetList *next; - SInt32 offset; -} OffsetList; - -static OffsetList *trans_vtboffsets; -static BClassList cabi_pathroot; -static BClassList *cabi_pathcur; -static TypeClass *cabi_loop_class; -static Boolean cabi_loop_construct; - -short CABI_GetStructResultArgumentIndex(TypeFunc *tfunc) { - return 0; -} - -Type *CABI_GetSizeTType(void) { - return TYPE(&stunsignedlong); -} - -Type *CABI_GetPtrDiffTType(void) { - return TYPE(&stsignedlong); -} - -SInt16 CABI_StructSizeAlignValue(Type *type, SInt32 size) { - SInt16 align = CMach_GetTypeAlign(type); - if (align <= 1) - return 0; - else - return (align - 1) & (align - ((size & (align - 1)))); -} - -void CABI_ReverseBitField(TypeBitfield *tbitfield) { - UInt8 bits; - UInt8 a; - UInt8 b; - - switch (tbitfield->bitfieldtype->size) { - case 1: - bits = 8; - break; - case 2: - bits = 16; - break; - case 4: - bits = 32; - break; - case 8: - bits = 64; - break; - default: - CError_FATAL(172); - } - - b = tbitfield->bitlength; - a = tbitfield->offset; - tbitfield->offset = (bits - a) - b; -} - -static void CABI_AllocateZeroVTablePointer(void *unk, TypeClass *tclass) { - ClassList *base; - - for (base = tclass->bases; base; base = base->next) { - if (!base->is_virtual && base->base->vtable) - return; - } - - tclass->size += void_ptr.size; -} - -static SInt32 CABI_GetBaseSize(TypeClass *tclass) { - SInt32 size = tclass->size; - - if (copts.vbase_abi_v2 && tclass->vbases) - return tclass->vbases->offset; - - return size; -} - -static void CABI_AllocateBases(ClassLayout *layout, TypeClass *tclass) { - Boolean flag; - TypeClass *baseclass; - ClassList *base; - VClassList *vbase; - SInt32 size; - - flag = 0; - size = tclass->size; - - for (base = tclass->bases; base; base = base->next) { - if (!base->is_virtual) { - baseclass = base->base; - if (!(baseclass->flags & CLASS_EMPTY)) { - base->offset = size + CMach_MemberAlignValue(TYPE(baseclass), size); - if (copts.vbase_abi_v2) { - size = base->offset + CABI_GetBaseSize(baseclass); - } else { - size = base->offset + baseclass->size; - for (vbase = baseclass->vbases; vbase; vbase = vbase->next) - size -= vbase->base->size; - } - flag = 0; - } else { - if (flag) - base->offset = ++size; - else - base->offset = size; - flag = 1; - } - } - } - - tclass->size = size; -} - -static void CABI_AllocateVirtualBasePointers(ClassLayout *layout, TypeClass *tclass) { - ClassList *base; - SInt32 size; - - size = tclass->size; - - for (base = tclass->bases; base; base = base->next) { - if (base->is_virtual) { - base->offset = size + CMach_MemberAlignValue(TYPE(&void_ptr), size); - size = base->offset + void_ptr.size; - } - } - - tclass->size = size; -} - -static SInt32 CABI_GetMemberOffset(TypeClass *tclass, HashNameNode *name) { - ObjMemberVar *ivar; - - if (!name) - return 0; - - ivar = tclass->ivars; - while (1) { - if (ivar->name == name) - return ivar->offset; - - if (!(ivar = ivar->next)) - CError_FATAL(362); - } -} - -static void CABI_AllocateMembers(ClassLayout *layout, TypeClass *tclass) { - ObjMemberVar *ivar; - SInt32 initialSize; - SInt32 maxSize; - TypeClass *unionClass; - SInt32 unionStart; - Boolean inAnonUnion; - Boolean removeNoNameIvars; - - removeNoNameIvars = 0; - initialSize = maxSize = tclass->size; - CMach_StructLayoutInitOffset(maxSize); - - unionClass = NULL; - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - if (!ivar->anonunion) { - if (!(ivar->offset & 0x80000000)) { - if (tclass->mode == CLASS_MODE_UNION) - CMach_StructLayoutInitOffset(initialSize); - - if (IS_TYPE_BITFIELD(ivar->type)) - ivar->offset = CMach_StructLayoutBitfield(TYPE_BITFIELD(ivar->type), ivar->qual); - else - ivar->offset = CMach_StructLayoutGetOffset(ivar->type, ivar->qual); - - if (tclass->mode == CLASS_MODE_UNION) { - SInt32 tmp = CMach_StructLayoutGetCurSize(); - if (tmp > maxSize) - maxSize = tmp; - } - - unionClass = NULL; - } else { - CError_ASSERT(412, unionClass); - ivar->offset = unionStart + CABI_GetMemberOffset(unionClass, ivar->name); - if (!inAnonUnion) - ivar->anonunion = 1; - inAnonUnion = 0; - } - - if (ivar->name == no_name_node || ivar->name == NULL) - removeNoNameIvars = 1; - } else { - CError_ASSERT(422, IS_TYPE_CLASS(ivar->type)); - - if (tclass->mode == CLASS_MODE_UNION) - CMach_StructLayoutInitOffset(initialSize); - - unionStart = CMach_StructLayoutGetOffset(ivar->type, ivar->qual); - unionClass = TYPE_CLASS(ivar->type); - inAnonUnion = 1; - - if (tclass->mode == CLASS_MODE_UNION) { - SInt32 tmp = CMach_StructLayoutGetCurSize(); - if (tmp > maxSize) - maxSize = tmp; - } - - removeNoNameIvars = 1; - } - - if (layout->vtable_ivar == ivar) - tclass->vtable->offset = ivar->offset; - } - - if (removeNoNameIvars) { - ObjMemberVar **ptr = &tclass->ivars; - while (*ptr) { - if ((*ptr)->name == NULL || (*ptr)->name == no_name_node) - *ptr = (*ptr)->next; - else - ptr = &(*ptr)->next; - } - } - - if (tclass->mode == CLASS_MODE_UNION) - tclass->size = maxSize; - else - tclass->size = CMach_StructLayoutGetCurSize(); - - if (copts.reverse_bitfields) { - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - if (IS_TYPE_BITFIELD(ivar->type)) - CABI_ReverseBitField(TYPE_BITFIELD(ivar->type)); - } - } -} - -static void CABI_AllocateVirtualBases(ClassLayout *layout, TypeClass *tclass) { - VClassList *vbase; - SInt32 size; - - size = tclass->size; - - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - vbase->offset = size + CMach_MemberAlignValue(TYPE(vbase->base), size); - size = vbase->offset + CABI_GetBaseSize(vbase->base); - - if (vbase->has_override) - size += CMach_MemberAlignValue(TYPE(&stunsignedlong), size) + 4; - } - - tclass->size = size; -} - -static Boolean CABI_FindZeroDeltaVPtr(TypeClass *tclass) { - ClassList *base; - - for (base = tclass->bases; base; base = base->next) { - if (!base->is_virtual && base->base->vtable && !base->offset) { - tclass->vtable->offset = base->base->vtable->offset; - return 1; - } - } - - return 0; -} - -static Object *CABI_FindZeroVirtualBaseMember(TypeClass *tclass, Object *obj) { - NameSpaceObjectList *nsol; - ClassList *base; - Object *chk; - - for (base = tclass->bases; base; base = base->next) { - if (!base->is_virtual && !base->offset && !base->voffset && base->base->vtable) { - for (nsol = CScope_FindName(base->base->nspace, obj->name); nsol; nsol = nsol->next) { - chk = OBJECT(nsol->object); - if ( - chk->otype == OT_OBJECT && - chk->datatype == DVFUNC && - CClass_GetOverrideKind(TYPE_FUNC(chk->type), TYPE_FUNC(obj->type), 0) == 1 - ) - return chk; - } - - if ((chk = CABI_FindZeroVirtualBaseMember(base->base, obj))) - return chk; - } - } - - return NULL; -} - -void CABI_AddVTable(TypeClass *tclass) { - tclass->vtable = galloc(sizeof(VTable)); - memclrw(tclass->vtable, sizeof(VTable)); -} - -SInt32 CABI_GetVTableOffset(TypeClass *tclass) { - return 0; -} - -static SInt32 CABI_GetBaseVTableSize(TypeClass *tclass) { - VClassList *vbase; - SInt32 size; - - size = tclass->vtable->size; - - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - if (vbase->base->vtable) - size -= CABI_GetBaseVTableSize(vbase->base); - } - - return size; -} - -static void CABI_ApplyClassFlags(Object *obj, UInt8 flags, Boolean unused) { - if (flags & CLASS_EFLAGS_INTERNAL) - obj->flags = obj->flags | OBJECT_INTERNAL; - if (flags & CLASS_EFLAGS_IMPORT) - obj->flags = obj->flags | OBJECT_IMPORT; - if (flags & CLASS_EFLAGS_EXPORT) - obj->flags = obj->flags | OBJECT_EXPORT; -} - -static void CABI_AllocateVTable(ClassLayout *layout, TypeClass *tclass) { - SInt32 size; - ObjBase *objbase; - Object *obj; - ObjMemberVar *ivar; - ClassList *base; - VClassList *vbase; - int i; - - size = 0; - - if (!tclass->vtable) { - CABI_AddVTable(tclass); - layout->xA = layout->lex_order_count - 1; - } - - if (!CABI_FindZeroDeltaVPtr(tclass)) { - ivar = galloc(sizeof(ObjMemberVar)); - memclrw(ivar, sizeof(ObjMemberVar)); - - ivar->otype = OT_MEMBERVAR; - ivar->access = ACCESSPUBLIC; - ivar->name = vptr_name_node; - ivar->type = TYPE(&void_ptr); - layout->vtable_ivar = ivar; - - for (i = layout->xA; ; i--) { - if (i < 0) { - ivar->next = tclass->ivars; - tclass->ivars = ivar; - break; - } - - CError_ASSERT(666, layout->objlist[i]); - - if (layout->objlist[i]->otype == OT_MEMBERVAR) { - ivar->next = OBJ_MEMBER_VAR(layout->objlist[i])->next; - OBJ_MEMBER_VAR(layout->objlist[i])->next = ivar; - break; - } - } - - if (tclass->flags & (CLASS_SINGLE_OBJECT | CLASS_COM_OBJECT)) - size = void_ptr.size; - else - size = 8; - } else { - layout->vtable_ivar = NULL; - } - - for (base = tclass->bases; base; base = base->next) { - if (base->base->vtable && !base->is_virtual) { - base->voffset = size; - if (copts.vbase_abi_v2) { - size += CABI_GetBaseVTableSize(base->base); - } else { - size += base->base->vtable->size; - for (vbase = base->base->vbases; vbase; vbase = vbase->next) { - if (vbase->base->vtable) - size -= vbase->base->vtable->size; - } - } - } - } - - for (i = 0; i < layout->lex_order_count; i++) { - CError_ASSERT(714, objbase = layout->objlist[i]); - - if (objbase->otype == OT_OBJECT && OBJECT(objbase)->datatype == DVFUNC) { - TypeMemberFunc *tmethod = TYPE_METHOD(OBJECT(objbase)->type); - Object *baseobj = CABI_FindZeroVirtualBaseMember(tclass, OBJECT(objbase)); - - if (baseobj) { - tmethod->vtbl_index = TYPE_METHOD(baseobj->type)->vtbl_index; - } else { - tmethod->vtbl_index = size; - size += 4; - } - } - } - - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - if (vbase->base->vtable) { - vbase->voffset = size; - if (copts.vbase_abi_v2) - size += CABI_GetBaseVTableSize(vbase->base); - else - size += vbase->base->vtable->size; - } - } - - obj = CParser_NewCompilerDefDataObject(); - CABI_ApplyClassFlags(obj, tclass->eflags, 0); - - obj->name = CMangler_VTableName(tclass); - obj->type = CDecl_NewStructType(size, 4); - obj->qual = Q_CONST; - obj->nspace = tclass->nspace; - switch (tclass->action) { - case CLASS_ACTION_0: - obj->sclass = TK_STATIC; - obj->qual |= Q_20000; - break; - } - - CParser_UpdateObject(obj, NULL); - - tclass->vtable->object = obj; - tclass->vtable->owner = tclass; - tclass->vtable->size = size; -} - -void CABI_LayoutClass(ClassLayout *layout, TypeClass *tclass) { - char saveAlignMode = copts.structalignment; - - tclass->size = 0; - if (!tclass->sominfo) { - if (tclass->bases) - CABI_AllocateBases(layout, tclass); - if (tclass->flags & CLASS_HAS_VBASES) - CABI_AllocateVirtualBasePointers(layout, tclass); - if (layout->has_vtable) - CABI_AllocateVTable(layout, tclass); - CABI_AllocateMembers(layout, tclass); - if (tclass->flags & CLASS_HAS_VBASES) - CABI_AllocateVirtualBases(layout, tclass); - } else { - copts.structalignment = AlignMode2_PPC; - CABI_AllocateMembers(layout, tclass); - } - - tclass->align = CMach_GetClassAlign(tclass); - if (tclass->size == 0) { - tclass->size = 1; - tclass->flags = tclass->flags | CLASS_EMPTY; - } else { - tclass->size += CABI_StructSizeAlignValue(TYPE(tclass), tclass->size); - } - - tclass->flags = tclass->flags | CLASS_COMPLETED; - - copts.structalignment = saveAlignMode; -} - -void CABI_MakeDefaultArgConstructor(TypeClass *tclass, Object *func) { - DefArgCtorInfo *info; - Boolean saveDebugInfo; - ENodeList *copied; - ENodeList *argexprs; - FuncArg *args; - CScopeSave savedScope; - Statement firstStmt; - Statement returnStmt; - - CError_FATAL(860); - - if (anyerrors || func->access == ACCESSNONE) - return; - - CError_ASSERT(866, info = func->u.func.defargdata); - - CABI_ApplyClassFlags(func, tclass->eflags, 0); - - CScope_SetFunctionScope(func, &savedScope); - - CFunc_FuncGenSetup(&firstStmt, func); - - saveDebugInfo = copts.filesyminfo; - copts.filesyminfo = 0; - - CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); - - if (tclass->flags & CLASS_HAS_VBASES) - arguments->next->object->name = no_name_node; - - firstStmt.next = &returnStmt; - - memclrw(&returnStmt, sizeof(Statement)); - returnStmt.type = ST_RETURN; - returnStmt.expr = lalloc(sizeof(ENode)); - returnStmt.expr->type = EFUNCCALL; - returnStmt.expr->cost = 200; - returnStmt.expr->flags = 0; - returnStmt.expr->rtype = TYPE(&void_ptr); - - returnStmt.expr->data.funccall.funcref = CExpr_MakeObjRefNode(info->default_func, 0); - returnStmt.expr->data.funccall.functype = TYPE_FUNC(info->default_func->type); - args = TYPE_FUNC(info->default_func->type)->args; - returnStmt.expr->data.funccall.args = lalloc(sizeof(ENodeList)); - argexprs = returnStmt.expr->data.funccall.args; - - argexprs->node = create_objectnode(arguments->object); - - if (tclass->flags & CLASS_HAS_VBASES) { - args = args->next; - argexprs->next = lalloc(sizeof(ENodeList)); - argexprs = argexprs->next; - argexprs->node = create_objectnode(arguments->next->object); - } - - args = args->next; - argexprs->next = lalloc(sizeof(ENodeList)); - argexprs = argexprs->next; - argexprs->node = CInline_CopyExpression(info->default_arg, CopyMode0); - - while ((args = args->next) && args->dexpr) { - argexprs->next = lalloc(sizeof(ENodeList)); - argexprs = argexprs->next; - argexprs->node = CInline_CopyExpression(args->dexpr, CopyMode0); - } - - argexprs->next = NULL; - - CFunc_CodeCleanup(&firstStmt); - CFunc_Gen(&firstStmt, func, 0); - - CScope_RestoreScope(&savedScope); - copts.filesyminfo = saveDebugInfo; - - func->u.func.defargdata = NULL; -} - -static Object *CABI_ThisArg(void) { - CError_ASSERT(931, arguments && IS_TYPE_POINTER_ONLY(arguments->object->type)); - return arguments->object; -} - -ENode *CABI_MakeThisExpr(TypeClass *tclass, SInt32 offset) { - ENode *expr; - - if (tclass) { - if (!tclass->sominfo) { - expr = create_objectnode(CABI_ThisArg()); - if (tclass->flags & CLASS_HANDLEOBJECT) - expr = makemonadicnode(expr, EINDIRECT); - } else { - expr = CSOM_SOMSelfObjectExpr(tclass); - } - } else { - expr = create_objectnode(CABI_ThisArg()); - expr->rtype = TYPE(&void_ptr); - } - - if (offset) - expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); - - return expr; -} - -static Object *CABI_VArg(void) { - CError_ASSERT(976, arguments && arguments->next && IS_TYPE_INT(arguments->next->object->type)); - return arguments->next->object; -} - -static ENode *CABI_MakeVArgExpr(void) { - return create_objectnode(CABI_VArg()); -} - -static ENode *CABI_MakeCopyConArgExpr(TypeClass *tclass, Boolean flag) { - ObjectList *args; - - CError_ASSERT(1000, args = arguments); - CError_ASSERT(1001, args = args->next); - if (flag && (tclass->flags & CLASS_HAS_VBASES)) - CError_ASSERT(1002, args = args->next); - CError_ASSERT(1003, IS_TYPE_POINTER_ONLY(args->object->type)); - - return create_objectnode(args->object); -} - -static ENode *CABI_InitVBasePtr1(ENode *expr, TypeClass *tclass1, TypeClass *tclass2, TypeClass *tclass3, SInt32 offset) { - ClassList *base; - SInt32 newOffset; - OffsetList *list; - - for (base = tclass2->bases; base; base = base->next) { - if (base->base == tclass3 && base->is_virtual) { - newOffset = offset + base->offset; - - for (list = trans_vtboffsets; list; list = list->next) { - if (newOffset == list->offset) - break; - } - - if (!list) { - list = lalloc(sizeof(OffsetList)); - list->offset = newOffset; - list->next = trans_vtboffsets; - trans_vtboffsets = list; - - expr = makediadicnode( - makemonadicnode(CABI_MakeThisExpr(NULL, newOffset), EINDIRECT), - expr, - EASS); - } - } - - if (base->is_virtual) - newOffset = CClass_VirtualBaseOffset(tclass1, base->base); - else - newOffset = offset + base->offset; - - expr = CABI_InitVBasePtr1(expr, tclass1, base->base, tclass3, newOffset); - } - - return expr; -} - -static Statement *CABI_InitVBasePtrs(Statement *stmt, TypeClass *tclass) { - ENode *expr; - VClassList *vbase; - - for (vbase = tclass->vbases, trans_vtboffsets = NULL; vbase; vbase = vbase->next) { - expr = CABI_InitVBasePtr1(CABI_MakeThisExpr(NULL, vbase->offset), tclass, tclass, vbase->base, 0); - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = expr; - } - - return stmt; -} - -static OffsetList *CABI_GetVBasePath(TypeClass *tclass, TypeClass *baseclass) { - ClassList *base; - OffsetList *best; - OffsetList *list; - OffsetList *scan; - short bestLength; - short length; - - for (base = tclass->bases; base; base = base->next) { - if (base->base == baseclass && base->is_virtual) { - best = lalloc(sizeof(OffsetList)); - best->next = NULL; - best->offset = base->offset; - return best; - } - } - - best = NULL; - - for (base = tclass->bases; base; base = base->next) { - if ((list = CABI_GetVBasePath(base->base, baseclass))) { - for (scan = list->next, length = 1; scan; scan = scan->next) - length++; - - if (base->is_virtual) - length++; - - if (!best || length < bestLength) { - if (base->is_virtual) { - best = lalloc(sizeof(OffsetList)); - best->next = list; - best->offset = base->offset; - } else { - best = list; - best->offset += base->offset; - } - bestLength = length; - } - } - } - - return best; -} - -static ENode *CABI_GetVBasePtr(TypeClass *tclass, TypeClass *baseclass) { - OffsetList *path; - ENode *expr; - - CError_ASSERT(1127, path = CABI_GetVBasePath(tclass, baseclass)); - - expr = makemonadicnode(CABI_MakeThisExpr(NULL, path->offset), EINDIRECT); - - while ((path = path->next)) { - if (path->offset) - expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), path->offset), EADD); - expr = makemonadicnode(expr, EINDIRECT); - } - - return expr; -} - -static SInt32 CABI_FindNVBase(TypeClass *tclass, TypeClass *baseclass, SInt32 offset) { - ClassList *base; - SInt32 tmp; - - if (tclass == baseclass) - return offset; - - for (base = tclass->bases; base; base = base->next) { - if (!base->is_virtual && (tmp = CABI_FindNVBase(base->base, baseclass, offset + base->offset)) >= 0) - return tmp; - } - - return -1; -} - -SInt32 CABI_GetCtorOffsetOffset(TypeClass *tclass, TypeClass *baseclass) { - SInt32 baseSize; - SInt32 size; - char saveAlignMode; - - size = CABI_GetBaseSize(tclass); - if (baseclass) { - baseSize = CABI_FindNVBase(tclass, baseclass, 0); - CError_ASSERT(1178, baseSize >= 0); - size -= baseSize; - } - - saveAlignMode = copts.structalignment; - if (tclass->eflags & CLASS_EFLAGS_F0) - copts.structalignment = ((tclass->eflags & CLASS_EFLAGS_F0) >> 4) - 1; - size += CMach_MemberAlignValue(TYPE(&stunsignedlong), size); - copts.structalignment = saveAlignMode; - - return size; -} - -static Statement *CABI_InitVBaseCtorOffsets(Statement *stmt, TypeClass *tclass) { - VClassList *vbase; - Object *tempObj; - ENode *expr; - ENode *vbaseptr; - SInt32 vboffset; - SInt32 ctorOffsetOffset; - - tempObj = NULL; - - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - if (vbase->has_override) { - if (!tempObj) - tempObj = create_temp_object(TYPE(&void_ptr)); - - vboffset = CClass_VirtualBaseOffset(tclass, vbase->base); - ctorOffsetOffset = CABI_GetCtorOffsetOffset(vbase->base, NULL); - vbaseptr = CABI_GetVBasePtr(tclass, vbase->base); - CError_ASSERT(1215, vbaseptr); - - expr = makediadicnode(create_objectnode(tempObj), vbaseptr, EASS); - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = expr; - - expr = makediadicnode( - create_objectnode(tempObj), - intconstnode(TYPE(&stunsignedlong), ctorOffsetOffset), - EADD); - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = TYPE(&stunsignedlong); - expr = makediadicnode( - expr, - makediadicnode( - CABI_MakeThisExpr(NULL, vboffset), - create_objectnode(tempObj), - ESUB), - EASS); - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = expr; - } - } - - return stmt; -} - -static Statement *CABI_InitVTablePtrs(Statement *stmt, Object *vtableObj, TypeClass *tclass, TypeClass *baseclass, SInt32 offset, SInt32 voffset) { - ClassList *base; - BClassList *orig_pathcur; - SInt32 newOffset; - SInt32 newVOffset; - OffsetList *offsetList; - SInt32 vtblOffset; - ENode *vtblExpr; - ENode *pathExpr; - BClassList path; - - if (baseclass->vtable->owner == baseclass) { - vtblOffset = offset + baseclass->vtable->offset; - for (offsetList = trans_vtboffsets; offsetList; offsetList = offsetList->next) { - if (vtblOffset == offsetList->offset) - break; - } - - if (!offsetList) { - offsetList = lalloc(sizeof(OffsetList)); - offsetList->offset = vtblOffset; - offsetList->next = trans_vtboffsets; - trans_vtboffsets = offsetList; - - vtblExpr = create_objectrefnode(vtableObj); - vtblExpr->rtype = TYPE(&void_ptr); - if ((vtblOffset = voffset + CABI_GetVTableOffset(baseclass))) - vtblExpr = makediadicnode(vtblExpr, intconstnode(TYPE(&stunsignedlong), vtblOffset), EADD); - - pathExpr = CClass_AccessPathCast(&cabi_pathroot, CABI_MakeThisExpr(tclass, 0), 0); - if (baseclass->vtable->offset && !canadd(pathExpr, baseclass->vtable->offset)) { - pathExpr = makediadicnode(pathExpr, intconstnode(TYPE(&stunsignedlong), baseclass->vtable->offset), EADD); - optimizecomm(pathExpr); - } - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = makediadicnode(makemonadicnode(pathExpr, EINDIRECT), vtblExpr, EASS); - } - } - - for (base = baseclass->bases; base; base = base->next) { - if (base->base->vtable) { - orig_pathcur = cabi_pathcur; - - cabi_pathcur->next = &path; - path.next = NULL; - path.type = TYPE(base->base); - cabi_pathcur = &path; - - if (base->is_virtual) { - newOffset = CClass_VirtualBaseOffset(tclass, base->base); - newVOffset = CClass_VirtualBaseVTableOffset(tclass, base->base); - } else { - newOffset = offset + base->offset; - newVOffset = voffset + base->voffset; - } - - stmt = CABI_InitVTablePtrs(stmt, vtableObj, tclass, base->base, newOffset, newVOffset); - - cabi_pathcur = orig_pathcur; - } - } - - return stmt; -} - -static Boolean CABI_IsOperatorNew(ObjBase *obj) { - return - obj->otype == OT_OBJECT && - IS_TYPE_FUNC(OBJECT(obj)->type) && - TYPE_FUNC(OBJECT(obj)->type)->args && - TYPE_FUNC(OBJECT(obj)->type)->args->type == CABI_GetSizeTType() && - !TYPE_FUNC(OBJECT(obj)->type)->args->next; -} - -Object *CABI_ConstructorCallsNew(TypeClass *tclass) { - NameSpaceObjectList *nsol; - NameResult pr; - - if (!tclass->sominfo && (tclass->flags & CLASS_HANDLEOBJECT)) { - if (CScope_FindClassMemberObject(tclass, &pr, CMangler_OperatorName(TK_NEW))) { - if (pr.obj_10) { - if (CABI_IsOperatorNew(pr.obj_10)) - return OBJECT(pr.obj_10); - } else { - for (nsol = pr.nsol_14; nsol; nsol = nsol->next) { - if (CABI_IsOperatorNew(nsol->object)) - return OBJECT(nsol->object); - } - } - } - - return newh_func; - } - - return NULL; -} - -void CABI_TransConstructor(Object *obj, Statement *firstStmt, TypeClass *tclass, TransConstructorCallback callback, Boolean has_try) { - Statement *stmt; - Object *tmpfunc; - Object *tmpfunc2; - CLabel *label; - ENode *expr; - ClassList *base; - VClassList *vbase; - ObjMemberVar *ivar; - Type *type; - CtorChain *chain; - Boolean errorflag; - - stmt = firstStmt; - - if ((tmpfunc = CABI_ConstructorCallsNew(tclass))) { - label = newlabel(); - - stmt = CFunc_InsertStatement(ST_IFGOTO, firstStmt); - stmt->expr = CABI_MakeThisExpr(NULL, 0); - stmt->label = label; - - expr = makediadicnode( - CABI_MakeThisExpr(NULL, 0), - funccallexpr(tmpfunc, intconstnode(CABI_GetSizeTType(), tclass->size), NULL, NULL, NULL), - EASS); - stmt = CFunc_InsertStatement(ST_IFGOTO, stmt); - stmt->expr = expr; - stmt->label = label; - - stmt = CFunc_InsertStatement(ST_RETURN, stmt); - stmt->expr = NULL; - - stmt = CFunc_InsertStatement(ST_LABEL, stmt); - stmt->label = label; - label->stmt = stmt; - } - - if (has_try) { - for (stmt = firstStmt; ; stmt = stmt->next) { - CError_ASSERT(1408, stmt); - if (stmt->type == ST_BEGINCATCH) - break; - } - } - - if (!tclass->sominfo) { - if (tclass->flags & CLASS_HAS_VBASES) { - label = newlabel(); - - stmt = CFunc_InsertStatement(ST_IFGOTO, stmt); - stmt->expr = CExpr_New_EEQU_Node(CABI_MakeVArgExpr(), intconstnode(TYPE(&stsignedshort), 0)); - stmt->label = label; - - stmt = CABI_InitVBasePtrs(stmt, tclass); - - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - if (!callback) { - for (chain = ctor_chain; chain; chain = chain->next) { - if (chain->what == CtorChain_VBase && chain->u.vbase == vbase) - break; - } - - if (chain) { - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = chain->objexpr; - } else { - expr = CClass_DefaultConstructorCall( - vbase->base, - tclass, - CABI_MakeThisExpr(NULL, vbase->offset), - 0, 1, 1, &errorflag); - if (expr) { - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = expr; - } else if (errorflag) { - CError_Error(CErrorStr213, tclass, 0, vbase->base, 0); - } - } - } else { - stmt = callback(stmt, tclass, vbase->base, vbase->offset, 1); - } - - if ((tmpfunc = CClass_Destructor(vbase->base))) - CExcept_RegisterMember(stmt, CABI_ThisArg(), vbase->offset, tmpfunc, CABI_VArg(), 0); - } - - stmt = CFunc_InsertStatement(ST_LABEL, stmt); - stmt->label = label; - label->stmt = stmt; - } - - for (base = tclass->bases; base; base = base->next) { - if (base->is_virtual) - continue; - - if (!callback) { - for (chain = ctor_chain; chain; chain = chain->next) { - if (chain->what == CtorChain_Base && chain->u.base == base) - break; - } - - if (chain) { - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = chain->objexpr; - } else { - expr = CClass_DefaultConstructorCall( - base->base, - tclass, - CABI_MakeThisExpr(NULL, base->offset), - 0, 1, 0, &errorflag); - if (expr) { - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = expr; - } else if (errorflag) { - CError_Error(CErrorStr213, tclass, 0, base->base, 0); - } - } - } else { - stmt = callback(stmt, tclass, base->base, base->offset, 1); - } - - if ((tmpfunc = CClass_Destructor(base->base))) - CExcept_RegisterMember(stmt, CABI_ThisArg(), base->offset, tmpfunc, NULL, 0); - } - - if (tclass->vtable && tclass->vtable->object && tclass->vtable->owner == tclass) { - cabi_pathroot.next = NULL; - cabi_pathroot.type = TYPE(tclass); - cabi_pathcur = &cabi_pathroot; - trans_vtboffsets = NULL; - - stmt = CABI_InitVTablePtrs(stmt, tclass->vtable->object, tclass, tclass, 0, 0); - } - } - - if (!tclass->sominfo && (tclass->flags & CLASS_FLAGS_8000)) - stmt = CABI_InitVBaseCtorOffsets(stmt, tclass); - - if (!callback) { - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - for (chain = ctor_chain; chain; chain = chain->next) { - if (chain->what == CtorChain_MemberVar && chain->u.membervar == ivar) { - if (IS_TYPE_ARRAY(ivar->type)) - chain = NULL; - break; - } - } - - if (chain) { - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = chain->objexpr; - type = ivar->type; - switch (type->type) { - case TYPEARRAY: - do { - type = TPTR_TARGET(type); - } while (IS_TYPE_ARRAY(type)); - if (IS_TYPE_CLASS(type)) { - if ((tmpfunc = CClass_Destructor(TYPE_CLASS(type)))) { - CError_ASSERT(1560, type->size); - CExcept_RegisterMemberArray( - stmt, - CABI_ThisArg(), - ivar->offset, - tmpfunc, - ivar->type->size / type->size, - type->size); - } - } - break; - case TYPECLASS: - if ((tmpfunc = CClass_Destructor(TYPE_CLASS(type)))) { - CExcept_RegisterMember( - stmt, - CABI_ThisArg(), - ivar->offset, - tmpfunc, - NULL, - 1); - } - break; - } - } else { - type = ivar->type; - switch (type->type) { - case TYPEARRAY: - do { - type = TPTR_TARGET(type); - } while (IS_TYPE_ARRAY(type)); - if (IS_TYPE_CLASS(type) && CClass_Constructor(TYPE_CLASS(type))) { - if ( - (tmpfunc = CClass_DefaultConstructor(TYPE_CLASS(type))) || - (tmpfunc = CClass_DummyDefaultConstructor(TYPE_CLASS(type))) - ) - { - tmpfunc2 = CClass_Destructor(TYPE_CLASS(type)); - if (tmpfunc2) - tmpfunc2 = CABI_GetDestructorObject(tmpfunc2, 1); - - stmt = CInit_ConstructClassArray( - stmt, - TYPE_CLASS(type), - tmpfunc, - tmpfunc2, - CABI_MakeThisExpr(tclass, ivar->offset), - ivar->type->size / type->size); - - if (tmpfunc2) - CExcept_RegisterMemberArray( - stmt, - CABI_ThisArg(), - ivar->offset, - tmpfunc2, - ivar->type->size / type->size, - type->size); - } else { - CError_Error(CErrorStr214, tclass, 0, ivar->name->name); - } - } - break; - case TYPECLASS: - expr = CClass_DefaultConstructorCall( - TYPE_CLASS(type), - NULL, - CABI_MakeThisExpr(tclass, ivar->offset), - 1, 1, 0, &errorflag); - if (expr) { - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = expr; - } else if (errorflag) { - CError_Error(CErrorStr214, tclass, 0, ivar->name->name); - } - - if ((tmpfunc = CClass_Destructor(TYPE_CLASS(type)))) { - if (!expr) { - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = nullnode(); - } - CExcept_RegisterMember( - stmt, - CABI_ThisArg(), - ivar->offset, - tmpfunc, - NULL, - 1); - } - break; - } - } - } - } else { - stmt = callback(stmt, tclass, NULL, 0, 1); - } - - if (!tclass->sominfo) { - for (stmt = firstStmt->next; stmt; stmt = stmt->next) { - if (stmt->type == ST_RETURN) { - CError_ASSERT(1661, !stmt->expr); - stmt->expr = CABI_MakeThisExpr(NULL, 0); - } - } - } -} - -void CABI_MakeDefaultConstructor(TypeClass *tclass, Object *func) { - Boolean saveDebugInfo; - CScopeSave savedScope; - Statement firstStmt; - Statement returnStmt; - - if (anyerrors || func->access == ACCESSNONE) - return; - - CABI_ApplyClassFlags(func, tclass->eflags, 0); - - CScope_SetFunctionScope(func, &savedScope); - - CFunc_FuncGenSetup(&firstStmt, func); - - saveDebugInfo = copts.filesyminfo; - copts.filesyminfo = 0; - - CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); - - ctor_chain = NULL; - if (tclass->flags & CLASS_HAS_VBASES) - arguments->next->object->name = CParser_GetUniqueName(); - - firstStmt.next = &returnStmt; - - memclrw(&returnStmt, sizeof(Statement)); - returnStmt.type = ST_RETURN; - - CABI_TransConstructor(func, &firstStmt, tclass, NULL, 0); - - CFunc_CodeCleanup(&firstStmt); - CFunc_Gen(&firstStmt, func, 0); - - CScope_RestoreScope(&savedScope); - copts.filesyminfo = saveDebugInfo; -} - -static ENode *CABI_AssignObject(TypeClass *tclass, ENode *expr1, ENode *expr2) { - Object *assignfunc; - FuncArg *arg; - - assignfunc = CClass_AssignmentOperator(tclass); - if (!assignfunc) { - expr1 = makemonadicnode(expr1, EINDIRECT); - expr1->rtype = TYPE(tclass); - return makediadicnode(expr1, expr2, EASS); - } - - CError_ASSERT(1731, - IS_TYPE_FUNC(assignfunc->type) && - (arg = TYPE_FUNC(assignfunc->type)->args) && - (arg = arg->next)); - - expr2 = argumentpromotion(expr2, arg->type, arg->qual, 1); - return funccallexpr(assignfunc, expr1, expr2, NULL, NULL); -} - -static Type *CABI_FindIntegralSizeType(SInt32 size) { - if (stunsignedchar.size == size) - return TYPE(&stunsignedchar); - if (stunsignedshort.size == size) - return TYPE(&stunsignedshort); - if (stunsignedint.size == size) - return TYPE(&stunsignedint); - if (stunsignedlong.size == size) - return TYPE(&stunsignedlong); - if (stunsignedlonglong.size == size) - return TYPE(&stunsignedlonglong); - - CError_FATAL(1756); - return NULL; -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct CopyRegion { - struct CopyRegion *next; - Type *type; - SInt32 start; - SInt32 end; - Boolean flag; -} CopyRegion; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static CopyRegion *CABI_AppendCopyRegion(CopyRegion *regions, Type *type, SInt32 start, Boolean flag) { - CopyRegion *region; - SInt32 end; - - if (IS_TYPE_BITFIELD(type)) - type = TYPE_BITFIELD(type)->bitfieldtype; - - end = start + type->size; - - if (flag) { - for (region = regions; region; region = region->next) { - if (region->flag) { - if (region->start <= start && region->end >= end) - return regions; - - if (region->start >= start && region->end <= end) { - region->type = type; - region->start = start; - region->end = end; - for (region = region->next; region; region = region->next) { - if (region->start >= start && region->end <= end) - region->end = region->start; - } - return regions; - } - } - } - } - - if (regions) { - region = regions; - while (region->next) - region = region->next; - - region->next = lalloc(sizeof(CopyRegion)); - region = region->next; - } else { - regions = lalloc(sizeof(CopyRegion)); - region = regions; - } - - region->next = NULL; - region->type = type; - region->start = start; - region->end = end; - region->flag = flag; - - return regions; -} - -static ENode *CABI_ClassInitLoopCallBack(ENode *var1, ENode *var2) { - ENodeList *list; - - var2 = makemonadicnode(var2, EINDIRECT); - var2->rtype = TYPE(cabi_loop_class); - - if (cabi_loop_construct) { - list = lalloc(sizeof(ENodeList)); - memclrw(list, sizeof(ENodeList)); - list->node = var2; - return CExpr_ConstructObject(cabi_loop_class, var1, list, 1, 1, 0, 1, 1); - } else { - return CABI_AssignObject(cabi_loop_class, var1, var2); - } -} - -static Statement *CABI_CopyConAssignCB(Statement *stmt, TypeClass *tclass, TypeClass *baseclass, SInt32 offset, Boolean flag) { - ENode *expr; - ENode *expr2; - ENode *startExpr; - ENode *endExpr; - ENodeList *list; - ObjMemberVar *ivar; - CopyRegion *regions; - Type *type; - SInt32 i; - SInt32 count; - Boolean isFlagNotSet; - Object *tmpfunc; - - if (baseclass) { - if (baseclass->flags & CLASS_EMPTY) { - if ( - (flag && !CClass_CopyConstructor(baseclass)) || - (!flag && !CClass_AssignmentOperator(baseclass)) - ) - return stmt; - } - - expr = CABI_MakeCopyConArgExpr(tclass, flag); - expr->rtype = TYPE(baseclass); - expr->data.monadic = CClass_DirectBasePointerCast(expr->data.monadic, tclass, baseclass); - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - if (flag) { - list = lalloc(sizeof(ENodeList)); - list->next = NULL; - list->node = expr; - - stmt->expr = CExpr_ConstructObject( - baseclass, - CABI_MakeThisExpr(NULL, offset), - list, - 1, 0, 0, 0, 1); - } else { - stmt->expr = CABI_AssignObject( - baseclass, - CClass_DirectBasePointerCast(CABI_MakeThisExpr(NULL, 0), tclass, baseclass), - expr); - } - } else { - isFlagNotSet = !flag; - for (ivar = tclass->ivars, regions = NULL; ivar; ivar = ivar->next) { - if (ivar->name == vptr_name_node) - continue; - - type = ivar->type; - if (isFlagNotSet) { - if (CParser_IsConst(type, ivar->qual) || IS_TYPE_REFERENCE(type) != 0) { - CError_Error(CErrorStr387, tclass, 0); - isFlagNotSet = 0; - } - } - - switch (type->type) { - case TYPEARRAY: - while (IS_TYPE_ARRAY(type)) - type = TPTR_TARGET(type); - if (!IS_TYPE_CLASS(type)) { - regions = CABI_AppendCopyRegion(regions, ivar->type, ivar->offset, 1); - break; - } - case TYPECLASS: - if (flag) { - if (CClass_CopyConstructor(TYPE_CLASS(type)) || CClass_CopyConstructor(TYPE_CLASS(type))) { - regions = CABI_AppendCopyRegion(regions, ivar->type, ivar->offset, 0); - break; - } - } else { - if (CClass_AssignmentOperator(TYPE_CLASS(type))) { - regions = CABI_AppendCopyRegion(regions, ivar->type, ivar->offset, 0); - break; - } - } - default: - regions = CABI_AppendCopyRegion(regions, ivar->type, ivar->offset, 1); - } - } - - for (; regions; regions = regions->next) { - if (regions->start >= regions->end) - continue; - - type = regions->type; - expr = CABI_MakeCopyConArgExpr(tclass, flag); - expr->rtype = type; - - if (!canadd(expr->data.monadic, regions->start)) { - expr->data.monadic = makediadicnode( - expr->data.monadic, - intconstnode(TYPE(&stunsignedlong), regions->start), - EADD); - optimizecomm(expr->data.monadic); - } - - if (!regions->flag) { - if (IS_TYPE_ARRAY(type)) { - while (IS_TYPE_ARRAY(type)) - type = TPTR_TARGET(type); - - CError_ASSERT(1966, IS_TYPE_CLASS(type)); - - if (type->size) { - count = regions->type->size / type->size; - if (count > 4) { - startExpr = CABI_MakeThisExpr(tclass, regions->start); - endExpr = CABI_MakeThisExpr(tclass, regions->start + regions->type->size); - expr = CABI_MakeCopyConArgExpr(tclass, flag)->data.monadic; - if (!canadd(expr, regions->start)) { - expr = makediadicnode( - expr, - intconstnode(TYPE(&stunsignedlong), regions->start), - EADD); - optimizecomm(expr); - } - - cabi_loop_class = TYPE_CLASS(type); - cabi_loop_construct = flag; - stmt = CFunc_GenerateLoop( - stmt, - CDecl_NewPointerType(type), - startExpr, - endExpr, - intconstnode(TYPE(&stunsignedlong), type->size), - expr, - CABI_ClassInitLoopCallBack); - } else { - for (i = 0, offset = regions->start; i < count; i++, offset += type->size) { - expr = CABI_MakeCopyConArgExpr(tclass, flag); - expr->rtype = type; - - if (!canadd(expr->data.monadic, offset)) { - expr->data.monadic = makediadicnode( - expr->data.monadic, - intconstnode(TYPE(&stunsignedlong), offset), - EADD); - optimizecomm(expr->data.monadic); - } - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - if (flag) { - list = lalloc(sizeof(ENodeList)); - memclrw(list, sizeof(ENodeList)); - list->node = expr; - stmt->expr = CExpr_ConstructObject( - TYPE_CLASS(type), - CABI_MakeThisExpr(tclass, offset), - list, - 1, 1, 0, 1, 1); - } else { - stmt->expr = CABI_AssignObject( - TYPE_CLASS(type), - CABI_MakeThisExpr(tclass, offset), - expr); - } - } - } - - if (flag && (tmpfunc = CClass_Destructor(TYPE_CLASS(type)))) - CExcept_RegisterMemberArray(stmt, CABI_ThisArg(), regions->start, tmpfunc, count, type->size); - } - } else { - CError_ASSERT(2027, IS_TYPE_CLASS(type)); - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - - if (flag) { - list = lalloc(sizeof(ENodeList)); - memclrw(list, sizeof(ENodeList)); - list->node = expr; - stmt->expr = CExpr_ConstructObject( - TYPE_CLASS(type), - CABI_MakeThisExpr(tclass, regions->start), - list, - 1, 1, 0, 1, 1); - - if ((tmpfunc = CClass_Destructor(TYPE_CLASS(type)))) - CExcept_RegisterMember(stmt, CABI_ThisArg(), regions->start, tmpfunc, NULL, 1); - } else { - stmt->expr = CABI_AssignObject( - TYPE_CLASS(type), - CABI_MakeThisExpr(tclass, regions->start), - expr); - } - } - } else { - if (IS_TYPE_ARRAY(type)) { - if (type->size > 1 && ((regions->start & 1) || (type->size & 1))) { - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = funccallexpr( - copy_func, - CABI_MakeThisExpr(tclass, regions->start), - getnodeaddress(expr, 0), - intconstnode(CABI_GetSizeTType(), type->size), - NULL); - continue; - } - - type = CDecl_NewStructType(type->size, CMach_GetTypeAlign(type)); - expr->rtype = type; - } - - expr2 = makemonadicnode(CABI_MakeThisExpr(tclass, regions->start), EINDIRECT); - expr2->rtype = type; - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = makediadicnode(expr2, expr, EASS); - } - } - } - - return stmt; -} - -void CABI_MakeDefaultCopyConstructor(TypeClass *tclass, Object *func) { - Boolean saveDebugInfo; - CScopeSave savedScope; - Statement firstStmt; - Statement returnStmt; - - if (anyerrors || func->access == ACCESSNONE) - return; - - CABI_ApplyClassFlags(func, tclass->eflags, 0); - - CScope_SetFunctionScope(func, &savedScope); - - CFunc_FuncGenSetup(&firstStmt, func); - - saveDebugInfo = copts.filesyminfo; - copts.filesyminfo = 0; - - CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); - - ctor_chain = NULL; - if (tclass->flags & CLASS_HAS_VBASES) - arguments->next->object->name = CParser_GetUniqueName(); - - firstStmt.next = &returnStmt; - - memclrw(&returnStmt, sizeof(Statement)); - returnStmt.type = ST_RETURN; - - CABI_TransConstructor(func, &firstStmt, tclass, CABI_CopyConAssignCB, 0); - - CFunc_CodeCleanup(&firstStmt); - CFunc_Gen(&firstStmt, func, 0); - - CScope_RestoreScope(&savedScope); - copts.filesyminfo = saveDebugInfo; -} - -void CABI_MakeDefaultAssignmentOperator(TypeClass *tclass, Object *func) { - Boolean saveDebugInfo; - Statement *stmt; - ClassList *base; - VClassList *vbase; - ENode *expr1; - ENode *expr2; - CScopeSave savedScope; - Statement firstStmt; - - if (anyerrors || func->access == ACCESSNONE) - return; - - CABI_ApplyClassFlags(func, tclass->eflags, 0); - - CScope_SetFunctionScope(func, &savedScope); - - CFunc_FuncGenSetup(&firstStmt, func); - - saveDebugInfo = copts.filesyminfo; - copts.filesyminfo = 0; - - CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); - - stmt = curstmt; - - if (tclass->mode == CLASS_MODE_UNION) { - expr1 = makemonadicnode(CABI_MakeThisExpr(tclass, 0), EINDIRECT); - expr1->rtype = TYPE(tclass); - - expr2 = CABI_MakeCopyConArgExpr(tclass, 0); - expr2->rtype = TYPE(tclass); - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = makediadicnode(expr1, expr2, EASS); - } else { - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - stmt = CABI_CopyConAssignCB(stmt, tclass, vbase->base, vbase->offset, 0); - } - - for (base = tclass->bases; base; base = base->next) { - if (!base->is_virtual) - stmt = CABI_CopyConAssignCB(stmt, tclass, base->base, base->offset, 0); - } - - stmt = CABI_CopyConAssignCB(stmt, tclass, NULL, 0, 0); - } - - stmt = CFunc_InsertStatement(ST_RETURN, stmt); - stmt->expr = CABI_MakeThisExpr(NULL, 0); - - CFunc_CodeCleanup(&firstStmt); - CFunc_Gen(&firstStmt, func, 0); - - CScope_RestoreScope(&savedScope); - copts.filesyminfo = saveDebugInfo; -} - -static Statement *CABI_DestroyMembers(Statement *stmt, ObjMemberVar *ivars, TypeClass *tclass) { - Type *type; - Object *dtor; - ENode *expr; - - for (; ivars; ivars = ivars->next) { - type = ivars->type; - - if (IS_TYPE_ARRAY(type)) { - while (IS_TYPE_ARRAY(type)) - type = TPTR_TARGET(type); - - if (IS_TYPE_CLASS(type) && (dtor = CClass_Destructor(TYPE_CLASS(type)))) { - dtor = CABI_GetDestructorObject(dtor, 1); - stmt = CABI_DestroyMembers(stmt, ivars->next, tclass); - expr = create_objectrefnode(dtor); - expr->flags = expr->flags | ENODE_FLAG_80; - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = funccallexpr( - darr_func, - CABI_MakeThisExpr(tclass, ivars->offset), - expr, - intconstnode(TYPE(&stsignedlong), type->size), - intconstnode(TYPE(&stsignedlong), ivars->type->size / type->size) - ); - return stmt; - } - } else { - if (IS_TYPE_CLASS(type) && (dtor = CClass_Destructor(TYPE_CLASS(type)))) { - stmt = CABI_DestroyMembers(stmt, ivars->next, tclass); - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = CABI_DestroyObject( - dtor, - CABI_MakeThisExpr(tclass, ivars->offset), - CABIDestroy1, - 1, - 0 - ); - return stmt; - } - } - } - - return stmt; -} - -static Statement *CABI_DestroyBases(Statement *stmt, ClassList *bases) { - ClassList *base; - Object *dtor; - SInt32 count; - SInt32 i; - - base = bases; - count = 0; - while (base) { - base = base->next; - count++; - } - - while (count > 0) { - base = bases; - i = count; - while (i-- > 1) - base = base->next; - - if (!base->is_virtual && (dtor = CClass_Destructor(base->base))) { - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = CABI_DestroyObject( - dtor, - CABI_MakeThisExpr(NULL, base->offset), - CABIDestroy0, - 1, - 0); - } - - count--; - } - - return stmt; -} - -static Statement *CABI_DestroyVBases(Statement *stmt, VClassList *vbases) { - Object *dtor; - - for (; vbases; vbases = vbases->next) { - if ((dtor = CClass_Destructor(vbases->base))) { - stmt = CABI_DestroyVBases(stmt, vbases->next); - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = CABI_DestroyObject( - dtor, - CABI_MakeThisExpr(NULL, vbases->offset), - CABIDestroy0, - 1, - 0); - break; - } - } - - return stmt; -} - -void CABI_TransDestructor(Object *obj1, Object *obj2, Statement *stmt, TypeClass *tclass, CABIDestroyMode mode) { - CLabel *label2; - Boolean flag29; - CLabel *label; - Statement *scan; - Boolean flag25; - Boolean flag24; - Boolean flag23; - CLabel *label3; - Object *dealloc; - Boolean deallocFlag; - - if (tclass->sominfo) { - flag24 = 0; - flag25 = 0; - flag29 = 0; - flag23 = 1; - } else { - flag24 = 1; - flag23 = 1; - flag25 = 1; - flag29 = 1; - } - - label = newlabel(); - - for (scan = stmt; scan; scan = scan->next) { - if (scan->type == ST_RETURN) { - CError_ASSERT(2329, !scan->expr); - scan->type = ST_GOTO; - scan->label = label; - } - - if (scan->next && scan->next->type == ST_RETURN && !scan->next->next) { - CError_ASSERT(2334, !scan->next->expr); - scan->next = NULL; - break; - } - } - - scan = stmt; - - if (flag29) { - label2 = newlabel(); - scan = CFunc_InsertStatement(ST_IFNGOTO, scan); - scan->expr = CABI_MakeThisExpr(NULL, 0); - scan->label = label2; - } - - if (flag25 && tclass->vtable && tclass->vtable->object && tclass->vtable->owner == tclass) { - cabi_pathroot.next = NULL; - cabi_pathroot.type = TYPE(tclass); - cabi_pathcur = &cabi_pathroot; - trans_vtboffsets = NULL; - scan = CABI_InitVTablePtrs(scan, tclass->vtable->object, tclass, tclass, 0, 0); - } - - if (!tclass->sominfo && (tclass->flags & CLASS_FLAGS_8000)) - CABI_InitVBaseCtorOffsets(scan, tclass); - - scan = stmt; - while (scan->next) - scan = scan->next; - - scan = CFunc_InsertStatement(ST_LABEL, scan); - scan->label = label; - scan->dobjstack = NULL; - label->stmt = scan; - - if (flag23 && !(tclass->flags & CLASS_HANDLEOBJECT)) - scan = CABI_DestroyMembers(scan, tclass->ivars, tclass); - - if (flag25 && tclass->bases) - scan = CABI_DestroyBases(scan, tclass->bases); - - if (flag24 && (tclass->flags & CLASS_HAS_VBASES)) { - label3 = newlabel(); - scan = CFunc_InsertStatement(ST_IFNGOTO, scan); - scan->expr = CABI_MakeVArgExpr(); - scan->label = label3; - - scan = CABI_DestroyVBases(scan, tclass->vbases); - - scan = CFunc_InsertStatement(ST_LABEL, scan); - scan->label = label3; - label3->stmt = scan; - } - - if (flag29) { - scan = CFunc_InsertStatement(ST_IFGOTO, scan); - scan->expr = CExpr_New_ELESSEQU_Node(CABI_MakeVArgExpr(), intconstnode(TYPE(&stsignedshort), 0)); - scan->label = label2; - - scan = CFunc_InsertStatement(ST_EXPRESSION, scan); - dealloc = CParser_FindDeallocationObject(TYPE(tclass), NULL, 0, 0, &deallocFlag); - if (deallocFlag) { - scan->expr = funccallexpr( - dealloc, - CABI_MakeThisExpr(NULL, 0), - intconstnode(CABI_GetSizeTType(), tclass->size), - NULL, - NULL); - } else { - scan->expr = funccallexpr(dealloc, CABI_MakeThisExpr(NULL, 0), NULL, NULL, NULL); - } - - scan = CFunc_InsertStatement(ST_LABEL, scan); - scan->label = label2; - label2->stmt = scan; - } - - scan = CFunc_InsertStatement(ST_RETURN, scan); - if (tclass->sominfo) - scan->expr = NULL; - else - scan->expr = CABI_MakeThisExpr(NULL, 0); -} - -void CABI_MakeDefaultDestructor(TypeClass *tclass, Object *func) { - Boolean saveDebugInfo; - CScopeSave savedScope; - Statement firstStmt; - Statement returnStmt; - - if (anyerrors || func->access == ACCESSNONE) - return; - - CABI_ApplyClassFlags(func, tclass->eflags, 0); - - CScope_SetFunctionScope(func, &savedScope); - - CFunc_FuncGenSetup(&firstStmt, func); - - saveDebugInfo = copts.filesyminfo; - copts.filesyminfo = 0; - - CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); - - firstStmt.next = &returnStmt; - - memclrw(&returnStmt, sizeof(Statement)); - returnStmt.type = ST_RETURN; - - CFunc_CodeCleanup(&firstStmt); - - CABI_TransDestructor(func, func, &firstStmt, tclass, CABIDestroy0); - - CFunc_Gen(&firstStmt, func, 0); - - CScope_RestoreScope(&savedScope); - copts.filesyminfo = saveDebugInfo; -} - -static void CABI_CreateLayeredDestructor(TypeClass *tclass, Object *obj1, Object *func, CABIDestroyMode mode) { - Boolean saveDebugInfo; - CScopeSave savedScope; - Statement firstStmt; - Statement returnStmt; - - CError_FATAL(2524); - - CScope_SetFunctionScope(func, &savedScope); - - CFunc_FuncGenSetup(&firstStmt, func); - - saveDebugInfo = copts.filesyminfo; - copts.filesyminfo = 0; - - CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); - - firstStmt.next = &returnStmt; - - memclrw(&returnStmt, sizeof(Statement)); - returnStmt.type = ST_RETURN; - - CFunc_CodeCleanup(&firstStmt); - - CABI_TransDestructor(obj1, func, &firstStmt, tclass, mode); - - CFunc_Gen(&firstStmt, func, 0); - - CScope_RestoreScope(&savedScope); - copts.filesyminfo = saveDebugInfo; -} - -void CABI_MakeLayeredDestructor(TypeClass *tclass, Object *func) { - Object *dtor; - CABIDestroyMode mode; - - CError_FATAL(2557); - - if (anyerrors || func->access == ACCESSNONE) - return; - - if ((dtor = CClass_Destructor(tclass))) { - if (CABI_GetDestructorObject(dtor, CABIDestroy0) == func) - mode = CABIDestroy0; - else if (CABI_GetDestructorObject(dtor, CABIDestroy2) == func) - mode = CABIDestroy2; - else if (CABI_GetDestructorObject(dtor, CABIDestroy3) == func) - mode = CABIDestroy3; - else if (CABI_GetDestructorObject(dtor, CABIDestroy1) == func) - mode = CABIDestroy1; - else - CError_FATAL(2567); - } - - CABI_CreateLayeredDestructor(tclass, dtor, func, mode); -} - -Object *CABI_GetDestructorObject(Object *obj, CABIDestroyMode mode) { - return obj; -} - -static void CABI_AddLayeredDestructor(TypeClass *tclass, Object *dtor, HashNameNode *name, Boolean is_virtual) { - Object *func; - - CError_FATAL(2667); - - func = CParser_NewFunctionObject(NULL); - func->nspace = dtor->nspace; - func->name = name; - func->type = TYPE(CDecl_MakeDefaultDtorType(tclass, is_virtual)); - func->qual = Q_20000 | Q_MANGLE_NAME; - func->qual |= Q_INLINE; - CABI_ApplyClassFlags(func, tclass->eflags, 1); - - CError_ASSERT(2678, IS_TYPE_FUNC(func->type)); - TYPE_FUNC(func->type)->flags |= FUNC_AUTO_GENERATED; - - if (dtor->datatype == DVFUNC) { - func->datatype = DVFUNC; - CMangler_GetLinkName(func); - func->datatype = DFUNC; - } - - CScope_AddObject(func->nspace, func->name, OBJ_BASE(func)); -} - -void CABI_AddLayeredDestructors(TypeClass *tclass) { - Object *dtor; - - CError_FATAL(2707); - - if ((dtor = CClass_Destructor(tclass))) { - CABI_AddLayeredDestructor(tclass, dtor, CMangler_DeleteDtorName(), 1); - CABI_AddLayeredDestructor(tclass, dtor, CMangler_SDeleteDtorName(), 1); - if (tclass->vbases) - CABI_AddLayeredDestructor(tclass, dtor, CMangler_VBaseDtorName(), 0); - } -} - -ENode *CABI_DestroyObject(Object *dtor, ENode *objexpr, CABIDestroyMode mode, Boolean flag1, Boolean flag2) { - ENode *expr; - short arg; - ENodeList *list; - - switch (mode) { - case CABIDestroy2: - case CABIDestroy3: - if (flag2) - arg = 1; - else - arg = -1; - break; - case CABIDestroy1: - arg = -1; - break; - case CABIDestroy0: - arg = 0; - break; - default: - CError_FATAL(2786); - } - - expr = lalloc(sizeof(ENode)); - expr->type = EFUNCCALL; - expr->cost = 200; - expr->flags = 0; - expr->rtype = &stvoid; - expr->data.funccall.funcref = create_objectrefnode(dtor); - if (flag1) - expr->data.funccall.funcref->flags = expr->data.funccall.funcref->flags | ENODE_FLAG_80; - expr->data.funccall.functype = TYPE_FUNC(dtor->type); - dtor->flags = dtor->flags | OBJECT_USED; - - list = lalloc(sizeof(ENodeList)); - list->node = objexpr; - expr->data.funccall.args = list; - - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->next = NULL; - list->node = intconstnode(TYPE(&stsignedshort), arg); - - return expr; -} diff --git a/compiler_and_linker/unsorted/CBrowse.c b/compiler_and_linker/unsorted/CBrowse.c deleted file mode 100644 index 12ea4c8..0000000 --- a/compiler_and_linker/unsorted/CBrowse.c +++ /dev/null @@ -1,737 +0,0 @@ -#include "compiler/CBrowse.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CMangler.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CompilerTools.h" -#include "compiler/Unmangle.h" -#include "compiler/objects.h" -#include "compiler/templates.h" -#include "cos.h" -#include "plugin.h" - -Boolean gUseTokenStreamSource; -Boolean gForceSourceLoc; -Boolean gUseNameTable; -static GList gBrowseData; -static GList gClassData; -static GList gMemberFuncList; -static int gNextMemberFuncID; - -enum ELanguage { - langUnknown, - langC, - langCPlus, - langPascal, - langObjectPascal, - langJava, - langAssembler, - langFortran, - langRez -}; - -enum EBrowserItem { - browseFunction, - browseGlobal, - browseClass, - browseMacro, - browseEnum, - browseTypedef, - browseConstant, - browseTemplate, - browsePackage, - browseCompSymbolStart = 0x70, - browseEnd = 0xFF -}; - -enum { - kAbstract = 1, - kStatic = 2, - kFinal = 4, - kMember = 8, - - kInterface = 0x80, - kPublic = 0x100, - - kInline = 0x80, - kPascal = 0x100, - kAsm = 0x200, - kVirtual = 0x400, - kCtor = 0x800, - kDtor = 0x1000, - kNative = 0x2000, - kSynch = 0x4000, - kIntrinsic = 0x8000, - kConst = 0x10000, - - kTransient = 0x80, - kVolatile = 0x100 -}; - -enum EAccess { - accessNone = 0, - accessPrivate = 1, - accessProtected = 2, - accessPublic = 4 -}; - -enum EMember { - memberFunction, - memberData, - memberEnd = 0xFF -}; - -enum ETemplateType { - templateClass, - templateFunction -}; - -static enum EAccess gFromAccessType[] = { - accessPublic, - accessPrivate, - accessProtected, - accessNone -}; - -typedef struct BrowseHeader { - SInt32 browse_header; - SInt32 browse_version; - SInt16 browse_language; - SInt16 uses_name_table; - SInt32 earliest_compatible_version; - SInt32 reserved[15]; -} BrowseHeader; - -// forward decls -static void RecordUndefinedMemberFunctions(void); - -void CBrowse_Setup(CompilerLinkerParamBlk *params) { - BrowseHeader hdr; - - CError_ASSERT(123, params != NULL); - - params->object.browsedata = NULL; - - InitGList(&gBrowseData, 0x10000); - InitGList(&gMemberFuncList, 1024); - - gNextMemberFuncID = 1; - gForceSourceLoc = 0; - gUseNameTable = 0; - - memclrw(&hdr, sizeof(hdr)); - hdr.browse_header = 0xBEABBAEB; - hdr.browse_version = 2; - hdr.earliest_compatible_version = 2; - hdr.browse_language = copts.cplusplus ? langCPlus : langC; - hdr.uses_name_table = gUseNameTable; - - AppendGListData(&gBrowseData, &hdr, sizeof(hdr)); -} - -void CBrowse_Finish(CompilerLinkerParamBlk *params) { - CWMemHandle hnd; - - CError_ASSERT(151, params != NULL); - - if (gBrowseData.size >= sizeof(BrowseHeader)) { - RecordUndefinedMemberFunctions(); - AppendGListByte(&gBrowseData, -1); - - COS_ResizeHandle(gBrowseData.data, gBrowseData.size); - - if (CWSecretAttachHandle(params->context, gBrowseData.data, &hnd) == cwNoErr) { - params->object.browsedata = hnd; - gBrowseData.data = NULL; - } - } -} - -void CBrowse_Cleanup(CompilerLinkerParamBlk *params) { - FreeGList(&gBrowseData); - FreeGList(&gClassData); - FreeGList(&gMemberFuncList); -} - -static void AppendGList(GList *dst, GList *src) { - SInt32 offset = dst->size; - - AppendGListNoData(dst, src->size); - memcpy(*dst->data + offset, *src->data, src->size); -} - -static void RecordName(GList *gl, const char *str, SInt32 id) { - HashNameNode *name; - - CError_ASSERT(190, gl && str && *str); - - if (id < 0 && gUseNameTable) { - for (name = name_hash_nodes[CHash(str)]; name; name = name->next) { - if (!strcmp(str, name->name)) { - id = name->id; - break; - } - } - } - - if (id >= 0 && gUseNameTable) { - AppendGListWord(gl, -1); - AppendGListLong(gl, id); - } else { - int len = strlen(str); - AppendGListWord(gl, len); - if (len) - AppendGListData(gl, str, len + 1); - } -} - -void CBrowse_BeginClass(DeclInfo *di, GList *gl) { - char *buf; - ClassList *base; - SInt32 i; - TypeClass *tclass; - - CError_ASSERT(227, di && di->thetype && gl); - - *gl = gClassData; - - if ( - !di->file || - !di->file->fileID || - !di->file->recordbrowseinfo || - !di->file2 || - !di->file2->fileID || - di->sourceoffset <= 0 - ) - { - memclrw(&gClassData, sizeof(gClassData)); - return; - } - - if (IsTempName(TYPE_CLASS(di->thetype)->classname)) { - memclrw(&gClassData, sizeof(gClassData)); - return; - } - - InitGList(&gClassData, 0x4000); - AppendGListByte(&gClassData, browseClass); - AppendGListWord(&gClassData, di->file->fileID); - AppendGListWord(&gClassData, di->file2->fileID); - AppendGListLong(&gClassData, di->sourceoffset - 1); - CError_ASSERT(270, gClassData.size == 9); - AppendGListLong(&gClassData, di->sourceoffset - 1); - AppendGListLong(&gClassData, 0); - RecordName(&gClassData, TYPE_CLASS(di->thetype)->classname->name, TYPE_CLASS(di->thetype)->classname->id); - - CMangler_MangleType(di->thetype, 0); - AppendGListByte(&name_mangle_list, 0); - - buf = lalloc(name_mangle_list.size + 1); - strcpy(buf, *name_mangle_list.data); - - while (*buf && *buf >= '0' && *buf <= '9') - buf++; - - if (strcmp(TYPE_CLASS(di->thetype)->classname->name, buf)) - RecordName(&gClassData, buf, -1); - else - AppendGListWord(&gClassData, 0); - - AppendGListLong(&gClassData, 0); - - i = 0; - base = TYPE_CLASS(di->thetype)->bases; - while (base) { - base = base->next; - i++; - } - - AppendGListByte(&gClassData, i); - - for (base = TYPE_CLASS(di->thetype)->bases; base; base = base->next) { - AppendGListByte(&gClassData, gFromAccessType[base->access]); - AppendGListByte(&gClassData, base->is_virtual); - - tclass = base->base; - if ((tclass->flags & CLASS_IS_TEMPL_INST) && !TEMPL_CLASS_INST(tclass)->is_specialized) - tclass = TYPE_CLASS(TEMPL_CLASS_INST(tclass)->templ); - - CMangler_MangleType(TYPE(tclass), 0); - AppendGListByte(&name_mangle_list, 0); - - buf = lalloc(name_mangle_list.size + 1); - strcpy(buf, *name_mangle_list.data); - - while (*buf && *buf >= '0' && *buf <= '9') - buf++; - - i = base->base->classname->id; - while (*buf && *buf >= '0' && *buf <= '9') { - i = -1; - buf++; - } - - RecordName(&gClassData, buf, i); - } -} - -void CBrowse_AddClassMemberVar(ObjMemberVar *ivar, SInt32 startOffset, SInt32 endOffset) { - short len; - - CError_ASSERT(360, ivar); - - if (gClassData.data && startOffset > 0 && endOffset >= startOffset) { - if (tk == ';') - endOffset++; - - AppendGListByte(&gClassData, memberData); - AppendGListByte(&gClassData, gFromAccessType[ivar->access]); - AppendGListLong(&gClassData, 0); - AppendGListLong(&gClassData, startOffset - 1); - AppendGListLong(&gClassData, endOffset - 1); - - len = strlen(ivar->name->name); - AppendGListWord(&gClassData, len); - AppendGListData(&gClassData, ivar->name->name, len + 1); - } -} - -void CBrowse_AddClassMemberFunction(Object *object, SInt32 startOffset, SInt32 endOffset) { - SInt32 flags; - SInt32 id; - TypeMemberFunc *tfunc; - - CError_ASSERT(380, object); - - if ( - !IsTempName(object->name) && - gClassData.data && - startOffset > 0 && - endOffset >= startOffset - ) - { - flags = 0; - CError_ASSERT(391, object->type && IS_TYPE_FUNC(object->type)); - tfunc = TYPE_METHOD(object->type); - - if (tfunc->flags & FUNC_AUTO_GENERATED) - return; - - if (object->datatype == DVFUNC) - flags |= kVirtual; - if (tfunc->flags & FUNC_PURE) - flags |= kAbstract; - if (tfunc->is_static) - flags |= kStatic; - if (tfunc->flags & FUNC_IS_CTOR) - flags |= kCtor; - if (tfunc->flags & FUNC_IS_DTOR) - flags |= kDtor; - - AppendGListByte(&gClassData, memberFunction); - AppendGListByte(&gClassData, gFromAccessType[object->access]); - AppendGListLong(&gClassData, flags); - - id = tfunc->funcid; - if (id <= 0) { - // TODO: this is not 64-bit safe - if (!(tfunc->flags & FUNC_DEFINED) || id == -1) - AppendGListLong(&gMemberFuncList, (SInt32) object); - tfunc->funcid = id = gNextMemberFuncID++; - } - - AppendGListLong(&gClassData, id); - AppendGListLong(&gClassData, startOffset - 1); - AppendGListLong(&gClassData, endOffset); - } -} - -void CBrowse_AddClassMemberData(Object *object, SInt32 startOffset, SInt32 endOffset) { - short len; - - CError_ASSERT(435, object); - - if (gClassData.data && startOffset > 0 && endOffset >= startOffset && object->datatype == DDATA) { - if (tk == ';') - endOffset++; - - AppendGListByte(&gClassData, memberData); - AppendGListByte(&gClassData, gFromAccessType[object->access]); - AppendGListLong(&gClassData, kStatic); - AppendGListLong(&gClassData, startOffset - 1); - AppendGListLong(&gClassData, endOffset - 1); - - len = strlen(object->name->name); - AppendGListWord(&gClassData, len); - AppendGListData(&gClassData, object->name->name, len + 1); - } -} - -void CBrowse_EndClass(SInt32 offset, GList *gl) { - CError_ASSERT(453, gl); - - if (gClassData.data) { - if (gClassData.size > 0) { - if (tk == ';') - offset++; - memcpy(*gClassData.data + 9, &offset, 4); - AppendGList(&gBrowseData, &gClassData); - AppendGListByte(&gBrowseData, memberEnd); - } - FreeGList(&gClassData); - } - - gClassData = *gl; -} - -void CBrowse_BeginStruct(DeclInfo *di, TypeStruct *tstruct, GList *gl) { - HashNameNode *name; - - CError_ASSERT(480, di && gl); - - *gl = gClassData; - - if ( - !di->file || - !di->file->fileID || - !di->file->recordbrowseinfo || - !di->file2 || - !di->file2->fileID || - di->sourceoffset <= 0 - ) - { - memclrw(&gClassData, sizeof(gClassData)); - return; - } - - name = tstruct->name; - if (!name || IsTempName(name)) { - memclrw(&gClassData, sizeof(gClassData)); - return; - } - - InitGList(&gClassData, 0x4000); - AppendGListByte(&gClassData, browseClass); - AppendGListWord(&gClassData, di->file->fileID); - AppendGListWord(&gClassData, di->file2->fileID); - AppendGListLong(&gClassData, di->sourceoffset - 1); - CError_ASSERT(521, gClassData.size == 9); - AppendGListLong(&gClassData, di->sourceoffset - 1); - AppendGListLong(&gClassData, 0); - RecordName(&gClassData, name->name, name->id); - AppendGListWord(&gClassData, 0); - AppendGListLong(&gClassData, 0); - AppendGListByte(&gClassData, 0); -} - -void CBrowse_AddStructMember(StructMember *member, SInt32 startOffset, SInt32 endOffset) { - short len; - - if (tk == ';') - endOffset++; - - if (gClassData.data && member && startOffset > 0 && endOffset >= startOffset) { - AppendGListByte(&gClassData, memberData); - AppendGListByte(&gClassData, accessPublic); - AppendGListLong(&gClassData, 0); - AppendGListLong(&gClassData, startOffset - 1); - AppendGListLong(&gClassData, endOffset - 1); - - len = strlen(member->name->name); - AppendGListWord(&gClassData, len); - AppendGListData(&gClassData, member->name->name, len + 1); - } -} - -void CBrowse_EndStruct(SInt32 offset, GList *gl) { - CError_ASSERT(558, gl); - - if (gClassData.data) { - if (offset > 0 && gClassData.size > 0) { - memcpy(*gClassData.data + 9, &offset, 4); - AppendGList(&gBrowseData, &gClassData); - AppendGListByte(&gBrowseData, memberEnd); - } - FreeGList(&gClassData); - } - - gClassData = *gl; -} - -static void EmitStandardData(int item, int fileID1, int fileID2, SInt32 startOffset, SInt32 endOffset, const char *str, SInt32 id, const char *str2, SInt32 id2) { - CError_ASSERT(584, str); - - AppendGListByte(&gBrowseData, item); - AppendGListWord(&gBrowseData, fileID1); - AppendGListWord(&gBrowseData, fileID2); - AppendGListLong(&gBrowseData, startOffset - 1); - AppendGListLong(&gBrowseData, endOffset - 1); - AppendGListLong(&gBrowseData, 0); - - RecordName(&gBrowseData, str, id); - if (str2 && str2 != str) - RecordName(&gBrowseData, str2, id2); - else - AppendGListWord(&gBrowseData, 0); -} - -void CBrowse_NewTypedef(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { - CError_ASSERT(618, file1 && file1->recordbrowseinfo); - - if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) { - EmitStandardData(browseTypedef, - file1->fileID, file2->fileID, - startOffset, endOffset, - name->name, name->id, - CError_GetQualifiedName(nspace, name), -1); - } -} - -void CBrowse_NewEnum(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { - CError_ASSERT(632, file1 && file1->recordbrowseinfo); - - if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) { - EmitStandardData(browseEnum, - file1->fileID, file2->fileID, - startOffset, endOffset, - name->name, name->id, - CError_GetQualifiedName(nspace, name), -1); - } -} - -void CBrowse_NewEnumConstant(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { - CError_ASSERT(646, file1 && file1->recordbrowseinfo); - - if (tk == ',') - endOffset++; - - if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) { - EmitStandardData(browseConstant, - file1->fileID, file2->fileID, - startOffset, endOffset, - name->name, name->id, - CError_GetQualifiedName(nspace, name), -1); - } -} - -static HashNameNode *CBrowse_GetLinkName(Object *object) { - return CMangler_GetLinkName(object); -} - -static void RecordFunction(Object *object, int fileID1, int fileID2, SInt32 startOffset, SInt32 endOffset) { - TypeFunc *tfunc; - char *tmp; - Boolean flag; - char *str29; - HashNameNode *linkname; - SInt32 flags; - char *namestr; - SInt32 nameid; - char *namestr2; - SInt32 nameid2; - int funcid; - char buf[2048]; - char buf2[256]; - - CError_ASSERT(740, object->type && IS_TYPE_FUNC(object->type)); - - if (IsTempName(object->name)) - return; - - tfunc = TYPE_FUNC(object->type); - if ((tfunc->flags & (FUNC_AUTO_GENERATED | FUNC_INTRINSIC)) && (!fileID2 || startOffset < 0)) - return; - - linkname = object->name; - tmp = linkname->name; - if (!(linkname->name[0] == '_' && linkname->name[1] == '_')) { - namestr = tmp; - nameid = linkname->id; - switch (tmp[0]) { - case '.': - nameid = -1; - namestr += 1; - break; - case '_': - switch (tmp[1]) { - case '#': - case '%': - case '@': - nameid = -1; - namestr += 2; - break; - } - break; - } - } else { - flag = 1; - if (tfunc->flags & (FUNC_IS_CTOR | FUNC_IS_DTOR)) { - tmp = TYPE_METHOD(tfunc)->theclass->classname->name; - while (*tmp >= '0' && *tmp <= '9') - tmp++; - MWUnmangleClassName(tmp, buf, sizeof(buf)); - - str29 = buf; - if ((tmp = strrchr(str29, ':'))) - str29 = tmp + 1; - - if (tfunc->flags & FUNC_IS_DTOR) { - buf2[0] = '~'; - strncpy(&buf2[1], str29, sizeof(buf2) - 1); - namestr = buf2; - } else { - namestr = str29; - } - - flag = 0; - } - - if (flag) { - MWUnmangle(object->name->name, buf, sizeof(buf)); - namestr = buf; - } - - nameid = -1; - } - - while (*namestr >= '0' && *namestr <= '9') { - nameid = -1; - namestr++; - } - - namestr2 = NULL; - nameid2 = -1; - - linkname = CBrowse_GetLinkName(object); - if (object->name != linkname) { - namestr2 = linkname->name; - if (linkname->name[0] == '.') - namestr2++; - else - nameid2 = linkname->id; - } - - EmitStandardData(browseFunction, fileID1, fileID2, startOffset, endOffset, namestr, nameid, namestr2, nameid2); - - flags = 0; - if (object->qual & Q_INLINE) - flags |= kInline; - if (object->qual & Q_PASCAL) - flags |= kPascal; - if (object->qual & Q_ASM) - flags |= kAsm; - if (object->sclass == TK_STATIC) - flags |= kStatic; - if (tfunc->flags & FUNC_METHOD) - flags |= kMember; - AppendGListLong(&gBrowseData, flags); - - funcid = 0; - if (tfunc->flags & FUNC_METHOD) { - funcid = TYPE_METHOD(tfunc)->funcid; - if (funcid <= 0) { - TYPE_METHOD(tfunc)->funcid = funcid = gNextMemberFuncID++; - } - } - AppendGListLong(&gBrowseData, funcid); -} - -void CBrowse_NewFunction(Object *object, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { - CError_ASSERT(890, file1 && file1->recordbrowseinfo); - - if (file2 && file2->fileID && startOffset > 0 && (endOffset + 1) >= startOffset) - RecordFunction(object, file1->fileID, file2->fileID, startOffset, endOffset + 1); -} - -void CBrowse_NewData(Object *object, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { - char *namestr = NULL; - SInt32 flags = 0; - Boolean is_const = is_const_object(object); - - CError_ASSERT(912, file1 && file1->recordbrowseinfo); - CError_ASSERT(913, object); - - if (tk == ';') - endOffset++; - - if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) { - HashNameNode *name = CBrowse_GetLinkName(object); - if (object->name != name) - namestr = name->name; - - EmitStandardData( - is_const ? browseConstant : browseGlobal, - file1->fileID, file2->fileID, - startOffset, endOffset, - object->name->name, object->name->id, - namestr, name->id - ); - - if (!is_const) { - if (object->sclass == TK_STATIC) - flags |= kStatic; - AppendGListLong(&gBrowseData, flags); - } - } -} - -void CBrowse_NewMacro(Macro *macro, CPrepFileInfo *file, SInt32 startOffset, SInt32 endOffset) { - CError_ASSERT(951, !file || (file->recordbrowseinfo && !macro->is_special)); - - if (file && file->fileID && startOffset > 0 && endOffset >= startOffset) - EmitStandardData( - browseMacro, - file->fileID, file->fileID, - startOffset, endOffset, - macro->name->name, macro->name->id, - NULL, -1 - ); -} - -void CBrowse_NewTemplateClass(TemplClass *tmclass, CPrepFileInfo *file, SInt32 startOffset, SInt32 endOffset) { - CError_ASSERT(965, !file || file->recordbrowseinfo); - - if (file && file->fileID && startOffset > 0 && endOffset >= startOffset) { - EmitStandardData( - browseTemplate, - file->fileID, file->fileID, - startOffset, endOffset, - tmclass->theclass.classname->name, tmclass->theclass.classname->id, - NULL, -1 - ); - AppendGListByte(&gBrowseData, templateClass); - } -} - -void CBrowse_NewTemplateFunc(TemplateFunction *tmfunc) { - CError_ASSERT(979, !tmfunc->srcfile || tmfunc->srcfile->recordbrowseinfo); - - if (tmfunc->srcfile && tmfunc->srcfile->fileID && tmfunc->startoffset > 0 && tmfunc->endoffset >= tmfunc->startoffset) { - EmitStandardData( - browseTemplate, - tmfunc->srcfile->fileID, tmfunc->srcfile->fileID, - tmfunc->startoffset, tmfunc->endoffset, - tmfunc->name->name, tmfunc->name->id, - NULL, -1 - ); - AppendGListByte(&gBrowseData, templateFunction); - } -} - -static void RecordUndefinedMemberFunctions(void) { - int i; - int count; - Object **array; - - COS_LockHandleHi(gMemberFuncList.data); - - count = gMemberFuncList.size / sizeof(Object *); - array = (Object **) *gMemberFuncList.data; - for (i = 0; i < count; i++, array++) { - if (IS_TYPE_FUNC((*array)->type) && !(TYPE_FUNC((*array)->type)->flags & FUNC_DEFINED)) - RecordFunction(*array, 0, 0, -1, -1); - } - - COS_UnlockHandle(gMemberFuncList.data); -} diff --git a/compiler_and_linker/unsorted/CClass.c b/compiler_and_linker/unsorted/CClass.c deleted file mode 100644 index fad276e..0000000 --- a/compiler_and_linker/unsorted/CClass.c +++ /dev/null @@ -1,2312 +0,0 @@ -#include "compiler/CClass.h" -#include "compiler/CABI.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CInit.h" -#include "compiler/CInline.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CObjC.h" -#include "compiler/CParser.h" -#include "compiler/CRTTI.h" -#include "compiler/CSOM.h" -#include "compiler/CompilerTools.h" -#include "compiler/CodeGen.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct OVClassBase { - struct OVClassBase *next; - struct OVClass *ovclass; - Boolean is_virtual; -} OVClassBase; - -typedef struct OVFunc { - struct OVFunc *next; - Object *obj; - struct OVClass *ovc8; - struct OVFunc *ovfC; - struct OVFunc *ovf10; -} OVFunc; - -typedef struct OVClass { - TypeClass *tclass; - OVFunc *vfuncs; - OVClassBase *bases; - SInt32 offset; - SInt32 voffset; - Boolean alloced_vtable; -} OVClass; - -typedef struct ThunkList { - struct ThunkList *next; - Object *thunkobj; - Object *obj; - SInt32 a; - SInt32 b; - SInt32 c; -} ThunkList; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static TypeClass *main_class; -static ThunkList *cclass_thunklist; -static TypeClass *cclass_isbase_mostderived; -static SInt32 cclass_isbase_foundoffset; -static Boolean cclass_isambigbase; -static short cclass_founddepth; -static char *vtable_object_data; -static SInt32 vtable_data_size; -static OLinkList *vtable_object_links; -static TypeClass *cclass_vbase; -static OVClass *cclass_ovbase; -static OVClass *cclass_root; -static Object *found_pure; -static Boolean check_pures; -static Object *cclass_dominator_vobject; -static SInt32 cclass_dominator_voffset; -static Object *cclass_dominator_oobject; -static TypeClass *cclass_dominator_oclass; -static SInt32 cclass_dominator_ooffset; -static Object *cclass_dominator_eobject; - -void CClass_Init(void) { - cclass_thunklist = NULL; -} - -void CClass_GenThunks(void) { - ThunkList *list; - - for (list = cclass_thunklist; list; list = list->next) { - list->thunkobj->flags |= OBJECT_DEFINED; - CodeGen_GenVDispatchThunk(list->thunkobj, list->obj, list->a, list->b, list->c); - } -} - -static Object *CClass_ThunkObject(Object *obj, SInt32 a, SInt32 b, SInt32 c) { - Object *thunkobj; - ThunkList *list; - - CInline_ObjectAddrRef(obj); - for (list = cclass_thunklist; list; list = list->next) { - if (obj == list->obj && a == list->a && b == list->b && c == list->c) - return list->thunkobj; - } - - thunkobj = CParser_NewCompilerDefFunctionObject(); - thunkobj->name = CMangler_ThunkName(obj, a, b, c); - thunkobj->type = TYPE(&rt_func); - thunkobj->sclass = TK_EXTERN; - thunkobj->qual = Q_20000; - thunkobj->u.func.linkname = thunkobj->name; - - list = galloc(sizeof(ThunkList)); - list->thunkobj = thunkobj; - list->obj = obj; - list->a = a; - list->b = b; - list->c = c; - list->next = cclass_thunklist; - cclass_thunklist = list; - - return thunkobj; -} - -static Boolean CClass_IsZeroOffsetClass(TypeClass *a, TypeClass *b) { - while (1) { - if (a == b) - return 1; - - if (!a->bases || a->bases->is_virtual) - return 0; - - a = a->bases->base; - } -} - -static UInt8 CClass_IsCovariantResult(Type *a, UInt32 qualA, Type *b, UInt32 qualB, Boolean errorflag) { - TypeClass *tclassA; - TypeClass *tclassB; - - if ( - IS_TYPE_POINTER_ONLY(a) && - IS_TYPE_POINTER_ONLY(b) && - TPTR_QUAL(a) == TPTR_QUAL(b) && - !CParser_IsMoreCVQualified(qualB, qualA) && - IS_TYPE_CLASS(TPTR_TARGET(a)) && - IS_TYPE_CLASS(TPTR_TARGET(b)) - ) - { - tclassA = TYPE_CLASS(TPTR_TARGET(a)); - tclassB = TYPE_CLASS(TPTR_TARGET(b)); - if (tclassA == tclassB || CClass_IsBaseClass(tclassB, tclassA, NULL, errorflag, errorflag)) { - if (!CClass_IsZeroOffsetClass(tclassB, tclassA)) - return 2; - else - return 1; - } - } - - return 0; -} - -UInt8 CClass_GetOverrideKind(TypeFunc *a, TypeFunc *b, Boolean errorflag) { - if (!a->args || !b->args) - return 0; - - if ( - (a->flags & FUNC_CALL_CONV_MASK) != (b->flags & FUNC_CALL_CONV_MASK) || - !is_arglistsame(a->args->next, b->args->next) || - a->args->qual != b->args->qual - ) - return 0; - - if (!is_typesame(a->functype, b->functype)) { - switch (CClass_IsCovariantResult(a->functype, a->qual, b->functype, b->qual, errorflag)) { - case 0: - if (errorflag) - CError_Error(CErrorStr227); - return 0; - case 1: - return 1; - case 2: - return 2; - default: - CError_FATAL(225); - } - } - - return 1; -} - -Boolean CClass_IsEmpty(TypeClass *tclass) { - ClassList *base; - - if (tclass->ivars) - return 0; - - for (base = tclass->bases; base; base = base->next) { - if (!CClass_IsEmpty(base->base)) - return 0; - } - - return 1; -} - -Boolean CClass_IsNonStaticMemberFunc(TypeFunc *tfunc) { - return IS_TYPEFUNC_NONSTATIC_METHOD(tfunc) || (tfunc->flags & FUNC_FLAGS_80); -} - -Object *CClass_DefaultConstructor(TypeClass *tclass) { - NameSpaceObjectList *nsol; - Object *object; - - for (nsol = CScope_FindName(tclass->nspace, constructor_name_node); nsol; nsol = nsol->next) { - object = OBJECT(nsol->object); - if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type)) { - if ((tclass->flags & CLASS_HAS_VBASES) && !tclass->sominfo) { - if (TYPE_FUNC(object->type)->args->next && !TYPE_FUNC(object->type)->args->next->next) - return object; - } else { - if (!TYPE_FUNC(object->type)->args->next) - return object; - } - } - } - - return NULL; -} - -Object *CClass_DummyDefaultConstructor(TypeClass *tclass) { - Object *ctor; - FuncArg *args; - NameSpaceObjectList *nsol; - HashNameNode *name; - TypeMemberFunc *tmethod; - Object *object; - ObjectList list; - - ctor = NULL; - - for (nsol = CScope_FindName(tclass->nspace, constructor_name_node); nsol; nsol = nsol->next) { - object = OBJECT(nsol->object); - if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type)) { - CError_ASSERT(305, args = TYPE_FUNC(object->type)->args); - args = args->next; - if ((tclass->flags & CLASS_HAS_VBASES) && !tclass->sominfo) { - CError_ASSERT(309, args); - args = args->next; - } - CError_ASSERT(312, args); - - if (args->dexpr) { - if (ctor) { - list.next = NULL; - list.object = object; - CError_OverloadedFunctionError(ctor, &list); - break; - } - ctor = object; - } - } - } - - if (!ctor) { - CError_Error(CErrorStr203); - return NULL; - } - - name = GetHashNameNodeExport("__defctor"); - if ((nsol = CScope_FindName(tclass->nspace, name))) { - CError_ASSERT(339, nsol->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(nsol->object)->type)); - return OBJECT(nsol->object); - } - - tmethod = galloc(sizeof(TypeMemberFunc)); - memclrw(tmethod, sizeof(TypeMemberFunc)); - - tmethod->type = TYPEFUNC; - tmethod->functype = TYPE(&void_ptr); - tmethod->flags = FUNC_METHOD; - tmethod->theclass = tclass; - CDecl_SetFuncFlags(TYPE_FUNC(tmethod), 0); - - if ((tclass->flags & CLASS_HAS_VBASES) && !tclass->sominfo) - CDecl_AddArgument(TYPE_FUNC(tmethod), TYPE(&stsignedshort)); - - CDecl_AddThisPointerArgument(TYPE_FUNC(tmethod), tclass); - - object = CParser_NewCompilerDefFunctionObject(); - object->type = TYPE(tmethod); - object->qual = Q_INLINE | Q_MANGLE_NAME; - object->nspace = tclass->nspace; - object->name = name; - - CScope_AddObject(tclass->nspace, name, OBJ_BASE(object)); - CParser_RegisterDummyCtorFunction(object, ctor); - return object; -} - -ENode *CClass_DefaultConstructorCall(TypeClass *tclass, TypeClass *b, ENode *objexpr, SInt32 varg, Boolean flag1, Boolean flag2, Boolean *errorflag) { - NameSpaceObjectList *nsol; - Object *ctor; - Object *object; - FuncArg *args; - ENodeList *argexprs; - ENode *expr; - BClassList *path; - BClassList list1; - ObjectList objlist; - BClassList list2; - short founddepth; - Boolean isambigbase; - - *errorflag = 0; - - if (!(nsol = CScope_FindName(tclass->nspace, constructor_name_node))) - return NULL; - - ctor = NULL; - do { - object = OBJECT(nsol->object); - if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type)) { - CError_ASSERT(397, args = TYPE_FUNC(object->type)->args); - - args = args->next; - - if ((tclass->flags & CLASS_HAS_VBASES) && !tclass->sominfo) { - CError_ASSERT(401, args); - args = args->next; - } - - if (!args || args->dexpr) { - if (ctor) { - objlist.next = NULL; - objlist.object = object; - CError_OverloadedFunctionError(ctor, &objlist); - break; - } - ctor = object; - } - } - } while ((nsol = nsol->next)); - - if (!ctor) { - *errorflag = 1; - return NULL; - } - - if (flag1) { - if (b) { - if (flag2) { - if ((path = CClass_GetBasePath(b, tclass, &founddepth, &isambigbase))) - list1 = *path; - else - goto skipCheck; - } else { - list1.next = &list2; - list1.type = TYPE(b); - list2.next = NULL; - list2.type = TYPE(tclass); - } - } else { - list1.next = NULL; - list1.type = TYPE(tclass); - } - CClass_CheckPathAccess(&list1, ctor, ctor->access); - } - -skipCheck: - if ((tclass->flags & CLASS_HAS_VBASES) && !tclass->sominfo) { - argexprs = lalloc(sizeof(ENodeList)); - argexprs->next = NULL; - argexprs->node = intconstnode(TYPE(&stsignedshort), varg); - } else { - argexprs = NULL; - } - - CError_ASSERT(471, IS_TYPE_POINTER_ONLY(objexpr->rtype)); - - objexpr = makemonadicnode(objexpr, EINDIRECT); - objexpr->rtype = TYPE(tclass); - - list1.next = NULL; - list1.type = TYPE(tclass); - - expr = CExpr_GenericFuncCall( - &list1, - objexpr, - 0, - ctor, - NULL, - NULL, - argexprs, - 0, - 0, - 0 - ); - - if (ENODE_IS2(expr, EFUNCCALL, EFUNCCALLP)) - expr->rtype = CDecl_NewPointerType(TYPE(tclass)); - - return expr; -} - -Object *CClass_AssignmentOperator(TypeClass *tclass) { - NameSpaceObjectList *nsol; - Object *object; - - for (nsol = CScope_FindName(tclass->nspace, asop_name_node); nsol; nsol = nsol->next) { - object = OBJECT(nsol->object); - if ( - object->otype == OT_OBJECT && - IS_TYPE_FUNC(object->type) && - TYPE_FUNC(object->type)->args && - TYPE_FUNC(object->type)->args->next && - !TYPE_FUNC(object->type)->args->next->next - ) - { - if ( - IS_TYPE_CLASS(TYPE_FUNC(object->type)->args->next->type) && - TYPE_CLASS(TYPE_FUNC(object->type)->args->next->type) == tclass - ) - return object; - - if ( - IS_TYPE_REFERENCE(TYPE_FUNC(object->type)->args->next->type) && - TPTR_TARGET(TYPE_FUNC(object->type)->args->next->type) == TYPE(tclass) - ) - return object; - } - } - - return NULL; -} - -Object *CClass_CopyConstructor(TypeClass *tclass) { - NameSpaceObjectList *nsol; - Object *object; - FuncArg *args; - - if (tclass->sominfo) - return NULL; - - for (nsol = CScope_FindName(tclass->nspace, constructor_name_node); nsol; nsol = nsol->next) { - object = OBJECT(nsol->object); - if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type)) { - CError_ASSERT(532, args = TYPE_FUNC(object->type)->args); - - args = args->next; - - if (tclass->flags & CLASS_HAS_VBASES) { - CError_ASSERT(536, args); - args = args->next; - } - - if ( - args && - args != &elipsis && - (!args->next || args->next->dexpr) && - IS_TYPE_REFERENCE(args->type) && - TPTR_TARGET(args->type) == TYPE(tclass) - ) - return object; - } - } - - return NULL; -} - -NameSpaceObjectList *CClass_MemberObject(TypeClass *tclass, HashNameNode *name) { - NameSpaceObjectList *nsol; - - if ((nsol = CScope_FindName(tclass->nspace, name)) && nsol->object->otype == OT_OBJECT) - return nsol; - - return NULL; -} - -NameSpaceObjectList *CClass_Constructor(TypeClass *tclass) { - NameSpaceObjectList *nsol; - - if ( - (nsol = CScope_FindName(tclass->nspace, constructor_name_node)) && - nsol->object->otype == OT_OBJECT && - IS_TYPE_FUNC(OBJECT(nsol->object)->type) - ) - return nsol; - - return NULL; -} - -Object *CClass_Destructor(TypeClass *tclass) { - NameSpaceObjectList *nsol; - - for (nsol = CScope_FindName(tclass->nspace, destructor_name_node); nsol; nsol = nsol->next) { - if ( - nsol->object->otype == OT_OBJECT && - IS_TYPE_FUNC(OBJECT(nsol->object)->type) - ) - return OBJECT(nsol->object); - } - - return NULL; -} - -Boolean CClass_IsConstructor(Object *obj) { - return obj && IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_IS_CTOR); -} - -Boolean CClass_IsDestructor(Object *obj) { - return obj && IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_IS_DTOR); -} - -Boolean CClass_IsPODClass(TypeClass *tclass) { - NameSpaceObjectList *nsol; - Object *object; - ObjMemberVar *ivar; - Type *type; - - if (tclass->vtable || tclass->bases || CClass_Destructor(tclass)) - return 0; - - for (nsol = CClass_Constructor(tclass); nsol; nsol = nsol->next) { - if ( - nsol->object->otype == OT_OBJECT && - IS_TYPE_FUNC(OBJECT(nsol->object)->type) && - !(TYPE_FUNC(OBJECT(nsol->object)->type)->flags & FUNC_AUTO_GENERATED) - ) - return 0; - } - - object = CClass_AssignmentOperator(tclass); - if (object && !(TYPE_FUNC(object->type)->flags & FUNC_AUTO_GENERATED)) - return 0; - - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - if (ivar->access != ACCESSPUBLIC) - return 0; - - type = ivar->type; - while (IS_TYPE_ARRAY(type)) - type = TPTR_TARGET(type); - - switch (type->type) { - case TYPECLASS: - if (!CClass_IsPODClass(TYPE_CLASS(type))) - return 0; - break; - case TYPEMEMBERPOINTER: - return 0; - case TYPEPOINTER: - if (TPTR_QUAL(type) & Q_REFERENCE) - return 0; - break; - } - } - - return 1; -} - -Boolean CClass_IsTrivialCopyClass(TypeClass *tclass) { - Object *object; - ClassList *base; - ObjMemberVar *ivar; - Type *type; - - if (tclass->vtable || tclass->vbases || CClass_Destructor(tclass)) - return 0; - - object = CClass_CopyConstructor(tclass); - if (object && IS_TYPE_FUNC(object->type) && !(TYPE_FUNC(object->type)->flags & FUNC_AUTO_GENERATED)) - return 0; - - for (base = tclass->bases; base; base = base->next) { - if (!CClass_IsTrivialCopyClass(base->base)) - return 0; - } - - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - type = ivar->type; - while (IS_TYPE_ARRAY(type)) - type = TPTR_TARGET(type); - - if (IS_TYPE_CLASS(type) && !CClass_IsTrivialCopyClass(TYPE_CLASS(type))) - return 0; - } - - return 1; -} - -Boolean CClass_IsTrivialCopyAssignClass(TypeClass *tclass) { - Object *object; - ObjMemberVar *ivar; - Type *type; - - if (tclass->vtable || tclass->bases || CClass_Destructor(tclass)) - return 0; - - object = CClass_AssignmentOperator(tclass); - if (object && !(TYPE_FUNC(object->type)->flags & FUNC_AUTO_GENERATED)) - return 0; - - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - type = ivar->type; - while (IS_TYPE_ARRAY(type)) - type = TPTR_TARGET(type); - - if (IS_TYPE_REFERENCE(type)) - return 0; - if (CParser_IsConst(type, ivar->qual)) - return 0; - if (IS_TYPE_CLASS(type) && !CClass_IsTrivialCopyAssignClass(TYPE_CLASS(type))) - return 0; - } - - return 1; -} - -Boolean CClass_ReferenceArgument(TypeClass *tclass) { - if ((tclass->flags & (CLASS_COMPLETED | CLASS_IS_TEMPL_INST)) == CLASS_IS_TEMPL_INST) - CDecl_CompleteType(TYPE(tclass)); - - if (copts.simple_class_byval) - return !CClass_IsTrivialCopyClass(tclass); - - return CClass_Destructor(tclass) || CClass_CopyConstructor(tclass); -} - -BClassList *CClass_GetPathCopy(BClassList *path, Boolean is_global) { - BClassList *last; - BClassList *copy; - - if (!path) - return NULL; - - copy = last = is_global ? galloc(sizeof(BClassList)) : lalloc(sizeof(BClassList)); - last->next = path->next; - last->type = path->type; - - while ((path = path->next)) { - last->next = is_global ? galloc(sizeof(BClassList)) : lalloc(sizeof(BClassList)); - last = last->next; - last->next = path->next; - last->type = path->type; - } - - return copy; -} - -BClassList *CClass_AppendPath(BClassList *dest, BClassList *src) { - BClassList *last; - - if (!(last = dest)) - return src; - - while (last->next) - last = last->next; - - while (src && src->type == last->type) - src = src->next; - - last->next = src; - return dest; -} - -static AccessType CClass_GetPathAccess(BClassList *path) { - AccessType result; - ClassList *base; - TypeClass *tclass; - - CError_ASSERT(930, path); - - result = ACCESSPUBLIC; - - while (1) { - tclass = TYPE_CLASS(path->type); - if (!(path = path->next)) - break; - - for (base = tclass->bases; base; base = base->next) { - if (base->base == TYPE_CLASS(path->type)) - break; - } - - CError_ASSERT(939, base); - - switch (base->access) { - case ACCESSPUBLIC: - break; - case ACCESSPROTECTED: - if (result == ACCESSPUBLIC) - result = ACCESSPROTECTED; - break; - case ACCESSPRIVATE: - if (result == ACCESSPUBLIC || result == ACCESSPROTECTED) - result = ACCESSPRIVATE; - else - return ACCESSNONE; - break; - case ACCESSNONE: - return ACCESSNONE; - default: - CError_FATAL(960); - } - } - - return result; -} - -Boolean CClass_IsMoreAccessiblePath(BClassList *path1, BClassList *path2) { - switch (CClass_GetPathAccess(path2)) { - case ACCESSPUBLIC: - return 0; - case ACCESSNONE: - return 1; - default: - CError_FATAL(978); - case ACCESSPROTECTED: - switch (CClass_GetPathAccess(path1)) { - case ACCESSPUBLIC: - return 1; - case ACCESSPRIVATE: - case ACCESSPROTECTED: - case ACCESSNONE: - return 0; - default: - CError_FATAL(987); - } - case ACCESSPRIVATE: - switch (CClass_GetPathAccess(path1)) { - case ACCESSPUBLIC: - case ACCESSPROTECTED: - return 1; - case ACCESSPRIVATE: - case ACCESSNONE: - return 0; - default: - CError_FATAL(997); - } - } - - return 0; -} - -static BClassList *CClass_GetBasePathRec(TypeClass *a, TypeClass *b, SInt32 offset, short depth) { - ClassList *base; - BClassList *checkpath; - BClassList *bestpath; - BClassList *newpath; - SInt32 newOffset; - - for (base = a->bases, bestpath = NULL; base; base = base->next) { - if (base->is_virtual) - newOffset = CClass_VirtualBaseOffset(cclass_isbase_mostderived, base->base); - else - newOffset = offset + base->offset; - - if (base->base == b) { - if (cclass_founddepth && newOffset != cclass_isbase_foundoffset) { - cclass_isambigbase = 1; - return NULL; - } - - cclass_isbase_foundoffset = newOffset; - cclass_founddepth = depth; - - bestpath = lalloc(sizeof(BClassList)); - bestpath->next = NULL; - bestpath->type = TYPE(b); - } else if ((checkpath = CClass_GetBasePathRec(base->base, b, newOffset, depth + 1))) { - newpath = lalloc(sizeof(BClassList)); - newpath->next = checkpath; - newpath->type = TYPE(base->base); - if (!bestpath || CClass_IsMoreAccessiblePath(newpath, bestpath)) - bestpath = newpath; - } - } - - return bestpath; -} - -BClassList *CClass_GetBasePath(TypeClass *a, TypeClass *b, short *founddepth, Boolean *isambigbase) { - BClassList *path; - BClassList *result; - - if ((a->flags & (CLASS_COMPLETED | CLASS_IS_TEMPL_INST)) == CLASS_IS_TEMPL_INST) - CDecl_CompleteType(TYPE(a)); - if ((b->flags & (CLASS_COMPLETED | CLASS_IS_TEMPL_INST)) == CLASS_IS_TEMPL_INST) - CDecl_CompleteType(TYPE(b)); - - cclass_founddepth = 0; - cclass_isbase_mostderived = a; - cclass_isbase_foundoffset = -1; - cclass_isambigbase = 0; - - if ((path = CClass_GetBasePathRec(a, b, 0, 1))) { - *founddepth = cclass_founddepth; - *isambigbase = cclass_isambigbase; - - result = lalloc(sizeof(BClassList)); - result->next = path; - result->type = TYPE(a); - return result; - } else { - *isambigbase = 0; - return NULL; - } -} - -Boolean CClass_IsBaseClass(TypeClass *a, TypeClass *b, short *founddepth, Boolean pathcheckflag, Boolean ambigerrorflag) { - BClassList *path; - short depth; - Boolean isambigbase; - - if ((path = CClass_GetBasePath(a, b, &depth, &isambigbase))) { - if (isambigbase && ambigerrorflag) - CError_Error(CErrorStr188); - - if (pathcheckflag) - CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); - - if (founddepth) - *founddepth = depth; - - return 1; - } - - return 0; -} - -TypeClass *CClass_GetQualifiedClass(void) { - DeclInfo di; - - memclrw(&di, sizeof(di)); - CParser_GetDeclSpecs(&di, 0); - - if (IS_TYPE_CLASS(di.thetype)) - return TYPE_CLASS(di.thetype); - - return NULL; -} - -ENode *CClass_AccessPathCast(BClassList *path, ENode *expr, Boolean reverse) { - ClassList *base; - SInt32 offset; - - while (path && path->next) { - base = TYPE_CLASS(path->type)->bases; - while (1) { - if (base->base == TYPE_CLASS(path->next->type)) - break; - CError_ASSERT(1157, base = base->next); - } - - if (base->is_virtual) { - if (reverse) { - CError_Error(CErrorStr164); - break; - } - - if (!base->base->sominfo) { - offset = base->offset; - if (offset && !canadd(expr, offset)) { - expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); - optimizecomm(expr); - } - - expr->rtype = CDecl_NewPointerType(CDecl_NewPointerType(TYPE(base->base))); - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = expr->data.monadic->rtype; - } - } else { - offset = base->offset; - if (offset) { - if (reverse) - offset = -offset; - if (!canadd(expr, offset)) { - expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); - optimizecomm(expr); - } - } - } - - path = path->next; - } - - return expr; -} - -ENode *CClass_ClassPointerCast(ENode *expr, TypeClass *a, TypeClass *b, Boolean typconflag, Boolean ambigerrorflag, Boolean pathcheckflag) { - BClassList *path; - Boolean reverse; - short depth; - Boolean isambigbase; - - reverse = 0; - - if (a != b) { - if (!(path = CClass_GetBasePath(a, b, &depth, &isambigbase))) { - CError_ASSERT(1216, typconflag); - if ((path = CClass_GetBasePath(b, a, &depth, &isambigbase))) { - reverse = 1; - goto doCast; - } - } else { - doCast: - if (isambigbase && ambigerrorflag) - CError_Error(CErrorStr188); - if (pathcheckflag) - CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); - if (!(a->flags & CLASS_SINGLE_OBJECT) && !b->sominfo) - expr = CClass_AccessPathCast(path, expr, reverse); - } - } - - if (typconflag && ENODE_IS(expr, EINDIRECT) && IS_TYPE_POINTER_ONLY(expr->rtype)) - expr = makemonadicnode(expr, ETYPCON); - - return expr; -} - -ENode *CClass_DirectBasePointerCast(ENode *expr, TypeClass *a, TypeClass *b) { - ClassList *base; - VClassList *vbase; - BClassList *path; - BClassList list1; - BClassList list2; - short depth; - Boolean isambigbase; - - for (base = a->bases; base; base = base->next) { - if (base->base == b) { - list1.next = &list2; - list1.type = TYPE(a); - list2.next = NULL; - list2.type = TYPE(b); - return CClass_AccessPathCast(&list1, expr, 0); - } - } - - for (vbase = a->vbases; vbase; vbase = vbase->next) { - if (vbase->base == b) { - CError_ASSERT(1273, path = CClass_GetBasePath(a, b, &depth, &isambigbase)); - return CClass_AccessPathCast(path, expr, 0); - } - } - - CError_FATAL(1277); - return expr; -} - -SInt32 CClass_GetPathOffset(BClassList *path) { - SInt32 offset; - ClassList *base; - - offset = 0; - - while (path->next) { - if (path->type != path->next->type) { - for (base = TYPE_CLASS(path->type)->bases; base; base = base->next) { - if (base->base == TYPE_CLASS(path->next->type)) - break; - } - - if (!base) { - CError_Error(CErrorStr221); - return offset; - } - } - - if (base->is_virtual) - return -1; - offset += base->offset; - - path = path->next; - } - - return offset; -} - -Boolean CClass_ClassDominates(TypeClass *tclass, TypeClass *baseclass) { - ClassList *base; - - for (base = tclass->bases; base; base = base->next) { - if (base->base == baseclass || CClass_ClassDominates(base->base, baseclass)) - return 1; - } - - return 0; -} - -SInt32 CClass_VirtualBaseOffset(TypeClass *tclass, TypeClass *baseclass) { - VClassList *vbase; - - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - if (vbase->base == baseclass) - return vbase->offset; - } - - CError_FATAL(1342); - return 0; -} - -SInt32 CClass_VirtualBaseVTableOffset(TypeClass *tclass, TypeClass *baseclass) { - VClassList *vbase; - - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - if (vbase->base == baseclass) - return vbase->voffset; - } - - CError_FATAL(1359); - return 0; -} - -SInt32 CClass_GetMemberOffset(TypeClass *tclass, HashNameNode *name, ObjMemberVar **resultIvar) { - ObjMemberVar *ivar; - ClassList *base; - SInt32 offset; - SInt32 tmp; - Boolean foundflag; - - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - if (ivar->name == name) { - if (resultIvar) - *resultIvar = ivar; - return ivar->offset; - } - } - - for (base = tclass->bases, foundflag = 0; base; base = base->next) { - switch ((tmp = CClass_GetMemberOffset(base->base, name, resultIvar))) { - case -3: - case -2: - return tmp; - case -1: - break; - default: - if (base->is_virtual) - return -3; - if (foundflag) - return -2; - foundflag = 1; - offset = base->offset + tmp; - } - } - - return foundflag ? offset : -1; -} - -Boolean CClass_OverridesBaseMember(TypeClass *tclass, HashNameNode *name, Object *obj) { - NameSpaceObjectList *nsol; - ClassList *base; - Boolean result; - - result = 0; - for (base = tclass->bases; base; base = base->next) { - if (base->base->vtable) { - for (nsol = CScope_FindName(base->base->nspace, name); nsol; nsol = nsol->next) { - if ( - nsol->object->otype == OT_OBJECT && - OBJECT(nsol->object)->datatype == DVFUNC && - CClass_GetOverrideKind(TYPE_FUNC(OBJECT(nsol->object)->type), TYPE_FUNC(obj->type), 1) - ) - result = 1; - } - - if (CClass_OverridesBaseMember(base->base, name, obj)) - result = 1; - } - } - - return result; -} - -static OVClass *CClass_FindOVClass(OVClass *ovclass, TypeClass *tclass, SInt32 offset) { - OVClassBase *ovbase; - - if (ovclass->tclass == tclass && ovclass->offset == offset) - return ovclass; - - for (ovbase = ovclass->bases; ovbase; ovbase = ovbase->next) { - if ((ovclass = CClass_FindOVClass(ovbase->ovclass, tclass, offset))) - return ovclass; - } - - return NULL; -} - -static OVClass *CClass_BuildOVClassTree(OVClass *root, TypeClass *tclass, SInt32 offset, SInt32 voffset) { - ClassList *base; - Object *object; - OVClass *tree; - OVFunc *ovfunc; - OVClassBase *ovbase; - SInt32 vboffset; - SInt32 vbvoffset; - CScopeObjectIterator iter; - - tree = lalloc(sizeof(OVClass)); - memclrw(tree, sizeof(OVClass)); - - tree->tclass = tclass; - tree->offset = offset; - tree->voffset = voffset; - if (!root) - root = tree; - - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (object->datatype == DVFUNC) { - ovfunc = lalloc(sizeof(OVFunc)); - memclrw(ovfunc, sizeof(OVFunc)); - - ovfunc->next = tree->vfuncs; - ovfunc->obj = object; - tree->vfuncs = ovfunc; - } - } - - for (base = tclass->bases; base; base = base->next) { - if (base->base->vtable || base->base->sominfo) { - ovbase = lalloc(sizeof(OVClassBase)); - memclrw(ovbase, sizeof(OVClassBase)); - - if (base->is_virtual) { - vboffset = CClass_VirtualBaseOffset(main_class, base->base); - if (!(ovbase->ovclass = CClass_FindOVClass(root, base->base, vboffset))) { - vbvoffset = CClass_VirtualBaseVTableOffset(main_class, base->base); - ovbase->ovclass = CClass_BuildOVClassTree(root, base->base, vboffset, vbvoffset); - } - ovbase->is_virtual = 1; - } else { - ovbase->ovclass = CClass_BuildOVClassTree( - root, - base->base, - offset + base->offset, - voffset + base->voffset); - ovbase->is_virtual = 0; - } - - ovbase->next = tree->bases; - tree->bases = ovbase; - } - } - - return tree; -} - -static Boolean CClass_IsBaseOf(OVClass *a, OVClass *b) { - OVClassBase *ovbase; - - for (ovbase = b->bases; ovbase; ovbase = ovbase->next) { - if ( - (ovbase->ovclass->tclass == a->tclass && ovbase->ovclass->offset == a->offset) || - CClass_IsBaseOf(a, ovbase->ovclass) - ) - { - if (!cclass_ovbase && ovbase->is_virtual) - cclass_ovbase = ovbase->ovclass; - return 1; - } - } - - return 0; -} - -static void CClass_FindOVFunc(OVClass *a, OVClass *b, OVFunc *func) { - OVFunc *scan; - OVClassBase *ovbase; - UInt8 overrideKind; - - if (CClass_IsBaseOf(b, a)) { - for (scan = a->vfuncs; scan; scan = scan->next) { - if ( - (func->obj->name == scan->obj->name) && - (overrideKind = CClass_GetOverrideKind(TYPE_FUNC(func->obj->type), TYPE_FUNC(scan->obj->type), 0)) - ) - { - if (func->ovc8) { - if (func->ovc8->tclass == a->tclass || CClass_ClassDominates(func->ovc8->tclass, a->tclass)) - return; - if (!CClass_ClassDominates(a->tclass, func->ovc8->tclass)) { - func->ovf10 = scan; - return; - } - } - - if (a == cclass_root) { - TYPE_FUNC(scan->obj->type)->flags |= FUNC_FLAGS_20; - if (overrideKind == 2) - TYPE_FUNC(scan->obj->type)->flags |= FUNC_FLAGS_400000; - } - - func->ovc8 = a; - func->ovfC = scan; - func->ovf10 = NULL; - return; - } - } - - for (ovbase = a->bases; ovbase; ovbase = ovbase->next) - CClass_FindOVFunc(ovbase->ovclass, b, func); - } -} - -static TypeList *CClass_GetCoVariantClassList(TypeList *list, TypeClass *tclass, Object *func, Boolean flag) { - Object *object; - TypeList *scan; - Type *type; - ClassList *base; - CScopeObjectIterator iter; - - if (!flag) { - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if ( - object->name == func->name && - object->datatype == DVFUNC && - CClass_GetOverrideKind(TYPE_FUNC(object->type), TYPE_FUNC(func->type), 0) == 2 - ) - { - CError_ASSERT(1686, - IS_TYPE_POINTER_ONLY(TYPE_FUNC(object->type)->functype) && - IS_TYPE_CLASS(TPTR_TARGET(TYPE_FUNC(object->type)->functype))); - - type = TPTR_TARGET(TYPE_FUNC(object->type)->functype); - for (scan = list; scan; scan = scan->next) { - if (scan->type == type) - break; - } - - if (!scan) { - scan = lalloc(sizeof(TypeList)); - scan->type = type; - scan->next = list; - list = scan; - } - } - } - } - - for (base = tclass->bases; base; base = base->next) { - if (base->base->vtable) - list = CClass_GetCoVariantClassList(list, base->base, func, 0); - } - - return list; -} - -static TypeMemberFunc *CClass_GetCovariantType(TypeMemberFunc *tmethod, Type *type) { - TypePointer *tptr; - TypeMemberFunc *result; - - CError_ASSERT(1724, - IS_TYPE_METHOD(tmethod) && - IS_TYPE_POINTER_ONLY(tmethod->functype)); - - tptr = galloc(sizeof(TypePointer)); - *tptr = *TYPE_POINTER(tmethod->functype); - tptr->target = type; - - result = galloc(sizeof(TypeMemberFunc)); - *result = *tmethod; - result->flags &= ~(FUNC_FLAGS_20 | FUNC_FLAGS_400000); - result->functype = TYPE(tptr); - return result; -} - -static Object *CClass_FindCovariantFunction(Object *func, Type *type) { - NameSpaceObjectList *nsol; - - nsol = CScope_FindName( - TYPE_METHOD(func->type)->theclass->nspace, - CMangler_GetCovariantFunctionName(func, TYPE_CLASS(type))); - - CError_ASSERT(1754, nsol && !nsol->next && nsol->object->otype == OT_OBJECT); - - return OBJECT(nsol->object); -} - -static ObjectList *CClass_DeclareCovariantFuncs(ObjectList *list, Object *func, TypeClass *tclass) { - Object *newfunc; - HashNameNode *name; - TypeList *types; - ObjectList *newlist; - - for (types = CClass_GetCoVariantClassList(NULL, tclass, func, 1); types; types = types->next) { - name = CMangler_GetCovariantFunctionName(func, TYPE_CLASS(types->type)); - - newfunc = galloc(sizeof(Object)); - memclrw(newfunc, sizeof(Object)); - - newfunc->otype = OT_OBJECT; - newfunc->datatype = DFUNC; - newfunc->section = func->section; - newfunc->nspace = func->nspace; - newfunc->name = name; - newfunc->type = TYPE(CClass_GetCovariantType(TYPE_METHOD(func->type), types->type)); - newfunc->qual = func->qual & ~Q_INLINE; - newfunc->sclass = func->sclass; - newfunc->u.func.linkname = name; - - newlist = lalloc(sizeof(ObjectList)); - newlist->object = newfunc; - newlist->next = list; - list = newlist; - } - - return list; -} - -void CClass_DefineCovariantFuncs(Object *method, CI_FuncData *ifuncdata) { - NameSpace *nspace; - TypeList *types; - Object *covariantFunc; - Statement *stmt; - Type *tptr; - Statement firstStmt; - - for (types = CClass_GetCoVariantClassList(NULL, TYPE_METHOD(method->type)->theclass, method, 1); types; types = types->next) { - covariantFunc = CClass_FindCovariantFunction(method, types->type); - tptr = CDecl_NewPointerType(types->type); - - nspace = CFunc_FuncGenSetup(&firstStmt, covariantFunc); - CInline_UnpackIFunctionData(covariantFunc, ifuncdata, &firstStmt); - - for (stmt = &firstStmt; stmt; stmt = stmt->next) { - if (stmt->type == ST_RETURN && stmt->expr) - stmt->expr = CExpr_AssignmentPromotion(stmt->expr, tptr, ENODE_QUALS(stmt->expr), 0); - } - - CFunc_Gen(&firstStmt, covariantFunc, 0); - cscope_current = nspace->parent; - } -} - -static void CClass_OverrideOVClassTree(OVClass *ovclass) { - OVClassBase *ovbase; - OVFunc *ovfunc; - - if (cclass_root != ovclass) { - for (ovfunc = ovclass->vfuncs; ovfunc; ovfunc = ovfunc->next) - CClass_FindOVFunc(cclass_root, ovclass, ovfunc); - } - - for (ovbase = ovclass->bases; ovbase; ovbase = ovbase->next) - CClass_OverrideOVClassTree(ovbase->ovclass); -} - -static void CClass_AllocVTableRec(OVClass *ovclass) { - OVFunc *ovfunc; - Object *object; - SInt32 offset27; - SInt32 offset26; - SInt32 offset23; - OVClassBase *ovbase; - OLinkList *link; - - if (ovclass->alloced_vtable) - return; - - for (ovfunc = ovclass->vfuncs; ovfunc; ovfunc = ovfunc->next) { - offset27 = ovclass->voffset + TYPE_METHOD(ovfunc->obj->type)->vtbl_index + CABI_GetVTableOffset(ovclass->tclass); - CError_ASSERT(1867, offset27 < vtable_data_size); - - if (!(vtable_object_data[offset27])) { - if (ovfunc->ovfC) { - object = ovfunc->ovfC->obj; - if ( - (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_400000) && - CClass_GetOverrideKind(TYPE_FUNC(ovfunc->obj->type), TYPE_FUNC(object->type), 0) == 2 - ) - { - CError_ASSERT(1887, - IS_TYPE_POINTER_ONLY(TYPE_FUNC(ovfunc->obj->type)->functype) && - IS_TYPE_CLASS(TPTR_TARGET(TYPE_FUNC(ovfunc->obj->type)->functype))); - object = CClass_FindCovariantFunction( - object, - TPTR_TARGET(TYPE_FUNC(ovfunc->obj->type)->functype)); - } - - if ((offset26 = ovfunc->ovc8->offset - ovclass->offset)) { - if (!(TYPE_FUNC(object->type)->flags & FUNC_PURE)) { - cclass_ovbase = NULL; - CError_ASSERT(1899, CClass_IsBaseOf(ovclass, ovfunc->ovc8)); - - if (cclass_ovbase && (main_class->flags & CLASS_FLAGS_8000)) { - offset23 = ovclass->offset - cclass_ovbase->offset; - offset23 = CABI_GetCtorOffsetOffset(cclass_ovbase->tclass, NULL) - offset23; - CError_ASSERT(1906, offset23 > 0); - object = CClass_ThunkObject(object, offset26, 0, offset23); - } else { - object = CClass_ThunkObject(object, offset26, 0, -1); - } - } - } - } else { - object = ovfunc->obj; - } - - if (!(TYPE_FUNC(object->type)->flags & FUNC_PURE)) { - link = lalloc(sizeof(OLinkList)); - link->next = vtable_object_links; - link->obj = object; - link->offset = offset27; - link->somevalue = 0; - vtable_object_links = link; - vtable_object_data[offset27] = 1; - } - } - } - - ovclass->alloced_vtable = 1; - - for (ovbase = ovclass->bases; ovbase; ovbase = ovbase->next) - CClass_AllocVTableRec(ovbase->ovclass); -} - -static Object *CClass_CheckClass(OVClass *ovclass, Boolean errorflag) { - Object *object; - Object *check; - OVFunc *ovfunc; - OVClassBase *ovbase; - - object = NULL; - - for (ovfunc = ovclass->vfuncs; ovfunc; ovfunc = ovfunc->next) { - if (ovfunc->ovf10 && errorflag) - CError_Error(CErrorStr251, main_class, 0, ovfunc->obj, ovfunc->ovfC->obj, ovfunc->ovf10->obj); - - if (!object) { - check = ovfunc->ovfC ? ovfunc->ovfC->obj : ovfunc->obj; - if (TYPE_FUNC(check->type)->flags & FUNC_PURE) - object = check; - } - } - - for (ovbase = ovclass->bases; ovbase; ovbase = ovbase->next) { - if (object) - CClass_CheckClass(ovbase->ovclass, errorflag); - else - object = CClass_CheckClass(ovbase->ovclass, errorflag); - } - - return object; -} - -static void CClass_AllocVTable(TypeClass *tclass) { - OVClass *ovclass; - - main_class = tclass; - ovclass = CClass_BuildOVClassTree(NULL, tclass, 0, 0); - cclass_root = ovclass; - CClass_OverrideOVClassTree(ovclass); - CClass_CheckClass(ovclass, 1); - CClass_AllocVTableRec(ovclass); -} - -static Object *CClass_CheckVirtuals(TypeClass *tclass) { - OVClass *ovclass; - - main_class = tclass; - ovclass = CClass_BuildOVClassTree(NULL, tclass, 0, 0); - cclass_root = ovclass; - CClass_OverrideOVClassTree(ovclass); - return CClass_CheckClass(ovclass, 0); -} - -static void CClass_CheckVirtualBaseOverrides(OVClass *a, OVClass *b, Boolean flag) { - VClassList *vbase; - OVFunc *ovfunc; - OVClassBase *ovbase; - - if (flag) { - for (ovfunc = b->vfuncs; ovfunc; ovfunc = ovfunc->next) { - if (ovfunc->ovfC) { - cclass_ovbase = NULL; - CError_ASSERT(2040, CClass_IsBaseOf(b, ovfunc->ovc8)); - - if (cclass_ovbase) { - for (vbase = a->tclass->vbases; vbase; vbase = vbase->next) { - if (vbase->base == cclass_ovbase->tclass) - break; - } - - CError_ASSERT(2047, vbase); - vbase->has_override = 1; - } - } - } - } - - for (ovbase = b->bases; ovbase; ovbase = ovbase->next) { - CClass_CheckVirtualBaseOverrides(a, ovbase->ovclass, flag || ovbase->is_virtual); - } -} - -static void CClass_CheckHideVirtual(OVClass *a, OVClass *b) { - OVClassBase *ovbase; - OVFunc *ovfunc; - Object *foundObject; - Boolean isAlias; - Object *object; - CScopeObjectIterator iter; - - if (a != b) { - for (ovfunc = b->vfuncs; ovfunc; ovfunc = ovfunc->next) { - if (ovfunc->ovc8 != a) { - foundObject = NULL; - isAlias = 0; - CScope_InitObjectIterator(&iter, a->tclass->nspace); - - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (object->name == ovfunc->obj->name && IS_TYPE_FUNC(object->type)) { - if (object->datatype != DALIAS) { - if (!(TYPE_FUNC(object->type)->flags & FUNC_FLAGS_20)) - foundObject = object; - } else { - if (object->u.alias.object == ovfunc->obj) { - // don't show a warning if this is just an alias to the base function - isAlias = 1; - break; - } - } - } - } - - if (foundObject && !isAlias) - CError_Warning(CErrorStr225, foundObject, ovfunc->obj); - } - } - } - - for (ovbase = b->bases; ovbase; ovbase = ovbase->next) - CClass_CheckHideVirtual(a, ovbase->ovclass); -} - -void CClass_CheckOverrides(TypeClass *tclass) { - OVClass *tree; - Object *object; - ObjectList *objlist; - ClassList *base; - VClassList *vbase; - int i; - CScopeObjectIterator iter; - - i = 0; - for (base = tclass->bases; base; base = base->next) { - base->offset = i; - base->voffset = i; - i++; - } - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - vbase->offset = i; - vbase->voffset = i; - i++; - } - - main_class = tclass; - tree = CClass_BuildOVClassTree(NULL, tclass, 0, 0); - cclass_root = tree; - - CClass_OverrideOVClassTree(tree); - if (CClass_CheckClass(tree, 0)) - tclass->flags |= CLASS_ABSTRACT; - - if (copts.warn_hidevirtual) - CClass_CheckHideVirtual(tree, tree); - - if (tclass->flags & CLASS_FLAGS_8000) - CClass_CheckVirtualBaseOverrides(tree, tree, 0); - - objlist = NULL; - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (object->datatype == DVFUNC) { - CError_ASSERT(2175, IS_TYPE_FUNC(object->type)); - if (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_400000) - objlist = CClass_DeclareCovariantFuncs(objlist, object, tclass); - } - } - - while (objlist) { - CScope_AddObject(tclass->nspace, objlist->object->name, OBJ_BASE(objlist->object)); - objlist = objlist->next; - } - - for (base = tclass->bases; base; base = base->next) { - base->offset = 0; - base->voffset = 0; - } - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - vbase->offset = 0; - vbase->voffset = 0; - } -} - -static void CClass_FindDominator(TypeClass *tclass1, SInt32 offset1, Object *object1, TypeClass *tclass2, SInt32 offset2, TypeClass *tclass3) { - Object *object; - ClassList *base; - CScopeObjectIterator iter; - - CScope_InitObjectIterator(&iter, tclass1->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if ( - object->name == cclass_dominator_vobject->name && - object->datatype == DVFUNC && - CClass_GetOverrideKind(TYPE_FUNC(cclass_dominator_vobject->type), TYPE_FUNC(object->type), 0) - ) - { - if (object == cclass_dominator_vobject && offset1 == cclass_dominator_voffset) { - if (object1) { - if (cclass_dominator_oobject && cclass_dominator_ooffset != offset2) { - if (CClass_ClassDominates(cclass_dominator_oclass, tclass2)) - return; - if (!CClass_ClassDominates(tclass2, cclass_dominator_oclass)) { - cclass_dominator_eobject = object1; - cclass_vbase = tclass3; - return; - } - } - - cclass_dominator_oobject = object1; - cclass_dominator_ooffset = offset2; - cclass_dominator_oclass = tclass2; - cclass_dominator_eobject = NULL; - cclass_vbase = tclass3; - } - return; - } else { - if (!object1) { - object1 = object; - tclass2 = tclass1; - offset2 = offset1; - } - break; - } - } - } - - for (base = tclass1->bases; base; base = base->next) { - if (base->base->vtable) { - if (!base->is_virtual) { - CClass_FindDominator(base->base, offset1 + base->offset, object1, tclass2, offset2, tclass3); - } else { - SInt32 vboffset = CClass_VirtualBaseOffset(main_class, base->base); - CClass_FindDominator(base->base, vboffset, object1, tclass2, offset2, base->base); - } - } - } -} - -static void CClass_ConstructVTable(TypeClass *tclass, SInt32 voffset, SInt32 offset, TypeClass *baseclass) { - Object *object; - Object *thunkobject; - SInt32 newoffset; - SInt32 newvoffset; - ClassList *base; - SInt32 thunkoffset; - OLinkList *olink; - CScopeObjectIterator iter; - - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (object->datatype == DVFUNC) { - newoffset = voffset + TYPE_METHOD(object->type)->vtbl_index + CABI_GetVTableOffset(tclass); - CError_ASSERT(2288, newoffset < vtable_data_size); - - if (!vtable_object_data[newoffset]) { - cclass_dominator_vobject = object; - cclass_dominator_voffset = offset; - cclass_dominator_oobject = NULL; - cclass_dominator_ooffset = offset; - CClass_FindDominator(main_class, 0, NULL, NULL, 0, NULL); - - if (cclass_dominator_oobject) { - if (cclass_dominator_eobject) - CError_Error(CErrorStr251, main_class, 0, cclass_dominator_vobject, cclass_dominator_oobject, cclass_dominator_eobject); - } else { - cclass_dominator_oobject = object; - cclass_vbase = NULL; - } - - vtable_object_data[newoffset] = 1; - - if (!(TYPE_FUNC(cclass_dominator_oobject->type)->flags & FUNC_PURE)) { - if (!check_pures) { - thunkobject = cclass_dominator_oobject; - if ((thunkoffset = cclass_dominator_ooffset - offset)) { - if (cclass_vbase && (main_class->flags & CLASS_FLAGS_8000)) { - thunkobject = CClass_ThunkObject(cclass_dominator_oobject, thunkoffset, 0, - CABI_GetCtorOffsetOffset(cclass_vbase, tclass)); - } else { - thunkobject = CClass_ThunkObject(cclass_dominator_oobject, thunkoffset, 0, -1); - } - } - - olink = lalloc(sizeof(OLinkList)); - olink->next = vtable_object_links; - olink->obj = thunkobject; - olink->offset = newoffset; - olink->somevalue = 0; - vtable_object_links = olink; - } - } else { - found_pure = cclass_dominator_oobject; - } - } - } - } - - for (base = tclass->bases; base; base = base->next) { - if (base->base->vtable) { - if (base->is_virtual) { - newoffset = CClass_VirtualBaseOffset(main_class, base->base); - newvoffset = CClass_VirtualBaseVTableOffset(main_class, base->base); - CClass_ConstructVTable( - base->base, - newvoffset, - newoffset, - base->base - ); - } else { - CClass_ConstructVTable( - base->base, - voffset + base->voffset, - offset + base->offset, - baseclass - ); - } - } - } -} - -void CClass_ClassDefaultFuncAction(TypeClass *tclass) { -} - -void CClass_ClassAction(TypeClass *tclass) { - if (tclass->sominfo) { - CSOM_GenerateClassStructures(tclass); - } else if (tclass->vtable) { - vtable_data_size = tclass->vtable->size; - vtable_object_data = lalloc(vtable_data_size); - memclrw(vtable_object_data, vtable_data_size); - - main_class = tclass; - vtable_object_links = NULL; - found_pure = NULL; - check_pures = 0; - - CClass_AllocVTable(tclass); - - memclrw(vtable_object_data, vtable_data_size); - if (copts.RTTI && !(tclass->flags & (CLASS_SINGLE_OBJECT | CLASS_COM_OBJECT))) - vtable_object_links = CRTTI_ConstructVTableHeaders(tclass, vtable_object_data, vtable_object_links); - - CError_ASSERT(2492, tclass->vtable->object->type->size == tclass->vtable->size); - CInit_DeclareData(tclass->vtable->object, vtable_object_data, vtable_object_links, tclass->vtable->size); - } -} - -void CClass_MakeStaticActionClass(TypeClass *tclass) { - if (tclass->vtable) { - tclass->vtable->object->sclass = TK_STATIC; - tclass->vtable->object->qual |= Q_20000; - if (!(tclass->vtable->object->flags & OBJECT_FLAGS_2)) { - CParser_NewCallBackAction(tclass->vtable->object, tclass); - } else if (cparamblkptr->precompile != 1) { - CParser_NewClassAction(tclass); - } - } -} - -Object *CClass_CheckPures(TypeClass *tclass) { - return CClass_CheckVirtuals(tclass); -} - -void CClass_MemberDef(Object *obj, TypeClass *tclass) { - switch (tclass->action) { - case CLASS_ACTION_0: - break; - case CLASS_ACTION_1: - if (IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_4)) { - if (obj->qual & Q_INLINE) { - if (tclass->sominfo) - CError_Error(CErrorStr280); - tclass->action = CLASS_ACTION_0; - CClass_MakeStaticActionClass(tclass); - } else if (cparamblkptr->precompile != 1) { - CParser_NewClassAction(tclass); - } - } - break; - case CLASS_ACTION_2: - CError_FATAL(2682); - break; - case CLASS_ACTION_3: - break; - default: - CError_FATAL(2701); - } -} - -Object *CClass_ThisSelfObject(void) { - ObjectList *list; - - if (cscope_currentfunc && cscope_currentclass) { - if (cscope_currentclass->objcinfo) { - for (list = arguments; list; list = list->next) { - if (list->object->name == self_name_node) - return list->object; - } - CError_Error(CErrorStr301); - } else { - if (cscope_is_member_func) { - for (list = arguments; list; list = list->next) { - if (list->object->name == this_name_node) - return list->object; - } - } - CError_Error(CErrorStr189); - } - } - - CError_Error(copts.cplusplus ? CErrorStr189 : CErrorStr301); - return NULL; -} - -ENode *CClass_CreateThisSelfExpr(void) { - Object *object; - ENode *expr; - - if (!(object = CClass_ThisSelfObject())) - return NULL; - - expr = create_objectrefnode(object); - expr->rtype = CDecl_NewPointerType(TYPE(cscope_currentclass)); - expr = makemonadicnode(expr, EINDIRECT); - expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); - - return expr; -} - -static AccessType CClass_BaseMemberAccess(BClassList *path, AccessType access) { - ClassList *base; - - if (path->next) { - access = CClass_BaseMemberAccess(path->next, access); - switch (access) { - case ACCESSPRIVATE: - case ACCESSNONE: - return ACCESSNONE; - } - - for (base = TYPE_CLASS(path->type)->bases; ; base = base->next) { - if (!base) - return ACCESSNONE; - - if (base->base == TYPE_CLASS(path->next->type)) { - switch (base->access) { - case ACCESSNONE: - access = ACCESSNONE; - break; - case ACCESSPROTECTED: - if (access == ACCESSPUBLIC) - access = ACCESSPROTECTED; - break; - case ACCESSPRIVATE: - if (access == ACCESSPRIVATE) - access = ACCESSNONE; - else - access = ACCESSPRIVATE; - break; - case ACCESSPUBLIC: - break; - } - break; - } - } - } - - return access; -} - -static Boolean CClass_CanAccess(BClassList *path, AccessType access) { - AccessType access2; - BClassList *scan; - BClassList *next; - TypeClass *prevclass; - TypeClass *tclass; - ClassList *base; - ClassFriend *cfriend; - - tclass = TYPE_CLASS(path->type); - access2 = access; - if ((scan = path->next)) { - if (access2 != ACCESSPRIVATE) { - prevclass = tclass; - while (scan) { - for (base = prevclass->bases; base; base = base->next) { - if (base->base == TYPE_CLASS(scan->type)) - break; - } - - if (!base) - return 0; - - switch (base->access) { - case ACCESSNONE: - access2 = ACCESSNONE; - break; - case ACCESSPROTECTED: - if (access2 == ACCESSPUBLIC) - access2 = ACCESSPROTECTED; - break; - case ACCESSPRIVATE: - if (access2 == ACCESSPRIVATE) - access2 = ACCESSNONE; - else - access2 = ACCESSPRIVATE; - break; - case ACCESSPUBLIC: - break; - } - - prevclass = TYPE_CLASS(scan->type); - scan = scan->next; - } - } else { - access2 = ACCESSNONE; - } - } - - if (access2 == ACCESSPUBLIC) - return 1; - - if (access2 != ACCESSNONE) { - if (cscope_currentclass == tclass) - return 1; - if (cobjc_currentclass == tclass) - return 1; - - for (cfriend = tclass->friends; cfriend; cfriend = cfriend->next) { - if (cfriend->isclass) { - if (cfriend->u.theclass == cscope_currentclass) - return 1; - } else { - if (cfriend->u.obj == cscope_currentfunc) - return 1; - } - } - } - - for (scan = path; scan->next; scan = scan->next) { - if (CClass_CanAccess(scan->next, access)) { - if ((next = scan->next->next) || access != ACCESSPUBLIC) { - scan->next->next = NULL; - if (CClass_CanAccess(path, ACCESSPUBLIC)) { - scan->next->next = next; - return 1; - } - scan->next->next = next; - } - } - } - - return 0; -} - -void CClass_CheckPathAccess(BClassList *path, Object *obj, AccessType access) { - if (!CClass_CanAccess(path, access)) { - if (path && obj) - CError_Error(CErrorStr381, path->type, 0, obj); - else - CError_Error(CErrorStr187); - } -} - -static BClassList *CClass_PathCleanup(BClassList *path, TypeClass *tclass) { - BClassList *first; - ClassList *base; - - first = path; - - while (1) { - if (!path->next) { - if (!tclass) - return first; - if (path->type == TYPE(tclass)) - return first; - return NULL; - } - - if (path->type != path->next->type) { - for (base = TYPE_CLASS(path->type)->bases; base; base = base->next) { - if (base->base == TYPE_CLASS(path->next->type)) - break; - } - - if (base) { - path = path->next; - } else { - first = path = path->next; - } - } else { - path->next = path->next->next; - } - } -} - -void CClass_CheckStaticAccess(BClassList *path, TypeClass *tclass, AccessType access) { - ClassFriend *cfriend; - - if (path) { - path = CClass_PathCleanup(path, tclass); - if (path && path->next) { - if (!CClass_CanAccess(path, access)) - CError_Error(CErrorStr187); - return; - } - } - - switch (access) { - case ACCESSPUBLIC: - return; - case ACCESSPRIVATE: - case ACCESSPROTECTED: - if (tclass == cscope_currentclass) - return; - - for (cfriend = tclass->friends; cfriend; cfriend = cfriend->next) { - if (cfriend->isclass) { - if (cfriend->u.theclass == cscope_currentclass) - return; - } else { - if (cfriend->u.obj == cscope_currentfunc) - return; - } - } - case ACCESSNONE: - CError_Warning(CErrorStr187); - return; - default: - CError_FATAL(3013); - } -} - -void CClass_CheckObjectAccess(BClassList *path, Object *obj) { - short depth; - Boolean isambigbase; - - if (obj->nspace && obj->nspace->theclass) { - if (!path && cscope_currentclass) - path = CClass_GetBasePath(cscope_currentclass, obj->nspace->theclass, &depth, &isambigbase); - - CClass_CheckStaticAccess(path, obj->nspace->theclass, obj->access); - } -} - -void CClass_CheckEnumAccess(BClassList *path, ObjEnumConst *objec) { - if (path) { - if ((path = CClass_PathCleanup(path, NULL))) { - if (!CClass_CanAccess(path, objec->access)) - CError_Error(CErrorStr187); - return; - } - } - - if ( - objec->access != ACCESSPUBLIC && - IS_TYPE_ENUM(objec->type) && - TYPE_ENUM(objec->type)->nspace && - TYPE_ENUM(objec->type)->nspace->theclass - ) - CClass_CheckStaticAccess(NULL, TYPE_ENUM(objec->type)->nspace->theclass, objec->access); -} - -static Type *CClass_PointerTypeCopy(Type *type) { - Type *copy; - - switch (type->type) { - case TYPEPOINTER: - case TYPEARRAY: - copy = galloc(sizeof(TypePointer)); - *TYPE_POINTER(copy) = *TYPE_POINTER(type); - TPTR_TARGET(copy) = CClass_PointerTypeCopy(TPTR_TARGET(copy)); - return copy; - case TYPEMEMBERPOINTER: - copy = galloc(sizeof(TypeMemberPointer)); - *TYPE_MEMBER_POINTER(copy) = *TYPE_MEMBER_POINTER(type); - return copy; - default: - return type; - } -} - -Type *CClass_CombineClassAccessQualifiers(Type *type, UInt32 qual1, UInt32 qual2, UInt32 *outflags) { - Type *inner; - - qual2 = qual2 & (Q_CONST | Q_VOLATILE); - if (qual1 & Q_MUTABLE) - qual2 &= ~Q_CONST; - qual1 = qual1 & (Q_CONST | Q_VOLATILE); - - inner = type; - while (IS_TYPE_ARRAY(inner)) - inner = TPTR_TARGET(inner); - - switch (inner->type) { - case TYPEMEMBERPOINTER: - case TYPEPOINTER: - if (qual2) { - type = CClass_PointerTypeCopy(type); - inner = type; - while (IS_TYPE_ARRAY(inner)) - inner = TPTR_TARGET(inner); - - switch (inner->type) { - case TYPEPOINTER: - TPTR_QUAL(inner) |= qual2; - break; - case TYPEMEMBERPOINTER: - TYPE_MEMBER_POINTER(inner)->qual |= qual2; - break; - default: - CError_FATAL(3125); - } - } - break; - default: - qual1 |= qual2; - } - - *outflags = qual1; - return type; -} - -static void CClass_OptimizeBitFieldAccess(Type **ptype, SInt32 *poffset) { - Type *innertype; - TypeBitfield *newtype; - short i; - - innertype = TYPE_BITFIELD(*ptype)->bitfieldtype; - if (TYPE_BITFIELD(*ptype)->bitlength == 8) { - switch (TYPE_BITFIELD(*ptype)->offset) { - case 0: - i = 0; - break; - case 8: - i = 1; - break; - case 16: - i = 2; - break; - case 24: - i = 3; - break; - default: - i = -1; - break; - } - - if (i >= 0) { - if (innertype->size != 1) { - if (is_unsigned(TYPE_BITFIELD(*ptype)->bitfieldtype)) - *ptype = TYPE(&stunsignedchar); - else - *ptype = TYPE(&stsignedchar); - } else { - *ptype = innertype; - } - *poffset += i; - return; - } - } - - if (TYPE_BITFIELD(*ptype)->bitlength == 16) { - switch (TYPE_BITFIELD(*ptype)->offset) { - case 0: - i = 0; - break; - case 16: - i = 2; - break; - default: - i = -1; - break; - } - - if (i >= 0) { - if (innertype->size != stsignedshort.size) { - if (is_unsigned(innertype)) - *ptype = TYPE(&stunsignedshort); - else - *ptype = TYPE(&stsignedshort); - } else { - *ptype = innertype; - } - *poffset += i; - return; - } - } - - if (TYPE_BITFIELD(*ptype)->bitlength == 32 && TYPE_BITFIELD(*ptype)->offset == 0) { - if (innertype->size != stsignedlong.size) { - if (is_unsigned(innertype)) - *ptype = TYPE(&stunsignedlong); - else - *ptype = TYPE(&stsignedlong); - } else { - *ptype = innertype; - } - return; - } - - if ((*ptype)->size != stsignedchar.size) { - i = TYPE_BITFIELD(*ptype)->offset + TYPE_BITFIELD(*ptype)->bitlength - 1; - - if (TYPE_BITFIELD(*ptype)->bitlength < 8 && (TYPE_BITFIELD(*ptype)->offset & 0xFFF8) == (i & 0xFFF8)) { - newtype = galloc(sizeof(TypeBitfield)); - *newtype = *TYPE_BITFIELD(*ptype); - *ptype = TYPE(newtype); - - i = 0; - if (newtype->offset >= 8) - i = 1; - if (newtype->offset >= 16) - i = 2; - if (newtype->offset >= 24) - i = 3; - *poffset += i; - newtype->offset -= 8 * i; - - newtype->bitfieldtype = is_unsigned(innertype) ? TYPE(&stunsignedchar) : TYPE(&stsignedchar); - newtype->size = newtype->bitfieldtype->size; - return; - } - - if ((*ptype)->size != stsignedshort.size) { - if (TYPE_BITFIELD(*ptype)->bitlength < 16 && (TYPE_BITFIELD(*ptype)->offset & 0xFFF0) == (i & 0xFFF0)) { - newtype = galloc(sizeof(TypeBitfield)); - *newtype = *TYPE_BITFIELD(*ptype); - *ptype = TYPE(newtype); - - i = 0; - if (newtype->offset >= 16) - i = stsignedshort.size; - *poffset += i; - newtype->offset -= 8 * i; - - newtype->bitfieldtype = is_unsigned(innertype) ? TYPE(&stunsignedshort) : TYPE(&stsignedshort); - newtype->size = newtype->bitfieldtype->size; - return; - } - } - } -} - -ENode *CClass_AccessMember(ENode *classexpr, Type *type, UInt32 qual, SInt32 offset) { - Type *innertype; - UInt32 flags; - - innertype = NULL; - - if (IS_TYPE_CLASS(classexpr->rtype) && (TYPE_CLASS(classexpr->rtype)->flags & CLASS_HANDLEOBJECT)) { - classexpr = makemonadicnode(classexpr, EINDIRECT); - classexpr->data.monadic->rtype = CDecl_NewPointerType(classexpr->rtype); - } - - if (IS_TYPE_BITFIELD(type)) { - innertype = TYPE_BITFIELD(type)->bitfieldtype; - CClass_OptimizeBitFieldAccess(&type, &offset); - } - - if (offset && !canadd(classexpr->data.monadic, offset)) { - classexpr->data.monadic = makediadicnode( - classexpr->data.monadic, - intconstnode(TYPE(&stunsignedlong), offset), - EADD); - optimizecomm(classexpr->data.monadic); - } - - if (innertype) { - if (IS_TYPE_BITFIELD(type)) { - classexpr->data.monadic = makemonadicnode(classexpr->data.monadic, EBITFIELD); - classexpr->data.monadic->rtype = type; - classexpr->rtype = TYPE_BITFIELD(type)->bitfieldtype; - } else { - classexpr->rtype = type; - } - } else { - classexpr->rtype = type; - } - - classexpr->rtype = CClass_CombineClassAccessQualifiers(classexpr->rtype, qual, ENODE_QUALS(classexpr), &flags); - classexpr->flags = flags; - return classexpr; -} diff --git a/compiler_and_linker/unsorted/CCompiler.c b/compiler_and_linker/unsorted/CCompiler.c index 1eb6cd0..ed57c25 100644 --- a/compiler_and_linker/unsorted/CCompiler.c +++ b/compiler_and_linker/unsorted/CCompiler.c @@ -4,7 +4,7 @@ #include "compiler/CompilerTools.h" #include "compiler/CodeGen.h" #include "compiler/CodeGenOptPPC.h" -#include "compiler/IrOptimizer.h" +#include "../FrontEnd/Optimizer/IrOptimizer.h" #include "compiler/types.h" #include "pref_structs.h" diff --git a/compiler_and_linker/unsorted/CDecl.c b/compiler_and_linker/unsorted/CDecl.c deleted file mode 100644 index 43ca92e..0000000 --- a/compiler_and_linker/unsorted/CDecl.c +++ /dev/null @@ -1,4845 +0,0 @@ -#include "compiler/CDecl.h" -#include "compiler/CABI.h" -#include "compiler/CBrowse.h" -#include "compiler/CClass.h" -#include "compiler/CError.h" -#include "compiler/CException.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInit.h" -#include "compiler/CInline.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CObjC.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CSOM.h" -#include "compiler/CTemplateClass.h" -#include "compiler/CTemplateFunc.h" -#include "compiler/CTemplateNew.h" -#include "compiler/CTemplateTools.h" -#include "compiler/CompilerTools.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/templates.h" -#include "compiler/tokens.h" - -AccessType global_access; -FileOffsetInfo member_fileoffset; - -// forward declarations -static void scandirectdecl1(DeclInfo *declinfo); - -Type *CDecl_NewStructType(SInt32 size, SInt16 align) { - TypeStruct *tstruct = galloc(sizeof(TypeStruct)); - memclrw(tstruct, sizeof(TypeStruct)); - - tstruct->type = TYPESTRUCT; - tstruct->size = size; - tstruct->align = align; - tstruct->stype = STRUCT_TYPE_STRUCT; - - return (Type *) tstruct; -} - -Type *CDecl_NewArrayType(Type *type, SInt32 size) { - TypePointer *tarray = galloc(sizeof(TypePointer)); - memclrw(tarray, sizeof(TypePointer)); - - tarray->type = TYPEARRAY; - tarray->size = size; - tarray->target = type; - tarray->qual = 0; - - return (Type *) tarray; -} - -Type *CDecl_NewPointerType(Type *type) { - TypePointer *tptr = galloc(sizeof(TypePointer)); - memclrw(tptr, sizeof(TypePointer)); - - tptr->type = TYPEPOINTER; - tptr->size = 4; - tptr->target = type; - - return (Type *) tptr; -} - -Type *CDecl_NewRefPointerType(Type *type) { - TypePointer *tptr = galloc(sizeof(TypePointer)); - memclrw(tptr, sizeof(TypePointer)); - - tptr->type = TYPEPOINTER; - tptr->size = 4; - tptr->target = type; - tptr->qual = Q_REFERENCE; - - return (Type *) tptr; -} - -Type *CDecl_NewTemplDepType(TypeTemplDepType tdt) { - TypeTemplDep *t = galloc(sizeof(TypeTemplDep)); - memclrw(t, sizeof(TypeTemplDep)); - - t->type = TYPETEMPLATE; - t->size = 1; - t->dtype = tdt; - - return (Type *) t; -} - -void CDecl_SetResultReg(TypeFunc *tfunc) { -} - -static void CDecl_SetFuncResultReg(TypeFunc *tfunc) { -} - -void CDecl_SetFuncFlags(TypeFunc *tfunc, UInt32 flags) { - CDecl_SetResultReg(tfunc); -} - -static void CDecl_ParseCPPFuncDecl(TypeFunc *tfunc) { - for (;;) { - if (tk == TK_CONST) { - if (tfunc->flags & FUNC_CONST) - CError_Warning(CErrorStr313, "const"); - tfunc->flags |= FUNC_CONST; - tk = lex(); - } else if (tk == TK_VOLATILE) { - if (tfunc->flags & FUNC_VOLATILE) - CError_Warning(CErrorStr313, "volatile"); - tfunc->flags |= FUNC_VOLATILE; - tk = lex(); - } else { - break; - } - } - - if (tk == TK_THROW) - CExcept_ScanExceptionSpecification(tfunc); -} - -void CDecl_NewConvFuncType(DeclInfo *declinfo) { - TypeFunc *tfunc; - - if (tk != '(') - CError_Error(CErrorStr114); - else - tk = lex(); - - if (tk == TK_VOID) - tk = lex(); - - if (tk != ')') - CError_Error(CErrorStr115); - else - tk = lex(); - - tfunc = galloc(sizeof(TypeFunc)); - memclrw(tfunc, sizeof(TypeFunc)); - declinfo->name = CMangler_ConversionFuncName(declinfo->thetype, declinfo->qual); - tfunc->type = TYPEFUNC; - tfunc->functype = declinfo->thetype; - tfunc->qual = declinfo->qual & (Q_CONST | Q_VOLATILE); - tfunc->flags = FUNC_CONVERSION; - declinfo->x49 = 0; - CDecl_SetFuncFlags(tfunc, 1); - CDecl_ParseCPPFuncDecl(tfunc); - - declinfo->thetype = (Type *) tfunc; - declinfo->qual &= ~(Q_CONST | Q_VOLATILE); - declinfo->storageclass = 0; -} - -void CDecl_CompleteType(Type *type) { - switch (type->type) { - case TYPEPOINTER: - if ((TYPE_POINTER(type)->qual & Q_REFERENCE) && IS_TYPE_CLASS(TYPE_POINTER(type)->target)) { - type = TYPE_POINTER(type)->target; - break; - } - return; - case TYPEARRAY: - do { - type = TYPE_POINTER(type)->target; - } while (IS_TYPE_ARRAY(type)); - if (IS_TYPE_CLASS(type)) - break; - return; - case TYPECLASS: - break; - default: - return; - } - - if ((TYPE_CLASS(type)->flags & (CLASS_COMPLETED | CLASS_IS_TEMPL_INST)) == CLASS_IS_TEMPL_INST) - CTempl_InstantiateTemplateClass(TYPE_CLASS(type)); -} - -Boolean IsCompleteType(Type *type) { - switch (type->type) { - case TYPEVOID: - CError_Error(CErrorStr126); - return 0; - case TYPEFUNC: - CError_Error(CErrorStr146); - return 0; - case TYPESTRUCT: - if (!type->size) { - CError_Error(CErrorStr136, type, 0); - return 0; - } - return 1; - case TYPECLASS: - if ( - !(TYPE_CLASS(type)->flags & CLASS_COMPLETED) && - ( - !(TYPE_CLASS(type)->flags & CLASS_IS_TEMPL_INST) || - !CTempl_InstantiateTemplateClass(TYPE_CLASS(type)) - ) - ) - { - CError_Error(CErrorStr136, type, 0); - return 0; - } - return 1; - default: - if (!type->size) { - CError_Error(CErrorStr145); - return 0; - } - return 1; - } -} - -Boolean CanAllocObject(Type *type) { - switch (type->type) { - case TYPEVOID: - CError_Error(CErrorStr126); - return 0; - case TYPEFUNC: - CError_Error(CErrorStr146); - return 0; - case TYPECLASS: - if (TYPE_CLASS(type)->flags & CLASS_ABSTRACT) { - CError_AbstractClassError(TYPE_CLASS(type)); - return 0; - } - default: - return 1; - } -} - -Boolean CanCreateObject(Type *type) { - if (!CanAllocObject(type)) - return 0; - - if (IS_TYPE_CLASS(type)) { - if (TYPE_CLASS(type)->flags & CLASS_HANDLEOBJECT) { - CError_Error(CErrorStr191); - return 0; - } - if (TYPE_CLASS(type)->objcinfo) { - CError_Error(CErrorStr307); - return 0; - } - } - - return 1; -} - -static Boolean CanCreateHandleMemberObject(Type *type) { - while (IS_TYPE_ARRAY(type)) - type = TYPE_POINTER(type)->target; - - if (!CanCreateObject(type)) - return 0; - - if (IS_TYPE_CLASS(type)) { - if (CClass_Destructor(TYPE_CLASS(type)) || CClass_Constructor(TYPE_CLASS(type))) { - CError_Error(CErrorStr191); - return 0; - } - } - - return 1; -} - -void makethetypepointer(DeclInfo *declinfo, UInt32 qual) { - declinfo->thetype = CDecl_NewPointerType(declinfo->thetype); - TYPE_POINTER(declinfo->thetype)->qual = qual; -} - -void CDecl_AddThisPointerArgument(TypeFunc *tfunc, TypeClass *tclass) { - Type *ptype; - FuncArg *arg; - - ptype = CDecl_NewPointerType(!tclass->sominfo ? (Type *) tclass : &stvoid); - TYPE_POINTER(ptype)->qual = Q_CONST; - - arg = CParser_NewFuncArg(); - arg->name = this_name_node; - arg->type = ptype; - if (tfunc->flags & FUNC_CONST) - arg->qual |= Q_CONST; - if (tfunc->flags & FUNC_VOLATILE) - arg->qual |= Q_VOLATILE; - arg->next = tfunc->args; - tfunc->args = arg; -} - -void CDecl_MakePTMFuncType(TypeFunc *tfunc) { - Type *cvoidp; - FuncArg *arg1; - FuncArg *arg2; - - cvoidp = CDecl_NewPointerType(&stvoid); - TYPE_POINTER(cvoidp)->qual = Q_CONST; - - arg1 = CParser_NewFuncArg(); - arg1->name = this_name_node; - arg1->type = cvoidp; - if (tfunc->flags & FUNC_CONST) - arg1->qual |= Q_CONST; - if (tfunc->flags & FUNC_VOLATILE) - arg1->qual |= Q_VOLATILE; - - arg2 = CParser_NewFuncArg(); - arg2->name = this_name_node; - arg2->type = cvoidp; - arg2->qual = Q_CONST; - - arg1->next = tfunc->args; - arg2->next = arg1; - tfunc->args = arg2; - tfunc->flags |= FUNC_FLAGS_80; -} - -void CDecl_AddArgument(TypeFunc *tfunc, Type *argtype) { - FuncArg *arg = CParser_NewFuncArg(); - arg->type = argtype; - - arg->next = tfunc->args; - tfunc->args = arg; - - if (arg->next && arg->next->type == &stvoid) - arg->next = NULL; -} - -Boolean CDecl_CheckArrayIntegr(Type *type) { - if (!IsCompleteType(type)) - return 0; - - if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo) { - CError_Error(CErrorStr289); - return 0; - } - - if (IS_TYPE_REFERENCE(type)) { - CError_Error(CErrorStr196); - return 0; - } - - return CanCreateObject(type); -} - -static Boolean checkfuncintegr(Type *type) { - if (IS_TYPE_VOID(type)) - return 1; - - if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo) { - CError_Error(CErrorStr283); - return 0; - } - - return CanCreateObject(type); -} - -void CDecl_ParseDirectFuncDecl(DeclInfo *declinfo) { - FuncArg *list; - TypeFunc *tfunc; - - if (tk == ')') { - if (copts.cplusplus) - list = NULL; - else - list = &oldstyle; - tk = lex(); - } else { - list = parameter_type_list(declinfo); - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - } - - tfunc = galloc(sizeof(TypeFunc)); - memclrw(tfunc, sizeof(TypeFunc)); - tfunc->type = TYPEFUNC; - tfunc->args = list; - if (declinfo->qual & Q_PASCAL) { - declinfo->qual &= ~Q_PASCAL; - tfunc->flags = FUNC_PASCAL; - } - - if (copts.cplusplus) { - CDecl_ParseCPPFuncDecl(tfunc); - if (declinfo->storageclass == TK_TYPEDEF && tfunc->exspecs) - CError_Error(CErrorStr264); - } - - scandirectdecl1(declinfo); - if (!checkfuncintegr(declinfo->thetype)) - declinfo->thetype = &stvoid; - - tfunc->functype = declinfo->thetype; - tfunc->qual = declinfo->qual & (Q_CONST | Q_VOLATILE); - declinfo->thetype = (Type *) tfunc; - declinfo->qual &= ~(Q_CONST | Q_VOLATILE); - declinfo->x49 = 0; -} - -static void scandirectdecl1(DeclInfo *declinfo) { - Boolean flag; - CInt64 len; - ENode *expr; - TypeTemplDep *ttempl; - - flag = 0; - if (tk == '[') { - if ((tk = lex()) == ']') { - len = cint64_zero; - tk = lex(); - flag = 1; - } else { - if (!declinfo->x46 || declinfo->x47) { - expr = CExpr_IntegralConstOrDepExpr(); - if (!ENODE_IS(expr, EINTCONST)) { - if (tk != ']') - CError_ErrorSkip(CErrorStr125); - else - tk = lex(); - declinfo->x47 = 1; - scandirectdecl1(declinfo); - if (!CDecl_CheckArrayIntegr(declinfo->thetype)) - declinfo->thetype = (Type *) &stsignedchar; - ttempl = (TypeTemplDep *) CDecl_NewTemplDepType(TEMPLDEP_ARRAY); - ttempl->u.array.type = declinfo->thetype; - ttempl->u.array.index = CInline_CopyExpression(expr, CopyMode1); - declinfo->thetype = (Type *) ttempl; - return; - } - len = expr->data.intval; - if (CInt64_IsNegative(&len)) { - CError_Error(CErrorStr124); - len = cint64_one; - } else if (CInt64_IsZero(&len)) { - if (!copts.ANSIstrict && declinfo->x50) { - flag = 1; - } else { - CError_Error(CErrorStr124); - len = cint64_one; - } - } - } else { - len = cint64_one; - expr = expression(); - if (IS_TYPE_INT(expr->rtype)) { - if (!ENODE_IS(expr, EINTCONST)) - declinfo->x24 = expr; - else - len = expr->data.intval; - } else { - CError_Error(CErrorStr124); - } - } - - if (tk != ']') - CError_ErrorSkip(CErrorStr125); - else - tk = lex(); - } - - declinfo->x47 = 1; - scandirectdecl1(declinfo); - - if (!flag && !CDecl_CheckArrayIntegr(declinfo->thetype)) - declinfo->thetype = (Type *) &stsignedchar; - - if (!declinfo->thetype->size && CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) { - ttempl = (TypeTemplDep *) CDecl_NewTemplDepType(TEMPLDEP_ARRAY); - ttempl->u.array.type = declinfo->thetype; - ttempl->u.array.index = CInline_CopyExpression(intconstnode((Type *) &stsignedint, CInt64_GetULong(&len)), CopyMode1); - declinfo->thetype = (Type *) ttempl; - } else { - declinfo->thetype = CDecl_NewArrayType(declinfo->thetype, declinfo->thetype->size * CInt64_GetULong(&len)); - } - } else if (tk == '(') { - if (!copts.cplusplus || !declinfo->name || IS_TYPE_VOID(declinfo->thetype) || CParser_TryParamList(!IS_TYPE_CLASS(declinfo->thetype))) { - tk = lex(); - CDecl_ParseDirectFuncDecl(declinfo); - } - } -} - -static void substitute_type(Type *type1, Type *type2) { - SInt32 oldsize; - - while (1) { - switch (type1->type) { - case TYPEPOINTER: - if (TYPE_POINTER(type1)->target == &stillegal) { - TYPE_POINTER(type1)->target = type2; - type1->size = 4; - return; - } - type1 = TYPE_POINTER(type1)->target; - break; - case TYPEMEMBERPOINTER: - if (TYPE_MEMBER_POINTER(type1)->ty1 == &stillegal) { - TYPE_MEMBER_POINTER(type1)->ty1 = type2; - if (IS_TYPE_FUNC(type2)) { - CDecl_MakePTMFuncType(TYPE_FUNC(type2)); - type1->size = 12; - } else { - type1->size = 4; - } - return; - } - type1 = TYPE_MEMBER_POINTER(type1)->ty1; - break; - case TYPEARRAY: - if (TYPE_POINTER(type1)->target == &stillegal) { - if (!CDecl_CheckArrayIntegr(type2)) - type2 = (Type *) &stsignedchar; - type1->size *= type2->size; - TYPE_POINTER(type1)->target = type2; - return; - } - oldsize = TYPE_POINTER(type1)->target->size; - substitute_type(TYPE_POINTER(type1)->target, type2); - if (oldsize != TYPE_POINTER(type1)->target->size && oldsize != 0) - type1->size = TYPE_POINTER(type1)->target->size * (type1->size / oldsize); - return; - case TYPEFUNC: - if (TYPE_FUNC(type1)->functype == &stillegal) { - if (!checkfuncintegr(type2)) - type2 = &stvoid; - TYPE_FUNC(type1)->functype = type2; - CDecl_SetFuncResultReg((TypeFunc *) type1); - return; - } - type1 = TYPE_FUNC(type1)->functype; - break; - case TYPETEMPLATE: - if (TYPE_TEMPLATE(type1)->dtype == TEMPLDEP_ARRAY) { - if (TYPE_TEMPLATE(type1)->u.array.type == &stillegal) { - if (!CDecl_CheckArrayIntegr(type2)) - type2 = (Type *) &stsignedchar; - TYPE_TEMPLATE(type1)->u.array.type = type2; - return; - } - type1 = TYPE_TEMPLATE(type1)->u.array.type; - } else { - CError_Error(CErrorStr146); - return; - } - break; - default: - CError_Error(CErrorStr121); - return; - } - } -} - -static void scandecl(DeclInfo *declinfo) { - Type *oldtype; - Type *newtype; - - oldtype = declinfo->thetype; - declinfo->thetype = &stillegal; - scandeclarator(declinfo); - - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - - newtype = declinfo->thetype; - if (newtype == &stillegal) { - declinfo->thetype = oldtype; - scandirectdecl1(declinfo); - } else { - declinfo->thetype = oldtype; - scandirectdecl1(declinfo); - substitute_type(newtype, declinfo->thetype); - declinfo->thetype = newtype; - } -} - -static Boolean CDecl_ParseOperatorDecl(DeclInfo *declinfo) { - if (declinfo->operator_token) { - CError_Error(CErrorStr121); - return 0; - } - - declinfo->operator_token = 0; - if (!CParser_ParseOperatorName(&declinfo->operator_token, declinfo->x4A && cscope_current->theclass, 0)) - return 0; - - if (!declinfo->operator_token) { - conversion_type_name(declinfo); - tkidentifier = CMangler_ConversionFuncName(declinfo->thetype, declinfo->qual); - declinfo->x54 = 1; - } - return 1; -} - -static Boolean CDecl_IsEnumClassTypeOrRef(Type *type) { - if (IS_TYPE_CLASS(type) || IS_TYPE_ENUM(type)) - return 1; - if (!IS_TYPE_REFERENCE(type)) - return 0; - type = TYPE_POINTER(type)->target; - return IS_TYPE_CLASS(type) || IS_TYPE_ENUM(type); -} - -static Boolean CDecl_CheckOperatorType(DeclInfo *declinfo, Boolean flag) { - FuncArg *args; - FuncArg *secondarg; - Type *functype; - short argCount; - Boolean isMethod; - - if (!IS_TYPE_FUNC(declinfo->thetype)) { - CError_Error(CErrorStr193); - return 0; - } - - functype = TYPE_FUNC(declinfo->thetype)->functype; - args = TYPE_FUNC(declinfo->thetype)->args; - if (args) { - if (args != &elipsis && args != &oldstyle) { - argCount = 1; - if (args->dexpr) { - switch (declinfo->operator_token) { - case TK_NEW: - case TK_DELETE: - case TK_NEW_ARRAY: - case TK_DELETE_ARRAY: - break; - default: - CError_Error(CErrorStr205); - } - } - - secondarg = args->next; - if (secondarg) { - argCount = ((secondarg != &elipsis && !secondarg->next) != 0) ? 2 : 3; - if (secondarg->dexpr) { - switch (declinfo->operator_token) { - case '(': - case TK_NEW: - case TK_DELETE: - case TK_NEW_ARRAY: - case TK_DELETE_ARRAY: - break; - default: - CError_Error(CErrorStr205); - } - } - } - } else { - argCount = 3; - } - } else { - CError_Error(CErrorStr193); - return 0; - } - - isMethod = flag && - IS_TYPEFUNC_METHOD(TYPE_FUNC(declinfo->thetype)) && - !TYPE_METHOD(declinfo->thetype)->is_static; - - switch (declinfo->operator_token) { - case TK_NEW: - case TK_NEW_ARRAY: - if (isMethod || !is_typesame(functype, TYPE(&void_ptr)) || argCount < 1 || args->type != CABI_GetSizeTType()) { - CError_Error(CErrorStr193); - return 0; - } - return 1; - case TK_DELETE: - case TK_DELETE_ARRAY: - if (isMethod || !IS_TYPE_VOID(functype) || argCount < 1 || !is_typesame(args->type, TYPE(&void_ptr))) { - CError_Error(CErrorStr193); - return 0; - } - return 1; - case '=': - if (!isMethod) { - CError_Error(CErrorStr193); - return 0; - } - break; - case '(': - if (!isMethod) { - CError_Error(CErrorStr193); - return 0; - } - return 1; - case '[': - if (!isMethod) { - CError_Error(CErrorStr193); - return 0; - } - break; - case TK_ARROW: - if (argCount != 1 || isMethod == 0) { - CError_Error(CErrorStr193); - return 0; - } - return 1; - case TK_INCREMENT: - case TK_DECREMENT: - if (argCount == 2 && secondarg->type != TYPE(&stsignedint)) { - CError_Error(CErrorStr193); - return 0; - } - break; - } - - if (flag && !isMethod) { - CError_Error(CErrorStr193); - return 0; - } - - switch (declinfo->operator_token) { - case '&': - case '*': - case '+': - case '-': - case TK_INCREMENT: - case TK_DECREMENT: - if (argCount != 1) - goto whatever; - case '!': - case '~': - if (argCount == 1) { - if (flag || CDecl_IsEnumClassTypeOrRef(args->type)) - return 1; - } - break; - case '%': - case ',': - case '/': - case '<': - case '=': - case '>': - case '[': - case '^': - case '|': - case TK_MULT_ASSIGN: - case TK_DIV_ASSIGN: - case TK_MOD_ASSIGN: - case TK_ADD_ASSIGN: - case TK_SUB_ASSIGN: - case TK_SHL_ASSIGN: - case TK_SHR_ASSIGN: - case TK_AND_ASSIGN: - case TK_XOR_ASSIGN: - case TK_OR_ASSIGN: - case TK_LOGICAL_OR: - case TK_LOGICAL_AND: - case TK_LOGICAL_EQ: - case TK_LOGICAL_NE: - case TK_LESS_EQUAL: - case TK_GREATER_EQUAL: - case TK_SHL: - case TK_SHR: - case TK_ARROW: - case TK_DOT_STAR: - case TK_ARROW_STAR: - whatever: - if (argCount == 2) { - if (flag || CDecl_IsEnumClassTypeOrRef(args->type) || CDecl_IsEnumClassTypeOrRef(secondarg->type)) - return 1; - } - break; - } - - CError_Error(CErrorStr193); - return 0; -} - -static void scandirectdeclarator(DeclInfo *declinfo, NameSpace *nspace) { - HashNameNode *saveident; - CScopeSave scopesave; - Boolean flag; - - if (nspace) - CScope_SetNameSpaceScope(nspace, &scopesave); - - if (tk == '(') { - if ((tk = lex()) == ')') { - if (declinfo->x55) { - CDecl_ParseDirectFuncDecl(declinfo); - if (nspace) - CScope_RestoreScope(&scopesave); - return; - } else { - CError_Error(CErrorStr121); - if (nspace) - CScope_RestoreScope(&scopesave); - return; - } - } - - if (!(tk >= TK_AUTO && tk <= TK_BYREF)) { - if (!(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) { - scandecl(declinfo); - if (nspace) - CScope_RestoreScope(&scopesave); - return; - } else { - saveident = tkidentifier; - switch (lookahead()) { - case ')': - case ',': - break; - default: - tkidentifier = saveident; - scandecl(declinfo); - if (nspace) - CScope_RestoreScope(&scopesave); - return; - } - } - } - - if (declinfo->name) - CError_Error(CErrorStr121); - - CDecl_ParseDirectFuncDecl(declinfo); - if (nspace) - CScope_RestoreScope(&scopesave); - return; - } - - if (nspace) { - if (tk == TK_OPERATOR) { - if (!CDecl_ParseOperatorDecl(declinfo)) { - CScope_RestoreScope(&scopesave); - return; - } - - if (declinfo->x54) { - declinfo->nspace = nspace; - declinfo->name = tkidentifier; - if (nspace) - CScope_RestoreScope(&scopesave); - - if (tk == '(') { - tk = lex(); - CDecl_ParseDirectFuncDecl(declinfo); - if (IS_TYPE_FUNC(declinfo->thetype)) - TYPE_FUNC(declinfo->thetype)->flags |= FUNC_CONVERSION; - else - CError_Error(CErrorStr121); - } else { - CError_Error(CErrorStr114); - } - return; - } - - flag = 1; - } else if (tk != TK_IDENTIFIER) { - CError_Error(CErrorStr107); - CScope_RestoreScope(&scopesave); - return; - } else { - flag = 0; - } - - if (declinfo->name) { - CError_Error(CErrorStr121); - CScope_RestoreScope(&scopesave); - return; - } - - declinfo->nspace = nspace; - declinfo->name = tkidentifier; - if (!flag) - tk = lex(); - } else if (tk == TK_IDENTIFIER) { - if (declinfo->name) - CError_Error(CErrorStr121); - declinfo->name = tkidentifier; - tk = lex(); - } else if (tk == TK_OPERATOR) { - if (!CDecl_ParseOperatorDecl(declinfo)) - return; - declinfo->name = tkidentifier; - } - - if (tk == '<' && declinfo->x51) { - declinfo->expltargs = CTempl_ParseUncheckTemplArgs(NULL, 0); - declinfo->has_expltargs = 1; - declinfo->x51 = 0; - tk = lex(); - } - - scandirectdecl1(declinfo); - - if (nspace) - CScope_RestoreScope(&scopesave); -} - -void makememberpointertype(DeclInfo *declinfo, TypeClass *tclass, UInt32 qual) { - TypeMemberPointer *tmemp; - TypeFunc *tfunc; - - if (tclass->flags & CLASS_HANDLEOBJECT) { - CError_Error(CErrorStr191); - declinfo->thetype = (Type *) &stsignedint; - return; - } - if (tclass->sominfo) { - CError_Error(CErrorStr290); - declinfo->thetype = (Type *) &stsignedint; - return; - } - - tmemp = galloc(sizeof(TypeMemberPointer)); - memclrw(tmemp, sizeof(TypeMemberPointer)); - tmemp->type = TYPEMEMBERPOINTER; - tmemp->ty2 = (Type *) tclass; - tmemp->qual = qual; - - if (IS_TYPE_FUNC(declinfo->thetype)) { - tfunc = galloc(sizeof(TypeFunc)); - *tfunc = *TYPE_FUNC(declinfo->thetype); - tmemp->ty1 = (Type *) tfunc; - tmemp->size = 12; - CDecl_MakePTMFuncType(tfunc); - } else { - tmemp->size = 4; - tmemp->ty1 = declinfo->thetype; - } - declinfo->thetype = (Type *) tmemp; -} - -void CDecl_ScanPointer(DeclInfo *declinfo, NameSpace *nspace, Boolean flag) { - NameResult pr; - UInt32 qual; - - while (1) { - qual = (tk == '&') ? Q_REFERENCE : 0; - - for (tk = lex(); ; tk = lex()) { - switch (tk) { - case TK_CONST: - if (qual & Q_CONST) - CError_Error(CErrorStr121); - qual |= Q_CONST; - continue; - case TK_VOLATILE: - if (qual & Q_VOLATILE) - CError_Error(CErrorStr121); - qual |= Q_VOLATILE; - continue; - case TK_RESTRICT: - if (qual & Q_RESTRICT) - CError_Error(CErrorStr121); - qual |= Q_RESTRICT; - continue; - default: - break; - } - break; - } - - if (IS_TYPE_REFERENCE(declinfo->thetype) || ((qual & Q_REFERENCE) && IS_TYPE_VOID(declinfo->thetype))) { - CError_Error(CErrorStr196); - return; - } - - if (nspace) { - makememberpointertype(declinfo, nspace->theclass, qual); - nspace = NULL; - } else { - makethetypepointer(declinfo, qual); - } - - switch (tk) { - case '*': - continue; - case '&': - if (!copts.cplusplus) { - if (flag) - scandirectdeclarator(declinfo, NULL); - return; - } - continue; - case TK_IDENTIFIER: - if (!copts.cplusplus) - break; - if (copts.cpp_extensions && cscope_current->theclass && cscope_current->theclass->classname == tkidentifier && lookahead() == TK_COLON_COLON) { - tk = lex(); - tk = lex(); - break; - } - case TK_COLON_COLON: - if (CScope_ParseQualifiedNameSpace(&pr, 1, 0)) { - if ((nspace = pr.nspace_0)) { - if (nspace->theclass && tk == '*') - continue; - } else { - if (pr.type && IS_TYPE_TEMPLATE(pr.type) && declinfo->x30) { - if (CTempl_IsQualifiedMember(declinfo, pr.type, &nspace)) - scandirectdeclarator(declinfo, nspace); - else - declinfo->x20 = pr.type; - return; - } - CError_Error(CErrorStr121); - } - } - break; - } - break; - } - - if (flag) - scandirectdeclarator(declinfo, nspace); -} - -static void CDecl_TemplatePTM(DeclInfo *declinfo, Type *type) { - TypeMemberPointer *tmemp = galloc(sizeof(TypeMemberPointer)); - tmemp->type = TYPEMEMBERPOINTER; - if (IS_TYPE_FUNC(declinfo->thetype)) { - CDecl_MakePTMFuncType((TypeFunc *) declinfo->thetype); - tmemp->size = 12; - } else { - tmemp->size = 4; - } - - tmemp->ty1 = declinfo->thetype; - tmemp->ty2 = type; - tmemp->qual = 0; - declinfo->thetype = (Type *) tmemp; -} - -void scandeclarator(DeclInfo *declinfo) { - NameResult pr; - NameSpace *nspace; - - switch (tk) { - case '&': - if (!copts.cplusplus) - break; - case '*': - CDecl_ScanPointer(declinfo, NULL, 1); - if (tk == TK_UU_ATTRIBUTE_UU) - CParser_ParseAttribute(NULL, declinfo); - return; - case TK_IDENTIFIER: - if (!copts.cplusplus) - break; - case TK_COLON_COLON: - if (CScope_ParseQualifiedNameSpace(&pr, 1, 0)) { - nspace = pr.nspace_0; - if (nspace) { - if (nspace->theclass && tk == '*') - CDecl_ScanPointer(declinfo, nspace, 1); - else - scandirectdeclarator(declinfo, nspace); - return; - } - if (pr.type && IS_TYPE_TEMPLATE(pr.type)) { - if (declinfo->x30 && CTempl_IsQualifiedMember(declinfo, pr.type, &nspace)) { - scandirectdeclarator(declinfo, nspace); - return; - } else if (declinfo->x30 && tk == TK_OPERATOR) { - declinfo->x20 = pr.type; - return; - } else if ((tk = lex()) == TK_COLON_COLON && (tk = lex()) == '*') { - CDecl_TemplatePTM(declinfo, pr.type); - tk = lex(); - break; - } else if (declinfo->x30) { - declinfo->x20 = pr.type; - return; - } - } - CError_Error(CErrorStr121); - } - break; - } - - scandirectdeclarator(declinfo, NULL); - if (tk == TK_UU_ATTRIBUTE_UU) - CParser_ParseAttribute(NULL, declinfo); -} - -void conversion_type_name(DeclInfo *declinfo) { - NameResult pr; - DeclInfo subdeclinfo; - - memclrw(&subdeclinfo, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&subdeclinfo, 0); - - switch (tk) { - case '&': - case '*': - CDecl_ScanPointer(&subdeclinfo, NULL, 0); - break; - case TK_IDENTIFIER: - case TK_COLON_COLON: - if (CScope_ParseQualifiedNameSpace(&pr, 0, 0)) { - if (pr.nspace_0 && pr.nspace_0->theclass && tk == '*') - CDecl_ScanPointer(&subdeclinfo, pr.nspace_0, 0); - else - CError_Error(CErrorStr121); - } - break; - } - - declinfo->name = subdeclinfo.name; - declinfo->thetype = subdeclinfo.thetype; - declinfo->qual |= subdeclinfo.qual; -} - -static void scaninlinefunc(Object *obj) { - short array[256]; - short r29; - CInt64 val; - - if (tk == '{') { - tk = lex(); - r29 = 0; - while (1) { - if (r29 >= 256) { - CError_Error(CErrorStr127); - r29 = 255; - } - val = CExpr_IntegralConstExpr(); - array[r29++] = CInt64_GetULong(&val); - if (tk != '}') { - if (tk != ',') - CError_Error(CErrorStr116); - tk = lex(); - } else { - tk = lex(); - break; - } - } - } else { - val = CExpr_IntegralConstExpr(); - array[0] = CInt64_GetULong(&val); - r29 = 1; - } - - obj->datatype = DINLINEFUNC; - obj->u.ifunc.size = r29 * 2; - obj->u.ifunc.data = galloc(obj->u.ifunc.size); - obj->u.ifunc.xrefs = NULL; - memcpy(obj->u.ifunc.data, array, obj->u.ifunc.size); - - if (tk != ';') - CError_Error(CErrorStr123); -} - -typedef enum { - OverloadMode0, - OverloadMode1, - OverloadMode2, - OverloadMode3 -} OverloadMode; - -static Object *CDecl_OverloadFunctionObject(NameSpaceObjectList *list, DeclInfo *declinfo, Boolean *outflag, OverloadMode mode, Boolean flag2) { - TypeFunc *scanfunc; - NameSpaceObjectList *scan; - TypeFunc *tfunc; - FuncArg *args; - FuncArg *scanargs; - Object *obj; - Boolean r24; - short compareresult; - - if (outflag) - *outflag = 0; - - tfunc = (TypeFunc *) declinfo->thetype; - args = tfunc->args; - r24 = 0; - for (scan = list; scan; scan = scan->next) { - obj = OBJECT(scan->object); - if (obj->otype != OT_OBJECT) - continue; - - scanfunc = TYPE_FUNC(obj->type); - if (!IS_TYPE_FUNC(scanfunc)) - continue; - - scanargs = scanfunc->args; - if (scanfunc->flags & FUNC_IS_TEMPL) - r24 = 1; - - if (IS_TYPEFUNC_METHOD(scanfunc)) { - switch (mode) { - case OverloadMode0: - CError_Error(CErrorStr197); - break; - case OverloadMode1: - if (!TYPE_METHOD(scanfunc)->is_static) - continue; - break; - case OverloadMode2: - if (TYPE_METHOD(scanfunc)->is_static) - continue; - break; - case OverloadMode3: - if (!TYPE_METHOD(scanfunc)->is_static) { - if (scanargs->qual & Q_CV) - continue; - scanargs = scanargs->next; - } - break; - } - } else { - if (mode) - CError_Error(CErrorStr197); - } - - compareresult = CParser_CompareArgLists(args, scanargs); - if (compareresult == 1) { - if (scanfunc->flags & FUNC_CONVERSION) { - if (!(tfunc->flags & FUNC_CONVERSION)) { - CError_Error(CErrorStr197); - break; - } - if (!is_typesame(tfunc->functype, scanfunc->functype)) - continue; - if ((tfunc->qual & Q_CV) != (scanfunc->qual & Q_CV)) - continue; - if ((tfunc->flags & FUNC_CALL_CONV_MASK) != (scanfunc->flags & FUNC_CALL_CONV_MASK)) { - CError_Error(CErrorStr197); - break; - } - if (tfunc->exspecs || scanfunc->exspecs) - CExcept_CompareSpecifications(tfunc->exspecs, scanfunc->exspecs); - return obj; - } - - if (tfunc->flags & FUNC_CONVERSION) { - CError_Error(CErrorStr197); - break; - } - - if ( - !is_typesame(tfunc->functype, scanfunc->functype) || - ((tfunc->qual & (Q_CONST | Q_PASCAL)) != (scanfunc->qual & (Q_CONST | Q_PASCAL))) || - ((tfunc->flags & FUNC_CALL_CONV_MASK) != (scanfunc->flags & FUNC_CALL_CONV_MASK)) - ) - { - CError_Error(CErrorStr197); - break; - } - - if (tfunc->exspecs || scanfunc->exspecs) { - if (obj->name != newp_fobj->name && obj->name != newa_fobj->name && obj->name != delp_fobj->name && obj->name != dela_fobj->name) - CExcept_CompareSpecifications(tfunc->exspecs, scanfunc->exspecs); - } - - return obj; - } else if (compareresult == 2) { - CError_Error(CErrorStr197); - break; - } - } - - if (r24 && (flag2 || declinfo->x3C)) { - if ((obj = CTempl_TemplateFunctionCheck(declinfo, list))) - return obj; - } - - if (!outflag) { - CError_Error(CErrorStr197); - return NULL; - } - - if (declinfo->nspace) - CError_Error(CErrorStr336); - - *outflag = 1; - obj = CParser_NewFunctionObject(declinfo); - CheckDefaultArgs(TYPE_FUNC(obj->type)->args); - - if (tfunc->flags & FUNC_PASCAL) { - for (scan = list; scan; scan = scan->next) { - if (scan->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(scan->object)->type)) { - if (TYPE_FUNC(OBJECT(scan->object)->type)->flags & FUNC_PASCAL) - CError_Error(CErrorStr226); - } - } - } - - if (copts.cplusplus && declinfo->is_extern_c) { - for (scan = list; scan; scan = scan->next) { - if (scan->object->otype == OT_OBJECT && !(OBJECT(scan->object)->qual & Q_MANGLE_NAME)) - CError_Error(CErrorStr197); - } - } - - CScope_AddObject(cscope_current, declinfo->name, OBJ_BASE(obj)); - if (cscope_current->theclass && (cscope_current->theclass->flags & CLASS_IS_TEMPL) && - CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) - CTemplClass_RegisterObjectDef(TEMPL_CLASS(cscope_current->theclass), OBJ_BASE(obj)); - - return obj; -} - -void MergeDefaultArgs(FuncArg *a, FuncArg *b) { - FuncArg *scan_a; - FuncArg *scan_b; - - if (a == &oldstyle || b == &oldstyle) - return; - - scan_a = a; - scan_b = b; - while (scan_a && scan_b) { - if (scan_a->dexpr) { - while (scan_b) { - if (scan_b->dexpr) { - while (a) { - a->dexpr = NULL; - a = a->next; - } - while (b) { - b->dexpr = NULL; - b = b->next; - } - CError_Error(CErrorStr205); - return; - } - scan_b = scan_b->next; - } - break; - } else if (scan_b->dexpr) { - do { - scan_a = scan_a->next; - scan_b = scan_b->next; - if (!scan_a) goto secondpart; - if (scan_a == &elipsis) goto secondpart; - if (scan_a->dexpr && scan_b->dexpr) break; - } while (scan_a->dexpr || scan_b->dexpr); - - while (a) { - a->dexpr = NULL; - a = a->next; - } - while (b) { - b->dexpr = NULL; - b = b->next; - } - CError_Error(CErrorStr205); - return; - } else { - scan_a = scan_a->next; - scan_b = scan_b->next; - } - } - -secondpart: - while (a && b) { - if (b->dexpr) - a->dexpr = b->dexpr; - else - b->dexpr = a->dexpr; - a = a->next; - b = b->next; - } -} - -void CheckDefaultArgs(FuncArg *args) { - FuncArg *scan; - - scan = args; - while (scan && !scan->dexpr) - scan = scan->next; - - while (scan && scan != &elipsis && scan != &oldstyle) { - if (!scan->dexpr) { - while (args) { - args->dexpr = NULL; - args = args->next; - } - CError_Error(CErrorStr205); - return; - } - scan = scan->next; - } -} - -static void CDecl_FuncRedeclCheck(Object *obj, DeclInfo *declinfo, Boolean flag) { - if (declinfo->storageclass == TK_STATIC && obj->sclass != TK_STATIC) { - if (copts.cplusplus) - CError_Error(CErrorStr260); - else - obj->sclass = TK_STATIC; - } - - obj->qual |= declinfo->qual; - if (flag) - CheckDefaultArgs(TYPE_FUNC(obj->type)->args); - else - MergeDefaultArgs(TYPE_FUNC(obj->type)->args, TYPE_FUNC(declinfo->thetype)->args); - - if (!declinfo->x45) - TYPE_FUNC(obj->type)->args = TYPE_FUNC(declinfo->thetype)->args; -} - -Object *CDecl_GetFunctionObject(DeclInfo *declinfo, NameSpace *nspace, Boolean *pflag, Boolean someotherflag) { - NameSpace *nspace2; - Type *type; - Object *obj; - NameSpaceObjectList *list; - TypeMemberFunc tmp; - Boolean r27; - Boolean outflag; - - r27 = 0; - if (pflag) - *pflag = 0; - - nspace2 = declinfo->nspace; - if (!nspace2) - nspace2 = cscope_current; - - CError_QualifierCheck(declinfo->qual & ~(Q_ALIGNED_MASK | Q_WEAK | Q_20000 | Q_INLINE | Q_PASCAL | Q_ASM | Q_VOLATILE | Q_CONST)); - switch (TYPE_FUNC(declinfo->thetype)->functype->type) { - case TYPEFUNC: - case TYPEARRAY: - CError_Error(CErrorStr128); - TYPE_FUNC(declinfo->thetype)->functype = TYPE(&stsignedint); - break; - } - - if (nspace2->theclass) { - CError_ASSERT(1969, declinfo->name); - if (!nspace2->theclass->size) - CDecl_CompleteType(TYPE(nspace2->theclass)); - if (!(list = CScope_GetLocalObject(nspace2, declinfo->name))) { - CError_Error(CErrorStr140, declinfo->name->name); - return NULL; - } - - obj = OBJECT(list->object); - type = obj->type; - if (!IS_TYPE_FUNC(type)) { - CError_Error(CErrorStr249, CError_GetObjectName(obj), type, obj->qual, declinfo->thetype, declinfo->qual); - return NULL; - } - - if (declinfo->has_expltargs) - return CTempl_TemplateFunctionCheck(declinfo, list); - - if (declinfo->x3C || (list->next && list->next->object->otype == OT_OBJECT)) { - if (TYPE_FUNC(declinfo->thetype)->flags & (FUNC_CONST | FUNC_VOLATILE)) { - CDecl_AddThisPointerArgument(TYPE_FUNC(declinfo->thetype), nspace2->theclass); - obj = CDecl_OverloadFunctionObject(list, declinfo, NULL, OverloadMode2, someotherflag); - if (!obj) - return NULL; - } else { - obj = CDecl_OverloadFunctionObject(list, declinfo, NULL, OverloadMode3, someotherflag); - if (!obj) - return NULL; - if (!TYPE_METHOD(obj->type)->is_static) - CDecl_AddThisPointerArgument(TYPE_FUNC(declinfo->thetype), nspace2->theclass); - } - } else { - if (TYPE_METHOD(type)->is_static) { - if (nspace2->theclass->sominfo) - CSOM_FixNewDeleteFunctype(TYPE_FUNC(declinfo->thetype)); - } else { - CDecl_AddThisPointerArgument(TYPE_FUNC(declinfo->thetype), nspace2->theclass); - } - - if (copts.cpp_extensions) { - declinfo->qual |= obj->qual & (Q_PASCAL | Q_CONST); - TYPE_FUNC(declinfo->thetype)->qual |= TYPE_FUNC(obj->type)->qual & (Q_PASCAL | Q_CONST); - TYPE_FUNC(declinfo->thetype)->flags |= TYPE_FUNC(obj->type)->flags & (FUNC_FLAGS_4000000 | FUNC_FLAGS_10000000); - } - - if (!is_typesame(declinfo->thetype, obj->type) || (declinfo->qual & (Q_PASCAL | Q_CONST)) != (obj->qual & (Q_PASCAL | Q_CONST))) { - tmp = *TYPE_METHOD(obj->type); - *(TYPE_FUNC(&tmp)) = *TYPE_FUNC(declinfo->thetype); - tmp.flags |= FUNC_METHOD; - CError_Error(CErrorStr249, CError_GetObjectName(obj), obj->type, obj->qual, &tmp, declinfo->qual); - } - - if (TYPE_FUNC(declinfo->thetype)->exspecs || TYPE_FUNC(obj->type)->exspecs) - CExcept_CompareSpecifications(TYPE_FUNC(declinfo->thetype)->exspecs, TYPE_FUNC(obj->type)->exspecs); - } - - CDecl_FuncRedeclCheck(obj, declinfo, 0); - if (declinfo->x3C) { - if (obj->nspace->theclass && !(obj->nspace->theclass->flags & CLASS_IS_TEMPL_INST)) - CError_Error(CErrorStr335); - declinfo->x3C = 0; - } - } else { - if (TYPE_FUNC(declinfo->thetype)->flags & (FUNC_VOLATILE | FUNC_CONST)) - CError_Error(CErrorStr384); - - if (declinfo->operator_token && !CDecl_CheckOperatorType(declinfo, 0)) - return NULL; - - list = CScope_GetLocalObject(nspace2, declinfo->name); - if (declinfo->has_expltargs) - return CTempl_TemplateFunctionCheck(declinfo, list); - - if (list) { - if (copts.cplusplus) { - obj = CDecl_OverloadFunctionObject(list, declinfo, &outflag, OverloadMode0, someotherflag); - if (!obj) - return NULL; - if (pflag) - *pflag = outflag; - if (nspace) - obj->nspace = nspace; - } else { - obj = OBJECT(list->object); - if (!is_typesame(declinfo->thetype, obj->type) || (declinfo->qual & (Q_CONST | Q_PASCAL)) != (obj->qual & (Q_CONST | Q_PASCAL))) { - CError_Error(CErrorStr249, CError_GetObjectName(obj), obj->type, obj->qual, declinfo->thetype, declinfo->qual); - r27 = 1; - if (!IS_TYPE_FUNC(obj->type)) - return NULL; - } - } - - if (!r27 && pflag) - CDecl_FuncRedeclCheck(obj, declinfo, *pflag); - } else { - if (declinfo->nspace) - CError_Error(CErrorStr336); - - if (declinfo->has_expltargs) { - if (declinfo->name) - CError_Error(CErrorStr140, declinfo->name->name); - else - CError_Error(CErrorStr127); - } - - obj = CParser_NewFunctionObject(declinfo); - if (nspace) - obj->nspace = nspace; - if (pflag) - *pflag = 1; - else - CError_Error(CErrorStr127); - - CheckDefaultArgs(TYPE_FUNC(obj->type)->args); - CScope_AddObject(nspace2, declinfo->name, OBJ_BASE(obj)); - } - } - - return obj; -} - -void CDecl_TypedefDeclarator(DeclInfo *declinfo) { - NameSpace *nspace; - NameSpaceObjectList *list; - ObjType *objt; - - nspace = declinfo->nspace; - if (!nspace) - nspace = cscope_current; - - CError_QualifierCheck(declinfo->qual & ~(Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST)); - if (declinfo->x48 || declinfo->x44) - CError_Error(CErrorStr121); - if (declinfo->operator_token) - CError_Error(CErrorStr193); - - objt = NULL; - list = CScope_FindName(nspace, declinfo->name); - if (list) { - switch (list->object->otype) { - case OT_TYPE: - objt = OBJ_TYPE(list->object); - break; - case OT_TYPETAG: - break; - case OT_NAMESPACE: - CError_Error(CErrorStr321); - return; - case OT_ENUMCONST: - case OT_OBJECT: - CError_Error(CErrorStr322); - return; - default: - CError_FATAL(2156); - } - } - - if (objt) { - const UInt32 mask = Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST; - if (!is_typesame(objt->type, declinfo->thetype) || (objt->qual & mask) != (declinfo->qual & mask)) { - CError_Error(CErrorStr249, declinfo->name->name, objt->type, objt->qual, declinfo->thetype, declinfo->qual); - } else if (!copts.cplusplus && (copts.pedantic || copts.ANSIstrict)) { - if (copts.pedantic) - CError_Warning(CErrorStr122, declinfo->name->name); - else - CError_Error(CErrorStr122, declinfo->name->name); - } - return; - } - - objt = galloc(sizeof(ObjType)); - memclrw(objt, sizeof(ObjType)); - objt->otype = OT_TYPE; - objt->access = ACCESSPUBLIC; - objt->type = declinfo->thetype; - objt->qual = declinfo->qual; - CScope_AddObject(nspace, declinfo->name, OBJ_BASE(objt)); - - if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL) && - CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) - CTemplClass_RegisterObjectDef(TEMPL_CLASS(nspace->theclass), OBJ_BASE(objt)); - - if (copts.cplusplus) { - if (IS_TYPE_CLASS(declinfo->thetype) && IsTempName(TYPE_CLASS(declinfo->thetype)->classname)) { - TYPE_CLASS(declinfo->thetype)->classname = declinfo->name; - TYPE_CLASS(declinfo->thetype)->nspace->name = declinfo->name; - } - if (IS_TYPE_ENUM(declinfo->thetype) && IsTempName(TYPE_ENUM(declinfo->thetype)->enumname)) { - TYPE_ENUM(declinfo->thetype)->enumname = declinfo->name; - } - } - - if (cparamblkptr->browseoptions.recordTypedefs && declinfo->file->recordbrowseinfo) - CBrowse_NewTypedef(nspace, declinfo->name, declinfo->file, declinfo->file2, declinfo->sourceoffset, CPrep_BrowserFileOffset()); -} - -static void CDecl_DataDeclarator(DeclInfo *declinfo, AccessType access, Boolean flag) { - NameSpaceObjectList *list; - Object *obj; - NameSpace *nspace; - Boolean tmpflag; - ENode *expr; - - nspace = declinfo->nspace; - if (!nspace) - nspace = cscope_current; - - CError_QualifierCheck(declinfo->qual & ~(Q_ALIGNED_MASK | Q_WEAK | Q_20000 | Q_PASCAL | Q_VOLATILE | Q_CONST)); - if (declinfo->x48 || declinfo->x44) - CError_Error(CErrorStr121); - if (declinfo->operator_token) - CError_Error(CErrorStr193); - - obj = NULL; - list = CScope_FindName(nspace, declinfo->name); - if (list) { - switch (list->object->otype) { - case OT_OBJECT: - obj = OBJECT(list->object); - if (flag) - CError_Error(CErrorStr122, declinfo->name->name); - break; - case OT_TYPETAG: - break; - case OT_NAMESPACE: - CError_Error(CErrorStr321); - return; - case OT_ENUMCONST: - case OT_TYPE: - CError_Error(CErrorStr322); - break; - case OT_MEMBERVAR: - CError_Error(CErrorStr221); - break; - default: - CError_FATAL(2281); - } - } - - if (copts.cplusplus) { - if (!flag) - CDecl_CompleteType(declinfo->thetype); - switch (declinfo->storageclass) { - case TK_EXTERN: - if (tk == '=' || tk == '(') - declinfo->storageclass = 0; - break; - case 0: - if (CParser_IsConst(declinfo->thetype, declinfo->qual)) { - if ((!obj && !nspace->theclass) || (obj && obj->sclass != TK_EXTERN && !obj->nspace->theclass)) - declinfo->storageclass = TK_STATIC; - } - break; - } - } else { - if (declinfo->storageclass == TK_EXTERN && tk == '=') - declinfo->storageclass = 0; - } - - if (IS_TYPE_ARRAY(declinfo->thetype) && !declinfo->thetype->size && !declinfo->storageclass && tk != '=') - declinfo->storageclass = TK_EXTERN; - - if (obj) { - if ((!obj->type->size || !declinfo->thetype->size) && IS_TYPE_ARRAY(declinfo->thetype) && IS_TYPE_ARRAY(obj->type)) - tmpflag = is_typesame(TYPE_POINTER(declinfo->thetype)->target, TYPE_POINTER(obj->type)->target); - else - tmpflag = is_typesame(declinfo->thetype, obj->type); - - if (!tmpflag || (obj->qual & (Q_PASCAL | Q_VOLATILE | Q_CONST)) != (declinfo->qual & (Q_PASCAL | Q_VOLATILE | Q_CONST))) - CError_Error(CErrorStr249, CError_GetObjectName(obj), obj->type, obj->qual, declinfo->thetype, declinfo->qual); - - if (obj->qual & Q_INLINE_DATA) { - if (tk == ',' || tk == ';') - return; - CError_Error(CErrorStr333, obj); - } - - if (declinfo->storageclass != TK_EXTERN) { - if (obj->sclass != TK_EXTERN && declinfo->storageclass && obj->sclass != declinfo->storageclass) - CError_Error(CErrorStr333, obj); - - if (tmpflag) { - obj->sclass = declinfo->storageclass; - obj->qual |= declinfo->qual; - if (declinfo->thetype->size) - obj->type = declinfo->thetype; - } - - CParser_UpdateObject(obj, declinfo); - } else { - flag = 1; - } - } else { - if (declinfo->nspace) - CError_Error(CErrorStr336); - if (IS_TYPE_CLASS(declinfo->thetype) && TYPE_CLASS(declinfo->thetype)->sominfo) - CError_Error(CErrorStr288); - if (!CanCreateObject(declinfo->thetype)) - declinfo->thetype = TYPE(&stsignedint); - - obj = CParser_NewGlobalDataObject(declinfo); - obj->access = access; - CScope_AddObject(nspace, declinfo->name, OBJ_BASE(obj)); - - if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL) && - CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) - CTemplClass_RegisterObjectDef(TEMPL_CLASS(nspace->theclass), OBJ_BASE(obj)); - - if (flag && nspace->theclass && cparamblkptr->browseoptions.recordClasses) - CBrowse_AddClassMemberData(obj, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset()); - } - - if (!flag) { - if (declinfo->nspace) { - CScopeSave save; - CScope_SetNameSpaceScope(declinfo->nspace, &save); - CInit_InitializeData(obj); - CScope_RestoreScope(&save); - - if (declinfo->x3C && obj->nspace->theclass && (TYPE_CLASS(obj->nspace->theclass)->flags & CLASS_IS_TEMPL_INST)) - declinfo->x3C = 0; - } else { - CInit_InitializeData(obj); - } - - if (declinfo->file->recordbrowseinfo && obj->sclass != TK_EXTERN) - CBrowse_NewData(obj, declinfo->file, declinfo->file2, declinfo->sourceoffset, CPrep_BrowserFileOffset()); - } else if (tk == '=') { - tk = lex(); - expr = CExpr_IntegralConstOrDepExpr(); - if (IS_TYPE_TEMPLATE(obj->type) || !ENODE_IS(expr, EINTCONST)) { - CError_ASSERT(2426, nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL)); - CTemplClass_RegisterObjectInit(TEMPL_CLASS(nspace->theclass), obj, expr); - } else if ((obj->qual & Q_CONST) && IS_TYPE_INT_OR_ENUM(obj->type)) { - obj->u.data.u.intconst = expr->data.intval; - obj->qual |= Q_INLINE_DATA | Q_20000; - } else { - CError_Error(CErrorStr354, obj->name->name); - } - } -} - -Boolean CDecl_FunctionDeclarator(DeclInfo *declinfo, NameSpace *nspace, Boolean flag, Boolean flag2) { - Object *obj; - Boolean pflag; - - obj = CDecl_GetFunctionObject(declinfo, nspace, &pflag, 0); - if (obj) { - if (declinfo->x44 || tk == '{' || tk == TK_TRY || (declinfo->x4B && tk == ':') || (!copts.cplusplus && isdeclaration(0, 0, 0, 0))) { - if (!flag || cscope_currentfunc) { - CError_Error(CErrorStr127); - if (cscope_currentfunc) - return 0; - } - - if (obj->nspace == cscope_root && !strcmp(obj->name->name, "main")) { - if (obj->sclass == TK_STATIC || (copts.ANSIstrict && TYPE_FUNC(obj->type)->functype != (Type *) &stsignedint)) - CError_Error(CErrorStr334); - } else if (copts.checkprotos && (pflag || declinfo->x64)) { - if (obj->sclass != TK_STATIC && !(obj->qual & Q_INLINE) && !obj->nspace->is_unnamed) - CError_Warning(CErrorStr178); - } - - CFunc_ParseFuncDef(obj, declinfo, NULL, 0, 0, NULL); - if (declinfo->file->recordbrowseinfo) - CBrowse_NewFunction( - obj, - declinfo->file, - declinfo->file2, - declinfo->sourceoffset, - CPrep_BrowserFileOffset()); - - if (copts.cplusplus && lookahead() == ';') - tk = lex(); - return 0; - } - } - - return 1; -} - -static void CDecl_ParseSpecialMember(DeclInfo *declinfo, Boolean flag) { - Object *r28; - NameSpace *r25; - - if (!(r28 = declinfo->x10)) { - CError_ASSERT(2544, declinfo->x14); - r28 = OBJECT(declinfo->x14->object); - CError_ASSERT(2546, r28->otype == OT_OBJECT); - } - - if (!r28->nspace->theclass) { - CError_Error(CErrorStr121); - return; - } - - if (IS_TYPE_FUNC(r28->type)) { - if (TYPE_FUNC(r28->type)->flags & (FUNC_IS_CTOR | FUNC_IS_DTOR)) { - if (r28->nspace->theclass->sominfo) - declinfo->thetype = TYPE(&stvoid); - else - declinfo->thetype = TYPE(&void_ptr); - declinfo->nspace = r28->nspace; - declinfo->name = r28->name; - if (TYPE_FUNC(r28->type)->flags & FUNC_IS_CTOR) - declinfo->x4B = 1; - - if ((tk = lex()) == '(') { - tk = lex(); - - r25 = cscope_current; - cscope_current = r28->nspace; - CDecl_ParseDirectFuncDecl(declinfo); - cscope_current = r25; - - if (IS_TYPE_FUNC(declinfo->thetype)) { - if (TYPE_FUNC(r28->type)->flags & FUNC_IS_CTOR) { - if ((r28->nspace->theclass->flags & CLASS_HAS_VBASES) && !r28->nspace->theclass->sominfo) - CDecl_AddArgument(TYPE_FUNC(declinfo->thetype), TYPE(&stsignedshort)); - } else { - if (!r28->nspace->theclass->sominfo) - CDecl_AddArgument(TYPE_FUNC(declinfo->thetype), TYPE(&stsignedshort)); - } - if (flag) - CDecl_FunctionDeclarator(declinfo, NULL, 1, 1); - } else { - CError_Error(CErrorStr121); - } - } else { - CError_Error(CErrorStr114); - } - return; - } else if (TYPE_FUNC(r28->type)->flags & FUNC_CONVERSION) { - CError_FATAL(2603); - - declinfo->thetype = TYPE_FUNC(r28->type)->functype; - declinfo->qual |= TYPE_FUNC(r28->type)->qual; - declinfo->nspace = r28->nspace; - declinfo->name = r28->name; - - if ((tk = lex()) == '(') { - tk = lex(); - CDecl_ParseDirectFuncDecl(declinfo); - if (IS_TYPE_FUNC(declinfo->thetype)) { - TYPE_FUNC(declinfo->thetype)->flags |= FUNC_CONVERSION; - if (flag) - CDecl_FunctionDeclarator(declinfo, NULL, 1, 1); - } else { - CError_Error(CErrorStr121); - } - } else { - CError_Error(CErrorStr114); - } - return; - } else { - declinfo->thetype = TYPE(&stsignedint); - declinfo->nspace = r28->nspace; - declinfo->name = r28->name; - - if ((tk = lex()) == '(') { - tk = lex(); - - r25 = cscope_current; - cscope_current = r28->nspace; - CDecl_ParseDirectFuncDecl(declinfo); - cscope_current = r25; - - if (IS_TYPE_FUNC(declinfo->thetype)) { - if (flag) - CDecl_FunctionDeclarator(declinfo, NULL, 1, 1); - return; - } - } else { - CError_Error(CErrorStr114); - } - } - } - - CError_Error(CErrorStr121); -} - -void CDecl_ScanDeclarator(DeclInfo *declinfo) { - if (declinfo->x14 || declinfo->x10) { - CDecl_ParseSpecialMember(declinfo, 0); - CDecl_GetFunctionObject(declinfo, NULL, NULL, 1); - return; - } - - if (IS_TYPE_FUNC(declinfo->thetype)) { - TypeFunc *copy = galloc(sizeof(TypeFunc)); - *copy = *TYPE_FUNC(declinfo->thetype); - declinfo->thetype = TYPE(copy); - } - scandeclarator(declinfo); - if (!declinfo->name) { - CError_Error(CErrorStr121); - return; - } - - if (declinfo->storageclass && declinfo->storageclass != TK_EXTERN) - CError_Error(CErrorStr177); - - if (IS_TYPE_FUNC(declinfo->thetype)) { - CDecl_GetFunctionObject(declinfo, NULL, NULL, 1); - return; - } - - if (declinfo->x48 || declinfo->x44) - CError_Error(CErrorStr121); - - if (declinfo->operator_token) - CError_Error(CErrorStr193); - - if ( - (declinfo->qual & ~(Q_ALIGNED_MASK | Q_WEAK | Q_20000 | Q_PASCAL | Q_VOLATILE | Q_CONST)) || - (declinfo->storageclass == TK_TYPEDEF && (declinfo->qual & ~(Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST))) - ) - CError_Error(CErrorStr176); -} - -void scandeclaratorlist(DeclInfo *declinfo) { - CScopeSave savescope; - Type *r30; - UInt32 r29; - Boolean r28; - - if (declinfo->x14 || declinfo->x10) { - CDecl_ParseSpecialMember(declinfo, 1); - return; - } - - CScope_GetScope(&savescope); - CError_ASSERT(2707, declinfo->thetype); - - r28 = 1; - while (1) { - r30 = declinfo->thetype; - r29 = declinfo->qual; - declinfo->nspace = NULL; - declinfo->operator_token = 0; - if (IS_TYPE_FUNC(r30)) { - declinfo->thetype = galloc(sizeof(TypeFunc)); - *TYPE_FUNC(declinfo->thetype) = *TYPE_FUNC(r30); - } - declinfo->name = NULL; - scandeclarator(declinfo); - if (!declinfo->name) { - CError_Error(CErrorStr121); - break; - } - - if (declinfo->storageclass != TK_TYPEDEF) { - if (IS_TYPE_FUNC(declinfo->thetype)) { - if (!CDecl_FunctionDeclarator(declinfo, NULL, r28, 1)) - return; - } else { - CDecl_DataDeclarator(declinfo, ACCESSPUBLIC, 0); - } - } else { - CDecl_TypedefDeclarator(declinfo); - } - - CScope_RestoreScope(&savescope); - declinfo->thetype = r30; - declinfo->qual = r29; - - if (tk != ',') - break; - tk = lex(); - r28 = 0; - } - - if (tk != ';') - CError_Error(CErrorStr123); -} - -static TypeIntegral *CDecl_FindSignedType(short size) { - if (stsignedchar.size == size) - return &stsignedchar; - if (stsignedshort.size == size) - return &stsignedshort; - if (stsignedint.size == size) - return &stsignedint; - if (stsignedlong.size == size) - return &stsignedlong; - if (copts.longlong && copts.longlong_enums && stsignedlonglong.size == size) - return &stsignedlonglong; - return &stsignedlong; -} - -static TypeIntegral *CDecl_FindUnsignedType(short size) { - if (stunsignedchar.size == size) - return &stunsignedchar; - if (stunsignedshort.size == size) - return &stunsignedshort; - if (stunsignedint.size == size) - return &stunsignedint; - if (stunsignedlong.size == size) - return &stunsignedlong; - if (copts.longlong && copts.longlong_enums && stunsignedlonglong.size == size) - return &stunsignedlonglong; - return &stunsignedlong; -} - -static TypeIntegral *CDecl_IterateIntegralEnumType(int *t) { - switch (*t) { - case 0: - *t = 1; - return &stsignedchar; - case 1: - if (stsignedshort.size > stsignedchar.size) { - *t = 2; - return &stsignedshort; - } - case 2: - if (stsignedint.size > stsignedshort.size) { - *t = 3; - return &stsignedint; - } - case 3: - if (stsignedlong.size > stsignedint.size) { - *t = 4; - return &stsignedlong; - } - case 4: - *t = 5; - if (stsignedlonglong.size > stsignedlong.size && copts.longlong && copts.longlong_enums) - return &stsignedlonglong; - default: - return NULL; - } -} - -static TypeIntegral *CDecl_IterateUIntegralEnumType(int *t) { - switch (*t) { - case 0: - *t = 1; - return &stunsignedchar; - case 1: - if (stunsignedshort.size > stunsignedchar.size) { - *t = 2; - return &stunsignedshort; - } - case 2: - if (stunsignedint.size > stunsignedshort.size) { - *t = 3; - return &stunsignedint; - } - case 3: - if (stunsignedlong.size > stunsignedint.size) { - *t = 4; - return &stunsignedlong; - } - case 4: - *t = 5; - if (stunsignedlonglong.size > stunsignedlong.size && copts.longlong && copts.longlong_enums) - return &stunsignedlonglong; - default: - return NULL; - } -} - -static TypeEnum *CDecl_OldParseEnumList(TypeEnum *tenum, HashNameNode *name) { - AccessType access; - Boolean has_template_value; - Boolean r24; - Boolean r23; - ObjEnumConst *oec; - ObjEnumConst *last; - Boolean overflowed; - CInt64 val; - CInt64 minimum; - CInt64 maximum; - CInt64 var_74; - CInt64 unused; - Type *basetype; - Type *basetype2; - CPrepFileInfo *fileinfo; - SInt32 offset; - ENode *expr; - Type *tmp; - - if (!tenum) { - tenum = galloc(sizeof(TypeEnum)); - memclrw(tenum, sizeof(TypeEnum)); - tenum->type = TYPEENUM; - tenum->nspace = cscope_current; - - if (name) { - tenum->enumname = name; - CScope_DefineTypeTag(cscope_current, name, TYPE(tenum)); - } - - if (!cscope_current->is_global) { - do { - tenum->nspace = tenum->nspace->parent; - } while (!tenum->nspace->is_global); - if (tenum->enumname) - tenum->enumname = CParser_AppendUniqueNameFile(tenum->enumname->name); - } - } - - if (cscope_current->theclass && (cscope_current->theclass->flags & CLASS_IS_TEMPL)) { - CTemplClass_RegisterEnumType(TEMPL_CLASS(cscope_current->theclass), tenum); - } - - access = cscope_current->theclass ? global_access : ACCESSPUBLIC; - last = NULL; - unused = cint64_zero; - val = cint64_zero; - minimum = cint64_zero; - maximum = cint64_zero; - r23 = 0; - if (copts.enumsalwaysint) { - basetype = TYPE(&stsignedint); - r24 = 1; - } else { - basetype = TYPE(&stunsignedchar); - r24 = 0; - } - - tk = lex(); - if (!copts.cplusplus || tk != '}') { - do { - if (tk != TK_IDENTIFIER) { - if (tk == '}') { - if (copts.cpp_extensions) - break; - if (!copts.warn_extracomma) - break; - } - CError_Warning(CErrorStr107); - break; - } - - oec = galloc(sizeof(ObjEnumConst)); - memclrw(oec, sizeof(ObjEnumConst)); - oec->otype = OT_ENUMCONST; - oec->access = access; - oec->type = TYPE(tenum); - oec->name = tkidentifier; - CPrep_BrowserFilePosition(&fileinfo, &offset); - overflowed = 0; - if ((tk = lex()) == '=') { - tk = lex(); - val = CExpr_IntegralConstExprType(&basetype2); - if (!CInt64_IsNegative(&val) || is_unsigned(basetype2)) { - if (CInt64_GreaterU(val, minimum)) { - minimum = val; - overflowed = 1; - } - } else { - if (CInt64_Less(val, maximum)) { - maximum = val; - overflowed = 1; - } - if (!r24) { - basetype = TYPE(&stsignedchar); - r24 = 1; - } - } - r23 = 0; - } else { - if (r23) - CError_Error(CErrorStr154); - - if (!r24 || !CInt64_IsNegative(&val)) { - if (CInt64_GreaterU(val, minimum)) { - minimum = val; - overflowed = 1; - } - } else { - if (CInt64_Less(val, maximum)) { - maximum = val; - overflowed = 1; - } - } - } - - if (copts.enumsalwaysint) { - if (copts.ANSIstrict) { - if (!CInt64_IsInRange(val, stsignedint.size)) - CError_Error(CErrorStr154); - } else { - if (!CInt64_IsInRange(val, stsignedint.size) && !CInt64_IsInURange(val, stunsignedint.size)) - CError_Error(CErrorStr154); - } - } else if (r24) { - switch (basetype->size) { - case 1: - if (CInt64_IsInRange(minimum, 1) && CInt64_IsInRange(maximum, 1)) - break; - basetype = TYPE(CDecl_FindSignedType(2)); - case 2: - if (CInt64_IsInRange(minimum, 2) && CInt64_IsInRange(maximum, 2)) - break; - basetype = TYPE(CDecl_FindSignedType(4)); - case 4: - if (CInt64_IsInRange(minimum, 4) && CInt64_IsInRange(maximum, 4)) - break; - basetype = TYPE(CDecl_FindSignedType(8)); - if (basetype->size != 8) { - if (!copts.ANSIstrict && CInt64_IsInRange(maximum, 4) && CInt64_IsInURange(minimum, 4)) - break; - if (overflowed) - CError_Error(CErrorStr154); - break; - } - case 8: - if (CInt64_Equal(val, minimum) && CInt64_IsNegative(&val)) - CError_Error(CErrorStr154); - break; - default: - CError_FATAL(3071); - } - } else { - switch (basetype->size) { - case 1: - if (CInt64_IsInURange(minimum, 1)) - break; - basetype = TYPE(CDecl_FindUnsignedType(2)); - case 2: - if (CInt64_IsInURange(minimum, 2)) - break; - basetype = TYPE(CDecl_FindUnsignedType(4)); - case 4: - if (CInt64_IsInURange(minimum, 4)) - break; - basetype = TYPE(CDecl_FindUnsignedType(8)); - if (basetype->size != 8) { - if (overflowed) - CError_Error(CErrorStr154); - break; - } - case 8: - break; - default: - CError_FATAL(3099); - } - } - - tenum->size = basetype->size; - tenum->enumtype = basetype; - oec->val = val; - CScope_AddObject(cscope_current, oec->name, OBJ_BASE(oec)); - - if (last) { - last->next = oec; - last = oec; - } else { - last = oec; - tenum->enumlist = oec; - } - - if (cparamblkptr->browseoptions.recordEnums) { - CPrepFileInfo *f = CPrep_BrowserCurrentFile(); - if (f->recordbrowseinfo) { - CBrowse_NewEnumConstant(cscope_current, oec->name, f, fileinfo, offset, CPrep_BrowserFileOffset()); - } - } - - var_74 = CInt64_Add(val, cint64_one); - if (r24) { - if (CInt64_IsNegative(&var_74) && !CInt64_IsNegative(&val)) - r23 = 1; - } else { - if (CInt64_IsZero(&var_74)) - r23 = 1; - } - val = var_74; - - if (tk != ',') - break; - tk = lex(); - } while (1); - } - - tenum->size = basetype->size; - tenum->enumtype = basetype; - - for (oec = tenum->enumlist; oec; oec = oec->next) - oec->type = TYPE(tenum); - - if (tk != '}') - CError_ErrorSkip(CErrorStr130); - else - tk = lex(); - - return tenum; -} - -static Type *CDecl_MaxType(Type *a, Type *b) { - if (a->size > b->size) - return a; - if (b->size > a->size) - return b; - if (is_unsigned(b)) - return b; - else - return a; -} - -void CDecl_ComputeUnderlyingEnumType(TypeEnum *tenum) { - ObjEnumConst *oec; - ObjEnumConst *oec2; - Type *r26; - int t; - - if (!copts.enumsalwaysint) { - for (oec2 = tenum->enumlist; oec2; oec2 = oec2->next) { - if (CInt64_IsNegative(&oec2->val) && !is_unsigned(oec2->type)) - break; - } - - if (oec2) { - CInt64 unused = cint64_zero; - CInt64 minimum = cint64_zero; - CInt64 maximum = cint64_zero; - for (oec = tenum->enumlist; oec; oec = oec->next) { - if (CInt64_IsNegative(&oec->val) && !is_unsigned(oec->type)) { - if (CInt64_Less(oec->val, minimum)) - minimum = oec->val; - } else { - if (CInt64_GreaterU(oec->val, maximum)) - maximum = oec->val; - } - } - - if (CInt64_IsNegative(&maximum)) - CError_Error(CErrorStr154); - - t = 0; - do { - r26 = TYPE(CDecl_IterateIntegralEnumType(&t)); - if (!r26) { - r26 = TYPE(&stsignedlong); - CError_Error(CErrorStr154); - break; - } - - if (CInt64_IsInRange(maximum, r26->size) && CInt64_IsInRange(minimum, r26->size)) - break; - if (r26->size == stsignedlong.size && !copts.ANSIstrict && CInt64_IsInRange(minimum, r26->size) && CInt64_IsInURange(maximum, r26->size)) - break; - } while (1); - } else { - CInt64 val = cint64_zero; - - for (oec = tenum->enumlist; oec; oec = oec->next) { - if (CInt64_GreaterU(oec->val, val)) - val = oec->val; - } - - t = 0; - do { - r26 = TYPE(CDecl_IterateUIntegralEnumType(&t)); - if (!r26) { - r26 = TYPE(&stunsignedlong); - CError_Error(CErrorStr154); - break; - } - if (CInt64_IsInURange(val, r26->size)) - break; - } while (1); - } - } else { - r26 = TYPE(&stsignedint); - } - - tenum->size = r26->size; - tenum->enumtype = r26; - for (oec = tenum->enumlist; oec; oec = oec->next) - oec->type = TYPE(tenum); -} - -static Type *CDecl_FindUnderlyingType(short size, CInt64 *a, CInt64 *b) { - if (CInt64_IsZero(a)) { - if (size <= stsignedchar.size && CInt64_IsInURange(*b, stunsignedchar.size)) - return TYPE(&stunsignedchar); - if (size <= stsignedshort.size && CInt64_IsInURange(*b, stunsignedshort.size)) - return TYPE(&stunsignedshort); - if (size <= stsignedint.size && CInt64_IsInURange(*b, stunsignedint.size)) - return TYPE(&stunsignedint); - if (size <= stsignedlong.size && CInt64_IsInURange(*b, stunsignedlong.size)) - return TYPE(&stunsignedlong); - if (size <= stsignedlonglong.size && copts.longlong && copts.longlong_enums && CInt64_IsInURange(*b, stunsignedlonglong.size)) - return TYPE(&stunsignedlonglong); - } else { - if (size <= stsignedchar.size && CInt64_IsInRange(*a, stsignedchar.size) && CInt64_IsInRange(*b, stsignedchar.size)) - return TYPE(&stsignedchar); - if (size <= stsignedshort.size && CInt64_IsInRange(*a, stsignedshort.size) && CInt64_IsInRange(*b, stsignedshort.size)) - return TYPE(&stsignedshort); - if (size <= stsignedint.size && CInt64_IsInRange(*a, stsignedint.size) && CInt64_IsInRange(*b, stsignedint.size)) - return TYPE(&stsignedint); - if (size <= stsignedlong.size && CInt64_IsInRange(*a, stsignedlong.size) && CInt64_IsInRange(*b, stsignedlong.size)) - return TYPE(&stsignedlong); - if (size <= stsignedlonglong.size && copts.longlong && copts.longlong_enums && CInt64_IsInRange(*a, stsignedlonglong.size) && CInt64_IsInRange(*b, stsignedlonglong.size)) - return TYPE(&stsignedlonglong); - if (!copts.ANSIstrict && size <= stsignedlong.size && CInt64_IsInRange(*a, stsignedlong.size) && CInt64_IsInURange(*b, stunsignedlong.size)) - return TYPE(&stsignedlong); - } - - return NULL; -} - -static TypeEnum *CDecl_ParseEnumList(TypeEnum *tenum, HashNameNode *name) { - AccessType access; - TemplClass *tmclass; - ObjEnumConst *oec; - Boolean has_template_value; - Boolean overflowed; - Boolean is_first; - CInt64 val; - CInt64 minimum; - CInt64 maximum; - CInt64 unused; - Type *basetype; - CPrepFileInfo *fileinfo; - SInt32 offset; - ENode *expr; - Type *tmp; - ObjEnumConst *last; - - if (!tenum) { - tenum = galloc(sizeof(TypeEnum)); - memclrw(tenum, sizeof(TypeEnum)); - tenum->type = TYPEENUM; - tenum->nspace = cscope_current; - - if (name) { - tenum->enumname = name; - CScope_DefineTypeTag(cscope_current, name, TYPE(tenum)); - } - - if (!cscope_current->is_global) { - do { - tenum->nspace = tenum->nspace->parent; - } while (!tenum->nspace->is_global); - if (tenum->enumname) - tenum->enumname = CParser_AppendUniqueNameFile(tenum->enumname->name); - } - } - - if (cscope_current->theclass && (cscope_current->theclass->flags & CLASS_IS_TEMPL)) { - tmclass = TEMPL_CLASS(cscope_current->theclass); - CTemplClass_RegisterEnumType(tmclass, tenum); - } else { - tmclass = NULL; - } - - access = cscope_current->theclass ? global_access : ACCESSPUBLIC; - last = NULL; - is_first = 1; - has_template_value = 0; - unused = cint64_zero; - val = cint64_zero; - minimum = cint64_zero; - maximum = cint64_zero; - basetype = copts.enumsalwaysint ? TYPE(&stsignedint) : TYPE(&stsignedchar); - tenum->size = basetype->size; - tenum->enumtype = basetype; - - do { - if ((tk = lex()) != TK_IDENTIFIER) { - if (tk == '}') { - if (is_first) { - if (copts.cplusplus) - break; - } else { - if (!copts.warn_extracomma) - break; - if (copts.c9x) - break; - if (copts.cpp_extensions) - break; - } - CError_Warning(CErrorStr107); - } else { - CError_Error(CErrorStr107); - } - break; - } - - oec = galloc(sizeof(ObjEnumConst)); - memclrw(oec, sizeof(ObjEnumConst)); - oec->otype = OT_ENUMCONST; - oec->access = access; - oec->name = tkidentifier; - CPrep_BrowserFilePosition(&fileinfo, &offset); - overflowed = 0; - if ((tk = lex()) == '=') { - tk = lex(); - if (tmclass) { - expr = CExpr_IntegralConstOrDepExpr(); - if (ENODE_IS(expr, EINTCONST)) { - val = expr->data.intval; - basetype = expr->rtype; - has_template_value = 0; - } else { - val = cint64_zero; - basetype = TYPE(tenum); - CTemplClass_RegisterEnumerator(tmclass, oec, expr); - has_template_value = 1; - } - } else { - val = CExpr_IntegralConstExprType(&basetype); - has_template_value = 0; - } - } else if (has_template_value) { - CTemplClass_RegisterEnumerator(tmclass, oec, NULL); - } else if (!is_first) { - if (is_unsigned(basetype)) { - val = CInt64_Add(val, cint64_one); - if (CInt64_IsZero(&val)) - overflowed = 1; - } else if (!CInt64_IsNegative(&val)) { - val = CInt64_Add(val, cint64_one); - if (CInt64_IsNegative(&val)) - overflowed = 1; - } else { - val = CInt64_Add(val, cint64_one); - } - } - - if (!has_template_value) { - if (copts.enumsalwaysint) { - if (!CInt64_IsInRange(val, stsignedint.size) && (copts.ANSIstrict || !CInt64_IsInURange(val, stunsignedint.size))) - overflowed = 1; - basetype = TYPE(&stsignedint); - } else if (CInt64_IsNegative(&val) && !is_unsigned(basetype)) { - if (CInt64_Less(val, minimum)) { - minimum = val; - if ((tmp = CDecl_FindUnderlyingType(tenum->size, &minimum, &maximum))) { - tenum->size = tmp->size; - tenum->enumtype = tmp; - } else { - overflowed = 1; - } - } - } else { - if (CInt64_GreaterU(val, maximum)) { - maximum = val; - if ((tmp = CDecl_FindUnderlyingType(tenum->size, &minimum, &maximum))) { - tenum->size = tmp->size; - tenum->enumtype = tmp; - } else { - overflowed = 1; - } - } - } - } - - if (overflowed) - CError_Error(CErrorStr154); - - oec->val = val; - oec->type = basetype; - CScope_AddObject(cscope_current, oec->name, OBJ_BASE(oec)); - - if (last) { - last->next = oec; - last = oec; - } else { - last = oec; - tenum->enumlist = oec; - } - - if (cparamblkptr->browseoptions.recordEnums) { - CPrepFileInfo *f = CPrep_BrowserCurrentFile(); - if (f->recordbrowseinfo) { - CBrowse_NewEnumConstant(cscope_current, oec->name, f, fileinfo, offset, CPrep_BrowserFileOffset()); - } - } - - is_first = 0; - } while (tk == ','); - - for (oec = tenum->enumlist; oec; oec = oec->next) - oec->type = TYPE(tenum); - - if (tk != '}') - CError_ErrorSkip(CErrorStr130); - else - tk = lex(); - - return tenum; -} - -void scanenum(DeclInfo *declinfo) { - HashNameNode *name; - Type *type; - NameResult pr; - - if (tk == '{') { - declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, NULL)); - TYPE_ENUM(declinfo->thetype)->enumname = CParser_AppendUniqueNameFile("@enum"); - return; - } - - if (tk == TK_IDENTIFIER) { - name = tkidentifier; - if (lookahead() == '{') { - type = CScope_GetLocalTagType(cscope_current, name); - if (type) { - lex(); - do_shit: - if (type->size || !IS_TYPE_ENUM(type)) { - CError_Error(CErrorStr122, name->name); - declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, NULL)); - return; - } - declinfo->thetype = TYPE(CDecl_ParseEnumList(TYPE_ENUM(type), NULL)); - } else { - lex(); - declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, name)); - } - - if (cparamblkptr->browseoptions.recordEnums && declinfo->file->recordbrowseinfo) - CBrowse_NewEnum( - cscope_current, - TYPE_ENUM(declinfo->thetype)->enumname, - declinfo->file, - declinfo->file2, - declinfo->sourceoffset, - CPrep_BrowserFileOffset()); - return; - } else { - CError_ASSERT(3851, !copts.cplusplus || tk != ';'); - tkidentifier = name; - } - } - - if (CScope_ParseElaborateName(&pr)) { - if ((type = pr.type)) { - if (!IS_TYPE_ENUM(type)) - CError_Error(CErrorStr121); - if ((tk = lex()) == '{') - goto do_shit; - declinfo->thetype = type; - return; - } else { - CError_ASSERT(3865, pr.name_4); - if ((tk = lex()) == '{') { - declinfo->thetype = TYPE(CDecl_ParseEnumList(NULL, pr.name_4)); - return; - } else { - CError_Error(CErrorStr140, pr.name_4->name); - } - } - } else { - CError_Error(CErrorStr121); - } - - declinfo->thetype = TYPE(&stsignedint); -} - -void CDecl_ScanStructDeclarator(BigDeclInfo *bde) { - ENode *expr; - short val; - short bits; - Boolean is_bitfield; - TypeTemplDep *ttempl; - TypeBitfield *tbitfield; - Type *type; - - bde->declinfo2 = bde->declinfo; - bde->declinfo2.name = NULL; - bde->declinfo2.operator_token = 0; - bde->xCD = 0; - is_bitfield = 0; - - if (tk == ':') { - bde->declinfo2.name = no_name_node; - is_bitfield = 1; - } else { - bde->declinfo2.x50 = 1; - scandeclarator(&bde->declinfo2); - if (!bde->declinfo2.name) { - CError_Error(CErrorStr131); - return; - } - - if ((!copts.ANSIstrict || copts.c9x) && !bde->declinfo2.thetype->size && IS_TYPE_ARRAY(bde->declinfo2.thetype)) { - if (bde->declinfo2.storageclass != TK_STATIC && bde->declinfo2.storageclass != TK_TYPEDEF) { - type = TYPE_POINTER(bde->declinfo2.thetype)->target; - while (IS_TYPE_ARRAY(type)) - type = TYPE_POINTER(type)->target; - if (!IsCompleteType(type)) - return; - if (tk != ';' || lookahead() != '}') { - CError_Error(CErrorStr145); - return; - } - } - } else { - if (bde->declinfo2.storageclass != TK_STATIC && bde->declinfo2.storageclass != TK_TYPEDEF) { - if (!IS_TYPE_FUNC(bde->declinfo2.thetype) && !IsCompleteType(bde->declinfo2.thetype)) - return; - } - } - - if (IS_TYPE_CLASS(bde->declinfo2.thetype) && TYPE_CLASS(bde->declinfo2.thetype)->sominfo) { - CError_Error(CErrorStr287); - return; - } - - if (tk != ':') - goto not_a_bitfield; - } - - if (!IS_TYPE_INT_OR_ENUM(bde->declinfo2.thetype)) { - if (CTemplTool_IsTemplateArgumentDependentType(bde->declinfo2.thetype)) - goto fuckup; - CError_Error(CErrorStr138); - bde->declinfo2.thetype = TYPE(&stunsignedint); - } else if (copts.ANSIstrict && !copts.cplusplus) { - if (bde->declinfo2.thetype != TYPE(&stsignedint) && bde->declinfo2.thetype != TYPE(&stunsignedint)) { - CError_Error(CErrorStr138); - bde->declinfo2.thetype = TYPE(&stunsignedint); - } - } - - switch (bde->declinfo2.thetype->size) { - case 1: - bits = 8; - break; - case 2: - bits = 16; - break; - case 4: - bits = 32; - break; - default: - CError_Error(CErrorStr138); - return; - } -fuckup: - tk = lex(); - expr = CExpr_IntegralConstOrDepExpr(); - if (!ENODE_IS(expr, EINTCONST)) { - ttempl = TYPE_TEMPLATE(CDecl_NewTemplDepType(TEMPLDEP_BITFIELD)); - ttempl->u.bitfield.type = bde->declinfo2.thetype; - ttempl->u.bitfield.size = CInline_CopyExpression(expr, CopyMode1); - bde->declinfo2.thetype = TYPE(ttempl); - bde->xCD = 1; - return; - } - val = CInt64_GetULong(&expr->data.intval); - if (is_bitfield) { - if (val < 0 || val > bits) { - CError_Error(CErrorStr138); - return; - } - } else { - if (val <= 0 || val > bits) { - CError_Error(CErrorStr138); - return; - } - } - - tbitfield = galloc(sizeof(TypeBitfield)); - memclrw(tbitfield, sizeof(TypeBitfield)); - tbitfield->type = TYPEBITFIELD; - tbitfield->size = bde->declinfo2.thetype->size; - tbitfield->bitfieldtype = bde->declinfo2.thetype; - tbitfield->bitlength = val; - bde->declinfo2.thetype = TYPE(tbitfield); - - if (tk == TK_UU_ATTRIBUTE_UU) - CParser_ParseAttribute(NULL, &bde->declinfo2); - -not_a_bitfield: - bde->xCD = 1; -} - -static void CDecl_LayoutStruct(TypeStruct *tstruct) { - StructMember *member; - SInt32 r28; - StructMember *innermember; - SInt32 innerbase; - StructMember *newmember; - StructMember **memberp; - TypeBitfield *bf; - SInt32 r24; - Boolean r23; - SInt32 tmp; - - r28 = 0; - r23 = 0; - CMach_StructLayoutInitOffset(0); - for (member = tstruct->members; member; member = member->next) { - if (tstruct->stype == STRUCT_TYPE_UNION) - CMach_StructLayoutInitOffset(0); - - if (IS_TYPE_BITFIELD(member->type)) - member->offset = CMach_StructLayoutBitfield(TYPE_BITFIELD(member->type), member->qual); - else - member->offset = CMach_StructLayoutGetOffset(member->type, member->qual); - - if (tstruct->stype == STRUCT_TYPE_UNION) { - tmp = CMach_StructLayoutGetCurSize(); - if (tmp > r28) - r28 = tmp; - } - - if (member->name == no_name_node) - r23 = 1; - - if (!member->name) { - CError_ASSERT(4064, IS_TYPE_STRUCT(member->type)); - innerbase = member->offset; - innermember = TYPE_STRUCT(member->type)->members; - r23 = 1; - while (innermember) { - if (ismember(tstruct, innermember->name)) - CError_Error(CErrorStr133, innermember->name->name); - if (r23) { - member->type = innermember->type; - member->name = innermember->name; - member->qual = innermember->qual; - member->offset = innerbase + innermember->offset; - } else { - newmember = galloc(sizeof(StructMember)); - memclrw(newmember, sizeof(StructMember)); - newmember->next = member->next; - newmember->type = innermember->type; - newmember->name = innermember->name; - newmember->qual = innermember->qual | Q_WEAK; - newmember->offset = innerbase + innermember->offset; - member->next = newmember; - member = newmember; - } - if (copts.reverse_bitfields && IS_TYPE_BITFIELD(member->type)) { - bf = galloc(sizeof(TypeBitfield)); - *bf = *TYPE_BITFIELD(member->type); - CABI_ReverseBitField(bf); - member->type = TYPE(bf); - } - r23 = 0; - innermember = innermember->next; - } - r23 = 1; - } - } - - if (r23) { - memberp = &tstruct->members; - while (*memberp) { - if ((*memberp)->name == no_name_node || !(*memberp)->name) - *memberp = (*memberp)->next; - else - memberp = &(*memberp)->next; - } - } - - if (tstruct->stype == STRUCT_TYPE_UNION) - r24 = r28; - else - r24 = CMach_StructLayoutGetCurSize(); - tstruct->size = r24; - tstruct->align = CMach_GetStructAlign(tstruct); - tstruct->size = r24 + CABI_StructSizeAlignValue(TYPE(tstruct), r24); - - if (copts.reverse_bitfields) { - for (member = tstruct->members; member; member = member->next) { - if (IS_TYPE_BITFIELD(member->type)) - CABI_ReverseBitField(TYPE_BITFIELD(member->type)); - } - } - - if (copts.warn_padding && tstruct->stype != STRUCT_TYPE_UNION) { - StructMember *prev; - - member = tstruct->members; - prev = NULL; - while (member) { - if (prev && (prev->offset + prev->type->size) < member->offset) { - CError_Warning(CErrorStr350, member->offset - (prev->offset + prev->type->size), prev->name->name); - } - prev = member; - member = member->next; - } - - if (prev && (prev->offset + prev->type->size) < tstruct->size) { - CError_Warning(CErrorStr350, tstruct->size - (prev->offset + prev->type->size), prev->name->name); - } - } -} - -static SInt32 scanstructdeclarationlist(TypeStruct *tstruct, Boolean flag) { - SInt32 offset; - StructMember *member; - BigDeclInfo bde; - - offset = -1; - memclrw(&bde, sizeof(BigDeclInfo)); - - if (tk == TK_AT_DEFS) { - CPrep_NewFileOffsetInfo(&member_fileoffset, NULL); - CObjC_ParseDefs(tstruct); - if ((tk = lex()) != '}') - CError_Error(CErrorStr130); - } else { - do { - CPrep_NewFileOffsetInfo(&member_fileoffset, NULL); - memclrw(&bde.declinfo, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&bde.declinfo, 0); - if (bde.declinfo.storageclass || bde.declinfo.x44) { - CError_Error(CErrorStr131); - tstruct->members = NULL; - return -1; - } - - if (tk != ';') { - while (1) { - CDecl_ScanStructDeclarator(&bde); - if (!CanCreateObject(bde.declinfo2.thetype)) { - CError_Error(CErrorStr131); - bde.xCD = 0; - } - - if (bde.declinfo2.operator_token) { - CError_Error(CErrorStr131); - bde.xCD = 0; - } - - if (bde.xCD) { - if (bde.declinfo2.name == no_name_node || !ismember(tstruct, bde.declinfo2.name)) { - member = galloc(sizeof(StructMember)); - memclrw(member, sizeof(StructMember)); - member->type = bde.declinfo2.thetype; - member->name = bde.declinfo2.name; - member->qual = bde.declinfo2.qual; - appendmember(tstruct, member); - - if (flag) { - CBrowse_AddStructMember(member, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset()); - } - } else { - CError_Error(CErrorStr133, bde.declinfo2.name->name); - } - } - - if (tk != ',') - break; - tk = lex(); - } - } else if (!copts.ANSIstrict && IS_TYPE_STRUCT(bde.declinfo.thetype)) { - member = galloc(sizeof(StructMember)); - memclrw(member, sizeof(StructMember)); - member->type = bde.declinfo.thetype; - appendmember(tstruct, member); - } else { - CError_Error(CErrorStr131); - } - - if (tk != ';') { - tstruct->members = NULL; - CError_Error(CErrorStr123); - return -1; - } - - CPrep_TokenStreamFlush(); - } while ((tk = lex()) != '}'); - CDecl_LayoutStruct(tstruct); - } - - if (flag) { - offset = CPrep_BrowserFileOffset(); - if (tk == ';') - offset++; - } - - tk = lex(); - return offset; -} - -static TypeStruct *CDecl_DefineStruct(HashNameNode *name, short stype) { - TypeStruct *tstruct; - - tstruct = galloc(sizeof(TypeStruct)); - memclrw(tstruct, sizeof(TypeStruct)); - - tstruct->type = TYPESTRUCT; - tstruct->align = 1; - tstruct->stype = stype; - if (name) { - tstruct->name = name; - CScope_DefineTypeTag((in_func_arglist && !copts.cplusplus) ? cscope_root : cscope_current, name, (Type *) tstruct); - } - - return tstruct; -} - -void scanstruct(DeclInfo *declinfo, short structtype) { - Type *type; - HashNameNode *name; - TypeStruct typecopy; - Boolean add_to_browse; - GList gl; - SInt32 offset; - - if (copts.cplusplus) { - CDecl_ParseClass(declinfo, structtype, 1, 0); - return; - } - - if (tk == TK_IDENTIFIER) { - name = tkidentifier; - type = CScope_GetTagType(cscope_current, name); - if (type) { - if (IS_TYPE_CLASS(type)) { - CDecl_ParseClass(declinfo, structtype, 1, 0); - return; - } - - tk = lex(); - if (!CScope_GetLocalTagType(cscope_current, name) && (tk == ';' || tk == '{')) - type = (Type *) CDecl_DefineStruct(name, structtype); - - if (!IS_TYPE_STRUCT(type) || TYPE_STRUCT(type)->stype != structtype) { - CError_Error(CErrorStr132, name->name); - declinfo->thetype = type; - return; - } - - if (tk != '{') { - declinfo->thetype = type; - return; - } - - if (type->size) { - CError_Error(CErrorStr132, name->name); - type = (Type *) CDecl_DefineStruct(NULL, structtype); - } - } else { - type = (Type *) CDecl_DefineStruct(name, structtype); - if ((tk = lex()) != '{') { - declinfo->thetype = type; - return; - } - } - } else if (tk != '{') { - CError_Error(CErrorStr131); - declinfo->thetype = (Type *) &stsignedint; - return; - } else { - type = (Type *) CDecl_DefineStruct(NULL, structtype); - } - - if ((add_to_browse = cparamblkptr->browseoptions.recordClasses && declinfo->file->recordbrowseinfo)) - CBrowse_BeginStruct(declinfo, TYPE_STRUCT(type), &gl); - - typecopy = *TYPE_STRUCT(type); - tk = lex(); - offset = scanstructdeclarationlist(&typecopy, add_to_browse); - *TYPE_STRUCT(type) = typecopy; - declinfo->thetype = type; - - if (add_to_browse) - CBrowse_EndStruct(offset, &gl); -} - -static void InlineFunctionObject(Object *obj, TypeClass *tclass) { - TokenStream stream; - CPrepFileInfo *file; - - obj->qual |= Q_INLINE; - TYPE_FUNC(obj->type)->flags |= FUNC_DEFINED; - - CPrep_StreamGetBlock(&stream, NULL, 1); - if (stream.tokens) { - if (IS_TYPEFUNC_METHOD(TYPE_FUNC(obj->type)) && (TYPE_METHOD(obj->type)->theclass->flags & CLASS_IS_TEMPL)) { - TYPE_FUNC(obj->type)->flags |= FUNC_IS_TEMPL_INSTANCE; - CTemplClass_DefineMember(TEMPL_CLASS(TYPE_METHOD(obj->type)->theclass), obj, &member_fileoffset, &stream); - } else { - CInline_AddInlineFunctionAction(obj, tclass, &member_fileoffset, &stream, 0); - } - } - - file = CPrep_BrowserCurrentFile(); - if (file->recordbrowseinfo) { - CBrowse_NewFunction( - obj, file, - member_fileoffset.file, - CPrep_BrowserTokenOffset(&member_fileoffset) + 1, - CPrep_BrowserFileOffset()); - } - - if (lookahead() == ';') - tk = lex(); - else - tk = ';'; -} - -void CDecl_ExtractClassExportFlags(DeclInfo *declinfo, UInt8 flags) { - if (flags & CLASS_EFLAGS_INTERNAL) - declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_INTERNAL; - if (flags & CLASS_EFLAGS_IMPORT) - declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_IMPORT; - if (flags & CLASS_EFLAGS_EXPORT) - declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_EXPORT; -} - -TypeMemberFunc *CDecl_MakeTypeMemberFunc(TypeFunc *tfunc, TypeClass *tclass, Boolean flag) { - TypeMemberFunc *method; - - method = galloc(sizeof(TypeMemberFunc)); - memclrw(method, sizeof(TypeMemberFunc)); - *TYPE_FUNC(method) = *tfunc; - method->theclass = tclass; - method->is_static = flag; - method->flags |= FUNC_METHOD; - if (!flag) - CDecl_AddThisPointerArgument(TYPE_FUNC(method), tclass); - - if ((flag || (tfunc->flags & (FUNC_IS_CTOR | FUNC_IS_DTOR))) && (tfunc->flags & (FUNC_CONST | FUNC_VOLATILE))) - CError_Error(CErrorStr384); - - return method; -} - -static void CDecl_MakeFunctionVirtual(TypeClass *tclass, Object *func) { - if (is_pascal_object(func)) - CError_Error(CErrorStr219); - if (tclass->mode == CLASS_MODE_UNION) - CError_Error(CErrorStr352, func); - func->datatype = DVFUNC; -} - -static void CDecl_AddFunctionMember(ClassLayout *decle, TypeClass *tclass, DeclInfo *declinfo, AccessType access, Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4) { - NameSpaceObjectList *list; // r20 - Object *obj; // also r20 - TypeMemberFunc *tfunc; // r19 - Boolean r31; - Boolean outflag; - - if (IS_TYPE_ARRAY(TYPE_FUNC(declinfo->thetype)->functype) || IS_TYPE_FUNC(TYPE_FUNC(declinfo->thetype)->functype)) { - CError_Error(CErrorStr128); - TYPE_FUNC(declinfo->thetype)->functype = (Type *) &stsignedint; - } - - if (tclass->sominfo) - CSOM_CheckFuncType(TYPE_FUNC(declinfo->thetype)); - - r31 = 0; - if (declinfo->qual & Q_VIRTUAL) { - declinfo->qual &= ~Q_VIRTUAL; - r31 = 1; - flag1 = 1; - } - - if ((list = CScope_FindName(tclass->nspace, declinfo->name))) { - if (list->object->otype != OT_TYPETAG) { - if (list->object->otype != OT_OBJECT || !IS_TYPE_FUNC(OBJECT(list->object)->type)) - CError_Error(CErrorStr133, declinfo->name->name); - } else { - list = NULL; - } - } - - if (!IS_TYPEFUNC_METHOD(TYPE_FUNC(declinfo->thetype))) { - tfunc = CDecl_MakeTypeMemberFunc(TYPE_FUNC(declinfo->thetype), tclass, flag4); - declinfo->thetype = (Type *) tfunc; - } else { - tfunc = TYPE_METHOD(declinfo->thetype); - CError_ASSERT(4579, !tclass->sominfo); - } - - CDecl_ExtractClassExportFlags(declinfo, tclass->eflags); - - CError_ASSERT(4597, cscope_current == tclass->nspace); - - if (list) { - obj = CDecl_OverloadFunctionObject(list, declinfo, &outflag, flag4 ? OverloadMode1 : OverloadMode2, 0); - if (!obj) - return; - if (outflag) - tfunc->vtbl_index = ++decle->lex_order_count; - else - CError_Error(CErrorStr133, CError_GetObjectName(obj)); - } else { - tfunc->vtbl_index = ++decle->lex_order_count; - obj = CParser_NewFunctionObject(declinfo); - if ((tclass->flags & CLASS_IS_TEMPL) && CTemplTool_IsTemplateArgumentDependentType(declinfo->thetype)) - CTemplClass_RegisterObjectDef(TEMPL_CLASS(tclass), OBJ_BASE(obj)); - CScope_AddObject(tclass->nspace, declinfo->name, OBJ_BASE(obj)); - } - - obj->access = access; - CheckDefaultArgs(TYPE_FUNC(obj->type)->args); - - if (flag2) { - tfunc->flags |= FUNC_CONVERSION; - tclass->flags = tclass->flags | CLASS_IS_CONVERTIBLE; - } - - if (r31) { - CDecl_MakeFunctionVirtual(tclass, obj); - decle->has_vtable = 1; - } - - if ((flag1 || r31) && flag3 && (tk == '=')) { - if ((tk = lex()) == TK_INTCONST) { - if (!CInt64_IsZero(&tkintconst)) - CError_Error(CErrorStr121); - tfunc->flags |= FUNC_PURE; - tclass->flags = tclass->flags | CLASS_ABSTRACT; - tk = lex(); - } else { - CError_Error(CErrorStr121); - } - } - - if (flag3 && ((tk == '{') || (tk == TK_TRY) || ((tk == ':') && CClass_IsConstructor(obj)))) { - if (declinfo->x49) - CError_Error(CErrorStr127); - InlineFunctionObject(obj, NULL); - } - - if (cparamblkptr->browseoptions.recordClasses) - CBrowse_AddClassMemberFunction(obj, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset()); -} - -static Boolean CDecl_IsAccessDeclaration(TypeClass *tclass, AccessType access) { - SInt32 state; - Boolean flag; - - CPrep_TokenStreamGetState(&state); - flag = 0; - -restart: - switch (tk) { - case TK_IDENTIFIER: - if ((tk = lex()) != ';') - break; - case TK_OPERATOR: - CPrep_TokenStreamSetCurState(&state); - if (flag) { - CScope_ParseUsingDeclaration(tclass->nspace, access, 1); - return 1; - } - return 0; - default: - CPrep_TokenStreamSetCurState(&state); - return 0; - } - - switch (tk) { - case TK_COLON_COLON: - flag = 1; - tk = lex(); - goto restart; - case '<': - tk = lex(); - while (1) { - switch (tk) { - case 0: - case ';': - case '{': - case '}': - CPrep_TokenStreamSetCurState(&state); - return 0; - case '>': - if ((tk = lex()) == TK_COLON_COLON) { - flag = 1; - tk = lex(); - goto restart; - } - default: - tk = lex(); - } - } - } - - CPrep_TokenStreamSetCurState(&state); - return 0; -} - -void CDecl_PackDeclInfo(PackedDeclInfo *packed, DeclInfo *declinfo) { - packed->thetype = declinfo->thetype; - packed->qual = declinfo->qual; - packed->nspace = declinfo->nspace; - packed->name = declinfo->name; - packed->expltargs = CTemplTool_MakeGlobalTemplArgCopy(declinfo->expltargs); - packed->storageclass = declinfo->storageclass; - packed->section = declinfo->section; - packed->exportflags = declinfo->exportflags; - packed->has_expltargs = declinfo->has_expltargs; -} - -void CDecl_UnpackDeclInfo(DeclInfo *declinfo, PackedDeclInfo *packed) { - memclrw(declinfo, sizeof(DeclInfo)); - declinfo->thetype = packed->thetype; - declinfo->qual = packed->qual; - declinfo->nspace = packed->nspace; - declinfo->name = packed->name; - declinfo->expltargs = packed->expltargs; - declinfo->storageclass = packed->storageclass; - declinfo->section = packed->section; - declinfo->exportflags = packed->exportflags; - declinfo->has_expltargs = packed->has_expltargs; -} - -void CDecl_AddFriend(TypeClass *tclass, Object *friendfunc, TypeClass *friendclass) { - ClassFriend *scan; - ClassFriend *newfriend; - - if (friendfunc) { - for (scan = tclass->friends; scan; scan = scan->next) { - if (!scan->isclass && scan->u.obj == friendfunc) - break; - } - if (!scan) { - newfriend = galloc(sizeof(ClassFriend)); - memclrw(newfriend, sizeof(ClassFriend)); - newfriend->next = tclass->friends; - tclass->friends = newfriend; - newfriend->u.obj = friendfunc; - newfriend->isclass = 0; - } - } - - if (friendclass) { - for (scan = tclass->friends; scan; scan = scan->next) { - if (scan->isclass && scan->u.theclass == friendclass) - break; - } - if (!scan) { - newfriend = galloc(sizeof(ClassFriend)); - memclrw(newfriend, sizeof(ClassFriend)); - newfriend->next = tclass->friends; - tclass->friends = newfriend; - newfriend->u.theclass = friendclass; - newfriend->isclass = 1; - } - } -} - -static void CDecl_ParseFriendDecl(TypeClass *tclass) { - DeclInfo declinfo; - DeclInfo declinfo_copy; - Boolean is_templ; - Boolean r27; - Boolean pflag; - CScopeSave save; - Object *obj; - NameSpace *nspace; - - is_templ = (tclass->flags & CLASS_IS_TEMPL) != 0; - r27 = (tk == TK_CLASS || tk == TK_STRUCT || tk == TK_UNION); - memclrw(&declinfo, sizeof(DeclInfo)); - - declinfo.in_friend_decl = 1; - CParser_GetDeclSpecs(&declinfo, 1); - if (declinfo.storageclass) { - CError_Error(CErrorStr177); - declinfo.storageclass = 0; - } - declinfo.in_friend_decl = 0; - - if (tk == ';') { - if (!r27) - CError_Error(CErrorStr201); - - if (IS_TYPE_CLASS(declinfo.thetype)) { - if (!(TYPE_CLASS(declinfo.thetype)->flags & CLASS_IS_TEMPL) || CParser_CheckTemplateClassUsage(TEMPL_CLASS(declinfo.thetype), 1)) { - if (!is_templ) - CDecl_AddFriend(tclass, NULL, TYPE_CLASS(declinfo.thetype)); - else - CTemplClass_RegisterFriend(TEMPL_CLASS(tclass), &declinfo); - } - } else { - if (IS_TYPE_TEMPLATE(declinfo.thetype) && is_templ) - CTemplClass_RegisterFriend(TEMPL_CLASS(tclass), &declinfo); - else - CError_Error(CErrorStr201); - } - } else { - if (declinfo.x14 || declinfo.x10) { - CDecl_ParseSpecialMember(&declinfo, 0); - if (declinfo.name) { - obj = CDecl_GetFunctionObject(&declinfo, NULL, &pflag, 0); - if (obj) - CDecl_AddFriend(tclass, obj, NULL); - if (tk != ';') - CError_Error(CErrorStr123); - else - tk = lex(); - } - return; - } else { - nspace = CScope_FindGlobalNS(cscope_current); - declinfo_copy = declinfo; - while (1) { - declinfo = declinfo_copy; - declinfo.x4D = 1; - declinfo.x51 = 1; - scandeclarator(&declinfo); - - if (IS_TYPE_FUNC(declinfo.thetype)) { - if (!is_templ) { - CScope_SetNameSpaceScope(nspace, &save); - obj = CDecl_GetFunctionObject(&declinfo, NULL, &pflag, 0); - CScope_RestoreScope(&save); - - if (obj) { - CDecl_AddFriend(tclass, obj, NULL); - if (!declinfo.nspace && tk == '{') { - InlineFunctionObject(obj, tclass); - } else { - if (!obj->sclass) - obj->sclass = TK_EXTERN; - } - } - } else { - CTemplClass_RegisterFriend(TEMPL_CLASS(tclass), &declinfo); - } - } else { - CError_Error(CErrorStr201); - } - - if (tk != ',') - break; - tk = lex(); - } - } - } - - if (tk == ';') - tk = lex(); - else - CError_Error(CErrorStr123); -} - -static ObjMemberVar *CDecl_InstanceDataDeclarator(ClassLayout *decle, TypeClass *tclass, Type *type, UInt32 qual, HashNameNode *name, AccessType access) { - NameSpaceObjectList *list; - ObjMemberVar *ivar; - ObjMemberVar *scan; - - if (name && (list = CScope_FindName(tclass->nspace, name))) { - switch (list->object->otype) { - case OT_NAMESPACE: - CError_Error(CErrorStr321); - return NULL; - case OT_ENUMCONST: - case OT_TYPE: - case OT_OBJECT: - CError_Error(CErrorStr322); - return NULL; - case OT_MEMBERVAR: - CError_Error(CErrorStr122, name->name); - return NULL; - case OT_TYPETAG: - break; - default: - CError_FATAL(4989); - } - } - - ivar = galloc(sizeof(ObjMemberVar)); - memclrw(ivar, sizeof(ObjMemberVar)); - ivar->otype = OT_MEMBERVAR; - ivar->access = access; - ivar->name = name; - ivar->type = type; - ivar->qual = qual; - if (!tclass->sominfo) - decle->lex_order_count++; - - if ((scan = tclass->ivars)) { - while (scan->next) - scan = scan->next; - scan->next = ivar; - } else { - tclass->ivars = ivar; - } - - if (name && name != no_name_node) { - CScope_AddObject(tclass->nspace, name, OBJ_BASE(ivar)); - if ((tclass->flags & CLASS_IS_TEMPL) && CTemplTool_IsTemplateArgumentDependentType(type)) - CTemplClass_RegisterObjectDef(TEMPL_CLASS(tclass), OBJ_BASE(ivar)); - if (cparamblkptr->browseoptions.recordClasses) - CBrowse_AddClassMemberVar(ivar, CPrep_BrowserTokenOffset(&member_fileoffset) + 1, CPrep_BrowserFileOffset()); - } - - return ivar; -} - -void CDecl_CheckCtorIntegrity(FuncArg *args, TypeClass *tclass) { - if (args && args->type == TYPE(tclass)) { - if (!args->next || args->next->dexpr) { - CError_Error(CErrorStr239); - args->type = &stvoid; - } - } -} - -static void CDecl_ParseClassMembers(ClassLayout *decle, TypeClass *tclass, short mode) { - AccessType access; - Boolean r17; - BigDeclInfo bde; - DeclInfo declinfo; - //Type *newtype - ObjMemberVar *ivar; - ObjMemberVar *scanivar; - Type *tmptype; - UInt32 r22; - UInt32 r21; - UInt8 r20; - UInt8 r18; - Boolean r19; - short t; - - r17 = (tclass->flags & CLASS_IS_TEMPL) && TEMPL_CLASS(tclass)->pspec_owner; - memclrw(&bde, sizeof(BigDeclInfo)); - - access = (mode == CLASS_MODE_CLASS) ? ACCESSPRIVATE : ACCESSPUBLIC; - global_access = access; - - restart: - while (tk != '}') { - CPrep_NewFileOffsetInfo(&member_fileoffset, NULL); - r21 = 0; - r22 = 0; - r20 = 0; - r18 = 0; - - if (tk == TK_TEMPLATE) { - NameSpace *nspace = cscope_current; - TemplClass *tmclass; - - if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL)) { - tmclass = TEMPL_CLASS(nspace->theclass); - } else { - for (; nspace; nspace = nspace->parent) { - if (!nspace->name && !nspace->theclass && nspace->parent && !nspace->is_templ) { - CError_Error(CErrorStr347); - break; - } - } - } - - CTempl_Parse(TEMPL_CLASS(tclass), access); - tk = lex(); - continue; - } - - restart2: - r19 = 0; - switch (tk) { - case TK_UU_DECLSPEC: - if ((tk = lex()) != '(') - CError_Error(CErrorStr114); - memclrw(&declinfo, sizeof(DeclInfo)); - CParser_ParseDeclSpec(&declinfo, 1); - r21 |= declinfo.qual; - r20 |= declinfo.exportflags; - r18 = declinfo.section; - if ((tk = lex()) != ')') - CError_Error(CErrorStr115); - tk = lex(); - goto restart2; - case TK_PRIVATE: - global_access = access = ACCESSPRIVATE; - goto check_access; - case TK_PROTECTED: - global_access = access = ACCESSPROTECTED; - goto check_access; - case TK_PUBLIC: - global_access = access = ACCESSPUBLIC; - check_access: - if (r22 || r20) - CError_Error(CErrorStr121); - if ((tk = lex()) != ':') - CError_Error(CErrorStr170); - else - tk = lex(); - goto restart; - case TK_EXPLICIT: - CError_QualifierCheck(r22 & Q_EXPLICIT); - r22 |= Q_EXPLICIT; - tk = lex(); - goto restart2; - case TK_INLINE: - CError_QualifierCheck(r22 & Q_INLINE); - r22 |= Q_INLINE; - tk = lex(); - goto restart2; - case TK_ASM: - CError_QualifierCheck(r22 & Q_ASM); - r22 |= Q_ASM; - tk = lex(); - goto restart2; - case TK_VIRTUAL: - CError_QualifierCheck(r22 & Q_VIRTUAL); - r22 |= Q_VIRTUAL; - tk = lex(); - goto restart2; - case TK_IDENTIFIER: - while (1) { - if (tkidentifier == tclass->classname) { - t = lookahead(); - tkidentifier = tclass->classname; - r19 = 1; - if (copts.cpp_extensions && t == TK_COLON_COLON) { - lex(); - tk = lex(); - if (tk == TK_IDENTIFIER) - continue; - if (tk == '~') - goto restart2; - CError_Error(CErrorStr107); - } - - if (t == '(') { - redo_thing: - CError_QualifierCheck(r22 & ~(Q_EXPLICIT | Q_INLINE | Q_ASM)); - memclrw(&bde.declinfo2, sizeof(DeclInfo)); - if (tclass->sominfo) - bde.declinfo2.thetype = &stvoid; - else - bde.declinfo2.thetype = TYPE(&void_ptr); - - bde.declinfo2.qual = r22; - bde.declinfo2.exportflags = r20; - bde.declinfo2.section = r18; - bde.declinfo2.x4B = 1; - scandeclarator(&bde.declinfo2); - if (IS_TYPE_FUNC(bde.declinfo2.thetype)) { - if (r17) - bde.declinfo2.thetype = CTemplTool_ResolveMemberSelfRefs(TEMPL_CLASS(tclass), bde.declinfo2.thetype, &bde.declinfo2.qual); - if (tclass->sominfo) { - if (TYPE_FUNC(bde.declinfo2.thetype)->args) - CError_Error(CErrorStr272); - bde.declinfo2.qual |= Q_VIRTUAL; - } else { - CDecl_CheckCtorIntegrity(TYPE_FUNC(bde.declinfo2.thetype)->args, tclass); - if (tclass->flags & CLASS_HAS_VBASES) - CDecl_AddArgument(TYPE_FUNC(bde.declinfo2.thetype), TYPE(&stsignedshort)); - bde.declinfo2.qual &= ~Q_VIRTUAL; - } - TYPE_FUNC(bde.declinfo2.thetype)->flags |= FUNC_IS_CTOR; - bde.declinfo2.name = constructor_name_node; - bde.declinfo2.qual |= r21; - CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 0, 0, 1, 0); - } else { - CError_Error(CErrorStr241); - } - if (tk == ';') - tk = lex(); - else - CError_Error(CErrorStr123); - goto restart; - } - } - // 6F8D8 - if (!r22 && CDecl_IsAccessDeclaration(tclass, access)) { - tk = lex(); - goto restart; - } - break; - } - break; - case TK_USING: - CError_QualifierCheck(r22); - tk = lex(); - CScope_ParseUsingDeclaration(tclass->nspace, access, 0); - tk = lex(); - goto restart; - case '~': - if ((tk = lex()) != TK_IDENTIFIER || tkidentifier != tclass->classname) { - CError_Error(CErrorStr241); - goto restart; - } - CError_QualifierCheck(r22 & ~(Q_VIRTUAL | Q_INLINE | Q_ASM)); - if (tclass->flags & CLASS_IS_TEMPL_ANY) { - t = lookahead(); - tkidentifier = tclass->classname; - if (t == '<') { - memclrw(&bde.declinfo, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&bde.declinfo, 0); - if (tk != '(' || bde.declinfo.thetype != TYPE(tclass) || bde.declinfo.nspace) { - CError_Error(CErrorStr241); - goto restart; - } - CPrep_UnLex(); - tk = TK_IDENTIFIER; - tkidentifier = tclass->classname; - } - } - memclrw(&bde.declinfo2, sizeof(DeclInfo)); - bde.declinfo2.qual = r22; - bde.declinfo2.exportflags = r20; - bde.declinfo2.section = r18; - if (tclass->sominfo) - bde.declinfo2.thetype = &stvoid; - else - bde.declinfo2.thetype = TYPE(&void_ptr); - scandeclarator(&bde.declinfo2); - if (IS_TYPE_FUNC(bde.declinfo2.thetype) && !TYPE_FUNC(bde.declinfo2.thetype)->args) { - if (!CScope_FindName(tclass->nspace, destructor_name_node)) { - if (tclass->sominfo) - bde.declinfo2.qual |= Q_VIRTUAL; - else - CDecl_AddArgument(TYPE_FUNC(bde.declinfo2.thetype), TYPE(&stsignedshort)); - bde.declinfo2.name = destructor_name_node; - TYPE_FUNC(bde.declinfo2.thetype)->flags |= FUNC_IS_DTOR; - bde.declinfo2.qual |= r21; - CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 1, 0, 1, 0); - } else { - CError_Error(CErrorStr133, CError_GetFunctionName(tclass->nspace, destructor_name_node, NULL)); - } - } else { - CError_Error(CErrorStr146); - } - if (tk == ';') - tk = lex(); - else - CError_Error(CErrorStr123); - goto restart; - case TK_OPERATOR: - if (CMangler_OperatorName(lookahead())) { - memclrw(&bde.declinfo, sizeof(DeclInfo)); - bde.declinfo.thetype = TYPE(&stsignedint); - goto after_various_things; - } else { - tk = lex(); - CError_QualifierCheck(r22 & ~(Q_VIRTUAL | Q_INLINE | Q_ASM)); - memclrw(&bde.declinfo2, sizeof(DeclInfo)); - bde.declinfo2.qual = r22; - bde.declinfo2.exportflags = r20; - bde.declinfo2.section = r18; - conversion_type_name(&bde.declinfo2); - bde.declinfo2.qual |= r21; - tmptype = bde.declinfo2.thetype; - CDecl_NewConvFuncType(&bde.declinfo2); - if ((tclass->flags & CLASS_IS_TEMPL) && CTemplTool_IsTemplateArgumentDependentType(tmptype)) - bde.declinfo2.name = CParser_GetUniqueName(); - CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 1, 1, 1, 0); - if (tk == ';') - tk = lex(); - else - CError_Error(CErrorStr123); - goto restart; - } - case TK_FRIEND: - tk = lex(); - CDecl_ParseFriendDecl(tclass); - goto restart; - } - - CError_QualifierCheck(r22 & Q_EXPLICIT); - global_access = access; - memclrw(&bde.declinfo, sizeof(DeclInfo)); - bde.declinfo.qual = r22; - bde.declinfo.exportflags = r20; - bde.declinfo.section = r18; - CParser_GetDeclSpecs(&bde.declinfo, 0); - - if (r19 && tk == '(' && (tclass->flags & CLASS_IS_TEMPL_ANY) && bde.declinfo.thetype == TYPE(tclass) && !bde.declinfo.nspace) { - CPrep_UnLex(); - tk = TK_IDENTIFIER; - tkidentifier = tclass->classname; - r22 = bde.declinfo.qual; - goto redo_thing; - } - - after_various_things: - switch (bde.declinfo.storageclass) { - case 0: - case TK_STATIC: - case TK_TYPEDEF: - case TK_MUTABLE: - break; - default: - CError_Error(CErrorStr177); - bde.declinfo.storageclass = 0; - } - - if (tk != ';') { - while (1) { - CDecl_ScanStructDeclarator(&bde); - if (r17) - bde.declinfo2.thetype = CTemplTool_ResolveMemberSelfRefs(TEMPL_CLASS(tclass), bde.declinfo2.thetype, &bde.declinfo2.qual); - if (bde.declinfo2.nspace) - CError_Error(CErrorStr200); - if (bde.declinfo2.operator_token) { - if (bde.declinfo.storageclass == TK_MUTABLE) - CError_QualifierCheck(Q_MUTABLE); - r19 = 0; - switch (bde.declinfo2.operator_token) { - case TK_NEW: - case TK_NEW_ARRAY: - CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL); - r19 = 1; - break; - case TK_DELETE: - case TK_DELETE_ARRAY: - CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL); - r19 = 1; - break; - default: - if (bde.declinfo2.storageclass == TK_STATIC) - CError_Error(CErrorStr193); - if (tclass->sominfo) - CError_Error(CErrorStr193); - } - - bde.declinfo2.storageclass = 0; - if (IS_TYPE_FUNC(bde.declinfo2.thetype)) { - bde.declinfo2.qual |= r21; - CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, r19 == 0, 0, 1, r19); - CDecl_CheckOperatorType(&bde.declinfo2, 1); - if (tclass->sominfo) - CSOM_FixNewDeleteFunctype(TYPE_FUNC(bde.declinfo2.thetype)); - } else { - CError_Error(CErrorStr121); - } - } else if (bde.xCD) { - if (bde.declinfo2.name == constructor_name_node || bde.declinfo2.name == destructor_name_node) - CError_Error(CErrorStr241); - switch (bde.declinfo2.storageclass) { - case TK_TYPEDEF: - CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL); - CDecl_TypedefDeclarator(&bde.declinfo2); - break; - case TK_STATIC: - CError_QualifierCheck(bde.declinfo2.qual & Q_VIRTUAL); - if (tclass->sominfo) - CError_Error(CErrorStr271); - if (IS_TYPE_FUNC(bde.declinfo2.thetype)) { - bde.declinfo2.qual |= r21; - bde.declinfo2.storageclass = 0; - if (bde.declinfo2.name == tclass->classname) - CError_Error(CErrorStr241); - CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 0, 0, 1, 1); - } else { - CDecl_ExtractClassExportFlags(&bde.declinfo2, tclass->eflags); - bde.declinfo2.storageclass = 0; - CDecl_DataDeclarator(&bde.declinfo2, access, 1); - } - break; - case 0: - case TK_MUTABLE: - if (IS_TYPE_FUNC(bde.declinfo2.thetype)) { - if (bde.declinfo2.name == tclass->classname) - CError_Error(CErrorStr241); - if (bde.declinfo.storageclass == TK_MUTABLE) - CError_QualifierCheck(Q_MUTABLE); - bde.declinfo2.qual |= r21; - CDecl_AddFunctionMember(decle, tclass, &bde.declinfo2, access, 1, 0, 1, 0); - } else { - CDecl_CompleteType(bde.declinfo2.thetype); - CanCreateObject(bde.declinfo2.thetype); - CError_QualifierCheck(bde.declinfo2.qual & (Q_VIRTUAL | Q_INLINE)); - if (bde.declinfo2.storageclass == TK_MUTABLE) - bde.declinfo2.qual |= Q_MUTABLE; - CDecl_InstanceDataDeclarator(decle, tclass, bde.declinfo2.thetype, bde.declinfo2.qual, bde.declinfo2.name, access); - } - break; - default: - CError_Error(CErrorStr177); - } - } - - // this should be 70058 - if (tk != ',') - break; // goes to 70148 - tk = lex(); - } - } else if (CParser_IsAnonymousUnion(&bde.declinfo, 1)) { - if ((ivar = CDecl_InstanceDataDeclarator(decle, tclass, bde.declinfo.thetype, 0, NULL, access))) - ivar->anonunion = 1; - for (scanivar = TYPE_CLASS(bde.declinfo.thetype)->ivars; scanivar; scanivar = scanivar->next) { - tmptype = scanivar->type; - if (IS_TYPE_BITFIELD(tmptype) && copts.reverse_bitfields) { - TypeBitfield *newtype = galloc(sizeof(TypeBitfield)); - *newtype = *TYPE_BITFIELD(tmptype); - CABI_ReverseBitField(newtype); - tmptype = TYPE(newtype); - } - if ((ivar = CDecl_InstanceDataDeclarator(decle, tclass, tmptype, scanivar->qual, scanivar->name, access))) - ivar->offset = scanivar->offset | 0x80000000; - } - } - - // this should be 70148 i think - if (tk != ';') { - CError_Error(CErrorStr123); - return; - } - CPrep_TokenStreamFlush(); - tk = lex(); - } -} - -static VClassList *AddVBaseToList(TypeClass *tclass, TypeClass *baseclass) { - VClassList *scan; - VClassList *vbase; - - for (scan = tclass->vbases; scan; scan = scan->next) { - if (scan->base == baseclass) - return NULL; - } - - vbase = galloc(sizeof(VClassList)); - memclrw(vbase, sizeof(VClassList)); - vbase->base = baseclass; - - if ((scan = tclass->vbases)) { - while (scan->next) - scan = scan->next; - scan->next = vbase; - } else { - tclass->vbases = vbase; - } - - return vbase; -} - -void CDecl_MakeVBaseList(TypeClass *tclass) { - ClassList *base; - VClassList *vbase; - VClassList *new_vbase; - SInt32 offset; - - if (copts.vbase_ctor_offset) - tclass->flags = tclass->flags | CLASS_FLAGS_8000; - - for (base = tclass->bases, offset = tclass->size; base; base = base->next) { - for (vbase = base->base->vbases; vbase; vbase = vbase->next) { - if ((new_vbase = AddVBaseToList(tclass, vbase->base))) { - new_vbase->offset = offset + CMach_MemberAlignValue(TYPE(vbase->base), offset); - offset = new_vbase->offset + vbase->base->size; - } - } - - if (base->is_virtual && (new_vbase = AddVBaseToList(tclass, base->base))) { - new_vbase->offset = offset + CMach_MemberAlignValue(TYPE(base->base), offset); - offset = new_vbase->offset + base->base->size; - } - } -} - -Boolean CDecl_CheckNewBase(TypeClass *tclass, TypeClass *baseclass, Boolean is_virtual) { - ClassList *scan; - - if (tclass == baseclass) { - CError_Error(CErrorStr131); - return 0; - } - - if (!(baseclass->flags & CLASS_COMPLETED)) { - CError_Error(CErrorStr136, baseclass, 0); - return 0; - } - - if (baseclass->flags & CLASS_SINGLE_OBJECT) { - if (is_virtual || tclass->bases) { - CError_Error(CErrorStr191); - return 0; - } - tclass->flags = tclass->flags | CLASS_SINGLE_OBJECT; - } - - if (baseclass->flags & CLASS_HANDLEOBJECT) { - if (is_virtual || tclass->bases) { - CError_Error(CErrorStr191); - return 0; - } - tclass->flags = tclass->flags | CLASS_HANDLEOBJECT; - } - - if (baseclass->sominfo) { - if (!is_virtual) - CError_Error(CErrorStr268); - CSOM_MakeSOMClass(tclass); - } else if (tclass->sominfo) { - CError_Error(CErrorStr267); - } - - if (tclass->bases && (tclass->flags & CLASS_SINGLE_OBJECT) && (tclass->flags & CLASS_SINGLE_OBJECT)) { - CError_Error(CErrorStr131); - return 0; - } - - if (copts.ecplusplus && (is_virtual || tclass->bases)) { - CError_Error(CErrorStr339); - return 0; - } - - for (scan = tclass->bases; scan; scan = scan->next) { - if (scan->base == baseclass) { - CError_Error(CErrorStr131); - return 0; - } - } - - if (baseclass->flags & CLASS_COM_OBJECT) - tclass->flags = tclass->flags | CLASS_COM_OBJECT; - if (baseclass->flags & CLASS_IS_CONVERTIBLE) - tclass->flags = tclass->flags | CLASS_IS_CONVERTIBLE; - if (baseclass->flags & CLASS_HAS_VBASES) - tclass->flags = tclass->flags | CLASS_HAS_VBASES; - - if (is_virtual) - tclass->flags = tclass->flags | CLASS_HAS_VBASES; - - return 1; -} - -static void CDecl_ParseBaseClassList(TypeClass *tclass, short mode, Boolean is_templ) { - Boolean is_virtual; - AccessType access; - NameResult pr; - ObjType *inherited_type; - ClassList *base; - ClassList *scan; - TypeClass *baseclass; - - do { - if (mode == CLASS_MODE_CLASS) - access = ACCESSPRIVATE; - else - access = ACCESSPUBLIC; - - is_virtual = 0; - if ((tk = lex()) == TK_VIRTUAL) { - tk = lex(); - is_virtual = 1; - } - - switch (tk) { - case TK_PRIVATE: - access = ACCESSPRIVATE; - tk = lex(); - break; - case TK_PUBLIC: - access = ACCESSPUBLIC; - tk = lex(); - break; - case TK_PROTECTED: - if (!copts.ARMconform) { - access = ACCESSPROTECTED; - tk = lex(); - } - break; - } - - if (tk == TK_VIRTUAL) { - if (is_virtual) - CError_Error(CErrorStr121); - is_virtual = 1; - tk = lex(); - } - - if (CScope_ParseDeclName(&pr)) { - if (!pr.type) { - if (!pr.name_4) { - CError_Error(CErrorStr121); - } else if (tk == TK_IDENTIFIER && pr.name_4 == tkidentifier) { - goto special_parsing; - } - CError_Error(CErrorStr140, tkidentifier->name); - continue; - } - - CDecl_CompleteType(pr.type); - if (is_templ && CTemplTool_IsTemplateArgumentDependentType(pr.type)) { - if (!IS_TYPE_CLASS(pr.type) || !(TYPE_CLASS(pr.type)->flags & CLASS_IS_TEMPL) || - CParser_CheckTemplateClassUsage(TEMPL_CLASS(pr.type), 1)) { - CTemplClass_RegisterBaseClass(TEMPL_CLASS(tclass), pr.type, access, is_virtual); - if (is_virtual) - tclass->flags = tclass->flags | CLASS_HAS_VBASES; - } - continue; - } - - if (!IS_TYPE_CLASS(pr.type) || (TYPE_CLASS(pr.type)->flags & CLASS_IS_TEMPL)) { - CError_Error(CErrorStr131); - continue; - } - baseclass = TYPE_CLASS(pr.type); - } else { - special_parsing: - if (!strcmp(tkidentifier->name, "HandleObject")) { - if (tclass->bases) - CError_Error(CErrorStr191); - tclass->flags |= CLASS_SINGLE_OBJECT | CLASS_HANDLEOBJECT; - tk = lex(); - break; - } - if (!strcmp(tkidentifier->name, "SingleObject") || !strcmp(tkidentifier->name, "SingleInheritance")) { - if (tclass->bases) - CError_Error(CErrorStr191); - tclass->flags = tclass->flags | CLASS_SINGLE_OBJECT; - tk = lex(); - break; - } - if (!strcmp(tkidentifier->name, "__comobject")) { - tclass->flags = tclass->flags | CLASS_COM_OBJECT; - tk = lex(); - break; - } - if (!strcmp(tkidentifier->name, "__somobject")) { - if (!is_virtual) - CError_Error(CErrorStr268); - CSOM_MakeSOMClass(tclass); - tk = lex(); - break; - } - if (!strcmp(tkidentifier->name, "__javaobject")) { - tk = lex(); - tclass->action = CLASS_ACTION_3; - break; - } - - CError_Error(CErrorStr140, tkidentifier->name); - continue; - } - - if (CDecl_CheckNewBase(tclass, baseclass, is_virtual)) { - base = galloc(sizeof(ClassList)); - memclrw(base, sizeof(ClassList)); - base->base = baseclass; - base->access = access; - base->is_virtual = is_virtual; - if ((scan = tclass->bases)) { - while (scan->next) - scan = scan->next; - scan->next = base; - } else { - tclass->bases = base; - } - } - } while ((tk = lex()) == ','); - - if (tclass->flags & CLASS_HAS_VBASES) - CDecl_MakeVBaseList(tclass); - - if (copts.def_inherited && tclass->bases && !tclass->bases->next) { - inherited_type = galloc(sizeof(ObjType)); - memclrw(inherited_type, sizeof(ObjType)); - inherited_type->otype = OT_TYPE; - inherited_type->access = ACCESSPUBLIC; - inherited_type->type = TYPE(tclass->bases->base); - CScope_AddObject(tclass->nspace, GetHashNameNodeExport("inherited"), OBJ_BASE(inherited_type)); - } -} - -static AccessType getaccesstype(AccessType a, AccessType b, AccessType c) { - if (a == ACCESSNONE || b == ACCESSNONE || b == ACCESSPRIVATE) - return ACCESSNONE; - - if (c == ACCESSPUBLIC && b != ACCESSPUBLIC) - return ACCESSNONE; - - return ACCESSPUBLIC; -} - -static TypeMemberFunc *CDecl_MakeDefaultCtorType(TypeClass *tclass) { - TypeMemberFunc *tmeth = galloc(sizeof(TypeMemberFunc)); - memclrw(tmeth, sizeof(TypeMemberFunc)); - tmeth->type = TYPEFUNC; - tmeth->functype = TYPE(&void_ptr); - tmeth->flags = FUNC_IS_CTOR | FUNC_AUTO_GENERATED | FUNC_METHOD; - tmeth->theclass = tclass; - CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1); - - if (tclass->flags & CLASS_HAS_VBASES) - CDecl_AddArgument(TYPE_FUNC(tmeth), TYPE(&stsignedshort)); - - CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass); - return tmeth; -} - -static void CDecl_AddDefArgConstructor(TypeClass *tclass) { - // empty -} - -static void CDecl_AddMemberFunctionObject(TypeClass *tclass, HashNameNode *name, TypeMemberFunc *tmeth, AccessType access) { - Object *obj = CParser_NewCompilerDefFunctionObject(); - obj->name = name; - obj->type = TYPE(tmeth); - obj->qual = Q_MANGLE_NAME; - obj->access = access; - obj->nspace = tclass->nspace; - obj->qual = obj->qual | Q_INLINE; - CScope_AddObject(tclass->nspace, obj->name, OBJ_BASE(obj)); -} - -static void CDecl_AddDefaultConstructor(ClassLayout *decle, TypeClass *tclass) { - ClassList *base; - ObjMemberVar *ivar; - Object *obj; - Boolean has_ctor; - - if (CClass_Constructor(tclass)) { - CDecl_AddDefArgConstructor(tclass); - return; - } - - has_ctor = 0; - - if (tclass->flags & CLASS_HAS_VBASES) - has_ctor = 1; - if (decle->has_vtable) - has_ctor = 1; - - for (base = tclass->bases; base; base = base->next) { - if (CClass_Constructor(base->base)) - has_ctor = 1; - } - - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - Type *type = ivar->type; - while (IS_TYPE_ARRAY(type)) - type = TYPE_POINTER(type)->target; - if (IS_TYPE_CLASS(type) && CClass_Constructor(TYPE_CLASS(type))) - has_ctor = 1; - } - - if (has_ctor) { - CDecl_AddMemberFunctionObject( - tclass, - constructor_name_node, - CDecl_MakeDefaultCtorType(tclass), - ACCESSPUBLIC - ); - } -} - -static TypeMemberFunc *CDecl_MakeCopyCtorType(TypeClass *tclass, Boolean is_const) { - FuncArg *arg; - TypeMemberFunc *tmeth = galloc(sizeof(TypeMemberFunc)); - memclrw(tmeth, sizeof(TypeMemberFunc)); - tmeth->type = TYPEFUNC; - tmeth->functype = TYPE(&void_ptr); - tmeth->flags = FUNC_IS_CTOR | FUNC_AUTO_GENERATED | FUNC_METHOD; - tmeth->theclass = tclass; - CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1); - - arg = CParser_NewFuncArg(); - if (is_const) - arg->qual = Q_CONST; - arg->type = CDecl_NewRefPointerType(TYPE(tclass)); - tmeth->args = arg; - - if (tclass->flags & CLASS_HAS_VBASES) - CDecl_AddArgument(TYPE_FUNC(tmeth), TYPE(&stsignedshort)); - - CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass); - return tmeth; -} - -static void CDecl_AddDefaultCopyConstructor(ClassLayout *decle, TypeClass *tclass) { - ClassList *base; - ObjMemberVar *ivar; - Object *obj; - AccessType access; - Boolean has_copyctor; - Boolean is_const; - FuncArg *arg; - - if (CClass_CopyConstructor(tclass)) - return; - - access = ACCESSPUBLIC; - is_const = 1; - has_copyctor = 0; - - if (CClass_Constructor(tclass)) - has_copyctor = 1; - if ((tclass->flags & CLASS_HAS_VBASES) || decle->has_vtable) - has_copyctor = 1; - - for (base = tclass->bases; base; base = base->next) { - if ((obj = CClass_CopyConstructor(base->base))) { - has_copyctor = 1; - access = getaccesstype(access, obj->access, ACCESSPRIVATE); - arg = TYPE_FUNC(obj->type)->args->next; - if (base->base->flags & CLASS_HAS_VBASES) - arg = arg->next; - if (!(arg->qual & Q_CONST)) - is_const = 0; - } - } - - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - Type *type = ivar->type; - while (IS_TYPE_ARRAY(type)) - type = TYPE_POINTER(type)->target; - if (IS_TYPE_CLASS(type) && (obj = CClass_CopyConstructor(TYPE_CLASS(type)))) { - has_copyctor = 1; - access = getaccesstype(access, obj->access, ACCESSPUBLIC); - arg = TYPE_FUNC(obj->type)->args->next; - if (TYPE_CLASS(type)->flags & CLASS_HAS_VBASES) - arg = arg->next; - if (!(arg->qual & Q_CONST)) - is_const = 0; - } - } - - if (has_copyctor) { - CDecl_AddMemberFunctionObject( - tclass, - constructor_name_node, - CDecl_MakeCopyCtorType(tclass, is_const), - access - ); - } -} - -static TypeMemberFunc *CDecl_MakeAssignmentOperatorType(TypeClass *tclass, Boolean is_const) { - FuncArg *arg; - TypeMemberFunc *tmeth = galloc(sizeof(TypeMemberFunc)); - memclrw(tmeth, sizeof(TypeMemberFunc)); - tmeth->type = TYPEFUNC; - tmeth->functype = CDecl_NewRefPointerType(TYPE(tclass)); - tmeth->flags = FUNC_AUTO_GENERATED | FUNC_METHOD; - tmeth->theclass = tclass; - CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1); - - arg = CParser_NewFuncArg(); - if (is_const) - arg->qual = Q_CONST; - arg->type = CDecl_NewRefPointerType(TYPE(tclass)); - tmeth->args = arg; - - CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass); - return tmeth; -} - -static void CDecl_AddDefaultAssignmentOperator(ClassLayout *decle, TypeClass *tclass) { - ClassList *base; - ObjMemberVar *ivar; - Object *obj; - AccessType access; - Boolean is_const; - Boolean has_ass; - DeclInfo declinfo; - - is_const = 1; - has_ass = 0; - access = ACCESSPUBLIC; - - if (!CClass_AssignmentOperator(tclass)) { - if (!copts.old_argmatch) - has_ass = 1; - - if ((tclass->flags & CLASS_HAS_VBASES) || decle->has_vtable || CClass_MemberObject(tclass, asop_name_node)) - has_ass = 1; - - for (base = tclass->bases; base; base = base->next) { - if ((obj = CClass_AssignmentOperator(base->base))) { - has_ass = 1; - access = getaccesstype(access, obj->access, ACCESSPRIVATE); - if (!(TYPE_FUNC(obj->type)->args->next->qual & Q_CONST)) - is_const = 0; - } - } - - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - Type *type = ivar->type; - while (IS_TYPE_ARRAY(type)) - type = TYPE_POINTER(type)->target; - if (IS_TYPE_CLASS(type) && (obj = CClass_AssignmentOperator(TYPE_CLASS(type)))) { - has_ass = 1; - access = getaccesstype(access, obj->access, ACCESSPUBLIC); - if (!(TYPE_FUNC(obj->type)->args->next->qual & Q_CONST)) - is_const = 0; - } - } - } - - if (has_ass) { - memclrw(&declinfo, sizeof(DeclInfo)); - declinfo.qual |= Q_INLINE; - declinfo.thetype = (Type *) CDecl_MakeAssignmentOperatorType(tclass, is_const); - declinfo.name = asop_name_node; - CDecl_AddFunctionMember(decle, tclass, &declinfo, access, 1, 0, 0, 0); - } -} - -TypeMemberFunc *CDecl_MakeDefaultDtorType(TypeClass *tclass, Boolean is_virtual) { - TypeMemberFunc *tmeth = galloc(sizeof(TypeMemberFunc)); - memclrw(tmeth, sizeof(TypeMemberFunc)); - tmeth->type = TYPEFUNC; - tmeth->functype = (Type *) &void_ptr; - tmeth->flags = FUNC_IS_DTOR | FUNC_AUTO_GENERATED | FUNC_METHOD; - tmeth->theclass = tclass; - CDecl_SetFuncFlags(TYPE_FUNC(tmeth), 1); - if (is_virtual) - CDecl_AddArgument(TYPE_FUNC(tmeth), TYPE(&stsignedshort)); - CDecl_AddThisPointerArgument(TYPE_FUNC(tmeth), tclass); - return tmeth; -} - -static void CDecl_AddDefaultDestructor(ClassLayout *decle, TypeClass *tclass) { - ClassList *base; - ObjMemberVar *ivar; - Object *obj; - AccessType access; - Boolean has_dtor; - Boolean is_virtual; - DeclInfo declinfo; - - if (CClass_Destructor(tclass)) - return; - - has_dtor = 0; - is_virtual = 0; - access = ACCESSPUBLIC; - - for (base = tclass->bases; base; base = base->next) { - if ((obj = CClass_Destructor(base->base))) { - has_dtor = 1; - if (obj->datatype == DVFUNC) - is_virtual = 1; - access = getaccesstype(access, obj->access, ACCESSPRIVATE); - } - } - - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - Type *type = ivar->type; - while (IS_TYPE_ARRAY(type)) - type = TYPE_POINTER(type)->target; - if (IS_TYPE_CLASS(type) && (obj = CClass_Destructor(TYPE_CLASS(type)))) { - has_dtor = 1; - access = getaccesstype(access, obj->access, ACCESSPUBLIC); - } - } - - if (has_dtor) { - memclrw(&declinfo, sizeof(DeclInfo)); - declinfo.qual |= Q_INLINE; - if (is_virtual) - declinfo.qual |= Q_VIRTUAL; - - declinfo.thetype = (Type *) CDecl_MakeDefaultDtorType(tclass, 1); - declinfo.name = destructor_name_node; - CDecl_AddFunctionMember(decle, tclass, &declinfo, access, 1, 0, 0, 0); - } -} - -static void CDecl_SetupClassLayout(ClassLayout *decle, TypeClass *tclass, ObjBase **objbuf) { - SInt32 index; - SInt32 i; - Object *obj; - CScopeObjectIterator iter; - ObjMemberVar *ivar; - SInt32 bufsize; - - if (decle->lex_order_count > 32) { - bufsize = decle->lex_order_count * sizeof(ObjBase *); - objbuf = lalloc(bufsize); - } else { - bufsize = 32 * sizeof(ObjBase *); - } - memclrw(objbuf, bufsize); - decle->objlist = objbuf; - - CScope_InitObjectIterator(&iter, tclass->nspace); - index = 0; - while (1) { - obj = OBJECT(CScope_NextObjectIteratorObject(&iter)); - if (!obj) break; - - if (!IS_TYPE_FUNC(obj->type)) - continue; - if (!IS_TYPEFUNC_METHOD(TYPE_FUNC(obj->type))) - continue; - if (obj->datatype == DALIAS) - continue; - - i = TYPE_METHOD(obj->type)->vtbl_index; - if (i > 0) { - CError_ASSERT(6363, (i - 1) < decle->lex_order_count && !objbuf[(int) (i - 1)]); - objbuf[(int) (i - 1)] = OBJ_BASE(obj); - index++; - if (obj->datatype != DVFUNC && !TYPE_METHOD(obj->type)->is_static && CClass_OverridesBaseMember(tclass, obj->name, obj)) - CDecl_MakeFunctionVirtual(tclass, obj); - - if (obj->datatype == DVFUNC) { - decle->has_vtable = 1; - if (!tclass->vtable) { - CABI_AddVTable(tclass); - decle->xA = i - 1; - } else { - if ((i - 1) < decle->xA) - decle->xA = i - 1; - } - } else if (TYPE_FUNC(obj->type)->flags & FUNC_PURE) { - CError_Error(CErrorStr351, obj); - TYPE_FUNC(obj->type)->flags &= ~FUNC_PURE; - } - } else { - CError_ASSERT(6412, i == 0); - } - - if (!tclass->sominfo) - TYPE_METHOD(obj->type)->vtbl_index = 0; - } - - if (!tclass->action) { - for (i = 0; i < decle->lex_order_count; i++) { - Object *obj2 = OBJECT(objbuf[i]); - if (obj2 && obj2->datatype == DVFUNC && !(obj2->qual & Q_INLINE) && !(TYPE_FUNC(obj2->type)->flags & FUNC_PURE)) { - tclass->action = CLASS_ACTION_1; - TYPE_FUNC(obj2->type)->flags |= FUNC_FLAGS_4; - break; - } - } - } - - if (!tclass->sominfo) { - for (i = 0, ivar = tclass->ivars; i < decle->lex_order_count; i++) { - if (!objbuf[i]) { - CError_ASSERT(6449, ivar); - objbuf[i] = OBJ_BASE(ivar); - ivar = ivar->next; - index++; - } - } - CError_ASSERT(6455, ivar == NULL); - } - - CError_ASSERT(6458, index == decle->lex_order_count); -} - -void CDecl_CompleteClass(ClassLayout *decle, TypeClass *tclass) { - ClassList *base; - ObjBase *buf[32]; - - for (base = tclass->bases; base; base = base->next) { - if (base->base->vtable) - decle->has_vtable = 1; - } - - if (!tclass->sominfo) { - CDecl_AddDefaultDestructor(decle, tclass); - CDecl_AddDefaultAssignmentOperator(decle, tclass); - CDecl_AddDefaultConstructor(decle, tclass); - CDecl_AddDefaultCopyConstructor(decle, tclass); - } - - CDecl_SetupClassLayout(decle, tclass, buf); - if (decle->has_vtable) - CClass_CheckOverrides(tclass); - CABI_LayoutClass(decle, tclass); - if (tclass->sominfo) - CSOM_ClassComplete(tclass); - - if ((tclass->flags & CLASS_IS_TEMPL_INST) && !TEMPL_CLASS_INST(tclass)->is_specialized) - tclass->action = CLASS_ACTION_0; - - if (!tclass->action) - CClass_MakeStaticActionClass(tclass); - CClass_ClassDefaultFuncAction(tclass); -} - -TypeClass *CDecl_DefineClass(NameSpace *nspace, HashNameNode *name, TypeClass *tclass, short mode, Boolean flag2, Boolean flag3) { - NameSpace *mynspace; - ObjType *objtype; - - if (!tclass && nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL)) { - CError_ASSERT(6556, !flag2); - return TYPE_CLASS(CTemplClass_DefineNestedClass(TEMPL_CLASS(nspace->theclass), name, mode)); - } - - mynspace = CScope_NewListNameSpace(name, 1); - if (!tclass) { - tclass = galloc(sizeof(TypeClass)); - memclrw(tclass, sizeof(TypeClass)); - } - - tclass->type = TYPECLASS; - tclass->align = 1; - tclass->mode = mode; - tclass->action = CLASS_ACTION_0; - if (name) { - tclass->classname = name; - if (flag3) { - if (flag2) { - objtype = galloc(sizeof(ObjType)); - memclrw(objtype, sizeof(ObjType)); - objtype->otype = OT_TYPE; - objtype->access = ACCESSPUBLIC; - objtype->type = (Type *) tclass; - CScope_AddObject(nspace, name, OBJ_BASE(objtype)); - } else { - CScope_DefineTypeTag(nspace, name, (Type *) tclass); - } - } - CScope_DefineTypeTag(mynspace, name, (Type *) tclass); - - if (cscope_currentfunc) - mynspace->name = CParser_AppendUniqueNameFile(name->name); - - if (copts.direct_to_som && nspace == cscope_root && !strcmp(name->name, "SOMObject")) - CSOM_MakeSOMClass(tclass); - } else { - tclass->classname = CParser_AppendUniqueNameFile("@class"); - mynspace->name = tclass->classname; - } - - tclass->nspace = mynspace; - mynspace->theclass = tclass; - mynspace->parent = nspace; - if (!nspace->is_global) - CParser_RegisterNonGlobalClass(tclass); - - return tclass; -} - -void CDecl_ParseClassDeclSpec(UInt8 *declspec) { - DeclInfo declinfo; - - if ((tk = lex()) == '(') { - memclrw(&declinfo, sizeof(DeclInfo)); - CParser_ParseDeclSpec(&declinfo, 1); - if (declinfo.exportflags & EXPORT_FLAGS_INTERNAL) - *declspec = *declspec | CLASS_EFLAGS_INTERNAL; - if (declinfo.exportflags & EXPORT_FLAGS_IMPORT) - *declspec = *declspec | CLASS_EFLAGS_IMPORT; - if (declinfo.exportflags & EXPORT_FLAGS_EXPORT) - *declspec = *declspec | CLASS_EFLAGS_EXPORT; - if ((tk = lex()) != ')') - CError_Error(CErrorStr115); - else - tk = lex(); - } else { - CError_Error(CErrorStr114); - } -} - -static TemplClass *CDecl_SpecializeTemplateClass(TemplClass *tmclass) { - tmclass->theclass.nspace->names = 0; - tmclass->theclass.nspace->data.list = NULL; - tmclass->theclass.ivars = NULL; - tmclass->theclass.bases = NULL; - tmclass->theclass.vbases = NULL; - tmclass->theclass.friends = NULL; - tmclass->theclass.vtable = NULL; - tmclass->members = NULL; - tmclass->instances = NULL; - tmclass->pspec_owner = NULL; - tmclass->pspecs = NULL; - tmclass->actions = NULL; - tmclass->lex_order_count = 0; - tmclass->align = 0; - tmclass->flags = TEMPLCLASS_FLAGS_2; - return tmclass; -} - -void CDecl_ParseClass(DeclInfo *declinfo, short mode, Boolean flag1, UInt8 class_declspec) { - ClassLayout decle; - TypeClass *tclass; - HashNameNode *classname; - Type *search; - short t; - NameSpace *nspace; - NameResult pr; - CScopeSave scopesave; - GList gl; - FileOffsetInfo offsetsave; - SInt32 offset; - Boolean is_templ; - Boolean add_to_browse; - - memclrw(&decle, sizeof(ClassLayout)); - if (declinfo->x28) { - tclass = TYPE_CLASS(declinfo->x28); - } else { - if (tk == TK_UU_DECLSPEC) - CDecl_ParseClassDeclSpec(&class_declspec); - - switch (tk) { - case ':': - case '{': - tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1); - tclass->eflags |= class_declspec; - break; - case TK_IDENTIFIER: - classname = tkidentifier; - if (!declinfo->in_friend_decl && !declinfo->x4F && ((t = lookahead()) == ':' || t == ';' || t == '{')) { - tk = lex(); - search = CScope_GetLocalTagType(cscope_current, classname); - if (search) { - tagtype_search: - if (!IS_TYPE_CLASS(search)) { - if ((IS_TYPE_TEMPLATE(search) || IS_TYPE_STRUCT(search)) && tk != '{' && tk != ':') { - declinfo->thetype = search; - return; - } - if (!IS_TYPE_TEMPLATE(search) || !(tclass = TYPE_CLASS(CTemplTool_GetSelfRefTemplate(search)))) { - CError_Error(CErrorStr132, classname->name); - tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1); - break; - } - } else { - tclass = TYPE_CLASS(search); - } - if (tclass->mode != mode) { - if ( - (mode == CLASS_MODE_CLASS && tclass->mode == CLASS_MODE_STRUCT) || - (mode == CLASS_MODE_STRUCT && tclass->mode == CLASS_MODE_CLASS) - ) - { - if (copts.warn_structclass) - CError_Warning(CErrorStr343); - } else { - CError_Error(CErrorStr132, classname); - } - } - tclass->eflags |= class_declspec; - break; - } else { - tclass = CDecl_DefineClass(cscope_current, classname, NULL, mode, 0, 1); - tclass->eflags |= class_declspec; - break; - } - } else { - tkidentifier = classname; - } - default: - if (!CScope_ParseElaborateName(&pr)) { - CError_Error(CErrorStr121); - declinfo->thetype = TYPE(&stsignedint); - return; - } - - tk = lex(); - if ((search = pr.type)) { - goto tagtype_search; - } - - CError_ASSERT(6786, pr.name_4); - - tclass = CDecl_DefineClass(CScope_FindNonClassNonFunctionNS(cscope_current), pr.name_4, NULL, mode, 0, 1); - tclass->eflags |= class_declspec; - } - } - - declinfo->thetype = TYPE(tclass); - if (tk == ':' || tk == '{') { - if (declinfo->in_friend_decl) - CError_Error(CErrorStr201); - - if (tclass->flags & CLASS_COMPLETED) { - if ( - (tclass->flags & CLASS_IS_TEMPL) && - !TEMPL_CLASS(tclass)->instances && - !(TEMPL_CLASS(tclass)->flags & TEMPLCLASS_FLAGS_2) - ) - { - tclass = TYPE_CLASS(CDecl_SpecializeTemplateClass(TEMPL_CLASS(tclass))); - } else { - CError_Error(CErrorStr132, tclass->classname->name); - tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1); - } - } - - for (nspace = cscope_current; nspace; nspace = nspace->parent) { - if (nspace == tclass->nspace) { - CError_Error(CErrorStr132, tclass->classname->name); - tclass = CDecl_DefineClass(cscope_current, NULL, NULL, mode, 0, 1); - break; - } - } - - is_templ = (tclass->flags & CLASS_IS_TEMPL) != 0; - if (tclass->flags & CLASS_IS_TEMPL_INST) { - TEMPL_CLASS_INST(tclass)->is_instantiated = 1; - if (!declinfo->x28) - TEMPL_CLASS_INST(tclass)->is_specialized = 1; - } - - CError_ASSERT(6853, copts.structalignment >= 0 && copts.structalignment <= 14); - - tclass->eflags = tclass->eflags | (((copts.structalignment + 1) << 4) & 0xF0); - if (tk == ':') - CDecl_ParseBaseClassList(tclass, mode, is_templ); - - CScope_SetClassDefScope(tclass, &scopesave); - if (tk == '{') { - tk = lex(); - if ((add_to_browse = cparamblkptr->browseoptions.recordClasses && declinfo->file->recordbrowseinfo)) { - offsetsave = member_fileoffset; - CBrowse_BeginClass(declinfo, &gl); - } - CDecl_ParseClassMembers(&decle, tclass, mode); - offset = CPrep_BrowserFileOffset(); - if (flag1) - tk = lex(); - if (add_to_browse) { - member_fileoffset = offsetsave; - if (flag1 && tk == ';') - CPrep_BrowserFileOffset(); - CBrowse_EndClass(offset, &gl); - } - } else { - CError_Error(CErrorStr135); - } - - if (is_templ) - CTemplClass_CompleteClass(TEMPL_CLASS(tclass), &decle); - else - CDecl_CompleteClass(&decle, tclass); - CScope_RestoreScope(&scopesave); - } -} diff --git a/compiler_and_linker/unsorted/CError.c b/compiler_and_linker/unsorted/CError.c deleted file mode 100644 index 02265c3..0000000 --- a/compiler_and_linker/unsorted/CError.c +++ /dev/null @@ -1,1098 +0,0 @@ -#include "cos.h" -#include "compiler/CClass.h" -#include "compiler/CError.h" -#include "compiler/CFunc.h" -#include "compiler/CInt64.h" -#include "compiler/CMangler.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CTemplateNew.h" -#include "compiler/CompilerTools.h" -#include "compiler/InlineAsm.h" -#include "compiler/Unmangle.h" -#include "compiler/enode.h" -#include "compiler/objc.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/templates.h" -#include "compiler/tokens.h" - -TStreamElement *cerror_locktoken; -static TStreamElement *cerror_token; -static short cerror_errorcount; -static SInt32 cerror_lasterrorline; -char cerror_synchdata[32]; -short cerror_synchoffset; -int CError_BreakPointcount; - -// forward decls -static void CError_BufferAppendType(CErrorBuffer *eb, Type *ty, UInt32 qual); -static void CError_AppendObjectName(CErrorBuffer *eb, Object *obj); - -void CError_Init(void) { - cerror_errorcount = 0; - cerror_lasterrorline = -1; - cerror_token = 0; - cerror_locktoken = 0; -} - -void CError_SetErrorToken(TStreamElement *token) { - if (token && token->tokenfile) - cerror_token = token; -} - -void CError_SetNullErrorToken(void) { - cerror_token = (TStreamElement *) -1; -} - -void CError_LockErrorPos(TStreamElement *token, TStreamElement **saved) { - *saved = cerror_locktoken; - if (token && token->tokenfile) - cerror_locktoken = token; -} - -void CError_UnlockErrorPos(TStreamElement **saved) { - cerror_locktoken = *saved; -} - -void CError_ResetErrorSkip(void) { - cerror_lasterrorline = -1; -} - -static void CError_GetErrorString(char *buf, short code) { - CError_ASSERT(142, code >= CErrorStr100 && code < CErrorStrMAX); - COS_GetString(buf, 10000, code - 99); -} - -static void CError_BufferInit(CErrorBuffer *eb, char *buf, SInt32 bufSize) { - eb->start = eb->end = buf; - eb->size = eb->remaining = bufSize - 1; -} - -static void CError_BufferGrow(CErrorBuffer *eb, SInt32 amount) { - char *newBuf; - - newBuf = lalloc(eb->size + amount); - memcpy(newBuf, eb->start, eb->size); - eb->start = newBuf; - eb->end = newBuf + eb->size - eb->remaining; - eb->size += amount; - eb->remaining += amount; -} - -static void CError_BufferAppendChar(CErrorBuffer *eb, char ch) { - if (eb) { - if (!eb->remaining) - CError_BufferGrow(eb, 256); - *(eb->end++) = ch; - eb->remaining--; - } -} - -static void CError_BufferAppendString(CErrorBuffer *eb, const char *str) { - size_t len; - - if (eb) { - len = strlen(str); - if (eb->remaining < len) - CError_BufferGrow(eb, len); - memcpy(eb->end, str, len); - eb->end += len; - eb->remaining -= len; - } -} - -static void CError_BufferTerminate(CErrorBuffer *eb) { - if (eb->remaining == 0) - CError_BufferGrow(eb, 1); - *eb->end = 0; - eb->remaining = 0; -} - -static void CError_BufferAppendQualifier(CErrorBuffer *eb, UInt32 qual) { - if (qual & Q_PASCAL) - CError_BufferAppendString(eb, "pascal "); - if (qual & Q_CONST) - CError_BufferAppendString(eb, "const "); - if (qual & Q_VOLATILE) - CError_BufferAppendString(eb, "volatile "); - if (qual & Q_EXPLICIT) - CError_BufferAppendString(eb, "explicit "); - if (qual & Q_RESTRICT) - CError_BufferAppendString(eb, "restrict "); -} - -static void CError_BufferAppendTemplArgExpr(CErrorBuffer *eb, ENode *node) { - char buf[32]; - - if (node) { - switch (node->type) { - case EINTCONST: - CInt64_PrintDec(buf, node->data.intval); - CError_BufferAppendString(eb, buf); - return; - case EOBJREF: - CError_BufferAppendChar(eb, '&'); - CError_AppendObjectName(eb, node->data.objref); - return; - } - } - - CError_BufferAppendString(eb, "{targ_expr}"); -} - -static void CError_BufferAppendTemplArg(CErrorBuffer *eb, TemplArg *targ) { - switch (targ->pid.type) { - case TPT_TYPE: - CError_BufferAppendType(eb, targ->data.typeparam.type, targ->data.typeparam.qual); - break; - case TPT_NONTYPE: - CError_BufferAppendTemplArgExpr(eb, targ->data.paramdecl.expr); - break; - case TPT_TEMPLATE: - CError_BufferAppendType(eb, targ->data.ttargtype, 0); - break; - default: - CError_FATAL(300); - } -} - -static void CError_BufferAppendTemplArgs(CErrorBuffer *eb, TemplArg *targs) { - if (targs) { - CError_BufferAppendChar(eb, '<'); - while (targs) { - CError_BufferAppendTemplArg(eb, targs); - if (targs->next) - CError_BufferAppendString(eb, ", "); - targs = targs->next; - } - CError_BufferAppendChar(eb, '>'); - } -} - -static void CError_BufferAppendNameSpace(CErrorBuffer *eb, NameSpace *nspace) { - while (nspace) { - if (nspace->name) { - CError_BufferAppendNameSpace(eb, nspace->parent); - if (nspace->theclass) { - CError_BufferAppendString(eb, nspace->theclass->classname->name); - if (nspace->theclass->flags & CLASS_IS_TEMPL_INST) - CError_BufferAppendTemplArgs( - eb, - !TEMPL_CLASS_INST(nspace->theclass)->oargs ? TEMPL_CLASS_INST(nspace->theclass)->inst_args : TEMPL_CLASS_INST(nspace->theclass)->oargs - ); - } else { - CError_BufferAppendString(eb, nspace->name->name); - } - CError_BufferAppendString(eb, "::"); - return; - } - nspace = nspace->parent; - } -} - -static void CError_BufferAppendPType(CErrorBuffer *eb, Type *ty) { - switch (ty->type) { - case TYPEPOINTER: - CError_BufferAppendPType(eb, TYPE_POINTER(ty)->target); - if (TYPE_POINTER(ty)->qual & Q_REFERENCE) - CError_BufferAppendString(eb, "&"); - else - CError_BufferAppendString(eb, "*"); - CError_BufferAppendQualifier(eb, TYPE_POINTER(ty)->qual); - break; - case TYPEMEMBERPOINTER: - CError_BufferAppendPType(eb, TYPE_MEMBER_POINTER(ty)->ty1); - CError_BufferAppendType(eb, TYPE_MEMBER_POINTER(ty)->ty2, 0); - CError_BufferAppendString(eb, "::*"); - CError_BufferAppendQualifier(eb, TYPE_MEMBER_POINTER(ty)->qual); - break; - } -} - -static void CError_BufferAppendTemplDepType(CErrorBuffer *eb, TypeTemplDep *type) { - char buf[64]; - switch (type->dtype) { - case TEMPLDEP_ARGUMENT: - if (type->u.pid.nindex) - sprintf(buf, "T%" PRId32 "_%" PRId32, type->u.pid.nindex, type->u.pid.index); - else - sprintf(buf, "T%" PRId32, type->u.pid.index); - CError_BufferAppendString(eb, buf); - break; - case TEMPLDEP_QUALNAME: - CError_BufferAppendTemplDepType(eb, type->u.qual.type); - CError_BufferAppendString(eb, "::"); - CError_BufferAppendString(eb, type->u.qual.name->name); - break; - case TEMPLDEP_TEMPLATE: - CError_BufferAppendType(eb, (Type *) type->u.templ.templ, 0); - CError_BufferAppendTemplArgs(eb, type->u.templ.args); - break; - case TEMPLDEP_ARRAY: - CError_BufferAppendType(eb, type->u.array.type, 0); - CError_BufferAppendChar(eb, '['); - CError_BufferAppendTemplArgExpr(eb, type->u.array.index); - CError_BufferAppendChar(eb, ']'); - break; - case TEMPLDEP_QUALTEMPL: - CError_BufferAppendTemplDepType(eb, type->u.qualtempl.type); - CError_BufferAppendString(eb, "::"); - CError_BufferAppendTemplArgs(eb, type->u.qualtempl.args); - break; - case TEMPLDEP_BITFIELD: - CError_BufferAppendType(eb, type->u.bitfield.type, 0); - CError_BufferAppendChar(eb, '['); - CError_BufferAppendTemplArgExpr(eb, type->u.bitfield.size); - CError_BufferAppendChar(eb, ']'); - break; - default: - CError_FATAL(463); - } -} - -static void CError_BufferAppendFuncArgs(CErrorBuffer *eb, TypeFunc *tfunc, Boolean isMethod) { - FuncArg *arg; - UInt32 qual; - - qual = 0; - CError_BufferAppendChar(eb, '('); - if ((arg = tfunc->args)) { - if (isMethod) { - qual = arg->qual; - arg = arg->next; - if (arg) - arg = arg->next; - } else if ((tfunc->flags & FUNC_METHOD) && !TYPE_METHOD(tfunc)->is_static) { - qual = arg->qual; - arg = arg->next; - if (arg) { - if ((tfunc->flags & FUNC_IS_DTOR) || ((tfunc->flags & FUNC_IS_CTOR) && (TYPE_METHOD(tfunc)->theclass->flags & CLASS_HAS_VBASES))) - arg = arg->next; - } - } - - while (arg) { - if (arg == &elipsis || arg == &oldstyle) { - CError_BufferAppendString(eb, "..."); - break; - } - - CError_BufferAppendType(eb, arg->type, arg->qual); - - if ((arg = arg->next)) - CError_BufferAppendString(eb, ", "); - else - break; - } - } - CError_BufferAppendChar(eb, ')'); - if (qual) - CError_BufferAppendQualifier(eb, qual); -} - -static void CError_BufferAppendType(CErrorBuffer *eb, Type *ty, UInt32 qual) { - // not matching - register issues - Type *scan; - Type *scan2; - char buf[16]; - - switch (ty->type) { - case TYPEVOID: - CError_BufferAppendQualifier(eb, qual); - CError_BufferAppendString(eb, "void"); - return; - case TYPEINT: - case TYPEFLOAT: - CError_BufferAppendQualifier(eb, qual); - switch (TYPE_INTEGRAL(ty)->integral) { - case IT_BOOL: - CError_BufferAppendString(eb, "bool"); - return; - case IT_CHAR: - CError_BufferAppendString(eb, "char"); - return; - case IT_UCHAR: - CError_BufferAppendString(eb, "unsigned char"); - return; - case IT_SCHAR: - CError_BufferAppendString(eb, "signed char"); - return; - case IT_WCHAR_T: - CError_BufferAppendString(eb, "wchar_t"); - return; - case IT_SHORT: - CError_BufferAppendString(eb, "short"); - return; - case IT_USHORT: - CError_BufferAppendString(eb, "unsigned short"); - return; - case IT_INT: - CError_BufferAppendString(eb, "int"); - return; - case IT_UINT: - CError_BufferAppendString(eb, "unsigned int"); - return; - case IT_LONG: - CError_BufferAppendString(eb, "long"); - return; - case IT_ULONG: - CError_BufferAppendString(eb, "unsigned long"); - return; - case IT_LONGLONG: - CError_BufferAppendString(eb, "long long"); - return; - case IT_ULONGLONG: - CError_BufferAppendString(eb, "unsigned long long"); - return; - case IT_FLOAT: - CError_BufferAppendString(eb, "float"); - return; - case IT_SHORTDOUBLE: - CError_BufferAppendString(eb, "short double"); - return; - case IT_DOUBLE: - CError_BufferAppendString(eb, "double"); - return; - case IT_LONGDOUBLE: - CError_BufferAppendString(eb, "long double"); - return; - default: - CError_FATAL(584); - } - case TYPEENUM: - CError_BufferAppendQualifier(eb, qual); - CError_BufferAppendNameSpace(eb, TYPE_ENUM(ty)->nspace); - if (TYPE_ENUM(ty)->enumname) - CError_BufferAppendString(eb, TYPE_ENUM(ty)->enumname->name); - else - CError_BufferAppendString(eb, "{unnamed-enum}"); - return; - case TYPESTRUCT: - CError_BufferAppendQualifier(eb, qual); - switch (TYPE_STRUCT(ty)->stype) { - case STRUCT_TYPE_STRUCT: - CError_BufferAppendString(eb, "struct "); - break; - case STRUCT_TYPE_UNION: - CError_BufferAppendString(eb, "union "); - break; - case STRUCT_VECTOR_UCHAR: - case STRUCT_VECTOR_SCHAR: - case STRUCT_VECTOR_BCHAR: - case STRUCT_VECTOR_USHORT: - case STRUCT_VECTOR_SSHORT: - case STRUCT_VECTOR_BSHORT: - case STRUCT_VECTOR_UINT: - case STRUCT_VECTOR_SINT: - case STRUCT_VECTOR_BINT: - case STRUCT_VECTOR_FLOAT: - case STRUCT_VECTOR_PIXEL: - break; - default: - CError_FATAL(618); - } - if (TYPE_STRUCT(ty)->name) - CError_BufferAppendString(eb, TYPE_STRUCT(ty)->name->name); - return; - case TYPECLASS: - CError_BufferAppendQualifier(eb, qual); - CError_BufferAppendNameSpace(eb, TYPE_CLASS(ty)->nspace->parent); - if (TYPE_CLASS(ty)->classname) { - CError_BufferAppendString(eb, TYPE_CLASS(ty)->classname->name); - if (TYPE_CLASS(ty)->flags & CLASS_IS_TEMPL_INST) - CError_BufferAppendTemplArgs( - eb, - TEMPL_CLASS_INST(ty)->oargs ? TEMPL_CLASS_INST(ty)->oargs : TEMPL_CLASS_INST(ty)->inst_args - ); - } else { - CError_BufferAppendString(eb, "{unnamed-class}"); - } - return; - case TYPEPOINTER: - case TYPEMEMBERPOINTER: - scan = ty; - next_ptr: - switch (scan->type) { - case TYPEPOINTER: - scan = TYPE_POINTER(scan)->target; - goto next_ptr; - case TYPEMEMBERPOINTER: - scan = TYPE_MEMBER_POINTER(scan)->ty1; - goto next_ptr; - } - - CError_BufferAppendQualifier(eb, qual); - switch (scan->type) { - case TYPEFUNC: - if (TYPE_FUNC(scan)->flags & FUNC_PASCAL) - CError_BufferAppendString(eb, "pascal "); - CError_BufferAppendType(eb, TYPE_FUNC(scan)->functype, 0); - CError_BufferAppendString(eb, " ("); - CError_BufferAppendPType(eb, ty); - CError_BufferAppendChar(eb, ')'); - CError_BufferAppendFuncArgs(eb, TYPE_FUNC(scan), ty->type == TYPEMEMBERPOINTER); - return; - case TYPEARRAY: - scan2 = scan; - while (scan->type == TYPEARRAY) - scan = TYPE_POINTER(scan)->target; - CError_BufferAppendType(eb, scan, 0); - CError_BufferAppendString(eb, " ("); - CError_BufferAppendPType(eb, ty); - CError_BufferAppendChar(eb, ')'); - ty = scan2; - goto append_array_lengths; - default: - CError_BufferAppendType(eb, scan, 0); - CError_BufferAppendChar(eb, ' '); - CError_BufferAppendPType(eb, ty); - return; - } - break; - case TYPEFUNC: - if (TYPE_FUNC(ty)->flags & FUNC_PASCAL) - CError_BufferAppendString(eb, "pascal "); - CError_BufferAppendQualifier(eb, qual); - CError_BufferAppendType(eb, TYPE_FUNC(ty)->functype, 0); - CError_BufferAppendChar(eb, ' '); - CError_BufferAppendFuncArgs(eb, TYPE_FUNC(ty), 0); - return; - case TYPEARRAY: - CError_BufferAppendQualifier(eb, qual); - scan = ty; - while (scan->type == TYPEARRAY) - scan = TYPE_POINTER(scan)->target; - CError_BufferAppendType(eb, scan, 0); - append_array_lengths: - while (ty->type == TYPEARRAY) { - CError_BufferAppendChar(eb, '['); - if (ty->size && TYPE_POINTER(ty)->target->size) { - sprintf(buf, "%" PRId32, ty->size / TYPE_POINTER(ty)->target->size); - CError_BufferAppendString(eb, buf); - } - CError_BufferAppendChar(eb, ']'); - ty = TYPE_POINTER(ty)->target; - } - return; - case TYPETEMPLATE: - CError_BufferAppendQualifier(eb, qual); - CError_BufferAppendTemplDepType(eb, TYPE_TEMPLATE(ty)); - return; - case TYPETEMPLDEPEXPR: - CError_BufferAppendString(eb, "T"); - return; - case TYPEBITFIELD: - sprintf(buf, "bitfield:%" PRId32, TYPE_BITFIELD(ty)->bitlength); - CError_BufferAppendString(eb, buf); - return; - default: - CError_FATAL(752); - } -} - -char *CError_GetTypeName(Type *ty, UInt32 qual, Boolean useGlobalHeap) { - CErrorBuffer eb; - char buf[256]; - char *ptr; - - CError_BufferInit(&eb, buf, sizeof(buf)); - CError_BufferAppendType(&eb, ty, qual); - CError_BufferTerminate(&eb); - - if (useGlobalHeap) - ptr = galloc(eb.size + 1); - else - ptr = lalloc(eb.size + 1); - - return strcpy(ptr, eb.start); -} - -static void CError_AppendUnqualFunctionName(CErrorBuffer *eb, NameSpace *nspace, HashNameNode *name, TypeFunc *tfunc) { - Boolean flag = 0; - char *opname; - - if (nspace && nspace->theclass) { - if (name == constructor_name_node) { - CError_BufferAppendString(eb, nspace->theclass->classname->name); - flag = 1; - } else if (name == destructor_name_node) { - CError_BufferAppendChar(eb, '~'); - CError_BufferAppendString(eb, nspace->theclass->classname->name); - flag = 1; - } - } - - if (!flag) { - opname = CMangler_GetOperator(name); - if (!opname) { - if (tfunc && (tfunc->flags & FUNC_CONVERSION)) { - CError_BufferAppendString(eb, "operator "); - CError_BufferAppendType(eb, tfunc->functype, tfunc->qual); - } else { - CError_BufferAppendString(eb, name->name); - } - } else { - CError_BufferAppendString(eb, opname); - } - } -} - -static void CError_AppendFunctionName(CErrorBuffer *eb, NameSpace *nspace, HashNameNode *name, TemplArg *templargs, TypeFunc *tfunc) { - while (nspace->is_templ && nspace->parent) - nspace = nspace->parent; - - CError_BufferAppendNameSpace(eb, nspace); - CError_AppendUnqualFunctionName(eb, nspace, name, tfunc); - CError_BufferAppendTemplArgs(eb, templargs); - if (tfunc) { - if (!templargs && (tfunc->flags & FUNC_IS_TEMPL)) - CError_BufferAppendString(eb, "<...>"); - CError_BufferAppendFuncArgs(eb, tfunc, 0); - } else { - CError_BufferAppendString(eb, "()"); - } -} - -static void CError_AppendObjectName(CErrorBuffer *eb, Object *obj) { - if (obj->type->type == TYPEFUNC) { - CError_AppendFunctionName(eb, obj->nspace, obj->name, obj->u.func.inst ? obj->u.func.inst->args : NULL, TYPE_FUNC(obj->type)); - } else { - CError_BufferAppendNameSpace(eb, obj->nspace); - CError_BufferAppendString(eb, obj->name->name); - } -} - -static void CError_AppendMethodName(CErrorBuffer *eb, ObjCMethod *meth) { - ObjCMethodArg *arg; - - CError_BufferAppendChar(eb, meth->is_class_method ? '+' : '-'); - CError_BufferAppendChar(eb, '('); - CError_BufferAppendType(eb, meth->return_type, meth->return_qual); - CError_BufferAppendChar(eb, ')'); - for (arg = meth->selector_args; arg; arg = arg->next) { - if (arg->selector) - CError_BufferAppendString(eb, arg->selector->name); - if (arg->type) { - CError_BufferAppendString(eb, ":("); - CError_BufferAppendType(eb, arg->type, arg->qual); - CError_BufferAppendChar(eb, ')'); - } - } - if (meth->has_valist) - CError_BufferAppendString(eb, ",..."); -} - -char *CError_GetQualifiedName(NameSpace *nspace, HashNameNode *name) { - CErrorBuffer eb; - char buf[256]; - char *ptr; - - CError_BufferInit(&eb, buf, sizeof(buf)); - CError_BufferAppendNameSpace(&eb, nspace); - CError_BufferAppendString(&eb, name->name); - CError_BufferTerminate(&eb); - - ptr = lalloc(eb.size + 1); - return strcpy(ptr, eb.start); -} - -char *CError_GetFunctionName(NameSpace *nspace, HashNameNode *name, TypeFunc *tfunc) { - CErrorBuffer eb; - char buf[256]; - char *ptr; - - CError_BufferInit(&eb, buf, sizeof(buf)); - CError_AppendFunctionName(&eb, nspace, name, 0, tfunc); - CError_BufferTerminate(&eb); - - ptr = lalloc(eb.size + 1); - return strcpy(ptr, eb.start); -} - -char *CError_GetObjectName(Object *obj) { - CErrorBuffer eb; - char buf[256]; - char *ptr; - - CError_BufferInit(&eb, buf, sizeof(buf)); - CError_AppendObjectName(&eb, obj); - CError_BufferTerminate(&eb); - - ptr = lalloc(eb.size + 1); - return strcpy(ptr, eb.start); -} - -char *CError_GetNameString(NameSpace *nspace, HashNameNode *operatorName) { - CErrorBuffer eb; - char buf[256]; - char *ptr; - char *opStr; - - CError_ASSERT(973, operatorName); - - opStr = CMangler_GetOperator(operatorName); - if (!opStr) - opStr = operatorName->name; - - if (nspace && nspace->name) { - CError_BufferInit(&eb, buf, sizeof(buf)); - CError_BufferAppendNameSpace(&eb, nspace); - CError_BufferAppendString(&eb, opStr); - CError_BufferTerminate(&eb); - ptr = lalloc(eb.size + 1); - return strcpy(ptr, eb.start); - } else { - return opStr; - } -} - -void CError_ErrorMessage(int errTable, char *str, Boolean flag1, Boolean flag2) { - TStreamElement *token; - short tokensize; - CPrepFileInfo *tokenfile; - CWMessageRef myref; - char buf[128]; - CWMessageRef *ref; - unsigned char messagetype; - - if (CWDisplayLines(cparamblkptr->context, lines) != cwNoErr) - CError_UserBreak(); - - if (!in_assembler && !flag1 && cerror_lasterrorline == lines) { - if (cerror_errorcount++ >= 50) { - if (cerror_errorcount > 60) - longjmp(errorreturn, 1); - tk = lex(); - cerror_errorcount = 0; - if (tk == 0) { - CompilerGetCString(1, buf); - CWReportMessage(cparamblkptr->context, NULL, buf, NULL, messagetypeError, errTable); - longjmp(errorreturn, 1); - } - } - } else { - if (!flag2) { - cerror_lasterrorline = lines; - cerror_errorcount = 0; - } - if (copts.warningerrors) - flag2 = 0; - - if (cerror_token) - token = cerror_token; - else if (cerror_locktoken) - token = cerror_locktoken; - else - token = NULL; - //token = cerror_token ? cerror_token : cerror_locktoken ? cerror_locktoken : NULL; - if ((SInt32) token == -1) { - ref = NULL; - } else { - CPrep_GetTokenContext(token, &tokenfile, &myref.selectionoffset, &tokensize, &myref.linenumber, buf, &myref.tokenoffset, &myref.tokenlength, cerror_synchdata, &cerror_synchoffset); - myref.selectionlength = tokensize; - myref.sourcefile = tokenfile->textfile; - ref = &myref; - } - messagetype = flag2 ? messagetypeWarning : messagetypeError; - if (!flag2) { - anyerrors = 1; - fatalerrors = 1; - } - if (CWReportMessage(cparamblkptr->context, ref, str, buf, messagetype, errTable) != cwNoErr) - longjmp(errorreturn, 1); - } - - cerror_token = NULL; -} - -static void CError_BufferAppendTemplateStack(CErrorBuffer *eb) { - TemplStack *stack[64]; - TemplStack *scan; - int index; - int indent; - int count; - - scan = ctempl_curinstance; - for (count = 0; scan && count < 64; count++) { - stack[count] = scan; - scan = scan->next; - } - - for (index = count - 1; index >= 0; index--) { - CError_BufferAppendChar(eb, LF); - for (indent = index; indent < count; indent++) - CError_BufferAppendChar(eb, ' '); - CError_BufferAppendString(eb, "(instantiating: '"); - if (stack[index]->is_func) - CError_AppendObjectName(eb, stack[index]->u.func); - else - CError_BufferAppendType(eb, (Type *) stack[index]->u.theclass, 0); - CError_BufferAppendString(eb, "')"); - } - - CError_BufferTerminate(eb); -} - -void CError_ErrorMessageVA(int code, const char *format, va_list list, Boolean flag1, Boolean flag2) { - // register allocation is fucked, matches otherwise - CErrorBuffer eb; - char buf[256]; - char unmangleBuf[256]; - SInt32 moddate; - Type *type; - UInt32 qual; - const char *p; - CError_BufferInit(&eb, buf, sizeof(buf)); - - p = format; - do { - switch (p[0]) { - case 0: - break; - case '%': - switch (p[1]) { - case 'n': - MWUnmangle(va_arg(list, const char *), unmangleBuf, sizeof(unmangleBuf)); - CError_BufferAppendString(&eb, unmangleBuf); - p += 2; - continue; - case 'u': - CError_BufferAppendString(&eb, va_arg(list, const char *)); - p += 2; - continue; - case 'o': - CError_AppendObjectName(&eb, va_arg(list, Object *)); - p += 2; - continue; - case 'm': - CError_AppendMethodName(&eb, va_arg(list, ObjCMethod *)); - p += 2; - continue; - case 't': - type = va_arg(list, Type *); - qual = va_arg(list, UInt32); - CError_BufferAppendType(&eb, type, qual); - p += 2; - continue; - case '%': - CError_BufferAppendChar(&eb, '%'); - p += 2; - continue; - case 'i': - sprintf(unmangleBuf, "%" PRId32, va_arg(list, SInt32)); - CError_BufferAppendString(&eb, unmangleBuf); - p += 2; - continue; - case 'f': - CError_BufferAppendString(&eb, CTool_GetPathName(va_arg(list, FSSpec *), &moddate)->name); - p += 2; - continue; - default: - CError_FATAL(1174); - } - break; - default: - CError_BufferAppendChar(&eb, *(p++)); - continue; - } - break; - } while (1); - - CError_BufferAppendTemplateStack(&eb); - CError_ErrorMessage(code, eb.start, flag1, flag2); -} - -static void CError_VAErrorMessage(int code, va_list list, Boolean flag1, Boolean flag2) { - char buf[256]; - - CError_GetErrorString(buf, code); - CError_ErrorMessageVA(code + 10000, buf, list, flag1, flag2); -} - -void CError_Error(int code, ...) { - va_list va; - - if (trychain) - longjmp(trychain->jmpbuf, 1); - - va_start(va, code); - CError_VAErrorMessage(code, va, 0, 0); - va_end(va); - - if (in_assembler && !preprocessing_only) - AssemblerError(); -} - -void CError_ErrorTerm(short code) { - CError_GetErrorString(string, code); - CError_ErrorMessage(code + 10000, string, 0, 0); - longjmp(errorreturn, 1); -} - -void CError_ErrorSkip(int code, ...) { - va_list va; - - if (trychain) - longjmp(trychain->jmpbuf, 1); - - va_start(va, code); - CError_VAErrorMessage(code, va, 0, 0); - va_end(va); - - if (tk != ';' && tk != ')' && tk != '}' && tk != ',' && tk != ']') - tk = lex(); -} - -void CError_ErrorFuncCall(short code, NameSpaceObjectList *args, ENodeList *argNodes) { - // does not match - one branch has loop weirdness - CErrorBuffer eb; - char buf[256]; - char *p; - ENodeList *argscan; - - if (trychain) - longjmp(trychain->jmpbuf, 1); - - CError_GetErrorString(string, code); - CError_BufferInit(&eb, buf, sizeof(buf)); - - while (args && args->object->otype != OT_OBJECT) - args = args->next; - CError_ASSERT(1268, args); - - p = string; - do { - switch (*p) { - case 0: - goto exit_main_loop; - case '*': - if (OBJECT(args->object)->type->type == TYPEFUNC) { - CError_AppendUnqualFunctionName( - &eb, - OBJECT(args->object)->nspace, - OBJECT(args->object)->name, - TYPE_FUNC(OBJECT(args->object)->type)); - if (TYPE_FUNC(OBJECT(args->object)->type)->flags & FUNC_METHOD) - if (TYPE_FUNC(OBJECT(args->object)->type)->flags & FUNC_IS_CTOR) - if (TYPE_METHOD(OBJECT(args->object)->type)->theclass->flags & CLASS_HAS_VBASES) - if (argNodes) - argNodes = argNodes->next; - } else { - CError_BufferAppendString(&eb, OBJECT(args->object)->name->name); - } - CError_BufferAppendChar(&eb, '('); - argscan = argNodes; - while (argscan) { - CError_BufferAppendType(&eb, argscan->node->rtype, argscan->node->flags & ENODE_FLAG_QUALS); - if ((argscan = argscan->next)) - CError_BufferAppendString(&eb, ", "); - else - break; - } - CError_BufferAppendChar(&eb, ')'); - break; - default: - CError_BufferAppendChar(&eb, *p); - } - p++; - } while (1); - -exit_main_loop: - while (args) { - if (args->object->otype == OT_OBJECT) { - CError_BufferAppendChar(&eb, LF); - CError_BufferAppendChar(&eb, '\''); - CError_AppendObjectName(&eb, (Object *) args->object); - CError_BufferAppendChar(&eb, '\''); - } - args = args->next; - } - - CError_BufferAppendTemplateStack(&eb); - CError_ErrorMessage(10000 + code, eb.start, 0, 0); -} - -void CError_OverloadedFunctionError2(Object *obj, ObjectList *olst, ENodeList *argNodes) { - // not sure if the arg is actually ObjectList since it's never called lmao - NameSpaceObjectList first; - NameSpaceObjectList *current; - - first.object = (ObjBase *) obj; - current = &first; - while (olst) { - current->next = lalloc(sizeof(NameSpaceObjectList)); - current = current->next; - current->object = (ObjBase *) olst->object; - olst = olst->next; - } - current->next = NULL; - - CError_ErrorFuncCall(CErrorStr392, &first, argNodes); -} - -void CError_OverloadedFunctionError(Object *obj, ObjectList *olst) { - // not sure if this arg is ObjectList or NameSpaceObjectList - CErrorBuffer eb; - char buf[256]; - - if (trychain) - longjmp(trychain->jmpbuf, 1); - - CError_GetErrorString(string, CErrorStr199); - CError_BufferInit(&eb, buf, sizeof(buf)); - CError_BufferAppendString(&eb, string); - - if (obj) { - CError_BufferAppendChar(&eb, LF); - CError_BufferAppendChar(&eb, '\''); - CError_AppendObjectName(&eb, obj); - CError_BufferAppendChar(&eb, '\''); - } - while (olst) { - CError_BufferAppendChar(&eb, LF); - CError_BufferAppendChar(&eb, '\''); - CError_AppendObjectName(&eb, olst->object); - CError_BufferAppendChar(&eb, '\''); - olst = olst->next; - } - CError_BufferAppendTemplateStack(&eb); - CError_ErrorMessage(10199, eb.start, 0, 0); -} - -void CError_AbstractClassError(TypeClass *tclass) { - Object *result = CClass_CheckPures(tclass); - if (!result) - CError_Error(CErrorStr372, tclass, 0); - else - CError_Error(CErrorStr194, result); -} - -void CError_Warning(int code, ...) { - va_list va; - if (trychain || copts.supress_warnings) - return; - - va_start(va, code); - CError_VAErrorMessage(code, va, 0, 1); - va_end(va); -} - -void CError_BreakPoint(const char *a, const char *b) { - if (!a || !strcmp(a, b)) - CError_BreakPointcount++; -} - -void CError_Internal(char *filename, int line) { - char tmp[128]; - CompilerGetCString(5, tmp); - sprintf(string, tmp, filename, line); - CError_ErrorMessage(10001, string, 1, 0); - longjmp(errorreturn, 1); - CError_BreakPoint(0, 0); -} - -void CError_ExpressionTooComplex(void) { - CompilerGetCString(6, string); - CError_ErrorMessage(10002, string, 1, 0); - longjmp(errorreturn, 1); -} - -void CError_NoMem(void) { - cprep_nomem_exit = 1; - longjmp(errorreturn, 1); -} - -void CError_UserBreak(void) { - CompilerGetCString(8, string); - longjmp(errorreturn, 1); -} - -void CError_CannotOpen(void) { - CompilerGetCString(9, string); - CWReportMessage(cparamblkptr->context, NULL, string, NULL, messagetypeError, 0); - longjmp(errorreturn, 1); -} - -void CError_QualifierCheck(UInt32 qual) { - if (qual) { - Boolean anything = 0; - - if (qual & Q_CONST) { - CError_Error(CErrorStr313, "const"); - anything = 1; - } - if (qual & Q_VOLATILE) { - CError_Error(CErrorStr313, "volatile"); - anything = 1; - } - if (qual & Q_RESTRICT) { - CError_Error(CErrorStr313, "restrict"); - anything = 1; - } - if (qual & Q_ASM) { - CError_Error(CErrorStr313, "asm"); - anything = 1; - } - if (qual & Q_PASCAL) { - CError_Error(CErrorStr313, "pascal"); - anything = 1; - } - if (qual & Q_INLINE) { - CError_Error(CErrorStr313, "inline"); - anything = 1; - } - if (qual & Q_REFERENCE) { - CError_Error(CErrorStr313, "& reference type"); - anything = 1; - } - if (qual & Q_EXPLICIT) { - CError_Error(CErrorStr313, "explicit"); - anything = 1; - } - if (qual & Q_MUTABLE) { - CError_Error(CErrorStr313, "mutable"); - anything = 1; - } - if (qual & Q_VIRTUAL) { - CError_Error(CErrorStr313, "virtual"); - anything = 1; - } - if (qual & Q_FRIEND) { - CError_Error(CErrorStr313, "friend"); - anything = 1; - } - if (qual & Q_IN) { - CError_Error(CErrorStr313, "in"); - anything = 1; - } - if (qual & Q_OUT) { - CError_Error(CErrorStr313, "out"); - anything = 1; - } - if (qual & Q_INOUT) { - CError_Error(CErrorStr313, "inout"); - anything = 1; - } - if (qual & Q_BYCOPY) { - CError_Error(CErrorStr313, "bycopy"); - anything = 1; - } - if (qual & Q_BYREF) { - CError_Error(CErrorStr313, "byref"); - anything = 1; - } - if (qual & Q_ONEWAY) { - CError_Error(CErrorStr313, "oneway"); - anything = 1; - } - if (qual & Q_ALIGNED_MASK) { - CError_Error(CErrorStr313, "__attribute__((aligned(?)))"); - anything = 1; - } - - if (!anything) - CError_Error(CErrorStr176); - } -} diff --git a/compiler_and_linker/unsorted/CException.c b/compiler_and_linker/unsorted/CException.c deleted file mode 100644 index d68ce13..0000000 --- a/compiler_and_linker/unsorted/CException.c +++ /dev/null @@ -1,2183 +0,0 @@ -#include "compiler/CException.h" -#include "compiler/CABI.h" -#include "compiler/CClass.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInline.h" -#include "compiler/CInit.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CScope.h" -#include "compiler/CompilerTools.h" -#include "compiler/Exceptions.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/types.h" - -typedef struct UniqueObj { - struct UniqueObj *next; - Object *object; - SInt32 uniqueid; -} UniqueObj; - -ExceptionAction *cexcept_dobjstack; -Boolean cexcept_hasdobjects; -Boolean cexcept_magic; -static UniqueObj *cexcept_uniqueobjs; -static Boolean cexcept_canthrow; -static DtorTemp *cexcept_dtortemps; -static Statement *cexcept_prevstmt; -static ExceptionAction *cexcept_eabefore; -static ExceptionAction *cexcept_eaafter; -static Boolean cexcept_expandtrycatch; -static Boolean cexcept_hastrycatch; -static Boolean cexcept_serialize; - -// forward decls -static ENode *CExcept_TempTransExprCond(ENode *expr); -static ENode *CExcept_TempTransExpr(ENode *expr); - -void CExcept_Setup(void) { - cexcept_dobjstack = NULL; - cexcept_uniqueobjs = NULL; - cexcept_hasdobjects = 0; - cexcept_magic = 0; -} - -Boolean CExcept_CanThrowException(Object *object, Boolean flag) { - if (copts.optEH && IS_TYPE_FUNC(object->type)) { - if (flag) - return 1; - - if (TYPE_FUNC(object->type)->flags & FUNC_NOTHROW) - return 0; - - if ( - !flag && - TYPE_FUNC(object->type)->exspecs && - TYPE_FUNC(object->type)->exspecs && - !TYPE_FUNC(object->type)->exspecs->type - ) - return 0; - - if ( - copts.optEH2 && - !(object->qual & Q_MANGLE_NAME) && - object != rt_ptmf_call && - object != rt_ptmf_scall && - object != Rdync_func && - object != rt_som_glue1 && - object != rt_som_glue2 && - object != rt_som_glue3 && - object != carr_func && - object != cnar_func && - object != darr_func && - object != dnar_func && - object != dnar3_func && - object != Xthrw_func - ) - return 0; - } - - return 1; -} - -void CExcept_CheckStackRefs(ExceptionAction *actions) { - while (actions) { - switch (actions->type) { - case EAT_DESTROYLOCAL: - CInline_ObjectAddrRef(actions->data.destroy_local.dtor); - break; - case EAT_DESTROYLOCALCOND: - CInline_ObjectAddrRef(actions->data.destroy_local_cond.dtor); - break; - case EAT_DESTROYLOCALOFFSET: - CInline_ObjectAddrRef(actions->data.destroy_local_offset.dtor); - break; - case EAT_DESTROYLOCALPOINTER: - CInline_ObjectAddrRef(actions->data.destroy_local_pointer.dtor); - break; - case EAT_DESTROYLOCALARRAY: - CInline_ObjectAddrRef(actions->data.destroy_local_array.dtor); - break; - case EAT_DESTROYPARTIALARRAY: - CInline_ObjectAddrRef(actions->data.destroy_partial_array.dtor); - break; - case EAT_DESTROYMEMBER: - case EAT_DESTROYBASE: - CInline_ObjectAddrRef(actions->data.destroy_member.dtor); - break; - case EAT_DESTROYMEMBERCOND: - CInline_ObjectAddrRef(actions->data.destroy_member_cond.dtor); - break; - case EAT_DESTROYMEMBERARRAY: - CInline_ObjectAddrRef(actions->data.destroy_member_array.dtor); - break; - case EAT_DELETEPOINTER: - case EAT_DELETELOCALPOINTER: - CInline_ObjectAddrRef(actions->data.delete_pointer.deletefunc); - break; - case EAT_DELETEPOINTERCOND: - CInline_ObjectAddrRef(actions->data.delete_pointer_cond.deletefunc); - break; - case EAT_CATCHBLOCK: - case EAT_ACTIVECATCHBLOCK: - case EAT_SPECIFICATION: - case EAT_TERMINATE: - break; - default: - CError_FATAL(192); - } - actions = actions->prev; - } -} - -void CExcept_CompareSpecifications(ExceptSpecList *a, ExceptSpecList *b) { - ExceptSpecList *aa; - ExceptSpecList *bb; - - aa = a; - bb = b; - while (1) { - if (!aa) { - if (!bb) - break; - CError_Error(CErrorStr265); - return; - } - - if (!bb) { - CError_Error(CErrorStr265); - return; - } - - aa = aa->next; - bb = bb->next; - } - - if (a->type == NULL) { - if (b->type != NULL) - CError_Error(CErrorStr265); - } else if (b->type == NULL) { - CError_Error(CErrorStr265); - } else { - for (aa = a; aa; aa = aa->next) { - for (bb = b; bb; bb = bb->next) { - if (is_typesame(aa->type, bb->type) && aa->qual == bb->qual) - break; - } - - if (bb == NULL) { - CError_Error(CErrorStr265); - return; - } - } - } -} - -Boolean CExcept_ActionCompare(ExceptionAction *a, ExceptionAction *b) { - if (a->type == b->type) { - switch (a->type) { - case EAT_DESTROYLOCAL: - return a->data.destroy_local.local == b->data.destroy_local.local; - case EAT_DESTROYLOCALCOND: - return a->data.destroy_local_cond.local == b->data.destroy_local_cond.local; - case EAT_DESTROYLOCALOFFSET: - return a->data.destroy_local_offset.local == b->data.destroy_local_offset.local && - a->data.destroy_local_offset.offset == b->data.destroy_local_offset.offset; - case EAT_DESTROYLOCALPOINTER: - return a->data.destroy_local_pointer.pointer == b->data.destroy_local_pointer.pointer; - case EAT_DESTROYLOCALARRAY: - return a->data.destroy_local_array.localarray == b->data.destroy_local_array.localarray; - case EAT_DESTROYPARTIALARRAY: - return a->data.destroy_partial_array.arraypointer == b->data.destroy_partial_array.arraypointer; - case EAT_DESTROYMEMBER: - case EAT_DESTROYBASE: - return a->data.destroy_member.objectptr == b->data.destroy_member.objectptr && - a->data.destroy_member.offset == b->data.destroy_member.offset; - case EAT_DESTROYMEMBERCOND: - return a->data.destroy_member_cond.objectptr == b->data.destroy_member_cond.objectptr && - a->data.destroy_member_cond.offset == b->data.destroy_member_cond.offset; - case EAT_DESTROYMEMBERARRAY: - return a->data.destroy_member_array.objectptr == b->data.destroy_member_array.objectptr && - a->data.destroy_member_array.offset == b->data.destroy_member_array.offset; - case EAT_DELETEPOINTER: - case EAT_DELETELOCALPOINTER: - return a->data.delete_pointer.pointerobject == b->data.delete_pointer.pointerobject && - a->data.delete_pointer.deletefunc == b->data.delete_pointer.deletefunc; - case EAT_DELETEPOINTERCOND: - return a->data.delete_pointer_cond.cond == b->data.delete_pointer_cond.cond; - case EAT_CATCHBLOCK: - return a->data.catch_block.catch_label == b->data.catch_block.catch_label; - case EAT_ACTIVECATCHBLOCK: - return a->data.active_catch_block.catch_info_object == b->data.active_catch_block.catch_info_object; - case EAT_TERMINATE: - return 1; - case EAT_SPECIFICATION: - return a->data.specification.unexp_id == b->data.specification.unexp_id; - default: - CError_FATAL(314); - } - } - - return 0; -} - -int CExcept_IsSubList(ExceptionAction *a, ExceptionAction *b) { - int diff; - int i; - int count1; - int count2; - ExceptionAction *scan; - - if (a == b) - return 0; - - count1 = 0; - scan = a; - while (scan) { - scan = scan->prev; - count1++; - } - - scan = b; - count2 = 0; - while (scan) { - scan = scan->prev; - count2++; - } - - diff = count2 - count1; - if (diff < 0) - return -1; - - for (i = 0; i < diff; i++) - b = b->prev; - - while (a != b) { - if (!a || !b || !CExcept_ActionCompare(a, b)) - return -1; - a = a->prev; - b = b->prev; - } - - return diff; -} - -Boolean CExcept_ActionNeedsDestruction(ExceptionAction *action) { - switch (action->type) { - case EAT_CATCHBLOCK: - return 0; - case EAT_DESTROYLOCAL: - case EAT_DESTROYLOCALOFFSET: - case EAT_DESTROYLOCALARRAY: - case EAT_DELETELOCALPOINTER: - case EAT_ACTIVECATCHBLOCK: - return 1; - case EAT_NOP: - case EAT_DESTROYMEMBER: - case EAT_DESTROYMEMBERCOND: - case EAT_DESTROYMEMBERARRAY: - case EAT_DESTROYBASE: - break; - default: - CError_FATAL(363); - } - - return 0; -} - -ENode *CExcept_RegisterDestructorObject(Object *local, SInt32 offset, Object *dtor, Boolean flag) { - ExceptionAction *action; - ENode *expr; - Object *dtorObject; - - action = lalloc(sizeof(ExceptionAction)); - memclrw(action, sizeof(ExceptionAction)); - - action->prev = cexcept_dobjstack; - cexcept_dobjstack = action; - - expr = create_objectrefnode(local); - dtorObject = CABI_GetDestructorObject(dtor, CABIDestroy1); - - if (offset == 0) { - action->type = EAT_DESTROYLOCAL; - action->data.destroy_local.local = local; - action->data.destroy_local.dtor = dtorObject; - } else { - action->type = EAT_DESTROYLOCALOFFSET; - action->data.destroy_local_offset.local = local; - action->data.destroy_local_offset.dtor = dtorObject; - action->data.destroy_local_offset.offset = offset; - expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); - } - - cexcept_hasdobjects = 1; - return expr; -} - -void CExcept_RegisterLocalArray(Statement *stmt, Object *localarray, Object *dtor, SInt32 elements, SInt32 element_size) { - ExceptionAction *action; - Object *dtorObject; - - action = lalloc(sizeof(ExceptionAction)); - memclrw(action, sizeof(ExceptionAction)); - - action->prev = cexcept_dobjstack; - cexcept_dobjstack = action; - - dtorObject = CABI_GetDestructorObject(dtor, CABIDestroy1); - - action->type = EAT_DESTROYLOCALARRAY; - action->data.destroy_local_array.localarray = localarray; - action->data.destroy_local_array.dtor = dtorObject; - action->data.destroy_local_array.elements = elements; - action->data.destroy_local_array.element_size = element_size; - - cexcept_hasdobjects = 1; -} - -void CExcept_RegisterDeleteObject(Statement *stmt, Object *pointerobject, Object *deletefunc) { - ExceptionAction *action; - - action = lalloc(sizeof(ExceptionAction)); - memclrw(action, sizeof(ExceptionAction)); - - action->prev = cexcept_dobjstack; - cexcept_dobjstack = action; - - action->type = EAT_DELETELOCALPOINTER; - action->data.delete_pointer.pointerobject = pointerobject; - action->data.delete_pointer.deletefunc = deletefunc; - - cexcept_hasdobjects = 1; -} - -static void CExcept_PatchConstructorAction(Statement *stmt, ExceptionAction *actionArg) { - ExceptionAction *action30; - ExceptionAction *action; - ExceptionAction *scan; - - for (action = stmt->dobjstack; action; action = action->prev) { - switch (action->type) { - case EAT_DESTROYMEMBER: - case EAT_DESTROYMEMBERCOND: - case EAT_DESTROYMEMBERARRAY: - case EAT_SPECIFICATION: - case EAT_DESTROYBASE: - goto exitFirstLoop; - case EAT_CATCHBLOCK: - action30 = action; - while (1) { - if (!action30->prev) - goto exitFirstLoop; - action30 = action30->prev; - if (action30->type != EAT_CATCHBLOCK) { - CError_FATAL(481); - } - } - } - } - exitFirstLoop: - if (action == NULL) { - while (stmt) { - if ((scan = stmt->dobjstack)) { - while (1) { - if (scan == actionArg) - break; - if (scan->prev == NULL) { - scan->prev = actionArg; - break; - } - scan = scan->prev; - } - } else { - stmt->dobjstack = actionArg; - } - stmt = stmt->next; - } - } else { - actionArg->prev = action; - while (stmt) { - if (stmt->dobjstack != action) { - scan = stmt->dobjstack; - do { - if (scan == actionArg) - goto nextStmt; - if (scan->prev == action) { - scan->prev = actionArg; - goto nextStmt; - } - } while ((scan = scan->prev)); - - while (1) { - if (action->type == EAT_CATCHBLOCK && action->prev == NULL) - return; - - action = action->prev; - if (!action) - CError_FATAL(531); - } - } else { - stmt->dobjstack = actionArg; - } - nextStmt: - stmt = stmt->next; - } - } -} - -void CExcept_Terminate(void) { - ExceptionAction *action; - - action = lalloc(sizeof(ExceptionAction)); - memclrw(action, sizeof(ExceptionAction)); - - action->type = EAT_TERMINATE; - - action->prev = cexcept_dobjstack; - cexcept_dobjstack = action; -} - -void CExcept_Magic(void) { - cexcept_magic = 1; -} - -static Object *CExcept_FindLocalObject(char *name) { - NameResult result; - NameSpaceObjectList *list; - - list = CScope_FindObjectList(&result, GetHashNameNodeExport(name)); - if (list && list->object->otype == OT_OBJECT && OBJECT(list->object)->datatype == DLOCAL) - return OBJECT(list->object); - - CError_FATAL(580); - return NULL; -} - -void CExcept_ArrayInit(void) { - ExceptionAction *action; - - action = lalloc(sizeof(ExceptionAction)); - memclrw(action, sizeof(ExceptionAction)); - - action->type = EAT_DESTROYPARTIALARRAY; - action->data.destroy_partial_array.arraypointer = CExcept_FindLocalObject("ptr"); - action->data.destroy_partial_array.arraycounter = CExcept_FindLocalObject("i"); - action->data.destroy_partial_array.dtor = CExcept_FindLocalObject("dtor"); - action->data.destroy_partial_array.element_size = CExcept_FindLocalObject("size"); - - action->prev = cexcept_dobjstack; - cexcept_dobjstack = action; -} - -void CExcept_RegisterMember(Statement *stmt, Object *objectptr, SInt32 offset, Object *dtor, Object *cond, Boolean isMember) { - ExceptionAction *action; - - action = lalloc(sizeof(ExceptionAction)); - memclrw(action, sizeof(ExceptionAction)); - - if (cond == NULL) { - if (isMember) { - action->type = EAT_DESTROYMEMBER; - action->data.destroy_member.dtor = CABI_GetDestructorObject(dtor, CABIDestroy1); - } else { - action->type = EAT_DESTROYBASE; - action->data.destroy_member.dtor = CABI_GetDestructorObject(dtor, CABIDestroy0); - } - action->data.destroy_member.objectptr = objectptr; - action->data.destroy_member.offset = offset; - } else { - CError_ASSERT(632, cond->type == TYPE(&stsignedshort)); - action->type = EAT_DESTROYMEMBERCOND; - action->data.destroy_member_cond.objectptr = objectptr; - action->data.destroy_member_cond.cond = cond; - action->data.destroy_member_cond.dtor = CABI_GetDestructorObject(dtor, CABIDestroy1); - action->data.destroy_member_cond.offset = offset; - } - - CExcept_PatchConstructorAction(stmt, action); - stmt->flags |= StmtFlag_2; -} - -void CExcept_RegisterMemberArray(Statement *stmt, Object *objectptr, SInt32 offset, Object *dtor, SInt32 elements, SInt32 element_size) { - ExceptionAction *action; - - action = lalloc(sizeof(ExceptionAction)); - memclrw(action, sizeof(ExceptionAction)); - - action->type = EAT_DESTROYMEMBERARRAY; - action->data.destroy_member_array.objectptr = objectptr; - action->data.destroy_member_array.dtor = CABI_GetDestructorObject(dtor, CABIDestroy1); - action->data.destroy_member_array.offset = offset; - action->data.destroy_member_array.elements = elements; - action->data.destroy_member_array.element_size = element_size; - - CExcept_PatchConstructorAction(stmt, action); - stmt->flags |= StmtFlag_2; -} - -static Statement *CExcept_DestroyLocal(ExceptionAction *ea, Statement *stmt, Object *object, Object *dtor, SInt32 offset) { - ENode *expr; - - expr = create_objectrefnode(object); - if (offset) - expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); - - expr = CABI_DestroyObject(dtor, expr, CABIDestroy1, 1, 0); - - CError_ASSERT(687, expr->type == EFUNCCALL && expr->data.funccall.funcref->type == EOBJREF); - if (expr->data.funccall.funcref->data.objref->datatype == DVFUNC) - expr->data.funccall.funcref->flags |= ENODE_FLAG_80; - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = expr; - stmt->dobjstack = ea->prev; - return stmt; -} - -static Statement *CExcept_DestroyLocalPointer(ExceptionAction *ea, Statement *stmt, Object *object, Object *deletefunc) { - Statement *newStmt; - - newStmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - newStmt->expr = funccallexpr(deletefunc, create_objectnode2(object), NULL, NULL, NULL); - newStmt->dobjstack = ea->prev; - return newStmt; -} - -static Statement *CExcept_DestroyLocalArray(ExceptionAction *ea, Statement *stmt, Object *object, Object *dtor, SInt32 elements, SInt32 element_size) { - Statement *newStmt; - ENode *dtorExpr; - - newStmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - - if (dtor) - dtorExpr = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1)); - else - dtorExpr = nullnode(); - - newStmt->expr = funccallexpr( - darr_func, - create_objectrefnode(object), - dtorExpr, - intconstnode(TYPE(&stunsignedlong), element_size), - intconstnode(TYPE(&stunsignedlong), elements) - ); - - newStmt->dobjstack = ea->prev; - return newStmt; -} - -static Statement *CExcept_EndCatch(ExceptionAction *ea, Statement *stmt) { - stmt = CFunc_InsertStatement(ST_ENDCATCHDTOR, stmt); - stmt->expr = create_objectrefnode(ea->data.active_catch_block.catch_info_object); - stmt->dobjstack = ea->prev; - if (!ea->data.active_catch_block.call_dtor) - stmt->type = ST_ENDCATCH; - return stmt; -} - -Statement *CExcept_ActionCleanup(ExceptionAction *ea, Statement *stmt) { - switch (ea->type) { - case EAT_DESTROYLOCALCOND: - case EAT_DESTROYLOCALPOINTER: - case EAT_DESTROYPARTIALARRAY: - case EAT_DESTROYMEMBER: - case EAT_DESTROYMEMBERCOND: - case EAT_DESTROYMEMBERARRAY: - case EAT_DELETEPOINTER: - case EAT_DELETEPOINTERCOND: - case EAT_CATCHBLOCK: - case EAT_SPECIFICATION: - case EAT_TERMINATE: - case EAT_DESTROYBASE: - break; - case EAT_DESTROYLOCAL: - stmt = CExcept_DestroyLocal( - ea, stmt, - ea->data.destroy_local.local, - ea->data.destroy_local.dtor, - 0); - break; - case EAT_DESTROYLOCALOFFSET: - stmt = CExcept_DestroyLocal( - ea, stmt, - ea->data.destroy_local.local, - ea->data.destroy_local.dtor, - ea->data.destroy_local_offset.offset); - break; - case EAT_DELETELOCALPOINTER: - stmt = CExcept_DestroyLocalPointer( - ea, stmt, - ea->data.delete_pointer.pointerobject, - ea->data.delete_pointer.deletefunc); - break; - case EAT_DESTROYLOCALARRAY: - stmt = CExcept_DestroyLocalArray( - ea, stmt, - ea->data.destroy_local_array.localarray, - ea->data.destroy_local_array.dtor, - ea->data.destroy_local_array.elements, - ea->data.destroy_local_array.element_size); - break; - case EAT_ACTIVECATCHBLOCK: - stmt = CExcept_EndCatch(ea, stmt); - break; - default: - CError_FATAL(827); - } - - return stmt; -} - -static void CExcept_MangleNameSpaceName(NameSpace *nspace) { - while (nspace) { - if (nspace->name) { - CExcept_MangleNameSpaceName(nspace->parent); - AppendGListName(&name_mangle_list, nspace->name->name); - AppendGListName(&name_mangle_list, "::"); - break; - } - nspace = nspace->parent; - } -} - -static void CExcept_MangleClassName(TypeClass *tclass) { - NameSpace *nspace; - char buf[64]; - - CExcept_MangleNameSpaceName(tclass->nspace->parent); - AppendGListName(&name_mangle_list, tclass->classname->name); - - for (nspace = tclass->nspace->parent; nspace; nspace = nspace->parent) { - if (!nspace->is_global && !nspace->is_templ && !nspace->name) { - CError_ASSERT(868, cscope_currentfunc != NULL); - - sprintf(buf, "*%" PRIxPTR "*%" PRIxPTR "*", &cscope_currentfunc, &nspace); - AppendGListName(&name_mangle_list, buf); - break; - } - } -} - -typedef struct BCL { - struct BCL *next; - TypeClass *tclass; - SInt32 offset; - Boolean is_virtual; - Boolean is_public; - Boolean is_ambig; -} BCL; - -static void CExcept_MakeBaseClassListAmbig(BCL *bcl, TypeClass *tclass) { - BCL *scan; - ClassList *list; - - for (scan = bcl; scan; scan = scan->next) { - if (scan->tclass == tclass) - scan->is_ambig = 1; - } - - for (list = tclass->bases; list; list = list->next) - CExcept_MakeBaseClassListAmbig(bcl, list->base); -} - -static BCL *CExcept_GetBaseClassList(BCL *bcl, TypeClass *tclass1, TypeClass *tclass2, SInt32 offset, Boolean is_virtual, Boolean is_public) { - BCL *node; - ClassList *base; - Boolean new_is_public; - - for (node = bcl; node; node = node->next) { - if (node->tclass == tclass2) { - if (is_virtual && node->is_virtual) { - if (is_public) - node->is_public = 1; - } else { - CExcept_MakeBaseClassListAmbig(bcl, tclass2); - } - return bcl; - } - } - - node = lalloc(sizeof(BCL)); - node->tclass = tclass2; - node->offset = offset; - node->is_virtual = is_virtual; - node->is_public = is_public; - node->is_ambig = 0; - node->next = bcl; - bcl = node; - - for (base = tclass2->bases; base; base = base->next) { - new_is_public = is_public && (base->access == ACCESSPUBLIC); - bcl = base->is_virtual - ? CExcept_GetBaseClassList(bcl, tclass1, base->base, CClass_VirtualBaseOffset(tclass1, base->base), 1, new_is_public) - : CExcept_GetBaseClassList(bcl, tclass1, base->base, offset + base->offset, 0, new_is_public); - } - - return bcl; -} - -static void CExcept_MangleClass(TypeClass *tclass) { - BCL *bcl; - char buf[20]; - - for (bcl = CExcept_GetBaseClassList(NULL, tclass, tclass, 0, 0, 1); bcl; bcl = bcl->next) { - if (bcl->is_public && !bcl->is_ambig) { - CExcept_MangleClassName(bcl->tclass); - AppendGListByte(&name_mangle_list, '!'); - - if (bcl->offset) { - sprintf(buf, "%" PRId32 "!", bcl->offset); - AppendGListName(&name_mangle_list, buf); - } else { - AppendGListByte(&name_mangle_list, '!'); - } - } - } -} - -static ENode *CExcept_GetTypeID(Type *type, UInt32 qual, Boolean flag) { - ENode *expr; - TypePointer my_tptr; - - if (IS_TYPE_REFERENCE(type)) - type = TPTR_TARGET(type); - - if (IS_TYPE_CLASS(type) || (IS_TYPE_POINTER_ONLY(type) && IS_TYPE_CLASS(TPTR_TARGET(type)))) { - name_mangle_list.size = 0; - if (IS_TYPE_POINTER_ONLY(type)) { - AppendGListByte(&name_mangle_list, '*'); - type = TPTR_TARGET(type); - } else { - AppendGListByte(&name_mangle_list, '!'); - } - - if (flag) { - CExcept_MangleClass(TYPE_CLASS(type)); - } else { - CExcept_MangleClassName(TYPE_CLASS(type)); - AppendGListByte(&name_mangle_list, '!'); - } - } else { - if (IS_TYPE_POINTER_ONLY(type)) { - if (TPTR_QUAL(type) & (Q_CONST | Q_VOLATILE)) { - my_tptr = *TYPE_POINTER(type); - my_tptr.qual = 0; - type = TYPE(&my_tptr); - } - } else { - qual = 0; - } - CMangler_MangleType(type, qual); - } - - AppendGListByte(&name_mangle_list, 0); - - expr = CExpr_NewENode(ESTRINGCONST); - expr->rtype = CDecl_NewPointerType(TYPE(&stchar)); - expr->data.string.size = name_mangle_list.size; - expr->data.string.data = galloc(name_mangle_list.size); - memcpy(expr->data.string.data, *name_mangle_list.data, name_mangle_list.size); - return expr; -} - -static Object *CExcept_TypeID(Type *type, UInt32 qual) { - ENode *expr = CExcept_GetTypeID(type, qual, 0); - CError_ASSERT(1086, expr->type == ESTRINGCONST); - return CInit_DeclareString(expr->data.string.data, expr->data.string.size, 0, 0); -} - -void CExcept_ScanExceptionSpecification(TypeFunc *tfunc) { - ExceptSpecList *exspecs; - ExceptSpecList *exspec; - DeclInfo di; - - exspecs = NULL; - - if (lex() != '(') { - CError_Error(CErrorStr114); - return; - } - - if ((tk = lex()) != ')') { - while (1) { - memclrw(&di, sizeof(di)); - CParser_GetDeclSpecs(&di, 0); - if (di.storageclass) - CError_Error(CErrorStr177); - - CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_ALIGNED_MASK)); - - scandeclarator(&di); - if (di.name) - CError_Error(CErrorStr146); - - if (IS_TYPE_POINTER_ONLY(di.thetype)) { - if (TPTR_QUAL(di.thetype) & (Q_CONST | Q_VOLATILE)) { - TypePointer *newtype = galloc(sizeof(TypePointer)); - *newtype = *TYPE_POINTER(di.thetype); - newtype->qual = 0; - di.thetype = TYPE(newtype); - } - } else { - di.qual = 0; - } - - for (exspec = exspecs; exspec; exspec = exspec->next) { - if (is_typesame(exspec->type, di.thetype) && exspec->qual == di.qual) - break; - } - - if (!exspec) { - exspec = galloc(sizeof(ExceptSpecList)); - memclrw(exspec, sizeof(ExceptSpecList)); - exspec->next = exspecs; - exspec->type = di.thetype; - exspec->qual = di.qual; - exspecs = exspec; - } - - if (tk == ')') - break; - - if (tk != ',') { - CError_Error(CErrorStr115); - break; - } - - tk = lex(); - } - } - - if (!exspecs) { - exspecs = galloc(sizeof(ExceptSpecList)); - memclrw(exspecs, sizeof(ExceptSpecList)); - } - tfunc->exspecs = exspecs; - tk = lex(); -} - -static ENode *CExcept_CallCopyCtor(Object *object, Type *type, ENode *expr1, ENode *expr2) { - ENodeList *list; - ENode *expr; - FuncArg *arg; - - if ( - !IS_TYPE_FUNC(object->type) || - !(arg = TYPE_FUNC(object->type)->args) || - !(arg = arg->next) - ) - CError_FATAL(1169); - - expr = funccallexpr(object, expr1, NULL, NULL, NULL); - list = expr->data.funccall.args; - - if (TYPE_CLASS(type)->flags & CLASS_HAS_VBASES) { - CError_ASSERT(1179, arg = arg->next); - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->next = NULL; - list->node = intconstnode(TYPE(&stsignedshort), 1); - } - - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->next = NULL; - list->node = expr2; - - while ((arg = arg->next)) { - CError_ASSERT(1195, arg->dexpr); - - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->next = NULL; - list->node = CExpr_GetDefaultArgument(expr->data.funccall.funcref, arg); - } - - return expr; -} - -ENode *CExcept_ScanThrowExpression(void) { - ENode *expr; - Object *func; - ENode *resultExpr; - Object *obj; - ENode *thrownExpr; - ENode *tempExpr; - - if (!copts.exceptions) - CError_Error(CErrorStr252); - - switch ((tk = lex())) { - case ')': - case ',': - case ':': - case ';': - expr = funccallexpr(Xthrw_func, nullnode(), nullnode(), nullnode(), NULL); - break; - default: - thrownExpr = pointer_generation(assignment_expression()); - obj = create_temp_object(thrownExpr->rtype); - if (!IS_TYPE_CLASS(thrownExpr->rtype) || !(resultExpr = CExpr_IsTempConstruction(thrownExpr, thrownExpr->rtype, &expr))) { - tempExpr = create_objectrefnode(obj); - if (IS_TYPE_CLASS(thrownExpr->rtype) && (func = CClass_CopyConstructor(TYPE_CLASS(thrownExpr->rtype)))) { - resultExpr = CExcept_CallCopyCtor(func, thrownExpr->rtype, tempExpr, getnodeaddress(thrownExpr, 0)); - } else { - if (thrownExpr->rtype->size == 0) - CError_Error(CErrorStr146); - - tempExpr = makemonadicnode(tempExpr, EINDIRECT); - tempExpr->rtype = thrownExpr->rtype; - resultExpr = makediadicnode(tempExpr, thrownExpr, EASS); - resultExpr = makediadicnode(resultExpr, create_objectrefnode(obj), ECOMMA); - resultExpr->rtype = TYPE(&void_ptr); - } - } else { - *expr = *create_objectrefnode(obj); - } - - expr = CExcept_GetTypeID(thrownExpr->rtype, ENODE_QUALS(thrownExpr), 1); - if (IS_TYPE_CLASS(thrownExpr->rtype) && (func = CClass_Destructor(TYPE_CLASS(thrownExpr->rtype)))) { - expr = funccallexpr( - Xthrw_func, - expr, - resultExpr, - create_objectrefnode(CABI_GetDestructorObject(func, CABIDestroy1)), - NULL); - } else { - expr = funccallexpr( - Xthrw_func, - expr, - resultExpr, - nullnode(), - NULL); - } - } - - expr->flags |= ENODE_FLAG_VOLATILE; - return expr; -} - -static Boolean CExcept_MightNeedDtor(Type *type) { - if (type) { - if (IS_TYPE_CLASS(type)) { - if (!CClass_Destructor(TYPE_CLASS(type))) - return 0; - } else if (IS_TYPE_POINTER_ONLY(type)) { - if (!(TPTR_QUAL(type) & Q_REFERENCE) || !IS_TYPE_CLASS(TPTR_TARGET(type))) - return 0; - } else { - return 0; - } - } - - return 1; -} - -typedef struct CatchBlock { - struct CatchBlock *next; - Object *catch_object; - Object *catch_info_object; - Statement *stmt; - Statement *anotherStmt; - Type *type; - UInt32 qual; -} CatchBlock; - -static void CExcept_PatchDObjStack(Statement *beginCatchStmt, Statement *tryEndStmt, Statement *endStmt, CatchBlock *catchBlock) { - ExceptionAction *ea; - ExceptionAction *stackHead; - ExceptionAction *stackTail; - ExceptionAction *firstEA; - Statement *stmt; - Object *catch_info_object; - Boolean call_dtor; - - catch_info_object = catchBlock->catch_info_object; - call_dtor = 0; - stackHead = stackTail = beginCatchStmt->dobjstack; - firstEA = NULL; - - while (catchBlock) { - ea = lalloc(sizeof(ExceptionAction)); - memclrw(ea, sizeof(ExceptionAction)); - - ea->prev = stackTail; - stackTail = ea; - - if (!firstEA) - firstEA = ea; - - ea->type = EAT_CATCHBLOCK; - ea->data.catch_block.catch_object = catchBlock->catch_object; - ea->data.catch_block.catch_label = catchBlock->stmt->label; - if (catchBlock->type) - ea->data.catch_block.catch_typeid = CExcept_TypeID(catchBlock->type, catchBlock->qual); - ea->data.catch_block.catch_info_object = catch_info_object; - - if (!call_dtor && CExcept_MightNeedDtor(catchBlock->type)) - call_dtor = 1; - - ea->data.catch_block.catch_type = catchBlock->type; - ea->data.catch_block.catch_qual = catchBlock->qual; - catchBlock = catchBlock->next; - } - - stmt = beginCatchStmt; - while (1) { - if ((ea = stmt->dobjstack) != stackHead) { - while (1) { - CError_ASSERT(1404, ea); - if (ea->prev == stackTail) - break; - if (ea->prev == stackHead) { - ea->prev = stackTail; - break; - } - ea = ea->prev; - } - } else { - stmt->dobjstack = stackTail; - } - - if (stmt == endStmt) - break; - - if (stmt == tryEndStmt) { - ea = lalloc(sizeof(ExceptionAction)); - memclrw(ea, sizeof(ExceptionAction)); - ea->prev = stackHead; - ea->type = EAT_ACTIVECATCHBLOCK; - ea->data.active_catch_block.catch_info_object = catch_info_object; - ea->data.active_catch_block.call_dtor = call_dtor; - stackTail = ea; - } - - stmt = stmt->next; - CError_ASSERT(1426, stmt); - } - - cexcept_hasdobjects = 1; -} - -static void CExcept_CheckTryObjects(ENode *expr) { - if (expr->data.objref->datatype == DLOCAL && expr->data.objref->u.var.info) - expr->data.objref->u.var.info->noregister = 1; -} - -static ENode *CExcept_CatchExpressionInit(DeclInfo *di, CatchBlock *catchBlock) { - Object *catch_object; - Object *copyCtor; - Object *dtor; - ENode *expr; - - if (CScope_FindName(cscope_current, di->name)) - CError_Error(CErrorStr122, di->name->name); - - catch_object = CParser_NewLocalDataObject(di, 1); - CFunc_SetupLocalVarInfo(catch_object); - CScope_AddObject(cscope_current, di->name, OBJ_BASE(catch_object)); - catchBlock->catch_object = catch_object; - - expr = makediadicnode( - create_objectrefnode(catchBlock->catch_info_object), - intconstnode(TYPE(&stunsignedlong), 12), - EADD); - expr->rtype = CDecl_NewPointerType(CDecl_NewPointerType(di->thetype)); - - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = CDecl_NewPointerType(di->thetype); - - if (IS_TYPE_REFERENCE(di->thetype)) - return makediadicnode(create_objectnode2(catch_object), expr, EASS); - - if (IS_TYPE_CLASS(di->thetype) && (copyCtor = CClass_CopyConstructor(TYPE_CLASS(di->thetype)))) { - dtor = CClass_Destructor(TYPE_CLASS(di->thetype)); - return CExcept_CallCopyCtor( - copyCtor, - di->thetype, - (dtor == NULL) ? create_objectrefnode(catch_object) : CExcept_RegisterDestructorObject(catch_object, 0, dtor, 0), - expr); - } - - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = di->thetype; - return makediadicnode(create_objectnode(catch_object), expr, EASS); -} - -void CExcept_ScanTryBlock(DeclThing *dt, Boolean flag) { - Object *catch_info_object; // r27 - Statement *beginCatchStmt; // r14 - Statement *tryEndStmt; // r16 - Statement *endStmt; // r17 - Statement *stmt; // r14 - CLabel *catchEndLabel; // r19 - CLabel *endLabel; // r24 - CatchBlock *catchStack; // r23 - CatchBlock *catchBlock; // r22 - DeclBlock *declBlock; // r20 - DeclInfo di; - - if (!copts.exceptions) - CError_Error(CErrorStr252); - - catch_info_object = create_temp_object(TYPE(&catchinfostruct)); - if (cexcept_magic) { - catch_info_object->name = GetHashNameNodeExport("__exception_magic"); - CScope_AddObject(cscope_current, catch_info_object->name, OBJ_BASE(catch_info_object)); - } - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->flags = StmtFlag_1; - stmt->label = newlabel(); - stmt->label->stmt = stmt; - - beginCatchStmt = CFunc_AppendStatement(ST_BEGINCATCH); - beginCatchStmt->expr = create_objectrefnode(catch_info_object); - - if (tk != '{') { - CError_Error(CErrorStr135); - return; - } - - CFunc_CompoundStatement(dt); - - if (tk != TK_CATCH) { - CError_Error(CErrorStr242); - return; - } - - stmt = CFunc_AppendStatement(ST_GOTO); - catchEndLabel = stmt->label = newlabel(); - tryEndStmt = stmt; - - endLabel = newlabel(); - catchStack = NULL; - - while (1) { - CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->flags = StmtFlag_1; - stmt->label = newlabel(); - stmt->label->stmt = stmt; - - declBlock = NULL; - - catchBlock = lalloc(sizeof(ExceptionAction)); - memclrw(catchBlock, sizeof(ExceptionAction)); - catchBlock->next = catchStack; - catchStack = catchBlock; - - catchBlock->stmt = stmt; - catchBlock->catch_info_object = catch_info_object; - - if ((tk = lex()) != '(') { - CError_Error(CErrorStr114); - break; - } - - if ((tk = lex()) == TK_ELLIPSIS) { - tk = lex(); - } else { - memclrw(&di, sizeof(di)); - CParser_GetDeclSpecs(&di, 0); - - if (di.x48) - CError_Error(CErrorStr121); - if (di.storageclass) - CError_Error(CErrorStr177); - - CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_ALIGNED_MASK)); - - scandeclarator(&di); - - if (IS_TYPE_FUNC(di.thetype)) - di.thetype = CDecl_NewPointerType(di.thetype); - else if (IS_TYPE_ARRAY(di.thetype)) - di.thetype = CDecl_NewPointerType(TPTR_TARGET(di.thetype)); - - IsCompleteType(di.thetype); - if (IS_TYPE_CLASS(di.thetype) && (TYPE_CLASS(di.thetype)->flags & CLASS_ABSTRACT)) - CError_AbstractClassError(TYPE_CLASS(di.thetype)); - - catchBlock->type = di.thetype; - catchBlock->qual = di.qual; - - if (di.name) { - ENode *expr; - declBlock = CFunc_NewDeclBlock(); - expr = CExcept_CatchExpressionInit(&di, catchBlock); - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = expr; - } - } - - if (tk != ')') { - CError_Error(CErrorStr115); - break; - } - - if ((tk = lex()) != '{') { - CError_Error(CErrorStr123); - break; - } - - CFunc_CompoundStatement(dt); - if (flag) { - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = funccallexpr(Xthrw_func, nullnode(), nullnode(), nullnode(), NULL); - } - - catchBlock->anotherStmt = stmt; - - if (declBlock) - CFunc_RestoreBlock(declBlock); - - if (tk != TK_CATCH) - break; - - CFunc_AppendStatement(ST_GOTO)->label = endLabel; - } - - endStmt = CFunc_AppendStatement(ST_LABEL); - endStmt->label = endLabel; - endLabel->stmt = endStmt; - - CExcept_PatchDObjStack(beginCatchStmt, tryEndStmt, endStmt, catchBlock); - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = catchEndLabel; - catchEndLabel->stmt = stmt; -} - -static Statement *CExcept_InsertPrevStatement(StatementType sttype) { - Statement *stmt = CFunc_InsertStatement(sttype, cexcept_prevstmt); - stmt->sourceoffset = stmt->next->sourceoffset; - stmt->sourcefilepath = stmt->next->sourcefilepath; - stmt->dobjstack = cexcept_eabefore; - return stmt; -} - -static Object *CExcept_GetETEMPObject(ENode *expr) { - UniqueObj *uobj; - SInt32 id; - - if ((id = expr->data.temp.uniqueid)) { - for (uobj = cexcept_uniqueobjs; uobj; uobj = uobj->next) { - if (uobj->uniqueid == id) - return uobj->object; - } - - uobj = galloc(sizeof(UniqueObj)); - uobj->next = cexcept_uniqueobjs; - cexcept_uniqueobjs = uobj; - uobj->uniqueid = id; - return (uobj->object = create_temp_object(expr->data.temp.type)); - } else { - return create_temp_object(expr->data.temp.type); - } -} - -static ENode *CExcept_TempTrans_ETEMP(ENode *expr) { - Object *object; - ExceptionAction *ea; - DtorTemp *dtorTemp; - Object *dtor; - - object = CExcept_GetETEMPObject(expr); - if (expr->data.temp.needs_dtor) { - dtorTemp = lalloc(sizeof(DtorTemp)); - dtorTemp->next = cexcept_dtortemps; - cexcept_dtortemps = dtorTemp; - dtorTemp->object = object; - dtorTemp->temp = NULL; - - if ( - !IS_TYPE_CLASS(expr->data.temp.type) || - !(dtorTemp->dtor = CClass_Destructor(TYPE_CLASS(expr->data.temp.type))) - ) - CError_FATAL(1749); - - ea = lalloc(sizeof(ExceptionAction)); - ea->prev = cexcept_eabefore; - cexcept_eabefore = ea; - ea->type = EAT_DESTROYLOCAL; - ea->data.destroy_local.local = dtorTemp->object; - ea->data.destroy_local.dtor = CABI_GetDestructorObject(dtorTemp->dtor, CABIDestroy1); - - ea = lalloc(sizeof(ExceptionAction)); - *ea = *cexcept_eabefore; - ea->prev = cexcept_eaafter; - cexcept_eaafter = ea; - } - - expr->type = EOBJREF; - expr->data.objref = object; - return expr; -} - -static ENode *CExcept_TransNewException(ENode *expr, Boolean isCond) { - Object *tempObj; - CLabel *label; - Boolean isArray; - Statement *stmt; - ExceptionAction *ea; - ENode *result; - - isArray = expr->type == ENEWEXCEPTIONARRAY; - - if (isCond) { - expr->data.newexception.initexpr = CExcept_TempTransExprCond(expr->data.newexception.initexpr); - expr->data.newexception.tryexpr = CExcept_TempTransExprCond(expr->data.newexception.tryexpr); - tempObj = create_temp_object(TYPE(&stchar)); - - stmt = CExcept_InsertPrevStatement(ST_EXPRESSION); - stmt->expr = makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 0), EASS); - cexcept_prevstmt = stmt; - - ea = lalloc(sizeof(ExceptionAction)); - ea->prev = cexcept_eabefore; - cexcept_eabefore = ea; - - ea->type = EAT_DELETEPOINTERCOND; - ea->data.delete_pointer_cond.pointerobject = expr->data.newexception.pointertemp; - ea->data.delete_pointer_cond.deletefunc = expr->data.newexception.deletefunc; - ea->data.delete_pointer_cond.cond = tempObj; - - if (isArray) { - result = makediadicnode( - makediadicnode( - expr->data.newexception.initexpr, - makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 1), EASS), - ECOMMA - ), - expr->data.newexception.tryexpr, - ECOMMA - ); - - result = makediadicnode( - result, - makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 0), EASS), - ECOMMA - ); - - result = makediadicnode( - result, - create_objectnode(expr->data.newexception.pointertemp), - ECOMMA - ); - } else { - result = makediadicnode( - makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 1), EASS), - expr->data.newexception.tryexpr, - ECOMMA - ); - - result = makediadicnode( - expr->data.newexception.initexpr, - makediadicnode( - result, - makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 0), EASS), - ECOMMA - ), - ELAND - ); - - result = makediadicnode( - result, - create_objectnode(expr->data.newexception.pointertemp), - ECOMMA - ); - } - } else { - expr->data.newexception.initexpr = CExcept_TempTransExpr(expr->data.newexception.initexpr); - expr->data.newexception.tryexpr = CExcept_TempTransExpr(expr->data.newexception.tryexpr); - - if (isArray) { - stmt = CExcept_InsertPrevStatement(ST_EXPRESSION); - stmt->expr = expr->data.newexception.initexpr; - } else { - stmt = CExcept_InsertPrevStatement(ST_IFNGOTO); - stmt->expr = expr->data.newexception.initexpr; - label = newlabel(); - stmt->label = label; - } - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = expr->data.newexception.tryexpr; - - ea = lalloc(sizeof(ExceptionAction)); - ea->prev = cexcept_eabefore; - ea->type = EAT_DELETEPOINTER; - ea->data.delete_pointer.pointerobject = expr->data.newexception.pointertemp; - ea->data.delete_pointer.deletefunc = expr->data.newexception.deletefunc; - stmt->dobjstack = ea; - - if (!isArray) { - stmt = CFunc_InsertStatement(ST_LABEL, stmt); - stmt->label = label; - label->stmt = stmt; - stmt->dobjstack = cexcept_eabefore; - } - - cexcept_prevstmt = stmt; - result = create_objectnode(expr->data.newexception.pointertemp); - } - - result->rtype = expr->rtype; - return result; -} - -static ENode *CExcept_TransInitTryCatch(ENode *expr, Boolean isCond) { - CLabel *label1; - CLabel *label2; - CLabel *label3; - Object *catch_info_object; - Statement *stmt; - ExceptionAction *ea; - - cexcept_hastrycatch = 1; - - if (isCond) { - CError_ASSERT(1877, !cexcept_expandtrycatch); - - cexcept_serialize = 1; - expr->data.itc.initexpr = CExcept_TempTransExprCond(expr->data.itc.initexpr); - expr->data.itc.tryexpr = CExcept_TempTransExprCond(expr->data.itc.tryexpr); - expr->data.itc.catchexpr = CExcept_TempTransExprCond(expr->data.itc.catchexpr); - expr->data.itc.result = CExcept_TempTransExprCond(expr->data.itc.result); - return expr; - } - - expr->data.itc.initexpr = CExcept_TempTransExpr(expr->data.itc.initexpr); - expr->data.itc.tryexpr = CExcept_TempTransExpr(expr->data.itc.tryexpr); - expr->data.itc.catchexpr = CExcept_TempTransExpr(expr->data.itc.catchexpr); - expr->data.itc.result = CExcept_TempTransExpr(expr->data.itc.result); - - if (!cexcept_expandtrycatch) - return expr; - - label1 = newlabel(); - label2 = newlabel(); - label3 = newlabel(); - - catch_info_object = create_temp_object(TYPE(&catchinfostruct)); - - stmt = CExcept_InsertPrevStatement(ST_IFNGOTO); - stmt->expr = expr->data.itc.initexpr; - stmt->label = label3; - - ea = lalloc(sizeof(ExceptionAction)); - memclrw(ea, sizeof(ExceptionAction)); - ea->type = EAT_CATCHBLOCK; - ea->data.catch_block.catch_label = label2; - ea->data.catch_block.catch_info_object = catch_info_object; - ea->prev = stmt->dobjstack; - - stmt = CFunc_InsertStatement(ST_LABEL, stmt); - stmt->flags = StmtFlag_1; - stmt->label = label1; - label1->stmt = stmt; - stmt->dobjstack = ea; - - stmt = CFunc_InsertStatement(ST_BEGINCATCH, stmt); - stmt->expr = create_objectrefnode(catch_info_object); - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = expr->data.itc.tryexpr; - - stmt = CFunc_InsertStatement(ST_GOTO, stmt); - stmt->label = label3; - - CError_ASSERT(1928, stmt->dobjstack == ea); - - stmt->dobjstack = ea->prev; - - ea = lalloc(sizeof(ExceptionAction)); - memclrw(ea, sizeof(ExceptionAction)); - ea->type = EAT_ACTIVECATCHBLOCK; - ea->data.active_catch_block.catch_info_object = catch_info_object; - ea->prev = stmt->dobjstack; - - stmt = CFunc_InsertStatement(ST_LABEL, stmt); - stmt->flags = StmtFlag_1; - stmt->label = label2; - label2->stmt = stmt; - stmt->dobjstack = ea; - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = expr->data.itc.catchexpr; - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = funccallexpr(Xthrw_func, nullnode(), nullnode(), nullnode(), NULL); - - stmt = CFunc_InsertStatement(ST_LABEL, stmt); - stmt->label = label3; - label3->stmt = stmt; - - CError_ASSERT(1968, stmt->dobjstack == ea); - - stmt->dobjstack = ea->prev; - - cexcept_prevstmt = stmt; - return expr->data.itc.result; -} - -static ENode *CExcept_TempTransFuncCall(ENode *expr, Boolean isCond) { - ENodeList *tempArg; - ENodeList **argArray; - ENodeList *args; - ExceptionAction *ea; - Statement *stmt; - DtorTemp *dtorTemp; - ENode *tempNode; - - tempArg = NULL; - if ((args = expr->data.funccall.args)) { - tempNode = args->node; - if (tempNode->type == ETEMP) { - if (tempNode->data.temp.needs_dtor) - tempArg = args; - } else if (args->next) { - tempNode = args->next->node; - if (tempNode->type == ETEMP) { - if (tempNode->data.temp.needs_dtor) - tempArg = args->next; - } - } - } - - if (tempArg) { - if (isCond) { - ENodeList *arg = args; - SInt32 i = 0; - while (arg) { - arg = arg->next; - i++; - } - - argArray = lalloc(sizeof(ENodeList *) * i); - for (args = expr->data.funccall.args, i = 0; args; args = args->next) - argArray[i++] = args; - - while (i > 0) { - i--; - if (argArray[i] != tempArg) - argArray[i]->node = CExcept_TempTransExprCond(argArray[i]->node); - } - } else { - while (args) { - if (args != tempArg) - args->node = CExcept_TempTransExpr(args->node); - args = args->next; - } - } - - dtorTemp = lalloc(sizeof(DtorTemp)); - dtorTemp->next = cexcept_dtortemps; - cexcept_dtortemps = dtorTemp; - - dtorTemp->object = CExcept_GetETEMPObject(tempNode); - dtorTemp->temp = NULL; - - if ( - !IS_TYPE_CLASS(tempNode->data.temp.type) || - !(dtorTemp->dtor = CClass_Destructor(TYPE_CLASS(tempNode->data.temp.type))) - ) - CError_FATAL(2046); - - tempNode->type = EOBJREF; - tempNode->data.objref = dtorTemp->object; - - if (isCond) { - Type *type24 = expr->rtype; - dtorTemp->temp = create_temp_object(TYPE(&stchar)); - - expr = makediadicnode( - expr, - makediadicnode(create_objectnode(dtorTemp->temp), intconstnode(TYPE(&stchar), 1), EASS), - ECOMMA - ); - - expr = makediadicnode( - expr, - create_objectrefnode(dtorTemp->object), - ECOMMA - ); - expr->rtype = type24; - - stmt = CExcept_InsertPrevStatement(ST_EXPRESSION); - stmt->expr = makediadicnode( - create_objectnode(dtorTemp->temp), - intconstnode(TYPE(&stchar), 0), - EASS - ); - cexcept_prevstmt = stmt; - - ea = lalloc(sizeof(ExceptionAction)); - ea->prev = cexcept_eabefore; - cexcept_eabefore = ea; - - ea->type = EAT_DESTROYLOCALCOND; - ea->data.destroy_local_cond.local = dtorTemp->object; - ea->data.destroy_local_cond.dtor = CABI_GetDestructorObject(dtorTemp->dtor, CABIDestroy1); - ea->data.destroy_local_cond.cond = dtorTemp->temp; - - ea = lalloc(sizeof(ExceptionAction)); - *ea = *cexcept_eabefore; - ea->prev = cexcept_eaafter; - cexcept_eaafter = ea; - } else { - stmt = CExcept_InsertPrevStatement(ST_EXPRESSION); - stmt->expr = expr; - cexcept_prevstmt = stmt; - - ea = lalloc(sizeof(ExceptionAction)); - ea->prev = cexcept_eabefore; - cexcept_eabefore = ea; - - ea->type = EAT_DESTROYLOCAL; - ea->data.destroy_local.local = dtorTemp->object; - ea->data.destroy_local.dtor = CABI_GetDestructorObject(dtorTemp->dtor, CABIDestroy1); - - ea = lalloc(sizeof(ExceptionAction)); - *ea = *cexcept_eabefore; - ea->prev = cexcept_eaafter; - cexcept_eaafter = ea; - - expr = lalloc(sizeof(ENode)); - *expr = *stmt->expr; - expr->type = EOBJREF; - expr->data.objref = tempArg->node->data.objref; - } - return expr; - } else { - if (isCond) { - SInt32 i = 0; - while (args) { - args = args->next; - i++; - } - - argArray = lalloc(sizeof(ENodeList *) * i); - for (args = expr->data.funccall.args, i = 0; args; args = args->next) - argArray[i++] = args; - - while (i > 0) { - i--; - argArray[i]->node = CExcept_TempTransExprCond(argArray[i]->node); - } - - expr->data.funccall.funcref = CExcept_TempTransExprCond(expr->data.funccall.funcref); - } else { - while (args) { - args->node = CExcept_TempTransExpr(args->node); - args = args->next; - } - - expr->data.funccall.funcref = CExcept_TempTransExpr(expr->data.funccall.funcref); - } - - return expr; - } -} - -static ENode *CExcept_TempTransExprCond(ENode *expr) { - switch (expr->type) { - case ETEMP: - return CExcept_TempTrans_ETEMP(expr); - case ENEWEXCEPTION: - case ENEWEXCEPTIONARRAY: - return CExcept_TransNewException(expr, 1); - case EINITTRYCATCH: - return CExcept_TransInitTryCatch(expr, 1); - case ENULLCHECK: - expr->data.nullcheck.nullcheckexpr = CExcept_TempTransExprCond(expr->data.nullcheck.nullcheckexpr); - expr->data.nullcheck.condexpr = CExcept_TempTransExprCond(expr->data.nullcheck.condexpr); - return expr; - case ECOND: - expr->data.cond.cond = CExcept_TempTransExprCond(expr->data.cond.cond); - expr->data.cond.expr1 = CExcept_TempTransExprCond(expr->data.cond.expr1); - expr->data.cond.expr2 = CExcept_TempTransExprCond(expr->data.cond.expr2); - return expr; - case ELAND: - case ELOR: - expr->data.diadic.left = CExcept_TempTransExprCond(expr->data.diadic.left); - expr->data.diadic.right = CExcept_TempTransExprCond(expr->data.diadic.right); - return expr; - case EFUNCCALL: - case EFUNCCALLP: - return CExcept_TempTransFuncCall(expr, 1); - case EMUL: - case EDIV: - case EMODULO: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case ECOMMA: - case EROTL: - case EROTR: - expr->data.diadic.left = CExcept_TempTransExprCond(expr->data.diadic.left); - expr->data.diadic.right = CExcept_TempTransExprCond(expr->data.diadic.right); - return expr; - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EINDIRECT: - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case ETYPCON: - case EBITFIELD: - expr->data.monadic = CExcept_TempTransExprCond(expr->data.monadic); - return expr; - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case EPRECOMP: - case ELABEL: - case EINSTRUCTION: - case EVECTOR128CONST: - return expr; - default: - CError_FATAL(2236); - return expr; - } -} - -static ENode *CExcept_TempTransExpr(ENode *expr) { - switch (expr->type) { - case ETEMP: - return CExcept_TempTrans_ETEMP(expr); - case ENEWEXCEPTION: - case ENEWEXCEPTIONARRAY: - return CExcept_TransNewException(expr, 0); - case EINITTRYCATCH: - return CExcept_TransInitTryCatch(expr, 0); - case ENULLCHECK: - expr->data.nullcheck.nullcheckexpr = CExcept_TempTransExpr(expr->data.nullcheck.nullcheckexpr); - expr->data.nullcheck.condexpr = CExcept_TempTransExprCond(expr->data.nullcheck.condexpr); - return expr; - case ECOND: - expr->data.cond.cond = CExcept_TempTransExpr(expr->data.cond.cond); - expr->data.cond.expr1 = CExcept_TempTransExprCond(expr->data.cond.expr1); - expr->data.cond.expr2 = CExcept_TempTransExprCond(expr->data.cond.expr2); - return expr; - case ELAND: - case ELOR: - case ECOMMA: - expr->data.diadic.left = CExcept_TempTransExpr(expr->data.diadic.left); - expr->data.diadic.right = CExcept_TempTransExprCond(expr->data.diadic.right); - return expr; - case EFUNCCALL: - case EFUNCCALLP: - return CExcept_TempTransFuncCall(expr, 0); - case EMUL: - case EDIV: - case EMODULO: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case EROTL: - case EROTR: - expr->data.diadic.left = CExcept_TempTransExpr(expr->data.diadic.left); - expr->data.diadic.right = CExcept_TempTransExpr(expr->data.diadic.right); - return expr; - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EINDIRECT: - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case ETYPCON: - case EBITFIELD: - expr->data.monadic = CExcept_TempTransExpr(expr->data.monadic); - return expr; - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case EMFPOINTER: - case EPRECOMP: - case ELABEL: - case EOBJLIST: - case EMEMBER: - case EINSTRUCTION: - case EVECTOR128CONST: - return expr; - default: - CError_FATAL(2350); - return expr; - } -} - -static Statement *CExcept_DtorTransform(Statement *stmt) { - DtorTemp *dtorTemp; - Statement *curStmt; - CLabel *lastLabel; - - dtorTemp = cexcept_dtortemps; - curStmt = stmt; - while (dtorTemp) { - if ( - cexcept_eaafter && - (cexcept_eaafter->type == EAT_DESTROYLOCAL || cexcept_eaafter->type == EAT_DESTROYLOCALCOND) && - cexcept_eaafter->data.destroy_local.local == dtorTemp->object - ) - { - cexcept_eaafter = cexcept_eaafter->prev; - } else { - CError_FATAL(2374); - } - - if (dtorTemp->temp) { - curStmt = CFunc_InsertStatement(ST_IFNGOTO, curStmt); - curStmt->expr = create_objectnode(dtorTemp->temp); - curStmt->dobjstack = cexcept_eaafter; - lastLabel = curStmt->label = newlabel(); - } - - curStmt = CFunc_InsertStatement(ST_EXPRESSION, curStmt); - curStmt->expr = CABI_DestroyObject(dtorTemp->dtor, create_objectrefnode(dtorTemp->object), CABIDestroy1, 1, 0); - curStmt->dobjstack = cexcept_eaafter; - - if (dtorTemp->temp) { - curStmt = CFunc_InsertStatement(ST_LABEL, curStmt); - curStmt->label = lastLabel; - lastLabel->stmt = curStmt; - } - - dtorTemp = dtorTemp->next; - } - - return curStmt; -} - -static void CExcept_TempTransform(Statement *stmt, Boolean flag1, Boolean flag2) { - Statement *prevStmt; - Statement *iter; - Statement copy; - Object *tempObj; - - prevStmt = cexcept_prevstmt; - cexcept_dtortemps = NULL; - cexcept_serialize = 0; - cexcept_expandtrycatch = 0; - cexcept_hastrycatch = 0; - stmt->expr = CExcept_TempTransExpr(stmt->expr); - - if (cexcept_hastrycatch) { - cexcept_expandtrycatch = 1; - if (cexcept_serialize) { - CInline_SerializeStatement(stmt); - cexcept_prevstmt = stmt; - } else { - cexcept_prevstmt = prevStmt; - } - - iter = prevStmt; - while (1) { - CError_ASSERT(2425, iter); - - switch (iter->type) { - case ST_RETURN: - CError_ASSERT(2429, iter->expr != NULL); - case ST_EXPRESSION: - case ST_SWITCH: - case ST_IFGOTO: - case ST_IFNGOTO: - iter->expr = CExcept_TempTransExpr(iter->expr); - } - - if (iter == stmt) - break; - cexcept_prevstmt = iter; - iter = iter->next; - } - } - - if (cexcept_dtortemps) { - if (!flag1) { - if (flag2) { - ENode *expr = stmt->expr; - CError_ASSERT(2456, !IS_TYPE_CLASS(expr->rtype) || !CClass_Destructor(TYPE_CLASS(expr->rtype))); - - tempObj = create_temp_object(expr->rtype); - stmt->expr = makediadicnode(create_objectnode(tempObj), expr, EASS); - } - - copy = *stmt; - stmt->type = ST_EXPRESSION; - stmt = CExcept_DtorTransform(stmt); - stmt = CFunc_InsertStatement(copy.type, stmt); - stmt->label = copy.label; - - if (flag2) - stmt->expr = create_objectnode(tempObj); - else - stmt->expr = nullnode(); - } else { - CExcept_DtorTransform(stmt); - } - } -} - -static void CExcept_CleanupExceptionActions(Statement *stmt) { - Statement *iter; - ENode *expr; - ExceptionAction *ea; - - cexcept_prevstmt = stmt; - for (iter = stmt; iter; iter = iter->next) { - cexcept_eabefore = cexcept_eaafter = ea = iter->dobjstack; - - if (iter->flags & StmtFlag_2) { - cexcept_eabefore = ea->prev; - } else if (iter->type == ST_EXPRESSION) { - expr = iter->expr; - while (ENODE_IS(expr, ECOMMA)) - expr = expr->data.diadic.left; - if (ENODE_IS(expr, EINDIRECT)) - expr = expr->data.monadic; - - if ( - ENODE_IS(expr, EFUNCCALL) && - ENODE_IS(expr->data.funccall.funcref, EOBJREF) && - CClass_IsConstructor(expr->data.funccall.funcref->data.objref) && - iter->dobjstack && - iter->dobjstack->type == EAT_DESTROYLOCAL && - expr->data.funccall.args && - ENODE_IS(expr->data.funccall.args->node, EOBJREF) && - expr->data.funccall.args->node->data.objref == iter->dobjstack->data.destroy_local.local - ) - cexcept_eabefore = cexcept_eabefore->prev; - } - - switch (iter->type) { - case ST_EXPRESSION: - CExcept_TempTransform(iter, 1, 0); - break; - case ST_SWITCH: - case ST_IFGOTO: - case ST_IFNGOTO: - CExcept_TempTransform(iter, 0, 1); - break; - case ST_RETURN: - if (iter->expr) { - CExcept_TempTransform( - iter, - 0, - CMach_GetFunctionResultClass(TYPE_FUNC(cscope_currentfunc->type)) != 1 - ); - } - break; - } - - iter->dobjstack = cexcept_eabefore; - cexcept_prevstmt = iter; - } -} - -static void CExcept_InsertSpecificationActions(Statement *stmt, ExceptSpecList *exspecs) { - Statement *iter; - Statement *last; - ExceptionAction *ea_spec; - ExceptionAction *ea; - ExceptSpecList *spec_iter; - SInt32 i; - Object *catch_info_object; - CLabel *label; - - ea_spec = lalloc(sizeof(ExceptionAction)); - memclrw(ea_spec, sizeof(ExceptionAction)); - ea_spec->type = EAT_SPECIFICATION; - - for (iter = stmt; iter; iter = iter->next) { - if ((ea = iter->dobjstack)) { - while (1) { - if (ea->type == EAT_SPECIFICATION) - break; - if (ea->prev == NULL) { - ea->prev = ea_spec; - break; - } - ea = ea->prev; - } - } else { - iter->dobjstack = ea_spec; - } - } - - last = stmt; - while (last->next) - last = last->next; - - if (last->type != ST_GOTO && last->type != ST_RETURN) { - last = CFunc_InsertStatement(ST_RETURN, last); - last->expr = NULL; - last->dobjstack = NULL; - if (TYPE_FUNC(cscope_currentfunc->type)->functype != &stvoid && (copts.pedantic || copts.cplusplus)) - CError_Warning(CErrorStr184); - } - - last = CFunc_InsertStatement(ST_LABEL, last); - last->label = newlabel(); - last->label->stmt = last; - last->flags = StmtFlag_1; - last->dobjstack = NULL; - - catch_info_object = create_temp_object(TYPE(&catchinfostruct)); - - if (!exspecs->type) - exspecs = NULL; - - i = 0; - spec_iter = exspecs; - while (spec_iter) { - spec_iter = spec_iter->next; - i++; - } - - ea_spec->data.specification.unexp_ids = i; - ea_spec->data.specification.unexp_id = galloc(sizeof(Object *) * i); - ea_spec->data.specification.unexp_label = last->label; - ea_spec->data.specification.unexp_info_object = catch_info_object; - - i = 0; - while (exspecs) { - ea_spec->data.specification.unexp_id[i] = CExcept_TypeID(exspecs->type, exspecs->qual); - exspecs = exspecs->next; - i++; - } - - last = CFunc_InsertStatement(ST_EXPRESSION, last); - last->expr = funccallexpr(Xunex_func, create_objectrefnode(catch_info_object), NULL, NULL, NULL); - - ea = lalloc(sizeof(ExceptionAction)); - memclrw(ea, sizeof(ExceptionAction)); - ea->type = EAT_ACTIVECATCHBLOCK; - ea->data.active_catch_block.catch_info_object = catch_info_object; - ea->data.active_catch_block.call_dtor = 1; - last->dobjstack = ea; - - last = CFunc_InsertStatement(ST_LABEL, last); - last->label = label = newlabel(); - last->label->stmt = last; - last->dobjstack = NULL; - - last = CFunc_InsertStatement(ST_GOTO, last); - last->label = label; -} - -static void CExcept_HasFuncCallCallBack(ENode *expr) { - ENode *funcref = expr->data.funccall.funcref; - if (ENODE_IS(funcref, EOBJREF)) { - Object *func = funcref->data.objref; - if (CExcept_CanThrowException(func, func->datatype == DVFUNC && !(expr->flags & ENODE_FLAG_80))) - cexcept_canthrow = 1; - } else { - cexcept_canthrow = 1; - } -} - -static Boolean CExcept_CanThrowCheck(Object *func, Statement *stmt) { - cexcept_canthrow = 0; - - while (stmt) { - switch (stmt->type) { - case ST_NOP: - case ST_LABEL: - case ST_GOTO: - case ST_ASM: - break; - case ST_RETURN: - if (!stmt->expr) - break; - case ST_EXPRESSION: - case ST_SWITCH: - case ST_IFGOTO: - case ST_IFNGOTO: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - case ST_GOTOEXPR: - CExpr_SearchExprTree(stmt->expr, CExcept_HasFuncCallCallBack, 2, EFUNCCALL, EFUNCCALLP); - break; - default: - CError_FATAL(2687); - } - stmt = stmt->next; - } - - if (!cexcept_canthrow) { - TYPE_FUNC(cscope_currentfunc->type)->flags |= FUNC_NOTHROW; - return 0; - } else { - return 1; - } -} - -void CExcept_ExceptionTansform(Statement *stmt) { - cexcept_uniqueobjs = NULL; - CExcept_CleanupExceptionActions(stmt); - - if (cscope_currentfunc && CExcept_CanThrowCheck(cscope_currentfunc, stmt)) { - CError_ASSERT(2716, IS_TYPE_FUNC(cscope_currentfunc->type)); - if (TYPE_FUNC(cscope_currentfunc->type)->exspecs && copts.exceptions) - CExcept_InsertSpecificationActions(stmt, TYPE_FUNC(cscope_currentfunc->type)->exspecs); - } -} diff --git a/compiler_and_linker/unsorted/CExpr.c b/compiler_and_linker/unsorted/CExpr.c deleted file mode 100644 index 484f56d..0000000 --- a/compiler_and_linker/unsorted/CExpr.c +++ /dev/null @@ -1,4971 +0,0 @@ -#include "compiler/CExpr.h" -#include "compiler/CABI.h" -#include "compiler/CClass.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CException.h" -#include "compiler/CInit.h" -#include "compiler/CInline.h" -#include "compiler/CIRTransform.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CInt64.h" -#include "compiler/CObjC.h" -#include "compiler/CObjCModern.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CRTTI.h" -#include "compiler/CSOM.h" -#include "compiler/CTemplateNew.h" -#include "compiler/CTemplateTools.h" -#include "compiler/CodeGen.h" -#include "compiler/CompilerTools.h" -#include "compiler/PPCError.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/templates.h" - -Boolean (*name_obj_check)(HashNameNode *, Object *); -Boolean disallowgreaterthan; - -// forward declarations -static ENode *makeaddnode(ENode *left, ENode *right); -static ENode *makesubnode(ENode *left, ENode *right); - -ENode *CExpr_RewriteConst(ENode *expr) { - Object *obj; - -restart: - if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EOBJREF)) { - obj = expr->data.monadic->data.objref; - if (obj->datatype == DALIAS) { - CExpr_AliasTransform(expr->data.monadic); - goto restart; - } - - if ((obj->qual & Q_INLINE_DATA) && expr->rtype == obj->type) { - switch (expr->rtype->type) { - case TYPEINT: - case TYPEENUM: - expr->type = EINTCONST; - expr->data.intval = obj->u.data.u.intconst; - break; - case TYPEPOINTER: - expr->type = EINTCONST; - expr->data.intval = obj->u.data.u.intconst; - expr->rtype = TYPE(&stunsignedlong); - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = obj->type; - break; - case TYPEFLOAT: - expr->type = EFLOATCONST; - if (obj->u.data.u.floatconst) - expr->data.floatval = *obj->u.data.u.floatconst; - else - expr->data.floatval = CMach_CalcFloatConvertFromInt(TYPE(&stsignedlong), cint64_zero); - break; - default: - CError_FATAL(105); - } - } - } - - return expr; -} - -void optimizecomm(ENode *expr) { - ENode *right; - ENode *left; - - if (ENODE_IS((right = expr->data.diadic.right), EINTCONST)) - return; - if (ENODE_IS((left = expr->data.diadic.left), EINTCONST)) { - swap: - expr->data.diadic.right = left; - expr->data.diadic.left = right; - return; - } - - if (ENODE_IS(left, EFLOATCONST)) - return; - if (ENODE_IS(right, EFLOATCONST)) - goto swap; - - if (expr->rtype->type > TYPEFLOAT) - return; - - if (left->cost > right->cost) - goto swap; -} - -static void checkadditive(ENode *expr) { - switch (expr->rtype->type) { - case TYPEINT: - if (expr->rtype == TYPE(&stbool)) - break; - case TYPEFLOAT: - return; - case TYPEENUM: - if (copts.cplusplus) - break; - return; - case TYPEPOINTER: - if (TPTR_TARGET(expr->rtype)->size == 0) - CDecl_CompleteType(TPTR_TARGET(expr->rtype)); - if (TPTR_TARGET(expr->rtype)->size == 0) - break; - return; - case TYPEARRAY: - if (ENODE_IS(expr, EOBJREF)) - return; - } - - CError_Error(CErrorStr376, expr->rtype, ENODE_QUALS(expr)); -} - -static void CExpr_CompareConvert(ENode **leftp, char *opname, ENode **rightp, Boolean flag) { - ENode *left; - ENode *right; - CInt64 val; - - left = *leftp; - right = *rightp; - - switch (left->rtype->type) { - case TYPEINT: - break; - case TYPEFLOAT: - if (left->rtype != right->rtype) - CExpr_ArithmeticConversion(leftp, rightp); - return; - case TYPEENUM: - left->rtype = TYPE_ENUM(left->rtype)->enumtype; - break; - default: - CError_Error(CErrorStr377, - left->rtype, ENODE_QUALS(left), - opname, - right->rtype, ENODE_QUALS(right)); - left = nullnode(); - } - - switch (right->rtype->type) { - case TYPEINT: - break; - case TYPEFLOAT: - CExpr_ArithmeticConversion(leftp, rightp); - return; - case TYPEENUM: - right->rtype = TYPE_ENUM(right->rtype)->enumtype; - break; - default: - CError_Error(CErrorStr377, - left->rtype, ENODE_QUALS(left), - opname, - right->rtype, ENODE_QUALS(right)); - right = nullnode(); - } - - if (left->rtype == right->rtype) { - *leftp = left; - *rightp = right; - return; - } - - if (left->rtype->size == right->rtype->size) { - if (is_unsigned(left->rtype) == is_unsigned(right->rtype)) { - left->rtype = right->rtype; - *leftp = left; - *rightp = right; - return; - } - } else { - if (ENODE_IS(right, EINTCONST) && left->rtype->size <= right->rtype->size && (is_unsigned(left->rtype) == is_unsigned(right->rtype) || is_unsigned(left->rtype))) { - val = CMach_CalcIntDiadic(left->rtype, right->data.intval, '+', cint64_zero); - val = CMach_CalcIntDiadic(right->rtype, val, '+', cint64_zero); - if (CInt64_Equal(val, right->data.intval)) { - right->rtype = left->rtype; - *leftp = left; - *rightp = right; - return; - } - } - - if (ENODE_IS(left, EINTCONST) && left->rtype->size >= right->rtype->size && (is_unsigned(left->rtype) == is_unsigned(right->rtype) || is_unsigned(right->rtype))) { - val = CMach_CalcIntDiadic(right->rtype, left->data.intval, '+', cint64_zero); - val = CMach_CalcIntDiadic(left->rtype, val, '+', cint64_zero); - if (CInt64_Equal(val, left->data.intval)) { - left->rtype = right->rtype; - *leftp = left; - *rightp = right; - return; - } - } - } - - *leftp = left; - *rightp = right; - CExpr_ArithmeticConversion(leftp, rightp); -} - -static ENode *CExpr_ConstResult(ENode *expr, SInt32 value) { - ENode *constnode; - - if (IS_TYPE_FLOAT(expr->rtype)) { - constnode = intconstnode(TYPE(&stsignedint), value); - constnode->type = EFLOATCONST; - constnode->data.floatval = CMach_CalcFloatConvertFromInt(TYPE(&stsignedint), constnode->data.intval); - constnode->rtype = expr->rtype; - } else { - constnode = intconstnode(expr->rtype, value); - } - - if (CInline_ExpressionHasSideEffect(expr)) - return makediadicnode(expr, constnode, ECOMMA); - else - return constnode; -} - -static ENode *makemultnode(ENode *left, ENode *right) { - CExpr_ArithmeticConversion(&left, &right); - if (iszero(left)) - return CExpr_ConstResult(right, 0); - if (iszero(right)) - return CExpr_ConstResult(left, 0); - - if (CExpr_IsOne(right)) - return left; - if (CExpr_IsOne(left)) - return right; - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '*', right->data.intval); - return left; - } - if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - left->data.floatval = CMach_CalcFloatDiadic(left->rtype, left->data.floatval, '*', right->data.floatval); - return left; - } - - left = makediadicnode(left, right, EMUL); - optimizecomm(left); - if (IS_TYPE_INT(left->rtype) && left->rtype->size > 2) { - left->cost++; - if (left->cost > 200) - left->cost = 200; - } - - if (IS_TYPE_FLOAT(left->rtype)) - left = CExpr_BinaryFloatExpression(left); - - return left; -} - -static ENode *makedivnode(ENode *left, ENode *right, Boolean no_warning) { - CExpr_ArithmeticConversion(&left, &right); - if (iszero(right) && IS_TYPE_INT(right->rtype)) { - if (!no_warning) - CError_Warning(CErrorStr139); - return right; - } - - if (CExpr_IsOne(right)) - return left; - - if (iszero(left) && IS_TYPE_INT(left->rtype)) - return CExpr_ConstResult(right, 0); - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '/', right->data.intval); - return left; - } - if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - left->data.floatval = CMach_CalcFloatDiadic(left->rtype, left->data.floatval, '/', right->data.floatval); - return left; - } - - left = makediadicnode(left, right, EDIV); - if (IS_TYPE_FLOAT(left->rtype)) - left = CExpr_BinaryFloatExpression(left); - - return left; -} - -static short canadd2(ENode *expr, CInt64 value) { - Float tmp; - - if (CInt64_IsZero(&value)) - return 1; - - switch (expr->type) { - case EINTCONST: - expr->data.intval = CMach_CalcIntDiadic(expr->rtype, expr->data.intval, '+', value); - return 1; - case EFLOATCONST: - tmp = CMach_CalcFloatConvertFromInt(TYPE(&stsignedlong), value); - expr->data.floatval = CMach_CalcFloatDiadic(expr->rtype, expr->data.floatval, '+', tmp); - return 1; - case EADD: - if (canadd2(expr->data.diadic.left, value)) - return 1; - if (canadd2(expr->data.diadic.right, value)) - return 1; - return 0; - case ESUB: - if (canadd2(expr->data.diadic.left, value)) - return 1; - if (canadd2(expr->data.diadic.right, CInt64_Neg(value))) - return 1; - return 0; - case ETYPCON: - if (IS_TYPE_POINTER_ONLY(expr->rtype) && ENODE_IS(expr->data.monadic, EINTCONST)) { - expr->data.monadic->data.intval = CMach_CalcIntDiadic(TYPE(&stunsignedlong), expr->data.monadic->data.intval, '+', value); - return 1; - } - return 0; - default: - return 0; - } -} - -short canadd(ENode *expr, SInt32 value) { - CInt64 value64; - CInt64_SetLong(&value64, value); - return canadd2(expr, value64); -} - -static ENode *addconst(ENode *expr, SInt32 value) { - ENode *right; - - if (canadd(expr, value)) - return expr; - - if (stsignedint.size < 4 && (value > 0x7FFF || value < -0x8000)) - right = intconstnode(TYPE(&stsignedlong), value); - else - right = intconstnode(TYPE(&stsignedint), value); - - CExpr_ArithmeticConversion(&expr, &right); - expr = makediadicnode(expr, right, EADD); - return expr; -} - -static ENode *integralpointerpromote(ENode *expr) { - Boolean uns; - Type *type; - - if (!IS_TYPE_INT(expr->rtype)) - expr = forceintegral(expr); - - if (expr->rtype->size != 4) { - type = TYPE(&stunsignedlong); - if (is_unsigned(type) != (uns = is_unsigned(expr->rtype))) { - if (uns) { - if (stunsignedlong.size == 4) { - type = TYPE(&stunsignedlong); - } else if (stunsignedint.size == 4) { - type = TYPE(&stunsignedint); - } else { - CError_FATAL(480); - } - } else { - if (stsignedlong.size == 4) { - type = TYPE(&stsignedlong); - } else if (stsignedint.size == 4) { - type = TYPE(&stsignedint); - } else { - CError_FATAL(486); - } - } - } - - if (ENODE_IS(expr, EINTCONST)) - expr->data.intval = CExpr_IntConstConvert(type, expr->rtype, expr->data.intval); - else - expr = makemonadicnode(expr, ETYPCON); - - expr->rtype = type; - } - - return expr; -} - -static ENode *padd(ENode *left, ENode *right) { - Type *innertype; - SInt32 innersize; - ENode *expr; - - right = integralpointerpromote(right); - innertype = TPTR_TARGET(left->rtype); - innersize = innertype->size; - if (innersize == 0) { - CDecl_CompleteType(innertype); - innersize = innertype->size; - if (innersize == 0) { - CError_Error(CErrorStr146); - return left; - } - } - - expr = makemultnode( - right, - intconstnode((innersize > 0x7FFF) ? TYPE(&stsignedlong) : TYPE(&stsignedint), innersize)); - - if (ENODE_IS(expr, EINTCONST) && canadd2(left, expr->data.intval)) - return left; - - if (ENODE_IS(left, EADD) && ENODE_IS(left->data.diadic.right, EINTCONST)) { - left->data.diadic.left = makediadicnode(left->data.diadic.left, expr, EADD); - return left; - } - - expr = makediadicnode(left, expr, EADD); - expr->rtype = left->rtype; - expr->flags = left->flags; - return expr; -} - -static ENode *psub(ENode *left, ENode *right) { - Type *innertype; - SInt32 innersize; - ENode *expr; - - if (IS_TYPE_POINTER(right->rtype)) { - innersize = TPTR_TARGET(left->rtype)->size; - if (innersize == 0) { - CDecl_CompleteType(TPTR_TARGET(left->rtype)); - innersize = TPTR_TARGET(left->rtype)->size; - if (innersize == 0) { - CError_Error(CErrorStr146); - return left; - } - } - - if (!is_typeequal(left->rtype, right->rtype)) { - CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); - return left; - } - - if (ENODE_IS(left, ETYPCON) && ENODE_IS(left->data.monadic, EINTCONST) && ENODE_IS(right, ETYPCON) && ENODE_IS(right->data.monadic, EINTCONST)) { - left->data.monadic->rtype = right->data.monadic->rtype = CABI_GetPtrDiffTType(); - expr = makesubnode(left->data.monadic, right->data.monadic); - if (innersize > 1) - expr = makedivnode(expr, intconstnode(CABI_GetPtrDiffTType(), innersize), 11); - return expr; - } - - expr = makediadicnode(left, right, ESUB); - expr->rtype = CABI_GetPtrDiffTType(); - if (innersize > 1) - expr = makediadicnode(expr, intconstnode(CABI_GetPtrDiffTType(), innersize), EDIV); - return expr; - } - - right = integralpointerpromote(right); - innertype = TPTR_TARGET(left->rtype); - innersize = innertype->size; - if (innersize == 0) { - CDecl_CompleteType(innertype); - innersize = innertype->size; - if (innersize == 0) { - CError_Error(CErrorStr146); - return left; - } - } - - expr = makemultnode(right, intconstnode(CABI_GetPtrDiffTType(), innersize)); - if (ENODE_IS(expr, EINTCONST) && canadd2(left, CInt64_Neg(expr->data.intval))) - return left; - - expr = makediadicnode(left, expr, ESUB); - expr->rtype = left->rtype; - expr->flags = left->flags; - return expr; -} - -static ENode *makeaddnode(ENode *left, ENode *right) { - if (IS_TYPE_POINTER(left->rtype)) - return padd(left, right); - if (IS_TYPE_POINTER(right->rtype)) - return padd(right, left); - - CExpr_ArithmeticConversion(&left, &right); - if (iszero(right)) - return left; - if (iszero(left)) - return right; - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '+', right->data.intval); - return left; - } - if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - left->data.floatval = CMach_CalcFloatDiadic(left->rtype, left->data.floatval, '+', right->data.floatval); - return left; - } - - if (ENODE_IS(left, EINTCONST) && canadd2(right, left->data.intval)) - return right; - if (ENODE_IS(right, EINTCONST) && canadd2(left, right->data.intval)) - return left; - - left = makediadicnode(left, right, EADD); - optimizecomm(left); - if (IS_TYPE_FLOAT(left->rtype)) - left = CExpr_BinaryFloatExpression(left); - return left; -} - -static ENode *makesubnode(ENode *left, ENode *right) { - if (ENODE_IS(right, EINTCONST) && !is_unsigned(right->rtype) && !IS_TYPE_FLOAT(left->rtype)) { - right->data.intval = CInt64_Neg(right->data.intval); - return makeaddnode(left, right); - } - - if (IS_TYPE_POINTER(left->rtype)) - return psub(left, right); - - CExpr_ArithmeticConversion(&left, &right); - if (iszero(right)) - return left; - if (iszero(left)) { - if (ENODE_IS(right, EINTCONST)) { - right->data.intval = CInt64_Neg(right->data.intval); - return right; - } - if (ENODE_IS(right, EFLOATCONST)) { - right->data.floatval = CMach_CalcFloatMonadic(right->rtype, '-', right->data.floatval); - return right; - } - return CExpr_UnaryFloatExpression(makemonadicnode(right, EMONMIN)); - } - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '-', right->data.intval); - return left; - } - if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - left->data.floatval = CMach_CalcFloatDiadic(left->rtype, left->data.floatval, '-', right->data.floatval); - return left; - } - - if (ENODE_IS(right, EINTCONST) && canadd2(left, CInt64_Neg(right->data.intval))) - return left; - - left = makediadicnode(left, right, ESUB); - if (IS_TYPE_FLOAT(left->rtype)) - left = CExpr_BinaryFloatExpression(left); - return left; -} - -ENode *checkreference(ENode *expr) { - if (!IS_TYPE_REFERENCE(expr->rtype)) - return expr; - - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = TPTR_TARGET(expr->rtype); - return expr; -} - -static ENode *pointer_generation2(ENode *expr) { - switch (expr->type) { - case EINDIRECT: - switch (expr->rtype->type) { - case TYPEARRAY: - switch (expr->data.monadic->type) { - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - expr->type = ETYPCON; - expr->rtype = CDecl_NewPointerType(TPTR_TARGET(expr->rtype)); - return expr; - default: - expr->data.monadic->rtype = CDecl_NewPointerType(TPTR_TARGET(expr->rtype)); - expr->data.monadic->flags = expr->flags; - return expr->data.monadic; - } - case TYPEFUNC: - expr = expr->data.monadic; - if (ENODE_IS(expr, EOBJREF) && expr->data.objref->datatype == DINLINEFUNC) - CError_Error(CErrorStr175); - return expr; - } - } - return expr; -} - -ENode *pointer_generation(ENode *expr) { - return CExpr_RewriteConst(pointer_generation2(expr)); -} - -ENode *CExpr_PointerGeneration(ENode *expr) { - switch (expr->type) { - case EINDIRECT: - switch (expr->rtype->type) { - case TYPEARRAY: - expr->data.monadic->rtype = CDecl_NewPointerType(TPTR_TARGET(expr->rtype)); - return expr->data.monadic; - case TYPEFUNC: - return expr->data.monadic; - } - } - return expr; -} - -static void CExpr_ConstPointerCheck(ENode *expr, Type *type, short qual) { - Type *exprtype; - Type *b; - Type *a; - short exprqual; - - exprtype = expr->rtype; - if (IS_TYPE_POINTER_ONLY(type) && IS_TYPE_POINTER_ONLY(exprtype)) { - exprqual = expr->flags; - - if (TPTR_TARGET(type) == &stvoid) { - exprqual = CParser_GetCVTypeQualifiers(TPTR_TARGET(exprtype), exprqual); - } else { - a = TPTR_TARGET(type); - b = TPTR_TARGET(exprtype); - while (IS_TYPE_POINTER_ONLY(a) && IS_TYPE_POINTER_ONLY(b)) { - if (CParser_IsMoreCVQualified(TPTR_QUAL(b), TPTR_QUAL(a))) { - CError_Warning(CErrorStr220, expr->rtype, ENODE_QUALS(expr), type, qual); - return; - } - a = TPTR_TARGET(a); - b = TPTR_TARGET(b); - } - } - - if (CParser_IsMoreCVQualified(exprqual, qual)) { - CError_Warning(CErrorStr220, expr->rtype, ENODE_QUALS(expr), type, (UInt32) qual); - } - } -} - -ENode *oldassignmentpromotion(ENode *expr, Type *type, short qual, Boolean flag) { - Boolean is_ref; - UInt32 ref_qual; - short orig_qual; - - is_ref = 0; - if (!IS_TYPE_MEMBERPOINTER(type)) { - if (IS_TYPE_REFERENCE(type)) { - if (ENODE_IS(expr, ECOND)) - expr = CExpr_LValue(expr, 0, 0); - expr = pointer_generation2(expr); - ref_qual = CParser_GetCVTypeQualifiers(expr->rtype, expr->flags); - is_ref = 1; - } else { - expr = pointer_generation(expr); - } - } - - if (ENODE_IS(expr, EMEMBER)) - expr = getpointertomemberfunc(expr, type, 1); - - if (!is_ref) - CExpr_ConstPointerCheck(expr, type, qual); - else - CExpr_ConstPointerCheck(expr, TPTR_TARGET(type), qual); - - if (!(assign_check(expr, type, orig_qual = qual, 1, 0, flag))) - return expr; - - if (is_ref) { - if (temp_reference_init) { - switch (TPTR_TARGET(type)->type) { - case TYPEPOINTER: - qual = TPTR_QUAL(TPTR_TARGET(type)); - } - if (!(qual & Q_CONST)) - CError_Warning(CErrorStr228); - } else { - if (ref_qual && ref_qual > CParser_GetCVTypeQualifiers(TPTR_TARGET(type), orig_qual)) - CError_Warning(CErrorStr259); - } - } - - return assign_node; -} - -ENode *argumentpromotion(ENode *expr, Type *type, short qual, Boolean flag) { - ENode *tmp; - ENodeList *list; - - if (IS_TYPE_CLASS(type) && CClass_ReferenceArgument(TYPE_CLASS(type))) { - if ((tmp = CExpr_IsTempConstruction(expr, type, NULL))) - return tmp; - - list = lalloc(sizeof(ENodeList)); - list->next = NULL; - list->node = expr; - tmp = CExpr_ConstructObject( - TYPE_CLASS(type), - create_temp_node(type), - list, 1, 1, 1, 1, 0); - return getnodeaddress(tmp, 0); - } - - return CExpr_AssignmentPromotion(expr, type, qual, flag); -} - -ENode *classargument(ENode *expr) { - ENodeList *list; - - if (CClass_CopyConstructor(TYPE_CLASS(expr->rtype))) { - list = lalloc(sizeof(ENodeList)); - list->next = NULL; - list->node = expr; - return CExpr_ConstructObject( - TYPE_CLASS(expr->rtype), - create_temp_node(expr->rtype), - list, 1, 1, 1, 1, 0); - } - - return expr; -} - -ENodeList *CExpr_ScanExpressionList(Boolean is_parens) { - ENodeList *list; - ENodeList *current; - - if (is_parens && tk == ')') - return NULL; - - list = current = lalloc(sizeof(ENodeList)); - - while (1) { - current->next = NULL; - current->node = assignment_expression(); - if (copts.old_argmatch && !ENODE_IS(current->node, EMEMBER)) - current->node = pointer_generation(current->node); - - if (is_parens) { - if (tk == ')') - break; - } else { - if (tk == ']') - break; - } - - if (tk != ',') { - CError_ErrorSkip(CErrorStr116); - break; - } - - tk = lex(); - current->next = lalloc(sizeof(ENodeList)); - current = current->next; - } - - return list; -} - -static ENode *skipcommaexpr(ENode *expr) { - while (ENODE_IS(expr, ECOMMA)) - expr = expr->data.diadic.right; - return expr; -} - -ENode *CExpr_DoExplicitConversion(Type *type, UInt32 qual, ENodeList *list) { - Object *obj; - ENode *tmp; - - if (!IS_TYPE_CLASS(type)) { - if (!list) - return do_typecast(nullnode(), type, qual); - if (list->next) - CError_Error(CErrorStr356); - return do_typecast(pointer_generation(list->node), type, qual); - } - - CDecl_CompleteType(type); - if (!(TYPE_CLASS(type)->flags & CLASS_COMPLETED)) - CError_Error(CErrorStr136, type, 0); - - CanCreateObject(type); - if (!list && CClass_IsPODClass(TYPE_CLASS(type))) { - obj = CParser_NewGlobalDataObject(NULL); - obj->name = CParser_GetUniqueName(); - obj->nspace = cscope_root; - obj->type = type; - obj->qual = qual; - obj->sclass = TK_STATIC; - CInit_DeclareData(obj, NULL, NULL, type->size); - - tmp = makemonadicnode(create_temp_node(type), EINDIRECT); - tmp->rtype = type; - tmp->flags = qual & ENODE_FLAG_QUALS; - return makediadicnode(tmp, create_objectnode(obj), EASS); - } - - return CExpr_ConstructObject(TYPE_CLASS(type), create_temp_node(type), list, 1, 1, 1, 1, 1); -} - -static ENode *CExpr_TemplArgDepCast(Type *type, UInt32 qual, ENodeList *args) { - ENode *expr = CExpr_NewTemplDepENode(TDE_CAST); - expr->data.templdep.u.cast.args = args; - expr->data.templdep.u.cast.type = type; - expr->data.templdep.u.cast.qual = qual; - return expr; -} - -static ENode *CExpr_ParseExplicitConversion(Type *type, UInt32 qual) { - ENodeList *args; - ENodeList *scan; - - if (IS_TEMPL_CLASS(type) && !CParser_CheckTemplateClassUsage(TEMPL_CLASS(type), 1)) - type = TYPE(&stsignedint); - - if (tk == '(') - tk = lex(); - else - CError_Error(CErrorStr114); - - args = CExpr_ScanExpressionList(1); - if (tk != ')') { - CError_Error(CErrorStr115); - return nullnode(); - } - - tk = lex(); - if (CTemplTool_IsTemplateArgumentDependentType(type)) - return CExpr_TemplArgDepCast(type, qual, args); - - for (scan = args; scan; scan = scan->next) { - if (CTemplTool_IsTemplateArgumentDependentExpression(scan->node)) - return CExpr_TemplArgDepCast(type, qual, args); - } - - return CExpr_DoExplicitConversion(type, qual, args); -} - -static ENode *CExpr_MemberVarAccess(BClassList *path, ObjMemberVar *var, ENode *expr) { - ENode *accessnode; - BClassList *varpath; - - CError_ASSERT(1152, path); - - if (TYPE_CLASS(path->type)->sominfo) - return CSOM_MemberVarAccess(path, var, expr); - - varpath = NULL; - if (var->has_path) - varpath = OBJ_MEMBER_VAR_PATH(var)->path; - accessnode = CExpr_GetClassAccessNode(path, varpath, expr, NULL, var->access, 1); - if (!accessnode) - return nullnode(); - - return CClass_AccessMember(accessnode, var->type, var->qual, var->offset); -} - -static Boolean CExpr_IsTemplateFunc(Object *obj) { - return IS_TEMPL_FUNC(obj->type); -} - -static ENode *CExpr_ExplicitTemplateArgCheck(NameResult *pr) { - NameSpaceObjectList *list; - NameSpaceObjectList *newhead; - NameSpaceObjectList *newlist; - ENode *expr; - - if (pr->obj_10) { - if (pr->obj_10->otype != OT_OBJECT || !CExpr_IsTemplateFunc(OBJECT(pr->obj_10))) - return NULL; - - list = lalloc(sizeof(NameSpaceObjectList)); - memclrw(list, sizeof(NameSpaceObjectList)); - list->object = pr->obj_10; - } else if (pr->nsol_14) { - for (list = pr->nsol_14; list; list = list->next) { - if (list->object->otype == OT_OBJECT && CExpr_IsTemplateFunc(OBJECT(list->object))) { - newhead = newlist = galloc(sizeof(NameSpaceObjectList)); - *newlist = *list; - newlist->next = NULL; - while ((list = list->next)) { - if (list->object->otype == OT_OBJECT && CExpr_IsTemplateFunc(OBJECT(list->object))) { - newlist->next = galloc(sizeof(NameSpaceObjectList)); - newlist = newlist->next; - *newlist = *list; - newlist->next = NULL; - } - } - list = newhead; - break; - } - } - if (!list) - return NULL; - } else { - return NULL; - } - - expr = CExpr_NewENode(EOBJLIST); - expr->rtype = OBJECT(list->object)->type; - expr->data.objlist.list = list; - expr->data.objlist.templargs = CTempl_ParseUncheckTemplArgs(NULL, 0); - - tk = lex(); - return expr; -} - -ENode *CExpr_MakeNameLookupResultExpr(NameResult *pr) { - ENode *expr; - - if (pr->obj_10) { - switch (pr->obj_10->otype) { - case OT_OBJECT: - CClass_CheckObjectAccess(pr->bcl_18, OBJECT(pr->obj_10)); - return create_objectnode(OBJECT(pr->obj_10)); - case OT_ENUMCONST: - CClass_CheckEnumAccess(pr->bcl_18, OBJ_ENUM_CONST(pr->obj_10)); - expr = lalloc(sizeof(ENode)); - expr->type = EINTCONST; - expr->cost = 0; - expr->flags = 0; - expr->rtype = OBJ_ENUM_CONST(pr->obj_10)->type; - expr->data.intval = OBJ_ENUM_CONST(pr->obj_10)->val; - return expr; - case OT_MEMBERVAR: - CError_Error(CErrorStr221); - return nullnode(); - default: - CError_FATAL(1268); - } - } - - if (pr->nsol_14) { - expr = CExpr_NewENode(EOBJLIST); - expr->rtype = OBJECT(pr->nsol_14->object)->type; - expr->data.objlist.list = pr->nsol_14; - return expr; - } - - CError_FATAL(1278); - return NULL; -} - -static Type *CExpr_NewPTMType(EMemberInfo *member, Object *obj) { - TypeMemberPointer *ptm; - TypeMemberFunc *tmethod; - BClassList *path; - - ptm = galloc(sizeof(TypeMemberPointer)); - memclrw(ptm, sizeof(TypeMemberPointer)); - ptm->type = TYPEMEMBERPOINTER; - - if (member->list->object->otype == OT_MEMBERVAR) { - path = member->path; - while (path->next) - path = path->next; - ptm->size = 4; - ptm->ty2 = path->type; - ptm->ty1 = OBJ_MEMBER_VAR(member->list->object)->type; - } else { - if (!obj) { - CError_ASSERT(1306, member->list->object->otype == OT_OBJECT); - obj = OBJECT(member->list->object); - CError_ASSERT(1308, IS_TYPE_FUNC(obj->type)); - } - - tmethod = galloc(sizeof(TypeMemberFunc)); - memclrw(tmethod, sizeof(TypeMemberFunc)); - *tmethod = *TYPE_METHOD(obj->type); - - CError_ASSERT(1312, tmethod->args); - - tmethod->args = tmethod->args->next; - CDecl_MakePTMFuncType(TYPE_FUNC(tmethod)); - tmethod->flags &= ~FUNC_DEFINED; - - ptm->size = 12; - ptm->ty2 = TYPE(tmethod->theclass); - ptm->ty1 = TYPE(tmethod); - } - - return TYPE(ptm); -} - -static ENode *CExpr_ParseNameResultExpr(NameResult *pr, ENode *expr, Boolean flag1, Boolean flag2) { - ENode *result; - ENode *ta_expr; - ObjEnumConst *oec; - TemplateAction *act; - EMemberInfo *member; - NameSpaceObjectList *list; - Object *obj; - TypeFunc *tfunc; - SInt32 val; - - if (pr->type) { - if (copts.cplusplus) { - if (IS_TYPE_TEMPLATE(pr->type)) { - if (TYPE_TEMPLATE(pr->type)->dtype == TEMPLDEP_ARGUMENT && TYPE_TEMPLATE(pr->type)->u.pid.type == TPT_NONTYPE) { - result = CExpr_NewTemplDepENode(TDE_PARAM); - result->data.templdep.u.pid = TYPE_TEMPLATE(pr->type)->u.pid; - tk = lex(); - return result; - } - if (TYPE_TEMPLATE(pr->type)->dtype == TEMPLDEP_QUALNAME && !pr->x20) { - result = CExpr_NewTemplDepENode(TDE_QUALNAME); - result->data.templdep.u.qual.type = TYPE_TEMPLATE(pr->type)->u.qual.type; - result->data.templdep.u.qual.name = TYPE_TEMPLATE(pr->type)->u.qual.name; - tk = lex(); - return result; - } - } - tk = lex(); - return CExpr_ParseExplicitConversion(pr->type, pr->qual); - } - CError_ErrorSkip(CErrorStr141); - tk = lex(); - return nullnode(); - } - - if (pr->obj_10) { - switch (pr->obj_10->otype) { - case OT_OBJECT: - if (OBJECT(pr->obj_10)->nspace && OBJECT(pr->obj_10)->nspace->theclass && (OBJECT(pr->obj_10)->nspace->theclass->flags & CLASS_IS_TEMPL)) { - result = CExpr_NewTemplDepENode(TDE_OBJ); - result->data.templdep.u.obj = OBJECT(pr->obj_10); - tk = lex(); - return result; - } - if (!expr || !IS_TEMPL_FUNC(OBJECT(pr->obj_10)->type)) { - if (!IS_TYPE_NONSTATIC_METHOD(OBJECT(pr->obj_10)->type)) { - tk = lex(); - if (tk == '<' && (ta_expr = CExpr_ExplicitTemplateArgCheck(pr))) - return ta_expr; - if (OBJECT(pr->obj_10)->datatype == DLOCAL && OBJECT(pr->obj_10)->u.var.info->func != cscope_currentfunc) { - CError_Error(CErrorStr330); - return nullnode(); - } - if (OBJECT(pr->obj_10)->datatype == DEXPR) { - result = CInline_CopyExpression(OBJECT(pr->obj_10)->u.expr, CopyMode0); - if (IS_TYPE_POINTER_ONLY(result->rtype) && ENODE_IS(result, EINTCONST)) { - result = makemonadicnode(result, ETYPCON); - result->data.monadic->rtype = TYPE(&stunsignedlong); - } - return result; - } - CClass_CheckObjectAccess(pr->bcl_18, OBJECT(pr->obj_10)); - if (tk == '(' && flag2 && OBJECT(pr->obj_10)->datatype == DFUNC && copts.cplusplus && !pr->x1D && !IS_TYPEFUNC_METHOD(TYPE_FUNC(OBJECT(pr->obj_10)->type))) { - result = CExpr_NewENode(EOBJLIST); - result->rtype = OBJECT(pr->obj_10)->type; - result->data.objlist.list = galloc(sizeof(NameSpaceObjectList)); - result->data.objlist.list->next = pr->nsol_14; - result->data.objlist.list->object = pr->obj_10; - result->data.objlist.name = OBJECT(pr->obj_10)->name; - return result; - } - - result = create_objectnode(OBJECT(pr->obj_10)); - if (expr) { - while (ENODE_IS(expr, EINDIRECT)) - expr = expr->data.monadic; - switch (expr->type) { - case EINTCONST: - case EOBJREF: - case EOBJLIST: - break; - default: - result = makecommaexpression(expr, result); - } - } - return result; - } - if (CClass_IsDestructor(OBJECT(pr->obj_10))) { - if ((tk = lex()) != '(') { - CError_Error(CErrorStr114); - return nullnode(); - } - if ((tk = lex()) != ')') { - CError_Error(CErrorStr115); - return nullnode(); - } - if (!expr && (!cscope_currentfunc || !cscope_currentclass || !cscope_is_member_func)) { - CError_Error(CErrorStr221); - return nullnode(); - } - if (pr->isambig) - CError_Error(CErrorStr188); - - if ((expr = CExpr_GetClassAccessNode(pr->bcl_18, NULL, expr, OBJECT(pr->obj_10), pr->obj_10->access, 1))) { - tk = lex(); - return CABI_DestroyObject(OBJECT(pr->obj_10), expr->data.monadic, 1, pr->x1D, 0); - } - } - } - break; - case OT_ENUMCONST: - CClass_CheckEnumAccess(pr->bcl_18, OBJ_ENUM_CONST(pr->obj_10)); - oec = OBJ_ENUM_CONST(pr->obj_10); - if (CInt64_IsZero(&oec->val) && IS_TYPE_ENUM(oec->type) && TYPE_ENUM(oec->type)->nspace && TYPE_ENUM(oec->type)->nspace->theclass && (TYPE_ENUM(oec->type)->nspace->theclass->flags & CLASS_IS_TEMPL)) { - val = 0; - expr = NULL; - for (act = TEMPL_CLASS(TYPE_ENUM(oec->type)->nspace->theclass)->actions; act; act = act->next) { - if (act->type == TAT_ENUMERATOR) { - if (act->u.enumerator.initexpr) { - expr = act->u.enumerator.initexpr; - val = 0; - } else { - val++; - } - if (act->u.enumerator.objenumconst == oec) { - CError_ASSERT(1521, expr); - expr = CInline_CopyExpression(expr, CopyMode0); - if (val) - expr = makediadicnode(expr, intconstnode(TYPE(&stsignedlong), val), EADD); - tk = lex(); - return expr; - } - } - } - } - result = lalloc(sizeof(ENode)); - result->type = EINTCONST; - result->cost = 0; - result->flags = 0; - result->rtype = OBJ_ENUM_CONST(pr->obj_10)->type; - result->data.intval = OBJ_ENUM_CONST(pr->obj_10)->val; - tk = lex(); - return result; - case OT_MEMBERVAR: - if (!flag1 || expr || !pr->x1D) { - if (pr->isambig) - CError_Error(CErrorStr188); - result = checkreference(CExpr_MemberVarAccess(pr->bcl_18, OBJ_MEMBER_VAR(pr->obj_10), expr)); - tk = lex(); - return result; - } - break; - default: - CError_FATAL(1552); - } - - member = lalloc(sizeof(EMemberInfo)); - memclrw(member, sizeof(EMemberInfo)); - member->path = pr->bcl_18; - member->expr = expr; - member->pr_1D = pr->x1D; - member->isambig = pr->isambig; - if ((tk = lex()) == '<' && (ta_expr = CExpr_ExplicitTemplateArgCheck(pr))) { - CError_ASSERT(1564, ENODE_IS(ta_expr, EOBJLIST)); - member->list = ta_expr->data.objlist.list; - member->templargs = ta_expr->data.objlist.templargs; - } else { - member->list = galloc(sizeof(NameSpaceObjectList)); - member->list->next = NULL; - member->list->object = pr->obj_10; - } - - result = CExpr_NewENode(EMEMBER); - result->data.emember = member; - result->rtype = &stvoid; - return result; - } - - if (pr->nsol_14) { - if ((tk = lex()) == '<' && (ta_expr = CExpr_ExplicitTemplateArgCheck(pr))) { - CError_ASSERT(1591, ENODE_IS(ta_expr, EOBJLIST)); - for (list = ta_expr->data.objlist.list; list; list = list->next) { - if (list->object->otype == OT_OBJECT && IS_TYPE_NONSTATIC_METHOD(OBJECT(list->object)->type)) { - member = lalloc(sizeof(EMemberInfo)); - memclrw(member, sizeof(EMemberInfo)); - - member->path = pr->bcl_18; - member->expr = expr; - member->list = ta_expr->data.objlist.list; - member->templargs = ta_expr->data.objlist.templargs; - member->pr_1D = pr->x1D; - member->isambig = pr->isambig; - - result = CExpr_NewENode(EMEMBER); - result->data.emember = member; - result->rtype = &stvoid; - return result; - } - } - return ta_expr; - } - - for (list = pr->nsol_14; list; list = list->next) { - if (list->object->otype == OT_OBJECT && IS_TYPE_NONSTATIC_METHOD(OBJECT(list->object)->type)) { - member = lalloc(sizeof(EMemberInfo)); - memclrw(member, sizeof(EMemberInfo)); - - member->path = pr->bcl_18; - member->expr = expr; - member->list = pr->nsol_14; - member->pr_1D = pr->x1D; - member->isambig = pr->isambig; - - result = CExpr_NewENode(EMEMBER); - result->data.emember = member; - result->rtype = &stvoid; - return result; - } - } - - if (tk == '<' && (ta_expr = CExpr_ExplicitTemplateArgCheck(pr))) - return ta_expr; - - result = CExpr_NewENode(EOBJLIST); - result->rtype = OBJECT(pr->nsol_14->object)->type; - result->data.objlist.list = pr->nsol_14; - if (tk == '(' && copts.cplusplus && flag2 && !pr->x1D && pr->nsol_14->object->otype == OT_OBJECT) - result->data.objlist.name = OBJECT(pr->nsol_14->object)->name; - return result; - } - - if (pr->name_4) { - if (copts.cplusplus && flag2) { - if (lookahead() == '(') { - result = CExpr_NewENode(EOBJLIST); - result->rtype = &stvoid; - result->data.objlist.name = pr->name_4; - tk = lex(); - return result; - } - CError_Error(CErrorStr140, pr->name_4->name); - tk = lex(); - return nullnode(); - } - - if (lookahead() != '(') { - CError_Error(CErrorStr140, pr->name_4->name); - tk = lex(); - return nullnode(); - } - - if (copts.checkprotos) - CError_Error(CErrorStr178); - - tfunc = galloc(sizeof(TypeFunc)); - memclrw(tfunc, sizeof(TypeFunc)); - tfunc->type = TYPEFUNC; - tfunc->functype = TYPE(&stsignedint); - tfunc->args = &oldstyle; - CDecl_SetFuncFlags(tfunc, 0); - - obj = CParser_NewFunctionObject(NULL); - obj->name = pr->name_4; - obj->sclass = TK_EXTERN; - obj->nspace = cscope_root; - obj->type = TYPE(tfunc); - - CScope_AddGlobalObject(obj); - tk = lex(); - return create_objectrefnode(obj); - } - - CError_FATAL(1711); - return NULL; -} - -static ENode *CExpr_ParseRotate(Boolean is_right) { - ENode *expr1; - ENode *expr2; - - if (lex() != '(') { - CError_Error(CErrorStr114); - return nullnode(); - } - - tk = lex(); - expr1 = assignment_expression(); - - if (tk != ',') { - CError_Error(CErrorStr116); - return nullnode(); - } - - tk = lex(); - expr2 = assignment_expression(); - - if (tk != ')') { - CError_Error(CErrorStr115); - return nullnode(); - } - - if (!IS_TYPE_INT(expr1->rtype)) - expr1 = forceintegral(expr1); - expr2 = integralpromote(expr2); - - tk = lex(); - if (iszero(expr1) || iszero(expr2)) - return expr1; - - return makediadicnode(expr1, expr2, is_right ? EROTR : EROTL); -} - -static ENode *CExpr_ParseNextArg(void) { - NameSpaceObjectList *list; - NameResult pr; - ENode *expr; - SInt32 rounded_size; - - if ((tk = lex()) != '(') { - CError_Error(CErrorStr114); - return nullnode(); - } - if ((tk = lex()) != TK_IDENTIFIER) { - CError_Error(CErrorStr107); - return nullnode(); - } - - list = CScope_FindObjectList(&pr, tkidentifier); - if (!list) { - CError_Error(CErrorStr140, tkidentifier->name); - return nullnode(); - } - - if (list->object->otype != OT_OBJECT || OBJECT(list->object)->datatype != DLOCAL) { - CError_Error(CErrorStr140, tkidentifier->name); - return nullnode(); - } - - rounded_size = CMach_RoundedSizeOf(OBJECT(list->object)); - expr = CExpr_MakeObjRefNode(OBJECT(list->object), 1); - expr = makediadicnode(expr, intconstnode(CABI_GetPtrDiffTType(), rounded_size), EADD); - expr->rtype = TYPE(&void_ptr); - - if ((tk = lex()) != ')') { - CError_Error(CErrorStr115); - return expr; - } else { - tk = lex(); - return expr; - } -} - -static ENode *CExpr_ParseVecStep(void) { - ENode *expr; - Type *type; - SInt32 value; - DeclInfo di; - - expr = intconstnode(TYPE(&stsignedint), 0); - if ((tk = lex()) == '(') { - if (tk == '(' && islookaheaddeclaration()) { - tk = lex(); - memclrw(&di, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&di, 0); - scandeclarator(&di); - if (di.name) - CError_Error(CErrorStr121); - - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - - type = di.thetype; - if (IS_TYPE_REFERENCE(type)) - type = TPTR_TARGET(type); - } else { - expr = unary_expression(); - if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EBITFIELD)) - CError_Error(CErrorStr144); - type = expr->rtype; - } - - CDecl_CompleteType(type); - if (IS_TYPE_VECTOR(type)) { - switch (TYPE_STRUCT(type)->stype) { - case STRUCT_VECTOR_UCHAR: - case STRUCT_VECTOR_SCHAR: - case STRUCT_VECTOR_BCHAR: - value = 16; - break; - case STRUCT_VECTOR_USHORT: - case STRUCT_VECTOR_SSHORT: - case STRUCT_VECTOR_BSHORT: - case STRUCT_VECTOR_PIXEL: - value = 8; - break; - default: - value = 4; - } - expr = intconstnode(TYPE(&stsignedint), value); - } else { - PPCError_Error(PPCErrorStr104, "vec_step", "vec_step", type, 0); - } - } else { - CError_Error(CErrorStr114); - } - - return expr; -} - -static SInt32 CExpr_BuiltInComputeAlign(Type *type) { - return CMach_GetTypeAlign(type); -} - -static SInt32 CExpr_AtomTypeID(IntegralType what) { - switch (what) { - case IT_BOOL: return 1; - case IT_CHAR: return 2; - case IT_SCHAR: return 3; - case IT_UCHAR: return 4; - case IT_WCHAR_T: return 5; - case IT_SHORT: return 6; - case IT_USHORT: return 7; - case IT_INT: return 8; - case IT_UINT: return 9; - case IT_LONG: return 10; - case IT_ULONG: return 10; - case IT_LONGLONG: return 12; - case IT_ULONGLONG: return 13; - case IT_FLOAT: return 14; - case IT_SHORTDOUBLE: return 15; - case IT_DOUBLE: return 16; - case IT_LONGDOUBLE: return 17; - case IT_17: return 32; - case IT_18: return 33; - case IT_19: return 34; - case IT_20: return 35; - case IT_21: return 36; - case IT_22: return 37; - case IT_23: return 38; - case IT_24: return 39; - default: - CError_FATAL(1976); - return 0; - } -} - -static SInt32 CExpr_BuiltInComputeType(Type *type) { - switch (type->type) { - case TYPEINT: - return 0x100 | CExpr_AtomTypeID(TYPE_INTEGRAL(type)->integral); - case TYPEFLOAT: - return 0x200 | CExpr_AtomTypeID(TYPE_INTEGRAL(type)->integral); - case TYPEENUM: - return 0x400 | (CExpr_BuiltInComputeType(TYPE_ENUM(type)->enumtype) & 0xFF); - case TYPEPOINTER: - return 0x800; - case TYPEARRAY: - return 0x1000; - case TYPESTRUCT: - return 0x2000; - case TYPECLASS: - return 0x2000; - case TYPEMEMBERPOINTER: - return 0x4000; - case TYPEFUNC: - return 0x8000; - default: - CError_Error(CErrorStr146); - case TYPEVOID: - return 0; - } -} - -static SInt32 CExpr_BuiltInClassifyType(Type *type) { - switch (type->type) { - case TYPEVOID: return 0; - case TYPEFUNC: return 10; - case TYPEENUM: return 3; - case TYPEINT: return 1; - case TYPEFLOAT: return 8; - case TYPEPOINTER: case TYPEMEMBERPOINTER: return 5; - case TYPEARRAY: return 14; - case TYPESTRUCT: return 12; - case TYPECLASS: return 12; - case TYPEBITFIELD: return -1; - case TYPETEMPLATE: return -1; - default: return -1; - } -} - -static SInt32 CExpr_BuiltInComputeVArgType(Type *type) { - switch (type->type) { - case TYPEINT: - case TYPEENUM: - return 0; - case TYPEFLOAT: - return 1; - default: - return 2; - } -} - -static Type *CExpr_ParseTypeExpression(Boolean *outflag) { - ENode *expr; - Type *type; - DeclInfo di; - - tk = lex(); - if (tk == '(' && islookaheaddeclaration()) { - tk = lex(); - memclrw(&di, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&di, 0); - scandeclarator(&di); - if (di.name) - CError_Error(CErrorStr121); - - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - - type = di.thetype; - if (IS_TYPE_REFERENCE(type)) - type = TPTR_TARGET(type); - } else { - expr = unary_expression(); - if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EBITFIELD)) - CError_Error(CErrorStr144); - - if (outflag) - *outflag = ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval); - - type = expr->rtype; - } - - CDecl_CompleteType(type); - return type; -} - -static ENode *CExpr_ParseBuiltin(SInt32 (*parser)(Type *)) { - ENode *expr; - expr = intconstnode(TYPE(&stsignedint), 0); - CInt64_SetLong(&expr->data.intval, parser(CExpr_ParseTypeExpression(NULL))); - return expr; -} - -static ENode *CExpr_ParseBuiltin_isintconst(void) { - ENode *expr; - expr = intconstnode(TYPE(&stsignedint), 0); - - tk = lex(); - if (tk != '(') - CError_ErrorSkip(CErrorStr121); - else - tk = lex(); - - if (ENODE_IS(expression(), EINTCONST)) - CInt64_SetLong(&expr->data.intval, 1); - - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - - return expr; -} - -static ENode *primary_expression(Boolean flag) { - NameResult pr; - ENode *expr; - - switch (tk) { - case TK_TRUE: - expr = lalloc(sizeof(ENode)); - expr->type = EINTCONST; - expr->cost = 0; - expr->flags = 0; - expr->rtype = TYPE(&stbool); - CInt64_SetULong(&expr->data.intval, 1); - tk = lex(); - return expr; - case TK_FALSE: - expr = lalloc(sizeof(ENode)); - expr->type = EINTCONST; - expr->cost = 0; - expr->flags = 0; - expr->rtype = TYPE(&stbool); - CInt64_SetULong(&expr->data.intval, 0); - tk = lex(); - return expr; - case TK_INTCONST: - expr = lalloc(sizeof(ENode)); - expr->type = EINTCONST; - expr->cost = 0; - expr->flags = 0; - expr->rtype = atomtype(); - expr->data.intval = tkintconst; - tk = lex(); - return expr; - case TK_FLOATCONST: - expr = lalloc(sizeof(ENode)); - expr->type = EFLOATCONST; - expr->cost = 0; - expr->flags = 0; - expr->rtype = atomtype(); - expr->data.floatval = tkfloatconst; - tk = lex(); - return expr; - case TK_STRING: - expr = CExpr_NewENode(ESTRINGCONST); - expr->rtype = CDecl_NewArrayType(ispascalstring ? TYPE(&stunsignedchar) : TYPE(&stchar), tksize); - expr->data.string.size = tksize; - expr->data.string.data = tkstring; - expr->data.string.ispascal = ispascalstring; - if (copts.const_strings) - expr->flags = ENODE_FLAG_CONST; - expr = makemonadicnode(expr, EINDIRECT); - expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); - tk = lex(); - return expr; - case TK_STRING_WIDE: - expr = CExpr_NewENode(ESTRINGCONST); - expr->rtype = CDecl_NewArrayType(CParser_GetWCharType(), tksize); - expr->data.string.size = tksize; - expr->data.string.data = tkstring; - expr->data.string.ispascal = ispascalstring; - if (copts.const_strings) - expr->flags = ENODE_FLAG_CONST; - expr = makemonadicnode(expr, EINDIRECT); - expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); - tk = lex(); - return expr; - case TK_THIS: - case TK_SELF: - expr = CClass_CreateThisSelfExpr(); - if (!expr) - expr = nullnode(); - tk = lex(); - return expr; - case TK_AT_SELECTOR: - return CObjC_ParseSelectorExpression(); - case TK_AT_ENCODE: - return CObjC_ParseEncodeExpression(); - case TK_AT_PROTOCOL: - return CObjC_ParseProtocolExpression(); - case '@': - if (copts.objective_c) - return CObjC_ParseAtExpression(); - break; - case '(': - tk = lex(); - expr = s_expression(); - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - if (ENODE_IS(expr, EASS)) - expr->flags = expr->flags | ENODE_FLAG_80; - return expr; - case '[': - if (copts.objective_c) - return CObjC_ParseMessageExpression(); - break; - case TK_IDENTIFIER: - if (tkidentifier->name[0] == '_' && tkidentifier->name[1] == '_') { - if (!strcmp(tkidentifier->name, "__builtin_align")) - return CExpr_ParseBuiltin(CExpr_BuiltInComputeAlign); - if (!strcmp(tkidentifier->name, "__builtin_ntype")) - return CExpr_ParseBuiltin(CExpr_BuiltInComputeType); - if (!strcmp(tkidentifier->name, "__builtin_type") || !strcmp(tkidentifier->name, "__builtin_vargtype")) - return CExpr_ParseBuiltin(CExpr_BuiltInComputeVArgType); - if (!strcmp(tkidentifier->name, "__builtin_classify_type")) - return CExpr_ParseBuiltin(CExpr_BuiltInClassifyType); - if (!strcmp(tkidentifier->name, "__builtin_next_arg")) - return CExpr_ParseNextArg(); - } - if (copts.altivec_model && !strcmp("vec_step", tkidentifier->name)) - return CExpr_ParseVecStep(); - case '~': - case TK_OPERATOR: - case TK_INHERITED: - case TK_COLON_COLON: - if (CScope_ParseExprName(&pr)) - return CExpr_ParseNameResultExpr(&pr, NULL, flag, 1); - tk = lex(); - return nullnode(); - } - - CError_ErrorSkip(CErrorStr141); - return nullnode(); -} - -static ENode *CExpr_SimpleExplicitConversion(void) { - DeclInfo di; - - memclrw(&di, sizeof(DeclInfo)); - - if (!copts.cpp_extensions && tk != TK_UU_TYPEOF_UU && tk != TK_TYPENAME && lookahead() != '(') - CError_Error(CErrorStr114); - - CParser_GetDeclSpecs(&di, 0); - return CExpr_ParseExplicitConversion(di.thetype, di.qual); -} - -static ENode *CExpr_NewPTMFCall(void) { - tk = lex(); - CExpr_ScanExpressionList(1); - - if (tk != ')') { - CError_Error(CErrorStr115); - return nullnode(); - } else { - CError_FATAL(2465); - return nullnode(); - } -} - -static ENode *call_ptmf(ENode *expr) { - Type *rettype; - ENodeList *args; - ENodeList *list1; - ENodeList *list2; - Object *callobj; - - rettype = TYPE_FUNC(TPTR_TARGET(expr->data.mfpointer.mfpointer->rtype))->functype; - tk = lex(); - args = CExpr_ScanExpressionList(1); - - if (tk != ')') { - CError_Error(CErrorStr115); - return nullnode(); - } - - if (IS_TYPE_STRUCT(rettype) || IS_TYPE_CLASS(rettype) || IS_TYPE_12BYTES_MEMBERPOINTER(rettype)) - callobj = rt_ptmf_scall4; - else - callobj = rt_ptmf_scall; - - list1 = lalloc(sizeof(ENodeList)); - list1->next = args; - list1->node = expr->data.mfpointer.accessnode->data.monadic; - - list2 = lalloc(sizeof(ENodeList)); - list2->next = list1; - list2->node = expr->data.mfpointer.mfpointer->data.monadic; - - if (!copts.old_argmatch) { - CError_ASSERT(2568, IS_TYPE_POINTER_ONLY(list2->node->rtype)); - list2->node->rtype = TYPE(&void_ptr); - } - - expr = CExpr_GenericPtmfCall( - callobj, - TYPE_FUNC(TPTR_TARGET(expr->data.mfpointer.mfpointer->rtype)), - list2); - tk = lex(); - return expr; -} - -static ENode *CExpr_DummyDestr(ENode *expr) { - SInt32 state; - NameResult pr; - DeclInfo di; - NameSpace *nspace; - - CPrep_TokenStreamGetState(&state); - nspace = cscope_current; - if ((tk = lex()) == TK_COLON_COLON) { - nspace = cscope_root; - tk = lex(); - } else if (tk != '~' && tk != TK_IDENTIFIER && !(tk >= TK_AUTO && tk <= TK_BYREF)) { - CPrep_TokenStreamSetCurState(&state); - return NULL; - } - -loop: - if (tk == '~') - goto is_tilde; - if (tk == TK_IDENTIFIER) { - if (CScope_FindTypeName(nspace, tkidentifier, &pr)) { - tk = lex(); - if (pr.nspace_0) { - if (tk == TK_COLON_COLON) { - tk = lex(); - nspace = pr.nspace_0; - goto loop; - } - } else if (IS_TYPE_CLASS(pr.type) && tk == TK_COLON_COLON) { - tk = lex(); - nspace = TYPE_CLASS(pr.type)->nspace; - goto loop; - } else { - if (!is_typesame(pr.type, expr->rtype)) - CError_Error(CErrorStr146); - if (tk == TK_COLON_COLON && ((tk = lex()) == '~') && ((tk = lex()) == TK_IDENTIFIER)) { - parse_dtor: - if (CScope_FindTypeName(nspace, tkidentifier, &pr) && !pr.nspace_0) { - if (!is_typesame(pr.type, expr->rtype)) - CError_Error(CErrorStr146); - tk = lex(); - goto parsed; - } - } - } - } - } else if (tk >= TK_AUTO && tk <= TK_BYREF) { - memclrw(&di, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&di, 0); - if (di.storageclass || di.qual || !is_typesame(di.thetype, expr->rtype)) - CError_Error(CErrorStr146); - if (tk == TK_COLON_COLON && ((tk = lex()) == '~')) { - is_tilde: - if ((tk = lex()) == TK_IDENTIFIER) - goto parse_dtor; - memclrw(&di, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&di, 0); - if (di.storageclass || !is_typesame(di.thetype, expr->rtype)) - CError_Error(CErrorStr146); - goto parsed; - } - } - - CError_Error(CErrorStr141); - return NULL; - -parsed: - if (tk == '(') { - if ((tk = lex()) != ')') - CError_Error(CErrorStr115); - else - tk = lex(); - } else { - CError_Error(CErrorStr114); - } - - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = &stvoid; - return expr; -} - -static ENode *postfix_expression(Boolean flag) { - NameResult pr; - Conversion conv; - ENode *expr; - ENode *subexpr; - ENode *funcexpr; - ENodeList *args; - ENode *copy; - ENode *tmp; - StructMember *member; - - if (copts.cplusplus) { - switch (tk) { - case TK_VOID: - case TK_CHAR: - case TK_SHORT: - case TK_INT: - case TK_LONG: - case TK_FLOAT: - case TK_DOUBLE: - case TK_SIGNED: - case TK_UNSIGNED: - case TK_UNK_113: - case TK_UNK_114: - case TK_UNK_115: - case TK_UNK_116: - case TK_UNK_117: - case TK_UNK_118: - case TK_UNK_119: - case TK_UNK_11A: - case TK_UU_TYPEOF_UU: - case TK_BOOL: - case TK_WCHAR_T: - case TK_TYPENAME: - expr = CExpr_SimpleExplicitConversion(); - break; - default: - expr = primary_expression(flag); - break; - case TK_CONST_CAST: - expr = CRTTI_Parse_const_cast(); - break; - case TK_DYNAMIC_CAST: - expr = CRTTI_Parse_dynamic_cast(); - break; - case TK_REINTERPRET_CAST: - expr = CRTTI_Parse_reinterpret_cast(); - break; - case TK_STATIC_CAST: - expr = CRTTI_Parse_static_cast(); - break; - case TK_TYPEID: - expr = CRTTI_ParseTypeID(); - break; - } - } else { - expr = primary_expression(flag); - } - -loop: - switch (tk) { - case '[': - expr = pointer_generation(expr); - tk = lex(); - subexpr = expression(); - if (copts.cplusplus && CExpr_CheckOperator('[', expr, subexpr, &conv)) { - if ((expr = conv.x0)) { - if (tk != ']') - CError_ErrorSkip(CErrorStr125); - else - tk = lex(); - goto loop; - } - - CError_ASSERT(2753, expr = conv.left); - CError_ASSERT(2754, subexpr = conv.right); - } - - if (IS_TYPE_POINTER(expr->rtype)) { - expr = padd(expr, subexpr); - } else if (IS_TYPE_POINTER(subexpr->rtype)) { - expr = padd(subexpr, expr); - } else { - CError_Error(CErrorStr148); - goto dont_do_indirect; - } - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = TPTR_TARGET(expr->rtype); - dont_do_indirect: - if (tk != ']') - CError_ErrorSkip(CErrorStr125); - else - tk = lex(); - goto loop; - - case '(': - funcexpr = CExpr_PointerGeneration(expr); - if (copts.cplusplus) { - if (CExpr_CheckOperator('(', funcexpr, NULL, &conv)) { - CError_ASSERT(2775, expr = conv.x0); - goto loop; - } - if (ENODE_IS(funcexpr, EMFPOINTER)) { - expr = checkreference(call_ptmf(funcexpr)); - goto loop; - } - } - - tk = lex(); - args = CExpr_ScanExpressionList(1); - if (tk != ')') - CError_Error(CErrorStr115); - - if (ENODE_IS(funcexpr, ETEMPLDEP)) { - expr = CExpr_NewENode(EFUNCCALL); - expr->rtype = &sttemplexpr; - expr->data.funccall.funcref = funcexpr; - expr->data.funccall.args = args; - expr->data.funccall.functype = &rt_func; - tk = lex(); - } else { - expr = checkreference(CExpr_MakeFunctionCall(funcexpr, args)); - tk = lex(); - } - goto loop; - - case TK_ARROW: - expr = pointer_generation(expr); - if (copts.cplusplus) { - while (IS_TYPE_CLASS(expr->rtype) && CExpr_CheckOperator(TK_ARROW, expr, NULL, &conv)) { - CError_ASSERT(2810, subexpr = conv.x0); - expr = pointer_generation(subexpr); - } - } - - if (!IS_TYPE_POINTER(expr->rtype)) { - CError_ErrorSkip(CErrorStr148); - return expr; - } - - if (copts.cplusplus && copts.objective_c && CObjC_IsType_id(expr->rtype)) { - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = TPTR_TARGET(expr->rtype); - if ((subexpr = CObjC_CheckModernSendMessage(NULL, expr))) - return subexpr; - } else { - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = TPTR_TARGET(expr->rtype); - } - case '.': - expr = pointer_generation(expr); - if (IS_TYPE_CLASS(expr->rtype)) { - CDecl_CompleteType(expr->rtype); - if (TYPE_CLASS(expr->rtype)->objcinfo && copts.cplusplus && (subexpr = CObjC_CheckModernSendMessage(TYPE_CLASS(expr->rtype), expr))) - return subexpr; - - if (!(TYPE_CLASS(expr->rtype)->flags & CLASS_COMPLETED)) - CError_Error(CErrorStr136, expr->rtype, 0); - - if ((tk = lex()) == TK_TEMPLATE && (tk = lex()) != TK_IDENTIFIER) - CError_Error(CErrorStr107); - - if (CScope_ParseMemberName(TYPE_CLASS(expr->rtype), &pr, 0)) { - if (pr.x1C) { - if ((tk = lex()) == '(') { - if ((tk = lex()) != ')') - CError_Error(CErrorStr115); - else - tk = lex(); - } else { - CError_Error(CErrorStr114); - } - - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = &stvoid; - } else { - expr = checkreference(CExpr_ParseNameResultExpr(&pr, expr, 0, 0)); - } - } - goto loop; - } - if (!IS_TYPE_STRUCT(expr->rtype) || TYPE_STRUCT(expr->rtype)->stype > STRUCT_TYPE_MAX) { - if (copts.cplusplus && (subexpr = CExpr_DummyDestr(expr))) - return subexpr; - CError_ErrorSkip(CErrorStr149); - return expr; - } - if (!ENODE_IS(expr, EINDIRECT)) { - subexpr = CExpr_NewETEMPNode(expr->rtype, 1); - copy = lalloc(sizeof(ENode)); - *copy = *subexpr; - - tmp = makemonadicnode(subexpr, EINDIRECT); - tmp->rtype = expr->rtype; - - tmp = makediadicnode(tmp, expr, EASS); - tmp = makediadicnode(tmp, copy, ECOMMA); - tmp->rtype = copy->rtype; - - tmp = makemonadicnode(tmp, EINDIRECT); - tmp->rtype = expr->rtype; - expr = tmp; - } - if ((tk = lex()) != TK_IDENTIFIER) { - CError_Error(CErrorStr107); - return expr; - } - - member = ismember(TYPE_STRUCT(expr->rtype), tkidentifier); - if (!member) { - if (!expr->rtype->size) - CError_Error(CErrorStr136, expr->rtype, 0); - else - CError_Error(CErrorStr150, tkidentifier->name); - return expr; - } - - if (!IS_TYPE_POINTER(expr->data.monadic->rtype)) { - CError_ErrorSkip(CErrorStr149); - return expr; - } - - expr = checkreference(CClass_AccessMember(expr, member->type, member->qual, member->offset)); - tk = lex(); - goto loop; - - case TK_INCREMENT: - tmp = pointer_generation(expr); - if (copts.cplusplus && CExpr_CheckOperator(TK_INCREMENT, tmp, nullnode(), &conv)) { - if ((expr = conv.x0)) { - tk = lex(); - goto loop; - } - CError_ASSERT(2952, tmp = conv.left); - } - tmp = CExpr_LValue(tmp, 1, 1); - if (tmp->rtype == TYPE(&stbool)) { - expr = CExpr_TempModifyExpr(tmp); - tk = lex(); - } else { - checkadditive(tmp); - expr = makemonadicnode(tmp, EPOSTINC); - tk = lex(); - } - goto loop; - - case TK_DECREMENT: - tmp = pointer_generation(expr); - if (copts.cplusplus && CExpr_CheckOperator(TK_DECREMENT, tmp, nullnode(), &conv)) { - if ((expr = conv.x0)) { - tk = lex(); - goto loop; - } - CError_ASSERT(2976, tmp = conv.left); - } - tmp = CExpr_LValue(tmp, 1, 1); - checkadditive(tmp); - expr = makemonadicnode(tmp, EPOSTDEC); - tk = lex(); - goto loop; - } - - return expr; -} - -static ENode *CExpr_ParseSizeof(void) { - Type *type; - ENode *expr; - - type = CExpr_ParseTypeExpression(NULL); - if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo) - CError_Error(CErrorStr286); - - if (CTemplTool_IsTemplateArgumentDependentType(type)) { - expr = CExpr_NewTemplDepENode(TDE_SIZEOF); - expr->data.templdep.u.typeexpr.type = type; - return expr; - } - - if (type->size == 0) { - if (copts.gcc_extensions && (IS_TYPE_FUNC(type) || IS_TYPE_VOID(type))) - return intconstnode(CABI_GetSizeTType(), 1); - - if (IS_TYPE_CLASS(type) || IS_TYPE_STRUCT(type)) - CError_Error(CErrorStr136, type, 0); - else - CError_Error(CErrorStr146); - } - - return intconstnode(CABI_GetSizeTType(), type->size); -} - -SInt32 scansizeof(void) { - ENode *expr; - - expr = CExpr_ParseSizeof(); - if (!ENODE_IS(expr, EINTCONST)) { - CError_Error(CErrorStr190); - return 0; - } - - return CInt64_GetULong(&expr->data.intval); -} - -static ENode *CExpr_ParseAlignof(void) { - Type *type; - ENode *expr; - SInt16 align; - - type = CExpr_ParseTypeExpression(NULL); - if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo) - CError_Error(CErrorStr364); - - if (CTemplTool_IsTemplateArgumentDependentType(type)) { - expr = CExpr_NewTemplDepENode(TDE_ALIGNOF); - expr->data.templdep.u.typeexpr.type = type; - return expr; - } - - if (type->size == 0) { - if (IS_TYPE_CLASS(type) || IS_TYPE_STRUCT(type)) - CError_Error(CErrorStr136, type, 0); - else - CError_Error(CErrorStr146); - } - - align = CMach_GetTypeAlign(type); - if (align == 0) - align = 1; - - return intconstnode(CABI_GetSizeTType(), align); -} - -SInt32 scanalignof(void) { - ENode *expr; - - expr = CExpr_ParseAlignof(); - if (!ENODE_IS(expr, EINTCONST)) { - CError_Error(CErrorStr190); - return 0; - } - - return CInt64_GetULong(&expr->data.intval); -} - -static ENode *logicalexpression(ENode *expr) { - if (copts.cplusplus && copts.booltruefalse) - expr->rtype = TYPE(&stbool); - else - expr->rtype = TYPE(&stsignedint); - return expr; -} - -ENode *getnodeaddress(ENode *expr, Boolean flag) { - ENode *result; - Object *obj; - - if (!ENODE_IS(expr, EINDIRECT)) { - expr = CExpr_LValue(expr, flag, flag); - if (!ENODE_IS(expr, EINDIRECT)) { - if (!flag) - CError_Error(CErrorStr142); - return nullnode(); - } - } else { - if (flag && - ENODE_IS(expr->data.monadic, EOBJREF) && - expr->data.monadic->data.objref->name == this_name_node && - cscope_currentfunc && - cscope_currentclass && - expr->data.monadic->data.objref == CClass_ThisSelfObject()) - CError_Error(CErrorStr189); - } - - result = lalloc(sizeof(ENode)); - *result = *expr; -restart: - switch (result->data.monadic->type) { - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - result->type = ETYPCON; - if (IS_TYPE_POINTER_ONLY(result->rtype)) - result->flags = TPTR_QUAL(result->rtype) & ENODE_FLAG_QUALS; - result->rtype = CDecl_NewPointerType(result->rtype); - return result; - case EOBJREF: - obj = result->data.monadic->data.objref; - if (obj->datatype == DALIAS) { - CExpr_AliasTransform(result->data.monadic); - goto restart; - } - if (obj->datatype == DINLINEFUNC) - CError_Error(CErrorStr175); - obj->flags = obj->flags | OBJECT_FLAGS_2; - if (flag && !copts.cplusplus && obj->sclass == TK_REGISTER) - CError_Error(CErrorStr163); - break; - case EFUNCCALL: - if (flag && !IS_TYPE_POINTER_ONLY(result->data.monadic->data.funccall.functype->functype)) - CError_Warning(CErrorStr142); - break; - case EBITFIELD: - CError_Error(CErrorStr144); - return nullnode(); - } - - switch (result->rtype->type) { - case TYPEPOINTER: - result->data.monadic->rtype = CDecl_NewPointerType(result->rtype); - result->data.monadic->flags = result->flags; - break; - default: - result->data.monadic->rtype = CDecl_NewPointerType(result->rtype); - result->data.monadic->flags = result->flags; - } - - return result->data.monadic; -} - -static ENode *CExpr_MakeStaticMemberList(NameSpaceObjectList *list) { - NameSpaceObjectList *newlist; - NameSpaceObjectList *n; - ENode *result; - - newlist = NULL; - while (list) { - if (list->object->otype == OT_OBJECT && IS_TYPE_STATIC_METHOD(OBJECT(list->object)->type)) { - n = galloc(sizeof(NameSpaceObjectList)); - *n = *list; - n->next = newlist; - newlist = n; - } - list = list->next; - } - - if (!newlist) { - CError_Warning(CErrorStr331); - return nullnode(); - } - - result = CExpr_NewENode(EOBJLIST); - result->rtype = OBJECT(newlist->object)->type; - result->data.objlist.list = newlist; - return result; -} - -static ENode *CExpr_MakePTDM(ENode *expr) { - ENode *result; - - CError_ASSERT(3414, ENODE_IS(expr, EMEMBER) && expr->data.emember->list->object->otype == OT_MEMBERVAR); - - result = nullnode(); - result->rtype = CExpr_NewPTMType(expr->data.emember, NULL); - CInt64_SetLong(&result->data.intval, OBJ_MEMBER_VAR(expr->data.emember->list->object)->offset + 1); - return result; -} - -ENode *getpointertomemberfunc(ENode *expr, Type *type, Boolean flag) { - NameSpaceObjectList *list; - Object *obj; - Object *dataobj; - Type *ptmtype; - TypeMemberFunc *tmethod; - OLinkList *olist; - SInt32 data[3]; - - CError_ASSERT(3442, ENODE_IS(expr, EMEMBER)); - - if (expr->data.emember->expr && !copts.cpp_extensions) - CError_Error(CErrorStr141); - - if (!copts.cpp_extensions) { - if (!(expr->data.emember->x11 && expr->data.emember->pr_1D)) { - if (type && IS_TYPE_MEMBERPOINTER(type)) - CError_Warning(CErrorStr331); - } - } - - if (expr->data.emember->list->next) { - if (type) { - if (IS_TYPE_MEMBERPOINTER(type)) { - type = TYPE_MEMBER_POINTER(type)->ty1; - for (list = expr->data.emember->list; list; list = list->next) { - if (list->object->otype == OT_OBJECT && is_memberpointerequal(OBJECT(list->object)->type, type)) { - obj = OBJECT(list->object); - break; - } - } - if (!list) { - CError_Error(CErrorStr146); - return nullnode(); - } - } else { - return CExpr_MakeStaticMemberList(expr->data.emember->list); - } - } else { - obj = OBJECT(expr->data.emember->list->object); - } - } else { - obj = OBJECT(expr->data.emember->list->object); - } - - while (obj->datatype == DALIAS) - obj = obj->u.alias.object; - - CError_ASSERT(3503, obj->otype == OT_OBJECT && IS_TYPE_NONSTATIC_METHOD(obj->type)); - - if (TYPE_FUNC(obj->type)->flags & FUNC_IS_TEMPL) - CError_Error(CErrorStr190); - - ptmtype = CExpr_NewPTMType(expr->data.emember, obj); - tmethod = TYPE_METHOD(obj->type); - dataobj = CParser_NewGlobalDataObject(NULL); - dataobj->name = CParser_GetUniqueName(); - dataobj->nspace = cscope_root; - dataobj->type = ptmtype; - dataobj->sclass = TK_STATIC; - - if (flag) { - data[0] = 0; - if (obj->datatype == DVFUNC) { - olist = NULL; - data[1] = tmethod->vtbl_index; - data[2] = tmethod->theclass->vtable->offset; - } else { - data[1] = -1; - data[2] = 0; - olist = galloc(sizeof(OLinkList)); - olist->next = NULL; - olist->obj = obj; - olist->somevalue = 0; - olist->offset = 8; - } - CInit_DeclareData(dataobj, data, olist, dataobj->type->size); - } - - return create_objectnode(dataobj); -} - -static ENode *getpointertomember(ENode *expr) { - CError_ASSERT(3554, ENODE_IS(expr, EMEMBER)); - - if (expr->data.emember->expr) - CError_Error(CErrorStr141); - - expr->data.emember->x11 = 1; - if (!expr->data.emember->list->next) { - if (expr->data.emember->list->object->otype == OT_MEMBERVAR) - return CExpr_MakePTDM(expr); - else - return getpointertomemberfunc(expr, NULL, 1); - } - - return expr; -} - -ENode *CExpr_New_ELOGNOT_Node(ENode *input) { - ENode *expr; - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(input->rtype)) - return CTempl_MakeTemplDepExpr(NULL, ELOGNOT, input); - - expr = pointer_generation(input); - if (copts.cplusplus && CExpr_CheckOperator('!', expr, NULL, &conv)) { - if ((input = conv.x0)) - return input; - CError_ASSERT(3593, expr = conv.left); - } - - switch (expr->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEPOINTER: - case TYPEARRAY: - break; - case TYPEENUM: - expr = forceintegral(expr); - break; - case TYPEMEMBERPOINTER: - expr = CExpr_ConvertToCondition(expr); - break; - default: - CError_Error(CErrorStr144); - return expr; - } - - switch (expr->type) { - case EINTCONST: - expr->data.intval = CInt64_Not(expr->data.intval); - break; - case EFLOATCONST: - expr->type = EINTCONST; - CInt64_SetLong(&expr->data.intval, CMach_FloatIsZero(expr->data.floatval)); - break; - default: - expr = makemonadicnode(expr, ELOGNOT); - } - - return logicalexpression(expr); -} - -ENode *CExpr_New_EMONMIN_Node(ENode *input) { - ENode *expr; - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(input->rtype)) - return CTempl_MakeTemplDepExpr(NULL, EMONMIN, input); - - expr = pointer_generation(input); - if (copts.cplusplus && CExpr_CheckOperator('-', expr, NULL, &conv)) { - if ((input = conv.x0)) - return input; - CError_ASSERT(3652, expr = conv.left); - } - - switch (expr->rtype->type) { - case TYPEINT: - case TYPEENUM: - expr = integralpromote(expr); - if (ENODE_IS(expr, EINTCONST)) { - expr->data.intval = CMach_CalcIntMonadic(expr->rtype, '-', expr->data.intval); - return expr; - } - return makemonadicnode(expr, EMONMIN); - case TYPEFLOAT: - if (ENODE_IS(expr, EFLOATCONST)) { - expr->data.floatval = CMach_CalcFloatMonadic(expr->rtype, '-', expr->data.floatval); - return expr; - } - return CExpr_UnaryFloatExpression(makemonadicnode(expr, EMONMIN)); - default: - CError_Error(CErrorStr144); - return expr; - } -} - -ENode *CExpr_New_EBINNOT_Node(ENode *input) { - ENode *expr; - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(input->rtype)) - return CTempl_MakeTemplDepExpr(NULL, EBINNOT, input); - - expr = pointer_generation(input); - if (copts.cplusplus && CExpr_CheckOperator('~', expr, NULL, &conv)) { - if ((input = conv.x0)) - return input; - CError_ASSERT(3702, expr = conv.left); - } - - expr = integralpromote(expr); - - if (ENODE_IS(expr, EINTCONST)) { - expr->data.intval = CMach_CalcIntMonadic(expr->rtype, '~', expr->data.intval); - return expr; - } - return makemonadicnode(expr, EBINNOT); -} - -ENode *unary_expression(void) { - ENode *expr; - ENode *tmp; - Conversion conv; - - switch (tk) { - case TK_COLON_COLON: - switch (lookahead()) { - case TK_NEW: - tk = lex(); - return scannew(1); - case TK_DELETE: - tk = lex(); - return scandelete(1); - } - return postfix_expression(0); - - case TK_NEW: - return scannew(0); - case TK_DELETE: - return scandelete(0); - case TK_INCREMENT: - tk = lex(); - if (copts.cplusplus) { - expr = pointer_generation(cast_expression()); - if (CExpr_CheckOperator(TK_INCREMENT, expr, NULL, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(3748, expr = conv.left); - } - } else { - expr = pointer_generation(unary_expression()); - } - expr = CExpr_LValue(expr, 1, 1); - if (expr->rtype == TYPE(&stbool)) { - tmp = nullnode(); - tmp->rtype = TYPE(&stbool); - CInt64_SetLong(&tmp->data.intval, 1); - return makediadicnode(expr, tmp, EASS); - } else { - checkadditive(expr); - return makemonadicnode(expr, EPREINC); - } - case TK_DECREMENT: - tk = lex(); - if (copts.cplusplus) { - expr = pointer_generation(cast_expression()); - if (CExpr_CheckOperator(TK_DECREMENT, expr, NULL, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(3776, expr = conv.left); - } - } else { - expr = pointer_generation(unary_expression()); - } - expr = CExpr_LValue(expr, 1, 1); - checkadditive(expr); - return makemonadicnode(expr, EPREDEC); - - case '&': - if (copts.cplusplus) { - switch ((tk = lex())) { - case TK_IDENTIFIER: - case TK_INHERITED: - case TK_COLON_COLON: - expr = postfix_expression(1); - if (ENODE_IS(expr, EMEMBER)) - return getpointertomember(expr); - break; - default: - expr = cast_expression(); - } - - if (CExpr_CheckOperator('&', expr, NULL, &conv)) { - CError_ASSERT(3809, conv.x0); - return conv.x0; - } - } else { - tk = lex(); - expr = cast_expression(); - } - - if (copts.mpwc_relax && !copts.cplusplus && IS_TYPE_ARRAY(expr->rtype) && ENODE_IS(expr, EINDIRECT)) - return pointer_generation(expr); - if (ENODE_IS(expr, EOBJLIST)) - return expr; - - if (IS_TYPE_TEMPLDEPEXPR(expr->rtype)) { - tmp = CExpr_NewTemplDepENode(TDE_ADDRESS_OF); - tmp->data.templdep.u.monadic = expr; - return tmp; - } - - return getnodeaddress(expr, 1); - - case '*': - tk = lex(); - expr = pointer_generation(cast_expression()); - if (copts.cplusplus && CExpr_CheckOperator('*', expr, NULL, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(3840, expr = conv.left); - } - - if (!IS_TYPE_POINTER(expr->rtype)) { - CError_Error(CErrorStr148); - return expr; - } - - tmp = makemonadicnode(expr, EINDIRECT); - CDecl_CompleteType(tmp->rtype = TPTR_TARGET(tmp->rtype)); - return tmp; - - case '+': - tk = lex(); - expr = pointer_generation(cast_expression()); - if (copts.cplusplus && CExpr_CheckOperator('+', expr, NULL, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(3852, expr = conv.left); - } - - switch (expr->rtype->type) { - case TYPEINT: - case TYPEENUM: - return integralpromote(expr); - case TYPEFLOAT: - case TYPEPOINTER: - case TYPEARRAY: - return expr; - default: - CError_Error(CErrorStr144); - return expr; - } - - case '-': - tk = lex(); - return CExpr_New_EMONMIN_Node(cast_expression()); - case '~': - tk = lex(); - return CExpr_New_EBINNOT_Node(cast_expression()); - case '!': - tk = lex(); - return CExpr_New_ELOGNOT_Node(cast_expression()); - - case TK_SIZEOF: - return CExpr_ParseSizeof(); - case TK_UU_ALIGNOF_UU: - return CExpr_ParseAlignof(); - - case TK_LOGICAL_AND: - if (copts.ANSIstrict) - break; - - if ((tk = lex()) != TK_IDENTIFIER) { - CError_Error(CErrorStr107); - return nullnode(); - } - - expr = lalloc(sizeof(ENode)); - expr->type = ELABEL; - expr->cost = 0; - expr->flags = 0; - expr->rtype = TYPE(&void_ptr); - expr->data.label = findlabel(); - if (!expr->data.label) { - expr->data.label = newlabel(); - expr->data.label->name = tkidentifier; - expr->data.label->next = Labels; - Labels = expr->data.label; - } - tk = lex(); - return expr; - } - - return postfix_expression(0); -} - -ENode *do_castnullcheck(ENode *condexpr, ENode *nullcheckexpr) { - ENode *result; - - if (isnotzero(nullcheckexpr)) - return condexpr; - - result = lalloc(sizeof(ENode)); - *result = *condexpr; - result->type = ENULLCHECK; - result->data.nullcheck.nullcheckexpr = lalloc(sizeof(ENode)); - *result->data.nullcheck.nullcheckexpr = *nullcheckexpr; - result->data.nullcheck.condexpr = condexpr; - result->data.nullcheck.precompid = CParser_GetUniqueID(); - - nullcheckexpr->type = EPRECOMP; - nullcheckexpr->data.precompid = result->data.nullcheck.precompid; - - return result; -} - -ENode *CExpr_SafeClassPointerCast(ENode *expr, TypeClass *a, TypeClass *b, Boolean typconflag, Boolean pathcheckflag) { - ENode *result; - - result = CClass_ClassPointerCast(expr, a, b, typconflag, 1, pathcheckflag); - if (result != expr) { - if (!(ENODE_IS(result, ETYPCON) && result->data.monadic == expr)) - result = do_castnullcheck(result, expr); - } - return result; -} - -ENode *PointerToMemberCast(ENode *expr, TypeMemberPointer *tm1, TypeMemberPointer *tm2, Boolean flag) { - BClassList *path; - Boolean negate; - short depth; - Boolean isambig; - SInt32 pathoffset; - CInt64 pathoffset64; - ENode *tmp; - - CError_ASSERT(3984, IS_TYPE_CLASS(tm1->ty2)); - CError_ASSERT(3985, IS_TYPE_CLASS(tm2->ty2)); - - if (tm1->ty2 == tm2->ty2) { - expr->rtype = TYPE(tm2); - return expr; - } - - negate = 0; - path = CClass_GetBasePath(TYPE_CLASS(tm2->ty2), TYPE_CLASS(tm1->ty2), &depth, &isambig); - if (!path) { - path = CClass_GetBasePath(TYPE_CLASS(tm1->ty2), TYPE_CLASS(tm2->ty2), &depth, &isambig); - if (!path) - goto failed; - negate = 1; - } - - if (isambig) - CError_Error(CErrorStr188); - - if ((pathoffset = CClass_GetPathOffset(path)) < 0) - goto failed; - if (negate) - pathoffset = -pathoffset; - - if (flag) - CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); - - if (tm1->size != tm2->size) { - failed: - CError_Error(CErrorStr247, tm1, 0, tm2, 0); - return nullnode(); - } - - if (!pathoffset) { - expr->rtype = TYPE(tm2); - return expr; - } - - if (tm1->size == 4u) { - if (ENODE_IS(expr, EINTCONST)) { - if (!CInt64_IsZero(&expr->data.intval)) { - CInt64_SetLong(&pathoffset64, pathoffset); - expr->data.intval = CInt64_Add(expr->data.intval, pathoffset64); - } - expr->rtype = TYPE(tm2); - return expr; - } else { - expr->rtype = TYPE(&stunsignedlong); - tmp = intconstnode(TYPE(&stunsignedlong), pathoffset); - tmp = makediadicnode(expr, tmp, EADD); - tmp = makemonadicnode(tmp, ETYPCON); - tmp->rtype = TYPE(tm2); - return do_castnullcheck(tmp, expr); - } - } else { - tmp = create_temp_node(TYPE(&ptmstruct)); - expr = getnodeaddress(expr, 0); - tmp = funccallexpr(rt_ptmf_cast, intconstnode(TYPE(&stsignedlong), pathoffset), expr, tmp, NULL); - tmp = makemonadicnode(tmp, EINDIRECT); - tmp->rtype = TYPE(tm2); - return tmp; - } -} - -ENode *CExpr_MemberPointerConversion(ENode *expr, TypeMemberPointer *type, Boolean flag1) { - if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval)) { - if (IS_TYPE_FUNC(type->ty1)) - expr = create_objectnode(rt_ptmf_null); - expr->rtype = TYPE(type); - } else if (ENODE_IS(expr, EMEMBER)) { - expr = getpointertomemberfunc(expr, TYPE(type), flag1); - } - - return expr; -} - -static ENode *CExpr_MemberPointerCast(ENode *expr, TypeMemberPointer *type, UInt32 qual) { - if (!IS_TYPE_MEMBERPOINTER(expr->rtype)) - expr = CExpr_MemberPointerConversion(expr, type, 1); - - if (!IS_TYPE_MEMBERPOINTER(expr->rtype)) { - CError_Error(CErrorStr164); - return nullnode(); - } - - expr = PointerToMemberCast(expr, TYPE_MEMBER_POINTER(expr->rtype), type, 0); - expr->flags = qual & ENODE_FLAG_QUALS; - return expr; -} - -ENode *do_typecast(ENode *expr, Type *type, UInt32 qual) { - TypePointer *tptr; - ENode *tmp; - short flags; - - if (!copts.old_argmatch) - return CExpr_Convert(expr, type, qual, 1, 0); - - if (copts.cpp_extensions && is_typesame(expr->rtype, type) && !ENODE_IS(expr, EOBJLIST)) { - expr->rtype = type; - expr->flags &= ~ENODE_FLAG_QUALS; - expr->flags |= qual & ENODE_FLAG_QUALS; - return expr; - } - - switch (type->type) { - case TYPEARRAY: - CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); - return expr; - case TYPEMEMBERPOINTER: - if (!IS_TYPE_CLASS(expr->rtype)) - return CExpr_MemberPointerCast(expr, TYPE_MEMBER_POINTER(type), qual); - } - - flags = qual & ENODE_FLAG_QUALS; - - if (ENODE_IS(expr, EOBJLIST)) - return CExpr_AssignmentPromotion(expr, type, qual & ENODE_FLAG_QUALS, 1); - - if (ENODE_IS(expr, EOBJREF) && IS_TYPE_NONSTATIC_METHOD(expr->data.objref->type)) { - CError_Error(CErrorStr221); - return nullnode(); - } - - if (type == &stvoid) { - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = type; - expr->flags = flags; - return expr; - } - - if (IS_TYPE_REFERENCE(type)) { - tmp = getnodeaddress(expr, 0); - tptr = galloc(sizeof(TypePointer)); - *tptr = *TYPE_POINTER(type); - tptr->qual &= ~Q_REFERENCE; - - tmp = do_typecast(tmp, TYPE(tptr), qual); - tmp = makemonadicnode(tmp, EINDIRECT); - tmp->rtype = TPTR_TARGET(type); - tmp->flags = flags; - return tmp; - } - - if (IS_TYPE_CLASS(expr->rtype) || IS_TYPE_CLASS(type)) { - if (expr->rtype->size == 0) - CDecl_CompleteType(expr->rtype); - - if (expr->rtype == type && !CClass_CopyConstructor(TYPE_CLASS(type))) - return expr; - - if (user_assign_check(expr, type, qual, 1, 1, 1)) { - assign_node->flags = flags; - return assign_node; - } - - CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); - return nullnode(); - } - - if (IS_TYPE_STRUCT(type) && copts.cplusplus && is_typesame(expr->rtype, type)) { - expr->rtype = type; - expr->flags = flags; - return expr; - } - - if (type == TYPE(&stbool)) { - expr = CExpr_ConvertToBool(expr, 1); - expr->flags = flags; - return expr; - } - - if (IS_TYPE_ENUM(type)) { - tmp = do_typecast(expr, TYPE_ENUM(type)->enumtype, qual); - if (!ENODE_IS(tmp, EINTCONST)) - tmp = makemonadicnode(tmp, ETYPCON); - tmp->rtype = type; - tmp->flags = flags; - return tmp; - } - - if (IS_TYPE_INT_OR_FLOAT(type)) { - if (ENODE_IS(expr, ETYPCON) && expr->rtype->type == type->type && expr->rtype->size == type->size) { - if (is_unsigned(expr->rtype) == is_unsigned(type) && ENODE_QUALS(expr) == qual) { - expr->rtype = type; - expr->flags = expr->flags | ENODE_FLAG_80; - return expr; - } - } - - if (IS_TYPE_ENUM(expr->rtype)) - expr = forceintegral(expr); - - if (IS_TYPE_INT_OR_FLOAT(expr->rtype)) { - expr = promote(expr, type); - expr->flags = flags; - return expr; - } - - if (!(IS_TYPE_POINTER_ONLY(expr->rtype) && !IS_TYPE_FLOAT(type))) - CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); - - if (ENODE_IS(expr, ETYPCON) && ENODE_IS(tmp = expr->data.monadic, EINTCONST)) { - tmp->rtype = type; - tmp->flags = flags; - tmp->data.intval = CExpr_IntConstConvert(type, TYPE(&stunsignedlong), tmp->data.intval); - return tmp; - } - - if (type->size != 4) { - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = TYPE(&stunsignedlong); - } - - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = type; - expr->flags = flags; - return expr; - } - - if (IS_TYPE_POINTER(type)) { - if (IS_TYPE_POINTER(expr->rtype)) { - if (IS_TYPE_CLASS(TPTR_TARGET(expr->rtype)) && IS_TYPE_CLASS(TPTR_TARGET(type))) - expr = CExpr_SafeClassPointerCast(expr, TYPE_CLASS(TPTR_TARGET(expr->rtype)), TYPE_CLASS(TPTR_TARGET(type)), 1, 0); - - if (!ENODE_IS(expr, ETYPCON)) - expr = makemonadicnode(expr, ETYPCON); - - expr->rtype = type; - expr->flags = flags; - return expr; - } - - if (!IS_TYPE_INT(expr->rtype)) { - if (!IS_TYPE_ENUM(expr->rtype)) { - CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); - return expr; - } - expr = forceintegral(expr); - } - - if (expr->rtype->size != 4) { - if (!ENODE_IS(expr, EINTCONST)) - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = TYPE(&stunsignedlong); - } - - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = type; - expr->flags = flags; - return expr; - } - - if ((tmp = CodeGen_HandleTypeCast(expr, type, qual))) - return tmp; - - CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); - return nullnode(); -} - -static Boolean isvectorconst(ENode *node) { - if (ENODE_IS3(node, ECOMMA, EINTCONST, EFLOATCONST)) - return 1; - else - return 0; -} - -ENode *cast_expression(void) { - ENode *expr; - ENode *tmp; - ENodeList *args; - MWVector128 vec; - DeclInfo di; - - if (!(tk == '(' && islookaheaddeclaration())) - return unary_expression(); - tk = lex(); - - memclrw(&di, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&di, 0); - scandeclarator(&di); - - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - - if (di.name) - CError_Error(CErrorStr164); - - if (copts.altivec_model && tk == '(' && IS_TYPE_VECTOR(di.thetype)) { - tk = lex(); - expr = s_expression(); - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - - if (CodeGen_CollapseVectorExpression(expr, &vec, di.thetype)) { - tmp = lalloc(sizeof(ENode)); - tmp->type = EVECTOR128CONST; - if ((tmp->cost = expr->cost) == 0) - tmp->cost = 1; - tmp->flags = ENODE_QUALS(expr); - tmp->rtype = di.thetype; - tmp->data.vector128val = vec; - } else { - tmp = makemonadicnode(expr, ETYPCON); - } - tmp->rtype = di.thetype; - tmp->flags = expr->flags; - return tmp; - } - - if (tk == '{' && (!copts.ANSIstrict || copts.c9x) && !IS_TYPE_VECTOR(di.thetype)) - return CInit_AutoObject(NULL, di.thetype, di.qual); - - expr = cast_expression(); - if (copts.cplusplus && (CTemplTool_IsTemplateArgumentDependentType(di.thetype) || - CTemplTool_IsTemplateArgumentDependentExpression(expr))) { - args = lalloc(sizeof(ENodeList)); - args->next = NULL; - args->node = expr; - return CExpr_TemplArgDepCast(di.thetype, di.qual, args); - } - - if (!IS_TYPE_REFERENCE(di.thetype)) - expr = pointer_generation(expr); - return do_typecast(expr, di.thetype, di.qual); -} - -static ENode *pm_expression(void) { - ENode *left; - ENode *right; - ENode *tmp; - Type *type; - UInt32 qual; - short flags; - Conversion conv; - - left = cast_expression(); -restart: - switch (tk) { - case TK_ARROW_STAR: - left = pointer_generation(left); - tk = lex(); - right = pointer_generation(cast_expression()); - - if (CExpr_CheckOperator(TK_ARROW_STAR, left, right, &conv)) { - CError_ASSERT(4457, left = conv.x0); - goto restart; - } - - if (!IS_TYPE_POINTER(left->rtype)) { - CError_Error(CErrorStr148); - return left; - } - - left = makemonadicnode(left, EINDIRECT); - left->rtype = TPTR_TARGET(left->rtype); - goto common_part; - case TK_DOT_STAR: - left = pointer_generation(left); - tk = lex(); - right = pointer_generation(cast_expression()); - if (!ENODE_IS(left, EINDIRECT)) { - CError_Error(CErrorStr142); - return left; - } - common_part: - if (!IS_TYPE_CLASS(left->rtype)) { - CError_Error(CErrorStr149); - return left; - } - if (!IS_TYPE_MEMBERPOINTER(right->rtype)) { - CError_Error(CErrorStr144); - return left; - } - if (left->rtype != TYPE_MEMBER_POINTER(right->rtype)->ty2) { - if (CClass_IsBaseClass(TYPE_CLASS(left->rtype), TYPE_CLASS(TYPE_MEMBER_POINTER(right->rtype)->ty2), NULL, 1, 1)) { - left->data.monadic = CClass_ClassPointerCast( - left->data.monadic, - TYPE_CLASS(left->rtype), - TYPE_CLASS(TYPE_MEMBER_POINTER(right->rtype)->ty2), - 0, 1, 1); - left->rtype = TYPE_MEMBER_POINTER(right->rtype)->ty2; - } else { - CError_Error(CErrorStr146); - return left; - } - } - type = CClass_CombineClassAccessQualifiers( - TYPE_MEMBER_POINTER(right->rtype)->ty1, - ENODE_QUALS(right), - left->flags, - &qual); - flags = qual; - if (!IS_TYPE_FUNC(type)) { - if (!ENODE_IS(right, EINTCONST)) { - if (!canadd(left->data.monadic, -1)) { - left->data.monadic = makediadicnode(left->data.monadic, nullnode(), EADD); - CInt64_SetLong(&left->data.monadic->data.diadic.right->data.intval, -1); - optimizecomm(left->data.monadic); - } - right->rtype = TYPE(&stunsignedlong); - left->data.monadic = makediadicnode(left->data.monadic, right, EADD); - optimizecomm(left->data.monadic); - } else { - right->data.intval = CInt64_Sub(right->data.intval, cint64_one); - if (!canadd2(left->data.monadic, right->data.intval)) { - right->rtype = TYPE(&stunsignedlong); - left->data.monadic = makediadicnode(left->data.monadic, right, EADD); - optimizecomm(left->data.monadic); - } - } - - if (IS_TYPE_BITFIELD(type)) { - left->data.monadic = makemonadicnode(left->data.monadic, EBITFIELD); - left->data.monadic->rtype = type; - left->rtype = TYPE_BITFIELD(type)->bitfieldtype; - } else { - left->rtype = type; - } - left->flags = flags; - left = checkreference(left); - goto restart; - } else { - CError_ASSERT(4535, ENODE_IS(right, EINDIRECT)); - tmp = lalloc(sizeof(ENode)); - tmp->type = EMFPOINTER; - tmp->cost = 4; - tmp->flags = 0; - tmp->rtype = &stvoid; - tmp->data.mfpointer.accessnode = left; - tmp->data.mfpointer.mfpointer = right; - return tmp; - } - default: - return left; - } -} - -ENode *CExpr_New_EMUL_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EMUL, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('*', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4566, left = conv.left); - CError_ASSERT(4567, right = conv.right); - } - - return makemultnode(left, right); -} - -ENode *CExpr_New_EDIV_Node(ENode *left, ENode *right, Boolean no_warning) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EDIV, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('/', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4592, left = conv.left); - CError_ASSERT(4593, right = conv.right); - } - - return makedivnode(left, right, no_warning); -} - -ENode *CExpr_New_EMODULO_Node(ENode *left, ENode *right, Boolean no_warning) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EMODULO, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('%', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4618, left = conv.left); - CError_ASSERT(4619, right = conv.right); - } - - left = integralpromote(left); - right = integralpromote(right); - CExpr_ArithmeticConversion(&left, &right); - - if (iszero(right)) { - if (!no_warning) - CError_Warning(CErrorStr139); - return left; - } - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '%', right->data.intval); - return left; - } - - if (iszero(left)) - return makediadicnode(right, left, ECOMMA); - - if (CExpr_IsOne(right)) { - right = nullnode(); - right->rtype = left->rtype; - return makediadicnode(left, right, ECOMMA); - } - - return makediadicnode(left, right, EMODULO); -} - -ENode *CExpr_New_EADD_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EADD, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('+', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4665, left = conv.left); - CError_ASSERT(4666, right = conv.right); - } - - return makeaddnode(left, right); -} - -ENode *CExpr_New_ESUB_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, ESUB, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('-', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4690, left = conv.left); - CError_ASSERT(4691, right = conv.right); - } - - return makesubnode(left, right); -} - -ENode *CExpr_New_ESHL_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, ESHL, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator(TK_SHL, left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4715, left = conv.left); - CError_ASSERT(4716, right = conv.right); - } - - left = integralpromote(left); - right = integralpromote(right); - - if (iszero(left) || iszero(right)) { - return left; - } - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_SHL, right->data.intval); - return left; - } - - return makediadicnode(left, right, ESHL); -} - -ENode *CExpr_New_ESHR_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, ESHR, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator(TK_SHR, left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4752, left = conv.left); - CError_ASSERT(4753, right = conv.right); - } - - left = integralpromote(left); - right = integralpromote(right); - - if (iszero(left) || iszero(right)) { - return left; - } - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_SHR, right->data.intval); - return left; - } - - return makediadicnode(left, right, ESHR); -} - -static ENode *pointercompare(ENodeType nt, ENode *left, ENode *right) { - Type *ltype; - Type *rtype; - - ltype = left->rtype; - rtype = right->rtype; - if (IS_TYPE_POINTER_ONLY(ltype) && IS_TYPE_POINTER_ONLY(rtype)) { - ltype = TPTR_TARGET(left->rtype); - rtype = TPTR_TARGET(right->rtype); - if (IS_TYPE_CLASS(ltype) && IS_TYPE_CLASS(rtype)) { - if (ltype != rtype) { - if (ltype == TPTR_TARGET(left->rtype)) { - if (CClass_IsBaseClass(TYPE_CLASS(ltype), TYPE_CLASS(rtype), NULL, 0, 1)) { - left = CExpr_SafeClassPointerCast(left, TYPE_CLASS(ltype), TYPE_CLASS(rtype), 0, 1); - } else if (CClass_IsBaseClass(TYPE_CLASS(rtype), TYPE_CLASS(ltype), NULL, 0, 1)) { - right = CExpr_SafeClassPointerCast(right, TYPE_CLASS(rtype), TYPE_CLASS(ltype), 0, 1); - } else { - CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); - } - } else { - CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); - } - } - } else if (!is_typeequal(left->rtype, right->rtype)) { - if (!copts.objective_c || !CObjC_IsCompatibleType(left->rtype, right->rtype)) { - CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); - } - } - } else if (nt == EEQU || nt == ENOTEQU) { - if (IS_TYPE_INT(ltype)) { - if (!(ENODE_IS(left, EINTCONST) && CInt64_IsZero(&left->data.intval))) - CError_Error(CErrorStr144); - CError_ASSERT(4847, IS_TYPE_POINTER_ONLY(rtype)); - left->rtype = TYPE(&stunsignedlong); - } else if (IS_TYPE_INT(rtype)) { - if (!(ENODE_IS(right, EINTCONST) && CInt64_IsZero(&right->data.intval))) - CError_Error(CErrorStr144); - CError_ASSERT(4855, IS_TYPE_POINTER_ONLY(ltype)); - right->rtype = TYPE(&stunsignedlong); - } else if (!is_typeequal(ltype, rtype)) { - CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); - } - } else { - if (!is_typeequal(ltype, rtype)) - CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right)); - } - - return logicalexpression(makediadicnode(left, right, nt)); -} - -static ENode *unsigncheck(ENode *expr, Boolean flag1, Boolean flag2) { - if (is_unsigned(expr->data.diadic.left->rtype)) { - if (ENODE_IS(expr->data.diadic.left, EINTCONST) && CInt64_IsZero(&expr->data.diadic.left->data.intval)) { - flag1 = !flag1; - } else if (!(ENODE_IS(expr->data.diadic.right, EINTCONST) && CInt64_IsZero(&expr->data.diadic.right->data.intval))) { - return logicalexpression(expr); - } - - if (flag1 && flag2) { - expr->type = EEQU; - return logicalexpression(expr); - } - if (!flag1 && !flag2) { - expr->type = ENOTEQU; - return logicalexpression(expr); - } - return CExpr_ConstResult(logicalexpression(expr), !flag1); - } - return logicalexpression(expr); -} - -ENode *CExpr_New_ELESS_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, ELESS, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('<', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4929, left = conv.left); - CError_ASSERT(4930, right = conv.right); - } - - if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) - return pointercompare(ELESS, left, right); - - CExpr_CompareConvert(&left, "<", &right, 0); - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '<', right->data.intval); - left->rtype = CParser_GetBoolType(); - } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, '<', right->data.floatval)); - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - } else { - left = unsigncheck(makediadicnode(left, right, ELESS), 1, 0); - } - - return left; -} - -ENode *CExpr_New_ELESSEQU_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, ELESSEQU, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator(TK_LESS_EQUAL, left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(4976, left = conv.left); - CError_ASSERT(4977, right = conv.right); - } - - if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) - return pointercompare(ELESSEQU, left, right); - - CExpr_CompareConvert(&left, "<=", &right, 0); - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_LESS_EQUAL, right->data.intval); - left->rtype = CParser_GetBoolType(); - } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, TK_LESS_EQUAL, right->data.floatval)); - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - } else { - left = unsigncheck(makediadicnode(left, right, ELESSEQU), 1, 1); - } - - return left; -} - -ENode *CExpr_New_EGREATER_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EGREATER, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('>', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5023, left = conv.left); - CError_ASSERT(5024, right = conv.right); - } - - if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) - return pointercompare(EGREATER, left, right); - - CExpr_CompareConvert(&left, ">", &right, 0); - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '>', right->data.intval); - left->rtype = CParser_GetBoolType(); - } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, '>', right->data.floatval)); - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - } else { - left = unsigncheck(makediadicnode(left, right, EGREATER), 0, 0); - } - - return left; -} - -ENode *CExpr_New_EGREATEREQU_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EGREATEREQU, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator(TK_GREATER_EQUAL, left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5070, left = conv.left); - CError_ASSERT(5071, right = conv.right); - } - - if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) - return pointercompare(EGREATEREQU, left, right); - - CExpr_CompareConvert(&left, ">=", &right, 0); - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_GREATER_EQUAL, right->data.intval); - left->rtype = CParser_GetBoolType(); - } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, TK_GREATER_EQUAL, right->data.floatval)); - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - } else { - left = unsigncheck(makediadicnode(left, right, EGREATEREQU), 0, 1); - } - - return left; -} - -ENode *memberpointercompare(ENodeType nt, ENode *left, ENode *right) { - Object *func; - ENodeList *arg; - - if (!IS_TYPE_MEMBERPOINTER(left->rtype)) { - if (!(IS_TYPE_INT(left->rtype) && ENODE_IS(left, EINTCONST) && CInt64_IsZero(&left->data.intval))) { - CError_Error(CErrorStr144); - return nullnode(); - } - } else if (!IS_TYPE_MEMBERPOINTER(right->rtype)) { - if (!(IS_TYPE_INT(right->rtype) && ENODE_IS(right, EINTCONST) && CInt64_IsZero(&right->data.intval))) { - CError_Error(CErrorStr144); - return nullnode(); - } - } else if (!is_typeequal(left->rtype, right->rtype)) { - left = PointerToMemberCast(left, TYPE_MEMBER_POINTER(left->rtype), TYPE_MEMBER_POINTER(right->rtype), 1); - } - - if ((ENODE_IS(left, EINTCONST) || !IS_TYPE_FUNC(TYPE_MEMBER_POINTER(left->rtype)->ty1)) && (ENODE_IS(right, EINTCONST) || !IS_TYPE_FUNC(TYPE_MEMBER_POINTER(right->rtype)->ty1))) { - left->rtype = TYPE(&stunsignedlong); - right->rtype = TYPE(&stunsignedlong); - return logicalexpression(makediadicnode(left, right, nt)); - } - - arg = lalloc(sizeof(ENodeList)); - if (ENODE_IS(left, EINTCONST) || ENODE_IS(right, EINTCONST)) { - func = rt_ptmf_test; - if (ENODE_IS(left, EINTCONST)) - arg->node = getnodeaddress(right, 0); - else - arg->node = getnodeaddress(left, 0); - arg->next = NULL; - } else { - func = rt_ptmf_cmpr; - arg->next = lalloc(sizeof(ENodeList)); - arg->node = getnodeaddress(left, 0); - arg->next->node = getnodeaddress(right, 0); - arg->next->next = NULL; - } - - left = lalloc(sizeof(ENode)); - left->type = EFUNCCALL; - left->rtype = TYPE(&stsignedlong); - left->cost = 4; - left->data.funccall.funcref = create_objectrefnode(func); - left->data.funccall.args = arg; - left->data.funccall.functype = TYPE_FUNC(func->type); - left->flags = TYPE_FUNC(func->type)->qual & ENODE_FLAG_QUALS; - - if (nt == EEQU) - left = makemonadicnode(left, ELOGNOT); - - return left; -} - -ENode *CExpr_New_EEQU_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EEQU, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator(TK_LOGICAL_EQ, left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5201, left = conv.left); - CError_ASSERT(5202, right = conv.right); - } - - if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) - return pointercompare(EEQU, left, right); - if (IS_TYPE_MEMBERPOINTER(left->rtype) || IS_TYPE_MEMBERPOINTER(right->rtype)) - return memberpointercompare(EEQU, left, right); - - CExpr_CompareConvert(&left, "==", &right, 1); - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_LOGICAL_EQ, right->data.intval); - left->rtype = CParser_GetBoolType(); - } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - left->type = EINTCONST; - CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, TK_LOGICAL_EQ, right->data.floatval)); - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - } else { - left = makediadicnode(left, right, EEQU); - optimizecomm(left); - } - - return logicalexpression(left); -} - -ENode *CExpr_New_ENOTEQU_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, ENOTEQU, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator(TK_LOGICAL_NE, left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5261, left = conv.left); - CError_ASSERT(5262, right = conv.right); - } - - if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype)) - return pointercompare(ENOTEQU, left, right); - if (IS_TYPE_MEMBERPOINTER(left->rtype) || IS_TYPE_MEMBERPOINTER(right->rtype)) - return memberpointercompare(ENOTEQU, left, right); - - CExpr_CompareConvert(&left, "!=", &right, 1); - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_LOGICAL_NE, right->data.intval); - left->rtype = CParser_GetBoolType(); - } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) { - CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, TK_LOGICAL_NE, right->data.floatval)); - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - } else { - left = makediadicnode(left, right, ENOTEQU); - optimizecomm(left); - } - - return logicalexpression(left); -} - -ENode *CExpr_New_EAND_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EAND, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('&', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5321, left = conv.left); - CError_ASSERT(5322, right = conv.right); - } - - left = integralpromote(left); - right = integralpromote(right); - CExpr_ArithmeticConversion(&left, &right); - - if (iszero(left) || CExpr_AllBitsSet(right)) - return left; - if (iszero(right) || CExpr_AllBitsSet(left)) - return right; - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '&', right->data.intval); - return left; - } - - left = makediadicnode(left, right, EAND); - optimizecomm(left); - return left; -} - -ENode *CExpr_New_EXOR_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EXOR, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('^', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5360, left = conv.left); - CError_ASSERT(5361, right = conv.right); - } - - left = integralpromote(left); - right = integralpromote(right); - CExpr_ArithmeticConversion(&left, &right); - - if (iszero(right)) - return left; - if (iszero(left)) - return right; - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '^', right->data.intval); - return left; - } - - left = makediadicnode(left, right, EXOR); - optimizecomm(left); - return left; -} - -ENode *CExpr_New_EOR_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, EOR, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator('|', left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5399, left = conv.left); - CError_ASSERT(5400, right = conv.right); - } - - left = integralpromote(left); - right = integralpromote(right); - CExpr_ArithmeticConversion(&left, &right); - - if (iszero(right) || CExpr_AllBitsSet(left)) - return left; - if (iszero(left) || CExpr_AllBitsSet(right)) - return right; - - if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) { - left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '|', right->data.intval); - return left; - } - - left = makediadicnode(left, right, EOR); - optimizecomm(left); - return left; -} - -ENode *CExpr_New_ELAND_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, ELAND, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator(TK_LOGICAL_AND, left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5438, left = conv.left); - CError_ASSERT(5439, right = conv.right); - } - - switch (left->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEPOINTER: - case TYPEARRAY: - break; - case TYPEENUM: - case TYPEMEMBERPOINTER: - left = CExpr_ConvertToCondition(left); - break; - default: - CError_Error(CErrorStr144); - left = nullnode(); - } - switch (right->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEPOINTER: - case TYPEARRAY: - break; - case TYPEENUM: - case TYPEMEMBERPOINTER: - right = CExpr_ConvertToCondition(right); - break; - default: - CError_Error(CErrorStr144); - right = nullnode(); - } - - if (iszero(left)) { - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - CInt64_SetLong(&left->data.intval, 0); - return left; - } - - if (isnotzero(left)) { - if (iszero(right)) { - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - CInt64_SetLong(&left->data.intval, 0); - return left; - } else if (isnotzero(right)) { - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - CInt64_SetLong(&left->data.intval, 1); - return left; - } else { - left = makemonadicnode(right, ELOGNOT); - left->rtype = CParser_GetBoolType(); - return makemonadicnode(left, ELOGNOT); - } - } else { - if (isnotzero(right)) { - left = makemonadicnode(left, ELOGNOT); - left->rtype = CParser_GetBoolType(); - return makemonadicnode(left, ELOGNOT); - } else if (iszero(right)) { - right->type = EINTCONST; - right->rtype = CParser_GetBoolType(); - CInt64_SetLong(&right->data.intval, 0); - return makecommaexpression(left, right); - } else { - left = makediadicnode(left, right, ELAND); - left->rtype = CParser_GetBoolType(); - return left; - } - } -} - -ENode *CExpr_New_ELOR_Node(ENode *left, ENode *right) { - Conversion conv; - - if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype)) - return CTempl_MakeTemplDepExpr(left, ELOR, right); - - left = pointer_generation(left); - right = pointer_generation(right); - if (copts.cplusplus && CExpr_CheckOperator(TK_LOGICAL_OR, left, right, &conv)) { - if (conv.x0) - return conv.x0; - CError_ASSERT(5543, left = conv.left); - CError_ASSERT(5544, right = conv.right); - } - - switch (left->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEPOINTER: - case TYPEARRAY: - break; - case TYPEENUM: - case TYPEMEMBERPOINTER: - left = CExpr_ConvertToCondition(left); - break; - default: - CError_Error(CErrorStr144); - left = nullnode(); - } - switch (right->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEPOINTER: - case TYPEARRAY: - break; - case TYPEENUM: - case TYPEMEMBERPOINTER: - right = CExpr_ConvertToCondition(right); - break; - default: - CError_Error(CErrorStr144); - right = nullnode(); - } - - if (isnotzero(left)) { - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - CInt64_SetLong(&left->data.intval, 1); - return left; - } - - if (iszero(left)) { - if (iszero(right)) { - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - CInt64_SetLong(&left->data.intval, 0); - return left; - } else if (isnotzero(right)) { - left->type = EINTCONST; - left->rtype = CParser_GetBoolType(); - CInt64_SetLong(&left->data.intval, 1); - return left; - } else { - left = makemonadicnode(right, ELOGNOT); - left->rtype = CParser_GetBoolType(); - return makemonadicnode(left, ELOGNOT); - } - } else { - if (isnotzero(right)) { - right->type = EINTCONST; - right->rtype = CParser_GetBoolType(); - CInt64_SetLong(&right->data.intval, 1); - } else if (iszero(right)) { - left = makemonadicnode(left, ELOGNOT); - left->rtype = CParser_GetBoolType(); - return makemonadicnode(left, ELOGNOT); - } - left = makediadicnode(left, right, ELOR); - left->rtype = CParser_GetBoolType(); - return left; - } -} - -ENode *CExpr_NewDyadicNode(ENode *left, ENodeType nt, ENode *right) { - switch (nt) { - default: - CError_FATAL(5642); - case EADD: return CExpr_New_EADD_Node(left, right); - case ESUB: return CExpr_New_ESUB_Node(left, right); - case EMUL: return CExpr_New_EMUL_Node(left, right); - case EDIV: return CExpr_New_EDIV_Node(left, right, 1); - case EMODULO: return CExpr_New_EMODULO_Node(left, right, 1); - case EAND: return CExpr_New_EAND_Node(left, right); - case EXOR: return CExpr_New_EXOR_Node(left, right); - case EOR: return CExpr_New_EOR_Node(left, right); - case ESHL: return CExpr_New_ESHL_Node(left, right); - case ESHR: return CExpr_New_ESHR_Node(left, right); - case ELESS: return CExpr_New_ELESS_Node(left, right); - case EGREATER: return CExpr_New_EGREATER_Node(left, right); - case ELESSEQU: return CExpr_New_ELESSEQU_Node(left, right); - case EGREATEREQU: return CExpr_New_EGREATEREQU_Node(left, right); - case EEQU: return CExpr_New_EEQU_Node(left, right); - case ENOTEQU: return CExpr_New_ENOTEQU_Node(left, right); - case ELAND: return CExpr_New_ELAND_Node(left, right); - case ELOR: return CExpr_New_ELOR_Node(left, right); - } -} - -typedef struct DyadicInfo { - ENodeType t; - UInt8 prec; -} DyadicInfo; - -static Boolean CExpr_GetDyadicInfo(short token, DyadicInfo *info) { - switch (token) { - case '*': - info->t = EMUL; - info->prec = 20; - return 1; - case '/': - info->t = EDIV; - info->prec = 20; - return 1; - case '%': - info->t = EMODULO; - info->prec = 20; - return 1; - case '+': - info->t = EADD; - info->prec = 19; - return 1; - case '-': - info->t = ESUB; - info->prec = 19; - return 1; - case TK_SHL: - info->t = ESHL; - info->prec = 18; - return 1; - case TK_SHR: - info->t = ESHR; - info->prec = 18; - return 1; - case '<': - info->t = ELESS; - info->prec = 17; - return 1; - case TK_LESS_EQUAL: - info->t = ELESSEQU; - info->prec = 17; - return 1; - case '>': - if (disallowgreaterthan) - return 0; - info->t = EGREATER; - info->prec = 17; - return 1; - case TK_GREATER_EQUAL: - info->t = EGREATEREQU; - info->prec = 17; - return 1; - case TK_LOGICAL_EQ: - info->t = EEQU; - info->prec = 16; - return 1; - case TK_LOGICAL_NE: - info->t = ENOTEQU; - info->prec = 16; - return 1; - case '&': - info->t = EAND; - info->prec = 15; - return 1; - case '^': - info->t = EXOR; - info->prec = 14; - return 1; - case '|': - info->t = EOR; - info->prec = 13; - return 1; - case TK_LOGICAL_AND: - info->t = ELAND; - info->prec = 12; - return 1; - case TK_LOGICAL_OR: - info->t = ELOR; - info->prec = 11; - return 1; - default: - return 0; - } -} - -static ENode *CExpr_ParseDyadicExpression(ENode *left, UInt8 prec, Boolean no_warning) { - ENode *right; - Boolean is_eland_or_elor; - Boolean save_dgt; - Boolean cont; - DyadicInfo left_info; - DyadicInfo right_info; - - save_dgt = disallowgreaterthan; - if (!left) { - disallowgreaterthan = 0; - left = pm_expression(); - disallowgreaterthan = save_dgt; - } - - do { - if (!CExpr_GetDyadicInfo(tk, &left_info)) - return left; - - switch (left_info.t) { - case ELAND: - CExpr_CheckUnwantedAssignment(left); - if (iszero(left)) - no_warning = 1; - is_eland_or_elor = 1; - break; - case ELOR: - CExpr_CheckUnwantedAssignment(left); - if (isnotzero(left)) - no_warning = 1; - is_eland_or_elor = 1; - break; - default: - is_eland_or_elor = 0; - } - - tk = lex(); - disallowgreaterthan = 0; - right = pm_expression(); - disallowgreaterthan = save_dgt; - inner_loop: - if (CExpr_GetDyadicInfo(tk, &right_info)) { - if (left_info.prec >= right_info.prec) { - cont = (prec >= right_info.prec); - } else { - right = CExpr_ParseDyadicExpression(right, left_info.prec, no_warning); - goto inner_loop; - } - } else { - cont = 1; - } - - if (is_eland_or_elor) - CExpr_CheckUnwantedAssignment(right); - - switch (left_info.t) { - case EDIV: - left = CExpr_New_EDIV_Node(left, right, no_warning); - break; - case EMODULO: - left = CExpr_New_EMODULO_Node(left, right, no_warning); - break; - default: - left = CExpr_NewDyadicNode(left, left_info.t, right); - } - } while (!cont); - - return left; -} - -static Boolean CExpr_IsBlockMoveType(Type *type) { - switch (type->type) { - case TYPESTRUCT: - case TYPECLASS: - return 1; - case TYPEMEMBERPOINTER: - return type->size != 4; - default: - return 0; - } -} - -ENode *CExpr_New_ECOND_Node(ENode *cond, ENode *expr1, ENode *expr2) { - ENode *result; - ENodeList *args; - short cost; - Conversion conv; - - cond = CExpr_ConvertToCondition(pointer_generation(cond)); - expr1 = pointer_generation(expr1); - expr2 = pointer_generation(expr2); - - if (!IS_TYPE_INT_OR_FLOAT(cond->rtype) && !IS_TYPE_POINTER_ONLY(cond->rtype)) { - CError_Error(CErrorStr144); - return nullnode(); - } - - cost = cond->cost + 1; - if (expr1->cost > expr2->cost) - cost += expr1->cost; - else - cost += expr2->cost; - if (expr2->cost > cost) - cost = expr2->cost; - if (cost > 200) - cost = 200; - - result = CExpr_NewENode(ECOND); - result->cost = cost; - result->rtype = expr1->rtype; - result->flags = expr1->flags | expr2->flags; - result->data.cond.cond = cond; - if (ENODE_IS(expr1, EFUNCCALL) && expr1->rtype == &stvoid && (expr1->flags & ENODE_FLAG_VOLATILE) != 0) { - result->rtype = expr2->rtype; - result->flags = expr2->flags; - result->data.cond.expr1 = expr1; - result->data.cond.expr2 = expr2; - return result; - } - if (ENODE_IS(expr2, EFUNCCALL) && expr2->rtype == &stvoid && (expr2->flags & ENODE_FLAG_VOLATILE) != 0) { - result->rtype = expr1->rtype; - result->flags = expr1->flags; - result->data.cond.expr1 = expr1; - result->data.cond.expr2 = expr2; - return result; - } - - if ( - ENODE_IS(expr1, EINDIRECT) && - ENODE_IS(expr2, EINDIRECT) && - is_typesame(expr1->rtype, expr2->rtype) && - ENODE_QUALS(expr1) == ENODE_QUALS(expr2) && - CExpr_IsBlockMoveType(expr1->rtype) && - !ENODE_IS(expr1->data.monadic, EBITFIELD) && - !ENODE_IS(expr2->data.monadic, EBITFIELD) - ) { - if (isnotzero(cond)) - return expr1; - if (iszero(cond)) - return expr2; - result->data.cond.expr1 = getnodeaddress(expr1, 0); - result->data.cond.expr2 = getnodeaddress(expr2, 0); - result->rtype = result->data.cond.expr1->rtype; - result = makemonadicnode(result, EINDIRECT); - result->rtype = TPTR_TARGET(result->rtype); - return result; - } - - if ((IS_TYPE_CLASS(expr1->rtype) || IS_TYPE_CLASS(expr2->rtype)) && !is_typesame(expr1->rtype, expr2->rtype)) { - if (!copts.old_argmatch) { - if (CExpr_CondOperatorMatch(expr1, expr2, &conv)) { - CError_ASSERT(6246, !conv.x0); - expr1 = conv.left; - expr2 = conv.right; - } else if (CExpr_CanImplicitlyConvert(expr1, expr2->rtype, ENODE_QUALS(expr2))) { - if (CExpr_CanImplicitlyConvert(expr2, expr1->rtype, ENODE_QUALS(expr1))) - CError_Error(CErrorStr188); - expr1 = CExpr_Convert(expr1, expr2->rtype, ENODE_QUALS(expr2), 0, 1); - } else if (CExpr_CanImplicitlyConvert(expr2, expr1->rtype, ENODE_QUALS(expr1))) { - expr2 = CExpr_Convert(expr2, expr1->rtype, ENODE_QUALS(expr1), 0, 1); - } else { - goto failed; - } - - result->rtype = expr1->rtype; - } else { - args = lalloc(sizeof(ENodeList)); - args->node = expr1; - args->next = lalloc(sizeof(ENodeList)); - args->next->node = expr2; - args->next->next = NULL; - - if (CExpr_CheckOperatorConversion(':', expr1, expr2, args, &conv)) { - CError_ASSERT(6274, !conv.x0); - expr1 = conv.left; - expr2 = conv.right; - } - - result->rtype = expr1->rtype; - } - } - - switch (expr1->rtype->type) { - case TYPEENUM: - if (expr1->rtype == expr2->rtype) - break; - expr1 = forceintegral(expr1); - case TYPEINT: - if (IS_TYPE_POINTER_ONLY(expr2->rtype) || IS_TYPE_MEMBERPOINTER(expr2->rtype)) { - expr1 = CExpr_Convert(expr1, expr2->rtype, ENODE_QUALS(expr2), 0, 1); - result->rtype = expr2->rtype; - break; - } - case TYPEFLOAT: - if (expr1->rtype != expr2->rtype) { - CExpr_ArithmeticConversion(&expr1, &expr2); - result->rtype = expr1->rtype; - } - break; - case TYPEPOINTER: - if (ENODE_IS(expr2, EINTCONST) && CInt64_IsZero(&expr2->data.intval)) { - expr2->rtype = TYPE(&stunsignedlong); - break; - } - if (IS_TYPE_POINTER_ONLY(expr2->rtype)) { - if (IS_TYPE_CLASS(TPTR_TARGET(expr1->rtype)) && IS_TYPE_CLASS(TPTR_TARGET(expr2->rtype))) { - if (TPTR_TARGET(expr1->rtype) != TPTR_TARGET(expr2->rtype)) { - if (CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(expr1->rtype)), TYPE_CLASS(TPTR_TARGET(expr2->rtype)), NULL, 0, 1)) { - expr1 = CExpr_SafeClassPointerCast( - expr1, - TYPE_CLASS(TPTR_TARGET(expr1->rtype)), - TYPE_CLASS(TPTR_TARGET(expr2->rtype)), - 0, 1); - expr1->rtype = expr2->rtype; - } else if (CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(expr2->rtype)), TYPE_CLASS(TPTR_TARGET(expr1->rtype)), NULL, 0, 1)) { - expr2 = CExpr_SafeClassPointerCast( - expr2, - TYPE_CLASS(TPTR_TARGET(expr2->rtype)), - TYPE_CLASS(TPTR_TARGET(expr1->rtype)), - 0, 1); - expr2->rtype = expr1->rtype; - } else { - goto failed; - } - } - result->rtype = expr1->rtype; - break; - } - if (TPTR_TARGET(expr2->rtype) == &stvoid) - result->rtype = expr2->rtype; - } - if (!is_typeequal(expr1->rtype, expr2->rtype)) { - if (!copts.objective_c) - goto failed; - if (!CObjC_IsCompatibleType(expr1->rtype, expr2->rtype)) - goto failed; - expr1->rtype = expr2->rtype = CObjC_GetObjCType_id(1); - } - break; - case TYPEVOID: - if (!is_typeequal(expr1->rtype, expr2->rtype)) - goto failed; - break; - case TYPESTRUCT: - case TYPECLASS: - if (!is_typeequal(expr1->rtype, expr2->rtype)) - goto failed; - result->rtype = expr1->rtype; - break; - case TYPEMEMBERPOINTER: - if (IS_TYPE_MEMBERPOINTER(expr2->rtype) && TYPE_MEMBER_POINTER(expr1->rtype)->ty2 == TYPE_MEMBER_POINTER(expr2->rtype)->ty2) { - expr2 = CExpr_Convert(expr2, expr1->rtype, ENODE_QUALS(expr1), 0, 1); - } else if (CExpr_CanImplicitlyConvert(expr1, expr2->rtype, ENODE_QUALS(expr2))) { - if (CExpr_CanImplicitlyConvert(expr2, expr1->rtype, ENODE_QUALS(expr1))) - CError_Error(CErrorStr188); - expr1 = CExpr_Convert(expr1, expr2->rtype, ENODE_QUALS(expr2), 0, 1); - } else if (CExpr_CanImplicitlyConvert(expr2, expr1->rtype, ENODE_QUALS(expr1))) { - expr2 = CExpr_Convert(expr2, expr1->rtype, ENODE_QUALS(expr1), 0, 1); - } else { - goto failed; - } - result->rtype = expr1->rtype; - break; - default: - failed: - CError_Error(CErrorStr245, expr1->rtype, ENODE_QUALS(expr1), expr2->rtype, ENODE_QUALS(expr2)); - return nullnode(); - } - - result->data.cond.expr1 = expr1; - result->data.cond.expr2 = expr2; - if (isnotzero(cond)) - result = expr1; - else if (iszero(cond)) - result = expr2; - return result; -} - -static ENode *conditional_expression(void) { - ENode *cond; - ENode *expr1; - ENode *expr2; - ENode *result; - Boolean is_templdep_cond; - - is_templdep_cond = 0; - cond = CExpr_ParseDyadicExpression(NULL, 0, 0); - if (tk != '?') - return cond; - - cond = pointer_generation(cond); - if (!IS_TYPE_TEMPLDEPEXPR(cond->rtype)) { - cond = CExpr_ConvertToCondition(cond); - if (!IS_TYPE_INT_OR_FLOAT(cond->rtype) && !IS_TYPE_POINTER_ONLY(cond->rtype)) { - CError_Error(CErrorStr144); - return nullnode(); - } - } else { - is_templdep_cond = 1; - } - - tk = lex(); - expr1 = expression(); - if (tk != ':') - CError_ErrorSkip(CErrorStr141); - else - tk = lex(); - - expr2 = (copts.cplusplus && !copts.ARMconform) ? assignment_expression() : conditional_expression(); - - if (is_templdep_cond || IS_TYPE_TEMPLDEPEXPR(expr1->rtype) || IS_TYPE_TEMPLDEPEXPR(expr2->rtype)) { - result = CExpr_NewENode(ECOND); - result->rtype = &sttemplexpr; - result->data.cond.cond = cond; - result->data.cond.expr1 = expr1; - result->data.cond.expr2 = expr2; - return result; - } - - return CExpr_New_ECOND_Node(cond, expr1, expr2); -} - -static ENode *CExpr_MakeOpAssNode(ENode *left, ENode *right, ENodeType nt) { - if (left->rtype != right->rtype) { - switch (right->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - break; - case TYPEENUM: - right->rtype = TYPE_ENUM(right->rtype)->enumtype; - break; - default: - right = CExpr_AssignmentPromotion(right, left->rtype, 0, 1); - } - if (IS_TYPE_FLOAT(left->rtype)) { - if (IS_TYPE_INT(right->rtype) || (IS_TYPE_FLOAT(right->rtype) && left->rtype->size >= right->rtype->size)) - right = CExpr_AssignmentPromotion(right, left->rtype, 0, 1); - } else if (IS_TYPE_INT(left->rtype)) { - if (IS_TYPE_INT(right->rtype) && (left->rtype->size > right->rtype->size || (left->rtype->size == right->rtype->size && is_unsigned(left->rtype) == is_unsigned(right->rtype)))) - right = CExpr_AssignmentPromotion(right, left->rtype, 0, 1); - } - } - - return makediadicnode(left, right, nt); -} - -static ENode *makeassignmentnode(ENode *left, ENodeType nt, short token) { - ENode *right; - ENode *tmp; - ENode *funcexpr; - ENodeList *args; - Conversion conv; - - tk = lex(); - right = assignment_expression(); - if (copts.cplusplus) { - if (copts.old_argmatch && !ENODE_IS(right, EMEMBER)) - right = pointer_generation(right); - if (CExpr_CheckOperator(token, left, right, &conv)) { - if (!conv.x0) { - if (nt == EASS) - goto continue_anyway; - CError_FATAL(6531); - } - return conv.x0; - } - if (IS_TYPE_CLASS(left->rtype) && CClass_AssignmentOperator(TYPE_CLASS(left->rtype))) - CError_Error(CErrorStr144); - } -continue_anyway: - if (IS_TYPE_ARRAY(left->rtype)) { - if (copts.gcc_extensions && nt == EASS && is_typesame(left->rtype, right->rtype)) { - tmp = makediadicnode(left, right, nt); - tmp->flags = left->flags; - return tmp; - } - CError_Error(CErrorStr144); - return nullnode(); - } - - left = CExpr_LValue(pointer_generation(left), 1, 1); - if (nt != EASS) { - if (!IS_TYPE_INT(right->rtype)) { - if (!IS_TYPE_ENUM(right->rtype)) { - CError_Error(CErrorStr144); - return left; - } - right = forceintegral(right); - } - if (!IS_TYPE_INT(left->rtype)) { - if (copts.cplusplus) { - CError_Error(CErrorStr144); - return left; - } - left = forceintegral(left); - if (!IS_TYPE_INT(left->rtype)) { - CError_Error(CErrorStr144); - return left; - } - } - return CExpr_MakeOpAssNode(left, right, nt); - } - - if (IS_TYPE_CLASS(left->rtype) && TYPE_CLASS(left->rtype)->sominfo) { - CError_Error(CErrorStr285); - return left; - } - - if (copts.warn_implicitconv && ENODE_IS(left, EINDIRECT) && ENODE_IS(left->data.monadic, EBITFIELD) && !ENODE_IS(right, EINTCONST)) { - copts.warn_implicitconv = 0; - right = CExpr_AssignmentPromotion(right, left->rtype, left->flags, 1); - copts.warn_implicitconv = 1; - } else { - right = CExpr_AssignmentPromotion(right, left->rtype, left->flags, 1); - } - - tmp = right; - if (IS_TYPE_FLOAT(right->rtype) && ENODE_IS(right, ETYPCON) && right->rtype->size == right->data.monadic->rtype->size) - tmp = right->data.monadic; - - if ( - ENODE_IS(left, EINDIRECT) && - ENODE_IS(left->data.monadic, EOBJREF) && - ENODE_IS(tmp, EINDIRECT) && - (ENODE_IS(funcexpr = right->data.monadic, EFUNCCALL) || ENODE_IS(funcexpr, EFUNCCALLP)) && - left->rtype == funcexpr->data.funccall.functype->functype && - CMach_GetFunctionResultClass(funcexpr->data.funccall.functype) == 1 && - (args = funcexpr->data.funccall.args) - ) { - switch (CABI_GetStructResultArgumentIndex(funcexpr->data.funccall.functype)) { - case 0: - break; - case 1: - if ((args = args->next)) - break; - CError_FATAL(6625); - default: - CError_FATAL(6626); - } - if (ENODE_IS(args->node, ETEMP)) { - if (!(IS_TYPE_CLASS(left->rtype) && CClass_Destructor(TYPE_CLASS(left->rtype)))) { - args->node = getnodeaddress(left, 0); - return right; - } - } - } - - right = makediadicnode(left, right, nt); - right->flags = left->flags; - return right; -} - -static ENode *makepassignmentnode(ENode *left, ENodeType nt, short token) { - ENode *right; - Boolean is_array; - Conversion conv; - - is_array = IS_TYPE_ARRAY(left->rtype); - left = pointer_generation(left); - if (copts.cplusplus) { - tk = lex(); - right = pointer_generation(assignment_expression()); - if (CExpr_CheckOperator(token, left, right, &conv)) { - CError_ASSERT(6669, conv.x0); - return conv.x0; - } - left = CExpr_LValue(left, 1, 1); - } else { - left = CExpr_LValue(left, 1, 1); - tk = lex(); - right = pointer_generation(assignment_expression()); - } - - if (is_array) - CError_Error(CErrorStr144); - - switch (left->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEPOINTER: - break; - case TYPEENUM: - if (copts.cplusplus) { - CError_Error(CErrorStr144); - return left; - } - left = forceintegral(left); - break; - default: - CError_Error(CErrorStr144); - return left; - } - - if (IS_TYPE_ENUM(right->rtype)) - right = forceintegral(right); - - if (iszero(right)) - return left; - - if (IS_TYPE_POINTER_ONLY(left->rtype)) { - if (IS_TYPE_INT(right->rtype)) { - if (nt == ESUBASS) { - left = psub(left, right); - if (ENODE_IS(left, ESUB)) - left->type = ESUBASS; - return left; - } else { - left = padd(left, right); - if (ENODE_IS(left, EADD)) - left->type = EADDASS; - return left; - } - } - CError_Error(CErrorStr144); - return left; - } else { - return CExpr_MakeOpAssNode(left, right, nt); - } -} - -static ENode *makemulassignmentnode(ENode *left, ENodeType nt, short token) { - ENode *right; - Boolean is_array; - Conversion conv; - - is_array = IS_TYPE_ARRAY(left->rtype); - left = pointer_generation(left); - if (copts.cplusplus) { - tk = lex(); - right = pointer_generation(assignment_expression()); - if (CExpr_CheckOperator(token, left, right, &conv)) { - CError_ASSERT(6753, conv.x0); - return conv.x0; - } - if (!IS_TYPE_INT(left->rtype) && !(IS_TYPE_FLOAT(left->rtype) && nt != EMODASS)) { - CError_Error(CErrorStr144); - return nullnode(); - } - left = CExpr_LValue(left, 1, 1); - } else { - if (IS_TYPE_ENUM(left->rtype)) - left = forceintegral(left); - if (!IS_TYPE_INT(left->rtype) && !(IS_TYPE_FLOAT(left->rtype) && nt != EMODASS)) { - CError_Error(CErrorStr144); - return nullnode(); - } - - left = CExpr_LValue(left, 1, 1); - tk = lex(); - right = pointer_generation(assignment_expression()); - } - - if (is_array) - CError_Error(CErrorStr144); - - if (IS_TYPE_ENUM(right->rtype)) - right = forceintegral(right); - - if (IS_TYPE_INT(left->rtype) && IS_TYPE_FLOAT(right->rtype) && nt == EMODASS) { - CError_Error(CErrorStr144); - return nullnode(); - } - - return CExpr_MakeOpAssNode(left, right, nt); -} - -static ENode *CExpr_TransformOpAssign(ENode *expr) { - switch (expr->type) { - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - if (expr->rtype == TYPE(&stbool)) { - expr = CIRTrans_TransformOpAss(expr); - if (ENODE_IS(expr, EASS)) { - expr->data.diadic.right = makemonadicnode(expr->data.diadic.right, ELOGNOT); - expr->data.diadic.right->rtype = TYPE(&stbool); - expr->data.diadic.right = makemonadicnode(expr->data.diadic.right, ELOGNOT); - } - } - } - - return expr; -} - -ENode *assignment_expression(void) { - ENode *expr; - - if (tk == TK_THROW) - return CExcept_ScanThrowExpression(); - - expr = conditional_expression(); - switch (tk) { - case '=': - return makeassignmentnode(expr, EASS, tk); - case TK_ADD_ASSIGN: - return CExpr_TransformOpAssign(makepassignmentnode(expr, EADDASS, tk)); - case TK_SUB_ASSIGN: - return CExpr_TransformOpAssign(makepassignmentnode(expr, ESUBASS, tk)); - case TK_MULT_ASSIGN: - expr = makemulassignmentnode(expr, EMULASS, tk); - if (ENODE_IS(expr, EMULASS) && CExpr_IsOne(expr->data.diadic.right)) - return expr->data.diadic.left; - return CExpr_TransformOpAssign(expr); - case TK_DIV_ASSIGN: - expr = makemulassignmentnode(expr, EDIVASS, tk); - if (ENODE_IS(expr, EDIVASS)) { - if (iszero(expr->data.diadic.right) && !IS_TYPE_FLOAT(expr->rtype)) { - CError_Warning(CErrorStr139); - return expr->data.diadic.left; - } - if (CExpr_IsOne(expr->data.diadic.right)) - return expr->data.diadic.left; - } - return CExpr_TransformOpAssign(expr); - case TK_MOD_ASSIGN: - expr = makemulassignmentnode(expr, EMODASS, tk); - if (ENODE_IS(expr, EMODASS)) { - if (iszero(expr->data.diadic.right)) { - CError_Warning(CErrorStr139); - return expr->data.diadic.left; - } - } - return CExpr_TransformOpAssign(expr); - case TK_SHL_ASSIGN: - expr = makeassignmentnode(expr, ESHLASS, tk); - if (ENODE_IS(expr, ESHLASS) && iszero(expr->data.diadic.right)) - return expr->data.diadic.left; - return CExpr_TransformOpAssign(expr); - case TK_SHR_ASSIGN: - expr = makeassignmentnode(expr, ESHRASS, tk); - if (ENODE_IS(expr, ESHRASS) && iszero(expr->data.diadic.right)) - return expr->data.diadic.left; - return CExpr_TransformOpAssign(expr); - case TK_AND_ASSIGN: - expr = makeassignmentnode(expr, EANDASS, tk); - if (ENODE_IS(expr, EANDASS) && CExpr_AllBitsSet(expr->data.diadic.right)) - return expr->data.diadic.left; - return expr; - case TK_XOR_ASSIGN: - expr = makeassignmentnode(expr, EXORASS, tk); - if (ENODE_IS(expr, EXORASS) && iszero(expr->data.diadic.right)) - return expr->data.diadic.left; - return CExpr_TransformOpAssign(expr); - case TK_OR_ASSIGN: - expr = makeassignmentnode(expr, EORASS, tk); - if (ENODE_IS(expr, EORASS) && iszero(expr->data.diadic.right)) - return expr->data.diadic.left; - return CExpr_TransformOpAssign(expr); - default: - return expr; - } -} - -ENode *conv_assignment_expression(void) { - return pointer_generation(assignment_expression()); -} - -static Boolean CExpr_HasSideEffect(ENode *expr) { - switch (expr->type) { - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case EMUL: - case EDIV: - case EMODULO: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case ELAND: - case ELOR: - case EROTL: - case EROTR: - case EBITFIELD: - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case ETEMP: - case EARGOBJ: - case ELOCOBJ: - case EOBJLIST: - case EMEMBER: - case EVECTOR128CONST: - return 0; - case ETYPCON: - return IS_TYPE_VOID(expr->rtype); - case EINDIRECT: - switch (expr->data.monadic->type) { - case EFUNCCALL: - case EFUNCCALLP: - return 1; - default: - return 0; - } - case ECOMMA: - return CInline_ExpressionHasSideEffect(expr->data.diadic.right); - case ECOND: - return CInline_ExpressionHasSideEffect(expr->data.cond.expr1) || CInline_ExpressionHasSideEffect(expr->data.cond.expr2); - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EFORCELOAD: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case EFUNCCALL: - case EFUNCCALLP: - case EMFPOINTER: - case ENULLCHECK: - case EPRECOMP: - case ELABEL: - case ENEWEXCEPTION: - case ENEWEXCEPTIONARRAY: - case EINITTRYCATCH: - case EINSTRUCTION: - return 1; - default: - CError_FATAL(7056); - return 0; - } -} - -void CExpr_CheckUnusedExpression(ENode *expr) { - ENode *scan; - ENodeList *arg; - - if (copts.warn_possunwant) { - scan = expr; - while (ENODE_IS(scan, ETYPCON)) - scan = scan->data.monadic; - if (ENODE_IS(scan, EEQU)) { - CError_Warning(CErrorStr208); - return; - } - } - - if (copts.warn_no_side_effect) { - if (!CExpr_HasSideEffect(expr)) { - CError_Warning(CErrorStr369); - return; - } - } - - if (copts.warn_resultnotused) { - scan = expr; - if (IS_TYPE_VOID(expr->rtype)) - return; - if (ENODE_IS(expr, EINDIRECT)) - scan = expr->data.monadic; - - switch (scan->type) { - case EFUNCCALL: - case EFUNCCALLP: - if (ENODE_IS(scan->data.funccall.funcref, EOBJREF) && scan->data.funccall.funcref->data.objref->name == asop_name_node) - return; - if (CMach_GetFunctionResultClass(scan->data.funccall.functype) == 1 && (arg = scan->data.funccall.args)) { - switch (CABI_GetStructResultArgumentIndex(scan->data.funccall.functype)) { - case 0: - break; - case 1: - if ((arg = arg->next)) - break; - CError_FATAL(7110); - default: - CError_FATAL(7111); - } - - if (!ENODE_IS(arg->node, ETEMP)) - return; - } - CError_Warning(CErrorStr370); - } - } -} - -ENode *s_expression(void) { - ENode *left; - ENode *right; - Conversion conv; - - left = assignment_expression(); - while (tk == ',') { - left = pointer_generation(left); - tk = lex(); - right = pointer_generation(assignment_expression()); - - if (copts.cplusplus && CExpr_CheckOperator(',', left, right, &conv)) { - CError_ASSERT(7143, left = conv.x0); - } else { - CExpr_CheckUnusedExpression(left); - left = makecommaexpression(left, right); - left->rtype = right->rtype; - } - } - - return left; -} - -ENode *expression(void) { - return pointer_generation(s_expression()); -} - -CInt64 CExpr_IntegralConstExprType(Type **tint) { - ENode *expr; - - expr = pointer_generation(conditional_expression()); - if (ENODE_IS(expr, EINTCONST)) { - switch (expr->rtype->type) { - case TYPEINT: - *tint = expr->rtype; - return expr->data.intval; - case TYPEENUM: - *tint = TYPE_ENUM(expr->rtype)->enumtype; - return expr->data.intval; - } - } - - CError_Error(CErrorStr124); - *tint = TYPE(&stchar); - return cint64_zero; -} - -ENode *CExpr_IntegralConstOrDepExpr(void) { - ENode *expr; - - expr = pointer_generation(conditional_expression()); - if (ENODE_IS(expr, EINTCONST)) { - switch (expr->rtype->type) { - case TYPEINT: - return expr; - case TYPEENUM: - expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; - return expr; - default: - CError_FATAL(7209); - } - } - - if (CTemplTool_IsTemplateArgumentDependentExpression(expr)) - return expr; - - CError_Error(CErrorStr124); - expr = nullnode(); - expr->rtype = TYPE(&stchar); - return expr; -} - -CInt64 CExpr_IntegralConstExpr(void) { - Type *throwaway; - return CExpr_IntegralConstExprType(&throwaway); -} - -void CExpr_CheckUnwantedAssignment(ENode *expr) { - if (copts.warn_possunwant) { - if (ENODE_IS(expr, EASS) && !(expr->flags & ENODE_FLAG_80)) - CError_Warning(CErrorStr207); - } -} - -Boolean CExpr_ParseAsmExpr(Object **objptr, CInt64 *valptr) { - ENode *expr; - - if (objptr) - *objptr = NULL; - *valptr = cint64_zero; - - expr = pointer_generation(assignment_expression()); - if (ENODE_IS(expr, EINTCONST)) { - *valptr = expr->data.intval; - return 1; - } - - if (objptr) { - switch (expr->type) { - case EINDIRECT: - if (CInit_RelocInitCheck(expr->data.monadic, objptr, valptr, 1)) - return 1; - break; - case EOBJREF: - *objptr = expr->data.objref; - while ((*objptr)->datatype == DALIAS) - *objptr = (*objptr)->u.alias.object; - return 1; - case EMEMBER: - if (expr->data.emember->list->object->otype == OT_OBJECT) { - if (expr->data.emember->list->next && expr->data.emember->list->next->object->otype == OT_OBJECT) - CError_Error(CErrorStr199); - *objptr = OBJECT(expr->data.emember->list->object); - while ((*objptr)->datatype == DALIAS) - *objptr = (*objptr)->u.alias.object; - return 1; - } - break; - case EOBJLIST: - CError_Error(CErrorStr199); - return 0; - } - } - - CError_Error(CErrorStr155); - return 0; -} diff --git a/compiler_and_linker/unsorted/CExpr2.c b/compiler_and_linker/unsorted/CExpr2.c deleted file mode 100644 index e5c662a..0000000 --- a/compiler_and_linker/unsorted/CExpr2.c +++ /dev/null @@ -1,4206 +0,0 @@ -#include "compiler/CExpr.h" -#include "compiler/CABI.h" -#include "compiler/CClass.h" -#include "compiler/CDecl.h" -#include "compiler/CInit.h" -#include "compiler/CInt64.h" -#include "compiler/CError.h" -#include "compiler/CFunc.h" -#include "compiler/CInline.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CObjC.h" -#include "compiler/CObjCModern.h" -#include "compiler/CParser.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CScope.h" -#include "compiler/CSOM.h" -#include "compiler/CTemplateFunc.h" -#include "compiler/CTemplateTools.h" -#include "compiler/CodeGen.h" -#include "compiler/CompilerTools.h" -#include "compiler/enode.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/templates.h" - -#ifdef __MWERKS__ -#undef va_start -#undef va_arg -#define va_start(ap, parm) ap = __va_start(parm) -#define __va_start(parm) (va_list) (&parm + 1) -//#define va_arg(ap, type) ((((type *) (ap = (va_list) (( ((long) ap + sizeof(type) - 1) & ~(sizeof(type)) ) + sizeof(type) ) ))[-1])) -#define va_arg(ap, type) (*(((type *) (ap = (char *)((((unsigned long)ap + __builtin_align(type) - 1) & ~(__builtin_align(type) - 1) ) + sizeof(type)))) - 1)) -#endif - -ENode *assign_node; -Boolean temp_reference_init; -static SInt32 assign_value; // type? -static ENode *firstarrayexpr; -static Match5 user_std_match; -static Boolean cexpr_hascall; -static Boolean cexpr_esearch_bool[MAXEXPR]; -static Boolean cexpr_rsearch_bool[MAXEXPR]; -static CExprSearchCB cexpr_esearch_callback; -static CExprReplaceCB cexpr_rsearch_callback; -static Type *cexpr_left_conversion_type; -static Type *cexpr_right_conversion_type; - -static FuncArg mon_arg = {NULL, NULL, NULL, NULL, 0, 0, 0, 0}; -static FuncArg diadic_arg2 = {NULL, NULL, NULL, NULL, 0, 0, 0, 0}; -static FuncArg diadic_arg1 = {&diadic_arg1, NULL, NULL, NULL, 0, 0, 0, 0}; - -static void CExpr_RecSearchExprTree(ENode *expr) { - ENodeList *list; - -restart: - if (cexpr_esearch_bool[expr->type]) - cexpr_esearch_callback(expr); - - switch (expr->type) { - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EINDIRECT: - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case EFORCELOAD: - case ETYPCON: - case EBITFIELD: - expr = expr->data.monadic; - goto restart; - case EMUL: - case EMULV: - case EDIV: - case EMODULO: - case EADDV: - case ESUBV: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case ELAND: - case ELOR: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case ECOMMA: - case EPMODULO: - case EROTL: - case EROTR: - case EBCLR: - case EBTST: - case EBSET: - CExpr_RecSearchExprTree(expr->data.diadic.left); - expr = expr->data.diadic.right; - goto restart; - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case EPRECOMP: - case ETEMP: - case EARGOBJ: - case ELOCOBJ: - case ELABEL: - case EOBJLIST: - case EMEMBER: - case EINSTRUCTION: - case EVECTOR128CONST: - return; - case EFUNCCALL: - case EFUNCCALLP: - for (list = expr->data.funccall.args; list; list = list->next) - CExpr_RecSearchExprTree(list->node); - expr = expr->data.funccall.funcref; - goto restart; - case ENULLCHECK: - CExpr_RecSearchExprTree(expr->data.nullcheck.nullcheckexpr); - expr = expr->data.nullcheck.condexpr; - goto restart; - case EMFPOINTER: - CExpr_RecSearchExprTree(expr->data.mfpointer.accessnode); - expr = expr->data.mfpointer.mfpointer; - goto restart; - case ECOND: - CExpr_RecSearchExprTree(expr->data.cond.cond); - CExpr_RecSearchExprTree(expr->data.cond.expr1); - expr = expr->data.cond.expr2; - goto restart; - case ENEWEXCEPTION: - case ENEWEXCEPTIONARRAY: - CExpr_RecSearchExprTree(expr->data.newexception.initexpr); - expr = expr->data.newexception.tryexpr; - goto restart; - case EINITTRYCATCH: - if (expr->data.itc.initexpr) - CExpr_RecSearchExprTree(expr->data.itc.initexpr); - if (expr->data.itc.tryexpr) - CExpr_RecSearchExprTree(expr->data.itc.tryexpr); - if (expr->data.itc.catchexpr) - CExpr_RecSearchExprTree(expr->data.itc.catchexpr); - if (expr->data.itc.result) - CExpr_RecSearchExprTree(expr->data.itc.result); - return; - default: - CError_FATAL(128); - } -} - -void CExpr_SearchExprTree(ENode *expr, CExprSearchCB callback, int count, ...) { - va_list ap; - short i; - - cexpr_esearch_callback = callback; - - va_start(ap, count); - for (i = 0; i < MAXEXPR; i++) - cexpr_esearch_bool[i] = 0; - i = 0; - while ((short) i < count) { - cexpr_esearch_bool[va_arg(ap, int)] = 1; - ++i; - } - va_end(ap); - - CExpr_RecSearchExprTree(expr); -} - -static ENode *CExpr_RecSearchExprTreeReplace(ENode *expr) { - ENodeList *list; - ENode *replaced; - - if (cexpr_rsearch_bool[expr->type]) { - replaced = cexpr_rsearch_callback(expr); - if (!replaced) - return expr; - expr = replaced; - } - - switch (expr->type) { - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EINDIRECT: - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case EFORCELOAD: - case ETYPCON: - case EBITFIELD: - expr->data.monadic = CExpr_RecSearchExprTreeReplace(expr->data.monadic); - return expr; - case EMUL: - case EMULV: - case EDIV: - case EMODULO: - case EADDV: - case ESUBV: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case ELAND: - case ELOR: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case ECOMMA: - case EPMODULO: - case EROTL: - case EROTR: - case EBCLR: - case EBTST: - case EBSET: - expr->data.diadic.left = CExpr_RecSearchExprTreeReplace(expr->data.diadic.left); - expr->data.diadic.right = CExpr_RecSearchExprTreeReplace(expr->data.diadic.right); - return expr; - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case EPRECOMP: - case ETEMP: - case EARGOBJ: - case ELOCOBJ: - case ELABEL: - case EMEMBER: - case EINSTRUCTION: - case EVECTOR128CONST: - return expr; - case EFUNCCALL: - case EFUNCCALLP: - for (list = expr->data.funccall.args; list; list = list->next) - list->node = CExpr_RecSearchExprTreeReplace(list->node); - expr->data.funccall.funcref = CExpr_RecSearchExprTreeReplace(expr->data.funccall.funcref); - return expr; - case ENULLCHECK: - expr->data.nullcheck.nullcheckexpr = CExpr_RecSearchExprTreeReplace(expr->data.nullcheck.nullcheckexpr); - expr->data.nullcheck.condexpr = CExpr_RecSearchExprTreeReplace(expr->data.nullcheck.condexpr); - return expr; - case EMFPOINTER: - expr->data.mfpointer.accessnode = CExpr_RecSearchExprTreeReplace(expr->data.mfpointer.accessnode); - expr->data.mfpointer.mfpointer = CExpr_RecSearchExprTreeReplace(expr->data.mfpointer.mfpointer); - return expr; - case ECOND: - expr->data.cond.cond = CExpr_RecSearchExprTreeReplace(expr->data.cond.cond); - expr->data.cond.expr1 = CExpr_RecSearchExprTreeReplace(expr->data.cond.expr1); - expr->data.cond.expr2 = CExpr_RecSearchExprTreeReplace(expr->data.cond.expr2); - return expr; - default: - CError_FATAL(220); - return NULL; - } -} - -ENode *CExpr_SearchExprTreeReplace(ENode *expr, CExprReplaceCB callback, int count, ...) { - va_list ap; - short i; - - cexpr_rsearch_callback = callback; - - va_start(ap, count); - for (i = 0; i < MAXEXPR; i++) - cexpr_rsearch_bool[i] = 0; - i = 0; - while ((short) i < count) { - cexpr_rsearch_bool[va_arg(ap, int)] = 1; - ++i; - } - va_end(ap); - - return CExpr_RecSearchExprTreeReplace(expr); -} - -static void CExpr_HasFuncCallCallBack(ENode *expr) { - cexpr_hascall = 1; -} - -Boolean CExpr_HasFuncCall(ENode *expr) { - cexpr_hascall = 0; - CExpr_SearchExprTree(expr, CExpr_HasFuncCallCallBack, 2, EFUNCCALL, EFUNCCALLP); - return cexpr_hascall; -} - -void CExpr_AliasTransform(ENode *expr) { - ENode *n; - - Object *obj = expr->data.objref; - if (obj->u.alias.offset) { - n = makediadicnode( - create_objectrefnode(obj->u.alias.object), - intconstnode(TYPE(&stunsignedlong), obj->u.alias.offset), - EADD); - *expr = *n; - } else { - expr->data.objref = obj->u.alias.object; - } -} - -ENode *CExpr_UnaryFloatExpression(ENode *expr) { - return expr; -} - -ENode *CExpr_BinaryFloatExpression(ENode *expr) { - return expr; -} - -ENode *CExpr_NewENode(ENodeType ty) { - ENode *expr = lalloc(sizeof(ENode)); - memclrw(expr, sizeof(ENode)); - expr->type = ty; - return expr; -} - -ENode *CExpr_NewTemplDepENode(TemplDepSubType t) { - ENode *expr = CExpr_NewENode(ETEMPLDEP); - expr->rtype = &sttemplexpr; - expr->data.templdep.subtype = t; - return expr; -} - -ENode *nullnode(void) { - ENode *expr = CExpr_NewENode(EINTCONST); - expr->rtype = (Type *) &stsignedlong; - return expr; -} - -ENode *intconstnode(Type *type, SInt32 value) { - ENode *expr = CExpr_NewENode(EINTCONST); - expr->rtype = type; - CInt64_SetLong(&expr->data.intval, value); - return expr; -} - -ENode *stringconstnode(char *str) { - ENode *expr; - SInt32 size; - - size = strlen(str) + 1; - expr = CExpr_NewENode(ESTRINGCONST); - expr->rtype = CDecl_NewArrayType((Type *) &stchar, size); - expr->data.string.size = size; - expr->data.string.data = str; - expr->data.string.ispascal = 0; - if (copts.const_strings) - expr->flags = Q_CONST; - - expr = makemonadicnode(expr, EINDIRECT); - expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); - return expr; -} - -ENode *forceintegral(ENode *expr) { - if (!IS_TYPE_ENUM(expr->rtype)) { - CError_Error(CErrorStr144); - return nullnode(); - } else { - expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; - return expr; - } -} - -ENode *makemonadicnode(ENode *inner, ENodeType ty) { - ENode *expr = lalloc(sizeof(ENode)); - expr->type = ty; - if ((expr->cost = inner->cost) == 0) - expr->cost = 1; - expr->flags = inner->flags & ENODE_FLAG_QUALS; - expr->rtype = inner->rtype; - expr->data.monadic = inner; - return expr; -} - -ENode *makediadicnode(ENode *left, ENode *right, ENodeType ty) { - ENode *expr = lalloc(sizeof(ENode)); - expr->type = ty; - expr->rtype = left->rtype; - expr->data.diadic.left = left; - expr->data.diadic.right = right; - - if (left->cost != right->cost) { - expr->cost = right->cost; - if (left->cost > expr->cost) - expr->cost = left->cost; - } else { - expr->cost = right->cost + 1; - if (expr->cost > 200) - expr->cost = 200; - } - - expr->flags = (left->flags | right->flags) & ENODE_FLAG_QUALS; - return expr; -} - -ENode *makecommaexpression(ENode *left, ENode *right) { - ENode *expr; - - if (ENODE_IS(right, EINDIRECT) && !ENODE_IS(right->data.monadic, EBITFIELD)) { - Boolean savecpp = copts.cplusplus; - copts.cplusplus = 1; - expr = makediadicnode(left, getnodeaddress(right, 0), ECOMMA); - copts.cplusplus = savecpp; - expr->rtype = expr->data.diadic.right->rtype; - expr = makemonadicnode(expr, EINDIRECT); - } else { - expr = makediadicnode(left, right, ECOMMA); - } - - expr->rtype = right->rtype; - expr->flags = right->flags; - return expr; -} - -short iszero(ENode *expr) { - switch (expr->type) { - case EINTCONST: - return CInt64_IsZero(&expr->data.intval); - case EFLOATCONST: - return CMach_FloatIsZero(expr->data.floatval); - default: - return 0; - } -} - -short isnotzero(ENode *expr) { - Object *obj; - - switch (expr->type) { - case EINTCONST: - return !CInt64_IsZero(&expr->data.intval); - case EFLOATCONST: - return !CMach_FloatIsZero(expr->data.floatval); - case ESTRINGCONST: - case ETEMP: - return 1; - case EOBJREF: - obj = expr->data.objref; - break; - case EADD: - case ESUB: - if (ENODE_IS(expr->data.diadic.left, EOBJREF) && ENODE_IS(expr->data.diadic.right, EINTCONST)) { - obj = expr->data.diadic.left->data.objref; - break; - } - if (ENODE_IS(expr->data.diadic.left, EINTCONST) && ENODE_IS(expr->data.diadic.right, EOBJREF)) { - obj = expr->data.diadic.right->data.objref; - break; - } - return 0; - default: - return 0; - } - - switch (obj->datatype) { - case DLOCAL: - return 1; - default: - return 0; - } -} - -Boolean CExpr_IsOne(ENode *expr) { - if (ENODE_IS(expr, EINTCONST)) - return CInt64_Equal(expr->data.intval, cint64_one); - else if (ENODE_IS(expr, EFLOATCONST)) - return CMach_FloatIsOne(expr->data.floatval); - else - return 0; -} - -Boolean CExpr_AllBitsSet(ENode *expr) { - SInt32 v; - - if (ENODE_IS(expr, EINTCONST)) { - switch (expr->rtype->size) { - case 1: - v = CInt64_GetULong(&expr->data.intval) & 0xFF; - return v == 0xFF; - case 2: - v = CInt64_GetULong(&expr->data.intval) & 0xFFFF; - return v == 0xFFFF; - case 3: - v = CInt64_GetULong(&expr->data.intval) & 0xFFFFFF; - return v == 0xFFFFFF; - case 4: - v = CInt64_GetULong(&expr->data.intval) & 0xFFFFFFFF; - return v == 0xFFFFFFFF; - default: - return CInt64_Equal(expr->data.intval, cint64_negone); - } - } - - return 0; -} - -ENode *CExpr_NewETEMPNode(Type *type, Boolean assign_id) { - ENode *expr = lalloc(sizeof(ENode)); - expr->type = ETEMP; - expr->cost = 0; - expr->flags = 0; - expr->rtype = CDecl_NewPointerType(type); - expr->data.temp.type = type; - expr->data.temp.uniqueid = assign_id ? CParser_GetUniqueID() : 0; - expr->data.temp.needs_dtor = 0; - return expr; -} - -static ENode *CExpr_DerefETEMPCopy(ENode *expr) { - ENode *copy; - - CError_ASSERT(636, IS_TYPE_POINTER_ONLY(expr->rtype)); - - copy = lalloc(sizeof(ENode)); - *copy = *expr; - copy = makemonadicnode(copy, EINDIRECT); - copy->rtype = TYPE_POINTER(copy->rtype)->target; - return copy; -} - -ENode *CExpr_GetETEMPCopy(ENode *expr) { - ENode *newnode; - ENode *assnode; - ENode *finalnode; - - newnode = CExpr_NewETEMPNode(expr->rtype, 1); - newnode->flags = expr->flags; - - assnode = makediadicnode(CExpr_DerefETEMPCopy(newnode), expr, EASS); - assnode->data.diadic.right = lalloc(sizeof(ENode)); - *assnode->data.diadic.right = *expr; - *expr = *assnode; - - finalnode = makemonadicnode(newnode, EINDIRECT); - finalnode->rtype = expr->rtype; - return finalnode; -} - -ENode *integralpromote(ENode *expr) { - if (!IS_TYPE_INT(expr->rtype)) - expr = forceintegral(expr); - - if (TYPE_INTEGRAL(expr->rtype)->integral >= IT_INT) - return expr; - - if (!ENODE_IS(expr, EINTCONST)) - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = (Type *) &stsignedint; - - return expr; -} - -CInt64 CExpr_IntConstConvert(Type *a, Type *b, CInt64 val) { - if (a == (Type *) &stbool) - return CMach_CalcIntDiadic(b, val, TK_LOGICAL_NE, cint64_zero); - else - return CMach_CalcIntDiadic(a, val, '+', cint64_zero); -} - -ENode *promote(ENode *expr, Type *type) { - if (ENODE_IS(expr, EINTCONST)) { - if (IS_TYPE_FLOAT(type)) { - expr->type = EFLOATCONST; - expr->data.floatval = CMach_CalcFloatConvertFromInt(expr->rtype, expr->data.intval); - } else { - expr->data.intval = CExpr_IntConstConvert(type, expr->rtype, expr->data.intval); - } - expr->rtype = type; - return expr; - } - if (ENODE_IS(expr, EFLOATCONST)) { - if (IS_TYPE_FLOAT(type)) { - expr->data.floatval = CMach_CalcFloatConvert(type, expr->data.floatval); - expr->rtype = type; - return expr; - } else if (IS_TYPE_INT(type)) { - expr->data.intval = CMach_CalcIntConvertFromFloat(type, expr->data.floatval); - expr->type = EINTCONST; - expr->rtype = type; - return expr; - } - } - - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = type; - return expr; -} - -void CExpr_ArithmeticConversion(ENode **left, ENode **right) { - switch ((*left)->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - break; - case TYPEENUM: - (*left)->rtype = TYPE_ENUM((*left)->rtype)->enumtype; - break; - default: - CError_Error(CErrorStr144); - (*left) = nullnode(); - } - - switch ((*right)->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - break; - case TYPEENUM: - (*right)->rtype = TYPE_ENUM((*right)->rtype)->enumtype; - break; - default: - CError_Error(CErrorStr144); - (*right) = nullnode(); - } - - if (IS_TYPE_FLOAT((*left)->rtype) || IS_TYPE_FLOAT((*right)->rtype)) { - if ((*left)->rtype != (*right)->rtype) { - if (TYPE_INTEGRAL((*left)->rtype)->integral > TYPE_INTEGRAL((*right)->rtype)->integral) - *right = promote(*right, (*left)->rtype); - else - *left = promote(*left, (*right)->rtype); - } - return; - } - - *left = integralpromote(*left); - *right = integralpromote(*right); - if ((*left)->rtype != (*right)->rtype) { - if (TYPE_INTEGRAL((*left)->rtype)->integral < TYPE_INTEGRAL((*right)->rtype)->integral) { - ENode **tmp = left; - left = right; - right = tmp; - } - - if ((*left)->rtype->size == (*right)->rtype->size && !is_unsigned((*left)->rtype) && is_unsigned((*right)->rtype)) { - if ((*left)->rtype == (Type *) &stsignedlong) { - *left = promote(*left, (Type *) &stunsignedlong); - } else { - CError_ASSERT(838, (*left)->rtype == (Type *) &stsignedlonglong); - *left = promote(*left, (Type *) &stunsignedlonglong); - } - } - - *right = promote(*right, (*left)->rtype); - } -} - -static ENode *CExpr_GetEA(ENode *expr) { - ENode *copy; - - for (;;) { - switch (expr->type) { - case EINDIRECT: - expr = expr->data.monadic; - for (;;) { - switch (expr->type) { - case EOBJREF: - copy = lalloc(sizeof(ENode)); - *copy = *expr; - return copy; - case ECOMMA: - expr = expr->data.diadic.right; - continue; - default: - return CExpr_GetETEMPCopy(expr); - } - } - break; - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - expr = expr->data.monadic; - continue; - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - expr = expr->data.monadic; - continue; - case ECOMMA: - expr = expr->data.diadic.right; - continue; - default: - return NULL; - } - } -} - -ENode *CExpr_TempModifyExpr(ENode *expr) { - Type *type; - ENode *left; - ENode *right; - ENode *eanode; - ENode *tempnode; - ENode *indnode; - ENode *truenode; - - type = expr->rtype; - tempnode = CExpr_NewETEMPNode(type, 1); - eanode = CExpr_GetEA(expr); - if (!eanode) { - CError_Error(CErrorStr142); - return expr; - } - - // tempnode = expr - left = makemonadicnode(tempnode, EINDIRECT); - left->rtype = type; - left = makediadicnode(left, expr, EASS); - - // eanode = true - indnode = makemonadicnode(eanode, EINDIRECT); - indnode->rtype = type; - truenode = nullnode(); - truenode->rtype = (Type *) &stbool; - CInt64_SetLong(&truenode->data.intval, 1); - right = makediadicnode(indnode, truenode, EASS); - - expr = makediadicnode(left, right, ECOMMA); - - indnode = makemonadicnode(tempnode, EINDIRECT); - indnode->rtype = type; - return makediadicnode(expr, indnode, ECOMMA); -} - -Boolean CExpr_IsLValue(ENode *expr) { - while (!ENODE_IS(expr, EINDIRECT)) { - switch (expr->type) { - case EPREINC: - case EPREDEC: - return copts.cplusplus; - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - if (!copts.cplusplus) - return 0; - expr = expr->data.diadic.left; - continue; - case ECOMMA: - if (!copts.cplusplus) - return 0; - expr = expr->data.diadic.right; - continue; - case ECOND: - if ( - copts.cplusplus && - is_typesame(expr->data.cond.expr1->rtype, expr->data.cond.expr2->rtype) && - (expr->data.cond.expr1->rtype->type != TYPEPOINTER || (UInt32) (expr->data.cond.expr1->flags & ENODE_FLAG_QUALS) == (expr->data.cond.expr2->flags & ENODE_FLAG_QUALS)) - ) { - return CExpr_IsLValue(expr->data.cond.expr1) && CExpr_IsLValue(expr->data.cond.expr2); - } - return 0; - default: - return 0; - } - } - - expr = expr->data.monadic; - switch (expr->type) { - case ETEMP: - return 0; - case EFUNCCALL: - if (expr->data.funccall.functype->functype->type != TYPEPOINTER || (expr->data.funccall.functype->flags & FUNC_IS_CTOR)) - return 0; - default: - return 1; - } -} - -ENode *CExpr_LValue(ENode *expr, Boolean flag1, Boolean flag2) { - ENode *eanode; - ENode *tmpnode; - -loop: - switch (expr->type) { - case ETYPCON: - if (copts.pointercast_lvalue || !copts.ANSIstrict) { - if (expr->rtype->type == TYPEPOINTER && expr->data.monadic->rtype->type == TYPEPOINTER) { - switch (expr->data.monadic->type) { - case EINDIRECT: - case ETYPCON: - expr->data.monadic->rtype = expr->rtype; - expr->data.monadic->flags = expr->flags; - expr = expr->data.monadic; - goto loop; - } - } - } - break; - case EINDIRECT: - if (flag2) { - if (!CExpr_IsLValue(expr)) - CError_Warning(CErrorStr142); - - if ( - ENODE_IS(expr->data.monadic, EOBJREF) && - expr->data.monadic->data.objref->name == this_name_node && - cscope_currentfunc && - cscope_currentclass && - expr->data.monadic->data.objref == CClass_ThisSelfObject()) - CError_Error(CErrorStr189); - } - if (flag1) { - if (CParser_IsConst(expr->rtype, expr->flags & ENODE_FLAG_QUALS)) - CError_Error(CErrorStr179); - } - return expr; - case EPREINC: - case EPREDEC: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case ECOMMA: - if (copts.cplusplus) { - if ((eanode = CExpr_GetEA(expr))) { - tmpnode = makediadicnode(expr, eanode, ECOMMA); - tmpnode->rtype = tmpnode->data.diadic.right->rtype; - tmpnode = makemonadicnode(tmpnode, EINDIRECT); - tmpnode->rtype = expr->rtype; - return tmpnode; - } - CError_Error(CErrorStr190); - return expr; - } - break; - case ECOND: - if ( - copts.cplusplus && - is_typesame(expr->data.cond.expr1->rtype, expr->data.cond.expr2->rtype) && - (expr->data.cond.expr1->rtype->type != TYPEPOINTER || (UInt32) (expr->data.cond.expr1->flags & ENODE_FLAG_QUALS) == (expr->data.cond.expr2->flags & ENODE_FLAG_QUALS)) - ) { - expr->data.cond.expr1 = CExpr_LValue(expr->data.cond.expr1, flag1, flag2); - expr->data.cond.expr2 = CExpr_LValue(expr->data.cond.expr2, flag1, flag2); - if (ENODE_IS(expr->data.cond.expr1, EINDIRECT) && ENODE_IS(expr->data.cond.expr2, EINDIRECT)) { - if (!ENODE_IS(expr->data.cond.expr1->data.monadic, EBITFIELD) && !ENODE_IS(expr->data.cond.expr2->data.monadic, EBITFIELD)) { - expr->data.cond.expr1 = getnodeaddress(expr->data.cond.expr1, 0); - expr->data.cond.expr2 = getnodeaddress(expr->data.cond.expr2, 0); - expr->rtype = expr->data.cond.expr1->rtype; - tmpnode = makemonadicnode(expr, EINDIRECT); - tmpnode->rtype = TYPE_POINTER(tmpnode->rtype)->target; - return tmpnode; - } - } - } - break; - } - - if (flag2) - CError_Error(CErrorStr142); - return expr; -} - -ENode *CExpr_MakeObjRefNode(Object *obj, Boolean flag) { - ENode *expr; - - if (obj->sclass == TK_TYPEDEF) { - CError_Error(CErrorStr141); - return intconstnode((Type *) &void_ptr, 0); - } - - expr = lalloc(sizeof(ENode)); - memclrw(expr, sizeof(ENode)); - expr->type = EOBJREF; - expr->data.objref = obj; - expr->rtype = CDecl_NewPointerType(obj->type); - - if (!IS_TYPE_FUNC(obj->type)) - expr->flags = obj->qual & ENODE_FLAG_QUALS; - if (flag) - obj->flags |= OBJECT_USED; - - return expr; -} - -ENode *create_objectrefnode(Object *obj) { - if (name_obj_check && !name_obj_check(NULL, obj)) - return intconstnode((Type *) &void_ptr, 0); - return CExpr_MakeObjRefNode(obj, 1); -} - -ENode *create_objectnode2(Object *obj) { - ENode *expr; - - if (name_obj_check && !name_obj_check(NULL, obj)) - return nullnode(); - - expr = makemonadicnode(CExpr_MakeObjRefNode(obj, 1), EINDIRECT); - expr->rtype = TYPE_POINTER(expr->rtype)->target; - return expr; -} - -ENode *create_objectnode(Object *obj) { - return checkreference(create_objectnode2(obj)); -} - -static ENode *CExpr_ExpandArg(ENode *expr, Type *type) { - if (ENODE_IS(expr, ETYPCON) && IS_TYPE_FLOAT(type)) { - expr->rtype = type; - return expr; - } else { - return promote(expr, type); - } -} - -ENode *CExpr_IsTempConstruction(ENode *expr, Type *type, ENode **resultexpr) { - ENodeList *args; - ENode *funccall; - ENode *funcref; - - if ( - !ENODE_IS(expr, EINDIRECT) || - expr->rtype != type || - !ENODE_IS((funccall = expr->data.monadic), EFUNCCALL) || - !(args = funccall->data.funccall.args) - ) - return NULL; - - if (!ENODE_IS((funcref = funccall->data.funccall.funcref), EOBJREF) || !CClass_IsConstructor(funcref->data.objref)) { - if (expr->data.monadic->data.funccall.functype->functype != type) - return NULL; - if (CABI_GetStructResultArgumentIndex(expr->data.monadic->data.funccall.functype) == 1) { - args = args->next; - CError_ASSERT(1277, args); - } - } - - if (resultexpr) - *resultexpr = args->node; - return expr->data.monadic; -} - -ENode *CExpr_AdjustFunctionCall(ENode *expr) { - ENodeList *list; - - switch (expr->data.funccall.functype->functype->type) { - case TYPECLASS: - CDecl_CompleteType(expr->data.funccall.functype->functype); - case TYPESTRUCT: - if (!expr->data.funccall.functype->functype->size) - CError_Error(CErrorStr136, expr->data.funccall.functype->functype, 0); - } - - if (CMach_GetFunctionResultClass(expr->data.funccall.functype)) { - list = lalloc(sizeof(ENodeList)); - if (IS_TYPE_CLASS(expr->data.funccall.functype->functype)) { - CDecl_CompleteType(expr->data.funccall.functype->functype); - if (CClass_Destructor(TYPE_CLASS(expr->data.funccall.functype->functype))) - list->node = create_temp_node2(expr->rtype); - else - list->node = create_temp_node(expr->rtype); - } else { - list->node = create_temp_node(expr->rtype); - } - list->next = expr->data.funccall.args; - expr->data.funccall.args = list; - - if (expr->data.funccall.funcref->flags & ENODE_FLAG_10) - expr = CSOM_EnvCheck(expr, list); - - expr = makemonadicnode(expr, EINDIRECT); - expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype); - return expr; - } - - if (expr->data.funccall.funcref->flags & ENODE_FLAG_10) - expr = CSOM_EnvCheck(expr, NULL); - return expr; -} - -ENode *funccallexpr(Object *func, ENode *arg1, ENode *arg2, ENode *arg3, ENode *arg4) { - ENode *expr; - TypeFunc *tfunc; - ENodeList *list; - - tfunc = TYPE_FUNC(func->type); - CError_ASSERT(1411, IS_TYPE_FUNC(tfunc)); - - expr = lalloc(sizeof(ENode)); - expr->type = EFUNCCALL; - expr->cost = 4; - expr->rtype = tfunc->functype; - expr->flags = tfunc->qual & ENODE_FLAG_QUALS; - expr->data.funccall.funcref = create_objectrefnode(func); - expr->data.funccall.functype = tfunc; - - if (arg1) { - list = lalloc(sizeof(ENodeList)); - expr->data.funccall.args = list; - list->node = arg1; - if (arg2) { - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->node = arg2; - if (arg3) { - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->node = arg3; - if (arg4) { - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->node = arg4; - } - } - } - list->next = NULL; - } else { - expr->data.funccall.args = NULL; - } - - return CExpr_AdjustFunctionCall(expr); -} - -ENode *CExpr_FuncCallSix(Object *func, ENode *arg1, ENode *arg2, ENode *arg3, ENode *arg4, ENode *arg5, ENode *arg6) { - ENode *expr; - TypeFunc *tfunc; - ENodeList *list; - - tfunc = TYPE_FUNC(func->type); - CError_ASSERT(1460, IS_TYPE_FUNC(tfunc)); - - expr = lalloc(sizeof(ENode)); - expr->type = EFUNCCALL; - expr->cost = 4; - expr->rtype = tfunc->functype; - expr->flags = tfunc->qual & ENODE_FLAG_QUALS; - expr->data.funccall.funcref = create_objectrefnode(func); - expr->data.funccall.functype = tfunc; - - list = lalloc(sizeof(ENodeList)); - expr->data.funccall.args = list; - list->node = arg1; - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->node = arg2; - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->node = arg3; - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->node = arg4; - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->node = arg5; - if (arg6) { - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->node = arg6; - } - list->next = NULL; - - return CExpr_AdjustFunctionCall(expr); -} - -static void CExpr_CalcStdAssign(short checkresult, Match5 *match, Type *t1, UInt32 q1, Type *t2, UInt32 q2, Boolean flag) { - memclrw(match, sizeof(Match5)); - switch (checkresult) { - case CheckResult1: - match->x0++; - break; - case CheckResult2: - match->x2++; - break; - case CheckResult3: - match->x4++; - match->x6 += assign_value; - break; - default: - CError_FATAL(1504); - } - - if (flag || (IS_TYPE_POINTER_ONLY(t2) && (IS_TYPE_POINTER_ONLY(t1) || IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(t2))) != 0)) { - if ((q2 & Q_CONST) == (q1 & Q_CONST)) - match->x8++; - if ((q2 & Q_VOLATILE) == (q1 & Q_VOLATILE)) - match->x8++; - } -} - -void CExpr_MatchCV(Type *t1, UInt32 q1, Type *t2, UInt32 q2, Match13 *match) { - Boolean r8; - - if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(t2))) { - t2 = TYPE_POINTER(t2)->target; - r8 = 1; - } else { - r8 = 0; - } - - while (IS_TYPE_POINTER_ONLY(t2) && IS_TYPE_POINTER_ONLY(t1)) { - if (r8) { - if ((TYPE_POINTER(t1)->qual & Q_CONST) != (TYPE_POINTER(t2)->qual & Q_CONST)) - match->anotherm5.x8--; - if ((TYPE_POINTER(t1)->qual & Q_VOLATILE) != (TYPE_POINTER(t2)->qual & Q_VOLATILE)) - match->anotherm5.x8--; - } - t2 = TYPE_POINTER(t2)->target; - t1 = TYPE_POINTER(t1)->target; - r8 = 1; - } - - if ((q1 & Q_CONST) != (q2 & Q_CONST)) - match->anotherm5.x8--; - if ((q1 & Q_VOLATILE) != (q2 & Q_VOLATILE)) - match->anotherm5.x8--; -} - -Boolean CExpr_MatchAssign(Type *type, UInt32 qual, ENode *expr, Match13 *match) { - switch (assign_check(expr, type, qual, 0, 0, 1)) { - case CheckResult0: - return 0; - case CheckResult1: - match->anotherm5.x0++; - break; - case CheckResult2: - match->anotherm5.x2++; - break; - case CheckResult3: - match->anotherm5.x4++; - match->anotherm5.x6 += assign_value; - break; - case CheckResult4: - match->xE++; - match->match5.x0 += user_std_match.x0; - match->match5.x2 += user_std_match.x2; - match->match5.x4 += user_std_match.x4; - match->match5.x6 += user_std_match.x6; - match->match5.x8 += user_std_match.x8; - break; - default: - CError_FATAL(1585); - } - - if (IS_TYPE_POINTER_ONLY(type)) - CExpr_MatchCV(expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, qual, match); - - return 1; -} - -static short CExpr_StdMatchCompare(Match5 *a, Match5 *b, Boolean flag) { - if (a->x0 > b->x0) return 1; - if (a->x0 == b->x0) { - if (a->x2 > b->x2) return 1; - if (a->x2 == b->x2) { - if (a->x4 > b->x4) return 1; - if (a->x4 == b->x4) { - if (a->x6 > b->x6) return 1; - if (a->x6 == b->x6) { - if (!flag) - return 0; - if (a->x8 > b->x8) return 1; - if (a->x8 == b->x8) return 0; - } - } - } - } - return -1; -} - -static short CExpr2_MemberPointerConversion(Type *type, ENode *expr, Boolean flag1) { - ENode *newnode; - short depth; - - newnode = lalloc(sizeof(ENode)); - *newnode = *expr; - if (!IS_TYPE_MEMBERPOINTER(newnode->rtype)) { - newnode = CExpr_MemberPointerConversion(newnode, TYPE_MEMBER_POINTER(type), flag1); - if (iscpp_typeequal(newnode->rtype, type)) { - if (flag1) - assign_node = newnode; - return CheckResult3; - } - } - - if (IS_TYPE_MEMBERPOINTER(newnode->rtype)) { - CError_ASSERT(1656, IS_TYPE_CLASS(TYPE_MEMBER_POINTER(type)->ty2)); - CError_ASSERT(1657, IS_TYPE_CLASS(TYPE_MEMBER_POINTER(newnode->rtype)->ty2)); - - if (CClass_IsBaseClass(TYPE_CLASS(TYPE_MEMBER_POINTER(type)->ty2), TYPE_CLASS(TYPE_MEMBER_POINTER(newnode->rtype)->ty2), &depth, 0, 0)) { - assign_value = 1000 - depth; - if (flag1) - assign_node = PointerToMemberCast(newnode, TYPE_MEMBER_POINTER(newnode->rtype), TYPE_MEMBER_POINTER(type), 1); - return CheckResult3; - } - } - - return CheckResult0; -} - -ENode *CExpr_ClassPointerCast(BClassList *cls, ENode *origexpr, Boolean nullcheckflag) { - ENode *expr; - ClassList *base; - Boolean do_nullcheck; - TypeClass *tclass; - SInt32 offset; - ENode *tmp; - - expr = origexpr; - tclass = TYPE_CLASS(cls->type); - do_nullcheck = 0; - CError_ASSERT(1691, cls); - - if (!IS_TYPE_POINTER_ONLY(origexpr->rtype)) { - CError_Error(CErrorStr141); - return origexpr; - } - - cls = cls->next; - while (cls) { - for (base = tclass->bases; base; base = base->next) { - if (base->base == TYPE_CLASS(cls->type)) - break; - } - - if (!base) { - CError_Error(CErrorStr221); - while (cls->next) - cls = cls->next; - - tmp = nullnode(); - tmp->rtype = CDecl_NewPointerType(cls->type); - return tmp; - } - - if (base->is_virtual) { - if (!base->base->sominfo) { - do_nullcheck = 1; - if ((offset = base->offset) && !canadd(expr, offset)) { - expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); - optimizecomm(expr); - } - expr->rtype = CDecl_NewPointerType(CDecl_NewPointerType(TYPE(base->base))); - expr = makemonadicnode(expr, EINDIRECT); - } - } else { - if ((offset = base->offset)) { - do_nullcheck = 1; - if (!canadd(expr, offset)) { - expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); - optimizecomm(expr); - } - } - } - - switch (expr->type) { - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - expr = makemonadicnode(expr, ETYPCON); - } - - expr->rtype = CDecl_NewPointerType(TYPE(base->base)); - tclass = TYPE_CLASS(cls->type); - cls = cls->next; - } - - if (nullcheckflag && do_nullcheck) - expr = do_castnullcheck(expr, origexpr); - return expr; -} - -ENode *CExpr_GetClassAccessNode(BClassList *a, BClassList *b, ENode *expr, Object *obj, AccessType access, Boolean flag) { - TypeClass *tclass; - ENode *tmp; - - if (!expr) { - if (!cscope_currentfunc || !cscope_currentclass || !cscope_is_member_func || !(expr = CClass_CreateThisSelfExpr())) { - CError_Error(CErrorStr221); - return NULL; - } - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = TYPE(cscope_currentclass); - } - - CError_ASSERT(1786, a); - CError_ASSERT(1787, IS_TYPE_CLASS(expr->rtype)); - - tclass = TYPE_CLASS(expr->rtype); - a = CScope_GetClassAccessPath(a, tclass); - if (!a || a->type != TYPE(tclass)) { - CError_Error(CErrorStr221); - return NULL; - } - - if (flag) - CClass_CheckPathAccess(a, obj, access); - - if (!TYPE_CLASS(a->type)->sominfo) { - if (b) - a = CClass_AppendPath(a, b); - - if (!ENODE_IS(expr, EINDIRECT)) - expr = CExpr_LValue(expr, 0, 0); - - if (ENODE_IS(expr, EINDIRECT)) { - expr->data.monadic->flags = expr->flags; - tmp = expr->data.monadic; - switch (tmp->type) { - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - tmp = makemonadicnode(tmp, ETYPCON); - } - expr = makemonadicnode(CExpr_ClassPointerCast(a, tmp, 0), EINDIRECT); - expr->rtype = TYPE(tclass); - } - } - - return expr; -} - -static short std_assign_check_overload(NameSpaceObjectList *list, TemplArg *templargs, Type *type, Boolean flag1) { - Object *obj; - Object *used_obj; - Boolean found_non_template_func; - Boolean is_ambig; - TemplFuncInstance *instance; - ENode *expr; - Object *cmp1; - Object *cmp2; - - if (!IS_TYPE_POINTER_ONLY(type) || !IS_TYPE_FUNC(TYPE_POINTER(type)->target)) - return CheckResult0; - - used_obj = NULL; - type = TYPE_POINTER(type)->target; - found_non_template_func = 0; - is_ambig = 0; - for (; list; list = list->next) { - obj = OBJECT(list->object); - if (obj->otype != OT_OBJECT) - continue; - - if (IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_IS_TEMPL)) { - if (!found_non_template_func && CTempl_CanDeduceFunc(obj, TYPE_FUNC(type), templargs)) { - instance = CTempl_DeduceFunc(obj, TYPE_FUNC(type), templargs, NULL, 0); - CError_ASSERT(1861, instance); - if (is_typesame(instance->object->type, type)) { - if (used_obj && used_obj != instance->object) - is_ambig = 1; - else - used_obj = instance->object; - } - } - } else { - if (is_typesame(obj->type, type)) { - if (used_obj && found_non_template_func) { - cmp1 = obj; - if (obj->datatype == DALIAS) - cmp1 = obj->u.alias.object; - cmp2 = used_obj; - if (used_obj->datatype == DALIAS) - cmp2 = used_obj->u.alias.object; - if (cmp1 != cmp2) - is_ambig = 1; - } else { - is_ambig = 0; - used_obj = obj; - } - found_non_template_func = 1; - } - } - } - - if (used_obj) { - if (flag1) { - if (is_ambig) - CError_Error(CErrorStr199); - expr = CExpr_MakeObjRefNode(used_obj, 1); - assign_node = expr; - expr->rtype = CDecl_NewPointerType(used_obj->type); - expr->flags = obj->qual & ENODE_FLAG_QUALS; - used_obj->flags |= OBJECT_USED; - if (used_obj->datatype == DINLINEFUNC) - CError_Error(CErrorStr175); - } - return CheckResult1; - } else { - return CheckResult0; - } -} - -ENode *CExpr_ConvertToBool(ENode *expr, Boolean isExplicit) { - if (IS_TYPE_MEMBERPOINTER(expr->rtype)) - expr = CExpr_ConvertToCondition(expr); - - switch (expr->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - case TYPEPOINTER: - if (IS_TYPE_ENUM(expr->rtype)) - expr = forceintegral(expr); - switch (expr->type) { - case EINTCONST: - CInt64_SetLong(&expr->data.intval, !CInt64_IsZero(&expr->data.intval)); - break; - case EFLOATCONST: - CInt64_SetLong(&expr->data.intval, !CMach_FloatIsZero(expr->data.floatval)); - expr->type = EINTCONST; - break; - default: - expr = makemonadicnode(expr, ELOGNOT); - expr->rtype = TYPE(&stbool); - expr = makemonadicnode(expr, ELOGNOT); - } - break; - default: - CError_Error( - isExplicit ? CErrorStr247 : CErrorStr209, - expr->rtype, - expr->flags & ENODE_FLAG_QUALS, - &stbool, - 0); - expr = nullnode(); - } - - expr->rtype = TYPE(&stbool); - return expr; -} - -static short std_assign_check(ENode *expr, Type *type, Boolean flag1, Boolean flag2) { - short result; - - if (copts.cplusplus) { - illegalimplicitconversion = 0; - - if ((result = iscpp_typeequal(expr->rtype, type))) { - assign_node = expr; - if (result == -1) { - assign_value = 1; - return CheckResult3; - } else { - return CheckResult1; - } - } - - if (flag1 && illegalimplicitconversion) { - CError_Error(CErrorStr209, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, 0); - return CheckResult0; - } - } else { - if (is_typeequal(expr->rtype, type)) { - assign_node = expr; - return CheckResult1; - } - } - - if (type == TYPE(&stbool)) { - switch (expr->rtype->type) { - case TYPEPOINTER: - case TYPEMEMBERPOINTER: - assign_value = 0; - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - if (flag1) - assign_node = CExpr_ConvertToBool(expr, 0); - return CheckResult3; - default: - return CheckResult0; - } - } - - if (IS_TYPE_ENUM(expr->rtype) && (IS_TYPE_INT(type) || IS_TYPE_FLOAT(type))) { - result = CheckResult3; - if (IS_TYPE_INT(type)) { - if (TYPE_ENUM(expr->rtype)->enumtype == type) { - result = CheckResult2; - } else if (TYPE_INTEGRAL(TYPE_ENUM(expr->rtype)->enumtype)->integral < IT_INT) { - switch (TYPE_INTEGRAL(type)->integral) { - case IT_INT: - if (expr->rtype->size < stsignedint.size || TYPE_ENUM(expr->rtype)->enumtype == TYPE(&stsignedshort)) - result = CheckResult2; - break; - case IT_UINT: - if (expr->rtype->size >= stsignedint.size && TYPE_ENUM(expr->rtype)->enumtype != TYPE(&stsignedshort)) - result = CheckResult2; - break; - } - } - } - if (flag1) { - expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; - assign_node = promote(expr, type); - } - return result; - } - - if (IS_TYPE_INT(expr->rtype) && (IS_TYPE_INT(type) || IS_TYPE_FLOAT(type))) { - result = CheckResult3; - if (TYPE_INTEGRAL(expr->rtype)->integral <= IT_INT) { - if (type == TYPE(&stsignedint) || type == TYPE(&stunsignedint)) { - switch (TYPE_INTEGRAL(type)->integral) { - case IT_INT: - if (expr->rtype->size < stsignedint.size || type != TYPE(&stunsignedshort)) - result = CheckResult2; - break; - case IT_UINT: - if (expr->rtype->size == stsignedint.size && type == TYPE(&stunsignedshort)) - result = CheckResult2; - break; - } - } - } - - if (flag1 && type != expr->rtype) - assign_node = promote(expr, type); - else - assign_node = expr; - return result; - } - - if (IS_TYPE_FLOAT(expr->rtype) && (IS_TYPE_INT(type) || IS_TYPE_FLOAT(type))) { - if (type == TYPE(&stdouble) && (expr->rtype == TYPE(&stfloat) || expr->rtype == TYPE(&stshortdouble))) - result = CheckResult2; - else - result = CheckResult3; - - if (flag1 && (!IS_TYPE_FLOAT(type) || type->size != expr->rtype->size)) - assign_node = promote(expr, type); - else - assign_node = expr; - return result; - } - - if (IS_TYPE_POINTER_ONLY(type)) { - if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval) && (IS_TYPE_INT(expr->rtype) || (!copts.cplusplus && IS_TYPE_ENUM(expr->rtype)))) { - if (flag1) - expr->rtype = TYPE(&stunsignedlong); - assign_node = expr; - return CheckResult3; - } - if (ENODE_IS(expr, EOBJLIST)) { - return std_assign_check_overload(expr->data.objlist.list, expr->data.objlist.templargs, type, flag1); - } - if (IS_TYPE_POINTER_ONLY(expr->rtype)) { - if (ENODE_IS(expr, EOBJREF) && IS_TYPE_FUNC(expr->data.objref->type) && (TYPE_FUNC(expr->data.objref->type)->flags & FUNC_IS_TEMPL)) { - NameSpaceObjectList list; - list.next = NULL; - list.object = OBJ_BASE(expr->data.objref); - return std_assign_check_overload(&list, NULL, type, flag1); - } - if (copts.objective_c && CObjC_IsCompatibleType(expr->rtype, type)) { - assign_value = 1; - return CheckResult3; - } - if (IS_TYPE_CLASS(TYPE_POINTER(expr->rtype)->target) && IS_TYPE_CLASS(TYPE_POINTER(type)->target)) { - short depth; - Boolean isambig; - BClassList *path; - path = CClass_GetBasePath( - TYPE_CLASS(TYPE_POINTER(expr->rtype)->target), - TYPE_CLASS(TYPE_POINTER(type)->target), - &depth, &isambig - ); - if (path) { - assign_value = 1000 - depth; - if (flag1) { - if (isambig) - CError_Error(CErrorStr188); - if (flag2) - CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); - assign_node = CExpr_ClassPointerCast(path, expr, 1); - } - return CheckResult3; - } else { - if (flag1) { - if (isambig) - CError_Error(CErrorStr188); - else - CError_Error( - CErrorStr244, - expr->rtype, - expr->flags & ENODE_FLAG_QUALS, - type, - 0); - } - return CheckResult0; - } - } - } - } - - if (IS_TYPE_MEMBERPOINTER(type) && !IS_TYPE_CLASS(expr->rtype)) { - return CExpr2_MemberPointerConversion(type, expr, flag1); - } - - if (IS_TYPE_CLASS(expr->rtype) && IS_TYPE_CLASS(type)) { - short depth; - Boolean isambig; - BClassList *path; - path = CClass_GetBasePath( - TYPE_CLASS(expr->rtype), - TYPE_CLASS(type), - &depth, &isambig - ); - if (path) { - assign_value = 1000 - depth; - if (flag1) { - if (isambig) - CError_Error(CErrorStr188); - CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); - assign_node = getnodeaddress(expr, 0); - assign_node = CExpr_ClassPointerCast(path, assign_node, 0); - assign_node = makemonadicnode(assign_node, EINDIRECT); - assign_node->rtype = type; - } - return CheckResult3; - } - } - - if (IS_TYPE_ENUM(type)) { - switch (expr->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - if (!copts.cplusplus) { - if (flag1) { - if (copts.pedantic) - CError_Warning(CErrorStr217, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, 0); - assign_node = do_typecast(expr, type, 0); - assign_node->flags = expr->flags; - } - return CheckResult2; - } else { - if (flag1) - CError_Error(CErrorStr217, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, 0); - } - } - } - - return CodeGen_AssignCheck(expr, type, flag1, flag2); -} - -static short is_compatible_conversion(Type *a, Type *b) { - if (IS_TYPE_REFERENCE(a)) - a = TYPE_POINTER(a)->target; - if (IS_TYPE_REFERENCE(b)) - b = TYPE_POINTER(b)->target; - return iscpp_typeequal(b, a); -} - -static void CExpr_ConIteratorInit(ConIterator *iter) { - ClassList *base; - ConIterator *subiter; - ConIteratorList *list; - - for (base = iter->tclass->bases; base; base = base->next) { - if (base->base->flags & CLASS_IS_CONVERTIBLE) { - subiter = galloc(sizeof(ConIterator)); - memclrw(subiter, sizeof(ConIterator)); - subiter->parent = iter; - subiter->tclass = base->base; - CExpr_ConIteratorInit(subiter); - - list = galloc(sizeof(ConIteratorList)); - memclrw(list, sizeof(ConIteratorList)); - list->iter = subiter; - list->next = iter->children; - iter->children = list; - } - } -} - -void CExpr_ConversionIteratorInit(ConversionIterator *iter, TypeClass *tclass) { - memclrw(iter, sizeof(ConversionIterator)); - if (tclass->flags & CLASS_IS_CONVERTIBLE) { - iter->coniter = &iter->myconiter; - iter->myconiter.tclass = tclass; - CExpr_ConIteratorInit(&iter->myconiter); - CScope_InitObjectIterator(&iter->objiter, tclass->nspace); - } -} - -static Boolean CExpr_ConversionIteratorIsHidden(ConIterator *iter, TypeFunc *tfunc) { - CScopeObjectIterator objiter; - ObjBase *obj; - TypeFunc *objtfunc; - - while (iter) { - CScope_InitObjectIterator(&objiter, iter->tclass->nspace); - while (1) { - if (!(obj = CScope_NextObjectIteratorObject(&objiter))) - break; - - objtfunc = TYPE_FUNC(OBJECT(obj)->type); - if ( - IS_TYPE_FUNC(objtfunc) && - (objtfunc->flags & FUNC_CONVERSION) && - is_compatible_conversion(tfunc->functype, objtfunc->functype) && - (tfunc->args->qual & Q_CONST) == (objtfunc->args->qual & Q_CONST) && - (tfunc->qual & Q_CONST) == (objtfunc->qual & Q_CONST) - ) - return 1; - } - iter = iter->parent; - } - - return 0; -} - -Object *CExpr_ConversionIteratorNext(ConversionIterator *iter) { - ConIterator *ci; - Object *obj; - - ci = iter->coniter; - if (!ci) - return NULL; - -restart: - if ((obj = OBJECT(CScope_NextObjectIteratorObject(&iter->objiter)))) { - if ( - IS_TYPE_FUNC(obj->type) && - (TYPE_FUNC(obj->type)->flags & FUNC_CONVERSION) && - !CExpr_ConversionIteratorIsHidden(ci->parent, TYPE_FUNC(obj->type)) - ) { - return obj; - } - goto restart; - } - - do { - if (ci->children) { - iter->coniter = ci->children->iter; - ci->children = ci->children->next; - ci = iter->coniter; - CScope_InitObjectIterator(&iter->objiter, ci->tclass->nspace); - goto restart; - } - } while ((ci = ci->parent)); - - return NULL; -} - -short user_assign_check(ENode *expr, Type *type, UInt32 qual, Boolean flag1, Boolean flag2, Boolean flag3) { - Object *r26; - ENode *r25; - Boolean r24; - Boolean r23; - Boolean r22; - Type *r18b; - short r18; - TypeFunc *r17; - Object *r17b; - NameSpaceObjectList *r16b; - Object *r16; - Object *r15; - ENode *r15b; - ENode *r14; - short r14b; - TypeFunc *r14c; - ENodeList *r14d; - TypeMemberFunc *r13; - ENodeList *r13b; - short result; - FuncArg *arg; - ConversionIterator iter; - Match5 stdmatch; - Match5 match_8C; - Match5 match_98; - BClassList path; - UInt16 chk; - Boolean is_const, is_volatile; - - CError_ASSERT(2378, copts.old_argmatch); - - memclrw(&stdmatch, sizeof(Match5)); - r24 = 0; - r22 = 0; - r23 = 0; - - if (!type->size) - CDecl_CompleteType(type); - if (!expr->rtype->size) - CDecl_CompleteType(expr->rtype); - - if (IS_TYPE_CLASS(expr->rtype)) { - r18 = 0; - CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(expr->rtype)); - while ((r16 = CExpr_ConversionIteratorNext(&iter))) { - r17 = TYPE_FUNC(r16->type); - r14 = CExpr_NewENode(ETEMP); - r14->rtype = r17->functype; - if (IS_TYPE_REFERENCE(r14->rtype)) { - r14->rtype = TYPE_POINTER(r14->rtype)->target; - if (!CParser_IsConst(r14->rtype, r17->qual)) { - r14 = makemonadicnode(r14, EINDIRECT); - r14->data.monadic->rtype = TYPE(&void_ptr); - r14 = makemonadicnode(r14, EINDIRECT); - r14->data.monadic->rtype = TYPE(&void_ptr); - } - } - if ((result = std_assign_check(r14, type, 0, flag3))) { - CExpr_CalcStdAssign(result, &match_98, r17->functype, r17->qual, type, qual, 1); - CError_ASSERT(2419, r17->args && IS_TYPE_POINTER_ONLY(r17->args->type)); - chk = expr->flags; - if (!(is_const = (r17->args->qual & Q_CONST)) && (chk & Q_CONST) != 0) - continue; - if (!(is_volatile = (r17->args->qual & Q_VOLATILE)) && (chk & Q_VOLATILE) != 0) - continue; - //if (((r17->args->qual & Q_CONST) == 0 && (chk & Q_CONST) != 0) || ((r17->args->qual & Q_VOLATILE) == 0 && (chk & Q_VOLATILE) != 0)) - // continue; - - r14b = 0; - if (is_const == (expr->flags & Q_CONST)) - r14b++; - if (is_volatile == (expr->flags & Q_VOLATILE)) - r14b++; - switch (CExpr_StdMatchCompare(&match_98, &stdmatch, 1)) { - case -1: - continue; - case 0: - if (r26 == r16) - continue; - if (r14b < r18) - continue; - if (r14b != r18) - break; - r22 = 1; - continue; - } - r26 = r16; - stdmatch = match_98; - r24 = 1; - r22 = 0; - r18 = r14b; - } - } - } - - if (IS_TYPE_CLASS(type) && (r16b = CClass_Constructor(TYPE_CLASS(type)))) { - memclrw(&match_8C, sizeof(Match5)); - for (; r16b; r16b = r16b->next) { - r17b = OBJECT(r16b->object); - if (r17b->otype != OT_OBJECT) - continue; - r14c = TYPE_FUNC(r17b->type); - if (!IS_TYPE_FUNC(r14c)) - continue; - if (!flag2 && (r14c->qual & Q_EXPLICIT)) - continue; - if (!r14c->args) - continue; - if (!(arg = r14c->args->next)) - continue; - if ((TYPE_CLASS(type)->flags & CLASS_HAS_VBASES) && !(arg = arg->next)) - continue; - if (arg == &elipsis) - continue; - if (arg->next && !arg->next->dexpr && arg->next != &elipsis) - continue; - - r18b = arg->type; - if (IS_TYPE_REFERENCE(r18b)) { - r18b = TYPE_POINTER(r18b)->target; - if (!CParser_IsConst(r18b, arg->qual) && !CExpr_IsLValue(expr)) - continue; - } - - if ((result = std_assign_check(expr, r18b, 0, flag3))) { - CExpr_CalcStdAssign(result, &match_98, r14c->functype, r14c->qual, type, qual, 0); - switch (CExpr_StdMatchCompare(&match_98, &match_8C, 1)) { - case -1: - case 0: - continue; - } - r25 = expr; - match_8C = match_98; - r23 = 1; - r15 = r17b; - } - } - - if (r23) { - if (r24) { - switch (CExpr_StdMatchCompare(&stdmatch, &match_8C, 1)) { - case -1: - stdmatch = match_8C; - r24 = 0; - break; - case 0: - r22 = 1; - break; - } - } else { - stdmatch = match_8C; - } - } - } - - if (r22 && flag1) - CError_Error(CErrorStr199); - - if (r24 || r23) { - if (flag1) { - if (r24) { - r13 = TYPE_METHOD(r26->type); - CError_ASSERT(2537, r13->flags & FUNC_METHOD); - r15b = create_objectrefnode(r26); - r26->flags |= OBJECT_USED; - r14d = lalloc(sizeof(ENodeList)); - r14d->next = NULL; - expr = getnodeaddress(expr, 0); - r14d->node = CExpr_AssignmentPromotion(expr, CDecl_NewPointerType(TYPE(r13->theclass)), expr->flags, 0); - - expr = lalloc(sizeof(ENode)); - expr->type = EFUNCCALL; - expr->cost = 4; - expr->rtype = r13->functype; - expr->flags = r13->qual & ENODE_FLAG_QUALS; - expr->data.funccall.funcref = r15b; - expr->data.funccall.args = r14d; - expr->data.funccall.functype = TYPE_FUNC(r26->type); - assign_node = checkreference(CExpr_AdjustFunctionCall(expr)); - if (assign_node->rtype != type) - assign_node = CExpr_AssignmentPromotion(assign_node, type, qual, 1); - if (!IS_TYPE_REFERENCE(r13->functype)) - temp_reference_init = 1; - } else { - r13b = lalloc(sizeof(ENodeList)); - r13b->next = NULL; - r13b->node = r25; - if (TYPE_CLASS(type)->flags & CLASS_HAS_VBASES) { - r13b->next = lalloc(sizeof(ENodeList)); - r13b->next->node = r25; - r13b->next->next = NULL; - r13b->node = intconstnode(TYPE(&stsignedshort), 1); - } - path.next = NULL; - path.type = type; - assign_node = makemonadicnode(create_temp_node(type), EINDIRECT); - assign_node->rtype = type; - assign_node = CExpr_GenericFuncCall(&path, assign_node, 0, r15, NULL, NULL, r13b, 0, 0, 1); - if (ENODE_IS2(assign_node, EFUNCCALL, EFUNCCALLP)) { - assign_node->rtype = CDecl_NewPointerType(type); - assign_node = makemonadicnode(assign_node, EINDIRECT); - assign_node->rtype = type; - } - temp_reference_init = 1; - } - } - - user_std_match = stdmatch; - return CheckResult4; - } else { - if (flag1) - CError_Error(CErrorStr244, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, qual); - return CheckResult0; - } -} - -ENode *CExpr_ConvertToCondition(ENode *expr) { - switch (expr->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEPOINTER: - return expr; - case TYPEENUM: - expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; - return expr; - case TYPEMEMBERPOINTER: - return memberpointercompare(ENOTEQU, expr, nullnode()); - case TYPECLASS: - return CExpr_Convert(expr, TYPE(&stbool), 0, 0, 1); - default: - CError_Error(CErrorStr376, expr->rtype, expr->flags & ENODE_FLAG_QUALS); - return nullnode(); - } -} - -ENode *CExpr_ConvertToIntegral(ENode *expr) { - ConversionIterator iter; - Type *found; - Object *obj; - - switch (expr->rtype->type) { - case TYPEINT: - case TYPEENUM: - return integralpromote(expr); - case TYPECLASS: - CDecl_CompleteType(expr->rtype); - found = NULL; - CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(expr->rtype)); - while ((obj = CExpr_ConversionIteratorNext(&iter))) { - if (IS_TYPE_INT_OR_ENUM(TYPE_FUNC(obj->type)->functype)) { - if (found) { - CError_Error(CErrorStr199); - break; - } - found = TYPE_FUNC(obj->type)->functype; - } - } - if (found) - return integralpromote(CExpr_Convert(expr, found, 0, 0, 1)); - break; - } - - CError_Error(CErrorStr376, expr->rtype, expr->flags & ENODE_FLAG_QUALS); - return nullnode(); -} - -void CExpr_CheckArithmConversion(ENode *expr, Type *type) { - CInt64 val; - - if (expr->rtype == type) - return; - if (expr->rtype == TYPE(&stbool)) - return; - - if (IS_TYPE_INT(expr->rtype)) { - if (IS_TYPE_FLOAT(type)) - return; - CError_ASSERT(2772, IS_TYPE_INT(type)); - - if (type->size > expr->rtype->size) - return; - if (type->size == expr->rtype->size && is_unsigned(type) == is_unsigned(expr->rtype)) - return; - - switch (expr->type) { - case EINTCONST: - if (!CInt64_IsNegative(&expr->data.intval) || is_unsigned(expr->rtype) || !is_unsigned(type)) { - val = CExpr_IntConstConvert(type, expr->rtype, expr->data.intval); - val = CExpr_IntConstConvert(expr->rtype, type, val); - if (CInt64_Equal(val, expr->data.intval)) - return; - } - break; - case ELOGNOT: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case ELAND: - case ELOR: - return; - } - } else { - if (IS_TYPE_FLOAT(type) && type->size >= expr->rtype->size) - return; - } - - CError_Warning(CErrorStr317, expr->rtype, 0, type, 0); -} - -ENode *get_address_of_temp_copy(ENode *expr, Boolean flag) { - char buf[64]; - ENode *result; - Object *obj; - Type *innertype; - - if (flag) { - if (ENODE_IS2(expr, EINTCONST, EFLOATCONST)) { - obj = CParser_NewCompilerDefDataObject(); - obj->type = expr->rtype; - obj->name = CParser_GetUniqueName(); - obj->sclass = TK_STATIC; - if (ENODE_IS(expr, EINTCONST)) { - innertype = expr->rtype; - switch (innertype->type) { - case TYPEINT: - break; - case TYPEENUM: - innertype = TYPE_ENUM(innertype)->enumtype; - break; - case TYPEPOINTER: - innertype = TYPE(&stunsignedlong); - break; - default: - CError_FATAL(2857); - } - CMach_InitIntMem(innertype, expr->data.intval, buf); - } else { - CMach_InitFloatMem(expr->rtype, expr->data.floatval, buf); - } - CInit_DeclareData(obj, buf, NULL, obj->type->size); - return create_objectrefnode(obj); - } - - if (cinit_tempnodefunc == NULL) - result = CExpr_NewETEMPNode(expr->rtype, 1); - else - result = cinit_tempnodefunc(expr->rtype, 0); - result = makemonadicnode(result, EINDIRECT); - result->rtype = TYPE_POINTER(result->rtype)->target; - return makecommaexpression(makediadicnode(result, expr, EASS), result->data.monadic); - } else { - result = nullnode(); - CInt64_SetLong(&result->data.intval, -1); - result->rtype = CDecl_NewPointerType(expr->rtype); - return result; - } -} - -short assign_check(ENode *expr, Type *type, UInt32 qual, Boolean flag1, Boolean flag2, Boolean flag3) { - Type *type2; - Boolean r30; - Boolean r29; - short result; - - assign_value = 1000; - r30 = 0; - r29 = 0; - temp_reference_init = 0; - - type2 = type; - if (IS_TYPE_REFERENCE(type) && !IS_TYPE_FUNC(TYPE_POINTER(type)->target)) { - type2 = TYPE_POINTER(type)->target; - r30 = 1; - } - - assign_node = expr; - if (IS_TYPE_ARRAY(type2)) { - r29 = 1; - type2 = CDecl_NewPointerType(TYPE_POINTER(type2)->target); - } - - if (!type2->size) { - CDecl_CompleteType(type2); - if (!type2->size && !r30) { - if (flag1) { - if (IS_TYPE_CLASS(type2)) - CError_Error(CErrorStr136, type2, 0); - else - CError_Error(CErrorStr244, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type2, qual); - } - return CheckResult0; - } - } - - if (copts.warn_implicitconv && flag1 && !flag2) { - if (IS_TYPE_INT_OR_FLOAT(type2) && IS_TYPE_INT_OR_FLOAT(expr->rtype)) - CExpr_CheckArithmConversion(expr, type2); - } - - result = std_assign_check(expr, type2, flag1, flag3); - if (!result) { - if (IS_TYPE_CLASS(expr->rtype) || IS_TYPE_CLASS(type2)) { - result = user_assign_check(expr, type2, qual, flag1, flag2, flag3); - } else if (flag1) { - CError_Error(CErrorStr244, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type2, qual); - } - } - - if (r30 && result) { - if (flag1) { - if (!ENODE_IS(assign_node, EINDIRECT)) { - if (!r29) { - assign_node = CExpr_LValue(assign_node, 0, 0); - if (!ENODE_IS(assign_node, EINDIRECT)) { - assign_node = get_address_of_temp_copy(assign_node, 1); - temp_reference_init = 1; - } else { - assign_node = getnodeaddress(assign_node, 0); - } - } - } else { - if (!CExpr_IsLValue(assign_node)) - temp_reference_init = 1; - if (!r29) - assign_node = getnodeaddress(assign_node, 0); - } - } else { - if (!r29 && !CExpr_IsLValue(assign_node) && !CParser_IsConst(TYPE_POINTER(type)->target, qual)) { - result = CheckResult0; - } - } - } - - return result; -} - -Boolean CExpr_MatchCompare(Object *obj, Match13 *a, Match13 *b) { - Object *tmp; - ObjectList *list; - - switch (CExpr_StdMatchCompare(&b->anotherm5, &a->anotherm5, 0)) { - case -1: - return 0; - case 0: - if (a->xE > b->xE) - return 0; - if (a->xE != b->xE) - break; - switch (CExpr_StdMatchCompare(&b->match5, &a->match5, 1)) { - case -1: - return 0; - case 0: - if (a->anotherm5.x8 > b->anotherm5.x8) - return 0; - if (a->anotherm5.x8 == b->anotherm5.x8 && (tmp = a->obj)) { - if (tmp->datatype == obj->datatype) { - add_it: - list = lalloc(sizeof(ObjectList)); - list->next = a->list; - a->list = list; - list->object = obj; - return 0; - } - if (obj->datatype == DALIAS) - return 0; - if (tmp->datatype != DALIAS) - goto add_it; - } - } - } - - *a = *b; - a->obj = obj; - return 1; -} - -static void MatchOverloadFunc(Object *obj, FuncArg *args, ENodeList *argexprs, Match13 *match) { - Match13 match2; - - if (IS_TYPE_FUNC(obj->type) && !(TYPE_FUNC(obj->type)->flags & FUNC_IS_TEMPL)) { - memclrw(&match2, sizeof(Match13)); - while (1) { - if (!args || args->type == &stvoid) { - if (!argexprs) - break; - return; - } - - if (args == &elipsis) - break; - if (args == &oldstyle) - break; - - if (!argexprs) { - if (args->dexpr) - break; - return; - } - - if (!CExpr_MatchAssign(args->type, args->qual, argexprs->node, &match2)) - return; - - argexprs = argexprs->next; - args = args->next; - } - - CExpr_MatchCompare(obj, match, &match2); - } -} - -Boolean CExpr_GetFuncMatchArgs(Object *obj, ENodeList *argexprs, ENode *expr, FuncMatchArgs *result) { - ENode *intexpr; - - if (!(TYPE_FUNC(obj->type)->flags & FUNC_METHOD)) { - result->exprs = argexprs; - result->args = TYPE_FUNC(obj->type)->args; - return 1; - } - - if (TYPE_METHOD(obj->type)->is_static) { - result->exprs = argexprs; - result->args = TYPE_FUNC(obj->type)->args; - return 1; - } - - if (TYPE_FUNC(obj->type)->flags & FUNC_IS_CTOR) { - result->exprs = argexprs; - result->args = TYPE_FUNC(obj->type)->args->next; - return 1; - } - - if (expr) { - intexpr = lalloc(sizeof(ENode)); - intexpr->type = EINTCONST; - intexpr->cost = 0; - intexpr->flags = expr->flags; - intexpr->rtype = CDecl_NewPointerType(expr->rtype); - intexpr->data.intval = cint64_zero; - - result->exprs = lalloc(sizeof(ENodeList)); - result->exprs->next = argexprs; - result->exprs->node = intexpr; - - if (obj->datatype == DALIAS) { - result->args = lalloc(sizeof(FuncArg)); - *result->args = *TYPE_FUNC(obj->type)->args; - result->args->type = CDecl_NewPointerType(expr->rtype); - } else { - result->args = TYPE_FUNC(obj->type)->args; - } - - return 1; - } - - return 0; -} - -static NameSpaceObjectList *CExpr_CopyNameSpaceObjectList(NameSpaceObjectList *list) { - NameSpaceObjectList *first; - NameSpaceObjectList *work; - - first = work = lalloc(sizeof(NameSpaceObjectList)); - while (1) { - work->object = list->object; - list = list->next; - if (!list) { - work->next = NULL; - break; - } else { - work->next = lalloc(sizeof(NameSpaceObjectList)); - work = work->next; - } - } - return first; -} - -static void CExpr_MatchArgList(NameSpaceObjectList *list, TemplArg *templargs, ENodeList *argexprs, Match13 *match, ENode *expr, Boolean flag) { - NameSpaceObjectList *copied_list; - NameSpaceObjectList *scan_list; - Object *obj; - ENodeList *scan_expr; - Boolean is_template; - FuncMatchArgs fma; - - if (!copts.old_argmatch) { - CExpr_FuncArgMatch(CExpr_CopyNameSpaceObjectList(list), templargs, argexprs, match, expr, flag); - return; - } - - copied_list = CExpr_CopyNameSpaceObjectList(list); - - for (scan_expr = argexprs; scan_expr; scan_expr = scan_expr->next) - CDecl_CompleteType(scan_expr->node->rtype); - - scan_list = copied_list; - is_template = 0; - for (; scan_list; scan_list = scan_list->next) { - obj = OBJECT(scan_list->object); - if (obj->otype != OT_OBJECT) - continue; - if (IS_TYPE_FUNC(obj->type) && (!flag || !(obj->qual & Q_EXPLICIT))) { - if (!(TYPE_FUNC(obj->type)->flags & FUNC_IS_TEMPL)) { - if (CExpr_GetFuncMatchArgs(obj, argexprs, expr, &fma)) - MatchOverloadFunc(obj, fma.args, fma.exprs, match); - } else { - is_template = 1; - } - } - } - - if (is_template) { - if (!match->obj || match->anotherm5.x2 || match->anotherm5.x4 || match->xE) - CTempl_FuncMatch(copied_list, templargs, argexprs, match, expr); - } -} - -ENode *CExpr_GetDefaultArgument(ENode *funcexpr, FuncArg *arg) { - ENode *tmp; - - if (CTemplTool_IsTemplateArgumentDependentExpression(arg->dexpr)) { - CError_ASSERT(3264, ENODE_IS(funcexpr, EOBJREF)); - tmp = CTemplTool_DeduceDefaultArg( - funcexpr->data.objref, - CInline_CopyExpression(arg->dexpr, CopyMode0) - ); - return argumentpromotion(tmp, arg->type, arg->qual, 1); - } - - return CInline_CopyExpression(arg->dexpr, CopyMode0); -} - -static ENode *CExpr_GenericCall(ENode *funcexpr, ENodeList *argexprs, TypeFunc *tfunc, FuncArg *args) { - ENodeList *list; - ENode *callexpr; - - while (args) { - if (args->dexpr) { - if (argexprs) { - list = argexprs; - while (list->next) - list = list->next; - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - } else { - list = argexprs = lalloc(sizeof(ENodeList)); - } - list->next = NULL; - list->node = CExpr_GetDefaultArgument(funcexpr, args); - } - args = args->next; - } - - callexpr = lalloc(sizeof(ENode)); - callexpr->type = EFUNCCALL; - callexpr->cost = 4; - callexpr->rtype = tfunc->functype; - callexpr->flags = tfunc->qual & ENODE_FLAG_QUALS; - callexpr->data.funccall.funcref = funcexpr; - callexpr->data.funccall.funcref->rtype = CDecl_NewPointerType(TYPE(tfunc)); - callexpr->data.funccall.args = argexprs; - callexpr->data.funccall.functype = tfunc; - funcexpr->data.objref->flags |= OBJECT_USED; - return CExpr_AdjustFunctionCall(callexpr); -} - -static Boolean CExpr_IsObjrefPlusX(ENode *expr) { - Type *type; - - if (ENODE_IS(expr, EOBJREF)) { - type = expr->data.objref->type; - while (IS_TYPE_ARRAY(type)) - type = TYPE_POINTER(type)->target; - return IS_TYPE_CLASS(type); - } - - if (ENODE_IS2(expr, EADD, ESUB)) { - if (CExpr_IsObjrefPlusX(expr->data.diadic.left)) - return 1; - if (CExpr_IsObjrefPlusX(expr->data.diadic.right)) - return 1; - } - - return 0; -} - -static Boolean CExpr_IsStaticType(ENode *expr) { - return ENODE_IS(expr, EINDIRECT) && CExpr_IsObjrefPlusX(expr->data.monadic); -} - -ENode *CExpr_VarArgPromotion(ENode *expr, Boolean flag) { - if (!copts.old_argmatch) - expr = pointer_generation(expr); - - switch (expr->rtype->type) { - case TYPEVOID: - case TYPEFUNC: - CError_Error(CErrorStr353); - expr = nullnode(); - break; - case TYPEINT: - case TYPEENUM: - expr = integralpromote(expr); - break; - case TYPEFLOAT: - if (TYPE_INTEGRAL(expr->rtype)->integral < IT_DOUBLE) - expr = promote(expr, TYPE(&stdouble)); - break; - case TYPECLASS: - expr = classargument(expr); - break; - } - - if (!flag && copts.warn_largeargs) { - if ((IS_TYPE_INT(expr->rtype) && TYPE_INTEGRAL(expr->rtype)->integral >= IT_LONGLONG) || IS_TYPE_FLOAT(expr->rtype)) - CError_Warning(CErrorStr316); - } - - return expr; -} - -ENode *CExpr_GenericFuncCall(BClassList *path, ENode *funcexpr, Boolean flag1, Object *obj, NameSpaceObjectList *nsol, TemplArg *templargs, ENodeList *nodes, Boolean flag2, Boolean flag3, Boolean flag4) { - TypeFunc *tfunc; - AccessType access; - FuncArg *scan_arg; - BClassList *buildpath; - ENode *objexpr; - ENodeList *scan_expr; - BClassList *pathcopy; - Boolean had_alias; - NameSpaceObjectList my_list; - Match13 match; - - memclrw(&match, sizeof(Match13)); - - if (!obj || IS_TEMPL_FUNC(obj->type)) { - if (!funcexpr && cscope_currentfunc && cscope_currentclass && cscope_is_member_func) { - funcexpr = CClass_CreateThisSelfExpr(); - if (funcexpr) { - funcexpr = makemonadicnode(funcexpr, EINDIRECT); - funcexpr->rtype = TYPE(cscope_currentclass); - } - } - - if (obj) { - my_list.next = NULL; - my_list.object = OBJ_BASE(obj); - nsol = &my_list; - } - - CExpr_MatchArgList(nsol, templargs, nodes, &match, funcexpr, flag2); - if (!match.obj) { - CError_ErrorFuncCall(CErrorStr248, nsol, nodes); - return nullnode(); - } - if (match.list) - CError_OverloadedFunctionError(match.obj, match.list); - obj = match.obj; - } - - objexpr = create_objectrefnode(obj); - tfunc = TYPE_FUNC(obj->type); - if (!IS_TYPE_FUNC(tfunc)) { - CError_Error(CErrorStr161); - return nullnode(); - } - - if (IS_TYPEFUNC_METHOD(tfunc) && !TYPE_METHOD(tfunc)->is_static) { - had_alias = 0; - buildpath = NULL; - access = obj->access; - while (obj->datatype == DALIAS) { - buildpath = buildpath ? CClass_AppendPath(buildpath, CClass_GetPathCopy(obj->u.alias.member, 0)) : CClass_GetPathCopy(obj->u.alias.member, 0); - obj = obj->u.alias.object; - objexpr = create_objectrefnode(obj); - had_alias = 1; - } - if (flag3) - CError_Error(CErrorStr188); - - if (TYPE_METHOD(tfunc)->theclass->sominfo && (!(obj->qual & Q_INLINE) || (obj->datatype == DVFUNC && !flag1))) { - pathcopy = CClass_GetPathCopy(path, 0); - funcexpr = CExpr_GetClassAccessNode(path, buildpath, funcexpr, obj, access, flag4); - if (!funcexpr) - return nullnode(); - objexpr = CSOM_MethodAccess(pathcopy, obj, flag1); - } else { - if (obj->datatype == DVFUNC) { - if (flag1 || (!copts.always_vdispatch && !had_alias && funcexpr && CExpr_IsStaticType(funcexpr))) - objexpr->flags |= ENODE_FLAG_80; - } - funcexpr = CExpr_GetClassAccessNode(path, buildpath, funcexpr, obj, access, flag4); - if (!funcexpr) - return nullnode(); - } - - if ( - (tfunc->flags & FUNC_PURE) && - cscope_currentfunc && - (TYPE_FUNC(cscope_currentfunc->type)->flags & (FUNC_IS_CTOR | FUNC_IS_DTOR)) && - cscope_currentclass == TYPE_METHOD(tfunc)->theclass && - ENODE_IS(funcexpr, EINDIRECT) && - ENODE_IS(funcexpr->data.monadic, EINDIRECT) && - ENODE_IS(funcexpr->data.monadic->data.monadic, EOBJREF) && - funcexpr->data.monadic->data.monadic->data.objref->name == this_name_node && - !(objexpr->flags & ENODE_FLAG_80) - ) - CError_Warning(CErrorStr195); - - scan_expr = lalloc(sizeof(ENodeList)); - scan_expr->next = nodes; - scan_expr->node = funcexpr->data.monadic; - if (ENODE_IS(scan_expr->node, EOBJREF)) - scan_expr->node->data.objref->flags |= OBJECT_FLAGS_2; - - if (((funcexpr->flags & Q_CONST) && !(tfunc->args->qual & Q_CONST)) || ((funcexpr->flags & Q_VOLATILE) && !(tfunc->args->qual & Q_VOLATILE))) { - if (!(tfunc->flags & (FUNC_IS_CTOR | FUNC_IS_DTOR))) - CError_Error(CErrorStr236); - } - - nodes = scan_expr; - scan_expr = scan_expr->next; - scan_arg = tfunc->args->next; - } else { - if (flag4 && obj->access != ACCESSPROTECTED) - CClass_CheckObjectAccess(path, obj); - - scan_arg = tfunc->args; - scan_expr = nodes; - if (tfunc->flags & FUNC_METHOD) { - CError_ASSERT(3599, TYPE_METHOD(tfunc)->theclass->sominfo == NULL); - } - } - - while (scan_expr) { - if (scan_arg && scan_arg != &elipsis && scan_arg != &oldstyle) { - scan_expr->node = argumentpromotion(scan_expr->node, scan_arg->type, scan_arg->qual, 1); - scan_arg = scan_arg->next; - } else { - if (!scan_arg) { - my_list.next = NULL; - my_list.object = OBJ_BASE(obj); - CError_ErrorFuncCall(CErrorStr248, &my_list, nodes); - } - scan_expr->node = CExpr_VarArgPromotion(scan_expr->node, scan_arg == &elipsis); - } - scan_expr = scan_expr->next; - } - - if (scan_arg) { - if (scan_arg != &elipsis && scan_arg != &oldstyle) { - if (!scan_arg->dexpr) { - my_list.next = NULL; - my_list.object = OBJ_BASE(obj); - CError_ErrorFuncCall(CErrorStr248, &my_list, nodes); - scan_arg = NULL; - } - } else { - scan_arg = NULL; - } - } - - return CExpr_GenericCall(objexpr, nodes, tfunc, scan_arg); -} - -ENode *CExpr_GenericPtmfCall(Object *obj, TypeFunc *tfunc, ENodeList *arg_exprs) { - ENodeList *scan_expr; - FuncArg *arg; - - scan_expr = arg_exprs; - arg = tfunc->args; - while (scan_expr) { - if (!arg) { - CError_Error(CErrorStr162); - return nullnode(); - } - - if (arg != &elipsis && arg != &oldstyle) { - scan_expr->node = argumentpromotion(scan_expr->node, arg->type, arg->qual, 1); - arg = arg->next; - } else { - scan_expr->node = CExpr_VarArgPromotion(scan_expr->node, arg == &elipsis); - } - scan_expr = scan_expr->next; - } - - if (arg) { - if (arg != &elipsis && arg != &oldstyle) { - if (!arg->dexpr) { - CError_Error(CErrorStr162); - arg = NULL; - } - } else { - arg = NULL; - } - } - - return CExpr_GenericCall(create_objectrefnode(obj), arg_exprs, tfunc, arg); -} - -static ENode *CExpr_ConvertEMember(ENode *expr) { - ENode *result; - - if (expr->data.emember->list->next || expr->data.emember->templargs) { - result = CExpr_NewENode(EOBJLIST); - result->rtype = OBJECT(expr->data.emember->list->object)->type; - result->data.objlist.list = expr->data.emember->list; - result->data.objlist.templargs = expr->data.emember->templargs; - return result; - } - - if (expr->data.emember->list->object->otype != OT_OBJECT) - return NULL; - return CExpr_MakeObjRefNode(OBJECT(expr->data.emember->list->object), 1); -} - -ENode *CExpr_MakeFunctionCall(ENode *funcexpr, ENodeList *arg_exprs) { - ENode *expr; - TypeFunc *tfunc; - BClassList *save_path; - ENode *save_expr; - Boolean save_1D; - Boolean save_isambig; - - FuncArg *scan_arg; - ENodeList *scan_expr; - Boolean has_varargs; - - if (ENODE_IS(funcexpr, EOBJLIST) && funcexpr->data.objlist.name) { - funcexpr->data.objlist.list = CScope_ArgumentDependentNameLookup( - funcexpr->data.objlist.list, - funcexpr->data.objlist.name, - arg_exprs, 0); - if (!funcexpr->data.objlist.list) { - CError_Error(CErrorStr140, CError_GetNameString(NULL, funcexpr->data.objlist.name)); - return nullnode(); - } - - if ( - funcexpr->data.objlist.list->object->otype == OT_OBJECT && - (TYPE_FUNC(OBJECT(funcexpr->data.objlist.list->object)->type)->flags & FUNC_INTRINSIC) && - (expr = CodeGen_HandleIntrinsicCall(OBJECT(funcexpr->data.objlist.list->object), arg_exprs))) - return expr; - - return CExpr_GenericFuncCall( - NULL, NULL, 0, NULL, - funcexpr->data.objlist.list, - funcexpr->data.objlist.templargs, - arg_exprs, 0, 0, 1); - } - - if (ENODE_IS(funcexpr, EMEMBER)) { - save_path = funcexpr->data.emember->path; - save_expr = funcexpr->data.emember->expr; - save_1D = funcexpr->data.emember->pr_1D; - save_isambig = funcexpr->data.emember->isambig; - funcexpr = CExpr_ConvertEMember(funcexpr); - if (!funcexpr) { - CError_Error(CErrorStr161); - return nullnode(); - } - } else { - save_path = NULL; - save_expr = NULL; - save_1D = 0; - save_isambig = 0; - } - - if (ENODE_IS(funcexpr, EOBJREF) && IS_TYPE_FUNC(funcexpr->data.objref->type) && (TYPE_FUNC(funcexpr->data.objref->type)->flags & FUNC_INTRINSIC)) { - if (!(expr = CodeGen_HandleIntrinsicCall(funcexpr->data.objref, arg_exprs))) { - expr = CExpr_GenericFuncCall( - save_path, save_expr, save_1D, funcexpr->data.objref, - NULL, NULL, - arg_exprs, 0, save_isambig, 1); - } - return expr; - } - - if (ENODE_IS(funcexpr, EOBJLIST)) { - return CExpr_GenericFuncCall( - save_path, save_expr, save_1D, NULL, - funcexpr->data.objlist.list, funcexpr->data.objlist.templargs, - arg_exprs, 0, save_isambig, 1); - } - - if (!IS_TYPE_POINTER_ONLY(funcexpr->rtype) || !IS_TYPE_FUNC((tfunc = TYPE_FUNC(TYPE_POINTER(funcexpr->rtype)->target)))) { - CError_Error(CErrorStr161); - return nullnode(); - } - - if (ENODE_IS(funcexpr, EOBJREF)) { - return CExpr_GenericFuncCall( - save_path, save_expr, save_1D, funcexpr->data.objref, - NULL, NULL, arg_exprs, 0, save_isambig, 1); - } - - scan_expr = arg_exprs; // r25 - scan_arg = tfunc->args; // r26 - has_varargs = 0; - while (scan_expr) { - if (!has_varargs) { - if (!scan_arg) { - CError_Error(CErrorStr162); - return nullnode(); - } - if (scan_arg == &elipsis || scan_arg == &oldstyle) { - scan_expr->node = CExpr_VarArgPromotion(scan_expr->node, scan_arg == &elipsis); - has_varargs = 1; - } else { - scan_expr->node = argumentpromotion(scan_expr->node, scan_arg->type, scan_arg->qual, 1); - scan_arg = scan_arg->next; - } - } else { - scan_expr->node = CExpr_VarArgPromotion(scan_expr->node, 0); - } - scan_expr = scan_expr->next; - } - - if (!has_varargs && scan_arg && scan_arg != &elipsis && scan_arg != &oldstyle) { - do { - if (!scan_arg->dexpr) { - CError_Error(CErrorStr162); - return nullnode(); - } - - if (arg_exprs) { - scan_expr = arg_exprs; - while (scan_expr->next) - scan_expr = scan_expr->next; - scan_expr->next = lalloc(sizeof(ENodeList)); - scan_expr = scan_expr->next; - } else { - scan_expr = lalloc(sizeof(ENodeList)); - arg_exprs = scan_expr; - } - - scan_expr->next = NULL; - scan_expr->node = CExpr_GetDefaultArgument(funcexpr, scan_arg); - } while ((scan_arg = scan_arg->next) && scan_arg != &elipsis && scan_arg != &oldstyle); - } - - expr = CExpr_NewENode(EFUNCCALL); - expr->cost = 4; - expr->rtype = tfunc->functype; - expr->flags = tfunc->qual & ENODE_FLAG_QUALS; - expr->data.funccall.funcref = funcexpr; - expr->data.funccall.args = arg_exprs; - expr->data.funccall.functype = tfunc; - return CExpr_AdjustFunctionCall(expr); -} - -static Boolean accept_conversion_type(Type *type, short mode) { - switch (mode) { - case 0: - return IS_TYPE_INT(type); - case 1: - return IS_TYPE_INT_OR_FLOAT(type); - case 2: - return IS_TYPE_INT_OR_FLOAT(type) || IS_TYPE_POINTER_ONLY(type); - case 3: - return IS_TYPE_POINTER_ONLY(type); - default: - CError_FATAL(3912); - return 0; - } -} - -static ENode *CExpr_OperatorConversion(ENode *expr, Type *type, UInt32 qual) { - if (IS_TYPE_CLASS(expr->rtype) && type) { - if (user_assign_check(expr, type, qual, 1, 0, 1)) - return assign_node; - CError_Error(CErrorStr144); - } - return expr; -} - -static Boolean wild_conversion_check(ENode *left, ENode *right, Conversion *conv) { - ConversionIterator iter; - Object *obj; - - Type *check; - Type *left_type; - Type *right_type; - - left_type = right_type = NULL; - if (IS_TYPE_CLASS(left->rtype)) { - CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(left->rtype)); - while ((obj = CExpr_ConversionIteratorNext(&iter))) { - check = TYPE_FUNC(obj->type)->functype; - if (accept_conversion_type(check, 2)) { - while ((obj = CExpr_ConversionIteratorNext(&iter))) { - if (accept_conversion_type(TYPE_FUNC(obj->type)->functype, 2)) - CError_Error(CErrorStr199); - } - left_type = check; - goto found_left; - } - } - return 0; - } -found_left: - if (IS_TYPE_CLASS(right->rtype)) { - CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(right->rtype)); - while ((obj = CExpr_ConversionIteratorNext(&iter))) { - check = TYPE_FUNC(obj->type)->functype; - if (accept_conversion_type(check, 2)) { - while ((obj = CExpr_ConversionIteratorNext(&iter))) { - if (accept_conversion_type(TYPE_FUNC(obj->type)->functype, 2)) - CError_Error(CErrorStr199); - } - right_type = check; - goto found_right; - } - } - return 0; - } -found_right: - conv->x0 = NULL; - conv->left = CExpr_OperatorConversion(left, left_type, 0); - conv->right = CExpr_OperatorConversion(right, right_type, 0); - return 1; -} - -static Boolean monadic_conversion_check(ENode *expr, short which, Conversion *conv) { - ConversionIterator iter; - Object *obj; - Type *check; - - if (!IS_TYPE_CLASS(expr->rtype)) - return 0; - - if (which == 4) - which = 2; - else if (which == 5) - which = 1; - - CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(expr->rtype)); - while ((obj = CExpr_ConversionIteratorNext(&iter))) { - check = TYPE_FUNC(obj->type)->functype; - if (accept_conversion_type(check, which)) { - while ((obj = CExpr_ConversionIteratorNext(&iter))) { - if (accept_conversion_type(TYPE_FUNC(obj->type)->functype, which)) - CError_Error(CErrorStr199); - } - - conv->x0 = NULL; - conv->left = CExpr_OperatorConversion(expr, check, 0); - conv->right = NULL; - return 1; - } - } - - return 0; -} - -static Boolean is_legal_type_combination(Type *left, Type *right, short mode) { - int left_type; - int right_type; - - if (IS_TYPE_ENUM(left)) - left = TYPE_ENUM(left)->enumtype; - if (IS_TYPE_ENUM(right)) - right = TYPE_ENUM(right)->enumtype; - - if (IS_TYPE_REFERENCE(left)) - left = TYPE_POINTER(left)->target; - if (IS_TYPE_REFERENCE(right)) - right = TYPE_POINTER(right)->target; - - left_type = left->type; // r7 - right_type = right->type; // r8 - switch (mode) { - case 3: - if (left_type != TYPEPOINTER || right_type != TYPEPOINTER) - return 0; - use_cpp_typeequal: - diadic_arg1.type = left; - diadic_arg2.type = right; - return iscpp_typeequal(left, right); - case 7: - if ((left_type == TYPEPOINTER && right_type == TYPEINT) || (left_type == TYPEINT && right_type == TYPEPOINTER)) { - diadic_arg1.type = left; - diadic_arg2.type = right; - return 1; - } - return 0; - case 6: - if ((left_type == TYPEPOINTER && right_type == TYPEINT) || (left_type == TYPEINT && right_type == TYPEPOINTER)) { - diadic_arg1.type = left; - diadic_arg2.type = right; - return 1; - } - case 2: - if (left_type == TYPEPOINTER || right_type == TYPEPOINTER) - goto use_cpp_typeequal; - case 1: - mode1: - if (left_type == TYPEFLOAT || right_type == TYPEFLOAT) { - if (left_type == TYPEFLOAT) { - if (right_type == TYPEFLOAT) { - if (TYPE_INTEGRAL(right)->integral > TYPE_INTEGRAL(left)->integral) - left = right; - diadic_arg2.type = left; - diadic_arg1.type = left; - return 1; - } - if (right_type != TYPEINT) - return 0; - diadic_arg2.type = left; - diadic_arg1.type = left; - return 1; - } - if (left_type != TYPEINT) - return 0; - diadic_arg2.type = right; - diadic_arg1.type = right; - return 1; - } - case 0: - if (left_type != TYPEINT || right_type != TYPEINT) - return 0; - if (TYPE_INTEGRAL(right)->integral > TYPE_INTEGRAL(left)->integral) - left = right; - if (TYPE_INTEGRAL(left)->integral < IT_INT) - left = TYPE(&stsignedint); - diadic_arg2.type = left; - diadic_arg1.type = left; - return 1; - case 4: - if (left_type == TYPEPOINTER) { - if (right_type != TYPEINT) - return 0; - diadic_arg1.type = left; - diadic_arg2.type = right; - return 1; - } - if (right_type == TYPEPOINTER) { - if (left_type != TYPEINT) - return 0; - diadic_arg1.type = left; - diadic_arg2.type = right; - return 1; - } - goto mode1; - case 5: - if (left_type != TYPEPOINTER) - goto mode1; - if (right_type == TYPEPOINTER) - goto use_cpp_typeequal; - if (right_type != TYPEINT) - return 0; - diadic_arg1.type = left; - diadic_arg2.type = right; - return 1; - default: - CError_FATAL(4132); - return 0; - } -} - -static void match_class_type_conversion(Match13 *match, ENode *left, ENode *right, ENodeList *list, short which) { - ConversionIterator iter; - Object *obj; - - if (which == 6) { - if (!ENODE_IS(right, EINTCONST) || !CInt64_IsZero(&right->data.intval) || !IS_TYPE_INT(right->rtype)) - which = 2; - } - - CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(left->rtype)); - while ((obj = CExpr_ConversionIteratorNext(&iter))) { - if (is_legal_type_combination(TYPE_FUNC(obj->type)->functype, right->rtype, which)) { - MatchOverloadFunc(obj, &diadic_arg1, list, match); - if (match->obj == obj) { - cexpr_left_conversion_type = diadic_arg1.type; - cexpr_right_conversion_type = diadic_arg2.type; - } - } - } -} - -static void match_type_class_conversion(Match13 *match, ENode *left, ENode *right, ENodeList *list, short which) { - ConversionIterator iter; - Object *obj; - - if (which == 6) { - if (!ENODE_IS(left, EINTCONST) || !CInt64_IsZero(&left->data.intval) || !IS_TYPE_INT(left->rtype)) - which = 2; - } - - CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(right->rtype)); - while ((obj = CExpr_ConversionIteratorNext(&iter))) { - if (is_legal_type_combination(left->rtype, TYPE_FUNC(obj->type)->functype, which)) { - MatchOverloadFunc(obj, &diadic_arg1, list, match); - if (match->obj == obj) { - cexpr_left_conversion_type = diadic_arg1.type; - cexpr_right_conversion_type = diadic_arg2.type; - } - } - } -} - -static void match_class_class_conversion(Match13 *match, ENode *left, ENode *right, ENodeList *list, short which) { - ConversionIterator iter_left; - ConversionIterator iter_right; - Object *obj_left; - Object *obj_right; - - if (which == 6) - which = 2; - - CExpr_ConversionIteratorInit(&iter_left, TYPE_CLASS(left->rtype)); - while ((obj_left = CExpr_ConversionIteratorNext(&iter_left))) { - CExpr_ConversionIteratorInit(&iter_right, TYPE_CLASS(right->rtype)); - while ((obj_right = CExpr_ConversionIteratorNext(&iter_right))) { - if (is_legal_type_combination(TYPE_FUNC(obj_left->type)->functype, TYPE_FUNC(obj_right->type)->functype, which)) { - MatchOverloadFunc(obj_left, &diadic_arg1, list, match); - if (match->obj == obj_left) { - cexpr_left_conversion_type = diadic_arg1.type; - cexpr_right_conversion_type = diadic_arg2.type; - } - } - } - } -} - -Boolean CExpr_CheckOperatorConversion(short token, ENode *left, ENode *right, ENodeList *list, Conversion *conv) { - Match13 match; - short which; - - switch (token) { - case '*': - if (!right) { - which = 3; - break; - } - case '/': - which = 1; - break; - case '&': - if (!right) - return 0; - case '%': - case '^': - case '|': - case '~': - case TK_SHL: - case TK_SHR: - which = 0; - break; - case '[': - which = 7; - break; - case '+': - which = 4; - break; - case '-': - which = 5; - break; - case '!': - case ':': - case '<': - case '>': - case TK_LESS_EQUAL: - case TK_GREATER_EQUAL: - which = 2; - break; - case TK_LOGICAL_EQ: - case TK_LOGICAL_NE: - which = 6; - break; - case TK_LOGICAL_OR: - case TK_LOGICAL_AND: - return wild_conversion_check(left, right, conv); - default: - return 0; - } - - if (!right) - return monadic_conversion_check(left, which, conv); - - cexpr_left_conversion_type = cexpr_right_conversion_type = NULL; - memclrw(&match, sizeof(Match13)); - - if (IS_TYPE_CLASS(left->rtype)) { - if (IS_TYPE_CLASS(right->rtype)) - match_class_class_conversion(&match, left, right, list, which); - else - match_class_type_conversion(&match, left, right, list, which); - } else { - if (IS_TYPE_CLASS(right->rtype)) - match_type_class_conversion(&match, left, right, list, which); - else - return 0; - } - - if (!match.obj) - return 0; - if (match.list) - CError_OverloadedFunctionError(match.obj, match.list); - - conv->x0 = NULL; - conv->left = CExpr_OperatorConversion(left, cexpr_left_conversion_type, 0); - conv->right = CExpr_OperatorConversion(right, cexpr_right_conversion_type, 0); - return 1; -} - -Boolean CExpr_CheckOperator(short token, ENode *left, ENode *right, Conversion *conv) { - Match13 match; - NameResult pr; - NameResult pr2; - ENode *expr; - Object *obj; - ENodeList *nodes; - HashNameNode *name; - BClassList *path; - EMemberInfo *member; - Object *prev_obj; - NameSpaceObjectList mylist_A8; - NameSpaceObjectList mylist_B0; - - if (!copts.old_argmatch) { - if (token == '(') { - CDecl_CompleteType(left->rtype); - if (IS_TYPE_CLASS(left->rtype) && CScope_FindClassMemberObject(TYPE_CLASS(left->rtype), &pr, - CMangler_OperatorName(token))) { - if (pr.nsol_14 || (pr.obj_10 && pr.obj_10->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(pr.obj_10)->type))) { - member = lalloc(sizeof(EMemberInfo)); - memclrw(member, sizeof(EMemberInfo)); - member->path = pr.bcl_18; - member->expr = left; - member->pr_1D = pr.x1D; - if (!pr.nsol_14) { - member->list = galloc(sizeof(NameSpaceObjectList)); - member->list->next = NULL; - member->list->object = pr.obj_10; - } else { - member->list = pr.nsol_14; - } - expr = CExpr_NewENode(EMEMBER); - expr->rtype = &stvoid; - expr->data.emember = member; - tk = lex(); - conv->x0 = checkreference(CExpr_MakeFunctionCall(expr, CExpr_ScanExpressionList(1))); - conv->left = NULL; - conv->right = NULL; - tk = lex(); - return 1; - } else { - CError_FATAL(4371); - } - } - return 0; - } else { - return CExpr_OperatorMatch(token, left, right, conv); - } - } - - if (!IS_TYPE_CLASS(left->rtype)) { - if (!IS_TYPE_ENUM(left->rtype)) { - if (!right) - return 0; - if (!IS_TYPE_CLASS(right->rtype) && !IS_TYPE_ENUM(right->rtype)) - return 0; - } - } else { - CDecl_CompleteType(left->rtype); - } - - memclrw(&match, sizeof(Match13)); - name = CMangler_OperatorName(token); - if (token == '(') { - if (IS_TYPE_CLASS(left->rtype) && CScope_FindClassMemberObject(TYPE_CLASS(left->rtype), &pr2, name)) { - if (pr2.nsol_14 || (pr2.obj_10 && pr2.obj_10->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(pr2.obj_10)->type))) { - member = lalloc(sizeof(EMemberInfo)); - memclrw(member, sizeof(EMemberInfo)); - member->path = pr2.bcl_18; - member->expr = left; - member->pr_1D = pr2.x1D; - if (!pr2.nsol_14) { - member->list = galloc(sizeof(NameSpaceObjectList)); - member->list->next = NULL; - member->list->object = pr2.obj_10; - } else { - member->list = pr2.nsol_14; - } - expr = CExpr_NewENode(EMEMBER); - expr->rtype = &stvoid; - expr->data.emember = member; - tk = lex(); - conv->x0 = checkreference(CExpr_MakeFunctionCall(expr, CExpr_ScanExpressionList(1))); - conv->left = NULL; - conv->right = NULL; - tk = lex(); - return 1; - } else { - CError_FATAL(4439); - } - } - return 0; - } - - nodes = lalloc(sizeof(ENodeList)); - nodes->node = left; - if (right) { - nodes->next = lalloc(sizeof(ENodeList)); - nodes->next->node = right; - nodes->next->next = NULL; - } else { - nodes->next = NULL; - } - - obj = NULL; - if (IS_TYPE_CLASS(left->rtype) && CScope_FindClassMemberObject(TYPE_CLASS(left->rtype), &pr2, name)) { - if (pr2.obj_10) { - mylist_B0.next = NULL; - mylist_B0.object = pr2.obj_10; - pr2.nsol_14 = &mylist_B0; - } else { - CError_ASSERT(4470, pr2.nsol_14); - } - - if (token != '=' || (pr2.bcl_18->type == left->rtype && pr2.bcl_18->next == NULL)) { - prev_obj = match.obj; - CExpr_MatchArgList(pr2.nsol_14, NULL, nodes->next, &match, left, 0); - if (prev_obj != match.obj) { - obj = match.obj; - path = pr2.bcl_18; - } - } - } - - if (CScope_FindNonClassObject(cscope_current, &pr2, name)) { - if (pr2.obj_10) { - mylist_A8.next = NULL; - mylist_A8.object = pr2.obj_10; - pr2.nsol_14 = &mylist_A8; - } - } else { - pr2.nsol_14 = NULL; - } - - if (copts.arg_dep_lookup) - pr2.nsol_14 = CScope_ArgumentDependentNameLookup(pr2.nsol_14, name, nodes, 1); - if (pr2.nsol_14) - CExpr_MatchArgList(pr2.nsol_14, NULL, nodes, &match, NULL, 0); - - if (!match.obj) { - if (!IS_TYPE_CLASS(left->rtype) && (!right || !IS_TYPE_CLASS(right->rtype))) - return 0; - return CExpr_CheckOperatorConversion(token, left, right, nodes, conv); - } - - if (!(token == '&' && !right) && (token != ',')) { - if (!IS_TYPE_CLASS(left->rtype) && (!right || !IS_TYPE_CLASS(right->rtype)) && match.xE) - return 0; - if (right && match.xE == 2 && CExpr_CheckOperatorConversion(token, left, right, nodes, conv)) - return 1; - } - - if (match.list) - CError_OverloadedFunctionError(match.obj, match.list); - - if (match.obj == obj) { - conv->x0 = CExpr_GenericFuncCall(path, nodes->node, 0, match.obj, NULL, NULL, nodes->next, 0, 0, 1); - } else { - conv->x0 = CExpr_GenericFuncCall(NULL, NULL, 0, match.obj, NULL, NULL, nodes, 0, 0, 1); - } - - conv->x0 = checkreference(conv->x0); - conv->left = NULL; - conv->right = NULL; - return 1; -} - -ENode *CExpr_ConstructObject(TypeClass *tclass, ENode *addr_expr, ENodeList *args, Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4, Boolean flag5) { - ENode *expr; - NameSpaceObjectList *ctorlist; - BClassList path; - - CError_ASSERT(4595, IS_TYPE_POINTER_ONLY(addr_expr->rtype)); - - addr_expr = makemonadicnode(addr_expr, EINDIRECT); - addr_expr->rtype = TYPE(tclass); - - if (!flag3 && args && !args->next && args->node->rtype == TYPE(tclass) && !CClass_CopyConstructor(tclass)) { - CError_ASSERT(4605, IS_TYPE_CLASS(addr_expr->rtype)); - expr = makediadicnode(addr_expr, args->node, EASS); - if (!flag1) - expr = getnodeaddress(expr, 0); - return expr; - } - - if ((ctorlist = CClass_Constructor(tclass))) { - if (tclass->flags & CLASS_HAS_VBASES) { - ENodeList *list = lalloc(sizeof(ENodeList)); - list->next = args; - args = list; - list->node = intconstnode(TYPE(&stsignedshort), flag2 != 0); - } - path.next = NULL; - path.type = TYPE(tclass); - expr = CExpr_GenericFuncCall(&path, addr_expr, 0, NULL, ctorlist, NULL, args, !flag5, 0, flag4); - if (ENODE_IS2(expr, EFUNCCALL, EFUNCCALLP)) - expr->rtype = CDecl_NewPointerType(TYPE(tclass)); - if (flag1) { - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = TYPE(tclass); - } - return expr; - } else { - if (args) { - if (!args->next && ENODE_IS(addr_expr, EINDIRECT)) { - return makediadicnode( - addr_expr, - CExpr_AssignmentPromotion(args->node, TYPE(tclass), 0, 1), - EASS); - } - CError_Error(CErrorStr174); - } - return addr_expr; - } -} - -static ENode *CExpr_DeleteFuncCall(Object *obj, ENode *arg, Type *type, Boolean include_size) { - ENode *expr; - ENodeList *list; - - expr = lalloc(sizeof(ENode)); - expr->type = EFUNCCALL; - expr->cost = 4; - expr->flags = 0; - expr->rtype = &stvoid; - expr->data.funccall.funcref = create_objectrefnode(obj); - expr->data.funccall.functype = TYPE_FUNC(obj->type); - obj->flags |= OBJECT_USED; - - list = lalloc(sizeof(ENodeList)); - list->node = arg; - expr->data.funccall.args = list; - - if (include_size) { - list->next = lalloc(sizeof(ENodeList)); - list->next->node = nullnode(); - CInt64_SetLong(&list->next->node->data.intval, type->size); - list->next->node->rtype = CABI_GetSizeTType(); - list->next->next = NULL; - } else { - list->next = NULL; - } - - return expr; -} - -static ENode *CExpr_CopyPlacementNewArg(ENodeList *list) { - switch (list->node->type) { - case EINDIRECT: - if (!ENODE_IS(list->node->data.monadic, EOBJREF)) - break; - if (list->node->data.monadic->data.objref->datatype != DLOCAL && !is_const_object(list->node->data.monadic->data.objref)) - break; - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case EARGOBJ: - case ELOCOBJ: - case EOBJLIST: - case EVECTOR128CONST: - return CInline_CopyExpression(list->node, CopyMode0); - } - - switch (list->node->rtype->type) { - default: - CError_FATAL(4726); - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - case TYPESTRUCT: - case TYPECLASS: - case TYPEMEMBERPOINTER: - case TYPEPOINTER: - case TYPEOBJCID: - return CExpr_GetETEMPCopy(list->node); - } -} - -static ENode *CExpr_PlacementDeleteCall(Type *type, ENode *expr, Object *obj, Boolean flag1, Boolean flag2) { - ENodeList *list; - Object *funcobj; - ENode *result; - ENodeList *inputarg; - Boolean outflag; - - CError_ASSERT(4752, ENODE_IS(expr, EFUNCCALL) && ENODE_IS(expr->data.funccall.funcref, EOBJREF)); - - funcobj = expr->data.funccall.funcref->data.objref; - CError_ASSERT(4756, IS_TYPE_FUNC(funcobj->type) && TYPE_FUNC(funcobj->type)->args && TYPE_FUNC(funcobj->type)->args->next); - - funcobj = CParser_FindDeallocationObject(type, TYPE_FUNC(funcobj->type)->args->next, flag1, flag2, &outflag); - if (!funcobj) - return NULL; - - result = CExpr_NewENode(EFUNCCALL); - result->type = EFUNCCALL; - result->cost = 4; - result->rtype = &stvoid; - result->data.funccall.funcref = create_objectrefnode(funcobj); - result->data.funccall.functype = TYPE_FUNC(funcobj->type); - funcobj->flags |= OBJECT_USED; - - list = lalloc(sizeof(ENodeList)); - list->node = create_objectnode(obj); - result->data.funccall.args = list; - - CError_ASSERT(4780, (inputarg = expr->data.funccall.args) && (inputarg = inputarg->next)); - - do { - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->node = CExpr_CopyPlacementNewArg(inputarg); - inputarg = inputarg->next; - } while (inputarg); - list->next = NULL; - - return result; -} - -static Type *scan_type_name(UInt32 *qual) { - DeclInfo di; - memclrw(&di, sizeof(DeclInfo)); - - CParser_GetDeclSpecs(&di, 0); - di.x46 = 1; - scandeclarator(&di); - - if (di.name) - CError_Error(CErrorStr146); - - firstarrayexpr = di.x24; - *qual = di.qual; - return di.thetype; -} - -static UInt32 cv_qualifier_list(void) { - UInt32 qual; - - qual = 0; - tk = lex(); - while (tk >= TK_CONST && tk <= TK_ASM) { - switch (tk) { - case TK_CONST: - if (qual & Q_CONST) - CError_Error(CErrorStr121); - qual |= Q_CONST; - break; - case TK_VOLATILE: - if (qual & Q_VOLATILE) - CError_Error(CErrorStr121); - qual |= Q_VOLATILE; - break; - default: - CError_Error(CErrorStr121); - } - - tk = lex(); - } - - return qual; -} - -static void scan_new_declarator(DeclInfo *di, Boolean flag) { - NameResult pr; - SInt32 size; - ENode *expr; - - switch (tk) { - case '*': - makethetypepointer(di, cv_qualifier_list()); - if (tk != '[') - scan_new_declarator(di, flag); - break; - case TK_IDENTIFIER: - case TK_COLON_COLON: - if (CScope_ParseQualifiedNameSpace(&pr, 1, 0) && pr.nspace_0 && pr.nspace_0->theclass && tk == '*') { - makememberpointertype(di, pr.nspace_0->theclass, cv_qualifier_list()); - if (tk != '[') - scan_new_declarator(di, flag); - } else { - CError_Error(CErrorStr121); - } - break; - } - - if (tk == '[') { - tk = lex(); - expr = expression(); - - if (IS_TYPE_ENUM(expr->rtype)) - expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; - if (!IS_TYPE_INT(expr->rtype)) - CError_Error(CErrorStr146); - - if (tk != ']') - CError_Error(CErrorStr125); - else - tk = lex(); - - if (tk == '[') - scan_new_declarator(di, 0); - - if (CanCreateObject(di->thetype) && IsCompleteType(di->thetype)) { - di->thetype = CDecl_NewArrayType(di->thetype, 0); - if (!ENODE_IS(expr, EINTCONST)) { - size = 1; - if (!flag) - CError_Error(CErrorStr124); - else - firstarrayexpr = expr; - } else { - size = CInt64_GetULong(&expr->data.intval); - } - TYPE_POINTER(di->thetype)->size = size * TYPE_POINTER(di->thetype)->target->size; - } else { - CError_Error(CErrorStr129); - } - } -} - -static Type *scan_new_type_name(UInt32 *qual) { - DeclInfo di; - memclrw(&di, sizeof(DeclInfo)); - - di.x4F = 1; - CParser_GetDeclSpecs(&di, 0); - scan_new_declarator(&di, 1); - - *qual = di.qual; - return di.thetype; -} - -static ENode *CExpr_NewAlloc(Type *type, ENodeList *args, Boolean flag1, Boolean flag2) { - NameSpaceObjectList *list; - Object *obj; - Boolean found; - HashNameNode *name; - NameResult pr; - - found = 0; - if (!flag1 && IS_TYPE_CLASS(type)) { - list = NULL; - obj = NULL; - name = (flag2 && copts.array_new_delete) ? newa_fobj->name : newp_fobj->name; - if (CScope_FindClassMemberObject(TYPE_CLASS(type), &pr, name)) { - list = pr.nsol_14; - obj = OBJECT(pr.obj_10); - CError_ASSERT(4935, list || obj); - found = 1; - } else if (TYPE_CLASS(type)->flags & CLASS_HANDLEOBJECT) { - CError_ASSERT(4942, !flag2); - obj = newh_func; - found = 1; - } - } - - if (!found) { - if (flag2 && copts.array_new_delete) - list = &newa_fobj->first; - else - list = &newp_fobj->first; - obj = NULL; - } - - return CExpr_GenericFuncCall(NULL, NULL, 0, obj, list, NULL, args, 0, 0, 1); -} - -static ENode *CExpr_NewExceptionSafeAlloc(Type *type, ENode *node, ENodeList *args, Boolean flag1, Boolean flag2, Object **objptr) { - Object *obj; - ENode *result; - ENode *catchexpr; - Object *deletefunc; - Boolean include_size; - - if (!cscope_currentfunc || !copts.delete_exception || !copts.exceptions) - return NULL; - - obj = create_temp_object(TYPE(&void_ptr)); - *objptr = obj; - deletefunc = NULL; - catchexpr = NULL; - include_size = 0; - if (args) - catchexpr = CExpr_PlacementDeleteCall(type, node, obj, flag1, flag2); - if (!args) - deletefunc = CParser_FindDeallocationObject(type, NULL, flag1, flag2, &include_size); - - if (!deletefunc && !catchexpr) - return NULL; - - result = lalloc(sizeof(ENode)); - *result = *node; - node = makediadicnode(create_objectnode(obj), node, EASS); - if (!catchexpr && !include_size) { - result->type = ENEWEXCEPTION; - result->data.newexception.initexpr = node; - result->data.newexception.tryexpr = NULL; - result->data.newexception.pointertemp = obj; - result->data.newexception.deletefunc = deletefunc; - } else { - if (!catchexpr) - catchexpr = CExpr_DeleteFuncCall(deletefunc, create_objectnode(obj), type, include_size); - result->type = EINITTRYCATCH; - result->data.itc.initexpr = node; - result->data.itc.tryexpr = NULL; - result->data.itc.result = create_objectnode(obj); - result->data.itc.catchexpr = catchexpr; - } - - return result; -} - -static ENode *CExpr_NewExceptionSafeInit(ENode *expr, ENode *tryexpr) { - switch (expr->type) { - case ENEWEXCEPTION: - expr->data.newexception.tryexpr = tryexpr; - break; - case EINITTRYCATCH: - expr->data.itc.tryexpr = tryexpr; - break; - default: - CError_FATAL(5056); - } - return expr; -} - -static ENode *CExpr_NewArray(Type *type, UInt32 qual, ENodeList *nodelist, Boolean flag) { - Type *tptr; - Type *sizetype; - Type *innertype; - ENodeList *newlist; - ENode *result; - Object *ctor; - Object *dtor; - ENode *ass; - ENode *etemp; - ENode *mul; - SInt32 count; - ENode *newalloc; - ENode *newESalloc; - Object *tempobj; - ENode *callexpr; - - tptr = CDecl_NewPointerType(TYPE_POINTER(type)->target); - sizetype = CABI_GetSizeTType(); - innertype = TYPE_POINTER(type)->target; - while (IS_TYPE_ARRAY(innertype)) - innertype = TYPE_POINTER(innertype)->target; - - if (!CanAllocObject(innertype) || !IsCompleteType(innertype)) - return nullnode(); - - newlist = lalloc(sizeof(ENodeList)); - newlist->next = nodelist; - if (tk == '(') { - tk = lex(); - if (CExpr_ScanExpressionList(1)) - CError_Error(CErrorStr174); - if (tk == ')') - tk = lex(); - else - CError_Error(CErrorStr115); - } - - if (!IS_TYPE_CLASS(innertype) || CClass_IsPODClass(TYPE_CLASS(innertype))) { - newlist->node = intconstnode(sizetype, type->size); - if (firstarrayexpr) { - newlist->node = makediadicnode(newlist->node, promote(firstarrayexpr, sizetype), EMUL); - optimizecomm(newlist->node); - } - result = CExpr_NewAlloc(innertype, newlist, flag, 1); - result->rtype = tptr; - result->flags |= (qual & ENODE_FLAG_QUALS); - return result; - } - - ctor = NULL; - if (CClass_Constructor(TYPE_CLASS(innertype))) { - ctor = CClass_DefaultConstructor(TYPE_CLASS(innertype)); - if (ctor) { - ctor->flags |= OBJECT_USED; - } else { - ctor = CClass_DummyDefaultConstructor(TYPE_CLASS(innertype)); - if (!ctor) - CError_Error(CErrorStr203); - } - } - - dtor = CClass_Destructor(TYPE_CLASS(innertype)); - if (dtor) - dtor = CABI_GetDestructorObject(dtor, CABIDestroy1); - - ass = NULL; - if (firstarrayexpr) { - etemp = CExpr_NewETEMPNode(sizetype, 1); - mul = promote(firstarrayexpr, sizetype); - if (innertype->size) - count = type->size / innertype->size; - else - count = 0; - if (count > 1) { - mul = makediadicnode(mul, intconstnode(sizetype, count), EMUL); - optimizecomm(mul); - } - ass = makediadicnode(CExpr_DerefETEMPCopy(etemp), mul, EASS); - mul = makediadicnode(CExpr_DerefETEMPCopy(etemp), intconstnode(sizetype, innertype->size), EMUL); - optimizecomm(mul); - mul = makediadicnode(mul, intconstnode(sizetype, 16), EADD); - optimizecomm(mul); - newlist->node = mul; - etemp = CExpr_DerefETEMPCopy(etemp); - } else { - newlist->node = intconstnode(sizetype, type->size + 16); - if (innertype->size) - count = type->size / innertype->size; - else - count = 0; - etemp = intconstnode(sizetype, count); - } - - newalloc = CExpr_NewAlloc(innertype, newlist, flag, 1); - newalloc->rtype = tptr; - newESalloc = CExpr_NewExceptionSafeAlloc(innertype, newalloc, nodelist, 1, flag, &tempobj); - if (newESalloc) { - callexpr = CExpr_FuncCallSix( - cnar_func, - create_objectnode(tempobj), - ctor ? create_objectrefnode(ctor) : nullnode(), - dtor ? create_objectrefnode(dtor) : nullnode(), - intconstnode(sizetype, innertype->size), - etemp, - NULL - ); - result = CExpr_NewExceptionSafeInit(newESalloc, makediadicnode(create_objectnode(tempobj), callexpr, EASS)); - } else { - result = CExpr_FuncCallSix( - cnar_func, - newalloc, - ctor ? create_objectrefnode(ctor) : nullnode(), - dtor ? create_objectrefnode(dtor) : nullnode(), - intconstnode(sizetype, innertype->size), - etemp, - NULL - ); - } - - if (ass) - result = makecommaexpression(ass, result); - result->rtype = tptr; - result->flags |= (qual & ENODE_FLAG_QUALS); - return result; -} - -static ENode *CExpr_NewSimpleClass(TypeClass *tclass, ENode *expr, ENodeList *args) { - ENode *precomp; - ENode *nullcheck; - - precomp = lalloc(sizeof(ENode)); - *precomp = *expr; - precomp->type = EPRECOMP; - precomp->data.precompid = CParser_GetUniqueID(); - - nullcheck = lalloc(sizeof(ENode)); - *nullcheck = *expr; - nullcheck->type = ENULLCHECK; - nullcheck->cost = 4; - nullcheck->data.nullcheck.nullcheckexpr = expr; - nullcheck->data.nullcheck.condexpr = CExpr_ConstructObject(tclass, precomp, args, 0, 1, 1, 1, 1); - nullcheck->data.nullcheck.precompid = precomp->data.precompid; - return nullcheck; -} - -static ENode *CExpr_NewClass(TypeClass *tclass, ENode *expr, ENodeList *args1, ENodeList *args2, Boolean flag) { - Object *objptr; - ENode *newESalloc; - - if (!args2 && !flag && CABI_ConstructorCallsNew(tclass)) { - expr = nullnode(); - expr->rtype = CDecl_NewPointerType(TYPE(tclass)); - return CExpr_ConstructObject(tclass, expr, args1, 0, 1, 1, 1, 1); - } else { - newESalloc = CExpr_NewExceptionSafeAlloc(TYPE(tclass), expr, args2, 0, flag, &objptr); - if (newESalloc) { - return CExpr_NewExceptionSafeInit( - newESalloc, - CExpr_ConstructObject(tclass, create_objectnode(objptr), args1, 0, 1, 1, 1, 1)); - } else { - return CExpr_NewSimpleClass(tclass, expr, args1); - } - } -} - -ENode *scannew(Boolean flag) { - Type *type; // r27 - UInt32 qual; - ENodeList *args; // r28 - Boolean placement_flag; // r26 - ENodeList *newargs; // r26 - ENode *expr; // r26 - ENodeList *args2; // r29 - Object *tempobj; - ENode *newESalloc; // r28 - ENode *tempobj_expr; // r25 - ENode *etemp_expr; // r28 - ENode *indirect_expr; // r25 - ENode *ass; // r25 - ENode *cond; // r27 - - type = NULL; - args = NULL; - firstarrayexpr = NULL; - if ((tk = lex()) == '(') { - tk = lex(); - placement_flag = isdeclaration(1, 1, 1, ')'); - if (!placement_flag) - args = CExpr_ScanExpressionList(1); - if (placement_flag) - type = scan_type_name(&qual); - if (tk != ')') - CError_Error(CErrorStr115); - else - tk = lex(); - } - - if (!type) { - if (tk == '(') { - tk = lex(); - type = scan_type_name(&qual); - if (tk != ')') - CError_Error(CErrorStr115); - else - tk = lex(); - } else { - type = scan_new_type_name(&qual); - } - } - - if (IS_TYPE_ARRAY(type)) - return CExpr_NewArray(type, qual, args, flag); - - if (IS_TYPE_CLASS(type)) { - if (TYPE_CLASS(type)->sominfo) - return CSOM_New(TYPE_CLASS(type)); - if (TYPE_CLASS(type)->objcinfo) - return CObjC_New(TYPE_CLASS(type)); - } - - if (!IsCompleteType(type) || !CanAllocObject(type)) - return nullnode(); - - newargs = lalloc(sizeof(ENodeList)); - newargs->next = args; - newargs->node = intconstnode(CABI_GetSizeTType(), type->size); - - expr = CExpr_NewAlloc(type, newargs, flag, 0); - expr->rtype = CDecl_NewPointerType(type); - expr->flags |= (qual & ENODE_FLAG_QUALS); - - if (tk == '(') { - tk = lex(); - args2 = CExpr_ScanExpressionList(1); - if (!args2 && !IS_TYPE_CLASS(type)) { - args2 = lalloc(sizeof(ENodeList)); - memclrw(args2, sizeof(ENodeList)); - args2->node = do_typecast(nullnode(), type, 0); - } - if (tk == ')') - tk = lex(); - else - CError_Error(CErrorStr115); - } else { - args2 = NULL; - } - - if (ENODE_IS(expr, EINTCONST)) - return expr; - - if (IS_TYPE_CLASS(type) && CClass_Constructor(TYPE_CLASS(type))) - return CExpr_NewClass(TYPE_CLASS(type), expr, args2, args, flag); - - if (args2) { - if (args2->next) { - CError_Error(CErrorStr174); - return nullnode(); - } - - newESalloc = CExpr_NewExceptionSafeAlloc(type, expr, args, 0, flag, &tempobj); - if (newESalloc) { - tempobj_expr = makemonadicnode(create_objectnode(tempobj), EINDIRECT); - tempobj_expr->rtype = type; - tempobj_expr->flags = args2->node->flags & ENODE_FLAG_QUALS; - return CExpr_NewExceptionSafeInit( - newESalloc, - makediadicnode(tempobj_expr, CExpr_AssignmentPromotion(args2->node, type, newESalloc->flags, 1), EASS) - ); - } else { - etemp_expr = CExpr_GetETEMPCopy(expr); - indirect_expr = makemonadicnode(etemp_expr, EINDIRECT); - indirect_expr->rtype = type; - indirect_expr->flags = args2->node->flags & ENODE_FLAG_QUALS; - ass = makediadicnode(indirect_expr, CExpr_AssignmentPromotion(args2->node, type, indirect_expr->flags, 1), EASS); - cond = CExpr_NewENode(ECOND); - cond->cost = 4; - cond->rtype = &stvoid; - cond->data.cond.cond = expr; - cond->data.cond.expr1 = ass; - cond->data.cond.expr2 = nullnode(); - cond = makecommaexpression(cond, etemp_expr); - cond->rtype = etemp_expr->rtype; - cond->flags = etemp_expr->flags; - return cond; - } - } else { - return expr; - } -} - -static ENode *CExpr_DeleteArray(ENode *expr, Type *type, Boolean flag) { - Object *obj; - Object *dtor; - Boolean outflag; - ENode *precomp; - SInt32 precompid; - ENode *tmp; - ENode *result; - - obj = CParser_FindDeallocationObject(type, NULL, 1, flag, &outflag); - - if (!IS_TYPE_CLASS(type) || CClass_IsPODClass(TYPE_CLASS(type))) - return CExpr_DeleteFuncCall(obj, expr, type, outflag); - - dtor = CClass_Destructor(TYPE_CLASS(type)); - if (dtor || outflag) { - if (obj->nspace == cscope_root && !outflag) { - return funccallexpr(dnar_func, expr, dtor ? create_objectrefnode(dtor) : nullnode(), NULL, NULL); - } - return funccallexpr( - dnar3_func, - expr, - dtor ? create_objectrefnode(dtor) : nullnode(), - create_objectrefnode(obj), - intconstnode(TYPE(&stsignedshort), outflag)); - } - - precomp = lalloc(sizeof(ENode)); - *precomp = *expr; - precomp->type = EPRECOMP; - precomp->data.precompid = precompid = CParser_GetUniqueID(); - tmp = CExpr_DeleteFuncCall(obj, makediadicnode(precomp, intconstnode(CABI_GetSizeTType(), 16), ESUB), type, 0); - - result = CExpr_NewENode(ENULLCHECK); - result->rtype = &stvoid; - result->cost = 4; - result->data.nullcheck.nullcheckexpr = expr; - result->data.nullcheck.condexpr = tmp; - result->data.nullcheck.precompid = precompid; - - return result; -} - -ENode *scandelete(Boolean flag) { - Boolean is_array; // r24 - ENode *expr; // r25 - Type *conv_type; // r22 - UInt32 conv_qual; // r23 - Type *innertype; // r23 - Type *t; - Object *obj; - Object *dtor; // r24 - ENode *result_expr; // r24??? - ENode *precomp_orig; // r31 - SInt32 precompid; // r30 - Boolean is_virtual; // r23 - ENode *nc; - ConversionIterator iter; - Boolean outflag; - BClassList path; - - if ((tk = lex()) == '[') { - if ((tk = lex()) != ']') - CError_Error(CErrorStr125); - else - tk = lex(); - is_array = 1; - } else { - is_array = 0; - } - - expr = cast_expression(); - if (!IS_TYPE_POINTER_ONLY(expr->rtype)) { - if (IS_TYPE_CLASS(expr->rtype)) { - conv_type = NULL; - CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(expr->rtype)); - while ((obj = CExpr_ConversionIteratorNext(&iter))) { - if (IS_TYPE_POINTER_ONLY(TYPE_FUNC(obj->type)->functype)) { - if (conv_type) { - CError_Error(CErrorStr199); - break; - } - conv_type = TYPE_FUNC(obj->type)->functype; - conv_qual = TYPE_FUNC(obj->type)->qual; - } - } - if (conv_type) { - if (!copts.old_argmatch) { - expr = CExpr_Convert(expr, conv_type, conv_qual, 1, 1); - } else { - if (user_assign_check(expr, conv_type, conv_qual, 1, 0, 1)) - expr = assign_node; - } - } - } - if (!IS_TYPE_POINTER_ONLY(expr->rtype)) { - CError_Error(CErrorStr146); - return nullnode(); - } - } - - innertype = TYPE_POINTER(expr->rtype)->target; - if (innertype->size == 0) - CDecl_CompleteType(innertype); - - if (IS_TYPE_ARRAY(innertype) && !is_array) - CError_Error(CErrorStr146); - - if (is_array) { - t = innertype; - while (IS_TYPE_ARRAY(t)) - t = TYPE_POINTER(t)->target; - return CExpr_DeleteArray(expr, t, flag); - } - - if (copts.objective_c && CObjC_IsType_id(expr->rtype)) - return CObjC_Delete(NULL, expr); - - if (!IS_TYPE_CLASS(innertype)) { - obj = CParser_FindDeallocationObject(innertype, NULL, 0, flag, &outflag); - CClass_CheckObjectAccess(NULL, obj); - return CExpr_DeleteFuncCall(obj, expr, innertype, outflag); - } - - if (TYPE_CLASS(innertype)->sominfo) - return CSOM_Delete(TYPE_CLASS(innertype), expr); - - if (TYPE_CLASS(innertype)->objcinfo) - return CObjC_Delete(TYPE_CLASS(innertype), expr); - - if (!(TYPE_CLASS(innertype)->flags & CLASS_COMPLETED) && copts.pedantic) - CError_Warning(CErrorStr136, innertype, 0); - - obj = CParser_FindDeallocationObject(innertype, NULL, 0, flag, &outflag); - CClass_CheckObjectAccess(NULL, obj); - dtor = CClass_Destructor(TYPE_CLASS(innertype)); - if (!dtor) - return CExpr_DeleteFuncCall(obj, expr, innertype, outflag); - - path.next = NULL; - path.type = innertype; - CClass_CheckObjectAccess(&path, dtor); - - result_expr = lalloc(sizeof(ENode)); - result_expr->type = EFUNCCALL; - result_expr->cost = 4; - result_expr->flags = 0; - result_expr->rtype = &stvoid; - if (dtor->datatype == DVFUNC) { - precomp_orig = expr; - expr = lalloc(sizeof(ENode)); - *expr = *precomp_orig; - expr->type = EPRECOMP; - expr->data.precompid = precompid = CParser_GetUniqueID(); - is_virtual = 1; - } else { - is_virtual = 0; - } - - if (!flag) { - result_expr = CABI_DestroyObject(dtor, expr, 2, 0, 1); - } else { - CError_ASSERT(5650, !outflag); - result_expr = CABI_DestroyObject(dtor, expr, 2, 0, 0); - result_expr->rtype = TYPE(&void_ptr); - result_expr = funccallexpr(obj, result_expr, NULL, NULL, NULL); - obj->flags |= OBJECT_USED; - } - - if (is_virtual) { - nc = lalloc(sizeof(ENode)); - nc->type = ENULLCHECK; - nc->rtype = &stvoid; - nc->cost = 4; - nc->flags = 0; - nc->data.nullcheck.nullcheckexpr = precomp_orig; - nc->data.nullcheck.condexpr = result_expr; - nc->data.nullcheck.precompid = precompid; - return nc; - } else { - return result_expr; - } -} diff --git a/compiler_and_linker/unsorted/CExprConvMatch.c b/compiler_and_linker/unsorted/CExprConvMatch.c deleted file mode 100644 index 5cc145f..0000000 --- a/compiler_and_linker/unsorted/CExprConvMatch.c +++ /dev/null @@ -1,2518 +0,0 @@ -#include "compiler/CExpr.h" -#include "compiler/CABI.h" -#include "compiler/CClass.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CInt64.h" -#include "compiler/CFunc.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CObjC.h" -#include "compiler/CParser.h" -#include "compiler/CScope.h" -#include "compiler/CTemplateFunc.h" -#include "compiler/CodeGen.h" -#include "compiler/CompilerTools.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/templates.h" - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct StandardConv { - Type *type1; - Type *type2; - UInt32 qual1; - UInt32 qual2; - Boolean x10; // unknown - Boolean x11; - Boolean x12; - Boolean x13; - Boolean x14; - Boolean x15; -} StandardConv; - -typedef enum EImplicitConvType { - ICT_0, - ICT_1, - ICT_2, - ICT_3 -} EImplicitConvType; - -typedef struct ImplicitConv { - EImplicitConvType type; - union { - struct { - Object *x2; - StandardConv standardConv; - } ic2; - struct { - StandardConv standardConv; - } ic3; - } u; -} ImplicitConv; - -typedef struct ConversionTypeList { - struct ConversionTypeList *next; - Object *func; - Type *type; - UInt32 qual; -} ConversionTypeList; - -typedef struct Match { - struct Match *next; - Object *object; - Object *specialfunc; - Type *type; - UInt32 qual; - Type *type2; - UInt32 qual2; - ImplicitConv conv[3]; -} Match; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -// forward decls -static ENode *CExpr_DerivedToBase(ENode *expr, Type *type2, UInt32 qual2, Boolean flag1, Boolean flag2, Boolean flag3); - -static Type *CExpr_GetImplictObjectParamType(Object *object, UInt32 *qual) { - Type *type; - - CError_ASSERT(98, IS_TYPE_FUNC(object->type)); - CError_ASSERT(99, TYPE_FUNC(object->type)->flags & FUNC_METHOD); - CError_ASSERT(100, !TYPE_METHOD(object->type)->is_static); - CError_ASSERT(101, TYPE_METHOD(object->type)->args); - - type = CDecl_NewRefPointerType(TYPE(TYPE_METHOD(object->type)->theclass)); - *qual = TYPE_METHOD(object->type)->args->qual & Q_CV; - return type; -} - -static Type *CExpr_GetParamType(Object *object, int index, UInt32 *qual) { - FuncArg *arg; - - CError_ASSERT(120, IS_TYPE_FUNC(object->type)); - CError_ASSERT(121, arg = TYPE_FUNC(object->type)->args); - if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(object->type))) - CError_ASSERT(125, arg = arg->next); - - while (index > 0) { - CError_ASSERT(129, arg = arg->next); - index--; - } - - *qual = arg->qual & Q_CV; - return arg->type; -} - -static Boolean CExpr_HasNParams(Object *object, int count) { - FuncArg *arg; - int i; - - CError_ASSERT(146, IS_TYPE_FUNC(object->type)); - CError_ASSERT(147, arg = TYPE_FUNC(object->type)->args); - if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(object->type))) - arg = arg->next; - - i = 0; - while (arg) { - arg = arg->next; - i++; - } - - return i == count; -} - -typedef enum TypeCompareMode { - TCM_0, - TCM_1, - TCM_2 -} TypeCompareMode; - -static Boolean CExpr_TypeCompare(Type *typeA, UInt32 qualA, Type *typeB, UInt32 qualB, TypeCompareMode mode) { - if (typeA->type != typeB->type) - return 0; - - switch (mode) { - case TCM_0: - while (1) { - switch (typeA->type) { - case TYPEPOINTER: - typeA = TPTR_TARGET(typeA); - typeB = TPTR_TARGET(typeB); - if (typeA->type != typeB->type) - return 0; - continue; - - case TYPEMEMBERPOINTER: - if (!is_typesame(TYPE_MEMBER_POINTER(typeA)->ty2, TYPE_MEMBER_POINTER(typeB)->ty2)) - return 0; - typeA = TYPE_MEMBER_POINTER(typeA)->ty1; - typeB = TYPE_MEMBER_POINTER(typeB)->ty1; - if (typeA->type != typeB->type) - return 0; - continue; - } - break; - } - break; - - case TCM_1: - switch (typeA->type) { - case TYPEPOINTER: - if ((qualA & Q_CV) != (qualB & Q_CV)) - return 0; - - typeA = TPTR_TARGET(typeA); - typeB = TPTR_TARGET(typeB); - break; - - case TYPEMEMBERPOINTER: - if ((qualA & Q_CV) != (qualB & Q_CV)) - return 0; - - if (!is_typesame(TYPE_MEMBER_POINTER(typeA)->ty2, TYPE_MEMBER_POINTER(typeB)->ty2)) - return 0; - typeA = TYPE_MEMBER_POINTER(typeA)->ty1; - typeB = TYPE_MEMBER_POINTER(typeB)->ty1; - break; - } - break; - - case TCM_2: - if ((qualA & Q_CV) != (qualB & Q_CV)) - return 0; - break; - } - - return is_typesame(typeA, typeB); -} - -static int CExpr_IsReferenceCompatible(Type *typeA, UInt32 qualA, Type *typeB, UInt32 qualB) { - if (CParser_IsSameOrMoreCVQualified(CParser_GetCVTypeQualifiers(typeA, qualA), CParser_GetCVTypeQualifiers(typeB, qualB))) { - if (CExpr_TypeCompare(typeA, qualA, typeB, qualB, TCM_1)) - return 1; - - if (IS_TYPE_CLASS(typeB) && IS_TYPE_CLASS(typeA)) { - short depth; - Boolean isambigbase; - if (CClass_GetBasePath(TYPE_CLASS(typeB), TYPE_CLASS(typeA), &depth, &isambigbase)) - return 2; - } - } - - return 0; -} - -static Boolean CExpr_IsBaseOf(TypeClass *baseclass, TypeClass *superclass) { - ClassList *base; - - for (base = superclass->bases; base; base = base->next) { - if (base->base == baseclass || CExpr_IsBaseOf(baseclass, base->base)) - return 1; - } - - return 0; -} - -static Boolean CExpr_IsBetterClassConversion(TypeClass *a, TypeClass *b, TypeClass *c, TypeClass *d) { - if (a == c) - return CExpr_IsBaseOf(d, b); - if (b == d) - return CExpr_IsBaseOf(a, c); - return 0; -} - -CW_INLINE Boolean Inline_501D40(Type *a, Type *b) { - return (a == TYPE(&stbool)) && (IS_TYPE_POINTER_ONLY(b) || IS_TYPE_MEMBERPOINTER(b)); -} - -static Boolean CExpr_IsBetterStandardConv(StandardConv *a, StandardConv *b) { - Boolean flag10; - Boolean flag3; - - flag10 = 1; - flag3 = 0; - - if (b->x11) { - if (!a->x11) - flag3 = 1; - } else { - if (a->x11) - flag10 = 0; - } - - if (b->x12) { - if (!a->x12) - flag3 = 1; - } else { - if (a->x12) - flag10 = 0; - } - - if (b->x13) { - if (a->x13) { - if (Inline_501D40(b->type2, b->type1)) { - if (!Inline_501D40(a->type2, a->type1)) - return 1; - } else { - if (Inline_501D40(a->type2, a->type1)) - return 0; - } - } else { - flag3 = 1; - } - } else { - if (a->x13) - flag10 = 0; - } - - if (flag10 && flag3) - return 1; - - if (!a->x13) { - if (b->x13) - return 1; - - if (a->x12) { - if (!b->x12) - return 0; - } else { - if (b->x12) - return 1; - } - } else { - if (!b->x13) - return 0; - } - - if ( - IS_TYPE_POINTER_ONLY(a->type1) && - IS_TYPE_CLASS(TPTR_TARGET(a->type1)) && - IS_TYPE_POINTER_ONLY(a->type2) && - IS_TYPE_POINTER_ONLY(b->type1) && - IS_TYPE_CLASS(TPTR_TARGET(b->type1)) && - IS_TYPE_POINTER_ONLY(b->type2) - ) - { - if (TPTR_TARGET(b->type2) == &stvoid) { - if (TPTR_TARGET(a->type2) == &stvoid) { - if (CExpr_IsBaseOf(TYPE_CLASS(TPTR_TARGET(a->type1)), TYPE_CLASS(TPTR_TARGET(b->type1)))) - return 1; - } else { - if (TPTR_TARGET(a->type1) == TPTR_TARGET(b->type1) && IS_TYPE_CLASS(TPTR_TARGET(a->type2))) - return 1; - } - } else if (IS_TYPE_CLASS(TPTR_TARGET(a->type2)) && IS_TYPE_CLASS(TPTR_TARGET(b->type2))) { - if (CExpr_IsBetterClassConversion( - TYPE_CLASS(TPTR_TARGET(a->type1)), - TYPE_CLASS(TPTR_TARGET(a->type2)), - TYPE_CLASS(TPTR_TARGET(b->type1)), - TYPE_CLASS(TPTR_TARGET(b->type2)) - )) - return 1; - } - } - - if ( - IS_TYPE_CLASS(a->type1) && - IS_TYPE_CLASS(a->type2) && - IS_TYPE_CLASS(b->type1) && - IS_TYPE_CLASS(b->type2) && - CExpr_IsBetterClassConversion( - TYPE_CLASS(a->type1), - TYPE_CLASS(a->type2), - TYPE_CLASS(b->type1), - TYPE_CLASS(b->type2) - ) - ) - return 1; - - if ( - IS_TYPE_MEMBERPOINTER(a->type1) && - IS_TYPE_MEMBERPOINTER(a->type2) && - IS_TYPE_MEMBERPOINTER(b->type1) && - IS_TYPE_MEMBERPOINTER(b->type2) && - IS_TYPE_CLASS(TYPE_MEMBER_POINTER(a->type1)->ty2) && - IS_TYPE_CLASS(TYPE_MEMBER_POINTER(a->type2)->ty2) && - IS_TYPE_CLASS(TYPE_MEMBER_POINTER(b->type1)->ty2) && - IS_TYPE_CLASS(TYPE_MEMBER_POINTER(b->type2)->ty2) && - CExpr_IsBetterClassConversion( - TYPE_CLASS(TYPE_MEMBER_POINTER(b->type1)->ty2), - TYPE_CLASS(TYPE_MEMBER_POINTER(b->type2)->ty2), - TYPE_CLASS(TYPE_MEMBER_POINTER(a->type1)->ty2), - TYPE_CLASS(TYPE_MEMBER_POINTER(a->type2)->ty2) - ) - ) - return 1; - - if ( - a->x14 && - b->x14 && - CExpr_TypeCompare(a->type2, a->qual2, b->type2, b->qual2, TCM_1) && - CParser_IsMoreCVQualified( - CParser_GetTypeQualifiers(b->type2, b->qual2), - CParser_GetTypeQualifiers(a->type2, a->qual2) - ) - ) - return 1; - - return 0; -} - -static Boolean CExpr_IsBetterImplicitConv(ImplicitConv *a, ImplicitConv *b) { - if (a->type > b->type) - return 1; - if (a->type != b->type) - return 0; - - if (a->type == ICT_3) - return CExpr_IsBetterStandardConv(&a->u.ic3.standardConv, &b->u.ic3.standardConv); - - if (a->type == ICT_2 && a->u.ic2.x2 == b->u.ic2.x2 && CExpr_IsBetterStandardConv(&a->u.ic2.standardConv, &b->u.ic2.standardConv)) - return 1; - - return 0; -} - -typedef enum SSCRMode { - SSCR_0, - SSCR_1, - SSCR_2 -} SSCRMode; - -static Boolean CExpr_SetupStandardConversionResult(ENode *expr, Type *type2, UInt32 qual2, SSCRMode mode, Boolean x14, Boolean refFlag, StandardConv *result) { - UInt32 cv1; - UInt32 cv2; - - if (x14) { - if (!CParser_IsConst(type2, qual2)) { - if (!refFlag && !CExpr_IsLValue(expr)) - return 0; - if (mode != SSCR_0 && !IS_TYPE_CLASS(type2)) - return 0; - } - - cv2 = CParser_GetTypeQualifiers(type2, qual2) & Q_CV; - cv1 = CParser_GetTypeQualifiers(expr->rtype, ENODE_QUALS(expr)) & Q_CV; - if (cv2 != cv1 && !CParser_IsMoreCVQualified(cv2, cv1)) - return 0; - } - - memclrw(result, sizeof(StandardConv)); - result->type2 = type2; - result->qual2 = qual2; - result->type1 = expr->rtype; - result->qual1 = ENODE_QUALS(expr); - result->x14 = x14; - - switch (mode) { - case SSCR_0: - break; - case SSCR_1: - result->x12 = 1; - break; - case SSCR_2: - result->x13 = 1; - break; - default: - CError_FATAL(581); - } - - return 1; -} - -typedef enum MysteryEnum { - ME_0, - ME_1, - ME_255 = 255 -} MysteryEnum; - -CW_INLINE MysteryEnum Inline_501FF0(UInt32 qual1, UInt32 qual2) { - if ((qual1 & Q_CV) == (qual2 & Q_CV)) - return ME_0; - - if (((qual2 & Q_CONST) && !(qual1 & Q_CONST)) || ((qual2 & Q_VOLATILE) && !(qual1 & Q_VOLATILE))) - return ME_255; - - return ME_1; -} - -static Boolean CExpr_SetQualConversionResult(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, StandardConv *result) { - Boolean flag = 1; - UInt32 cv1; - UInt32 cv2; - - while (1) { - cv1 = CParser_GetCVTypeQualifiers(type1, qual1); - cv2 = CParser_GetCVTypeQualifiers(type2, qual2); - - switch (Inline_501FF0(cv1, cv2)) { - case ME_0: - break; - - case ME_1: - result->x11 = 1; - if (!flag) - return 0; - break; - - default: - return 0; - } - - if (!(cv1 & Q_CONST)) - flag = 0; - - if (IS_TYPE_POINTER_ONLY(type1)) { - CError_ASSERT(635, IS_TYPE_POINTER_ONLY(type2)); - type1 = TPTR_TARGET(type1); - type2 = TPTR_TARGET(type2); - } else { - if (!IS_TYPE_MEMBERPOINTER(type1)) - return 1; - - CError_ASSERT(642, IS_TYPE_MEMBERPOINTER(type2)); - type1 = TYPE_MEMBER_POINTER(type1)->ty1; - type2 = TYPE_MEMBER_POINTER(type2)->ty1; - } - } -} - -static Boolean CExpr_OverloadFuncMatch(NameSpaceObjectList *list, TemplArg *templargs, Type *type, ENode **outExpr) { - Object *object; - TemplFuncInstance *inst; - ENode *expr; - FuncArg *arg; - int i; - ObjectList *objlist; - Object *object26; - ObjectList *objlist25; - ObjectList *objlist24; - Boolean flag23; - - if (!IS_TYPE_POINTER_ONLY(type) || !IS_TYPE_FUNC(type = TPTR_TARGET(type))) - return 0; - - object26 = NULL; - objlist25 = NULL; - objlist24 = NULL; - flag23 = 0; - - while (list) { - object = OBJECT(list->object); - if (object->otype == OT_OBJECT) { - if (IS_TEMPL_FUNC(object->type)) { - if (!flag23 && CTempl_CanDeduceFunc(object, TYPE_FUNC(type), templargs)) { - CError_ASSERT(685, inst = CTempl_DeduceFunc(object, TYPE_FUNC(type), templargs, NULL, 0)); - if (is_typesame(inst->object->type, type)) { - objlist = lalloc(sizeof(ObjectList)); - objlist->next = objlist24; - objlist->object = object; - objlist24 = objlist; - - if (object26 && object26 != inst->object) { - objlist = lalloc(sizeof(ObjectList)); - objlist->next = objlist25; - objlist->object = inst->object; - objlist25 = objlist; - } else { - object26 = inst->object; - } - } - } - } else if (is_typesame(object->type, type)) { - if (object26 && flag23) { - Object *checkA, *checkB; - checkA = object; - if (checkA->datatype == DALIAS) - checkA = checkA->u.alias.object; - checkB = object26; - if (checkB->datatype == DALIAS) - checkB = checkB->u.alias.object; - if (checkA != checkB) { - objlist = lalloc(sizeof(ObjectList)); - objlist->next = objlist25; - objlist->object = object; - objlist25 = objlist; - } - } else { - objlist25 = NULL; - object26 = object; - } - flag23 = 1; - } - } - list = list->next; - } - - if (object26) { - if (outExpr) { - if (objlist25) { - i = 0; - for (arg = TYPE_FUNC(object->type)->args; arg; arg = arg->next) - i++; - - if (!flag23 && (object = CTempl_PartialOrdering(objlist24->object, objlist24->next, i))) { - CError_ASSERT(741, inst = CTempl_DeduceFunc(object, TYPE_FUNC(type), templargs, NULL, 0)); - object26 = inst->object; - } else { - CError_OverloadedFunctionError(object26, objlist25); - } - } - - expr = CExpr_MakeObjRefNode(object26, 1); - *outExpr = expr; - expr->rtype = CDecl_NewPointerType(object26->type); - expr->flags = object->qual & ENODE_FLAG_QUALS; - object26->flags |= OBJECT_USED; - if (object26->datatype == DINLINEFUNC) - CError_Error(CErrorStr175); - } - - return 1; - } - - return 0; -} - -static Boolean CExpr_StandardConversionMatch(ENode *expr, Type *type2, UInt32 qual2, Boolean x14, StandardConv *result) { - Type *type1; - UInt32 qual1; - Boolean refFlag; - Type *inner2; - Type *inner1; - SSCRMode mode; - NameSpaceObjectList list; - - if (IS_TYPE_REFERENCE(type2)) { - type2 = TPTR_TARGET(type2); - if (IS_TYPE_POINTER_ONLY(type2)) - expr = pointer_generation(expr); - refFlag = 1; - } else { - if ( - (IS_TYPE_ARRAY(expr->rtype) && !IS_TYPE_ARRAY(type2)) || - (IS_TYPE_FUNC(expr->rtype) && !IS_TYPE_FUNC(type2)) - ) - expr = pointer_generation(expr); - refFlag = 0; - } - - type1 = expr->rtype; - qual1 = ENODE_QUALS(expr); - - if (IS_TYPE_POINTER_ONLY(type2)) { - if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval)) { - if (IS_TYPE_INT(type1) || (!copts.cplusplus && IS_TYPE_ENUM(type1))) - return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, x14, refFlag, result); - } - - if ( - IS_TYPE_INT(expr->rtype) && - ENODE_IS_INDIRECT_TO(expr, EOBJREF) && - (expr->data.monadic->data.objref->qual & Q_INLINE_DATA) && - CInt64_IsZero(&expr->data.monadic->data.objref->u.data.u.intconst) - ) - return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, x14, refFlag, result); - - if (ENODE_IS(expr, EOBJLIST)) - return CExpr_OverloadFuncMatch(expr->data.objlist.list, expr->data.objlist.templargs, type2, NULL) && - CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result); - - if (ENODE_IS(expr, EOBJREF) && IS_TEMPL_FUNC(expr->data.objref->type)) { - list.next = NULL; - list.object = OBJ_BASE(expr->data.objref); - return CExpr_OverloadFuncMatch(&list, NULL, type2, NULL) && - CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result); - } - - if (IS_TYPE_POINTER_ONLY(type1)) { - if ( - ENODE_IS(expr, ESTRINGCONST) && - TPTR_TARGET(type2) == TPTR_TARGET(type1) && - !(qual2 & Q_CONST) && - ( - TPTR_TARGET(type2) == TYPE(&stchar) || - TPTR_TARGET(type2) == TYPE(&stunsignedchar) || - TPTR_TARGET(type2) == CParser_GetWCharType() - ) - ) - { - if ( - CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result) && - CExpr_SetQualConversionResult(TPTR_TARGET(type2), qual2, TPTR_TARGET(type1), qual1 & ~Q_CONST, result) - ) - { - result->x11 = 1; - return 1; - } else { - return 0; - } - } - - if (copts.objective_c && CObjC_IsCompatibleType(expr->rtype, type2)) - return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, x14, refFlag, result); - - if (IS_TYPE_VOID(TPTR_TARGET(type2)) || (!copts.cplusplus && IS_TYPE_VOID(TPTR_TARGET(type1)))) { - if (CExpr_SetupStandardConversionResult(expr, type2, qual2, IS_TYPE_VOID(TPTR_TARGET(type1)) ? SSCR_0 : SSCR_2, refFlag, x14, result)) { - switch (Inline_501FF0(qual2, CParser_GetCVTypeQualifiers(TPTR_TARGET(type1), qual1))) { - case ME_1: - result->x11 = 1; - case ME_0: - return 1; - default: - return 0; - } - } else { - return 0; - } - } - - inner2 = TPTR_TARGET(type2); - inner1 = TPTR_TARGET(type1); - while (1) { - if (inner2->type != inner1->type) - break; - - switch (inner2->type) { - case TYPEPOINTER: - inner2 = TPTR_TARGET(inner2); - inner1 = TPTR_TARGET(inner1); - continue; - case TYPEMEMBERPOINTER: - if (!is_typesame(TYPE_MEMBER_POINTER(inner2)->ty2, TYPE_MEMBER_POINTER(inner1)->ty2)) - break; - - inner2 = TYPE_MEMBER_POINTER(inner2)->ty1; - inner1 = TYPE_MEMBER_POINTER(inner1)->ty1; - if (!IS_TYPE_POINTER_ONLY(inner2) && !IS_TYPE_MEMBERPOINTER(inner2)) { - if (!is_memberpointerequal(inner2, inner1)) - break; - - if (CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result)) - return CExpr_SetQualConversionResult(TPTR_TARGET(type2), qual2, TPTR_TARGET(type1), qual1, result); - else - return 0; - } - continue; - default: - if (!is_typesame(inner2, inner1)) - break; - - if (CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result)) - return CExpr_SetQualConversionResult(TPTR_TARGET(type2), qual2, TPTR_TARGET(type1), qual1, result); - else - return 0; - } - - break; - } - - if (IS_TYPE_CLASS(TPTR_TARGET(type2)) && IS_TYPE_CLASS(TPTR_TARGET(type1))) { - short depth; - Boolean isambigbase; - if (CClass_GetBasePath(TYPE_CLASS(TPTR_TARGET(type1)), TYPE_CLASS(TPTR_TARGET(type2)), &depth, &isambigbase)) { - if (CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, refFlag, x14, result)) - return CExpr_SetQualConversionResult(TPTR_TARGET(type2), qual2, TPTR_TARGET(type1), qual1, result); - else - return 0; - } - } - } - - if (copts.mpwc_relax && !copts.cplusplus && IS_TYPE_POINTER_ONLY(type1)) { - if (CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, refFlag, x14, result)) - return 1; - } - - return 0; - } - - if (is_typesame(type2, type1)) - return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_0, refFlag, x14, result); - - if (type2 == TYPE(&stbool)) { - switch (type1->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - case TYPEMEMBERPOINTER: - case TYPEPOINTER: - return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, refFlag, x14, result); - default: - return 0; - } - } - - if (IS_TYPE_MEMBERPOINTER(type2)) { - if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval)) { - if (IS_TYPE_INT(type1) || (!copts.cplusplus && IS_TYPE_ENUM(type1))) - return CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, refFlag, x14, result); - } - - if (ENODE_IS(expr, EMEMBER)) { - expr = getpointertomemberfunc(expr, type2, 0); - type1 = expr->rtype; - } - - if (IS_TYPE_MEMBERPOINTER(type1)) { - short depth; - Boolean isambigbase; - - CError_ASSERT(996, IS_TYPE_CLASS(TYPE_MEMBER_POINTER(type2)->ty2) && IS_TYPE_CLASS(TYPE_MEMBER_POINTER(type1)->ty2)); - if (!is_memberpointerequal(TYPE_MEMBER_POINTER(type2)->ty1, TYPE_MEMBER_POINTER(type1)->ty1)) - return 0; - - if ( - TYPE_MEMBER_POINTER(type2)->ty2 == TYPE_MEMBER_POINTER(type1)->ty2 || - CClass_GetBasePath(TYPE_CLASS(TYPE_MEMBER_POINTER(type2)->ty2), TYPE_CLASS(TYPE_MEMBER_POINTER(type1)->ty2), &depth, &isambigbase) - ) - { - if (CExpr_SetupStandardConversionResult(expr, type2, qual2, SSCR_2, refFlag, x14, result)) - return CExpr_SetQualConversionResult(TYPE_MEMBER_POINTER(type2)->ty1, qual2, TYPE_MEMBER_POINTER(type1)->ty1, qual1, result); - else - return 0; - } - } - - return 0; - } - - mode = SSCR_2; - switch (type1->type) { - case TYPEINT: - switch (type2->type) { - case TYPEINT: - if (TYPE_INTEGRAL(type1)->integral < IT_INT) { - if (type2 == TYPE(&stsignedint)) { - if (type1->size < type2->size || !is_unsigned(type1)) - mode = SSCR_1; - } else if (type2 == TYPE(&stunsignedint)) { - if (type2->size == type1->size && is_unsigned(type1)) - mode = SSCR_1; - } - } - break; - case TYPEFLOAT: - break; - case TYPEENUM: - if (copts.cplusplus) - return 0; - break; - default: - return 0; - } - break; - - case TYPEFLOAT: - switch (type2->type) { - case TYPEINT: - break; - case TYPEFLOAT: - if (type2 == TYPE(&stdouble)) { - if (type1 == TYPE(&stfloat) || type1 == TYPE(&stshortdouble)) - mode = SSCR_1; - } - break; - case TYPEENUM: - if (copts.cplusplus) - return 0; - break; - default: - return 0; - } - break; - - case TYPEENUM: - switch (type2->type) { - case TYPEINT: - if (TYPE_INTEGRAL(TYPE_ENUM(expr->rtype)->enumtype)->integral < IT_INT) { - if (type1->size == type2->size && is_unsigned(TYPE_ENUM(type1)->enumtype)) { - if (type2 == TYPE(&stunsignedint)) - mode = SSCR_1; - } else { - if (type2 == TYPE(&stsignedint)) - mode = SSCR_1; - } - } else { - if (TYPE_ENUM(type1)->enumtype == type2) - mode = SSCR_1; - } - break; - case TYPEFLOAT: - break; - case TYPEENUM: - if (copts.cplusplus) - return 0; - break; - default: - return 0; - } - break; - - case TYPECLASS: { - short depth; - Boolean isambigbase; - - if (!IS_TYPE_CLASS(type1) || !CClass_GetBasePath(TYPE_CLASS(type1), TYPE_CLASS(type2), &depth, &isambigbase)) - return 0; - break; - } - - default: - return 0; - } - - return CExpr_SetupStandardConversionResult(expr, type2, qual2, mode, refFlag, x14, result); -} - -static ENode *CExpr_UserConversion(ENode *expr, Type *type2, UInt32 qual2, ImplicitConv *result, Boolean flag1, Boolean isExplicit, Boolean flag3) { - Object *object28; - Object *object27; - Object *object26; - ObjectList *objlist25; - ObjectList *objlist24; - ObjectList *objlist; - TypeFunc *tfunc23; - Type *tmptype23; - NameSpaceObjectList *list22; - Boolean flag22; - Boolean flag21; - FuncArg *arg21; - Boolean flag20; - ENode *newExpr; - ENode *funcref; - ENode *tmpExpr; - ENodeList *arglist; - UInt32 q1; - UInt32 q2; - StandardConv sc3; - StandardConv sc2; - StandardConv sc1; - ConversionIterator convIter; - ENodeList myarglist; - ObjectList myobjlist; - BClassList path; - - object28 = NULL; - object27 = NULL; - objlist25 = NULL; - objlist24 = NULL; - - if (type2->size == 0) - CDecl_CompleteType(type2); - if (expr->rtype->size == 0) - CDecl_CompleteType(expr->rtype); - - if (IS_TYPE_CLASS(expr->rtype)) { - CExpr_ConversionIteratorInit(&convIter, TYPE_CLASS(expr->rtype)); - flag22 = 1; - while ((object26 = CExpr_ConversionIteratorNext(&convIter))) { - tfunc23 = TYPE_FUNC(object26->type); - if (tfunc23->flags & FUNC_IS_TEMPL) { - object26 = CTempl_DeduceFromConversion(object26, type2, qual2); - if (!object26) - continue; - tfunc23 = TYPE_FUNC(object26->type); - } - - if (flag3) { - if ( - !IS_TYPE_REFERENCE(tfunc23->functype) || - !CExpr_IsReferenceCompatible(type2, qual2, TPTR_TARGET(tfunc23->functype), tfunc23->qual) - ) - continue; - } - - CError_ASSERT(1230, tfunc23->args && IS_TYPE_POINTER_ONLY(tfunc23->args->type)); - - q1 = ENODE_QUALS(expr); - q2 = tfunc23->args->qual; - if ((q1 & Q_CV) != (q2 & Q_CV)) { - if (!flag22) - continue; - if ((q1 & Q_CONST) && !(q2 & Q_CONST)) - continue; - if ((q1 & Q_VOLATILE) && !(q2 & Q_VOLATILE)) - continue; - flag21 = 1; - } else { - flag21 = 0; - } - - newExpr = CExpr_NewENode(ETEMP); - newExpr->rtype = tfunc23->functype; - newExpr->flags = tfunc23->qual & ENODE_FLAG_QUALS; - flag20 = 0; - - if (IS_TYPE_REFERENCE(newExpr->rtype)) { - newExpr->rtype = TPTR_TARGET(newExpr->rtype); - if (!CParser_IsConst(newExpr->rtype, tfunc23->qual)) { - newExpr = makemonadicnode(newExpr, EINDIRECT); - newExpr->data.monadic->rtype = TYPE(&void_ptr); - newExpr = makemonadicnode(newExpr, EINDIRECT); - newExpr->data.monadic->rtype = TYPE(&void_ptr); - flag20 = 1; - } - } - - if (CExpr_StandardConversionMatch(newExpr, type2, qual2, 0, &sc1)) { - if (flag22 && !flag21) { - object28 = NULL; - objlist25 = NULL; - flag22 = 0; - } - - if (object28 && object28 != object26) { - if (CExpr_IsBetterStandardConv(&sc3, &sc1)) - continue; - - if (!CExpr_IsBetterStandardConv(&sc1, &sc3)) { - objlist = lalloc(sizeof(ObjectList)); - objlist->next = objlist25; - objlist->object = object28; - objlist25 = objlist; - } else { - objlist25 = NULL; - } - } - - object28 = object26; - sc3 = sc1; - sc3.x15 = flag20; - } - } - } - - if (!flag3 && IS_TYPE_CLASS(type2) && (list22 = CClass_Constructor(TYPE_CLASS(type2)))) { - for (; list22; list22 = list22->next) { - object26 = OBJECT(list22->object); - if ( - object26->otype == OT_OBJECT && - IS_TYPE_FUNC(tfunc23 = TYPE_FUNC(object26->type)) && - (isExplicit || !(object26->qual & Q_EXPLICIT)) - ) - { - if (tfunc23->flags & FUNC_IS_TEMPL) { - myarglist.next = NULL; - myarglist.node = expr; - object26 = CTempl_DeduceFromFunctionCall(object26, NULL, &myarglist); - if (!object26) - continue; - tfunc23 = TYPE_FUNC(object26->type); - } - - if (!(arg21 = tfunc23->args)) - continue; - if (!(arg21 = arg21->next)) - continue; - if ((TYPE_CLASS(type2)->flags & CLASS_HAS_VBASES) && !(arg21 = arg21->next)) - continue; - if (arg21 == &elipsis) - continue; - if (arg21->next && !arg21->next->dexpr && arg21->next != &elipsis) - continue; - - tmptype23 = arg21->type; - if (IS_TYPE_REFERENCE(tmptype23)) { - tmptype23 = TPTR_TARGET(tmptype23); - if (!CParser_IsConst(tmptype23, arg21->qual) && !CExpr_IsLValue(expr)) - continue; - } - - if (CExpr_StandardConversionMatch(expr, tmptype23, arg21->qual, 0, &sc1)) { - if (object27) { - if (object26->u.func.inst && !object27->u.func.inst) - continue; - if (CExpr_IsBetterStandardConv(&sc2, &sc1)) - continue; - - if (!CExpr_IsBetterStandardConv(&sc1, &sc2)) { - if (!object26->u.func.inst && object27->u.func.inst) { - objlist24 = NULL; - } else { - objlist = lalloc(sizeof(ObjectList)); - objlist->next = objlist25; - objlist->object = object28; - objlist25 = objlist; - } - } else { - objlist25 = NULL; - } - } - - object27 = object26; - sc2 = sc1; - } - } - } - } - - if (object28 && object27) { - if (!CExpr_IsBetterStandardConv(&sc2, &sc3)) { - if (!CExpr_IsBetterStandardConv(&sc3, &sc2)) { - if (result) { - result->type = ICT_2; - result->u.ic2.x2 = object28; - result->u.ic2.standardConv = sc3; - } - if (flag1) { - myobjlist.next = NULL; - myobjlist.object = object27; - CError_OverloadedFunctionError(object28, &myobjlist); - } - } else { - object27 = NULL; - } - } else { - object28 = NULL; - } - } - - if (object28) { - if (result) { - result->type = ICT_2; - result->u.ic2.x2 = object28; - result->u.ic2.standardConv = sc3; - } - if (!flag1) - return expr; - if (objlist25) - CError_OverloadedFunctionError(object28, objlist25); - tfunc23 = TYPE_FUNC(object28->type); - CError_ASSERT(1416, IS_TYPEFUNC_METHOD(tfunc23)); - - funcref = create_objectrefnode(object28); - object28->flags |= OBJECT_USED; - - arglist = lalloc(sizeof(ENodeList)); - arglist->next = NULL; - - expr = getnodeaddress(expr, 0); - arglist->node = CExpr_AssignmentPromotion( - expr, - CDecl_NewPointerType(TYPE(TYPE_METHOD(tfunc23)->theclass)), - expr->flags, - 0); - - newExpr = lalloc(sizeof(ENode)); - newExpr->type = EFUNCCALL; - newExpr->cost = 4; - newExpr->rtype = tfunc23->functype; - newExpr->flags = tfunc23->qual & ENODE_FLAG_QUALS; - newExpr->data.funccall.funcref = funcref; - newExpr->data.funccall.args = arglist; - newExpr->data.funccall.functype = TYPE_FUNC(object28->type); - newExpr = CExpr_AdjustFunctionCall(newExpr); - newExpr = checkreference(newExpr); - - if (newExpr->rtype != type2) { - if (flag3) { - tmpExpr = CExpr_DerivedToBase(newExpr, type2, qual2, 1, 0, 1); - if (tmpExpr) - return tmpExpr; - } - newExpr = CExpr_Convert(newExpr, type2, qual2, 0, 1); - } - return newExpr; - } - - if (object27) { - if (result) { - result->type = ICT_2; - result->u.ic2.x2 = object27; - result->u.ic2.standardConv = sc2; - } - if (!flag1) - return expr; - if (objlist24) - CError_OverloadedFunctionError(object27, objlist24); - - arglist = lalloc(sizeof(ENodeList)); - arglist->next = NULL; - arglist->node = expr; - - if (TYPE_CLASS(type2)->flags & CLASS_HAS_VBASES) { - arglist->next = lalloc(sizeof(ENodeList)); - arglist->next->node = expr; - arglist->next->next = NULL; - arglist->node = intconstnode(TYPE(&stsignedshort), 1); - } - - path.next = NULL; - path.type = type2; - - tmpExpr = makemonadicnode(create_temp_node(type2), EINDIRECT); - tmpExpr->rtype = type2; - - newExpr = CExpr_GenericFuncCall( - &path, tmpExpr, 0, object27, NULL, NULL, arglist, 0, 0, 1 - ); - - if (ENODE_IS2(newExpr, EFUNCCALL, EFUNCCALLP)) { - newExpr->rtype = CDecl_NewPointerType(type2); - newExpr = makemonadicnode(newExpr, EINDIRECT); - newExpr->rtype = type2; - } - - return newExpr; - } - - return NULL; -} - -static Boolean CExpr_UserConversionMatch(ENode *expr, Type *type2, UInt32 qual2, ImplicitConv *result) { - Boolean flag; - - if (IS_TYPE_REFERENCE(type2)) { - type2 = TPTR_TARGET(type2); - flag = !CParser_IsConst(type2, qual2); - } else { - expr = pointer_generation(expr); - flag = 0; - } - - if (CExpr_UserConversion(expr, type2, qual2, result, 0, 0, flag)) - return 1; - - return 0; -} - -static Boolean CExpr_ImplicitConversionMatch(ENode *expr, Type *type2, UInt32 qual2, ImplicitConv *result) { - if (CExpr_StandardConversionMatch(expr, type2, qual2, 0, &result->u.ic3.standardConv)) { - result->type = ICT_3; - return 1; - } - - if (IS_TYPE_CLASS(expr->rtype) || IS_TYPE_CLASS(type2) || (IS_TYPE_REFERENCE(type2) && IS_TYPE_CLASS(TPTR_TARGET(type2)))) { - if (CExpr_UserConversionMatch(expr, type2, qual2, result)) { - result->type = ICT_2; - return 1; - } - } - - return 0; -} - -Boolean CExpr_CanImplicitlyConvert(ENode *expr, Type *type2, UInt32 qual2) { - ImplicitConv result; - return CExpr_ImplicitConversionMatch(expr, type2, qual2, &result); -} - -static ENode *CExpr_DerivedToBase(ENode *expr, Type *type2, UInt32 qual2, Boolean flag1, Boolean nullcheckflag, Boolean pathcheckflag) { - BClassList *path; - short depth; - Boolean isambigbase; - - if ( - IS_TYPE_CLASS(type2) && - IS_TYPE_CLASS(expr->rtype) && - (path = CClass_GetBasePath(TYPE_CLASS(expr->rtype), TYPE_CLASS(type2), &depth, &isambigbase)) - ) - { - if (isambigbase) - CError_Error(CErrorStr188); - if (flag1) - CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC); - - if (pathcheckflag) { - expr = getnodeaddress(expr, 0); - expr = makemonadicnode(CExpr_ClassPointerCast(path, expr, nullcheckflag), EINDIRECT); - expr->rtype = type2; - expr->flags = qual2 & ENODE_FLAG_QUALS; - } - - return expr; - } - else { - return NULL; - } -} - -static ENode *CExpr_ClassReferenceConversion(ENode *expr, Type *type2, UInt32 qual2, Boolean pathcheckflag) { - int refcompat; - - if (CExpr_IsLValue(expr) && IS_TYPE_CLASS(type2) && IS_TYPE_CLASS(expr->rtype)) { - refcompat = CExpr_IsReferenceCompatible(type2, 0, expr->rtype, 0); - if (refcompat > 0) { - if (refcompat == 2) { - CError_ASSERT(1668, IS_TYPE_CLASS(type2) && IS_TYPE_CLASS(expr->rtype)); - expr = CExpr_DerivedToBase(expr, type2, qual2, pathcheckflag, 0, 1); - } - expr->flags = qual2 & ENODE_FLAG_QUALS; - return expr; - } - - refcompat = CExpr_IsReferenceCompatible(expr->rtype, 0, type2, 0); - if (refcompat > 0) { - expr = CClass_ClassPointerCast( - getnodeaddress(expr, 0), - TYPE_CLASS(expr->rtype), TYPE_CLASS(type2), - 1, 1, pathcheckflag - ); - CError_ASSERT(1680, IS_TYPE_POINTER_ONLY(expr->rtype)); - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = type2; - expr->flags = qual2 & ENODE_FLAG_QUALS; - return expr; - } - } - - if (IS_TYPE_CLASS(expr->rtype)) { - if ((expr = CExpr_UserConversion(expr, type2, qual2, NULL, 1, 0, 1))) - return expr; - } - - return NULL; -} - -static ENode *CExpr_BindToReference(ENode *expr, Type *type2, UInt32 qual2) { - UInt32 cv; - int refcompat; - ENode *tmp; - - cv = CParser_GetCVTypeQualifiers(type2, qual2); - - if (CExpr_IsLValue(expr)) { - refcompat = CExpr_IsReferenceCompatible(type2, qual2, expr->rtype, ENODE_QUALS(expr)); - if (refcompat > 0) { - if (refcompat == 2) { - CError_ASSERT(1718, IS_TYPE_CLASS(type2) && IS_TYPE_CLASS(expr->rtype)); - expr = CExpr_DerivedToBase(expr, type2, qual2, 1, 0, 1); - } - return getnodeaddress(expr, 0); - } - } else if (IS_TYPE_CLASS(type2) && IS_TYPE_CLASS(expr->rtype)) { - refcompat = CExpr_IsReferenceCompatible(type2, qual2, expr->rtype, ENODE_QUALS(expr)); - if (refcompat > 0) { - if (refcompat == 2) - expr = CExpr_DerivedToBase(expr, type2, qual2, 1, 0, 1); - return getnodeaddress(expr, 0); - } - } - - if (IS_TYPE_CLASS(expr->rtype)) { - if ((tmp = CExpr_UserConversion(expr, type2, qual2, NULL, 1, 0, 1))) - return getnodeaddress(tmp, 0); - } - - if (!(cv & Q_CONST)) - CError_Error(CErrorStr228); - if (cv & Q_VOLATILE) - CError_Error(CErrorStr259); - - if (expr->rtype != type2) - expr = CExpr_Convert(expr, type2, qual2, 0, 1); - - if (!CExpr_IsLValue(expr)) { - expr = CExpr_LValue(expr, 0, 0); - if (!ENODE_IS(expr, EINDIRECT)) - expr = get_address_of_temp_copy(expr, 1); - else - expr = getnodeaddress(expr, 0); - } else { - expr = getnodeaddress(expr, 0); - } - - return expr; -} - -ENode *CExpr_Convert(ENode *expr, Type *type, UInt32 qual, Boolean isExplicit, Boolean flag2) { - UInt32 cv; - ENode *refExpr; - ENode *newExpr; - Type *typeCopy; - NameSpaceObjectList myList; - - cv = qual & Q_CV; - - if (copts.cpp_extensions && is_typesame(expr->rtype, type) && !ENODE_IS(expr, EOBJLIST)) { - expr = CExpr_RewriteConst(expr); - expr->rtype = type; - expr->flags &= ~ENODE_FLAG_QUALS; - expr->flags |= cv; - return expr; - } - - if (type == TYPE(&stvoid)) { - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = type; - expr->flags = cv; - return expr; - } - - if (IS_TYPE_REFERENCE(type)) { - if (isExplicit) { - refExpr = CExpr_ClassReferenceConversion(expr, TPTR_TARGET(type), qual, flag2); - if (refExpr) - return refExpr; - - expr = getnodeaddress(expr, 0); - typeCopy = galloc(sizeof(TypePointer)); - *TYPE_POINTER(typeCopy) = *TYPE_POINTER(type); - TPTR_QUAL(typeCopy) &= ~Q_REFERENCE; - expr = CExpr_Convert(expr, typeCopy, qual, 0, flag2); - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = TPTR_TARGET(type); - expr->flags = cv; - return expr; - } else { - return CExpr_BindToReference(expr, TPTR_TARGET(type), qual); - } - } - - if ( - (IS_TYPE_ARRAY(expr->rtype) && !IS_TYPE_ARRAY(type)) || - (IS_TYPE_FUNC(expr->rtype) && !IS_TYPE_FUNC(type)) - ) - { - expr = pointer_generation(expr); - } else { - expr = CExpr_RewriteConst(expr); - } - - if (ENODE_IS(expr, EOBJLIST)) { - if (CExpr_OverloadFuncMatch(expr->data.objlist.list, expr->data.objlist.templargs, type, &refExpr)) - return refExpr; - } else if (ENODE_IS(expr, EOBJREF) && IS_TEMPL_FUNC(expr->data.objref->type)) { - myList.next = NULL; - myList.object = OBJ_BASE(expr->data.objref); - if (CExpr_OverloadFuncMatch(&myList, NULL, type, &refExpr)) - return refExpr; - } else if (IS_TYPE_CLASS(expr->rtype) || IS_TYPE_CLASS(type)) { - if (expr->rtype->size == 0) - CDecl_CompleteType(expr->rtype); - - if (IS_TYPE_CLASS(type)) { - CanAllocObject(type); - if (!CClass_CopyConstructor(TYPE_CLASS(type)) || CClass_IsTrivialCopyClass(TYPE_CLASS(type))) { - if (expr->rtype == type) - return expr; - - refExpr = CExpr_DerivedToBase(expr, type, qual, flag2, 0, 1); - if (refExpr) - return refExpr; - } - } - - refExpr = CExpr_UserConversion(expr, type, qual, NULL, 1, isExplicit, 0); - if (refExpr) { - refExpr->flags = cv; - return refExpr; - } - } else if (!isExplicit && is_typesame(expr->rtype, type)) { - if (ENODE_IS(expr, EINDIRECT) && ENODE_QUALS(expr) != cv) - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = type; - expr->flags = cv; - return expr; - } else { - if ( - copts.warn_implicitconv && - !isExplicit && - IS_TYPE_INT_OR_FLOAT(type) && - IS_TYPE_INT_OR_FLOAT(expr->rtype) - ) - CExpr_CheckArithmConversion(expr, type); - - switch (type->type) { - case TYPEINT: - if (type == TYPE(&stbool)) { - switch (expr->rtype->type) { - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - case TYPEMEMBERPOINTER: - case TYPEPOINTER: - return CExpr_ConvertToBool(expr, isExplicit); - } - } else { - switch (expr->rtype->type) { - case TYPEENUM: - expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; - case TYPEINT: - case TYPEFLOAT: - do_int_float_conversion: - if ( - ENODE_IS(expr, ETYPCON) && - expr->rtype->type == type->type && - expr->rtype->size == type->size && - is_unsigned(expr->rtype) == is_unsigned(type) && - ENODE_QUALS(expr) == qual - ) - { - expr->rtype = type; - expr->flags |= ENODE_FLAG_80; - return expr; - } else { - refExpr = promote(expr, type); - refExpr->flags = cv; - return refExpr; - } - break; - case TYPEPOINTER: - if (expr->rtype->size > type->size && copts.warn_ptr_int_conv) - CError_Warning(CErrorStr382); - if (ENODE_IS(expr, ETYPCON)) { - ENode *inner = expr->data.monadic; - if (ENODE_IS(inner, EINTCONST)) { - inner->rtype = type; - inner->flags = cv; - inner->data.intval = CExpr_IntConstConvert(type, TYPE(&stunsignedlong), inner->data.intval); - return inner; - } - } - if (type->size != 4) { - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = TYPE(&stunsignedlong); - } - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = type; - expr->flags = cv; - return expr; - } - } - break; - - case TYPEFLOAT: - switch (expr->rtype->type) { - case TYPEENUM: - expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; - case TYPEINT: - case TYPEFLOAT: - goto do_int_float_conversion; - } - break; - - case TYPEENUM: - expr = CExpr_Convert(expr, TYPE_ENUM(type)->enumtype, qual, isExplicit, flag2); - if (!ENODE_IS(expr, EINTCONST)) - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = type; - expr->flags = cv; - return expr; - - case TYPEPOINTER: - switch (expr->rtype->type) { - case TYPEENUM: - expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; - case TYPEINT: - if (expr->rtype->size != 4) { - if (!ENODE_IS(expr, EINTCONST)) - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = TYPE(&stunsignedlong); - } - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = type; - expr->flags = cv; - return expr; - - case TYPEPOINTER: - if (IS_TYPE_CLASS(TPTR_TARGET(expr->rtype)) && IS_TYPE_CLASS(TPTR_TARGET(type))) - expr = CExpr_SafeClassPointerCast(expr, TYPE_CLASS(TPTR_TARGET(expr->rtype)), TYPE_CLASS(TPTR_TARGET(type)), 1, flag2); - if (!ENODE_IS(expr, ETYPCON)) - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = type; - expr->flags = cv; - return expr; - } - break; - - case TYPEMEMBERPOINTER: - if (!IS_TYPE_MEMBERPOINTER(expr->rtype)) - expr = CExpr_MemberPointerConversion(expr, TYPE_MEMBER_POINTER(type), 1); - - if (IS_TYPE_MEMBERPOINTER(expr->rtype)) { - expr = PointerToMemberCast(expr, TYPE_MEMBER_POINTER(expr->rtype), TYPE_MEMBER_POINTER(type), flag2); - expr->flags = cv; - return expr; - } - break; - } - } - - if (isExplicit) { - if ((newExpr = CodeGen_HandleTypeCast(expr, type, qual))) - return newExpr; - } - - CError_Error( - isExplicit ? CErrorStr247 : CErrorStr209, - expr->rtype, ENODE_QUALS(expr), - type, qual); - return nullnode(); -} - -ENode *CExpr_AssignmentPromotion(ENode *expr, Type *type2, UInt32 qual2, Boolean flag) { - ImplicitConv result; - - if (copts.old_argmatch) - return oldassignmentpromotion(expr, type2, qual2, flag); - - if (ENODE_IS(expr, EMEMBER)) - expr = getpointertomemberfunc(expr, type2, 1); - - if (!CExpr_ImplicitConversionMatch(expr, type2, qual2, &result)) { - CError_Error(CErrorStr209, expr->rtype, ENODE_QUALS(expr), type2, qual2); - return nullnode(); - } - - return CExpr_Convert(expr, type2, qual2, 0, flag); -} - -static Boolean CExpr_IsBetterMatch(Match *a, Match *b, int count) { - ImplicitConv *convA; - ImplicitConv *convB; - int i; - Boolean flag; - - convA = a->conv; - convB = b->conv; - flag = 0; - - if (convA->type != ICT_0 && convB->type != ICT_0) { - if (CExpr_IsBetterImplicitConv(convB, convA)) - return 0; - if (CExpr_IsBetterImplicitConv(convA, convB)) - flag = 1; - } - - for (i = 0; i < count; i++) { - if (CExpr_IsBetterImplicitConv(++convB, ++convA)) - return 0; - if (CExpr_IsBetterImplicitConv(convA, convB)) - flag = 1; - } - - if (flag) - return 1; - - if (b->object) { - CError_ASSERT(2165, IS_TYPE_FUNC(b->object->type)); - if (b->object->u.func.inst) { - if (!a->object) - return 1; - - CError_ASSERT(2169, IS_TYPE_FUNC(a->object->type)); - if (!a->object->u.func.inst) - return 1; - - CError_ASSERT(2174, a->specialfunc && b->specialfunc); - if (CTempl_FuncIsMoreSpecialized(a->specialfunc, b->specialfunc)) - return 1; - } - } - - return 0; -} - -static Boolean CExpr_MatchArgs(Object *func, ENodeList *argexprs, ENode *expr, ImplicitConv *convs) { - FuncArg *args; - ENode *newExpr; - Type *type; - - args = TYPE_FUNC(func->type)->args; - - if (!(TYPE_FUNC(func->type)->flags & FUNC_METHOD)) { - convs->type = ICT_0; - } else if (TYPE_METHOD(func->type)->is_static) { - convs->type = ICT_0; - } else if (TYPE_FUNC(func->type)->flags & FUNC_IS_CTOR) { - convs->type = ICT_0; - args = args->next; - } else { - if (!expr) - return 0; - - newExpr = lalloc(sizeof(ENode)); - newExpr->type = EINTCONST; - newExpr->cost = 0; - newExpr->flags = expr->flags; - newExpr->rtype = CDecl_NewPointerType(expr->rtype); - newExpr->data.intval = cint64_zero; - - if (func->datatype == DALIAS) { - CError_ASSERT(2231, func->u.alias.member); - type = CDecl_NewPointerType(func->u.alias.member->type); - } else { - type = args->type; - } - - if (!CExpr_ImplicitConversionMatch(newExpr, type, args->qual, convs)) - return 0; - args = args->next; - } - - convs++; - while (1) { - if (!args || args->type == &stvoid) { - if (argexprs) - return 0; - else - return 1; - } - - if (args == &elipsis || args == &oldstyle) { - while (argexprs) { - convs->type = ICT_1; - argexprs = argexprs->next; - convs++; - } - return 1; - } - - if (!argexprs) - return args->dexpr != NULL; - - if (!CExpr_ImplicitConversionMatch(argexprs->node, args->type, args->qual, convs)) - return 0; - - argexprs = argexprs->next; - args = args->next; - convs++; - } -} - -static Object *CExpr_GetMatchObject(Match *match, HashNameNode *name) { - Object *object; - FuncArg *arg; - TypeFunc *tfunc; - - if (match->object) - return match->object; - - tfunc = lalloc(sizeof(TypeFunc)); - memclrw(tfunc, sizeof(TypeFunc)); - tfunc->type = TYPEFUNC; - tfunc->functype = &stvoid; - - arg = lalloc(sizeof(FuncArg)); - memclrw(arg, sizeof(FuncArg)); - arg->type = match->type; - arg->qual = match->qual; - tfunc->args = arg; - - if (match->type2) { - arg = lalloc(sizeof(FuncArg)); - memclrw(arg, sizeof(FuncArg)); - arg->type = match->type2; - arg->qual = match->qual2; - tfunc->args->next = arg; - } - - object = lalloc(sizeof(Object)); - memclrw(object, sizeof(Object)); - object->name = name; - object->datatype = DFUNC; - object->nspace = cscope_root; - object->type = TYPE(tfunc); - return object; -} - -static Match *CExpr_FindBestMatch(Match *matches, int count, HashNameNode *name, ObjectList **outList, ENodeList *argExprs) { - Match *scan; - Match *best; - ObjectList *listHead; - ObjectList *list; - - best = matches; - for (scan = matches->next; scan; scan = scan->next) { - if (CExpr_IsBetterMatch(scan, best, count)) - best = scan; - } - - for (scan = matches, listHead = NULL; scan; scan = scan->next) { - if (scan != best && !CExpr_IsBetterMatch(best, scan, count)) { - list = lalloc(sizeof(ObjectList)); - list->next = listHead; - list->object = CExpr_GetMatchObject(scan, name); - listHead = list; - } - } - - if (!outList) { - if (listHead) - CError_OverloadedFunctionError(CExpr_GetMatchObject(best, name), listHead); - } else { - *outList = listHead; - } - - return best; -} - -void CExpr_FuncArgMatch(NameSpaceObjectList *list, TemplArg *templargs, ENodeList *argexprs, Match13 *match13, ENode *expr, Boolean flag) { - NameSpaceObjectList *i; - NameSpaceObjectList *j; - Match *match; - Match *matches; - Object *object; - Object *object2; - Object *specialfunc; - ENodeList *argscan; - int argcount; - - for (argscan = argexprs, argcount = 0; argscan; argscan = argscan->next) { - CDecl_CompleteType(argscan->node->rtype); - argcount++; - } - - matches = NULL; - match = lalloc(sizeof(Match) + ((argcount - 2) * sizeof(ImplicitConv))); - - for (i = list; i; i = i->next) { - object = OBJECT(i->object); - if ( - object->otype == OT_OBJECT && - IS_TYPE_FUNC(object->type) && - (!flag || !(object->qual & Q_EXPLICIT)) - ) - { - if (object->datatype == DALIAS && (TYPE_FUNC(object->type)->flags & FUNC_METHOD)) { - for (j = list; j; j = j->next) { - if (j == i) - continue; - - object2 = OBJECT(j->object); - if ( - object2->otype == OT_OBJECT && - IS_TYPE_METHOD(object2->type) && - (TYPE_FUNC(object2->type)->flags & FUNC_FLAGS_CV) == (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_CV) - ) - { - FuncArg *argsA; - FuncArg *argsB; - argsA = TYPE_FUNC(object->type)->args; - if (argsA && !TYPE_METHOD(object->type)->is_static) - argsA = argsA->next; - argsB = TYPE_FUNC(object2->type)->args; - if (argsB && !TYPE_METHOD(object2->type)->is_static) - argsB = argsB->next; - if (is_arglistsame(argsA, argsB)) - break; - } - } - - if (j) - continue; - } - - if (TYPE_FUNC(object->type)->flags & FUNC_IS_TEMPL) { - specialfunc = object; - object = CTempl_DeduceFromFunctionCall(object, templargs, argexprs); - if (!object) - continue; - } else { - if (templargs) - continue; - specialfunc = NULL; - } - - if (CExpr_MatchArgs(object, argexprs, expr, match->conv)) { - match->object = object; - match->specialfunc = specialfunc; - match->next = matches; - matches = match; - match = lalloc(sizeof(Match) + ((argcount - 2) * sizeof(ImplicitConv))); - } - } - } - - if (matches) { - matches = CExpr_FindBestMatch(matches, argcount, NULL, &match13->list, argexprs); - match13->obj = matches->object; - } -} - -static ConversionTypeList *CExpr_BuildConversionTypeList(ENode *expr) { - ConversionTypeList *first; - ConversionTypeList *list; - Object *object; - Type *type; - ConversionIterator convIter; - - if (!IS_TYPE_CLASS(expr->rtype)) { - first = lalloc(sizeof(ConversionTypeList)); - first->next = NULL; - first->func = NULL; - first->type = expr->rtype; - first->qual = ENODE_QUALS(expr); - if (IS_TYPE_ENUM(first->type)) - first->qual = 0; - } else { - first = NULL; - CExpr_ConversionIteratorInit(&convIter, TYPE_CLASS(expr->rtype)); - while ((object = CExpr_ConversionIteratorNext(&convIter))) { - type = TYPE_FUNC(object->type)->functype; - if (IS_TYPE_REFERENCE(type)) - type = TPTR_TARGET(type); - - if (!IS_TYPE_CLASS(type)) { - list = lalloc(sizeof(ConversionTypeList)); - list->next = first; - list->func = object; - list->type = type; - list->qual = TYPE_FUNC(object->type)->qual & Q_CV; - first = list; - } - } - } - - return first; -} - -static Type *CExpr_NextPromotedIntegralType(int *p) { - switch (++(*p)) { - case 1: return TYPE(&stsignedint); - case 2: return TYPE(&stunsignedint); - case 3: return TYPE(&stsignedlong); - case 4: return TYPE(&stunsignedlong); - case 5: - if (copts.longlong) - return TYPE(&stsignedlonglong); - else - return NULL; - case 6: - if (copts.longlong) - return TYPE(&stunsignedlonglong); - else - return NULL; - } - - return NULL; -} - -static Type *CExpr_NextArithmeticType(int *p) { - switch (++(*p)) { - case 1: return TYPE(&stbool); - case 2: return TYPE(&stchar); - case 3: return TYPE(&stsignedchar); - case 4: return TYPE(&stunsignedchar); - case 5: return TYPE(&stwchar); - case 6: return TYPE(&stsignedshort); - case 7: return TYPE(&stunsignedshort); - case 8: return TYPE(&stsignedint); - case 9: return TYPE(&stunsignedint); - case 10: return TYPE(&stsignedlong); - case 11: return TYPE(&stunsignedlong); - case 12: return TYPE(&stfloat); - case 13: return TYPE(&stdouble); - case 14: return TYPE(&stlongdouble); - case 15: - if (copts.longlong) - return TYPE(&stsignedlonglong); - else - return NULL; - case 16: - if (copts.longlong) - return TYPE(&stunsignedlonglong); - else - return NULL; - } - - return NULL; -} - -static Type *CExpr_NextPromotedArithmeticType(int *p) { - switch (++(*p)) { - case 1: return TYPE(&stsignedint); - case 2: return TYPE(&stunsignedint); - case 3: return TYPE(&stsignedlong); - case 4: return TYPE(&stunsignedlong); - case 5: return TYPE(&stdouble); - case 6: return TYPE(&stlongdouble); - case 7: - if (copts.longlong) - return TYPE(&stsignedlonglong); - else - return NULL; - case 8: - if (copts.longlong) - return TYPE(&stunsignedlonglong); - else - return NULL; - } - - return NULL; -} - -static Match *CExpr_MatchBuiltin(Match *matches, ENode *left, Type *leftType, UInt32 leftQual, ENode *right, Type *rightType, UInt32 rightQual) { - Match *scan; - Match mymatch; - - if (CExpr_ImplicitConversionMatch(left, leftType, leftQual, &mymatch.conv[0])) { - if (!right || CExpr_ImplicitConversionMatch(right, rightType, rightQual, &mymatch.conv[1])) { - if (right) { - for (scan = matches; scan; scan = scan->next) { - if ( - !scan->object && - is_typesame(scan->type, leftType) && - scan->qual == leftQual && - is_typesame(scan->type2, rightType) && - scan->qual2 == rightQual - ) - return matches; - } - } - - mymatch.next = matches; - mymatch.object = NULL; - mymatch.specialfunc = NULL; - mymatch.type = leftType; - mymatch.qual = leftQual; - mymatch.type2 = rightType; - mymatch.qual2 = rightQual; - - matches = lalloc(sizeof(Match)); - *matches = mymatch; - } - } - - return matches; -} - -static Match *CExpr_CheckIncDecBuiltin(Match *matches, short token, ENode *expr1, ENode *expr2) { - Object *object; - Type *type; - TypeFunc *tfunc; - ConversionIterator convIter; - - if (IS_TYPE_CLASS(expr1->rtype)) { - CExpr_ConversionIteratorInit(&convIter, TYPE_CLASS(expr1->rtype)); - while ((object = CExpr_ConversionIteratorNext(&convIter))) { - tfunc = TYPE_FUNC(object->type); - if (IS_TYPE_REFERENCE(tfunc->functype)) { - type = TPTR_TARGET(tfunc->functype); - switch (type->type) { - case TYPEINT: - if (type == TYPE(&stbool) && token == TK_DECREMENT) - break; - case TYPEFLOAT: - case TYPEPOINTER: - if (!CParser_IsConst(type, tfunc->qual)) { - matches = CExpr_MatchBuiltin( - matches, - expr1, type, tfunc->qual, - expr2, expr2 ? TYPE(&stsignedint) : NULL, 0 - ); - } - break; - } - } - } - } - - return matches; -} - -static Match *CExpr_CheckUnaryBuiltin(Match *matches, short token, ENode *expr) { - ConversionTypeList *typelist; - Type *type; - int typenum; - - switch (token) { - case TK_INCREMENT: - case TK_DECREMENT: - return CExpr_CheckIncDecBuiltin(matches, token, expr, NULL); - - case '!': - matches = CExpr_MatchBuiltin(matches, expr, TYPE(&stbool), 0, NULL, NULL, 0); - break; - - case '~': - typenum = 0; - while ((type = CExpr_NextPromotedIntegralType(&typenum))) { - matches = CExpr_MatchBuiltin(matches, expr, type, 0, NULL, NULL, 0); - } - break; - - case '*': - case '+': - for (typelist = CExpr_BuildConversionTypeList(expr); typelist; typelist = typelist->next) { - if (IS_TYPE_POINTER_ONLY(typelist->type)) - matches = CExpr_MatchBuiltin(matches, expr, typelist->type, typelist->qual, NULL, NULL, 0); - } - if (token != '+') - break; - - case '-': - typenum = 0; - while ((type = CExpr_NextPromotedArithmeticType(&typenum))) { - matches = CExpr_MatchBuiltin(matches, expr, type, 0, NULL, NULL, 0); - } - break; - } - - return matches; -} - -static Match *CExpr_CheckBinaryBuiltin(Match *matches, ENode *left, short token, ENode *right) { - int typenum1; - int typenum2; - Type *type1; - Type *type2; - Type *ptrdiff; - Boolean allowPtrDiffOnRight; - Boolean allowPtrCV; - Boolean allowPtrDiffOnLeft; - Boolean allowMemberPtrs; - Boolean allowEnum; - ConversionTypeList *leftList; - ConversionTypeList *rightList; - ConversionTypeList *scan; - - switch (token) { - case TK_INCREMENT: - case TK_DECREMENT: - return CExpr_CheckIncDecBuiltin(matches, token, left, right); - - case '*': - case '+': - case '-': - case '/': - case ':': - case '<': - case '>': - case TK_LOGICAL_EQ: - case TK_LOGICAL_NE: - case TK_LESS_EQUAL: - case TK_GREATER_EQUAL: - typenum1 = 0; - while ((type1 = CExpr_NextPromotedArithmeticType(&typenum1))) { - typenum2 = 0; - while ((type2 = CExpr_NextPromotedArithmeticType(&typenum2))) { - matches = CExpr_MatchBuiltin(matches, left, type1, 0, right, type2, 0); - } - } - break; - - case '%': - case '&': - case '^': - case '|': - case TK_SHL: - case TK_SHR: - typenum1 = 0; - while ((type1 = CExpr_NextPromotedIntegralType(&typenum1))) { - typenum2 = 0; - while ((type2 = CExpr_NextPromotedIntegralType(&typenum2))) { - matches = CExpr_MatchBuiltin(matches, left, type1, 0, right, type2, 0); - } - } - return matches; - - case TK_LOGICAL_OR: - case TK_LOGICAL_AND: - return CExpr_MatchBuiltin(matches, left, TYPE(&stbool), 0, right, TYPE(&stbool), 0); - } - - allowEnum = 0; - allowMemberPtrs = 0; - allowPtrCV = 0; - allowPtrDiffOnLeft = 0; - allowPtrDiffOnRight = 0; - - switch (token) { - case '+': - case '[': - allowPtrDiffOnLeft = 1; - allowPtrDiffOnRight = 1; - break; - case '-': - allowPtrCV = 1; - allowPtrDiffOnRight = 1; - break; - case ':': - case TK_LOGICAL_EQ: - case TK_LOGICAL_NE: - allowMemberPtrs = 1; - case '<': - case '>': - case TK_LESS_EQUAL: - case TK_GREATER_EQUAL: - allowPtrCV = 1; - allowEnum = 1; - break; - default: - return matches; - } - - leftList = CExpr_BuildConversionTypeList(left); - rightList = CExpr_BuildConversionTypeList(right); - ptrdiff = CABI_GetPtrDiffTType(); - - for (scan = leftList; ; scan = scan->next) { - if (!scan) { - scan = rightList; - if (!rightList) - break; - rightList = NULL; - } - - type1 = scan->type; - if (IS_TYPE_REFERENCE(type1)) - type1 = TPTR_TARGET(type1); - - switch (type1->type) { - case TYPEENUM: - if (allowEnum) - matches = CExpr_MatchBuiltin(matches, left, type1, scan->qual, right, type1, scan->qual); - break; - - case TYPEPOINTER: - if (allowPtrDiffOnRight) - matches = CExpr_MatchBuiltin(matches, left, type1, scan->qual, right, ptrdiff, 0); - if (allowPtrDiffOnLeft) - matches = CExpr_MatchBuiltin(matches, left, ptrdiff, 0, right, type1, scan->qual); - if (allowPtrCV) { - if (IS_TYPE_POINTER_ONLY(TPTR_TARGET(type1))) { - type2 = galloc(sizeof(TypePointer)); - *TYPE_POINTER(type2) = *TYPE_POINTER(type1); - TPTR_QUAL(type2) |= Q_CONST | Q_VOLATILE; - matches = CExpr_MatchBuiltin(matches, left, type2, scan->qual, right, type2, scan->qual); - } else { - matches = CExpr_MatchBuiltin(matches, left, type1, Q_CONST | Q_VOLATILE, right, type1, Q_CONST | Q_VOLATILE); - } - } - break; - - case TYPEMEMBERPOINTER: - if (allowMemberPtrs) - matches = CExpr_MatchBuiltin(matches, left, type1, scan->qual, right, type1, scan->qual); - break; - } - } - - return matches; -} - -static Boolean CExpr_MatchOperands(ENode *left, Type *leftType, UInt32 leftQual, ENode *right, Type *rightType, UInt32 rightQual, ImplicitConv *twoResults, Boolean flag) { - if (flag) { - if (!CExpr_StandardConversionMatch(left, leftType, leftQual, 1, &twoResults[0].u.ic3.standardConv)) - return 0; - twoResults[0].type = ICT_3; - } else { - if (!CExpr_ImplicitConversionMatch(left, leftType, leftQual, &twoResults[0])) - return 0; - } - - if (right) { - if (!CExpr_ImplicitConversionMatch(right, rightType, rightQual, &twoResults[1])) - return 0; - } - - return 1; -} - -Boolean CExpr_CondOperatorMatch(ENode *left, ENode *right, Conversion *conv) { - Match *match; - - if ((match = CExpr_CheckBinaryBuiltin(NULL, left, ':', right))) { - match = CExpr_FindBestMatch(match, 1, GetHashNameNode("operator?:"), NULL, NULL); - CError_ASSERT(2931, !match->object); - - conv->x0 = NULL; - conv->left = CExpr_Convert(left, match->type, match->qual, 0, 1); - conv->right = CExpr_Convert(right, match->type2, match->qual2, 0, 1); - return 1; - } - - return 0; -} - -Boolean CExpr_OperatorMatch(short token, ENode *left, ENode *right, Conversion *conv) { - HashNameNode *name; - ENodeList *argExprs; - BClassList *path; - int hasArg; - Match *matches; - Object *object; - Object *specialfunc; - NameSpaceObjectList *list; - Type *leftType; - UInt32 leftQual; - Type *rightType; - UInt32 rightQual; - NameResult pr; - NameSpaceObjectList myList; - Match myMatch; - - if (!IS_TYPE_CLASS(left->rtype)) { - if (!IS_TYPE_ENUM(left->rtype)) { - if (!right || !(IS_TYPE_CLASS(right->rtype) || IS_TYPE_ENUM(right->rtype))) - return 0; - } - } else { - CDecl_CompleteType(left->rtype); - } - - name = CMangler_OperatorName(token); - path = NULL; - - argExprs = lalloc(sizeof(ENodeList)); - argExprs->node = left; - if (right) { - argExprs->next = lalloc(sizeof(ENodeList)); - argExprs->next->node = right; - argExprs->next->next = NULL; - hasArg = 1; - } else { - argExprs->next = NULL; - hasArg = 0; - } - - matches = NULL; - - if (IS_TYPE_CLASS(left->rtype) && CScope_FindClassMemberObject(TYPE_CLASS(left->rtype), &pr, name)) { - if (token != '=' || (pr.bcl_18->type == left->rtype && !pr.bcl_18->next)) { - if (pr.obj_10) { - myList.next = NULL; - myList.object = pr.obj_10; - pr.nsol_14 = &myList; - } else { - CError_ASSERT(3009, pr.nsol_14); - } - - for (list = pr.nsol_14; list; list = list->next) { - object = OBJECT(list->object); - if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type)) { - if (TYPE_FUNC(object->type)->flags & FUNC_IS_TEMPL) { - specialfunc = object; - object = CTempl_DeduceFromFunctionCall(object, NULL, argExprs->next); - if (!object) - continue; - } else { - specialfunc = NULL; - } - - leftType = CExpr_GetImplictObjectParamType(object, &leftQual); - if (right) { - if (!CExpr_HasNParams(object, 1)) - continue; - rightType = CExpr_GetParamType(object, 0, &rightQual); - } else { - if (!CExpr_HasNParams(object, 0)) - continue; - } - - if (CExpr_MatchOperands(left, leftType, leftQual, right, rightType, rightQual, myMatch.conv, 1)) { - myMatch.object = object; - myMatch.specialfunc = specialfunc; - myMatch.next = matches; - matches = lalloc(sizeof(Match)); - *matches = myMatch; - path = pr.bcl_18; - } - } - } - } - } - - if (CScope_FindNonClassObject(cscope_current, &pr, name)) { - if (pr.obj_10) { - myList.next = NULL; - myList.object = pr.obj_10; - pr.nsol_14 = &myList; - } - } else { - pr.nsol_14 = NULL; - } - - if (copts.arg_dep_lookup) - pr.nsol_14 = CScope_ArgumentDependentNameLookup(pr.nsol_14, name, argExprs, 1); - - for (list = pr.nsol_14; list; list = list->next) { - object = OBJECT(list->object); - if (object->otype == OT_OBJECT && IS_TYPE_NONMETHOD(object->type)) { - if (TYPE_FUNC(object->type)->flags & FUNC_IS_TEMPL) { - specialfunc = object; - object = CTempl_DeduceFromFunctionCall(object, NULL, argExprs); - if (!object) - continue; - } else { - specialfunc = NULL; - } - - leftType = CExpr_GetParamType(object, 0, &leftQual); - if (right) { - if (!CExpr_HasNParams(object, 2)) - continue; - rightType = CExpr_GetParamType(object, 1, &rightQual); - } else { - if (!CExpr_HasNParams(object, 1)) - continue; - } - - if (CExpr_MatchOperands(left, leftType, leftQual, right, rightType, rightQual, myMatch.conv, 0)) { - myMatch.object = object; - myMatch.specialfunc = specialfunc; - myMatch.next = matches; - matches = lalloc(sizeof(Match)); - *matches = myMatch; - } - } - } - - if (right) - matches = CExpr_CheckBinaryBuiltin(matches, left, token, right); - else - matches = CExpr_CheckUnaryBuiltin(matches, token, left); - - if (matches) { - conv->x0 = NULL; - conv->left = NULL; - conv->right = NULL; - - matches = CExpr_FindBestMatch(matches, hasArg, name, NULL, argExprs); - object = matches->object; - if (!object) { - if (IS_TYPE_CLASS(left->rtype)) - conv->left = CExpr_Convert(left, matches->type, matches->qual, 0, 1); - else - conv->left = left; - - if (right) { - if (IS_TYPE_CLASS(right->rtype)) - conv->right = CExpr_Convert(right, matches->type2, matches->qual2, 0, 1); - else - conv->right = right; - } - - return 1; - } - - if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(object->type))) { - CError_ASSERT(3125, path); - left = CExpr_GenericFuncCall(path, argExprs->node, 0, object, NULL, NULL, argExprs->next, 0, 0, 1); - } else { - left = CExpr_GenericFuncCall(NULL, NULL, 0, object, NULL, NULL, argExprs, 0, 0, 1); - } - - conv->x0 = checkreference(left); - return 1; - } - - return 0; -} - -static ENode *CExpr_ClassCopyInit(TypeClass *tclass, ENode *expr1, ENode *expr2) { - Object *best; - NameSpaceObjectList *list; - ObjectList *objlist; - ObjectList *objlistEntry; - ENodeList *argExprs; - FuncArg *arg; - Type *type; - Object *object; - ImplicitConv bestConv; - ImplicitConv conv; - BClassList path; - ConversionIterator convIter; - - best = NULL; - objlist = NULL; - - for (list = CClass_Constructor(tclass); list; list = list->next) { - object = OBJECT(list->object); - if (object->otype == OT_OBJECT && IS_TYPE_FUNC(object->type) && !(object->qual & Q_EXPLICIT)) { - arg = TYPE_FUNC(object->type)->args; - - CError_ASSERT(3199, arg); - arg = arg->next; - - if (tclass->flags & CLASS_HAS_VBASES) { - CError_ASSERT(3203, arg); - arg = arg->next; - } - - if ( - arg && - arg != &elipsis && - (!arg->next || arg->next->dexpr) && - CExpr_ImplicitConversionMatch(expr2, arg->type, arg->qual, &conv) - ) - { - if (!best || CExpr_IsBetterImplicitConv(&conv, &bestConv)) { - best = object; - bestConv = conv; - objlist = NULL; - } else if (!CExpr_IsBetterImplicitConv(&bestConv, &conv)) { - objlistEntry = lalloc(sizeof(ObjectList)); - objlistEntry->next = objlist; - objlistEntry->object = object; - objlist = objlistEntry; - } - } - } - } - - if (IS_TYPE_CLASS(expr2->rtype)) { - CExpr_ConversionIteratorInit(&convIter, TYPE_CLASS(expr2->rtype)); - while ((object = CExpr_ConversionIteratorNext(&convIter))) { - type = TYPE_FUNC(object->type)->functype; - if (IS_TYPE_REFERENCE(type)) - type = TPTR_TARGET(type); - - if ( - IS_TYPE_CLASS(type) && - (tclass == TYPE_CLASS(type) || CClass_IsBaseClass(tclass, TYPE_CLASS(type), NULL, 0, 0)) - ) - { - CError_ASSERT(3248, TYPE_FUNC(object->type)->args && - IS_TYPE_POINTER_ONLY(TYPE_FUNC(object->type)->args->type)); - - type = galloc(sizeof(TypePointer)); - *TYPE_POINTER(type) = *TYPE_POINTER(TYPE_FUNC(object->type)->args->type); - TPTR_QUAL(type) = Q_REFERENCE; - if (CExpr_ImplicitConversionMatch(expr2, type, TYPE_FUNC(object->type)->args->qual, &conv)) { - if (!best || CExpr_IsBetterImplicitConv(&conv, &bestConv)) { - best = object; - bestConv = conv; - objlist = NULL; - } else if (!CExpr_IsBetterImplicitConv(&bestConv, &conv)) { - objlistEntry = lalloc(sizeof(ObjectList)); - objlistEntry->next = objlist; - objlistEntry->object = object; - objlist = objlistEntry; - } - } - } - } - } - - if (objlist) - CError_OverloadedFunctionError(best, objlist); - - if (!best) { - CError_Error(CErrorStr209, expr2->rtype, ENODE_QUALS(expr2), tclass, 0); - return expr1; - } - - CError_ASSERT(3284, IS_TYPE_POINTER_ONLY(expr1->rtype)); - - expr1 = makemonadicnode(expr1, EINDIRECT); - expr1->rtype = TYPE(tclass); - - argExprs = lalloc(sizeof(ENodeList)); - argExprs->node = expr2; - if (tclass->flags & CLASS_HAS_VBASES) { - argExprs->next = lalloc(sizeof(ENodeList)); - argExprs->next->next = NULL; - argExprs->next->node = intconstnode(TYPE(&stsignedshort), 1); - } else { - argExprs->next = NULL; - } - - path.next = NULL; - path.type = TYPE(tclass); - expr1 = CExpr_GenericFuncCall(&path, expr1, 0, best, NULL, NULL, argExprs, 0, 0, 1); - - if (ENODE_IS2(expr1, EFUNCCALL, EFUNCCALLP)) - expr1->rtype = CDecl_NewPointerType(TYPE(tclass)); - - expr1 = makemonadicnode(expr1, EINDIRECT); - expr1->rtype = TYPE(tclass); - return expr1; -} diff --git a/compiler_and_linker/unsorted/CFunc.c b/compiler_and_linker/unsorted/CFunc.c deleted file mode 100644 index 38cfab3..0000000 --- a/compiler_and_linker/unsorted/CFunc.c +++ /dev/null @@ -1,3224 +0,0 @@ -#include "compiler/CFunc.h" -#include "compiler/CABI.h" -#include "compiler/CClass.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CException.h" -#include "compiler/CExpr.h" -#include "compiler/CInit.h" -#include "compiler/CInline.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CParser.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CSOM.h" -#include "compiler/CTemplateTools.h" -#include "compiler/CodeGen.h" -#include "compiler/CompilerTools.h" -#include "compiler/Exceptions.h" -#include "compiler/FuncLevelAsmPPC.h" -#include "compiler/InlineAsmPPC.h" -#include "compiler/ObjGenMachO.h" -#include "compiler/Switch.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/types.h" - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -struct CFuncSave { - CScopeSave scope; - ObjectList *arguments; - ObjectList *locals; - CLabel *labels; - Statement *curstmt; - DeclBlock *firstblock; - DeclBlock *currentblock; - ExceptionAction *cexcept_dobjstack; - CLabel *sinit_label; - ENode *ainit_expr; - CtorChain *ctor_chain; - ParserTryBlock *trychain; - TempNodeCB cinit_tempnodefunc; - HashNameNode *tkidentifier; - Object *sinit_first_object; - FileOffsetInfo cparser_fileoffset; - TStreamElement symdecltoken; - SInt32 functionbodyoffset; - HashNameNode *functionbodypath; - SInt32 symdecloffset; - SInt32 symdeclend; - SInt32 sourceoffset; - HashNameNode *sourcefilepath; - SInt32 curstmtvalue; - NameObjCheckCB name_obj_check; - FuncArg *check_arglist; - short blockcount; - short localcount; - short tk; - AccessType global_access; - Boolean cexcept_hasdobjects; - Boolean ainit_only_one; - Boolean cfunc_is_extern_c; - Boolean temp_reference_init; -}; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -FuncArg elipsis; -FuncArg oldstyle; -ObjectList *arguments; -ObjectList *locals; -short localcount; -SInt32 curstmtvalue; -SInt32 sourceoffset; -HashNameNode *sourcefilepath; -SInt32 functionbodyoffset; -HashNameNode *functionbodypath; -InitExpr *init_expressions; -CLabel *Labels; -CtorChain *ctor_chain; -Statement *curstmt; -static short temp_destructor_object_regmem; -static short temp_destructor_objects; -static short temp_expression_has_conditionals; -static DeclBlock *firstblock; -static DeclBlock *currentblock; -static short blockcount; -static Object *sinit_first_object; -static CLabel *sinit_label; -static Boolean ainit_only_one; -static ENode *ainit_expr; -static FuncArg *check_arglist; -static Boolean cfunc_is_extern_c; -static short cfunc_staticvarcount; -static void *destroyobjects; -static Boolean cfunc_hasdtortemp; - -// forward decls -static void statement(DeclThing *thing); - -static void CFunc_LoopIncrement(void) { - if (curstmtvalue >= 0x1000) { - if (curstmtvalue >= 0xF000) - curstmtvalue++; - else - curstmtvalue += 0x1000; - } else { - curstmtvalue <<= 3; - } -} - -static void CFunc_LoopDecrement(void) { - if (curstmtvalue > 0x1000) { - if (curstmtvalue > 0xF000) - curstmtvalue--; - else - curstmtvalue -= 0x1000; - } else { - curstmtvalue >>= 3; - } - - if (curstmtvalue < 1) - curstmtvalue = 1; -} - -DeclBlock *CFunc_NewDeclBlock(void) { - DeclBlock *block; - NameSpace *nspace; - - block = lalloc(sizeof(DeclBlock)); - if (firstblock) { - currentblock->next = block; - currentblock = block; - } else { - firstblock = block; - currentblock = block; - } - - block->index = blockcount++; - block->parent_nspace = cscope_current; - block->dobjstack = cexcept_dobjstack; - - nspace = CScope_NewListNameSpace(NULL, 0); - nspace->parent = cscope_current; - cscope_current = nspace; - - return block; -} - -void CFunc_RestoreBlock(DeclBlock *block) { - if (curstmt && curstmt->dobjstack != cexcept_dobjstack) { - Statement *stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = nullnode(); - } - - cscope_current = block->parent_nspace; - cexcept_dobjstack = block->dobjstack; -} - -void CFunc_SetupLocalVarInfo(Object *obj) { - obj->u.var.info = CodeGen_GetNewVarInfo(); - obj->u.var.info->func = cscope_currentfunc; - - if (obj->sclass == TK_REGISTER) { - if (!copts.optimizesize) - obj->u.var.info->usage = 100; - else - obj->u.var.info->usage = 5; - } - - if (obj->type && is_volatile_object(obj)) - obj->u.var.info->noregister = 1; -} - -static void adjustargumenttype(DeclInfo *declinfo) { - switch (declinfo->thetype->type) { - case TYPECLASS: - if (TYPE_CLASS(declinfo->thetype)->sominfo) { - CError_Error(CErrorStr284); - declinfo->thetype = TYPE(&stsignedint); - } - break; - case TYPEFUNC: - makethetypepointer(declinfo, 0); - return; - case TYPEARRAY: - declinfo->thetype = CDecl_NewPointerType(TPTR_TARGET(declinfo->thetype)); - return; - case TYPETEMPLATE: - if (TYPE_TEMPLATE(declinfo->thetype)->dtype == TEMPLDEP_ARRAY) - declinfo->thetype = CDecl_NewPointerType(TYPE_TEMPLATE(declinfo->thetype)->u.array.type); - return; - } - - if (!CanCreateObject(declinfo->thetype)) - declinfo->thetype = TYPE(&stsignedint); -} - -static FuncArg *CFunc_IsInArgList(FuncArg *list, HashNameNode *name) { - while (list) { - if (name == list->name) - return list; - list = list->next; - } - - return NULL; -} - -static Object *CFunc_IsInObjList(ObjectList *list, HashNameNode *name) { - while (list) { - if (name == list->object->name) - return list->object; - list = list->next; - } - - return NULL; -} - -static void CFunc_AppendArg(FuncArg **list, FuncArg *arg) { - FuncArg *tail; - - if ((tail = *list)) { - while (tail->next) - tail = tail->next; - tail->next = arg; - } else { - *list = arg; - } -} - -static void identifier_list(DeclInfo *declinfo) { - FuncArg *arg; - - declinfo->x45 = 1; - - while (1) { - if (tk != TK_IDENTIFIER) { - CError_Error(CErrorStr121); - } else { - if (CFunc_IsInArgList(declinfo->x18, tkidentifier)) - CError_Error(CErrorStr122, tkidentifier->name); - - arg = CParser_NewFuncArg(); - arg->name = tkidentifier; - CFunc_AppendArg(&declinfo->x18, arg); - declinfo->x44 = 1; - } - - if ((tk = lex()) != ',') - break; - tk = lex(); - } -} - -static Boolean defarg_name_obj_check(HashNameNode *name, Object *obj) { - FuncArg *arg; - - if (name) { - for (arg = check_arglist; arg; arg = arg->next) { - if (arg->name == name) { - CError_Error(CErrorStr205); - return 0; - } - } - } - - if (obj && obj->datatype == DLOCAL) { - CError_Error(CErrorStr205); - return 0; - } - - return 1; -} - -ENode *CFunc_DefaultArg(Type *type, UInt32 qual, FuncArg *args) { - TStreamElement *element; - ENode *expr; - ENode *templdepexpr; - - name_obj_check = defarg_name_obj_check; - check_arglist = args; - expr = conv_assignment_expression(); - name_obj_check = NULL; - - if ( - !CTemplTool_IsTemplateArgumentDependentExpression(expr) && - !CTemplTool_IsTemplateArgumentDependentType(type) - ) - { - expr = argumentpromotion(expr, type, qual, 1); - } else { - element = CPrep_CurStreamElement(); - if (element && element->tokenfile) { - templdepexpr = CExpr_NewTemplDepENode(TDE_SOURCEREF); - templdepexpr->data.templdep.u.sourceref.expr = expr; - templdepexpr->data.templdep.u.sourceref.token = galloc(sizeof(TStreamElement)); - *templdepexpr->data.templdep.u.sourceref.token = *element; - expr = templdepexpr; - } - } - - return CInline_CopyExpression(expr, CopyMode1); -} - -static FuncArg *parameter_list(DeclInfo *declinfo) { - Boolean flag26; - FuncArg *args; - FuncArg *arg; - DeclInfo my_di; - Boolean isArray; - - args = NULL; - flag26 = 1; - - while (1) { - if (tk == TK_ELLIPSIS) { - if (flag26) { - if (!copts.cplusplus && copts.ANSIstrict) - CError_Warning(CErrorStr127); - args = &elipsis; - } else { - CFunc_AppendArg(&args, &elipsis); - } - - tk = lex(); - return args; - } - - memclrw(&my_di, sizeof(my_di)); - CParser_GetDeclSpecs(&my_di, 0); - if (my_di.x48) - CError_Error(CErrorStr127); - - if ( - my_di.storageclass && - my_di.storageclass != TK_REGISTER && - (!copts.cplusplus || my_di.storageclass != TK_AUTO) - ) - { - CError_Error(CErrorStr127); - my_di.storageclass = 0; - } - - my_di.name = NULL; - - scandeclarator(&my_di); - - if (flag26) { - flag26 = 0; - if (my_di.thetype == &stvoid) { - if (my_di.storageclass || my_di.qual || my_di.name) - CError_Error(CErrorStr127); - return NULL; - } - } - - isArray = IS_TYPE_ARRAY(my_di.thetype); - adjustargumenttype(&my_di); - - if (my_di.name) { - if (args && CFunc_IsInArgList(args, my_di.name)) - CError_Error(CErrorStr122, my_di.name->name); - } else { - my_di.name = no_name_node; - } - - if (my_di.thetype == &stvoid) - CError_Error(CErrorStr126); - - arg = CParser_NewFuncArg(); - arg->name = my_di.name; - arg->type = my_di.thetype; - arg->qual = my_di.qual; - arg->sclass = my_di.storageclass; - arg->is_array = isArray; - CFunc_AppendArg(&args, arg); - - if (copts.cplusplus && tk == '=') { - tk = lex(); - arg->dexpr = CFunc_DefaultArg(arg->type, arg->qual, args); - } - - if (tk != ',') { - if (tk != TK_ELLIPSIS || !copts.cplusplus) - return args; - } else { - tk = lex(); - } - } -} - -Boolean CFunc_ParseFakeArgList(Boolean flag) { - DeclInfo di; - - if (tk == TK_ELLIPSIS) - return 1; - - do { - memclrw(&di, sizeof(di)); - CParser_GetDeclSpecs(&di, 0); - - if (di.x48) - return 0; - - scandeclarator(&di); - - if (tk == '=') { - tk = lex(); - assignment_expression(); - } - - switch (tk) { - case TK_ELLIPSIS: - return 1; - case ',': - if (!flag) - tk = lex(); - else - return 1; - break; - default: - return 0; - } - } while (tk != TK_ELLIPSIS); - - return 1; -} - -FuncArg *parameter_type_list(DeclInfo *declinfo) { - FuncArg *args; - NameSpace *nspace; - Boolean save_in_func_arglist; - - declinfo->x44 = 0; - declinfo->x45 = 0; - declinfo->x1C = NULL; - - if (tk == TK_ELLIPSIS || isdeclaration(0, 0, 0, 0)) { - if (!copts.cplusplus) { - nspace = CScope_NewListNameSpace(NULL, 0); - nspace->parent = cscope_current; - cscope_current = nspace; - - save_in_func_arglist = in_func_arglist; - in_func_arglist = 1; - args = parameter_list(declinfo); - in_func_arglist = save_in_func_arglist; - - cscope_current = nspace->parent; - - if (!CScope_IsEmptyNameSpace(nspace)) - declinfo->x1C = nspace; - } else { - args = parameter_list(declinfo); - } - } else if (copts.cplusplus) { - args = NULL; - if (tk != ')') - CError_Error(CErrorStr127); - } else { - identifier_list(declinfo); - args = &oldstyle; - } - - return args; -} - -CLabel *findlabel(void) { - CLabel *scan; - - for (scan = Labels; scan; scan = scan->next) { - if (tkidentifier == scan->name) - return scan; - } - - return NULL; -} - -CLabel *newlabel(void) { - CLabel *label = lalloc(sizeof(CLabel)); - memclrw(label, sizeof(CLabel)); - - label->name = label->uniquename = CParser_GetUniqueName(); - return label; -} - -Statement *CFunc_AppendStatement(StatementType sttype) { - Statement *stmt = lalloc(sizeof(Statement)); - - stmt->next = NULL; - stmt->type = sttype; - stmt->value = curstmtvalue; - stmt->flags = 0; - stmt->sourceoffset = sourceoffset; - stmt->sourcefilepath = sourcefilepath; - stmt->dobjstack = cexcept_dobjstack; - - curstmt->next = stmt; - curstmt = stmt; - return stmt; -} - -Statement *CFunc_InsertStatement(StatementType sttype, Statement *after) { - Statement *stmt = lalloc(sizeof(Statement)); - - stmt->next = after->next; - after->next = stmt; - stmt->type = sttype; - stmt->value = after->value; - stmt->flags = 0; - stmt->sourceoffset = after->sourceoffset; - stmt->sourcefilepath = after->sourcefilepath; - stmt->dobjstack = after->dobjstack; - - return stmt; -} - -Statement *CFunc_InsertBeforeStatement(StatementType sttype, Statement *before) { - Statement *stmt = lalloc(sizeof(Statement)); - - *stmt = *before; - before->next = stmt; - before->type = sttype; - before->flags = 0; - - return before; -} - -void CheckCLabels(void) { - CLabel *scan; - - for (scan = Labels; scan; scan = scan->next) { - if (!scan->stmt) - CError_Error(CErrorStr159, scan->name->name); - } -} - -Object *create_temp_object(Type *type) { - Object *object = CParser_NewLocalDataObject(NULL, 1); - object->name = CParser_GetUniqueName(); - object->type = type; - CFunc_SetupLocalVarInfo(object); - return object; -} - -ENode *create_temp_node(Type *type) { - ENode *node; - - if (cinit_tempnodefunc) - return cinit_tempnodefunc(type, 0); - - node = CExpr_NewETEMPNode(type, 0); - if (IS_TYPE_CLASS(type) && CClass_Destructor(TYPE_CLASS(type))) - node->data.temp.needs_dtor = 1; - return node; -} - -ENode *create_temp_node2(Type *type) { - ENode *node; - - if (cinit_tempnodefunc) - return cinit_tempnodefunc(type, 1); - - node = CExpr_NewETEMPNode(type, 0); - node->data.temp.needs_dtor = 1; - return node; -} - -static ENode *CFunc_DestroyReverse(ENode *expr, DtorTemp *list) { - expr = makediadicnode(expr, CABI_DestroyObject(list->dtor, create_objectrefnode(list->object), CABIDestroy1, 1, 0), ECOMMA); - expr->rtype = &stvoid; - if (list->next) - expr = CFunc_DestroyReverse(expr, list->next); - return expr; -} - -static ENode *CFunc_TempTransDestroy(ENode *expr, DtorTemp *list, Boolean flag) { - Object *tempobj; - - if (flag) { - CError_ASSERT(738, !(IS_TYPE_CLASS(expr->rtype) && CClass_Destructor(TYPE_CLASS(expr->rtype)))); - tempobj = create_temp_object(expr->rtype); - expr = makediadicnode(create_objectnode(tempobj), expr, EASS); - } - - expr = CFunc_DestroyReverse(expr, list); - - if (flag) { - expr = makediadicnode(expr, create_objectnode(tempobj), ECOMMA); - expr->rtype = tempobj->type; - } - - return expr; -} - -void CFunc_WarnUnused(void) { - if (copts.warn_unusedvar) { - ObjectList *list; - for (list = locals; list; list = list->next) { - if ( - !(list->object->flags & OBJECT_USED) && - !IsTempName(list->object->name) && - !(list->object->qual & Q_INLINE_DATA) - ) - { - CError_SetErrorToken(&list->object->u.var.info->deftoken); - CError_Warning(CErrorStr182, &list->object->name->name); - } - } - } - - if (copts.warn_unusedarg) { - ObjectList *list; - for (list = arguments; list; list = list->next) { - if ( - !(list->object->flags & OBJECT_USED) && - !IsTempName(list->object->name) && - list->object->name != this_name_node && - list->object->name != self_name_node - ) - { - CError_SetErrorToken(&symdecltoken); - CError_Warning(CErrorStr182, &list->object->name->name); - } - } - } -} - -void CFunc_CodeCleanup(Statement *stmt) { - if (cscope_currentclass && cscope_currentclass->sominfo) - CSOM_InitSOMSelf(cscope_currentclass, stmt); - - CFunc_WarnUnused(); - CExcept_ExceptionTansform(stmt); -} - -static Boolean DestructorNeeded(ExceptionAction *ea, ExceptionAction *end) { - while (ea) { - if (CExcept_ActionNeedsDestruction(ea)) - return 1; - if (ea == end) - break; - ea = ea->prev; - } - - return 0; -} - -static Statement *DestructLocals(Statement *stmt, ExceptionAction *ea, ExceptionAction *end) { - while (ea) { - stmt = CExcept_ActionCleanup(ea, stmt); - if (ea == end) - break; - ea = ea->prev; - } - - return stmt; -} - -static Boolean NeedsDestruction(Statement *stmt1, Statement *stmt2) { - ExceptionAction *ea2; - ExceptionAction *ea1; - ExceptionAction *scan; - - ea1 = stmt1->dobjstack; - ea2 = stmt2->dobjstack; - - for (scan = ea2; scan; scan = scan->prev) { - if (scan == ea1) - return 0; - } - - while (ea1 && ea1 != ea2) { - if (CExcept_ActionNeedsDestruction(ea1)) - return 1; - ea1 = ea1->prev; - } - - return 0; -} - -static ExceptionAction *FindLastNonCommonStackObj(Statement *stmt1, Statement *stmt2) { - ExceptionAction *ea1; - ExceptionAction *ea2; - - for (ea2 = stmt2->dobjstack; ea2; ea2 = ea2->prev) { - for (ea1 = stmt1->dobjstack; ea1; ea1 = ea1->prev) { - if (ea1->prev == ea2) - return ea1; - } - } - - return NULL; -} - -static void DestructorReturnTransform(Statement *stmt1, Statement *stmt2) { - Statement *stmt; - Object *tempobj; - - if (stmt1->dobjstack != stmt2->dobjstack && NeedsDestruction(stmt1, stmt2)) - stmt1 = DestructLocals(stmt1, stmt1->dobjstack, FindLastNonCommonStackObj(stmt1, stmt2)); - - if (DestructorNeeded(stmt2->dobjstack, NULL)) { - if (CMach_GetFunctionResultClass(TYPE_FUNC(cscope_currentfunc->type)) != 1) { - tempobj = create_temp_object(stmt2->expr->rtype); - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt1); - stmt->expr = makediadicnode(create_objectnode(tempobj), stmt2->expr, EASS); - stmt->sourceoffset = stmt2->sourceoffset; - stmt->sourcefilepath = stmt2->sourcefilepath; - DestructLocals(stmt, stmt2->dobjstack, NULL); - stmt2->expr = create_objectnode(tempobj); - } else { - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt1); - stmt->expr = stmt2->expr; - stmt->sourceoffset = stmt2->sourceoffset; - stmt->sourcefilepath = stmt2->sourcefilepath; - DestructLocals(stmt, stmt2->dobjstack, NULL); - stmt2->expr = nullnode(); - } - } -} - -static Statement *DestructorIfTransform(Statement *stmt) { - CLabel *label; - Statement *newStmt; - - if (stmt->type == ST_IFGOTO) - stmt->type = ST_IFNGOTO; - else - stmt->type = ST_IFGOTO; - - label = newlabel(); - newStmt = DestructLocals(stmt, stmt->dobjstack, FindLastNonCommonStackObj(stmt, stmt->label->stmt)); - newStmt = CFunc_InsertStatement(ST_GOTO, newStmt); - newStmt->label = stmt->label; - newStmt = CFunc_InsertStatement(ST_LABEL, newStmt); - newStmt->label = label; - label->stmt = newStmt; - stmt->label = label; - newStmt->dobjstack = stmt->dobjstack; - return newStmt; -} - -static Boolean IsSubStack(ExceptionAction *exc1, ExceptionAction *exc2) { - if (!exc1) - return 1; - - while (exc2) { - if (exc2 == exc1) - return 1; - exc2 = exc2->prev; - } - - return 0; -} - -static void CFunc_CheckInitSkip(Statement *stmt, ExceptionAction *exc) { - if (stmt->dobjstack != exc && !IsSubStack(exc, stmt->dobjstack)) { - while (exc) { - if (CExcept_ActionNeedsDestruction(exc) && exc->type != EAT_ACTIVECATCHBLOCK) { - CError_Warning(CErrorStr211); - break; - } - exc = exc->prev; - } - } -} - -void CFunc_DestructorCleanup(Statement *stmt) { - Statement *scan; - Statement *next; - SwitchCase *swcase; - - if (copts.cplusplus) { - for (scan = stmt; scan; scan = scan->next) { - switch (scan->type) { - case ST_NOP: - case ST_LABEL: - case ST_EXPRESSION: - case ST_RETURN: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - case ST_GOTOEXPR: - case ST_ASM: - break; - case ST_SWITCH: - CFunc_CheckInitSkip(scan, ((SwitchInfo *) scan->label)->defaultlabel->stmt->dobjstack); - for (swcase = ((SwitchInfo *) scan->label)->cases; swcase; swcase = swcase->next) { - CFunc_CheckInitSkip(scan, swcase->label->stmt->dobjstack); - } - break; - case ST_GOTO: - case ST_IFGOTO: - case ST_IFNGOTO: - CFunc_CheckInitSkip(scan, scan->label->stmt->dobjstack); - break; - default: - CError_FATAL(1045); - } - } - - if (cexcept_hasdobjects) { - while (1) { - next = stmt->next; - if (!next) { - if (stmt->type != ST_RETURN && stmt->dobjstack) - DestructLocals(stmt, stmt->dobjstack, NULL); - return; - } - - switch (next->type) { - case ST_GOTO: - if ( - stmt->dobjstack != next->label->stmt->dobjstack && - NeedsDestruction(stmt, next->label->stmt) - ) - { - DestructLocals(stmt, stmt->dobjstack, FindLastNonCommonStackObj(stmt, next->label->stmt)); - } - stmt = next; - continue; - - case ST_RETURN: - if (next->expr && DestructorNeeded(stmt->dobjstack, NULL)) { - DestructorReturnTransform(stmt, next); - } else if (stmt->dobjstack) { - DestructLocals(stmt, stmt->dobjstack, NULL); - } - stmt = next; - continue; - } - - switch (stmt->type) { - case ST_GOTO: - case ST_SWITCH: - case ST_RETURN: - case ST_GOTOEXPR: - break; - case ST_NOP: - case ST_LABEL: - case ST_EXPRESSION: - case ST_IFGOTO: - case ST_IFNGOTO: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - case ST_ASM: - if ( - stmt->dobjstack != next->dobjstack && - NeedsDestruction(stmt, next) - ) - { - DestructLocals(stmt, stmt->dobjstack, FindLastNonCommonStackObj(stmt, next)); - } - break; - default: - CError_FATAL(1109); - } - - switch (next->type) { - case ST_NOP: - case ST_LABEL: - case ST_EXPRESSION: - case ST_SWITCH: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - case ST_ASM: - stmt = next; - continue; - - case ST_IFGOTO: - case ST_IFNGOTO: - if ( - next->dobjstack != next->label->stmt->dobjstack && - NeedsDestruction(next, next->label->stmt) - ) - { - stmt = DestructorIfTransform(next); - } else { - stmt = next; - } - break; - - default: - CError_FATAL(1138); - } - } - } - } -} - -static void scancase(DeclThing *thing) { - SwitchCase *swcase; - Statement *stmt; - CInt64 min; - CInt64 max; - - if (!thing->switchinfo) { - CError_Error(CErrorStr169); - return; - } - - tk = lex(); - min = CExpr_IntConstConvert(thing->switchinfo->x8, thing->switchinfo->x8, CExpr_IntegralConstExpr()); - if (!copts.ANSIstrict && tk == TK_ELLIPSIS) { - tk = lex(); - max = CExpr_IntConstConvert(thing->switchinfo->x8, thing->switchinfo->x8, CExpr_IntegralConstExpr()); - if (CInt64_Greater(min, max)) - CError_Error(CErrorStr366); - if (thing->switchinfo->x8->size == stsignedlonglong.size) - CError_Error(CErrorStr368); - } else { - max = min; - } - - for (swcase = thing->switchinfo->cases; swcase; swcase = swcase->next) { - if (CInt64_GreaterEqual(swcase->min, min) && CInt64_LessEqual(swcase->min, max)) - CError_Error(CErrorStr172); - if (CInt64_GreaterEqual(swcase->max, min) && CInt64_LessEqual(swcase->max, max)) - CError_Error(CErrorStr172); - if (CInt64_Less(swcase->min, min) && CInt64_Greater(swcase->max, max)) - CError_Error(CErrorStr172); - } - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = newlabel(); - stmt->label->stmt = stmt; - - swcase = lalloc(sizeof(SwitchCase)); - swcase->min = min; - swcase->label = stmt->label; - swcase->next = thing->switchinfo->cases; - thing->switchinfo->cases = swcase; - swcase->max = max; - - if (tk != ':') - CError_ErrorSkip(CErrorStr170); - else - tk = lex(); - - statement(thing); -} - -static void CFunc_NameLocalStaticDataObject(Object *obj, char *str) { - char buf[64]; - HashNameNode *name; - - if (!(cscope_currentfunc && (cscope_currentfunc->qual & Q_INLINE)) || CParser_HasInternalLinkage(cscope_currentfunc)) { - obj->name = CParser_AppendUniqueName(str); - } else { - sprintf(buf, "$localstatic%" PRId32 "$", cfunc_staticvarcount++); - name = CMangler_GetLinkName(cscope_currentfunc); - name = CParser_NameConcat(buf, name->name); - name = CParser_NameConcat(str, name->name); - obj->name = name; - obj->qual |= Q_20000; - obj->sclass = 0; - } -} - -static void sinit_insert_expr(ENode *expr) { - Statement *stmt; - - if (!sinit_first_object) { - sinit_first_object = CParser_NewCompilerDefDataObject(); - sinit_first_object->type = TYPE(&stsignedchar); - sinit_first_object->sclass = TK_STATIC; - CFunc_NameLocalStaticDataObject(sinit_first_object, "init"); - CInit_DeclareData(sinit_first_object, NULL, NULL, sinit_first_object->type->size); - - sinit_label = newlabel(); - stmt = CFunc_AppendStatement(ST_IFGOTO); - stmt->expr = create_objectnode(sinit_first_object); - stmt->label = sinit_label; - } - - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = expr; -} - -static void ainit_insert_expr(ENode *expr) { - Statement *stmt; - - if (ainit_only_one) { - if (ainit_expr) { - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = ainit_expr; - } - ainit_expr = expr; - } else { - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = expr; - } -} - -static ENode *ainit_register_object(Type *type, Object *local, SInt32 offset, Boolean flag) { - return CExcept_RegisterDestructorObject(local, offset, CClass_Destructor(TYPE_CLASS(type)), flag); -} - -static void CFunc_LocalDataDeclarator(DeclInfo *di, TStreamElement *deftoken, Boolean flag1, Boolean flag2) { - Object *object; - Object *aliasObject; - NameSpace *globalNS; - NameSpaceObjectList *nsol; - NameSpaceName *nsname; - Statement *stmt; - - if (di->nspace) - CError_Error(CErrorStr121); - - CDecl_CompleteType(di->thetype); - - object = NULL; - - if ((nsol = CScope_FindName(cscope_current, di->name))) { - switch (nsol->object->otype) { - case OT_OBJECT: - object = OBJECT(nsol->object); - break; - case OT_NAMESPACE: - CError_Error(CErrorStr321); - return; - case OT_ENUMCONST: - case OT_TYPE: - CError_Error(CErrorStr322); - break; - case OT_TYPETAG: - break; - default: - CError_FATAL(1344); - } - } - - if (object) - CError_Error(CErrorStr333, object); - - if (di->storageclass == TK_EXTERN) { - object = NULL; - globalNS = CScope_FindGlobalNS(cscope_current); - if ((nsol = CScope_FindName(globalNS, di->name))) { - switch (nsol->object->otype) { - case OT_OBJECT: - object = OBJECT(nsol->object); - break; - case OT_NAMESPACE: - CError_Error(CErrorStr321); - return; - case OT_ENUMCONST: - case OT_TYPE: - CError_Error(CErrorStr322); - break; - case OT_TYPETAG: - break; - default: - CError_FATAL(1381); - } - } - - if (object) { - if ( - !is_typesame(di->thetype, object->type) || - (di->qual & (Q_CONST | Q_VOLATILE | Q_PASCAL | Q_20000 | Q_WEAK | Q_ALIGNED_MASK)) != (object->qual & (Q_CONST | Q_VOLATILE | Q_PASCAL | Q_20000 | Q_WEAK | Q_ALIGNED_MASK)) - ) - { - CError_Error(CErrorStr249, di->name->name, object->type, object->qual, di->thetype, di->qual); - } - } else { - object = CParser_NewGlobalDataObject(di); - object->nspace = globalNS; - } - - CParser_NewAliasObject(object, 0); - return; - } - - if (di->storageclass != TK_STATIC) - object = CParser_NewObject(di); - else - object = CParser_NewGlobalDataObject(di); - - object->name = di->name; - object->type = di->thetype; - object->qual = di->qual; - object->sclass = di->storageclass; - - switch (di->storageclass) { - case TK_STATIC: - if (flag1) { - CError_Error(CErrorStr177); - return; - } - if (flag2) - CError_Error(CErrorStr174); - - if (CanCreateObject(di->thetype)) { - CError_QualifierCheck(di->qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_20000 | Q_WEAK | Q_ALIGNED_MASK)); - CParser_NewAliasObject(object, 0); - object->nspace = cscope_root; - object->datatype = DDATA; - CFunc_NameLocalStaticDataObject(object, object->name->name); - - if (copts.cplusplus) { - sinit_first_object = NULL; - CInit_InitializeStaticData(object, sinit_insert_expr); - if (sinit_first_object) { - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = makediadicnode( - create_objectnode(sinit_first_object), - intconstnode(TYPE(&stsignedchar), 1), - EASS); - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = sinit_label; - sinit_label->stmt = stmt; - } - } else { - CInit_InitializeData(object); - } - } - break; - - case 0: - case TK_AUTO: - case TK_REGISTER: - if (CanCreateObject(di->thetype)) { - CError_QualifierCheck(di->qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_ALIGNED_MASK)); - object->datatype = DLOCAL; - CFunc_SetupLocalVarInfo(object); - - object->u.var.info->deftoken = *deftoken; - if (object->sclass == TK_REGISTER && flag1) - object->u.var.info->usage = 100; - - CScope_AddObject(cscope_current, object->name, OBJ_BASE(object)); - - if (!flag1) { - if (IS_TYPE_SOM_CLASS(di->thetype)) { - CSOM_InitAutoClass(object); - } else { - CInit_InitializeAutoData(object, ainit_insert_expr, ainit_register_object); - if (object->type != di->thetype && (IS_TYPE_STRUCT(object->type) || IS_TYPE_CLASS(object->type))) { - CError_ASSERT(1478, !cscope_current->is_hash); - CError_ASSERT(1479, nsname = CScope_FindNameSpaceName(cscope_current, object->name)); - CError_ASSERT(1480, nsname->first.object == OBJ_BASE(object)); - CError_ASSERT(1481, !nsname->first.next); - nsname->name = CParser_AppendUniqueName(object->name->name); - - aliasObject = CParser_NewAliasObject(object, 0); - aliasObject->type = di->thetype; - } - } - } - - if (object->datatype == DLOCAL) { - ObjectList *list = lalloc(sizeof(ObjectList)); - list->object = object; - list->next = locals; - locals = list; - } - - IsCompleteType(di->thetype); - } - break; - - default: - CError_FATAL(1504); - } -} - -static ENode *CFunc_ParseLocalDeclarationList(Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4) { - Type *type; - UInt32 qual; - DeclInfo di; - TStreamElement deftoken; - - ainit_expr = NULL; - ainit_only_one = flag2; - - while (flag2 || isdeclaration(copts.cplusplus, 0, 0, 0)) { - CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); - - memclrw(&di, sizeof(di)); - di.is_extern_c = cfunc_is_extern_c; - CParser_GetDeclSpecs(&di, 0); - - if (IS_TYPE_TEMPLATE(di.thetype)) { - CError_Error(CErrorStr146); - di.thetype = TYPE(&stsignedint); - } - - type = di.thetype; - qual = di.qual; - - if (tk != ';') { - while (1) { - deftoken = *CPrep_CurStreamElement(); - di.name = NULL; - scandeclarator(&di); - - if (di.name) { - if (di.storageclass != TK_TYPEDEF) { - if (IS_TYPE_FUNC(di.thetype)) { - if (!CDecl_FunctionDeclarator(&di, CScope_FindGlobalNS(cscope_current), 0, 0)) - break; - } else { - CFunc_LocalDataDeclarator(&di, &deftoken, flag1, flag2); - } - } else { - CDecl_TypedefDeclarator(&di); - } - } else { - CError_Error(CErrorStr134); - } - - if (tk == ';') - break; - - if (tk != ',') { - if (!flag2) - CError_Error(CErrorStr123); - break; - } - - di.nspace = NULL; - di.thetype = type; - di.qual = qual; - tk = lex(); - } - } else { - CParser_CheckAnonymousUnion(&di, 1); - } - - if (flag2) - break; - if (flag4) - break; - tk = lex(); - } - - if (flag2) { - if (!ainit_expr) { - if (!flag3) { - CError_Error(CErrorStr141); - ainit_expr = nullnode(); - } - } else { - ainit_expr = checkreference(ainit_expr); - } - } - - return ainit_expr; -} - -static void makeifstatement(ENode *expr, CLabel *label1, CLabel *label2, Boolean flag1, Boolean flag2) { - Statement *stmt; - CLabel *tmplabel; - - if (!expr) { - if (flag1) { - stmt = CFunc_AppendStatement(ST_GOTO); - stmt->label = label1; - return; - } - return; - } - - if ( - ENODE_IS(expr, ETYPCON) && - IS_TYPE_INT(expr->rtype) && - IS_TYPE_INT(expr->data.monadic->rtype) && - expr->rtype->size >= expr->data.monadic->rtype->size - ) - expr = expr->data.monadic; - - if (isnotzero(expr)) { - if (flag1) { - stmt = CFunc_AppendStatement(ST_GOTO); - stmt->label = label1; - return; - } - return; - } - - if (iszero(expr)) { - if (!flag1) { - stmt = CFunc_AppendStatement(ST_GOTO); - stmt->label = label1; - return; - } - return; - } - - if (ENODE_IS(expr, ELOGNOT)) { - makeifstatement(expr->data.monadic, label1, label2, !flag1, flag2); - return; - } - - if (ENODE_IS(expr, ELOR)) { - tmplabel = newlabel(); - if (flag1) { - makeifstatement(expr->data.diadic.left, label1, tmplabel, 1, flag2); - tmplabel->stmt = CFunc_AppendStatement(ST_LABEL); - tmplabel->stmt->label = tmplabel; - makeifstatement(expr->data.diadic.right, label1, label2, 1, flag2); - return; - } else { - makeifstatement(expr->data.diadic.left, label2, tmplabel, 1, flag2); - tmplabel->stmt = CFunc_AppendStatement(ST_LABEL); - tmplabel->stmt->label = tmplabel; - makeifstatement(expr->data.diadic.right, label1, label2, 0, flag2); - return; - } - } - - if (ENODE_IS(expr, ELAND)) { - tmplabel = newlabel(); - if (flag1) { - makeifstatement(expr->data.diadic.left, label2, tmplabel, 0, flag2); - tmplabel->stmt = CFunc_AppendStatement(ST_LABEL); - tmplabel->stmt->label = tmplabel; - makeifstatement(expr->data.diadic.right, label1, label2, 1, flag2); - return; - } else { - makeifstatement(expr->data.diadic.left, label1, tmplabel, 0, flag2); - tmplabel->stmt = CFunc_AppendStatement(ST_LABEL); - tmplabel->stmt->label = tmplabel; - makeifstatement(expr->data.diadic.right, label1, label2, 0, flag2); - return; - } - } - - stmt = CFunc_AppendStatement(ST_IFGOTO); - stmt->label = label1; - stmt->expr = expr; - if (!flag1) - stmt->type = ST_IFNGOTO; - if (flag2) - stmt->flags = stmt->flags | StmtFlag_4; -} - -static void CFunc_HasDtorTempCallBack(ENode *expr) { - if (expr->data.temp.needs_dtor || expr->data.temp.uniqueid) - cfunc_hasdtortemp = 1; -} - -static void ifstatement(Boolean flag1, ENode *expr, CLabel *label, Boolean flag2) { - Statement *stmt; - CLabel *tmplabel; - - if (expr && copts.cplusplus && copts.exceptions) { - cfunc_hasdtortemp = 0; - CExpr_SearchExprTree(expr, CFunc_HasDtorTempCallBack, 1, ETEMP); - if (cfunc_hasdtortemp) { - stmt = CFunc_AppendStatement(flag1 ? ST_IFGOTO : ST_IFNGOTO); - stmt->label = label; - stmt->expr = expr; - if (flag2) - stmt->flags = stmt->flags | StmtFlag_4; - return; - } - } - - tmplabel = newlabel(); - makeifstatement(expr, label, tmplabel, flag1, flag2); - tmplabel->stmt = CFunc_AppendStatement(ST_LABEL); - tmplabel->stmt->label = tmplabel; -} - -Statement *CFunc_GenerateLoop(Statement *stmt, Type *type, ENode *lowerBound, ENode *upperBound, ENode *increment1, ENode *increment2, ENode *(*callback)(ENode *, ENode *)) { - ENode *var1; - ENode *var2; - CLabel *label; - ENode *ind; - ENode *ind2; - Statement *s; - - var1 = CExpr_NewETEMPNode(type, 1); - ind = lalloc(sizeof(ENode)); - *ind = *var1; - ind = makemonadicnode(ind, EINDIRECT); - ind->rtype = type; - - // initialise var1 to lowerBound - if (stmt) { - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - s = stmt; - } else { - s = CFunc_AppendStatement(ST_EXPRESSION); - } - s->expr = makediadicnode(ind, lowerBound, EASS); - - if (increment2) { - var2 = CExpr_NewETEMPNode(type, 1); - ind = lalloc(sizeof(ENode)); - *ind = *var2; - ind = makemonadicnode(ind, EINDIRECT); - ind->rtype = type; - - // initialise var2 to upperBound - if (stmt) { - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - s = stmt; - } else { - s = CFunc_AppendStatement(ST_EXPRESSION); - } - s->expr = makediadicnode(ind, upperBound, EASS); - } - - // label for loop body - label = newlabel(); - if (stmt) { - stmt = CFunc_InsertStatement(ST_LABEL, stmt); - s = stmt; - } else { - s = CFunc_AppendStatement(ST_LABEL); - } - s->label = label; - label->stmt = s; - - if (callback) { - ind = lalloc(sizeof(ENode)); - *ind = *var1; - ind = makemonadicnode(ind, EINDIRECT); - ind->rtype = type; - - if (increment2) { - ind2 = lalloc(sizeof(ENode)); - *ind2 = *var2; - ind2 = makemonadicnode(ind2, EINDIRECT); - ind2->rtype = type; - } else { - ind2 = NULL; - } - - // generate a loop body - if ((ind = callback(ind, ind2))) { - if (stmt) { - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - s = stmt; - } else { - s = CFunc_AppendStatement(ST_EXPRESSION); - } - s->expr = ind; - } - } - - if (increment1) { - ind = lalloc(sizeof(ENode)); - *ind = *var1; - ind = makemonadicnode(ind, EINDIRECT); - ind->rtype = type; - - // add increment1 to var1 - if (stmt) { - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - s = stmt; - } else { - s = CFunc_AppendStatement(ST_EXPRESSION); - } - s->expr = makediadicnode(ind, increment1, EADDASS); - - if (increment2) { - ind = lalloc(sizeof(ENode)); - *ind = *var2; - ind = makemonadicnode(ind, EINDIRECT); - ind->rtype = type; - - // add increment2 to var2 - if (stmt) { - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - s = stmt; - } else { - s = CFunc_AppendStatement(ST_EXPRESSION); - } - s->expr = makediadicnode(ind, increment2, EADDASS); - } - } - - ind = lalloc(sizeof(ENode)); - *ind = *var1; - ind = makemonadicnode(ind, EINDIRECT); - ind->rtype = type; - - // loop if var1 < upperBound - if (stmt) { - stmt = CFunc_InsertStatement(ST_IFGOTO, stmt); - s = stmt; - } else { - s = CFunc_AppendStatement(ST_IFGOTO); - } - s->expr = makediadicnode(ind, upperBound, ELESS); - s->expr->rtype = TYPE(&stbool); - s->label = label; - s->flags = StmtFlag_4; - - return stmt; -} - -static Boolean checklabel(void) { - HashNameNode *savename; - short savesize; - short token; - - savename = tkidentifier; - savesize = tksize; - token = lookahead(); - tkidentifier = savename; - tksize = savesize; - - return token == ':'; -} - -static ENode *returnstatementadjust(ENode *expr, Type *type, UInt32 qual) { - Object *object; - ENode *expr2; - ENode *objexpr; - ObjectList *list; - ENodeList *exprlist; - - for (list = arguments; list; list = list->next) { - if (list->object->name == temp_argument_name) - break; - } - - CError_ASSERT(1907, list); - - object = list->object; - if ((expr2 = CExpr_IsTempConstruction(expr, type, &objexpr)) && ENODE_IS(objexpr, ETEMP)) { - *objexpr = *create_objectnode(object); - return expr2; - } - - if (IS_TYPE_CLASS(type)) { - expr2 = create_objectnode(object); - exprlist = lalloc(sizeof(ENodeList)); - exprlist->next = NULL; - exprlist->node = expr; - return CExpr_ConstructObject(TYPE_CLASS(type), expr2, exprlist, 1, 1, 0, 1, 0); - } - - expr2 = create_objectnode(object); - expr2 = makemonadicnode(expr2, EINDIRECT); - expr2->rtype = type; - - return makediadicnode(expr2, CExpr_AssignmentPromotion(expr, type, qual, 1), EASS); -} - -static void CFunc_AutoResultCheck(ENode *expr) { - while (1) { - while (ENODE_IS(expr, ECOMMA)) - expr = expr->data.diadic.right; - - switch (expr->type) { - case EOBJREF: - if (expr->data.objref->datatype != DLOCAL) - break; - case ETEMP: - CError_Warning(CErrorStr326); - break; - case EADD: - case ESUB: - CFunc_AutoResultCheck(expr->data.diadic.left); - expr = expr->data.diadic.right; - continue; - default: - break; - } - break; - } -} - -static void statement(DeclThing *thing) { - Statement *stmt; - Statement *stmt2; - CLabel *label; - DeclBlock *block; - ENode *expr; - HashNameNode *name; - DeclThing subthing; - - CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); - - switch (tk) { - case TK_RETURN: - tk = lex(); - if ( - (thing->thetype == &stvoid && !copts.cplusplus) || - CClass_IsConstructor(cscope_currentfunc) || - CClass_IsDestructor(cscope_currentfunc) - ) - { - if (tk != ';') { - CError_Error(CErrorStr315); - expression(); - } - - stmt = CFunc_AppendStatement(ST_RETURN); - stmt->expr = NULL; - CError_ResetErrorSkip(); - tk = lex(); - return; - } - - if (tk == ';') { - if (thing->thetype != &stvoid && (copts.pedantic || copts.cplusplus)) - CError_Warning(CErrorStr184); - - stmt = CFunc_AppendStatement(ST_RETURN); - stmt->expr = NULL; - CError_ResetErrorSkip(); - tk = lex(); - return; - } - - if (copts.old_argmatch) - expr = expression(); - else - expr = s_expression(); - - if (thing->thetype == &stvoid) { - if (expr->rtype != &stvoid) - CError_Error(CErrorStr315); - - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = expr; - - stmt = CFunc_AppendStatement(ST_RETURN); - stmt->expr = NULL; - } else { - if (CMach_GetFunctionResultClass(TYPE_FUNC(cscope_currentfunc->type)) == 1) - expr = returnstatementadjust(expr, thing->thetype, thing->qual); - else - expr = CExpr_AssignmentPromotion(expr, thing->thetype, thing->qual, 1); - - stmt = CFunc_AppendStatement(ST_RETURN); - stmt->expr = expr; - - if (IS_TYPE_POINTER_ONLY(thing->thetype)) - CFunc_AutoResultCheck(expr); - } - - break; - - case TK_CASE: - scancase(thing); - return; - - case TK_DEFAULT: - if (!thing->switchinfo) { - CError_Error(CErrorStr169); - return; - } - - if (lex() != ':') - CError_ErrorSkip(CErrorStr170); - else - tk = lex(); - - if (thing->switchinfo->defaultlabel) - CError_ErrorSkip(CErrorStr173); - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = newlabel(); - stmt->label->stmt = stmt; - thing->switchinfo->defaultlabel = stmt->label; - statement(thing); - return; - - case TK_SWITCH: - if (lex() != '(') - CError_ErrorSkip(CErrorStr114); - else - tk = lex(); - - if (copts.cplusplus && !copts.ARMscoping && isdeclaration(1, 0, 0, '=')) { - block = CFunc_NewDeclBlock(); - expr = CFunc_ParseLocalDeclarationList(0, 1, 0, 0); - if (CScope_IsEmptyNameSpace(cscope_current)) { - CFunc_RestoreBlock(block); - block = NULL; - } - } else { - expr = expression(); - block = NULL; - } - - stmt = CFunc_AppendStatement(ST_SWITCH); - stmt->expr = CExpr_ConvertToIntegral(expr); - - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - - stmt->label = (CLabel *) lalloc(sizeof(SwitchInfo)); - ((SwitchInfo *) stmt->label)->defaultlabel = NULL; - ((SwitchInfo *) stmt->label)->cases = NULL; - ((SwitchInfo *) stmt->label)->x8 = stmt->expr->rtype; - - label = newlabel(); - subthing = *thing; - subthing.loopBreak = label; - subthing.switchinfo = (SwitchInfo *) stmt->label; - CFunc_CompoundStatement(&subthing); - - if (!subthing.switchinfo->defaultlabel) - subthing.switchinfo->defaultlabel = label; - - if (!subthing.switchinfo->cases) { - stmt->type = ST_EXPRESSION; - stmt2 = lalloc(sizeof(Statement)); - *stmt2 = *stmt; - stmt->next = stmt2; - stmt2->type = ST_GOTO; - stmt2->label = subthing.switchinfo->defaultlabel; - stmt2->dobjstack = cexcept_dobjstack; - } - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = label; - label->stmt = stmt; - - if (block) - CFunc_RestoreBlock(block); - return; - - case TK_GOTO: - if ((tk = lex()) != TK_IDENTIFIER) { - if (tk == '*' && !copts.ANSIstrict) { - tk = lex(); - stmt = CFunc_AppendStatement(ST_GOTOEXPR); - stmt->expr = expression(); - if (!IS_TYPE_POINTER_ONLY(stmt->expr->rtype)) { - CError_Error(CErrorStr146); - stmt->expr = nullnode(); - stmt->expr->rtype = TYPE(&void_ptr); - } - } else { - CError_Error(CErrorStr107); - return; - } - } else { - stmt = CFunc_AppendStatement(ST_GOTO); - if (!(stmt->label = findlabel())) { - stmt->label = newlabel(); - stmt->label->next = Labels; - Labels = stmt->label; - stmt->label->name = tkidentifier; - } - tk = lex(); - } - break; - - case TK_BREAK: - if (thing->loopBreak) { - stmt = CFunc_AppendStatement(ST_GOTO); - stmt->label = thing->loopBreak; - } else { - CError_Error(CErrorStr169); - } - tk = lex(); - break; - - case TK_CONTINUE: - if (thing->loopContinue) { - stmt = CFunc_AppendStatement(ST_GOTO); - stmt->label = thing->loopContinue; - } else { - CError_Error(CErrorStr169); - } - tk = lex(); - break; - - case TK_FOR: { - CLabel *forLabel1; - CLabel *forLabel2; - CLabel *forLabel3; - ENode *forCond; - ENode *forInc; - - if (lex() != '(') - CError_ErrorSkip(CErrorStr114); - else - tk = lex(); - - block = NULL; - if (tk != ';') { - if (!copts.cplusplus || !isdeclaration(1, 0, 0, 0)) { - expr = expression(); - CExpr_CheckUnusedExpression(expr); - } else { - if (!copts.ARMscoping) - block = CFunc_NewDeclBlock(); - expr = CFunc_ParseLocalDeclarationList(0, 1, 1, 0); - if (block && CScope_IsEmptyNameSpace(cscope_current)) { - CFunc_RestoreBlock(block); - block = NULL; - } - } - - if (expr) { - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = expr; - } - - if (tk == ';') - CError_ResetErrorSkip(); - else - CError_Error(CErrorStr123); - } else { - CError_ResetErrorSkip(); - } - - if ((tk = lex()) != ';') { - if (copts.cplusplus && !copts.ARMscoping && isdeclaration(1, 0, 0, '=')) { - if (!block) - block = CFunc_NewDeclBlock(); - expr = CFunc_ParseLocalDeclarationList(0, 1, 0, 0); - if (CScope_IsEmptyNameSpace(cscope_current)) { - CFunc_RestoreBlock(block); - block = NULL; - } - } else { - expr = expression(); - CExpr_CheckUnwantedAssignment(expr); - } - - forCond = CExpr_ConvertToCondition(expr); - - if (tk == ';') - CError_ResetErrorSkip(); - else - CError_Error(CErrorStr123); - } else { - CError_ResetErrorSkip(); - forCond = NULL; - } - - if ((tk = lex()) != ')') { - forInc = expression(); - CExpr_CheckUnusedExpression(forInc); - if (tk == ')') - CError_ResetErrorSkip(); - else - CError_Error(CErrorStr115); - } else { - CError_ResetErrorSkip(); - forInc = NULL; - } - - if (copts.warn_possunwant) { - spaceskip = 0; - if ((tk = lex()) == ';' && !spaceskip) - CError_Warning(CErrorStr206); - } else { - tk = lex(); - } - - if (forCond) { - stmt = CFunc_AppendStatement(ST_GOTO); - label = newlabel(); - stmt->label = label; - } else { - label = newlabel(); - } - - CFunc_LoopIncrement(); - - stmt = CFunc_AppendStatement(ST_LABEL); - forLabel1 = stmt->label = newlabel(); - forLabel1->stmt = stmt; - - forLabel2 = newlabel(); - forLabel3 = newlabel(); - - subthing = *thing; - subthing.loopContinue = forLabel3; - subthing.loopBreak = forLabel2; - - if (tk != '{') { - DeclBlock *b = CFunc_NewDeclBlock(); - CFunc_CompoundStatement(&subthing); - CFunc_RestoreBlock(b); - } else { - CFunc_CompoundStatement(&subthing); - } - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = forLabel3; - forLabel3->stmt = stmt; - - if (forInc) { - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = forInc; - } - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = label; - label->stmt = stmt; - - ifstatement(1, forCond, forLabel1, 1); - CFunc_LoopDecrement(); - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = forLabel2; - forLabel2->stmt = stmt; - - if (block) - CFunc_RestoreBlock(block); - - return; - } - - case TK_DO: { - CLabel *label1; - CLabel *label2; - CLabel *label3; - - CFunc_LoopIncrement(); - stmt = CFunc_AppendStatement(ST_LABEL); - label1 = stmt->label = newlabel(); - label1->stmt = stmt; - - label2 = newlabel(); - label3 = newlabel(); - - subthing = *thing; - subthing.loopContinue = label2; - subthing.loopBreak = label3; - - tk = lex(); - CFunc_CompoundStatement(&subthing); - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = label2; - label2->stmt = stmt; - - if (tk != TK_WHILE) - CError_Error(CErrorStr105); - - if (lex() != '(') - CError_ErrorSkip(CErrorStr114); - else - tk = lex(); - - expr = CExpr_ConvertToCondition(expression()); - CExpr_CheckUnwantedAssignment(expr); - - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - - ifstatement(1, expr, label1, 1); - - CFunc_LoopDecrement(); - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = label3; - label3->stmt = stmt; - break; - } - - case TK_WHILE: { - CLabel *label1; - CLabel *label2; - CLabel *label3; - - if ((tk = lex()) != '(') - CError_ErrorSkip(CErrorStr114); - else - tk = lex(); - - if (copts.cplusplus && !copts.ARMscoping && isdeclaration(1, 0, 0, '=')) { - block = CFunc_NewDeclBlock(); - expr = CFunc_ParseLocalDeclarationList(0, 1, 0, 0); - if (CScope_IsEmptyNameSpace(cscope_current)) { - CFunc_RestoreBlock(block); - block = NULL; - } - } else { - expr = expression(); - block = NULL; - CExpr_CheckUnwantedAssignment(expr); - } - expr = CExpr_ConvertToCondition(expr); - - if (tk != ')') { - CError_ErrorSkip(CErrorStr115); - } else { - if (copts.warn_possunwant) { - spaceskip = 0; - if ((tk = lex()) == ';' && !spaceskip) - CError_Warning(CErrorStr206); - } else { - tk = lex(); - } - } - - stmt = CFunc_AppendStatement(ST_GOTO); - label1 = newlabel(); - stmt->label = label1; - - CFunc_LoopIncrement(); - - stmt = CFunc_AppendStatement(ST_LABEL); - label2 = stmt->label = newlabel(); - label2->stmt = stmt; - - label3 = newlabel(); - - subthing = *thing; - subthing.loopContinue = label1; - subthing.loopBreak = label3; - - CFunc_CompoundStatement(&subthing); - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = label1; - label1->stmt = stmt; - - ifstatement(1, expr, label2, 1); - - CFunc_LoopDecrement(); - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = label3; - label3->stmt = stmt; - - if (block) - CFunc_RestoreBlock(block); - return; - } - - case TK_IF: { - CLabel *label1; - if ((tk = lex()) != '(') - CError_ErrorSkip(CErrorStr114); - else - tk = lex(); - - if (copts.cplusplus && !copts.ARMscoping && isdeclaration(1, 0, 0, '=')) { - block = CFunc_NewDeclBlock(); - expr = CFunc_ParseLocalDeclarationList(0, 1, 0, 0); - if (CScope_IsEmptyNameSpace(cscope_current)) { - CFunc_RestoreBlock(block); - block = NULL; - } - } else { - expr = expression(); - block = NULL; - CExpr_CheckUnwantedAssignment(expr); - } - - expr = CExpr_ConvertToCondition(expr); - - label1 = newlabel(); - ifstatement(0, expr, label1, 0); - - if (tk != ')') { - CError_ErrorSkip(CErrorStr115); - } else { - if (copts.warn_possunwant) { - spaceskip = 0; - if ((tk = lex()) == ';' && !spaceskip) - CError_Warning(CErrorStr206); - } else { - tk = lex(); - } - } - - CFunc_CompoundStatement(thing); - - if (tk == TK_ELSE) { - if (copts.warn_possunwant) { - spaceskip = 0; - if ((tk = lex()) == ';' && !spaceskip) - CError_Warning(CErrorStr206); - } else { - tk = lex(); - } - - stmt = CFunc_AppendStatement(ST_GOTO); - label = stmt->label = newlabel(); - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = label1; - label1->stmt = stmt; - - CFunc_CompoundStatement(thing); - - label1 = label; - } - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = label1; - label1->stmt = stmt; - - if (block) - CFunc_RestoreBlock(block); - - return; - } - - case '{': - CFunc_CompoundStatement(thing); - return; - - case TK_ASM: - if (copts.cplusplus || !copts.ANSIstrict) { - tk = lex(); - volatileasm = 0; - - if (tk == TK_VOLATILE || (tk == TK_IDENTIFIER && !strcmp(tkidentifier->name, "__volatile__"))) { - tk = lex(); - volatileasm = 1; - } - - if (tk == '(') { - InlineAsm_Assemble(); - if (tk == ')') { - tk = lex(); - break; - } else { - CError_Error(CErrorStr115); - return; - } - } - - if (tk == '{') { - InlineAsm_Assemble(); - if (tk != '}') { - CError_Error(CErrorStr130); - return; - } - if ((tk = lex()) == ';') - tk = lex(); - CError_ResetErrorSkip(); - return; - } - - CError_Error(CErrorStr114); - } else { - CError_Error(CErrorStr121); - } - return; - - case TK_TRY: - tk = lex(); - CExcept_ScanTryBlock(thing, 0); - return; - - case TK_USING: - if ((tk = lex()) == TK_NAMESPACE) { - tk = lex(); - CScope_ParseUsingDirective(cscope_current); - } else { - CScope_ParseUsingDeclaration(cscope_current, 0, 0); - } - return; - - case TK_NAMESPACE: - if ((tk = lex()) != TK_IDENTIFIER) { - CError_Error(CErrorStr107); - return; - } - name = tkidentifier; - if ((tk = lex()) != '=') { - CError_Error(CErrorStr121); - return; - } - - CScope_ParseNameSpaceAlias(name); - break; - - case ';': - break; - - case TK_IDENTIFIER: - if (checklabel()) { - stmt = CFunc_AppendStatement(ST_LABEL); - if ((stmt->label = findlabel())) { - if (stmt->label->stmt) - CError_Error(CErrorStr171, tkidentifier->name); - } else { - stmt->label = newlabel(); - stmt->label->next = Labels; - Labels = stmt->label; - stmt->label->name = tkidentifier; - } - - stmt->label->stmt = stmt; - tk = lex(); - tk = lex(); - statement(thing); - return; - } - tk = TK_IDENTIFIER; - - default: - if (copts.cplusplus && isdeclaration(1, 0, 0, 0)) { - CFunc_ParseLocalDeclarationList(0, 0, 0, 1); - tk = lex(); - return; - } - - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = expression(); - CExpr_CheckUnusedExpression(stmt->expr); - } - - if (tk == ';') { - CPrep_TokenStreamFlush(); - tk = lex(); - CError_ResetErrorSkip(); - } else { - CError_ErrorSkip(CErrorStr123); - } -} - -void CFunc_CompoundStatement(DeclThing *thing) { - DeclBlock *block; - - block = CFunc_NewDeclBlock(); - - if (tk == '{') { - tk = lex(); - if (!copts.cplusplus && isdeclaration(0, 0, 0, 0)) - CFunc_ParseLocalDeclarationList(0, 0, 0, 0); - - while (tk != '}') - statement(thing); - - CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); - tk = lex(); - } else { - statement(thing); - } - - CFunc_RestoreBlock(block); -} - -static void CFunc_InsertArgumentCopyConversion(Object *obj, Type *type1, Type *type2, Boolean flag) { - Object *newobj; - Statement *stmt; - ENode *expr; - NameSpaceObjectList *nsol; - ObjectList *list; - - newobj = lalloc(sizeof(Object)); - *newobj = *obj; - newobj->type = type2; - - CFunc_SetupLocalVarInfo(newobj); - - obj->name = CParser_GetUniqueName(); - if (flag) - obj->type = CDecl_NewPointerType(type1); - else - obj->type = type1; - - CError_ASSERT(2527, (nsol = CScope_FindName(cscope_current, newobj->name)) && nsol->object == OBJ_BASE(obj)); - nsol->object = OBJ_BASE(newobj); - - list = lalloc(sizeof(ObjectList)); - list->object = newobj; - list->next = locals; - locals = list; - - stmt = CFunc_AppendStatement(ST_EXPRESSION); - expr = create_objectnode(obj); - if (flag) { - expr->rtype = CDecl_NewPointerType(type1); - expr = makemonadicnode(expr, EINDIRECT); - } - expr->rtype = type1; - - if (type1 != type2) - expr = promote(expr, type2); - - stmt->expr = makediadicnode(create_objectnode(newobj), expr, EASS); -} - -static void CFunc_AdjustOldStyleArgs(void) { - ObjectList *list; - - for (list = arguments; list; list = list->next) { - if (IS_TYPE_FLOAT(list->object->type) && list->object->type->size < stdouble.size) - CFunc_InsertArgumentCopyConversion(list->object, TYPE(&stdouble), list->object->type, 0); - } -} - -void CFunc_SetupNewFuncArgs(Object *func, FuncArg *args) { - Object *obj; - ObjectList *newlist; - - arguments = NULL; - - if (args != &elipsis && args != &oldstyle) { - newlist = NULL; - - while (args && args != &elipsis) { - IsCompleteType(args->type); - - obj = CParser_NewLocalDataObject(NULL, 0); - obj->name = !args->name ? no_name_node : args->name; - obj->type = args->type; - obj->qual = args->qual; - obj->sclass = args->sclass; - - CFunc_SetupLocalVarInfo(obj); - - if (IS_TYPE_CLASS(obj->type) && CClass_ReferenceArgument(TYPE_CLASS(obj->type))) { - obj->type = CDecl_NewPointerType(obj->type); - TPTR_QUAL(obj->type) = Q_REFERENCE | Q_RESTRICT; - } - - if (obj->name == no_name_node && copts.ANSIstrict && !copts.cplusplus && !(func->qual & Q_MANGLE_NAME)) - CError_Error(CErrorStr127); - - if (newlist) { - newlist->next = lalloc(sizeof(ObjectList)); - newlist = newlist->next; - } else { - newlist = lalloc(sizeof(ObjectList)); - arguments = newlist; - } - - newlist->next = NULL; - newlist->object = obj; - - args = args->next; - } - } -} - -static ObjectList *CFunc_CopyObjectList(const FuncArg *args) { - Object *obj; - ObjectList *list; - ObjectList *last; - - list = NULL; - - while (args) { - if (list) { - last->next = lalloc(sizeof(ObjectList)); - last = last->next; - } else { - last = lalloc(sizeof(ObjectList)); - list = last; - } - - obj = CParser_NewLocalDataObject(NULL, 0); - obj->name = args->name; - obj->type = args->type; - obj->qual = args->qual; - obj->sclass = args->sclass; - CFunc_SetupLocalVarInfo(obj); - - last->object = obj; - last->next = NULL; - - args = args->next; - } - - return list; -} - -static void SetupFunctionArguments(Object *func, DeclInfo *di, Statement *firstStmt) { - ObjectList *list; - Object *resultobj; - Object *obj; - Type *type; - DeclInfo my_di; - - if (TYPE_FUNC(func->type)->args) { - if (di->x45) { - arguments = CFunc_CopyObjectList(di->x18); - while (1) { - if (tk == '{') - break; - - memclrw(&my_di, sizeof(my_di)); - CParser_GetDeclSpecs(&my_di, 0); - - type = my_di.thetype; - if (my_di.storageclass && my_di.storageclass != TK_REGISTER) - CError_Error(CErrorStr127); - - while (1) { - my_di.thetype = type; - my_di.name = NULL; - scandeclarator(&my_di); - if (!my_di.name) { - CError_Error(CErrorStr107); - break; - } - - adjustargumenttype(&my_di); - IsCompleteType(my_di.thetype); - - if ((obj = CFunc_IsInObjList(arguments, my_di.name))) { - if (obj->type) - CError_Error(CErrorStr333, obj); - obj->type = my_di.thetype; - obj->sclass = my_di.storageclass; - obj->qual = my_di.qual; - } else { - CError_Error(CErrorStr127); - } - - if (tk != ',') - break; - tk = lex(); - } - - if (tk != ';') - CError_ErrorSkip(CErrorStr123); - else - tk = lex(); - } - - for (list = arguments; list; list = list->next) { - if (!list->object->type) - list->object->type = TYPE(&stsignedint); - } - } else { - CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); - } - } - - if (CMach_GetFunctionResultClass(TYPE_FUNC(func->type)) == 1) { - resultobj = CParser_NewLocalDataObject(NULL, 0); - resultobj->name = temp_argument_name; - resultobj->type = CDecl_NewPointerType(TYPE_FUNC(func->type)->functype); - CFunc_SetupLocalVarInfo(resultobj); - - list = lalloc(sizeof(ObjectList)); - list->object = resultobj; - if (CABI_GetStructResultArgumentIndex(TYPE_FUNC(func->type))) { - CError_ASSERT(2797, arguments); - list->next = arguments->next; - arguments->next = list; - } else { - list->next = arguments; - arguments = list; - } - } - - for (list = arguments; list; list = list->next) { - NameSpaceObjectList *nsol = CScope_InsertName(cscope_current, list->object->name); - nsol->object = OBJ_BASE(list->object); - } -} - -NameSpace *CFunc_FuncGenSetup(Statement *stmt, Object *func) { - NameSpace *nspace; - DeclBlock *block; - - nspace = CScope_NewListNameSpace(NULL, 0); - nspace->parent = cscope_current; - cscope_current = nspace; - - arguments = NULL; - locals = NULL; - Labels = NULL; - - localcount = 0; - cfunc_staticvarcount = 0; - - CExcept_Setup(); - - memclrw(stmt, sizeof(Statement)); - curstmt = stmt; - stmt->type = ST_NOP; - curstmtvalue = 1; - stmt->value = 1; - - blockcount = 0; - block = lalloc(sizeof(DeclBlock)); - memclrw(block, sizeof(DeclBlock)); - block->index = blockcount++; - block->parent_nspace = cscope_current; - - firstblock = block; - currentblock = block; - - return nspace; -} - -CFuncSave *CFunc_GetGlobalCompilerState(void) { - CFuncSave *state; - - if (!cscope_currentfunc && !cscope_currentclass && cscope_current == cscope_root) - return NULL; - - locklheap(); - state = lalloc(sizeof(CFuncSave)); - - CScope_SetNameSpaceScope(cscope_root, &state->scope); - - state->arguments = arguments; - arguments = NULL; - - state->locals = locals; - locals = NULL; - - state->labels = Labels; - Labels = NULL; - - state->curstmt = curstmt; - curstmt = NULL; - - state->firstblock = firstblock; - firstblock = NULL; - - state->currentblock = currentblock; - currentblock = NULL; - - state->cexcept_dobjstack = cexcept_dobjstack; - cexcept_dobjstack = NULL; - - state->sinit_label = sinit_label; - sinit_label = NULL; - - state->ainit_expr = ainit_expr; - ainit_expr = NULL; - - state->ctor_chain = ctor_chain; - ctor_chain = NULL; - - state->cinit_tempnodefunc = cinit_tempnodefunc; - cinit_tempnodefunc = NULL; - - state->trychain = trychain; - trychain = NULL; - - state->cparser_fileoffset = cparser_fileoffset; - state->symdecltoken = symdecltoken; - - state->functionbodyoffset = functionbodyoffset; - functionbodyoffset = 0; - - state->functionbodypath = functionbodypath; - functionbodypath = NULL; - - state->symdecloffset = symdecloffset; - symdecloffset = 0; - - state->symdeclend = symdeclend; - - state->sourceoffset = sourceoffset; - sourceoffset = 0; - - state->sourcefilepath = sourcefilepath; - sourcefilepath = NULL; - - state->curstmtvalue = curstmtvalue; - curstmtvalue = 0; - - state->name_obj_check = name_obj_check; - name_obj_check = NULL; - - state->check_arglist = check_arglist; - check_arglist = NULL; - - state->blockcount = blockcount; - blockcount = 0; - - state->localcount = localcount; - localcount = 0; - - state->tk = tk; - state->tkidentifier = tkidentifier; - - state->global_access = global_access; - - state->cexcept_hasdobjects = cexcept_hasdobjects; - cexcept_hasdobjects = 0; - - state->sinit_first_object = sinit_first_object; - sinit_first_object = NULL; - - state->ainit_only_one = ainit_only_one; - ainit_only_one = 0; - - state->cfunc_is_extern_c = cfunc_is_extern_c; - cfunc_is_extern_c = 0; - - state->temp_reference_init = temp_reference_init; - - return state; -} - -void CFunc_SetGlobalCompilerState(CFuncSave *state) { - if (state) { - CScope_RestoreScope(&state->scope); - - arguments = state->arguments; - locals = state->locals; - Labels = state->labels; - curstmt = state->curstmt; - firstblock = state->firstblock; - currentblock = state->currentblock; - cexcept_dobjstack = state->cexcept_dobjstack; - sinit_label = state->sinit_label; - ainit_expr = state->ainit_expr; - ctor_chain = state->ctor_chain; - cinit_tempnodefunc = state->cinit_tempnodefunc; - trychain = state->trychain; - name_obj_check = state->name_obj_check; - check_arglist = state->check_arglist; - curstmtvalue = state->curstmtvalue; - cparser_fileoffset = state->cparser_fileoffset; - symdecltoken = state->symdecltoken; - functionbodyoffset = state->functionbodyoffset; - functionbodypath = state->functionbodypath; - symdecloffset = state->symdecloffset; - symdeclend = state->symdeclend; - sourceoffset = state->sourceoffset; - sourcefilepath = state->sourcefilepath; - blockcount = state->blockcount; - tk = state->tk; - tkidentifier = state->tkidentifier; - global_access = state->global_access; - localcount = state->localcount; - cexcept_hasdobjects = state->cexcept_hasdobjects; - sinit_first_object = state->sinit_first_object; - ainit_only_one = state->ainit_only_one; - cfunc_is_extern_c = state->cfunc_is_extern_c; - temp_reference_init = state->temp_reference_init; - - unlocklheap(); - } -} - -void CFunc_Gen(Statement *stmt, Object *func, UInt8 unk) { - Boolean flag; - CI_FuncData packed; - - if ((TYPE_FUNC(func->type)->flags & FUNC_FLAGS_400000) && !anyerrors) { - CInline_PackIFunctionData(&packed, stmt, func); - flag = 1; - } else { - flag = 0; - } - - CInline_GenFunc(stmt, func, unk); - - if (flag) - CClass_DefineCovariantFuncs(func, &packed); -} - -static void CFunc_CheckCtorInitializer(TypeClass *tclass, CtorChain *chain) { - ObjMemberVar *ivar; - CtorChain *scan; - - if (tclass->mode != CLASS_MODE_UNION) { - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - if (IS_TYPE_REFERENCE(ivar->type)) { - for (scan = chain; scan; scan = scan->next) { - if (scan->what == CtorChain_MemberVar && scan->u.membervar == ivar) - break; - } - - if (!scan) - CError_Error(CErrorStr256, ivar->name->name); - } else if (CParser_IsConst(ivar->type, ivar->qual)) { - for (scan = chain; scan; scan = scan->next) { - if (scan->what == CtorChain_MemberVar && scan->u.membervar == ivar) - break; - } - - if (!scan && !IS_TYPE_CLASS(ivar->type)) - CError_Error(CErrorStr255, ivar->name->name); - } - } - } -} - -void CFunc_CheckClassCtors(TypeClass *tclass) { - CFunc_CheckCtorInitializer(tclass, NULL); -} - -static void CFunc_ParseCtorInitializer(void) { - CtorChain *chain; - ENodeList *args; - TypeClass *tclass; - ObjMemberVar *ivar; - ClassList *base; - VClassList *vbase; - ENode *expr; - Type *origtype; - - ctor_chain = NULL; - - if (tk == ':') { - do { - tclass = NULL; - switch ((tk = lex())) { - case TK_IDENTIFIER: - for (ivar = cscope_currentclass->ivars; ivar; ivar = ivar->next) { - if (ivar->name == tkidentifier && lookahead() == '(') - goto do_ivar; - } - for (base = cscope_currentclass->bases; base; base = base->next) { - if (base->base->classname == tkidentifier) { - if (lookahead() == '(') { - tclass = base->base; - tk = lex(); - } else { - tkidentifier = base->base->classname; - } - break; - } - } - break; - - case TK_COLON_COLON: - break; - - default: - CError_Error(CErrorStr212); - return; - } - - if (!tclass) - tclass = CClass_GetQualifiedClass(); - - if (tclass) { - for (vbase = cscope_currentclass->vbases; vbase; vbase = vbase->next) { - if (vbase->base == tclass) - break; - } - - if (vbase) { - for (chain = ctor_chain; chain; chain = chain->next) { - if (chain->what == CtorChain_VBase && chain->u.vbase == vbase) { - CError_Error(CErrorStr212); - return; - } - } - - chain = lalloc(sizeof(CtorChain)); - chain->what = CtorChain_VBase; - chain->u.vbase = vbase; - } else { - for (base = cscope_currentclass->bases; base; base = base->next) { - if (base->base == tclass) - break; - } - - if (base) { - for (chain = ctor_chain; chain; chain = chain->next) { - if (chain->what == CtorChain_Base && chain->u.base == base) { - CError_Error(CErrorStr212); - return; - } - } - - chain = lalloc(sizeof(CtorChain)); - chain->what = CtorChain_Base; - chain->u.base = base; - } else { - CError_Error(CErrorStr212); - return; - } - } - } else { - for (ivar = cscope_currentclass->ivars; ivar; ivar = ivar->next) { - if (ivar->name == tkidentifier) - break; - } - - if (ivar) { - do_ivar: - for (chain = ctor_chain; chain; chain = chain->next) { - if (chain->what == CtorChain_MemberVar && chain->u.membervar == ivar) - CError_Error(CErrorStr212); - } - - chain = lalloc(sizeof(CtorChain)); - chain->what = CtorChain_MemberVar; - chain->u.membervar = ivar; - } else { - CError_Error(CErrorStr212); - return; - } - - tk = lex(); - } - - if (tk != '(') { - CError_Error(CErrorStr114); - return; - } - - tk = lex(); - args = CExpr_ScanExpressionList(1); - - if (tk != ')') { - CError_Error(CErrorStr115); - return; - } - - switch (chain->what) { - case CtorChain_Base: - expr = CABI_MakeThisExpr(NULL, chain->u.base->offset); - chain->objexpr = CExpr_ConstructObject(chain->u.base->base, expr, args, 1, 0, 0, 0, 1); - break; - case CtorChain_VBase: - expr = CABI_MakeThisExpr(chain->u.vbase->base, chain->u.vbase->offset); - chain->objexpr = CExpr_ConstructObject(chain->u.vbase->base, expr, args, 1, 0, 0, 0, 1); - break; - case CtorChain_MemberVar: - expr = CABI_MakeThisExpr(cscope_currentclass, chain->u.membervar->offset); - expr->flags = chain->u.membervar->qual & ENODE_FLAG_QUALS; - switch (chain->u.membervar->type->type) { - case TYPECLASS: - chain->objexpr = CExpr_ConstructObject(TYPE_CLASS(chain->u.membervar->type), expr, args, 1, 1, 0, 1, 1); - break; - case TYPEARRAY: - if (args) { - CError_Error(CErrorStr212); - continue; - } - chain->objexpr = NULL; - break; - default: - if (!args) { - args = lalloc(sizeof(ENodeList)); - args->next = NULL; - args->node = CExpr_DoExplicitConversion(chain->u.membervar->type, chain->u.membervar->qual, NULL); - } - if (args->next) { - CError_Error(CErrorStr212); - return; - } - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = chain->u.membervar->type; - if (IS_TYPE_BITFIELD(origtype = expr->rtype)) { - expr->data.monadic = makemonadicnode(expr->data.monadic, EBITFIELD); - expr->data.monadic->rtype = origtype; - expr->rtype = TYPE_BITFIELD(origtype)->bitfieldtype; - } - - chain->objexpr = makediadicnode(expr, CExpr_AssignmentPromotion(args->node, expr->rtype, expr->flags, 1), EASS); - } - break; - default: - CError_FATAL(3286); - } - - chain->next = ctor_chain; - ctor_chain = chain; - } while ((tk = lex()) == ','); - } -} - -static void CFunc_FunctionRedefinedCheck(Object *func) { - if (TYPE_FUNC(func->type)->flags & FUNC_AUTO_GENERATED) - CError_Error(CErrorStr333, func); - - if ((TYPE_FUNC(func->type)->flags & FUNC_DEFINED) && func->datatype != DINLINEFUNC) - CError_Error(CErrorStr333, func); - - TYPE_FUNC(func->type)->flags |= FUNC_DEFINED; -} - -static Object *CFunc_DeclareFuncName(char *str, HashNameNode *name) { - Object *obj; - Object *aliasobj; - DeclInfo di; - - memclrw(&di, sizeof(di)); - di.name = name; - di.storageclass = TK_STATIC; - di.qual = Q_CONST; - di.thetype = CDecl_NewArrayType(TYPE(&stchar), strlen(str) + 1); - - obj = CParser_NewGlobalDataObject(&di); - aliasobj = CParser_NewAliasObject(obj, 0); - obj->nspace = cscope_root; - obj->datatype = DDATA; - CFunc_NameLocalStaticDataObject(obj, obj->name->name); - - return aliasobj; -} - -void CFunc_ParseFuncDef(Object *func, DeclInfo *di, TypeClass *tclass, Boolean is_method, Boolean is_static, NameSpace *nspace) { - Boolean has_try; - Object *nameobj_func; - Object *nameobj_FUNCTION; - Object *nameobj_pretty; - char *prettyname; - Statement *stmt18; - Statement *stmt16; - Statement firstStmt; - DeclThing thing; - CScopeSave scope; - - nameobj_func = NULL; - nameobj_FUNCTION = NULL; - nameobj_pretty = NULL; - prettyname = NULL; - - CError_ASSERT(3373, IS_TYPE_FUNC(func->type)); - - CFunc_FunctionRedefinedCheck(func); - CParser_UpdateObject(func, di); - - if (!is_method) { - CScope_SetFunctionScope(func, &scope); - if (tclass) - cscope_current = tclass->nspace; - } else { - CScope_SetMethodScope(func, tclass, is_static, &scope); - } - - if (nspace) - cscope_current = nspace; - - if (cscope_currentclass) - CClass_MemberDef(func, cscope_currentclass); - - cfunc_is_extern_c = di->is_extern_c; - - CError_ASSERT(3392, IS_TYPE_FUNC(func->type)); - if (di->x45 && (func->qual & Q_ASM)) - CError_Error(CErrorStr176); - - if (cparamblkptr->precompile == 1 && !(func->qual & Q_INLINE)) - CError_ErrorTerm(CErrorStr180); - - if (di->x49) - CError_Error(CErrorStr127); - - CFunc_FuncGenSetup(&firstStmt, func); - if (!IS_TYPE_VOID(TYPE_FUNC(func->type)->functype)) - IsCompleteType(TYPE_FUNC(func->type)->functype); - - SetupFunctionArguments(func, di, &firstStmt); - - stmt18 = curstmt; - CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); - functionbodyoffset = sourceoffset; - firstStmt.sourceoffset = sourceoffset; - functionbodypath = sourcefilepath; - firstStmt.sourcefilepath = sourcefilepath; - - if (di->x45) - CFunc_AdjustOldStyleArgs(); - - if (di->x1C) - CScope_MergeNameSpace(cscope_current, di->x1C); - - if (tk == TK_TRY) { - tk = lex(); - has_try = 1; - } else { - has_try = 0; - } - - if (CClass_IsConstructor(func)) { - CError_ASSERT(3445, cscope_currentclass); - CFunc_ParseCtorInitializer(); - CFunc_CheckCtorInitializer(cscope_currentclass, ctor_chain); - } - - CPrep_TokenStreamFlush(); - - if (!(func->qual & Q_ASM)) { - if (tk == '{') { - if (!has_try) - tk = lex(); - } else { - CError_ErrorSkip(CErrorStr135); - has_try = 0; - } - - if (func->name) { - nameobj_func = CFunc_DeclareFuncName(func->name->name, GetHashNameNode("__func__")); - nameobj_FUNCTION = CFunc_DeclareFuncName(func->name->name, GetHashNameNode("__FUNCTION__")); - prettyname = CError_GetObjectName(func); - nameobj_pretty = CFunc_DeclareFuncName(prettyname, GetHashNameNode("__PRETTY_FUNCTION__")); - } - - if (!copts.cplusplus) - CFunc_ParseLocalDeclarationList(0, 0, 0, 0); - - thing.switchinfo = NULL; - thing.loopContinue = NULL; - thing.loopBreak = NULL; - thing.thetype = TYPE_FUNC(func->type)->functype; - thing.qual = TYPE_FUNC(func->type)->qual; - - if (has_try) { - CExcept_ScanTryBlock(&thing, CClass_IsConstructor(func) || CClass_IsDestructor(func)); - if (tk != 0) - CPrep_UnLex(); - tk = '}'; - } else { - while (tk != '}') - statement(&thing); - } - - stmt16 = curstmt; - - if (stmt16->type != ST_RETURN && stmt16->type != ST_GOTO) { - CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); - CFunc_AppendStatement(ST_RETURN); - - curstmt->dobjstack = NULL; - curstmt->expr = NULL; - - if ( - (copts.cplusplus || copts.c9x) && - !strcmp(func->name->name, "main") && - TYPE_FUNC(func->type)->functype == TYPE(&stsignedint) - ) - curstmt->expr = intconstnode(TYPE(&stsignedint), 0); - - if ( - stmt16->type == ST_EXPRESSION && - stmt16->expr->type == EFUNCCALL && - stmt16->expr->rtype == &stvoid && - (stmt16->expr->flags & ENODE_FLAG_VOLATILE) - ) - curstmt->flags = curstmt->flags | StmtFlag_8; - } - - CheckCLabels(); - - if (nameobj_func && (nameobj_func->flags & OBJECT_USED)) - CInit_DeclareData(nameobj_func->u.alias.object, func->name->name, NULL, strlen(func->name->name) + 1); - if (nameobj_FUNCTION && (nameobj_FUNCTION->flags & OBJECT_USED)) - CInit_DeclareData(nameobj_FUNCTION->u.alias.object, func->name->name, NULL, strlen(func->name->name) + 1); - if (nameobj_pretty && (nameobj_pretty->flags & OBJECT_USED)) - CInit_DeclareData(nameobj_pretty->u.alias.object, prettyname, NULL, strlen(prettyname) + 1); - - if (!fatalerrors) { - if (CClass_IsConstructor(func)) - CABI_TransConstructor(func, stmt18, cscope_currentclass, NULL, has_try); - if (CClass_IsDestructor(func)) - CABI_TransDestructor(func, func, &firstStmt, cscope_currentclass, 0); - - CFunc_DestructorCleanup(&firstStmt); - CFunc_CodeCleanup(&firstStmt); - symdeclend = CPrep_GetFileOffsetInfo(&cparser_fileoffset); - CFunc_Gen(&firstStmt, func, di->x45); - } - } else { - if (tk == '{') { - in_assembler = 1; - tk = lex(); - in_assembler = 0; - } else { - CError_ErrorSkip(CErrorStr135); - } - - CFunc_ParseLocalDeclarationList(1, 0, 0, 0); - Assembler(func); - } - - if (tk != '}') - CError_Error(CErrorStr130); - - CScope_RestoreScope(&scope); -} - -void InitExpr_Register(ENode *expr, Object *object) { - InitExpr *initexpr; - InitExpr *scan; - - if ( - cparamblkptr->precompile == 1 && - object->sclass != TK_STATIC && - !(object->qual & (Q_20000 | Q_WEAK)) - ) - { - CError_Error(CErrorStr180); - return; - } - - if (copts.suppress_init_code) - return; - - initexpr = galloc(sizeof(InitExpr)); - initexpr->next = NULL; - initexpr->object = object; - initexpr->expr = CInline_CopyExpression(expr, CopyMode1); - - if (init_expressions) { - scan = init_expressions; - while (scan->next) - scan = scan->next; - scan->next = initexpr; - } else { - init_expressions = initexpr; - } -} - -void CFunc_GenerateDummyFunction(Object *func) { - NameSpace *nspace; - Boolean saveDebugInfo; - Statement firstStmt; - - if (!anyerrors) { - nspace = CFunc_FuncGenSetup(&firstStmt, NULL); - - saveDebugInfo = copts.filesyminfo; - copts.filesyminfo = 0; - - CFunc_CodeCleanup(&firstStmt); - CFunc_Gen(&firstStmt, func, 0); - - cscope_current = nspace->parent; - copts.filesyminfo = saveDebugInfo; - } -} - -void CFunc_GenerateSingleExprFunc(Object *func, ENode *expr) { - NameSpace *nspace; - Boolean saveDebugInfo; - Statement firstStmt; - Statement *stmt; - - if (cparamblkptr->precompile == 1) { - CError_Error(CErrorStr180); - return; - } - - if (!anyerrors) { - nspace = CFunc_FuncGenSetup(&firstStmt, func); - - saveDebugInfo = copts.filesyminfo; - copts.filesyminfo = 0; - - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = expr; - - CFunc_CodeCleanup(&firstStmt); - CInline_GenFunc(&firstStmt, func, 0); - - cscope_current = nspace->parent; - copts.filesyminfo = saveDebugInfo; - } -} - -void CFunc_GenerateDummyCtorFunc(Object *func, Object *real_ctor) { - ENode *expr; - NameSpace *nspace; - FuncArg *arg1; - FuncArg *arg0; - ENodeList *list; - Boolean saveDebugInfo; - Statement firstStmt; - Statement *stmt; - - if (cparamblkptr->precompile == 1) { - CError_Error(CErrorStr180); - return; - } - - if (!anyerrors) { - cscope_currentfunc = func; - - nspace = CFunc_FuncGenSetup(&firstStmt, func); - - saveDebugInfo = copts.filesyminfo; - copts.filesyminfo = 0; - - CFunc_SetupNewFuncArgs(func, TYPE_FUNC(func->type)->args); - - expr = CExpr_NewENode(EFUNCCALL); - expr->type = EFUNCCALL; - expr->cost = 200; - expr->rtype = TYPE(&void_ptr); - expr->data.funccall.funcref = CExpr_MakeObjRefNode(real_ctor, 0); - expr->data.funccall.functype = TYPE_FUNC(func->type); - - CError_ASSERT(3716, IS_TYPE_FUNC(real_ctor->type)); - CError_ASSERT(3717, TYPE_FUNC(real_ctor->type)->flags & FUNC_METHOD); - CError_ASSERT(3718, arg0 = TYPE_FUNC(real_ctor->type)->args); - CError_ASSERT(3720, arg1 = arg0->next); - CError_ASSERT(3721, arguments); - - list = lalloc(sizeof(ENodeList)); - expr->data.funccall.args = list; - list->node = create_objectnode(arguments->object); - - if (TYPE_METHOD(real_ctor->type)->theclass->flags & CLASS_HAS_VBASES) { - CError_ASSERT(3727, arg1 = arg1->next); - CError_ASSERT(3728, arguments->next); - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->node = create_objectnode(arguments->next->object); - } - - while (arg1) { - CError_ASSERT(3737, arg1->dexpr); - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->node = CExpr_GetDefaultArgument(expr->data.funccall.funcref, arg1); - arg1 = arg1->next; - } - - list->next = NULL; - - stmt = CFunc_AppendStatement(ST_RETURN); - stmt->expr = expr; - - CFunc_CodeCleanup(&firstStmt); - CInline_GenFunc(&firstStmt, func, 0); - - cscope_current = nspace->parent; - cscope_currentfunc = NULL; - copts.filesyminfo = saveDebugInfo; - } -} diff --git a/compiler_and_linker/unsorted/CIRTransform.c b/compiler_and_linker/unsorted/CIRTransform.c deleted file mode 100644 index b91f6af..0000000 --- a/compiler_and_linker/unsorted/CIRTransform.c +++ /dev/null @@ -1,534 +0,0 @@ -#include "compiler/CIRTransform.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInit.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/objects.h" -#include "compiler/types.h" -#include "compiler/CompilerTools.h" -#include "compiler/CDecl.h" - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct CIRTransTemp { - struct CIRTransTemp *next; - Object *object; - Boolean flag; -} CIRTransTemp; - -typedef struct MultiAccessOperand { - Object *object; - Object *tempobj; - ENode *ass; - Type *type; - Type *bitfieldType; -} MultiAccessOperand; - -// no idea what this is for... -typedef struct StrangeRuntimeFunction { - Object *object; - short unk; - char name[1]; -} StrangeRuntimeFunction; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static TypeFunc cirtrans_rtfunc8 = { - TYPEFUNC, 0, NULL, NULL, TYPE(&void_ptr), 0, 0 -}; -static TypeFunc cirtrans_rtfunc4 = { - TYPEFUNC, 0, NULL, NULL, TYPE(&stunsignedlong), 0, 0 -}; -static TypeFunc cirtrans_rtfunc2 = { - TYPEFUNC, 0, NULL, NULL, TYPE(&stsignedshort), 0, 0 -}; - -static CIRTransTemp *cirtrans_temps; -Boolean modulo_generated; -Boolean bigswitch_generated; -Boolean alloca_called; - -// forward decls -static ENode *CIRTrans_TransExpr(ENode *expr, Boolean flag); - -void CIRTrans_Setup(void) { -} - -void CIRTrans_Cleanup(void) { -} - -static Object *CIRTrans_GetRuntimeFunction(StrangeRuntimeFunction *rtfunc, Type *type) { - Object *object; - - object = rtfunc->object; - if (!object) { - object = CParser_NewFunctionObject(NULL); - rtfunc->object = object; - - object->nspace = cscope_root; - object->name = GetHashNameNodeExport(rtfunc->name); - object->flags = OBJECT_INTERNAL; - - if (type) { - switch (type->size) { - case 2: - object->type = TYPE(&cirtrans_rtfunc2); - break; - case 4: - object->type = TYPE(&cirtrans_rtfunc4); - break; - case 8: - object->type = TYPE(&cirtrans_rtfunc8); - break; - default: - CError_FATAL(427); - } - } else { - object->type = TYPE(&cirtrans_rtfunc8); - } - } - - return object; -} - -static Object *CIRTrans_GetTemporary(Type *type) { - CIRTransTemp *temp; - - for (temp = cirtrans_temps; temp; temp = temp->next) { - if (temp->object->type->size == type->size && !temp->flag) { - temp->flag = 1; - return temp->object; - } - } - - temp = oalloc(sizeof(CIRTransTemp)); - temp->next = cirtrans_temps; - cirtrans_temps = temp; - - temp->object = create_temp_object(type); - temp->flag = 1; - return temp->object; -} - -static ENode *CIRTrans_CheckRuntimeAssign(ENode *expr) { - ENode *inner; - - if (ENODE_IS(expr->data.diadic.right, EINDIRECT)) { - inner = expr->data.diadic.right->data.monadic; - if ( - ENODE_IS(inner, EFUNCCALL) && - (inner->flags & ENODE_FLAG_80) && - inner->data.funccall.args && - ENODE_IS(inner->data.funccall.args->node, EOBJREF) - ) - { - CError_ASSERT(502, ENODE_IS(expr->data.diadic.left, EINDIRECT)); - inner->data.funccall.args->node = expr->data.diadic.left->data.monadic; - inner->flags &= ~ENODE_FLAG_80; - return expr->data.diadic.right; - } - } - - return expr; -} - -static void CIRTrans_SetupMultiAccessOperand(MultiAccessOperand *mop, ENode *expr) { - memclrw(mop, sizeof(MultiAccessOperand)); - - mop->type = expr->rtype; - - CError_ASSERT(522, ENODE_IS(expr, EINDIRECT)); - expr = expr->data.monadic; - - if (ENODE_IS(expr, EOBJREF)) { - mop->object = expr->data.objref; - } else { - if (ENODE_IS(expr, EBITFIELD)) { - mop->bitfieldType = expr->rtype; - expr = expr->data.monadic; - } - expr->rtype = CDecl_NewPointerType(mop->type); - mop->tempobj = create_temp_object(expr->rtype); - mop->ass = makediadicnode(create_objectnode(mop->tempobj), expr, EASS); - } -} - -static ENode *CIRTrans_GetMultiAccessOperand(MultiAccessOperand *mop) { - ENode *expr; - - if (mop->object == NULL) { - expr = create_objectnode(mop->tempobj); - if (mop->bitfieldType) { - expr = makemonadicnode(expr, EBITFIELD); - expr->rtype = mop->bitfieldType; - } - expr = makemonadicnode(expr, EINDIRECT); - } else { - expr = create_objectnode(mop->object); - } - - expr->rtype = mop->type; - return expr; -} - -static ENode *CIRTrans_InitMultiAccessExpression(MultiAccessOperand *mop, ENode *expr) { - if (mop->ass) { - expr = makediadicnode(mop->ass, expr, ECOMMA); - expr->rtype = expr->data.diadic.right->rtype; - } - return expr; -} - -ENode *CIRTrans_TransformOpAss(ENode *expr) { - ENodeType nt; - ENode *expr2; - MultiAccessOperand mop; - - if (!ENODE_IS(expr->data.diadic.left, EINDIRECT)) { - CError_Error(CErrorStr142); - return nullnode(); - } - - CIRTrans_SetupMultiAccessOperand(&mop, expr->data.diadic.left); - - switch (expr->type) { - case EMULASS: - nt = EMUL; - break; - case EDIVASS: - nt = EDIV; - break; - case EMODASS: - nt = EMODULO; - break; - case EADDASS: - nt = EADD; - break; - case ESUBASS: - nt = ESUB; - break; - case ESHLASS: - nt = ESHL; - break; - case ESHRASS: - nt = ESHR; - break; - case EANDASS: - nt = EAND; - break; - case EXORASS: - nt = EXOR; - break; - case EORASS: - nt = EOR; - break; - default: - CError_FATAL(622); - } - - expr2 = CIRTrans_GetMultiAccessOperand(&mop); - - if (!IS_TYPE_POINTER_ONLY(expr2->rtype)) { - expr2 = CExpr_NewDyadicNode(expr2, nt, expr->data.diadic.right); - if (expr2->rtype != expr->data.diadic.left->rtype) { - expr2 = makemonadicnode(expr2, ETYPCON); - expr2->rtype = expr->data.diadic.left->rtype; - } - } else { - expr2 = makediadicnode(expr2, expr->data.diadic.right, nt); - } - - if (IS_TYPE_FLOAT(expr2->rtype)) - expr2 = CExpr_BinaryFloatExpression(expr2); - - expr2 = makediadicnode(CIRTrans_GetMultiAccessOperand(&mop), expr2, EASS); - return CIRTrans_InitMultiAccessExpression(&mop, expr2); -} - -static void CIRTrans_TransIncDec() { - // empty, never called -} - -static ENode *CIRTrans_TransIntConst(ENode *expr) { - Object *obj; - UInt8 data[16]; - - CMach_InitIntMem(expr->rtype, expr->data.intval, data); - - obj = CParser_NewGlobalDataObject(NULL); - obj->name = CParser_GetUniqueName(); - obj->type = expr->rtype; - obj->sclass = TK_STATIC; - obj->datatype = DDATA; - CScope_AddGlobalObject(obj); - CInit_DeclareData(obj, data, NULL, obj->type->size); - return create_objectnode(obj); -} - -static ENode *CIRTrans_TransFloatConst(ENode *expr) { - Object *obj; - UInt8 data[16]; - - CMach_InitFloatMem(expr->rtype, expr->data.floatval, data); - - obj = CParser_NewGlobalDataObject(NULL); - obj->name = CParser_GetUniqueName(); - obj->type = expr->rtype; - obj->sclass = TK_STATIC; - obj->datatype = DDATA; - CScope_AddGlobalObject(obj); - CInit_DeclareData(obj, data, NULL, obj->type->size); - return create_objectnode(obj); -} - -static ENode *CIRTrans_TransUnary(ENode *expr, Type *type, StrangeRuntimeFunction *rtfunc) { - if (type->size > 4) { - expr = funccallexpr( - CIRTrans_GetRuntimeFunction(rtfunc, type), - create_objectrefnode(CIRTrans_GetTemporary(type)), - expr, - NULL, - NULL); - expr->flags |= ENODE_FLAG_80; - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = type; - return expr; - } else { - expr = funccallexpr( - CIRTrans_GetRuntimeFunction(rtfunc, type), - expr, - NULL, - NULL, - NULL); - expr->rtype = type; - return expr; - } -} - -static ENode *CIRTrans_TransBinary(ENode *expr, StrangeRuntimeFunction *rtfunc) { - ENode *expr2; - - if (expr->rtype->size > 4) { - expr2 = funccallexpr( - CIRTrans_GetRuntimeFunction(rtfunc, expr->rtype), - create_objectrefnode(CIRTrans_GetTemporary(expr->rtype)), - expr->data.diadic.left, - expr->data.diadic.right, - NULL); - expr2->flags |= ENODE_FLAG_80; - expr2 = makemonadicnode(expr2, EINDIRECT); - expr2->rtype = expr->rtype; - return expr2; - } else { - expr2 = funccallexpr( - CIRTrans_GetRuntimeFunction(rtfunc, expr->rtype), - expr->data.diadic.left, - expr->data.diadic.right, - NULL, - NULL); - expr2->rtype = expr->rtype; - return expr2; - } -} - -static ENodeList *CIRTrans_TransExprList(ENodeList *list) { - ENodeList *scan; - - for (scan = list; scan; scan = scan->next) - scan->node = CIRTrans_TransExpr(scan->node, 1); - - return list; -} - -static ENode *CIRTrans_TransExpr(ENode *expr, Boolean flag) { - switch (expr->type) { - case EINDIRECT: - case EFORCELOAD: - case EBITFIELD: - expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); - break; - case EPOSTINC: - expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, 1); - break; - case EPOSTDEC: - expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, 1); - break; - case EPREINC: - expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, 1); - break; - case EPREDEC: - expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, 1); - break; - case ETYPCON: - expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); - if (!flag) - return expr->data.monadic; - break; - case EBINNOT: - expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); - break; - case ELOGNOT: - expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); - break; - case EMONMIN: - expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); - break; - case EADD: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); - break; - case ESUB: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); - break; - case EMUL: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); - case EDIV: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); - break; - case EMODULO: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); - break; - case ESHL: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); - break; - case ESHR: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); - break; - case EROTL: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); - break; - case EROTR: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); - break; - case EAND: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); - break; - case EXOR: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); - break; - case EOR: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); - break; - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); - if (!flag) { - expr->type = ECOMMA; - expr->rtype = expr->data.diadic.right->rtype; - return expr; - } - break; - case ELAND: - case ELOR: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 1); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); - break; - case EMULV: - case EADDV: - case ESUBV: - case EPMODULO: - case EBCLR: - case EBTST: - case EBSET: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); - break; - case EASS: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 1); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, 1); - break; - case EMULASS: - case EDIVASS: - case EADDASS: - case ESUBASS: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 1); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, 1); - break; - case EMODASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 1); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, 1); - break; - case ECOMMA: - expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 0); - expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); - break; - case ECOND: - expr->data.cond.cond = CIRTrans_TransExpr(expr->data.cond.cond, 1); - expr->data.cond.expr1 = CIRTrans_TransExpr(expr->data.cond.expr1, 1); - expr->data.cond.expr2 = CIRTrans_TransExpr(expr->data.cond.expr2, 1); - break; - case EMFPOINTER: - expr->data.mfpointer.accessnode = CIRTrans_TransExpr(expr->data.mfpointer.accessnode, flag); - expr->data.mfpointer.mfpointer = CIRTrans_TransExpr(expr->data.mfpointer.mfpointer, flag); - break; - case EFUNCCALL: - case EFUNCCALLP: - if ( - ENODE_IS(expr->data.funccall.funcref, EOBJREF) && - !strcmp(expr->data.funccall.funcref->data.objref->name->name, "__alloca") - ) - alloca_called = 1; - expr->data.funccall.funcref = CIRTrans_TransExpr(expr->data.funccall.funcref, 1); - expr->data.funccall.args = CIRTrans_TransExprList(expr->data.funccall.args); - break; - case ENULLCHECK: - expr->data.nullcheck.nullcheckexpr = CIRTrans_TransExpr(expr->data.nullcheck.nullcheckexpr, 1); - expr->data.nullcheck.condexpr = CIRTrans_TransExpr(expr->data.nullcheck.condexpr, 1); - break; - case ENEWEXCEPTION: - case ENEWEXCEPTIONARRAY: - expr->data.newexception.initexpr = CIRTrans_TransExpr(expr->data.newexception.initexpr, 1); - expr->data.newexception.tryexpr = CIRTrans_TransExpr(expr->data.newexception.tryexpr, 1); - break; - case EINITTRYCATCH: - expr->data.itc.initexpr = CIRTrans_TransExpr(expr->data.itc.initexpr, 1); - expr->data.itc.tryexpr = CIRTrans_TransExpr(expr->data.itc.tryexpr, 1); - expr->data.itc.catchexpr = CIRTrans_TransExpr(expr->data.itc.catchexpr, 1); - expr->data.itc.result = CIRTrans_TransExpr(expr->data.itc.result, 1); - break; - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case EPRECOMP: - case ETEMP: - case ELABEL: - case EMEMBER: - case EINSTRUCTION: - case EVECTOR128CONST: - break; - default: - CError_FATAL(1947); - } - - return expr; -} - -void CIRTrans_Transform(void) { - cirtrans_temps = NULL; -} diff --git a/compiler_and_linker/unsorted/CInit.c b/compiler_and_linker/unsorted/CInit.c deleted file mode 100644 index c2d2299..0000000 --- a/compiler_and_linker/unsorted/CInit.c +++ /dev/null @@ -1,3082 +0,0 @@ -#include "compiler/CInit.h" -#include "compiler/CABI.h" -#include "compiler/CClass.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CException.h" -#include "compiler/CExpr.h" -#include "compiler/CInline.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/CPrec.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CScope.h" -#include "compiler/CompilerTools.h" -#include "compiler/ObjGenMachO.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -TempNodeCB cinit_tempnodefunc; -InitInfo *cinit_initinfo; -static PooledString *cinit_stringlist; -static PooledString *cinit_pooledstringlist; -static PooledString *cinit_pooledwstringlist; -static ObjectList *cinit_tentative; -static TypeClass *cinit_loop_class; -static ENodeList *cinit_fdtnode; -static Boolean cinit_fdtambig; - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct CInit_1C { - struct CInit_1C *next; - Type *type; - ENode *expr; - SInt32 offset; -} CInit_1C; - -typedef struct CInit_Stuff { - struct CInit_Stuff *x0; - struct CInit_Stuff *x4; - char *buffer; - SInt32 xC; - SInt32 size; - SInt32 bufferSize; - SInt32 x18; - CInit_1C *x1C; - OLinkList *list; - Boolean flag; -} CInit_Stuff; - -typedef enum { - Stage0, - Stage1, - Stage2, - Stage3, - Stage4 -} Stage; - -typedef struct CInit_Stuff2 { - ENode *expr; - ENode myexpr; - Stage stage; - Boolean x23; - SInt32 x24; - Type *type; -} CInit_Stuff2; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -// forward decls -static void CInit_InitType(CInit_Stuff *s, CInit_Stuff2 *s2, Type *type, UInt32 qual, Boolean flag); -static void CInit_Type(Type *type, UInt32 qual, Boolean flag); - -void CInit_Init(void) { - cinit_tempnodefunc = NULL; - cinit_initinfo = NULL; - cinit_stringlist = NULL; - cinit_pooledstringlist = NULL; - cinit_pooledwstringlist = NULL; - cinit_tentative = NULL; -} - -static void CInit_SetupInitInfo(InitInfo *info, Object *obj) { - memclrw(info, sizeof(InitInfo)); - info->obj = obj; - info->next = cinit_initinfo; - cinit_initinfo = info; -} - -static void CInit_CleanupInitInfo(InitInfo *info) { - cinit_initinfo = info->next; -} - -static void CInit_SetupInitInfoBuffer(Type *type) { - SInt32 size = type->size; - cinit_initinfo->size = size; - - if (!size) - size = 512; - else if (size & 1) - size++; - - cinit_initinfo->buffer = lalloc(size); - cinit_initinfo->bufferSize = size; - memclrw(cinit_initinfo->buffer, size); -} - -static void CInit_SetData(void *data, SInt32 offset, SInt32 size) { - SInt32 end; - char *buffer; - - end = offset + size; - if (end > cinit_initinfo->size) - cinit_initinfo->size = end; - - if (end > cinit_initinfo->bufferSize) { - if (cinit_initinfo->obj->type->size == 0) { - if (end < 8000) - end += 0x400; - else - end += 0x4000; - } - if (end & 1) - end++; - - buffer = lalloc(end); - memclrw(buffer, end); - memcpy(buffer, cinit_initinfo->buffer, cinit_initinfo->bufferSize); - cinit_initinfo->buffer = buffer; - cinit_initinfo->bufferSize = end; - } - - if (data) - memcpy(cinit_initinfo->buffer + offset, data, size); -} - -typedef struct CInit_Initializer { - struct CInit_Initializer *next; - struct CInit_Initializer *sublist; - ENode *expr; - TStreamElement element; -} CInit_Initializer; - -static CInit_Initializer *CInit_ParseInitializerList(void) { - CInit_Initializer *r30; - CInit_Initializer *r29; - CInit_Initializer *tmp; - - if ((tk = lex()) == '}') - return NULL; - - r30 = NULL; - do { - if (r30) { - tmp = lalloc(sizeof(CInit_Initializer)); - r29->next = tmp; - r29 = tmp; - } - if (!r30) { - r30 = r29 = lalloc(sizeof(CInit_Initializer)); - } - r29->next = NULL; - - if (tk == '{') { - r29->element = *CPrep_CurStreamElement(); - r29->sublist = CInit_ParseInitializerList(); - r29->expr = NULL; - tk = lex(); - } else { - r29->sublist = NULL; - r29->expr = conv_assignment_expression(); - r29->element = *CPrep_CurStreamElement(); - } - - if (tk == '}') - return r30; - - if (tk != ',') { - CError_Error(CErrorStr116); - return r30; - } - } while ((tk = lex()) != '}'); - - return r30; -} - -static CInit_Initializer *CInit_ParseInitializerClause(void) { - CInit_Initializer *init; - - init = lalloc(sizeof(CInit_Initializer)); - init->next = NULL; - if (tk != '{') { - init->sublist = NULL; - init->expr = conv_assignment_expression(); - init->element = *CPrep_CurStreamElement(); - } else { - init->element = *CPrep_CurStreamElement(); - init->expr = NULL; - init->sublist = CInit_ParseInitializerList(); - tk = lex(); - } - - return init; -} - -static ENode *CInit_ParseInitializer(ENode *expr) { - CInt64 save_int; - Float save_float; - SInt32 save_size; - short t; - - switch (tk) { - case TK_INTCONST: - case TK_FLOATCONST: - save_int = tkintconst; - save_float = tkfloatconst; - save_size = tksize; - t = lookahead(); - tkintconst = save_int; - tkfloatconst = save_float; - tksize = save_size; - - switch (t) { - case ',': - case ';': - case '}': - memclrw(expr, sizeof(ENode)); - switch (tk) { - case TK_INTCONST: - expr->type = EINTCONST; - expr->rtype = atomtype(); - expr->data.intval = tkintconst; - break; - case TK_FLOATCONST: - expr->type = EFLOATCONST; - expr->rtype = atomtype(); - expr->data.floatval = tkfloatconst; - break; - } - tk = lex(); - CPrep_TokenStreamFlush(); - return expr; - } - } - - expr = assignment_expression(); - CPrep_TokenStreamFlush(); - return expr; -} - -static Stage CInit_ParseNextInit(CInit_Stuff2 *s) { - DeclInfo di; - short t; - - s->expr = NULL; - if (tk == ';') { - s->stage = Stage4; - return Stage4; - } - switch (s->stage) { - case Stage0: - if (s->x23) { - if (tk == '(') { - tk = lex(); - CParser_GetDeclSpecs(&di, 1); - s->type = di.thetype; - if (tk == ')') - tk = lex(); - else - CError_Error(CErrorStr115); - - if (tk == '(') - tk = lex(); - else - CError_Error(CErrorStr114); - s->x24++; - t = lookahead(); - if (t == TK_UU_VECTOR || (t == TK_IDENTIFIER && !strcmp("vector", tkidentifier->name))) - CInit_ParseNextInit(s); - s->stage = Stage1; - return Stage1; - } - } else { - if (tk == '{') { - tk = lex(); - s->x24 = 0; - s->stage = Stage1; - return Stage1; - } - } - s->expr = CInit_ParseInitializer(&s->myexpr); - s->stage = Stage2; - return Stage2; - case Stage1: - break; - case Stage2: - case Stage3: - if (tk == ',') { - tk = lex(); - break; - } - if (s->x24) { - if (tk != ')') - CError_Error(CErrorStr174); - if (s->x24 > 1) { - s->x24--; - tk = lex(); - CInit_ParseNextInit(s); - } - } else { - if (tk != '}') - CError_Error(CErrorStr174); - } - s->stage = Stage3; - return Stage3; - default: - CError_FATAL(389); - } - - switch (tk) { - case '{': - tk = lex(); - s->stage = Stage1; - return Stage1; - case '}': - s->stage = Stage3; - return Stage3; - case '(': - if (s->x23) { - tk = lex(); - s->stage = Stage1; - return Stage1; - } - case ')': - if (s->x23 && s->x24) { - if (s->x24 > 1) { - s->x24--; - tk = lex(); - CInit_ParseNextInit(s); - } - s->stage = Stage3; - return Stage3; - } - default: - s->expr = CInit_ParseInitializer(&s->myexpr); - s->stage = Stage2; - return Stage2; - } -} - -static void CInit_CloseInitList(void) { - if (tk == ',' && copts.cplusplus) - tk = lex(); - - if (tk != '}') - CError_ErrorSkip(CErrorStr130); - else - tk = lex(); -} - -static Boolean CInit_IsAllZero(char *buf, SInt32 size) { - SInt32 i; - - if (copts.explicit_zero_data) - return 0; - - for (i = 0; i < size; i++) - if (buf[i]) return 0; - - return 1; -} - -static Boolean CInit_ClassNeedsConstruction(TypeClass *tclass) { - return CClass_Constructor(tclass) || CClass_Destructor(tclass); -} - -static Boolean CInit_IsSimpleStructArrayInit(Type *type) { - switch (type->type) { - case TYPESTRUCT: - return 1; - case TYPEARRAY: - while (IS_TYPE_ARRAY(type)) - type = TYPE_POINTER(type)->target; - if (!IS_TYPE_CLASS(type)) - return 1; - case TYPECLASS: - return !CInit_ClassNeedsConstruction(TYPE_CLASS(type)); - default: - return 0; - } -} - -static Boolean CInit_IsSimpleInit(Type *type) { - switch (type->type) { - case TYPEPOINTER: - return (TYPE_POINTER(type)->qual & Q_REFERENCE) == 0; - case TYPEARRAY: - while (IS_TYPE_ARRAY(type)) - type = TYPE_POINTER(type)->target; - if (!IS_TYPE_CLASS(type)) - return 1; - case TYPECLASS: - return !CInit_ClassNeedsConstruction(TYPE_CLASS(type)); - default: - return 1; - } -} - -static Object *CInit_GetInitObject(Object *obj) { - if (obj->datatype == DALIAS) { - CError_ASSERT(521, !obj->u.alias.offset); - obj = obj->u.alias.object; - } - return obj; -} - -static Object *CInit_CreateStaticDataObject(Type *type, UInt32 qual, HashNameNode *name) { - Object *obj; - DeclInfo di; - - memclrw(&di, sizeof(DeclInfo)); - di.thetype = type; - di.name = name ? name : CParser_GetUniqueName(); - di.qual = qual; - di.storageclass = TK_STATIC; - di.is_extern_c = 1; - - obj = CParser_NewGlobalDataObject(&di); - obj->nspace = cscope_root; - return obj; -} - -static Type *CInit_GetRegMemType(void) { - return CDecl_NewStructType(void_ptr.size * 3, CMach_GetTypeAlign((Type *) &void_ptr)); -} - -static Object *CInit_CreateStaticData(Type *type) { - Object *obj = CInit_CreateStaticDataObject(type, 0, NULL); - CInit_DeclareData(obj, NULL, NULL, obj->type->size); - return obj; -} - -static void CInit_InitNonConst(CInit_Stuff *s, Type *type, ENode *expr) { - CInit_1C *entry; - CInit_1C *scan; - MWVector128 *vec; - - if (s->x4->flag || IS_TYPE_VECTOR(type)) { - if (IS_TYPE_VECTOR(type) && ENODE_IS(expr, EVECTOR128CONST)) { - vec = (MWVector128 *) (s->buffer + s->size); - *vec = expr->data.vector128val; - CMach_InitVectorMem(type, *vec, vec, 1); - } - - entry = lalloc(sizeof(CInit_1C)); - memclrw(entry, sizeof(CInit_1C)); - entry->next = NULL; - entry->type = type; - entry->expr = expr; - entry->offset = s->xC + s->size; - if ((scan = s->x4->x1C)) { - while (scan->next) - scan = scan->next; - scan->next = entry; - } else { - s->x4->x1C = entry; - } - } else { - CError_Error(CErrorStr124); - } -} - -static CInit_Stuff *CInit_GrowBuffer(CInit_Stuff *s, SInt32 size) { - CInit_Stuff *newbuf; - - newbuf = lalloc(sizeof(CInit_Stuff)); - memclrw(newbuf, sizeof(CInit_Stuff)); - newbuf->x4 = s->x4; - newbuf->buffer = lalloc(size); - newbuf->xC = s->xC + s->size; - newbuf->bufferSize = size; - s->x0 = newbuf; - memset(newbuf->buffer, 0, newbuf->bufferSize); - return newbuf; -} - -Boolean CInit_RelocInitCheck(ENode *expr, Object **objptr, CInt64 *valptr, Boolean flag) { - Object *objcheck1; - Object *objcheck2; - CInt64 valcheck1; - CInt64 valcheck2; - - *objptr = NULL; - valptr->lo = 0; - valptr->hi = 0; - - while (1) { - switch (expr->type) { - case EINTCONST: - *valptr = expr->data.intval; - return 1; - case EOBJREF: - objcheck1 = CInit_GetInitObject(expr->data.objref); - if (objcheck1->datatype == DLOCAL && !flag) - return 0; - *objptr = objcheck1; - return 1; - case ESTRINGCONST: - CInit_RewriteString(expr, 0); - continue; - case ETYPCON: - do { - if (expr->rtype->size != expr->data.monadic->rtype->size) - return 0; - expr = expr->data.monadic; - if (!IS_TYPE_POINTER_ONLY(expr->rtype) && !IS_TYPE_INT(expr->rtype)) - return 0; - } while (ENODE_IS(expr, ETYPCON)); - continue; - case EADD: - if (!CInit_RelocInitCheck(expr->data.diadic.left, &objcheck1, &valcheck1, flag)) - return 0; - if (!CInit_RelocInitCheck(expr->data.diadic.right, &objcheck2, &valcheck2, flag)) - return 0; - - if (objcheck1) { - if (objcheck2) - return 0; - *objptr = objcheck1; - } else { - *objptr = objcheck1; - } - - *valptr = CMach_CalcIntDiadic(TYPE(&stunsignedlong), valcheck1, '+', valcheck2); - return 1; - case ESUB: - if (!CInit_RelocInitCheck(expr->data.diadic.left, &objcheck1, &valcheck1, flag)) - return 0; - if (!CInit_RelocInitCheck(expr->data.diadic.right, &objcheck2, &valcheck2, flag)) - return 0; - - if (objcheck2) - return 0; - - *objptr = objcheck1; - *valptr = CMach_CalcIntDiadic(TYPE(&stunsignedlong), valcheck1, '-', valcheck2); - return 1; - default: - return 0; - } - } -} - -static void CInit_InitTypePointer(CInit_Stuff *s, ENode *expr, TypePointer *tptr, UInt32 qual) { - Object *obj; - CInt64 val; - OLinkList *list; - - expr = CExpr_AssignmentPromotion(expr, TYPE(tptr), qual & (Q_CONST | Q_VOLATILE), 1); - if (IS_TYPE_POINTER_ONLY(expr->rtype) || ENODE_IS(expr, EINTCONST)) { - if (CInit_RelocInitCheck(expr, &obj, &val, 0)) { - if (obj) { - list = lalloc(sizeof(OLinkList)); - list->next = s->x4->list; - list->obj = obj; - list->somevalue = CInt64_GetULong(&val); - list->offset = s->xC + s->size; - s->x4->list = list; - } else { - CMach_InitIntMem(TYPE(&stunsignedlong), val, s->buffer + s->size); - } - } else { - CInit_InitNonConst(s, TYPE(tptr), expr); - } - } else { - CError_Error(CErrorStr174); - } -} - -static void CInit_InitTypeInt(CInit_Stuff *s, ENode *expr, TypeIntegral *tint, UInt32 qual) { - expr = CExpr_AssignmentPromotion(expr, TYPE(tint), qual & (Q_CONST | Q_VOLATILE), 1); - if (IS_TYPE_INT(expr->rtype)) { - if (ENODE_IS(expr, EINTCONST)) { - CMach_InitIntMem(TYPE(tint), expr->data.intval, s->buffer + s->size); - } else if (ENODE_IS(expr, ETYPCON) && IS_TYPE_POINTER_ONLY(expr->data.monadic->rtype) && expr->rtype->size == 4 && (copts.cplusplus || !copts.ANSIstrict)) { - CInit_InitTypePointer(s, expr->data.monadic, TYPE_POINTER(expr->data.monadic->rtype), qual); - } else { - CInit_InitNonConst(s, TYPE(tint), expr); - } - } else { - CError_Error(CErrorStr174); - } -} - -static void CInit_InitTypeFloat(CInit_Stuff *s, ENode *expr, TypeIntegral *tint, UInt32 qual) { - expr = CExpr_AssignmentPromotion(expr, TYPE(tint), qual & (Q_CONST | Q_VOLATILE), 1); - if (IS_TYPE_FLOAT(expr->rtype)) { - if (ENODE_IS(expr, EFLOATCONST)) { - CMach_InitFloatMem(TYPE(tint), expr->data.floatval, s->buffer + s->size); - } else { - CInit_InitNonConst(s, TYPE(tint), expr); - } - } else { - CError_Error(CErrorStr174); - } -} - -static void CInit_InitTypeEnum(CInit_Stuff *s, ENode *expr, TypeEnum *tenum, UInt32 qual) { - expr = CExpr_AssignmentPromotion(expr, TYPE(tenum), qual & (Q_CONST | Q_VOLATILE), 1); - if (IS_TYPE_ENUM(expr->rtype)) { - if (ENODE_IS(expr, EINTCONST)) { - CMach_InitIntMem(tenum->enumtype, expr->data.intval, s->buffer + s->size); - } else { - CInit_InitNonConst(s, TYPE(tenum), expr); - } - } else { - CError_Error(CErrorStr174); - } -} - -static void CInit_InitTypeMemberPointer(CInit_Stuff *s, ENode *expr, TypeMemberPointer *tmptr, UInt32 qual) { - expr = CExpr_AssignmentPromotion(expr, TYPE(tmptr), qual & (Q_CONST | Q_VOLATILE), 1); - if (ENODE_IS(expr, EINTCONST)) { - CMach_InitIntMem(TYPE(&stsignedlong), expr->data.intval, s->buffer + s->size); - } else { - CInit_InitNonConst(s, TYPE(tmptr), expr); - } -} - -static void CInit_SetBitfield(TypeBitfield *tbitfield, UInt8 *buffer, CInt64 val) { - int i; - int pos; - int step; - - if (copts.littleendian) { - pos = tbitfield->offset; - step = 1; - } else { - pos = tbitfield->bitlength + tbitfield->offset - 1; - step = -1; - } - for (i = 0; i < tbitfield->bitlength; i++, pos += step) { - if (CInt64_GetULong(&val) & 1) { - if (copts.littleendian) { - buffer[pos >> 3] |= 1 << (pos & 7); - } else { - buffer[pos >> 3] |= 0x80 >> (pos & 7); - } - } - val = CInt64_ShrU(val, cint64_one); - } -} - -static void CInit_InitTypeBitfield(CInit_Stuff *s, ENode *expr, TypeBitfield *tbitfield, UInt32 qual) { - Type *inner; - - inner = tbitfield->bitfieldtype; - if (IS_TYPE_ENUM(inner)) - inner = TYPE_ENUM(inner)->enumtype; - expr = CExpr_AssignmentPromotion(expr, inner, qual & (Q_CONST | Q_VOLATILE), 1); - - if (IS_TYPE_INT(expr->rtype)) { - if (ENODE_IS(expr, EINTCONST)) { - CInit_SetBitfield(tbitfield, (UInt8 *) s->buffer + s->size, expr->data.intval); - } else { - CInit_InitNonConst(s, TYPE(tbitfield), expr); - } - } else { - CError_Error(CErrorStr174); - } -} - -static void CInit_InitTypeArray(CInit_Stuff *s, CInit_Stuff2 *s2, TypePointer *tptr, UInt32 qual, Boolean errorflag) { - SInt32 targetsize; - SInt32 start; - SInt32 i; - Boolean flag; - Boolean is_zero_size; - SInt32 size; - SInt32 tmp; - Boolean is_char_ptr; - Boolean is_wchar_ptr; - - is_zero_size = tptr->size == 0; - targetsize = tptr->target->size; - if (!targetsize) { - CError_Error(CErrorStr145); - return; - } - - is_char_ptr = IS_TYPE_INT(tptr->target) && (targetsize == 1); - is_wchar_ptr = IS_TYPE_INT(tptr->target) && (targetsize == stwchar.size); - switch (s2->stage) { - case Stage1: - flag = 1; - if (CInit_ParseNextInit(s2) == Stage3) { - if (is_zero_size) - CError_Error(CErrorStr174); - tk = lex(); - return; - } - break; - case Stage2: - flag = 0; - break; - } - switch (s2->stage) { - case Stage1: - case Stage2: - break; - default: - CError_Error(CErrorStr174); - return; - } - - if (s2->stage == Stage2) - s2->expr = pointer_generation(s2->expr); - - if (s2->stage == Stage2 && ENODE_IS(s2->expr, ESTRINGCONST) && (is_char_ptr || is_wchar_ptr)) { - if (IS_TYPE_POINTER_ONLY(s2->expr->rtype) && tptr->target->size != TYPE_POINTER(s2->expr->rtype)->target->size) - CError_Warning(CErrorStr174); - size = tmp = s2->expr->data.string.size; - if (is_zero_size) { - tptr->size = s2->expr->data.string.size; - if (s->bufferSize < tmp) - s = CInit_GrowBuffer(s, tmp); - memcpy(s->buffer, s2->expr->data.string.data, size); - s->size = size; - } else { - if (s2->expr->data.string.size > tptr->size) { - if (copts.cplusplus || (s2->expr->data.string.size - 1) > tptr->size) - CError_Error(CErrorStr147); - s2->expr->data.string.size = tptr->size; - size = tptr->size; - } - memcpy(s->buffer + s->size, s2->expr->data.string.data, size); - } - } else { - if (!flag && errorflag) { - CError_Error(CErrorStr174); - return; - } - - start = s->size; - i = 0; - while (1) { - if (is_zero_size) { - size = (i + 1) * targetsize; - s->size = start + size - targetsize - s->xC; - if (s->size + targetsize > s->bufferSize) - s = CInit_GrowBuffer(s, targetsize * 16); - CInit_InitType(s, s2, tptr->target, qual, 0); - tptr->size = size; - s->size = start + size - s->xC; - } else { - if (tptr->size <= i * targetsize) { - i--; - CError_Error(CErrorStr147); - } - s->size = start + i * targetsize; - CInit_InitType(s, s2, tptr->target, qual, 0); - if (!flag && tptr->size <= (i + 1) * targetsize) - break; - } - - switch (CInit_ParseNextInit(s2)) { - case Stage1: - case Stage2: - break; - case Stage3: - if (flag) - tk = lex(); - return; - default: - CError_Error(CErrorStr130); - return; - } - - i++; - } - } - - if (flag) { - switch (CInit_ParseNextInit(s2)) { - case Stage3: - tk = lex(); - return; - case Stage2: - CError_Error(CErrorStr147); - return; - default: - CError_Error(CErrorStr130); - } - } -} - -static void CInit_InitTypeStruct(CInit_Stuff *s, CInit_Stuff2 *s2, const TypeStruct *tstruct, UInt32 qual, Boolean errorflag) { - StructMember *member; - SInt32 start; - Boolean flag; - SInt32 count; - TypePointer arraytype; - MWVector128 *vecp; - int i; - - count = 0; - if (s2->type) - tstruct = TYPE_STRUCT(s2->type); - - if (!(member = tstruct->members)) { - CError_Error(CErrorStr145); - return; - } - - switch (s2->stage) { - case Stage1: - flag = 1; - if (CInit_ParseNextInit(s2) == Stage3) { - tk = lex(); - return; - } - break; - case Stage2: - flag = 0; - break; - } - - switch (s2->stage) { - case Stage1: - case Stage2: - break; - default: - CError_Error(CErrorStr174); - return; - } - - if (!flag && s2->stage == Stage2 && (errorflag || s2->expr->rtype == TYPE(tstruct))) { - s2->expr = CExpr_AssignmentPromotion(s2->expr, TYPE(tstruct), qual, 1); - if (IS_TYPE_STRUCT(s2->expr->rtype)) - CInit_InitNonConst(s, TYPE(tstruct), s2->expr); - return; - } - - start = s->size; - while (1) { - s->size = start + member->offset; - if (!member->type->size) { - if (!errorflag || !IS_TYPE_ARRAY(member->type)) { - CError_Error(CErrorStr147); - if (!IS_TYPE_ARRAY(member->type)) - return; - } - - arraytype = *TYPE_POINTER(member->type); - CInit_InitTypeArray(s, s2, &arraytype, member->qual, 1); - s->x18 = arraytype.size; - } else { - CInit_InitType(s, s2, member->type, member->qual, 0); - } - - count++; - if (IS_TYPESTRUCT_VECTOR(tstruct) && s2->expr) - CError_ASSERT(1218, !ENODE_IS(s2->expr, EVECTOR128CONST)); - - do { - member = member->next; - } while (member && (member->qual & Q_WEAK)); - - if (!member || tstruct->stype == STRUCT_TYPE_UNION) { - if (flag) { - switch (CInit_ParseNextInit(s2)) { - case Stage3: - if (IS_TYPESTRUCT_VECTOR(tstruct)) { - vecp = (MWVector128 *) (s->buffer + start); - CMach_InitVectorMem(TYPE(tstruct), *vecp, vecp, 0); - } - tk = lex(); - return; - case Stage2: - CError_Error(CErrorStr147); - return; - default: - CError_Error(CErrorStr130); - return; - } - } - return; - } else { - switch (CInit_ParseNextInit(s2)) { - case Stage1: - case Stage2: - continue; - case Stage3: - if (flag) - tk = lex(); - if (IS_TYPESTRUCT_VECTOR(tstruct)) { - switch (TYPE_STRUCT(tstruct)->stype) { - case STRUCT_VECTOR_UCHAR: - case STRUCT_VECTOR_SCHAR: - case STRUCT_VECTOR_BCHAR: - if (count != 16) { - if (count == 1) { - UInt8 val, *p; - p = (UInt8 *) s->buffer; - val = p[0]; - for (i = 1; i < 16; i++) - p[i] = val; - } else { - CError_Error(CErrorStr174); - } - } - break; - case STRUCT_VECTOR_USHORT: - case STRUCT_VECTOR_SSHORT: - case STRUCT_VECTOR_BSHORT: - case STRUCT_VECTOR_PIXEL: - if (count != 8) { - if (count == 1) { - SInt16 val, *p; - p = (SInt16 *) s->buffer; - val = p[0]; - for (i = 1; i < 8; i++) - p[i] = val; - } else { - CError_Error(CErrorStr174); - } - } - break; - case STRUCT_VECTOR_UINT: - case STRUCT_VECTOR_SINT: - case STRUCT_VECTOR_BINT: - case STRUCT_VECTOR_FLOAT: - if (count != 4) { - if (count == 1) { - UInt32 val, *p; - p = (UInt32 *) s->buffer; - val = p[0]; - for (i = 1; i < 4; i++) - p[i] = val; - } else { - CError_Error(CErrorStr174); - } - } - break; - } - } - return; - default: - CError_Error(CErrorStr174); - return; - } - } - } -} - -static ObjMemberVar *CInit_FindNextMember(ObjMemberVar *ivar) { - ObjMemberVar *scan = ivar; - while (1) { - scan = scan->next; - if (!scan) - return NULL; - if (!scan->anonunion) - return scan; - if (scan->offset > ivar->offset) - return scan; - if (IS_TYPE_BITFIELD(scan->type) && IS_TYPE_BITFIELD(ivar->type) && TYPE_BITFIELD(scan->type)->offset != TYPE_BITFIELD(ivar->type)->offset) - return scan; - } -} - -static void CInit_InitTypeClass(CInit_Stuff *s, CInit_Stuff2 *s2, TypeClass *tclass, UInt32 qual, Boolean errorflag) { - ObjMemberVar *ivar; - SInt32 start; - Boolean flag; - SInt32 last_offset; - TypePointer arraytype; - - if (tclass->bases || tclass->vtable) { - CError_Error(CErrorStr174); - return; - } - - switch (s2->stage) { - case Stage1: - flag = 1; - if (CInit_ParseNextInit(s2) == Stage3) { - tk = lex(); - return; - } - break; - case Stage2: - flag = 0; - break; - } - - switch (s2->stage) { - case Stage1: - case Stage2: - break; - default: - CError_Error(CErrorStr174); - return; - } - - if (!flag && s2->stage == Stage2 && (errorflag || s2->expr->rtype == TYPE(tclass) || CExpr_CanImplicitlyConvert(s2->expr, TYPE(tclass), 0))) { - s2->expr = CExpr_AssignmentPromotion(s2->expr, TYPE(tclass), qual, 1); - if (IS_TYPE_CLASS(s2->expr->rtype)) - CInit_InitNonConst(s, TYPE(tclass), s2->expr); - return; - } - - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - if (ivar->access != ACCESSPUBLIC) { - CError_Error(CErrorStr174); - break; - } - } - - if (!(ivar = tclass->ivars)) { - CError_Error(CErrorStr147); - return; - } - start = s->size; - while (1) { - s->size = start + ivar->offset; - if (!ivar->type->size) { - if (!errorflag || !IS_TYPE_ARRAY(ivar->type)) { - CError_Error(CErrorStr147); - if (!IS_TYPE_ARRAY(ivar->type)) - return; - } - - arraytype = *TYPE_POINTER(ivar->type); - CInit_InitTypeArray(s, s2, &arraytype, ivar->qual, 1); - s->x18 = arraytype.size; - } else { - CInit_InitType(s, s2, ivar->type, ivar->qual, 0); - } - - last_offset = ivar->offset; - if (!(ivar = CInit_FindNextMember(ivar)) || (tclass->mode == CLASS_MODE_UNION && ivar->offset == last_offset)) { - if (flag) { - switch (CInit_ParseNextInit(s2)) { - case Stage3: - tk = lex(); - return; - case Stage2: - CError_Error(CErrorStr147); - return; - default: - CError_Error(CErrorStr130); - return; - } - } - return; - } else { - switch (CInit_ParseNextInit(s2)) { - case Stage1: - case Stage2: - continue; - case Stage3: - if (flag) - tk = lex(); - break; - default: - CError_Error(CErrorStr174); - } - return; - } - } -} - -static void CInit_InitType(CInit_Stuff *s, CInit_Stuff2 *s2, Type *type, UInt32 qual, Boolean errorflag) { - Boolean flag; - - switch (type->type) { - case TYPEVOID: - CError_Error(CErrorStr174); - break; - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - case TYPEBITFIELD: - case TYPEMEMBERPOINTER: - case TYPEPOINTER: - switch (s2->stage) { - case Stage1: - flag = 1; - CInit_ParseNextInit(s2); - break; - case Stage2: - flag = 0; - break; - } - if (s2->stage != Stage2) { - CError_Error(CErrorStr174); - return; - } - - switch (type->type) { - case TYPEINT: - CInit_InitTypeInt(s, s2->expr, TYPE_INTEGRAL(type), qual); - break; - case TYPEFLOAT: - CInit_InitTypeFloat(s, s2->expr, TYPE_INTEGRAL(type), qual); - break; - case TYPEENUM: - CInit_InitTypeEnum(s, s2->expr, TYPE_ENUM(type), qual); - break; - case TYPEPOINTER: - CInit_InitTypePointer(s, s2->expr, TYPE_POINTER(type), qual); - break; - case TYPEMEMBERPOINTER: - CInit_InitTypeMemberPointer(s, s2->expr, TYPE_MEMBER_POINTER(type), qual); - break; - case TYPEBITFIELD: - CInit_InitTypeBitfield(s, s2->expr, TYPE_BITFIELD(type), qual); - break; - default: - CError_FATAL(1542); - } - - if (flag) { - switch (CInit_ParseNextInit(s2)) { - case Stage3: - tk = lex(); - break; - case Stage2: - CError_Error(CErrorStr147); - break; - default: - CError_Error(CErrorStr130); - } - } - break; - case TYPESTRUCT: - CInit_InitTypeStruct(s, s2, TYPE_STRUCT(type), qual, errorflag); - break; - case TYPEARRAY: - CInit_InitTypeArray(s, s2, TYPE_POINTER(type), qual, errorflag); - break; - case TYPECLASS: - CInit_InitTypeClass(s, s2, TYPE_CLASS(type), qual, errorflag); - break; - default: - CError_FATAL(1573); - } -} - -static void CInit_InitData(CInit_Stuff *s, Type *type, UInt32 qual, Boolean flag) { - CInit_Stuff2 s2; - SInt32 size; - CInit_Stuff *tmp; - char *buffer; - - locklheap(); - memclrw(s, sizeof(CInit_Stuff)); - s->x4 = s; - if (type->size == 0) { - if (IS_TYPE_ARRAY(type)) - s->bufferSize = 16 * TYPE_POINTER(type)->target->size; - else - CError_Error(CErrorStr145); - } else { - s->bufferSize = type->size; - } - - s->buffer = lalloc(s->bufferSize); - memset(s->buffer, 0, s->bufferSize); - s->flag = flag; - - s2.stage = Stage0; - s2.x23 = 0; - if (IS_TYPE_VECTOR(type)) { - s2.x23 = 1; - s->flag = 1; - } - if (IS_TYPE_ARRAY(type) && IS_TYPE_VECTOR(TYPE_POINTER(type)->target)) { - s->flag = 1; - } - - s2.type = NULL; - s2.x24 = 0; - CInit_ParseNextInit(&s2); - CInit_InitType(s, &s2, type, qual, 1); - - if ((size = type->size + s->x18)) { - if (s->x0) { - buffer = lalloc(size); - for (tmp = s; tmp; tmp = tmp->x0) { - CError_ASSERT(1647, (tmp->xC + tmp->size) <= size); - memcpy(buffer + tmp->xC, tmp->buffer, tmp->size); - } - s->buffer = buffer; - } - } else { - CError_Error(CErrorStr174); - } - - s->size = size; - s->x0 = NULL; - unlocklheap(); -} - -static ENode *CInit_InitConcat(ENode *a1, ENode *a2, SInt32 offset, Type *type, ENode *a5) { - ENode *r30; - ENode *r28; - ENode *tmp; - - r28 = lalloc(sizeof(ENode)); - *r28 = *a2; - if (offset) - r28 = makediadicnode(r28, intconstnode(TYPE(&stunsignedlong), offset), EADD); - - if (IS_TYPE_BITFIELD(type)) { - tmp = makemonadicnode(r28, EBITFIELD); - tmp->rtype = type; - tmp = makemonadicnode(tmp, EINDIRECT); - tmp->rtype = TYPE_BITFIELD(type)->bitfieldtype; - } else { - tmp = makemonadicnode(r28, EINDIRECT); - tmp->rtype = type; - } - - r30 = makediadicnode(tmp, a5, EASS); - if (!a1) { - return r30; - } else { - tmp = makediadicnode(a1, r30, ECOMMA); - tmp->rtype = r30->rtype; - return tmp; - } -} - -static ENode *CInit_RegisterDtorObject(Type *type, Object *dtor, ENode *objexpr) { - ENode *expr; - - if (copts.no_static_dtors) - return objexpr; - - expr = lalloc(sizeof(ENode)); - expr->type = EFUNCCALL; - expr->cost = 4; - expr->flags = 0; - expr->rtype = CDecl_NewPointerType(type); - expr->data.funccall.funcref = create_objectrefnode(Xgreg_func); - expr->data.funccall.functype = TYPE_FUNC(Xgreg_func->type); - expr->data.funccall.args = lalloc(sizeof(ENodeList)); - expr->data.funccall.args->node = objexpr; - expr->data.funccall.args->next = lalloc(sizeof(ENodeList)); - expr->data.funccall.args->next->node = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1)); - expr->data.funccall.args->next->next = lalloc(sizeof(ENodeList)); - expr->data.funccall.args->next->next->node = create_objectrefnode(CInit_CreateStaticData(CInit_GetRegMemType())); - expr->data.funccall.args->next->next->next = NULL; - - return expr; -} - -static Boolean CInit_ConstructGlobalObject(Object *obj, TypeClass *tclass, ENode *valueexpr, SInt32 offset, Boolean flag) { - NameSpaceObjectList *ctor; - Object *dtor; - ENodeList *list; - ENode *expr; - Boolean ctorflag; - - ctor = CClass_Constructor(tclass); - dtor = CClass_Destructor(tclass); - if (!ctor && !dtor) - return 0; - - if (flag && !ctor && tk == '=' && lookahead() == '{') - return 0; - - if (flag && tk == '(') { - tk = lex(); - list = CExpr_ScanExpressionList(1); - if (tk == ')') - tk = lex(); - else - CError_Error(CErrorStr115); - } else if (valueexpr) { - list = lalloc(sizeof(ENodeList)); - list->node = valueexpr; - list->next = NULL; - } else { - list = NULL; - } - - expr = create_objectrefnode(obj); - if (offset) - expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); - - if (ctor) { - ctorflag = 1; - if (tk == '=') { - ctorflag = 0; - if (list) - CError_Error(CErrorStr174); - - list = lalloc(sizeof(ENodeList)); - list->next = NULL; - tk = lex(); - list->node = conv_assignment_expression(); - } - - expr = CExpr_ConstructObject(tclass, expr, list, 0, 1, 0, 1, ctorflag); - if (expr->rtype->type != TYPEPOINTER) { - CError_Error(CErrorStr174); - return 1; - } - } else { - if (list) - CError_Error(CErrorStr174); - } - - if (dtor) - expr = CInit_RegisterDtorObject(TYPE(tclass), dtor, expr); - - if (cinit_initinfo->x16) - cinit_initinfo->init_expr_register_cb(expr); - else - InitExpr_Register(expr, obj); - - return 1; -} - -static Boolean CInit_ConstructAutoObject(TypeClass *tclass, ENode *expr, SInt32 offset, Boolean flag) { - ENodeList *r30; - ENode *r29; - NameSpaceObjectList *ctor; - Object *dtor; - Boolean r24; - - ctor = CClass_Constructor(tclass); - dtor = CClass_Destructor(tclass); - if (!ctor && !dtor) - return 0; - - if (dtor) - CClass_CheckStaticAccess(NULL, tclass, dtor->access); - - if (flag && !ctor && tk == '=' && lookahead() == '{') - return 0; - - if (flag && tk == '(') { - tk = lex(); - r30 = CExpr_ScanExpressionList(1); - if (tk == ')') - tk = lex(); - else - CError_Error(CErrorStr115); - } else if (expr) { - r30 = lalloc(sizeof(ENodeList)); - r30->node = expr; - r30->next = NULL; - } else { - r30 = NULL; - } - - if (ctor) { - r24 = 1; - if (tk == '=') { - if (r30) - CError_Error(CErrorStr174); - r30 = lalloc(sizeof(ENodeList)); - r30->next = NULL; - tk = lex(); - r30->node = conv_assignment_expression(); - r24 = 0; - } - - if (!dtor) { - r29 = create_objectrefnode(cinit_initinfo->obj1C); - if (offset) - r29 = makediadicnode(r29, intconstnode(TYPE(&stunsignedlong), offset), EADD); - } else { - r29 = cinit_initinfo->register_object_cb(TYPE(tclass), cinit_initinfo->obj1C, offset, 0); - } - - r29 = CExpr_ConstructObject(tclass, r29, r30, 0, 1, 0, 1, r24); - if (!IS_TYPE_POINTER_ONLY(r29->rtype)) { - CError_Error(CErrorStr174); - return 1; - } - r29 = makemonadicnode(r29, EINDIRECT); - r29->rtype = TYPE_POINTER(r29->rtype)->target; - cinit_initinfo->insert_expr_cb(r29); - } else { - if (r30) - CError_Error(CErrorStr174); - if (dtor) - r29 = cinit_initinfo->register_object_cb(TYPE(tclass), cinit_initinfo->obj1C, offset, 0); - cinit_initinfo->insert_expr_cb(r29); - } - - return 1; -} - -static void CInit_ExprPointer(TypePointer *tptr, ENode *expr) { - Object *obj; - CInt64 val; - OLinkList *list; - - if (CInit_RelocInitCheck(expr, &obj, &val, 0)) { - if (obj) { - list = lalloc(sizeof(OLinkList)); - list->next = cinit_initinfo->list; - list->obj = obj; - list->somevalue = CInt64_GetULong(&val); - list->offset = cinit_initinfo->expr_offset; - cinit_initinfo->list = list; - } else { - CMach_InitIntMem(TYPE(&stunsignedlong), val, cinit_initinfo->buffer + cinit_initinfo->expr_offset); - } - } else if (cinit_initinfo->expr_cb) { - cinit_initinfo->expr_cb(TYPE(tptr), expr, 0); - cinit_initinfo->expr_cb_called = 1; - } else { - CError_Error(CErrorStr124); - } - - cinit_initinfo->expr_offset += 4; -} - -static void CInit_ExprInt(TypeIntegral *tint, ENode *expr) { - if (ENODE_IS(expr, EINTCONST)) { - CMach_InitIntMem(TYPE(tint), expr->data.intval, cinit_initinfo->buffer + cinit_initinfo->expr_offset); - } else if (ENODE_IS(expr, ETYPCON) && IS_TYPE_POINTER_ONLY(expr->data.monadic->rtype) && expr->rtype->size == 4 && (copts.cplusplus || !copts.ANSIstrict)) { - CInit_ExprPointer(TYPE_POINTER(expr->data.monadic->rtype), expr->data.monadic); - } else if (cinit_initinfo->expr_cb) { - cinit_initinfo->expr_cb(TYPE(tint), expr, 0); - cinit_initinfo->expr_cb_called = 1; - } else { - CError_Error(CErrorStr124); - } - - cinit_initinfo->expr_offset += tint->size; -} - -static void CInit_ExprFloat(TypeIntegral *tint, ENode *expr) { - if (ENODE_IS(expr, EFLOATCONST)) { - CMach_InitFloatMem(TYPE(tint), expr->data.floatval, cinit_initinfo->buffer + cinit_initinfo->expr_offset); - } else if (cinit_initinfo->expr_cb) { - cinit_initinfo->expr_cb(TYPE(tint), expr, 0); - cinit_initinfo->expr_cb_called = 1; - } else { - CError_Error(CErrorStr124); - } - - cinit_initinfo->expr_offset += tint->size; -} - -static void CInit_ExprEnum(TypeEnum *tenum, ENode *expr) { - if (ENODE_IS(expr, EINTCONST)) { - CMach_InitIntMem(tenum->enumtype, expr->data.intval, cinit_initinfo->buffer + cinit_initinfo->expr_offset); - } else if (cinit_initinfo->expr_cb) { - cinit_initinfo->expr_cb(TYPE(tenum), expr, 0); - cinit_initinfo->expr_cb_called = 1; - } else { - CError_Error(CErrorStr124); - } - - cinit_initinfo->expr_offset += tenum->size; -} - -static void CInit_ExprMemberPointer(TypeMemberPointer *tmptr, ENode *expr) { - if (ENODE_IS(expr, EINTCONST)) { - CMach_InitIntMem(TYPE(&stsignedlong), expr->data.intval, cinit_initinfo->buffer + cinit_initinfo->expr_offset); - } else if (cinit_initinfo->expr_cb) { - cinit_initinfo->expr_cb(TYPE(tmptr), expr, 0); - cinit_initinfo->expr_cb_called = 1; - } else { - CError_Error(CErrorStr124); - } - - cinit_initinfo->expr_offset += tmptr->size; -} - -static void CInit_TypeExpr(Type *type, ENode *expr) { - switch (type->type) { - case TYPEINT: - CInit_ExprInt(TYPE_INTEGRAL(type), expr); - break; - case TYPEFLOAT: - CInit_ExprFloat(TYPE_INTEGRAL(type), expr); - break; - case TYPEENUM: - CInit_ExprEnum(TYPE_ENUM(type), expr); - break; - case TYPEPOINTER: - CInit_ExprPointer(TYPE_POINTER(type), expr); - break; - case TYPEMEMBERPOINTER: - CInit_ExprMemberPointer(TYPE_MEMBER_POINTER(type), expr); - break; - case TYPESTRUCT: - case TYPECLASS: - if (cinit_initinfo->expr_cb) { - cinit_initinfo->expr_cb(type, expr, 0); - cinit_initinfo->expr_cb_called = 1; - } else { - CError_Error(CErrorStr124); - } - break; - case TYPEARRAY: - CError_Error(CErrorStr174); - break; - default: - CError_FATAL(2082); - } -} - -static void CInit_Bitfield(TypeBitfield *tbitfield) { - Boolean r30; - ENode *expr; - ENode myexpr; - - r30 = tk == '{'; - if (r30) - tk = lex(); - - expr = CInit_ParseInitializer(&myexpr); - expr = CExpr_AssignmentPromotion( - expr, - IS_TYPE_ENUM(tbitfield->bitfieldtype) ? TYPE_ENUM(tbitfield->bitfieldtype)->enumtype : tbitfield->bitfieldtype, - 0, - 1); - if (ENODE_IS(expr, EINTCONST)) - CInit_SetBitfield(tbitfield, (UInt8 *) cinit_initinfo->buffer + cinit_initinfo->expr_offset, expr->data.intval); - else - CError_Error(CErrorStr124); - - if (r30) - CInit_CloseInitList(); -} - -static void CInit_Array(TypePointer *tptr, UInt32 qual, Boolean flag) { - SInt32 start; - SInt32 i; - SInt32 targetsize1; - SInt32 targetsize2; - Boolean in_block; - Boolean is_char_ptr; - Boolean needs_construction; - Boolean is_wchar_ptr; - - targetsize1 = tptr->target->size; - targetsize2 = tptr->target->size; - if (!tptr->target->size) { - if (!IS_TYPE_ARRAY(tptr->target)) { - CError_Error(CErrorStr145); - return; - } - targetsize1 = tptr->target->size; - targetsize2 = tptr->target->size; - if (!tptr->target->size) { - CError_Error(CErrorStr145); - return; - } - } - - is_char_ptr = IS_TYPE_INT(tptr->target) && (tptr->target->size == 1); - is_wchar_ptr = IS_TYPE_INT(tptr->target) && (tptr->target->size == stwchar.size); - - in_block = 1; - if (flag && !(tk == TK_STRING && is_char_ptr) && !(tk == TK_STRING_WIDE && is_wchar_ptr)) { - if (tk != '{') { - CError_ErrorSkip(CErrorStr135); - return; - } - tk = lex(); - } else { - if (tk == '{') - tk = lex(); - else - in_block = 0; - } - - if ((tk == TK_STRING && is_char_ptr) || (tk == TK_STRING_WIDE && is_wchar_ptr)) { - if (tptr->size) { - if (tksize > tptr->size) { - if (copts.cplusplus || (tksize - (is_wchar_ptr ? stwchar.size : 1)) > tptr->size) - CError_Error(CErrorStr147); - tksize = tptr->size; - } - memcpy(cinit_initinfo->buffer + cinit_initinfo->expr_offset, tkstring, tksize); - } else { - tptr->size = tksize; - CInit_SetData(tkstring, cinit_initinfo->expr_offset, tptr->size); - } - cinit_initinfo->expr_offset += tptr->size; - tk = lex(); - if (in_block) - CInit_CloseInitList(); - return; - } - - if (IS_TYPE_CLASS(tptr->target) && CInit_ClassNeedsConstruction(TYPE_CLASS(tptr->target))) - needs_construction = 1; - else - needs_construction = 0; - - start = cinit_initinfo->expr_offset; - i = 0; - while (1) { - if (tk == '}') { - innerloop: - if (tptr->size) { - if (needs_construction) { - while (tptr->size > (i * targetsize1)) { - cinit_initinfo->expr_offset = start + i * targetsize2; - if (cinit_initinfo->expr_cb) { - cinit_initinfo->expr_cb(tptr->target, NULL, 1); - cinit_initinfo->expr_cb_called = 1; - } else { - CError_Error(CErrorStr174); - } - i++; - } - } - } else { - tptr->size = i * targetsize1; - } - cinit_initinfo->expr_offset = start + tptr->size; - if (in_block) - tk = lex(); - return; - } - - if (!tptr->size) { - cinit_initinfo->expr_offset = start + i * targetsize2; - CInit_SetData(NULL, cinit_initinfo->expr_offset, targetsize2); - if (needs_construction) { - if (cinit_initinfo->expr_cb) { - cinit_initinfo->expr_cb(tptr->target, conv_assignment_expression(), 1); - cinit_initinfo->expr_cb_called = 1; - } else { - CError_Error(CErrorStr174); - } - } else { - CInit_Type(tptr->target, qual, 0); - } - } else { - if (tptr->size <= i * targetsize1) { - i--; - CError_Error(CErrorStr147); - } - - cinit_initinfo->expr_offset = start + i * targetsize2; - if (needs_construction) { - if (cinit_initinfo->expr_cb) { - cinit_initinfo->expr_cb(tptr->target, conv_assignment_expression(), 1); - cinit_initinfo->expr_cb_called = 1; - } else { - CError_Error(CErrorStr174); - } - } else { - CInit_Type(tptr->target, qual, 0); - } - - if (!in_block) { - if (tptr->size <= (i + 1) * targetsize1) - return; - } - } - - if (tk != '}') { - if (tk != ',') { - CError_ErrorSkip(CErrorStr121); - in_block = 0; - i++; - goto innerloop; - } - tk = lex(); - } - i++; - } -} - -static void CInit_Struct(TypeStruct *tstruct, Boolean flag) { - StructMember *member; - SInt32 start; - Boolean in_block; - - if (!(member = tstruct->members)) { - CError_Error(CErrorStr145); - return; - } - - if (tstruct->stype == STRUCT_TYPE_UNION) { - if (tk == '{') { - tk = lex(); - CInit_Type(member->type, member->qual, 0); - if (tk == '}') - tk = lex(); - } else { - CInit_Type(member->type, member->qual, 0); - } - return; - } - - if (IS_TYPE_VECTOR(tstruct) && tk != '{') { - CInit_TypeExpr(TYPE(tstruct), CExpr_AssignmentPromotion(conv_assignment_expression(), TYPE(tstruct), 0, 1)); - return; - } - - if (tk != '{') { - if (flag) - CError_ErrorSkip(CErrorStr135); - in_block = 0; - } else { - in_block = 1; - tk = lex(); - } - - start = cinit_initinfo->expr_offset; - while (1) { - if (tk == '}') - break; - - cinit_initinfo->expr_offset = start + member->offset; - if (!member->type->size && IS_TYPE_ARRAY(member->type)) { - CError_Error(CErrorStr147); - break; - } - - CInit_Type(member->type, member->qual, 0); - if (tk == '}') - break; - - if (tk != ',') { - CError_Error(CErrorStr121); - break; - } - - do { - member = member->next; - } while (member && (member->qual & Q_WEAK)); - - if (!member) { - if (!in_block) - break; - if ((tk = lex()) != '}') { - CError_Error(CErrorStr147); - break; - } - } else { - tk = lex(); - } - } - - cinit_initinfo->expr_offset = start + tstruct->size; - if (tk == '}' && in_block) - tk = lex(); -} - -static void CInit_Class(TypeClass *tclass, Boolean flag) { - ObjMemberVar *ivar; - SInt32 start; - Boolean in_block; - - if (tk == '{') { - in_block = 1; - tk = lex(); - } else { - in_block = 0; - } - - if (tclass->bases || tclass->vtable) { - CError_Error(CErrorStr174); - return; - } - - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - if (ivar->access != ACCESSPUBLIC) - break; - } - - if (!ivar && !CClass_Constructor(tclass) && (!CClass_Destructor(tclass) || in_block)) { - if ((ivar = tclass->ivars)) { - start = cinit_initinfo->expr_offset; - while (1) { - if (tk == '}') - break; - - if (!ivar->type->size && IS_TYPE_ARRAY(ivar->type)) { - CError_Error(CErrorStr147); - break; - } - - cinit_initinfo->expr_offset = start + ivar->offset; - CInit_Type(ivar->type, ivar->qual, 0); - - if (tk == '}') - break; - - if (tk != ',') { - CError_Error(CErrorStr121); - break; - } - - do { - ivar = ivar->next; - } while (ivar && ivar->anonunion); - - if (!ivar) { - if (!in_block) - break; - if ((tk = lex()) != '}') { - CError_Error(CErrorStr147); - break; - } - } else { - tk = lex(); - } - } - } else { - if (in_block && tk != '}') - CError_Error(CErrorStr147); - } - } else { - if (in_block) - CError_Error(CErrorStr174); - CInit_TypeExpr(TYPE(tclass), CExpr_AssignmentPromotion(conv_assignment_expression(), TYPE(tclass), 0, 1)); - } - - cinit_initinfo->expr_offset = start + tclass->size; - if (tk == '}' && in_block) - tk = lex(); -} - -static void CInit_Type(Type *type, UInt32 qual, Boolean flag) { - ENode *expr; - ENode myexpr; - - switch (type->type) { - case TYPEVOID: - CError_Error(CErrorStr174); - break; - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - case TYPEPOINTER: - case TYPEMEMBERPOINTER: - if (tk == '{') { - tk = lex(); - expr = CInit_ParseInitializer(&myexpr); - expr = CExpr_AssignmentPromotion(expr, type, qual & (Q_CONST | Q_VOLATILE), 1); - CInit_CloseInitList(); - } else { - expr = CInit_ParseInitializer(&myexpr); - expr = CExpr_AssignmentPromotion(expr, type, qual & (Q_CONST | Q_VOLATILE), 1); - } - CInit_TypeExpr(type, expr); - break; - case TYPEBITFIELD: - CInit_Bitfield(TYPE_BITFIELD(type)); - break; - case TYPEARRAY: - CInit_Array(TYPE_POINTER(type), qual, flag); - break; - case TYPESTRUCT: - CInit_Struct(TYPE_STRUCT(type), flag); - break; - case TYPECLASS: - CInit_Class(TYPE_CLASS(type), flag); - break; - default: - CError_FATAL(2482); - } -} - -static void CInit_GlobalStaticInit(Type *type, ENode *valueexpr, Boolean flag) { - ENode *expr; - ENode *tmp; - - cinit_initinfo->x15 = 1; - if (flag) { - CInit_ConstructGlobalObject(cinit_initinfo->obj, TYPE_CLASS(type), valueexpr, cinit_initinfo->expr_offset, 0); - } else { - expr = create_objectrefnode(cinit_initinfo->obj); - if (!IS_TYPE_POINTER_ONLY(expr->rtype)) { - CError_Error(CErrorStr174); - return; - } - TYPE_POINTER(expr->rtype)->target = type; - - if (cinit_initinfo->expr_offset) - expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), cinit_initinfo->expr_offset), EADD); - - tmp = makemonadicnode(expr, EINDIRECT); - tmp->rtype = type; - expr = makediadicnode(tmp, valueexpr, EASS); - if (cinit_initinfo->x16) - cinit_initinfo->init_expr_register_cb(expr); - else - InitExpr_Register(expr, cinit_initinfo->obj); - } -} - -static void CInit_AutoInit(Type *type, ENode *valueexpr, Boolean flag) { - ENode *expr; - ENode *tmp; - Type *copy; - SInt32 size; - - if (flag) { - CInit_ConstructAutoObject(TYPE_CLASS(type), valueexpr, cinit_initinfo->expr_offset, 0); - } else { - if (IS_TYPE_ARRAY(type) && (type->size & 1)) { - copy = galloc(sizeof(TypePointer)); - *TYPE_POINTER(copy) = *TYPE_POINTER(type); - type = copy; - copy->size++; - } - expr = create_objectrefnode(cinit_initinfo->obj1C); - if (!IS_TYPE_POINTER_ONLY(expr->rtype)) { - CError_Error(CErrorStr174); - return; - } - TYPE_POINTER(expr->rtype)->target = type; - - if (cinit_initinfo->expr_offset) - expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), cinit_initinfo->expr_offset), EADD); - - tmp = makemonadicnode(expr, EINDIRECT); - tmp->rtype = type; - expr = makediadicnode(tmp, valueexpr, EASS); - if (!copts.cplusplus) - CError_Error(CErrorStr124); - cinit_initinfo->insert_expr_cb(expr); - } -} - -static SInt32 CInit_AdjustObjectDataSize(Object *obj) { - if (obj->type->size <= 1) - return obj->type->size; - if (obj->type->size & 1) - return obj->type->size + 1; - else - return obj->type->size; -} - -static ENode *CInit_GenericData(Object *obj, Type *type, UInt32 qual, ExprCB expr_cb, Boolean flag) { - Object *r31; - ENode *expr; - ENode *tmpexpr; - Type *inner; - Type *copy; - SInt32 size; - Boolean lastflag; - SInt16 cv; - - cinit_initinfo->expr_cb = expr_cb; - expr = NULL; - - if (tk == '(') { - if (IS_TYPE_ARRAY(type)) - CError_Error(CErrorStr174); - tk = lex(); - expr = CExpr_AssignmentPromotion(assignment_expression(), type, qual, 1); - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - goto jump_ahead; - } - - tk = lex(); - switch (type->type) { - case TYPECLASS: - if (tk == '{' && CClass_Constructor(TYPE_CLASS(type))) - CError_Error(CErrorStr174); - case TYPESTRUCT: - if (tk != '{') - goto generic_type; - case TYPEARRAY: - if (!obj) { - if (IS_TYPE_ARRAY(type)) { - inner = type; - while (IS_TYPE_ARRAY(inner)) - inner = TYPE_POINTER(inner)->target; - - if (IS_TYPE_CLASS(inner) && CInit_ClassNeedsConstruction(TYPE_CLASS(inner))) { - CInit_SetupInitInfoBuffer(type); - cinit_initinfo->obj = cinit_initinfo->obj1C; - CInit_Type(type, cinit_initinfo->obj->qual, 1); - return 0; - } - if (type->size & 1) { - copy = galloc(sizeof(TypePointer)); - *TYPE_POINTER(copy) = *TYPE_POINTER(type); - type = copy; - type->size++; - } - } - - obj = CInit_CreateStaticDataObject(type, qual, NULL); - cinit_initinfo->obj = obj; - expr = create_objectnode(obj); - cinit_initinfo->obj1C = obj; - } - CInit_SetupInitInfoBuffer(type); - CInit_Type(type, obj->qual, 1); - CError_ASSERT(2639, obj->type->size == (size = cinit_initinfo->size)); - if (cinit_initinfo->list || !CInit_IsAllZero(cinit_initinfo->buffer, size)) { - CInit_AdjustObjectDataSize(obj); - CInit_DeclareData(obj, cinit_initinfo->buffer, cinit_initinfo->list, obj->type->size); - } else { - CInit_AdjustObjectDataSize(obj); - CInit_DeclareData(obj, NULL, NULL, obj->type->size); - } - return expr; - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - case TYPEPOINTER: - case TYPEMEMBERPOINTER: - generic_type: - if (obj) - cv = obj->qual & Q_CV; - else - cv = cinit_initinfo->obj1C->qual & Q_CV; - - if (tk == '{') { - tk = lex(); - expr = assignment_expression(); - CInit_CloseInitList(); - } else { - expr = assignment_expression(); - } - expr = CExpr_AssignmentPromotion(expr, type, cv, 1); - jump_ahead: - if (obj == NULL) - r31 = cinit_initinfo->obj1C; - else - r31 = obj; - - if (is_const_object(r31)) { - switch (r31->type->type) { - case TYPEINT: - case TYPEENUM: - if (ENODE_IS(expr, EINTCONST)) { - r31->u.data.u.intconst = expr->data.intval; - goto common_8068C; - } - break; - case TYPEFLOAT: - if (ENODE_IS(expr, EFLOATCONST)) { - Float fl; - r31->u.data.u.floatconst = galloc(sizeof(Float)); - fl = CMach_CalcFloatConvert(r31->type, expr->data.floatval); - *r31->u.data.u.floatconst = fl; - goto common_8068C; - } - break; - case TYPEPOINTER: - tmpexpr = expr; - while (ENODE_IS(tmpexpr, ETYPCON)) - tmpexpr = tmpexpr->data.monadic; - if (!ENODE_IS(tmpexpr, EINTCONST)) - break; - r31->u.data.u.intconst = tmpexpr->data.intval; - common_8068C: - r31->qual |= Q_INLINE_DATA; - if (!obj) { - r31->sclass = TK_STATIC; - r31->datatype = DDATA; - r31->u.data.linkname = CParser_AppendUniqueName(r31->name->name); - } else if (r31->sclass != TK_STATIC || (r31->flags & OBJECT_FLAGS_2)) { - CInit_ExportConst(r31); - } - return NULL; - } - } - - if (!obj || (flag && copts.cplusplus)) { - if (obj) { - IsCompleteType(obj->type); - CError_ASSERT(2747, obj->type->size == type->size); - CInit_DeclareData(obj, NULL, NULL, obj->type->size); - } - return expr; - } - - CInit_SetupInitInfoBuffer(type); - CInit_TypeExpr(type, expr); - CError_ASSERT(2756, obj->type->size == cinit_initinfo->size); - - IsCompleteType(obj->type); - CInit_AdjustObjectDataSize(obj); - lastflag = !cinit_initinfo->x15 && is_const_object(r31); - if (cinit_initinfo->list || !CInit_IsAllZero(cinit_initinfo->buffer, obj->type->size)) { - if (lastflag) - CInit_DeclareReadOnlyData(obj, cinit_initinfo->buffer, cinit_initinfo->list, obj->type->size); - else - CInit_DeclareData(obj, cinit_initinfo->buffer, cinit_initinfo->list, obj->type->size); - } else { - if (lastflag) - CInit_DeclareReadOnlyData(obj, NULL, NULL, obj->type->size); - else - CInit_DeclareData(obj, NULL, NULL, obj->type->size); - } - break; - - default: - CError_FATAL(2776); - } - - return NULL; -} - -void CInit_ExportConst(Object *obj) { - char buffer[64]; - - if (obj->flags & OBJECT_DEFINED) - return; - - switch (obj->type->type) { - case TYPEINT: - CMach_InitIntMem(obj->type, obj->u.data.u.intconst, buffer); - break; - case TYPEENUM: - CMach_InitIntMem(TYPE_ENUM(obj->type)->enumtype, obj->u.data.u.intconst, buffer); - break; - case TYPEPOINTER: - CMach_InitIntMem(TYPE(&stunsignedlong), obj->u.data.u.intconst, buffer); - break; - case TYPEFLOAT: - CMach_InitFloatMem(obj->type, *obj->u.data.u.floatconst, buffer); - break; - default: - CError_FATAL(2807); - } - - if (is_const_object(obj)) - CInit_DeclareReadOnlyData(obj, buffer, NULL, obj->type->size); - else - CInit_DeclareData(obj, buffer, NULL, obj->type->size); -} - -static ENode *CInit_ClassInitLoopCallBack(ENode *expr) { - return CExpr_ConstructObject(cinit_loop_class, expr, NULL, 0, 1, 0, 1, 1); -} - -Statement *CInit_ConstructClassArray(Statement *stmt, TypeClass *tclass, Object *ctor, Object *dtor, ENode *firstarg, SInt32 count) { - ENode *dtor_expr; - - if (stmt) - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - else - stmt = CFunc_AppendStatement(ST_EXPRESSION); - - if (dtor) - dtor_expr = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1)); - else - dtor_expr = nullnode(); - - stmt->expr = CExpr_FuncCallSix( - carr_func, - firstarg, - create_objectrefnode(ctor), - dtor_expr, - intconstnode(TYPE(&stunsignedlong), tclass->size), - intconstnode(TYPE(&stunsignedlong), count), - NULL - ); - - return stmt; -} - -static void CInit_InitializeClassArray(Object *obj, TypeClass *tclass, Boolean flag) { - Object *ctor; - Object *dtor; - SInt32 count; - SInt32 i; - ENode *expr; - SInt32 offset; - ENode *dtor_expr; - Statement *stmt; - TypeFunc *tfunc; - Object *funcobj; - - dtor = CClass_Destructor(tclass); - count = obj->type->size / tclass->size; - if (CClass_Constructor(tclass)) { - ctor = CClass_DefaultConstructor(tclass); - if (!ctor) { - ctor = CClass_DummyDefaultConstructor(tclass); - if (!ctor) { - CError_Error(CErrorStr203); - return; - } - } - } else { - ctor = NULL; - } - - if (count <= 1 || (!flag && count <= 8)) { - if (flag) { - for (i = 0; i < count; i++) { - CInit_ConstructGlobalObject(obj, tclass, NULL, i * tclass->size, 0); - } - } else { - for (i = 0; i < count; i++) { - offset = i * tclass->size; - expr = create_objectrefnode(obj); - if (offset) - expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); - if (ctor) - expr = CExpr_ConstructObject(tclass, expr, NULL, 0, 1, 0, 1, 1); - cinit_initinfo->insert_expr_cb(expr); - if (dtor) - CExcept_RegisterDestructorObject(obj, offset, dtor, 1); - } - if (dtor) { - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = nullnode(); - } - } - } else { - if (ctor) { - if (!flag && !dtor) { - CInit_ConstructClassArray(NULL, tclass, ctor, dtor, create_objectrefnode(obj), count); - expr = nullnode(); - } else { - if (dtor) - dtor_expr = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1)); - else - dtor_expr = nullnode(); - expr = CExpr_FuncCallSix( - carr_func, - create_objectrefnode(obj), - create_objectrefnode(ctor), - dtor_expr, - intconstnode(TYPE(&stunsignedlong), tclass->size), - intconstnode(TYPE(&stunsignedlong), count), - NULL - ); - } - } else { - expr = nullnode(); - } - - if (flag) { - if (dtor && !copts.no_static_dtors) { - tfunc = galloc(sizeof(TypeFunc)); - memclrw(tfunc, sizeof(TypeFunc)); - tfunc->type = TYPEFUNC; - tfunc->functype = &stvoid; - CDecl_SetFuncFlags(tfunc, 1); - - funcobj = CParser_NewCompilerDefFunctionObject(); - funcobj->name = CParser_AppendUniqueName("__arraydtor"); - funcobj->type = TYPE(tfunc); - funcobj->sclass = TK_STATIC; - funcobj->qual = Q_INLINE; - - CParser_RegisterSingleExprFunction(funcobj, funccallexpr( - darr_func, - create_objectrefnode(obj), - create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1)), - intconstnode(TYPE(&stsignedlong), tclass->size), - intconstnode(TYPE(&stsignedlong), count) - )); - - expr = makediadicnode(expr, nullnode(), ECOMMA); - expr->rtype = TYPE(&void_ptr); - - expr = funccallexpr( - Xgreg_func, - expr, - create_objectrefnode(funcobj), - create_objectrefnode(CInit_CreateStaticData(CInit_GetRegMemType())), - NULL - ); - } - if (cinit_initinfo->x16) - cinit_initinfo->init_expr_register_cb(expr); - else - InitExpr_Register(expr, obj); - } else { - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = expr; - if (dtor) { - CExcept_RegisterLocalArray(stmt, obj, dtor, count, tclass->size); - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = nullnode(); - } - } - } -} - -static ENode *CInit_AutoTempNode(Type *type, Boolean flag) { - ENode *node; - node = CExpr_NewETEMPNode(type, 0); - if (IS_TYPE_CLASS(type) && CClass_Destructor(TYPE_CLASS(type))) - node->data.temp.needs_dtor = 1; - return node; -} - -static ENode *CInit_GlobalTempNode(Type *type, Boolean flag) { - Object *dtor; - ENode *node; - ENode *funcnode; - - node = create_objectrefnode(CInit_CreateStaticData(type)); - if (IS_TYPE_CLASS(type) && (dtor = CClass_Destructor(TYPE_CLASS(type))) && !copts.no_static_dtors) { - if (flag) - CError_Error(CErrorStr190); - - funcnode = galloc(sizeof(ENode)); - funcnode->type = EFUNCCALL; - funcnode->cost = 200; - funcnode->flags = 0; - funcnode->rtype = CDecl_NewPointerType(type); - funcnode->data.funccall.funcref = create_objectrefnode(Xgreg_func); - funcnode->data.funccall.functype = TYPE_FUNC(Xgreg_func->type); - funcnode->data.funccall.args = lalloc(sizeof(ENodeList)); - funcnode->data.funccall.args->node = node; - funcnode->data.funccall.args->next = lalloc(sizeof(ENodeList)); - funcnode->data.funccall.args->next->node = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1)); - funcnode->data.funccall.args->next->next = lalloc(sizeof(ENodeList)); - funcnode->data.funccall.args->next->next->node = create_objectrefnode(CInit_CreateStaticData(CInit_GetRegMemType()));; - funcnode->data.funccall.args->next->next->next = NULL; - node = funcnode; - } - return node; -} - -static void CInit_RefInit(Type *type, ENode *expr, Boolean flag) { - ENode *objexpr; - - objexpr = create_objectrefnode(cinit_initinfo->obj); - if (!IS_TYPE_POINTER_ONLY(objexpr->rtype)) { - CError_Error(CErrorStr174); - return; - } - TYPE_POINTER(objexpr->rtype)->target = type; - - if (cinit_initinfo->expr_offset) - objexpr = makediadicnode(objexpr, intconstnode(TYPE(&stunsignedlong), cinit_initinfo->expr_offset), EADD); - - objexpr = makemonadicnode(objexpr, EINDIRECT); - objexpr->rtype = type; - - expr = makediadicnode(objexpr, expr, EASS); - if (cinit_initinfo->x16) - cinit_initinfo->init_expr_register_cb(expr); - else - InitExpr_Register(expr, cinit_initinfo->obj); -} - -static Boolean CInit_IsDtorTemp(ENode *expr) { - return ENODE_IS(expr, ETEMP) && expr->data.temp.needs_dtor; -} - -static void CInit_FindDtorTemp(ENode *expr) { - ENodeList *list; - - while (ENODE_IS(expr, ECOMMA)) - expr = expr->data.diadic.right; - - if (IS_TYPE_POINTER_ONLY(expr->rtype) && IS_TYPE_CLASS(TYPE_POINTER(expr->rtype)->target)) { - switch (expr->type) { - case ETYPCON: - CInit_FindDtorTemp(expr->data.monadic); - break; - case EADD: - case ESUB: - CInit_FindDtorTemp(expr->data.diadic.left); - CInit_FindDtorTemp(expr->data.diadic.right); - break; - case EFUNCCALL: - case EFUNCCALLP: - if ((list = expr->data.funccall.args)) { - if (CInit_IsDtorTemp(list->node) || ((list = list->next) && CInit_IsDtorTemp(list->node))) { - if (!cinit_fdtnode) - cinit_fdtnode = list; - else - cinit_fdtambig = 1; - } - } - break; - } - } -} - -static void CInit_RefTempTransform(Type *type, ENode *expr) { - Object *obj; - - CError_ASSERT(3164, IS_TYPE_POINTER_ONLY(type)); - - if (IS_TYPE_CLASS(TYPE_POINTER(type)->target)) { - cinit_fdtnode = NULL; - cinit_fdtambig = 0; - CInit_FindDtorTemp(expr); - if (cinit_fdtnode) { - CError_ASSERT(3172, !cinit_fdtambig); - obj = create_temp_object(cinit_fdtnode->node->data.temp.type); - cinit_initinfo->register_object_cb(cinit_fdtnode->node->data.temp.type, obj, 0, 0); - cinit_fdtnode->node = create_objectrefnode(obj); - } - } -} - -static Boolean CInit_InitReference(Object *obj, Boolean flag) { - ENode *expr; - - if (tk == '=') { - cinit_tempnodefunc = flag ? CInit_AutoTempNode : CInit_GlobalTempNode; - tk = lex(); - expr = CExpr_AssignmentPromotion(assignment_expression(), obj->type, obj->qual & (Q_CONST | Q_VOLATILE), 1); - cinit_tempnodefunc = NULL; - - if (flag) { - CInit_RefTempTransform(obj->type, expr); - expr = makediadicnode(create_objectnode2(obj), expr, EASS); - cinit_initinfo->insert_expr_cb(expr); - } else { - cinit_initinfo->expr_cb = CInit_RefInit; - CInit_SetupInitInfoBuffer(obj->type); - CInit_ExprPointer(TYPE_POINTER(obj->type), expr); - CError_ASSERT(3213, obj->type->size == cinit_initinfo->size); - - if (cinit_initinfo->list || !CInit_IsAllZero(cinit_initinfo->buffer, obj->type->size)) { - IsCompleteType(obj->type); - CInit_AdjustObjectDataSize(obj); - CInit_DeclareData(obj, cinit_initinfo->buffer, cinit_initinfo->list, obj->type->size); - } else { - IsCompleteType(obj->type); - CInit_AdjustObjectDataSize(obj); - CInit_DeclareData(obj, NULL, NULL, obj->type->size); - } - } - - return 1; - } - - return 0; -} - -ENode *CInit_AutoObject(Object *obj, Type *type, UInt32 qual) { - CInit_Stuff s; - CInit_1C *entry; - ENode *expr; - ENode *indirect_expr; - ENode *obj_expr; - ENode *const_expr; - Type *newtype; - Object *newobj; - - CInit_InitData(&s, type, qual, copts.cplusplus || copts.gcc_extensions || copts.c9x || !obj); - if (!obj && !cscope_currentfunc) { - obj = CParser_NewCompilerDefDataObject(); - obj->name = CParser_GetUniqueName(); - obj->type = type; - obj->qual = qual; - obj->sclass = TK_STATIC; - CScope_AddGlobalObject(obj); - } - - if (IS_TYPE_VECTOR(type) && !s.x1C) { - if (obj) - obj_expr = create_objectrefnode(obj); - else - obj_expr = CExpr_NewETEMPNode(type, 1); - - const_expr = CExpr_NewENode(EVECTOR128CONST); - const_expr->rtype = type; - const_expr->data.vector128val = *((MWVector128 *) s.buffer); - - indirect_expr = makemonadicnode(obj_expr, EINDIRECT); - indirect_expr->rtype = type; - - expr = makediadicnode(indirect_expr, const_expr, EASS); - if (!obj) { - ENode *tmp = lalloc(sizeof(ENode)); - *tmp = *obj_expr; - tmp = makemonadicnode(tmp, EINDIRECT); - tmp->rtype = type; - tmp->flags = qual & ENODE_FLAG_QUALS; - expr = makecommaexpression(expr, tmp); - } - return expr; - } - - if (s.x18) { - type = CDecl_NewStructType(type->size + s.x18, CMach_GetTypeAlign(type)); - if (obj) - obj->type = type; - } - - if (obj) - obj_expr = create_objectrefnode(obj); - else - obj_expr = CExpr_NewETEMPNode(type, 1); - - newtype = type; - if (IS_TYPE_ARRAY(type)) - newtype = CDecl_NewStructType(type->size, CMach_GetTypeAlign(type)); - newobj = CInit_CreateStaticDataObject(newtype, 0, NULL); - if (s.list || !CInit_IsAllZero(s.buffer, s.size)) - CInit_DeclareReadOnlyData(newobj, s.buffer, s.list, s.size); - else - CInit_DeclareReadOnlyData(newobj, NULL, NULL, s.size); - - indirect_expr = makemonadicnode(obj_expr, EINDIRECT); - indirect_expr->rtype = newtype; - expr = makediadicnode(indirect_expr, create_objectnode(newobj), EASS); - - for (entry = s.x1C; entry; entry = entry->next) { - expr = CInit_InitConcat(expr, obj_expr, entry->offset, entry->type, entry->expr); - } - - if (!obj) { - ENode *tmp = lalloc(sizeof(ENode)); - *tmp = *obj_expr; - tmp = makemonadicnode(tmp, EINDIRECT); - tmp->rtype = type; - tmp->flags = qual & ENODE_FLAG_QUALS; - expr = makecommaexpression(expr, tmp); - } else if (IS_TYPE_ARRAY(type)) { - expr = makecommaexpression(expr, create_objectnode(obj)); - } - - return expr; -} - -static void CInit_GlobalObject(Object *obj) { - CInit_Stuff s; - CInit_1C *entry; - ENode *obj_expr; - ENode *expr; - - CInit_InitData(&s, obj->type, obj->qual, copts.cplusplus); - obj_expr = create_objectrefnode(obj); - - IsCompleteType(obj->type); - - if (!s.x1C && is_const_object(obj)) - CInit_DeclareReadOnlyData(obj, s.buffer, s.list, s.size); - else - CInit_DeclareData(obj, s.buffer, s.list, s.size); - - if (s.x1C) { - entry = s.x1C; - expr = NULL; - while (entry) { - if (!ENODE_IS(entry->expr, EVECTOR128CONST)) - expr = CInit_InitConcat(expr, obj_expr, entry->offset, entry->type, entry->expr); - entry = entry->next; - } - - if (expr) - InitExpr_Register(expr, obj); - } -} - -void CInit_InitializeAutoData(Object *obj, InsertExprCB insert_cb, RegisterObjectCB register_cb) { - ENode *expr; - Type *type; - InitInfo initinfo; - - if (CInit_IsSimpleStructArrayInit(obj->type)) { - if (tk == '=' || (tk == '(' && copts.cplusplus)) { - if (tk == '(') { - tk = lex(); - expr = conv_assignment_expression(); - if (tk != ')') - CError_Error(CErrorStr115); - tk = lex(); - } else if (tk == '=' && ((tk = lex()) == '{' || IS_TYPE_ARRAY(obj->type))) { - insert_cb(CInit_AutoObject(obj, obj->type, obj->qual)); - return; - } else { - expr = conv_assignment_expression(); - } - expr = CExpr_AssignmentPromotion(expr, obj->type, obj->qual & (Q_CONST | Q_VOLATILE), 1); - insert_cb(makediadicnode(create_objectnode2(obj), expr, EASS)); - } else if (copts.cplusplus && is_const_object(obj)) { - CError_Error(CErrorStr224); - } - - return; - } - - CInit_SetupInitInfo(&initinfo, obj); - initinfo.obj1C = obj; - initinfo.insert_expr_cb = insert_cb; - initinfo.register_object_cb = register_cb; - - if (IS_TYPE_CLASS(obj->type) && CInit_ConstructAutoObject(TYPE_CLASS(obj->type), NULL, 0, 1)) { - CInit_CleanupInitInfo(&initinfo); - return; - } - - if (IS_TYPE_REFERENCE(obj->type) && CInit_InitReference(obj, 1)) { - CInit_CleanupInitInfo(&initinfo); - return; - } - - if (tk != '=' && (tk != '(' || !copts.cplusplus)) { - if (IS_TYPE_ARRAY(obj->type)) { - type = obj->type; - while (IS_TYPE_ARRAY(type)) - type = TYPE_POINTER(type)->target; - if (IS_TYPE_CLASS(type)) { - if (CInit_ClassNeedsConstruction(TYPE_CLASS(type))) { - CInit_InitializeClassArray(obj, TYPE_CLASS(type), 0); - CInit_CleanupInitInfo(&initinfo); - return; - } - CFunc_CheckClassCtors(TYPE_CLASS(type)); - } - } - - if (IS_TYPE_CLASS(obj->type)) - CFunc_CheckClassCtors(TYPE_CLASS(obj->type)); - - if ((IS_TYPE_REFERENCE(obj->type) || is_const_object(obj)) && copts.cplusplus) - CError_Error(CErrorStr224); - } else { - if (obj->type->size || IS_TYPE_ARRAY(obj->type)) { - if ((expr = CInit_GenericData(NULL, obj->type, obj->qual, CInit_AutoInit, 0))) - insert_cb(makediadicnode(create_objectnode2(obj), expr, EASS)); - } else { - CError_Error(CErrorStr145); - } - } - - if (IS_TYPE_CLASS(obj->type) && CClass_Destructor(TYPE_CLASS(obj->type))) - register_cb(obj->type, obj, 0, 0); - - CInit_CleanupInitInfo(&initinfo); -} - -void CInit_InitializeStaticData(Object *obj, InitExprRegisterCB cb) { - ENode *expr; - Type *type; - InitInfo initinfo; - CInit_Stuff s; - CInit_1C *entry; - ENode *obj_expr; - - if (CInit_IsSimpleStructArrayInit(obj->type)) { - if (tk == '=' || (tk == '(' && copts.cplusplus)) { - if (tk == '=') - tk = lex(); - CInit_InitData(&s, obj->type, obj->qual, copts.cplusplus); - - IsCompleteType(obj->type); - - if (!s.x1C && is_const_object(obj)) - CInit_DeclareReadOnlyData(obj, s.buffer, s.list, s.size); - else - CInit_DeclareData(obj, s.buffer, s.list, s.size); - - if (s.x1C) { - obj_expr = create_objectrefnode(obj); - entry = s.x1C; - expr = NULL; - while (entry) { - expr = CInit_InitConcat(expr, obj_expr, entry->offset, entry->type, entry->expr); - entry = entry->next; - } - cb(expr); - } - } else { - if (copts.cplusplus && is_const_object(obj)) - CError_Error(CErrorStr224); - - if (is_const_object(obj)) - CInit_DeclareReadOnlyData(obj, NULL, NULL, obj->type->size); - else - CInit_DeclareData(obj, NULL, NULL, obj->type->size); - } - return; - } - - CInit_SetupInitInfo(&initinfo, obj); - initinfo.x16 = 1; - initinfo.init_expr_register_cb = cb; - - if (IS_TYPE_CLASS(obj->type) && CInit_ConstructGlobalObject(obj, TYPE_CLASS(obj->type), NULL, 0, 1)) { - IsCompleteType(obj->type); - CInit_DeclareData(obj, NULL, NULL, obj->type->size); - CInit_CleanupInitInfo(&initinfo); - return; - } - - if (IS_TYPE_REFERENCE(obj->type) && CInit_InitReference(obj, 0)) { - CInit_CleanupInitInfo(&initinfo); - return; - } - - if (tk != '=' && (tk != '(' || !copts.cplusplus)) { - if (IsCompleteType(obj->type)) - CInit_DeclareData(obj, NULL, NULL, obj->type->size); - - if (IS_TYPE_ARRAY(obj->type)) { - type = obj->type; - while (IS_TYPE_ARRAY(type)) - type = TYPE_POINTER(type)->target; - if (IS_TYPE_CLASS(type)) { - if (CInit_ClassNeedsConstruction(TYPE_CLASS(type))) { - CInit_InitializeClassArray(obj, TYPE_CLASS(type), 1); - CInit_CleanupInitInfo(&initinfo); - return; - } - CFunc_CheckClassCtors(TYPE_CLASS(type)); - } - } - - if (IS_TYPE_CLASS(obj->type)) - CFunc_CheckClassCtors(TYPE_CLASS(obj->type)); - - if ((IS_TYPE_REFERENCE(obj->type) || is_const_object(obj)) && copts.cplusplus) - CError_Error(CErrorStr224); - } else { - if (obj->type->size || IS_TYPE_ARRAY(obj->type)) { - if ((expr = CInit_GenericData(obj, obj->type, obj->qual, CInit_GlobalStaticInit, 1))) - cb(makediadicnode(create_objectnode2(obj), expr, EASS)); - } else { - CError_Error(CErrorStr145); - } - } - - CInit_CleanupInitInfo(&initinfo); -} - -void CInit_InitializeData(Object *obj) { - Object *dtor; - ObjectList *list; - CInt64 val; - InitInfo initinfo; - Boolean needs_construction; - Type *type; - - if (tk == ':') { - tk = lex(); - obj->datatype = DABSOLUTE; - val = CExpr_IntegralConstExpr(); - obj->u.address = CInt64_GetULong(&val); - return; - } - - if (tk != '=' && (tk != '(' || !copts.cplusplus)) { - if (obj->sclass != TK_EXTERN) { - if (!copts.cplusplus) { - if (IsCompleteType(obj->type)) { - for (list = cinit_tentative; list; list = list->next) { - if (list->object == obj) - break; - } - if (!list) { - list = galloc(sizeof(ObjectList)); - list->object = obj; - list->next = cinit_tentative; - cinit_tentative = list; - obj->qual |= Q_1000000; - } - } - } else { - if (obj->flags & OBJECT_DEFINED) - CError_Error(CErrorStr329, obj); - obj->flags = obj->flags | OBJECT_DEFINED; - - needs_construction = 0; - if (IS_TYPE_ARRAY(obj->type)) { - type = obj->type; - while (IS_TYPE_ARRAY(type)) - type = TYPE_POINTER(type)->target; - if (IS_TYPE_CLASS(type)) { - if (CInit_ClassNeedsConstruction(TYPE_CLASS(type))) { - CInit_SetupInitInfo(&initinfo, obj); - CInit_InitializeClassArray(obj, TYPE_CLASS(type), 1); - CInit_CleanupInitInfo(&initinfo); - needs_construction = 1; - } else { - CFunc_CheckClassCtors(TYPE_CLASS(type)); - } - } - } else { - if (IS_TYPE_CLASS(obj->type)) { - if (CInit_ClassNeedsConstruction(TYPE_CLASS(obj->type))) { - CInit_SetupInitInfo(&initinfo, obj); - CInit_ConstructGlobalObject(obj, TYPE_CLASS(obj->type), NULL, 0, 0); - CInit_CleanupInitInfo(&initinfo); - needs_construction = 1; - } else { - CFunc_CheckClassCtors(TYPE_CLASS(obj->type)); - } - } - } - - if (!needs_construction && copts.cplusplus) { - if (IS_TYPE_REFERENCE(obj->type) || is_const_object(obj)) - CError_Error(CErrorStr224); - } - if (IsCompleteType(obj->type)) - CInit_DeclareData(obj, NULL, NULL, obj->type->size); - } - } - return; - } - - if (obj->flags & OBJECT_DEFINED) - CError_Error(CErrorStr329, obj); - - if (CInit_IsSimpleStructArrayInit(obj->type)) { - if (tk == '=') - tk = lex(); - else - CError_Error(CErrorStr121); - CInit_GlobalObject(obj); - return; - } - - CInit_SetupInitInfo(&initinfo, obj); - if (IS_TYPE_CLASS(obj->type) && CInit_ConstructGlobalObject(obj, TYPE_CLASS(obj->type), NULL, 0, 1)) { - IsCompleteType(obj->type); - CInit_DeclareData(obj, NULL, NULL, obj->type->size); - CInit_CleanupInitInfo(&initinfo); - return; - } - - if (IS_TYPE_REFERENCE(obj->type) && CInit_InitReference(obj, 0)) { - CInit_CleanupInitInfo(&initinfo); - return; - } - - if (obj->type->size == 0 && !IS_TYPE_ARRAY(obj->type)) { - CError_Error(CErrorStr145); - CInit_CleanupInitInfo(&initinfo); - return; - } - - if (copts.cplusplus) - CInit_GenericData(obj, obj->type, obj->qual, &CInit_GlobalStaticInit, 0); - else - CInit_GenericData(obj, obj->type, obj->qual, NULL, 0); - - if (IS_TYPE_CLASS(obj->type) && (dtor = CClass_Destructor(TYPE_CLASS(obj->type)))) - InitExpr_Register(CInit_RegisterDtorObject(obj->type, dtor, create_objectrefnode(obj)), obj); - - CInit_CleanupInitInfo(&initinfo); -} - -Object *CInit_DeclareString(char *data, SInt32 size, Boolean ispascal, Boolean iswide) { - PooledString *str; - Object *obj; - PooledString *scan; - - if (!copts.dont_reuse_strings) { - for (scan = cinit_stringlist; scan; scan = scan->next) { - if (scan->size == size && scan->ispascal == ispascal && scan->iswide == iswide && !memcmp(scan->data, data, size)) - return scan->obj; - } - } - - obj = CParser_NewCompilerDefDataObject(); - obj->name = CParser_GetUniqueName(); - if (iswide) { - obj->type = CDecl_NewArrayType(CParser_GetWCharType(), size); - } else { - obj->type = CDecl_NewArrayType(ispascal ? TYPE(&stunsignedchar) : TYPE(&stchar), size); - } - obj->sclass = TK_STATIC; - CScope_AddGlobalObject(obj); - - if (!iswide && !ispascal && size == (strlen(data) + 1)) - obj->section = SECT_TEXT_CSTRING; - else - obj->section = SECT_CONST; - - if (copts.readonly_strings) - CInit_DeclareReadOnlyData(obj, data, NULL, obj->type->size); - else - CInit_DeclareData(obj, data, NULL, obj->type->size); - - str = galloc(sizeof(PooledString)); - str->next = cinit_stringlist; - cinit_stringlist = str; - str->obj = obj; - str->offset = 0; - str->size = size; - str->ispascal = ispascal; - str->iswide = iswide; - str->data = galloc(size); - memcpy(str->data, data, size); - - return obj; -} - -PooledString *CInit_DeclarePooledString(char *data, SInt32 size, Boolean ispascal) { - PooledString *str; - Object *obj; - PooledString *scan; - SInt32 offset; - - if (!copts.dont_reuse_strings) { - for (scan = cinit_pooledstringlist; scan; scan = scan->next) { - if (scan->size == size && scan->ispascal == ispascal && !memcmp(scan->data, data, size)) - return scan; - } - } - - if (cinit_pooledstringlist) { - obj = cinit_pooledstringlist->obj; - offset = cinit_pooledstringlist->offset + cinit_pooledstringlist->size; - } else { - obj = CInit_CreateStaticDataObject( - CDecl_NewArrayType(ispascal ? TYPE(&stunsignedchar) : TYPE(&stchar), size), - 0, GetHashNameNodeExport("@stringBase0")); - obj->section = SECT_CONST; - offset = 0; - } - - str = galloc(sizeof(PooledString)); - str->next = cinit_pooledstringlist; - cinit_pooledstringlist = str; - str->obj = obj; - str->offset = offset; - str->size = size; - str->ispascal = ispascal; - str->data = galloc(size); - memcpy(str->data, data, size); - return str; -} - -PooledString *CInit_DeclarePooledWString(char *data, SInt32 size) { - PooledString *str; - Object *obj; - PooledString *scan; - SInt32 offset; - - if (!copts.dont_reuse_strings) { - for (scan = cinit_pooledwstringlist; scan; scan = scan->next) { - if (scan->size == size && !memcmp(scan->data, data, size)) - return scan; - } - } - - if (cinit_pooledwstringlist) { - obj = cinit_pooledwstringlist->obj; - offset = cinit_pooledwstringlist->offset + cinit_pooledwstringlist->size; - } else { - obj = CInit_CreateStaticDataObject( - CDecl_NewArrayType(CParser_GetWCharType(), size), - 0, GetHashNameNodeExport("@wstringBase0")); - obj->section = SECT_CONST; - offset = 0; - } - - str = galloc(sizeof(PooledString)); - str->next = cinit_pooledwstringlist; - cinit_pooledwstringlist = str; - str->obj = obj; - str->offset = offset; - str->size = size; - str->ispascal = 0; - str->data = galloc(size); - memcpy(str->data, data, size); - return str; -} - -void CInit_RewriteString(ENode *expr, Boolean flag) { - PooledString *str; - Boolean is_wide; - - if (cparamblkptr->precompile == 1) - CError_Error(CErrorStr180); - - CError_ASSERT(4220, expr->rtype->type == TYPEPOINTER); - - is_wide = TYPE_POINTER(expr->rtype)->target->size != 1; - if (copts.poolstrings) { - if (is_wide) - str = CInit_DeclarePooledWString(expr->data.string.data, expr->data.string.size); - else - str = CInit_DeclarePooledString(expr->data.string.data, expr->data.string.size, expr->data.string.ispascal); - - if (str->offset) { - expr->type = EADD; - expr->data.diadic.right = intconstnode(TYPE(&stunsignedlong), str->offset); - expr->data.diadic.left = create_objectrefnode(str->obj); - expr->cost = 1; - } else { - expr->type = EOBJREF; - expr->data.objref = str->obj; - } - } else { - expr->type = EOBJREF; - expr->data.objref = CInit_DeclareString(expr->data.string.data, expr->data.string.size, expr->data.string.ispascal, is_wide); - } -} - -void CInit_DeclarePooledStrings(void) { - SInt32 size; - char *buffer; - PooledString *str; - - size = 0; - for (str = cinit_pooledstringlist; str; str = str->next) - size += str->size; - - if (size) { - cinit_pooledstringlist->obj->type = CDecl_NewArrayType(TYPE(&stchar), size); - buffer = galloc(size); - for (str = cinit_pooledstringlist; str; str = str->next) - memcpy(buffer + str->offset, str->data, str->size); - - if (copts.readonly_strings) - CInit_DeclareReadOnlyData(cinit_pooledstringlist->obj, buffer, NULL, size); - else - CInit_DeclareData(cinit_pooledstringlist->obj, buffer, NULL, size); - } - - size = 0; - for (str = cinit_pooledwstringlist; str; str = str->next) - size += str->size; - - if (size) { - cinit_pooledwstringlist->obj->type = CDecl_NewArrayType(CParser_GetWCharType(), size); - buffer = galloc(size); - for (str = cinit_pooledwstringlist; str; str = str->next) - memcpy(buffer + str->offset, str->data, str->size); - - if (copts.readonly_strings) - CInit_DeclareReadOnlyData(cinit_pooledwstringlist->obj, buffer, NULL, size); - else - CInit_DeclareData(cinit_pooledwstringlist->obj, buffer, NULL, size); - } -} - -static void declaredata(Object *obj, void *data, OLinkList *list, SInt32 size, Boolean is_readonly) { - OLinkList *scan; - UInt32 qual; - - qual = obj->qual; - - if (cparamblkptr->precompile == 1) { - PreComp_StaticData(obj, data, list, size); - } else { - obj->flags = obj->flags | OBJECT_DEFINED; - if (!fatalerrors) { - for (scan = list; scan; scan = scan->next) - CInline_ObjectAddrRef(scan->obj); - if (copts.filesyminfo) - CPrep_SetSourceFile(&cparser_fileoffset); - if (is_readonly) - ObjGen_DeclareReadOnlyData(obj, data, list, size); - else - ObjGen_DeclareData(obj, data, list, size); - obj->qual = qual; - } - } -} - -void CInit_DeclareData(Object *obj, void *data, OLinkList *list, SInt32 size) { - declaredata(obj, data, list, size, 0); -} - -void CInit_DeclareReadOnlyData(Object *obj, void *data, OLinkList *list, SInt32 size) { - declaredata(obj, data, list, size, 1); -} - -void CInit_DefineTentativeData(void) { - ObjectList *list; - - for (list = cinit_tentative; list; list = list->next) { - if (!(list->object->flags & OBJECT_DEFINED)) - CInit_DeclareData(list->object, NULL, NULL, list->object->type->size); - } - - cinit_tentative = NULL; -} diff --git a/compiler_and_linker/unsorted/CInline.c b/compiler_and_linker/unsorted/CInline.c deleted file mode 100644 index de51ab7..0000000 --- a/compiler_and_linker/unsorted/CInline.c +++ /dev/null @@ -1,4206 +0,0 @@ -#include "compiler/CInline.h" -#include "compiler/CABI.h" -#include "compiler/CClass.h" -#include "compiler/CError.h" -#include "compiler/CException.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInit.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/COptimizer.h" -#include "compiler/CParser.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CTemplateNew.h" -#include "compiler/CodeGen.h" -#include "compiler/CompilerTools.h" -#include "compiler/Exceptions.h" -#include "compiler/InlineAsm.h" -#include "compiler/ObjGenMachO.h" -#include "compiler/Switch.h" -#include "compiler/enode.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/templates.h" - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct IDTrans { - struct IDTrans *next; - SInt32 from; - SInt32 to; -} IDTrans; - -typedef struct LabelTrans { - struct LabelTrans *next; - CLabel **labelptr; - short id; -} LabelTrans; - -typedef struct UIDTemp { - struct UIDTemp *next; - Object *object; - SInt32 uid; -} UIDTemp; - -typedef struct CI_Export { - struct CI_Export *next; - Object *object; - CI_FuncData *funcdata; - Boolean xC; -} CI_Export; - -typedef struct AObject { - Object *object; - ENode *expr1; - ENode *expr2; -} AObject; - -typedef struct CI_StmtLink { - struct CI_StmtLink *next; - Statement *stmt; - CI_Statement *ciStmt; -} CI_StmtLink; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static CInlineCopyMode enode_copymode; -static Boolean enode_globalcopy; -static IDTrans *enode_idtrans; -static Object **local_dobjects; -static AObject *local_aobjects; -static CI_Var *loc_args; -static CI_Var *loc_vars; -static Boolean inline_expanded; -static Boolean any_inline_expanded; -static short cinline_level; -static LabelTrans *cinline_label_trans; -static Statement *cinline_first_stmt; -static ENode *cinline_stmtlevelexpr[16]; -static short cinline_stmtlevelexprs; -static Boolean cinline_unconditionalpart; -static Boolean cinline_serialize_stmt; -static CI_Export *cinline_exportlist; // type? -static CI_Action *cinline_actionlist; -CI_Action *cinline_tactionlist; -static ObjectList *cinline_freflist; -static Boolean cinline_gendeps; -static Statement *cinline_serial_stmt; -static Statement *cinline_cur_serial_stmt; -static UIDTemp *cinline_uid_temps; -static Boolean cinline_has_sideeffect; -static SInt32 inline_max_size; -static Boolean recursive_inline; -static Object *expanding_function; -static Boolean cinline_funccallfound; - -// forward decls -static ENode *CInline_FoldConst(ENode *expr); -static ENode *CInline_CopyNodes(ENode *node); -static SInt32 CInline_EstimateSizeOfFunc(CI_FuncData *funcdata, SInt32 size, SInt32 level); -static ENode *CInline_SerializeExpr(ENode *expr); -static void CInline_AddFRefList_InlineFunc(CI_FuncData *data); - -void CInline_Init(void) { - cinline_exportlist = NULL; - cinline_actionlist = NULL; - cinline_tactionlist = NULL; - cinline_gendeps = 0; -} - -static ENode *CInline_MakeNotNot(ENode *expr) { - expr = CInline_FoldConst(expr); - - if (!ENODE_IS(expr, EINTCONST)) { - expr = makemonadicnode(expr, ELOGNOT); - expr->rtype = CParser_GetBoolType(); - expr = makemonadicnode(expr, ELOGNOT); - } else { - expr->data.intval = CInt64_Not(CInt64_Not(expr->data.intval)); - } - - return expr; -} - -static ENode *CInline_FoldConst(ENode *expr) { - ENode *inner; - ENode *right; - ENode *left; - ENodeList *list; - - switch (expr->type) { - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case EPRECOMP: - case ETEMP: - case ELABEL: - case EOBJLIST: - case EINSTRUCTION: - case EVECTOR128CONST: - return expr; - - case EMONMIN: - case EBINNOT: - case ELOGNOT: - expr->data.monadic = CInline_FoldConst(expr->data.monadic); - inner = expr->data.monadic; - switch (inner->type) { - case EINTCONST: - if (!ENODE_IS(expr, ELOGNOT)) { - inner->data.intval = CMach_CalcIntMonadic( - expr->rtype, CParser_GetOperator(expr->type), inner->data.intval); - } else { - inner->data.intval = CInt64_Not(inner->data.intval); - } - inner->rtype = expr->rtype; - return inner; - - case EFLOATCONST: - if (ENODE_IS(expr, ELOGNOT)) { - inner->type = EINTCONST; - CInt64_SetLong(&inner->data.intval, CMach_FloatIsZero(inner->data.floatval)); - } else { - inner->data.floatval = CMach_CalcFloatMonadic( - expr->rtype, CParser_GetOperator(expr->type), inner->data.floatval); - } - inner->rtype = expr->rtype; - return inner; - } - - return expr; - - case ETYPCON: - expr->data.monadic = CInline_FoldConst(expr->data.monadic); - switch (expr->data.monadic->type) { - case EINTCONST: - switch (expr->rtype->type) { - case TYPEFLOAT: - expr->type = EFLOATCONST; - expr->data.floatval = CMach_CalcFloatConvertFromInt( - expr->data.monadic->rtype, expr->data.monadic->data.intval); - return expr; - - case TYPEINT: - expr->type = EINTCONST; - expr->data.intval = CExpr_IntConstConvert( - expr->rtype, expr->data.monadic->rtype, expr->data.monadic->data.intval); - break; - } - break; - - case EFLOATCONST: - switch (expr->rtype->type) { - case TYPEFLOAT: - expr->type = EFLOATCONST; - expr->data.floatval = CMach_CalcFloatConvert( - expr->rtype, expr->data.monadic->data.floatval); - return expr; - - case TYPEINT: - expr->type = EINTCONST; - expr->data.intval = CMach_CalcIntConvertFromFloat( - expr->rtype, expr->data.monadic->data.floatval); - return expr; - } - break; - } - - return expr; - - case EPOSTINC: - case EPOSTDEC: - expr->data.monadic = CInline_FoldConst(expr->data.monadic); - switch (expr->data.monadic->type) { - case EINTCONST: - case EFLOATCONST: - expr->data.monadic->rtype = expr->rtype; - return expr->data.monadic; - } - - return expr; - - case EPREINC: - case EPREDEC: - case EINDIRECT: - case EFORCELOAD: - case EBITFIELD: - expr->data.monadic = CInline_FoldConst(expr->data.monadic); - return expr; - - case EMUL: - case EDIV: - case EMODULO: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case EAND: - case EXOR: - case EOR: - expr->data.diadic.left = CInline_FoldConst(expr->data.diadic.left); - expr->data.diadic.right = CInline_FoldConst(expr->data.diadic.right); - if ((left = expr->data.diadic.left)->type == (right = expr->data.diadic.right)->type) { - switch (left->type) { - case EINTCONST: - left->data.intval = CMach_CalcIntDiadic( - expr->rtype, - expr->data.diadic.left->data.intval, - CParser_GetOperator(expr->type), - right->data.intval); - left->rtype = expr->rtype; - return left; - - case EFLOATCONST: - left->data.floatval = CMach_CalcFloatDiadic( - expr->rtype, - expr->data.diadic.left->data.floatval, - CParser_GetOperator(expr->type), - right->data.floatval); - left->rtype = expr->rtype; - return left; - } - } - - return expr; - - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - expr->data.diadic.left = CInline_FoldConst(expr->data.diadic.left); - expr->data.diadic.right = CInline_FoldConst(expr->data.diadic.right); - if ((left = expr->data.diadic.left)->type == (right = expr->data.diadic.right)->type) { - switch (left->type) { - case EINTCONST: - left->data.intval = CMach_CalcIntDiadic( - left->rtype, - expr->data.diadic.left->data.intval, - CParser_GetOperator(expr->type), - right->data.intval); - left->rtype = expr->rtype; - return left; - - case EFLOATCONST: - CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool( - left->rtype, - expr->data.diadic.left->data.floatval, - CParser_GetOperator(expr->type), - right->data.floatval - )); - left->type = EINTCONST; - left->rtype = expr->rtype; - return left; - } - } - - return expr; - - case ELAND: - expr->data.diadic.left = CInline_FoldConst(expr->data.diadic.left); - if (iszero(expr->data.diadic.left)) - return expr->data.diadic.left; - if (isnotzero(expr->data.diadic.left)) - return CInline_MakeNotNot(expr->data.diadic.right); - - expr->data.diadic.right = CInline_FoldConst(expr->data.diadic.right); - if (isnotzero(expr->data.diadic.right)) - return CInline_MakeNotNot(expr->data.diadic.left); - - return expr; - - case ELOR: - expr->data.diadic.left = CInline_FoldConst(expr->data.diadic.left); - if (iszero(expr->data.diadic.left)) - return CInline_MakeNotNot(expr->data.diadic.right); - if (isnotzero(expr->data.diadic.left)) - return CInline_MakeNotNot(expr->data.diadic.left); - - expr->data.diadic.right = CInline_FoldConst(expr->data.diadic.right); - if (iszero(expr->data.diadic.right)) - return CInline_MakeNotNot(expr->data.diadic.left); - - return expr; - - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case ECOMMA: - case EROTL: - case EROTR: - expr->data.diadic.left = CInline_FoldConst(expr->data.diadic.left); - expr->data.diadic.right = CInline_FoldConst(expr->data.diadic.right); - return expr; - - case ECOND: - expr->data.cond.cond = CInline_FoldConst(expr->data.cond.cond); - if (isnotzero(expr->data.cond.cond)) - return CInline_FoldConst(expr->data.cond.expr1); - if (iszero(expr->data.cond.cond)) - return CInline_FoldConst(expr->data.cond.expr2); - - expr->data.cond.expr1 = CInline_FoldConst(expr->data.cond.expr1); - expr->data.cond.expr2 = CInline_FoldConst(expr->data.cond.expr2); - return expr; - - case EMFPOINTER: - expr->data.mfpointer.accessnode = CInline_FoldConst(expr->data.mfpointer.accessnode); - expr->data.mfpointer.mfpointer = CInline_FoldConst(expr->data.mfpointer.mfpointer); - return expr; - - case EFUNCCALL: - case EFUNCCALLP: - expr->data.funccall.funcref = CInline_FoldConst(expr->data.funccall.funcref); - for (list = expr->data.funccall.args; list; list = list->next) - list->node = CInline_FoldConst(list->node); - return expr; - - case ENULLCHECK: - expr->data.nullcheck.nullcheckexpr = CInline_FoldConst(expr->data.nullcheck.nullcheckexpr); - expr->data.nullcheck.condexpr = CInline_FoldConst(expr->data.nullcheck.condexpr); - return expr; - - case EMEMBER: - if (expr->data.emember->expr) - expr->data.emember->expr = CInline_FoldConst(expr->data.emember->expr); - return expr; - - default: - CError_FATAL(421); - return expr; - } -} - -// unknown name -CW_INLINE SInt32 CInline_GetLocalID2(Object *object) { - ObjectList *list; - SInt32 counter; - - for (list = locals, counter = 0; list; list = list->next) { - if (list->object->datatype == DLOCAL) { - if (list->object == object) - return counter; - counter++; - } - } - - return -1; -} - -SInt32 CInline_GetLocalID(Object *object) { - ObjectList *list; - SInt32 counter; - - if (object) { - for (list = arguments, counter = 0; list; list = list->next, counter++) { - if (list->object == object) { - loc_args[counter].xD = 1; - loc_args[counter].xE = 0; - return counter - 0x7FFFFFFF; - } - } - - counter = CInline_GetLocalID2(object); - CError_ASSERT(465, counter >= 0); - loc_vars[counter].xD = 1; - return counter + 1; - } - - return 0; -} - -static Boolean CInline_IsTrivialExpression(ENode *expr) { - while (1) { - switch (expr->type) { - case EINTCONST: - case EFLOATCONST: - case EOBJREF: - case EARGOBJ: - case ELOCOBJ: - case EOBJLIST: - case EVECTOR128CONST: - return 0; - - case ESTRINGCONST: - return copts.dont_reuse_strings; - - case EMEMBER: - if (expr->data.emember->expr) - return CInline_IsTrivialExpression(expr->data.emember->expr); - return 0; - - case EINDIRECT: - if (ENODE_IS(expr->data.monadic, EOBJREF)) { - if (expr->data.monadic->data.objref->datatype == DLOCAL && - !(expr->data.monadic->data.objref->flags & OBJECT_FLAGS_2)) - return 0; - - if (is_const_object(expr->data.monadic->data.objref)) - return 0; - - return 1; - } - - return 1; - - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EFORCELOAD: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case EFUNCCALL: - case EFUNCCALLP: - case EMFPOINTER: - case ENULLCHECK: - case EPRECOMP: - case ETEMP: - case ELABEL: - case EINSTRUCTION: - return 1; - - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case ETYPCON: - case EBITFIELD: - expr = expr->data.monadic; - continue; - - case EMUL: - case EDIV: - case EMODULO: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case ELAND: - case ELOR: - case ECOMMA: - case EROTL: - case EROTR: - if (CInline_IsTrivialExpression(expr->data.diadic.left)) - return 1; - expr = expr->data.diadic.right; - continue; - - case ECOND: - if (CInline_IsTrivialExpression(expr->data.cond.cond)) - return 1; - if (CInline_IsTrivialExpression(expr->data.cond.expr1)) - return 1; - expr = expr->data.cond.expr2; - continue; - - default: - CError_FATAL(582); - } - } -} - -Boolean CInline_ExpressionHasSideEffect(ENode *expr) { - while (1) { - switch (expr->type) { - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case EPRECOMP: - case ETEMP: - case EARGOBJ: - case ELOCOBJ: - case ELABEL: - case EOBJLIST: - case EVECTOR128CONST: - return 0; - - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case EFUNCCALL: - case EFUNCCALLP: - case EINSTRUCTION: - return 1; - - case EINDIRECT: - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case EFORCELOAD: - case ETYPCON: - case EBITFIELD: - expr = expr->data.monadic; - continue; - - case EMUL: - case EDIV: - case EMODULO: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case ELAND: - case ELOR: - case ECOMMA: - case EROTL: - case EROTR: - if (CInline_ExpressionHasSideEffect(expr->data.diadic.left)) - return 1; - expr = expr->data.diadic.right; - continue; - - case EMEMBER: - if (expr->data.emember->expr) - return CInline_ExpressionHasSideEffect(expr->data.emember->expr); - return 0; - - case EMFPOINTER: - if (CInline_ExpressionHasSideEffect(expr->data.mfpointer.accessnode)) - return 1; - expr = expr->data.mfpointer.mfpointer; - continue; - - case ENULLCHECK: - if (CInline_ExpressionHasSideEffect(expr->data.nullcheck.nullcheckexpr)) - return 1; - expr = expr->data.nullcheck.condexpr; - continue; - - case ECOND: - if (CInline_ExpressionHasSideEffect(expr->data.cond.cond)) - return 1; - if (CInline_ExpressionHasSideEffect(expr->data.cond.expr1)) - return 1; - expr = expr->data.cond.expr2; - continue; - - default: - CError_FATAL(689); - } - } -} - -static ENode *CInline_CopyExpressionSave(ENode *expr) { - CInlineCopyMode save_copymode; - Boolean save_globalcopy; - IDTrans *save_idtrans; - - save_globalcopy = enode_globalcopy; - enode_globalcopy = 1; - - save_copymode = enode_copymode; - enode_copymode = CopyMode4; - - save_idtrans = enode_idtrans; - enode_idtrans = NULL; - - expr = CInline_CopyNodes(expr); - - enode_globalcopy = save_globalcopy; - enode_copymode = save_copymode; - enode_idtrans = save_idtrans; - - return expr; -} - -static SInt32 CInline_TranslateID(SInt32 id) { - IDTrans *trans; - - for (trans = enode_idtrans; trans; trans = trans->next) { - if (trans->from == id) - return trans->to; - } - - trans = lalloc(sizeof(IDTrans)); - trans->next = enode_idtrans; - enode_idtrans = trans; - - trans->from = id; - trans->to = CParser_GetUniqueID(); - - return trans->to; -} - -static short CInline_GetLabelStatementNumber(HashNameNode *name) { - Statement *stmt; - short i; - - for (stmt = cinline_first_stmt, i = 0; stmt; stmt = stmt->next, i++) { - if (stmt->type == ST_LABEL && stmt->label->uniquename == name) - return i; - } - - CError_FATAL(742); - return 0; -} - -static ENodeList *CInline_CopyNodeList(ENodeList *list) { - ENodeList *copy; - ENodeList *first; - ENodeList *last; - - first = NULL; - while (list) { - if (enode_globalcopy) - copy = galloc(sizeof(ENodeList)); - else - copy = lalloc(sizeof(ENodeList)); - - copy->node = CInline_CopyNodes(list->node); - copy->next = NULL; - - if (first) { - last->next = copy; - last = copy; - } else { - first = last = copy; - } - - list = list->next; - } - - return first; -} - -static EMemberInfo *CInline_CopyEMemberInfo(EMemberInfo *mi) { - EMemberInfo *copy; - - if (enode_globalcopy) - copy = galloc(sizeof(EMemberInfo)); - else - copy = lalloc(sizeof(EMemberInfo)); - - *copy = *mi; - if (copy->path) - copy->path = CClass_GetPathCopy(copy->path, enode_globalcopy); - if (copy->expr) - copy->expr = CInline_CopyNodes(copy->expr); - - return copy; -} - -static ENode *CInline_CopyNodes(ENode *node) { - ENode *copy; - - if (enode_globalcopy) - copy = galloc(sizeof(ENode)); - else - copy = lalloc(sizeof(ENode)); - - while (1) { - *copy = *node; - switch (copy->type) { - case ETEMPLDEP: - switch (copy->data.templdep.subtype) { - case TDE_PARAM: - case TDE_SIZEOF: - case TDE_ALIGNOF: - case TDE_QUALNAME: - case TDE_OBJ: - break; - case TDE_CAST: - copy->data.templdep.u.cast.args = CInline_CopyNodeList(copy->data.templdep.u.cast.args); - break; - case TDE_SOURCEREF: - copy->data.templdep.u.sourceref.expr = CInline_CopyNodes(copy->data.templdep.u.sourceref.expr); - break; - case TDE_ADDRESS_OF: - copy->data.templdep.u.monadic = CInline_CopyNodes(copy->data.templdep.u.monadic); - break; - default: - CError_FATAL(840); - } - break; - - case ETEMP: - if (enode_copymode == CopyMode3 && copy->data.temp.uniqueid) - copy->data.temp.uniqueid = CInline_TranslateID(copy->data.temp.uniqueid); - break; - - case ELABEL: - switch (enode_copymode) { - case CopyMode2: - copy->data.precompid = CInline_GetLabelStatementNumber(copy->data.label->uniquename); - return copy; - case CopyMode3: - case CopyMode4: { - LabelTrans *trans = lalloc(sizeof(LabelTrans)); - trans->next = cinline_label_trans; - cinline_label_trans = trans; - trans->id = copy->data.precompid; - trans->labelptr = ©->data.label; - return copy; - } - } - break; - - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJLIST: - case EINSTRUCTION: - case EVECTOR128CONST: - break; - - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case EFORCELOAD: - case ETYPCON: - case EBITFIELD: - copy->data.monadic = CInline_CopyNodes(copy->data.monadic); - break; - - ENODE_CASE_DIADIC_ALL: - copy->data.diadic.left = CInline_CopyNodes(copy->data.diadic.left); - copy->data.diadic.right = CInline_CopyNodes(copy->data.diadic.right); - break; - - case ECOND: - copy->data.cond.cond = CInline_CopyNodes(copy->data.cond.cond); - copy->data.cond.expr1 = CInline_CopyNodes(copy->data.cond.expr1); - copy->data.cond.expr2 = CInline_CopyNodes(copy->data.cond.expr2); - break; - - case EMFPOINTER: - copy->data.mfpointer.accessnode = CInline_CopyNodes(copy->data.mfpointer.accessnode); - copy->data.mfpointer.mfpointer = CInline_CopyNodes(copy->data.mfpointer.mfpointer); - break; - - case EFUNCCALL: - case EFUNCCALLP: - copy->data.funccall.funcref = CInline_CopyNodes(copy->data.funccall.funcref); - copy->data.funccall.args = CInline_CopyNodeList(copy->data.funccall.args); - break; - - case ENULLCHECK: - copy->data.nullcheck.precompid = CInline_TranslateID(copy->data.nullcheck.precompid); - copy->data.nullcheck.nullcheckexpr = CInline_CopyNodes(copy->data.nullcheck.nullcheckexpr); - copy->data.nullcheck.condexpr = CInline_CopyNodes(copy->data.nullcheck.condexpr); - break; - - case EPRECOMP: - copy->data.precompid = CInline_TranslateID(copy->data.precompid); - break; - - case EINDIRECT: - if ( - enode_copymode == CopyMode4 && - ENODE_IS(copy->data.monadic, EARGOBJ) && - local_aobjects[copy->data.monadic->data.longval].object == NULL - ) - { - CError_ASSERT(910, local_aobjects[copy->data.monadic->data.longval].expr1); - copy = CInline_CopyExpressionSave(local_aobjects[copy->data.monadic->data.longval].expr1); - if (copy->rtype != node->rtype) { - if (IS_TYPE_INT(copy->rtype) && IS_TYPE_INT(node->rtype)) - copy = makemonadicnode(copy, ETYPCON); - copy->rtype = node->rtype; - } - return copy; - } - - copy->data.monadic = CInline_CopyNodes(copy->data.monadic); - break; - - case EOBJREF: - if (enode_copymode == CopyMode2) { - ObjectList *list; - int i; - - if (node->data.objref->datatype == DALIAS) { - CExpr_AliasTransform(node); - continue; - } - - if (node->data.objref->datatype == DDATA) - return copy; - - for (list = arguments, i = 0; list; list = list->next, i++) { - if (list->object == copy->data.objref) { - copy->type = EARGOBJ; - copy->data.longval = i; - return copy; - } - } - - i = CInline_GetLocalID2(copy->data.objref); - if (i >= 0) { - copy->type = ELOCOBJ; - copy->data.longval = i; - return copy; - } - - if (node->data.objref->datatype == DLOCAL) - CError_FATAL(949); - } - break; - - case EARGOBJ: - switch (enode_copymode) { - case CopyMode4: - CError_ASSERT(957, local_aobjects[copy->data.longval].object); - copy->type = EOBJREF; - copy->data.objref = local_aobjects[copy->data.longval].object; - return copy; - - case CopyMode3: { - ObjectList *list; - int i; - for (list = arguments, i = 0; list; list = list->next, i++) { - if (i == copy->data.longval) { - copy->type = EOBJREF; - copy->data.objref = list->object; - CError_ASSERT(966, copy->data.objref); - return copy; - } - } - } - - default: - CError_FATAL(971); - } - - case ELOCOBJ: - switch (enode_copymode) { - case CopyMode4: - copy->type = EOBJREF; - copy->data.objref = local_dobjects[copy->data.longval]; - return copy; - - case CopyMode3: { - ObjectList *list; - int i; - for (list = locals, i = 0; list; list = list->next, i++) { - if (i == copy->data.longval) { - copy->type = EOBJREF; - copy->data.objref = list->object; - CError_ASSERT(986, copy->data.objref); - return copy; - } - } - } - - default: - CError_FATAL(991); - } - break; - - case ENEWEXCEPTION: - case ENEWEXCEPTIONARRAY: - copy->data.newexception.initexpr = CInline_CopyNodes(copy->data.newexception.initexpr); - copy->data.newexception.tryexpr = CInline_CopyNodes(copy->data.newexception.tryexpr); - break; - - case EINITTRYCATCH: - copy->data.itc.initexpr = CInline_CopyNodes(copy->data.itc.initexpr); - copy->data.itc.tryexpr = CInline_CopyNodes(copy->data.itc.tryexpr); - copy->data.itc.catchexpr = CInline_CopyNodes(copy->data.itc.catchexpr); - copy->data.itc.result = CInline_CopyNodes(copy->data.itc.result); - break; - - case EMEMBER: - copy->data.emember = CInline_CopyEMemberInfo(copy->data.emember); - break; - - default: - CError_FATAL(1015); - } - - return copy; - } -} - -static void CInline_CheckUsage(ENode *expr, Boolean flag) { - ENodeList *list; - ENode *inner; - - while (1) { - switch (expr->type) { - case EARGOBJ: - loc_args[expr->data.longval].xD = 1; - loc_args[expr->data.longval].xE = 0; - return; - - case ELOCOBJ: - loc_vars[expr->data.longval].xD = 1; - return; - - case EINDIRECT: - if (ENODE_IS((inner = expr->data.monadic), EARGOBJ)) { - loc_args[inner->data.longval].xD = 1; - if (flag) - loc_args[inner->data.longval].xE = 0; - return; - } - expr = expr->data.monadic; - flag = 0; - continue; - - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case EFORCELOAD: - case ETYPCON: - case EBITFIELD: - expr = expr->data.monadic; - flag = 0; - continue; - - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - expr = expr->data.monadic; - flag = 1; - continue; - - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - CInline_CheckUsage(expr->data.diadic.left, 1); - expr = expr->data.diadic.right; - flag = 0; - continue; - - case EMUL: - case EDIV: - case EMODULO: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case ELAND: - case ELOR: - case ECOMMA: - case EROTL: - case EROTR: - CInline_CheckUsage(expr->data.diadic.left, 0); - expr = expr->data.diadic.right; - flag = 0; - continue; - - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case EPRECOMP: - case ETEMP: - case ELABEL: - case EOBJLIST: - case EVECTOR128CONST: - return; - - case EMEMBER: - if (expr->data.emember->expr) - CInline_CheckUsage(expr->data.emember->expr, 0); - return; - - case EFUNCCALL: - case EFUNCCALLP: - CInline_CheckUsage(expr->data.funccall.funcref, 0); - for (list = expr->data.funccall.args; list; list = list->next) - CInline_CheckUsage(list->node, 0); - return; - - case ENULLCHECK: - CInline_CheckUsage(expr->data.nullcheck.nullcheckexpr, 0); - expr = expr->data.nullcheck.condexpr; - flag = 0; - continue; - - case EMFPOINTER: - CInline_CheckUsage(expr->data.mfpointer.accessnode, 0); - expr = expr->data.mfpointer.mfpointer; - flag = 0; - continue; - - case ECOND: - CInline_CheckUsage(expr->data.cond.cond, 0); - CInline_CheckUsage(expr->data.cond.expr1, 0); - expr = expr->data.cond.expr2; - flag = 0; - continue; - - case EINSTRUCTION: - return; - - default: - CError_FATAL(1146); - } - } -} - -ENode *CInline_CopyExpression(ENode *expr, CInlineCopyMode mode) { - enode_copymode = mode; - - switch (mode) { - case CopyMode0: - case CopyMode4: - enode_idtrans = NULL; - enode_globalcopy = 0; - expr = CInline_CopyNodes(expr); - break; - case CopyMode3: - enode_globalcopy = 0; - expr = CInline_CopyNodes(expr); - break; - case CopyMode1: - enode_idtrans = NULL; - enode_globalcopy = 1; - expr = CInline_CopyNodes(expr); - break; - case CopyMode2: - enode_idtrans = NULL; - enode_globalcopy = 1; - expr = CInline_CopyNodes(expr); - CInline_CheckUsage(expr, 0); - break; - } - - return expr; -} - -static UInt8 CInline_GetObjectSFlags(Object *object) { - UInt8 flags; - - switch (object->sclass) { - case 0: - flags = CI_SFLAGS_NoClass; - break; - case TK_REGISTER: - flags = CI_SFLAGS_Register; - break; - case TK_AUTO: - flags = CI_SFLAGS_Auto; - break; - default: - CError_FATAL(1204); - } - - if (object->flags & OBJECT_FLAGS_2) - flags |= CI_SFLAGS_HasObjectFlag2; - - return flags; -} - -static void CInline_SetObjectSFlags(Object *object, UInt8 sflags) { - if (sflags & CI_SFLAGS_HasObjectFlag2) { - object->flags |= OBJECT_FLAGS_2; - sflags &= ~CI_SFLAGS_HasObjectFlag2; - } - - switch (sflags) { - case CI_SFLAGS_NoClass: - object->sclass = 0; - break; - case CI_SFLAGS_Register: - object->sclass = TK_REGISTER; - break; - case CI_SFLAGS_Auto: - object->sclass = TK_AUTO; - break; - default: - CError_FATAL(1229); - } -} - -static Object *CInline_NewLocalObject(Type *type, short qual, UInt8 sflags, int unk) { - Object *object = CParser_NewLocalDataObject(NULL, 1); - object->name = CParser_GetUniqueName(); - object->type = type; - object->qual = qual; - CInline_SetObjectSFlags(object, sflags); - CFunc_SetupLocalVarInfo(object); - return object; -} - -static ENode *CInline_FuncArgConvert(ENode *expr) { - ENode *copy; - - switch (expr->type) { - case EOBJREF: - copy = lalloc(sizeof(ENode)); - *copy = *expr; - return copy; - case ETEMP: - CError_FATAL(1272); - } - - return NULL; -} - -static ENode *CInline_RefArgTransform(ENode *expr, Boolean flag) { - ENodeList *arg; - - while (ENODE_IS(expr, ECOMMA)) - expr = expr->data.diadic.right; - - switch (expr->type) { - case EOBJREF: - case ETEMP: - if (flag) - return CInline_FuncArgConvert(expr); - break; - - case EFUNCCALL: - if (IS_TYPE_POINTER_ONLY(expr->rtype) && IS_TYPE_CLASS(TPTR_TARGET(expr->rtype))) { - if ( - ENODE_IS(expr->data.funccall.funcref, EOBJREF) && - CClass_IsConstructor(expr->data.funccall.funcref->data.objref) && - expr->data.funccall.args - ) - return CInline_FuncArgConvert(expr->data.funccall.args->node); - - if ( - TPTR_TARGET(expr->rtype) == expr->data.funccall.functype->functype && - CMach_GetFunctionResultClass(expr->data.funccall.functype) == 1 && - (arg = expr->data.funccall.args) - ) - { - switch (CABI_GetStructResultArgumentIndex(expr->data.funccall.functype)) { - case 0: - break; - case 1: - if ((arg = arg->next)) - break; - CError_FATAL(1313); - default: - CError_FATAL(1314); - } - - return CInline_FuncArgConvert(arg->node); - } - } - break; - } - - return NULL; -} - -static ENode *CInline_SetupArgsExpression(Object *object, CI_FuncData *data, ENodeList *list) { - ENode *commaNodes; - CI_Var *var; - ENodeList *scan; - ENode *expr; - SInt32 i; - Boolean is_oldstyle; - - is_oldstyle = 0; - if (TYPE_FUNC(object->type)->args == &oldstyle) - is_oldstyle = 1; - - local_dobjects = lalloc(sizeof(Object *) * data->numlocals); - local_aobjects = lalloc(sizeof(AObject) * data->numarguments); - - for (i = 0, var = data->locals; i < data->numlocals; i++, var++) { - if (var->xD) { - object = CInline_NewLocalObject(var->type, var->qual, var->sflags, 0); - local_dobjects[i] = object; - if (!var->xE) - object->flags |= OBJECT_FLAGS_2; - } else { - local_dobjects[i] = NULL; - } - } - - for (i = 0, var = data->arguments, scan = list; i < data->numarguments; i++, var++) { - local_aobjects[i].expr2 = NULL; - - if (!var->xD) { - local_aobjects[i].object = NULL; - local_aobjects[i].expr1 = NULL; - } else if ( - scan && - var->xE && - !CInline_IsTrivialExpression(scan->node) && - (!is_oldstyle || scan->node->rtype->size == var->type->size) - ) - { - local_aobjects[i].object = NULL; - local_aobjects[i].expr1 = scan->node; - } else if ( - scan && - var->xE && - IS_TYPE_REFERENCE(var->type) && - (expr = CInline_RefArgTransform(scan->node, 1)) - ) - { - local_aobjects[i].object = NULL; - local_aobjects[i].expr1 = expr; - local_aobjects[i].expr2 = scan->node; - } else { - local_aobjects[i].object = CInline_NewLocalObject(var->type, var->qual, var->sflags, 0); - local_aobjects[i].expr1 = NULL; - } - - if (scan) - scan = scan->next; - } - - commaNodes = NULL; - - for (i = 0, scan = list; scan; scan = scan->next, i++) { - if (i >= data->numarguments) { - if (!commaNodes) - commaNodes = scan->node; - else - commaNodes = makecommaexpression(scan->node, commaNodes); - } else if (!local_aobjects[i].object || local_aobjects[i].expr2) { - if (local_aobjects[i].expr2) { - if (!commaNodes) - commaNodes = local_aobjects[i].expr2; - else - commaNodes = makecommaexpression(local_aobjects[i].expr2, commaNodes); - } else if (!local_aobjects[i].expr1 && CInline_IsTrivialExpression(scan->node)) { - commaNodes = !commaNodes ? scan->node : makecommaexpression(scan->node, commaNodes); - CError_ASSERT(1470, !ENODE_IS(scan->node, EPRECOMP)); - } - } else { - if (is_oldstyle && scan->node->rtype->size != local_aobjects[i].object->type->size) { - scan->node = makemonadicnode(scan->node, ETYPCON); - scan->node->rtype = local_aobjects[i].object->type; - } - - expr = makediadicnode(create_objectnode2(local_aobjects[i].object), scan->node, EASS); - if (!commaNodes) - commaNodes = expr; - else - commaNodes = makecommaexpression(expr, commaNodes); - } - } - - return commaNodes; -} - -static void CInline_ReturnCheckCB(ENode *expr) { - cinline_has_sideeffect = 1; -} - -static ENode *CInline_ReturnCheck(ENode *expr) { - ENode *copy; - - if (ENODE_IS(expr, EFORCELOAD)) - return expr; - - cinline_has_sideeffect = 0; - CExpr_SearchExprTree(expr, CInline_ReturnCheckCB, 3, EINDIRECT, EFUNCCALL, EFUNCCALLP); - - if (!cinline_has_sideeffect) - return expr; - - copy = lalloc(sizeof(ENode)); - *copy = *expr; - copy->type = EFORCELOAD; - - copy->data.monadic = expr; - return copy; -} - -static ENode *CInline_ReturnMemResult(Object *object) { - int index = CABI_GetStructResultArgumentIndex(TYPE_FUNC(object->type)); - if (local_aobjects[index].object == NULL) - return CInline_CopyExpressionSave(local_aobjects[index].expr1); - else - return create_objectnode(local_aobjects[index].object); -} - -static ENode *CInline_InlineFunctionExpression(ENode *expr) { - Object *object; - CI_FuncData *funcdata; - short i; - Boolean flag26; - ENode *argsExpr; - - object = expr->data.funccall.funcref->data.objref; - if (object->datatype == DALIAS) - object = object->u.alias.object; - - funcdata = object->u.func.u.ifuncdata; - if (!funcdata) - return expr; - - if (funcdata->can_inline < CI_CanInline6) { - if (funcdata->can_inline == CI_CanInline3) { - if (cinline_unconditionalpart && cinline_stmtlevelexprs < 16) - cinline_stmtlevelexpr[cinline_stmtlevelexprs++] = expr; - cinline_serialize_stmt = 1; - } - return expr; - } - - flag26 = CMach_GetFunctionResultClass(TYPE_FUNC(object->type)) == 1; - argsExpr = CInline_SetupArgsExpression(object, funcdata, expr->data.funccall.args); - - for (i = 0; i < funcdata->numstatements; i++) { - switch (funcdata->statements[i].type) { - case ST_RETURN: - if (funcdata->statements[i].u.expr) { - ENode *copy = CInline_CopyExpression(funcdata->statements[i].u.expr, CopyMode4); - if (flag26) { - if (argsExpr) - argsExpr = makecommaexpression(argsExpr, copy); - else - argsExpr = copy; - - argsExpr = makecommaexpression(argsExpr, CInline_ReturnMemResult(object)); - } else { - if (argsExpr) - argsExpr = makecommaexpression(argsExpr, CInline_ReturnCheck(copy)); - else - argsExpr = CInline_ReturnCheck(copy); - } - } - break; - case ST_EXPRESSION: - if (argsExpr) - argsExpr = makecommaexpression(argsExpr, CInline_CopyExpression(funcdata->statements[i].u.expr, CopyMode4)); - else - argsExpr = CInline_CopyExpression(funcdata->statements[i].u.expr, CopyMode4); - break; - - default: - CError_FATAL(1632); - } - } - - if (!argsExpr) - argsExpr = nullnode(); - if (!IS_TYPE_VOID(expr->rtype)) - argsExpr->rtype = expr->rtype; - - inline_expanded = 1; - return CInline_FoldConst(argsExpr); -} - -static Boolean CInline_CanExpand(ENode *expr) { - TypeFunc *tfunc; - Object *object; - - object = expr->data.objref; - tfunc = TYPE_FUNC(object->type); - - if ( - IS_TYPE_FUNC(tfunc) && - ((object->qual & Q_INLINE) || (tfunc->flags & FUNC_FLAGS_800)) && - (object->datatype == DFUNC || (object->datatype == DVFUNC && (expr->flags & ENODE_FLAG_80))) - ) - return 1; - - return 0; -} - -static SInt32 CInline_EstimateSizeOfExpr(ENode *expr, SInt32 size, SInt32 level) { - ENodeList *list; - - switch (expr->type) { - ENODE_CASE_MONADIC: - size = CInline_EstimateSizeOfExpr(expr->data.monadic, size, level) + 1; - break; - - ENODE_CASE_DIADIC_ALL: - size = CInline_EstimateSizeOfExpr(expr->data.diadic.left, size, level); - if (size <= inline_max_size) - size = CInline_EstimateSizeOfExpr(expr->data.diadic.right, size, level) + 1; - break; - - case EFUNCCALL: - case EFUNCCALLP: - if ( - ENODE_IS(expr->data.funccall.funcref, EOBJREF) && - expr->data.funccall.funcref->data.objref->u.func.u.ifuncdata && - CInline_CanExpand(expr->data.funccall.funcref) - ) - { - recursive_inline |= expr->data.funccall.funcref->data.objref == expanding_function; - if (level == 0) { - if (!recursive_inline) - size = inline_max_size + 1; - } else { - size = CInline_EstimateSizeOfFunc(expr->data.funccall.funcref->data.objref->u.func.u.ifuncdata, size, level - 1); - } - } else { - size++; - } - - for (list = expr->data.funccall.args; list; list = list->next) { - if (size > inline_max_size) - break; - - size = CInline_EstimateSizeOfExpr(list->node, size, level); - } - break; - - case ECOND: - size = CInline_EstimateSizeOfExpr(expr->data.cond.cond, size, level); - if (size <= inline_max_size) - size = CInline_EstimateSizeOfExpr(expr->data.cond.expr1, size, level) + 1; - if (size <= inline_max_size) - size = CInline_EstimateSizeOfExpr(expr->data.cond.expr2, size, level) + 1; - break; - - case ENULLCHECK: - size = CInline_EstimateSizeOfExpr(expr->data.nullcheck.nullcheckexpr, size, level); - if (size <= inline_max_size) - size = CInline_EstimateSizeOfExpr(expr->data.nullcheck.condexpr, size, level) + 1; - break; - - case EMFPOINTER: - size = CInline_EstimateSizeOfExpr(expr->data.mfpointer.accessnode, size, level); - if (size <= inline_max_size) - size = CInline_EstimateSizeOfExpr(expr->data.mfpointer.mfpointer, size, level) + 1; - break; - - case EMEMBER: - if (expr->data.emember->expr) - size = CInline_EstimateSizeOfExpr(expr->data.emember->expr, size, level) + 1; - break; - - default: - size++; - } - - return size; -} - -static SInt32 CInline_EstimateSizeOfFunc(CI_FuncData *funcdata, SInt32 size, SInt32 level) { - CI_Statement *stmt; - SInt32 i; - - size += funcdata->numstatements; - if (size > inline_max_size) - return size; - - for (i = 0, stmt = funcdata->statements; i < funcdata->numstatements; i++, stmt++) { - switch (stmt->type) { - case ST_NOP: - case ST_LABEL: - case ST_GOTO: - case ST_ASM: - break; - case ST_EXPRESSION: - case ST_IFGOTO: - case ST_IFNGOTO: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - case ST_GOTOEXPR: - size = CInline_EstimateSizeOfExpr(stmt->u.expr, size, level); - break; - case ST_SWITCH: - size = CInline_EstimateSizeOfExpr(stmt->u.switchdata->expr, size, level); - break; - case ST_RETURN: - if (stmt->u.expr) - size = CInline_EstimateSizeOfExpr(stmt->u.expr, size, level); - break; - default: - CError_FATAL(1840); - } - - if (size > inline_max_size) - break; - } - - return size; -} - -static SInt32 EstimateExpandedSizeOfExpr(ENode *expr, SInt32 level) { - ENodeList *list; - SInt32 size; - - size = 0; - - switch (expr->type) { - ENODE_CASE_MONADIC: - size = EstimateExpandedSizeOfExpr(expr->data.monadic, level) + 1; - break; - - ENODE_CASE_DIADIC_ALL: - size = EstimateExpandedSizeOfExpr(expr->data.diadic.left, level) + 1; - size += EstimateExpandedSizeOfExpr(expr->data.diadic.right, level); - break; - - case EFUNCCALL: - case EFUNCCALLP: - if ( - ENODE_IS(expr->data.funccall.funcref, EOBJREF) && - expr->data.funccall.funcref->data.objref->u.func.u.ifuncdata && - CInline_CanExpand(expr->data.funccall.funcref) - ) - { - if (level) { - SInt32 est = CInline_EstimateSizeOfFunc(expr->data.funccall.funcref->data.objref->u.func.u.ifuncdata, size, level - 1); - if (est > inline_max_size) - size++; - else - size += est; - } else { - size++; - } - } else { - size++; - } - - for (list = expr->data.funccall.args; list; list = list->next) - size += EstimateExpandedSizeOfExpr(list->node, level); - break; - - case ECOND: - size = EstimateExpandedSizeOfExpr(expr->data.cond.cond, level) + 1; - size += EstimateExpandedSizeOfExpr(expr->data.cond.expr1, level); - size += EstimateExpandedSizeOfExpr(expr->data.cond.expr2, level); - break; - - case ENULLCHECK: - size = EstimateExpandedSizeOfExpr(expr->data.nullcheck.nullcheckexpr, level) + 1; - size += EstimateExpandedSizeOfExpr(expr->data.nullcheck.condexpr, level); - break; - - case EMFPOINTER: - size = EstimateExpandedSizeOfExpr(expr->data.mfpointer.accessnode, level) + 1; - size += EstimateExpandedSizeOfExpr(expr->data.mfpointer.mfpointer, level); - break; - - case EMEMBER: - if (expr->data.emember->expr) - size = EstimateExpandedSizeOfExpr(expr->data.emember->expr, level); - break; - - default: - size++; - } - - return size; -} - -static SInt32 EstimateExpandedSizeOfFunction(Statement *stmt) { - SInt32 size; - SInt32 level; - - level = copts.inlinelevel; - if (!level) - level = 8; - - size = 0; - - while (stmt) { - switch (stmt->type) { - case ST_NOP: - break; - case ST_EXPRESSION: - case ST_SWITCH: - case ST_IFGOTO: - case ST_IFNGOTO: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - case ST_GOTOEXPR: - size++; - size += EstimateExpandedSizeOfExpr(stmt->expr, level); - break; - case ST_RETURN: - size++; - if (stmt->expr) - size = EstimateExpandedSizeOfExpr(stmt->expr, level); - break; - case ST_LABEL: - case ST_GOTO: - case ST_ASM: - size++; - break; - default: - CError_FATAL(2015); - } - - stmt = stmt->next; - } - - return size; -} - -static Boolean CInline_InlineFunctionCheck(ENode *expr) { - Object *object; - SInt32 level; - CI_FuncData *funcdata; - - object = expr->data.objref; - if (object->datatype == DALIAS) - object = object->u.alias.object; - - if ( - IS_TYPE_FUNC(object->type) && - ((object->qual & Q_INLINE) || (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_800)) && - (object->datatype == DFUNC || (object->datatype == DVFUNC && (expr->flags & ENODE_FLAG_80))) - ) - { - if (copts.alwaysinline) - return 1; - - if (copts.inline_bottom_up) { - if (!object->u.func.u.ifuncdata) - return 0; - - level = (copts.inlinelevel == 0) ? (7 - cinline_level) : (copts.inlinelevel - cinline_level - 1); - if ((object->qual & Q_INLINE) && level == 0) - return 1; - - if (CInline_EstimateSizeOfFunc(object->u.func.u.ifuncdata, 0, level) > inline_max_size) - return 0; - } else if (cinline_level > 0 && copts.inlinelevel == 0) { - funcdata = object->u.func.u.ifuncdata; - if (!funcdata) - return 0; - - if (funcdata->numstatements > 10) - return 0; - if (cinline_level > 1 && funcdata->numstatements > 7) - return 0; - if (cinline_level > 2 && funcdata->numstatements > 3) - return 0; - } - - return 1; - } else { - return 0; - } - - return 0; -} - -static ENode *CInline_ExpandExpression(ENode *expr) { - ENodeList *list; - Boolean save; - - switch (expr->type) { - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EINDIRECT: - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case ETYPCON: - case EBITFIELD: - expr->data.monadic = CInline_ExpandExpression(expr->data.monadic); - break; - - case EFORCELOAD: - expr->data.monadic = CInline_ExpandExpression(expr->data.monadic); - if (ENODE_IS(expr->data.monadic, EFORCELOAD)) - expr->data.monadic = expr->data.monadic->data.monadic; - break; - - case EMUL: - case EDIV: - case EMODULO: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case EPMODULO: - case EROTL: - case EROTR: - expr->data.diadic.left = CInline_ExpandExpression(expr->data.diadic.left); - expr->data.diadic.right = CInline_ExpandExpression(expr->data.diadic.right); - break; - - case ELAND: - case ELOR: - case ECOMMA: - expr->data.diadic.left = CInline_ExpandExpression(expr->data.diadic.left); - save = cinline_unconditionalpart; - cinline_unconditionalpart = 0; - expr->data.diadic.right = CInline_ExpandExpression(expr->data.diadic.right); - cinline_unconditionalpart = save; - break; - - case EFUNCCALL: - case EFUNCCALLP: - expr->data.funccall.funcref = CInline_ExpandExpression(expr->data.funccall.funcref); - for (list = expr->data.funccall.args; list; list = list->next) - list->node = CInline_ExpandExpression(list->node); - - if (ENODE_IS(expr->data.funccall.funcref, EOBJREF) && CInline_InlineFunctionCheck(expr->data.funccall.funcref)) - expr = CInline_InlineFunctionExpression(expr); - break; - - case ENULLCHECK: - expr->data.nullcheck.nullcheckexpr = CInline_ExpandExpression(expr->data.nullcheck.nullcheckexpr); - save = cinline_unconditionalpart; - cinline_unconditionalpart = 0; - expr->data.nullcheck.condexpr = CInline_ExpandExpression(expr->data.nullcheck.condexpr); - cinline_unconditionalpart = save; - break; - - case EMFPOINTER: - expr->data.mfpointer.accessnode = CInline_ExpandExpression(expr->data.mfpointer.accessnode); - expr->data.mfpointer.mfpointer = CInline_ExpandExpression(expr->data.mfpointer.mfpointer); - break; - - case ECOND: - expr->data.cond.cond = CInline_ExpandExpression(expr->data.cond.cond); - save = cinline_unconditionalpart; - cinline_unconditionalpart = 0; - expr->data.cond.expr1 = CInline_ExpandExpression(expr->data.cond.expr1); - expr->data.cond.expr2 = CInline_ExpandExpression(expr->data.cond.expr2); - cinline_unconditionalpart = save; - break; - - case EMEMBER: - if (expr->data.emember->expr) - expr = CInline_ExpandExpression(expr->data.emember->expr); - else - expr = nullnode(); - break; - - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case EPRECOMP: - case ELABEL: - case EOBJLIST: - case EINSTRUCTION: - case EVECTOR128CONST: - break; - - default: - CError_FATAL(2235); - } - - return expr; -} - -static Statement *CInline_NewStatement(StatementType sttype) { - Statement *stmt = lalloc(sizeof(Statement)); - memclrw(stmt, sizeof(Statement)); - - stmt->type = sttype; - if (cinline_serial_stmt) - cinline_cur_serial_stmt->next = stmt; - else - cinline_serial_stmt = stmt; - cinline_cur_serial_stmt = stmt; - - return stmt; -} - -static ENode *CInline_LoadToTemp(ENode *expr, Object **objectptr) { - Object *object; - - object = *objectptr; - if (!object) { - switch (expr->rtype->type) { - case TYPEVOID: - return expr; - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - case TYPESTRUCT: - case TYPECLASS: - case TYPEMEMBERPOINTER: - case TYPEPOINTER: - object = create_temp_object(expr->rtype); - *objectptr = object; - break; - default: - CError_FATAL(2288); - } - } - - return makediadicnode(create_objectnode(object), expr, EASS); -} - -static ENode *CInline_SerializeEFORCELOAD(ENode *expr) { - Statement *stmt; - Object *temp = NULL; - - while (ENODE_IS(expr->data.monadic, EFORCELOAD)) { - expr->data.monadic = expr->data.monadic->data.monadic; - } - - expr->data.monadic = CInline_SerializeExpr(expr->data.monadic); - stmt = CInline_NewStatement(ST_EXPRESSION); - stmt->expr = CInline_LoadToTemp(expr->data.monadic, &temp); - return create_objectnode(temp); -} - -static ENode *CInline_SerializeECOMMA(ENode *expr) { - Statement *stmt; - - expr->data.diadic.left = CInline_SerializeExpr(expr->data.diadic.left); - stmt = CInline_NewStatement(ST_EXPRESSION); - stmt->expr = expr->data.diadic.left; - return CInline_SerializeExpr(expr->data.diadic.right); -} - -static ENode *CInline_SerializeELOR(ENode *expr) { - ENode *n; - Statement *stmt; - CLabel *label; - Object *temp = NULL; - - label = newlabel(); - - n = makemonadicnode(CInline_SerializeExpr(expr->data.diadic.left), ELOGNOT); - n->rtype = expr->rtype; - n = makemonadicnode(n, ELOGNOT); - n = CInline_LoadToTemp(n, &temp); - stmt = CInline_NewStatement(ST_IFGOTO); - stmt->expr = n; - stmt->label = label; - - n = makemonadicnode(CInline_SerializeExpr(expr->data.diadic.right), ELOGNOT); - n->rtype = expr->rtype; - n = makemonadicnode(n, ELOGNOT); - n = CInline_LoadToTemp(n, &temp); - stmt = CInline_NewStatement(ST_EXPRESSION); - stmt->expr = n; - - stmt = CInline_NewStatement(ST_LABEL); - stmt->label = label; - label->stmt = stmt; - - return create_objectnode(temp); -} - -static ENode *CInline_SerializeELAND(ENode *expr) { - ENode *n; - Statement *stmt; - CLabel *label; - Object *temp = NULL; - - label = newlabel(); - - n = makemonadicnode(CInline_SerializeExpr(expr->data.diadic.left), ELOGNOT); - n->rtype = expr->rtype; - n = makemonadicnode(n, ELOGNOT); - n = CInline_LoadToTemp(n, &temp); - stmt = CInline_NewStatement(ST_IFNGOTO); - stmt->expr = n; - stmt->label = label; - - n = makemonadicnode(CInline_SerializeExpr(expr->data.diadic.right), ELOGNOT); - n->rtype = expr->rtype; - n = makemonadicnode(n, ELOGNOT); - n = CInline_LoadToTemp(n, &temp); - stmt = CInline_NewStatement(ST_EXPRESSION); - stmt->expr = n; - - stmt = CInline_NewStatement(ST_LABEL); - stmt->label = label; - label->stmt = stmt; - - return create_objectnode(temp); -} - -static ENode *CInline_SerializeEPRECOMP(ENode *expr) { - UIDTemp *uidtemp; - - uidtemp = cinline_uid_temps; - while (1) { - if (!uidtemp) - CError_FATAL(2449); - if (uidtemp->uid == expr->data.precompid) - return create_objectnode(uidtemp->object); - uidtemp = uidtemp->next; - } -} - -static ENode *CInline_SerializeENULLCHECK(ENode *expr) { - Statement *stmt; - CLabel *label; - ENode *n; - Object *temp = NULL; - UIDTemp uidtemp; - - label = newlabel(); - - n = CInline_SerializeExpr(expr->data.nullcheck.nullcheckexpr); - stmt = CInline_NewStatement(ST_IFNGOTO); - stmt->expr = CInline_LoadToTemp(n, &temp); - stmt->label = label; - - uidtemp.next = cinline_uid_temps; - uidtemp.object = temp; - uidtemp.uid = expr->data.nullcheck.precompid; - cinline_uid_temps = &uidtemp; - - n = CInline_SerializeExpr(expr->data.nullcheck.condexpr); - stmt = CInline_NewStatement(ST_EXPRESSION); - stmt->expr = CInline_LoadToTemp(n, &temp); - - cinline_uid_temps = uidtemp.next; - - stmt = CInline_NewStatement(ST_LABEL); - stmt->label = label; - label->stmt = stmt; - - return create_objectnode(temp); -} - -static ENode *CInline_SerializeECOND(ENode *expr) { - Statement *stmt; - CLabel *label1; - CLabel *label2; - ENode *n; - Object *temp = NULL; - - label1 = newlabel(); - label2 = newlabel(); - - n = CInline_SerializeExpr(expr->data.cond.cond); - stmt = CInline_NewStatement(ST_IFNGOTO); - stmt->expr = n; - stmt->label = label1; - - n = CInline_SerializeExpr(expr->data.cond.expr1); - n = CInline_LoadToTemp(n, &temp); - stmt = CInline_NewStatement(ST_EXPRESSION); - stmt->expr = n; - - stmt = CInline_NewStatement(ST_GOTO); - stmt->label = label2; - - stmt = CInline_NewStatement(ST_LABEL); - stmt->label = label1; - label1->stmt = stmt; - - n = CInline_SerializeExpr(expr->data.cond.expr2); - n = CInline_LoadToTemp(n, &temp); - stmt = CInline_NewStatement(ST_EXPRESSION); - stmt->expr = n; - - stmt = CInline_NewStatement(ST_LABEL); - stmt->label = label2; - label2->stmt = stmt; - - if (!temp) { - n = nullnode(); - n->rtype = &stvoid; - return n; - } - - return create_objectnode(temp); -} - -static ENode *CInline_SerializeExpr(ENode *expr) { - ENodeList *list; - - switch (expr->type) { - case EFORCELOAD: - return CInline_SerializeEFORCELOAD(expr); - case ECOMMA: - return CInline_SerializeECOMMA(expr); - case ELAND: - return CInline_SerializeELAND(expr); - case ELOR: - return CInline_SerializeELOR(expr); - case EPRECOMP: - return CInline_SerializeEPRECOMP(expr); - case ENULLCHECK: - return CInline_SerializeENULLCHECK(expr); - case ECOND: - return CInline_SerializeECOND(expr); - - case EINITTRYCATCH: - expr->data.itc.initexpr = CInline_SerializeExpr(expr->data.itc.initexpr); - expr->data.itc.tryexpr = CInline_SerializeExpr(expr->data.itc.tryexpr); - expr->data.itc.catchexpr = CInline_SerializeExpr(expr->data.itc.catchexpr); - expr->data.itc.result = CInline_SerializeExpr(expr->data.itc.result); - return expr; - - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EINDIRECT: - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case ETYPCON: - case EBITFIELD: - expr->data.monadic = CInline_SerializeExpr(expr->data.monadic); - return expr; - - case EMUL: - case EDIV: - case EMODULO: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case EPMODULO: - case EROTL: - case EROTR: - expr->data.diadic.left = CInline_SerializeExpr(expr->data.diadic.left); - expr->data.diadic.right = CInline_SerializeExpr(expr->data.diadic.right); - return expr; - - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case ELABEL: - case EOBJLIST: - case EINSTRUCTION: - case EVECTOR128CONST: - return expr; - - case EFUNCCALL: - case EFUNCCALLP: - expr->data.funccall.funcref = CInline_SerializeExpr(expr->data.funccall.funcref); - for (list = expr->data.funccall.args; list; list = list->next) - list->node = CInline_SerializeExpr(list->node); - return expr; - - case EMFPOINTER: - // bug??? - expr->data.mfpointer.accessnode = CInline_SerializeExpr(expr->data.mfpointer.accessnode); - expr->data.mfpointer.accessnode = CInline_SerializeExpr(expr->data.mfpointer.mfpointer); - return expr; - - case EMEMBER: - if (expr->data.emember->expr) - return CInline_SerializeExpr(expr->data.emember->expr); - return expr; - - default: - CError_FATAL(2684); - return expr; - } -} - -void CInline_SerializeStatement(Statement *stmt) { - Statement *scan; - Statement *copy; - - cinline_serial_stmt = NULL; - cinline_uid_temps = NULL; - stmt->expr = CInline_SerializeExpr(stmt->expr); - - if (cinline_serial_stmt) { - for (scan = cinline_serial_stmt; scan; scan = scan->next) { - scan->value = stmt->value; - scan->dobjstack = stmt->dobjstack; - scan->sourceoffset = stmt->sourceoffset; - scan->sourcefilepath = stmt->sourcefilepath; - } - - copy = CInline_NewStatement(ST_EXPRESSION); - *copy = *stmt; - - *stmt = *cinline_serial_stmt; - } -} - -static void CInline_UnpackSwitch(Statement *stmt, CI_Statement *packstmt, CLabel **labels) { - SwitchInfo *info; - SwitchCase *swcase; - short i; - - info = lalloc(sizeof(SwitchInfo)); - stmt->label = (CLabel *) info; - CError_ASSERT(2730, info->defaultlabel = labels[packstmt->u.switchdata->defaultlabelID]); - info->x8 = packstmt->u.switchdata->unkSwitch8; - - for (i = 0; i < packstmt->u.switchdata->numcases; i++) { - if (i == 0) { - swcase = lalloc(sizeof(SwitchCase)); - info->cases = swcase; - } else { - swcase->next = lalloc(sizeof(SwitchCase)); - swcase = swcase->next; - } - - swcase->next = NULL; - swcase->min = packstmt->u.switchdata->cases[i].min; - swcase->max = packstmt->u.switchdata->cases[i].max; - CError_ASSERT(2740, swcase->label = labels[packstmt->u.switchdata->cases[i].labelID]); - } -} - -Object *CInline_GetLocalObj(SInt32 id, Boolean flag) { - ObjectList *list; - - if (id) { - if (id & 0x80000000) { - id = (id & 0x7FFFFFFF) - 1; - if (flag) { - CError_ASSERT(2761, local_aobjects[id].object); - return local_aobjects[id].object; - } - - for (list = arguments; list; list = list->next, id--) { - if (id == 0) - return list->object; - } - - CError_FATAL(2765); - } else { - id--; - if (flag) { - CError_ASSERT(2772, local_dobjects[id]); - return local_dobjects[id]; - } - - for (list = locals; list; list = list->next, id--) { - if (id == 0) - return list->object; - } - - CError_FATAL(2776); - } - } - - return NULL; -} - -static ExceptionAction *CInline_UnpackActions(CI_Statement *packstmt, Boolean flag) { - ExceptionAction *packexc; - ExceptionAction *last; - ExceptionAction *exc; - - packexc = packstmt->dobjstack; - last = NULL; - - while (packexc) { - exc = galloc(sizeof(ExceptionAction)); - exc->prev = last; - last = exc; - - exc->type = packexc->type; - - switch (packexc->type) { - case EAT_DESTROYLOCAL: - exc->data.destroy_local.local = CInline_GetLocalObj((SInt32) packexc->data.destroy_local.local, flag); - exc->data.destroy_local.dtor = packexc->data.destroy_local.dtor; - break; - case EAT_DESTROYLOCALCOND: - exc->data.destroy_local_cond.local = CInline_GetLocalObj((SInt32) packexc->data.destroy_local_cond.local, flag); - exc->data.destroy_local_cond.dtor = packexc->data.destroy_local_cond.dtor; - exc->data.destroy_local_cond.cond = CInline_GetLocalObj((SInt32) packexc->data.destroy_local_cond.cond, flag); - break; - case EAT_DESTROYLOCALOFFSET: - exc->data.destroy_local_offset.local = CInline_GetLocalObj((SInt32) packexc->data.destroy_local_offset.local, flag); - exc->data.destroy_local_offset.dtor = packexc->data.destroy_local_offset.dtor; - exc->data.destroy_local_offset.offset = packexc->data.destroy_local_offset.offset; - break; - case EAT_DESTROYLOCALPOINTER: - exc->data.destroy_local_pointer.pointer = CInline_GetLocalObj((SInt32) packexc->data.destroy_local_pointer.pointer, flag); - exc->data.destroy_local_pointer.dtor = packexc->data.destroy_local_pointer.dtor; - break; - case EAT_DESTROYLOCALARRAY: - exc->data.destroy_local_array.localarray = CInline_GetLocalObj((SInt32) packexc->data.destroy_local_array.localarray, flag); - exc->data.destroy_local_array.dtor = packexc->data.destroy_local_array.dtor; - exc->data.destroy_local_array.elements = packexc->data.destroy_local_array.elements; - exc->data.destroy_local_array.element_size = packexc->data.destroy_local_array.element_size; - break; - case EAT_DESTROYPARTIALARRAY: - exc->data.destroy_partial_array.arraypointer = CInline_GetLocalObj((SInt32) packexc->data.destroy_partial_array.arraypointer, flag); - exc->data.destroy_partial_array.arraycounter = CInline_GetLocalObj((SInt32) packexc->data.destroy_partial_array.arraycounter, flag); - exc->data.destroy_partial_array.dtor = CInline_GetLocalObj((SInt32) packexc->data.destroy_partial_array.dtor, flag); - exc->data.destroy_partial_array.element_size = CInline_GetLocalObj((SInt32) packexc->data.destroy_partial_array.element_size, flag); - break; - case EAT_DESTROYMEMBER: - case EAT_DESTROYBASE: - exc->data.destroy_member.objectptr = CInline_GetLocalObj((SInt32) packexc->data.destroy_member.objectptr, flag); - exc->data.destroy_member.dtor = packexc->data.destroy_member.dtor; - exc->data.destroy_member.offset = packexc->data.destroy_member.offset; - break; - case EAT_DESTROYMEMBERCOND: - exc->data.destroy_member_cond.objectptr = CInline_GetLocalObj((SInt32) packexc->data.destroy_member_cond.objectptr, flag); - exc->data.destroy_member_cond.cond = CInline_GetLocalObj((SInt32) packexc->data.destroy_member_cond.cond, flag); - exc->data.destroy_member_cond.dtor = packexc->data.destroy_member_cond.dtor; - exc->data.destroy_member_cond.offset = packexc->data.destroy_member_cond.offset; - break; - case EAT_DESTROYMEMBERARRAY: - exc->data.destroy_member_array.objectptr = CInline_GetLocalObj((SInt32) packexc->data.destroy_member_array.objectptr, flag); - exc->data.destroy_member_array.dtor = packexc->data.destroy_member_array.dtor; - exc->data.destroy_member_array.offset = packexc->data.destroy_member_array.offset; - exc->data.destroy_member_array.elements = packexc->data.destroy_member_array.elements; - exc->data.destroy_member_array.element_size = packexc->data.destroy_member_array.element_size; - break; - case EAT_DELETEPOINTER: - case EAT_DELETELOCALPOINTER: - exc->data.delete_pointer.pointerobject = CInline_GetLocalObj((SInt32) packexc->data.delete_pointer.pointerobject, flag); - exc->data.delete_pointer.deletefunc = packexc->data.delete_pointer.deletefunc; - break; - case EAT_DELETEPOINTERCOND: - exc->data.delete_pointer_cond.pointerobject = CInline_GetLocalObj((SInt32) packexc->data.delete_pointer_cond.pointerobject, flag); - exc->data.delete_pointer_cond.deletefunc = packexc->data.delete_pointer_cond.deletefunc; - exc->data.delete_pointer_cond.cond = CInline_GetLocalObj((SInt32) packexc->data.delete_pointer_cond.cond, flag); - break; - case EAT_CATCHBLOCK: { - LabelTrans *trans; - exc->data.catch_block.catch_object = CInline_GetLocalObj((SInt32) packexc->data.catch_block.catch_object, flag); - exc->data.catch_block.catch_info_object = CInline_GetLocalObj((SInt32) packexc->data.catch_block.catch_info_object, flag); - - trans = lalloc(sizeof(LabelTrans)); - trans->next = cinline_label_trans; - cinline_label_trans = trans; - - trans->id = (SInt32) packexc->data.catch_block.catch_label; - trans->labelptr = &exc->data.catch_block.catch_label; - - exc->data.catch_block.catch_typeid = packexc->data.catch_block.catch_typeid; - exc->data.catch_block.catch_type = packexc->data.catch_block.catch_type; - exc->data.catch_block.catch_qual = packexc->data.catch_block.catch_qual; - break; - } - case EAT_ACTIVECATCHBLOCK: - exc->data.active_catch_block.catch_info_object = CInline_GetLocalObj((SInt32) packexc->data.active_catch_block.catch_info_object, flag); - break; - case EAT_SPECIFICATION: { - LabelTrans *trans; - exc->data.specification.unexp_ids = packexc->data.specification.unexp_ids; - exc->data.specification.unexp_id = packexc->data.specification.unexp_id; - - trans = lalloc(sizeof(LabelTrans)); - trans->next = cinline_label_trans; - cinline_label_trans = trans; - - trans->id = (SInt32) packexc->data.specification.unexp_label; - trans->labelptr = &exc->data.specification.unexp_label; - - exc->data.specification.unexp_info_object = CInline_GetLocalObj((SInt32) packexc->data.specification.unexp_info_object, flag); - break; - } - case EAT_TERMINATE: - break; - default: - CError_FATAL(2904); - } - - packexc = packexc->prev; - } - - return last; -} - -static Statement *CInline_ExpandStatements(Object *funcobj, Statement *stmt, CI_FuncData *funcdata, ENode *funccall, CLabel *label, Object *resultobj, Boolean flag) { - CLabel **labels; - CI_Statement *packstmt; - short i; - CI_StmtLink *stmtLinks; - CI_StmtLink *link; - ENode *setupArgs; - Boolean is_result_class_1; - Statement origStmt; - - origStmt = *stmt; - is_result_class_1 = CMach_GetFunctionResultClass(TYPE_FUNC(funcobj->type)) == 1; - - if ((setupArgs = CInline_SetupArgsExpression(funcobj, funcdata, funccall->data.funccall.args))) { - stmt->type = ST_EXPRESSION; - stmt->expr = CInline_FoldConst(setupArgs); - } else { - stmt->type = ST_NOP; - } - - stmtLinks = NULL; - cinline_label_trans = NULL; - - labels = lalloc(sizeof(CLabel *) * funcdata->numstatements); - memclrw(labels, sizeof(CLabel *) * funcdata->numstatements); - - for (i = 0, packstmt = funcdata->statements; i < funcdata->numstatements; i++, packstmt++) { - stmt->next = lalloc(sizeof(Statement)); - stmt = stmt->next; - *stmt = origStmt; - - stmt->type = packstmt->type; - stmt->flags = packstmt->flags; - stmt->value += packstmt->value; - - if (packstmt->dobjstack) { - ExceptionAction *unpacked = CInline_UnpackActions(packstmt, 1); - if (stmt->dobjstack) { - ExceptionAction *scan = unpacked; - while (scan->prev) - scan = scan->prev; - scan->prev = stmt->dobjstack; - } - stmt->dobjstack = unpacked; - } - - switch (stmt->type) { - case ST_NOP: - break; - - case ST_EXPRESSION: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - case ST_GOTOEXPR: - stmt->expr = CInline_FoldConst(CInline_CopyExpression(packstmt->u.expr, CopyMode4)); - break; - - case ST_RETURN: - if (packstmt->u.expr) { - stmt->expr = CInline_FoldConst(CInline_CopyExpression(packstmt->u.expr, CopyMode4)); - if (is_result_class_1) - stmt->expr = makecommaexpression(stmt->expr, CInline_ReturnMemResult(funcobj)); - - if (resultobj) { - stmt->type = ST_EXPRESSION; - stmt->expr = makediadicnode(create_objectnode2(resultobj), stmt->expr, EASS); - } else { - stmt->type = origStmt.type; - if (stmt->type == ST_EXPRESSION && !CInline_ExpressionHasSideEffect(stmt->expr)) - stmt->type = ST_NOP; - } - - if (label) { - stmt->next = lalloc(sizeof(Statement)); - stmt = stmt->next; - *stmt = origStmt; - stmt->type = ST_GOTO; - stmt->label = label; - } - } else { - if (label) { - stmt->type = ST_GOTO; - stmt->label = label; - } else { - stmt->type = ST_NOP; - } - } - break; - - case ST_LABEL: - labels[i] = stmt->label = newlabel(); - stmt->label->stmt = stmt; - break; - - case ST_IFGOTO: - case ST_IFNGOTO: - stmt->expr = CInline_FoldConst(CInline_CopyExpression(packstmt->u.ifgoto.expr, CopyMode4)); - case ST_GOTO: - link = lalloc(sizeof(CI_StmtLink)); - link->next = stmtLinks; - stmtLinks = link; - - link->stmt = stmt; - link->ciStmt = packstmt; - break; - - case ST_SWITCH: - stmt->expr = CInline_FoldConst(CInline_CopyExpression(packstmt->u.switchdata->expr, CopyMode4)); - case ST_ASM: - link = lalloc(sizeof(CI_StmtLink)); - link->next = stmtLinks; - stmtLinks = link; - - link->stmt = stmt; - link->ciStmt = packstmt; - break; - - default: - CError_FATAL(3040); - } - } - - if (label) { - stmt->next = lalloc(sizeof(Statement)); - stmt = stmt->next; - *stmt = origStmt; - - stmt->type = ST_LABEL; - stmt->label = label; - label->stmt = stmt; - - if (flag) { - stmt->next = lalloc(sizeof(Statement)); - stmt = stmt->next; - *stmt = origStmt; - } - } - - while (stmtLinks) { - Statement *linkstmt = stmtLinks->stmt; - packstmt = stmtLinks->ciStmt; - - switch (linkstmt->type) { - case ST_GOTO: - CError_ASSERT(3060, linkstmt->label = labels[packstmt->u.statementnum]); - break; - case ST_IFGOTO: - case ST_IFNGOTO: - CError_ASSERT(3065, linkstmt->label = labels[packstmt->u.ifgoto.statementnum]); - break; - case ST_SWITCH: - CInline_UnpackSwitch(linkstmt, packstmt, labels); - break; - case ST_ASM: - InlineAsm_UnpackAsmStatement(linkstmt, labels, 1, packstmt->u.asmdata.data, packstmt->u.asmdata.size); - break; - default: - CError_FATAL(3076); - } - - stmtLinks = stmtLinks->next; - } - - while (cinline_label_trans) { - CError_ASSERT(3083, *cinline_label_trans->labelptr = labels[cinline_label_trans->id]); - cinline_label_trans = cinline_label_trans->next; - } - - return stmt; -} - -static Statement *CInline_InlineFunctionStatement(Statement *stmt, Boolean *changed) { - Object *object; - CI_FuncData *funcdata; - CLabel *label; - - *changed = 0; - - object = stmt->expr->data.funccall.funcref->data.objref; - if (object->datatype == DALIAS) - object = object->u.alias.object; - - funcdata = object->u.func.u.ifuncdata; - if (!funcdata || funcdata->can_inline < CI_CanInline3) - return stmt; - - if (stmt->type != ST_EXPRESSION) { - short i; - for (i = 0; i < (funcdata->numstatements - 1); i++) { - if (funcdata->statements[i].type == ST_RETURN) - return stmt; - } - - if (funcdata->statements[funcdata->numstatements - 1].type != ST_RETURN) - return stmt; - - label = NULL; - } else { - label = newlabel(); - } - - *changed = 1; - return CInline_ExpandStatements(object, stmt, funcdata, stmt->expr, label, NULL, 0); -} - -static Statement *CInline_ExtractInlineFunction(Statement *stmt) { - ENode *expr; - CI_FuncData *funcdata; - short i; - Object *funcObject; - Object *resultObject; - - for (i = 0; i < cinline_stmtlevelexprs; i++) { - expr = cinline_stmtlevelexpr[i]; - - funcObject = expr->data.funccall.funcref->data.objref; - if (funcObject->datatype == DALIAS) - funcObject = funcObject->u.alias.object; - - if ((funcdata = funcObject->u.func.u.ifuncdata)) { - TypeFunc *tfunc = TYPE_FUNC(funcObject->type); - CError_ASSERT(3141, IS_TYPE_FUNC(tfunc)); - - if (!IS_TYPE_VOID(tfunc->functype)) { - if (CMach_GetFunctionResultClass(TYPE_FUNC(funcObject->type)) == 1) - resultObject = CInline_NewLocalObject(CDecl_NewPointerType(tfunc->functype), 0, 0, 0); - else - resultObject = CInline_NewLocalObject(tfunc->functype, 0, 0, 0); - } else { - resultObject = NULL; - } - - stmt = CInline_ExpandStatements(funcObject, stmt, funcdata, expr, newlabel(), resultObject, 1); - - if (resultObject) - *expr = *create_objectnode2(resultObject); - else - *expr = *nullnode(); - } - } - - return stmt; -} - -static Statement *CInline_ExpandStatement(Statement *stmt) { - Boolean changed; - - do { - changed = 0; - - if ( - stmt->type == ST_EXPRESSION && - ENODE_IS(stmt->expr, EINDIRECT) && - !CParser_IsVolatile(stmt->expr->rtype, ENODE_QUALS(stmt->expr)) - ) - { - stmt->expr = stmt->expr->data.monadic; - changed = 1; - if (ENODE_IS2(stmt->expr, EOBJREF, EBITFIELD)) - stmt->expr = nullnode(); - } - - if (ENODE_IS(stmt->expr, ECOMMA)) { - Statement *newStmt = lalloc(sizeof(Statement)); - *newStmt = *stmt; - - stmt->next = newStmt; - stmt->type = ST_EXPRESSION; - stmt->expr = stmt->expr->data.diadic.left; - newStmt->expr = newStmt->expr->data.diadic.right; - - changed = 1; - } - } while (changed); - - if ( - ENODE_IS2(stmt->expr, EFUNCCALL, EFUNCCALLP) && - ENODE_IS(stmt->expr->data.funccall.funcref, EOBJREF) && - CInline_InlineFunctionCheck(stmt->expr->data.funccall.funcref) - ) - { - stmt = CInline_InlineFunctionStatement(stmt, &changed); - if (changed) { - any_inline_expanded = 1; - return stmt; - } - } - - inline_expanded = 0; - cinline_unconditionalpart = 1; - cinline_serialize_stmt = 0; - cinline_stmtlevelexprs = 0; - stmt->expr = CInline_ExpandExpression(stmt->expr); - - if (cinline_serialize_stmt) { - cinline_unconditionalpart = 1; - cinline_serialize_stmt = 0; - cinline_stmtlevelexprs = 0; - CInline_SerializeStatement(stmt); - stmt->expr = CInline_ExpandExpression(stmt->expr); - } - - if (inline_expanded) { - stmt->expr = CInline_FoldConst(stmt->expr); - any_inline_expanded = 1; - } - - if (cinline_stmtlevelexprs) { - stmt = CInline_ExtractInlineFunction(stmt); - any_inline_expanded = 1; - } - - return stmt; -} - -static void CInline_ForceReverseSearch(ENode *) { - cinline_funccallfound = 1; -} - -static ENode *CInline_ForceReverseEvaluation(ENode *expr) { - ENode *commanodes; - ENodeList *list; - int counter; - ENode *ass; - ENode *inner; - ENode *copy; - - list = expr->data.funccall.args; - counter = 0; - commanodes = NULL; - - while (list) { - cinline_funccallfound = 0; - inner = list->node; - CExpr_SearchExprTree(inner, CInline_ForceReverseSearch, 2, EFUNCCALL, EFUNCCALLP); - - if (cinline_funccallfound && ++counter > 0) { - inner = create_objectrefnode(create_temp_object(inner->rtype)); - copy = lalloc(sizeof(ENode)); - *copy = *inner; - - copy = makemonadicnode(copy, EINDIRECT); - copy->rtype = TPTR_TARGET(copy->rtype); - - inner = makemonadicnode(inner, EINDIRECT); - inner->rtype = TPTR_TARGET(inner->rtype); - - ass = makediadicnode(inner, copy, EASS); - list->node = copy; - - if (commanodes) - commanodes = makediadicnode(ass, commanodes, ECOMMA); - else - commanodes = ass; - } - - list = list->next; - } - - if (commanodes) { - commanodes = makediadicnode(commanodes, expr, ECOMMA); - commanodes->rtype = expr->rtype; - return commanodes; - } - - return expr; -} - -static void CInline_ExportCheck(ENode *expr) { - while (1) { - switch (expr->type) { - case EOBJREF: - CInline_ObjectAddrRef(expr->data.objref); - if (expr->data.objref->datatype == DALIAS) { - CExpr_AliasTransform(expr); - continue; - } - return; - - ENODE_CASE_MONADIC: - expr = expr->data.monadic; - continue; - - ENODE_CASE_DIADIC_ALL: - CInline_ExportCheck(expr->data.diadic.left); - expr = expr->data.diadic.right; - continue; - - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EPRECOMP: - case EINSTRUCTION: - case EVECTOR128CONST: - return; - - case ELABEL: - if (expr->data.label->stmt) - expr->data.label->stmt->flags |= StmtFlag_1; - return; - - case EFUNCCALL: - case EFUNCCALLP: { - ENodeList *list; - TypeClass *tclass; - SInt32 index; - - for (list = expr->data.funccall.args; list; list = list->next) - CInline_ExportCheck(list->node); - - expr = expr->data.funccall.funcref; - if ( - copts.warn_notinlined && - !copts.dontinline && - ENODE_IS(expr, EOBJREF) && - (expr->data.objref->qual & Q_INLINE) && - expr->data.objref->datatype != DINLINEFUNC && - !CParser_IsVirtualFunction(expr->data.objref, &tclass, &index) - ) - CError_Warning(CErrorStr342, expr->data.objref); - - continue; - } - - case ENULLCHECK: - CInline_ExportCheck(expr->data.nullcheck.nullcheckexpr); - expr = expr->data.nullcheck.condexpr; - continue; - - case EMFPOINTER: - *expr = *nullnode(); - continue; - - case ECOND: - CInline_ExportCheck(expr->data.cond.cond); - CInline_ExportCheck(expr->data.cond.expr1); - expr = expr->data.cond.expr2; - continue; - - case EMEMBER: - if (expr->data.emember->expr) { - *expr = *expr->data.emember->expr; - continue; - } - case EOBJLIST: - *expr = *nullnode(); - continue; - - default: - CError_FATAL(3372); - } - } -} - -static void CInline_Expand(Statement *stmt) { - Statement *scan; - - if (!copts.dontinline && copts.inlinelevel >= 0) { - if (copts.inline_bottom_up) { - inline_max_size = copts.inlinemaxsize; - while (inline_max_size > 1 && EstimateExpandedSizeOfFunction(stmt) > copts.inlinemaxtotalsize) - inline_max_size >>= 1; - } - - cinline_level = 0; - while (1) { - any_inline_expanded = 0; - for (scan = stmt; scan; scan = scan->next) { - switch (scan->type) { - case ST_NOP: - case ST_LABEL: - case ST_GOTO: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - case ST_ASM: - break; - case ST_RETURN: - if (!scan->expr) - break; - case ST_EXPRESSION: - case ST_SWITCH: - case ST_IFGOTO: - case ST_IFNGOTO: - case ST_GOTOEXPR: - scan = CInline_ExpandStatement(scan); - break; - default: - CError_FATAL(3438); - } - } - - if (!copts.inline_bottom_up && !any_inline_expanded) - break; - - if (!copts.alwaysinline || copts.inline_bottom_up) { - if (copts.inlinelevel == 0) { - if (copts.inline_bottom_up) { - if ((cinline_level + 1) >= 8) - break; - } else { - if (cinline_level >= 3) - break; - } - } else { - if ((cinline_level + 1) >= copts.inlinelevel) - break; - } - } - - if (CWDisplayLines(cparamblkptr->context, lines) != cwNoErr) - CError_UserBreak(); - - cinline_level++; - } - } - - while (stmt) { - if (stmt->dobjstack) - CExcept_CheckStackRefs(stmt->dobjstack); - - switch (stmt->type) { - case ST_NOP: - case ST_LABEL: - case ST_GOTO: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - case ST_ASM: - break; - case ST_RETURN: - if (!stmt->expr) - break; - case ST_EXPRESSION: - case ST_SWITCH: - case ST_IFGOTO: - case ST_IFNGOTO: - case ST_GOTOEXPR: - CInline_ExportCheck(stmt->expr); - break; - default: - CError_FATAL(3501); - } - - stmt = stmt->next; - } -} - -SInt16 CInline_GetStatementNumber(Statement *first, Statement *stmt) { - SInt16 number = 0; - - while (first) { - if (first == stmt) - return number; - - first = first->next; - number++; - } - - CError_FATAL(3517); - return 0; -} - -static CI_Switch *CInline_PackSwitch(Statement *start, Statement *stmt) { - SwitchInfo *info; - SwitchCase *swcase; - short numcases; - CI_Switch *packed; - - info = (SwitchInfo *) stmt->label; - swcase = info->cases; - numcases = 0; - while (swcase) { - swcase = swcase->next; - numcases++; - } - - packed = galloc(sizeof(CI_Switch) + numcases * sizeof(CI_SwitchCase)); - packed->expr = CInline_CopyExpression(stmt->expr, CopyMode2); - packed->defaultlabelID = CInline_GetStatementNumber(start, info->defaultlabel->stmt); - packed->unkSwitch8 = info->x8; - packed->numcases = numcases; - - for (swcase = info->cases, numcases = 0; swcase; swcase = swcase->next, numcases++) { - packed->cases[numcases].labelID = CInline_GetStatementNumber(start, swcase->label->stmt); - packed->cases[numcases].min = swcase->min; - packed->cases[numcases].max = swcase->max; - } - - return packed; -} - -static UInt8 CInline_CanInline(Object *object, Statement *stmt) { - UInt8 resultClass; - FuncArg *arg; - UInt8 result; - - resultClass = CMach_GetFunctionResultClass(TYPE_FUNC(object->type)); - if ( - resultClass && - (resultClass != 1 || (IS_TYPE_CLASS(TYPE_FUNC(object->type)->functype) && CClass_Destructor(TYPE_CLASS(TYPE_FUNC(object->type)->functype)))) - ) - return CI_CanInline0; - - for (arg = TYPE_FUNC(object->type)->args; arg; arg = arg->next) { - if (arg == &elipsis) - return CI_CanInline0; - if (arg == &oldstyle) - break; - - if (IS_TYPE_CLASS(arg->type) && CClass_Destructor(TYPE_CLASS(arg->type))) - return CI_CanInline0; - } - - result = CI_CanInline6; - - while (stmt) { - if (stmt->dobjstack) - return CI_CanInline3; - - switch (stmt->type) { - case ST_EXPRESSION: - break; - case ST_RETURN: - if (stmt->next || (stmt->expr == NULL && TYPE_FUNC(object->type)->functype != &stvoid)) - result = CI_CanInline3; - break; - default: - result = CI_CanInline3; - } - - stmt = stmt->next; - } - - return result; -} - -static ExceptionAction *CInline_PackActions(Statement *start, Statement *stmt) { - ExceptionAction *exc; - ExceptionAction *last; - ExceptionAction *packexc; - - exc = stmt->dobjstack; - last = NULL; - - while (exc) { - packexc = galloc(sizeof(ExceptionAction)); - packexc->prev = last; - last = packexc; - - packexc->type = exc->type; - - switch (exc->type) { - case EAT_DESTROYLOCAL: - packexc->data.destroy_local.local = (void *) CInline_GetLocalID(exc->data.destroy_local.local); - packexc->data.destroy_local.dtor = exc->data.destroy_local.dtor; - break; - case EAT_DESTROYLOCALCOND: - packexc->data.destroy_local_cond.local = (void *) CInline_GetLocalID(exc->data.destroy_local_cond.local); - packexc->data.destroy_local_cond.dtor = exc->data.destroy_local_cond.dtor; - packexc->data.destroy_local_cond.cond = (void *) CInline_GetLocalID(exc->data.destroy_local_cond.cond); - break; - case EAT_DESTROYLOCALOFFSET: - packexc->data.destroy_local_offset.local = (void *) CInline_GetLocalID(exc->data.destroy_local_offset.local); - packexc->data.destroy_local_offset.dtor = exc->data.destroy_local_offset.dtor; - packexc->data.destroy_local_offset.offset = exc->data.destroy_local_offset.offset; - break; - case EAT_DESTROYLOCALPOINTER: - packexc->data.destroy_local_pointer.pointer = (void *) CInline_GetLocalID(exc->data.destroy_local_pointer.pointer); - packexc->data.destroy_local_pointer.dtor = exc->data.destroy_local_pointer.dtor; - break; - case EAT_DESTROYLOCALARRAY: - packexc->data.destroy_local_array.localarray = (void *) CInline_GetLocalID(exc->data.destroy_local_array.localarray); - packexc->data.destroy_local_array.dtor = exc->data.destroy_local_array.dtor; - packexc->data.destroy_local_array.elements = exc->data.destroy_local_array.elements; - packexc->data.destroy_local_array.element_size = exc->data.destroy_local_array.element_size; - break; - case EAT_DESTROYPARTIALARRAY: - packexc->data.destroy_partial_array.arraypointer = (void *) CInline_GetLocalID(exc->data.destroy_partial_array.arraypointer); - packexc->data.destroy_partial_array.arraycounter = (void *) CInline_GetLocalID(exc->data.destroy_partial_array.arraycounter); - packexc->data.destroy_partial_array.dtor = (void *) CInline_GetLocalID(exc->data.destroy_partial_array.dtor); - packexc->data.destroy_partial_array.element_size = (void *) CInline_GetLocalID(exc->data.destroy_partial_array.element_size); - break; - case EAT_DESTROYMEMBER: - case EAT_DESTROYBASE: - packexc->data.destroy_member.objectptr = (void *) CInline_GetLocalID(exc->data.destroy_member.objectptr); - packexc->data.destroy_member.dtor = exc->data.destroy_member.dtor; - packexc->data.destroy_member.offset = exc->data.destroy_member.offset; - break; - case EAT_DESTROYMEMBERCOND: - packexc->data.destroy_member_cond.objectptr = (void *) CInline_GetLocalID(exc->data.destroy_member_cond.objectptr); - packexc->data.destroy_member_cond.cond = (void *) CInline_GetLocalID(exc->data.destroy_member_cond.cond); - packexc->data.destroy_member_cond.dtor = exc->data.destroy_member_cond.dtor; - packexc->data.destroy_member_cond.offset = exc->data.destroy_member_cond.offset; - break; - case EAT_DESTROYMEMBERARRAY: - packexc->data.destroy_member_array.objectptr = (void *) CInline_GetLocalID(exc->data.destroy_member_array.objectptr); - packexc->data.destroy_member_array.dtor = exc->data.destroy_member_array.dtor; - packexc->data.destroy_member_array.offset = exc->data.destroy_member_array.offset; - packexc->data.destroy_member_array.elements = exc->data.destroy_member_array.elements; - packexc->data.destroy_member_array.element_size = exc->data.destroy_member_array.element_size; - break; - case EAT_DELETEPOINTER: - case EAT_DELETELOCALPOINTER: - packexc->data.delete_pointer.pointerobject = (void *) CInline_GetLocalID(exc->data.delete_pointer.pointerobject); - packexc->data.delete_pointer.deletefunc = exc->data.delete_pointer.deletefunc; - break; - case EAT_DELETEPOINTERCOND: - packexc->data.delete_pointer_cond.pointerobject = (void *) CInline_GetLocalID(exc->data.delete_pointer_cond.pointerobject); - packexc->data.delete_pointer_cond.deletefunc = exc->data.delete_pointer_cond.deletefunc; - packexc->data.delete_pointer_cond.cond = (void *) CInline_GetLocalID(exc->data.delete_pointer_cond.cond); - break; - case EAT_CATCHBLOCK: - packexc->data.catch_block.catch_object = (void *) CInline_GetLocalID(exc->data.catch_block.catch_object); - packexc->data.catch_block.catch_info_object = (void *) CInline_GetLocalID(exc->data.catch_block.catch_info_object); - packexc->data.catch_block.catch_label = (void *) CInline_GetStatementNumber(start->next, exc->data.catch_block.catch_label->stmt); - packexc->data.catch_block.catch_typeid = exc->data.catch_block.catch_typeid; - packexc->data.catch_block.catch_type = exc->data.catch_block.catch_type; - packexc->data.catch_block.catch_qual = exc->data.catch_block.catch_qual; - break; - case EAT_ACTIVECATCHBLOCK: - packexc->data.active_catch_block.catch_info_object = (void *) CInline_GetLocalID(exc->data.active_catch_block.catch_info_object); - packexc->data.active_catch_block.call_dtor = exc->data.active_catch_block.call_dtor; - break; - case EAT_SPECIFICATION: - packexc->data.specification.unexp_ids = exc->data.specification.unexp_ids; - packexc->data.specification.unexp_id = exc->data.specification.unexp_id; - packexc->data.specification.unexp_label = (void *) CInline_GetStatementNumber(start->next, exc->data.specification.unexp_label->stmt); - packexc->data.specification.unexp_info_object = (void *) CInline_GetLocalID(exc->data.specification.unexp_info_object); - break; - case EAT_TERMINATE: - break; - default: - CError_FATAL(3720); - } - - exc = exc->prev; - } - - return last; -} - -void CInline_PackIFunctionData(CI_FuncData *funcdata, Statement *stmt, Object *object) { - ObjectList *list; - CI_Var *var; - Statement *scan; - CI_Statement *packstmt; - int i; - - cinline_first_stmt = stmt->next; - memclrw(funcdata, sizeof(CI_FuncData)); - - funcdata->can_inline = CInline_CanInline(object, stmt->next); - - if (copts.filesyminfo) { - funcdata->fileoffset = cparser_fileoffset; - funcdata->fileoffset.is_inline = 1; - funcdata->symdecloffset = symdecloffset; - funcdata->functionbodyoffset = functionbodyoffset; - funcdata->functionbodypath = functionbodypath; - funcdata->symdeclend = symdeclend; - } - - list = arguments; - i = 0; - while (list) { - list = list->next; - i++; - } - - if ((funcdata->numarguments = i) > 0) { - loc_args = funcdata->arguments = galloc(sizeof(CI_Var) * i); - memclrw(funcdata->arguments, sizeof(CI_Var) * i); - - for (list = arguments, var = funcdata->arguments; list; list = list->next, var++) { - var->name = list->object->name; - var->type = list->object->type; - var->qual = list->object->qual; - var->sflags = CInline_GetObjectSFlags(list->object); - var->xD = 0; - var->xE = 1; - } - } - - list = locals; - i = 0; - while (list) { - if (list->object->datatype == DLOCAL) - i++; - list = list->next; - } - - if ((funcdata->numlocals = i) > 0) { - loc_vars = funcdata->locals = galloc(sizeof(CI_Var) * i); - memclrw(funcdata->locals, sizeof(CI_Var) * i); - - for (list = locals, var = funcdata->locals; list; list = list->next) { - if (list->object->datatype == DLOCAL) { - var->name = list->object->name; - var->type = list->object->type; - var->qual = list->object->qual; - var->sflags = CInline_GetObjectSFlags(list->object); - var->xD = 0; - var->xE = 0; - var++; - } - } - } - - scan = stmt->next; - i = 0; - while (scan) { - scan = scan->next; - i++; - } - - funcdata->numstatements = i; - funcdata->statements = galloc(sizeof(CI_Statement) * i); - - for (scan = stmt->next, packstmt = funcdata->statements; scan; scan = scan->next, packstmt++) { - packstmt->type = scan->type; - packstmt->flags = scan->flags; - packstmt->value = scan->value; - packstmt->dobjstack = CInline_PackActions(stmt, scan); - packstmt->sourceoffset = scan->sourceoffset; - packstmt->sourcefilepath = scan->sourcefilepath; - - switch (scan->type) { - case ST_NOP: - case ST_LABEL: - break; - case ST_EXPRESSION: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - case ST_GOTOEXPR: - packstmt->u.expr = CInline_CopyExpression(scan->expr, CopyMode2); - break; - case ST_RETURN: - if (scan->expr) - packstmt->u.expr = CInline_CopyExpression(scan->expr, CopyMode2); - else - packstmt->u.expr = NULL; - break; - case ST_GOTO: - packstmt->u.statementnum = CInline_GetStatementNumber(stmt->next, scan->label->stmt); - break; - case ST_IFGOTO: - case ST_IFNGOTO: - packstmt->u.ifgoto.expr = CInline_CopyExpression(scan->expr, CopyMode2); - packstmt->u.ifgoto.statementnum = CInline_GetStatementNumber(stmt->next, scan->label->stmt); - break; - case ST_SWITCH: - packstmt->u.switchdata = CInline_PackSwitch(stmt->next, scan); - break; - case ST_ASM: - InlineAsm_PackAsmStatement(scan, stmt->next, &packstmt->u.asmdata.data, &packstmt->u.asmdata.size); - break; - default: - CError_FATAL(3862); - } - } -} - -void CInline_UnpackIFunctionData(Object *object, CI_FuncData *funcdata, Statement *firstStmt) { - CLabel **labels; - CI_Var *var; - ObjectList *last; - Statement *stmt; - CI_Statement *packstmt; - int i; - - cparser_fileoffset = funcdata->fileoffset; - symdecloffset = funcdata->symdecloffset; - functionbodyoffset = funcdata->functionbodyoffset; - functionbodypath = funcdata->functionbodypath; - symdeclend = funcdata->symdeclend; - - for (i = 0, var = funcdata->arguments; i < funcdata->numarguments; i++, var++) { - if (i == 0) { - last = lalloc(sizeof(ObjectList)); - arguments = last; - } else { - last->next = lalloc(sizeof(ObjectList)); - last = last->next; - } - - object = galloc(sizeof(Object)); - memclrw(object, sizeof(Object)); - last->object = object; - last->next = NULL; - - object->otype = OT_OBJECT; - object->access = ACCESSPUBLIC; - object->datatype = DLOCAL; - object->name = var->name; - object->type = var->type; - object->qual = var->qual; - CInline_SetObjectSFlags(object, var->sflags); - CFunc_SetupLocalVarInfo(object); - - if (funcdata->fileoffset.file) { - object->u.var.info->deftoken.tokenfile = funcdata->fileoffset.file; - object->u.var.info->deftoken.tokenoffset = funcdata->functionbodyoffset; - } - } - - for (i = 0, var = funcdata->locals; i < funcdata->numlocals; i++, var++) { - if (i == 0) { - last = lalloc(sizeof(ObjectList)); - locals = last; - } else { - last->next = lalloc(sizeof(ObjectList)); - last = last->next; - } - - object = galloc(sizeof(Object)); - memclrw(object, sizeof(Object)); - last->object = object; - last->next = NULL; - - object->otype = OT_OBJECT; - object->access = ACCESSPUBLIC; - object->datatype = DLOCAL; - object->name = var->name; - object->type = var->type; - object->qual = var->qual; - CInline_SetObjectSFlags(object, var->sflags); - CFunc_SetupLocalVarInfo(object); - - if (funcdata->fileoffset.file) { - object->u.var.info->deftoken.tokenfile = funcdata->fileoffset.file; - object->u.var.info->deftoken.tokenoffset = funcdata->functionbodyoffset; - } - } - - enode_idtrans = NULL; - cinline_label_trans = NULL; - - labels = lalloc(sizeof(CLabel *) * funcdata->numstatements); - memclrw(labels, sizeof(CLabel *) * funcdata->numstatements); - - for (i = 0, stmt = firstStmt, packstmt = funcdata->statements; i < funcdata->numstatements; i++, packstmt++) { - stmt->next = lalloc(sizeof(Statement)); - stmt = stmt->next; - - stmt->type = packstmt->type; - stmt->flags = packstmt->flags; - stmt->value = packstmt->value; - stmt->sourceoffset = packstmt->sourceoffset; - stmt->sourcefilepath = packstmt->sourcefilepath; - stmt->dobjstack = CInline_UnpackActions(packstmt, 0); - stmt->next = NULL; - - switch (stmt->type) { - case ST_NOP: - case ST_GOTO: - case ST_ASM: - break; - case ST_EXPRESSION: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - case ST_GOTOEXPR: - stmt->expr = CInline_CopyExpression(packstmt->u.expr, CopyMode3); - break; - case ST_RETURN: - if (packstmt->u.expr) - stmt->expr = CInline_CopyExpression(packstmt->u.expr, CopyMode3); - else - stmt->expr = NULL; - break; - case ST_LABEL: - labels[i] = stmt->label = newlabel(); - stmt->label->stmt = stmt; - break; - case ST_IFGOTO: - case ST_IFNGOTO: - stmt->expr = CInline_CopyExpression(packstmt->u.ifgoto.expr, CopyMode3); - break; - case ST_SWITCH: - stmt->expr = CInline_CopyExpression(packstmt->u.switchdata->expr, CopyMode3); - break; - default: - CError_FATAL(4017); - } - } - - for (stmt = firstStmt->next, packstmt = funcdata->statements; stmt; stmt = stmt->next, packstmt++) { - switch (stmt->type) { - case ST_GOTO: - CError_ASSERT(4024, stmt->label = labels[packstmt->u.statementnum]); - break; - case ST_IFGOTO: - case ST_IFNGOTO: - CError_ASSERT(4029, stmt->label = labels[packstmt->u.ifgoto.statementnum]); - break; - case ST_SWITCH: - CInline_UnpackSwitch(stmt, packstmt, labels); - break; - case ST_ASM: - InlineAsm_UnpackAsmStatement(stmt, labels, 0, packstmt->u.asmdata.data, packstmt->u.asmdata.size); - break; - } - } - - cinline_first_stmt = firstStmt->next; - - while (cinline_label_trans) { - CError_ASSERT(4045, *cinline_label_trans->labelptr = labels[cinline_label_trans->id]); - cinline_label_trans = cinline_label_trans->next; - } -} - -static void CInline_GenIFunctionCode(Object *object, CI_FuncData *func, UInt8 unk) { - Boolean saveDebugInfo; - CScopeSave saveScope; - Statement firstStmt; - - if (cparamblkptr->precompile != 1 && func) { - ObjGen_SetupSym(); - CScope_SetFunctionScope(object, &saveScope); - CFunc_FuncGenSetup(&firstStmt, object); - CInline_UnpackIFunctionData(object, func, &firstStmt); - - saveDebugInfo = copts.filesyminfo; - if (copts.nosyminline || (!symdecloffset && !symdeclend)) - copts.filesyminfo = 0; - - expanding_function = object; - recursive_inline = 0; - CInline_Expand(&firstStmt); - - if (!anyerrors) { - if (copts.filesyminfo) - CPrep_SetSourceFile(&cparser_fileoffset); - CodeGen_Generator(&firstStmt, object, unk, 0); - } - - CScope_RestoreScope(&saveScope); - copts.filesyminfo = saveDebugInfo; - } -} - -void CInline_AddDefaultFunctionAction(Object *object) { - CI_Action *action; - - for (action = cinline_actionlist; action; action = action->next) { - if (action->obj == object) - return; - } - - action = galloc(sizeof(CI_Action)); - memclrw(action, sizeof(CI_Action)); - - action->actiontype = CI_ActionDefaultFunc; - action->obj = object; - - action->next = cinline_actionlist; - cinline_actionlist = action; -} - -void CInline_AddInlineFunctionAction(Object *object, TypeClass *tclass, FileOffsetInfo *fileoffset, TokenStream *stream, Boolean flag) { - CI_Action *action; - - for (action = flag ? cinline_tactionlist : cinline_actionlist; action; action = action->next) { - if (action->obj == object) - return; - } - - CError_ASSERT(4132, IS_TYPE_FUNC(object->type)); - - TYPE_FUNC(object->type)->flags |= FUNC_IS_TEMPL_INSTANCE; - - action = galloc(sizeof(CI_Action)); - memclrw(action, sizeof(CI_Action)); - - action->actiontype = CI_ActionInlineFunc; - action->obj = object; - action->u.inlinefunc.tclass = tclass; - action->u.inlinefunc.fileoffset = *fileoffset; - action->u.inlinefunc.stream = *stream; - - if (flag) { - action->next = cinline_tactionlist; - cinline_tactionlist = action; - TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_200000; - } else { - action->next = cinline_actionlist; - cinline_actionlist = action; - } -} - -void CInline_AddMemberFunctionAction(Object *object, TemplClass *templ, TemplClassInst *inst, TemplateMember *tmemb) { - CI_Action *action; - - for (action = cinline_tactionlist; action; action = action->next) { - if (action->obj == object) - return; - } - - action = galloc(sizeof(CI_Action)); - memclrw(action, sizeof(CI_Action)); - - action->actiontype = CI_ActionMemberFunc; - action->obj = object; - action->u.memberfunc.templ = templ; - action->u.memberfunc.inst = inst; - action->u.memberfunc.tmemb = tmemb; - - action->next = cinline_tactionlist; - cinline_tactionlist = action; - - TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_200000; -} - -void CInline_AddTemplateFunctionAction(Object *object, TemplateFunction *func, TemplFuncInstance *inst) { - CI_Action *action; - - for (action = cinline_tactionlist; action; action = action->next) { - if (action->obj == object) - return; - } - - action = galloc(sizeof(CI_Action)); - memclrw(action, sizeof(CI_Action)); - - action->actiontype = CI_ActionTemplateFunc; - action->obj = object; - action->u.templatefunc.func = func; - action->u.templatefunc.inst = inst; - - action->next = cinline_tactionlist; - cinline_tactionlist = action; - - TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_200000; -} - -static void CInline_AddFRefList_Object(Object *object) { - ObjectList *list; - - if ( - !(object->datatype == DFUNC || object->datatype == DVFUNC) || - (object->flags & OBJECT_DEFINED) || - IS_TEMPL_FUNC(object->type) - ) - return; - - for (list = cinline_freflist; list; list = list->next) { - if (list->object == object) - return; - } - - list = lalloc(sizeof(ObjectList)); - list->object = object; - list->next = cinline_freflist; - cinline_freflist = list; - - if ((object->qual & Q_INLINE) && object->u.func.u.ifuncdata) - CInline_AddFRefList_InlineFunc(object->u.func.u.ifuncdata); -} - -static void CInline_AddFRefList_ExAction(ExceptionAction *exc) { - while (exc) { - switch (exc->type) { - case EAT_DESTROYLOCAL: - CInline_AddFRefList_Object(exc->data.destroy_local.dtor); - break; - case EAT_DESTROYLOCALCOND: - CInline_AddFRefList_Object(exc->data.destroy_local_cond.dtor); - break; - case EAT_DESTROYLOCALOFFSET: - CInline_AddFRefList_Object(exc->data.destroy_local_offset.dtor); - break; - case EAT_DESTROYLOCALPOINTER: - CInline_AddFRefList_Object(exc->data.destroy_local_pointer.dtor); - break; - case EAT_DESTROYLOCALARRAY: - CInline_AddFRefList_Object(exc->data.destroy_local_array.dtor); - break; - case EAT_DESTROYPARTIALARRAY: - CInline_AddFRefList_Object(exc->data.destroy_partial_array.dtor); - break; - case EAT_DESTROYMEMBER: - case EAT_DESTROYBASE: - CInline_AddFRefList_Object(exc->data.destroy_member.dtor); - break; - case EAT_DESTROYMEMBERCOND: - CInline_AddFRefList_Object(exc->data.destroy_member_cond.dtor); - break; - case EAT_DESTROYMEMBERARRAY: - CInline_AddFRefList_Object(exc->data.destroy_member_array.dtor); - break; - case EAT_DELETEPOINTER: - case EAT_DELETELOCALPOINTER: - CInline_AddFRefList_Object(exc->data.delete_pointer.deletefunc); - break; - case EAT_DELETEPOINTERCOND: - CInline_AddFRefList_Object(exc->data.delete_pointer_cond.deletefunc); - break; - case EAT_CATCHBLOCK: - case EAT_ACTIVECATCHBLOCK: - case EAT_SPECIFICATION: - case EAT_TERMINATE: - break; - default: - CError_FATAL(4307); - } - exc = exc->prev; - } -} - -static void CInline_AddFRefList_ExprCB(ENode *expr) { - CInline_AddFRefList_Object(expr->data.objref); -} - -static void CInline_AddFRefList_Expr(ENode *expr) { - CExpr_SearchExprTree(expr, CInline_AddFRefList_ExprCB, 1, EOBJREF); -} - -static void CInline_AddFRefList_Statement(Statement *stmt) { - while (stmt) { - if (stmt->dobjstack) - CInline_AddFRefList_ExAction(stmt->dobjstack); - - switch (stmt->type) { - case ST_NOP: - case ST_LABEL: - case ST_GOTO: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - case ST_ASM: - break; - case ST_RETURN: - if (!stmt->expr) - break; - case ST_EXPRESSION: - case ST_SWITCH: - case ST_IFGOTO: - case ST_IFNGOTO: - case ST_GOTOEXPR: - CInline_AddFRefList_Expr(stmt->expr); - break; - default: - CError_FATAL(4368); - } - - stmt = stmt->next; - } -} - -static void CInline_AddFRefList_InlineFunc(CI_FuncData *data) { - short i; - CI_Statement *stmt; - ExceptionAction *exc; - - for (i = 0; i < data->numstatements; i++) { - stmt = data->statements + i; - - switch (stmt->type) { - case ST_NOP: - case ST_LABEL: - case ST_GOTO: - case ST_ASM: - break; - case ST_EXPRESSION: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - case ST_GOTOEXPR: - CInline_AddFRefList_Expr(stmt->u.expr); - break; - case ST_RETURN: - if (stmt->u.expr) - CInline_AddFRefList_Expr(stmt->u.expr); - break; - case ST_IFGOTO: - case ST_IFNGOTO: - CInline_AddFRefList_Expr(stmt->u.ifgoto.expr); - break; - case ST_SWITCH: - CInline_AddFRefList_Expr(stmt->u.switchdata->expr); - break; - default: - CError_FATAL(4420); - } - - for (exc = data->statements[i].dobjstack; exc; exc = exc->prev) { - switch (exc->type) { - case EAT_DESTROYLOCAL: - CInline_AddFRefList_Object(exc->data.destroy_local.dtor); - break; - case EAT_DESTROYLOCALCOND: - CInline_AddFRefList_Object(exc->data.destroy_local_cond.dtor); - break; - case EAT_DESTROYLOCALOFFSET: - CInline_AddFRefList_Object(exc->data.destroy_local_offset.dtor); - break; - case EAT_DESTROYLOCALPOINTER: - CInline_AddFRefList_Object(exc->data.destroy_local_pointer.dtor); - break; - case EAT_DESTROYLOCALARRAY: - CInline_AddFRefList_Object(exc->data.destroy_local_array.dtor); - break; - case EAT_DESTROYPARTIALARRAY: - break; - case EAT_DESTROYMEMBER: - case EAT_DESTROYBASE: - CInline_AddFRefList_Object(exc->data.destroy_member.dtor); - break; - case EAT_DESTROYMEMBERCOND: - CInline_AddFRefList_Object(exc->data.destroy_member_cond.dtor); - break; - case EAT_DESTROYMEMBERARRAY: - CInline_AddFRefList_Object(exc->data.destroy_member_array.dtor); - break; - case EAT_DELETEPOINTER: - case EAT_DELETELOCALPOINTER: - CInline_AddFRefList_Object(exc->data.delete_pointer.deletefunc); - break; - case EAT_DELETEPOINTERCOND: - CInline_AddFRefList_Object(exc->data.delete_pointer_cond.deletefunc); - break; - case EAT_CATCHBLOCK: - case EAT_ACTIVECATCHBLOCK: - case EAT_SPECIFICATION: - case EAT_TERMINATE: - break; - default: - CError_FATAL(4470); - } - } - } -} - -static void CInline_GenerateTemplateInline(Object *object) { - CI_Action **ptr; - CI_Action *action; - - ptr = &cinline_tactionlist; - while ((action = *ptr)) { - if (object == action->obj) { - *ptr = action->next; - action->next = cinline_actionlist; - cinline_actionlist = action; - - TYPE_FUNC(object->type)->flags &= ~FUNC_FLAGS_200000; - return; - } - - ptr = &action->next; - } - - CError_FATAL(4499); -} - -void CInline_ObjectAddrRef(Object *object) { - CI_FuncData *funcdata; - - object->flags |= OBJECT_FLAGS_2; - - switch (object->datatype) { - case DFUNC: - case DVFUNC: - if ( - (object->qual & Q_INLINE) && - (funcdata = object->u.func.u.ifuncdata) && - !(object->flags & OBJECT_DEFINED) && - !(TYPE_FUNC(object->type)->flags & FUNC_IS_TEMPL) - ) - { - CI_Export *export = galloc(sizeof(CI_Export)); - - export->object = object; - export->funcdata = funcdata; - export->xC = 0; - - export->next = cinline_exportlist; - cinline_exportlist = export; - - object->flags |= OBJECT_DEFINED; - return; - } - else if ( - (TYPE_FUNC(object->type)->flags & FUNC_AUTO_GENERATED) && - !(TYPE_FUNC(object->type)->flags & FUNC_DEFINED) - ) - { - CInline_AddDefaultFunctionAction(object); - return; - } - else if (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_200000) - { - CInline_GenerateTemplateInline(object); - return; - } - return; - - case DALIAS: - CInline_ObjectAddrRef(object->u.alias.object); - return; - - case DDATA: - if (object->qual & Q_INLINE_DATA) - CInit_ExportConst(object); - - if (object->flags & OBJECT_LAZY) { - object->flags &= ~OBJECT_LAZY; - CParser_CallBackAction(object); - } - return; - } -} - -static Boolean CInline_CheckDependencies(ObjectList *list) { - Object *object; - Boolean result; - - result = 0; - - while (list) { - object = list->object; - - if ( - (TYPE_FUNC(object->type)->flags & FUNC_AUTO_GENERATED) && - !(TYPE_FUNC(object->type)->flags & FUNC_DEFINED) - ) - { - CInline_AddDefaultFunctionAction(object); - result = 1; - } - else if ( - (object->qual & Q_IS_TEMPLATED) && - CTempl_InlineFunctionCheck(object) - ) - { - result = 1; - } - else { - CI_Action *action; - for (action = cinline_actionlist; action; action = action->next) { - if (object == action->obj) { - result = 1; - break; - } - } - - if (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_200000) { - CInline_GenerateTemplateInline(object); - result = 1; - } - } - - list = list->next; - } - - return result; -} - -static Boolean CInline_IsSmallFunction(Object *object, Statement *stmt) { - SInt32 statementCount; - ObjectList *list; - SInt32 localSize; - - statementCount = 0; - while (stmt) { - if (stmt->type != ST_NOP && stmt->type != ST_LABEL) - statementCount++; - if (statementCount > 15) - return 0; - stmt = stmt->next; - } - - for (list = locals, localSize = 0; list; list = list->next) - localSize += list->object->type->size; - - if (localSize > 1024) - return 0; - - return 1; -} - -static Boolean CInline_NoFPLocals(void) { - ObjectList *list; - - for (list = locals; list; list = list->next) { - if (IS_TYPE_FLOAT(list->object->type)) - return 0; - } - - return 1; -} - -void CInline_GenFunc(Statement *stmt, Object *object, UInt8 unk) { - CI_FuncData *funcdata; - CI_Export *export; - Boolean flag24; - Boolean flag30; - - TYPE_FUNC(object->type)->flags |= OBJECT_FLAGS_2; - - flag24 = 0; - flag30 = 0; - if (!(object->qual & Q_INLINE)) { - if ( - copts.auto_inline && - !copts.dontinline && - CInline_CanInline(object, stmt->next) && - CInline_IsSmallFunction(object, stmt->next) - ) - { - flag24 = 1; - flag30 = 1; - TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_800; - } - } else { - flag30 = 1; - } - - if (flag30) { - COpt_SimpleOptimizer(object, stmt); - - funcdata = galloc(sizeof(CI_FuncData)); - CInline_PackIFunctionData(funcdata, stmt, object); - - object->u.func.u.ifuncdata = funcdata; - - if (!flag24 && !(object->flags & OBJECT_FLAGS_2)) { - if (cinline_gendeps) { - cinline_freflist = NULL; - CInline_AddFRefList_Statement(stmt); - CInline_CheckDependencies(cinline_freflist); - } - return; - } - } - - object->flags |= OBJECT_DEFINED; - - cinline_freflist = NULL; - CInline_AddFRefList_Statement(stmt); - - if (CInline_CheckDependencies(cinline_freflist) || copts.defer_codegen) { - if (!flag30) { - funcdata = galloc(sizeof(CI_FuncData)); - CInline_PackIFunctionData(funcdata, stmt, object); - } else { - funcdata = object->u.func.u.ifuncdata; - } - - export = galloc(sizeof(CI_Export)); - export->object = object; - export->funcdata = funcdata; - export->xC = unk; - - export->next = cinline_exportlist; - cinline_exportlist = export; - - return; - } - - expanding_function = object; - recursive_inline = 0; - CInline_Expand(stmt); - - if (copts.filesyminfo) - CPrep_SetSourceFile(&cparser_fileoffset); - - if (!anyerrors) - CodeGen_Generator(stmt, object, unk, 0); -} - -static void CInline_GenerateDefaultFunc(Object *object) { - TypeClass *tclass; - - CError_ASSERT(4770, TYPE_FUNC(object->type)->flags & FUNC_AUTO_GENERATED); - CError_ASSERT(4771, TYPE_FUNC(object->type)->flags & FUNC_METHOD); - - tclass = TYPE_METHOD(object->type)->theclass; - - if (object == CClass_DefaultConstructor(tclass)) { - if (object->u.func.defargdata) - CABI_MakeDefaultArgConstructor(tclass, object); - else - CABI_MakeDefaultConstructor(tclass, object); - } else if (object == CClass_CopyConstructor(tclass)) { - CABI_MakeDefaultCopyConstructor(tclass, object); - } else if (object == CClass_AssignmentOperator(tclass)) { - CABI_MakeDefaultAssignmentOperator(tclass, object); - } else if (object == CClass_Destructor(tclass)) { - CABI_MakeDefaultDestructor(tclass, object); - } else { - CError_FATAL(4805); - } -} - -static TemplClassInst *CInline_FindNestedTemplInst(TypeClass *tclass) { - NameSpace *nspace; - - while (tclass) { - if ((tclass->flags & CLASS_IS_TEMPL_INST)) - return TEMPL_CLASS_INST(tclass); - - if (!copts.template_patch) - break; - - nspace = tclass->nspace->parent; - tclass = NULL; - while (nspace) { - if (nspace->theclass) { - tclass = nspace->theclass; - break; - } - nspace = nspace->parent; - } - } - - return NULL; -} - -static void CInline_GenerateInlineFunc(CI_Action *action) { - Object *object; - TemplClassInst *inst; - DeclInfo di; - SInt32 streamState; - - object = action->obj; - - CPrep_StreamInsert(&action->u.inlinefunc.stream, &streamState); - cparser_fileoffset = action->u.inlinefunc.fileoffset; - symdecloffset = cparser_fileoffset.tokenline; - - switch ((tk = lex())) { - case ':': - case '{': - case TK_TRY: - break; - default: - CError_FATAL(4860); - } - - symdecltoken = *CPrep_CurStreamElement(); - - TYPE_FUNC(object->type)->flags &= ~FUNC_DEFINED; - if (IS_TYPE_METHOD(object->type) && (inst = CInline_FindNestedTemplInst(TYPE_METHOD(object->type)->theclass))) { - CTempl_ParseInstanceScopeFunction(object, inst, NULL); - } else { - memclrw(&di, sizeof(di)); - if (action->u.inlinefunc.tclass) { - if ((inst = CInline_FindNestedTemplInst(action->u.inlinefunc.tclass))) { - CTempl_ParseInstanceScopeFunction(object, inst, action->u.inlinefunc.tclass); - } else { - CFunc_ParseFuncDef(object, &di, action->u.inlinefunc.tclass, 0, 0, NULL); - } - } else { - CFunc_ParseFuncDef(object, &di, NULL, 0, 0, NULL); - } - } - - CPrep_StreamRemove(&action->u.inlinefunc.stream, &streamState); -} - -Boolean CInline_CanFreeLHeap(void) { - CI_Action *action; - - if (!anyerrors) { - for (action = cinline_actionlist; action; action = action->next) { - if (action->actiontype == CI_ActionInlineFunc) - return 0; - } - } - - return 1; -} - -Boolean CInline_GenerateDeferredFuncs(void) { - CI_Action *action; - CI_Export *export; - - if (!anyerrors) { - if ((action = cinline_actionlist)) { - cinline_actionlist = action->next; - cinline_gendeps = 1; - - switch (action->actiontype) { - case CI_ActionDefaultFunc: - CInline_GenerateDefaultFunc(action->obj); - break; - case CI_ActionInlineFunc: - if (!(action->obj->flags & OBJECT_DEFINED)) - CInline_GenerateInlineFunc(action); - break; - case CI_ActionMemberFunc: - if (!(TYPE_FUNC(action->obj->type)->flags & FUNC_DEFINED)) - CTempl_InstantiateMember( - action->u.memberfunc.templ, action->u.memberfunc.inst, - action->u.memberfunc.tmemb, action->obj, 0); - break; - case CI_ActionTemplateFunc: - if (!(TYPE_FUNC(action->obj->type)->flags & FUNC_DEFINED) && !action->u.templatefunc.inst->is_specialized) - CTempl_GenFuncInstance(action->u.templatefunc.func, action->u.templatefunc.inst, 0); - break; - default: - CError_FATAL(5001); - } - - cinline_gendeps = 0; - return 1; - } else { - if ((export = cinline_exportlist) && !copts.defer_codegen) { - cinline_exportlist = export->next; - CInline_GenIFunctionCode(export->object, export->funcdata, export->xC); - return 1; - } - } - } - - return 0; -} - -static InitExpr *CInline_InitTemplateData(InitExpr *init) { - Statement *stmt; - CLabel *label; - Object *object; - Object *data; - - object = init->object; - - data = CParser_NewCompilerDefDataObject(); - data->type = TYPE(&stsignedchar); - data->name = CParser_NameConcat("__init__", CMangler_GetLinkName(object)->name); - data->qual = Q_WEAK; - CInit_DeclareData(data, NULL, NULL, data->type->size); - - stmt = CFunc_AppendStatement(ST_IFGOTO); - stmt->expr = create_objectnode(data); - label = newlabel(); - stmt->label = label; - - do { - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = CInline_CopyExpression(init->expr, CopyMode0); - init = init->next; - } while (init && init->object == object); - - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = makediadicnode(create_objectnode(data), intconstnode(TYPE(&stsignedchar), 1), EASS); - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = label; - label->stmt = stmt; - - return init; -} - -void CInline_Finish(void) { - NameSpace *nspace; - Boolean saveDebugInfo; - Statement firstStmt; - Statement *stmt; - InitExpr *init; - Boolean doMore; - - if (!init_expressions || anyerrors) - return; - - cinline_freflist = NULL; - - for (init = init_expressions; init; init = init->next) - CInline_AddFRefList_Expr(init->expr); - - CInline_CheckDependencies(cinline_freflist); - - do { - doMore = CInline_GenerateDeferredFuncs(); - } while (doMore); - - nspace = CFunc_FuncGenSetup(&firstStmt, NULL); - saveDebugInfo = copts.filesyminfo; - copts.filesyminfo = 0; - - init = init_expressions; - while (init) { - if (init->object->nspace->theclass && (init->object->nspace->theclass->flags & CLASS_IS_TEMPL_INST)) { - init = CInline_InitTemplateData(init); - } else { - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = CInline_CopyExpression(init->expr, CopyMode0); - init = init->next; - } - } - - CFunc_CodeCleanup(&firstStmt); - - expanding_function = NULL; - recursive_inline = 0; - CInline_Expand(&firstStmt); - - if (!anyerrors) { - if (copts.filesyminfo) - CPrep_SetSourceFile(&cparser_fileoffset); - CodeGen_Generator(&firstStmt, NULL, 0, 1); - } - - cscope_current = nspace->parent; - copts.filesyminfo = saveDebugInfo; -} diff --git a/compiler_and_linker/unsorted/CMachine.c b/compiler_and_linker/unsorted/CMachine.c deleted file mode 100644 index bfa7023..0000000 --- a/compiler_and_linker/unsorted/CMachine.c +++ /dev/null @@ -1,1488 +0,0 @@ -#include "compiler/CMachine.h" -#include "compiler/CClass.h" -#include "compiler/CError.h" -#include "compiler/CInt64.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CompilerTools.h" -#include "compiler/ScanFloat.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -TypeIntegral stbool = {TYPEINT, 1, IT_BOOL}; -TypeIntegral stchar = {TYPEINT, 1, IT_CHAR}; -TypeIntegral stsignedchar = {TYPEINT, 1, IT_SCHAR}; -TypeIntegral stunsignedchar = {TYPEINT, 1, IT_UCHAR}; -TypeIntegral stwchar = {TYPEINT, 4, IT_WCHAR_T}; -TypeIntegral stsignedshort = {TYPEINT, 2, IT_SHORT}; -TypeIntegral stunsignedshort = {TYPEINT, 2, IT_USHORT}; -TypeIntegral stsignedint = {TYPEINT, 4, IT_INT}; -TypeIntegral stunsignedint = {TYPEINT, 4, IT_UINT}; -TypeIntegral stsignedlong = {TYPEINT, 4, IT_LONG}; -TypeIntegral stunsignedlong = {TYPEINT, 4, IT_ULONG}; -TypeIntegral stsignedlonglong = {TYPEINT, 8, IT_LONGLONG}; -TypeIntegral stunsignedlonglong = {TYPEINT, 8, IT_ULONGLONG}; -TypeIntegral stfloat = {TYPEFLOAT, 4, IT_FLOAT}; -TypeIntegral stshortdouble = {TYPEFLOAT, 8, IT_SHORTDOUBLE}; -TypeIntegral stdouble = {TYPEFLOAT, 8, IT_DOUBLE}; -TypeIntegral stlongdouble = {TYPEFLOAT, 8, IT_LONGDOUBLE}; - -static StructMember stVUC_unsignedchar15 = {NULL, (Type *) &stunsignedchar, NULL, 15, 0}; -static StructMember stVUC_unsignedchar14 = {&stVUC_unsignedchar15, (Type *) &stunsignedchar, NULL, 14, 0}; -static StructMember stVUC_unsignedchar13 = {&stVUC_unsignedchar14, (Type *) &stunsignedchar, NULL, 13, 0}; -static StructMember stVUC_unsignedchar12 = {&stVUC_unsignedchar13, (Type *) &stunsignedchar, NULL, 12, 0}; -static StructMember stVUC_unsignedchar11 = {&stVUC_unsignedchar12, (Type *) &stunsignedchar, NULL, 11, 0}; -static StructMember stVUC_unsignedchar10 = {&stVUC_unsignedchar11, (Type *) &stunsignedchar, NULL, 10, 0}; -static StructMember stVUC_unsignedchar9 = {&stVUC_unsignedchar10, (Type *) &stunsignedchar, NULL, 9, 0}; -static StructMember stVUC_unsignedchar8 = {&stVUC_unsignedchar9, (Type *) &stunsignedchar, NULL, 8, 0}; -static StructMember stVUC_unsignedchar7 = {&stVUC_unsignedchar7, (Type *) &stunsignedchar, NULL, 7, 0}; -static StructMember stVUC_unsignedchar6 = {&stVUC_unsignedchar7, (Type *) &stunsignedchar, NULL, 6, 0}; -static StructMember stVUC_unsignedchar5 = {&stVUC_unsignedchar6, (Type *) &stunsignedchar, NULL, 5, 0}; -static StructMember stVUC_unsignedchar4 = {&stVUC_unsignedchar5, (Type *) &stunsignedchar, NULL, 4, 0}; -static StructMember stVUC_unsignedchar3 = {&stVUC_unsignedchar4, (Type *) &stunsignedchar, NULL, 3, 0}; -static StructMember stVUC_unsignedchar2 = {&stVUC_unsignedchar3, (Type *) &stunsignedchar, NULL, 2, 0}; -static StructMember stVUC_unsignedchar1 = {&stVUC_unsignedchar2, (Type *) &stunsignedchar, NULL, 1, 0}; -static StructMember stVUC_unsignedchar0 = {&stVUC_unsignedchar1, (Type *) &stunsignedchar, NULL, 0, 0}; - -static StructMember stVSC_signedchar15 = {NULL, (Type *) &stsignedchar, NULL, 15, 0}; -static StructMember stVSC_signedchar14 = {&stVSC_signedchar15, (Type *) &stsignedchar, NULL, 14, 0}; -static StructMember stVSC_signedchar13 = {&stVSC_signedchar14, (Type *) &stsignedchar, NULL, 13, 0}; -static StructMember stVSC_signedchar12 = {&stVSC_signedchar13, (Type *) &stsignedchar, NULL, 12, 0}; -static StructMember stVSC_signedchar11 = {&stVSC_signedchar12, (Type *) &stsignedchar, NULL, 11, 0}; -static StructMember stVSC_signedchar10 = {&stVSC_signedchar11, (Type *) &stsignedchar, NULL, 10, 0}; -static StructMember stVSC_signedchar9 = {&stVSC_signedchar10, (Type *) &stsignedchar, NULL, 9, 0}; -static StructMember stVSC_signedchar8 = {&stVSC_signedchar9, (Type *) &stsignedchar, NULL, 8, 0}; -static StructMember stVSC_signedchar7 = {&stVSC_signedchar7, (Type *) &stsignedchar, NULL, 7, 0}; -static StructMember stVSC_signedchar6 = {&stVSC_signedchar7, (Type *) &stsignedchar, NULL, 6, 0}; -static StructMember stVSC_signedchar5 = {&stVSC_signedchar6, (Type *) &stsignedchar, NULL, 5, 0}; -static StructMember stVSC_signedchar4 = {&stVSC_signedchar5, (Type *) &stsignedchar, NULL, 4, 0}; -static StructMember stVSC_signedchar3 = {&stVSC_signedchar4, (Type *) &stsignedchar, NULL, 3, 0}; -static StructMember stVSC_signedchar2 = {&stVSC_signedchar3, (Type *) &stsignedchar, NULL, 2, 0}; -static StructMember stVSC_signedchar1 = {&stVSC_signedchar2, (Type *) &stsignedchar, NULL, 1, 0}; -static StructMember stVSC_signedchar0 = {&stVSC_signedchar1, (Type *) &stsignedchar, NULL, 0, 0}; - -static StructMember stVUS_unsignedshort7 = {NULL, (Type *) &stunsignedshort, NULL, 14, 0}; -static StructMember stVUS_unsignedshort6 = {&stVUS_unsignedshort7, (Type *) &stunsignedshort, NULL, 12, 0}; -static StructMember stVUS_unsignedshort5 = {&stVUS_unsignedshort7, (Type *) &stunsignedshort, NULL, 10, 0}; -static StructMember stVUS_unsignedshort4 = {&stVUS_unsignedshort5, (Type *) &stunsignedshort, NULL, 8, 0}; -static StructMember stVUS_unsignedshort3 = {&stVUS_unsignedshort4, (Type *) &stunsignedshort, NULL, 6, 0}; -static StructMember stVUS_unsignedshort2 = {&stVUS_unsignedshort3, (Type *) &stunsignedshort, NULL, 4, 0}; -static StructMember stVUS_unsignedshort1 = {&stVUS_unsignedshort2, (Type *) &stunsignedshort, NULL, 2, 0}; -static StructMember stVUS_unsignedshort0 = {&stVUS_unsignedshort1, (Type *) &stunsignedshort, NULL, 0, 0}; - -static StructMember stVSS_signedshort7 = {NULL, (Type *) &stsignedshort, NULL, 14, 0}; -static StructMember stVSS_signedshort6 = {&stVSS_signedshort7, (Type *) &stsignedshort, NULL, 12, 0}; -static StructMember stVSS_signedshort5 = {&stVSS_signedshort7, (Type *) &stsignedshort, NULL, 10, 0}; -static StructMember stVSS_signedshort4 = {&stVSS_signedshort5, (Type *) &stsignedshort, NULL, 8, 0}; -static StructMember stVSS_signedshort3 = {&stVSS_signedshort4, (Type *) &stsignedshort, NULL, 6, 0}; -static StructMember stVSS_signedshort2 = {&stVSS_signedshort3, (Type *) &stsignedshort, NULL, 4, 0}; -static StructMember stVSS_signedshort1 = {&stVSS_signedshort2, (Type *) &stsignedshort, NULL, 2, 0}; -static StructMember stVSS_signedshort0 = {&stVSS_signedshort1, (Type *) &stsignedshort, NULL, 0, 0}; - -static StructMember stVUL_unsignedlong3 = {NULL, (Type *) &stunsignedlong, NULL, 12, 0}; -static StructMember stVUL_unsignedlong2 = {&stVUL_unsignedlong3, (Type *) &stunsignedlong, NULL, 8, 0}; -static StructMember stVUL_unsignedlong1 = {&stVUL_unsignedlong2, (Type *) &stunsignedlong, NULL, 4, 0}; -static StructMember stVUL_unsignedlong0 = {&stVUL_unsignedlong1, (Type *) &stunsignedlong, NULL, 0, 0}; - -static StructMember stVSL_signedlong3 = {NULL, (Type *) &stsignedlong, NULL, 12, 0}; -static StructMember stVSL_signedlong2 = {&stVSL_signedlong3, (Type *) &stsignedlong, NULL, 8, 0}; -static StructMember stVSL_signedlong1 = {&stVSL_signedlong2, (Type *) &stsignedlong, NULL, 4, 0}; -static StructMember stVSL_signedlong0 = {&stVSL_signedlong1, (Type *) &stsignedlong, NULL, 0, 0}; - -static StructMember stVF_float3 = {NULL, (Type *) &stfloat, NULL, 12, 0}; -static StructMember stVF_float2 = {&stVF_float3, (Type *) &stfloat, NULL, 8, 0}; -static StructMember stVF_float1 = {&stVF_float2, (Type *) &stfloat, NULL, 4, 0}; -static StructMember stVF_float0 = {&stVF_float1, (Type *) &stfloat, NULL, 0, 0}; - -TypeStruct stvectorunsignedchar = {TYPESTRUCT, 16, NULL, &stVUC_unsignedchar0, STRUCT_VECTOR_UCHAR, 16}; -TypeStruct stvectorsignedchar = {TYPESTRUCT, 16, NULL, &stVSC_signedchar0, STRUCT_VECTOR_SCHAR, 16}; -TypeStruct stvectorboolchar = {TYPESTRUCT, 16, NULL, &stVSC_signedchar0, STRUCT_VECTOR_BCHAR, 16}; - -TypeStruct stvectorunsignedshort = {TYPESTRUCT, 16, NULL, &stVUS_unsignedshort0, STRUCT_VECTOR_USHORT, 16}; -TypeStruct stvectorsignedshort = {TYPESTRUCT, 16, NULL, &stVSS_signedshort0, STRUCT_VECTOR_SSHORT, 16}; -TypeStruct stvectorboolshort = {TYPESTRUCT, 16, NULL, &stVSS_signedshort0, STRUCT_VECTOR_BSHORT, 16}; - -TypeStruct stvectorunsignedlong = {TYPESTRUCT, 16, NULL, &stVUL_unsignedlong0, STRUCT_VECTOR_UINT, 16}; -TypeStruct stvectorsignedlong = {TYPESTRUCT, 16, NULL, &stVSL_signedlong0, STRUCT_VECTOR_SINT, 16}; -TypeStruct stvectorboollong = {TYPESTRUCT, 16, NULL, &stVSL_signedlong0, STRUCT_VECTOR_BINT, 16}; - -TypeStruct stvectorfloat = {TYPESTRUCT, 16, NULL, &stVF_float0, STRUCT_VECTOR_FLOAT, 16}; - -TypeStruct stvectorpixel = {TYPESTRUCT, 16, NULL, &stVUS_unsignedshort0, STRUCT_VECTOR_PIXEL, 16}; - -TypeStruct stvector = {TYPESTRUCT, 16, NULL, NULL, STRUCT_VECTOR_UINT, 16}; - -static SInt32 cmach_structoffset; -static UInt8 cmach_structalign; -static short cmach_curbfsize; -static short cmach_curbfbasesize; -static int cmach_curbfoffset; - -static short cmach_packsize[] = { - 1, 2, 4, 8, 16 -}; - -// forward declarations -static SInt16 CMach_GetQualifiedTypeAlign(Type *type, Boolean flag); -static SInt16 CMach_GetMemberAlignment(Type *type, SInt32 align, Boolean flag); - -void CMach_Configure(void) { -} - -SInt32 CMach_GetQUALalign(UInt32 qual) { - SInt32 result = 0; - UInt32 chk; - - if ((chk = (qual & Q_ALIGNED_MASK))) { - if (chk == Q_ALIGNED_1) - result = 1; - else if (chk == Q_ALIGNED_2) - result = 2; - else if (chk == Q_ALIGNED_4) - result = 4; - else if (chk == Q_ALIGNED_8) - result = 8; - else if (chk == Q_ALIGNED_16) - result = 16; - else if (chk == Q_ALIGNED_32) - result = 32; - else if (chk == Q_ALIGNED_64) - result = 64; - else if (chk == Q_ALIGNED_128) - result = 128; - else if (chk == Q_ALIGNED_256) - result = 256; - else if (chk == Q_ALIGNED_512) - result = 512; - else if (chk == Q_ALIGNED_1024) - result = 1024; - else if (chk == Q_ALIGNED_2048) - result = 2048; - else if (chk == Q_ALIGNED_4096) - result = 4096; - else if (chk == Q_ALIGNED_8192) - result = 8192; - else - CError_FATAL(226); - } - - return result; -} - -SInt32 CMach_ArgumentAlignment(Type *type) { - char save_align_mode; - UInt8 save_oldalignment; - SInt32 align; - - save_align_mode = copts.structalignment; - save_oldalignment = copts.oldalignment; - copts.structalignment = AlignMode2_PPC; - copts.oldalignment = 0; - align = CMach_GetQualifiedTypeAlign(type, 0); - copts.structalignment = save_align_mode; - copts.oldalignment = save_oldalignment; - - if (type->type == TYPESTRUCT && !TYPE_STRUCT(type)->members) { - if (TYPE_STRUCT(type)->align > align) - return TYPE_STRUCT(type)->align; - else - return align; - } else { - return align; - } -} - -// TODO: investigate if this returns SInt16 actually -SInt32 CMach_AllocationAlignment(Type *type, UInt32 qual) { - SInt32 align; - SInt32 qualalign; - SInt32 argalign; - SInt32 anotheralign; - - qualalign = CMach_GetQUALalign(qual); - align = CMach_GetQualifiedTypeAlign(type, 1); - if (qualalign > align) - align = qualalign; - argalign = CMach_ArgumentAlignment(type); - if (argalign > align) - align = argalign; - - switch (type->type) { - case TYPEVOID: - case TYPEMEMBERPOINTER: - case TYPEPOINTER: - anotheralign = 4; - break; - default: - anotheralign = 1; - } - if (anotheralign > align) - align = anotheralign; - - if (copts.optimizationlevel > 0) { - if (type->type == TYPEARRAY || (type->type == TYPESTRUCT && (TYPE_STRUCT(type)->stype < STRUCT_VECTOR_UCHAR || TYPE_STRUCT(type)->stype > STRUCT_VECTOR_PIXEL)) || type->type == TYPECLASS || (type->type == TYPEMEMBERPOINTER && (UInt32) type->size == 12)) { - return (copts.min_struct_alignment > align) ? copts.min_struct_alignment : align; - } - } - - return align; -} - -CInt64 CMach_CalcIntDiadic(Type *type, CInt64 left, short op, CInt64 right) { - if (is_unsigned(type)) { - switch (type->size) { - case 1: - CInt64_ConvertUInt8(&left); - CInt64_ConvertUInt8(&right); - break; - case 2: - CInt64_ConvertUInt16(&left); - CInt64_ConvertUInt16(&right); - break; - case 4: - CInt64_ConvertUInt32(&left); - CInt64_ConvertUInt32(&right); - break; - case 8: - break; - default: - CError_FATAL(327); - } - - switch (op) { - case '*': - left = CInt64_MulU(left, right); - break; - case '/': - if (CInt64_IsZero(&right)) - CError_Warning(CErrorStr139); - else - left = CInt64_DivU(left, right); - break; - case '%': - if (CInt64_IsZero(&right)) - CError_Warning(CErrorStr139); - else - left = CInt64_ModU(left, right); - break; - case '+': - left = CInt64_Add(left, right); - break; - case '-': - left = CInt64_Sub(left, right); - break; - case TK_SHL: - left = CInt64_Shl(left, right); - break; - case TK_SHR: - left = CInt64_ShrU(left, right); - break; - case '<': - CInt64_SetLong(&left, CInt64_LessU(left, right)); - break; - case '>': - CInt64_SetLong(&left, CInt64_GreaterU(left, right)); - break; - case TK_LESS_EQUAL: - CInt64_SetLong(&left, CInt64_LessEqualU(left, right)); - break; - case TK_GREATER_EQUAL: - CInt64_SetLong(&left, CInt64_GreaterEqualU(left, right)); - break; - case TK_LOGICAL_EQ: - CInt64_SetLong(&left, CInt64_Equal(left, right)); - break; - case TK_LOGICAL_NE: - CInt64_SetLong(&left, CInt64_NotEqual(left, right)); - break; - case '&': - left = CInt64_And(left, right); - break; - case '^': - left = CInt64_Xor(left, right); - break; - case '|': - left = CInt64_Or(left, right); - break; - case TK_LOGICAL_AND: - CInt64_SetLong(&left, (!CInt64_IsZero(&left) && !CInt64_IsZero(&right))); - break; - case TK_LOGICAL_OR: - CInt64_SetLong(&left, (!CInt64_IsZero(&left) || !CInt64_IsZero(&right))); - break; - default: - CError_Error(CErrorStr120); - } - - switch (type->size) { - case 1: - CInt64_ConvertUInt8(&left); - break; - case 2: - CInt64_ConvertUInt16(&left); - break; - case 4: - CInt64_ConvertUInt32(&left); - break; - case 8: - break; - } - } else { - switch (type->size) { - case 1: - CInt64_ConvertInt8(&left); - CInt64_ConvertInt8(&right); - break; - case 2: - CInt64_ConvertInt16(&left); - CInt64_ConvertInt16(&right); - break; - case 4: - CInt64_ConvertInt32(&left); - CInt64_ConvertInt32(&right); - break; - case 8: - break; - default: - CError_FATAL(389); - } - - switch (op) { - case '*': - left = CInt64_Mul(left, right); - break; - case '/': - if (CInt64_IsZero(&right)) - CError_Warning(CErrorStr139); - else - left = CInt64_Div(left, right); - break; - case '%': - if (CInt64_IsZero(&right)) - CError_Warning(CErrorStr139); - else - left = CInt64_Mod(left, right); - break; - case '+': - left = CInt64_Add(left, right); - break; - case '-': - left = CInt64_Sub(left, right); - break; - case TK_SHL: - left = CInt64_Shl(left, right); - break; - case TK_SHR: - left = CInt64_Shr(left, right); - break; - case '<': - CInt64_SetLong(&left, CInt64_Less(left, right)); - break; - case '>': - CInt64_SetLong(&left, CInt64_Greater(left, right)); - break; - case TK_LESS_EQUAL: - CInt64_SetLong(&left, CInt64_LessEqual(left, right)); - break; - case TK_GREATER_EQUAL: - CInt64_SetLong(&left, CInt64_GreaterEqual(left, right)); - break; - case TK_LOGICAL_EQ: - CInt64_SetLong(&left, CInt64_Equal(left, right)); - break; - case TK_LOGICAL_NE: - CInt64_SetLong(&left, CInt64_NotEqual(left, right)); - break; - case '&': - left = CInt64_And(left, right); - break; - case '^': - left = CInt64_Xor(left, right); - break; - case '|': - left = CInt64_Or(left, right); - break; - case TK_LOGICAL_AND: - CInt64_SetLong(&left, (!CInt64_IsZero(&left) && !CInt64_IsZero(&right))); - break; - case TK_LOGICAL_OR: - CInt64_SetLong(&left, (!CInt64_IsZero(&left) || !CInt64_IsZero(&right))); - break; - default: - CError_Error(CErrorStr120); - } - - switch (type->size) { - case 1: - CInt64_ConvertInt8(&left); - break; - case 2: - CInt64_ConvertInt16(&left); - break; - case 4: - CInt64_ConvertInt32(&left); - break; - case 8: - break; - } - } - - return left; -} - -CInt64 CMach_CalcIntMonadic(Type *type, short op, CInt64 val) { - if (is_unsigned(type)) { - switch (type->size) { - case 1: - CInt64_ConvertUInt8(&val); - break; - case 2: - CInt64_ConvertUInt16(&val); - break; - case 4: - CInt64_ConvertUInt32(&val); - break; - case 8: - break; - default: - CError_FATAL(448); - } - - switch (op) { - case '-': - val = CInt64_Neg(val); - break; - case '~': - val = CInt64_Inv(val); - break; - case '!': - val = CInt64_Not(val); - break; - default: - CError_Error(CErrorStr120); - } - - switch (type->size) { - case 1: - CInt64_ConvertUInt8(&val); - break; - case 2: - CInt64_ConvertUInt16(&val); - break; - case 4: - CInt64_ConvertUInt32(&val); - break; - case 8: - break; - } - } else { - switch (type->size) { - case 1: - CInt64_ConvertInt8(&val); - break; - case 2: - CInt64_ConvertInt16(&val); - break; - case 4: - CInt64_ConvertInt32(&val); - break; - case 8: - break; - default: - CError_FATAL(478); - } - - switch (op) { - case '-': - val = CInt64_Neg(val); - break; - case '~': - val = CInt64_Inv(val); - break; - case '!': - val = CInt64_Not(val); - break; - default: - CError_Error(CErrorStr120); - } - - switch (type->size) { - case 1: - CInt64_ConvertInt8(&val); - break; - case 2: - CInt64_ConvertInt16(&val); - break; - case 4: - CInt64_ConvertInt32(&val); - break; - case 8: - break; - } - } - - return val; -} - -CInt64 CMach_CalcIntConvertFromFloat(Type *type, Float fval) { - CInt64 result; - - if ((type->type == TYPEINT || type->type == TYPEENUM) && (type->size == 8)) { - if (is_unsigned(type)) - CInt64_ConvertUFromLongDouble(&result, fval.value); - else - CInt64_ConvertFromLongDouble(&result, fval.value); - } else { - if (is_unsigned(type)) - CInt64_SetULong(&result, fval.value); - else - CInt64_SetLong(&result, fval.value); - } - - return result; -} - -void CMach_InitIntMem(Type *type, CInt64 val, void *mem) { - SInt32 lg; - SInt16 sh; - SInt8 ch; - - switch (type->type) { - case TYPEINT: - switch (type->size) { - case 1: - ch = CInt64_GetULong(&val); - memcpy(mem, &ch, 1); - break; - case 2: - sh = CTool_EndianConvertWord16(CInt64_GetULong(&val)); - memcpy(mem, &sh, 2); - break; - case 4: - lg = CTool_EndianConvertWord32(CInt64_GetULong(&val)); - memcpy(mem, &lg, 4); - break; - case 8: - CTool_EndianConvertWord64(val, mem); - break; - default: - CError_FATAL(566); - } - break; - default: - CError_FATAL(570); - } -} - -void CMach_InitVectorMem(Type *type, MWVector128 val, void *mem, Boolean flag) { - unsigned char uc[16]; - unsigned short us[8]; - unsigned int ul[4]; - float f[4]; - int i; - - switch (type->type) { - case TYPESTRUCT: - switch (TYPE_STRUCT(type)->stype) { - case STRUCT_VECTOR_UCHAR: - case STRUCT_VECTOR_SCHAR: - case STRUCT_VECTOR_BCHAR: - for (i = 0; i < 16; i++) - uc[i] = val.uc[i]; - memcpy(mem, uc, 16); - break; - case STRUCT_VECTOR_USHORT: - case STRUCT_VECTOR_SSHORT: - case STRUCT_VECTOR_BSHORT: - case STRUCT_VECTOR_PIXEL: - for (i = 0; i < 8; i++) - us[i] = val.us[i]; - memcpy(mem, us, 16); - break; - case STRUCT_VECTOR_UINT: - case STRUCT_VECTOR_SINT: - case STRUCT_VECTOR_BINT: - for (i = 0; i < 4; i++) - ul[i] = val.ul[i]; - memcpy(mem, ul, 16); - break; - case STRUCT_VECTOR_FLOAT: - for (i = 0; i < 4; i++) - f[i] = val.f[i]; - memcpy(mem, f, 16); - break; - default: - CError_FATAL(655); - } - break; - default: - CError_FATAL(659); - } -} - -Float CMach_CalcFloatDiadic(Type *type, Float left, short op, Float right) { - switch (op) { - case '+': - left.value += right.value; - break; - case '-': - left.value -= right.value; - break; - case '*': - left.value *= right.value; - break; - case '/': - left.value /= right.value; - break; - default: - CError_FATAL(679); - } - - return CMach_CalcFloatConvert(type, left); -} - -Float CMach_CalcFloatMonadic(Type *type, short op, Float fval) { - if (op != '-') - CError_FATAL(692); - - fval.value = -fval.value; - return CMach_CalcFloatConvert(type, fval); -} - -Boolean CMach_CalcFloatDiadicBool(Type *type, Float left, short op, Float right) { - switch (op) { - case TK_LOGICAL_EQ: - return left.value == right.value; - case TK_LOGICAL_NE: - return left.value != right.value; - case TK_LESS_EQUAL: - return left.value <= right.value; - case TK_GREATER_EQUAL: - return left.value >= right.value; - case '>': - return left.value > right.value; - case '<': - return left.value < right.value; - default: - CError_FATAL(714); - return 0; - } -} - -Boolean CMach_CalcVectorDiadicBool(Type *type, MWVector128 *left, short op, MWVector128 *right) { - switch (op) { - case TK_LOGICAL_EQ: - return (left->ul[0] == right->ul[0]) && (left->ul[1] == right->ul[1]) && (left->ul[2] == right->ul[2]) && (left->ul[3] == right->ul[3]); - case TK_LOGICAL_NE: - return (left->ul[0] != right->ul[0]) && (left->ul[1] != right->ul[1]) && (left->ul[2] != right->ul[2]) && (left->ul[3] != right->ul[3]); - default: - CError_FATAL(740); - return 0; - } -} - -char *CMach_FloatScan(char *input, Float *result, Boolean *fail) { - double resultval; - char *outpos; - - if (!(outpos = ScanFloat(input, &resultval, fail))) - CError_ErrorTerm(CErrorStr154); - - if (*fail) - result->value = 0.0; - else - result->value = resultval; - - return outpos; -} - -Float CMach_CalcFloatConvertFromInt(Type *type, CInt64 val) { - Float result; - - if ((type->type == TYPEINT || type->type == TYPEENUM) && (type->size == 8)) { - if (is_unsigned(type)) - result.value = CInt64_ConvertUToLongDouble(&val); - else - result.value = CInt64_ConvertToLongDouble(&val); - } else { - if (is_unsigned(type)) - result.value = val.lo; - else - result.value = (SInt32) val.lo; - } - - return result; -} - -Float CMach_CalcFloatConvert(Type *type, Float fval) { - switch (type->size) { - case 4: - fval.value = (float) fval.value; - break; - case 8: - fval.value = (double) fval.value; - break; - case 10: - case 12: - break; - default: - CError_FATAL(801); - } - return fval; -} - -Boolean CMach_FloatIsZero(Float fval) { - return fval.value == 0.0; -} - -Boolean CMach_FloatIsOne(Float fval) { - return fval.value == 1.0; -} - -Boolean CMach_FloatIsNegOne(Float fval) { - return fval.value == -1.0; -} - -void CMach_InitFloatMem(Type *type, Float val, void *mem) { - float f; - double d; - - if (type->type == TYPEFLOAT) { - switch (type->size) { - case 4: - f = val.value; - memcpy(mem, &f, 4); - CTool_EndianConvertMem(mem, 4); - return; - case 8: - d = val.value; - memcpy(mem, &d, 8); - CTool_EndianConvertMem(mem, 8); - return; - } - } - - CError_FATAL(866); -} - -void CMach_PrintFloat(char *buf, Float val) { - double f; - CMach_InitFloatMem((Type *) &stshortdouble, val, &f); - sprintf(buf, "%g", f); -} - -void CMach_PragmaParams(void) { - if (copts.warn_illpragma) - CError_Warning(CErrorStr186, 0); - - while (notendofline()) - lex(); -} - -void CMach_AdjustFuntionArgs() { - // not called so we will never know what the args should have been :( -} - -static SInt32 CMach_GetPPCTypeAlign(Type *type, Boolean flag1, Boolean flag2) { - ClassList *base; - ObjMemberVar *ivar; - StructMember *member; - SInt32 best; - SInt32 ivarAlign; - SInt32 qualAlign; - - SInt32 align = CMach_GetQualifiedTypeAlign(type, flag2); - if (align <= 8) { - while (type->type == TYPEARRAY) - type = TYPE_POINTER(type)->target; - - if (flag1) { - if (type->type == TYPEFLOAT && type->size > 4 && align < 8) - return 8; - } else if (align == 8) { - if (type->type == TYPECLASS) { - best = 4; - for (base = TYPE_CLASS(type)->bases; base; base = base->next) { - if (base->base->align > best) - best = base->base->align; - } - for (ivar = TYPE_CLASS(type)->ivars; ivar; ivar = ivar->next) { - ivarAlign = CMach_GetPPCTypeAlign(ivar->type, 0, flag2); - if (ivarAlign > best) - best = ivarAlign; - if (flag2) { - qualAlign = CMach_GetQUALalign(ivar->qual); - if (qualAlign > best) - best = qualAlign; - } - } - return best; - } - if (type->type == TYPESTRUCT) { - best = 4; - for (member = TYPE_STRUCT(type)->members; member; member = member->next) { - ivarAlign = CMach_GetPPCTypeAlign(member->type, 0, flag2); - if (ivarAlign > best) - best = ivarAlign; - if (flag2) { - qualAlign = CMach_GetQUALalign(member->qual); - if (qualAlign > best) - best = qualAlign; - } - } - return best; - } - } - } - - return align; -} - -static SInt16 CMach_GetQualifiedStructAlign(const TypeStruct *tstruct, Boolean flag) { - StructMember *member; - SInt32 best; - SInt32 align; - Boolean isFirst; - - if (tstruct->stype >= STRUCT_VECTOR_UCHAR && tstruct->stype <= STRUCT_VECTOR_PIXEL) - return 16; - - switch (copts.structalignment) { - case AlignMode3_1Byte: - case AlignMode8_Packed: - return 1; - case AlignMode0_Mac68k: - return 2; - case AlignMode1_Mac68k4byte: - return (tstruct->size <= 2) ? 2 : 4; - } - - if (tstruct->size <= 1) - return 1; - - best = 1; - switch (copts.structalignment) { - default: - CError_FATAL(1026); - case AlignMode4_2Byte: - case AlignMode5_4Byte: - case AlignMode6_8Byte: - case AlignMode7_16Byte: - for (member = tstruct->members; member; member = member->next) { - align = CMach_GetQualifiedTypeAlign(member->type, flag); - if (align > best) - best = align; - if (flag) { - align = CMach_GetQUALalign(member->qual); - if (align > best) - best = align; - } - } - return best; - case AlignMode2_PPC: - if (copts.oldalignment) { - for (member = tstruct->members; member; member = member->next) { - align = CMach_GetQualifiedTypeAlign(member->type, flag); - if (align > best) - best = align; - if (flag) { - align = CMach_GetQUALalign(member->qual); - if (align > best) - best = align; - } - } - } else if (TYPE_STRUCT(tstruct)->stype == STRUCT_TYPE_UNION) { - for (member = tstruct->members; member; member = member->next) { - align = CMach_GetPPCTypeAlign(member->type, 1, flag); - if (align > best) - best = align; - if (flag) { - align = CMach_GetQUALalign(member->qual); - if (align > best) - best = align; - } - } - } else { - isFirst = 1; - for (member = tstruct->members; member; member = member->next) { - align = CMach_GetPPCTypeAlign(member->type, isFirst || (best >= 8), flag); - if (align > best) - best = align; - if (flag) { - align = CMach_GetQUALalign(member->qual); - if (align > best) - best = align; - } - isFirst = 0; - } - } - return best; - } -} - -SInt16 CMach_GetStructAlign(TypeStruct *tstruct) { - return CMach_GetQualifiedStructAlign(tstruct, 1); -} - -static SInt16 CMach_GetQualifiedClassAlign(TypeClass *tclass, Boolean flag) { - ClassList *base; - ObjMemberVar *ivar; - SInt32 best; - SInt32 align; - Boolean isFirst; - - switch (copts.structalignment) { - case AlignMode3_1Byte: - case AlignMode8_Packed: - return 1; - case AlignMode0_Mac68k: - return 2; - case AlignMode1_Mac68k4byte: - return (tclass->size <= 2) ? 2 : 4; - } - if (tclass->size <= 1) - return 1; - best = 1; - switch (copts.structalignment) { - default: - CError_FATAL(1149); - case AlignMode4_2Byte: - case AlignMode5_4Byte: - case AlignMode6_8Byte: - case AlignMode7_16Byte: - for (base = tclass->bases; base; base = base->next) { - if ((align = base->base->align) > best) - best = align; - } - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - align = CMach_GetMemberAlignment(ivar->type, flag ? CMach_GetQUALalign(ivar->qual) : 0, flag); - if (align > best) - best = align; - } - return best; - case AlignMode2_PPC: - best = 1; - if (copts.oldalignment) { - for (base = tclass->bases; base; base = base->next) { - if ((align = base->base->align) > best) - best = align; - } - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - align = CMach_GetMemberAlignment(ivar->type, flag ? CMach_GetQUALalign(ivar->qual) : 0, flag); - if (align > best) - best = align; - } - } else { - isFirst = 1; - for (base = tclass->bases; base; base = base->next) { - if ((align = base->base->align) > best) - best = align; - isFirst = 0; - } - if (tclass->mode == 1) { - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - align = CMach_GetPPCTypeAlign(ivar->type, 1, flag); - if (align > best) - best = align; - if (flag) { - align = CMach_GetQUALalign(ivar->qual); - if (align > best) - best = align; - } - } - } else { - for (ivar = tclass->ivars; ivar; ivar = ivar->next) { - if (ivar->offset && align != 8) - isFirst = 0; - align = CMach_GetPPCTypeAlign(ivar->type, isFirst || (best >= 8), flag); - if (align > best) - best = align; - if (flag) { - align = CMach_GetQUALalign(ivar->qual); - if (align > best) - best = align; - } - } - } - } - return best; - } -} - -SInt16 CMach_GetClassAlign(TypeClass *tclass) { - return CMach_GetQualifiedClassAlign(tclass, 1); -} - -static SInt16 CMach_GetWinTypeAlign(Type *type) { - int packoffs = copts.structalignment - 3; - SInt32 align = cmach_packsize[packoffs]; - if (type->size < align) - align = type->size; - return align; -} - -static SInt16 CMach_GetWinMinimizeAlign(SInt16 align) { - int packoffs = copts.structalignment - 3; - SInt16 minimum = cmach_packsize[packoffs]; - if (minimum < align) - align = minimum; - return align; -} - -static SInt16 CMach_GetQualifiedTypeAlign(Type *type, Boolean flag) { - Boolean isWin; - SInt16 align; - - if (type->type == TYPESTRUCT && TYPE_STRUCT(type)->stype >= STRUCT_VECTOR_UCHAR && TYPE_STRUCT(type)->stype <= STRUCT_VECTOR_PIXEL) - return 16; - - switch (copts.structalignment) { - case AlignMode3_1Byte: - case AlignMode8_Packed: - return 1; - case AlignMode4_2Byte: - case AlignMode5_4Byte: - case AlignMode6_8Byte: - case AlignMode7_16Byte: - isWin = 1; - break; - default: - isWin = 0; - break; - } - -restart: - switch (type->type) { - case TYPEVOID: - return 0; - case TYPEFUNC: - return 0; - case TYPEENUM: - type = TYPE_ENUM(type)->enumtype; - case TYPEINT: - if (isWin) - return CMach_GetWinTypeAlign(type); - if (type->size == 1) - return 1; - if (copts.oldalignment && type->size == 8) - return 8; - if (copts.structalignment != AlignMode0_Mac68k && type->size >= 4) - return 4; - return 2; - case TYPEFLOAT: - if (isWin) - return CMach_GetWinTypeAlign(type); - switch (copts.structalignment) { - case AlignMode0_Mac68k: - return 2; - case AlignMode1_Mac68k4byte: - return 4; - case AlignMode2_PPC: - if (copts.oldalignment && type->size > 4) - return 8; - return 4; - default: - CError_FATAL(1346); - } - case TYPEMEMBERPOINTER: - case TYPEPOINTER: - if (isWin) - return CMach_GetWinTypeAlign(type); - if (copts.structalignment == AlignMode0_Mac68k) - return 2; - else - return 4; - case TYPEARRAY: - if (copts.alignarraymembers) { - if (isWin) - return CMach_GetWinTypeAlign(type); - if (type->size == 1) - return 1; - if (copts.structalignment == AlignMode0_Mac68k || type->size <= 2) - return 2; - if (copts.structalignment == AlignMode1_Mac68k4byte || type->size < 8) - return 4; - align = CMach_GetQualifiedTypeAlign(TYPE_POINTER(type)->target, flag); - if (align > 4) - return align; - else - return 4; - } else { - type = TYPE_POINTER(type)->target; - goto restart; - } - case TYPESTRUCT: - if (flag) - align = TYPE_STRUCT(type)->align; - else - align = CMach_GetQualifiedStructAlign(TYPE_STRUCT(type), flag); - if (isWin) - return CMach_GetWinMinimizeAlign(align); - else - return align; - case TYPECLASS: - if (flag) - align = TYPE_CLASS(type)->align; - else - align = CMach_GetQualifiedClassAlign(TYPE_CLASS(type), flag); - if (isWin) - return CMach_GetWinMinimizeAlign(align); - else - return align; - case TYPEBITFIELD: - type = TYPE_BITFIELD(type)->bitfieldtype; - goto restart; - case TYPETEMPLATE: - return 1; - default: - CError_FATAL(1392); - return 0; - } -} - -SInt16 CMach_GetTypeAlign(Type *type) { - return CMach_GetQualifiedTypeAlign(type, 1); -} - -static SInt16 CMach_GetMemberAlignment(Type *type, SInt32 var, Boolean flag) { - SInt32 align; - - align = CMach_GetQualifiedTypeAlign(type, flag); - if (align < 1) - align = 1; - - if (IS_TYPE_VECTOR(type) && align < 16) - align = 16; - - switch (copts.structalignment) { - case AlignMode8_Packed: - align = 1; - break; - case AlignMode0_Mac68k: - if (align > 2) - align = 2; - break; - case AlignMode1_Mac68k4byte: - if (align > 4) - align = 4; - break; - case AlignMode2_PPC: - if (!copts.oldalignment) - align = CMach_GetPPCTypeAlign(type, !cmach_structoffset || (cmach_structalign >= 8), flag); - if (var > align) - align = var; - break; - } - - if (align > cmach_structalign) - cmach_structalign = align; - return align; -} - -SInt16 CMach_MemberAlignValue(Type *type, SInt32 var) { - SInt16 align = CMach_GetMemberAlignment(type, 0, 1); - if (align <= 1) - return 0; - - return (align - 1) & (align - (var & (align - 1))); -} - -static SInt16 MemberAlignValue(Type *type, SInt32 var1, SInt32 var2) { - SInt16 align = CMach_GetMemberAlignment(type, var2, 1); - return (align - 1) & (align - (var1 & (align - 1))); -} - -void CMach_StructLayoutInitOffset(SInt32 offset) { - cmach_structoffset = offset; - cmach_structalign = 4; - cmach_curbfsize = 0; -} - -SInt32 CMach_StructLayoutGetCurSize(void) { - return cmach_structoffset; -} - -SInt32 CMach_StructLayoutGetOffset(Type *type, UInt32 qual) { - SInt32 align; - SInt32 offset; - - qual = CParser_GetTypeQualifiers(type, qual); - - cmach_curbfsize = 0; - align = MemberAlignValue(type, cmach_structoffset, CMach_GetQUALalign(qual)); - offset = cmach_structoffset + align; - cmach_structoffset = offset + type->size; - return offset; -} - -SInt32 CMach_StructLayoutBitfield(TypeBitfield *tbitfield, UInt32 qual) { - SInt16 align; - SInt16 padding_at_start; - SInt16 basesize; - SInt16 basesize_bits; - SInt16 required_alignment; - SInt16 r4; - - padding_at_start = 0; - required_alignment = 0; - align = CMach_GetQUALalign(qual); - if (align <= tbitfield->bitfieldtype->size) - align = 0; - - switch (tbitfield->bitfieldtype->size) { - case 1: - basesize = 1; - basesize_bits = 8; - required_alignment = 0; - break; - case 2: - basesize = 2; - basesize_bits = 16; - required_alignment = 2; - break; - case 4: - if (copts.structalignment != AlignMode0_Mac68k && copts.structalignment != AlignMode4_2Byte) - required_alignment = 4; - else - required_alignment = 2; - basesize = 4; - basesize_bits = 32; - break; - default: - CError_FATAL(1620); - } - - switch (copts.structalignment) { - case AlignMode3_1Byte: - case AlignMode8_Packed: - required_alignment = 0; - break; - } - - r4 = required_alignment; - if (align > required_alignment) - r4 = align; - if (r4 && (cmach_structoffset & (r4 - 1))) - padding_at_start = r4 - (cmach_structoffset & (r4 - 1)); - - if (!cmach_curbfsize) { - cmach_structoffset += padding_at_start; - if (!tbitfield->bitlength) - return cmach_structoffset; - cmach_curbfsize = tbitfield->bitlength; - cmach_curbfbasesize = basesize; - cmach_curbfoffset = cmach_structoffset; - cmach_structoffset += basesize; - tbitfield->offset = 0; - return cmach_curbfoffset; - } else { - if (!tbitfield->bitlength || (cmach_curbfsize + tbitfield->bitlength) > basesize_bits || cmach_curbfbasesize != basesize) { - cmach_structoffset += padding_at_start; - cmach_curbfsize = 0; - cmach_curbfbasesize = basesize; - if (!tbitfield->bitlength) - return cmach_structoffset; - cmach_curbfoffset = cmach_structoffset; - cmach_structoffset += basesize; - } - tbitfield->offset = cmach_curbfsize; - cmach_curbfsize += tbitfield->bitlength; - return cmach_curbfoffset; - } -} - -static Boolean CMach_IsTrivialClass(TypeClass *tclass) { - return !CClass_Constructor(tclass); -} - -UInt8 CMach_GetFunctionResultClass(TypeFunc *tfunc) { - switch (tfunc->functype->type) { - case TYPESTRUCT: - if (tfunc->functype->type == TYPESTRUCT && TYPE_STRUCT(tfunc->functype)->stype >= STRUCT_VECTOR_UCHAR && TYPE_STRUCT(tfunc->functype)->stype <= STRUCT_VECTOR_PIXEL) - return 0; - case TYPECLASS: - case TYPEMEMBERPOINTER: - return CMach_PassResultInHiddenArg(tfunc->functype) != 0; - default: - return 0; - } -} - -Boolean CMach_PassResultInHiddenArg(Type *type) { - switch (type->type) { - case TYPESTRUCT: - if (TYPE_STRUCT(type)->stype >= STRUCT_VECTOR_UCHAR && TYPE_STRUCT(type)->stype <= STRUCT_VECTOR_PIXEL) - return 0; - else - return 1; - case TYPECLASS: - return 1; - case TYPEMEMBERPOINTER: - return (type->size != 4); - default: - return 0; - } -} - -char *CMach_GetCPU(void) { - switch (copts.processor) { - case CPU_PPC401: return "__PPC401__"; - case CPU_PPC403: return "__PPC403__"; - case CPU_PPC505: return "__PPC505__"; - case CPU_PPC509: return "__PPC509__"; - case CPU_PPC555: return "__PPC555__"; - case CPU_PPC556: return "__PPC556__"; - case CPU_PPC565: return "__PPC565__"; - case CPU_PPC601: return "__PPC601__"; - case CPU_PPC602: return "__PPC602__"; - case CPU_PPC603: return "__PPC603__"; - case CPU_PPC603e: return "__PPC603e__"; - case CPU_PPC604: return "__PPC604__"; - case CPU_PPC604e: return "__PPC604e__"; - case CPU_PPC740: return "__PPC740__"; - case CPU_PPC750: return "__PPC750__"; - case CPU_PPC801: return "__PPC801__"; - case CPU_PPC821: return "__PPC821__"; - case CPU_PPC823: return "__PPC823__"; - case CPU_PPC850: return "__PPC850__"; - case CPU_PPC860: return "__PPC860__"; - case CPU_PPC7400: return "__PPC7400__"; - case CPU_PPC7450: return "__PPC7450__"; - case CPU_PPC8240: return "__PPC8240__"; - case CPU_PPC8260: return "__PPC8260__"; - case CPU_PPCGEKKO: return "__PPCGEKKO__"; - case CPU_PPCELF: return "__PPCELF__"; - default: return NULL; - } -} - -Boolean CMach_FloatIsPowerOf2(Float flt) { - return (flt.value == 2.0) || - (flt.value == 4.0) || - (flt.value == 8.0) || - (flt.value == 16.0) || - (flt.value == 32.0) || - (flt.value == 64.0) || - (flt.value == 128.0) || - (flt.value == 256.0) || - (flt.value == 512.0) || - (flt.value == 1024.0); -} - -Float CMach_FloatReciprocal(Float flt) { - flt.value = 1.0 / flt.value; - return flt; -} - -SInt32 CMach_RoundedSizeOf(Object *object) { - SInt32 size = object->type->size; - SInt32 align = CMach_GetTypeAlign(object->type) - 1; - return (size + align) & ~align; -} - -void CMach_ReInitRuntimeObjects(void) { - HashNameNode *e0 = GetHashNameNodeExport("[0]"); - HashNameNode *e1 = GetHashNameNodeExport("[1]"); - HashNameNode *e2 = GetHashNameNodeExport("[2]"); - HashNameNode *e3 = GetHashNameNodeExport("[3]"); - HashNameNode *e4 = GetHashNameNodeExport("[4]"); - HashNameNode *e5 = GetHashNameNodeExport("[5]"); - HashNameNode *e6 = GetHashNameNodeExport("[6]"); - HashNameNode *e7 = GetHashNameNodeExport("[7]"); - HashNameNode *e8 = GetHashNameNodeExport("[8]"); - HashNameNode *e9 = GetHashNameNodeExport("[9]"); - HashNameNode *e10 = GetHashNameNodeExport("[10]"); - HashNameNode *e11 = GetHashNameNodeExport("[11]"); - HashNameNode *e12 = GetHashNameNodeExport("[12]"); - HashNameNode *e13 = GetHashNameNodeExport("[13]"); - HashNameNode *e14 = GetHashNameNodeExport("[14]"); - HashNameNode *e15 = GetHashNameNodeExport("[15]"); - HashNameNode *vuc = GetHashNameNodeExport("vector unsigned char"); - HashNameNode *vus = GetHashNameNodeExport("vector unsigned short"); - HashNameNode *vui = GetHashNameNodeExport("vector unsigned int"); - HashNameNode *vsc = GetHashNameNodeExport("vector signed char"); - HashNameNode *vss = GetHashNameNodeExport("vector signed short"); - HashNameNode *vsi = GetHashNameNodeExport("vector signed int"); - HashNameNode *vbc = GetHashNameNodeExport("vector bool char"); - HashNameNode *vbs = GetHashNameNodeExport("vector bool short"); - HashNameNode *vbi = GetHashNameNodeExport("vector bool int"); - HashNameNode *vf = GetHashNameNodeExport("vector float"); - HashNameNode *vp = GetHashNameNodeExport("vector pixel"); - - stvectorunsignedchar.name = vuc; - stvectorunsignedshort.name = vus; - stvectorunsignedlong.name = vui; - stvectorsignedchar.name = vsc; - stvectorsignedshort.name = vss; - stvectorsignedlong.name = vsi; - stvectorboolchar.name = vbc; - stvectorboolshort.name = vbs; - stvectorboollong.name = vbi; - stvectorfloat.name = vf; - stvectorpixel.name = vp; - - stVUC_unsignedchar0.name = e0; - stVUC_unsignedchar1.name = e1; - stVUC_unsignedchar2.name = e2; - stVUC_unsignedchar3.name = e3; - stVUC_unsignedchar4.name = e4; - stVUC_unsignedchar5.name = e5; - stVUC_unsignedchar6.name = e6; - stVUC_unsignedchar7.name = e7; - stVUC_unsignedchar8.name = e8; - stVUC_unsignedchar9.name = e9; - stVUC_unsignedchar10.name = e10; - stVUC_unsignedchar11.name = e11; - stVUC_unsignedchar12.name = e12; - stVUC_unsignedchar13.name = e13; - stVUC_unsignedchar14.name = e14; - stVUC_unsignedchar15.name = e15; - stVSC_signedchar0.name = e0; - stVSC_signedchar1.name = e1; - stVSC_signedchar2.name = e2; - stVSC_signedchar3.name = e3; - stVSC_signedchar4.name = e4; - stVSC_signedchar5.name = e5; - stVSC_signedchar6.name = e6; - stVSC_signedchar7.name = e7; - stVSC_signedchar8.name = e8; - stVSC_signedchar9.name = e9; - stVSC_signedchar10.name = e10; - stVSC_signedchar11.name = e11; - stVSC_signedchar12.name = e12; - stVSC_signedchar13.name = e13; - stVSC_signedchar14.name = e14; - stVSC_signedchar15.name = e15; - - stVUS_unsignedshort0.name = e0; - stVUS_unsignedshort1.name = e1; - stVUS_unsignedshort2.name = e2; - stVUS_unsignedshort3.name = e3; - stVUS_unsignedshort4.name = e4; - stVUS_unsignedshort5.name = e5; - stVUS_unsignedshort6.name = e6; - stVUS_unsignedshort7.name = e7; - stVSS_signedshort0.name = e0; - stVSS_signedshort1.name = e1; - stVSS_signedshort2.name = e2; - stVSS_signedshort3.name = e3; - stVSS_signedshort4.name = e4; - stVSS_signedshort5.name = e5; - stVSS_signedshort6.name = e6; - stVSS_signedshort7.name = e7; - - stVUL_unsignedlong0.name = e0; - stVUL_unsignedlong1.name = e1; - stVUL_unsignedlong2.name = e2; - stVUL_unsignedlong3.name = e3; - stVSL_signedlong0.name = e0; - stVSL_signedlong1.name = e1; - stVSL_signedlong2.name = e2; - stVSL_signedlong3.name = e3; - - stVF_float0.name = e0; - stVF_float1.name = e1; - stVF_float2.name = e2; - stVF_float3.name = e3; -} diff --git a/compiler_and_linker/unsorted/CMangler.c b/compiler_and_linker/unsorted/CMangler.c deleted file mode 100644 index 615abf5..0000000 --- a/compiler_and_linker/unsorted/CMangler.c +++ /dev/null @@ -1,713 +0,0 @@ -#include "compiler/CMangler.h" -#include "compiler/CError.h" -#include "compiler/CInt64.h" -#include "compiler/CFunc.h" -#include "compiler/CParser.h" -#include "compiler/CTemplateTools.h" -#include "compiler/CompilerTools.h" -#include "compiler/enode.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/templates.h" -#include "compiler/types.h" -#include "cos.h" - -HashNameNode *constructor_name_node; -HashNameNode *destructor_name_node; -HashNameNode *asop_name_node; - -// forward decls -static void CMangler_MangleClassName(TypeClass *tclass); -static void CMangler_MangleTypeAppend(Type *type, UInt32 qual); -static void CMangler_MangleArgs(FuncArg *args); - -void CMangler_Setup(void) { - constructor_name_node = GetHashNameNodeExport("__ct"); - destructor_name_node = GetHashNameNodeExport("__dt"); - asop_name_node = GetHashNameNodeExport("__as"); -} - -HashNameNode *CMangler_BasicDtorName(void) { - return GetHashNameNodeExport("__dtb"); -} - -HashNameNode *CMangler_VBaseDtorName(void) { - return GetHashNameNodeExport("__dtv"); -} - -HashNameNode *CMangler_ArrayDtorName(void) { - return GetHashNameNodeExport("__dta"); -} - -HashNameNode *CMangler_SDeleteDtorName(void) { - return GetHashNameNodeExport("__dts"); -} - -HashNameNode *CMangler_DeleteDtorName(void) { - return GetHashNameNodeExport("__dt"); -} - -char *CMangler_GetOperator(HashNameNode *name) { - char *str; - - if (name == asop_name_node) - return "operator="; - - str = name->name; - if (!strcmp(str, "__nw")) return "operator new"; - if (!strcmp(str, "__dl")) return "operator delete"; - if (!strcmp(str, "__nwa")) return "operator new[]"; - if (!strcmp(str, "__dla")) return "operator delete[]"; - if (!strcmp(str, "__pl")) return "operator+"; - if (!strcmp(str, "__mi")) return "operator-"; - if (!strcmp(str, "__ml")) return "operator*"; - if (!strcmp(str, "__dv")) return "operator/"; - if (!strcmp(str, "__md")) return "operator%"; - if (!strcmp(str, "__er")) return "operator^"; - if (!strcmp(str, "__ad")) return "operator&"; - if (!strcmp(str, "__or")) return "operator|"; - if (!strcmp(str, "__co")) return "operator~"; - if (!strcmp(str, "__nt")) return "operator!"; - if (!strcmp(str, "__lt")) return "operator<"; - if (!strcmp(str, "__gt")) return "operator>"; - if (!strcmp(str, "__apl")) return "operator+="; - if (!strcmp(str, "__ami")) return "operator-="; - if (!strcmp(str, "__amu")) return "operator*="; - if (!strcmp(str, "__adv")) return "operator/="; - if (!strcmp(str, "__amd")) return "operator%="; - if (!strcmp(str, "__aer")) return "operator^="; - if (!strcmp(str, "__aad")) return "operator&="; - if (!strcmp(str, "__aor")) return "operator|="; - if (!strcmp(str, "__ls")) return "operator<<"; - if (!strcmp(str, "__rs")) return "operator>>"; - if (!strcmp(str, "__als")) return "operator<<="; - if (!strcmp(str, "__ars")) return "operator>>="; - if (!strcmp(str, "__eq")) return "operator=="; - if (!strcmp(str, "__ne")) return "operator!="; - if (!strcmp(str, "__le")) return "operator<="; - if (!strcmp(str, "__ge")) return "operator>="; - if (!strcmp(str, "__aa")) return "operator&&"; - if (!strcmp(str, "__oo")) return "operator||"; - if (!strcmp(str, "__pp")) return "operator++"; - if (!strcmp(str, "__mm")) return "operator--"; - if (!strcmp(str, "__cm")) return "operator,"; - if (!strcmp(str, "__rm")) return "operator->*"; - if (!strcmp(str, "__rf")) return "operator*"; - if (!strcmp(str, "__cl")) return "operator()"; - if (!strcmp(str, "__vc")) return "operator[]"; - return NULL; -} - -HashNameNode *CMangler_OperatorName(short token) { - switch (token) { - case TK_NEW: return GetHashNameNodeExport("__nw"); - case TK_DELETE: return GetHashNameNodeExport("__dl"); - case TK_NEW_ARRAY: return GetHashNameNodeExport("__nwa"); - case TK_DELETE_ARRAY: return GetHashNameNodeExport("__dla"); - case '+': return GetHashNameNodeExport("__pl"); - case '-': return GetHashNameNodeExport("__mi"); - case '*': return GetHashNameNodeExport("__ml"); - case '/': return GetHashNameNodeExport("__dv"); - case '%': return GetHashNameNodeExport("__md"); - case '^': return GetHashNameNodeExport("__er"); - case '&': return GetHashNameNodeExport("__ad"); - case '|': return GetHashNameNodeExport("__or"); - case '~': return GetHashNameNodeExport("__co"); - case '!': return GetHashNameNodeExport("__nt"); - case '=': return asop_name_node; - case '<': return GetHashNameNodeExport("__lt"); - case '>': return GetHashNameNodeExport("__gt"); - case TK_ADD_ASSIGN: return GetHashNameNodeExport("__apl"); - case TK_SUB_ASSIGN: return GetHashNameNodeExport("__ami"); - case TK_MULT_ASSIGN: return GetHashNameNodeExport("__amu"); - case TK_DIV_ASSIGN: return GetHashNameNodeExport("__adv"); - case TK_MOD_ASSIGN: return GetHashNameNodeExport("__amd"); - case TK_XOR_ASSIGN: return GetHashNameNodeExport("__aer"); - case TK_AND_ASSIGN: return GetHashNameNodeExport("__aad"); - case TK_OR_ASSIGN: return GetHashNameNodeExport("__aor"); - case TK_SHL: return GetHashNameNodeExport("__ls"); - case TK_SHR: return GetHashNameNodeExport("__rs"); - case TK_SHL_ASSIGN: return GetHashNameNodeExport("__als"); - case TK_SHR_ASSIGN: return GetHashNameNodeExport("__ars"); - case TK_LOGICAL_EQ: return GetHashNameNodeExport("__eq"); - case TK_LOGICAL_NE: return GetHashNameNodeExport("__ne"); - case TK_LESS_EQUAL: return GetHashNameNodeExport("__le"); - case TK_GREATER_EQUAL: return GetHashNameNodeExport("__ge"); - case TK_LOGICAL_AND: return GetHashNameNodeExport("__aa"); - case TK_LOGICAL_OR: return GetHashNameNodeExport("__oo"); - case TK_INCREMENT: return GetHashNameNodeExport("__pp"); - case TK_DECREMENT: return GetHashNameNodeExport("__mm"); - case ',': return GetHashNameNodeExport("__cm"); - case TK_ARROW_STAR: return GetHashNameNodeExport("__rm"); - case TK_ARROW: return GetHashNameNodeExport("__rf"); - case '(': return GetHashNameNodeExport("__cl"); - case '[': return GetHashNameNodeExport("__vc"); - default: return NULL; - } -} - -HashNameNode *CMangler_VTableName(TypeClass *theclass) { - HashNameNode *name; - - name_mangle_list.size = 0; - AppendGListName(&name_mangle_list, "__vt__"); - CMangler_MangleClassName(theclass); - AppendGListByte(&name_mangle_list, 0); - COS_LockHandle(name_mangle_list.data); - name = GetHashNameNodeExport(*name_mangle_list.data); - COS_UnlockHandle(name_mangle_list.data); - return name; -} - -HashNameNode *CMangler_RTTIObjectName(Type *type, UInt32 qual) { - HashNameNode *name; - - name_mangle_list.size = 0; - AppendGListName(&name_mangle_list, "__RTTI__"); - CMangler_MangleTypeAppend(type, qual); - AppendGListByte(&name_mangle_list, 0); - COS_LockHandle(name_mangle_list.data); - name = GetHashNameNodeExport(*name_mangle_list.data); - COS_UnlockHandle(name_mangle_list.data); - return name; -} - -HashNameNode *CMangler_ThunkName(Object *vfunc, SInt32 this_delta, SInt32 return_delta, SInt32 ctoroffset) { - HashNameNode *linkname; - HashNameNode *name; - char buf[64]; - - linkname = CMangler_GetLinkName(vfunc); - name_mangle_list.size = 0; - if (return_delta == 0) { - if (ctoroffset < 0) - sprintf(buf, "_@%" PRId32 "@", -this_delta); - else - sprintf(buf, "_@%" PRId32 "@%" PRId32 "@", -this_delta, ctoroffset); - } else { - sprintf(buf, "_@%" PRId32 "@%" PRId32 "@%" PRId32 "@", -this_delta, ctoroffset, return_delta); - } - AppendGListName(&name_mangle_list, buf); - AppendGListID(&name_mangle_list, linkname->name + 1); - COS_LockHandle(name_mangle_list.data); - name = GetHashNameNodeExport(*name_mangle_list.data); - COS_UnlockHandle(name_mangle_list.data); - return name; -} - -static void CMangler_CheckTemplateArguments(TemplArg *arg) { - ENode *expr; - - while (arg) { - if (arg->pid.type == TPT_NONTYPE) { - expr = arg->data.paramdecl.expr; - CError_ASSERT(360, expr); - if (expr->rtype->type != TYPETEMPLDEPEXPR) { - switch (expr->type) { - case EINTCONST: - break; - case EOBJREF: - CMangler_GetLinkName(expr->data.objref); - break; - default: - CError_FATAL(383); - } - } - } - arg = arg->next; - } -} - -static void CMangler_AppendTemplateArgumentList(TemplArg *arg) { - ENode *expr; - char buf[32]; - - AppendGListByte(&name_mangle_list, '<'); - - while (arg) { - if (arg->pid.type == TPT_NONTYPE) { - expr = arg->data.paramdecl.expr; - CError_ASSERT(409, expr); - if (expr->rtype->type != TYPETEMPLDEPEXPR) { - switch (expr->type) { - case EINTCONST: - CInt64_PrintDec(buf, expr->data.intval); - AppendGListName(&name_mangle_list, buf); - break; - case EOBJREF: - AppendGListByte(&name_mangle_list, '&'); - AppendGListName(&name_mangle_list, CMangler_GetLinkName(expr->data.objref)->name); - break; - default: - CError_FATAL(452); - } - } else { - AppendGListByte(&name_mangle_list, 'T'); - } - } else if (arg->pid.type == TPT_TYPE) { - CMangler_MangleTypeAppend(arg->data.typeparam.type, arg->data.typeparam.qual); - } else { - CError_ASSERT(467, arg->pid.type == TPT_TEMPLATE); - CMangler_MangleTypeAppend(arg->data.ttargtype, 0); - } - - if (arg->next) - AppendGListByte(&name_mangle_list, ','); - arg = arg->next; - } - - AppendGListByte(&name_mangle_list, '>'); -} - -HashNameNode *CMangler_TemplateInstanceName(HashNameNode *basename, TemplArg *args) { - HashNameNode *name; - - CMangler_CheckTemplateArguments(args); - name_mangle_list.size = 0; - AppendGListName(&name_mangle_list, basename->name); - CMangler_AppendTemplateArgumentList(args); - AppendGListByte(&name_mangle_list, 0); - - COS_LockHandle(name_mangle_list.data); - name = GetHashNameNodeExport(*name_mangle_list.data); - COS_UnlockHandle(name_mangle_list.data); - return name; -} - -static void CMangler_MangleTypeName(char *str) { - char buf[16]; - - sprintf(buf, "%d", strlen(str)); - AppendGListName(&name_mangle_list, buf); - AppendGListName(&name_mangle_list, str); -} - -static void CMangler_MangleNameSpaceName(NameSpace *nspace, char *str) { - char *stack[10]; - int stackp; - - stack[0] = str; - stackp = 1; - while (nspace) { - if (nspace->name) { - stack[stackp++] = nspace->name->name; - if (stackp >= 9) - break; - } - nspace = nspace->parent; - } - - if (stackp > 1) { - AppendGListByte(&name_mangle_list, 'Q'); - AppendGListByte(&name_mangle_list, '0' + stackp); - } - - while (--stackp >= 0) - CMangler_MangleTypeName(stack[stackp]); -} - -static void CMangler_MangleClassName(TypeClass *tclass) { - if (!tclass->classname) - CMangler_MangleNameSpaceName(tclass->nspace->parent, "class"); - else - CMangler_MangleNameSpaceName(tclass->nspace->parent, tclass->nspace->name->name); -} - -static void CMangler_MangleQualifier(UInt32 qual) { - if (qual & Q_CONST) - AppendGListByte(&name_mangle_list, 'C'); - if (qual & Q_VOLATILE) - AppendGListByte(&name_mangle_list, 'V'); -} - -static void CMangler_MangleTypeAppend(Type *type, UInt32 qual) { - char buf[16]; - - switch (type->type) { - case TYPEVOID: - CMangler_MangleQualifier(qual); - AppendGListByte(&name_mangle_list, 'v'); - break; - case TYPEINT: - case TYPEFLOAT: - CMangler_MangleQualifier(qual); - switch (TYPE_INTEGRAL(type)->integral) { - case IT_BOOL: - AppendGListByte(&name_mangle_list, 'b'); - return; - case IT_CHAR: - AppendGListByte(&name_mangle_list, 'c'); - return; - case IT_WCHAR_T: - AppendGListByte(&name_mangle_list, 'w'); - return; - case IT_UCHAR: - AppendGListName(&name_mangle_list, "Uc"); - return; - case IT_SCHAR: - AppendGListName(&name_mangle_list, "Sc"); - return; - case IT_SHORT: - AppendGListByte(&name_mangle_list, 's'); - return; - case IT_USHORT: - AppendGListName(&name_mangle_list, "Us"); - return; - case IT_INT: - AppendGListByte(&name_mangle_list, 'i'); - return; - case IT_UINT: - AppendGListName(&name_mangle_list, "Ui"); - return; - case IT_LONG: - AppendGListByte(&name_mangle_list, 'l'); - return; - case IT_ULONG: - AppendGListName(&name_mangle_list, "Ul"); - return; - case IT_LONGLONG: - AppendGListByte(&name_mangle_list, 'x'); - return; - case IT_ULONGLONG: - AppendGListName(&name_mangle_list, "Ux"); - return; - case IT_FLOAT: - AppendGListByte(&name_mangle_list, 'f'); - return; - case IT_SHORTDOUBLE: - AppendGListByte(&name_mangle_list, 'D'); - return; - case IT_DOUBLE: - AppendGListByte(&name_mangle_list, 'd'); - return; - case IT_LONGDOUBLE: - AppendGListByte(&name_mangle_list, 'r'); - return; - default: - CError_FATAL(619); - } - case TYPEENUM: - CMangler_MangleQualifier(qual); - if (!TYPE_ENUM(type)->enumname) - CMangler_MangleNameSpaceName(TYPE_ENUM(type)->nspace, "enum"); - else - CMangler_MangleNameSpaceName(TYPE_ENUM(type)->nspace, TYPE_ENUM(type)->enumname->name); - break; - case TYPEPOINTER: - CMangler_MangleQualifier(TYPE_POINTER(type)->qual); - if (TYPE_POINTER(type)->qual & Q_REFERENCE) - AppendGListByte(&name_mangle_list, 'R'); - else - AppendGListByte(&name_mangle_list, 'P'); - CMangler_MangleTypeAppend(TYPE_POINTER(type)->target, qual); - break; - case TYPEMEMBERPOINTER: - if (TYPE_MEMBER_POINTER(type)->ty2->type != TYPECLASS) { - AppendGListName(&name_mangle_list, "3"); - } else { - CMangler_MangleQualifier(TYPE_MEMBER_POINTER(type)->qual); - AppendGListByte(&name_mangle_list, 'M'); - CMangler_MangleClassName(TYPE_CLASS(TYPE_MEMBER_POINTER(type)->ty2)); - CMangler_MangleTypeAppend(TYPE_MEMBER_POINTER(type)->ty1, qual); - } - break; - case TYPEARRAY: - AppendGListByte(&name_mangle_list, 'A'); - if (TYPE_POINTER(type)->target->size) { - sprintf(buf, "%" PRId32 "", type->size / TYPE_POINTER(type)->target->size); - AppendGListName(&name_mangle_list, buf); - } else { - AppendGListByte(&name_mangle_list, '0'); - } - AppendGListByte(&name_mangle_list, '_'); - CMangler_MangleTypeAppend(TYPE_POINTER(type)->target, qual); - break; - case TYPEFUNC: - CMangler_MangleQualifier(qual); - AppendGListByte(&name_mangle_list, 'F'); - CMangler_MangleArgs(TYPE_FUNC(type)->args); - AppendGListByte(&name_mangle_list, '_'); - CMangler_MangleTypeAppend(TYPE_FUNC(type)->functype, TYPE_FUNC(type)->qual); - break; - case TYPESTRUCT: - CMangler_MangleQualifier(qual); - switch (TYPE_STRUCT(type)->stype) { - case STRUCT_VECTOR_UCHAR: - AppendGListName(&name_mangle_list, "XUc"); - return; - case STRUCT_VECTOR_SCHAR: - AppendGListName(&name_mangle_list, "Xc"); - return; - case STRUCT_VECTOR_BCHAR: - AppendGListName(&name_mangle_list, "XC"); - return; - case STRUCT_VECTOR_USHORT: - AppendGListName(&name_mangle_list, "XUs"); - return; - case STRUCT_VECTOR_SSHORT: - AppendGListName(&name_mangle_list, "Xs"); - return; - case STRUCT_VECTOR_BSHORT: - AppendGListName(&name_mangle_list, "XS"); - return; - case STRUCT_VECTOR_UINT: - AppendGListName(&name_mangle_list, "XUi"); - return; - case STRUCT_VECTOR_SINT: - AppendGListName(&name_mangle_list, "Xi"); - return; - case STRUCT_VECTOR_BINT: - AppendGListName(&name_mangle_list, "XI"); - return; - case STRUCT_VECTOR_FLOAT: - AppendGListName(&name_mangle_list, "Xf"); - return; - case STRUCT_VECTOR_PIXEL: - AppendGListName(&name_mangle_list, "Xp"); - return; - } - - if (TYPE_STRUCT(type)->name && !IsTempName(TYPE_STRUCT(type)->name)) { - CMangler_MangleTypeName(TYPE_STRUCT(type)->name->name); - return; - } - - switch (TYPE_STRUCT(type)->stype) { - case STRUCT_TYPE_STRUCT: - AppendGListName(&name_mangle_list, "struct"); - break; - case STRUCT_TYPE_UNION: - AppendGListName(&name_mangle_list, "union"); - break; - case STRUCT_TYPE_CLASS: - AppendGListName(&name_mangle_list, "class"); - break; - default: - CError_FATAL(701); - } - break; - - case TYPECLASS: - CMangler_MangleQualifier(qual); - CMangler_MangleClassName(TYPE_CLASS(type)); - break; - - case TYPETEMPLATE: - AppendGListName(&name_mangle_list, "1T"); - break; - - default: - CError_FATAL(716); - } -} - -void CMangler_MangleType(Type *type, UInt32 qual) { - name_mangle_list.size = 0; - CMangler_MangleTypeAppend(type, qual); -} - -static void CMangler_MangleArgs(FuncArg *args) { - TypePointer ptr; - - if (args) { - if (args->type) { - while (args) { - if (args != &elipsis && args != &oldstyle) { - if (args->type->type == TYPEPOINTER) { - ptr = *TYPE_POINTER(args->type); - ptr.qual &= ~(Q_CONST | Q_VOLATILE); - CMangler_MangleTypeAppend(TYPE(&ptr), args->qual); - } else { - CMangler_MangleTypeAppend(args->type, 0); - } - } else { - AppendGListByte(&name_mangle_list, 'e'); - } - args = args->next; - } - } else { - AppendGListByte(&name_mangle_list, 'e'); - } - } else { - AppendGListByte(&name_mangle_list, 'v'); - } -} - -static void CMangler_MangleFunction(Object *obj, NameSpace *nspace) { - TypeFunc *tfunc = TYPE_FUNC(obj->type); - FuncArg *arg = tfunc->args; - - AppendGListName(&name_mangle_list, obj->name->name); - if (obj->u.func.inst) { - if (tfunc->flags & FUNC_CONVERSION) - CMangler_MangleTypeAppend(tfunc->functype, tfunc->qual); - CMangler_AppendTemplateArgumentList(obj->u.func.inst->args); - } - AppendGListName(&name_mangle_list, "__"); - while (nspace && nspace->name == NULL) - nspace = nspace->parent; - - if (nspace) { - CMangler_MangleNameSpaceName(nspace->parent, nspace->name->name); - if (nspace->theclass) { - if (obj->name == destructor_name_node) { - AppendGListName(&name_mangle_list, "Fv"); - return; - } - if (arg) { - if (obj->name == constructor_name_node) { - arg = arg->next; - if (arg && (nspace->theclass->flags & CLASS_HAS_VBASES)) - arg = arg->next; - } else { - if ((tfunc->flags & FUNC_METHOD) && !TYPE_METHOD(tfunc)->is_static) { - CMangler_MangleQualifier(arg->qual); - arg = arg->next; - } - } - } - } - } - - AppendGListByte(&name_mangle_list, 'F'); - CMangler_MangleArgs(arg); - if (obj->u.func.inst && copts.new_mangler) { - AppendGListByte(&name_mangle_list, '_'); - CMangler_MangleTypeAppend(tfunc->functype, tfunc->qual); - } -} - -HashNameNode *CMangler_ConversionFuncName(Type *type, UInt32 qual) { - HashNameNode *name; - - if (CTemplTool_IsTemplateArgumentDependentType(type)) - return GetHashNameNodeExport("__op"); - - name_mangle_list.size = 0; - AppendGListName(&name_mangle_list, "__op"); - CMangler_MangleTypeAppend(type, qual); - AppendGListByte(&name_mangle_list, 0); - - COS_LockHandle(name_mangle_list.data); - name = GetHashNameNodeExport(*name_mangle_list.data); - COS_UnlockHandle(name_mangle_list.data); - return name; -} - -static HashNameNode *CMangler_MangleNameToUpper(char *str) { - HashNameNode *name; - - name_mangle_list.size = 0; - while (*str) { - AppendGListByte(&name_mangle_list, toupper(*(str++))); - } - AppendGListByte(&name_mangle_list, 0); - - COS_LockHandle(name_mangle_list.data); - name = GetHashNameNodeExport(*name_mangle_list.data); - COS_UnlockHandle(name_mangle_list.data); - return name; -} - -static HashNameNode *CMangler_FunctionLinkName(Object *obj) { - HashNameNode *name; - NameSpace *nspace; - - if (obj->u.func.inst) - CMangler_CheckTemplateArguments(obj->u.func.inst->args); - - for (nspace = obj->nspace; nspace; nspace = nspace->parent) { - if (nspace->name) - break; - } - - name_mangle_list.size = 0; - if (is_pascal_object(obj) && (!nspace || !nspace->theclass)) { - AppendGListData(&name_mangle_list, "_", 1); - AppendGListID(&name_mangle_list, obj->name->name); - } else if ((obj->qual & Q_MANGLE_NAME) && (strcmp("main", obj->name->name) || (obj->nspace != cscope_root))) { - AppendGListData(&name_mangle_list, "_", 1); - CMangler_MangleFunction(obj, nspace); - AppendGListByte(&name_mangle_list, 0); - } else { - AppendGListData(&name_mangle_list, "_", 1); - AppendGListID(&name_mangle_list, obj->name->name); - } - - COS_LockHandle(name_mangle_list.data); - name = GetHashNameNodeExport(*name_mangle_list.data); - COS_UnlockHandle(name_mangle_list.data); - return name; -} - -HashNameNode *CMangler_GetCovariantFunctionName(Object *dobj, TypeClass *theclass) { - HashNameNode *name; - - name = CMangler_GetLinkName(dobj); - name_mangle_list.size = 0; - AppendGListName(&name_mangle_list, name->name); - AppendGListName(&name_mangle_list, "@@"); - CMangler_MangleTypeAppend(TYPE(theclass), 0); - AppendGListByte(&name_mangle_list, 0); - - COS_LockHandle(name_mangle_list.data); - name = GetHashNameNodeExport(*name_mangle_list.data); - COS_UnlockHandle(name_mangle_list.data); - return name; -} - -static HashNameNode *CMangler_DataLinkName(Object *obj) { - NameSpace *nspace; - HashNameNode *name; - - nspace = obj->nspace; - while (nspace && nspace->name == NULL) - nspace = nspace->parent; - - name_mangle_list.size = 0; - AppendGListData(&name_mangle_list, "_", 1); - AppendGListName(&name_mangle_list, obj->name->name); - - while (nspace && nspace->name == NULL) - nspace = nspace->parent; - if (nspace && (obj->qual & Q_MANGLE_NAME)) { - AppendGListName(&name_mangle_list, "__"); - CMangler_MangleNameSpaceName(nspace->parent, nspace->name->name); - } - AppendGListByte(&name_mangle_list, 0); - - COS_LockHandle(name_mangle_list.data); - name = GetHashNameNodeExport(*name_mangle_list.data); - COS_UnlockHandle(name_mangle_list.data); - return name; -} - -HashNameNode *CMangler_GetLinkName(Object *obj) { - while (obj->datatype == DALIAS) - obj = obj->u.alias.object; - - switch (obj->datatype) { - case DFUNC: - case DVFUNC: - if (!obj->u.func.linkname) - obj->u.func.linkname = CMangler_FunctionLinkName(obj); - return obj->u.func.linkname; - case DDATA: - if (!obj->u.data.linkname) - obj->u.data.linkname = CMangler_DataLinkName(obj); - return obj->u.data.linkname; - case DINLINEFUNC: - return CMangler_FunctionLinkName(obj); - case DLOCAL: - case DABSOLUTE: - case DLABEL: - return obj->name; - case DNONLAZYPTR: - if (!obj->u.toc.linkname) - obj->u.toc.linkname = CMangler_DataLinkName(obj); - return obj->u.toc.linkname; - default: - CError_FATAL(1110); - return NULL; - } -} diff --git a/compiler_and_linker/unsorted/COptimizer.c b/compiler_and_linker/unsorted/COptimizer.c deleted file mode 100644 index 9833a2b..0000000 --- a/compiler_and_linker/unsorted/COptimizer.c +++ /dev/null @@ -1,1831 +0,0 @@ -#include "compiler/COptimizer.h" -#include "compiler/CompilerTools.h" -#include "compiler/CClass.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/InlineAsm.h" -#include "compiler/enode.h" -#include "compiler/objects.h" -#include "compiler/CodeGen.h" -#include "compiler/Switch.h" -#include "compiler/Exceptions.h" -#include "compiler/IrOptimizer.h" -#include "cos.h" - -COptBlock *basicblocks; -Boolean copt_isleaffunction; -static Boolean stmtchanged; -static COptBlock *currentblock; -static ENode *mexpr; -static short setbytes; -static COptCSE *csenodes[MAXEXPR]; -static COptCSEList *cselist; -static short extravars; -static Boolean cse_found; -static Boolean cse_invals; -static Boolean static_for_inlines; -static short replaces; -static ENode *objrefnode; -static int objrefnodes; - -static short bitmasks[] = { - 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, - 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000 -}; - -// forward decls -static COptCSE *cse_expression(ENode *expr); - -static COptCSE *cse_new(ENode *expr) { - COptCSE *cse = oalloc(sizeof(COptCSE)); - cse->expr = expr; - cse->replaced = NULL; - cse->block = currentblock; - cse->mexpr = mexpr; - cse->left = NULL; - cse->right = NULL; - cse->x1C = 1; - return cse; -} - -static COptCSE *cse_append(COptCSE *cse, ENode *expr) { - COptCSEList *list = oalloc(sizeof(COptCSEList)); - list->next = cselist; - cselist = list; - list->cse = cse; - list->expr = expr; - return cse; -} - -static void cse_cleanup(void) { - COptCSEList *scanlist; - COptCSEList *prevlist; - COptCSE *scan; - COptCSE *prev; - short op; - - scanlist = cselist; - while (scanlist && !scanlist->cse) - scanlist = scanlist->next; - cselist = scanlist; - - if (scanlist) { - do { - prevlist = scanlist; - do { - scanlist = scanlist->next; - } while (scanlist && !scanlist->cse); - prevlist->next = scanlist; - } while (scanlist); - } - - for (op = 0; op < MAXEXPR; op++) { - scan = csenodes[op]; - while (scan && scan->x1C < 0) - scan = scan->next; - csenodes[op] = scan; - - if (scan) { - do { - prev = scan; - do { - scan = scan->next; - } while (scan && scan->x1C < 0); - prev->next = scan; - } while (scan); - } - } -} - -static void cse_inval(COptCSE *cse) { - COptCSEList *scanlist; - COptCSE *scan; - short op; - - if (cse) { - for (scanlist = cselist; scanlist; scanlist = scanlist->next) { - if (scanlist->cse == cse) { - scanlist->cse = NULL; - scanlist->expr = NULL; - } - } - - cse->x1C = -1; - cse->left = NULL; - cse->right = NULL; - - for (op = 0; op < MAXEXPR; op++) { - for (scan = csenodes[op]; scan; scan = scan->next) { - if (scan->left == cse || scan->right == cse) - cse_inval(scan); - } - } - } -} - -static void cse_update_usages(COptCSE *cse, short amount) { - cse->x1C /= amount; - if (cse->left) - cse_update_usages(cse->left, amount); - if (cse->right) - cse_update_usages(cse->right, amount); -} - -static void cse_replace(ENode *expr, COptCSE *cse) { - COptCSEList *list; - - for (list = cselist; list; list = list->next) { - if (list->cse == cse) { - *list->expr = *expr; - replaces++; - list->cse = NULL; - list->expr = NULL; - } - } -} - -static short cse_objectcost(Object *obj) { - if (obj->datatype == DLOCAL && !obj->u.var.info->noregister) - return 0; - return 1; -} - -static void cse_treereplacemexpr(COptCSE *cse, ENode *from, ENode *to) { - if (cse->mexpr == from) - cse->mexpr = to; - if (cse->left) - cse_treereplacemexpr(cse->left, from, to); - if (cse->right) - cse_treereplacemexpr(cse->right, from, to); -} - -static Boolean cse_issubcse(COptCSE *a, COptCSE *b) { - if (a == b) - return 1; - if (b->left && cse_issubcse(a, b->left)) - return 1; - if (b->right && cse_issubcse(a, b->right)) - return 1; - - return 0; -} - -static short cse_cost(COptCSE *cse) { - short cost; - - if (cse) { - while (ENODE_IS(cse->expr, ETYPCON) && cse->expr->rtype->type == cse->expr->data.monadic->rtype->type && cse->expr->rtype->size == cse->expr->data.monadic->rtype->size) - cse = cse->left; - - if (ENODE_IS_INDIRECT_TO(cse->expr, EOBJREF)) - return cse_objectcost(cse->expr->data.monadic->data.objref); - - cost = 1; - if (!copts.optimizesize) { - if (ENODE_IS3(cse->expr, EMUL, EDIV, EMODULO)) - cost = 2; - } - return cse_cost(cse->left) + cse_cost(cse->right) + cost; - } - - return 0; -} - -static void cse_remove(void) { - short op; // r27 - COptCSE *cse; // r25 - COptCSE *best_cse; // r28 - int best_cost; // r30 - Object *obj; // r31 - Boolean did_replacement; // r24 - VarInfo *vi; // r27 - ObjectList *objlist; - ENode *expr1; - ENode *expr2; - ENode *expr3; - ENode *expr4; - ENode *mexprsave; - COptCSEList *list; - short cost; - - while (1) { - op = 0; - best_cse = NULL; - best_cost = 0; - did_replacement = 0; - - for (; op < MAXEXPR; op++) { - switch (op) { - case EINTCONST: - case EFLOATCONST: - case EOBJREF: - case EVECTOR128CONST: - break; - default: - for (cse = csenodes[op]; cse; cse = cse->next) { - if (cse->x1C > 1 && (cost = cse_cost(cse)) > 4) { - if (cse->replaced) { - replaces = 0; - cse_replace(cse->replaced, cse); - CError_ASSERT(348, replaces >= 1); - cse_found = 1; - did_replacement = 1; - cse_update_usages(cse, cse->x1C); - } else { - if ((cse->x1C * cost) > best_cost) { - best_cse = cse; - best_cost = cse->x1C * cost; - } - } - } - } - break; - } - } - - if (did_replacement) - continue; - if (!best_cse || extravars >= 256) - return; - - obj = lalloc(sizeof(Object)); - memclrw(obj, sizeof(Object)); - obj->name = CParser_GetUniqueName(); - obj->type = cse->expr->rtype; - obj->datatype = DLOCAL; - vi = CodeGen_GetNewVarInfo(); - obj->u.var.info = vi; - - objlist = lalloc(sizeof(ObjectList)); - objlist->object = obj; - objlist->next = locals; - locals = objlist; - - vi->used = 1; - vi->usage = cse->x1C + 1; - - expr1 = lalloc(sizeof(ENode)); - expr1->type = EOBJREF; - expr1->cost = 0; - expr1->flags = 0; - expr1->data.objref = obj; - expr1->rtype = CDecl_NewPointerType(obj->type); - - expr2 = lalloc(sizeof(ENode)); - expr2->type = EINDIRECT; - expr2->cost = 1; - expr2->flags = 0; - expr2->data.monadic = expr1; - expr2->rtype = obj->type; - - expr3 = lalloc(sizeof(ENode)); - expr3->type = EASS; - expr3->cost = -1; - expr3->flags = 0; - expr3->rtype = obj->type; - expr3->data.diadic.left = expr2; - expr3->data.diadic.right = lalloc(sizeof(ENode)); - - *expr3->data.diadic.right = *cse->expr; - cse->expr = expr3->data.diadic.right; - - replaces = 0; - cse_replace(expr2, cse); - cse->replaced = expr2; - - if (replaces < 2) - CError_FATAL(390); - else - cse_found = 1; - - expr4 = lalloc(sizeof(ENode)); - *expr4 = *cse->mexpr; - - cse->mexpr->type = ECOMMA; - cse->mexpr->data.diadic.left = expr3; - cse->mexpr->data.diadic.right = expr4; - - cse_update_usages(cse, cse->x1C); - extravars++; - - mexprsave = cse->mexpr; - if (mexpr == mexprsave) - mexpr = expr4; - - for (list = cselist; list; list = list->next) { - if (list->cse && !cse_issubcse(list->cse, cse)) { - if (list->cse->mexpr == mexprsave) - list->cse->mexpr = expr4; - if (list->cse->expr == mexprsave) - list->cse->expr = expr4; - if (list->expr == mexprsave) - list->expr = expr4; - } - } - } -} - -static COptCSE *cse_intconst(ENode *expr) { - COptCSE *cse = csenodes[EINTCONST]; - - for (; cse; cse = cse->next) { - if (expr->rtype == cse->expr->rtype) - if (CInt64_Equal(cse->expr->data.intval, expr->data.intval)) - return cse; - } - - cse = cse_new(expr); - cse->next = csenodes[EINTCONST]; - csenodes[EINTCONST] = cse; - return cse; -} - -static COptCSE *cse_floatconst(ENode *expr) { - COptCSE *cse = csenodes[EFLOATCONST]; - Float val = expr->data.floatval; - - for (; cse; cse = cse->next) { - if (CMach_CalcFloatDiadicBool(cse->expr->rtype, cse->expr->data.floatval, TK_LOGICAL_EQ, val)) - if (expr->rtype == cse->expr->rtype) - return cse; - } - - cse = cse_new(expr); - cse->next = csenodes[EFLOATCONST]; - csenodes[EFLOATCONST] = cse; - return cse; -} - -static COptCSE *cse_vectorconst(ENode *expr) { - COptCSE *cse = csenodes[EVECTOR128CONST]; - MWVector128 val = expr->data.vector128val; - - for (; cse; cse = cse->next) { - if (CMach_CalcVectorDiadicBool(cse->expr->rtype, &cse->expr->data.vector128val, TK_LOGICAL_EQ, &val)) - if (expr->rtype == cse->expr->rtype) - return cse; - } - - cse = cse_new(expr); - cse->next = csenodes[EVECTOR128CONST]; - csenodes[EVECTOR128CONST] = cse; - return cse; -} - -static COptCSE *cse_objref(ENode *expr) { - COptCSE *cse = csenodes[EOBJREF]; - Object *obj = expr->data.objref; - - for (; cse; cse = cse->next) { - if (cse->expr->data.objref == obj) - return cse; - } - - cse = cse_new(expr); - cse->next = csenodes[EOBJREF]; - csenodes[EOBJREF] = cse; - return cse; -} - -static COptCSE *cse_add_monadic_node(ENode *outer, COptCSE *innercse) { - COptCSE *cse; - - if (!innercse) - return NULL; - - for (cse = csenodes[outer->type]; cse; cse = cse->next) { - if (cse->left == innercse && cse->expr->rtype == outer->rtype) { - CError_ASSERT(524, cse->expr != outer); - cse->x1C++; - return cse; - } - } - - cse = cse_new(outer); - cse->next = csenodes[outer->type]; - csenodes[outer->type] = cse; - cse->left = innercse; - return cse; -} - -static COptCSE *cse_add_typecon_node(ENode *outer, COptCSE *innercse) { - COptCSE *cse; - - if (!innercse) - return NULL; - - for (cse = csenodes[outer->type]; cse; cse = cse->next) { - if (cse->left == innercse && cse->expr->rtype == outer->rtype) { - CError_ASSERT(552, cse->expr != outer); - cse->x1C++; - return cse; - } - } - - cse = cse_new(outer); - cse->next = csenodes[outer->type]; - csenodes[outer->type] = cse; - cse->left = innercse; - return cse; -} - -static COptCSE *cse_add_diadic_node(ENode *outer, COptCSE *leftcse, COptCSE *rightcse) { - COptCSE *cse; - - if (!leftcse || !rightcse) - return NULL; - - for (cse = csenodes[outer->type]; cse; cse = cse->next) { - if (cse->left == leftcse && cse->right == rightcse) { - CError_ASSERT(581, cse->expr != outer); - cse->x1C++; - return cse; - } - } - - cse = cse_new(outer); - cse->next = csenodes[outer->type]; - csenodes[outer->type] = cse; - cse->left = leftcse; - cse->right = rightcse; - return cse; -} - -static COptCSE *cse_add_commdiadic_node(ENode *outer, COptCSE *leftcse, COptCSE *rightcse) { - COptCSE *cse; - - if (!leftcse || !rightcse) - return NULL; - - for (cse = csenodes[outer->type]; cse; cse = cse->next) { - if ((cse->left == leftcse && cse->right == rightcse) || (cse->left == rightcse && cse->right == leftcse)) { - CError_ASSERT(612, cse->expr != outer); - cse->x1C++; - return cse; - } - } - - cse = cse_new(outer); - cse->next = csenodes[outer->type]; - csenodes[outer->type] = cse; - cse->left = leftcse; - cse->right = rightcse; - return cse; -} - -static void sfind_objref(ENode *expr) { - while (1) { - switch (expr->type) { - case ETYPCON: - expr = expr->data.monadic; - break; - case EOBJREF: - objrefnode = expr; - objrefnodes++; - return; - case EADD: - case ESUB: - sfind_objref(expr->data.diadic.left); - expr = expr->data.diadic.right; - break; - default: - return; - } - } -} - -static ENode *find_objref_node(ENode *expr) { - objrefnode = NULL; - objrefnodes = 0; - sfind_objref(expr); - if (objrefnodes == 1) - return objrefnode; - else - return NULL; -} - -static void cse_mem_modify(void) { - COptCSE *cse; - - for (cse = csenodes[EINDIRECT]; cse; cse = cse->next) { - if (ENODE_IS(cse->expr->data.monadic, EOBJREF)) { - Object *obj = cse->expr->data.monadic->data.objref; - CError_ASSERT(672, obj->datatype != DALIAS); - if (obj->datatype == DLOCAL && !obj->u.var.info->noregister) - continue; - } - - cse_inval(cse); - } -} - -static void cse_modify_expression(ENode *expr) { - if (!expr) { - short op; - - cse_remove(); - for (op = 0; op < MAXEXPR; op++) - csenodes[op] = NULL; - - cselist = NULL; - freeoheap(); - } else { - ENode *objnode; - Object *obj; - COptCSE *cse; - - cse_invals = 1; - if (ENODE_IS(expr, EINDIRECT) && (objnode = find_objref_node(expr->data.monadic))) { - do { - obj = objnode->data.objref; - cse_remove(); - for (cse = csenodes[EINDIRECT]; cse; cse = cse->next) { - if ((objnode = find_objref_node(cse->expr->data.monadic)) && obj == objnode->data.objref) - cse_inval(cse); - } - - objnode = find_objref_node(expr->data.monadic); - if (!objnode) { - cse_mem_modify(); - break; - } - } while (obj != objnode->data.objref); - } else { - cse_remove(); - cse_mem_modify(); - } - } -} - -static void cse_pascalcall(ENode *expr) { - ENodeList *list; - - for (list = expr->data.funccall.args; list; list = list->next) - cse_expression(list->node); - - if (ENODE_IS(expr, EFUNCCALLP)) - cse_expression(expr->data.funccall.funcref); - - cse_remove(); - cse_mem_modify(); -} - -static Boolean cse_pusharg(ENodeList *exprs, FuncArg *args) { - Boolean result; - - if (!exprs) - return 1; - - if (args && args != &elipsis && args != &oldstyle) - args = args->next; - if (exprs->next) - result = cse_pusharg(exprs->next, args); - - cse_expression(exprs->node); - return result; -} - -static void cse_ccall(ENode *expr) { - if (cse_pusharg(expr->data.funccall.args, expr->data.funccall.functype->args)) { - if (ENODE_IS(expr, EFUNCCALL)) - cse_expression(expr->data.funccall.funcref); - - cse_remove(); - cse_mem_modify(); - } else { - cse_modify_expression(NULL); - } -} - -static COptCSE *cse_expression(ENode *expr) { - ENode *save; - COptCSE *tmp; - ENodeType nt = expr->type; - - switch (nt) { - case EFUNCCALL: - cse_ccall(expr); - return NULL; - case EFUNCCALLP: - cse_pascalcall(expr); - return NULL; - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - save = mexpr; - mexpr = expr; - CError_ASSERT(816, ENODE_IS(expr->data.monadic, EINDIRECT)); - - cse_expression(expr->data.monadic->data.monadic); - cse_modify_expression(expr->data.monadic); - mexpr = save; - return NULL; - - case EINDIRECT: - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case EFORCELOAD: - return cse_append(cse_add_monadic_node(expr, cse_expression(expr->data.monadic)), expr); - - case ETYPCON: - return cse_append(cse_add_typecon_node(expr, cse_expression(expr->data.monadic)), expr); - - case EMUL: - case EMULV: - case EADDV: - case EADD: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - tmp = cse_expression(expr->data.diadic.left); - if (expr->type == nt) - return cse_append(cse_add_commdiadic_node(expr, tmp, cse_expression(expr->data.diadic.right)), expr); - else - return NULL; - - case EDIV: - case EMODULO: - case ESUBV: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EPMODULO: - case EROTL: - case EROTR: - case EBTST: - tmp = cse_expression(expr->data.diadic.left); - if (expr->type == nt) - return cse_append(cse_add_diadic_node(expr, tmp, cse_expression(expr->data.diadic.right)), expr); - else - return NULL; - - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - CError_ASSERT(887, ENODE_IS(expr->data.diadic.left, EINDIRECT)); - save = mexpr; - mexpr = expr; - cse_expression(expr->data.diadic.right); - if (expr->type == nt) { - cse_expression(expr->data.diadic.left->data.monadic); - cse_modify_expression(expr->data.diadic.left); - mexpr = save; - return NULL; - } else { - cse_modify_expression(NULL); - return NULL; - } - - case ECOMMA: - cse_expression(expr->data.diadic.left); - save = mexpr; - mexpr = expr->data.diadic.right; - tmp = cse_expression(expr->data.diadic.right); - mexpr = save; - return tmp; - - case EINTCONST: - return cse_intconst(expr); - case EFLOATCONST: - return cse_floatconst(expr); - case EVECTOR128CONST: - return cse_vectorconst(expr); - case EOBJREF: - return cse_objref(expr); - - case EBITFIELD: - cse_modify_expression(NULL); - return NULL; - - case ECOND: - cse_expression(expr->data.cond.cond); - cse_modify_expression(NULL); - return NULL; - - case ENULLCHECK: - cse_expression(expr->data.nullcheck.nullcheckexpr); - cse_modify_expression(NULL); - return NULL; - - case ELAND: - case ELOR: - cse_expression(expr->data.diadic.left); - cse_modify_expression(NULL); - return NULL; - - case ESTRINGCONST: - case ELABEL: - return NULL; - - case EPRECOMP: - CError_FATAL(948); - - default: - CError_FATAL(951); - return NULL; - } -} - -static void cse_block(COptBlock *block) { - Statement *stmt; - COptBlock *check; - COptBlockList *scan; - COptBlock *best; - short i; - SInt32 counter; - UInt32 starttime; - - starttime = COS_GetTicks(); - counter = 0; - - while (1) { - cse_invals = 0; - currentblock = block; - block->x1E = 1; - - for (stmt = block->stmt, i = block->x1C; i > 0; stmt = stmt->next, i--) { - switch (stmt->type) { - case ST_EXPRESSION: - case ST_SWITCH: - case ST_IFGOTO: - case ST_IFNGOTO: - mexpr = stmt->expr; - cse_expression(mexpr); - break; - case ST_RETURN: - mexpr = stmt->expr; - if (mexpr) - cse_expression(mexpr); - break; - } - } - - i = 0; - for (scan = block->blocks2; scan; scan = scan->next) { - check = scan->block; - if (!check->x1E && check->blocks && !check->blocks->next && check->blocks->block == block) { - best = check; - i++; - } - } - - if (i != 1) - break; - - block = best; - if (COS_GetTicks() > (starttime + 60)) { - if (counter++ & 1) { - if (CWDisplayLines(cparamblkptr->context, lines)) - CError_UserBreak(); - } else { - if (CWDisplayLines(cparamblkptr->context, lines + 1)) - CError_UserBreak(); - } - starttime = COS_GetTicks(); - } - - if (cse_invals) - cse_cleanup(); - } - - cse_remove(); -} - -static void CSE(void) { - COptBlock *block; - - for (block = basicblocks->next; block; block = block->next) - block->x1E = 0; - - for (block = basicblocks->next; block; block = block->next) { - if (!block->x1E) { - short op; - - for (op = 0; op < MAXEXPR; op++) - csenodes[op] = NULL; - - cselist = NULL; - cse_found = 0; - cse_block(block); - freeoheap(); - } - } -} - -static short TestSetBit(short *set, short bit) { - return set[bit >> 4] & bitmasks[bit & 15]; -} - -static void SetSetBit(short *set, short bit) { - set[bit >> 4] |= bitmasks[bit & 15]; -} - -UInt32 RegAllocMask(short var) { - COptBlock *block; - UInt32 mask = 0; - - for (block = basicblocks; block; block = block->next) { - if (TestSetBit(block->set1, var) || TestSetBit(block->set2, var)) - mask |= block->allocmask; - } - - return mask; -} - -void MarkRegAllocMask(short var, short bit, Boolean flag) { - COptBlock *block; - UInt32 mask = 1 << bit; - - if (flag) { - for (block = basicblocks; block; block = block->next) { - if (TestSetBit(block->set1, var) || TestSetBit(block->set2, var)) - block->allocmask |= mask; - } - } else { - for (block = basicblocks; block; block = block->next) { - block->allocmask |= mask; - } - } -} - -static COptBlock *newblock(void) { - COptBlock *block; - short i; - short max; - - block = lalloc(sizeof(COptBlock) + (setbytes * 2)); - block->x1E = 0; - block->next = NULL; - block->blocks = NULL; - block->blocks2 = NULL; - block->allocmask = 0; - block->set1 = (short *) (((long) block) + sizeof(COptBlock)); - block->set2 = (short *) (((long) block) + setbytes + sizeof(COptBlock)); - - for (i = 0, max = setbytes / 2; i < max; i++) { - block->set1[i] = 0; - block->set2[i] = 0; - } - - return block; -} - -static void MarkFollow(COptBlock *block) { - COptBlockList *list; - -restart: - block->x1E = 1; - if ((list = block->blocks2)) { - while (1) { - if (!list->block->x1E) { - if (!list->next) { - block = list->block; - goto restart; - } - MarkFollow(list->block); - list = list->next; - } else { - list = list->next; - if (!list) - break; - } - } - } -} - -static Boolean CheckInit(short var) { - Boolean result; - COptBlock *block; - - result = 1; - for (block = basicblocks; block; block = block->next) { - if (!block->x1E && TestSetBit(block->set2, var)) - MarkFollow(block); - } - - for (block = basicblocks; block; block = block->next) { - if (!block->x1E) { - if (TestSetBit(block->set1, var)) - result = 0; - } else { - block->x1E = 0; - } - } - - return result; -} - -static void CheckVarInit(void) { - COptBlock *block; - VarInfo *vi; - ObjectList *list; - - for (block = basicblocks; block; block = block->next) - block->x1E = 0; - - for (list = locals; list; list = list->next) { - if (list->object->datatype == DLOCAL && !IsTempName(list->object->name) && !is_volatile_object(list->object)) { - vi = list->object->u.var.info; - if (vi->used && !CheckInit(vi->varnumber)) { - if (!IS_TYPE_CLASS(list->object->type) || !CClass_IsEmpty(TYPE_CLASS(list->object->type))) { - CError_SetErrorToken(&vi->deftoken); - CError_Warning(CErrorStr185, list->object->name->name); - } - } - } - } -} - -static void AddVar(Object *obj, Boolean whichSet) { - VarInfo *vi; - - if (obj->datatype == DLOCAL) { - vi = obj->u.var.info; - if (!whichSet) { - SetSetBit(currentblock->set1, vi->varnumber); - } else { - if (!TestSetBit(currentblock->set1, vi->varnumber)) - SetSetBit(currentblock->set2, vi->varnumber); - } - } -} - -static void CheckExpr(ENode *expr) { - ENodeList *list; - - while (1) { - switch (expr->type) { - case EINDIRECT: - if (ENODE_IS(expr->data.monadic, EOBJREF)) { - AddVar(expr->data.monadic->data.objref, 0); - return; - } - expr = expr->data.monadic; - break; - case EOBJREF: - AddVar(expr->data.objref, 1); - return; - case EFUNCCALL: - case EFUNCCALLP: - CheckExpr(expr->data.funccall.funcref); - for (list = expr->data.funccall.args; list; list = list->next) - CheckExpr(list->node); - return; - case ECOND: - CheckExpr(expr->data.cond.cond); - CheckExpr(expr->data.cond.expr1); - CheckExpr(expr->data.cond.expr2); - return; - case EASS: - if (ENODE_IS_INDIRECT_TO(expr->data.diadic.left, EOBJREF)) { - CheckExpr(expr->data.diadic.right); - AddVar(expr->data.diadic.left->data.monadic->data.objref, 1); - return; - } - case EMUL: - case EMULV: - case EDIV: - case EMODULO: - case EADDV: - case ESUBV: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case ELAND: - case ELOR: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case ECOMMA: - case EPMODULO: - case EROTL: - case EROTR: - case EBCLR: - case EBTST: - case EBSET: - CheckExpr(expr->data.diadic.left); - expr = expr->data.diadic.right; - break; - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case EFORCELOAD: - case ETYPCON: - case EBITFIELD: - expr = expr->data.monadic; - break; - case ENULLCHECK: - CheckExpr(expr->data.nullcheck.nullcheckexpr); - expr = expr->data.nullcheck.condexpr; - break; - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EPRECOMP: - case ELABEL: - case EVECTOR128CONST: - return; - default: - CError_FATAL(1332); - } - } -} - -static short CheckPath(COptBlock *block, short var) { - COptBlockList *list; - - if (block->x1E) - return TestSetBit(block->set1, var); - - block->x1E = 1; - if (TestSetBit(block->set1, var)) - return -1; - if (TestSetBit(block->set2, var)) - return 0; - - for (list = block->blocks2; list; list = list->next) { - if (CheckPath(list->block, var)) { - SetSetBit(block->set1, var); - return -1; - } - } - - return 0; -} - -static void MarkPre(COptBlock *block, short var) { - COptBlockList *list; - -restart: - block->x1E = 1; - for (list = block->blocks; list; list = list->next) { - if (!list->block->x1E) { - if (!TestSetBit(list->block->set2, var)) { - SetSetBit(list->block->set1, var); - if (!list->next) { - block = list->block; - goto restart; - } - MarkPre(list->block, var); - } else { - list->block->x1E = 1; - } - } - } -} - -static void CheckVarUsage(void) { - short local; - COptBlock *block; - short counter; - - for (currentblock = basicblocks; currentblock; currentblock = currentblock->next) { - Statement *stmt = currentblock->stmt; - if (currentblock->x1C > 0 && stmt->type == ST_LABEL && (stmt->flags & StmtFlag_1)) { - short i; - for (i = 0; i < localcount; i++) - SetSetBit(currentblock->set2, i); - } - - for (counter = currentblock->x1C; counter > 0; counter--) { - if (stmt->type >= ST_EXPRESSION && stmt->type <= ST_GOTOEXPR && stmt->expr) - CheckExpr(stmt->expr); - stmt = stmt->next; - } - } - - for (local = 0; local < localcount; local++) { - for (block = basicblocks; block; block = block->next) { - if (!block->x1E && TestSetBit(block->set1, local)) - MarkPre(block, local); - } - for (block = basicblocks; block; block = block->next) { - block->x1E = 0; - } - } -} - -static void SplitCommaExpressions(void) { - COptBlock *block; - Statement *stmt; - ENode *expr; - Statement *stmtcopy; - short counter; - Boolean flag; - - block = basicblocks->next; - while (block) { - stmt = block->stmt; - counter = block->x1C; - flag = 1; - while (counter > 0) { - if (stmt->type >= ST_EXPRESSION && stmt->type <= ST_GOTOEXPR) { - if ((expr = stmt->expr) && ENODE_IS(expr, ECOMMA)) { - stmtcopy = lalloc(sizeof(Statement)); - *stmtcopy = *stmt; - stmt->next = stmtcopy; - stmt->type = ST_EXPRESSION; - stmt->expr = expr->data.diadic.left; - stmtcopy->expr = expr->data.diadic.right; - block->x1C++; - flag = 0; - break; - } - } - - stmt = stmt->next; - counter--; - } - - if (flag) - block = block->next; - } -} - -static void BasicBlockAnalyze(Statement *stmt) { - COptBlock *block; - ObjectList *objlist; - COptBlockList *scan; - COptBlockList *list; - CLabel *label; - COptBlock *iblock; - COptBlock *oblock; - SwitchCase *swcase; - - setbytes = 2 * ((localcount - 1) / 16) + 2; - if (copts.globaloptimizer) { - setbytes += 32; - extravars = 0; - } - - block = newblock(); - basicblocks = block; - block->stmt = NULL; - block->x1C = 0; - - if (stmt) { - list = lalloc(sizeof(COptBlockList)); - list->next = NULL; - block->blocks2 = list; - list->block = (COptBlock *) stmt; - } - - for (objlist = arguments; objlist; objlist = objlist->next) { - SetSetBit(block->set2, objlist->object->u.var.info->varnumber); - } - - while (stmt) { - int counter; - - block->next = newblock(); - block = block->next; - block->stmt = stmt; - counter = 1; - - innerLoop: - switch (stmt->type) { - case ST_ASM: - label = InlineAsm_GetReferencedLabel(stmt); - if (!label) - goto jumpahead; - list = lalloc(sizeof(COptBlockList)); - list->next = block->blocks2; - block->blocks2 = list; - list->block = (COptBlock *) label->stmt; - if (stmt->next) { - list = lalloc(sizeof(COptBlockList)); - list->next = block->blocks2; - block->blocks2 = list; - list->block = (COptBlock *) stmt->next; - } - stmt = stmt->next; - block->x1C = counter; - continue; - case ST_NOP: - case ST_LABEL: - case ST_ENTRY: - if (stmt->next && stmt->next->type != ST_LABEL) { - stmt = stmt->next; - counter++; - goto innerLoop; - } - break; - case ST_EXPRESSION: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - jumpahead: - if (stmt->next && stmt->next->type == ST_GOTO) { - stmt = stmt->next; - counter++; - goto innerLoop; - } - break; - } - - switch (stmt->type) { - case ST_SWITCH: - label = ((SwitchInfo *) stmt->label)->defaultlabel; - if (label != cleanreturnlabel) { - list = lalloc(sizeof(COptBlockList)); - list->next = block->blocks2; - block->blocks2 = list; - list->block = (COptBlock *) label->stmt; - } - for (swcase = ((SwitchInfo *) stmt->label)->cases; swcase; swcase = swcase->next) { - label = swcase->label; - if (label != cleanreturnlabel) { - list = lalloc(sizeof(COptBlockList)); - list->next = block->blocks2; - block->blocks2 = list; - list->block = (COptBlock *) label->stmt; - } - } - break; - case ST_RETURN: - case ST_EXIT: - case ST_GOTOEXPR: - break; - case ST_GOTO: - case ST_IFGOTO: - case ST_IFNGOTO: - case ST_OVF: - label = stmt->label; - if (label != cleanreturnlabel) { - list = lalloc(sizeof(COptBlockList)); - list->next = block->blocks2; - block->blocks2 = list; - list->block = (COptBlock *) label->stmt; - } - if (stmt->type == ST_GOTO) - break; - default: - if (stmt->next) { - list = lalloc(sizeof(COptBlockList)); - list->next = block->blocks2; - block->blocks2 = list; - list->block = (COptBlock *) stmt->next; - } - break; - } - - stmt = stmt->next; - block->x1C = counter; - } - - for (oblock = basicblocks; oblock; oblock = oblock->next) { - for (scan = oblock->blocks2; scan; scan = scan->next) { - stmt = (Statement *) scan->block; - for (iblock = basicblocks->next; iblock; iblock = iblock->next) { - if (iblock->stmt == stmt) { - scan->block = iblock; - list = lalloc(sizeof(COptBlockList)); - list->next = iblock->blocks; - iblock->blocks = list; - list->block = oblock; - break; - } - } - - CError_ASSERT(1602, iblock); - } - } - - SplitCommaExpressions(); - CheckVarUsage(); -} - -static CLabel *finallabel(CLabel *label, Statement *stmt) { - Statement *scan; - - for (scan = label->stmt; scan; scan = scan->next) { - if (scan->type > ST_LABEL) { - if (scan == stmt) - return label; - if (scan->type == ST_GOTO) { - if (scan->label != label) - stmtchanged = 1; - return scan->label; - } - return label; - } - } - - return label; -} - -static void optimizegoto(Statement *stmt) { - Statement *scan; - - for (scan = stmt->next; scan; scan = scan->next) { - if (stmt->label->stmt == scan) { - stmt->type = ST_NOP; - stmtchanged = 1; - return; - } - if (scan->type > ST_LABEL) - break; - } - - stmt->label = finallabel(stmt->label, stmt); -} - -static void removeif(Statement *stmt, Boolean flag) { - if (((stmt->type == ST_IFGOTO) && flag) || ((stmt->type == ST_IFNGOTO) && !flag)) { - Statement *copy = lalloc(sizeof(Statement)); - *copy = *stmt; - copy->type = ST_GOTO; - stmt->next = copy; - } - stmt->type = ST_EXPRESSION; - stmtchanged = 1; -} - -static void optimizeif(Statement *stmt) { - Statement *scan; - Statement *scan2; - Boolean flag; - - if (iszero(stmt->expr)) { - removeif(stmt, 0); - return; - } - if (isnotzero(stmt->expr)) { - removeif(stmt, 1); - return; - } - - for (scan = stmt->next, flag = 0; scan; scan = scan->next) { - if (scan->type > ST_LABEL) { - if (scan->type == ST_GOTO) { - if (scan->label == stmt->label) { - stmt->type = ST_EXPRESSION; - stmtchanged = 1; - return; - } - - if (!flag) { - for (scan2 = scan->next; scan2; scan2 = scan2->next) { - if (scan2->type > ST_LABEL) - break; - if (stmt->label->stmt == scan2) { - stmt->label = scan->label; - scan->type = ST_NOP; - if (stmt->type == ST_IFGOTO) - stmt->type = ST_IFNGOTO; - else - stmt->type = ST_IFGOTO; - stmtchanged = 1; - stmt->label = finallabel(stmt->label, stmt); - return; - } - } - } - } else if (scan->type == ST_RETURN && !scan->expr && !static_for_inlines && !flag) { - for (scan2 = scan->next; scan2; scan2 = scan2->next) { - if (scan2->type > ST_LABEL) - break; - if (stmt->label->stmt == scan2) { - stmt->label = cleanreturnlabel; - needs_cleanup = 1; - scan->type = ST_NOP; - if (stmt->type == ST_IFGOTO) - stmt->type = ST_IFNGOTO; - else - stmt->type = ST_IFGOTO; - stmtchanged = 1; - return; - } - } - } - break; - } - - if (scan->type == ST_LABEL) - flag = 1; - - if (stmt->label->stmt == scan) { - stmt->type = ST_EXPRESSION; - stmtchanged = 1; - return; - } - } - - stmt->label = finallabel(stmt->label, stmt); -} - -static void optimizeswitch(Statement *stmt) { - SwitchInfo *info; - SwitchCase *swcase; - - info = (SwitchInfo *) stmt->label; - CError_ASSERT(1746, info && info->cases && info->defaultlabel); - - info->defaultlabel = finallabel(info->defaultlabel, stmt); - for (swcase = info->cases; swcase; swcase = swcase->next) - swcase->label = finallabel(swcase->label, stmt); - - if (ENODE_IS(stmt->expr, EINTCONST)) { - for (swcase = info->cases; swcase; swcase = swcase->next) { - if (CInt64_GreaterEqual(swcase->min, stmt->expr->data.intval) && CInt64_LessEqual(swcase->max, stmt->expr->data.intval)) - break; - } - - stmt->type = ST_GOTO; - stmt->label = swcase ? swcase->label : info->defaultlabel; - } -} - -static void removeunusedlabels(Statement *stmt) { - Statement *scan; - CLabel *label; - SwitchCase *swcase; - ExceptionAction *action; - - for (scan = stmt; scan; scan = scan->next) - scan->marked = 0; - - for (scan = stmt; scan; scan = scan->next) { - switch (scan->type) { - case ST_GOTO: - case ST_IFGOTO: - case ST_IFNGOTO: - case ST_OVF: - if (scan->label->stmt) - scan->label->stmt->marked = 1; - break; - case ST_SWITCH: - ((SwitchInfo *) scan->label)->defaultlabel->stmt->marked = 1; - for (swcase = ((SwitchInfo *) scan->label)->cases; swcase; swcase = swcase->next) - swcase->label->stmt->marked = 1; - break; - case ST_ASM: - if ((label = InlineAsm_GetReferencedLabel(scan))) - label->stmt->marked = 1; - if ((label = InlineAsm_GetReferencedLabel2(scan))) - label->stmt->marked = 1; - break; - case ST_BEGINLOOP: - ((LoopInfo *) scan->expr)->stmt->marked = 1; - break; - case ST_ENDLOOP: - if (scan->next->type == ST_GOTO && scan->next->next->type == ST_LABEL) - scan->next->next->marked = 1; - break; - default: - for (action = scan->dobjstack; action; action = action->prev) { - if (action->type == EAT_CATCHBLOCK) { - action->data.catch_block.catch_label->stmt->marked = 1; - action->data.catch_block.catch_label->stmt->flags = action->data.catch_block.catch_label->stmt->flags | StmtFlag_1; - } else if (action->type == EAT_SPECIFICATION) { - action->data.specification.unexp_label->stmt->marked = 1; - action->data.specification.unexp_label->stmt->flags = action->data.specification.unexp_label->stmt->flags | StmtFlag_1; - } - } - } - } - - for (scan = stmt; scan; scan = scan->next) { - if (scan->type == ST_LABEL && !scan->marked && !(scan->flags & StmtFlag_1)) { - scan->type = ST_NOP; - stmtchanged = 1; - } - } -} - -static void optimizebranches(Statement *stmt) { - removeunusedlabels(stmt); - while (stmt) { - switch (stmt->type) { - case ST_GOTO: - optimizegoto(stmt); - break; - case ST_IFGOTO: - case ST_IFNGOTO: - optimizeif(stmt); - break; - case ST_SWITCH: - optimizeswitch(stmt); - break; - } - stmt = stmt->next; - } -} - -void SetVarUsage(Object *obj, Boolean noregister) { - VarInfo *vi; - CError_ASSERT(1875, obj->datatype != DALIAS); - - if (obj->datatype == DLOCAL || obj->datatype == DNONLAZYPTR) { - vi = obj->u.var.info; - vi->used = 1; - if (!copts.globaloptimizer) { - if (copts.optimizesize) - vi->usage++; - else - vi->usage += curstmtvalue; - } - - if (noregister) - vi->noregister = 1; - } -} - -static void checkexpression(ENode *expr) { - ENodeList *list; - - while (1) { - switch (expr->type) { - case EOBJREF: - SetVarUsage(expr->data.objref, 1); - return; - case EINDIRECT: - if (ENODE_IS(expr->data.monadic, EOBJREF)) { - SetVarUsage(expr->data.monadic->data.objref, 0); - return; - } - expr = expr->data.monadic; - break; - case EFUNCCALL: - case EFUNCCALLP: - copt_isleaffunction = 0; - checkexpression(expr->data.funccall.funcref); - for (list = expr->data.funccall.args; list; list = list->next) - checkexpression(list->node); - return; - case ECOND: - case ECONDASS: - checkexpression(expr->data.cond.cond); - checkexpression(expr->data.cond.expr1); - checkexpression(expr->data.cond.expr2); - return; - case EMUL: - case EMULV: - case EDIV: - case EMODULO: - case EADDV: - case ESUBV: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case ELAND: - case ELOR: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case ECOMMA: - case EPMODULO: - case EROTL: - case EROTR: - case EBCLR: - case EBTST: - case EBSET: - checkexpression(expr->data.diadic.left); - expr = expr->data.diadic.right; - break; - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case EFORCELOAD: - case ETYPCON: - case EBITFIELD: - expr = expr->data.monadic; - break; - case ENULLCHECK: - checkexpression(expr->data.nullcheck.nullcheckexpr); - expr = expr->data.nullcheck.condexpr; - break; - case EINTCONST: - case EFLOATCONST: - case EPRECOMP: - case ELABEL: - case EVECTOR128CONST: - return; - case ESTRINGCONST: - return; - default: - CError_FATAL(1998); - } - } -} - -static void checklocalusage(Statement *stmt) { - Statement *scan; - - for (scan = stmt; scan; scan = scan->next) { - if (scan->type >= ST_EXPRESSION && scan->type <= ST_GOTOEXPR && scan->expr) { - curstmtvalue = scan->value; - checkexpression(scan->expr); - } else if (scan->type == ST_ASM) { - curstmtvalue = scan->value; - InlineAsm_CheckLocalUsage(scan); - } - } -} - -static void colorcode(Statement *stmt) { - CLabel *label; - SwitchCase *swcase; - - while (stmt && !stmt->marked) { - stmt->marked = 1; - switch (stmt->type) { - case ST_GOTOEXPR: - return; - case ST_IFGOTO: - case ST_IFNGOTO: - case ST_OVF: - colorcode(stmt->label->stmt); - break; - case ST_GOTO: - case ST_EXIT: - stmt = stmt->label->stmt; - continue; - case ST_RETURN: - return; - case ST_SWITCH: - for (swcase = ((SwitchInfo *) stmt->label)->cases; swcase; swcase = swcase->next) - colorcode(swcase->label->stmt); - stmt = ((SwitchInfo *) stmt->label)->defaultlabel->stmt; - continue; - case ST_ASM: - if ((label = InlineAsm_GetReferencedLabel(stmt))) - colorcode(label->stmt); - if ((label = InlineAsm_GetReferencedLabel2(stmt))) - colorcode(label->stmt); - break; - case ST_ENDLOOP: - if (stmt->next && stmt->next->type == ST_GOTO) { - stmt = stmt->next; - stmt->marked = 1; - } - break; - case ST_NOP: - case ST_LABEL: - case ST_EXPRESSION: - case ST_ENTRY: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - case ST_BEGINLOOP: - break; - default: - CError_FATAL(2096); - } - stmt = stmt->next; - } -} - -static void removeunusedcode(Statement *stmt) { - Statement *scan; - - for (scan = stmt; scan; scan = scan->next) - scan->marked = 0; - - colorcode(stmt); - for (scan = stmt; scan; scan = scan->next) { - if (!scan->marked && (scan->flags & StmtFlag_1)) - colorcode(scan); - } - - for (scan = stmt; scan; scan = scan->next) { - if (!scan->marked && scan->type != ST_NOP) { - scan->type = ST_NOP; - stmtchanged = 1; - } - } -} - -static void COpt_ReturnCheck(Object *obj, Statement *stmt) { - if ((copts.pedantic || copts.cplusplus) && obj && TYPE_FUNC(obj->type)->functype != &stvoid) { - while (stmt) { - if (!stmt->next && stmt->type != ST_GOTO && stmt->type != ST_RETURN) { - CError_Warning(CErrorStr184); - break; - } - - if (stmt->type == ST_RETURN && !stmt->expr && !(stmt->flags & StmtFlag_8)) { - CError_Warning(CErrorStr184); - break; - } - - stmt = stmt->next; - } - } -} - -static void COpt_Optimize(Object *obj, Statement *stmt) { - Statement **ptr; - - do { - stmtchanged = 0; - optimizebranches(stmt->next); - removeunusedcode(stmt->next); - } while (stmtchanged); - - ptr = &stmt->next; - while (*ptr) { - if ((*ptr)->type == ST_NOP) - *ptr = (*ptr)->next; - else - ptr = &(*ptr)->next; - } -} - -static void COpt_ELABELCallBack(ENode *expr) { - CError_ASSERT(2195, expr->data.label->stmt && expr->data.label->stmt->type == ST_LABEL); - expr->data.label->stmt->flags = expr->data.label->stmt->flags | StmtFlag_1; -} - -void COpt_SimpleOptimizer(Object *obj, Statement *stmt) { - Statement *scan; - - for (scan = stmt; scan; scan = scan->next) { - if ((scan->type >= ST_EXPRESSION && scan->type <= ST_GOTOEXPR) && scan->expr) - CExpr_SearchExprTree(scan->expr, COpt_ELABELCallBack, 1, ELABEL); - } - - static_for_inlines = 1; - cleanreturnlabel = NULL; - COpt_Optimize(obj, stmt); - COpt_ReturnCheck(obj, stmt); -} - -Statement *COpt_Optimizer(Object *obj, Statement *stmt) { - copt_isleaffunction = 1; - if (copts.globaloptimizer) - stmt = IRO_Optimizer(obj, stmt); - - static_for_inlines = 0; - COpt_Optimize(obj, stmt); - - if (obj && !(obj->qual & Q_INLINE)) - COpt_ReturnCheck(obj, stmt); - - checklocalusage(stmt->next); - return stmt; -} diff --git a/compiler_and_linker/unsorted/CParser.c b/compiler_and_linker/unsorted/CParser.c deleted file mode 100644 index e53b0bf..0000000 --- a/compiler_and_linker/unsorted/CParser.c +++ /dev/null @@ -1,3477 +0,0 @@ -#include "compiler/CParser.h" -#include "compiler/CABI.h" -#include "compiler/CClass.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInit.h" -#include "compiler/CInline.h" -#include "compiler/CInt64.h" -#include "compiler/CIRTransform.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CObjC.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CScope.h" -#include "compiler/CSOM.h" -#include "compiler/CTemplateNew.h" -#include "compiler/CTemplateTools.h" -#include "compiler/CodeGen.h" -#include "compiler/CompilerTools.h" -#include "compiler/IrOptimizer.h" -#include "compiler/IroPointerAnalysis.h" -#include "compiler/ObjGenMachO.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/templates.h" -#include "cos.h" - -FileOffsetInfo cparser_fileoffset; -TStreamElement symdecltoken; -ParserTryBlock *trychain; -Boolean inassembler; -Boolean dont_set_references; -TypeStruct ptmstruct; -TypeStruct catchinfostruct; -Boolean in_assembler; -Boolean illegalimplicitconversion; -Boolean in_func_arglist; -NameSpaceName *newp_fobj; -NameSpaceName *newa_fobj; -NameSpaceName *delp_fobj; -NameSpaceName *dela_fobj; -Object *newh_func; -Object *delh_func; -Object *copy_func; -Object *clear_func; -Object *Rgtid_func; -Object *Rdync_func; -Object *rt_ptmf_cast; -Object *rt_ptmf_cmpr; -Object *rt_ptmf_test; -Object *rt_ptmf_call; -Object *rt_ptmf_scall; -Object *rt_ptmf_call4; -Object *rt_ptmf_scall4; -Object *rt_ptmf_null; -Object *rt_som_new; -Object *rt_som_newcheck; -Object *rt_som_check; -Object *rt_som_glue1; -Object *rt_som_glue2; -Object *rt_som_glue3; -Object *carr_func; -Object *cnar_func; -Object *darr_func; -Object *dnar_func; -Object *dnar3_func; -Object *Xgreg_func; -Object *Xthrw_func; -Object *Xicth_func; -Object *Xecth_func; -Object *Xunex_func; -CompilerLinkerOptions copts; -GList name_mangle_list; -HashNameNode *no_name_node; -HashNameNode *temp_argument_name; -HashNameNode *this_name_node; -HashNameNode *self_name_node; -HashNameNode *vptr_name_node; -CallbackAction *callbackactions; -Boolean fatalerrors; -Boolean anyerrors; -jmp_buf errorreturn; -static HashNameNode *uniquenamespacename; -static SInt32 uniqueid; - -struct ClassAction { - struct ClassAction *next; - TypeClass *tclass; -}; -static struct ClassAction *cparser_classactions; - -struct ParentCleanup { - struct ParentCleanup *next; - TypeClass *tclass; -}; -static struct ParentCleanup *cparser_parentcleanup; - -struct SFuncList { - struct SFuncList *next; - Object *func; - Object *obj; - ENode *expr; -}; -static struct SFuncList *cparser_sfunclist; - -char string[256]; -SInt32 compilererrornum; -SInt32 compilererrfile; -SInt32 compilererrline; - -Type sttemplexpr = {TYPETEMPLDEPEXPR, 0}; -Type stillegal = {TYPEILLEGAL, 1}; -Type stvoid = {TYPEVOID, 0}; -TypePointer void_ptr = {TYPEPOINTER, 0, &stvoid, 0}; -TypeFunc rt_func = {TYPEFUNC, 0, NULL, NULL, &stvoid, 0, 0}; - -// forward declarations -static void CParser_ParseDeclaration(DeclInfo *di); - -Object *CParser_NewRTFunc(Type *rettype, HashNameNode *name, Boolean flag, int argcount, ...) { - Object *obj; - FuncArg *args; - FuncArg *arg; - TypeFunc *tfunc; - va_list va; - - args = NULL; - if (argcount) { - va_start(va, argcount); - while (--argcount >= 0) { - if (args) { - arg->next = CParser_NewFuncArg(); - arg = arg->next; - } else { - arg = CParser_NewFuncArg(); - args = arg; - } - arg->type = va_arg(va, Type *); - } - va_end(va); - } - - obj = CParser_NewFunctionObject(NULL); - - tfunc = galloc(sizeof(TypeFunc)); - memclrw(tfunc, sizeof(TypeFunc)); - tfunc->type = TYPEFUNC; - tfunc->functype = rettype; - tfunc->args = args; - CDecl_SetFuncFlags(tfunc, 0); - - obj->name = name; - obj->type = TYPE(tfunc); - if (flag == 1) - obj->qual = Q_MANGLE_NAME; - - return obj; -} - -Boolean CParser_IsPublicRuntimeObject(Object *obj) { - if (newp_fobj->first.object == OBJ_BASE(obj) && !newp_fobj->first.next) - return 1; - if (newa_fobj->first.object == OBJ_BASE(obj) && !newa_fobj->first.next) - return 1; - if (delp_fobj->first.object == OBJ_BASE(obj) && !delp_fobj->first.next) - return 1; - if (dela_fobj->first.object == OBJ_BASE(obj) && !dela_fobj->first.next) - return 1; - return CodeGen_IsPublicRuntimeObject(obj); -} - -Object *CParser_FindPublicRuntimeObject(HashNameNode *name) { - NameSpaceObjectList *list = CScope_FindName(cscope_root, name); - if (list && list->object->otype == OT_OBJECT && (!list->next || list->next->object->otype == OT_TYPETAG)) - return OBJECT(list->object); - else - return NULL; -} - -Boolean CParser_ReInitRuntimeObjects(Boolean is_precompiler) { - if (!(newp_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_NEW)))) - return 0; - if (!(newa_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_NEW_ARRAY)))) - return 0; - if (!(delp_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_DELETE)))) - return 0; - if (!(dela_fobj = CScope_FindNameSpaceName(cscope_root, CMangler_OperatorName(TK_DELETE_ARRAY)))) - return 0; - - newh_func->name = GetHashNameNodeExport("__new_hdl"); - delh_func->name = GetHashNameNodeExport("__del_hdl"); - copy_func->name = GetHashNameNodeExport("__copy"); - clear_func->name = GetHashNameNodeExport("__clear"); - Rgtid_func->name = GetHashNameNodeExport("__get_typeid"); - Rdync_func->name = GetHashNameNodeExport("__dynamic_cast"); - rt_ptmf_cast->name = GetHashNameNodeExport("__ptmf_cast"); - rt_ptmf_cmpr->name = GetHashNameNodeExport("__ptmf_cmpr"); - rt_ptmf_test->name = GetHashNameNodeExport("__ptmf_test"); - rt_ptmf_call->name = GetHashNameNodeExport("__ptmf_call"); - rt_ptmf_scall->name = GetHashNameNodeExport("__ptmf_scall"); - rt_ptmf_call4->name = GetHashNameNodeExport("__ptmf_call4"); - rt_ptmf_scall4->name = GetHashNameNodeExport("__ptmf_scall4"); - rt_ptmf_null->name = GetHashNameNodeExport("__ptmf_null"); - rt_som_new->name = GetHashNameNodeExport("__som_new"); - rt_som_newcheck->name = GetHashNameNodeExport("__som_check_new"); - rt_som_check->name = GetHashNameNodeExport("__som_check_ev"); - rt_som_glue1->name = GetHashNameNodeExport("_som_ptrgl4"); - rt_som_glue2->name = GetHashNameNodeExport("_som_ptrgl5"); - rt_som_glue3->name = GetHashNameNodeExport("_som_ptrgl_"); - carr_func->name = GetHashNameNodeExport("__construct_array"); - cnar_func->name = GetHashNameNodeExport("__construct_new_array"); - darr_func->name = GetHashNameNodeExport("__destroy_arr"); - dnar_func->name = GetHashNameNodeExport("__destroy_new_array"); - dnar3_func->name = GetHashNameNodeExport("__destroy_new_array3"); - Xgreg_func->name = GetHashNameNodeExport("__register_global_object"); - Xthrw_func->name = GetHashNameNodeExport("__throw"); - Xicth_func->name = GetHashNameNodeExport("__init__catch"); - Xecth_func->name = GetHashNameNodeExport("__end__catch"); - Xunex_func->name = GetHashNameNodeExport("__unexpected"); - - CMangler_Setup(); - - no_name_node = GetHashNameNodeExport("@no_name@"); - temp_argument_name = GetHashNameNodeExport("@temp_ptr@"); - this_name_node = GetHashNameNodeExport("this"); - self_name_node = GetHashNameNodeExport("self"); - vptr_name_node = GetHashNameNodeExport("__vptr$"); - - CSOM_Setup(is_precompiler); - return CodeGen_ReInitRuntimeObjects(is_precompiler); -} - -static void CParser_SetupRuntimeObjects(void) { - ExceptSpecList *exspecs; - Type *sizet; - Object *func; - - exspecs = galloc(sizeof(ExceptSpecList)); - memclrw(exspecs, sizeof(ExceptSpecList)); - - sizet = CABI_GetSizeTType(); - - func = CParser_NewRTFunc( - TYPE(&void_ptr), CMangler_OperatorName(TK_NEW), 1, - 1, sizet); - CScope_AddGlobalObject(func); - - func = CParser_NewRTFunc( - TYPE(&void_ptr), CMangler_OperatorName(TK_NEW_ARRAY), 1, - 1, sizet); - CScope_AddGlobalObject(func); - - func = CParser_NewRTFunc( - TYPE(&stvoid), CMangler_OperatorName(TK_DELETE), 1, - 1, &void_ptr); - CError_ASSERT(379, IS_TYPE_FUNC(func->type)); - TYPE_FUNC(func->type)->exspecs = exspecs; - CScope_AddGlobalObject(func); - - func = CParser_NewRTFunc( - TYPE(&stvoid), CMangler_OperatorName(TK_DELETE_ARRAY), 1, - 1, &void_ptr); - CError_ASSERT(387, IS_TYPE_FUNC(func->type)); - TYPE_FUNC(func->type)->exspecs = exspecs; - CScope_AddGlobalObject(func); - - newh_func = CParser_NewRTFunc( - TYPE(&void_ptr), NULL, 0, - 1, sizet); - delh_func = CParser_NewRTFunc( - TYPE(&stvoid), NULL, 0, - 1, &void_ptr); - - Rgtid_func = CParser_NewRTFunc( - TYPE(&void_ptr), NULL, 0, - 2, &void_ptr, &stsignedlong); - Rdync_func = CParser_NewRTFunc( - TYPE(&void_ptr), NULL, 0, - 5, &void_ptr, &stsignedlong, &void_ptr, &void_ptr, &stsignedshort); - - copy_func = CParser_NewRTFunc( - TYPE(&void_ptr), NULL, 2, - 3, &void_ptr, &void_ptr, sizet); - clear_func = CParser_NewRTFunc( - TYPE(&void_ptr), NULL, 2, - 2, &void_ptr, sizet); - - rt_ptmf_cast = CParser_NewRTFunc( - TYPE(&void_ptr), NULL, 2, - 3, &stsignedlong, &void_ptr, &void_ptr); - rt_ptmf_cmpr = CParser_NewRTFunc( - TYPE(&stsignedlong), NULL, 2, - 2, &void_ptr, &void_ptr); - rt_ptmf_test = CParser_NewRTFunc( - TYPE(&stsignedlong), NULL, 2, - 1, &void_ptr); - - rt_ptmf_call = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); - rt_ptmf_scall = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); - rt_ptmf_call4 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); - rt_ptmf_scall4 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); - - rt_ptmf_null = CParser_NewGlobalDataObject(NULL); - rt_ptmf_null->type = &stvoid; - - rt_som_new = CParser_NewRTFunc( - TYPE(&void_ptr), NULL, 2, - 3, &void_ptr, &stsignedlong, &stsignedlong); - rt_som_newcheck = CParser_NewRTFunc( - TYPE(&stvoid), NULL, 0, - 1, &void_ptr); - rt_som_check = CParser_NewRTFunc( - TYPE(&stvoid), NULL, 0, - 1, &void_ptr); - rt_som_glue1 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); - rt_som_glue2 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); - rt_som_glue3 = CParser_NewRTFunc(TYPE(&stvoid), NULL, 2, 0); - - carr_func = CParser_NewRTFunc( - TYPE(&stvoid), NULL, 0, - 5, &void_ptr, &void_ptr, &void_ptr, sizet, sizet); - cnar_func = CParser_NewRTFunc( - TYPE(&void_ptr), NULL, 0, - 5, &void_ptr, &void_ptr, &void_ptr, sizet, sizet); - darr_func = CParser_NewRTFunc( - TYPE(&stvoid), NULL, 0, - 4, &void_ptr, &void_ptr, sizet, sizet); - dnar_func = CParser_NewRTFunc( - TYPE(&stvoid), NULL, 0, - 2, &void_ptr, &void_ptr); - dnar3_func = CParser_NewRTFunc( - TYPE(&stvoid), NULL, 0, - 4, &void_ptr, &void_ptr, &void_ptr, &stsignedshort); - - Xgreg_func = CParser_NewRTFunc( - TYPE(&void_ptr), NULL, 0, - 3, &void_ptr, &void_ptr, &void_ptr); - Xthrw_func = CParser_NewRTFunc( - TYPE(&stvoid), NULL, 0, - 3, &void_ptr, &void_ptr, &void_ptr); - Xicth_func = CParser_NewRTFunc( - TYPE(&stvoid), NULL, 0, - 1, &void_ptr); - Xecth_func = CParser_NewRTFunc( - TYPE(&stvoid), NULL, 0, - 1, &void_ptr); - Xunex_func = CParser_NewRTFunc( - TYPE(&stvoid), NULL, 0, - 1, &void_ptr); - - CodeGen_SetupRuntimeObjects(); - CError_ASSERT(534, CParser_ReInitRuntimeObjects(0)); -} - -void CParser_Setup(void) { - CScope_Setup(); - - name_mangle_list.data = NULL; - if (InitGList(&name_mangle_list, 256)) - CError_NoMem(); - - void_ptr.size = 4; - CError_Init(); - CInit_Init(); - CClass_Init(); - CIRTrans_Setup(); - CObjC_Setup(); - CInline_Init(); - - in_assembler = 0; - in_func_arglist = 0; - CParser_SetUniqueID(1); - dont_set_references = 0; - - copts.sideeffects = 1; - cparser_classactions = NULL; - name_obj_check = NULL; - callbackactions = NULL; - init_expressions = NULL; - cparser_sfunclist = NULL; - trychain = NULL; - cparser_parentcleanup = NULL; - - memclrw(&cparser_fileoffset, sizeof(FileOffsetInfo)); - - memclrw(&catchinfostruct, sizeof(TypeStruct)); - catchinfostruct.type = TYPESTRUCT; - catchinfostruct.size = 24; - catchinfostruct.stype = STRUCT_TYPE_STRUCT; - catchinfostruct.align = 4; - - memclrw(&ptmstruct, sizeof(TypeStruct)); - ptmstruct.type = TYPESTRUCT; - ptmstruct.size = 12; - ptmstruct.stype = STRUCT_TYPE_STRUCT; - ptmstruct.align = 4; - - CMach_Configure(); - CTempl_Setup(); - - uniquenamespacename = NULL; - disallowgreaterthan = 0; - - CParser_SetupRuntimeObjects(); -} - -void CParser_Cleanup(void) { - CTempl_Cleanup(); - CIRTrans_Cleanup(); - CObjC_Cleanup(); - CScope_Cleanup(); - FreeGList(&name_mangle_list); -} - -short GetPrec(short token) { - switch (token) { - case '%': - case '*': - case '/': - return 11; - case '+': - case '-': - return 10; - case TK_SHL: - case TK_SHR: - return 9; - case '<': - case '>': - case TK_LESS_EQUAL: - case TK_GREATER_EQUAL: - return 8; - case TK_LOGICAL_EQ: - case TK_LOGICAL_NE: - return 7; - case '&': - return 6; - case '^': - return 5; - case '|': - return 4; - case TK_LOGICAL_AND: - return 3; - case TK_LOGICAL_OR: - return 2; - default: - return 0; - } -} - -Boolean CParser_ParseOperatorName(short *token, Boolean flag1, Boolean flag2) { - HashNameNode *name; - - switch ((tk = lex())) { - case TK_NEW: - case TK_DELETE: - if (lookahead() == '[') { - lex(); - if (lex() != ']') - CError_Error(CErrorStr125); - //if (tk == TK_NEW) - // tk = TK_NEW_ARRAY; - //else - // tk = TK_DELETE_ARRAY; - tk = (tk == TK_NEW) ? TK_NEW_ARRAY : TK_DELETE_ARRAY; - } - break; - case '(': - if ((tk = lex()) != ')') { - CError_Error(CErrorStr204); - return 0; - } - tk = '('; - break; - case '[': - if ((tk = lex()) != ']') { - CError_Error(CErrorStr204); - return 0; - } - tk = '['; - break; - } - - if ((name = CMangler_OperatorName(tk))) { - if (token) - *token = tk; - tk = lex(); - tkidentifier = name; - return 1; - } - - if (flag1) { - if (flag2) { - DeclInfo declinfo; - memclrw(&declinfo, sizeof(DeclInfo)); - conversion_type_name(&declinfo); - tkidentifier = CMangler_ConversionFuncName(declinfo.thetype, declinfo.qual); - } - if (token) - *token = 0; - return 1; - } else { - CError_Error(CErrorStr204); - return 0; - } -} - -SInt32 CParser_GetUniqueID(void) { - return uniqueid++; -} - -void CParser_PrintUniqueID(char *buf) { - SInt32 id; - char mybuf[16]; - char *ptr; - - ptr = mybuf; - id = CParser_GetUniqueID(); - while (id) { - *(ptr++) = '0' + (id - ((id / 10) * 10)); - id = id / 10; - } - - while (ptr > mybuf) - *(buf++) = *(--ptr); - - *buf = 0; -} - -void CParser_SetUniqueID(SInt32 id) { - uniqueid = id; -} - -HashNameNode *CParser_GetUniqueName(void) { - char buf[20]; - buf[0] = '@'; - CParser_PrintUniqueID(buf + 1); - return GetHashNameNodeExport(buf); -} - -HashNameNode *CParser_NameConcat(const char *a, const char *b) { - char mybuf[256]; - char *buf; - char *dst; - int len; - - len = strlen(a) + strlen(b); - if (len > (sizeof(mybuf) - 1)) { - buf = lalloc(len + 1); - dst = buf; - } else { - buf = mybuf; - dst = buf; - } - - while (*a) - *(dst++) = *(a++); - while (*b) - *(dst++) = *(b++); - *dst = 0; - - return GetHashNameNodeExport(buf); -} - -HashNameNode *CParser_AppendUniqueName(char *prefix) { - char buf[256]; - char *dst; - int i; - - dst = buf; - for (i = 0; *prefix && i < 240; i++) { - *(dst++) = *(prefix++); - } - *(dst++) = '$'; - - CParser_PrintUniqueID(dst); - return GetHashNameNodeExport(buf); -} - -HashNameNode *CParser_AppendUniqueNameFile(char *prefix) { - Str255 filename; - char buf[256]; - char *src; - char *dst; - char c; - int i; - int j; - int len; - - dst = buf; - for (i = 0; *prefix && i < 200; i++) { - *(dst++) = *(prefix++); - } - *(dst++) = '$'; - - CParser_PrintUniqueID(dst); - - while (*dst) { - dst++; - i++; - } - - COS_FileGetFSSpecInfo(&cparamblkptr->sourcefile, NULL, NULL, filename); - src = (char *) &filename[1]; - len = filename[0]; - for (j = 0; j < len && i < 255; j++, i++) { - c = *(src++); - if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9')) - c = '_'; - *(dst++) = c; - } - - dst[0] = 0; - return GetHashNameNodeExport(buf); -} - -static HashNameNode *CParser_GetUnnamedNameSpaceName(void) { - Str255 filename; - char buf[256]; - char *src; - char *dst; - char c; - int i; - int len; - - if (!uniquenamespacename) { - strcpy(buf, "@unnamed@"); - dst = buf + strlen(buf); - - COS_FileGetFSSpecInfo(&cparamblkptr->sourcefile, NULL, NULL, filename); - src = (char *) &filename[1]; - len = filename[0]; - for (i = 0; i < len && dst < &buf[254]; i++) { - c = *(src++); - if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9')) - c = '_'; - *(dst++) = c; - } - - dst[0] = '@'; - dst[1] = 0; - uniquenamespacename = GetHashNameNodeExport(buf); - } - - return uniquenamespacename; -} - -Boolean IsTempName(HashNameNode *name) { - return !name || (name->name[0] == '@') || (name->name[0] == '$'); -} - -static void CParser_SetCFMFlags(Object *object, DeclInfo *declinfo) { - if (declinfo && declinfo->exportflags) - object->flags |= declinfo->exportflags; - - if (object->datatype == DDATA) { - if (copts.cfm_export) - object->flags = object->flags | OBJECT_EXPORT; - if (copts.cfm_internal) - object->flags = object->flags | OBJECT_INTERNAL; - } else if (copts.cfm_internal) { - object->flags = object->flags | OBJECT_INTERNAL; - } else { - if (copts.cfm_import) - object->flags = object->flags | OBJECT_IMPORT; - if (copts.cfm_export) - object->flags = object->flags | OBJECT_EXPORT; - if (copts.cfm_lib_export) - object->flags = object->flags | OBJECT_IMPORT | OBJECT_EXPORT; - } -} - -void CParser_UpdateObject(Object *object, DeclInfo *declinfo) { - if (declinfo && declinfo->section) - object->section = declinfo->section; - - CParser_SetCFMFlags(object, declinfo); - CodeGen_UpdateObject(object); -} - -Object *CParser_NewObject(DeclInfo *declinfo) { - Object *object = galloc(sizeof(Object)); - memclrw(object, sizeof(Object)); - CParser_SetCFMFlags(object, declinfo); - object->otype = OT_OBJECT; - object->access = ACCESSPUBLIC; - object->section = SECT_DEFAULT; - return object; -} - -Object *CParser_NewLocalDataObject(DeclInfo *declinfo, Boolean add_to_locals) { - Object *object = lalloc(sizeof(Object)); - memclrw(object, sizeof(Object)); - object->otype = OT_OBJECT; - object->access = ACCESSPUBLIC; - object->datatype = DLOCAL; - - if (declinfo) { - object->type = declinfo->thetype; - object->name = declinfo->name; - object->qual = declinfo->qual; - object->sclass = declinfo->storageclass; - } - - if (add_to_locals) { - ObjectList *list = lalloc(sizeof(ObjectList)); - list->object = object; - list->next = locals; - locals = list; - } - - return object; -} - -Object *CParser_NewGlobalDataObject(DeclInfo *declinfo) { - Object *object = galloc(sizeof(Object)); - memclrw(object, sizeof(Object)); - object->otype = OT_OBJECT; - object->access = ACCESSPUBLIC; - object->section = SECT_DEFAULT; - object->datatype = DDATA; - object->nspace = cscope_current; - - if (declinfo) { - object->type = declinfo->thetype; - object->name = declinfo->name; - object->qual = declinfo->qual; - object->sclass = declinfo->storageclass; - if (copts.cplusplus && !declinfo->is_extern_c) - object->qual |= Q_MANGLE_NAME; - } - - CParser_UpdateObject(object, declinfo); - return object; -} - -Object *CParser_NewCompilerDefDataObject(void) { - Object *object = galloc(sizeof(Object)); - memclrw(object, sizeof(Object)); - object->otype = OT_OBJECT; - object->access = ACCESSPUBLIC; - object->section = SECT_DEFAULT; - object->datatype = DDATA; - object->nspace = cscope_root; - - return object; -} - -Object *CParser_NewFunctionObject(DeclInfo *declinfo) { - Object *object = galloc(sizeof(Object)); - memclrw(object, sizeof(Object)); - object->otype = OT_OBJECT; - object->access = ACCESSPUBLIC; - object->section = SECT_DEFAULT; - object->datatype = DFUNC; - object->nspace = cscope_current; - - if (declinfo) { - object->type = declinfo->thetype; - object->name = declinfo->name; - object->qual = declinfo->qual; - object->sclass = declinfo->storageclass; - if (copts.cplusplus && !declinfo->is_extern_c) - object->qual |= Q_MANGLE_NAME; - } - - CParser_UpdateObject(object, declinfo); - return object; -} - -Object *CParser_NewCompilerDefFunctionObject(void) { - Object *object = galloc(sizeof(Object)); - memclrw(object, sizeof(Object)); - object->otype = OT_OBJECT; - object->access = ACCESSPUBLIC; - object->section = SECT_DEFAULT; - object->datatype = DFUNC; - object->nspace = cscope_root; - return object; -} - -Object *CParser_NewAliasObject(Object *object, SInt32 offset) { - Object *alias = galloc(sizeof(Object)); - *alias = *object; - alias->datatype = DALIAS; - alias->u.alias.object = object; - alias->u.alias.member = NULL; - alias->u.alias.offset = offset; - CScope_AddObject(cscope_current, alias->name, OBJ_BASE(alias)); - return alias; -} - -FuncArg *CParser_NewFuncArg(void) { - FuncArg *arg = galloc(sizeof(FuncArg)); - memclrw(arg, sizeof(FuncArg)); - return arg; -} - -Type *atomtype(void) { - switch (tksize) { - default: - CError_FATAL(1145); - case ATOM_VOID: return &stvoid; - case ATOM_CHAR: return TYPE(&stchar); - case ATOM_WCHAR: return TYPE(&stwchar); - case ATOM_UCHAR: return TYPE(&stunsignedchar); - case ATOM_SHORT: return TYPE(&stsignedshort); - case ATOM_USHORT: return TYPE(&stunsignedshort); - case ATOM_INT: return TYPE(&stsignedint); - case ATOM_UINT: return TYPE(&stunsignedint); - case ATOM_LONG: return TYPE(&stsignedlong); - case ATOM_ULONG: return TYPE(&stunsignedlong); - case ATOM_LONGLONG: return TYPE(&stsignedlonglong); - case ATOM_ULONGLONG: return TYPE(&stunsignedlonglong); - case ATOM_FLOAT: return TYPE(&stfloat); - case ATOM_SHORTDOUBLE: return TYPE(&stshortdouble); - case ATOM_DOUBLE: return TYPE(&stdouble); - case ATOM_LONGDOUBLE: return TYPE(&stlongdouble); - } -} - -Object *CParser_FindDeallocationObject(Type *type, FuncArg *args, Boolean flag1, Boolean flag2, Boolean *outflag) { - NameSpaceObjectList *list; - NameSpaceObjectList *scan; - NameSpaceObjectList mylist; - NameResult pr; - Boolean first_time; - Boolean retry_flag; - Object *obj; - Type *sizet; - - list = NULL; - *outflag = 0; - if (IS_TYPE_CLASS(type) && !flag2) { - HashNameNode *name; - name = (flag1 && copts.array_new_delete) ? dela_fobj->name : delp_fobj->name; - if (CScope_FindClassMemberObject(TYPE_CLASS(type), &pr, name)) { - if (pr.obj_10) { - mylist.next = NULL; - mylist.object = pr.obj_10; - list = &mylist; - } else { - CError_ASSERT(1202, pr.nsol_14); - list = pr.nsol_14; - } - } else if (TYPE_CLASS(type)->flags & CLASS_HANDLEOBJECT) { - CError_ASSERT(1210, !args && !flag1); - return delh_func; - } - } - - first_time = 1; - retry_flag = flag1; - while (1) { - if (!args) { - for (scan = list; scan; scan = scan->next) { - obj = OBJECT(scan->object); - if ( - obj->otype == OT_OBJECT && - IS_TYPE_FUNC(obj->type) && - TYPE_FUNC(obj->type)->args && - !TYPE_FUNC(obj->type)->args->next && - is_typesame(TYPE_FUNC(obj->type)->args->type, TYPE(&void_ptr)) - ) - return obj; - } - - CError_ASSERT(1231, first_time); - - sizet = CABI_GetSizeTType(); - for (scan = list; scan; scan = scan->next) { - obj = OBJECT(scan->object); - if ( - obj->otype == OT_OBJECT && - IS_TYPE_FUNC(obj->type) && - TYPE_FUNC(obj->type)->args && - TYPE_FUNC(obj->type)->args->next && - !TYPE_FUNC(obj->type)->args->next->next && - is_typesame(TYPE_FUNC(obj->type)->args->type, TYPE(&void_ptr)) && - TYPE_FUNC(obj->type)->args->next->type == sizet - ) { - *outflag = 1; - return obj; - } - } - } else { - for (scan = list; scan; scan = scan->next) { - obj = OBJECT(scan->object); - if ( - obj->otype == OT_OBJECT && - IS_TYPE_FUNC(obj->type) && - TYPE_FUNC(obj->type)->args && - TYPE_FUNC(obj->type)->args->next && - is_arglistsame(TYPE_FUNC(obj->type)->args->next, args) - ) { - *outflag = 1; - return obj; - } - } - - if (!first_time) - return NULL; - } - - if (list) - CError_Warning(CErrorStr375, type, 0); - - list = (retry_flag && copts.array_new_delete) ? &dela_fobj->first : &delp_fobj->first; - first_time = 0; - } -} - -static Boolean oldstylecompatible(FuncArg *arg) { - if (copts.ignore_oldstyle) - return 1; - - while (arg) { - if (arg == &elipsis) - return 0; - switch (arg->type->type) { - case TYPEINT: - if (TYPE_INTEGRAL(arg->type)->integral < IT_INT) - return 0; - break; - case TYPEFLOAT: - if (TYPE_INTEGRAL(arg->type)->integral < IT_DOUBLE) - return 0; - break; - } - arg = arg->next; - } - - return 1; -} - -static Boolean is_arglistequal(FuncArg *a, FuncArg *b) { - if (a == &oldstyle) { - if (b == &oldstyle) - return 1; - else - return oldstylecompatible(b); - } else { - if (b == &oldstyle) - return oldstylecompatible(a); - } - - while (1) { - if (a == &elipsis || b == &elipsis) - return 1; - - if (!a) - return !b; - if (!b) - return 0; - - if (copts.mpwc_relax && !copts.cplusplus) { - if (!is_typeequal(a->type, b->type)) - return 0; - } else { - if (!is_typesame(a->type, b->type)) - return 0; - } - - if (a->type->type == TYPEPOINTER && a->qual != b->qual) - return 0; - - a = a->next; - b = b->next; - } -} - -short is_memberpointerequal(Type *a, Type *b) { - FuncArg *arg_a; - FuncArg *arg_b; - - if (a->type != b->type) - return 0; - if (!IS_TYPE_FUNC(a)) - return is_typeequal(a, b); - - if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) - return 0; - - if ((TYPE_FUNC(a)->flags & FUNC_CALL_CONV_MASK) != (TYPE_FUNC(b)->flags & FUNC_CALL_CONV_MASK)) - return 0; - - CError_ASSERT(1345, arg_a = TYPE_FUNC(a)->args); - CError_ASSERT(1346, arg_b = TYPE_FUNC(b)->args); - - if (TYPE_FUNC(a)->flags & FUNC_FLAGS_80) - CError_ASSERT(1351, arg_a = arg_a->next); - - if (TYPE_FUNC(b)->flags & FUNC_FLAGS_80) - CError_ASSERT(1355, arg_b = arg_b->next); - - if (arg_a->qual != arg_b->qual) - return 0; - - return is_arglistsame(arg_a->next, arg_b->next); -} - -short is_typeequal(Type *a, Type *b) { -restart: - if (a->type != b->type) - return 0; - switch (a->type) { - case TYPEVOID: - return 1; - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - case TYPECLASS: - return a == b; - case TYPESTRUCT: - return a == b; - case TYPEPOINTER: - if (TYPE_POINTER(a)->target == &stvoid || TYPE_POINTER(b)->target == &stvoid) - return 1; - a = TYPE_POINTER(a)->target; - b = TYPE_POINTER(b)->target; - if (copts.mpwc_relax && !copts.cplusplus) - return 1; - goto restart; - case TYPEMEMBERPOINTER: - if (TYPE_MEMBER_POINTER(a)->ty2 != TYPE_MEMBER_POINTER(b)->ty2) - return 0; - return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1); - case TYPEARRAY: - if (a->size && b->size && a->size != b->size) - return 0; - a = TYPE_POINTER(a)->target; - b = TYPE_POINTER(b)->target; - goto restart; - case TYPEFUNC: - if (copts.cplusplus || !copts.cpp_extensions) { - if (copts.mpwc_relax && !copts.cplusplus) { - if (!is_typeequal(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) - return 0; - } else { - if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) - return 0; - } - if ((TYPE_FUNC(a)->flags & FUNC_CALL_CONV_MASK) != (TYPE_FUNC(b)->flags & FUNC_CALL_CONV_MASK)) - return 0; - } - return is_arglistequal(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args); - case TYPETEMPLATE: - return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b)); - default: - CError_FATAL(1441); - return 0; - } -} - -short iscpp_typeequal(Type *a, Type *b) { - restart: - if (a->type != b->type) - return 0; - switch (a->type) { - case TYPEVOID: - return 1; - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - case TYPECLASS: - return a == b; - case TYPESTRUCT: - return a == b; - case TYPEPOINTER: - if (TYPE_POINTER(b)->target == &stvoid) { - if (TYPE_POINTER(a)->target == &stvoid) - return 1; - else - return -1; - } - if (TYPE_POINTER(a)->target == &stvoid) { - illegalimplicitconversion = 1; - return 0; - } - a = TYPE_POINTER(a)->target; - b = TYPE_POINTER(b)->target; - goto restart; - case TYPEMEMBERPOINTER: - if (TYPE_MEMBER_POINTER(a)->ty2 != TYPE_MEMBER_POINTER(b)->ty2) - return 0; - return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1); - case TYPEARRAY: - if (a->size && b->size && a->size != b->size) - return 0; - a = TYPE_POINTER(a)->target; - b = TYPE_POINTER(b)->target; - goto restart; - case TYPEFUNC: - if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) - return 0; - if ((TYPE_FUNC(a)->flags & FUNC_CALL_CONV_MASK) != (TYPE_FUNC(b)->flags & FUNC_CALL_CONV_MASK)) - return 0; - return is_arglistequal(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args); - case TYPETEMPLATE: - return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b)); - default: - CError_FATAL(1500); - return 0; - } -} - -short CParser_CompareArgLists(FuncArg *a, FuncArg *b) { - Boolean r30; - - r30 = 0; - if (a == &oldstyle) { - if (b == &oldstyle) - return 1; - else - return 2; - } - if (b == &oldstyle) - return 2; - - while (1) { - if (a == &elipsis) { - if (b != &elipsis) - return 0; - break; - } - if (b == &elipsis) - return 0; - - if (a == NULL) { - if (b) - return 0; - break; - } - if (b == NULL) - return 0; - - if (a->type->type == TYPEPOINTER) { - if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(a->type))) { - if (IS_TYPE_REFERENCE(b->type)) { - if (!is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target)) - return 0; - if ((a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE))) - return 0; - } else { - if (!copts.old_argmatch) - return 0; - if (!is_typesame(TYPE_POINTER(a->type)->target, b->type)) - return 0; - if (b->type->type == TYPEPOINTER && (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE))) - return 0; - r30 = 1; - } - } else { - if (b->type->type == TYPEPOINTER) { - if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type))) { - if (!copts.old_argmatch) - return 0; - if (!is_typesame(a->type, TYPE_POINTER(b->type)->target)) - return 0; - if (a->type->type == TYPEPOINTER && (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE))) - return 0; - r30 = 1; - } else { - if (!is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target)) - return 0; - if ((a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE))) - return 0; - } - } else { - return 0; - } - } - } else { - if (b->type->type == TYPEPOINTER) { - if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type))) { - if (!copts.old_argmatch) - return 0; - if (!is_typesame(a->type, TYPE_POINTER(b->type)->target)) - return 0; - r30 = 1; - } else { - return 0; - } - } else { - if (!is_typesame(a->type, b->type)) - return 0; - } - } - - a = a->next; - b = b->next; - } - - if (r30) - return 2; - return 1; -} - -Boolean is_arglistsame(FuncArg *a, FuncArg *b) { - if (a == &oldstyle) { - if (b == &oldstyle) - return 1; - else - return oldstylecompatible(b); - } else { - if (b == &oldstyle) - return oldstylecompatible(a); - } - - while (1) { - if (!a || !b || a == &elipsis || b == &elipsis) - return a == b; - - if (a->type->type == TYPEPOINTER) { - if (b->type->type != TYPEPOINTER || - (a->qual & (Q_CONST | Q_VOLATILE)) != (b->qual & (Q_CONST | Q_VOLATILE)) || - !is_typesame(TYPE_POINTER(a->type)->target, TYPE_POINTER(b->type)->target) || - IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(a->type)) != IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(b->type))) - return 0; - } else { - if (!is_typesame(a->type, b->type)) - return 0; - } - - a = a->next; - b = b->next; - } -} - -short is_typesame(Type *a, Type *b) { -restart: - if (a->type != b->type) { - if (IS_TYPE_TEMPLATE(a) && IS_TYPE_CLASS(b) && (TYPE_CLASS(b)->flags & CLASS_IS_TEMPL)) - return CTemplTool_IsSameTemplateType(b, a); - if (IS_TYPE_TEMPLATE(b) && IS_TYPE_CLASS(a) && (TYPE_CLASS(a)->flags & CLASS_IS_TEMPL)) - return CTemplTool_IsSameTemplateType(a, b); - return 0; - } - - switch (a->type) { - case TYPEVOID: - return 1; - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - case TYPECLASS: - return a == b; - case TYPETEMPLATE: - return CTemplTool_TemplDepTypeCompare(TYPE_TEMPLATE(a), TYPE_TEMPLATE(b)); - case TYPESTRUCT: - return a == b; - case TYPEPOINTER: - if ((TYPE_POINTER(a)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE)) != (TYPE_POINTER(b)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE))) - return 0; - a = TYPE_POINTER(a)->target; - b = TYPE_POINTER(b)->target; - goto restart; - case TYPEMEMBERPOINTER: - if (!is_typesame(TYPE_MEMBER_POINTER(a)->ty2, TYPE_MEMBER_POINTER(b)->ty2)) - return 0; - if ((TYPE_MEMBER_POINTER(a)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE)) != (TYPE_MEMBER_POINTER(b)->qual & (Q_RESTRICT | Q_REFERENCE | Q_CONST | Q_VOLATILE))) - return 0; - return is_memberpointerequal(TYPE_MEMBER_POINTER(a)->ty1, TYPE_MEMBER_POINTER(b)->ty1); - case TYPEARRAY: - if (a->size != b->size) - return 0; - a = TYPE_POINTER(a)->target; - b = TYPE_POINTER(b)->target; - goto restart; - case TYPEFUNC: - if (!is_typesame(TYPE_FUNC(a)->functype, TYPE_FUNC(b)->functype)) - return 0; - if (TYPE_FUNC(a)->qual != TYPE_FUNC(b)->qual) - return 0; - if ((TYPE_FUNC(a)->flags & FUNC_CALL_CONV_MASK) != (TYPE_FUNC(b)->flags & FUNC_CALL_CONV_MASK)) - return 0; - return is_arglistsame(TYPE_FUNC(a)->args, TYPE_FUNC(b)->args); - default: - CError_FATAL(1709); - return 0; - } -} - -Type *CParser_GetBoolType(void) { - if (copts.cplusplus && copts.booltruefalse) - return TYPE(&stbool); - else - return TYPE(&stsignedint); -} - -Type *CParser_GetWCharType(void) { - if (copts.cplusplus && copts.wchar_type) - return TYPE(&stwchar); - else - return TYPE(&stsignedint); -} - -short CParser_GetOperator(ENodeType t) { - switch (t) { - default: - CError_FATAL(1748); - case EMONMIN: return '-'; - case EBINNOT: return '~'; - case ELOGNOT: return '!'; - case EADD: return '+'; - case ESUB: return '-'; - case EMUL: return '*'; - case EDIV: return '/'; - case EMODULO: return '%'; - case EAND: return '&'; - case EXOR: return '^'; - case EOR: return '|'; - case ESHL: return TK_SHL; - case ESHR: return TK_SHR; - case ELESS: return '<'; - case EGREATER: return '>'; - case ELESSEQU: return TK_LESS_EQUAL; - case EGREATEREQU: return TK_GREATER_EQUAL; - case EEQU: return TK_LOGICAL_EQ; - case ENOTEQU: return TK_LOGICAL_NE; - } -} - -Boolean CParser_IsMoreCVQualified(UInt32 a, UInt32 b) { - if ((a & Q_CONST) && !(b & Q_CONST)) { - return ((a & Q_VOLATILE) || !(b & Q_VOLATILE)); - } else if ((a & Q_VOLATILE) && !(b & Q_VOLATILE)) { - return ((a & Q_CONST) || !(b & Q_CONST)); - } - return 0; -} - -Boolean CParser_IsSameOrMoreCVQualified(UInt32 a, UInt32 b) { - if ((a & (Q_CONST | Q_VOLATILE)) == (b & (Q_CONST | Q_VOLATILE))) - return 1; - - if ((a & Q_CONST) && !(b & Q_CONST)) { - return ((a & Q_VOLATILE) || !(b & Q_VOLATILE)); - } else if ((a & Q_VOLATILE) && !(b & Q_VOLATILE)) { - return ((a & Q_CONST) || !(b & Q_CONST)); - } - return 0; -} - -Boolean is_unsigned(Type *type) { - if (IS_TYPE_ENUM(type)) - type = TYPE_ENUM(type)->enumtype; - - if ( - (type == TYPE(&stunsignedchar)) || - (type == TYPE(&stunsignedshort)) || - (type == TYPE(&stunsignedint)) || - (type == TYPE(&stunsignedlong)) || - (type == TYPE(&stunsignedlonglong)) || - (type == TYPE(&stbool)) || - (copts.unsigned_char && (type == TYPE(&stchar))) || - (type->type == TYPEPOINTER)) - return 1; - - return 0; -} - -StructMember *ismember(TypeStruct *tstruct, HashNameNode *name) { - StructMember *member; - - for (member = tstruct->members; member; member = member->next) { - if (member->name == name) - return member; - } - - return NULL; -} - -void appendmember(TypeStruct *tstruct, StructMember *member) { - StructMember *last; - - if (!tstruct->members) { - tstruct->members = member; - return; - } - - for (last = tstruct->members; last->next; last = last->next) {} - last->next = member; -} - -static void CParser_InsertTryBlock(ParserTryBlock *block) { - block->cscope_current = cscope_current; - block->cscope_currentclass = cscope_currentclass; - block->cscope_currentfunc = cscope_currentfunc; - block->ctempl_curinstance = ctempl_curinstance; - block->cerror_locktoken = cerror_locktoken; - block->cscope_is_member_func = cscope_is_member_func; - block->next = trychain; - trychain = block; -} - -static void CParser_RemoveTryBlock(ParserTryBlock *block) { - cscope_current = block->cscope_current; - cscope_currentclass = block->cscope_currentclass; - cscope_currentfunc = block->cscope_currentfunc; - ctempl_curinstance = block->ctempl_curinstance; - cerror_locktoken = block->cerror_locktoken; - cscope_is_member_func = block->cscope_is_member_func; - trychain = block->next; -} - -static Boolean TryIsDeclaration(Boolean flag1, Boolean flag2, Boolean flag3, short token) { - Boolean result; - DeclInfo declinfo; - struct ParserTryBlock tryblock; - - switch (tk) { - case TK_IDENTIFIER: - case TK_COLON_COLON: - break; - case TK_VOID: - case TK_CHAR: - case TK_SHORT: - case TK_INT: - case TK_LONG: - case TK_FLOAT: - case TK_DOUBLE: - case TK_SIGNED: - case TK_UNSIGNED: - case TK_UNK_113: - case TK_UNK_114: - case TK_UNK_115: - case TK_UNK_116: - case TK_UNK_117: - case TK_UNK_118: - case TK_UNK_119: - case TK_UNK_11A: - case TK_BOOL: - case TK_WCHAR_T: - if (lookahead() != '(') - return 1; - break; - default: - return 1; - } - - result = 0; - CParser_InsertTryBlock(&tryblock); - if (setjmp(tryblock.jmpbuf) == 0) { - memclrw(&declinfo, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&declinfo, 0); - if (!(IS_TYPE_TEMPLATE(declinfo.thetype) && TYPE_TEMPLATE(declinfo.thetype)->dtype == TEMPLDEP_QUALNAME && !declinfo.x53 && !declinfo.x49)) { - if (flag1) { - declinfo.x46 = flag3; - scandeclarator(&declinfo); - if (!(flag2 && declinfo.name)) { - if (!token) { - if (tk == ';' || tk == ',' || tk == '=' || tk == '(' || tk == ')' || tk == '>') - result = 1; - } else { - result = (tk == token); - } - } - } else { - result = 1; - } - } - } - - CParser_RemoveTryBlock(&tryblock); - return result; -} - -Boolean isdeclaration(UInt8 flag1, UInt8 flag2, UInt8 flag3, short token) { - SInt32 state; - - if (!(tk >= TK_AUTO && tk <= TK_BYREF) && tk != TK_COLON_COLON && !(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) { - if (!(tk == TK_IDENTIFIER && copts.altivec_model && !strcmp(tkidentifier->name, "vector"))) - return 0; - } else { - if (!copts.cplusplus) - return 1; - } - - CPrep_TokenStreamGetState(&state); - if (TryIsDeclaration(flag1, flag2, flag3, token)) { - CPrep_TokenStreamSetCurState(&state); - return 1; - } else { - CPrep_TokenStreamSetCurState(&state); - return 0; - } -} - -Boolean islookaheaddeclaration(void) { - SInt32 state; - - CPrep_TokenStreamGetState(&state); - tk = lex(); - if (!(tk >= TK_AUTO && tk <= TK_BYREF) && tk != TK_COLON_COLON && !(tk == TK_IDENTIFIER && CScope_PossibleTypeName(tkidentifier))) { - if (!(tk == TK_IDENTIFIER && copts.altivec_model && !strcmp(tkidentifier->name, "vector"))) { - CPrep_TokenStreamSetCurState(&state); - return 0; - } - } else { - if (!copts.cplusplus) { - CPrep_TokenStreamSetCurState(&state); - return 1; - } - } - - if (TryIsDeclaration(1, 1, 0, ')')) { - CPrep_TokenStreamSetCurState(&state); - return 1; - } else { - CPrep_TokenStreamSetCurState(&state); - return 0; - } -} - -Type *CParser_ParseTypeID(UInt32 *qual, Boolean *flag) { - SInt32 state; - DeclInfo di; - struct ParserTryBlock tryblock; - - memclrw(&di, sizeof(DeclInfo)); - CPrep_TokenStreamGetState(&state); - CParser_InsertTryBlock(&tryblock); - - if (setjmp(tryblock.jmpbuf) == 0) { - if (copts.cplusplus) - di.x55 = 1; - - if (flag) { - di.x56 = 1; - *flag = 0; - } - - CParser_GetDeclSpecs(&di, 0); - if (di.x57 && IS_TYPE_CLASS(di.thetype) && (TYPE_CLASS(di.thetype)->flags & CLASS_IS_TEMPL)) { - CParser_RemoveTryBlock(&tryblock); - *qual = di.qual; - *flag = 1; - return di.thetype; - } - - if (flag && IS_TYPE_TEMPLATE(di.thetype) && TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_ARGUMENT && - TYPE_TEMPLATE(di.thetype)->u.pid.type == TPT_TEMPLATE) { - CParser_RemoveTryBlock(&tryblock); - *qual = di.qual; - *flag = 1; - return di.thetype; - } - - scandeclarator(&di); - if (!di.name) { - CParser_RemoveTryBlock(&tryblock); - *qual = di.qual; - return di.thetype; - } - } - - CPrep_TokenStreamSetCurState(&state); - CParser_RemoveTryBlock(&tryblock); - return 0; -} - -Boolean CParser_TryFuncDecl(void) { - Boolean result; - SInt32 state; - DeclInfo di; - struct ParserTryBlock tryblock; - - result = 0; - CPrep_TokenStreamGetState(&state); - CParser_InsertTryBlock(&tryblock); - - if (setjmp(tryblock.jmpbuf) == 0) { - memclrw(&di, sizeof(DeclInfo)); - di.thetype = &stvoid; - scandeclarator(&di); - - if (IS_TYPE_FUNC(di.thetype)) - result = 1; - } - - CParser_RemoveTryBlock(&tryblock); - CPrep_TokenStreamSetCurState(&state); - return result; -} - -Boolean CParser_TryParamList(Boolean flag) { - Boolean result; - SInt32 state; - struct ParserTryBlock tryblock; - - result = 0; - CPrep_TokenStreamGetState(&state); - - switch ((tk = lex())) { - case ')': - case TK_ELLIPSIS: - result = 1; - break; - default: - CParser_InsertTryBlock(&tryblock); - if (setjmp(tryblock.jmpbuf) == 0) { - if (CFunc_ParseFakeArgList(flag) || tk == ')') - result = 1; - } - CParser_RemoveTryBlock(&tryblock); - break; - } - - CPrep_TokenStreamSetCurState(&state); - return result; -} - -Type *CParser_RemoveTopMostQualifiers(Type *type, UInt32 *qual) { - switch (type->type) { - case TYPEARRAY: - TYPE_POINTER(type)->target = CParser_RemoveTopMostQualifiers(TYPE_POINTER(type)->target, qual); - return type; - case TYPEPOINTER: - if (TYPE_POINTER(type)->qual & Q_CONST) { - TypePointer *newtype = galloc(sizeof(TypePointer)); - *newtype = *TYPE_POINTER(type); - newtype->qual = 0; - return TYPE(newtype); - } - return type; - case TYPEMEMBERPOINTER: - if (TYPE_MEMBER_POINTER(type)->qual & Q_CONST) { - TypeMemberPointer *newtype = galloc(sizeof(TypeMemberPointer)); - *newtype = *TYPE_MEMBER_POINTER(type); - newtype->qual = 0; - return TYPE(newtype); - } - return type; - default: - *qual = 0; - return type; - } -} - -UInt32 CParser_GetTypeQualifiers(Type *type, UInt32 qual) { - while (IS_TYPE_ARRAY(type)) - type = TYPE_POINTER(type)->target; - - switch (type->type) { - case TYPEPOINTER: - qual = TYPE_POINTER(type)->qual; - break; - case TYPEMEMBERPOINTER: - qual = TYPE_MEMBER_POINTER(type)->qual; - break; - } - - return qual; -} - -UInt32 CParser_GetCVTypeQualifiers(Type *type, UInt32 qual) { - while (IS_TYPE_ARRAY(type)) - type = TYPE_POINTER(type)->target; - - switch (type->type) { - case TYPEPOINTER: - qual = TYPE_POINTER(type)->qual; - break; - case TYPEMEMBERPOINTER: - qual = TYPE_MEMBER_POINTER(type)->qual; - break; - } - - return qual & (Q_CONST | Q_VOLATILE); -} - -Boolean CParser_IsConst(Type *type, UInt32 qual) { - while (IS_TYPE_ARRAY(type)) - type = TYPE_POINTER(type)->target; - - switch (type->type) { - case TYPEPOINTER: - qual = TYPE_POINTER(type)->qual; - break; - case TYPEMEMBERPOINTER: - qual = TYPE_MEMBER_POINTER(type)->qual; - break; - } - - return (qual & Q_CONST) != 0; -} - -Boolean CParser_IsVolatile(Type *type, UInt32 qual) { - while (IS_TYPE_ARRAY(type)) - type = TYPE_POINTER(type)->target; - - switch (type->type) { - case TYPEPOINTER: - qual = TYPE_POINTER(type)->qual; - break; - case TYPEMEMBERPOINTER: - qual = TYPE_MEMBER_POINTER(type)->qual; - break; - } - - return (qual & Q_VOLATILE) != 0; -} - -Boolean is_const_object(Object *obj) { - return CParser_IsConst(obj->type, obj->qual); -} - -Boolean is_volatile_object(Object *obj) { - return CParser_IsVolatile(obj->type, obj->qual); -} - -Boolean CParserIsConstExpr(ENode *expr) { - return CParser_IsConst(expr->rtype, expr->flags & ENODE_FLAG_QUALS); -} - -Boolean CParserIsVolatileExpr(ENode *expr) { - return CParser_IsVolatile(expr->rtype, expr->flags & ENODE_FLAG_QUALS); -} - -Boolean CParser_HasInternalLinkage(const Object *obj) { - NameSpace *nspace; - - for (nspace = obj->nspace; nspace; nspace = nspace->parent) { - if (nspace->is_unnamed) - return 1; - } - - if (obj->datatype == DLOCAL) - return 1; - if (obj->qual & (Q_20000 | Q_WEAK)) - return 0; - if (obj->sclass == TK_STATIC) - return 1; - - // this feels *wrong* but it's the only way to match this function that I can see - if (obj->qual & Q_INLINE) - ((Object *) obj)->qual |= Q_20000; - return 0; -} - -Boolean CParser_HasInternalLinkage2(const Object *obj) { - if (obj->datatype == DLOCAL) - return 1; - if (obj->qual & (Q_20000 | Q_WEAK)) - return 0; - if (obj->sclass == TK_STATIC) - return 1; - - // this feels *wrong* but it's the only way to match this function that I can see - if (obj->qual & Q_INLINE) - ((Object *) obj)->qual |= Q_20000; - return 0; -} - -Boolean CParser_IsVirtualFunction(Object *obj, TypeClass **tclass, SInt32 *index) { - if (obj->datatype == DVFUNC) { - *tclass = TYPE_METHOD(obj->type)->theclass; - *index = TYPE_METHOD(obj->type)->vtbl_index; - return 1; - } - - return 0; -} - -Boolean is_pascal_object(Object *obj) { - return IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_PASCAL); -} - -Boolean is_cfm_type(Type *type) { - return 0; -} - -Boolean CParser_IsVTableObject(Object *obj) { - return - obj->datatype == DDATA && - obj->nspace && - obj->nspace->theclass && - obj->nspace->theclass->vtable && - obj->nspace->theclass->vtable->object == obj; -} - -static Type *getthetype(short token, short size, short signedness) { - switch (token) { - case 0: - case TK_INT: - if (signedness == 1) { - switch (size) { - case 1: return TYPE(&stunsignedshort); - case 2: return TYPE(&stunsignedlong); - case 3: return TYPE(&stunsignedlonglong); - default: return TYPE(&stunsignedint); - } - } else { - switch (size) { - case 1: return TYPE(&stsignedshort); - case 2: return TYPE(&stsignedlong); - case 3: return TYPE(&stsignedlonglong); - default: return TYPE(&stsignedint); - } - } - case TK_BOOL: - return TYPE(&stbool); - case TK_WCHAR_T: - return TYPE(&stwchar); - case TK_CHAR: - switch (signedness) { - case 1: return TYPE(&stunsignedchar); - default: return TYPE(&stchar); - case -1: return TYPE(&stsignedchar); - } - case TK_DOUBLE: - switch (size) { - case 1: return TYPE(&stshortdouble); - case 2: return TYPE(&stlongdouble); - default: return TYPE(&stdouble); - } - case TK_FLOAT: - return TYPE(&stfloat); - case TK_VOID: - return TYPE(&stvoid); - default: - CError_Error(CErrorStr121); - return TYPE(&stvoid); - } -} - -void TypedefDeclInfo(DeclInfo *declinfo, Type *type, UInt32 qual) { - if (type->type == TYPEPOINTER) { - if (IS_TYPEPOINTER_REFERENCE(TYPE_POINTER(type))) { - declinfo->thetype = type; - declinfo->qual &= ~(Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); - declinfo->qual |= qual; - return; - } - - declinfo->thetype = galloc(sizeof(TypePointer)); - *TYPE_POINTER(declinfo->thetype) = *TYPE_POINTER(type); - TYPE_POINTER(declinfo->thetype)->qual |= declinfo->qual & (Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); - declinfo->qual &= ~(Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); - declinfo->qual |= qual & (Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST); - } else if (type->type == TYPEMEMBERPOINTER) { - declinfo->thetype = galloc(sizeof(TypeMemberPointer)); - *TYPE_MEMBER_POINTER(declinfo->thetype) = *TYPE_MEMBER_POINTER(type); - TYPE_MEMBER_POINTER(declinfo->thetype)->qual |= declinfo->qual & (Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); - declinfo->qual &= ~(Q_RESTRICT | Q_REFERENCE | Q_VOLATILE | Q_CONST); - declinfo->qual |= qual & (Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST); - } else { - declinfo->thetype = type; - declinfo->qual |= qual & (Q_ALIGNED_MASK | Q_REFERENCE | Q_PASCAL | Q_VOLATILE | Q_CONST); - if (IS_TYPE_ARRAY(declinfo->thetype) && !declinfo->thetype->size) { - declinfo->thetype = galloc(sizeof(TypePointer)); - *TYPE_POINTER(declinfo->thetype) = *TYPE_POINTER(type); - } - } - declinfo->x49 = 1; -} - -static void CParser_ParseAttributeFunctionSummary(DeclInfo *declinfo) { - Boolean flag; - - if ((tk = lex()) != '(') { - CError_Error(CErrorStr114); - return; - } - - flag = 1; - tk = lookahead(); - while (tk == TK_IDENTIFIER) { - if (flag && !strcmp(tkidentifier->name, "entry_points_to")) { - PointerAnalysis_ParseEntryPointsToSpecifier(declinfo); - } else if (!strcmp(tkidentifier->name, "exit_points_to")) { - PointerAnalysis_ParseExitPointsToSpecifier(declinfo); - flag = 0; - } else if (!strcmp(tkidentifier->name, "function_modifies")) { - PointerAnalysis_ParseFunctionModifiesSpecifier(declinfo); - flag = 0; - } else { - lex(); - CError_Error(CErrorStr121); - return; - } - - tk = lookahead(); - if (tk == ',') { - lex(); - tk = lookahead(); - } - } - - lex(); - if (tk != ')') - CError_Error(CErrorStr121); -} - -void CParser_ParseAttribute(Type *type, DeclInfo *declinfo) { - CInt64 val64; - SInt32 val; - - do { - if ((tk = lex()) != '(') { - CError_Error(CErrorStr121); - return; - } - if ((tk = lex()) != '(') { - CError_Error(CErrorStr121); - return; - } - if ((tk = lex()) != TK_IDENTIFIER && tk != TK_CONST) { - CError_Error(CErrorStr121); - return; - } - - if (!strcmp(tkidentifier->name, "aligned") || !strcmp(tkidentifier->name, "__aligned__")) { - if ((tk = lex()) != '(') { - CError_Error(CErrorStr121); - return; - } - - tk = lex(); - val64 = CExpr_IntegralConstExpr(); - switch ((val = CInt64_GetULong(&val64))) { - case 1: - case 2: - case 4: - case 8: - case 0x10: - case 0x20: - case 0x40: - case 0x80: - case 0x100: - case 0x200: - case 0x400: - case 0x800: - case 0x1000: - case 0x2000: - break; - default: - CError_Error(CErrorStr124); - return; - } - if (type) { - if (IS_TYPE_STRUCT(type)) { - if (val > TYPE_STRUCT(type)->align) { - TYPE_STRUCT(type)->align = val; - type->size += CABI_StructSizeAlignValue(type, type->size); - } - } else if (IS_TYPE_CLASS(type)) { - if (val > TYPE_CLASS(type)->align) { - TYPE_CLASS(type)->align = val; - type->size += CABI_StructSizeAlignValue(type, type->size); - } - } else { - CError_Error(CErrorStr149); - } - } else if (declinfo) { - declinfo->qual &= ~Q_ALIGNED_MASK; - switch (val) { - case 1: - declinfo->qual |= Q_ALIGNED_1; - break; - case 2: - declinfo->qual |= Q_ALIGNED_2; - break; - case 4: - declinfo->qual |= Q_ALIGNED_4; - break; - case 8: - declinfo->qual |= Q_ALIGNED_8; - break; - case 16: - declinfo->qual |= Q_ALIGNED_16; - break; - case 32: - declinfo->qual |= Q_ALIGNED_32; - break; - case 64: - declinfo->qual |= Q_ALIGNED_64; - break; - case 128: - declinfo->qual |= Q_ALIGNED_128; - break; - case 256: - declinfo->qual |= Q_ALIGNED_256; - break; - case 512: - declinfo->qual |= Q_ALIGNED_512; - break; - case 1024: - declinfo->qual |= Q_ALIGNED_1024; - break; - case 2048: - declinfo->qual |= Q_ALIGNED_2048; - break; - case 4096: - declinfo->qual |= Q_ALIGNED_4096; - break; - case 8192: - declinfo->qual |= Q_ALIGNED_8192; - break; - default: - CError_FATAL(2779); - break; - } - } else { - CError_Error(CErrorStr359); - } - - if (tk != ')') { - CError_Error(CErrorStr121); - return; - } - } else if (!strcmp(tkidentifier->name, "nothrow") || !strcmp(tkidentifier->name, "__nothrow__")) { - if (declinfo && declinfo->thetype && IS_TYPE_FUNC(declinfo->thetype)) - TYPE_FUNC(declinfo->thetype)->flags |= FUNC_NOTHROW; - else - CError_Error(CErrorStr359); - } else if (!strcmp("function_summary", tkidentifier->name)) { - CParser_ParseAttributeFunctionSummary(declinfo); - } else if (!strcmp(tkidentifier->name, "packed") || !strcmp(tkidentifier->name, "__packed__")) { - CError_Error(CErrorStr359); - } else if (!strcmp(tkidentifier->name, "unused") || !strcmp(tkidentifier->name, "__unused__")) { - } else if (!strcmp(tkidentifier->name, "noreturn") || !strcmp(tkidentifier->name, "__noreturn__")) { - } else if (tk == TK_CONST || !strcmp(tkidentifier->name, "__const__")) { - } else if (!strcmp(tkidentifier->name, "format") || !strcmp(tkidentifier->name, "__format__")) { - CError_Warning(CErrorStr359); - if ((tk = lex()) != '(') { - CError_Warning(CErrorStr114); - return; - } - tk = lex(); - if ((tk = lex()) != ',') { - CError_Warning(CErrorStr116); - return; - } - tk = lex(); - if ((tk = lex()) != ',') { - CError_Warning(CErrorStr116); - return; - } - tk = lex(); - if ((tk = lex()) != ')') { - CError_Warning(CErrorStr115); - return; - } - } else if (!strcmp(tkidentifier->name, "mode") || !strcmp(tkidentifier->name, "__mode__")) { - CError_Warning(CErrorStr359); - if ((tk = lex()) != '(') { - CError_Warning(CErrorStr114); - return; - } - tk = lex(); - if ((tk = lex()) != ')') { - CError_Warning(CErrorStr115); - return; - } - } else { - CError_Error(CErrorStr359); - } - - if ((tk = lex()) != ')') { - CError_Error(CErrorStr121); - return; - } - if ((tk = lex()) != ')') { - CError_Error(CErrorStr121); - return; - } - tk = lex(); - } while (tk == TK_UU_ATTRIBUTE_UU); -} - -static void CParser_ParseTypeOf(DeclInfo *declinfo) { - DeclInfo subdi; - ENode *expr; - - if ((tk = lex()) == '(' && islookaheaddeclaration()) { - tk = lex(); - - memclrw(&subdi, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&subdi, 0); - scandeclarator(&subdi); - if (subdi.name) - CError_Error(CErrorStr121); - - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - - TypedefDeclInfo(declinfo, subdi.thetype, subdi.qual); - } else { - expr = unary_expression(); - if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EBITFIELD)) - CError_Error(CErrorStr144); - TypedefDeclInfo(declinfo, expr->rtype, expr->flags & ENODE_FLAG_QUALS); - } -} - -void CParser_ParseDeclSpec(DeclInfo *declinfo, Boolean flag) { - if ((tk = lex()) != TK_IDENTIFIER) { - if (tk != TK_EXPORT) - CError_Error(CErrorStr107); - else - declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_EXPORT; - } else if (!strcmp("internal", tkidentifier->name)) { - declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_INTERNAL; - } else if (!strcmp("import", tkidentifier->name) || !strcmp("dllimport", tkidentifier->name)) { - declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_IMPORT; - } else if (!strcmp("export", tkidentifier->name) || !strcmp("dllexport", tkidentifier->name)) { - declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_EXPORT; - } else if (!strcmp("lib_export", tkidentifier->name)) { - declinfo->exportflags = declinfo->exportflags | EXPORT_FLAGS_IMPORT | EXPORT_FLAGS_EXPORT; - } else if (!strcmp("weak", tkidentifier->name)) { - declinfo->qual |= Q_WEAK; - } else { - CodeGen_ParseDeclSpec(tkidentifier, declinfo); - } -} - -static int CParser_GetVectorDeclSpec(Type **type) { - tk = lex(); - switch (tk) { - case TK_CHAR: - tk = lex(); - switch (tk) { - case TK_BOOL: - *type = TYPE(&stvectorboolchar); - tk = lex(); - return 1; - case TK_UNSIGNED: - *type = TYPE(&stvectorunsignedchar); - tk = lex(); - return 1; - case TK_SIGNED: - *type = TYPE(&stvectorsignedchar); - tk = lex(); - return 1; - case TK_IDENTIFIER: - if (tkidentifier == GetHashNameNode("bool")) { - *type = TYPE(&stvectorboolchar); - tk = lex(); - return 1; - } - default: - CError_Error(CErrorStr121); - } - break; - case TK_SIGNED: - tk = lex(); - switch (tk) { - case TK_CHAR: - *type = TYPE(&stvectorsignedchar); - tk = lex(); - return 1; - case TK_SHORT: - *type = TYPE(&stvectorsignedshort); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - case TK_LONG: - *type = TYPE(&stvectorsignedlong); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - case TK_INT: - tk = lex(); - switch (tk) { - case TK_SHORT: - *type = TYPE(&stvectorsignedshort); - tk = lex(); - return 1; - case TK_LONG: - *type = TYPE(&stvectorsignedlong); - tk = lex(); - return 1; - default: - *type = TYPE(&stvectorsignedlong); - return 1; - } - default: - CError_Error(CErrorStr121); - } - break; - case TK_UNSIGNED: - tk = lex(); - switch (tk) { - case TK_CHAR: - *type = TYPE(&stvectorunsignedchar); - tk = lex(); - return 1; - case TK_SHORT: - *type = TYPE(&stvectorunsignedshort); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - case TK_LONG: - *type = TYPE(&stvectorunsignedlong); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - case TK_INT: - tk = lex(); - switch (tk) { - case TK_SHORT: - *type = TYPE(&stvectorunsignedshort); - tk = lex(); - return 1; - case TK_LONG: - *type = TYPE(&stvectorunsignedlong); - tk = lex(); - return 1; - default: - *type = TYPE(&stvectorunsignedlong); - return 1; - } - default: - CError_Error(CErrorStr121); - } - break; - case TK_BOOL: - tk = lex(); - switch (tk) { - case TK_CHAR: - *type = TYPE(&stvectorboolchar); - tk = lex(); - return 1; - case TK_SHORT: - *type = TYPE(&stvectorboolshort); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - case TK_LONG: - *type = TYPE(&stvectorboollong); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - case TK_INT: - tk = lex(); - switch (tk) { - case TK_SHORT: - *type = TYPE(&stvectorboolshort); - tk = lex(); - return 1; - case TK_LONG: - *type = TYPE(&stvectorboollong); - tk = lex(); - return 1; - default: - *type = TYPE(&stvectorboollong); - return 1; - } - default: - CError_Error(CErrorStr121); - } - break; - case TK_SHORT: - tk = lex(); - switch (tk) { - case TK_BOOL: - *type = TYPE(&stvectorboolshort); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - case TK_SIGNED: - *type = TYPE(&stvectorsignedshort); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - case TK_UNSIGNED: - *type = TYPE(&stvectorunsignedshort); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - case TK_INT: - tk = lex(); - switch (tk) { - case TK_BOOL: - *type = TYPE(&stvectorboolshort); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - case TK_SIGNED: - *type = TYPE(&stvectorsignedshort); - tk = lex(); - return 1; - case TK_UNSIGNED: - *type = TYPE(&stvectorunsignedshort); - tk = lex(); - return 1; - case TK_IDENTIFIER: - if (tkidentifier == GetHashNameNode("bool")) { - *type = TYPE(&stvectorboolshort); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - } - default: - CError_Error(CErrorStr121); - } - break; - case TK_IDENTIFIER: - if (tkidentifier == GetHashNameNode("bool")) { - *type = TYPE(&stvectorboolshort); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - } - default: - CError_Error(CErrorStr121); - } - break; - case TK_LONG: - tk = lex(); - switch (tk) { - case TK_BOOL: - *type = TYPE(&stvectorboollong); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - case TK_SIGNED: - *type = TYPE(&stvectorsignedlong); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - case TK_UNSIGNED: - *type = TYPE(&stvectorunsignedlong); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - case TK_INT: - tk = lex(); - switch (tk) { - case TK_BOOL: - *type = TYPE(&stvectorboollong); - tk = lex(); - return 1; - case TK_SIGNED: - *type = TYPE(&stvectorsignedlong); - tk = lex(); - return 1; - case TK_UNSIGNED: - *type = TYPE(&stvectorunsignedlong); - tk = lex(); - return 1; - case TK_IDENTIFIER: - if (tkidentifier == GetHashNameNode("bool")) { - *type = TYPE(&stvectorboollong); - tk = lex(); - return 1; - } - default: - CError_Error(CErrorStr121); - } - break; - case TK_IDENTIFIER: - if (tkidentifier == GetHashNameNode("bool")) { - *type = TYPE(&stvectorboollong); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - } - default: - CError_Error(CErrorStr121); - } - break; - case TK_INT: - tk = lex(); - switch (tk) { - case TK_BOOL: - tk = lex(); - switch (tk) { - case TK_SHORT: - *type = TYPE(&stvectorboolshort); - tk = lex(); - return 1; - case TK_LONG: - *type = TYPE(&stvectorboollong); - tk = lex(); - return 1; - default: - *type = TYPE(&stvectorboollong); - return 1; - } - case TK_SIGNED: - tk = lex(); - switch (tk) { - case TK_SHORT: - *type = TYPE(&stvectorsignedshort); - tk = lex(); - return 1; - case TK_LONG: - *type = TYPE(&stvectorsignedlong); - tk = lex(); - return 1; - default: - *type = TYPE(&stvectorsignedlong); - return 1; - } - case TK_UNSIGNED: - tk = lex(); - switch (tk) { - case TK_SHORT: - *type = TYPE(&stvectorunsignedshort); - tk = lex(); - return 1; - case TK_LONG: - *type = TYPE(&stvectorunsignedlong); - tk = lex(); - return 1; - default: - *type = TYPE(&stvectorunsignedlong); - return 1; - } - case TK_SHORT: - tk = lex(); - switch (tk) { - case TK_BOOL: - *type = TYPE(&stvectorboolshort); - tk = lex(); - return 1; - case TK_SIGNED: - *type = TYPE(&stvectorsignedshort); - tk = lex(); - return 1; - case TK_UNSIGNED: - *type = TYPE(&stvectorunsignedshort); - tk = lex(); - return 1; - case TK_IDENTIFIER: - if (tkidentifier == GetHashNameNode("bool")) { - *type = TYPE(&stvectorboolshort); - tk = lex(); - return 1; - } - default: - CError_Error(CErrorStr121); - } - break; - case TK_LONG: - tk = lex(); - switch (tk) { - case TK_BOOL: - *type = TYPE(&stvectorboollong); - tk = lex(); - return 1; - case TK_SIGNED: - *type = TYPE(&stvectorsignedlong); - tk = lex(); - return 1; - case TK_UNSIGNED: - *type = TYPE(&stvectorunsignedlong); - tk = lex(); - return 1; - case TK_IDENTIFIER: - if (tkidentifier == GetHashNameNode("bool")) { - *type = TYPE(&stvectorboollong); - tk = lex(); - return 1; - } - } - case TK_IDENTIFIER: - if (tkidentifier == GetHashNameNode("bool")) { - tk = lex(); - switch (tk) { - case TK_LONG: - *type = TYPE(&stvectorboollong); - tk = lex(); - return 1; - case TK_SHORT: - *type = TYPE(&stvectorboolshort); - tk = lex(); - return 1; - default: - *type = TYPE(&stvectorboolshort); - return 1; - } - } - default: - CError_Error(CErrorStr121); - } - break; - case TK_FLOAT: - *type = TYPE(&stvectorfloat); - tk = lex(); - return 1; - case TK_IDENTIFIER: - if (tkidentifier == GetHashNameNode("pixel") || tkidentifier == GetHashNameNode("__pixel")) { - *type = TYPE(&stvectorpixel); - tk = lex(); - return 1; - } - if (tkidentifier == GetHashNameNode("bool")) { - tk = lex(); - switch (tk) { - case TK_CHAR: - *type = TYPE(&stvectorboolchar); - tk = lex(); - return 1; - case TK_SHORT: - *type = TYPE(&stvectorboolshort); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - case TK_LONG: - *type = TYPE(&stvectorboollong); - tk = lex(); - if (tk == TK_INT) - tk = lex(); - return 1; - case TK_INT: - tk = lex(); - switch (tk) { - case TK_SHORT: - *type = TYPE(&stvectorboolshort); - tk = lex(); - return 1; - case TK_LONG: - *type = TYPE(&stvectorboollong); - tk = lex(); - return 1; - default: - *type = TYPE(&stvectorboollong); - return 1; - } - } - } - default: - CError_Error(CErrorStr121); - } - - return 0; -} - -Boolean CParser_CheckTemplateClassUsage(TemplClass *tmclass, Boolean flag) { - NameSpace *nspace; - - if (tmclass->templ__params) { - nspace = cscope_current; - while (1) { - if (!nspace) { - if (flag) - CError_Error(CErrorStr230); - return 0; - } - if (nspace->theclass == TYPE_CLASS(tmclass)) - break; - nspace = nspace->parent; - } - } - - return 1; -} - -static Boolean CParser_IsAltiVecPrefix(void) { - HashNameNode *save = tkidentifier; - - switch (lookahead()) { - case TK_CHAR: - case TK_SHORT: - case TK_INT: - case TK_LONG: - case TK_FLOAT: - case TK_SIGNED: - case TK_UNSIGNED: - case TK_BOOL: - return 1; - case TK_IDENTIFIER: - if (!strcmp(tkidentifier->name, "bool") || !strcmp(tkidentifier->name, "pixel") || !strcmp(tkidentifier->name, "__pixel")) - return 1; - } - - tkidentifier = save; - return 0; -} - -void CParser_GetDeclSpecs(DeclInfo *di, Boolean flag) { - short typesize; - short signedness; - short typetoken; - Boolean r24; - Boolean r23; - SInt32 state; - NameResult pr; - - di->file = CPrep_BrowserCurrentFile(); - CPrep_BrowserFilePosition(&di->file2, &di->sourceoffset); - - r24 = 1; - r23 = copts.cplusplus; - typetoken = 0; - signedness = 0; - typesize = 0; - -restart: - switch (tk) { - case TK_AUTO: - case TK_REGISTER: - case TK_STATIC: - case TK_EXTERN: - case TK_TYPEDEF: - case TK_MUTABLE: - if (di->storageclass) - CError_Error(CErrorStr121); - di->storageclass = tk; - break; - case TK_CONST: - if (di->thetype) { - if (di->thetype->type == TYPEPOINTER) { - if (TYPE_POINTER(di->thetype)->qual & Q_CONST) - CError_QualifierCheck(Q_CONST); - TYPE_POINTER(di->thetype)->qual |= Q_CONST; - break; - } else if (di->thetype->type == TYPEMEMBERPOINTER) { - if (TYPE_MEMBER_POINTER(di->thetype)->qual & Q_CONST) - CError_QualifierCheck(Q_CONST); - TYPE_MEMBER_POINTER(di->thetype)->qual |= Q_CONST; - break; - } - } - if (di->qual & Q_CONST) - CError_QualifierCheck(Q_CONST); - di->qual |= Q_CONST; - break; - case TK_VOLATILE: - if (di->thetype) { - if (di->thetype->type == TYPEPOINTER) { - if (TYPE_POINTER(di->thetype)->qual & Q_VOLATILE) - CError_QualifierCheck(Q_VOLATILE); - TYPE_POINTER(di->thetype)->qual |= Q_VOLATILE; - break; - } else if (di->thetype->type == TYPEMEMBERPOINTER) { - if (TYPE_MEMBER_POINTER(di->thetype)->qual & Q_VOLATILE) - CError_QualifierCheck(Q_VOLATILE); - TYPE_MEMBER_POINTER(di->thetype)->qual |= Q_VOLATILE; - break; - } - } - if (di->qual & Q_VOLATILE) - CError_QualifierCheck(Q_VOLATILE); - di->qual |= Q_VOLATILE; - break; - case TK_PASCAL: - if (di->qual & Q_PASCAL) - CError_QualifierCheck(Q_PASCAL); - di->qual |= Q_PASCAL; - break; - case TK_EXPLICIT: - CError_QualifierCheck(di->qual & Q_EXPLICIT); - di->qual |= Q_EXPLICIT; - break; - case TK_VIRTUAL: - CError_QualifierCheck(di->qual & Q_VIRTUAL); - di->qual |= Q_VIRTUAL; - break; - case TK_IN: - CError_QualifierCheck(di->qual & Q_IN); - di->qual |= Q_IN; - break; - case TK_OUT: - CError_QualifierCheck(di->qual & Q_OUT); - di->qual |= Q_OUT; - break; - case TK_INOUT: - CError_QualifierCheck(di->qual & Q_INOUT); - di->qual |= Q_INOUT; - break; - case TK_BYCOPY: - CError_QualifierCheck(di->qual & Q_BYCOPY); - di->qual |= Q_BYCOPY; - break; - case TK_BYREF: - CError_QualifierCheck(di->qual & Q_BYREF); - di->qual |= Q_BYREF; - break; - case TK_ONEWAY: - CError_QualifierCheck(di->qual & Q_ONEWAY); - di->qual |= Q_ONEWAY; - break; - case TK_UU_DECLSPEC: - if ((tk = lex()) != '(') - CError_Error(CErrorStr114); - CParser_ParseDeclSpec(di, 0); - if ((tk = lex()) != ')') - CError_Error(CErrorStr115); - break; - case TK_ASM: - if (di->qual & Q_ASM) - CError_QualifierCheck(Q_ASM); - di->qual |= Q_ASM; - break; - case TK_INLINE: - if (di->qual & Q_INLINE) - CError_QualifierCheck(Q_INLINE); - di->qual |= Q_INLINE; - break; - case TK_SHORT: - if (typesize || (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE)) - CError_Error(CErrorStr121); - typesize = 1; - break; - case TK_LONG: - if (copts.longlong) { - if (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE) - CError_Error(CErrorStr121); - if (typesize) { - if (typesize != 2 || typetoken == TK_DOUBLE) - CError_Error(CErrorStr121); - typesize = 3; - } else { - typesize = 2; - } - } else { - if (typesize || (typetoken && typetoken != TK_INT && typetoken != TK_DOUBLE)) - CError_Error(CErrorStr121); - typesize = 2; - } - break; - case TK_SIGNED: - if (signedness || (typetoken && typetoken != TK_INT && typetoken != TK_CHAR)) - CError_Error(CErrorStr121); - signedness = -1; - break; - case TK_UNSIGNED: - if (signedness || (typetoken && typetoken != TK_INT && typetoken != TK_CHAR)) - CError_Error(CErrorStr121); - signedness = 1; - break; - case TK_VOID: - if (typetoken || typesize || signedness) - CError_Error(CErrorStr121); - typetoken = TK_VOID; - break; - case TK_FLOAT: - if (typetoken || typesize || signedness) - CError_Error(CErrorStr121); - typetoken = TK_FLOAT; - break; - case TK_BOOL: - if (typetoken || typesize) - CError_Error(CErrorStr121); - typetoken = TK_BOOL; - break; - case TK_CHAR: - if (typetoken || typesize) - CError_Error(CErrorStr121); - typetoken = TK_CHAR; - break; - case TK_WCHAR_T: - if (typetoken || typesize || signedness) - CError_Error(CErrorStr121); - typetoken = TK_WCHAR_T; - break; - case TK_INT: - if (typetoken) - CError_Error(CErrorStr121); - typetoken = TK_INT; - break; - case TK_DOUBLE: - if (typetoken || signedness) - CError_Error(CErrorStr121); - typetoken = TK_DOUBLE; - break; - case TK_STRUCT: - if (typetoken || signedness || typesize) - CError_Error(CErrorStr121); - tk = lex(); - scanstruct(di, STRUCT_TYPE_STRUCT); - if (tk == TK_UU_ATTRIBUTE_UU) - CParser_ParseAttribute(di->thetype, NULL); - if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) { - typetoken = -1; - goto restart; - } - return; - case TK_CLASS: - if (typetoken || signedness || typesize) - CError_Error(CErrorStr121); - tk = lex(); - CDecl_ParseClass(di, CLASS_MODE_CLASS, 1, 0); - if (tk == TK_UU_ATTRIBUTE_UU) - CParser_ParseAttribute(di->thetype, NULL); - if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) { - typetoken = -1; - goto restart; - } - return; - case TK_UNION: - if (typetoken || signedness || typesize) - CError_Error(CErrorStr121); - tk = lex(); - scanstruct(di, STRUCT_TYPE_UNION); - if (tk == TK_UU_ATTRIBUTE_UU) - CParser_ParseAttribute(di->thetype, NULL); - if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) { - typetoken = -1; - goto restart; - } - return; - case TK_ENUM: - if (typetoken || signedness || typesize) - CError_Error(CErrorStr121); - tk = lex(); - scanenum(di); - if (tk == TK_UU_ATTRIBUTE_UU) - CParser_ParseAttribute(di->thetype, NULL); - if (!(tk != TK_CONST && tk != TK_VOLATILE && tk != TK_UU_FAR && tk != TK_UU_DECLSPEC)) { - typetoken = -1; - goto restart; - } - return; - case TK_TYPENAME: - if (typetoken || signedness || typesize || di->x53) - CError_Error(CErrorStr121); - di->x53 = 1; - tk = lex(); - if (tk != TK_COLON_COLON && tk != TK_IDENTIFIER) { - CError_Error(CErrorStr121); - break; - } - goto some_shared_label; - case TK_COLON_COLON: - if (typetoken || signedness || typesize) - goto switchDefault; - goto some_shared_label; - case TK_UU_VECTOR: - if (typetoken || signedness || typesize) - CError_Error(CErrorStr121); - handle_vector: - if (CParser_GetVectorDeclSpec(&di->thetype)) { - if (tk == TK_CONST) { - if (di->qual == 0) { - di->qual |= Q_CONST; - tk = lex(); - } else { - CError_Error(CErrorStr121); - } - } - if (tk == TK_VOLATILE) { - if (di->qual == 0) { - di->qual |= Q_VOLATILE; - tk = lex(); - } else { - CError_Error(CErrorStr121); - } - } - return; - } - break; - case TK_UU_TYPEOF_UU: - if (typetoken || signedness || typesize) - CError_Error(CErrorStr121); - CParser_ParseTypeOf(di); - typetoken = -1; - goto bailOut; - case TK_IDENTIFIER: - if (copts.altivec_model && !typetoken && !signedness && !typesize && !strcmp(tkidentifier->name, "vector")) { - if (CParser_IsAltiVecPrefix()) - goto handle_vector; - } - if (!typetoken && !signedness && !typesize) { - if (copts.objective_c && !strcmp(tkidentifier->name, "id")) { - di->thetype = CObjC_ParseID(); - typetoken = -1; - goto bailOut; - } - some_shared_label: - CPrep_TokenStreamGetState(&state); - if (CScope_ParseDeclName(&pr)) { - if (pr.type) { - if (IS_TYPE_TEMPLATE(pr.type)) { - switch (TYPE_TEMPLATE(pr.type)->dtype) { - case TEMPLDEP_ARGUMENT: - switch (TYPE_TEMPLATE(pr.type)->u.pid.type) { - case TPT_TYPE: - break; - case TPT_NONTYPE: - CError_Error(CErrorStr348); - pr.type = TYPE(&stsignedint); - break; - case TPT_TEMPLATE: - CError_Error(CErrorStr230); - pr.type = TYPE(&stsignedint); - break; - default: - CError_FATAL(4109); - } - break; - case TEMPLDEP_QUALNAME: - if (!di->x53 && !pr.x20 && di->x55) - CError_Error(CErrorStr355); - break; - case TEMPLDEP_TEMPLATE: - case TEMPLDEP_ARRAY: - case TEMPLDEP_QUALTEMPL: - case TEMPLDEP_BITFIELD: - break; - default: - CError_FATAL(4136); - } - } - - if (IS_TYPE_CLASS(pr.type) && (TYPE_CLASS(pr.type)->flags & CLASS_IS_TEMPL)) { - if (!CParser_CheckTemplateClassUsage(TEMPL_CLASS(pr.type), 0)) { - if (di->x56) { - if (di->qual) - CError_Error(CErrorStr121); - di->thetype = pr.type; - di->x57 = 1; - tk = lex(); - return; - } else { - CError_Error(CErrorStr230); - pr.type = TYPE(&stsignedint); - } - } - } - - TypedefDeclInfo(di, pr.type, pr.qual); - di->x49 = pr.x20; - typetoken = -1; - tk = lex(); - if (tk == '<' && copts.objective_c && IS_TYPE_CLASS(di->thetype) && TYPE_CLASS(di->thetype)->objcinfo) - di->thetype = CObjC_ParseTypeProtocol(TYPE_CLASS(di->thetype)); - goto bailOut; - } else if (pr.nsol_14) { - if (pr.x1D) { - if (flag && (OBJECT(pr.nsol_14->object)->nspace == pr.nspace_0 || di->in_friend_decl)) { - di->x14 = pr.nsol_14; - if (IS_TYPE_FUNC(OBJECT(di->x14->object)->type) && ((TYPE_FUNC(OBJECT(di->x14->object)->type)->flags & FUNC_IS_CTOR) | FUNC_IS_DTOR)) - r23 = 0; - } else { - CError_Error(CErrorStr121); - } - } - } else if (pr.obj_10) { - switch (pr.obj_10->otype) { - case OT_OBJECT: - if (pr.x1D) { - if (flag && (OBJECT(pr.obj_10)->nspace == pr.nspace_0 || di->in_friend_decl)) { - di->x10 = OBJECT(pr.obj_10); - if (IS_TYPE_FUNC(di->x10->type) && ((TYPE_FUNC(di->x10->type)->flags & FUNC_IS_CTOR) | FUNC_IS_DTOR)) - r23 = 0; - } else { - CError_Error(CErrorStr121); - } - } - break; - case OT_ENUMCONST: - case OT_MEMBERVAR: - CError_Error(CErrorStr121); - break; - default: - CError_FATAL(4217); - } - } else if (pr.name_4) { - if (copts.cplusplus) - CError_Error(CErrorStr121); - } else if (pr.x21) { - CPrep_TokenStreamSetState(&state); - CPrep_UnLex(); - tk = lex(); - r23 = 0; - } else { - CError_FATAL(4234); - } - } - } - default: - switchDefault: - if (!typetoken && !signedness && !typesize) { - di->x4A = 1; - if (r23) { - if (!di->storageclass && !di->qual && !di->exportflags) - CError_Error(CErrorStr121); - else - CError_Warning(CErrorStr349); - } - } - if (typetoken >= 0) - di->thetype = getthetype(typetoken, typesize, signedness); - if (r24) - di->x48 = 1; - if (tk == TK_UU_ATTRIBUTE_UU) - CParser_ParseAttribute(NULL, di); - return; - case ';': - if (!typetoken && !signedness && !typesize && copts.warn_emptydecl) - CError_Warning(CErrorStr216); - if (typetoken >= 0) - di->thetype = getthetype(typetoken, typesize, signedness); - return; - } - - tk = lex(); -bailOut: - r24 = 0; - goto restart; -} - -void CParser_RegisterNonGlobalClass(TypeClass *tclass) { - struct ParentCleanup *p = lalloc(sizeof(struct ParentCleanup)); - p->next = cparser_parentcleanup; - p->tclass = tclass; - cparser_parentcleanup = p; -} - -void CParser_RegisterSingleExprFunction(Object *func, ENode *expr) { - struct SFuncList *p = lalloc(sizeof(struct SFuncList)); - p->next = cparser_sfunclist; - p->func = func; - p->obj = NULL; - p->expr = expr; - cparser_sfunclist = p; -} - -void CParser_RegisterDummyCtorFunction(Object *func, Object *obj) { - struct SFuncList *p = lalloc(sizeof(struct SFuncList)); - p->next = cparser_sfunclist; - p->func = func; - p->obj = obj; - p->expr = NULL; - cparser_sfunclist = p; -} - -static void CParser_FreeLocalHeap(void) { - struct SFuncList *s; - struct ParentCleanup *p; - - while ((s = cparser_sfunclist)) { - cparser_sfunclist = s->next; - if (s->expr) - CFunc_GenerateSingleExprFunc(s->func, s->expr); - else - CFunc_GenerateDummyCtorFunc(s->func, s->obj); - } - - if (cparser_parentcleanup) { - if (!CInline_CanFreeLHeap()) - return; - - for (p = cparser_parentcleanup; p; p = p->next) { - while (!p->tclass->nspace->parent->is_global) - p->tclass->nspace->parent = p->tclass->nspace->parent->parent; - } - - cparser_parentcleanup = NULL; - } - - freelheap(); -} - -static void CParser_GlobalCleanup(Boolean flag) { - Boolean working; - - do { - CParser_FreeLocalHeap(); - working = 0; - - if (flag) { - if (cparser_classactions) { - CClass_ClassAction(cparser_classactions->tclass); - cparser_classactions = cparser_classactions->next; - working = 1; - } else if (CTempl_Instantiate()) { - working = 1; - } - } - - while (CInline_GenerateDeferredFuncs()) { - CParser_FreeLocalHeap(); - working = 1; - } - } while (working); -} - -Boolean CParser_IsAnonymousUnion(DeclInfo *di, Boolean flag) { - return IS_TYPE_CLASS(di->thetype) && - ((TYPE_CLASS(di->thetype)->mode == CLASS_MODE_UNION || (flag && copts.cpp_extensions))) && - IsTempName(TYPE_CLASS(di->thetype)->classname); -} - -void CParser_CheckAnonymousUnion(DeclInfo *di, Boolean flag) { - ObjMemberVar *ivar; - Object *obj; - Object *ivar_obj; - - if (!CParser_IsAnonymousUnion(di, 0)) { - if (copts.warn_emptydecl) { - switch (di->thetype->type) { - case TYPEENUM: - case TYPESTRUCT: - case TYPECLASS: - if (!di->storageclass && !di->qual) - return; - } - CError_Warning(CErrorStr216); - } - return; - } - - if (!flag && di->storageclass != TK_STATIC) - CError_Error(CErrorStr177); - - if (flag && di->storageclass != TK_STATIC) { - obj = CParser_NewLocalDataObject(di, 1); - obj->name = CParser_GetUniqueName(); - CFunc_SetupLocalVarInfo(obj); - obj->u.var.info->noregister = 1; - } else { - obj = CParser_NewGlobalDataObject(di); - obj->name = CParser_GetUniqueName(); - obj->nspace = cscope_root; - obj->sclass = TK_STATIC; - CInit_DeclareData(obj, NULL, NULL, obj->type->size); - } - - for (ivar = TYPE_CLASS(di->thetype)->ivars; ivar; ivar = ivar->next) { - ivar_obj = galloc(sizeof(Object)); - *ivar_obj = *obj; - ivar_obj->name = ivar->name; - ivar_obj->type = ivar->type; - ivar_obj->qual = ivar->qual; - ivar_obj->datatype = DALIAS; - ivar_obj->u.alias.object = obj; - ivar_obj->u.alias.offset = ivar->offset; - ivar_obj->u.alias.member = NULL; - CScope_AddObject(cscope_current, ivar_obj->name, OBJ_BASE(ivar_obj)); - } -} - -void CParser_NewCallBackAction(Object *obj, TypeClass *tclass) { - CallbackAction *act = galloc(sizeof(CallbackAction)); - act->next = callbackactions; - act->obj = obj; - act->tclass = tclass; - callbackactions = act; - obj->flags = obj->flags | OBJECT_LAZY; -} - -void CParser_NewClassAction(TypeClass *tclass) { - struct ClassAction *act = galloc(sizeof(struct ClassAction)); - act->next = cparser_classactions; - act->tclass = tclass; - cparser_classactions = act; -} - -void CParser_CallBackAction(Object *obj) { - CallbackAction *act; - - for (act = callbackactions; act; act = act->next) { - if (act->obj == obj) { - CParser_NewClassAction(act->tclass); - return; - } - } - - CError_FATAL(4551); -} - -static Object *CParser_FindOverloadFunc(NameSpaceObjectList *list, TypeFunc *tfunc) { - while (list) { - if (list->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(list->object)->type)) - if (CParser_CompareArgLists(tfunc->args, TYPE_FUNC(OBJECT(list->object)->type)->args) == 1) - return OBJECT(list->object); - list = list->next; - } - - return NULL; -} - -Object *CParser_ParseObject(void) { - DeclInfo di; - NameResult pr; - NameSpaceObjectList *list; - Object *obj; - - memclrw(&di, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&di, 1); - scandeclarator(&di); - - if (di.name && (list = CScope_FindObjectList(&pr, di.name))) { - if (list->object->otype == OT_OBJECT) { - if (IS_TYPE_FUNC(di.thetype)) - return CParser_FindOverloadFunc(list, TYPE_FUNC(di.thetype)); - - if (is_typesame(di.thetype, OBJECT(list->object)->type) && OBJECT(list->object)->qual == di.qual) - return OBJECT(list->object); - - obj = OBJECT(list->object); - CError_Error(CErrorStr249, CError_GetObjectName(obj), obj->type, obj->qual, di.thetype, di.qual); - } - } - - return NULL; -} - -void CParser_ParseGlobalDeclaration(void) { - DeclInfo di; - - if (tk) { - CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL); - symdecloffset = cparser_fileoffset.tokenline; - symdecltoken = *CPrep_CurStreamElement(); - - memclrw(&di, sizeof(DeclInfo)); - CParser_GetDeclSpecs(&di, 1); - if (di.storageclass == TK_REGISTER || di.storageclass == TK_AUTO) { - CError_Error(CErrorStr177); - di.storageclass = 0; - } - - if (tk != ';') - scandeclaratorlist(&di); - else - CParser_CheckAnonymousUnion(&di, 0); - - tk = lex(); - } else { - CError_Error(CErrorStr102); - } -} - -static void CParser_ParseLinkageSpecification(DeclInfo *di) { - UInt32 qual; - UInt8 r28; - - if (!strcmp(tkstring, "C") || !strcmp(tkstring, "Objective C")) { - qual = 0; - r28 = 1; - } else if (!strcmp(tkstring, "C++")) { - qual = 0; - r28 = 0; - } else if (!strcmp(tkstring, "Pascal")) { - qual = Q_PASCAL; - r28 = 1; - } else { - CError_Error(CErrorStr121); - qual = 0; - r28 = 1; - } - - if ((tk = lex()) == '{') { - while (1) { - if ((tk = lex()) == 0) { - CError_Error(CErrorStr130); - return; - } - - if (tk == '}') - break; - - CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL); - symdecloffset = cparser_fileoffset.tokenline; - symdecltoken = *CPrep_CurStreamElement(); - - memclrw(di, sizeof(DeclInfo)); - di->is_extern_c = r28; - di->qual = qual; - CParser_ParseDeclaration(di); - } - } else if (tk == TK_EXTERN && copts.cpp_extensions && lookahead() == TK_STRING) { - tk = lex(); - CParser_ParseLinkageSpecification(di); - } else { - memclrw(di, sizeof(DeclInfo)); - di->is_extern_c = r28; - di->qual = qual; - CParser_GetDeclSpecs(di, 1); - - if (di->storageclass != TK_TYPEDEF) { - if (di->storageclass && copts.pedantic) - CError_Warning(CErrorStr177); - if (!di->storageclass) - di->storageclass = TK_EXTERN; - } - if (copts.cpp_extensions) - di->x48 = 0; - if (tk != ';') - scandeclaratorlist(di); - } -} - -static void CParser_ParseNameSpace(DeclInfo *di) { - NameSpace *nspace; - ObjNameSpace *objns; - HashNameNode *name; - Boolean flag; - CScopeSave save; - NameSpaceObjectList *list; - NameSpaceList *nsl; - - if ((tk = lex()) == TK_IDENTIFIER) { - name = tkidentifier; - flag = 0; - if ((tk = lex()) == '=') { - CScope_ParseNameSpaceAlias(name); - return; - } - } else { - if (tk != '{') { - CError_Error(CErrorStr107); - return; - } - name = CParser_GetUnnamedNameSpaceName(); - flag = 1; - } - - nspace = cscope_current; - if (!(list = CScope_FindName(nspace, name))) { - objns = galloc(sizeof(ObjNameSpace)); - memclrw(objns, sizeof(ObjNameSpace)); - objns->otype = OT_NAMESPACE; - objns->access = ACCESSPUBLIC; - if (flag) { - nspace = CScope_NewListNameSpace(name, 1); - nspace->is_unnamed = 1; - nsl = galloc(sizeof(NameSpaceList)); - nsl->next = cscope_current->usings; - nsl->nspace = nspace; - cscope_current->usings = nsl; - } else { - nspace = CScope_NewHashNameSpace(name); - if (cscope_current->is_unnamed) - nspace->is_unnamed = 1; - } - - nspace->parent = cscope_current; - objns->nspace = nspace; - CScope_AddObject(cscope_current, name, OBJ_BASE(objns)); - } else { - if (list->object->otype != OT_NAMESPACE) - CError_Error(CErrorStr320); - else - nspace = OBJ_NAMESPACE(list->object)->nspace; - } - - if (tk != '{') { - CError_Error(CErrorStr135); - return; - } - - CScope_SetNameSpaceScope(nspace, &save); - while (1) { - if ((tk = lex()) == 0) { - CError_Error(CErrorStr130); - break; - } - - if (tk == '}') - break; - - CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL); - symdecloffset = cparser_fileoffset.tokenline; - symdecltoken = *CPrep_CurStreamElement(); - - memclrw(di, sizeof(DeclInfo)); - CParser_ParseDeclaration(di); - } - CScope_RestoreScope(&save); -} - -static void CParser_ParseDeclaration(DeclInfo *di) { - switch (tk) { - case TK_AT_INTERFACE: - CObjC_ParseInterface(); - break; - case TK_AT_IMPLEMENTATION: - CObjC_ParseImplementation(); - break; - case TK_AT_PROTOCOL: - CObjC_ParseProtocol(); - break; - case TK_AT_CLASS: - CObjC_ParseClassDeclaration(); - break; - case TK_NAMESPACE: - CParser_ParseNameSpace(di); - break; - case TK_EXPORT: - CError_Error(CErrorStr190); - if ((tk = lex()) != TK_TEMPLATE) { - CError_Error(CErrorStr121); - return; - } - case TK_TEMPLATE: - CTempl_Parse(NULL, 0); - break; - case TK_USING: - if ((tk = lex()) == TK_NAMESPACE) { - tk = lex(); - CScope_ParseUsingDirective(cscope_current); - } else { - CScope_ParseUsingDeclaration(cscope_current, 0, 0); - } - break; - case TK_EXTERN: - if (copts.cplusplus) { - di->storageclass = TK_EXTERN; - if ((tk = lex()) == TK_STRING) { - CParser_ParseLinkageSpecification(di); - break; - } - } - default: - CParser_GetDeclSpecs(di, 1); - if ((di->storageclass == TK_REGISTER || di->storageclass == TK_AUTO) != 0) { - CError_Error(CErrorStr177); - di->storageclass = 0; - } - if (tk != ';') - scandeclaratorlist(di); - else - CParser_CheckAnonymousUnion(di, 0); - CParser_GlobalCleanup(0); - } -} - -void cparser(void) { - DeclInfo di; - - if (copts.crippled && copts.optimizationlevel > 1) { - CError_Warning(CErrorStr385); - copts.optimizationlevel = 1; - CodeGen_UpdateOptimizerOptions(); - CodeGen_UpdateBackEndOptions(); - } - - if ((tk = lex())) { - do { - CPrep_NewFileOffsetInfo(&cparser_fileoffset, NULL); - symdecloffset = cparser_fileoffset.tokenline; - symdecltoken = *CPrep_CurStreamElement(); - - memclrw(&di, sizeof(DeclInfo)); - CParser_ParseDeclaration(&di); - } while (tk && (tk = lex())); - } else { - if (!copts.cplusplus && copts.ANSIstrict) - CError_Error(CErrorStr102); - } - - CInit_DefineTentativeData(); - copts.defer_codegen = 0; - CParser_GlobalCleanup(1); - - if (cparamblkptr->precompile != 1) { - CInline_Finish(); - CParser_GlobalCleanup(1); - } - - CClass_GenThunks(); - if (cparamblkptr->precompile != 1) - CObjC_GenerateModule(); - - CSOM_Cleanup(); - CInit_DefineTentativeData(); -} diff --git a/compiler_and_linker/unsorted/CPrec.c b/compiler_and_linker/unsorted/CPrec.c deleted file mode 100644 index e61b96e..0000000 --- a/compiler_and_linker/unsorted/CPrec.c +++ /dev/null @@ -1,3482 +0,0 @@ -#include "compiler/CPrec.h" -#include "compiler/CError.h" -#include "compiler/CFunc.h" -#include "compiler/CInit.h" -#include "compiler/CInline.h" -#include "compiler/CMachine.h" -#include "compiler/CObjC.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CScope.h" -#include "compiler/CSOM.h" -#include "compiler/CTemplateNew.h" -#include "compiler/CompilerTools.h" -#include "compiler/Exceptions.h" -#include "compiler/enode.h" -#include "compiler/objc.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/som.h" -#include "compiler/templates.h" -#include "compiler/types.h" -#include "cos.h" -#include "compiler/CCompiler.h" -#include "compiler/InlineAsm.h" - -#define RESOLVE_BUFFER(offset) ((void *) (((char *) cprec_buffer) + ((uintptr_t) (offset)))) -#define RESOLVE_RAW_BUFFER(offset) ((void *) (((char *) cprec_rawbuffer) + ((uintptr_t) (offset)))) -#define RESOLVE_SAFE(offset) (!(offset) ? NULL : ((void *) (((char *) cprec_rawbuffer) + ((uintptr_t) (offset))))) - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct StaticData { - struct StaticData *next; - Object *object; - void *buffer; - OLinkList *links; - SInt32 size; -} StaticData; - -typedef struct Header { - UInt32 magic; - UInt16 version; - UInt16 x6; - char target; - Boolean check_header_flags; - Boolean cplusplus; - UInt32 xC; - UInt32 x10; - UInt32 x14; - UInt32 x18; - UInt32 x1C; - UInt32 x20; - UInt32 x24; - UInt32 x28; - UInt32 x2C; - UInt32 x30; - UInt32 compressedPatchCount; - UInt32 compressedPatchSize; - UInt32 compressedPatchOffset; - UInt32 builtinPatchSize; - UInt32 builtinPatchOffset; - UInt32 tokenStreamPatchSize; - UInt32 tokenStreamPatchOffset; - UInt32 root_names; - NameSpaceList *usings; - TemplClass *ctempl_templates; - CSOMStub *csom_stubs; - StaticData *cprec_staticdata; - UInt32 uniqueID; - CallbackAction *callbackactions; - Type *cobjc_type_class; - Type *cobjc_type_id; - Type *cobjc_type_sel; - ObjCSelector **cobjc_selhashtable; - BClassList *cobjc_classdefs; - ObjCProtocol *cobjc_protocols; - UInt32 cobjc_selrefcount; - UInt32 cobjc_classrefcount; - UInt32 cobjc_stringcount; - InitExpr *init_expressions; - CI_Action *cinline_tactionlist; - TemplateFunction *ctempl_templatefuncs; - UInt32 x9C; - UInt32 xA0; - UInt32 xA4; - UInt32 xA8; - UInt32 xAC; - UInt32 xB0; - UInt32 xB4; - UInt32 xB8; - UInt32 xBC; - UInt32 xC0; - UInt32 xC4; - UInt32 xC8; - UInt32 xCC; - UInt32 xD0; - UInt32 xD4; - UInt32 xD8; - UInt32 xDC; - UInt32 xE0; - UInt32 xE4; - HashNameNode *nametable[0x800]; - Macro *macrotable[0x800]; - NameSpaceName *root_nametable[0x400]; -} Header; - -typedef struct Patch { - struct Patch *next; - SInt32 offset; -} Patch; - -typedef struct AddrPatch { - struct AddrPatch *next; - void *addr; - void *value; -} AddrPatch; - -typedef struct BuiltIn { - void *target; - SInt32 idx; - Patch *patches; -} BuiltIn; - -static Boolean cprec_exportargnames; -static Boolean cprec_dowrite; -static OSErr cprec_ioerror; -static void *cprec_rawbuffer; -static void *cprec_buffer; -static SInt32 cprec_zero_offset; -static SInt32 cprec_offset; -static int cprec_builtins; -static void **cprec_builtin_array; - -typedef struct TokenPatch { - struct TokenPatch *next; - TStreamElement *tokens; - SInt32 count; -} TokenPatch; -static TokenPatch *cprec_tokenpatches; -static StaticData *cprec_staticdata; - -typedef struct PointerHash { - struct PointerHash *next; - TypePointer *tptr; - TypePointer *prec_tptr; -} PointerHash; -static PointerHash **cprec_pointerhash; - -static BuiltIn *cprec_builtin; -static Patch *cprec_patch_list; -static AddrPatch **cprec_addrhash; -static Header *cprec_header; -static GList cprec_glist; -static short cprec_refnum; -char *precomp_target_str; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -// Assorted forward declarations -static NameSpace *CPrec_GetNameSpacePatch(NameSpace *nspace); -static ObjEnumConst *CPrec_GetObjEnumConstPatch(ObjEnumConst *obj); -static Object *CPrec_GetObjectPatch(Object *obj); -static ObjBase *CPrec_GetObjBasePatch(ObjBase *obj); -static ObjMemberVar *CPrec_GetObjMemberVarPatch(ObjMemberVar *ivar); -static Type *CPrec_GetTypePatch(Type *type); -static ENode *CPrec_GetExpressionPatch(ENode *expr); -static ObjCMethod *CPrec_GetObjCMethodPatch(ObjCMethod *meth); -static ObjCProtocolList *CPrec_GetObjCProtocolListPatch(ObjCProtocolList *lst); -static TemplArg *CPrec_GetTemplateArgPatch(TemplArg *arg); -static NameSpaceObjectList *CPrec_GetNameSpaceObjectListPatch(NameSpaceObjectList *nsol); -static OSErr CPrec_FlushBufferCheck(void); - -void SetupPrecompiler(Boolean isPrecompiling) { - cprec_refnum = 0; - cprec_glist.data = NULL; - cprec_header = NULL; - cprec_staticdata = NULL; - cprec_ioerror = noErr; -} - -void CleanupPrecompiler(void) { - if (cprec_refnum) { - COS_FileClose(cprec_refnum); - cprec_refnum = 0; - } - - if (cprec_glist.data) - FreeGList(&cprec_glist); -} - -static OLinkList *CPrec_OLinkListCopy(OLinkList *list) { - OLinkList *copy; - - if (!list) - return NULL; - - copy = galloc(sizeof(OLinkList)); - *copy = *list; - copy->next = CPrec_OLinkListCopy(copy->next); - return copy; -} - -void PreComp_StaticData(Object *obj, const void *data, OLinkList *links, SInt32 size) { - StaticData *entry; - - if (obj->sclass != TK_STATIC && !(obj->qual & (Q_20000 | Q_WEAK))) - CError_Error(CErrorStr180); - - entry = galloc(sizeof(StaticData)); - entry->object = obj; - entry->size = size; - - entry->next = cprec_staticdata; - cprec_staticdata = entry; - - if (data) { - entry->buffer = galloc(obj->type->size); - memcpy(entry->buffer, data, obj->type->size); - } else { - entry->buffer = NULL; - } - - entry->links = CPrec_OLinkListCopy(links); -} - -static void CPrec_InitAddressHashTable(void) { - cprec_addrhash = lalloc(0x4000 * sizeof(AddrPatch *)); - memclrw(cprec_addrhash, 0x4000 * sizeof(AddrPatch *)); -} - -static void CPrec_InitPointerHashTable(void) { - cprec_pointerhash = lalloc(0x400 * sizeof(PointerHash *)); - memclrw(cprec_pointerhash, 0x400 * sizeof(PointerHash *)); -} - -static int CPrec_AddressHashVal(void *addr) { - UInt32 v = (UInt32) addr; - return ( - v + - ((unsigned char *) &v)[0] + - ((unsigned char *) &v)[1] + - ((unsigned char *) &v)[2] + - ((unsigned char *) &v)[3] - ) & 0x3FFF; -} - -static AddrPatch *CPrec_FindAddrPatch(void *addr) { - AddrPatch *scan; - - for (scan = cprec_addrhash[CPrec_AddressHashVal(addr)]; scan; scan = scan->next) { - if (scan->addr == addr) - return scan; - } - - return NULL; -} - -static AddrPatch *CPrec_NewAddrPatch(void *addr, void *value) { - AddrPatch **loc; - AddrPatch *patch; - - loc = cprec_addrhash + CPrec_AddressHashVal(addr); - patch = lalloc(sizeof(AddrPatch)); - patch->addr = addr; - patch->value = value; - patch->next = *loc; - *loc = patch; - return patch; -} - -static void CPrec_SetupBuiltInArray(void) { - int count1, count2; - Boolean flag; - void **array; - -#define REG_BUILTIN(a) \ - if (!flag) { array[count2++] = (a); } else { count1++; } - - for (count2 = count1 = 0, flag = 1; ;) { - REG_BUILTIN(cscope_root); - REG_BUILTIN(&stvoid); - REG_BUILTIN(&stbool); - REG_BUILTIN(&stchar); - REG_BUILTIN(&stsignedchar); - REG_BUILTIN(&stunsignedchar); - REG_BUILTIN(&stwchar); - REG_BUILTIN(&stsignedshort); - REG_BUILTIN(&stunsignedshort); - REG_BUILTIN(&stsignedint); - REG_BUILTIN(&stunsignedint); - REG_BUILTIN(&stsignedlong); - REG_BUILTIN(&stunsignedlong); - REG_BUILTIN(&stsignedlonglong); - REG_BUILTIN(&stunsignedlonglong); - REG_BUILTIN(&stfloat); - REG_BUILTIN(&stshortdouble); - REG_BUILTIN(&stdouble); - REG_BUILTIN(&stlongdouble); - REG_BUILTIN(&elipsis); - REG_BUILTIN(&oldstyle); - REG_BUILTIN(&stillegal); - REG_BUILTIN(&sttemplexpr); - REG_BUILTIN(&stvoid); - REG_BUILTIN(&void_ptr); - REG_BUILTIN(&rt_func); - REG_BUILTIN(&catchinfostruct); - REG_BUILTIN(newh_func); - REG_BUILTIN(delh_func); - REG_BUILTIN(copy_func); - REG_BUILTIN(clear_func); - REG_BUILTIN(Rgtid_func); - REG_BUILTIN(Rdync_func); - REG_BUILTIN(rt_ptmf_cast); - REG_BUILTIN(rt_ptmf_cmpr); - REG_BUILTIN(rt_ptmf_test); - REG_BUILTIN(rt_ptmf_call); - REG_BUILTIN(rt_ptmf_scall); - REG_BUILTIN(rt_ptmf_null); - REG_BUILTIN(rt_som_glue1); - REG_BUILTIN(rt_som_glue2); - REG_BUILTIN(rt_som_glue3); - REG_BUILTIN(rt_som_check); - REG_BUILTIN(rt_som_new); - REG_BUILTIN(rt_som_newcheck); - REG_BUILTIN(rt_ptmf_call4); - REG_BUILTIN(rt_ptmf_scall4); - REG_BUILTIN(carr_func); - REG_BUILTIN(cnar_func); - REG_BUILTIN(darr_func); - REG_BUILTIN(dnar_func); - REG_BUILTIN(dnar3_func); - REG_BUILTIN(Xgreg_func); - REG_BUILTIN(Xthrw_func); - REG_BUILTIN(Xicth_func); - REG_BUILTIN(Xecth_func); - REG_BUILTIN(Xunex_func); - REG_BUILTIN(&stvectorunsignedchar); - REG_BUILTIN(&stvectorsignedchar); - REG_BUILTIN(&stvectorboolchar); - REG_BUILTIN(&stvectorunsignedshort); - REG_BUILTIN(&stvectorsignedshort); - REG_BUILTIN(&stvectorboolshort); - REG_BUILTIN(&stvectorunsignedlong); - REG_BUILTIN(&stvectorsignedlong); - REG_BUILTIN(&stvectorboollong); - REG_BUILTIN(&stvectorfloat); - REG_BUILTIN(&stvectorpixel); - - if (flag) { - array = lalloc(sizeof(void *) * count1); - cprec_builtin_array = array; - cprec_builtins = count1; - flag = 0; - } else { - return; - } - } -} - -static void CPrec_SetupBuiltIn(void) { - int x; - - CPrec_SetupBuiltInArray(); - cprec_builtin = lalloc(sizeof(BuiltIn) * cprec_builtins); - memclrw(cprec_builtin, sizeof(BuiltIn) * cprec_builtins); - - for (x = 0; x < cprec_builtins; x++) { - cprec_builtin[x].target = cprec_builtin_array[x]; - cprec_builtin[x].idx = ~x; - CPrec_NewAddrPatch(cprec_builtin[x].target, (void *) cprec_builtin[x].idx); - } -} - -static void CPrec_NewPointerPatch(void *src, void *ptr) { - if (cprec_dowrite) { - Patch *patch = lalloc(sizeof(Patch)); - patch->offset = (SInt32) src; - CError_ASSERT(507, (patch->offset & 0x80000001) == 0); - - if ((SInt32) ptr < 0) { - ptr = (void *) ~((SInt32) ptr); - CError_ASSERT(513, (SInt32) ptr < cprec_builtins); - - patch->next = cprec_builtin[(SInt32) ptr].patches; - cprec_builtin[(SInt32) ptr].patches = patch; - ptr = NULL; - } else { - patch->next = cprec_patch_list; - cprec_patch_list = patch; - } - - src = (void *)((char *) src - cprec_zero_offset); - CError_ASSERT(525, (SInt32) src >= 0 && (SInt32) src <= cprec_glist.size); - *((void **) (*cprec_glist.data + (SInt32) src)) = ptr; - } -} - -static void CPrec_ExistingPointerPatch(void *src, void *ptr) { - if (cprec_dowrite) { - AddrPatch *addrPatch; - Patch *patch; - - CError_ASSERT(543, addrPatch = CPrec_FindAddrPatch(ptr)); - - patch = lalloc(sizeof(Patch)); - patch->offset = (SInt32) src; - patch->next = cprec_patch_list; - cprec_patch_list = patch; - - CError_ASSERT(548, (patch->offset & 0x80000001) == 0); - - src = (void *)((char *) src - cprec_zero_offset); - CError_ASSERT(552, (SInt32) src >= 0 && (SInt32) src <= cprec_glist.size); - *((void **) (*cprec_glist.data + (SInt32) src)) = addrPatch->value; - } -} - -static void CPrec_NamePatch(void *src, HashNameNode *name) { - name->id = 1; - CPrec_ExistingPointerPatch(src, name); -} - -static void *CPrec_AppendAlign(void) { - if (cprec_dowrite) { - while (cprec_offset & 3) { - AppendGListByte(&cprec_glist, 0); - ++cprec_offset; - } - } - - return (void *) cprec_offset; -} - -static UInt32 CPrec_AppendByte(UInt8 v) { - if (cprec_dowrite) - AppendGListByte(&cprec_glist, v); - return cprec_offset++; -} - -static UInt32 CPrec_AppendWord16(UInt16 v) { - UInt32 offset; - if (cprec_dowrite) - AppendGListWord(&cprec_glist, v); - offset = cprec_offset; - cprec_offset += 2; - return offset; -} - -static UInt32 CPrec_AppendWord32(UInt32 v) { - UInt32 offset; - if (cprec_dowrite) - AppendGListLong(&cprec_glist, v); - offset = cprec_offset; - cprec_offset += 4; - return offset; -} - -static UInt32 CPrec_AppendPointer(void *v) { - UInt32 offset; - if (cprec_dowrite) - AppendGListLong(&cprec_glist, (SInt32) v); - offset = cprec_offset; - cprec_offset += 4; - return offset; -} - -static UInt32 CPrec_AppendPointerPatch(void *v) { - AddrPatch *addrPatch; - - if (v) { - CError_ASSERT(644, addrPatch = CPrec_FindAddrPatch(v)); - - if (cprec_dowrite) { - Patch *patch = lalloc(sizeof(Patch)); - patch->offset = cprec_offset; - patch->next = cprec_patch_list; - cprec_patch_list = patch; - CError_ASSERT(651, (patch->offset & 0x80000001) == 0); - } - - return CPrec_AppendPointer(addrPatch->value); - } else { - return CPrec_AppendPointer(NULL); - } -} - -static void CPrec_AppendNamePatch(HashNameNode *name) { - if (name) { - CPrec_AppendPointerPatch(name); - name->id = 1; - } -} - -static void CPrec_AppendString(const char *str) { - int len = strlen(str) + 1; - if (cprec_dowrite) - AppendGListData(&cprec_glist, str, len); - cprec_offset += len; -} - -static void CPrec_AppendData(const void *data, int len) { - if (cprec_dowrite) - AppendGListData(&cprec_glist, data, len); - cprec_offset += len; -} - -static void CPrec_RawMemPatch(void *source, const void *data, int len) { - void *ptr = CPrec_AppendAlign(); - CPrec_AppendData(data, len); - CPrec_NewPointerPatch(source, ptr); -} - -static void CPrec_DumpNameTable(void) { - HashNameNode *name; - int i; - HashNameNode *p; - HashNameNode *next; - - if (cprec_dowrite) { - i = 0; - do { - name = name_hash_nodes[i]; - while (name && name->id == 0) - name = name->next; - - if (name) { - p = CPrec_AppendAlign(); - cprec_header->nametable[i] = p; - - while (1) { - CPrec_NewAddrPatch(name, p); - CPrec_AppendPointer(NULL); - CPrec_AppendWord32(0); - CPrec_AppendWord16(name->hashval); - CPrec_AppendString(name->name); - - name = name->next; - while (name && name->id == 0) - name = name->next; - - if (!name) - break; - - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(&p->next, next); - p = next; - } - } - } while (++i < 0x800); - } else { - i = 0; - do { - if ((name = name_hash_nodes[i])) { - p = CPrec_AppendAlign(); - while (1) { - CPrec_NewAddrPatch(name, p); - CPrec_AppendPointer(NULL); - CPrec_AppendWord32(0); - CPrec_AppendWord16(name->hashval); - CPrec_AppendString(name->name); - - name = name->next; - if (!name) - break; - - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(&p->next, next); - p = next; - } - } - } while (++i < 0x800); - } -} - -static void CPrec_DumpMacroTable(void) { - Macro *macro; - int i; - int j; - Macro *p; - Macro *next; - - i = 0; - do { - for (macro = macrohashtable[i]; macro; macro = macro->next) { - if (macro->c) { - CPrec_NewAddrPatch(macro->c, (void *) cprec_offset); - CPrec_AppendString(macro->c); - } - } - } while (++i < 0x800); - - i = 0; - do { - macro = macrohashtable[i]; - - if (macro) { - p = CPrec_AppendAlign(); - if (cprec_dowrite) - cprec_header->macrotable[i] = p; - - while (1) { - CPrec_AppendPointer(NULL); - CPrec_AppendNamePatch(macro->name); - CPrec_AppendPointerPatch(macro->c); - CPrec_AppendWord16(macro->xC); - CPrec_AppendByte(macro->is_special); - CPrec_AppendByte(macro->xF); - - for (j = 1; j < (macro->xC & 0x7FFF); j++) - CPrec_AppendNamePatch(macro->names[j - 1]); - - macro = macro->next; - if (!macro) - break; - - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(&p->next, next); - p = next; - } - } - } while (++i < 0x800); -} - -static BClassList *CPrec_GetClassAccessPatch(BClassList *path) { - AddrPatch *addrPatch; - BClassList *first, *current, *next; - - if ((addrPatch = CPrec_FindAddrPatch(path))) - return addrPatch->value; - - first = current = CPrec_AppendAlign(); - CPrec_NewAddrPatch(path, first); - - while (1) { - CPrec_AppendData(path, sizeof(BClassList)); - CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(path->type)); - if (!path->next) - break; - - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - path = path->next; - } - - return first; -} - -static int CPrec_PointerHash(TypePointer *type) { - Type *target; - int work; - FuncArg *arg; - - work = type->qual; - target = type->target; - -restart: - switch (target->type) { - case TYPECLASS: - if (TYPE_CLASS(target)->classname) - work += TYPE_CLASS(target)->classname->hashval; - break; - case TYPEENUM: - if (TYPE_ENUM(target)->enumname) - work += TYPE_ENUM(target)->enumname->hashval; - target = TYPE_ENUM(target)->enumtype; - work += 3; - case TYPEINT: - case TYPEFLOAT: - work += TYPE_INTEGRAL(target)->integral; - break; - case TYPEPOINTER: - work += TYPE_POINTER(target)->qual; - target = TYPE_POINTER(target)->target; - goto restart; - case TYPEARRAY: - work += target->size; - target = TYPE_POINTER(target)->target; - goto restart; - case TYPEFUNC: - work += TYPE_FUNC(target)->functype->type; - work += TYPE_FUNC(target)->functype->size; - for (arg = TYPE_FUNC(target)->args; arg; arg = arg->next) { - if (arg->type) { - work += arg->type->type; - work += arg->type->size; - } - } - break; - } - - work += target->type + target->size; - return (work + (work >> 24) + (work >> 16) + (work >> 8)) & 0x3FF; -} - -static TypePointer *CPrec_GetTypePointerPatch(TypePointer *tptr) { - TypePointer *p; - int hash; - PointerHash *phash; - TypePointer *scan1; - TypePointer *scan2; - - if (tptr->qual & Q_IS_OBJC_ID) { - p = CPrec_AppendAlign(); - CPrec_NewAddrPatch(tptr, p); - CPrec_AppendData(tptr, sizeof(TypeObjCID)); - if (TYPE_OBJC_ID(tptr)->protocols) - CPrec_NewPointerPatch(&TYPE_OBJC_ID(p)->protocols, CPrec_GetObjCProtocolListPatch(TYPE_OBJC_ID(tptr)->protocols)); - } else { - if (!copts.faster_pch_gen && cprec_dowrite && tptr->size > 0) { - hash = CPrec_PointerHash(tptr); - for (phash = cprec_pointerhash[hash]; phash; phash = phash->next) { - scan1 = tptr; - scan2 = phash->tptr; - check_again: - if (scan1->type == scan2->type && scan1->size == scan2->size && scan1->qual == scan2->qual) { - scan1 = TYPE_POINTER(TPTR_TARGET(scan1)); - scan2 = TYPE_POINTER(TPTR_TARGET(scan2)); - if (scan1->type == TYPEPOINTER && scan1->type == TYPEARRAY) - goto check_again; - if (scan1 == scan2) - return phash->prec_tptr; - } - } - - p = CPrec_AppendAlign(); - CPrec_NewAddrPatch(tptr, p); - - phash = lalloc(sizeof(PointerHash)); - phash->tptr = tptr; - phash->prec_tptr = p; - phash->next = cprec_pointerhash[hash]; - cprec_pointerhash[hash] = phash; - } else { - p = CPrec_AppendAlign(); - CPrec_NewAddrPatch(tptr, p); - } - - CPrec_AppendData(tptr, sizeof(TypePointer)); - } - - CPrec_NewPointerPatch(&p->target, CPrec_GetTypePatch(tptr->target)); - return p; -} - -static TypeEnum *CPrec_GetTypeEnumPatch(TypeEnum *type) { - TypeEnum *p = CPrec_AppendAlign(); - - CPrec_NewAddrPatch(type, p); - CPrec_AppendData(type, sizeof(TypeEnum)); - - if (type->nspace) - CPrec_NewPointerPatch(&p->nspace, CPrec_GetNameSpacePatch(type->nspace)); - if (type->enumlist) - CPrec_NewPointerPatch(&p->enumlist, CPrec_GetObjEnumConstPatch(type->enumlist)); - - CPrec_NewPointerPatch(&p->enumtype, CPrec_GetTypePatch(type->enumtype)); - if (type->enumname) - CPrec_NamePatch(&p->enumname, type->enumname); - - return p; -} - -static TypeBitfield *CPrec_GetTypeBitfieldPatch(TypeBitfield *type) { - TypeBitfield *p = CPrec_AppendAlign(); - - CPrec_NewAddrPatch(type, p); - CPrec_AppendData(type, sizeof(TypeBitfield)); - CPrec_NewPointerPatch(&p->bitfieldtype, CPrec_GetTypePatch(type->bitfieldtype)); - - return p; -} - -static TypeStruct *CPrec_GetTypeStructPatch(TypeStruct *tstruct) { - StructMember *member; - TypeStruct *p; - StructMember *current, *next; - - p = CPrec_AppendAlign(); - CPrec_NewAddrPatch(tstruct, p); - CPrec_AppendData(tstruct, sizeof(TypeStruct)); - - if (tstruct->name) - CPrec_NamePatch(&p->name, tstruct->name); - - if ((member = tstruct->members)) { - current = CPrec_AppendAlign(); - CPrec_NewPointerPatch(&p->members, current); - - while (1) { - CPrec_AppendData(member, sizeof(StructMember)); - CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(member->type)); - CPrec_NamePatch(¤t->name, member->name); - - if (!member->next) - break; - - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - - member = member->next; - } - } - - return p; -} - -static ExceptSpecList *CPrec_GetExceptSpecPatch(ExceptSpecList *exspec) { - ExceptSpecList *first, *current, *next; - - first = current = CPrec_AppendAlign(); - while (exspec) { - CPrec_AppendData(exspec, sizeof(ExceptSpecList)); - if (exspec->type) - CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(exspec->type)); - - if (!exspec->next) - break; - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - exspec = exspec->next; - } - - return first; -} - -static FuncArg *CPrec_GetArgListPatch(FuncArg *lst, Boolean includeNames) { - FuncArg *first, *current, *next; - AddrPatch *addrPatch; - - if ((addrPatch = CPrec_FindAddrPatch(lst))) - return addrPatch->value; - - first = current = CPrec_AppendAlign(); - while (1) { - if (!includeNames) - lst->name = NULL; - CPrec_AppendData(lst, sizeof(FuncArg)); - if (includeNames && lst->name) - CPrec_NamePatch(¤t->name, lst->name); - - if (lst->dexpr) - CPrec_NewPointerPatch(¤t->dexpr, CPrec_GetExpressionPatch(lst->dexpr)); - if (lst->type) - CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(lst->type)); - else - CError_FATAL(1167); - - if (!lst->next) - break; - - if ((addrPatch = CPrec_FindAddrPatch(lst->next))) { - CPrec_NewPointerPatch(¤t->next, addrPatch->value); - break; - } - - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - lst = lst->next; - CPrec_NewAddrPatch(lst, next); - } - - return first; -} - -static TypeFunc *CPrec_GetTypeFuncPatch(TypeFunc *type) { - TypeFunc *p = CPrec_AppendAlign(); - CPrec_NewAddrPatch(type, p); - - CPrec_AppendData(type, (type->flags & FUNC_METHOD) ? sizeof(TypeMemberFunc) : sizeof(TypeFunc)); - - CPrec_NewPointerPatch(&p->functype, CPrec_GetTypePatch(type->functype)); - if (type->args) - CPrec_NewPointerPatch(&p->args, CPrec_GetArgListPatch(type->args, (type->flags & FUNC_IS_TEMPL_ANY) != 0)); - if (type->exspecs) - CPrec_NewPointerPatch(&p->exspecs, CPrec_GetExceptSpecPatch(type->exspecs)); - if (type->flags & FUNC_METHOD) - CPrec_NewPointerPatch(&TYPE_METHOD(p)->theclass, CPrec_GetTypePatch((Type *) TYPE_METHOD(type)->theclass)); - - return p; -} - -static TypeMemberPointer *CPrec_GetTypeMemberPointerPatch(TypeMemberPointer *type) { - TypeMemberPointer *p = CPrec_AppendAlign(); - CPrec_NewAddrPatch(type, p); - - CPrec_AppendData(type, sizeof(TypeMemberPointer)); - - CPrec_NewPointerPatch(&p->ty1, CPrec_GetTypePatch(type->ty1)); - CPrec_NewPointerPatch(&p->ty2, CPrec_GetTypePatch(type->ty2)); - - return p; -} - -static TypeTemplDep *CPrec_GetTypeTemplDepPatch(TypeTemplDep *type) { - TypeTemplDep *p = CPrec_AppendAlign(); - CPrec_NewAddrPatch(type, p); - - CPrec_AppendData(type, sizeof(TypeTemplDep)); - - switch (type->dtype) { - case TEMPLDEP_ARGUMENT: - break; - case TEMPLDEP_QUALNAME: - CPrec_NewPointerPatch(&p->u.qual.type, CPrec_GetTypeTemplDepPatch(type->u.qual.type)); - CPrec_NamePatch(&p->u.qual.name, type->u.qual.name); - break; - case TEMPLDEP_TEMPLATE: - CPrec_NewPointerPatch(&p->u.templ.templ, CPrec_GetTypePatch((Type *) type->u.templ.templ)); - CPrec_NewPointerPatch(&p->u.templ.args, CPrec_GetTemplateArgPatch(type->u.templ.args)); - break; - case TEMPLDEP_ARRAY: - CPrec_NewPointerPatch(&p->u.array.type, CPrec_GetTypePatch(type->u.array.type)); - CPrec_NewPointerPatch(&p->u.array.index, CPrec_GetExpressionPatch(type->u.array.index)); - break; - case TEMPLDEP_QUALTEMPL: - CPrec_NewPointerPatch(&p->u.qualtempl.type, CPrec_GetTypeTemplDepPatch(type->u.qualtempl.type)); - CPrec_NewPointerPatch(&p->u.qualtempl.args, CPrec_GetTemplateArgPatch(type->u.qualtempl.args)); - break; - case TEMPLDEP_BITFIELD: - CPrec_NewPointerPatch(&p->u.bitfield.type, CPrec_GetTypePatch(type->u.bitfield.type)); - CPrec_NewPointerPatch(&p->u.bitfield.size, CPrec_GetExpressionPatch(type->u.bitfield.size)); - break; - default: - CError_FATAL(1295); - } - - return p; -} - -static ClassList *CPrec_GetClassListPatch(ClassList *cl) { - AddrPatch *addrPatch; - ClassList *first, *current, *next; - - if ((addrPatch = CPrec_FindAddrPatch(cl))) - return addrPatch->value; - - first = current = CPrec_AppendAlign(); - CPrec_NewAddrPatch(cl, first); - - do { - CPrec_AppendData(cl, sizeof(ClassList)); - CPrec_NewPointerPatch(¤t->base, CPrec_GetTypePatch((Type *) cl->base)); - - if (!cl->next) - break; - - if ((addrPatch = CPrec_FindAddrPatch(cl->next))) { - CPrec_NewPointerPatch(¤t->next, addrPatch->value); - break; - } else { - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - cl = cl->next; - } - } while (1); - - return first; -} - -static VClassList *CPrec_GetVClassListPatch(VClassList *vcl) { - VClassList *first, *current, *next; - first = current = CPrec_AppendAlign(); - - do { - CPrec_AppendData(vcl, sizeof(VClassList)); - CPrec_NewPointerPatch(¤t->base, CPrec_GetTypePatch((Type *) vcl->base)); - - if (!vcl->next) - break; - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - vcl = vcl->next; - } while (1); - - return first; -} - -static ClassFriend *CPrec_GetClassFriendPatch(ClassFriend *cf) { - ClassFriend *first, *current, *next; - first = current = CPrec_AppendAlign(); - - do { - CPrec_AppendData(cf, sizeof(ClassFriend)); - if (cf->isclass) - CPrec_NewPointerPatch(¤t->u.theclass, CPrec_GetTypePatch((Type *) cf->u.theclass)); - else - CPrec_NewPointerPatch(¤t->u.theclass, CPrec_GetObjectPatch(cf->u.obj)); - - if (!cf->next) - break; - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - cf = cf->next; - } while (1); - - return first; -} - -static BClassList *CPrec_GetBClassListPatch(BClassList *bcl) { - BClassList *first, *current, *next; - first = current = CPrec_AppendAlign(); - - do { - CPrec_AppendData(bcl, sizeof(BClassList)); - CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch((Type *) bcl->type)); - - if (!bcl->next) - break; - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - bcl = bcl->next; - } while (1); - - return first; -} - -static VTable *CPrec_GetVTablePatch(VTable *vtbl) { - VTable *p = CPrec_AppendAlign(); - CPrec_AppendData(vtbl, sizeof(VTable)); - - if (vtbl->object) - CPrec_NewPointerPatch(&p->object, CPrec_GetObjectPatch(vtbl->object)); - if (vtbl->owner) - CPrec_NewPointerPatch(&p->owner, CPrec_GetTypePatch((Type *) vtbl->owner)); - - return p; -} - -static SOMReleaseOrder *CPrec_GetSOMReleaseOrderPatch(SOMReleaseOrder *sro) { - SOMReleaseOrder *first, *current, *next; - first = current = CPrec_AppendAlign(); - - do { - CPrec_AppendData(sro, sizeof(SOMReleaseOrder)); - CPrec_NamePatch(¤t->name, sro->name); - if (!sro->next) - break; - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - sro = sro->next; - } while (1); - - return first; -} - -static SOMInfo *CPrec_GetSOMInfoPatch(SOMInfo *som) { - SOMInfo *p = CPrec_AppendAlign(); - CPrec_AppendData(som, sizeof(SOMInfo)); - - if (som->metaclass) - CPrec_NewPointerPatch(&p->metaclass, CPrec_GetTypePatch((Type *) som->metaclass)); - if (som->classdataobject) - CPrec_NewPointerPatch(&p->classdataobject, CPrec_GetObjectPatch(som->classdataobject)); - if (som->order) - CPrec_NewPointerPatch(&p->order, CPrec_GetSOMReleaseOrderPatch(som->order)); - - return p; -} - -static ObjCMethodArg *CPrec_GetObjCMethodArgPatch(ObjCMethodArg *arg) { - ObjCMethodArg *first, *current, *next; - first = current = CPrec_AppendAlign(); - - do { - CPrec_AppendData(arg, sizeof(ObjCMethod)); - if (arg->selector) - CPrec_NamePatch(¤t->selector, arg->selector); - if (arg->name) - CPrec_NamePatch(¤t->name, arg->name); - if (arg->type) - CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(arg->type)); - - if (!arg->next) - break; - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - arg = arg->next; - } while (1); - - return first; -} - -static ObjCMethodList *CPrec_GetObjCMethodListPatch(ObjCMethodList *lst) { - AddrPatch *addrPatch; - ObjCMethodList *first, *current, *next; - - if ((addrPatch = CPrec_FindAddrPatch(lst))) - return addrPatch->value; - - first = current = CPrec_AppendAlign(); - CPrec_NewAddrPatch(lst, first); - - do { - CPrec_AppendData(lst, sizeof(ObjCMethodList)); - if (lst->method) - CPrec_NewPointerPatch(¤t->method, CPrec_GetObjCMethodPatch(lst->method)); - - if (!lst->next) - break; - - if ((addrPatch = CPrec_FindAddrPatch(lst->next))) { - CPrec_NewPointerPatch(¤t->next, addrPatch->value); - break; - } else { - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - lst = lst->next; - CPrec_NewAddrPatch(lst, next); - } - } while (1); - - return first; -} - -static ObjCSelector *CPrec_GetObjCSelectorPatch(ObjCSelector *sel) { - AddrPatch *addrPatch; - ObjCSelector *current, *first, *next; - - if ((addrPatch = CPrec_FindAddrPatch(sel))) - return addrPatch->value; - - first = current = CPrec_AppendAlign(); - CPrec_NewAddrPatch(sel, first); - - do { - CPrec_AppendData(sel, sizeof(ObjCSelector)); - if (sel->selobject) - CPrec_NewPointerPatch(¤t->selobject, CPrec_GetObjectPatch(sel->selobject)); - CPrec_NamePatch(¤t->name, sel->name); - if (sel->methods) - CPrec_NewPointerPatch(¤t->methods, CPrec_GetObjCMethodListPatch(sel->methods)); - - if (!sel->next) - break; - - if ((addrPatch = CPrec_FindAddrPatch(sel->next))) { - CPrec_NewPointerPatch(¤t->next, addrPatch->value); - break; - } else { - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - sel = sel->next; - CPrec_NewAddrPatch(sel, next); - } - } while (1); - - return first; -} - -static ObjCMethod *CPrec_GetObjCMethodPatch(ObjCMethod *meth) { - // does not match - affected by weirdness where the arg goes into r31 instead of r28 - AddrPatch *addrPatch; - ObjCMethod *current, *first, *next; - - if ((addrPatch = CPrec_FindAddrPatch(meth))) - return addrPatch->value; - - first = current = CPrec_AppendAlign(); - CPrec_NewAddrPatch(meth, first); - - do { - CPrec_AppendData(meth, sizeof(ObjCMethod)); - if (meth->object) - CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(meth->object)); - if (meth->functype) - CPrec_NewPointerPatch(¤t->functype, CPrec_GetTypePatch((Type *) meth->functype)); - if (meth->selector) - CPrec_NewPointerPatch(¤t->selector, CPrec_GetObjCSelectorPatch(meth->selector)); - if (meth->return_type) - CPrec_NewPointerPatch(¤t->return_type, CPrec_GetTypePatch(meth->return_type)); - if (meth->selector_args) - CPrec_NewPointerPatch(¤t->selector_args, CPrec_GetObjCMethodArgPatch(meth->selector_args)); - - if (!meth->next) - break; - - if ((addrPatch = CPrec_FindAddrPatch(meth->next))) { - CPrec_NewPointerPatch(¤t->next, addrPatch->value); - break; - } else { - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - meth = meth->next; - CPrec_NewAddrPatch(meth, next); - } - } while (1); - - return first; -} - -static ObjCProtocol *CPrec_GetObjCProtocolPatch(ObjCProtocol *prot) { - AddrPatch *addrPatch; - ObjCProtocol *current, *first, *next; - - if ((addrPatch = CPrec_FindAddrPatch(prot))) - return addrPatch->value; - - first = current = CPrec_AppendAlign(); - CPrec_NewAddrPatch(prot, first); - - do { - CPrec_AppendData(prot, sizeof(ObjCProtocol)); - CPrec_NamePatch(¤t->name, prot->name); - if (prot->protocols) - CPrec_NewPointerPatch(¤t->protocols, CPrec_GetObjCProtocolListPatch(prot->protocols)); - if (prot->methods) - CPrec_NewPointerPatch(¤t->methods, CPrec_GetObjCMethodPatch(prot->methods)); - if (prot->object) - CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(prot->object)); - - if (!prot->next) - break; - - if ((addrPatch = CPrec_FindAddrPatch(prot->next))) { - CPrec_NewPointerPatch(¤t->next, addrPatch->value); - break; - } else { - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - prot = prot->next; - CPrec_NewAddrPatch(prot, next); - } - } while (1); - - return first; -} - -static ObjCProtocolList *CPrec_GetObjCProtocolListPatch(ObjCProtocolList *lst) { - AddrPatch *addrPatch; - ObjCProtocolList *first, *current, *next; - - if ((addrPatch = CPrec_FindAddrPatch(lst))) - return addrPatch->value; - - first = current = CPrec_AppendAlign(); - CPrec_NewAddrPatch(lst, first); - - do { - CPrec_AppendData(lst, sizeof(ObjCProtocolList)); - CPrec_NewPointerPatch(¤t->protocol, CPrec_GetObjCProtocolPatch(lst->protocol)); - - if (!lst->next) - break; - - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - lst = lst->next; - } while (1); - - return first; -} - -static ObjCCategory *CPrec_GetObjCCategoryPatch(ObjCCategory *cat) { - AddrPatch *addrPatch; - ObjCCategory *current, *first, *next; - - if ((addrPatch = CPrec_FindAddrPatch(cat))) - return addrPatch->value; - - first = current = CPrec_AppendAlign(); - CPrec_NewAddrPatch(cat, first); - - do { - CPrec_AppendData(cat, sizeof(ObjCCategory)); - CPrec_NamePatch(¤t->name, cat->name); - if (cat->protocols) - CPrec_NewPointerPatch(¤t->protocols, CPrec_GetObjCProtocolListPatch(cat->protocols)); - if (cat->methods) - CPrec_NewPointerPatch(¤t->methods, CPrec_GetObjCMethodPatch(cat->methods)); - - if (!cat->next) - break; - - if ((addrPatch = CPrec_FindAddrPatch(cat->next))) { - CPrec_NewPointerPatch(¤t->next, addrPatch->value); - break; - } else { - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - cat = cat->next; - CPrec_NewAddrPatch(cat, next); - } - } while (1); - - return first; -} - -static ObjCInfo *CPrec_GetObjCInfoPatch(ObjCInfo *info) { - ObjCInfo *p = CPrec_AppendAlign(); - CPrec_AppendData(info, sizeof(ObjCInfo)); - - if (info->classobject) - CPrec_NewPointerPatch(&p->classobject, CPrec_GetObjectPatch(info->classobject)); - if (info->metaobject) - CPrec_NewPointerPatch(&p->metaobject, CPrec_GetObjectPatch(info->metaobject)); - if (info->classrefobj) - CPrec_NewPointerPatch(&p->classrefobj, CPrec_GetObjectPatch(info->classrefobj)); - if (info->methods) - CPrec_NewPointerPatch(&p->methods, CPrec_GetObjCMethodPatch(info->methods)); - if (info->protocols) - CPrec_NewPointerPatch(&p->protocols, CPrec_GetObjCProtocolListPatch(info->protocols)); - if (info->categories) - CPrec_NewPointerPatch(&p->categories, CPrec_GetObjCCategoryPatch(info->categories)); - - return p; -} - -static TemplArg *CPrec_GetTemplateArgPatch(TemplArg *arg) { - TemplArg *first, *current, *next; - first = current = CPrec_AppendAlign(); - - do { - CPrec_AppendData(arg, sizeof(TemplArg)); - switch (arg->pid.type) { - case TPT_TYPE: - if (arg->data.typeparam.type) - CPrec_NewPointerPatch(¤t->data.typeparam.type, CPrec_GetTypePatch(arg->data.typeparam.type)); - break; - case TPT_NONTYPE: - if (arg->data.paramdecl.expr) - CPrec_NewPointerPatch(¤t->data.paramdecl.expr, CPrec_GetExpressionPatch(arg->data.paramdecl.expr)); - break; - case TPT_TEMPLATE: - if (arg->data.ttargtype) - CPrec_NewPointerPatch(¤t->data.ttargtype, CPrec_GetTypePatch(arg->data.ttargtype)); - break; - default: - CError_FATAL(1879); - } - - if (!arg->next) - break; - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - arg = arg->next; - } while (1); - - return first; -} - -static TemplParam *CPrec_GetTemplateParamPatch(TemplParam *param) { - // register swap issues - TemplParam *first, *current, *next; - first = current = CPrec_AppendAlign(); - - do { - CPrec_AppendData(param, sizeof(TemplParam)); - if (param->name) - CPrec_NamePatch(¤t->name, param->name); - - switch (param->pid.type) { - case TPT_TYPE: - if (param->data.typeparam.type) - CPrec_NewPointerPatch(¤t->data.typeparam.type, CPrec_GetTypePatch(param->data.typeparam.type)); - break; - case TPT_NONTYPE: - CPrec_NewPointerPatch(¤t->data.paramdecl.type, CPrec_GetTypePatch(param->data.paramdecl.type)); - if (param->data.paramdecl.defaultarg) - CPrec_NewPointerPatch(¤t->data.paramdecl.defaultarg, CPrec_GetExpressionPatch(param->data.paramdecl.defaultarg)); - break; - case TPT_TEMPLATE: - if (param->data.templparam.plist) - CPrec_NewPointerPatch(¤t->data.templparam.plist, CPrec_GetTemplateParamPatch(param->data.templparam.plist)); - CError_ASSERT(1953, !param->data.templparam.defaultarg); - break; - default: - CError_FATAL(1958); - } - - if (!param->next) - break; - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - param = param->next; - } while (1); - - return first; -} - -static TStreamElement *CPrec_GetTStreamPatch(TStreamElement *tokens, SInt32 count) { - TStreamElement elem; - TStreamElement *first, *current, *scan; - SInt32 x; - - scan = tokens; - x = 0; - while (x < count) { - elem = *scan; - memclrw(scan, sizeof(TStreamElement)); - - scan->tokentype = elem.tokentype; - switch (elem.tokentype) { - case TK_IDENTIFIER: - scan->data.tkidentifier = elem.data.tkidentifier; - break; - case TK_INTCONST: - scan->subtype = elem.subtype; - scan->data.tkintconst = elem.data.tkintconst; - break; - case TK_FLOATCONST: - scan->subtype = elem.subtype; - scan->data.tkfloatconst = elem.data.tkfloatconst; - break; - case TK_STRING: - case TK_STRING_WIDE: - scan->subtype = elem.subtype; - scan->data.tkstring = elem.data.tkstring; - break; - } - x++; - scan++; - } - - first = current = CPrec_AppendAlign(); - CPrec_AppendData(tokens, count * sizeof(TStreamElement)); - - if (cprec_dowrite) { - TokenPatch *tp = lalloc(sizeof(TokenPatch)); - tp->tokens = current; - tp->count = count; - tp->next = cprec_tokenpatches; - cprec_tokenpatches = tp; - } - - x = 0; - while (x < count) { - switch (tokens->tokentype) { - case TK_IDENTIFIER: - CPrec_NamePatch(¤t->data.tkidentifier, tokens->data.tkidentifier); - break; - case TK_INTCONST: - case TK_FLOATCONST: - break; - case TK_STRING: - case TK_STRING_WIDE: - CPrec_RawMemPatch(¤t->data.tkstring.data, tokens->data.tkstring.data, tokens->data.tkstring.size); - break; - case TK_EOL: - break; - default: - if (tokens->tokentype < 0) - CError_FATAL(2063); - } - x++; - tokens++; - current++; - } - - return first; -} - -static TemplFuncInstance *CPrec_GetTemplFuncInstancePatch(TemplFuncInstance *inst) { - AddrPatch *addrPatch; - TemplFuncInstance *first, *current, *next; - - if ((addrPatch = CPrec_FindAddrPatch(inst))) - return addrPatch->value; - - first = current = CPrec_AppendAlign(); - CPrec_NewAddrPatch(inst, first); - - do { - CPrec_AppendData(inst, sizeof(TemplFuncInstance)); - CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(inst->object)); - CPrec_NewPointerPatch(¤t->args, CPrec_GetTemplateArgPatch(inst->args)); - - if (!inst->next) - break; - - if ((addrPatch = CPrec_FindAddrPatch(inst->next))) { - CPrec_NewPointerPatch(¤t->next, addrPatch->value); - break; - } else { - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - inst = inst->next; - CPrec_NewAddrPatch(inst, next); - } - } while (1); - - return first; -} - -static TemplateMember *CPrec_GetTemplateMemberPatch(TemplateMember *memb) { - TemplateMember *current, *first, *next; - first = current = CPrec_AppendAlign(); - - do { - memclrw(&memb->fileoffset, sizeof(FileOffsetInfo)); - memb->srcfile = NULL; - memb->startoffset = 0; - memb->endoffset = 0; - - CPrec_AppendData(memb, sizeof(TemplateMember)); - if (memb->params) - CPrec_NewPointerPatch(¤t->params, CPrec_GetTemplateParamPatch(memb->params)); - CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(memb->object)); - if (memb->stream.firsttoken) - CPrec_NewPointerPatch(¤t->stream.firsttoken, CPrec_GetTStreamPatch(memb->stream.firsttoken, memb->stream.tokens)); - - if (!memb->next) - break; - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - memb = memb->next; - } while (1); - - return first; -} - -static TemplPartialSpec *CPrec_GetTemplPartialSpecPatch(TemplPartialSpec *pspec) { - TemplPartialSpec *first, *current, *next; - first = current = CPrec_AppendAlign(); - - do { - CPrec_AppendData(pspec, sizeof(TemplPartialSpec)); - if (pspec->templ) - CPrec_NewPointerPatch(¤t->templ, CPrec_GetTypePatch((Type *) pspec->templ)); - if (pspec->args) - CPrec_NewPointerPatch(¤t->args, CPrec_GetTemplateArgPatch(pspec->args)); - - if (!pspec->next) - break; - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - pspec = pspec->next; - } while (1); - - return first; -} - -static TemplateFriend *CPrec_GetTemplateFriendPatch(TemplateFriend *frnd) { - TemplateFriend *p; - - memclrw(&frnd->fileoffset, sizeof(FileOffsetInfo)); - p = CPrec_AppendAlign(); - CPrec_AppendData(frnd, sizeof(TemplateFriend)); - - if (frnd->decl.thetype) - CPrec_NewPointerPatch(&p->decl.thetype, CPrec_GetTypePatch(frnd->decl.thetype)); - if (frnd->decl.nspace) - CPrec_NewPointerPatch(&p->decl.nspace, CPrec_GetNameSpacePatch(frnd->decl.nspace)); - if (frnd->decl.name) - CPrec_NamePatch(&p->decl.name, frnd->decl.name); - if (frnd->decl.expltargs) - CPrec_NewPointerPatch(&p->decl.expltargs, CPrec_GetTemplateArgPatch(frnd->decl.expltargs)); - if (frnd->stream.firsttoken) - CPrec_NewPointerPatch(&p->stream.firsttoken, CPrec_GetTStreamPatch(frnd->stream.firsttoken, frnd->stream.tokens)); - - return p; -} - -static TemplateAction *CPrec_GetTemplateActionPatch(TemplateAction *act) { - // register swap issue - TemplateAction *current, *first, *next; - first = current = CPrec_AppendAlign(); - - do { - memclrw(&act->source_ref, sizeof(TStreamElement)); - CPrec_AppendData(act, sizeof(TemplateAction)); - - switch (act->type) { - case TAT_NESTEDCLASS: - CPrec_NewPointerPatch(¤t->u.tclasstype, CPrec_GetTypePatch((Type *) act->u.tclasstype)); - break; - case TAT_ENUMTYPE: - CPrec_NewPointerPatch(¤t->u.enumtype, CPrec_GetTypePatch((Type *) act->u.enumtype)); - break; - case TAT_FRIEND: - CPrec_NewPointerPatch(¤t->u.tfriend, CPrec_GetTemplateFriendPatch(act->u.tfriend)); - break; - case TAT_ENUMERATOR: - CPrec_NewPointerPatch(¤t->u.enumerator.objenumconst, CPrec_GetObjEnumConstPatch(act->u.enumerator.objenumconst)); - if (act->u.enumerator.initexpr) - CPrec_NewPointerPatch(¤t->u.enumerator.initexpr, CPrec_GetExpressionPatch(act->u.enumerator.initexpr)); - break; - case TAT_BASE: - CPrec_NewPointerPatch(¤t->u.base.type, CPrec_GetTypePatch(act->u.base.type)); - if (act->u.base.insert_after) - CPrec_NewPointerPatch(¤t->u.base.insert_after, CPrec_GetClassListPatch(act->u.base.insert_after)); - break; - case TAT_OBJECTINIT: - CPrec_NewPointerPatch(¤t->u.objectinit.object, CPrec_GetObjectPatch(act->u.objectinit.object)); - CPrec_NewPointerPatch(¤t->u.objectinit.initexpr, CPrec_GetExpressionPatch(act->u.objectinit.initexpr)); - break; - case TAT_USINGDECL: - CPrec_NewPointerPatch(¤t->u.usingdecl.type, CPrec_GetTypeTemplDepPatch(act->u.usingdecl.type)); - break; - case TAT_OBJECTDEF: - CPrec_NewPointerPatch(¤t->u.refobj, CPrec_GetObjBasePatch(act->u.refobj)); - break; - default: - CError_FATAL(2410); - } - - if (!act->next) - break; - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - act = act->next; - } while (1); - - return first; -} - -static TemplateFunction *CPrec_GetTemplateFunctionPatch(TemplateFunction *tf) { - // the same cursed register swaps - AddrPatch *addrPatch; - TemplateFunction *first, *current, *next; - - if ((addrPatch = CPrec_FindAddrPatch(tf))) - return addrPatch->value; - - first = current = CPrec_AppendAlign(); - CPrec_NewAddrPatch(tf, first); - - do { - memclrw(&tf->deftoken, sizeof(TStreamElement)); - tf->srcfile = NULL; - tf->startoffset = 0; - tf->endoffset = 0; - - CPrec_AppendData(tf, sizeof(TemplateFunction)); - if (tf->unk4) - CPrec_NewPointerPatch(¤t->unk4, CPrec_GetTemplateFunctionPatch(tf->unk4)); - CPrec_NamePatch(¤t->name, tf->name); - if (tf->params) - CPrec_NewPointerPatch(¤t->params, CPrec_GetTemplateParamPatch(tf->params)); - if (tf->stream.firsttoken) - CPrec_NewPointerPatch(¤t->stream.firsttoken, CPrec_GetTStreamPatch(tf->stream.firsttoken, tf->stream.tokens)); - CPrec_NewPointerPatch(¤t->tfunc, CPrec_GetObjectPatch(tf->tfunc)); - if (tf->instances) - CPrec_NewPointerPatch(¤t->instances, CPrec_GetTemplFuncInstancePatch(tf->instances)); - - if (!tf->next) - break; - - if ((addrPatch = CPrec_FindAddrPatch(tf->next))) { - CPrec_NewPointerPatch(¤t->next, addrPatch->value); - break; - } else { - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - tf = tf->next; - CPrec_NewAddrPatch(tf, next); - } - } while (1); - - return first; -} - -static TypeClass *CPrec_GetTypeClassPatch(TypeClass *tclass) { - TypeClass *first, *current, *next; - Boolean hasNextTempl, hasNextTemplInst; - first = current = CPrec_AppendAlign(); - - do_over: - hasNextTempl = hasNextTemplInst = 0; - CPrec_NewAddrPatch(tclass, current); - - if (tclass->flags & CLASS_IS_TEMPL) { - // template class - CPrec_AppendData(tclass, sizeof(TemplClass)); - if (TEMPL_CLASS(tclass)->next) - hasNextTempl = 1; - if (TEMPL_CLASS(tclass)->templ_parent) - CPrec_NewPointerPatch(&TEMPL_CLASS(current)->templ_parent, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->templ_parent)); - if (TEMPL_CLASS(tclass)->inst_parent) - CPrec_NewPointerPatch(&TEMPL_CLASS(current)->inst_parent, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->inst_parent)); - if (TEMPL_CLASS(tclass)->templ__params) - CPrec_NewPointerPatch(&TEMPL_CLASS(current)->templ__params, CPrec_GetTemplateParamPatch(TEMPL_CLASS(tclass)->templ__params)); - if (TEMPL_CLASS(tclass)->members) - CPrec_NewPointerPatch(&TEMPL_CLASS(current)->members, CPrec_GetTemplateMemberPatch(TEMPL_CLASS(tclass)->members)); - if (TEMPL_CLASS(tclass)->instances) - CPrec_NewPointerPatch(&TEMPL_CLASS(current)->instances, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->instances)); - if (TEMPL_CLASS(tclass)->pspec_owner) - CPrec_NewPointerPatch(&TEMPL_CLASS(current)->pspec_owner, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->pspec_owner)); - if (TEMPL_CLASS(tclass)->pspecs) - CPrec_NewPointerPatch(&TEMPL_CLASS(current)->pspecs, CPrec_GetTemplPartialSpecPatch(TEMPL_CLASS(tclass)->pspecs)); - if (TEMPL_CLASS(tclass)->actions) - CPrec_NewPointerPatch(&TEMPL_CLASS(current)->actions, CPrec_GetTemplateActionPatch(TEMPL_CLASS(tclass)->actions)); - } else if (tclass->flags & CLASS_IS_TEMPL_INST) { - // template class instance - CPrec_AppendData(tclass, sizeof(TemplClassInst)); - if (TEMPL_CLASS_INST(tclass)->next) - hasNextTemplInst = 1; - if (TEMPL_CLASS_INST(tclass)->parent) - CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->parent, CPrec_GetTypePatch((Type *) TEMPL_CLASS_INST(tclass)->parent)); - if (TEMPL_CLASS_INST(tclass)->templ) - CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->templ, CPrec_GetTypePatch((Type *) TEMPL_CLASS_INST(tclass)->templ)); - if (TEMPL_CLASS_INST(tclass)->inst_args) - CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->inst_args, CPrec_GetTemplateArgPatch(TEMPL_CLASS_INST(tclass)->inst_args)); - if (TEMPL_CLASS_INST(tclass)->oargs) - CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->oargs, CPrec_GetTemplateArgPatch(TEMPL_CLASS_INST(tclass)->oargs)); - } else { - // base - CPrec_AppendData(tclass, sizeof(TypeClass)); - } - - if (tclass->nspace) - CPrec_NewPointerPatch(¤t->nspace, CPrec_GetNameSpacePatch(tclass->nspace)); - if (tclass->classname) - CPrec_NamePatch(¤t->classname, tclass->classname); - if (tclass->bases) - CPrec_NewPointerPatch(¤t->bases, CPrec_GetClassListPatch(tclass->bases)); - if (tclass->vbases) - CPrec_NewPointerPatch(¤t->vbases, CPrec_GetVClassListPatch(tclass->vbases)); - if (tclass->ivars) - CPrec_NewPointerPatch(¤t->ivars, CPrec_GetObjMemberVarPatch(tclass->ivars)); - if (tclass->friends) - CPrec_NewPointerPatch(¤t->friends, CPrec_GetClassFriendPatch(tclass->friends)); - if (tclass->vtable) - CPrec_NewPointerPatch(¤t->vtable, CPrec_GetVTablePatch(tclass->vtable)); - if (tclass->sominfo) - CPrec_NewPointerPatch(¤t->sominfo, CPrec_GetSOMInfoPatch(tclass->sominfo)); - if (tclass->objcinfo) - CPrec_NewPointerPatch(¤t->objcinfo, CPrec_GetObjCInfoPatch(tclass->objcinfo)); - - if (hasNextTempl) { - AddrPatch *addrPatch = CPrec_FindAddrPatch(TEMPL_CLASS(tclass)->next); - if (!addrPatch) { - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(&TEMPL_CLASS(current)->next, next); - current = next; - tclass = (TypeClass *) TEMPL_CLASS(tclass)->next; - goto do_over; - } else { - CPrec_NewPointerPatch(&TEMPL_CLASS(current)->next, addrPatch->value); - } - } - - if (hasNextTemplInst) { - AddrPatch *addrPatch = CPrec_FindAddrPatch(TEMPL_CLASS_INST(tclass)->next); - if (!addrPatch) { - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->next, next); - current = next; - tclass = (TypeClass *) TEMPL_CLASS_INST(tclass)->next; - goto do_over; - } else { - CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->next, addrPatch->value); - } - } - - return first; -} - -static Type *CPrec_GetTypePatch(Type *type) { - AddrPatch *addrPatch = CPrec_FindAddrPatch(type); - if (addrPatch) - return addrPatch->value; - - switch (type->type) { - case TYPEPOINTER: - case TYPEARRAY: - return (Type *) CPrec_GetTypePointerPatch(TYPE_POINTER(type)); - case TYPEENUM: - return (Type *) CPrec_GetTypeEnumPatch(TYPE_ENUM(type)); - case TYPEBITFIELD: - return (Type *) CPrec_GetTypeBitfieldPatch(TYPE_BITFIELD(type)); - case TYPESTRUCT: - return (Type *) CPrec_GetTypeStructPatch(TYPE_STRUCT(type)); - case TYPEFUNC: - return (Type *) CPrec_GetTypeFuncPatch(TYPE_FUNC(type)); - case TYPEMEMBERPOINTER: - return (Type *) CPrec_GetTypeMemberPointerPatch(TYPE_MEMBER_POINTER(type)); - case TYPETEMPLATE: - return (Type *) CPrec_GetTypeTemplDepPatch(TYPE_TEMPLATE(type)); - case TYPECLASS: - return (Type *) CPrec_GetTypeClassPatch(TYPE_CLASS(type)); - case TYPEVOID: - case TYPEINT: - case TYPEFLOAT: - case TYPELABEL: - case TYPEOBJCID: - case TYPETEMPLDEPEXPR: - default: - CError_FATAL(2796); - return NULL; - } -} - -static ExceptionAction *CPrec_GetExceptionPatch(ExceptionAction *exc) { - ExceptionAction *first, *current, *next; - - first = current = CPrec_AppendAlign(); -repeat: - CPrec_AppendData(exc, sizeof(ExceptionAction)); - switch (exc->type) { - case EAT_DESTROYLOCAL: - CPrec_NewPointerPatch(¤t->data.destroy_local.dtor, CPrec_GetObjectPatch(exc->data.destroy_local.dtor)); - break; - case EAT_DESTROYLOCALCOND: - CPrec_NewPointerPatch(¤t->data.destroy_local_cond.dtor, CPrec_GetObjectPatch(exc->data.destroy_local_cond.dtor)); - break; - case EAT_DESTROYLOCALOFFSET: - CPrec_NewPointerPatch(¤t->data.destroy_local_offset.dtor, CPrec_GetObjectPatch(exc->data.destroy_local_offset.dtor)); - break; - case EAT_DESTROYLOCALPOINTER: - CPrec_NewPointerPatch(¤t->data.destroy_local_pointer.dtor, CPrec_GetObjectPatch(exc->data.destroy_local_pointer.dtor)); - break; - case EAT_DESTROYLOCALARRAY: - CPrec_NewPointerPatch(¤t->data.destroy_local_array.dtor, CPrec_GetObjectPatch(exc->data.destroy_local_array.dtor)); - break; - case EAT_DESTROYPARTIALARRAY: - break; - case EAT_DESTROYMEMBER: - case EAT_DESTROYBASE: - CPrec_NewPointerPatch(¤t->data.destroy_member.dtor, CPrec_GetObjectPatch(exc->data.destroy_member.dtor)); - break; - case EAT_DESTROYMEMBERCOND: - CPrec_NewPointerPatch(¤t->data.destroy_member_cond.dtor, CPrec_GetObjectPatch(exc->data.destroy_member_cond.dtor)); - break; - case EAT_DESTROYMEMBERARRAY: - CPrec_NewPointerPatch(¤t->data.destroy_member_array.dtor, CPrec_GetObjectPatch(exc->data.destroy_member_array.dtor)); - break; - case EAT_DELETEPOINTER: - case EAT_DELETELOCALPOINTER: - CPrec_NewPointerPatch(¤t->data.delete_pointer.deletefunc, CPrec_GetObjectPatch(exc->data.delete_pointer.deletefunc)); - break; - case EAT_DELETEPOINTERCOND: - CPrec_NewPointerPatch(¤t->data.delete_pointer_cond.deletefunc, CPrec_GetObjectPatch(exc->data.delete_pointer_cond.deletefunc)); - break; - case EAT_CATCHBLOCK: - if (exc->data.catch_block.catch_typeid) { - CPrec_NewPointerPatch(¤t->data.catch_block.catch_typeid, CPrec_GetObjectPatch(exc->data.catch_block.catch_typeid)); - CPrec_NewPointerPatch(¤t->data.catch_block.catch_type, CPrec_GetTypePatch(exc->data.catch_block.catch_type)); - } - break; - case EAT_ACTIVECATCHBLOCK: - break; - case EAT_SPECIFICATION: - if (exc->data.specification.unexp_id) { - int x; - char *ptrs; - ptrs = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->data.specification.unexp_id, ptrs); - CPrec_AppendData(exc->data.specification.unexp_id, sizeof(Object *) * exc->data.specification.unexp_ids); - for (x = 0; x < exc->data.specification.unexp_ids; x++) { - CPrec_NewPointerPatch(ptrs + x * sizeof(Object *), CPrec_GetObjectPatch(exc->data.specification.unexp_id[x])); - } - } - break; - case EAT_TERMINATE: - break; - default: - CError_FATAL(2905); - } - - if (exc->prev) { - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->prev, next); - current = next; - exc = exc->prev; - goto repeat; - } - return first; -} - -static ENodeList *CPrec_GetExpressionListPatch(ENodeList *lst) { - ENodeList *first, *current, *next; - first = current = CPrec_AppendAlign(); - - do { - CPrec_AppendData(lst, sizeof(ENodeList)); - CPrec_NewPointerPatch(¤t->node, CPrec_GetExpressionPatch(lst->node)); - - if (!lst->next) - break; - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - lst = lst->next; - } while (1); - - return first; -} - -static EMemberInfo *CPrec_GetEMemberInfoPatch(EMemberInfo *emember) { - EMemberInfo *p; - - CError_FATAL(2953); - - p = CPrec_AppendAlign(); - CPrec_AppendData(emember, sizeof(EMemberInfo)); - - if (emember->path) - CPrec_NewPointerPatch(&p->path, CPrec_GetClassAccessPatch(emember->path)); - if (emember->expr) - CPrec_NewPointerPatch(&p->expr, CPrec_GetExpressionPatch(emember->expr)); - CError_ASSERT(2968, !emember->templargs); - CPrec_NewPointerPatch(&p->list, CPrec_GetNameSpaceObjectListPatch(emember->list)); - - return p; -} - -static ENode *CPrec_GetExpressionPatch(ENode *expr) { - ENode *p; - - if (ENODE_IS(expr, ETEMPLDEP) && expr->data.templdep.subtype == TDE_SOURCEREF) - expr->data.templdep.u.sourceref.token = NULL; - - p = CPrec_AppendAlign(); - CPrec_AppendData(expr, sizeof(ENode)); - - CPrec_NewPointerPatch(&p->rtype, CPrec_GetTypePatch(expr->rtype)); - - switch (expr->type) { - ENODE_CASE_MONADIC: - CPrec_NewPointerPatch(&p->data.monadic, CPrec_GetExpressionPatch(expr->data.monadic)); - break; - ENODE_CASE_DIADIC_ALL: - CPrec_NewPointerPatch(&p->data.diadic.left, CPrec_GetExpressionPatch(expr->data.diadic.left)); - CPrec_NewPointerPatch(&p->data.diadic.right, CPrec_GetExpressionPatch(expr->data.diadic.right)); - break; - case ECOND: - CPrec_NewPointerPatch(&p->data.cond.cond, CPrec_GetExpressionPatch(expr->data.cond.cond)); - CPrec_NewPointerPatch(&p->data.cond.expr1, CPrec_GetExpressionPatch(expr->data.cond.expr1)); - CPrec_NewPointerPatch(&p->data.cond.expr2, CPrec_GetExpressionPatch(expr->data.cond.expr2)); - break; - case ESTRINGCONST: - CPrec_RawMemPatch(&p->data.string.data, expr->data.string.data, expr->data.string.size); - break; - case EOBJREF: - CPrec_NewPointerPatch(&p->data.objref, CPrec_GetObjectPatch(expr->data.objref)); - break; - case EOBJLIST: - CPrec_NewPointerPatch(&p->data.objlist.list, CPrec_GetNameSpaceObjectListPatch(expr->data.objlist.list)); - CError_ASSERT(3043, !expr->data.objlist.templargs); - if (expr->data.objlist.name) - CPrec_NamePatch(&p->data.objlist.name, expr->data.objlist.name); - break; - case EMFPOINTER: - CPrec_NewPointerPatch(&p->data.mfpointer.accessnode, CPrec_GetExpressionPatch(expr->data.mfpointer.accessnode)); - CPrec_NewPointerPatch(&p->data.mfpointer.mfpointer, CPrec_GetExpressionPatch(expr->data.mfpointer.mfpointer)); - break; - case ENULLCHECK: - CPrec_NewPointerPatch(&p->data.nullcheck.nullcheckexpr, CPrec_GetExpressionPatch(expr->data.nullcheck.nullcheckexpr)); - CPrec_NewPointerPatch(&p->data.nullcheck.condexpr, CPrec_GetExpressionPatch(expr->data.nullcheck.condexpr)); - break; - case ETEMP: - CPrec_NewPointerPatch(&p->data.temp.type, CPrec_GetTypePatch(expr->data.temp.type)); - break; - case EFUNCCALL: - case EFUNCCALLP: - CPrec_NewPointerPatch(&p->data.funccall.funcref, CPrec_GetExpressionPatch(expr->data.funccall.funcref)); - CPrec_NewPointerPatch(&p->data.funccall.functype, CPrec_GetTypePatch(TYPE(expr->data.funccall.functype))); - if (expr->data.funccall.args) - CPrec_NewPointerPatch(&p->data.funccall.args, CPrec_GetExpressionListPatch(expr->data.funccall.args)); - break; - case EMEMBER: - CPrec_NewPointerPatch(&p->data.emember, CPrec_GetEMemberInfoPatch(expr->data.emember)); - break; - case ETEMPLDEP: - switch (expr->data.templdep.subtype) { - case TDE_PARAM: - break; - case TDE_SIZEOF: - case TDE_ALIGNOF: - CPrec_NewPointerPatch(&p->data.templdep.u.typeexpr.type, CPrec_GetTypePatch(expr->data.templdep.u.typeexpr.type)); - break; - case TDE_CAST: - if (expr->data.templdep.u.cast.args) - CPrec_NewPointerPatch(&p->data.templdep.u.cast.args, CPrec_GetExpressionListPatch(expr->data.templdep.u.cast.args)); - CPrec_NewPointerPatch(&p->data.templdep.u.cast.type, CPrec_GetTypePatch(expr->data.templdep.u.cast.type)); - break; - case TDE_QUALNAME: - CPrec_NamePatch(&p->data.templdep.u.qual.name, expr->data.templdep.u.qual.name); - CPrec_NewPointerPatch(&p->data.templdep.u.qual.type, CPrec_GetTypePatch(TYPE(expr->data.templdep.u.qual.type))); - break; - case TDE_OBJ: - CPrec_NewPointerPatch(&p->data.templdep.u.obj, CPrec_GetObjectPatch(expr->data.templdep.u.obj)); - break; - case TDE_SOURCEREF: - CPrec_NewPointerPatch(&p->data.templdep.u.sourceref.expr, CPrec_GetExpressionPatch(expr->data.templdep.u.sourceref.expr)); - break; - case TDE_ADDRESS_OF: - CPrec_NewPointerPatch(&p->data.templdep.u.monadic, CPrec_GetExpressionPatch(expr->data.templdep.u.monadic)); - break; - default: - CError_FATAL(3136); - } - break; - case EINTCONST: - case EFLOATCONST: - case EPRECOMP: - case EARGOBJ: - case ELOCOBJ: - case ELABEL: - case EINSTRUCTION: - case EVECTOR128CONST: - break; - default: - CError_FATAL(3142); - } - - return p; -} - -static CI_Switch *CPrec_GetSwitchInfoPatch(CI_Switch *si) { - CI_Switch *p = CPrec_AppendAlign(); - CPrec_AppendData(si, sizeof(CI_Switch) + sizeof(CI_SwitchCase) * (si->numcases - 1)); - - CPrec_NewPointerPatch(&p->expr, CPrec_GetExpressionPatch(si->expr)); - CPrec_NewPointerPatch(&p->unkSwitch8, CPrec_GetTypePatch(si->unkSwitch8)); - return p; -} - -static InlineAsm *CPrec_GetInlineAsmPatch(InlineAsm *ia, SInt32 size) { - InlineAsm *p; - SInt32 index; - SInt32 offset; - Object *object; - - p = CPrec_AppendAlign(); - CPrec_AppendData(ia, size); - - index = 0; - while (1) { - object = InlineAsm_GetObjectOffset(ia, index, &offset); - if (!object) - break; - - object = CPrec_GetObjectPatch(object); - CPrec_NewPointerPatch((char *) p + offset, object); - index++; - } - - return p; -} - -static CI_Statement *CPrec_GetStatementPatch(CI_Statement *stmt, short count) { - short i; - CI_Statement *first, *current; - - for (i = 0; i < count; i++) { - stmt[i].sourcefilepath = NULL; - stmt[i].sourceoffset = -1; - } - - first = current = CPrec_AppendAlign(); - CPrec_AppendData(stmt, sizeof(CI_Statement) * count); - - for (i = 0; i < count; i++) { - if (stmt->dobjstack) - CPrec_NewPointerPatch(¤t->dobjstack, CPrec_GetExceptionPatch(stmt->dobjstack)); - - switch (stmt->type) { - case ST_EXPRESSION: - case ST_RETURN: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - if (stmt->u.expr) - CPrec_NewPointerPatch(¤t->u.expr, CPrec_GetExpressionPatch(stmt->u.expr)); - break; - case ST_IFGOTO: - case ST_IFNGOTO: - CPrec_NewPointerPatch(¤t->u.ifgoto.expr, CPrec_GetExpressionPatch(stmt->u.ifgoto.expr)); - break; - case ST_SWITCH: - CPrec_NewPointerPatch(¤t->u.switchdata, CPrec_GetSwitchInfoPatch(stmt->u.switchdata)); - break; - case ST_ASM: - CPrec_NewPointerPatch(¤t->u.asmdata.data, CPrec_GetInlineAsmPatch(stmt->u.asmdata.data, stmt->u.asmdata.size)); - break; - case ST_NOP: - case ST_LABEL: - case ST_GOTO: - break; - default: - CError_FATAL(3261); - } - - current++; - stmt++; - } - - return first; -} - -static CI_Var *CPrec_GetLocObjectPatch(CI_Var *obj, short count) { - CI_Var *first, *current; - short i; - - first = current = CPrec_AppendAlign(); - CPrec_AppendData(obj, sizeof(CI_Var) * count); - - for (i = 0; i < count; i++) { - CPrec_NamePatch(¤t->name, obj->name); - CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(obj->type)); - current++; - obj++; - } - - return first; -} - -static CI_FuncData *CPrec_GetInlineFuncPatch(CI_FuncData *ifunc) { - CI_FuncData *p; - - memclrw(&ifunc->fileoffset, sizeof(FileOffsetInfo)); - ifunc->symdecloffset = 0; - ifunc->functionbodyoffset = 0; - ifunc->functionbodypath = NULL; - ifunc->symdeclend = 0; - - p = CPrec_AppendAlign(); - CPrec_AppendData(ifunc, sizeof(CI_FuncData)); - - if (ifunc->numarguments) - CPrec_NewPointerPatch(&p->arguments, CPrec_GetLocObjectPatch(ifunc->arguments, ifunc->numarguments)); - if (ifunc->numlocals) - CPrec_NewPointerPatch(&p->locals, CPrec_GetLocObjectPatch(ifunc->locals, ifunc->numlocals)); - if (ifunc->numstatements) - CPrec_NewPointerPatch(&p->statements, CPrec_GetStatementPatch(ifunc->statements, ifunc->numstatements)); - - return p; -} - -static ObjEnumConst *CPrec_GetObjEnumConstPatch(ObjEnumConst *obj) { - AddrPatch *addrPatch; - ObjEnumConst *first, *current, *next; - - if ((addrPatch = CPrec_FindAddrPatch(obj))) - return addrPatch->value; - - first = current = CPrec_AppendAlign(); - CPrec_NewAddrPatch(obj, first); - - do { - CPrec_AppendData(obj, sizeof(ObjEnumConst)); - if (cprec_dowrite) { - CError_ASSERT(3349, obj->access != 255); - obj->access = 255; - } - CPrec_NamePatch(¤t->name, obj->name); - CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch( obj->type)); - - if (!obj->next) - break; - - if ((addrPatch = CPrec_FindAddrPatch(obj->next))) { - CPrec_NewPointerPatch(¤t->next, addrPatch->value); - break; - } else { - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - obj = obj->next; - CPrec_NewAddrPatch(obj, next); - } - } while (1); - - return first; -} - -static ObjType *CPrec_GetObjTypePatch(ObjType *obj) { - AddrPatch *addrPatch; - ObjType *p; - - if ((addrPatch = CPrec_FindAddrPatch(obj))) - return addrPatch->value; - - p = CPrec_AppendAlign(); - CPrec_NewAddrPatch(obj, p); - CPrec_AppendData(obj, sizeof(ObjType)); - CPrec_NewPointerPatch(&p->type, CPrec_GetTypePatch(obj->type)); - return p; -} - -static ObjTypeTag *CPrec_GetObjTypeTagPatch(ObjTypeTag *obj) { - AddrPatch *addrPatch; - ObjTypeTag *p; - - if ((addrPatch = CPrec_FindAddrPatch(obj))) - return addrPatch->value; - - p = CPrec_AppendAlign(); - CPrec_NewAddrPatch(obj, p); - CPrec_AppendData(obj, sizeof(ObjTypeTag)); - CPrec_NewPointerPatch(&p->type, CPrec_GetTypePatch(obj->type)); - return p; -} - -static ObjNameSpace *CPrec_GetObjNameSpacePatch(ObjNameSpace *obj) { - AddrPatch *addrPatch; - ObjNameSpace *p; - - if ((addrPatch = CPrec_FindAddrPatch(obj))) - return addrPatch->value; - - p = CPrec_AppendAlign(); - CPrec_NewAddrPatch(obj, p); - CPrec_AppendData(obj, sizeof(ObjNameSpace)); - CPrec_NewPointerPatch(&p->nspace, CPrec_GetNameSpacePatch(obj->nspace)); - return p; -} - -static ObjMemberVar *CPrec_GetObjMemberVarPatch(ObjMemberVar *ivar) { - AddrPatch *addrPatch; - ObjMemberVar *first, *current, *next; - - if ((addrPatch = CPrec_FindAddrPatch(ivar))) - return addrPatch->value; - - first = current = CPrec_AppendAlign(); - CPrec_NewAddrPatch(ivar, first); - - while (1) { - if (ivar->has_path) { - CPrec_AppendData(ivar, sizeof(ObjMemberVarPath)); - if (OBJ_MEMBER_VAR_PATH(ivar)->path) - CPrec_NewPointerPatch( - &OBJ_MEMBER_VAR_PATH(current)->path, - CPrec_GetClassAccessPatch(OBJ_MEMBER_VAR_PATH(ivar)->path)); - } else { - CPrec_AppendData(ivar, sizeof(ObjMemberVar)); - } - - if (ivar->name) - CPrec_NamePatch(¤t->name, ivar->name); - CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(ivar->type)); - - if (!ivar->next) - break; - - if ((addrPatch = CPrec_FindAddrPatch(ivar->next))) { - CPrec_NewPointerPatch(¤t->next, addrPatch->value); - break; - } - - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - - current = next; - ivar = ivar->next; - CPrec_NewAddrPatch(ivar, current); - } - - return first; -} - -static DefArgCtorInfo *CPrec_GetDefArgCtorInfoPatch(DefArgCtorInfo *dac) { - DefArgCtorInfo *p = CPrec_AppendAlign(); - CPrec_AppendData(dac, sizeof(DefArgCtorInfo)); - CPrec_NewPointerPatch(&p->default_func, CPrec_GetObjectPatch(dac->default_func)); - CPrec_NewPointerPatch(&p->default_arg, CPrec_GetExpressionPatch(dac->default_arg)); - return p; -} - -static InlineXRef *CPrec_GetInlineXRefPatch(InlineXRef *ix) { - InlineXRef *first, *current, *next; - first = current = CPrec_AppendAlign(); - - do { - CPrec_AppendData(ix, sizeof(InlineXRef) + sizeof(XRefOffset) * (ix->numxrefs - 1)); - CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(ix->object)); - - if (!ix->next) - break; - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - ix = ix->next; - } while (1); - - return first; -} - -static Object *CPrec_GetObjectPatch(Object *obj) { - AddrPatch *addrPatch; - Object *p; - - if (CWUserBreak(cparams.context) != cwNoErr) - CError_UserBreak(); - - if ((addrPatch = CPrec_FindAddrPatch(obj))) - return addrPatch->value; - - p = CPrec_AppendAlign(); - CPrec_NewAddrPatch(obj, p); - - obj->toc = NULL; - - if ((obj->qual & Q_IS_TEMPLATED) && obj->datatype != DALIAS) { - CPrec_AppendData(obj, sizeof(ObjectTemplated)); - CPrec_NewPointerPatch(&OBJECT_TEMPL(p)->parent, CPrec_GetObjectPatch(OBJECT_TEMPL(obj)->parent)); - } else { - CPrec_AppendData(obj, sizeof(Object)); - } - - if (obj->nspace) - CPrec_NewPointerPatch(&p->nspace, CPrec_GetNameSpacePatch(obj->nspace)); - if (obj->name) - CPrec_NamePatch(&p->name, obj->name); - CPrec_NewPointerPatch(&p->type, CPrec_GetTypePatch(obj->type)); - - switch (obj->datatype) { - case DABSOLUTE: - break; - - case DLOCAL: - CError_FATAL(3580); - break; - - case DFUNC: - case DVFUNC: - if (IS_TEMPL_FUNC(obj->type)) - CPrec_NewPointerPatch(&p->u.func.u.templ, CPrec_GetTemplateFunctionPatch(obj->u.func.u.templ)); - else if ((obj->qual & Q_INLINE) && obj->u.func.u.ifuncdata) - CPrec_NewPointerPatch(&p->u.func.u.ifuncdata, CPrec_GetInlineFuncPatch(obj->u.func.u.ifuncdata)); - - if (obj->u.func.defargdata) - CPrec_NewPointerPatch(&p->u.func.defargdata, CPrec_GetDefArgCtorInfoPatch(obj->u.func.defargdata)); - if (obj->u.func.linkname) - CPrec_NamePatch(&p->u.func.linkname, obj->u.func.linkname); - if (obj->u.func.inst) - CPrec_NewPointerPatch(&p->u.func.inst, CPrec_GetTemplFuncInstancePatch(obj->u.func.inst)); - break; - - case DDATA: - CError_ASSERT(3622, !obj->u.data.info); - if (obj->qual & Q_INLINE_DATA) { - switch (obj->type->type) { - case TYPEINT: - case TYPEENUM: - case TYPEPOINTER: - break; - case TYPEFLOAT: - CPrec_RawMemPatch(&p->u.data.u.floatconst, obj->u.data.u.floatconst, sizeof(Float)); - break; - default: - CError_FATAL(3638); - } - } - if (obj->u.data.linkname) - CPrec_NamePatch(&p->u.data.linkname, obj->u.data.linkname); - break; - - case DINLINEFUNC: - CPrec_RawMemPatch(&p->u.ifunc.data, obj->u.ifunc.data, obj->u.ifunc.size); - if (obj->u.ifunc.xrefs) - CPrec_NewPointerPatch(&p->u.ifunc.xrefs, CPrec_GetInlineXRefPatch(obj->u.ifunc.xrefs)); - break; - - case DALIAS: - CPrec_NewPointerPatch(&p->u.alias.object, CPrec_GetObjectPatch(obj->u.alias.object)); - if (obj->u.alias.member) - CPrec_NewPointerPatch(&p->u.alias.member, CPrec_GetClassAccessPatch(obj->u.alias.member)); - break; - - default: - CError_FATAL(3677); - } - - if (cprec_dowrite) - obj->datatype = -1; - - return p; -} - -static ObjBase *CPrec_GetObjBasePatch(ObjBase *obj) { - switch (obj->otype) { - default: - CError_FATAL(3694); - case OT_ENUMCONST: - return (ObjBase *) CPrec_GetObjEnumConstPatch((ObjEnumConst *) obj); - case OT_TYPE: - return (ObjBase *) CPrec_GetObjTypePatch((ObjType *) obj); - case OT_TYPETAG: - return (ObjBase *) CPrec_GetObjTypeTagPatch((ObjTypeTag *) obj); - case OT_NAMESPACE: - return (ObjBase *) CPrec_GetObjNameSpacePatch((ObjNameSpace *) obj); - case OT_MEMBERVAR: - return (ObjBase *) CPrec_GetObjMemberVarPatch((ObjMemberVar *) obj); - case OT_OBJECT: - return (ObjBase *) CPrec_GetObjectPatch((Object *) obj); - } -} - -static ObjectList *CPrec_GetObjectListPatch(ObjectList *ol) { - AddrPatch *addrPatch; - ObjectList *first, *current, *next; - - if ((addrPatch = CPrec_FindAddrPatch(ol))) - return addrPatch->value; - - first = current = CPrec_AppendAlign(); - CPrec_NewAddrPatch(ol, first); -restart: - CPrec_AppendData(ol, sizeof(ObjectList)); - CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(ol->object)); - if (ol->next) { - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - ol = ol->next; - goto restart; - } - - return first; -} - -static NameSpaceObjectList *CPrec_GetNameSpaceObjectListPatch(NameSpaceObjectList *nsol) { - AddrPatch *addrPatch; - NameSpaceObjectList *first, *current, *next; - - if ((addrPatch = CPrec_FindAddrPatch(nsol))) - return addrPatch->value; - - first = current = CPrec_AppendAlign(); - CPrec_NewAddrPatch(nsol, first); - - do { - CPrec_AppendData(nsol, sizeof(NameSpaceObjectList)); - CPrec_NewPointerPatch(¤t->object, CPrec_GetObjBasePatch(nsol->object)); - - if (!nsol->next) - break; - - if ((addrPatch = CPrec_FindAddrPatch(nsol->next))) { - CPrec_NewPointerPatch(¤t->next, addrPatch->value); - break; - } else { - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - nsol = nsol->next; - CPrec_NewAddrPatch(nsol, next); - } - } while (1); - - return first; -} - -static NameSpaceName *CPrec_GetNameSpaceNamePatch(NameSpaceName *nsn, Boolean flag) { - AddrPatch *addrPatch; - NameSpaceName *first, *current, *next; - - if ((addrPatch = CPrec_FindAddrPatch(nsn))) - return addrPatch->value; - - first = current = CPrec_AppendAlign(); - CPrec_NewAddrPatch(nsn, first); - - do { - CPrec_AppendData(nsn, sizeof(NameSpaceName)); - CPrec_NamePatch(¤t->name, nsn->name); - CPrec_NewPointerPatch(¤t->first.object, CPrec_GetObjBasePatch(nsn->first.object)); - if (nsn->first.next) - CPrec_NewPointerPatch(¤t->first.next, CPrec_GetNameSpaceObjectListPatch(nsn->first.next)); - - if (!nsn->next) - break; - - if ((addrPatch = CPrec_FindAddrPatch(nsn->next))) { - CPrec_NewPointerPatch(¤t->next, addrPatch->value); - break; - } else { - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - nsn = nsn->next; - CPrec_NewAddrPatch(nsn, next); - } - } while (!flag || !cprec_dowrite || CPrec_FlushBufferCheck() == noErr); - - return first; -} - -static NameSpaceList *CPrec_GetNameSpaceListPatch(NameSpaceList *nsl) { - NameSpaceList *first, *current, *next; - first = current = CPrec_AppendAlign(); - - do { - CPrec_AppendData(nsl, sizeof(NameSpaceList)); - CPrec_NewPointerPatch(¤t->nspace, CPrec_GetNameSpacePatch(nsl->nspace)); - - if (!nsl->next) - break; - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - nsl = nsl->next; - } while (1); - - return first; -} - -static NameSpace *CPrec_GetNameSpacePatch(NameSpace *nspace) { - NameSpace *p; - AddrPatch *addrPatch; - - if ((addrPatch = CPrec_FindAddrPatch(nspace))) - return addrPatch->value; - - p = CPrec_AppendAlign(); - CPrec_NewAddrPatch(nspace, p); - CPrec_AppendData(nspace, sizeof(NameSpace)); - - if (nspace->parent) - CPrec_NewPointerPatch(&p->parent, CPrec_GetNameSpacePatch(nspace->parent)); - if (nspace->name) - CPrec_NamePatch(&p->name, nspace->name); - if (nspace->usings) - CPrec_NewPointerPatch(&p->usings, CPrec_GetNameSpaceListPatch(nspace->usings)); - if (nspace->theclass) - CPrec_NewPointerPatch(&p->theclass, CPrec_GetTypePatch((Type *) nspace->theclass)); - - if (nspace->is_hash) { - char *hash; - int i; - hash = CPrec_AppendAlign(); - CPrec_NewPointerPatch(&p->data.hash, hash); - CPrec_AppendData(nspace->data.hash, sizeof(NameSpaceName *) * 1024); - for (i = 0; i < 1024; i++) { - if (nspace->data.hash[i]) - CPrec_NewPointerPatch(hash + (i * sizeof(NameSpaceName *)), CPrec_GetNameSpaceNamePatch(nspace->data.hash[i], 0)); - } - } else if (nspace->data.list) { - CPrec_NewPointerPatch(&p->data.list, CPrec_GetNameSpaceNamePatch(nspace->data.list, 0)); - } - - return p; -} - -static void CPrec_DumpRootNameSpace(void) { - NameSpaceList *nslist; - NameSpaceName *nsname; - int i; - - CError_ASSERT(3905, cscope_root->is_hash); - - if (cscope_root->usings) { - nslist = CPrec_GetNameSpaceListPatch(cscope_root->usings); - if (cprec_dowrite) - cprec_header->usings = nslist; - } - - if (cprec_dowrite) - cprec_header->root_names = cscope_root->names; - - i = 0; - do { - if (cscope_root->data.hash[i]) { - nsname = CPrec_GetNameSpaceNamePatch(cscope_root->data.hash[i], 1); - if (cprec_dowrite) { - if (cprec_ioerror != noErr) - break; - cprec_header->root_nametable[i] = nsname; - } - } - } while (++i < 0x400); -} - -static CSOMStub *CPrec_GetSOMPatch(CSOMStub *stub) { - CSOMStub *first, *current, *next; - - first = current = CPrec_AppendAlign(); - while (1) { - CPrec_AppendData(stub, sizeof(CSOMStub)); - - CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(stub->object)); - CPrec_NewPointerPatch(¤t->tclass, CPrec_GetTypePatch(TYPE(stub->tclass))); - - if (!stub->next) - break; - - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - stub = stub->next; - } - - return first; -} - -static OLinkList *CPrec_GetOLinkPatch(OLinkList *olink) { - OLinkList *first, *current, *next; - - first = current = CPrec_AppendAlign(); - while (1) { - CPrec_AppendData(olink, sizeof(OLinkList)); - - CPrec_NewPointerPatch(¤t->obj, CPrec_GetObjectPatch(olink->obj)); - - if (!olink->next) - break; - - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - olink = olink->next; - } - - return first; -} - -static StaticData *CPrec_GetStaticDataPatch(StaticData *sd) { - StaticData *current, *first, *next; - - first = current = CPrec_AppendAlign(); - while (1) { - CPrec_AppendData(sd, sizeof(StaticData)); - - CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(sd->object)); - if (sd->buffer) - CPrec_RawMemPatch(¤t->buffer, sd->buffer, sd->object->type->size); - if (sd->links) - CPrec_NewPointerPatch(¤t->links, CPrec_GetOLinkPatch(sd->links)); - - if (!sd->next) - break; - - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - sd = sd->next; - } - - return first; -} - -static CallbackAction *CPrec_GetCallbackPatch(CallbackAction *ca) { - CallbackAction *first, *current, *next; - - first = current = CPrec_AppendAlign(); - while (1) { - CPrec_AppendData(ca, sizeof(CallbackAction)); - - CPrec_NewPointerPatch(¤t->obj, CPrec_GetObjectPatch(ca->obj)); - CPrec_NewPointerPatch(¤t->tclass, CPrec_GetTypePatch(TYPE(ca->tclass))); - - if (!ca->next) - break; - - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - ca = ca->next; - } - - return first; -} - -static ObjCSelector **CPrec_GetSelHashTablePatch(ObjCSelector **table) { - ObjCSelector **first, **current; - int i; - - first = current = CPrec_AppendAlign(); - CPrec_AppendData(table, sizeof(ObjCSelector *) * 0x400); - - for (i = 0; i < 0x400; i++) { - if (*table) - CPrec_NewPointerPatch(current, CPrec_GetObjCSelectorPatch(*table)); - table++; - current++; - } - - return first; -} - -static InitExpr *CPrec_GetIExpressionPatch(InitExpr *initexpr) { - InitExpr *first, *current, *next; - - first = current = CPrec_AppendAlign(); - while (1) { - CPrec_AppendData(initexpr, sizeof(InitExpr)); - - CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(initexpr->object)); - CPrec_NewPointerPatch(¤t->expr, CPrec_GetExpressionPatch(initexpr->expr)); - - if (!initexpr->next) - break; - - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - initexpr = initexpr->next; - } - - return first; -} - -static CI_Action *CPrec_GetInlineActionPatch(CI_Action *act) { - CI_Action *current, *first, *next; - - first = current = CPrec_AppendAlign(); - while (1) { - if (act->actiontype == CI_ActionInlineFunc) - memclrw(&act->u.inlinefunc.fileoffset, sizeof(FileOffsetInfo)); - - CPrec_AppendData(act, sizeof(CI_Action)); - - CPrec_NewPointerPatch(¤t->obj, CPrec_GetObjectPatch(act->obj)); - - switch (act->actiontype) { - case CI_ActionInlineFunc: - if (act->u.inlinefunc.stream.firsttoken) - CPrec_NewPointerPatch( - ¤t->u.inlinefunc.stream.firsttoken, - CPrec_GetTStreamPatch(act->u.inlinefunc.stream.firsttoken, act->u.inlinefunc.stream.tokens)); - if (act->u.inlinefunc.tclass) - CPrec_NewPointerPatch(¤t->u.inlinefunc.tclass, CPrec_GetTypePatch(TYPE(act->u.inlinefunc.tclass))); - break; - - case CI_ActionMemberFunc: - CPrec_NewPointerPatch(¤t->u.memberfunc.templ, CPrec_GetTypePatch(TYPE(act->u.memberfunc.templ))); - CPrec_NewPointerPatch(¤t->u.memberfunc.inst, CPrec_GetTypePatch(TYPE(act->u.memberfunc.inst))); - CPrec_NewPointerPatch(¤t->u.memberfunc.tmemb, CPrec_GetTemplateMemberPatch(act->u.memberfunc.tmemb)); - break; - - case CI_ActionTemplateFunc: - CPrec_NewPointerPatch(¤t->u.templatefunc.func, CPrec_GetTemplateFunctionPatch(act->u.templatefunc.func)); - CPrec_NewPointerPatch(¤t->u.templatefunc.inst, CPrec_GetTemplFuncInstancePatch(act->u.templatefunc.inst)); - break; - - case CI_ActionDefaultFunc: - break; - - default: - CError_FATAL(4177); - } - - if (!act->next) - break; - - next = CPrec_AppendAlign(); - CPrec_NewPointerPatch(¤t->next, next); - current = next; - act = act->next; - } - - return first; -} - -static void CPrec_GenerateBuiltinPatches(void) { - int x; - int y; - Patch *scan; - - for (x = 0; x < cprec_builtins; x++) { - y = 0; - for (scan = cprec_builtin[x].patches; scan; scan = scan->next) - ++y; - - if (y) { - CPrec_AppendWord32(y); - CPrec_AppendWord32(x); - for (scan = cprec_builtin[x].patches; scan; scan = scan->next) - CPrec_AppendWord32(scan->offset); - } - } - - CPrec_AppendWord32(0); -} - -static void CPrec_GenerateTokenStreamPatches(void) { - TokenPatch *scan; - - for (scan = cprec_tokenpatches; scan; scan = scan->next) { - CPrec_AppendWord32((UInt32) scan->tokens); - CPrec_AppendWord32((UInt32) scan->count); - } - CPrec_AppendWord32(0); -} - -static OSErr CPrec_CompressWrite(const char *data, SInt32 size) { - char buf[2048 + 256]; - OSErr err; - int bufpos = 0; - int blockstart; - int c; - const char *p = data; - const char *end = data + size; - - for (;;) { - if (p < end) { - if (!*p) { - c = 224; - while (!*p && p < end && c < 256) { - c++; - p++; - } - buf[bufpos++] = c - 1; - } else { - blockstart = bufpos++; - c = 0; - while (p < end && c < 224) { - if (!p[0] && !p[1]) { - break; - } else { - buf[bufpos++] = *(p++); - c++; - } - } - buf[blockstart] = c - 1; - } - } - - if (p >= end || bufpos > 2048) { - if ((err = COS_FileWrite(cprec_refnum, buf, bufpos))) - return err; - - if (p >= end) - break; - else - bufpos = 0; - } - } - - return noErr; -} - -static OSErr CPrec_FlushRawBuffer(void) { - OSErr err; - - if (cprec_dowrite) { - CPrec_AppendAlign(); - cprec_zero_offset += cprec_glist.size; - COS_LockHandle(cprec_glist.data); - err = CPrec_CompressWrite(*cprec_glist.data, cprec_glist.size); - COS_UnlockHandle(cprec_glist.data); - cprec_glist.size = 0; - - return err; - } else { - return noErr; - } -} - -static OSErr CPrec_FlushBufferCheck(void) { - static SInt32 flushmax; - OSErr err; - - if (cprec_glist.size > flushmax) - flushmax = cprec_glist.size; - - if (cprec_glist.size > 10000) { - err = CPrec_FlushRawBuffer(); - if (err) { - cprec_ioerror = err; - return err; - } - } - - return noErr; -} - -static int CPrec_CompressPatches(void) { - Patch *scan; - int count; - SInt32 last; - - cprec_glist.size = 0; - - scan = cprec_patch_list; - last = 0; - count = 0; - while (scan) { - CError_ASSERT(4339, (scan->offset & 0x80000001) == 0); - - if ((scan->offset - last) >= -128 && (scan->offset - last) <= 126) - CPrec_AppendByte(((scan->offset - last) >> 1) | 0x80); - else - CPrec_AppendWord32(scan->offset); - - last = scan->offset; - scan = scan->next; - count++; - } - - return count; -} - -static OSErr CPrec_DumpColorSymbolTable(Boolean doWrite) { - OSErr err; - - freelheap(); - - CPrec_InitAddressHashTable(); - CPrec_InitPointerHashTable(); - - cprec_patch_list = NULL; - cprec_tokenpatches = NULL; - cprec_offset = 0; - cprec_zero_offset = 0; - cprec_dowrite = doWrite; - cprec_ioerror = noErr; - - CPrec_SetupBuiltIn(); - CPrec_AppendWord32(0); - - CPrec_DumpNameTable(); - if ((err = CPrec_FlushRawBuffer()) != noErr) - return err; - - CPrec_DumpMacroTable(); - if ((err = CPrec_FlushRawBuffer()) != noErr) - return err; - - CPrec_DumpRootNameSpace(); - if (doWrite) { - if (cprec_ioerror != noErr) - return cprec_ioerror; - if ((err = CPrec_FlushRawBuffer()) != noErr) - return err; - } - - if (ctempl_templates) { - TemplClass *p = TEMPL_CLASS(CPrec_GetTypePatch(TYPE(ctempl_templates))); - if (doWrite) - cprec_header->ctempl_templates = p; - if ((err = CPrec_FlushRawBuffer()) != noErr) - return err; - } - - if (ctempl_templatefuncs) { - TemplateFunction *p = CPrec_GetTemplateFunctionPatch(ctempl_templatefuncs); - if (doWrite) - cprec_header->ctempl_templatefuncs = p; - if ((err = CPrec_FlushRawBuffer()) != noErr) - return err; - } - - if (csom_stubs) { - CSOMStub *p = CPrec_GetSOMPatch(csom_stubs); - if (doWrite) - cprec_header->csom_stubs = p; - if ((err = CPrec_FlushRawBuffer()) != noErr) - return err; - } - - if (cprec_staticdata) { - StaticData *p = CPrec_GetStaticDataPatch(cprec_staticdata); - if (doWrite) - cprec_header->cprec_staticdata = p; - if ((err = CPrec_FlushRawBuffer()) != noErr) - return err; - } - - if (callbackactions) { - CallbackAction *p = CPrec_GetCallbackPatch(callbackactions); - if (doWrite) - cprec_header->callbackactions = p; - if ((err = CPrec_FlushRawBuffer()) != noErr) - return err; - } - - if (cobjc_type_class) { - Type *p = CPrec_GetTypePatch(cobjc_type_class); - if (doWrite) - cprec_header->cobjc_type_class = p; - if ((err = CPrec_FlushRawBuffer()) != noErr) - return err; - } - - if (cobjc_type_id) { - Type *p = CPrec_GetTypePatch(cobjc_type_id); - if (doWrite) - cprec_header->cobjc_type_id = p; - if ((err = CPrec_FlushRawBuffer()) != noErr) - return err; - } - - if (cobjc_type_sel) { - Type *p = CPrec_GetTypePatch(cobjc_type_sel); - if (doWrite) - cprec_header->cobjc_type_sel = p; - if ((err = CPrec_FlushRawBuffer()) != noErr) - return err; - } - - if (cobjc_selhashtable) { - ObjCSelector **p = CPrec_GetSelHashTablePatch(cobjc_selhashtable); - if (doWrite) - cprec_header->cobjc_selhashtable = p; - if ((err = CPrec_FlushRawBuffer()) != noErr) - return err; - } - - if (cobjc_classdefs) { - BClassList *p = CPrec_GetBClassListPatch(cobjc_classdefs); - if (doWrite) - cprec_header->cobjc_classdefs = p; - if ((err = CPrec_FlushRawBuffer()) != noErr) - return err; - } - - if (cobjc_protocols) { - ObjCProtocol *p = CPrec_GetObjCProtocolPatch(cobjc_protocols); - if (doWrite) - cprec_header->cobjc_protocols = p; - if ((err = CPrec_FlushRawBuffer()) != noErr) - return err; - } - - if (init_expressions) { - InitExpr *p = CPrec_GetIExpressionPatch(init_expressions); - if (doWrite) - cprec_header->init_expressions = p; - if ((err = CPrec_FlushRawBuffer()) != noErr) - return err; - } - - if (cinline_tactionlist) { - CI_Action *p = CPrec_GetInlineActionPatch(cinline_tactionlist); - if (doWrite) - cprec_header->cinline_tactionlist = p; - if ((err = CPrec_FlushRawBuffer()) != noErr) - return err; - } - - return noErr; -} - -static OSErr CPrec_FileAlign(short refnum, SInt32 *len) { - OSErr err; - SInt32 n; - char buf[8]; - - n = *len; - if ((n & 7) == 0) - return noErr; - - memclrw(buf, 8); - err = COS_FileWrite(refnum, buf, n = 8 - (n & 7)); - *len += n; - - return err; -} - -static OSErr CPrec_WriteFile(void) { - char str[128]; - int i; - HashNameNode *name; - OSErr err; - SInt32 offset; - - if (InitGList(&cprec_glist, 0x40000)) - CError_NoMem(); - - CompilerGetCString(10, str); - CWShowStatus(cparams.context, str, ""); - CPrep_RemoveSpecialMacros(); - - for (i = 0; i < 0x800; i++) { - for (name = name_hash_nodes[i]; name; name = name->next) - name->id = 0; - } - - if ((err = CPrec_DumpColorSymbolTable(0)) != noErr) - return err; - - CompilerGetCString(11, str); - CWShowStatus(cparams.context, str, ""); - - cprec_header = galloc(sizeof(Header)); - memclrw(cprec_header, sizeof(Header)); - - cprec_header->magic = 0xBEEFFACE; - cprec_header->version = 1047; - cprec_header->target = 2; - cprec_header->check_header_flags = copts.checkprecompflags; - cprec_header->cplusplus = copts.cplusplus; - cprec_header->uniqueID = CParser_GetUniqueID(); - cprec_header->cobjc_selrefcount = cobjc_selrefcount; - cprec_header->cobjc_classrefcount = cobjc_classrefcount; - cprec_header->cobjc_stringcount = cobjc_stringcount; - - if ((err = COS_FileWrite(cprec_refnum, cprec_header, sizeof(Header))) != noErr) - return err; - - offset = sizeof(Header); - - if ((err = CPrec_DumpColorSymbolTable(1)) != noErr) - return err; - - cprec_header->x28 = cprec_offset; - cprec_header->x30 = offset; - - if ((err = COS_FileGetPos(cprec_refnum, &offset)) != noErr) - return err; - - cprec_header->x2C = offset - cprec_header->x30; - - cprec_header->compressedPatchCount = CPrec_CompressPatches(); - cprec_header->compressedPatchSize = cprec_glist.size; - cprec_header->compressedPatchOffset = offset; - - if (cprec_header->compressedPatchCount) { - if ((err = COS_FileWrite(cprec_refnum, *cprec_glist.data, cprec_glist.size)) != noErr) - return err; - offset += cprec_glist.size; - } - - if ((err = CPrec_FileAlign(cprec_refnum, &offset)) != noErr) - return err; - - cprec_glist.size = 0; - CPrec_GenerateBuiltinPatches(); - cprec_header->builtinPatchSize = cprec_glist.size; - cprec_header->builtinPatchOffset = offset; - - if ((err = COS_FileWrite(cprec_refnum, *cprec_glist.data, cprec_glist.size)) != noErr) - return err; - offset += cprec_glist.size; - - if (cprec_tokenpatches) { - cprec_glist.size = 0; - CPrec_GenerateTokenStreamPatches(); - cprec_header->tokenStreamPatchSize = cprec_glist.size; - cprec_header->tokenStreamPatchOffset = offset; - - if ((err = COS_FileWrite(cprec_refnum, *cprec_glist.data, cprec_glist.size)) != noErr) - return err; - offset += cprec_glist.size; - } - - if ((err = COS_FileSetPos(cprec_refnum, 0)) != noErr) - return err; - - if ((err = COS_FileWrite(cprec_refnum, cprec_header, sizeof(Header))) != noErr) - return err; - - return noErr; -} - -void PrecompilerWrite(void) { - OSErr err; - short strindex; - char str[128]; - FSSpec spec; - - spec = cparamblkptr->sourcefile; - if (CWGetPrecompiledHeaderSpec(cparamblkptr->context, &spec, precomp_target_str) == cwNoErr) { - strindex = 3; - err = COS_FileNew(&spec, &cprec_refnum, copts.appltype, copts.headtype); - if (err == noErr) { - strindex = 4; - err = CPrec_WriteFile(); - } - CleanupPrecompiler(); - - if (err != noErr) { - CompilerGetCString(strindex, str); - sprintf(string, str, err); - CWReportMessage(cparamblkptr->context, NULL, string, NULL, messagetypeError, 0); - } else { - CWFileTime time = 0; - CWSetModDate(cparamblkptr->context, &spec, &time, 1); - } - } -} - -static void CPrec_ReadData(SInt32 offset, void *buffer, SInt32 size) { - if ( - COS_FileSetPos(cprec_refnum, offset) != noErr || - COS_FileRead(cprec_refnum, buffer, size) != noErr - ) - CError_ErrorTerm(CErrorStr181); -} - -static void CPrec_ReadRawBuffer(void) { - UInt8 *buffer; - UInt8 *work; - UInt8 *end; - UInt32 size; - int ch; - - if (!cprec_buffer) { - size = cprec_header->x28 + (cprec_header->x28 >> 7) + 64; - buffer = galloc(size); - cprec_rawbuffer = buffer; - - work = buffer + size - cprec_header->x2C; - CPrec_ReadData(cprec_header->x30, work, cprec_header->x2C); - } else { - buffer = galloc(cprec_header->x28); - cprec_rawbuffer = buffer; - work = (UInt8 *) cprec_buffer + cprec_header->x30; - } - - end = work + cprec_header->x2C; - - while (work < end) { - if ((ch = *(work++)) >= 0xE0) { - ch -= 0xE0; - do { - *(buffer++) = 0; - } while (--ch >= 0); - } else { - do { - *(buffer++) = *(work++); - } while (--ch >= 0); - } - } - - if (work != end || buffer != RESOLVE_RAW_BUFFER(cprec_header->x28)) - CError_ErrorTerm(CErrorStr181); -} - -static void CPrec_RelocateRawBuffer(void) { - UInt8 *patches; - UInt32 offset; - UInt8 *dest; - SInt32 count; - UInt8 *patch; - UInt32 var; - - if ((count = cprec_header->compressedPatchCount)) { - if (!cprec_buffer) { - patches = lalloc(cprec_header->compressedPatchSize); - CPrec_ReadData(cprec_header->compressedPatchOffset, patches, cprec_header->compressedPatchSize); - } else { - patches = RESOLVE_BUFFER(cprec_header->compressedPatchOffset); - } - - offset = 0; - patch = patches; - dest = cprec_rawbuffer; - do { - if (!(*patch & 0x80)) { - ((UInt8 *) &var)[0] = *(patch++); - ((UInt8 *) &var)[1] = *(patch++); - ((UInt8 *) &var)[2] = *(patch++); - ((UInt8 *) &var)[3] = *(patch++); - offset = var; - } else { - offset += (char) (*(patch++) * 2); - } - *((uintptr_t *) (dest + offset)) += (uintptr_t) dest; - } while (--count > 0); - - freelheap(); - - if (patch != (patches + cprec_header->compressedPatchSize)) - CError_ErrorTerm(CErrorStr181); - } -} - -static void CPrec_RelocateBuiltins(void) { - UInt32 *patches; - void *builtin; - UInt32 count; - UInt8 *buffer; - - if (cprec_header->builtinPatchSize) { - CPrec_SetupBuiltInArray(); - if (!cprec_buffer) { - patches = lalloc(cprec_header->builtinPatchSize); - CPrec_ReadData(cprec_header->builtinPatchOffset, patches, cprec_header->builtinPatchSize); - } else { - patches = RESOLVE_BUFFER(cprec_header->builtinPatchOffset); - } - - buffer = cprec_rawbuffer; - while (1) { - if (!(count = *(patches++))) - break; - - builtin = cprec_builtin_array[*(patches++)]; - do { - *((void **) (buffer + *(patches++))) = builtin; - } while (--count); - } - } -} - -static void CPrec_RelocateTokenStreams(void) { - UInt32 *patches; - UInt32 count; - TStreamElement *tokens; - UInt8 *buffer; - CPrepFileInfo *file; - SInt32 pos; - - if (cprec_header->tokenStreamPatchSize) { - CPrep_GetPrepPos(&file, &pos); - - if (!cprec_buffer) { - patches = lalloc(cprec_header->tokenStreamPatchSize); - CPrec_ReadData(cprec_header->tokenStreamPatchOffset, patches, cprec_header->tokenStreamPatchSize); - } else { - patches = RESOLVE_BUFFER(cprec_header->tokenStreamPatchOffset); - } - - buffer = cprec_rawbuffer; - while (1) { - if (!*patches) - break; - - tokens = (TStreamElement *) (buffer + *(patches++)); - count = *(patches++); - - while (count--) { - tokens->tokenfile = file; - tokens->tokenoffset = pos; - tokens++; - } - } - } -} - -static void CPrec_RelocateMacroTable(void) { - int i; - int j; - int count; - UInt8 *buffer; - Macro **prec_table; - Macro **table; - Macro *macro; - uintptr_t offset; - - buffer = cprec_rawbuffer; - prec_table = cprec_header->macrotable; - table = macrohashtable; - - i = 0; - do { - for (macro = *table; macro; macro = macro->next) { - macro->name = GetHashNameNodeExport(macro->name->name); - count = macro->xC & 0x7FFF; - for (j = 1; j < count; j++) - macro->names[j - 1] = GetHashNameNodeExport(macro->names[j - 1]->name); - } - - if ((offset = (uintptr_t) *prec_table)) { - if (*table) { - macro = (Macro *) (buffer + offset); - while (macro->next) - macro = macro->next; - macro->next = *table; - } - *table = (Macro *) (buffer + offset); - } - - prec_table++; - table++; - } while (++i < 0x800); -} - -static void CPrec_RelocateTable(void **table, int size, void **dest) { - int i; - void *buffer = cprec_rawbuffer; - - for (i = 0; i < size; i++) { - if (*table) - *dest = (char *) buffer + (uintptr_t) *table; - else - *dest = NULL; - table++; - dest++; - } -} - -static void CPrec_RelocateRootNameSpace(void) { - CError_ASSERT(4981, cscope_root->is_hash); - - cscope_root->names = cprec_header->root_names; - CPrec_RelocateTable( - (void **) cprec_header->root_nametable, - 0x400, - (void **) cscope_root->data.hash); -} - -static void CPrec_FixNameIds(void) { - int i; - HashNameNode *node; - - for (i = 0; i < 2048; i++) { - for (node = name_hash_nodes[i]; node; node = node->next) - node->id = -1; - } -} - -static void CPrec_DefineStaticData(void) { - StaticData *sd = cprec_staticdata; - cprec_staticdata = NULL; - - while (sd) { - CInit_DeclareData(sd->object, sd->buffer, sd->links, sd->size); - sd = sd->next; - } -} - -void PrecompilerRead(short refnum, void *buffer) { - cprec_refnum = refnum; - cprec_buffer = buffer; - - CPrep_RemoveSpecialMacros(); - - if (!CScope_IsEmptySymTable()) - CError_ErrorTerm(CErrorStr180); - - if (!cprec_buffer) { - cprec_header = galloc(sizeof(Header)); - CPrec_ReadData(0, cprec_header, sizeof(Header)); - } else { - cprec_header = cprec_buffer; - } - - if (cprec_header->magic != 0xBEEFFACE) - CError_ErrorTerm(CErrorStr181); - if (cprec_header->version != 1047) - CError_ErrorTerm(CErrorStr222); - if (cprec_header->target != 2) - CError_ErrorTerm(CErrorStr223); - - copts.checkprecompflags = cprec_header->check_header_flags; - - CPrec_ReadRawBuffer(); - CPrec_RelocateRawBuffer(); - CPrec_RelocateBuiltins(); - CPrec_RelocateTable((void **) cprec_header->nametable, 0x800, (void **) name_hash_nodes); - CPrec_FixNameIds(); - CPrec_RelocateMacroTable(); - CPrec_RelocateTokenStreams(); - CPrec_RelocateRootNameSpace(); - - if (!cprec_header->usings) - cscope_root->usings = NULL; - else - cscope_root->usings = RESOLVE_RAW_BUFFER(cprec_header->usings); - - ctempl_templates = RESOLVE_SAFE(cprec_header->ctempl_templates); - ctempl_templatefuncs = RESOLVE_SAFE(cprec_header->ctempl_templatefuncs); - csom_stubs = RESOLVE_SAFE(cprec_header->csom_stubs); - cprec_staticdata = RESOLVE_SAFE(cprec_header->cprec_staticdata); - callbackactions = RESOLVE_SAFE(cprec_header->callbackactions); - cobjc_type_class = RESOLVE_SAFE(cprec_header->cobjc_type_class); - cobjc_type_id = RESOLVE_SAFE(cprec_header->cobjc_type_id); - cobjc_type_sel = RESOLVE_SAFE(cprec_header->cobjc_type_sel); - cobjc_selhashtable = RESOLVE_SAFE(cprec_header->cobjc_selhashtable); - cobjc_classdefs = RESOLVE_SAFE(cprec_header->cobjc_classdefs); - cobjc_protocols = RESOLVE_SAFE(cprec_header->cobjc_protocols); - init_expressions = RESOLVE_SAFE(cprec_header->init_expressions); - cinline_tactionlist = RESOLVE_SAFE(cprec_header->cinline_tactionlist); - CParser_SetUniqueID(cprec_header->uniqueID); - cobjc_selrefcount = cprec_header->cobjc_selrefcount; - cobjc_classrefcount = cprec_header->cobjc_classrefcount; - cobjc_stringcount = cprec_header->cobjc_stringcount; - - cprec_refnum = 0; - - CleanupPrecompiler(); - cscope_current = cscope_root; - - if (!CParser_ReInitRuntimeObjects(1)) - CError_ErrorTerm(CErrorStr181); - - CPrep_InsertSpecialMacros(); - - if (cparamblkptr->precompile != 1) - CPrec_DefineStaticData(); -} diff --git a/compiler_and_linker/unsorted/CPreprocess.c b/compiler_and_linker/unsorted/CPreprocess.c deleted file mode 100644 index 4e6b3c0..0000000 --- a/compiler_and_linker/unsorted/CPreprocess.c +++ /dev/null @@ -1,676 +0,0 @@ -#include "compiler/CPreprocess.h" -#include "compiler/CError.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CompilerTools.h" -#include "cos.h" - -void CPrep_PreprocessDumpNewLine(void) { - if (copts.line_prepdump && pplist.data && filesp >= 0) - AppendGListData(&pplist, "\r", 1); -} - -void CPrep_PreprocessDumpFileInfo(Boolean flag) { - char linebuf[512]; - int size; - SInt16 tmp16; - SInt32 tmp32; - Str255 filename; - - if (pplist.data && filesp >= 0) { - if (nlflag && flag && pplist.size > 0) - AppendGListName(&pplist, "\r"); - - if (copts.line_prepdump) - size = sprintf(linebuf, "#line % " PRId32 "\t\"", linenumber); - else - size = sprintf(linebuf, "/* #line % " PRId32 "\t\"", linenumber); - AppendGListData(&pplist, linebuf, size); - - if (copts.fullpath_prepdump) { - if (prep_file->nameNode) { - AppendGListData(&pplist, prep_file->nameNode->name, strlen(prep_file->nameNode->name)); - } else { - COS_FileGetPathName(linebuf, &prep_file->textfile, &tmp32); - AppendGListData(&pplist, linebuf, strlen(linebuf)); - } - } else { - if (prep_file->nameNode) { - char *work = prep_file->nameNode->name + strlen(prep_file->nameNode->name); - while (work > prep_file->nameNode->name && !strchr("/\\:", work[-1])) - work--; - - AppendGListData(&pplist, work, strlen(work)); - } else { - COS_FileGetFSSpecInfo(&prep_file->textfile, &tmp16, &tmp32, filename); - AppendGListData(&pplist, &filename[1], filename[0]); - } - } - - size = sprintf(linebuf, "\"\t/* stack depth % " PRId32 " */", filesp); - AppendGListData(&pplist, linebuf, size); - - if (copts.line_prepdump && flag) - CPrep_PreprocessDumpNewLine(); - - nlflag = 1; - } -} - -static void CPrep_DumpWString(UInt16 *str, short len) { - int divisor; - int i; - - while (len--) { - if (*str < 32) { - AppendGListByte(&pplist, '\\'); - switch (*str) { - case 7: - AppendGListByte(&pplist, 'a'); - break; - case 8: - AppendGListByte(&pplist, 'b'); - break; - case 27: - AppendGListByte(&pplist, 'e'); - break; - case 12: - AppendGListByte(&pplist, 'f'); - break; - case 10: - AppendGListByte(&pplist, 'n'); - break; - case 13: - AppendGListByte(&pplist, 'r'); - break; - case 9: - AppendGListByte(&pplist, 't'); - break; - case 11: - AppendGListByte(&pplist, 'v'); - break; - default: - if (*str >= 8) - AppendGListByte(&pplist, '0' + (*str / 8)); - AppendGListByte(&pplist, '0' + (*str % 8)); - } - } else if (*str > 255) { - AppendGListByte(&pplist, '\\'); - AppendGListByte(&pplist, 'x'); - - divisor = 0x1000; - for (i = 0; i < 4; i++) { - AppendGListByte(&pplist, "0123456789ABCDEF"[(*str / divisor) % 16]); - divisor /= 16; - } - } else { - switch (*str) { - case '"': - case '\\': - AppendGListByte(&pplist, '\\'); - default: - AppendGListByte(&pplist, *str); - } - } - str++; - } -} - -static void CPrep_DumpString(UInt8 *str, short len) { - while (len--) { - if (*str < 32) { - AppendGListByte(&pplist, '\\'); - switch (*str) { - case 7: - AppendGListByte(&pplist, 'a'); - break; - case 8: - AppendGListByte(&pplist, 'b'); - break; - case 12: - AppendGListByte(&pplist, 'f'); - break; - case 10: - AppendGListByte(&pplist, 'n'); - break; - case 13: - AppendGListByte(&pplist, 'r'); - break; - case 9: - AppendGListByte(&pplist, 't'); - break; - case 11: - AppendGListByte(&pplist, 'v'); - break; - default: - if (*str >= 8) - AppendGListByte(&pplist, '0' + (*str / 8)); - AppendGListByte(&pplist, '0' + (*str % 8)); - } - } else { - switch (*str) { - case '"': - case '\\': - AppendGListByte(&pplist, '\\'); - default: - AppendGListByte(&pplist, *str); - } - } - str++; - } -} - -void CPrep_Preprocess(void) { - short innertoken; - short token; - char startToken; - char endToken; - int depth; - Boolean save_asmpoundcomment; // r16 - Boolean save_cplusplus; // r15 - char *p; - - startToken = 0; - depth = 0; - - if (InitGList(&pplist, 10000)) - CError_NoMem(); - - nlflag = 0; - spaceskip = 0; - - if ((token = lex())) { - do { - if (nlflag) { - if (!copts.line_prepdump) - AppendGListData(&pplist, "\r", 1); - } else { - if (spaceskip) - AppendGListByte(&pplist, ' '); - } - - while (1) { - switch ((innertoken = token)) { - case '(': - case ')': - case '{': - case '}': - AppendGListByte(&pplist, token); - if (cprep_nostring) { - if (innertoken == startToken) { - depth++; - } else if (innertoken == endToken) { - if (--depth == 0) { - cprep_nostring = 0; - in_assembler = 0; - copts.cplusplus = save_cplusplus; - copts.asmpoundcomment = save_asmpoundcomment; - } - } - } - break; - - case TK_INTCONST: - case TK_FLOATCONST: - if (tokenstacklevel > 0) - p = macropos; - else - p = prep_file_start + ts_current[-1].tokenoffset; - AppendGListData(&pplist, p, pos - p); - break; - - case TK_IDENTIFIER: - AppendGListData(&pplist, tkidentifier->name, strlen(tkidentifier->name)); - break; - - case TK_AUTO: - AppendGListData(&pplist, "auto", 4); - break; - case TK_REGISTER: - AppendGListData(&pplist, "register", 8); - break; - case TK_STATIC: - AppendGListData(&pplist, "static", 6); - break; - case TK_EXTERN: - AppendGListData(&pplist, "extern", 6); - break; - case TK_TYPEDEF: - AppendGListData(&pplist, "typedef", 7); - break; - case TK_INLINE: - AppendGListData(&pplist, "inline", 6); - break; - case TK_VOID: - AppendGListData(&pplist, "void", 4); - break; - case TK_CHAR: - AppendGListData(&pplist, "char", 4); - break; - case TK_SHORT: - AppendGListData(&pplist, "short", 5); - break; - case TK_INT: - AppendGListData(&pplist, "int", 3); - break; - case TK_LONG: - AppendGListData(&pplist, "long", 4); - break; - case TK_FLOAT: - AppendGListData(&pplist, "float", 5); - break; - case TK_DOUBLE: - AppendGListData(&pplist, "double", 6); - break; - case TK_SIGNED: - AppendGListData(&pplist, "signed", 6); - break; - case TK_UNSIGNED: - AppendGListData(&pplist, "unsigned", 8); - break; - case TK_STRUCT: - AppendGListData(&pplist, "struct", 6); - break; - case TK_UNION: - AppendGListData(&pplist, "union", 5); - break; - case TK_ENUM: - AppendGListData(&pplist, "enum", 4); - break; - case TK_CLASS: - AppendGListData(&pplist, "class", 5); - break; - case TK_CONST: - AppendGListData(&pplist, "const", 5); - break; - case TK_VOLATILE: - AppendGListData(&pplist, "volatile", 8); - break; - case TK_PASCAL: - AppendGListData(&pplist, "pascal", 6); - break; - case TK_UU_FAR: - AppendGListData(&pplist, "__far", 5); - break; - case TK_ONEWAY: - AppendGListData(&pplist, "oneway", 6); - break; - case TK_IN: - AppendGListData(&pplist, "in", 2); - break; - case TK_OUT: - AppendGListData(&pplist, "out", 3); - break; - case TK_INOUT: - AppendGListData(&pplist, "inout", 5); - break; - case TK_BYCOPY: - AppendGListData(&pplist, "bycopy", 6); - break; - case TK_BYREF: - AppendGListData(&pplist, "byref", 5); - break; - case TK_ASM: - AppendGListData(&pplist, "asm", 3); - endToken = 0; - startToken = 0; - AppendGListByte(&pplist, ' '); - token = lex(); - if (token == TK_VOLATILE || (token == TK_IDENTIFIER && !strcmp(tkidentifier->name, "__volatile__"))) { - AppendGListData(&pplist, "volatile", 8); - token = lex(); - } - if (token) { - if (token < ' ' || token > 255) - continue; - AppendGListByte(&pplist, token); - - if (token == '(') { - startToken = '('; - endToken = ')'; - } else if (token == '{') { - startToken = '{'; - endToken = '}'; - } else { - continue; - } - - cprep_nostring = 1; - in_assembler = 1; - depth = 1; - save_asmpoundcomment = copts.asmpoundcomment; - save_cplusplus = copts.cplusplus; - - token = lex(); - if (token == '"') { - AppendGListByte(&pplist, token); - copts.cplusplus = 0; - copts.asmpoundcomment = 1; - break; - } else if (token == 0) { - break; - } - continue; - } - break; - - case TK_CASE: - AppendGListData(&pplist, "case", 4); - break; - case TK_DEFAULT: - AppendGListData(&pplist, "default", 7); - break; - case TK_IF: - AppendGListData(&pplist, "if", 2); - break; - case TK_ELSE: - AppendGListData(&pplist, "else", 4); - break; - case TK_SWITCH: - AppendGListData(&pplist, "switch", 6); - break; - case TK_WHILE: - AppendGListData(&pplist, "while", 5); - break; - case TK_DO: - AppendGListData(&pplist, "do", 2); - break; - case TK_FOR: - AppendGListData(&pplist, "for", 3); - break; - case TK_GOTO: - AppendGListData(&pplist, "goto", 4); - break; - case TK_CONTINUE: - AppendGListData(&pplist, "continue", 8); - break; - case TK_BREAK: - AppendGListData(&pplist, "break", 5); - break; - case TK_RETURN: - AppendGListData(&pplist, "return", 6); - break; - case TK_SIZEOF: - AppendGListData(&pplist, "sizeof", 6); - break; - case TK_CATCH: - AppendGListData(&pplist, "catch", 5); - break; - case TK_DELETE: - AppendGListData(&pplist, "delete", 6); - break; - case TK_FRIEND: - AppendGListData(&pplist, "friend", 6); - break; - case TK_NEW: - AppendGListData(&pplist, "new", 3); - break; - case TK_OPERATOR: - AppendGListData(&pplist, "operator", 8); - break; - case TK_PRIVATE: - AppendGListData(&pplist, "private", 7); - break; - case TK_PROTECTED: - AppendGListData(&pplist, "protected", 9); - break; - case TK_PUBLIC: - AppendGListData(&pplist, "public", 6); - break; - case TK_TEMPLATE: - AppendGListData(&pplist, "template", 8); - break; - case TK_THIS: - AppendGListData(&pplist, "this", 4); - break; - case TK_THROW: - AppendGListData(&pplist, "throw", 5); - break; - case TK_TRY: - AppendGListData(&pplist, "try", 3); - break; - case TK_VIRTUAL: - AppendGListData(&pplist, "virtual", 7); - break; - case TK_INHERITED: - AppendGListData(&pplist, "inherited", 9); - break; - case TK_CONST_CAST: - AppendGListData(&pplist, "const_cast", 10); - break; - case TK_DYNAMIC_CAST: - AppendGListData(&pplist, "dynamic_cast", 12); - break; - case TK_EXPLICIT: - AppendGListData(&pplist, "explicit", 8); - break; - case TK_MUTABLE: - AppendGListData(&pplist, "mutable", 7); - break; - case TK_NAMESPACE: - AppendGListData(&pplist, "namespace", 9); - break; - case TK_REINTERPRET_CAST: - AppendGListData(&pplist, "reinterpret_cast", 16); - break; - case TK_STATIC_CAST: - AppendGListData(&pplist, "static_cast", 11); - break; - case TK_USING: - AppendGListData(&pplist, "using", 5); - break; - case TK_WCHAR_T: - AppendGListData(&pplist, "wchar_t", 7); - break; - case TK_TYPENAME: - AppendGListData(&pplist, "typename", 8); - break; - case TK_TRUE: - AppendGListData(&pplist, "true", 4); - break; - case TK_FALSE: - AppendGListData(&pplist, "false", 5); - break; - case TK_TYPEID: - AppendGListData(&pplist, "typeid", 6); - break; - case TK_EXPORT: - AppendGListData(&pplist, "export", 6); - break; - case TK_UU_STDCALL: - AppendGListData(&pplist, "__stdcall", 9); - break; - case TK_UU_CDECL: - AppendGListData(&pplist, "__cdecl", 7); - break; - case TK_UU_FASTCALL: - AppendGListData(&pplist, "__fastcall", 10); - break; - case TK_UU_DECLSPEC: - AppendGListData(&pplist, "__declspec", 10); - break; - case TK_MULT_ASSIGN: - AppendGListData(&pplist, "*=", 2); - break; - case TK_DIV_ASSIGN: - AppendGListData(&pplist, "/=", 2); - break; - case TK_MOD_ASSIGN: - AppendGListData(&pplist, "%=", 2); - break; - case TK_ADD_ASSIGN: - AppendGListData(&pplist, "+=", 2); - break; - case TK_SUB_ASSIGN: - AppendGListData(&pplist, "-=", 2); - break; - case TK_SHL_ASSIGN: - AppendGListData(&pplist, "<<=", 3); - break; - case TK_SHR_ASSIGN: - AppendGListData(&pplist, ">>=", 3); - break; - case TK_AND_ASSIGN: - AppendGListData(&pplist, "&=", 2); - break; - case TK_XOR_ASSIGN: - AppendGListData(&pplist, "^=", 2); - break; - case TK_OR_ASSIGN: - AppendGListData(&pplist, "|=", 2); - break; - case TK_LOGICAL_OR: - AppendGListData(&pplist, "||", 2); - break; - case TK_LOGICAL_AND: - AppendGListData(&pplist, "&&", 2); - break; - case TK_LOGICAL_EQ: - AppendGListData(&pplist, "==", 2); - break; - case TK_LOGICAL_NE: - AppendGListData(&pplist, "!=", 2); - break; - case TK_LESS_EQUAL: - AppendGListData(&pplist, "<=", 2); - break; - case TK_GREATER_EQUAL: - AppendGListData(&pplist, ">=", 2); - break; - case TK_SHL: - AppendGListData(&pplist, "<<", 2); - break; - case TK_SHR: - AppendGListData(&pplist, ">>", 2); - break; - case TK_INCREMENT: - AppendGListData(&pplist, "++", 2); - break; - case TK_DECREMENT: - AppendGListData(&pplist, "--", 2); - break; - case TK_ARROW: - AppendGListData(&pplist, "->", 2); - break; - case TK_ELLIPSIS: - AppendGListData(&pplist, "...", 3); - break; - case TK_DOT_STAR: - AppendGListData(&pplist, ".*", 2); - break; - case TK_ARROW_STAR: - AppendGListData(&pplist, "->*", 3); - break; - case TK_COLON_COLON: - AppendGListData(&pplist, "::", 2); - break; - case TK_AT_INTERFACE: - AppendGListData(&pplist, "@interface", 10); - break; - case TK_AT_IMPLEMENTATION: - AppendGListData(&pplist, "@implementation", 15); - break; - case TK_AT_PROTOCOL: - AppendGListData(&pplist, "@protocol", 9); - break; - case TK_AT_END: - AppendGListData(&pplist, "@end", 4); - break; - case TK_AT_PRIVATE: - AppendGListData(&pplist, "@private", 8); - break; - case TK_AT_PROTECTED: - AppendGListData(&pplist, "@protected", 10); - break; - case TK_AT_PUBLIC: - AppendGListData(&pplist, "@public", 7); - break; - case TK_AT_CLASS: - AppendGListData(&pplist, "@class", 6); - break; - case TK_AT_SELECTOR: - AppendGListData(&pplist, "@selector", 9); - break; - case TK_AT_ENCODE: - AppendGListData(&pplist, "@encode", 7); - break; - case TK_AT_DEFS: - AppendGListData(&pplist, "@defs", 5); - break; - case TK_SELF: - AppendGListData(&pplist, "self", 4); - break; - case TK_SUPER: - AppendGListData(&pplist, "super", 5); - break; - case TK_BOOL: - if (!copts.cplusplus && copts.c9x) - AppendGListData(&pplist, "_Bool", 5); - else - AppendGListData(&pplist, "bool", 4); - break; - case TK_RESTRICT: - if (copts.c9x) - AppendGListData(&pplist, "restrict", 8); - else - AppendGListData(&pplist, "__restrict", 10); - break; - case TK_UU_VECTOR: - AppendGListData(&pplist, "__vector", 8); - break; - case TK_UU_TYPEOF_UU: - AppendGListData(&pplist, "__typeof__", 10); - break; - case TK_UU_ATTRIBUTE_UU: - AppendGListData(&pplist, "__attribute__", 13); - break; - case TK_UU_ALIGNOF_UU: - AppendGListData(&pplist, "__alignof__", 11); - break; - case TK_UU_UUIDOF: - AppendGListData(&pplist, "__uuidof", 8); - break; - case TK_U_COMPLEX: - AppendGListData(&pplist, "_Complex", 8); - break; - case TK_U_IMAGINARY: - AppendGListData(&pplist, "_Imaginary", 10); - break; - - case TK_STRING: - if (ispascalstring) { - AppendGListData(&pplist, "\"\\p", 3); - CPrep_DumpString((UInt8 *) tkstring + 1, tksize - 1); - } else { - AppendGListByte(&pplist, '"'); - CPrep_DumpString((UInt8 *) tkstring, tksize - 1); - } - AppendGListByte(&pplist, '"'); - break; - - case TK_STRING_WIDE: - AppendGListData(&pplist, "L\"", 2); - CPrep_DumpWString((UInt16 *) tkstring, (tksize / stwchar.size) - 1); - AppendGListByte(&pplist, '"'); - break; - - default: - if (token >= 32 && token <= 255) - AppendGListByte(&pplist, token); - else - CError_FATAL(563); - } - break; - } - - CPrep_TokenStreamFlush(); - nlflag = 0; - spaceskip = 0; - } while ((token = lex())); - } - - AppendGListByte(&pplist, 0); - COS_ResizeHandle(pplist.data, pplist.size); -} diff --git a/compiler_and_linker/unsorted/CRTTI.c b/compiler_and_linker/unsorted/CRTTI.c deleted file mode 100644 index 3881153..0000000 --- a/compiler_and_linker/unsorted/CRTTI.c +++ /dev/null @@ -1,940 +0,0 @@ -#include "compiler/CRTTI.h" -#include "compiler/CClass.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CInit.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CParser.h" -#include "compiler/CScope.h" -#include "compiler/CompilerTools.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/types.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CPrep.h" - -typedef struct Offset { - struct Offset *next; - SInt32 offset; -} Offset; - -static Offset *crtti_offsets; -static OLinkList *crtti_olinks; - -// forward decls -static Object *CRTTI_ConstructTypeInfoObject(Type *type, UInt32 qual); - -typedef struct RTTISubClassList { - struct RTTISubClassList *next; - TypeClass *base; - SInt32 voffset; -} RTTISubClassList; - -typedef struct RTTIBaseList { - struct RTTIBaseList *next; - TypeClass *base; - RTTISubClassList *subclasses; - SInt32 voffset; - short numsubclasses; - Boolean x12; - Boolean x13; -} RTTIBaseList; - -static RTTIBaseList *CRTTI_CreateBaseList(TypeClass *tclass, TypeClass *tclassbase, RTTIBaseList *list, SInt32 voffset, Boolean flag) { - RTTIBaseList *scan; - ClassList *base; - Boolean flag27; - SInt32 newvoffset; - - if (tclass != tclassbase) { - flag27 = 0; - - for (scan = list; scan; scan = scan->next) { - if (scan->base == tclassbase) { - if (scan->voffset == voffset) { - if (!flag) - scan->x12 = 0; - flag27 = 0; - } else { - scan->x13 = 1; - flag27 = 1; - } - break; - } - } - - if (!scan || flag27) { - scan = lalloc(sizeof(RTTIBaseList)); - memclrw(scan, sizeof(RTTIBaseList)); - - scan->next = list; - list = scan; - scan->base = tclassbase; - scan->voffset = voffset; - scan->x12 = flag; - scan->x13 = flag27; - } - } - - for (base = tclassbase->bases; base; base = base->next) { - if (base->is_virtual) - newvoffset = CClass_VirtualBaseOffset(tclass, base->base); - else - newvoffset = voffset + base->offset; - - list = CRTTI_CreateBaseList(tclass, base->base, list, newvoffset, flag || base->access == ACCESSPRIVATE); - } - - return list; -} - -static void CRTTI_CreateSubClassList(TypeClass *tclass, RTTIBaseList *baselist, TypeClass *tclassbase, SInt32 voffset, Boolean flag) { - ClassList *base; - RTTISubClassList *scan; - SInt32 newvoffset; - - if (baselist->base != tclassbase) { - for (scan = baselist->subclasses; scan; scan = scan->next) { - if (scan->base == tclassbase && scan->voffset == voffset) - break; - } - - if (!scan) { - scan = lalloc(sizeof(RTTISubClassList)); - scan->next = baselist->subclasses; - baselist->subclasses = scan; - - scan->base = tclassbase; - scan->voffset = voffset; - baselist->numsubclasses++; - } - } - - for (base = tclassbase->bases; base; base = base->next) { - if (base->access == ACCESSPUBLIC) { - if (base->is_virtual) { - if (!flag) - continue; - newvoffset = CClass_VirtualBaseOffset(tclass, base->base); - } else { - newvoffset = voffset + base->offset; - } - - CRTTI_CreateSubClassList(tclass, baselist, base->base, newvoffset, flag); - } - } -} - -static Object *CRTTI_CreateBaseListObject(TypeClass *tclass) { - RTTIBaseList *baselist; - OLinkList *refs; - Object *object; - SInt32 *buf; - SInt32 size; - short count1; - short count2; - short total; - OLinkList *ref; - RTTIBaseList *scan; - RTTISubClassList *subclass; - SInt32 *work; - SInt32 *work2; - - baselist = CRTTI_CreateBaseList(tclass, tclass, NULL, 0, 0); - if (!baselist) - return NULL; - - count1 = 0; - count2 = 0; - total = 0; - - for (scan = baselist; scan; scan = scan->next) { - if (scan->x13 || scan->x12) { - CRTTI_CreateSubClassList(tclass, scan, scan->base, scan->voffset, scan->x13 == 0); - if (scan->numsubclasses) { - total += scan->numsubclasses; - count2++; - } - } else { - count1++; - } - } - - if (!count1 && !count2) - return NULL; - - size = (count1 + total) * 8 + count2 * 12 + 4; - buf = lalloc(size); - memclrw(buf, size); - - object = CParser_NewCompilerDefDataObject(); - object->name = CParser_GetUniqueName(); - object->type = CDecl_NewStructType(size, 4); - object->qual = Q_CONST; - object->sclass = TK_STATIC; - refs = NULL; - - work = buf; - - if (count1) { - for (scan = baselist; scan; scan = scan->next) { - if (!scan->x12 && !scan->x13) { - ref = lalloc(sizeof(OLinkList)); - ref->next = refs; - refs = ref; - - ref->obj = CRTTI_ConstructTypeInfoObject(TYPE(scan->base), 0); - ref->offset = ((char *) work) - ((char *) buf); - ref->somevalue = 0; - - work[1] = CTool_EndianConvertWord32(scan->voffset); - work += 2; - } - } - } - - if (count2) { - for (scan = baselist; scan; scan = scan->next) { - if (scan->numsubclasses) { - ref = lalloc(sizeof(OLinkList)); - ref->next = refs; - refs = ref; - - ref->obj = CRTTI_ConstructTypeInfoObject(TYPE(scan->base), 0); - ref->offset = ((char *) work) - ((char *) buf); - ref->somevalue = 0; - - work[1] = CTool_EndianConvertWord32(scan->voffset | 0x80000000); - work[2] = CTool_EndianConvertWord32(scan->numsubclasses); - work2 = work + 3; - - for (subclass = scan->subclasses; subclass; subclass = subclass->next) { - ref = lalloc(sizeof(OLinkList)); - ref->next = refs; - refs = ref; - - ref->obj = CRTTI_ConstructTypeInfoObject(TYPE(subclass->base), 0); - ref->offset = ((char *) work2) - ((char *) buf); - ref->somevalue = 0; - - work2[1] = CTool_EndianConvertWord32(subclass->voffset); - work2 += 2; - } - - work = work2; - } - } - } - - CInit_DeclareData(object, buf, refs, object->type->size); - return object; -} - -static Object *CRTTI_ConstructTypeInfoObject(Type *type, UInt32 qual) { - Object *baselistobj; - Object *nameobj; - HashNameNode *rttiname; - OLinkList *refs; - char *namestr; - int namelen; - Object *object; - NameSpaceObjectList *list; - TypePointer tptr_copy; - TypeMemberPointer tmemptr_copy; - UInt32 data[2]; - - switch (type->type) { - case TYPEPOINTER: - if (TPTR_QUAL(type) & (Q_CONST | Q_VOLATILE)) { - tptr_copy = *TYPE_POINTER(type); - tptr_copy.qual &= ~(Q_CONST | Q_VOLATILE); - type = TYPE(&tptr_copy); - } - break; - case TYPEMEMBERPOINTER: - if (TYPE_MEMBER_POINTER(type)->qual & (Q_CONST | Q_VOLATILE)) { - tmemptr_copy = *TYPE_MEMBER_POINTER(type); - tmemptr_copy.qual &= ~(Q_CONST | Q_VOLATILE); - type = TYPE(&tmemptr_copy); - } - break; - default: - qual = 0; - } - - if (IS_TYPE_CLASS(type) && type->size == 0) { - CDecl_CompleteType(type); - if (!(TYPE_CLASS(type)->flags & CLASS_COMPLETED)) - CError_Error(CErrorStr136, type, 0); - } - - rttiname = CMangler_RTTIObjectName(type, qual); - list = CScope_FindName(cscope_root, rttiname); - - if (!list || (object = OBJECT(list->object))->otype != OT_OBJECT || object->datatype != DDATA) { - namestr = CError_GetTypeName(type, qual, 0); - namelen = strlen(namestr) + 1; - nameobj = CInit_DeclareString(namestr, namelen, 0, 0); - - baselistobj = NULL; - if (IS_TYPE_CLASS(type)) - baselistobj = CRTTI_CreateBaseListObject(TYPE_CLASS(type)); - - memclrw(data, sizeof(data)); - - object = CParser_NewCompilerDefDataObject(); - object->name = rttiname; - object->type = CDecl_NewStructType(sizeof(data), 4); - object->qual = Q_CONST; - object->sclass = TK_STATIC; - - refs = lalloc(sizeof(OLinkList)); - refs->next = NULL; - refs->obj = nameobj; - refs->offset = 0; - refs->somevalue = 0; - - if (baselistobj) { - refs->next = lalloc(sizeof(OLinkList)); - refs->next->next = NULL; - refs->next->obj = baselistobj; - refs->next->offset = 4; - refs->next->somevalue = 0; - } - - CScope_AddGlobalObject(object); - CInit_DeclareData(object, data, refs, object->type->size); - } - - return object; -} - -static void CRTTI_ConstructVTableHeader(TypeClass *tclass1, TypeClass *tclass2, Object *typeinfoObj, char *data, SInt32 offset, SInt32 voffset) { - ClassList *base; - Offset *o; - OLinkList *olink; - SInt32 tmp; - SInt32 newoffset; - SInt32 newvoffset; - - if (tclass2->vtable->owner == tclass2) { - for (o = crtti_offsets; o; o = o->next) { - if (o->offset == voffset) - break; - } - - if (!o) { - o = lalloc(sizeof(Offset)); - o->next = crtti_offsets; - o->offset = voffset; - crtti_offsets = o; - - olink = lalloc(sizeof(OLinkList)); - olink->next = crtti_olinks; - olink->obj = typeinfoObj; - olink->offset = voffset; - olink->somevalue = 0; - crtti_olinks = olink; - - *((SInt32 *) (data + voffset + 4)) = CTool_EndianConvertWord32(-offset); - } else { - tmp = *((SInt32 *) (data + voffset + 4)); - CError_ASSERT(404, tmp == CTool_EndianConvertWord32(-offset)); - } - } - - for (base = tclass2->bases; base; base = base->next) { - if (base->base->vtable) { - if (base->is_virtual) { - newoffset = CClass_VirtualBaseOffset(tclass1, base->base); - newvoffset = CClass_VirtualBaseVTableOffset(tclass1, base->base); - } else { - newoffset = offset + base->offset; - newvoffset = voffset + base->voffset; - } - - CRTTI_ConstructVTableHeader(tclass1, base->base, typeinfoObj, data, newoffset, newvoffset); - } - } -} - -OLinkList *CRTTI_ConstructVTableHeaders(TypeClass *tclass, void *data, OLinkList *links) { - crtti_offsets = NULL; - crtti_olinks = links; - - CRTTI_ConstructVTableHeader( - tclass, tclass, - CRTTI_ConstructTypeInfoObject(TYPE(tclass), 0), - data, 0, 0); - - return crtti_olinks; -} - -static Type *CRTTI_FindTypeInfoType(void) { - NameSpace *nspace; - NameSpaceObjectList *list; - Type *type; - - if ((list = CScope_FindName(cscope_root, GetHashNameNodeExport("std"))) && list->object->otype == OT_NAMESPACE) - nspace = OBJ_NAMESPACE(list->object)->nspace; - else - nspace = cscope_root; - - type = CScope_GetLocalTagType(nspace, GetHashNameNodeExport("type_info")); - if (type && IS_TYPE_CLASS(type) && type->size) - return type; - - CError_Error(CErrorStr140, "::std::type_info"); - return TYPE(&stchar); -} - -ENode *CRTTI_ParseTypeID(void) { - ENode *expr; - Type *type; - Type *typeinfoType; - UInt32 qual; - - if (!copts.RTTI) - CError_Warning(CErrorStr257); - - typeinfoType = CRTTI_FindTypeInfoType(); - - if (lex() != '(') { - CError_Error(CErrorStr114); - return nullnode(); - } - - tk = lex(); - if ((type = CParser_ParseTypeID(&qual, NULL))) { - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - - if (IS_TYPE_REFERENCE(type)) - type = TPTR_TARGET(type); - } else { - expr = s_expression(); - - if (tk != ')') - CError_ErrorSkip(CErrorStr115); - else - tk = lex(); - - type = expr->rtype; - qual = ENODE_QUALS(expr); - - if (IS_TYPE_REFERENCE(type)) - type = TPTR_TARGET(type); - - if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->vtable) { - expr = funccallexpr( - Rgtid_func, - getnodeaddress(expr, 0), - intconstnode(TYPE(&stsignedlong), TYPE_CLASS(type)->vtable->offset), - NULL, - NULL); - expr->rtype = CDecl_NewPointerType(typeinfoType); - - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = typeinfoType; - expr->flags = ENODE_FLAG_CONST; - return expr; - } - } - - expr = create_objectrefnode(CRTTI_ConstructTypeInfoObject(type, qual)); - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = typeinfoType; - expr->flags = ENODE_FLAG_CONST; - return expr; -} - -static void CRTTI_ConstCastQualCheck(UInt32 qual1, UInt32 qual2) { - if ( - ((qual1 & Q_CONST) && !(qual2 & Q_CONST)) || - ((qual1 & Q_VOLATILE) && !(qual2 & Q_VOLATILE)) - ) - CError_Error(CErrorStr258); -} - -static void CRTTI_ConstCastCheck(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2) { - Boolean flag = 1; - if (IS_TYPE_REFERENCE(type2)) { - type2 = TPTR_TARGET(type2); - flag = 0; - } - - while (1) { - if (type1->type != type2->type) - break; - - switch (type1->type) { - case TYPEPOINTER: - if (!flag) - CRTTI_ConstCastQualCheck(TPTR_QUAL(type1), TPTR_QUAL(type2)); - type1 = TPTR_TARGET(type1); - type2 = TPTR_TARGET(type2); - flag = 0; - continue; - - case TYPEMEMBERPOINTER: - if (!flag) - CRTTI_ConstCastQualCheck(TYPE_MEMBER_POINTER(type1)->qual, TYPE_MEMBER_POINTER(type2)->qual); - type1 = TYPE_MEMBER_POINTER(type1)->ty1; - type2 = TYPE_MEMBER_POINTER(type2)->ty1; - flag = 0; - continue; - } - - break; - } - - if (!flag && !IS_TYPE_FUNC(type1) && !IS_TYPE_FUNC(type2)) - CRTTI_ConstCastQualCheck(CParser_GetCVTypeQualifiers(type1, qual1), CParser_GetCVTypeQualifiers(type2, qual2)); -} - -static ENode *CRTTI_ParseCast(DeclInfo *di) { - ENode *expr; - - if (lex() != '<') { - CError_Error(CErrorStr230); - return NULL; - } - - tk = lex(); - - memclrw(di, sizeof(DeclInfo)); - CParser_GetDeclSpecs(di, 0); - scandeclarator(di); - - if (di->name) - CError_Error(CErrorStr164); - - if (tk != '>') { - CError_Error(CErrorStr231); - return NULL; - } - - if (lex() != '(') { - CError_Error(CErrorStr114); - return NULL; - } - - tk = lex(); - expr = s_expression(); - if (!IS_TYPE_REFERENCE(di->thetype)) - expr = pointer_generation(expr); - - if (tk != ')') { - CError_Error(CErrorStr115); - return NULL; - } - - tk = lex(); - return expr; -} - -static void CRTTI_IncompleteCheck(Type *type) { - if (IS_TYPE_POINTER_ONLY(type)) - type = TPTR_TARGET(type); - - if (IS_TYPE_CLASS(type) && type->size == 0) { - CDecl_CompleteType(type); - if (!(TYPE_CLASS(type)->flags & CLASS_COMPLETED)) - CError_Error(CErrorStr136, type, 0); - } -} - -static Boolean CRTTI_IsSameType(Type *a, Type *b) { - while (1) { - if (a->type != b->type) - return 0; - - switch (a->type) { - case TYPEVOID: - return 1; - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - case TYPESTRUCT: - return a == b; - case TYPEPOINTER: - a = TPTR_TARGET(a); - b = TPTR_TARGET(b); - continue; - default: - return is_typesame(a, b); - } - } -} - -static ENode *CRTTI_UniversalCast(ENode *expr, Type *type, UInt32 qual, UInt8 mode) { - // type/qual are the target type - Boolean isSimpleCast; - Boolean needsTypcon; - Boolean failed; - - if (ENODE_IS(expr, EOBJLIST)) - return CExpr_AssignmentPromotion(expr, type, qual & (Q_CONST | Q_VOLATILE), 1); - - isSimpleCast = needsTypcon = failed = 0; - - switch (type->type) { - case TYPEINT: - case TYPEENUM: - if (mode == 2 && IS_TYPE_POINTER_ONLY(expr->rtype) && type != TYPE(&stbool)) - failed = 1; - break; - - case TYPEPOINTER: - if (TPTR_QUAL(type) & Q_REFERENCE) { - if ( - !CRTTI_IsSameType(TPTR_TARGET(type), expr->rtype) && - mode == 2 && - !( - IS_TYPE_CLASS(TPTR_TARGET(type)) && - IS_TYPE_CLASS(expr->rtype) && - ( - CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(type)), TYPE_CLASS(expr->rtype), NULL, 0, 1) || - CClass_IsBaseClass(TYPE_CLASS(expr->rtype), TYPE_CLASS(TPTR_TARGET(type)), NULL, 0, 1) - ) - ) - ) - { - failed = 1; - } - } else if (IS_TYPE_POINTER_ONLY(expr->rtype)) { - if ( - mode == 3 || - CRTTI_IsSameType(type, expr->rtype) || - IS_TYPE_VOID(TPTR_TARGET(type)) || - IS_TYPE_VOID(TPTR_TARGET(expr->rtype)) - ) - { - isSimpleCast = needsTypcon = 1; - } - else if ( - mode == 2 && - !( - IS_TYPE_CLASS(TPTR_TARGET(type)) && - IS_TYPE_CLASS(TPTR_TARGET(expr->rtype)) && - ( - CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(type)), TYPE_CLASS(TPTR_TARGET(expr->rtype)), NULL, 0, 1) || - CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(expr->rtype)), TYPE_CLASS(TPTR_TARGET(type)), NULL, 0, 1) - ) - ) - ) - { - failed = 1; - } - } else { - if (IS_TYPE_ENUM(expr->rtype)) - expr->rtype = TYPE_ENUM(expr->rtype)->enumtype; - - if (IS_TYPE_INT(expr->rtype)) { - if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval)) { - isSimpleCast = 1; - break; - } - - if (mode != 2) - break; - } - - if (IS_TYPE_CLASS(expr->rtype)) { - if (mode == 2) - break; - } - - failed = 1; - } - break; - } - - if (failed) { - CError_Error(CErrorStr247, expr->rtype, ENODE_QUALS(expr), type, qual); - return expr; - } - - if (isSimpleCast) { - if (needsTypcon && ENODE_IS(expr, EINDIRECT) && (copts.pointercast_lvalue || !copts.ANSIstrict)) - expr = makemonadicnode(expr, ETYPCON); - - expr->rtype = type; - expr->flags = qual & ENODE_FLAG_QUALS; - return expr; - } - - if (copts.old_argmatch) - return do_typecast(expr, type, qual); - - return CExpr_Convert(expr, type, qual, 1, 1); -} - -ENode *CRTTI_Parse_dynamic_cast(void) { - Boolean isRef; - ENode *expr; - TypeClass *srcclass; - TypeClass *destclass; - ENode *typeinfo; - DeclInfo di; - - expr = CRTTI_ParseCast(&di); - if (!expr) - return nullnode(); - - if (!copts.RTTI) - CError_Warning(CErrorStr257); - - CRTTI_ConstCastCheck(expr->rtype, expr->flags, di.thetype, di.qual); - if (!IS_TYPE_POINTER_ONLY(di.thetype)) { - CError_Error(CErrorStr164); - return expr; - } - - isRef = (TPTR_QUAL(di.thetype) & Q_REFERENCE) != 0; - - if (IS_TYPE_CLASS(TPTR_TARGET(di.thetype))) { - destclass = TYPE_CLASS(TPTR_TARGET(di.thetype)); - CDecl_CompleteType(TYPE(destclass)); - if (!(destclass->flags & CLASS_COMPLETED)) { - CError_Error(CErrorStr136, destclass, 0); - return expr; - } - } else if (!IS_TYPE_VOID(TPTR_TARGET(di.thetype))) { - CError_Error(CErrorStr164); - return expr; - } else { - destclass = NULL; - } - - if (isRef) { - if (!IS_TYPE_CLASS(expr->rtype)) { - CError_Error(CErrorStr164); - return expr; - } - - srcclass = TYPE_CLASS(expr->rtype); - if (destclass) { - if (srcclass == destclass || CClass_IsBaseClass(srcclass, destclass, NULL, 0, 1)) - return do_typecast(expr, di.thetype, di.qual); - } - - expr = getnodeaddress(expr, 1); - } else { - if (!IS_TYPE_POINTER_ONLY(expr->rtype) || !IS_TYPE_CLASS(TPTR_TARGET(expr->rtype))) { - CError_Error(CErrorStr164); - return expr; - } - - srcclass = TYPE_CLASS(TPTR_TARGET(expr->rtype)); - if (destclass) { - if (srcclass == destclass || CClass_IsBaseClass(srcclass, destclass, NULL, 0, 1)) - return do_typecast(expr, di.thetype, di.qual); - } - } - - if (!(srcclass->flags & CLASS_COMPLETED)) { - CError_Error(CErrorStr136, srcclass, 0); - return expr; - } - - if (!srcclass->vtable) { - CError_Error(CErrorStr164); - return expr; - } - - if (srcclass->sominfo) { - CError_Error(CErrorStr164); - return expr; - } - - if (destclass) { - typeinfo = create_objectrefnode(CRTTI_ConstructTypeInfoObject(TYPE(destclass), 0)); - if (destclass->sominfo) { - CError_Error(CErrorStr164); - return expr; - } - } else { - typeinfo = nullnode(); - } - - expr = CExpr_FuncCallSix( - Rdync_func, - expr, - intconstnode(TYPE(&stsignedlong), srcclass->vtable->offset), - typeinfo, - create_objectrefnode(CRTTI_ConstructTypeInfoObject(TYPE(srcclass), 0)), - intconstnode(TYPE(&stsignedshort), isRef), - NULL - ); - - if (isRef) { - expr->rtype = CDecl_NewPointerType(TYPE(destclass)); - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = TYPE(destclass); - } else { - expr->rtype = di.thetype; - } - expr->flags = di.qual & ENODE_FLAG_QUALS; - return expr; -} - -ENode *CRTTI_Parse_static_cast(void) { - ENode *expr; - DeclInfo di; - - expr = CRTTI_ParseCast(&di); - if (!expr) - return nullnode(); - - CRTTI_ConstCastCheck(expr->rtype, expr->flags, di.thetype, di.qual); - - if (IS_TYPE_REFERENCE(di.thetype)) { - if (IS_TYPE_CLASS(expr->rtype) && CExpr_CanImplicitlyConvert(expr, di.thetype, di.qual)) { - expr = CExpr_Convert(expr, di.thetype, di.qual, 0, 1); - CError_ASSERT(959, IS_TYPE_POINTER_ONLY(expr->rtype)); - - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = TPTR_TARGET(di.thetype); - expr->flags = di.qual & ENODE_FLAG_QUALS; - return expr; - } - } else { - if (CExpr_CanImplicitlyConvert(expr, di.thetype, di.qual)) - return CExpr_Convert(expr, di.thetype, di.qual, 1, 1); - } - - if (!IS_TYPE_VOID(di.thetype) && !(IS_TYPE_POINTER_ONLY(expr->rtype) && IS_TYPE_VOID(TPTR_TARGET(expr->rtype)))) { - CRTTI_IncompleteCheck(di.thetype); - CRTTI_IncompleteCheck(expr->rtype); - } - - return CRTTI_UniversalCast(expr, di.thetype, di.qual, 2); -} - -ENode *CRTTI_Parse_reinterpret_cast(void) { - ENode *expr; - Type *origtype; - ENode *lvalue; - DeclInfo di; - - expr = CRTTI_ParseCast(&di); - if (!expr) - return nullnode(); - - CRTTI_ConstCastCheck(expr->rtype, expr->flags, di.thetype, di.qual); - - if (IS_TYPE_REFERENCE(di.thetype)) { - lvalue = CExpr_LValue(expr, 0, 1); - if (!ENODE_IS(lvalue, EINDIRECT)) - return lvalue; - - lvalue->data.monadic->rtype = CDecl_NewPointerType(lvalue->rtype); - expr = lvalue->data.monadic; - origtype = di.thetype; - di.thetype = CDecl_NewPointerType(TPTR_TARGET(di.thetype)); - } else { - origtype = NULL; - } - - switch (di.thetype->type) { - case TYPEINT: - switch (expr->rtype->type) { - case TYPEMEMBERPOINTER: - case TYPEPOINTER: - expr = do_typecast(expr, di.thetype, di.qual); - break; - default: - CError_Error(CErrorStr164); - } - break; - case TYPEPOINTER: - switch (expr->rtype->type) { - case TYPEINT: - case TYPEENUM: - if (origtype) - di.thetype = origtype; - expr = do_typecast(expr, di.thetype, di.qual); - break; - case TYPEPOINTER: - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = di.thetype; - expr->flags = di.qual & ENODE_FLAG_QUALS; - break; - default: - CError_Error(CErrorStr164); - } - break; - case TYPEMEMBERPOINTER: - if (IS_TYPE_MEMBERPOINTER(expr->rtype)) { - if (IS_TYPE_FUNC(TYPE_MEMBER_POINTER(di.thetype)->ty1)) { - if (IS_TYPE_FUNC(TYPE_MEMBER_POINTER(expr->rtype)->ty1)) { - expr->rtype = di.thetype; - expr->flags = di.qual & ENODE_FLAG_QUALS; - break; - } - } else { - if (!IS_TYPE_FUNC(TYPE_MEMBER_POINTER(expr->rtype)->ty1)) { - expr->rtype = di.thetype; - expr->flags = di.qual & ENODE_FLAG_QUALS; - break; - } - } - } - expr = do_typecast(expr, di.thetype, di.qual); - break; - default: - CError_Error(CErrorStr164); - } - - if (origtype && IS_TYPE_POINTER_ONLY(expr->rtype)) { - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = TPTR_TARGET(di.thetype); - } - - return expr; -} - -ENode *CRTTI_Parse_const_cast(void) { - DeclInfo di; - ENode *expr; - - if (!(expr = CRTTI_ParseCast(&di))) - return nullnode(); - - if (IS_TYPE_POINTER_ONLY(di.thetype)) { - if (TPTR_QUAL(di.thetype) & Q_REFERENCE) { - if (!iscpp_typeequal(TPTR_TARGET(di.thetype), expr->rtype)) - CError_Error(CErrorStr164); - - if (ENODE_IS(expr, EINDIRECT)) { - expr->rtype = TPTR_TARGET(di.thetype); - expr->flags = di.qual & ENODE_FLAG_QUALS; - } else { - CError_Error(CErrorStr142); - } - } else { - if (!iscpp_typeequal(di.thetype, expr->rtype)) - CError_Error(CErrorStr164); - - expr = do_typecast(expr, di.thetype, di.qual); - } - } else if (IS_TYPE_MEMBERPOINTER(di.thetype)) { - if (!iscpp_typeequal(di.thetype, expr->rtype)) - CError_Error(CErrorStr164); - - expr = do_typecast(expr, di.thetype, di.qual); - } else { - if (!is_typesame(di.thetype, expr->rtype)) - CError_Error(CErrorStr164); - else - expr = do_typecast(expr, di.thetype, di.qual); - } - - return expr; -} diff --git a/compiler_and_linker/unsorted/CSOM.c b/compiler_and_linker/unsorted/CSOM.c deleted file mode 100644 index afd68a3..0000000 --- a/compiler_and_linker/unsorted/CSOM.c +++ /dev/null @@ -1,2069 +0,0 @@ -#include "compiler/CSOM.h" -#include "compiler/CClass.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CException.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInit.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CScope.h" -#include "compiler/CodeGen.h" -#include "compiler/CompilerTools.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/types.h" -#include "cos.h" - -// all pointers have been converted to UInt32 for the sake of maintaining 32-bit compat - -typedef struct { - SInt32 zero; - /* struct somStaticClassInfo * */ UInt32 sci; - /* void * */ UInt32 instanceDataToken; - SInt32 reserved[3]; - /* void * */ UInt32 tokens[1]; -} somClassDataStructure; - -enum { - mtVirtualMethod = 0, - mtProcedure = 1, - mtNonStatic = 2, - mtEmpty = 3, - mtDToken = 4 -}; - -enum { - pdUByte = 0, - pdSByte = 1, - pdUHalf = 2, - pdSHalf = 3, - pdULong = 4, - pdSLong = 5, - pdVLong = 6, - pdVoid = 7, - pdSFlt = 8, - pdDFlt = 9, - pdLFlt = 10, - pdVSAgg = 11, - pdNPtr = 12, - pdLPtr = 13, - pdSAgg = 14, - pdLAgg = 15 -}; - -enum { - fgShortOrChars = 1, - fgShortFloats = 2, - fgAnyFloats = 4, - fgAnyNon4Bytes = 8 -}; - -enum { - cfSharedStrings = 1, - cfTempClass = 2, - cfProxyClass = 4, - cfClassAllocate = 0x100, - cfClassDeallocate = 0x200, - cfClassInit = 0x400, - cfClassUninit = 0x800 -}; - -typedef struct { - UInt32 majorVersion; - UInt32 minorVersion; - UInt32 flags; - UInt16 dataAlignment; - UInt16 classTokenCount; - UInt16 numDirectParents; - UInt16 numMetaClasses; - UInt16 numOverriddenAncestors; - UInt16 numMigratedMethods; - UInt16 numSelectInherited; - UInt16 numUnused; - UInt16 dummy2a[4]; -} somStaticClassCounts; - -typedef UInt8 somSlotUsage; -typedef UInt8 somSignatureInfo; -typedef UInt16 somOverrideData; -typedef UInt16 somMigratedMethods; -typedef UInt16 somSelectedInherited; -typedef UInt32 somParentVersions; - -typedef struct { - /* const char * */ UInt32 className; - UInt32 instanceDataSize; - /* const somParentVersions * */ UInt32 parentVersions; - /* const somSlotUsage * */ UInt32 ttSlotUsage; - /* const somSignatureInfo * */ UInt32 signatureInfo; - /* const char * */ UInt32 methodNames; - /* const somOverrideData * */ UInt32 overrideData; - /* const somMigratedMethods * */ UInt32 migratedMethods; - /* const somSelectedInherited * */ UInt32 selectedInherited; - /* const void * */ UInt32 unused; - /* const void * */ UInt32 dummy4b[4]; -} somStaticClassDescription; - -typedef struct somStaticClassInfo { - UInt32 layoutVersion; - /* somClassDataStructure * */ UInt32 tokenTable; - /* somMethodPtr * */ UInt32 overrideMethods; - /* somClassDataStructure ** */ UInt32 specifiedAncestry; - /* somOpaque */ UInt32 DLLDesignator; - /* somMethodPtr * */ UInt32 specialProcs; - /* somRuntimeClassInfo * */ UInt32 runtimeClassInfo; - SInt32 interesting; - /* somClassDataStructure ** */ UInt32 actualAncestry; - /* void * */ UInt32 extra[4]; - /* const somStaticClassCounts * */ UInt32 classCounts; - somStaticClassDescription classDescription; -} somStaticClassInfo; - -CSOMStub *csom_stubs; -static HashNameNode *csom_initname; -static HashNameNode *csom_uninitname; -static HashNameNode *csom_envname; -static HashNameNode *csom_selfname; - -static FuncArg SOMIDT_arg1 = { - NULL, - NULL, - NULL, - TYPE(&void_ptr), - 0, - 0, - 0, - 0 -}; - -static TypeFunc SOMIDT_type = { - TYPEFUNC, - 0, - &SOMIDT_arg1, - NULL, - TYPE(&void_ptr), - 0, - 0 -}; - -void CSOM_Setup(Boolean flag) { - if (!flag) - csom_stubs = NULL; - - csom_initname = GetHashNameNodeExport("somInit"); - csom_uninitname = GetHashNameNodeExport("somUninit"); - csom_envname = GetHashNameNodeExport("Environment"); - csom_selfname = GetHashNameNodeExport("__somself"); -} - -void CSOM_Cleanup(void) { - CSOMStub *stub; - - if (cparamblkptr->precompile != 1) { - for (stub = csom_stubs; stub; stub = stub->next) { - switch (stub->x10) { - case 0: - CodeGen_SOMStub(stub->object, rt_som_glue1, stub->tclass->sominfo->classdataobject, stub->offset); - break; - case 1: - CodeGen_SOMStub(stub->object, rt_som_glue2, stub->tclass->sominfo->classdataobject, stub->offset); - break; - case 2: - CodeGen_SOMStub(stub->object, rt_som_glue3, stub->tclass->sominfo->classdataobject, stub->offset); - break; - default: - CError_FATAL(132); - } - } - } -} - -static HashNameNode *CSOM_NameTranslate(HashNameNode *name) { - if (name == constructor_name_node) - name = csom_initname; - else if (name == destructor_name_node) - name = csom_uninitname; - return name; -} - -static Type *CSOM_FindClassType(HashNameNode *name) { - Type *type; - - type = CScope_GetTagType(cscope_current, name); - if (!type) { - CPrep_ErrorName(CErrorStr281, name->name); - type = &stvoid; - } - - return type; -} - -CW_INLINE UInt16 CSOM_GetTokenTableIndex(const Object *object) { - CError_ASSERT(173, IS_TYPE_METHOD(object->type)); - return TYPE_METHOD(object->type)->vtbl_index; -} - -static SInt32 CSOM_GetTokenOffset(Object *object) { - return 24 + 4 * CSOM_GetTokenTableIndex(object); -} - -typedef struct TypeSig { - UInt8 x0; - UInt8 x1; - UInt8 x2; -} TypeSig; - -static int CSOM_GetTypeSig(TypeSig *sig, Type *type, Boolean flag) { - if (type->size > 4) - sig->x1 |= fgAnyNon4Bytes; - - switch (type->type) { - case TYPEVOID: - if (flag) - return pdVoid; - break; - case TYPEINT: - case TYPEENUM: - if (is_unsigned(type)) { - switch (type->size) { - case 1: - sig->x1 |= fgShortOrChars; - return pdUByte; - case 2: - sig->x1 |= fgShortOrChars; - return pdUHalf; - case 4: - return pdULong; - case 8: - return pdVLong; - } - } else { - switch (type->size) { - case 1: - sig->x1 |= fgShortOrChars; - return pdSByte; - case 2: - sig->x1 |= fgShortOrChars; - return pdSHalf; - case 4: - return pdSLong; - case 8: - return pdVLong; - } - } - break; - case TYPEFLOAT: - sig->x1 |= fgAnyFloats; - switch (type->size) { - case 4: - sig->x1 |= fgShortFloats; - return pdSFlt; - case 8: - return pdDFlt; - case 12: - case 16: - return pdLFlt; - } - break; - case TYPEPOINTER: - return pdNPtr; - case TYPESTRUCT: - case TYPECLASS: - if (flag) { - if (type->size <= 2) { - sig->x1 |= fgShortOrChars; - return pdVSAgg; - } else if (type->size <= 4) { - return pdSAgg; - } else { - return pdLAgg; - } - } - break; - } - - CError_Error(CErrorStr273); - return 5; -} - -static void CSOM_GetFuncSig(TypeFunc *tfunc, Boolean flag) { - FuncArg *arg; - Boolean pendingData; - UInt8 work; - TypeSig sig; - - sig.x2 = CSOM_GetTypeSig(&sig, tfunc->functype, 1); - sig.x1 = 0; - sig.x0 = 0; - - for (arg = tfunc->args; arg; arg = arg->next) { - if (arg == &elipsis || arg == &oldstyle || (++sig.x0 == 0)) { - CError_Error(CErrorStr273); - break; - } - - CSOM_GetTypeSig(&sig, arg->type, 0); - } - - if (flag) { - if ((arg = tfunc->args)) { - if (TYPE_METHOD(tfunc)->is_static == 0) - arg = arg->next; - if (arg && CMach_GetFunctionResultClass(tfunc) != 0) - arg = arg->next; - } - - AppendGListByte(&name_mangle_list, sig.x0); - AppendGListByte(&name_mangle_list, (sig.x1 << 4) | sig.x2); - if (sig.x1) { - pendingData = 0; - work = 0; - while (arg) { - work = (work << 4) | CSOM_GetTypeSig(&sig, arg->type, 0); - if (pendingData) { - AppendGListByte(&name_mangle_list, work); - pendingData = 0; - work = 0; - } else { - pendingData = 1; - } - arg = arg->next; - } - - if (pendingData) - AppendGListByte(&name_mangle_list, work << 4); - } - } -} - -void CSOM_CheckFuncType(TypeFunc *tfunc) { - CSOM_GetFuncSig(tfunc, 0); -} - -static Object *CSOM_MakeObject(char *name1, char *name2, SInt32 size) { - Object *object = CParser_NewCompilerDefDataObject(); - object->name = CParser_NameConcat(name1, name2); - object->type = CDecl_NewStructType(size, 4); - CScope_AddObject(object->nspace, object->name, OBJ_BASE(object)); - return object; -} - -void CSOM_MakeSOMClass(TypeClass *tclass) { - ClassList *base; - - for (base = tclass->bases; base; base = base->next) { - if (!base->base->sominfo) { - CError_Error(CErrorStr267); - break; - } - } - - if (!tclass->sominfo) { - SOMInfo *info = galloc(sizeof(SOMInfo)); - memclrw(info, sizeof(SOMInfo)); - tclass->sominfo = info; - - info->classdataobject = CSOM_MakeObject(tclass->classname->name, "ClassData", 28); - info->classdataobject->flags = info->classdataobject->flags | OBJECT_EXPORT; - } -} - -static Boolean CSOM_IsTokenListFunc(Object *object) { - Type *type = object->type; - if ( - IS_TYPE_FUNC(type) && - !(TYPE_FUNC(type)->flags & FUNC_FLAGS_20) && - !TYPE_METHOD(type)->is_static && - (!(object->qual & Q_INLINE) || object->datatype == DVFUNC) - ) - return 1; - - return 0; -} - -static Object **CSOM_GetLexicalOrderMethodArray(TypeClass *tclass, int *resultCount) { - Object *object; - int count; - Object **array; - CScopeObjectIterator iter; - - count = 0; - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (IS_TYPE_METHOD(object->type)) { - if (CSOM_IsTokenListFunc(object)) { - if (TYPE_METHOD(object->type)->vtbl_index > count) - count = TYPE_METHOD(object->type)->vtbl_index; - } else { - TYPE_METHOD(object->type)->vtbl_index = 0; - } - } - } - - *resultCount = ++count; - - array = lalloc(sizeof(Object *) * count); - memclrw(array, sizeof(Object *) * count); - - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (CSOM_IsTokenListFunc(object)) - array[TYPE_METHOD(object->type)->vtbl_index] = object; - } - - return array; -} - -void CSOM_ClassComplete(TypeClass *tclass) { - Object *object; - CScopeObjectIterator iter; - SInt32 counter; - SOMReleaseOrder *order; - - if (tclass->sominfo->order) { - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (CSOM_IsTokenListFunc(object)) { - HashNameNode *name; - - name = CSOM_NameTranslate(object->name); - for (order = tclass->sominfo->order, counter = 0; order; order = order->next, counter++) { - if (order->name == name) { - order->state = SOMMS_Method; - TYPE_METHOD(object->type)->vtbl_index = counter; - break; - } - } - - if (!order) - CError_Error(CErrorStr278, object); - } - } - - for (order = tclass->sominfo->order; order; order = order->next) { - if (order->state == SOMMS_Deleted) { - SOMReleaseOrder *order2; - VClassList *vbase; - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - for (order2 = vbase->base->sominfo->order; order2; order2 = order2->next) { - if (order->name == order2->name && order2->state == SOMMS_Method) { - order->state = SOMMS_Migrated; - break; - } - } - } - } - } - } else { - Object **array; - int arrayCount; - SInt32 i; - - array = CSOM_GetLexicalOrderMethodArray(tclass, &arrayCount); - for (i = counter = 0; i < arrayCount; i++) { - object = array[i]; - if (object) { - if (counter == 0 && copts.pedantic) - CError_Warning(CErrorStr291); - TYPE_METHOD(object->type)->vtbl_index = counter++; - } - } - } - - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - NameSpaceObjectList *nsol; - if (!(nsol = CScope_NextObjectIteratorObjectList(&iter))) - break; - - if (nsol->object->otype == OT_OBJECT && nsol->next && nsol->next->object->otype == OT_OBJECT) { - while (nsol) { - if ( - nsol->object->otype == OT_OBJECT && - (!(OBJECT(nsol->object)->qual & Q_INLINE) || OBJECT(nsol->object)->datatype == DVFUNC) - ) - CError_Error(CErrorStr270, nsol->object); - nsol = nsol->next; - } - } - } - - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (!(object->qual & Q_INLINE)) { - CError_ASSERT(529, IS_TYPE_FUNC(object->type)); - - TYPE_FUNC(object->type)->flags |= FUNC_FLAGS_4; - tclass->action = CLASS_ACTION_1; - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (IS_TYPE_FUNC(object->type)) - TYPE_FUNC(object->type)->flags &= ~FUNC_FLAGS_4; - } - break; - } - } - - if (tclass->sominfo->oidl_callstyle == 0) { - Type *envType; - envType = CSOM_FindClassType(csom_envname); - - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if ( - IS_TYPE_FUNC(object->type) && - TYPE_METHOD(object->type)->is_static == 0 && - !(TYPE_FUNC(object->type)->flags & FUNC_FLAGS_20) && - !( - TYPE_FUNC(object->type)->args && - TYPE_FUNC(object->type)->args->next && - IS_TYPE_POINTER_ONLY(TYPE_FUNC(object->type)->args->next->type) && - TPTR_TARGET(TYPE_FUNC(object->type)->args->next->type) == envType - ) - ) - { - CError_Error(CErrorStr282, object); - } - } - } - - if (tclass->action == CLASS_ACTION_0) - CError_Error(CErrorStr280); -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct SOMOverride { - struct SOMOverride *next; - Object *a; - Object *b; -} SOMOverride; - -typedef struct SOMAncestor { - struct SOMAncestor *next; - TypeClass *tclass; - SOMOverride *overrides; - Boolean xC; - Boolean xD; -} SOMAncestor; - -typedef struct SOMMethod { - struct SOMMethod *next; - HashNameNode *name; - union { - Object *object; - struct { - UInt16 a; - UInt16 b; - } pair; - } u; - SOMMethodState state; -} SOMMethod; - -typedef struct SOMGenerator { - SOMMethod *methods; - SOMAncestor *ancestors; - Object *sciObj; - Object *classAncestorsObj; - Object *overrideProcsObj; - Object *dlldFunc; - Object *specialProcsObj; - somStaticClassCounts counts; - int overrideProcsCount; - Boolean hasNew; - Boolean hasDelete; -} SOMGenerator; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static SOMAncestor *CSOM_FindAddAncestor(SOMGenerator *gen, TypeClass *tclass, TypeClass *ancestorClass, UInt16 *resultIndex) { - SOMAncestor *ancestor; - SOMAncestor *scan; - UInt16 index; - - ancestor = gen->ancestors; - for (scan = ancestor, index = 0; scan; scan = scan->next, index++) { - if (scan->tclass == ancestorClass) { - if (resultIndex) - *resultIndex = index; - return scan; - } - } - - if (ancestor) { - index = 1; - while (ancestor->next) { - index++; - ancestor = ancestor->next; - } - - ancestor->next = lalloc(sizeof(SOMAncestor)); - memclrw(ancestor->next, sizeof(SOMAncestor)); - ancestor = ancestor->next; - } else { - index = 0; - ancestor = lalloc(sizeof(SOMAncestor)); - memclrw(ancestor, sizeof(SOMAncestor)); - gen->ancestors = ancestor; - } - - ancestor->tclass = ancestorClass; - if (resultIndex) - *resultIndex = index; - return ancestor; -} - -static void CSOM_GenerateOverrideIntroLists(SOMGenerator *gen, TypeClass *tclass) { - Object *object; - VClassList *vbase; - ClassList *base; - SOMMethod *method; - SOMMethod **ptr; - CScopeObjectIterator iter; - - for (base = tclass->bases; base; base = base->next) { - SOMAncestor *ancestor = CSOM_FindAddAncestor(gen, tclass, base->base, NULL); - ancestor->xD = 1; - gen->counts.numDirectParents++; - } - - if (tclass->sominfo->metaclass && tclass->sominfo->metaclass->sominfo) { - SOMAncestor *ancestor = CSOM_FindAddAncestor(gen, tclass, tclass->sominfo->metaclass, NULL); - ancestor->xC = 1; - gen->counts.numMetaClasses++; - } - - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (IS_TYPE_FUNC(object->type) && (TYPE_FUNC(object->type)->flags & FUNC_FLAGS_20)) { - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - Object *object2; - CScopeObjectIterator iter2; - CScope_InitObjectIterator(&iter2, vbase->base->nspace); - while (1) { - if (!(object2 = OBJECT(CScope_NextObjectIteratorObject(&iter2)))) - break; - - if ( - IS_TYPE_FUNC(object2->type) && - object->name == object2->name && - object2->datatype == DVFUNC && - !(TYPE_FUNC(object2->type)->flags & FUNC_FLAGS_20) && - CClass_GetOverrideKind(TYPE_FUNC(object->type), TYPE_FUNC(object2->type), 0) != 0 - ) - { - SOMAncestor *ancestor; - SOMOverride *override; - ancestor = CSOM_FindAddAncestor(gen, tclass, vbase->base, NULL); - if (ancestor->overrides) { - override = lalloc(sizeof(SOMOverride)); - memclrw(override, sizeof(SOMOverride)); - override->next = ancestor->overrides; - ancestor->overrides = override; - } else { - override = lalloc(sizeof(SOMOverride)); - memclrw(override, sizeof(SOMOverride)); - ancestor->overrides = override; - gen->counts.numOverriddenAncestors++; - } - override->a = object; - override->b = object2; - break; - } - } - } - gen->overrideProcsCount++; - } - } - - ptr = &gen->methods; - if (tclass->sominfo->order) { - SOMReleaseOrder *order; - SOMReleaseOrder *order2; - SInt32 index; - UInt16 index2; - - for (order = tclass->sominfo->order, index = 0; order; order = order->next, index++) { - method = lalloc(sizeof(SOMMethod)); - memclrw(method, sizeof(SOMMethod)); - *ptr = method; - ptr = &method->next; - - method->name = order->name; - method->state = order->state; - switch (order->state) { - case SOMMS_Migrated: - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - for (order2 = vbase->base->sominfo->order, index2 = 0; order2; order2 = order2->next, index2++) { - if (order->name == order2->name && order2->state == SOMMS_Method) { - CSOM_FindAddAncestor(gen, tclass, vbase->base, &method->u.pair.a); - method->u.pair.b = index2; - break; - } - } - - if (order2) - break; - } - gen->counts.numMigratedMethods++; - break; - - case SOMMS_Method: - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if ( - IS_TYPE_FUNC(object->type) && - CSOM_NameTranslate(object->name) == order->name - ) - { - CError_ASSERT(733, TYPE_METHOD(object->type)->vtbl_index == index); - method->u.object = object; - break; - } - } - - CError_ASSERT(737, object != NULL); - break; - } - - gen->counts.classTokenCount++; - } - } else { - Object **array; - int arrayCount; - SInt32 i; - - array = CSOM_GetLexicalOrderMethodArray(tclass, &arrayCount); - for (i = 0; i < arrayCount; i++) { - object = array[i]; - if (object) { - method = lalloc(sizeof(SOMMethod)); - memclrw(method, sizeof(SOMMethod)); - *ptr = method; - ptr = &method->next; - - method->u.object = object; - method->name = object->name; - method->state = SOMMS_Method; - gen->counts.classTokenCount++; - } - } - } -} - -static void CSOM_GenerateClassAncestors(SOMGenerator *gen, TypeClass *tclass) { - SOMAncestor *ancestor; - Object *object; - OLinkList *relocs; - SInt32 size; - char *buf; - - if (gen->ancestors) { - object = CSOM_MakeObject(tclass->classname->name, "ClassAncestors", 4); - object->sclass = TK_STATIC; - - relocs = NULL; - size = 0; - for (ancestor = gen->ancestors; ancestor; ancestor = ancestor->next) { - OLinkList *reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = ancestor->tclass->sominfo->classdataobject; - reloc->offset = size; - reloc->somevalue = 0; - size += 4; - } - - buf = lalloc(size); - memclrw(buf, size); - object->type->size = size; - CInit_DeclareData(object, buf, relocs, object->type->size); - gen->classAncestorsObj = object; - } -} - -static void CSOM_GenerateOverrideProcs(SOMGenerator *gen, TypeClass *tclass) { - SOMOverride *override; - SOMAncestor *ancestor; - Object *object; - OLinkList *relocs; - SInt32 size; - SInt32 offset; - char *buf; - - if (gen->overrideProcsCount) { - size = gen->overrideProcsCount * 4; - object = CSOM_MakeObject(tclass->classname->name, "OverrideProcs", size); - object->sclass = TK_STATIC; - - relocs = NULL; - offset = 0; - for (ancestor = gen->ancestors; ancestor; ancestor = ancestor->next) { - if (ancestor->overrides) { - for (override = ancestor->overrides; override; override = override->next) { - OLinkList *reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = override->a; - reloc->offset = offset; - reloc->somevalue = 0; - offset += 4; - } - } - } - - buf = lalloc(size); - memclrw(buf, size); - CInit_DeclareData(object, buf, relocs, object->type->size); - gen->overrideProcsObj = object; - } -} - -static Object *CSOM_GenerateOverrideData(SOMGenerator *gen) { - SOMAncestor *ancestor; - Object *object; - short ancestorIndex; - - name_mangle_list.size = 0; - for (ancestor = gen->ancestors, ancestorIndex = 0; ancestor; ancestor = ancestor->next, ancestorIndex++) { - if (ancestor->overrides) { - SOMOverride *override; - short overrideCount; - - AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(ancestorIndex)); - - override = ancestor->overrides; - overrideCount = 0; - while (override) { - overrideCount++; - override = override->next; - } - AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(overrideCount)); - - for (override = ancestor->overrides; override; override = override->next) { - AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(CSOM_GetTokenTableIndex(override->b))); - } - } - } - - COS_LockHandle(name_mangle_list.data); - object = CInit_DeclareString(*name_mangle_list.data, name_mangle_list.size, 0, 0); - COS_UnlockHandle(name_mangle_list.data); - return object; -} - -static Object *CSOM_GenerateMigrateData(SOMGenerator *gen) { - SOMMethod *method; - Object *object; - int index; - - name_mangle_list.size = 0; - for (method = gen->methods, index = 0; method; method = method->next, index++) { - if (method->state == SOMMS_Migrated) { - AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(method->u.pair.a)); - AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(method->u.pair.b)); - AppendGListWord(&name_mangle_list, CTool_EndianConvertWord16(index)); - } - } - - COS_LockHandle(name_mangle_list.data); - object = CInit_DeclareString(*name_mangle_list.data, name_mangle_list.size, 0, 0); - COS_UnlockHandle(name_mangle_list.data); - return object; -} - -static void CSOM_GenerateDLLDFunc(SOMGenerator *gen, TypeClass *tclass) { - TypeFunc *tfunc; - Object *object; - - tfunc = galloc(sizeof(TypeFunc)); - memclrw(tfunc, sizeof(TypeFunc)); - tfunc->type = TYPEFUNC; - tfunc->functype = &stvoid; - - object = CParser_NewCompilerDefFunctionObject(); - object->type = TYPE(tfunc); - object->sclass = TK_STATIC; - object->name = CParser_NameConcat(tclass->classname->name, "DLLD"); - - if (CScope_GetLocalObject(cscope_root, object->name)) - CError_Error(CErrorStr333, object); - - gen->dlldFunc = object; - CFunc_GenerateDummyFunction(object); -} - -static void CSOM_GenerateSpecialProcs(SOMGenerator *gen, TypeClass *tclass) { - Object *newFunc; - Object *deleteFunc; - Object *object; - OLinkList *relocs; - SInt32 size; - CScopeObjectIterator iter; - char buf[16]; - - newFunc = deleteFunc = NULL; - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (IS_TYPE_FUNC(object->type)) { - if (object->name == CMangler_OperatorName(TK_NEW)) { - newFunc = object; - gen->hasNew = 1; - } else if (object->name == CMangler_OperatorName(TK_DELETE)) { - deleteFunc = object; - gen->hasDelete = 1; - } - } - } - - if (newFunc || deleteFunc) { - object = CSOM_MakeObject(tclass->classname->name, "SpecialProcs", 4); - object->sclass = TK_STATIC; - - relocs = NULL; - size = 0; - - if (newFunc) { - OLinkList *reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = newFunc; - reloc->offset = size; - reloc->somevalue = 0; - size += 4; - } - - if (deleteFunc) { - OLinkList *reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = deleteFunc; - reloc->offset = size; - reloc->somevalue = 0; - size += 4; - } - - memclrw(buf, sizeof(buf)); - object->type->size = size; - CInit_DeclareData(object, buf, relocs, object->type->size); - gen->specialProcsObj = object; - } -} - -static Object *CSOM_GenerateParentVersion(SOMGenerator *gen) { - SInt32 size; - UInt32 *buf; - SOMAncestor *ancestor; - SInt32 offset; - - size = 8 * (gen->counts.numDirectParents + gen->counts.numMetaClasses); - buf = lalloc(size); - - for (ancestor = gen->ancestors, offset = 0; ancestor; ancestor = ancestor->next) { - if (ancestor->xC || ancestor->xD) { - buf[offset++] = CTool_EndianConvertWord32(ancestor->tclass->sominfo->majorversion); - buf[offset++] = CTool_EndianConvertWord32(ancestor->tclass->sominfo->minorversion); - } - } - - return CInit_DeclareString((char *) buf, size, 0, 0); -} - -static void CSOM_SetNibble(char *buf, int offset, UInt8 value) { - int i = offset >> 1; - if (offset & 1) { - int left = buf[i] & 0xF0; - int right = value & 0xF; - buf[i] = left | right; - } else { - int left = value << 4; - int right = buf[i] & 0xF; - buf[i] = left | right; - } -} - -static Object *CSOM_GenerateSlotUsage(SOMGenerator *gen) { - SInt32 size; - SOMMethod *method; - char *buf; - int offset; - - size = (gen->counts.classTokenCount + 1) / 2; - buf = lalloc(size); - memclrw(buf, size); - - for (method = gen->methods, offset = 0; method; method = method->next, offset++) { - switch (method->state) { - case SOMMS_Deleted: - case SOMMS_Migrated: - CSOM_SetNibble(buf, offset, mtEmpty); - break; - case SOMMS_Method: - CSOM_SetNibble(buf, offset, mtVirtualMethod); - break; - default: - CError_FATAL(1048); - } - } - - return CInit_DeclareString(buf, size, 0, 0); -} - -static Object *CSOM_GenerateSignature(SOMGenerator *gen) { - Object *object; - SOMMethod *method; - - name_mangle_list.size = 0; - - for (method = gen->methods; method; method = method->next) { - if (method->state == SOMMS_Method) - CSOM_GetFuncSig(TYPE_FUNC(method->u.object->type), 1); - } - - COS_LockHandle(name_mangle_list.data); - object = CInit_DeclareString(*name_mangle_list.data, name_mangle_list.size, 0, 0); - COS_UnlockHandle(name_mangle_list.data); - return object; -} - -static Object *CSOM_GenerateMethodNames(SOMGenerator *gen) { - Object *object; - SOMMethod *method; - HashNameNode *name; - - name_mangle_list.size = 0; - - for (method = gen->methods; method; method = method->next) { - if (method->name) { - name = CSOM_NameTranslate(method->name); - AppendGListID(&name_mangle_list, name->name); - } - } - - COS_LockHandle(name_mangle_list.data); - object = CInit_DeclareString(*name_mangle_list.data, name_mangle_list.size, 0, 0); - COS_UnlockHandle(name_mangle_list.data); - return object; -} - -static void CSOM_SetupClassCounts(SOMGenerator *gen, TypeClass *tclass, somStaticClassCounts *counts) { - gen->counts.majorVersion = tclass->sominfo->majorversion; - gen->counts.minorVersion = tclass->sominfo->minorversion; - gen->counts.flags = cfSharedStrings; - if (gen->hasNew) - gen->counts.flags |= cfClassAllocate; - if (gen->hasDelete) - gen->counts.flags |= cfClassDeallocate; - - switch (tclass->align) { - case 1: - gen->counts.dataAlignment = 0; - break; - case 2: - gen->counts.dataAlignment = 1; - break; - case 4: - gen->counts.dataAlignment = 2; - break; - case 8: - gen->counts.dataAlignment = 3; - break; - default: - gen->counts.dataAlignment = 4; - break; - } - - gen->counts.numSelectInherited = 0; - - memclrw(counts, sizeof(somStaticClassCounts)); - counts->majorVersion = CTool_EndianConvertWord32(gen->counts.majorVersion); - counts->minorVersion = CTool_EndianConvertWord32(gen->counts.minorVersion); - counts->flags = CTool_EndianConvertWord32(gen->counts.flags); - counts->dataAlignment = CTool_EndianConvertWord16(gen->counts.dataAlignment); - counts->classTokenCount = CTool_EndianConvertWord16(gen->counts.classTokenCount); - counts->numDirectParents = CTool_EndianConvertWord16(gen->counts.numDirectParents); - counts->numMetaClasses = CTool_EndianConvertWord16(gen->counts.numMetaClasses); - counts->numOverriddenAncestors = CTool_EndianConvertWord16(gen->counts.numOverriddenAncestors); - counts->numMigratedMethods = CTool_EndianConvertWord16(gen->counts.numMigratedMethods); - counts->numSelectInherited = CTool_EndianConvertWord16(gen->counts.numSelectInherited); -} - -static void CSOM_GenerateSCIObject(SOMGenerator *gen, TypeClass *tclass) { - Object *object; - OLinkList *relocs; - OLinkList *reloc; - somStaticClassInfo sci; - somStaticClassCounts classCounts; - - object = CSOM_MakeObject(tclass->classname->name, "SCI", sizeof(sci)); - object->sclass = TK_STATIC; - - memclrw(&sci, sizeof(sci)); - sci.layoutVersion = CTool_EndianConvertWord32(70); - - reloc = lalloc(sizeof(OLinkList)); - reloc->next = NULL; - relocs = reloc; - reloc->obj = tclass->sominfo->classdataobject; - reloc->offset = 4; - reloc->somevalue = 0; - - if (gen->overrideProcsObj) { - reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = gen->overrideProcsObj; - reloc->offset = 8; - reloc->somevalue = 0; - } - - if (gen->classAncestorsObj) { - reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = gen->classAncestorsObj; - reloc->offset = 12; - reloc->somevalue = 0; - } - - if (gen->dlldFunc) { - reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = gen->dlldFunc; - reloc->offset = 16; - reloc->somevalue = 0; - } - - if (gen->specialProcsObj) { - reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = gen->specialProcsObj; - reloc->offset = 20; - reloc->somevalue = 0; - } - - CSOM_SetupClassCounts(gen, tclass, &classCounts); - - reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = CInit_DeclareString((char *) &classCounts, sizeof(classCounts), 0, 0); - reloc->offset = 52; - reloc->somevalue = 0; - - reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = CInit_DeclareString(tclass->classname->name, strlen(tclass->classname->name) + 1, 0, 0); - reloc->offset = 56; - reloc->somevalue = 0; - - sci.classDescription.instanceDataSize = CTool_EndianConvertWord32(tclass->size); - - reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = CSOM_GenerateParentVersion(gen); - reloc->offset = 64; - reloc->somevalue = 0; - - if (gen->methods) { - reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = CSOM_GenerateSlotUsage(gen); - reloc->offset = 68; - reloc->somevalue = 0; - - reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = CSOM_GenerateSignature(gen); - reloc->offset = 72; - reloc->somevalue = 0; - - reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = CSOM_GenerateMethodNames(gen); - reloc->offset = 76; - reloc->somevalue = 0; - } - - if (gen->overrideProcsObj) { - reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = CSOM_GenerateOverrideData(gen); - reloc->offset = 80; - reloc->somevalue = 0; - } - - if (gen->counts.numMigratedMethods) { - reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = CSOM_GenerateMigrateData(gen); - reloc->offset = 84; - reloc->somevalue = 0; - } - - sci.classDescription.selectedInherited = 0; - - CInit_DeclareData(object, &sci, relocs, object->type->size); - gen->sciObj = object; -} - -static void CSOM_GenerateClassDataObject(SOMGenerator *gen, TypeClass *tclass) { - void *buf; - OLinkList *relocs; - OLinkList *reloc; - SInt32 size; - SOMMethod *method; - - relocs = NULL; - for (size = 24, method = gen->methods; method; method = method->next) { - if (method->state == SOMMS_Method) { - reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = method->u.object; - reloc->offset = size; - reloc->somevalue = 0; - } - size += 4; - } - - buf = lalloc(size); - memclrw(buf, size); - - reloc = lalloc(sizeof(OLinkList)); - reloc->next = relocs; - relocs = reloc; - reloc->obj = gen->sciObj; - reloc->offset = 4; - reloc->somevalue = 0; - - tclass->sominfo->classdataobject->type->size = size; - CInit_DeclareData(tclass->sominfo->classdataobject, buf, relocs, tclass->sominfo->classdataobject->type->size); -} - -void CSOM_GenerateClassStructures(TypeClass *tclass) { - SOMGenerator gen; - - memclrw(&gen, sizeof(gen)); - CSOM_GenerateOverrideIntroLists(&gen, tclass); - CSOM_GenerateClassAncestors(&gen, tclass); - CSOM_GenerateOverrideProcs(&gen, tclass); - CSOM_GenerateDLLDFunc(&gen, tclass); - CSOM_GenerateSpecialProcs(&gen, tclass); - CSOM_GenerateSCIObject(&gen, tclass); - CSOM_GenerateClassDataObject(&gen, tclass); -} - -static TypeClass *CSOM_GetCurrentSOMClass(void) { - if (cscope_current->theclass && cscope_current->theclass->sominfo) - return cscope_current->theclass; - - CError_Error(CErrorStr277); - return NULL; -} - -void CSOM_PragmaReleaseOrder(void) { - TypeClass *tclass; - SOMReleaseOrder *firstOrder; - SOMReleaseOrder *order; - SOMReleaseOrder **ptr; - Boolean flag; - short token; - - if (!(tclass = CSOM_GetCurrentSOMClass())) - return; - - token = CPrep_PragmaLex(0); - if (token != '(') { - if (token != TK_IDENTIFIER) { - CPrep_Error(CErrorStr114); - return; - } - - if (!strcmp(tkidentifier->name, "list")) { - token = CPrep_PragmaLex(0); - if (token != TK_IDENTIFIER) { - CPrep_Error(CErrorStr107); - return; - } - } - - flag = 1; - } else { - flag = 0; - token = CPrep_PragmaLex(0); - } - - firstOrder = NULL; - if (flag || token != ')') { - ptr = &firstOrder; - while (1) { - if (token != TK_IDENTIFIER) { - CPrep_Error(CErrorStr107); - return; - } - - for (order = firstOrder; order; order = order->next) { - if (order->name == tkidentifier) { - CError_Error(CErrorStr122, tkidentifier->name); - return; - } - } - - order = galloc(sizeof(SOMReleaseOrder)); - *ptr = order; - ptr = &order->next; - - order->next = NULL; - order->name = tkidentifier; - order->state = SOMMS_Deleted; - - if (flag) { - token = CPrep_PragmaLex(1); - if (!token) - break; - } else { - token = CPrep_PragmaLex(0); - if (token == ')') - break; - } - - if (token != ',') { - CPrep_Error(CErrorStr116); - return; - } - - token = CPrep_PragmaLex(flag); - } - } - - tclass->sominfo->order = firstOrder; -} - -void CSOM_PragmaClassVersion(void) { - Type *type; - - if (CPrep_PragmaLex(0) != '(') { - CPrep_Error(CErrorStr114); - return; - } - - if (CPrep_PragmaLex(0) != TK_IDENTIFIER) { - CPrep_Error(CErrorStr107); - return; - } - - type = CScope_GetTagType(cscope_current, tkidentifier); - if (!(type && IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo)) { - CPrep_ErrorName(CErrorStr276, tkidentifier->name); - return; - } - - if (CPrep_PragmaLex(0) != ',') { - CPrep_Error(CErrorStr116); - return; - } - - if (CPrep_PragmaLex(0) != TK_INTCONST) { - CPrep_Error(CErrorStr186); - return; - } - - TYPE_CLASS(type)->sominfo->majorversion = CInt64_GetULong(&tkintconst); - - if (CPrep_PragmaLex(0) != ',') { - CPrep_Error(CErrorStr116); - return; - } - - if (CPrep_PragmaLex(0) != TK_INTCONST) { - CPrep_Error(CErrorStr186); - return; - } - - TYPE_CLASS(type)->sominfo->minorversion = CInt64_GetULong(&tkintconst); - - if (CPrep_PragmaLex(0) != ')') { - CPrep_Error(CErrorStr115); - return; - } -} - -void CSOM_PragmaMetaClass(void) { - Type *type; - Type *type2; - - if (CPrep_PragmaLex(0) != '(') { - CPrep_Error(CErrorStr114); - return; - } - - if (CPrep_PragmaLex(0) != TK_IDENTIFIER) { - CPrep_Error(CErrorStr107); - return; - } - - type = CScope_GetTagType(cscope_current, tkidentifier); - if (!(type && IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo)) { - CPrep_ErrorName(CErrorStr276, tkidentifier->name); - return; - } - - if (CPrep_PragmaLex(0) != ',') { - CPrep_Error(CErrorStr116); - return; - } - - if (CPrep_PragmaLex(0) != TK_IDENTIFIER) { - CPrep_Error(CErrorStr107); - return; - } - - type2 = CScope_GetTagType(cscope_current, tkidentifier); - if (!(type2 && IS_TYPE_CLASS(type2) && TYPE_CLASS(type2)->sominfo)) { - CPrep_ErrorName(CErrorStr276, tkidentifier->name); - return; - } - - TYPE_CLASS(type)->sominfo->metaclass = TYPE_CLASS(type2); - - if (CPrep_PragmaLex(0) != ')') { - CPrep_Error(CErrorStr115); - return; - } -} - -void CSOM_PragmaCallStyle(void) { - TypeClass *tclass; - - if (!(tclass = CSOM_GetCurrentSOMClass())) - return; - - if (CPrep_PragmaLex(0) != TK_IDENTIFIER) { - CPrep_Error(CErrorStr107); - return; - } - - if (!strcmp(tkidentifier->name, "IDL")) { - tclass->sominfo->oidl_callstyle = 0; - return; - } - - if (!strcmp(tkidentifier->name, "OIDL")) { - tclass->sominfo->oidl_callstyle = 1; - return; - } - - CPrep_Error(CErrorStr186); -} - -void CSOM_FixNewDeleteFunctype(TypeFunc *tfunc) { - FuncArg *arg = CParser_NewFuncArg(); - arg->name = GetHashNameNodeExport("__theclass"); - arg->type = CDecl_NewPointerType(CSOM_FindClassType(GetHashNameNodeExport("SOMClass"))); - arg->next = tfunc->args; - tfunc->args = arg; -} - -static Object *CSOM_FindRTFunc(char *namestr, char *sig) { - NameSpaceObjectList *nsol; - Object *object; - FuncArg *arg; - - if ( - (nsol = CScope_GetLocalObject(cscope_root, GetHashNameNodeExport(namestr))) && - nsol->object->otype == OT_OBJECT - ) - { - object = OBJECT(nsol->object); - if ( - IS_TYPE_FUNC(object->type) && - *(sig++) == 'p' && - IS_TYPE_POINTER_ONLY(TYPE_FUNC(object->type)->functype) - ) - { - for (arg = TYPE_FUNC(object->type)->args; arg; arg = arg->next) { - switch (*(sig++)) { - case 'p': - if (IS_TYPE_POINTER_ONLY(arg->type)) - continue; - break; - case 'i': - if (arg->type == TYPE(&stsignedint)) - continue; - break; - case 'I': - if (arg->type == TYPE(&stunsignedint)) - continue; - break; - case 'l': - if (arg->type == TYPE(&stsignedlong)) - continue; - break; - case 'L': - if (arg->type == TYPE(&stunsignedlong)) - continue; - break; - } - break; - } - - if (arg == NULL && *sig == 0) - return object; - } - - CError_Error(CErrorStr275, namestr); - } else { - CError_Error(CErrorStr274, namestr); - } - - return NULL; -} - -static ENode *CSOM_MakeTempCondition(ENode *left, ENode *cond, ENode *expr1, ENode *right) { - ENode *expr; - - expr = lalloc(sizeof(ENode)); - expr->type = ECOND; - expr->cost = 0; - expr->flags = 0; - expr->rtype = &stvoid; - expr->data.cond.cond = cond; - expr->data.cond.expr1 = expr1; - expr->data.cond.expr2 = nullnode(); - expr->data.cond.expr2->rtype = &stvoid; - - if (left) - expr = makediadicnode(left, expr, ECOMMA); - - if (right) { - expr = makediadicnode(expr, right, ECOMMA); - expr->rtype = right->rtype; - } - - return expr; -} - -ENode *CSOM_New(TypeClass *tclass) { - Object *newFunc; - ENode *expr; - - if (tk == '(') { - if ((tk = lex()) == ')') { - tk = lex(); - } else { - CError_Error(CErrorStr272); - } - } - - if (!copts.som_env_check || !copts.som_call_optimize) { - newFunc = CSOM_FindRTFunc("somNewObjectInstance", "ppll"); - if (!newFunc) - return nullnode(); - } else { - newFunc = rt_som_new; - } - - expr = funccallexpr( - newFunc, - create_objectrefnode(tclass->sominfo->classdataobject), - intconstnode(TYPE(&stunsignedlong), tclass->sominfo->majorversion), - intconstnode(TYPE(&stunsignedlong), tclass->sominfo->minorversion), - NULL - ); - expr->rtype = CDecl_NewPointerType(TYPE(tclass)); - - if (copts.som_env_check && !copts.som_call_optimize) { - ENode *tempExpr; - ENode *checkExpr; - ENode *notExpr; - tempExpr = CExpr_GetETEMPCopy(expr); - checkExpr = funccallexpr(rt_som_newcheck, nullnode(), NULL, NULL, NULL); - notExpr = makemonadicnode(tempExpr, ELOGNOT); - notExpr->rtype = CParser_GetBoolType(); - expr = CSOM_MakeTempCondition(NULL, notExpr, checkExpr, tempExpr); - } - - return expr; -} - -ENode *CSOM_Delete(TypeClass *tclass, ENode *objExpr) { - Object *func; - - if ((func = CSOM_FindRTFunc("somReleaseObjectReference", "pp"))) - return funccallexpr(func, objExpr, NULL, NULL, NULL); - - return nullnode(); -} - -void CSOM_InitAutoClass(Object *object) { - Type *type; - Statement *stmt; - Object *func; - - if ((func = CSOM_FindRTFunc("somReleaseObjectReference", "pp"))) { - type = object->type; - object->type = CDecl_NewPointerType(type); - TPTR_QUAL(object->type) = Q_REFERENCE; - - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = makediadicnode(create_objectnode2(object), CSOM_New(TYPE_CLASS(type)), EASS); - CExcept_RegisterDeleteObject(stmt, object, func); - } -} - -static void CSOM_FindIntroClassOffset(TypeClass *tclass, Object *func, TypeClass **resultClass, SInt32 *resultOffset) { - Object *scan; - VClassList *vbase; - CScopeObjectIterator iter; - - if (!(TYPE_FUNC(func->type)->flags & FUNC_FLAGS_20)) { - CScope_InitObjectIterator(&iter, tclass->nspace); - while (1) { - if (!(scan = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (scan == func) { - *resultClass = tclass; - *resultOffset = CSOM_GetTokenOffset(scan); - return; - } - } - - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - CScope_InitObjectIterator(&iter, vbase->base->nspace); - while (1) { - if (!(scan = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (scan == func) { - *resultClass = vbase->base; - *resultOffset = CSOM_GetTokenOffset(scan); - return; - } - } - } - } else { - for (vbase = tclass->vbases; vbase; vbase = vbase->next) { - CScope_InitObjectIterator(&iter, vbase->base->nspace); - while (1) { - if (!(scan = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - break; - - if (scan->name == func->name) { - if ( - IS_TYPE_FUNC(scan->type) && - scan->datatype == DVFUNC && - !(TYPE_FUNC(scan->type)->flags & FUNC_FLAGS_20) && - CClass_GetOverrideKind(TYPE_FUNC(func->type), TYPE_FUNC(scan->type), 0) - ) - { - *resultClass = vbase->base; - *resultOffset = CSOM_GetTokenOffset(scan); - return; - } - break; - } - } - } - } - - CError_FATAL(1731); -} - -static ENode *CSOM_ComputeSOMSelf(TypeClass *tclass, ENode *selfExpr) { - ENode *expr; - Object obj; - - expr = create_objectrefnode(tclass->sominfo->classdataobject); - expr = makediadicnode(expr, intconstnode(TYPE(&stsignedlong), 8), EADD); - expr->rtype = CDecl_NewPointerType(TYPE(&SOMIDT_type)); - expr = makemonadicnode(expr, EINDIRECT); - - memclrw(&obj, sizeof(Object)); - obj.otype = OT_OBJECT; - obj.type = TYPE(&SOMIDT_type); - obj.name = no_name_node; - obj.datatype = DFUNC; - selfExpr = funccallexpr(&obj, selfExpr, NULL, NULL, NULL); - - CError_ASSERT(1761, ENODE_IS(selfExpr, EFUNCCALL)); - - selfExpr->data.funccall.funcref = expr; - - return selfExpr; -} - -ENode *CSOM_SOMSelfObjectExpr(TypeClass *tclass) { - ObjectList *list; - Object *obj; - - for (list = locals; list; list = list->next) { - if (list->object->name == csom_selfname) - return create_objectnode(list->object); - } - - obj = CParser_NewLocalDataObject(NULL, 1); - obj->name = csom_selfname; - obj->type = CDecl_NewPointerType(TYPE(tclass)); - CFunc_SetupLocalVarInfo(obj); - return create_objectnode(obj); -} - -void CSOM_InitSOMSelf(TypeClass *tclass, Statement *stmt) { - ObjectList *list; - HashNameNode *name; - ENode *selfExpr; - - name = GetHashNameNodeExport("__somself"); - for (list = locals; list; list = list->next) { - if (list->object->name == name) { - selfExpr = CClass_CreateThisSelfExpr(); - CError_ASSERT(1811, selfExpr); - - selfExpr = CSOM_ComputeSOMSelf(tclass, selfExpr); - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = makediadicnode(create_objectnode(list->object), selfExpr, EASS); - break; - } - } -} - -ENode *CSOM_EnvCheck(ENode *funccall, ENodeList *checkArg) { - ENodeList *arg; // r26 - ENodeList *arg2; // r28 - ENode *expr26; // r26 - ENode *expr27; // r27 - ENode *expr28; // r28 - Type *returnType; // r31 - - returnType = funccall->rtype; - CError_ASSERT(1842, arg = funccall->data.funccall.args); - - if (arg == checkArg) - CError_ASSERT(1845, arg = arg->next); - - CError_ASSERT(1847, arg2 = arg->next); - - if (arg2 == checkArg) - CError_ASSERT(1850, arg2 = arg2->next); - - CError_ASSERT(1852, IS_TYPE_POINTER_ONLY(arg2->node->rtype)); - - if (!IS_TYPE_VOID(funccall->data.funccall.functype->functype)) { - if (checkArg) { - if (ENODE_IS(checkArg->node, ETEMP)) { - if (checkArg->node->data.temp.uniqueid == 0) - checkArg->node->data.temp.uniqueid = CParser_GetUniqueID(); - - expr26 = lalloc(sizeof(ENode)); - *expr26 = *checkArg->node; - expr26->data.temp.needs_dtor = 0; - } else { - expr26 = CExpr_GetETEMPCopy(checkArg->node); - } - } else { - expr26 = CExpr_GetETEMPCopy(funccall); - } - } else { - expr26 = NULL; - } - - if (!ENODE_IS(arg2->node, EOBJREF)) { - if (ENODE_IS_INDIRECT_TO(arg2->node, EOBJREF) && arg2->node->data.monadic->data.objref->datatype == DLOCAL) { - expr27 = lalloc(sizeof(ENode)); - *expr27 = *arg2->node; - } else { - expr27 = CExpr_GetETEMPCopy(arg2->node); - } - } else { - expr27 = lalloc(sizeof(ENode)); - *expr27 = *arg2->node; - } - - if (copts.som_call_optimize) { - funccall = makediadicnode(funccall, funccallexpr(rt_som_check, expr27, NULL, NULL, NULL), ECOMMA); - if (expr26) - funccall = makediadicnode(funccall, expr26, ECOMMA); - } else { - expr28 = lalloc(sizeof(ENode)); - *expr28 = *expr27; - expr28 = makemonadicnode(expr28, EINDIRECT); - expr28->rtype = TYPE(&stsignedlong); - - funccall = CSOM_MakeTempCondition( - funccall, - expr28, - funccallexpr(rt_som_check, expr27, NULL, NULL, NULL), - expr26); - } - - funccall->rtype = returnType; - return funccall; -} - -static Boolean CSOM_CanUseGlueCall(TypeFunc *tfunc) { - int gprCounter; - int fprCounter; - FuncArg *arg; - - gprCounter = 8; - fprCounter = 13; - if (CMach_GetFunctionResultClass(tfunc) != 0) - gprCounter = 7; - - for (arg = tfunc->args; arg; arg = arg->next) { - if (arg == &elipsis || arg == &oldstyle) - return 0; - - switch (arg->type->type) { - case TYPEINT: - case TYPEENUM: - case TYPEPOINTER: - if (--gprCounter < 0) - return 0; - break; - case TYPEFLOAT: - if (--fprCounter < 0) - return 0; - break; - default: - return 0; - } - } - - return 1; -} - -static char *CSOM_AppendString(char *dst, char *src) { - int ch; - while ((ch = *(src++))) - *(dst++) = ch; - return dst; -} - -static ENode *CSOM_SOMGlueCall(TypeClass *tclass, SInt32 offset, Object *object) { - UInt8 funcResultClass; - UInt32 bufsize; - char *buf; - char *ptr; - Object *stubObj; - CSOMStub *stub; - ENode *expr; - char mybuf[256]; - char numberbuf[16]; - - for (stub = csom_stubs; stub; stub = stub->next) { - if (stub->tclass == tclass && stub->offset == offset) - break; - } - - if (!stub) { - funcResultClass = CMach_GetFunctionResultClass(TYPE_FUNC(object->type)); - - bufsize = strlen(tclass->sominfo->classdataobject->name->name) + 32; - buf = (bufsize > sizeof(mybuf)) ? lalloc(bufsize) : mybuf; - - ptr = CSOM_AppendString(buf, "___glue_"); - if (tclass->sominfo->oidl_callstyle == 0) { - if (funcResultClass == 0) { - *(ptr++) = '4'; - } else { - *(ptr++) = '5'; - } - } else { - *(ptr++) = '_'; - } - *(ptr++) = '_'; - - sprintf(numberbuf, "%ld", strlen(tclass->sominfo->classdataobject->name->name)); - ptr = CSOM_AppendString(ptr, numberbuf); - ptr = CSOM_AppendString(ptr, tclass->sominfo->classdataobject->name->name); - *(ptr++) = '_'; - sprintf(numberbuf, "%" PRId32, offset); - ptr = CSOM_AppendString(ptr, numberbuf); - *ptr = 0; - - stubObj = CParser_NewCompilerDefFunctionObject(); - stubObj->nspace = cscope_root; - stubObj->name = GetHashNameNodeExport(buf); - stubObj->u.func.linkname = stubObj->name; - stubObj->type = object->type; - stubObj->qual = object->qual | Q_20000; - stubObj->flags = OBJECT_INTERNAL; - CScope_AddObject(stubObj->nspace, stubObj->name, OBJ_BASE(stubObj)); - - stub = galloc(sizeof(CSOMStub)); - stub->next = csom_stubs; - stub->object = stubObj; - stub->tclass = tclass; - stub->offset = offset; - csom_stubs = stub; - - if (tclass->sominfo->oidl_callstyle == 0) { - if (funcResultClass == 0) - stub->x10 = 0; - else - stub->x10 = 1; - } else { - stub->x10 = 2; - } - } - - expr = create_objectrefnode(stub->object); - expr->rtype = CDecl_NewPointerType(object->type); - return expr; -} - -ENode *CSOM_MemberVarAccess(BClassList *path, ObjMemberVar *ivar, ENode *thisExpr) { - if (!thisExpr) { - if ( - !cscope_currentfunc || - !cscope_currentclass || - !cscope_is_member_func || - !(thisExpr = CClass_CreateThisSelfExpr()) - ) - { - CError_Error(CErrorStr221); - return NULL; - } - } - - CError_ASSERT(2069, ENODE_IS(thisExpr, EINDIRECT)); - - thisExpr = thisExpr->data.monadic; - - if ( - path->next == NULL && - cscope_currentclass == TYPE_CLASS(path->type) && - ENODE_IS(thisExpr, EOBJREF) && - thisExpr->data.objref->name == this_name_node - ) - { - thisExpr = CSOM_SOMSelfObjectExpr(cscope_currentclass); - } - else - { - CClass_CheckPathAccess(path, NULL, ivar->access); - if (ivar->has_path) - path = OBJ_MEMBER_VAR_PATH(ivar)->path; - while (path->next) - path = path->next; - thisExpr = CSOM_ComputeSOMSelf(TYPE_CLASS(path->type), thisExpr); - } - - thisExpr = makemonadicnode(thisExpr, EINDIRECT); - thisExpr->rtype = path->type; - return CClass_AccessMember(thisExpr, ivar->type, ivar->qual, ivar->offset); -} - -ENode *CSOM_MethodAccess(BClassList *path, Object *func, Boolean flag) { - TypeClass *tclass; - TypeClass *tclass2; - TypeClass *tclass3; - ENode *expr; - SInt32 offset; - ClassList *base; - - CError_ASSERT(2107, path != NULL); - - tclass = TYPE_CLASS(path->type); - if (path->next) - path = path->next; - tclass2 = TYPE_CLASS(path->type); - - if (flag) { - SInt32 counter; - ENode *indirectExpr; - Object *resolveFunc; - - counter = 0; - if (tclass != tclass2) { - for (base = tclass->bases; base; base = base->next) { - counter++; - if (base->base == tclass2) - break; - } - - if (!base) - CError_Error(CErrorStr279); - } - - CSOM_FindIntroClassOffset(tclass2, func, &tclass3, &offset); - expr = create_objectrefnode(tclass3->sominfo->classdataobject); - expr = makediadicnode(expr, intconstnode(TYPE(&stsignedlong), offset), EADD); - indirectExpr = makemonadicnode(expr, EINDIRECT); - indirectExpr->rtype = CDecl_NewPointerType(func->type); - - resolveFunc = CSOM_FindRTFunc("somParentNumResolve", "ppip"); - if (!resolveFunc) - return nullnode(); - - expr = funccallexpr( - resolveFunc, - create_objectrefnode(tclass->sominfo->classdataobject), - intconstnode(TYPE(&stsignedint), counter), - indirectExpr, - NULL); - expr->rtype = indirectExpr->rtype; - if (copts.som_env_check && tclass3->sominfo->oidl_callstyle == 0) - expr->flags = expr->flags | ENODE_FLAG_10; - } else { - CSOM_FindIntroClassOffset(tclass2, func, &tclass3, &offset); - if (copts.som_call_optimize && CSOM_CanUseGlueCall(TYPE_FUNC(func->type))) - return CSOM_SOMGlueCall(tclass3, offset, func); - - expr = create_objectrefnode(tclass3->sominfo->classdataobject); - expr = makediadicnode(expr, intconstnode(TYPE(&stsignedlong), offset), EADD); - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = CDecl_NewPointerType(func->type); - if (copts.som_env_check && tclass3->sominfo->oidl_callstyle == 0) - expr->flags = expr->flags | ENODE_FLAG_10; - } - - return expr; -} diff --git a/compiler_and_linker/unsorted/CTemplateClass.c b/compiler_and_linker/unsorted/CTemplateClass.c deleted file mode 100644 index 8b3b889..0000000 --- a/compiler_and_linker/unsorted/CTemplateClass.c +++ /dev/null @@ -1,1632 +0,0 @@ -#include "compiler/CTemplateClass.h" -#include "compiler/CABI.h" -#include "compiler/CBrowse.h" -#include "compiler/CClass.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CInline.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CScope.h" -#include "compiler/CTemplateFunc.h" -#include "compiler/CTemplateNew.h" -#include "compiler/CTemplateTools.h" -#include "compiler/CompilerTools.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/templates.h" - -TemplClass *CTemplClass_GetMasterTemplate(TemplClass *tmclass) { - if (tmclass->inst_parent) { - tmclass = TEMPL_CLASS(tmclass->theclass.nspace->theclass); - CError_ASSERT(42, tmclass->theclass.flags & CLASS_IS_TEMPL); - } - - return tmclass; -} - -static void CTemplClass_SetupActionErrorRef(TemplateAction *action, TStreamElement **saved) { - CError_ResetErrorSkip(); - CError_LockErrorPos(&action->source_ref, saved); -} - -static void CTemplClass_RestoreActionErrorRef(TStreamElement **saved) { - CError_ResetErrorSkip(); - CError_UnlockErrorPos(saved); -} - -static void CTemplClass_AppendTemplateAction(TemplClass *tmclass, TemplateAction *action) { - TemplateAction *last; - - action->source_ref = *CPrep_CurStreamElement(); - - if ((last = tmclass->actions)) { - while (last->next) - last = last->next; - last->next = action; - } else { - tmclass->actions = action; - } -} - -static DefAction *CTemplClass_NewDefAction(TypeDeduce *deduce, TemplateAction *action) { - DefAction *defAction = lalloc(sizeof(DefAction)); - defAction->next = deduce->defActions; - defAction->action = action; - deduce->defActions = defAction; - return defAction; -} - -static void CTemplClass_InsertTemplateAction(TemplClass *tmclass, TemplateAction *action) { - action->source_ref = *CPrep_CurStreamElement(); - action->next = tmclass->actions; - tmclass->actions = action; -} - -void CTemplClass_RegisterUsingDecl(TemplClass *tmclass, TypeTemplDep *type, AccessType access) { - TemplateAction *action; - - action = galloc(sizeof(TemplateAction)); - memclrw(action, sizeof(TemplateAction)); - - action->type = TAT_USINGDECL; - action->u.usingdecl.type = type; - action->u.usingdecl.access = access; - - CTemplClass_AppendTemplateAction(tmclass, action); -} - -void CTemplClass_RegisterFriend(TemplClass *tmclass, DeclInfo *di) { - TemplateFriend *tfriend; - TemplateAction *action; - - tfriend = galloc(sizeof(TemplateFriend)); - memclrw(tfriend, sizeof(TemplateFriend)); - - if (tk == '{' && IS_TYPE_FUNC(di->thetype)) { - di->qual |= Q_INLINE; - TYPE_FUNC(di->thetype)->flags |= FUNC_DEFINED | FUNC_IS_TEMPL_INSTANCE; - tfriend->fileoffset = cparser_fileoffset; - - CPrep_StreamGetBlock(&tfriend->stream, NULL, 1); - - if (lookahead() == ';') - tk = lex(); - else - tk = ';'; - } - - CDecl_PackDeclInfo(&tfriend->decl, di); - - action = galloc(sizeof(TemplateAction)); - memclrw(action, sizeof(TemplateAction)); - - action->type = TAT_FRIEND; - action->u.tfriend = tfriend; - - CTemplClass_AppendTemplateAction(tmclass, action); -} - -void CTemplClass_RegisterBaseClass(TemplClass *tmclass, Type *type, AccessType access, Boolean is_virtual) { - TemplateAction *action; - ClassList *insert_after; - - if ((insert_after = tmclass->theclass.bases)) { - while (insert_after->next) - insert_after = insert_after->next; - } - - action = galloc(sizeof(TemplateAction)); - memclrw(action, sizeof(TemplateAction)); - - action->type = TAT_BASE; - action->u.base.type = type; - action->u.base.insert_after = insert_after; - action->u.base.access = access; - action->u.base.is_virtual = is_virtual; - - CTemplClass_InsertTemplateAction(tmclass, action); -} - -void CTemplClass_RegisterEnumType(TemplClass *tmclass, TypeEnum *enumtype) { - TemplateAction *action; - - action = galloc(sizeof(TemplateAction)); - memclrw(action, sizeof(TemplateAction)); - - action->type = TAT_ENUMTYPE; - action->u.enumtype = enumtype; - - CTemplClass_AppendTemplateAction(tmclass, action); -} - -void CTemplClass_RegisterEnumerator(TemplClass *tmclass, ObjEnumConst *objenumconst, ENode *initexpr) { - TemplateAction *action; - - action = galloc(sizeof(TemplateAction)); - memclrw(action, sizeof(TemplateAction)); - - action->type = TAT_ENUMERATOR; - action->u.enumerator.objenumconst = objenumconst; - action->u.enumerator.initexpr = initexpr ? CInline_CopyExpression(initexpr, CopyMode1) : NULL; - - CTemplClass_AppendTemplateAction(tmclass, action); -} - -void CTemplClass_RegisterObjectInit(TemplClass *tmclass, Object *object, ENode *initexpr) { - TemplateAction *action; - - action = galloc(sizeof(TemplateAction)); - memclrw(action, sizeof(TemplateAction)); - - action->type = TAT_OBJECTINIT; - action->u.objectinit.object = object; - action->u.objectinit.initexpr = CInline_CopyExpression(initexpr, CopyMode1); - - CTemplClass_AppendTemplateAction(tmclass, action); -} - -void CTemplClass_RegisterObjectDef(TemplClass *tmclass, ObjBase *refobj) { - TemplateAction *action; - - action = galloc(sizeof(TemplateAction)); - memclrw(action, sizeof(TemplateAction)); - - action->type = TAT_OBJECTDEF; - action->u.refobj = refobj; - - CTemplClass_AppendTemplateAction(tmclass, action); -} - -void CTemplClass_CompleteClass(TemplClass *templ, ClassLayout *de) { - templ->lex_order_count = de->lex_order_count; - if (de->has_vtable) - templ->flags |= TEMPLCLASS_HAS_VTABLE; - templ->theclass.flags |= CLASS_COMPLETED; -} - -static TemplClassInst *CTemplClass_NewInstance(TemplClass *templ, TemplArg *inst_args, TemplArg *oargs) { - TemplClassInst *inst; - ObjTypeTag *tag; - NameSpace *nspace; - HashNameNode *name; - - CError_ASSERT(288, !templ->pspec_owner); - - inst = galloc(sizeof(TemplClassInst)); - memclrw(inst, sizeof(TemplClassInst)); - - inst->next = templ->instances; - templ->instances = inst; - - if (templ->templ__params) - name = CMangler_TemplateInstanceName(templ->theclass.classname, oargs ? oargs : inst_args); - else - name = templ->theclass.classname; - - inst->inst_args = inst_args; - inst->oargs = oargs; - inst->parent = templ->inst_parent; - - nspace = CScope_NewListNameSpace(name, 1); - nspace->theclass = TYPE_CLASS(inst); - if (templ->templ_parent && templ->inst_parent) { - nspace->parent = TYPE_CLASS(templ->inst_parent)->nspace; - } else { - NameSpace *scan = templ->theclass.nspace->parent; - while (scan->is_templ) - scan = scan->parent; - nspace->parent = scan; - } - - inst->theclass.type = TYPECLASS; - inst->theclass.flags = CLASS_IS_TEMPL_INST; - inst->theclass.nspace = nspace; - inst->theclass.classname = templ->theclass.classname; - inst->theclass.mode = templ->theclass.mode; - inst->theclass.eflags = templ->theclass.eflags; - inst->templ = templ; - - tag = galloc(sizeof(ObjTypeTag)); - memclrw(tag, sizeof(ObjTypeTag)); - - tag->otype = OT_TYPETAG; - tag->access = ACCESSPUBLIC; - tag->type = TYPE(inst); - CScope_AddObject(nspace, templ->theclass.classname, OBJ_BASE(tag)); - - return inst; -} - -TemplClassInst *CTemplClass_GetInstance(TemplClass *tmclass, TemplArg *inst_args, TemplArg *oargs) { - TemplClassInst *inst; - - for (inst = tmclass->instances; inst; inst = inst->next) { - CError_ASSERT(353, !oargs); - - if (CTemplTool_EqualArgs(inst_args, inst->oargs ? inst->oargs : inst->inst_args)) - return inst; - } - - return CTemplClass_NewInstance(tmclass, inst_args, oargs); -} - -TemplateMember *CTemplClass_DefineMember(TemplClass *tmclass, Object *object, FileOffsetInfo *foi, TokenStream *stream) { - TemplateMember *member; - - for (member = tmclass->members; member; member = member->next) { - if (member->object == object) { - CError_Error(CErrorStr333, object); - return member; - } - } - - member = galloc(sizeof(TemplateMember)); - memclrw(member, sizeof(TemplateMember)); - member->next = tmclass->members; - tmclass->members = member; - - member->params = NULL; - member->object = object; - member->fileoffset = *foi; - member->stream = *stream; - - return member; -} - -static void CTemplClass_ParseBody(TemplClass *templ, short mode, SInt32 *offset) { - DeclInfo di; - - templ->align = copts.structalignment; - - memclrw(&di, sizeof(di)); - di.file = CPrep_BrowserCurrentFile(); - CPrep_BrowserFilePosition(&di.file2, &di.sourceoffset); - di.sourceoffset = *offset; - di.x28 = templ; - - CDecl_ParseClass(&di, mode, 1, 0); - - if (tk == TK_UU_ATTRIBUTE_UU) - CParser_ParseAttribute(di.thetype, NULL); - if (tk != ';') - CError_Error(CErrorStr123); - - CBrowse_NewTemplateClass(templ, di.file2, di.sourceoffset, CPrep_BrowserFileOffset() + 1); -} - -void CTemplClass_ParsePartialSpecialization(DeclFucker *what_is_this, TemplParam *params, short mode, SInt32 *offset) { - Type *type; - NameSpace *nspace; - TemplArg *args; - TemplPartialSpec *pspec; - TemplClass *templ; - TemplArg *arg; - TemplParam *param; - - nspace = what_is_this->nspace; - - if ((tk = lex()) != TK_IDENTIFIER) { - CError_Error(CErrorStr107); - return; - } - - if (!(type = CScope_GetLocalTagType(nspace, tkidentifier))) { - CError_Error(CErrorStr140, tkidentifier->name); - return; - } - - if (!IS_TEMPL_CLASS(type)) { - CError_Error(CErrorStr132, tkidentifier->name); - return; - } - - if ((tk = lex()) != '<') - CError_FATAL(469); - - for (param = params; param; param = param->next) { - switch (param->pid.type) { - case TPT_TYPE: - if (!param->data.typeparam.type) - continue; - CError_Error(CErrorStr344); - break; - - case TPT_NONTYPE: - if (!param->data.paramdecl.defaultarg) - continue; - CError_Error(CErrorStr344); - break; - - case TPT_TEMPLATE: - if (!param->data.templparam.defaultarg) - continue; - CError_Error(CErrorStr344); - break; - - default: - CError_FATAL(501); - } - - break; - } - - args = CTempl_ParseUncheckTemplArgs(TEMPL_CLASS(type)->templ__params, 0); - tk = lex(); - - arg = args; - param = TEMPL_CLASS(type)->templ__params; - while (1) { - if (!arg) { - if (!param) - break; - CError_Error(CErrorStr344); - return; - } - if (!param) { - CError_Error(CErrorStr344); - return; - } - if (param->pid.type != arg->pid.type) { - CError_Error(CErrorStr344); - return; - } - arg = arg->next; - param = param->next; - } - - if (CTemplTool_IsSameTemplate(TEMPL_CLASS(type)->templ__params, args)) - CError_Error(CErrorStr344); - - for (pspec = TEMPL_CLASS(type)->pspecs; pspec; pspec = pspec->next) { - if (CTemplTool_EqualParams(pspec->templ->templ__params, params, 0) && CTemplTool_EqualArgs(pspec->args, args)) - break; - } - - if (!pspec) { - templ = galloc(sizeof(TemplClass)); - memclrw(templ, sizeof(TemplClass)); - - templ->templ__params = params; - CDecl_DefineClass(nspace, TEMPL_CLASS(type)->theclass.classname, TYPE_CLASS(templ), mode, 0, 0); - - templ->theclass.flags = CLASS_IS_TEMPL; - templ->pspec_owner = TEMPL_CLASS(type); - - pspec = galloc(sizeof(TemplPartialSpec)); - memclrw(pspec, sizeof(TemplPartialSpec)); - - pspec->templ = templ; - pspec->args = CTemplTool_MakeGlobalTemplArgCopy(args); - pspec->next = TEMPL_CLASS(type)->pspecs; - TEMPL_CLASS(type)->pspecs = pspec; - } else { - if ((pspec->templ->theclass.flags & CLASS_COMPLETED) && tk != ';') { - CError_Error(CErrorStr132, TEMPL_CLASS(type)->theclass.classname->name); - return; - } - - if (tk == ':' || tk == '{') - CTemplTool_EqualParams(pspec->templ->templ__params, params, 1); - } - - switch (tk) { - case ':': - case '{': - CTemplClass_ParseBody(pspec->templ, mode, offset); - break; - case ';': - break; - default: - CError_Error(CErrorStr121); - } -} - -void CTemplClass_ParseClass(DeclFucker *what_is_this, TemplParam *params, short mode, SInt32 *offset) { - TemplClass *templ; - NameSpace *nspace; - Type *type; - UInt8 classDeclSpec = 0; - - nspace = what_is_this->nspace; - if ((tk = lex()) == TK_UU_DECLSPEC) - CDecl_ParseClassDeclSpec(&classDeclSpec); - - if (tk != TK_IDENTIFIER) { - CError_Error(CErrorStr107); - return; - } - - type = CScope_GetLocalTagType(nspace, tkidentifier); - if (!type) { - templ = galloc(sizeof(TemplClass)); - memclrw(templ, sizeof(TemplClass)); - - templ->next = ctempl_templates; - ctempl_templates = templ; - - templ->templ__params = params; - CDecl_DefineClass(nspace, tkidentifier, TYPE_CLASS(templ), mode, 0, 1); - templ->theclass.flags = CLASS_IS_TEMPL; - templ->theclass.eflags = classDeclSpec; - - tk = lex(); - if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL)) { - TemplateAction *action; - - templ->templ_parent = TEMPL_CLASS(nspace->theclass); - - action = galloc(sizeof(TemplateAction)); - memclrw(action, sizeof(TemplateAction)); - - action->type = TAT_NESTEDCLASS; - action->u.tclasstype = templ; - CTemplClass_AppendTemplateAction(templ->templ_parent, action); - } - } else { - if (!IS_TEMPL_CLASS(type)) { - CError_Error(CErrorStr132, tkidentifier->name); - return; - } - - templ = TEMPL_CLASS(type); - if (!CTemplTool_EqualParams(templ->templ__params, params, 0)) { - CError_Error(CErrorStr132, templ->theclass.classname->name); - return; - } - - CTemplTool_MergeDefaultArgs(templ->templ__params, params); - templ->theclass.eflags |= classDeclSpec; - - tk = lex(); - - if ((templ->theclass.flags & CLASS_COMPLETED) && tk != ';') { - CError_Error(CErrorStr132, templ->theclass.classname->name); - return; - } - - if (tk != ';') - CTemplTool_EqualParams(templ->templ__params, params, 1); - } - - switch (tk) { - case ':': - case '{': - CTemplClass_ParseBody(templ, mode, offset); - break; - case ';': - break; - default: - CError_Error(CErrorStr121); - } -} - -static Boolean CTemplClass_TypeParamCompare(TemplArg *arg, Type *type, UInt32 qual) { - return is_typesame(type, arg->data.typeparam.type) && arg->data.typeparam.qual == qual; -} - -static TemplArg *CTemplClass_PartialTemplateArgMatch(TemplPartialSpec *pspec, TemplArg *args, Boolean flag) { - TemplArg *argA; - TemplArg *argB; - int i; - DeduceInfo info; - - if (!CTemplTool_InitDeduceInfo(&info, pspec->templ->templ__params, NULL, 1)) - return NULL; - - argA = pspec->args; - argB = args; - while (1) { - if (!argA) { - if (argB) - return NULL; - - for (i = 0; i < info.maxCount; i++) { - if (!info.args[i].is_deduced) - return NULL; - } - - if (flag) - return CTemplTool_MakeTemplArgList(&info); - else - return args; - } - - if (!argB) - return NULL; - - if (argA->pid.type != argB->pid.type) - return NULL; - - switch (argA->pid.type) { - case TPT_TYPE: - if (CTemplTool_IsTemplateArgumentDependentType(argA->data.typeparam.type)) { - if (!CTempl_DeduceType( - argA->data.typeparam.type, argA->data.typeparam.qual, - argB->data.typeparam.type, argB->data.typeparam.qual, - info.args, 0, 0 - )) - return NULL; - } else { - if ( - !is_typesame(argA->data.typeparam.type, argB->data.typeparam.type) || - argA->data.typeparam.qual != argB->data.typeparam.qual - ) - return NULL; - } - break; - - case TPT_NONTYPE: - if (CTemplTool_IsTemplateArgumentDependentExpression(argA->data.paramdecl.expr)) { - i = CTempl_GetTemplateArgumentExpressionIndex(argA); - CError_ASSERT(789, i >= 0); - - if (info.args[i].is_deduced) { - if (!CTemplTool_EqualExprTypes(argB->data.paramdecl.expr, info.args[i].data.paramdecl.expr)) - return NULL; - } else { - info.args[i].data.paramdecl.expr = argB->data.paramdecl.expr; - info.args[i].pid.type = TPT_NONTYPE; - info.args[i].is_deduced = 1; - } - } else { - if (!CTemplTool_EqualExprTypes(argB->data.paramdecl.expr, argA->data.paramdecl.expr)) - return NULL; - } - break; - - case TPT_TEMPLATE: - if (CTemplTool_IsTemplateArgumentDependentType(argA->data.ttargtype)) { - if (!CTempl_DeduceType( - argA->data.ttargtype, 0, - argB->data.ttargtype, 0, - info.args, 0, 0 - )) - return NULL; - } else { - if (!is_typesame(argA->data.ttargtype, argB->data.ttargtype)) - return NULL; - } - break; - - default: - CError_FATAL(830); - } - - argA = argA->next; - argB = argB->next; - } -} - -static Boolean CTemplClass_PartialClassIsAtLeastAsSpecialized(TemplPartialSpec *pspec1, TemplPartialSpec *pspec2) { - TemplArg *argA; - TemplArg *argB; - int i; - DeduceInfo info; - - if (!CTemplTool_InitDeduceInfo(&info, pspec2->templ->templ__params, NULL, 1)) - return 0; - - argA = pspec1->args; - argB = pspec2->args; - - while (1) { - if (!argA) { - CError_ASSERT(856, !argB); - - for (i = 0; i < info.maxCount; i++) { - if (!info.args[i].is_deduced) - return 0; - } - - return 1; - } - - CError_ASSERT(865, argB); - CError_ASSERT(866, argA->pid.type == argB->pid.type); - - switch (argA->pid.type) { - case TPT_TYPE: - if (!CTempl_DeduceType( - argB->data.typeparam.type, argB->data.typeparam.qual, - argA->data.typeparam.type, argA->data.typeparam.qual, - info.args, 0, 0 - )) - return 0; - break; - - case TPT_NONTYPE: - if (CTemplTool_IsTemplateArgumentDependentExpression(argB->data.paramdecl.expr)) { - i = CTempl_GetTemplateArgumentExpressionIndex(argB); - CError_ASSERT(907, i >= 0); - - if (info.args[i].is_deduced) { - if (argA->data.paramdecl.expr) { - if (!info.args[i].data.paramdecl.expr || !CTemplTool_EqualExprTypes(argA->data.paramdecl.expr, info.args[i].data.paramdecl.expr)) - return 0; - } else { - if (info.args[i].data.paramdecl.expr || argA->pid.index != info.args[i].pid.index) - return 0; - } - } else { - info.args[i].data.paramdecl.expr = argA->data.paramdecl.expr; - info.args[i].pid.index = argA->pid.index; - info.args[i].pid.type = TPT_NONTYPE; - info.args[i].is_deduced = 1; - } - } else { - if ( - !argA->data.paramdecl.expr || - !CTemplTool_EqualExprTypes(argA->data.paramdecl.expr, argB->data.paramdecl.expr) - ) - return 0; - } - break; - - case TPT_TEMPLATE: - if (!CTempl_DeduceType( - argB->data.ttargtype, 0, - argA->data.ttargtype, 0, - info.args, 0, 0 - )) - return 0; - break; - - default: - CError_FATAL(955); - } - - argA = argA->next; - argB = argB->next; - } -} - -static Boolean CTemplClass_PartialClassIsMoreSpecialized(TemplPartialSpec *pspec1, TemplPartialSpec *pspec2) { - return CTemplClass_PartialClassIsAtLeastAsSpecialized(pspec1, pspec2) && - !CTemplClass_PartialClassIsAtLeastAsSpecialized(pspec2, pspec1); -} - -typedef struct PSpecList { - struct PSpecList *next; - TemplPartialSpec *pspec; -} PSpecList; - -static PSpecList *CTemplClass_FindMostSpecializedPartialSpecializations(PSpecList *list) { - PSpecList **array; - PSpecList *scan; - int i; - int j; - int count; - - scan = list; - count = 0; - while (scan) { - scan = scan->next; - count++; - } - - array = lalloc(sizeof(PSpecList *) * count); - for (i = 0, scan = list; scan; scan = scan->next) - array[i++] = scan; - - for (i = 0; i < count; i++) { - if (array[i]) { - for (j = 0; j < count; j++) { - if (array[j] && i != j && CTemplClass_PartialClassIsMoreSpecialized(array[i]->pspec, array[j]->pspec)) - array[j] = NULL; - } - } - } - - for (i = 0, list = NULL; i < count; i++) { - if (array[i]) { - if (!list) - list = array[i]; - else - array[j]->next = array[i]; - array[i]->next = NULL; - j = i; - } - } - - return list; -} - -Boolean CTemplClass_FindPartialTemplate(TemplArg *args, TemplClass **resultTempl, TemplArg **resultArgs) { - TemplPartialSpec *pspec; - PSpecList *list; - TemplClassInst *inst; - - for (inst = (*resultTempl)->instances; inst; inst = inst->next) { - if (inst->is_instantiated || inst->is_specialized) { - if (CTemplTool_EqualArgs(args, inst->oargs ? inst->oargs : inst->inst_args)) - return 0; - } - } - - list = NULL; - for (pspec = (*resultTempl)->pspecs; pspec; pspec = pspec->next) { - if (CTemplClass_PartialTemplateArgMatch(pspec, args, 0)) { - PSpecList *entry = lalloc(sizeof(PSpecList)); - entry->next = list; - entry->pspec = pspec; - list = entry; - } - } - - if (list) { - if (list->next) { - list = CTemplClass_FindMostSpecializedPartialSpecializations(list); - if (list->next) - CError_Error(CErrorStr346); - } - - if (!list->pspec->templ->templ__params) { - *resultTempl = list->pspec->templ; - *resultArgs = NULL; - return 1; - } - - *resultTempl = list->pspec->templ; - *resultArgs = CTemplClass_PartialTemplateArgMatch(list->pspec, args, 1); - return *resultArgs != NULL; - } else { - return 0; - } -} - -TemplClass *CTemplClass_DefineNestedClass(TemplClass *parent, HashNameNode *name, short mode) { - TemplateAction *action; - TemplClass *templ; - - templ = galloc(sizeof(TemplClass)); - memclrw(templ, sizeof(TemplClass)); - - templ->next = ctempl_templates; - ctempl_templates = templ; - - templ->templ_parent = parent; - templ->templ__params = NULL; - CDecl_DefineClass(parent->theclass.nspace, name, TYPE_CLASS(templ), mode, 0, 1); - - templ->theclass.flags = CLASS_IS_TEMPL; - templ->align = copts.structalignment; - - action = galloc(sizeof(TemplateAction)); - memclrw(action, sizeof(TemplateAction)); - - action->type = TAT_NESTEDCLASS; - action->u.tclasstype = templ; - CTemplClass_AppendTemplateAction(parent, action); - - return templ; -} - -static void CTemplClass_CopyNestedClass(TypeDeduce *deduce, TemplClass *templ) { - ObjTypeTag *tag; - - tag = galloc(sizeof(ObjTypeTag)); - memclrw(tag, sizeof(ObjTypeTag)); - - tag->otype = OT_TYPETAG; - tag->access = ACCESSPUBLIC; - - if (!templ->templ__params) { - TemplClassInst *inst = CTemplClass_NewInstance(templ, NULL, NULL); - inst->parent = deduce->inst; - inst->theclass.nspace->parent = deduce->inst->theclass.nspace; - - tag->type = TYPE(inst); - } else { - TemplClass *copy = galloc(sizeof(TemplClass)); - memclrw(copy, sizeof(TemplClass)); - - copy->next = ctempl_templates; - ctempl_templates = copy; - - copy->theclass = templ->theclass; - copy->templ_parent = deduce->tmclass; - copy->inst_parent = deduce->inst; - copy->templ__params = templ->templ__params; - copy->members = NULL; - copy->instances = NULL; - copy->pspecs = NULL; - copy->actions = templ->actions; - copy->lex_order_count = templ->lex_order_count; - copy->align = templ->align; - copy->flags = templ->flags; - - tag->type = TYPE(copy); - } - - CScope_AddObject(deduce->inst->theclass.nspace, templ->theclass.classname, OBJ_BASE(tag)); -} - -static void CTemplClass_CopyBaseClasses(TypeDeduce *deduce, TemplClassInst *inst, TemplClass *templ) { - TemplateAction *action; - ClassList *newBase; - ClassList *templbase; - ClassList *instbase; - ClassList *base; - UInt32 qual = 0; - - for (base = templ->theclass.bases; base; base = base->next) { - ClassList *scan; - newBase = galloc(sizeof(ClassList)); - *newBase = *base; - newBase->next = NULL; - - if ((scan = inst->theclass.bases)) { - while (1) { - if (scan->base == newBase->base) { - CError_Error(CErrorStr131); - break; - } - if (!scan->next) { - scan->next = newBase; - break; - } - scan = scan->next; - } - } else { - inst->theclass.bases = newBase; - } - } - - for (action = deduce->tmclass->actions; action; action = action->next) { - if (action->type == TAT_BASE) { - TStreamElement *save; - - CTemplClass_SetupActionErrorRef(action, &save); - - newBase = galloc(sizeof(ClassList)); - memclrw(newBase, sizeof(ClassList)); - - newBase->base = TYPE_CLASS(CTemplTool_DeduceTypeCopy(deduce, action->u.base.type, &qual)); - newBase->access = action->u.base.access; - newBase->is_virtual = action->u.base.is_virtual; - - if (IS_TYPE_CLASS(newBase->base)) { - if (newBase->base->size == 0) { - CDecl_CompleteType(TYPE(newBase->base)); - IsCompleteType(TYPE(newBase->base)); - } - - if (CDecl_CheckNewBase(TYPE_CLASS(inst), newBase->base, newBase->is_virtual)) { - if (action->u.base.insert_after) { - templbase = templ->theclass.bases; - instbase = inst->theclass.bases; - while (1) { - CError_ASSERT(1222, templbase && instbase); - - if (templbase == action->u.base.insert_after) { - newBase->next = instbase->next; - instbase->next = newBase; - break; - } - - templbase = templbase->next; - instbase = instbase->next; - } - } else { - newBase->next = inst->theclass.bases; - inst->theclass.bases = newBase; - } - } - } else { - CError_Error(CErrorStr131); - } - - CTemplClass_RestoreActionErrorRef(&save); - } - } - - if (inst->theclass.flags & CLASS_HAS_VBASES) - CDecl_MakeVBaseList(TYPE_CLASS(inst)); -} - -static void CTemplClass_CopyEnum(TypeDeduce *deduce, TemplateAction *action) { - TypeEnum *destenum; - TypeEnum *srcenum; - ObjEnumConst **destptr; - ObjEnumConst *src; - TemplateAction *scanaction; - - srcenum = action->u.enumtype; - destenum = galloc(sizeof(TypeEnum)); - memclrw(destenum, sizeof(TypeEnum)); - - destenum->type = TYPEENUM; - destenum->size = srcenum->size; - destenum->nspace = deduce->inst->theclass.nspace; - destenum->enumtype = srcenum->enumtype; - destenum->enumname = srcenum->enumname; - - if (destenum->enumname) - CScope_DefineTypeTag(destenum->nspace, destenum->enumname, TYPE(destenum)); - - src = srcenum->enumlist; - destptr = &destenum->enumlist; - while (src) { - ObjEnumConst *dest; - - dest = galloc(sizeof(ObjEnumConst)); - *dest = *src; - - *destptr = dest; - dest->next = NULL; - dest->type = TYPE(destenum); - CScope_AddObject(deduce->inst->theclass.nspace, dest->name, OBJ_BASE(dest)); - - src = src->next; - destptr = &(*destptr)->next; - } - - for (scanaction = deduce->tmclass->actions; scanaction; scanaction = scanaction->next) { - if (scanaction->type == TAT_ENUMERATOR && scanaction->u.enumerator.objenumconst->type == TYPE(srcenum)) { - CTemplClass_NewDefAction(deduce, action)->enumtype = destenum; - return; - } - } -} - -static void CTemplClass_CompleteEnumType(TypeDeduce *deduce, TemplateAction *action, TypeEnum *destenum) { - TypeEnum *srcenum; - ObjEnumConst *dest; - TemplateAction *scanaction; - ENode *expr; - ObjEnumConst *src; - - srcenum = action->u.enumtype; - - for (scanaction = deduce->tmclass->actions; scanaction; scanaction = scanaction->next) { - if (scanaction->type == TAT_ENUMERATOR) { - src = scanaction->u.enumerator.objenumconst; - if (src->type == TYPE(srcenum)) { - TStreamElement *save; - - CTemplClass_SetupActionErrorRef(scanaction, &save); - - dest = destenum->enumlist; - while (dest) { - if (dest->name == src->name) - break; - dest = dest->next; - } - - CError_ASSERT(1332, dest); - - if (scanaction->u.enumerator.initexpr) { - expr = CTemplTool_DeduceExpr(deduce, scanaction->u.enumerator.initexpr); - if (!ENODE_IS(expr, EINTCONST)) { - CError_Error(CErrorStr124); - CTemplClass_RestoreActionErrorRef(&save); - break; - } - } else { - CError_ASSERT(1347, expr); - expr->data.intval = CInt64_Add(expr->data.intval, cint64_one); - } - - dest->val = expr->data.intval; - dest->type = expr->rtype; - CTemplClass_RestoreActionErrorRef(&save); - } - } - } - - CDecl_ComputeUnderlyingEnumType(destenum); -} - -static void CTemplClass_CopyObjMemberVarPath(TypeDeduce *deduce, ObjMemberVarPath *ivar) { - ObjMemberVarPath *copy; - - copy = galloc(sizeof(ObjMemberVarPath)); - *copy = *ivar; - - if (copy->path && copy->path->type == TYPE(deduce->tmclass)) { - copy->path = CClass_GetPathCopy(copy->path, 1); - copy->path->type = TYPE(deduce->inst); - } - - CScope_AddObject(deduce->inst->theclass.nspace, copy->name, OBJ_BASE(copy)); -} - -static void CTemplClass_CopyIVars(TypeDeduce *deduce, TemplClassInst *inst, TemplClass *templ) { - ObjMemberVar *src; - ObjMemberVar *dest; - ObjMemberVar **destptr; - TemplateAction *scanaction; - - src = templ->theclass.ivars; - destptr = &inst->theclass.ivars; - - while (src) { - CError_ASSERT(1397, !src->has_path); - - dest = galloc(sizeof(ObjMemberVar)); - *dest = *src; - - for (scanaction = deduce->tmclass->actions; scanaction; scanaction = scanaction->next) { - if (scanaction->type == TAT_OBJECTDEF && scanaction->u.refobj == OBJ_BASE(src)) { - CTemplClass_NewDefAction(deduce, scanaction)->refobj = OBJ_BASE(dest); - break; - } - } - - if (!scanaction) { - dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); - if (dest->type->size == 0) { - CDecl_CompleteType(dest->type); - IsCompleteType(dest->type); - } - } - - if (dest->name && dest->name != no_name_node) - CScope_AddObject(inst->theclass.nspace, dest->name, OBJ_BASE(dest)); - - *destptr = dest; - destptr = &dest->next; - src = src->next; - } -} - -static void CTemplClass_CopyObjType(TypeDeduce *deduce, ObjType *src, HashNameNode *name) { - TemplateAction *scanaction; - NameSpaceObjectList *list; - NameSpaceObjectList *newlist; - ObjType *dest; - - for (scanaction = deduce->tmclass->actions; scanaction; scanaction = scanaction->next) { - if (scanaction->type == TAT_OBJECTDEF && scanaction->u.refobj == OBJ_BASE(src)) - break; - } - - dest = galloc(sizeof(ObjType)); - *dest = *src; - - if (scanaction) - CTemplClass_NewDefAction(deduce, scanaction)->refobj = OBJ_BASE(dest); - else - dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); - - if ((list = CScope_FindName(deduce->inst->theclass.nspace, name)) && list->object->otype == OT_TYPETAG) { - CError_ASSERT(1470, list->next == NULL); - - newlist = galloc(sizeof(NameSpaceObjectList)); - newlist->object = list->object; - newlist->next = NULL; - - list->object = OBJ_BASE(dest); - list->next = newlist; - } else { - CScope_AddObject(deduce->inst->theclass.nspace, name, OBJ_BASE(dest)); - } -} - -static void CTemplClass_CopyObjTypeTag(TypeDeduce *deduce, ObjTypeTag *src, HashNameNode *name) { - UInt32 qual = 0; - ObjTypeTag *dest = galloc(sizeof(ObjTypeTag)); - - *dest = *src; - dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &qual); - - CScope_AddObject(deduce->inst->theclass.nspace, name, OBJ_BASE(dest)); -} - -static void CTemplClass_CopyMemberTemplate(TypeDeduce *deduce, Object *src) { - TemplateFunction *desttempl; - Object *dest; - TemplateFunction *srctempl; - TemplateAction *action; - - srctempl = src->u.func.u.templ; - CError_ASSERT(1516, srctempl && srctempl->params); - - for (action = deduce->tmclass->actions; action; action = action->next) { - if (action->type == TAT_OBJECTDEF && action->u.refobj == OBJ_BASE(src)) - break; - } - - desttempl = galloc(sizeof(TemplateFunction)); - *desttempl = *srctempl; - - desttempl->next = ctempl_templatefuncs; - ctempl_templatefuncs = desttempl; - - desttempl->unk4 = srctempl; - - dest = galloc(sizeof(Object)); - *dest = *src; - - dest->u.func.u.templ = desttempl; - dest->nspace = deduce->inst->theclass.nspace; - - CError_ASSERT(1541, !deduce->x15); - deduce->x15 = 1; - deduce->nindex = srctempl->params->pid.nindex; - - if (action) - CTemplClass_NewDefAction(deduce, action)->refobj = OBJ_BASE(dest); - else - dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); - - deduce->x15 = 0; - - CError_ASSERT(1553, IS_TYPE_FUNC(dest->type)); - - TYPE_FUNC(dest->type)->flags |= FUNC_IS_TEMPL; - - if ( - (TYPE_FUNC(dest->type)->flags & FUNC_IS_CTOR) && - deduce->x17 && - !action - ) - { - FuncArg *arg; - CError_ASSERT(1560, TYPE_FUNC(dest->type)->args); - arg = CParser_NewFuncArg(); - arg->type = TYPE(&stsignedshort); - arg->next = TYPE_FUNC(dest->type)->args->next; - TYPE_FUNC(dest->type)->args->next = arg; - } - - CScope_AddObject(deduce->inst->theclass.nspace, dest->name, OBJ_BASE(dest)); -} - -static void CTemplClass_CopyObject(TypeDeduce *deduce, Object *src) { - ObjectTemplated *dest; - TemplateAction *action; - TemplateAction *action2; - Boolean flag; - - flag = 1; - if (src->nspace != deduce->tmclass->theclass.nspace) { - CError_ASSERT(1587, src->datatype == DALIAS); - flag = 0; - } - - if (IS_TEMPL_FUNC(src->type)) { - CTemplClass_CopyMemberTemplate(deduce, src); - return; - } - - for (action = deduce->tmclass->actions; action; action = action->next) { - if (action->type == TAT_OBJECTDEF && action->u.refobj == OBJ_BASE(src)) - break; - } - - dest = galloc(sizeof(ObjectTemplated)); - dest->object = *src; - - if (action) - CTemplClass_NewDefAction(deduce, action)->refobj = OBJ_BASE(dest); - else - dest->object.type = CTemplTool_DeduceTypeCopy(deduce, dest->object.type, &dest->object.qual); - - if (flag) - dest->object.nspace = deduce->inst->theclass.nspace; - - dest->object.qual |= Q_IS_TEMPLATED; - dest->parent = src; - - if (IS_TYPE_FUNC(dest->object.type)) - TYPE_FUNC(dest->object.type)->flags &= ~FUNC_DEFINED; - - switch (dest->object.datatype) { - case DDATA: - dest->object.u.data.linkname = NULL; - for (action2 = deduce->tmclass->actions; action2; action2 = action2->next) { - if (action2->type == TAT_OBJECTINIT && action2->u.objectinit.object == src) { - CTemplClass_NewDefAction(deduce, action2)->refobj = OBJ_BASE(dest); - break; - } - } - break; - - case DABSOLUTE: - break; - - case DFUNC: - case DVFUNC: - dest->object.u.func.linkname = NULL; - CError_ASSERT(1650, IS_TYPE_FUNC(dest->object.type)); - CError_ASSERT(1651, !dest->object.u.func.u.templ && !dest->object.u.func.defargdata); - - if ( - (TYPE_FUNC(dest->object.type)->flags & FUNC_IS_CTOR) && - deduce->x17 && - !action - ) - { - FuncArg *arg; - CError_ASSERT(1657, TYPE_FUNC(dest->object.type)->args); - arg = CParser_NewFuncArg(); - arg->type = TYPE(&stsignedshort); - arg->next = TYPE_FUNC(dest->object.type)->args->next; - TYPE_FUNC(dest->object.type)->args->next = arg; - } - - if (TYPE_FUNC(dest->object.type)->flags & FUNC_CONVERSION) { - CError_ASSERT(1665, IS_TYPE_FUNC(src->type)); - if (CTemplTool_IsTemplateArgumentDependentType(TYPE_FUNC(src->type)->functype)) { - CError_ASSERT(1668, action); - return; - } - } - - break; - - case DINLINEFUNC: - break; - - case DALIAS: - if (dest->object.u.alias.member && dest->object.u.alias.member->type == TYPE(deduce->tmclass)) { - dest->object.u.alias.member = CClass_GetPathCopy(dest->object.u.alias.member, 1); - dest->object.u.alias.member->type = TYPE(deduce->inst); - } - break; - - case DLOCAL: - case DEXPR: - CError_FATAL(1688); - - default: - CError_FATAL(1691); - } - - CScope_AddObject(deduce->inst->theclass.nspace, dest->object.name, OBJ_BASE(dest)); -} - -static void CTemplClass_CompleteObject(TypeDeduce *deduce, TemplateAction *action, ObjBase *refobj) { - if (refobj->otype == OT_MEMBERVAR) { - ObjMemberVar *ivar = OBJ_MEMBER_VAR(refobj); - ivar->type = CTemplTool_DeduceTypeCopy(deduce, ivar->type, &ivar->qual); - - if (ivar->type->size == 0) { - CDecl_CompleteType(ivar->type); - if (copts.experimental) { - if (ivar->next || ivar->type->size != 0 || !IS_TYPE_ARRAY(ivar->type)) - IsCompleteType(ivar->type); - } else { - IsCompleteType(ivar->type); - } - } - } else if (refobj->otype == OT_TYPE) { - ObjType *obj = OBJ_TYPE(refobj); - obj->type = CTemplTool_DeduceTypeCopy(deduce, obj->type, &obj->qual); - } else { - Object *dest; - Object *src; - - CError_ASSERT(1737, refobj->otype == OT_OBJECT); - - dest = OBJECT(refobj); - src = OBJECT(action->u.refobj); - - if (IS_TEMPL_FUNC(src->type)) { - TemplateFunction *templ = src->u.func.u.templ; - CError_ASSERT(1747, templ); - CError_ASSERT(1748, !deduce->x15); - - deduce->x15 = 1; - deduce->nindex = templ->params->pid.nindex; - dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); - deduce->x15 = 0; - - CError_ASSERT(1753, IS_TYPE_FUNC(dest->type)); - TYPE_FUNC(dest->type)->flags |= FUNC_IS_TEMPL; - } else { - dest->type = CTemplTool_DeduceTypeCopy(deduce, dest->type, &dest->qual); - dest->qual |= Q_IS_TEMPLATED; - - if (IS_TYPE_FUNC(dest->type)) - TYPE_FUNC(dest->type)->flags &= ~FUNC_DEFINED; - - switch (dest->datatype) { - case DFUNC: - case DVFUNC: - CError_ASSERT(1769, IS_TYPE_FUNC(dest->type)); - if (TYPE_FUNC(dest->type)->flags & FUNC_CONVERSION) { - CError_ASSERT(1772, IS_TYPE_FUNC(dest->type)); - if (CTemplTool_IsTemplateArgumentDependentType(TYPE_FUNC(src->type)->functype)) { - dest->name = CMangler_ConversionFuncName( - TYPE_FUNC(dest->type)->functype, TYPE_FUNC(dest->type)->qual); - CScope_AddObject(deduce->inst->theclass.nspace, dest->name, OBJ_BASE(dest)); - } - } - - if ((TYPE_FUNC(dest->type)->flags & FUNC_IS_CTOR) && deduce->x17) { - FuncArg *arg; - CError_ASSERT(1786, TYPE_FUNC(dest->type)->args); - arg = CParser_NewFuncArg(); - arg->type = TYPE(&stsignedshort); - arg->next = TYPE_FUNC(dest->type)->args->next; - TYPE_FUNC(dest->type)->args->next = arg; - } - - break; - } - } - } -} - -static void CTemplClass_CompleteObjectInit(TypeDeduce *deduce, TemplateAction *action, Object *object) { - ENode *expr = CTemplTool_DeduceExpr(deduce, action->u.objectinit.initexpr); - - if (ENODE_IS(expr, EINTCONST) && (object->qual & Q_CONST) && IS_TYPE_INT_OR_ENUM(object->type)) { - object->u.data.u.intconst = expr->data.intval; - object->qual |= Q_INLINE_DATA | Q_20000; - } else { - CError_Error(CErrorStr354, object->name->name); - } -} - -static void CTemplClass_CopyNameSpace(TypeDeduce *deduce, TemplClassInst *inst, TemplClass *templ) { - NameSpaceName *nsname; - NameSpaceObjectList *list; - - CError_ASSERT(1830, !templ->theclass.nspace->is_hash); - - for (nsname = templ->theclass.nspace->data.list; nsname; nsname = nsname->next) { - for (list = &nsname->first; list; list = list->next) { - switch (list->object->otype) { - case OT_ENUMCONST: - break; - case OT_MEMBERVAR: - if (OBJ_MEMBER_VAR(list->object)->has_path) - CTemplClass_CopyObjMemberVarPath(deduce, OBJ_MEMBER_VAR_PATH(list->object)); - break; - case OT_TYPE: - CTemplClass_CopyObjType(deduce, OBJ_TYPE(list->object), nsname->name); - break; - case OT_TYPETAG: - break; - case OT_NAMESPACE: - CError_FATAL(1854); - case OT_OBJECT: - CTemplClass_CopyObject(deduce, OBJECT(list->object)); - break; - default: - CError_FATAL(1861); - } - } - } -} - -static void CTemplClass_CopyUsingDecl(TypeDeduce *deduce, TypeTemplDep *type, AccessType access) { - TypeClass *tclass; - UInt32 qual = 0; - - CError_ASSERT(1878, IS_TYPE_TEMPLATE(type) && type->dtype == TEMPLDEP_QUALNAME); - - tclass = TYPE_CLASS(CTemplTool_DeduceTypeCopy(deduce, TYPE(type->u.qual.type), &qual)); - if (!IS_TYPE_CLASS(tclass)) { - CError_Error(CErrorStr340, type->u.qual.name->name); - return; - } - - CDecl_CompleteType(TYPE(tclass)); - CScope_AddClassUsingDeclaration(TYPE_CLASS(deduce->inst), tclass, type->u.qual.name, access); -} - -static void CTemplClass_CopyFriend(TypeDeduce *deduce, TemplateFriend *tfriend) { - TemplArg *arg; - Object *funcobj; - Boolean flag; - CScopeSave saveScope; - DeclInfo di; - - CDecl_UnpackDeclInfo(&di, &tfriend->decl); - - if (CTemplTool_IsTemplateArgumentDependentType(di.thetype)) - di.thetype = CTemplTool_DeduceTypeCopy(deduce, di.thetype, &di.qual); - - if (di.expltargs) { - di.expltargs = CTemplTool_MakeGlobalTemplArgCopy(di.expltargs); - for (arg = di.expltargs; arg; arg = arg->next) { - switch (arg->pid.type) { - case TPT_TYPE: - if (CTemplTool_IsTemplateArgumentDependentType(arg->data.typeparam.type)) - arg->data.typeparam.type = CTemplTool_DeduceTypeCopy(deduce, arg->data.typeparam.type, &arg->data.typeparam.qual); - break; - case TPT_NONTYPE: - if (CTemplTool_IsTemplateArgumentDependentExpression(arg->data.paramdecl.expr)) - arg->data.paramdecl.expr = CTemplTool_DeduceExpr(deduce, arg->data.paramdecl.expr); - break; - case TPT_TEMPLATE: - default: - CError_FATAL(1930); - } - } - } - - if (IS_TYPE_FUNC(di.thetype)) { - CScope_SetNameSpaceScope(CScope_FindGlobalNS(deduce->inst->theclass.nspace), &saveScope); - funcobj = CDecl_GetFunctionObject(&di, NULL, &flag, 0); - CScope_RestoreScope(&saveScope); - - if (funcobj) { - CDecl_AddFriend(TYPE_CLASS(deduce->inst), funcobj, NULL); - if (tfriend->stream.tokens) - CInline_AddInlineFunctionAction(funcobj, TYPE_CLASS(deduce->inst), &tfriend->fileoffset, &tfriend->stream, 0); - } else { - CError_Error(CErrorStr201); - } - } else { - CError_ASSERT(1963, IS_TYPE_CLASS(di.thetype)); - CDecl_AddFriend(TYPE_CLASS(deduce->inst), NULL, TYPE_CLASS(di.thetype)); - } -} - -Boolean CTempl_InstantiateTemplateClass(TypeClass *tclass) { - TemplClassInst *inst; - ParserTryBlock *tryBlock; - TemplateAction *action; - DefAction *defAction; - UInt8 saveAlignMode; - - TypeDeduce deduce; - TemplStack stack; - CScopeSave saveScope; - ClassLayout layout; - TemplClass *templ; - TStreamElement *saveErrorRef; - TemplArg *inst_args; - - CError_ASSERT(1989, tclass->flags & CLASS_IS_TEMPL_INST); - - if (tclass->flags & CLASS_COMPLETED) - return 1; - - inst = TEMPL_CLASS_INST(tclass); - if (inst->is_specialized) - return 0; - - templ = inst->templ; - if (!(templ->flags & TEMPLCLASS_FLAGS_2)) - templ = CTemplClass_GetMasterTemplate(templ); - - if (templ->pspecs && CTemplClass_FindPartialTemplate(inst->inst_args, &templ, &inst_args)) { - CError_ASSERT(2013, !inst->oargs); - inst->templ = templ; - inst->oargs = inst->inst_args; - inst->inst_args = inst_args; - } - - if (!(templ->theclass.flags & CLASS_COMPLETED)) - return 0; - - if (inst->is_instantiated) - return 0; - - inst->is_instantiated = 1; - CScope_SetClassScope(tclass, &saveScope); - CTemplTool_PushInstance(&stack, tclass, NULL); - - tryBlock = trychain; - trychain = NULL; - - memclrw(&deduce, sizeof(deduce)); - deduce.tmclass = templ; - deduce.inst = inst; - deduce.params = templ->templ__params; - deduce.args = inst->inst_args; - - CError_ASSERT(2045, !templ->theclass.sominfo); - CError_ASSERT(2047, !templ->theclass.objcinfo); - CError_ASSERT(2049, !templ->theclass.vtable); - - inst->theclass.flags |= templ->theclass.flags & - (CLASS_ABSTRACT | CLASS_SINGLE_OBJECT | CLASS_HAS_VBASES | CLASS_IS_CONVERTIBLE | CLASS_COM_OBJECT); - - CTemplClass_CopyBaseClasses(&deduce, inst, templ); - - deduce.x17 = (inst->theclass.flags & CLASS_HAS_VBASES) && !(templ->theclass.flags & CLASS_HAS_VBASES); - - for (action = templ->actions; action; action = action->next) { - switch (action->type) { - case TAT_NESTEDCLASS: - CTemplClass_SetupActionErrorRef(action, &saveErrorRef); - CTemplClass_CopyNestedClass(&deduce, action->u.tclasstype); - CTemplClass_RestoreActionErrorRef(&saveErrorRef); - break; - case TAT_ENUMTYPE: - CTemplClass_SetupActionErrorRef(action, &saveErrorRef); - CTemplClass_CopyEnum(&deduce, action); - CTemplClass_RestoreActionErrorRef(&saveErrorRef); - break; - case TAT_FRIEND: - case TAT_ENUMERATOR: - case TAT_BASE: - case TAT_OBJECTINIT: - case TAT_USINGDECL: - case TAT_OBJECTDEF: - break; - default: - CError_FATAL(2094); - } - } - - CTemplClass_CopyIVars(&deduce, inst, templ); - CTemplClass_CopyNameSpace(&deduce, inst, templ); - - CError_ASSERT(2105, !templ->theclass.friends); - - for (action = templ->actions; action; action = action->next) { - switch (action->type) { - case TAT_NESTEDCLASS: - break; - case TAT_ENUMTYPE: - for (defAction = deduce.defActions; defAction; defAction = defAction->next) { - if (defAction->action == action) { - CTemplClass_SetupActionErrorRef(action, &saveErrorRef); - CTemplClass_CompleteEnumType(&deduce, action, defAction->enumtype); - CTemplClass_RestoreActionErrorRef(&saveErrorRef); - break; - } - } - break; - case TAT_FRIEND: - CTemplClass_SetupActionErrorRef(action, &saveErrorRef); - CTemplClass_CopyFriend(&deduce, action->u.tfriend); - CTemplClass_RestoreActionErrorRef(&saveErrorRef); - break; - case TAT_ENUMERATOR: - break; - case TAT_BASE: - break; - case TAT_OBJECTINIT: - for (defAction = deduce.defActions; ; defAction = defAction->next) { - CError_ASSERT(2136, defAction); - if (defAction->action == action) { - CTemplClass_SetupActionErrorRef(action, &saveErrorRef); - CTemplClass_CompleteObjectInit(&deduce, action, OBJECT(defAction->refobj)); - CTemplClass_RestoreActionErrorRef(&saveErrorRef); - break; - } - } - break; - case TAT_USINGDECL: - CTemplClass_SetupActionErrorRef(action, &saveErrorRef); - CTemplClass_CopyUsingDecl(&deduce, action->u.usingdecl.type, action->u.usingdecl.access); - CTemplClass_RestoreActionErrorRef(&saveErrorRef); - break; - case TAT_OBJECTDEF: - for (defAction = deduce.defActions; ; defAction = defAction->next) { - CError_ASSERT(2156, defAction); - if (defAction->action == action) { - CTemplClass_SetupActionErrorRef(action, &saveErrorRef); - CTemplClass_CompleteObject(&deduce, action, defAction->refobj); - CTemplClass_RestoreActionErrorRef(&saveErrorRef); - break; - } - } - break; - } - } - - memclrw(&layout, sizeof(layout)); - layout.lex_order_count = templ->lex_order_count; - layout.has_vtable = templ->flags & TEMPLCLASS_HAS_VTABLE; - - saveAlignMode = copts.structalignment; - copts.structalignment = templ->align; - CDecl_CompleteClass(&layout, TYPE_CLASS(inst)); - copts.structalignment = saveAlignMode; - - if (templ->theclass.align > inst->theclass.align) { - inst->theclass.align = templ->theclass.align; - inst->theclass.size += CABI_StructSizeAlignValue(TYPE(inst), inst->theclass.size); - } - - CTemplTool_PopInstance(&stack); - CScope_RestoreScope(&saveScope); - trychain = tryBlock; - - return 1; -} diff --git a/compiler_and_linker/unsorted/CTemplateFunc.c b/compiler_and_linker/unsorted/CTemplateFunc.c deleted file mode 100644 index 3c5de98..0000000 --- a/compiler_and_linker/unsorted/CTemplateFunc.c +++ /dev/null @@ -1,1383 +0,0 @@ -#include "compiler/CTemplateFunc.h" -#include "compiler/CABI.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CInline.h" -#include "compiler/CInt64.h" -#include "compiler/CParser.h" -#include "compiler/CTemplateTools.h" -#include "compiler/CompilerTools.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/templates.h" -#include "compiler/types.h" - -static Boolean ctempl_conversion_deduction; -static UInt8 ctempl_explicitargs_nindex; -static int ctempl_explicitargs_num; -static Boolean ctempl_explicitargs_all; - -// forward decls -static Boolean CTempl_DeduceTypeTemplDep(TypeTemplDep *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray, Boolean flag); -static Boolean CTempl_DeduceType1(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray, Boolean flag); - -static void CTemplFunc_SetupTypeDeduce(TypeDeduce *deduce, TemplateFunction *templ, TemplArg *args) { - memclrw(deduce, sizeof(TypeDeduce)); - if (templ->tfunc->nspace->theclass && (templ->tfunc->nspace->theclass->flags & CLASS_IS_TEMPL)) - deduce->tmclass = TEMPL_CLASS(templ->tfunc->nspace->theclass); - deduce->params = templ->params; - deduce->args = args; -} - -Boolean CTempl_CanDeduceFunc(Object *object, TypeFunc *tfunc, TemplArg *args) { - DeduceInfo info; - int i; - - if (CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(object)->params, args, 0)) { - if (CTempl_DeduceType(object->type, 0, TYPE(tfunc), 0, info.args, 0, 0)) { - for (i = 0; i < info.maxCount; i++) { - if (!info.args[i].is_deduced) - return 0; - } - return 1; - } - } - - return 0; -} - -static TemplFuncInstance *CTempl_GetCreateFuncInstance(Object *funcobj, TemplArg *args, Object *object2) { - TemplFuncInstance *inst; - TemplateFunction *templ; - Object *instobj; - TemplParam *param; - TemplArg *arg; - TemplArg *last; - short paramCount; - short i; - TypeDeduce deduce; - - templ = CTemplTool_GetFuncTempl(funcobj); - - paramCount = 0; - param = templ->params; - while (param) { - param = param->next; - paramCount++; - } - - for (i = 1, arg = args; i < paramCount; i++, arg++) - arg->next = arg + 1; - arg->next = NULL; - - for (inst = templ->instances; inst; inst = inst->next) { - if (CTemplTool_EqualArgs(inst->args, args)) { - if (object2) - inst->object = object2; - return inst; - } - } - - inst = galloc(sizeof(TemplFuncInstance)); - memclrw(inst, sizeof(TemplFuncInstance)); - - for (i = 0, arg = NULL; i < paramCount; i++) { - if (arg) { - last->next = galloc(sizeof(TemplArg)); - last = last->next; - } else { - last = galloc(sizeof(TemplArg)); - arg = last; - } - - *last = *args; - last->next = NULL; - args++; - - if (last->pid.type == TPT_NONTYPE) { - CError_ASSERT(114, last->data.paramdecl.expr); - last->data.paramdecl.expr = CInline_CopyExpression(last->data.paramdecl.expr, CopyMode1); - } - } - - inst->args = arg; - inst->next = templ->instances; - templ->instances = inst; - - if (!object2) { - instobj = CParser_NewFunctionObject(NULL); - instobj->access = funcobj->access; - instobj->nspace = funcobj->nspace; - instobj->sclass = funcobj->sclass; - instobj->qual = funcobj->qual | Q_MANGLE_NAME; - instobj->name = templ->name; - instobj->u.func.inst = inst; - - CTemplFunc_SetupTypeDeduce(&deduce, templ, inst->args); - if (funcobj->nspace->theclass && (funcobj->nspace->theclass->flags & CLASS_IS_TEMPL_INST)) { - deduce.tmclass = TEMPL_CLASS_INST(funcobj->nspace->theclass)->templ; - deduce.inst = TEMPL_CLASS_INST(funcobj->nspace->theclass); - } - - instobj->type = CTemplTool_DeduceTypeCopy(&deduce, funcobj->type, &instobj->qual); - inst->object = instobj; - - if (IS_TYPE_FUNC(instobj->type)) { - TYPE_FUNC(instobj->type)->flags &= ~FUNC_DEFINED; - if (TYPE_FUNC(instobj->type)->flags & FUNC_IS_CTOR) { - FuncArg *funcarg; - CError_ASSERT(152, TYPE_FUNC(instobj->type)->flags & FUNC_METHOD); - CError_ASSERT(153, funcarg = TYPE_FUNC(instobj->type)->args); - - if (TYPE_METHOD(instobj->type)->theclass->flags & CLASS_HAS_VBASES) - CError_ASSERT(156, funcarg = funcarg->next); - - if (funcarg->next) - CDecl_CheckCtorIntegrity(funcarg->next, TYPE_METHOD(instobj->type)->theclass); - } - } - - if ((instobj->qual & Q_INLINE) && templ->stream.tokens) - CInline_AddTemplateFunctionAction(instobj, templ, inst); - - } else { - inst->object = object2; - } - - return inst; -} - -TemplFuncInstance *CTempl_CheckFuncInstance(Object *object1, TypeFunc *tfunc, TemplArg *args, Object *object2) { - DeduceInfo info; - int i; - - if (!CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(object1)->params, args, 1)) - return NULL; - - if (!CTempl_DeduceType(object1->type, 0, TYPE(tfunc), 0, info.args, 0, 0)) - return NULL; - - i = 0; - while (i < info.maxCount) { - if (!info.args[i++].is_deduced) - return NULL; - } - - return CTempl_GetCreateFuncInstance(object1, info.args, object2); -} - -TemplFuncInstance *CTempl_DeduceFunc(Object *object1, TypeFunc *tfunc, TemplArg *args, Object *object2, Boolean flag) { - return CTempl_CheckFuncInstance(object1, tfunc, args, object2); -} - -static Boolean CTempl_FuncIsAtLeastAsSpecialized(Object *func1, Object *func2) { - int i; - FuncArg *arg1; - FuncArg *arg2; - Type *type1; - Type *type2; - UInt32 qual1; - UInt32 qual2; - DeduceInfo info; - - arg1 = TYPE_FUNC(func2->type)->args; - if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(func2->type))) - arg1 = arg1->next; - - i = 0; - while (1) { - if (!arg1) - break; - CError_ASSERT(231, arg1->type != &stvoid); - if (arg1 == &elipsis) - break; - if (arg1 == &oldstyle) - break; - arg1 = arg1->next; - i++; - } - - if (!CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(func2)->params, NULL, 0)) - return 0; - - arg1 = TYPE_FUNC(func1->type)->args; - if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(func1->type))) - arg1 = arg1->next; - - arg2 = TYPE_FUNC(func2->type)->args; - if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(func2->type))) - arg2 = arg2->next; - - while (i > 0) { - if (!arg1) - break; - if (arg1 == &elipsis) - break; - if (arg1 == &oldstyle) - break; - - CError_ASSERT(255, arg2); - - type1 = arg1->type; - qual1 = arg1->qual & (Q_CONST | Q_VOLATILE); - qual2 = arg2->qual & (Q_CONST | Q_VOLATILE); - type2 = arg2->type; - - if (!CTemplTool_IsTemplateArgumentDependentType(type2)) { - if (IS_TYPE_REFERENCE(type1)) - type1 = TPTR_TARGET(type1); - type1 = CParser_RemoveTopMostQualifiers(type1, &qual1); - - if (IS_TYPE_REFERENCE(type2)) - type2 = TPTR_TARGET(type2); - type2 = CParser_RemoveTopMostQualifiers(type2, &qual2); - - if (!is_typesame(type1, type2) || qual1 != qual2) - return 0; - } else { - if (!CTempl_DeduceType(type2, qual2, type1, qual1, info.args, 0, 0)) - return 0; - } - - arg1 = arg1->next; - arg2 = arg2->next; - i--; - } - - return 1; -} - -Boolean CTempl_FuncIsMoreSpecialized(Object *object1, Object *object2) { - return CTempl_FuncIsAtLeastAsSpecialized(object1, object2) && !CTempl_FuncIsAtLeastAsSpecialized(object2, object1); -} - -Object *CTempl_PartialOrdering(Object *object, ObjectList *list, int count) { - int i; - int j; - Object **array; - ObjectList *scan; - Object *arrayBuffer[16]; - - for (count = 1, scan = list; scan; scan = scan->next) { - if (IS_TEMPL_FUNC(scan->object->type)) - count++; - } - - if (count > 16) - array = lalloc(sizeof(Object *) * count); - else - array = arrayBuffer; - - array[0] = object; - for (i = 1, scan = list; scan; scan = scan->next) { - if (IS_TEMPL_FUNC(scan->object->type)) - array[i++] = scan->object; - } - - for (i = 0; i < count; i++) { - if (array[i]) { - for (j = 0; j < count; j++) { - if (array[j] && i != j && CTempl_FuncIsMoreSpecialized(array[i], array[j])) - array[j] = NULL; - } - } - } - - object = NULL; - - for (i = 0; i < count; i++) { - if (array[i]) { - if (object) - return NULL; - object = array[i]; - } - } - - return object; -} - -int CTempl_GetTemplateArgumentExpressionIndex(TemplArg *arg) { - CError_ASSERT(529, arg->data.paramdecl.expr); - - if (ENODE_IS(arg->data.paramdecl.expr, ETEMPLDEP) && arg->data.paramdecl.expr->data.templdep.subtype == TDE_PARAM) - return arg->data.paramdecl.expr->data.templdep.u.pid.index; - - return -1; -} - -static Type *CTempl_GetSpecifiedType(TemplateFunction *templ, Type *type, UInt32 qual, TemplArg *args, UInt32 *resultQual) { - TypeDeduce deduce; - - CTemplFunc_SetupTypeDeduce(&deduce, templ, args); - *resultQual = qual; - return CTemplTool_DeduceTypeCopy(&deduce, type, resultQual); -} - -static Boolean CTempl_DeduceTemplateArgs(TemplArg *args1, TemplArg *args2, TemplArg *argArray) { - int index; - - while (1) { - if (!args1) - return !args2; - if (!args2) - return 0; - - if (args1->pid.type != args2->pid.type) - return 0; - - switch (args1->pid.type) { - case TPT_TYPE: - if (!CTempl_DeduceType1( - args1->data.typeparam.type, args1->data.typeparam.qual, - args2->data.typeparam.type, args2->data.typeparam.qual, - argArray, 1 - )) - return 0; - break; - - case TPT_NONTYPE: - if (CTemplTool_IsTemplateArgumentDependentExpression(args1->data.paramdecl.expr)) { - index = CTempl_GetTemplateArgumentExpressionIndex(args1); - if (index < 0) - return 1; - - if (argArray[index].is_deduced) { - if (!CTemplTool_EqualExprTypes(args2->data.paramdecl.expr, argArray[index].data.paramdecl.expr)) - return 0; - } else { - argArray[index].data.paramdecl.expr = args2->data.paramdecl.expr; - argArray[index].pid.type = TPT_NONTYPE; - argArray[index].is_deduced = 1; - } - } else { - if (!CTemplTool_EqualExprTypes(args2->data.paramdecl.expr, args1->data.paramdecl.expr)) - return 0; - } - break; - - case TPT_TEMPLATE: - if (!IS_TEMPL_CLASS(args2->data.ttargtype)) - return 0; - - index = args1->pid.index; - if (argArray[index].is_deduced) { - if (args2->data.ttargtype != argArray[index].data.ttargtype) - return 0; - } else { - argArray[index].data.ttargtype = args2->data.ttargtype; - argArray[index].pid.type = TPT_TEMPLATE; - argArray[index].is_deduced = 1; - } - break; - - default: - CError_FATAL(640); - } - - args1 = args1->next; - args2 = args2->next; - } -} - -static Boolean CTempl_DeduceTemplDepTemplate(TemplClass *templ1, TemplArg *args1, TemplClass *templ2, TemplArg *args2, TemplArg *argArray) { - if (templ1 != templ2) - return 0; - - return CTempl_DeduceTemplateArgs(args2, args1, argArray); -} - -static Boolean CTempl_DeduceTemplateType(TemplClass *templ, TemplArg *args, TemplClassInst *inst, TemplArg *argArray) { - TemplClassInst *scan; - - for (scan = templ->instances; scan; scan = scan->next) { - if (scan == inst) - return CTempl_DeduceTemplateArgs(args, scan->oargs ? scan->oargs : scan->inst_args, argArray); - } - - return 0; -} - -static Boolean CTempl_DeduceTemplateTypeBase(TemplClass *templ, TemplArg *args, TemplClassInst *inst, TemplArg *argArray, Boolean flag) { - ClassList *base; - - if (CTempl_DeduceTemplateType(templ, args, inst, argArray)) - return 1; - - if (flag) { - for (base = inst->theclass.bases; base; base = base->next) { - if (CTempl_DeduceTemplateType(templ, args, TEMPL_CLASS_INST(base->base), argArray)) { - ctempl_conversion_deduction = 1; - return 1; - } - } - - for (base = inst->theclass.bases; base; base = base->next) { - if (CTempl_DeduceTemplateTypeBase(templ, args, TEMPL_CLASS_INST(base->base), argArray, 1)) { - ctempl_conversion_deduction = 1; - return 1; - } - } - } - - return 0; -} - -static Boolean CTempl_DeduceQualTemplate(TypeTemplDep *type1, TemplArg *args1, Type *type2, TemplArg *argArray) { - int index; - - if (type1->dtype == TEMPLDEP_ARGUMENT && type1->u.pid.type == TPT_TEMPLATE) { - index = type1->u.pid.index; - if (IS_TEMPL_CLASS_INST(type2)) { - if (argArray[index].is_deduced) { - if (argArray[index].data.ttargtype != TYPE(TEMPL_CLASS_INST(type2)->templ)) - return 0; - } else { - argArray[index].data.ttargtype = TYPE(TEMPL_CLASS_INST(type2)->templ); - argArray[index].pid.type = TPT_TEMPLATE; - argArray[index].is_deduced = 1; - } - - return CTempl_DeduceTemplateArgs(args1, TEMPL_CLASS_INST(type2)->inst_args, argArray); - } - - if (IS_TYPE_TEMPLATE(type2)) { - if (TYPE_TEMPLATE(type2)->dtype == TEMPLDEP_TEMPLATE) { - if (argArray[index].is_deduced) { - if (argArray[index].data.ttargtype != TYPE(TYPE_TEMPLATE(type2)->u.templ.templ)) - return 0; - } else { - argArray[index].data.ttargtype = TYPE(TYPE_TEMPLATE(type2)->u.templ.templ); - argArray[index].pid.type = TPT_TEMPLATE; - argArray[index].is_deduced = 1; - } - - return CTempl_DeduceTemplateArgs(args1, TYPE_TEMPLATE(type2)->u.templ.args, argArray); - } - - if (TYPE_TEMPLATE(type2)->dtype == TEMPLDEP_QUALTEMPL) { - return - CTempl_DeduceTypeTemplDep(type1, 0, TYPE(TYPE_TEMPLATE(type2)->u.qualtempl.type), 0, argArray, 1) && - CTempl_DeduceTemplateArgs(args1, TYPE_TEMPLATE(type2)->u.qualtempl.args, argArray); - } - } - } - - return 0; -} - -static Boolean CTempl_DeduceTypeTemplDep(TypeTemplDep *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray, Boolean flag) { - Type *tmptype; - UInt32 tmpqual; - short index; - Boolean f; - UInt32 modqual; - - switch (type1->dtype) { - case TEMPLDEP_ARGUMENT: - index = type1->u.pid.index; - tmptype = type2; - if (type1->u.pid.type == TPT_TEMPLATE) { - if (argArray[index].is_deduced) { - if (!is_typesame(tmptype, argArray[index].data.ttargtype)) - return 0; - } else { - argArray[index].data.ttargtype = type2; - argArray[index].pid.type = TPT_TEMPLATE; - argArray[index].is_deduced = 1; - } - return 1; - } - - switch (type2->type) { - case TYPEPOINTER: - tmpqual = qual2; - f = 0; - qual2 = TPTR_QUAL(type2); - modqual = qual2; - - if ((modqual & Q_CONST) && (qual1 & Q_CONST)) { - modqual &= ~Q_CONST; - f = 1; - } - if ((modqual & Q_VOLATILE) && (qual1 & Q_VOLATILE)) { - modqual &= ~Q_VOLATILE; - f = 1; - } - - if (f) { - tmptype = galloc(sizeof(TypePointer)); - *TYPE_POINTER(tmptype) = *TYPE_POINTER(type2); - TPTR_QUAL(tmptype) = modqual; - } - - if (flag && (qual2 | modqual) != (qual1 | modqual)) - return 0; - - break; - - case TYPEMEMBERPOINTER: - tmpqual = qual2; - f = 0; - qual2 = TYPE_MEMBER_POINTER(type2)->qual; - modqual = qual2; - - if ((modqual & Q_CONST) && (qual1 & Q_CONST)) { - modqual &= ~Q_CONST; - f = 1; - } - if ((modqual & Q_VOLATILE) && (qual1 & Q_VOLATILE)) { - modqual &= ~Q_VOLATILE; - f = 1; - } - - if (f) { - tmptype = galloc(sizeof(TypeMemberPointer)); - *TYPE_MEMBER_POINTER(tmptype) = *TYPE_MEMBER_POINTER(type2); - TYPE_MEMBER_POINTER(tmptype)->qual = modqual; - } - - if (flag && (qual2 | modqual) != (qual1 | modqual)) - return 0; - - break; - - default: - tmpqual = 0; - if ((qual2 & Q_CONST) && !(qual1 & Q_CONST)) - tmpqual |= Q_CONST; - if ((qual2 & Q_VOLATILE) && !(qual1 & Q_VOLATILE)) - tmpqual |= Q_VOLATILE; - - if (flag && (qual2 | tmpqual) != (qual1 | tmpqual)) - return 0; - } - - if (argArray[index].is_deduced) { - if (!is_typesame(tmptype, argArray[index].data.typeparam.type) || tmpqual != argArray[index].data.typeparam.qual) - return 0; - } else { - argArray[index].data.typeparam.type = tmptype; - argArray[index].data.typeparam.qual = tmpqual; - argArray[index].pid.type = TPT_TYPE; - argArray[index].is_deduced = 1; - } - return 1; - - case TEMPLDEP_QUALNAME: - return 1; - - case TEMPLDEP_TEMPLATE: - if (IS_TYPE_CLASS(type2)) - return CTempl_DeduceTemplateTypeBase( - type1->u.templ.templ, type1->u.templ.args, - TEMPL_CLASS_INST(type2), argArray, 0); - - if (IS_TYPE_TEMPLATE(type2) && TYPE_TEMPLATE(type2)->dtype == TEMPLDEP_TEMPLATE) - return CTempl_DeduceTemplDepTemplate( - TYPE_TEMPLATE(type2)->u.templ.templ, TYPE_TEMPLATE(type2)->u.templ.args, - type1->u.templ.templ, type1->u.templ.args, - argArray - ); - - return 0; - - case TEMPLDEP_ARRAY: - if (IS_TYPE_ARRAY(type2)) { - SInt32 elements; - - if (!CTempl_DeduceType1(type1->u.array.type, qual1, TPTR_TARGET(type2), qual2, argArray, flag)) - return 0; - - if (ENODE_IS(type1->u.array.index, EINTCONST)) { - CError_ASSERT(961, TPTR_TARGET(type2)->size); - return (type2->size / TPTR_TARGET(type2)->size) == CInt64_GetULong(&type1->u.array.index->data.intval); - } - - if (!ENODE_IS(type1->u.array.index, ETEMPLDEP) || type1->u.array.index->data.templdep.subtype != TDE_PARAM) - return 1; - - CError_ASSERT(970, TPTR_TARGET(type2)->size); - - elements = type2->size / TPTR_TARGET(type2)->size; - index = type1->u.array.index->data.templdep.u.pid.index; - if (argArray[index].is_deduced) { - CError_ASSERT(976, ENODE_IS(argArray[index].data.paramdecl.expr, EINTCONST)); - return elements == CInt64_GetULong(&argArray[index].data.paramdecl.expr->data.intval); - } else { - argArray[index].data.paramdecl.expr = intconstnode(CABI_GetPtrDiffTType(), elements); - argArray[index].pid.type = TPT_NONTYPE; - argArray[index].is_deduced = 1; - return 1; - } - } else if (IS_TYPE_TEMPLATE(type2) && TYPE_TEMPLATE(type2)->dtype == TEMPLDEP_ARRAY) { - if (!CTempl_DeduceType1(type1->u.array.type, qual1, TYPE_TEMPLATE(type2)->u.array.type, qual2, argArray, flag)) - return 0; - - if (ENODE_IS(type1->u.array.index, EINTCONST)) { - return ENODE_IS(TYPE_TEMPLATE(type2)->u.array.index, EINTCONST) && - CInt64_Equal(type1->u.array.index->data.intval, TYPE_TEMPLATE(type2)->u.array.index->data.intval); - } - - if (!ENODE_IS(type1->u.array.index, ETEMPLDEP) || type1->u.array.index->data.templdep.subtype != TDE_PARAM) - return 1; - - index = type1->u.array.index->data.templdep.u.pid.index; - if (argArray[index].is_deduced) { - return CTemplTool_EqualExprTypes(TYPE_TEMPLATE(type2)->u.array.index, argArray[index].data.paramdecl.expr); - } else { - argArray[index].data.paramdecl.expr = TYPE_TEMPLATE(type2)->u.array.index; - argArray[index].pid.type = TPT_NONTYPE; - argArray[index].is_deduced = 1; - return 1; - } - } - - return 0; - - case TEMPLDEP_QUALTEMPL: - return CTempl_DeduceQualTemplate(type1->u.qualtempl.type, type1->u.qualtempl.args, type2, argArray); - - case TEMPLDEP_BITFIELD: - default: - CError_FATAL(1022); - return 1; - } -} - -static Boolean CTempl_DeduceFuncType(TypeFunc *tfunc1, TypeFunc *tfunc2, TemplArg *argArray) { - FuncArg *arg1; - FuncArg *arg2; - Type *type2; - Type *type1; - UInt32 qual2; - UInt32 qual1; - - arg1 = tfunc1->args; - arg2 = tfunc2->args; - - if (IS_TYPEFUNC_NONSTATIC_METHOD(tfunc1) && !IS_TYPEFUNC_METHOD(tfunc2)) { - CError_ASSERT(1045, arg1); - arg1 = arg1->next; - } - - while (1) { - if (arg1 == NULL) - return !arg2; - if (arg1 == &oldstyle) - return arg2 == &oldstyle; - if (arg1 == &elipsis) - return arg2 == &elipsis; - - if (arg2 == NULL || arg2 == &oldstyle || arg2 == &elipsis) - return 0; - - qual2 = arg2->qual; - type2 = CParser_RemoveTopMostQualifiers(arg2->type, &qual2); - - qual1 = arg1->qual; - type1 = CParser_RemoveTopMostQualifiers(arg1->type, &qual1); - - if (!CTempl_DeduceType1(type1, qual1, type2, qual2, argArray, 1)) - return 0; - - arg1 = arg1->next; - arg2 = arg2->next; - } -} - -static Boolean CTempl_DeduceType1(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray, Boolean flag) { - while (1) { - switch (type1->type) { - case TYPETEMPLATE: - return CTempl_DeduceTypeTemplDep(TYPE_TEMPLATE(type1), qual1, type2, qual2, argArray, flag); - - case TYPEVOID: - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - case TYPESTRUCT: - case TYPECLASS: - return type1 == type2; - - case TYPEMEMBERPOINTER: - if (type1->type != type2->type || TYPE_MEMBER_POINTER(type1)->qual != TYPE_MEMBER_POINTER(type2)->qual) - return 0; - if (!CTempl_DeduceType1(TYPE_MEMBER_POINTER(type1)->ty1, qual1, TYPE_MEMBER_POINTER(type2)->ty1, qual2, argArray, flag)) - return 0; - type1 = TYPE_MEMBER_POINTER(type1)->ty2; - type2 = TYPE_MEMBER_POINTER(type2)->ty2; - continue; - - case TYPEARRAY: - if (type2->type != TYPEARRAY) - return 0; - type1 = TPTR_TARGET(type1); - type2 = TPTR_TARGET(type2); - continue; - - case TYPEPOINTER: - if (type2->type != TYPEPOINTER || TPTR_QUAL(type1) != TPTR_QUAL(type2)) - return 0; - type1 = TPTR_TARGET(type1); - type2 = TPTR_TARGET(type2); - continue; - - case TYPEFUNC: - if (type1->type != type2->type) - return 0; - - if (CTempl_DeduceType1(TYPE_FUNC(type1)->functype, TYPE_FUNC(type1)->qual, TYPE_FUNC(type2)->functype, TYPE_FUNC(type2)->qual, argArray, flag)) - return CTempl_DeduceFuncType(TYPE_FUNC(type1), TYPE_FUNC(type2), argArray); - - return 0; - - default: - CError_FATAL(1124); - } - } -} - -static Boolean CTempl_DeduceType2(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray) { - while (1) { - switch (type1->type) { - case TYPEPOINTER: - if (type2->type != TYPEPOINTER) - return 0; - if (!CParser_IsSameOrMoreCVQualified(TPTR_QUAL(type2), TPTR_QUAL(type1))) - return 0; - type1 = TPTR_TARGET(type1); - type2 = TPTR_TARGET(type2); - continue; - - case TYPEMEMBERPOINTER: - if (type2->type != TYPEMEMBERPOINTER) - return 0; - if (!CParser_IsSameOrMoreCVQualified(TYPE_MEMBER_POINTER(type2)->qual, TYPE_MEMBER_POINTER(type1)->qual)) - return 0; - if (!CTempl_DeduceType2(TYPE_MEMBER_POINTER(type1)->ty1, qual1, TYPE_MEMBER_POINTER(type2)->ty1, qual2, argArray)) - return 0; - type1 = TYPE_MEMBER_POINTER(type1)->ty2; - type2 = TYPE_MEMBER_POINTER(type2)->ty2; - continue; - - default: - if (CParser_IsSameOrMoreCVQualified(qual2, qual1)) - return CTempl_DeduceType1(type1, qual2, type2, qual2, argArray, 0); - return 0; - } - } -} - -static Boolean CTempl_DeduceType3(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray) { - Boolean flag = 0; - - while (1) { - switch (type1->type) { - case TYPEPOINTER: - flag = 1; - if (type2->type != TYPEPOINTER) - return 0; - if (!CParser_IsSameOrMoreCVQualified(TPTR_QUAL(type2), TPTR_QUAL(type1))) - return 0; - type1 = TPTR_TARGET(type1); - type2 = TPTR_TARGET(type2); - continue; - - case TYPEMEMBERPOINTER: - flag = 1; - if (type2->type != TYPEMEMBERPOINTER) - return 0; - if (!CParser_IsSameOrMoreCVQualified(TYPE_MEMBER_POINTER(type2)->qual, TYPE_MEMBER_POINTER(type1)->qual)) - return 0; - if (!CTempl_DeduceType2(TYPE_MEMBER_POINTER(type1)->ty1, qual1, TYPE_MEMBER_POINTER(type2)->ty1, qual2, argArray)) - return 0; - type1 = TYPE_MEMBER_POINTER(type1)->ty2; - type2 = TYPE_MEMBER_POINTER(type2)->ty2; - continue; - - default: - if (!flag) - return 0; - if (CParser_IsSameOrMoreCVQualified(qual2, qual1)) - return CTempl_DeduceType1(type1, qual2, type2, qual2, argArray, 0); - return 0; - } - } -} - -static Boolean CTempl_DeduceType4(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray) { - if (IS_TYPE_POINTER_ONLY(type1)) { - if (!IS_TYPE_POINTER_ONLY(type2)) - return 0; - - if (!CParser_IsSameOrMoreCVQualified(TPTR_QUAL(type1), TPTR_QUAL(type2))) - return 0; - - type1 = TPTR_TARGET(type1); - type2 = TPTR_TARGET(type2); - } - - if (IS_TYPE_TEMPLATE(type1) && TYPE_TEMPLATE(type1)->dtype == TEMPLDEP_TEMPLATE && IS_TYPE_CLASS(type2)) { - if (CParser_IsSameOrMoreCVQualified(qual1, qual2)) - return CTempl_DeduceTemplateTypeBase( - TYPE_TEMPLATE(type1)->u.templ.templ, - TYPE_TEMPLATE(type1)->u.templ.args, - TEMPL_CLASS_INST(type2), - argArray, - 1); - else - return 0; - } - - return 0; -} - -Boolean CTempl_DeduceType(Type *type1, UInt32 qual1, Type *type2, UInt32 qual2, TemplArg *argArray, Boolean flag1, Boolean flag2) { - Boolean flag31; - Boolean flag8; - - flag31 = 0; - flag8 = 1; - - if (flag1 || flag2) { - if (IS_TYPE_REFERENCE(type1)) { - type1 = TPTR_TARGET(type1); - flag31 = 1; - } else { - switch (type2->type) { - case TYPEFUNC: - type2 = CDecl_NewPointerType(type2); - break; - case TYPEARRAY: - type2 = CDecl_NewPointerType(TPTR_TARGET(type2)); - break; - } - - type1 = CParser_RemoveTopMostQualifiers(type1, &qual1); - type2 = CParser_RemoveTopMostQualifiers(type2, &qual2); - } - flag8 = 0; - } - - if (CTempl_DeduceType1(type1, qual1, type2, qual2, argArray, flag8)) - return 1; - - if (flag1 || flag2) { - if (flag31 && CTempl_DeduceType2(type1, qual1, type2, qual2, argArray)) - return 1; - if (CTempl_DeduceType3(type1, qual1, type2, qual2, argArray)) - return 1; - if (flag1 && CTempl_DeduceType4(type1, qual1, type2, qual2, argArray)) - return 1; - } - - return 0; -} - -static Boolean CTempl_TypeNeedsDeduction(Type *type) { - FuncArg *arg; - Boolean result; - - while (1) { - switch (type->type) { - case TYPETEMPLATE: - switch (TYPE_TEMPLATE(type)->dtype) { - case TEMPLDEP_ARGUMENT: - if ( - TYPE_TEMPLATE(type)->u.pid.index >= ctempl_explicitargs_num || - TYPE_TEMPLATE(type)->u.pid.nindex != ctempl_explicitargs_nindex - ) - ctempl_explicitargs_all = 0; - return 1; - - case TEMPLDEP_QUALNAME: - CTempl_TypeNeedsDeduction(TYPE(TYPE_TEMPLATE(type)->u.qual.type)); - return 1; - - case TEMPLDEP_TEMPLATE: - ctempl_explicitargs_all = 0; - return 1; - - case TEMPLDEP_ARRAY: - CTempl_TypeNeedsDeduction(TYPE_TEMPLATE(type)->u.array.type); - ctempl_explicitargs_all = 0; - return 1; - - case TEMPLDEP_QUALTEMPL: - CTempl_TypeNeedsDeduction(TYPE(TYPE_TEMPLATE(type)->u.qualtempl.type)); - ctempl_explicitargs_all = 0; - return 1; - - case TEMPLDEP_BITFIELD: - default: - CError_FATAL(1357); - } - - case TYPEVOID: - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - case TYPESTRUCT: - case TYPECLASS: - return 0; - - case TYPEMEMBERPOINTER: - result = 0; - if (CTempl_TypeNeedsDeduction(TYPE_MEMBER_POINTER(type)->ty1)) - result = 1; - if (CTempl_TypeNeedsDeduction(TYPE_MEMBER_POINTER(type)->ty2)) - result = 1; - return result; - - case TYPEPOINTER: - case TYPEARRAY: - type = TPTR_TARGET(type); - continue; - - case TYPEFUNC: - result = 0; - for (arg = TYPE_FUNC(type)->args; arg && arg != &elipsis; arg = arg->next) { - if (CTempl_TypeNeedsDeduction(arg->type)) - result = 1; - } - - if (CTempl_TypeNeedsDeduction(TYPE_FUNC(type)->functype)) - result = 1; - return result; - - default: - CError_FATAL(1389); - } - } -} - -static Boolean CTempl_MatchTemplFunc(Object *object, DeduceInfo *info, FuncArg *args, ENodeList *exprs, Match13 *match13ptr) { - Match13 match13; - int i; - - memclrw(&match13, sizeof(match13)); - - while (1) { - if (!args || args->type == &stvoid) { - if (!exprs) - break; - return 0; - } - - if (args == &elipsis) - break; - if (args == &oldstyle) - break; - - if (!exprs) { - if (args->dexpr) - break; - return 0; - } - - ctempl_explicitargs_nindex = info->x12C; - ctempl_explicitargs_num = info->count; - ctempl_explicitargs_all = 1; - - if (CTempl_TypeNeedsDeduction(args->type)) { - if (!ctempl_explicitargs_all) { - UInt32 cv2; - UInt32 cv1; - Type *type2; - Type *type1; - UInt32 qual2; - UInt32 qual1; - - type1 = args->type; - qual1 = args->qual & (Q_CONST | Q_VOLATILE); - - type2 = exprs->node->rtype; - qual2 = ENODE_QUALS(exprs->node); - - if (IS_TYPE_REFERENCE(type1)) { - type1 = TPTR_TARGET(type1); - cv1 = CParser_GetCVTypeQualifiers(type1, qual1); - cv2 = CParser_GetCVTypeQualifiers(type2, qual2); - if ( - (!(cv1 & Q_CONST) && (cv2 & Q_CONST)) || - (!(cv1 & Q_VOLATILE) && (cv2 & Q_VOLATILE)) - ) - return 0; - - if (!(cv1 & Q_CONST) && !CExpr_IsLValue(exprs->node)) - return 0; - } - - type1 = CParser_RemoveTopMostQualifiers(type1, &qual1); - type2 = CParser_RemoveTopMostQualifiers(type2, &qual2); - - if (ENODE_IS(exprs->node, EOBJREF) && IS_TEMPL_FUNC(exprs->node->data.objref->type)) - return 0; - - if (ENODE_IS(exprs->node, EOBJLIST)) { - NameSpaceObjectList *list; - - for (list = exprs->node->data.objlist.list; list; list = list->next) { - if (list->object->otype == OT_OBJECT && IS_TEMPL_FUNC(OBJECT(list->object)->type)) - break; - } - - if (list) - return 0; - - if (IS_TYPE_FUNC(type2)) - type2 = CDecl_NewPointerType(type2); - } - - ctempl_conversion_deduction = 0; - if (!CTempl_DeduceType(type1, qual1, type2, qual2, info->args, 1, 0)) - return 0; - - if (ctempl_conversion_deduction) - match13.anotherm5.x4++; - else - match13.anotherm5.x0++; - - if (IS_TYPE_POINTER_ONLY(args->type)) - CExpr_MatchCV(type2, qual2, args->type, args->qual, &match13); - - } else { - Type *type; - UInt32 qual; - - type = CTempl_GetSpecifiedType(CTemplTool_GetFuncTempl(object), args->type, args->qual, info->args, &qual); - if (type && !CExpr_MatchAssign(type, qual, exprs->node, &match13)) - return 0; - } - } else { - if (copts.old_argmatch && !CExpr_MatchAssign(args->type, args->qual, exprs->node, &match13)) - return 0; - } - - exprs = exprs->next; - args = args->next; - } - - for (i = 0; i < info->maxCount; i++) { - if (!info->args[i].is_deduced) - return 0; - info->args[i].next = &info->args[i + 1]; - } - info->args[info->maxCount].next = NULL; - - return CExpr_MatchCompare(object, match13ptr, &match13); -} - -void CTempl_FuncMatch(NameSpaceObjectList *list, TemplArg *args, ENodeList *argexprs, Match13 *match13ptr, ENode *expr) { - Object *obj; - Object *success; - Object *object1; - FuncMatchArgs funcMatchArgs; - DeduceInfo info; - DeduceInfo info2; - - object1 = match13ptr->obj; - success = NULL; - while (list) { - obj = OBJECT(list->object); - if ( - obj->otype == OT_OBJECT && - IS_TEMPL_FUNC(obj->type) && - CExpr_GetFuncMatchArgs(obj, argexprs, expr, &funcMatchArgs) && - CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(obj)->params, args, 0) && - CTempl_MatchTemplFunc(obj, &info, funcMatchArgs.args, funcMatchArgs.exprs, match13ptr) - ) - { - info2 = info; - if (info.args == info.argBuffer) - info2.args = info2.argBuffer; - success = obj; - } - list = list->next; - } - - if (success) { - if (match13ptr->list) { - ENodeList *argexpr = argexprs; - int argexprcount = 0; - while (argexpr) { - argexpr = argexpr->next; - argexprcount++; - } - - obj = CTempl_PartialOrdering(match13ptr->obj, match13ptr->list, argexprcount); - if (!obj) { - CError_OverloadedFunctionError(match13ptr->obj, match13ptr->list); - match13ptr->list = NULL; - if (object1) - match13ptr->obj = object1; - else - match13ptr->obj = CTempl_GetCreateFuncInstance(success, info2.args, NULL)->object; - } else { - NameSpaceObjectList mylist; - mylist.next = NULL; - mylist.object = OBJ_BASE(obj); - memclrw(match13ptr, sizeof(Match13)); - CTempl_FuncMatch(&mylist, args, argexprs, match13ptr, expr); - } - } else { - match13ptr->obj = CTempl_GetCreateFuncInstance(success, info2.args, NULL)->object; - } - } else { - match13ptr->obj = object1; - } -} - -static Boolean CExpr_DeduceFromObjList(FuncArg *arg, NameSpaceObjectList *list, DeduceInfo *info) { - TemplArg *savebuf; - NameSpaceObjectList *scan; - SInt32 size; - - for (scan = list; scan; scan = scan->next) { - if (scan->object->otype == OT_OBJECT && IS_TEMPL_FUNC(OBJECT(scan->object)->type)) - return 0; - } - - size = sizeof(TemplArg) * info->maxCount; - savebuf = lalloc(size); - - for (scan = list; scan; scan = scan->next) { - if (scan->object->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(scan->object)->type)) { - Object *obj; - - memcpy(savebuf, info->args, size); - - obj = OBJECT(scan->object); - if (CTempl_DeduceType( - arg->type, arg->qual & (Q_CONST | Q_VOLATILE), - obj->type, obj->qual, - savebuf, 1, 0 - )) - { - memcpy(info->args, savebuf, size); - return 1; - } - } - } - - return 0; -} - -Object *CTempl_DeduceFromFunctionCall(Object *funcobj, TemplArg *templargs, ENodeList *argexprs) { - DeduceInfo info; - FuncArg *arg; - int i; - - CError_ASSERT(1655, IS_TEMPL_FUNC(funcobj->type)); - - if (CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(funcobj)->params, templargs, 0)) { - arg = TYPE_FUNC(funcobj->type)->args; - if (IS_TYPEFUNC_NONSTATIC_METHOD(TYPE_FUNC(funcobj->type))) { - CError_ASSERT(1664, arg); - arg = arg->next; - } - - while (1) { - if (!arg || arg->type == &stvoid) { - if (argexprs) - return NULL; - break; - } - - if (arg == &elipsis) - break; - if (arg == &oldstyle) - break; - - if (!argexprs) { - if (arg->dexpr) - break; - return NULL; - } - - ctempl_explicitargs_nindex = info.x12C; - ctempl_explicitargs_num = info.count; - ctempl_explicitargs_all = 1; - - if (CTempl_TypeNeedsDeduction(arg->type) && !ctempl_explicitargs_all) { - ENode *node = argexprs->node; - - if (ENODE_IS(node, EOBJREF) && IS_TEMPL_FUNC(node->data.objref->type)) - return NULL; - - if (ENODE_IS(node, EOBJLIST)) { - if (!CExpr_DeduceFromObjList(arg, node->data.objlist.list, &info)) - return NULL; - } else { - if (!CTempl_DeduceType( - arg->type, arg->qual & (Q_CONST | Q_VOLATILE), - node->rtype, ENODE_QUALS(node), - info.args, 1, 0)) - return NULL; - } - } - - argexprs = argexprs->next; - arg = arg->next; - } - - for (i = 0; i < info.maxCount; i++) { - if (!info.args[i].is_deduced) - return 0; - info.args[i].next = &info.args[i + 1]; - } - info.args[info.maxCount].next = NULL; - - return CTempl_GetCreateFuncInstance(funcobj, info.args, NULL)->object; - } else { - return NULL; - } -} - -Object *CTempl_DeduceFromConversion(Object *funcobj, Type *type, UInt32 qual) { - DeduceInfo info; - int i; - - CError_ASSERT(1745, IS_TEMPL_FUNC(funcobj->type)); - - if (!CTemplTool_InitDeduceInfo(&info, CTemplTool_GetFuncTempl(funcobj)->params, NULL, 0)) - return NULL; - - ctempl_explicitargs_nindex = info.x12C; - ctempl_explicitargs_num = info.count; - ctempl_explicitargs_all = 1; - - if (!CTempl_TypeNeedsDeduction(TYPE_FUNC(funcobj->type)->functype)) - return NULL; - - if (!CTempl_DeduceType(TYPE_FUNC(funcobj->type)->functype, TYPE_FUNC(funcobj->type)->qual, type, qual, info.args, 0, 1)) - return NULL; - - for (i = 0; i < info.maxCount; i++) { - if (!info.args[i].is_deduced) - return 0; - info.args[i].next = &info.args[i + 1]; - } - info.args[info.maxCount].next = NULL; - - return CTempl_GetCreateFuncInstance(funcobj, info.args, NULL)->object; -} - -static int CTemplFunc_TemplateNestLevel(NameSpace *nspace) { - int level = 0; - - while (nspace) { - if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL_ANY)) - level++; - nspace = nspace->parent; - } - - return level; -} - -static Boolean CTemplFunc_SameFuncType(TypeFunc *a, TypeFunc *b) { - FuncArg *arg1; - FuncArg *arg2; - - CError_ASSERT(1800, IS_TYPE_FUNC(a) && IS_TYPE_FUNC(b)); - - if (!is_typesame(a->functype, b->functype)) - return 0; - - if (a->qual != b->qual) - return 0; - - if ((a->flags & FUNC_CALL_CONV_MASK) != (b->flags & FUNC_CALL_CONV_MASK)) - return 0; - - arg1 = a->args; - if ((a->flags & FUNC_METHOD) && !TYPE_METHOD(a)->is_static) { - CError_ASSERT(1808, arg1); - arg1 = arg1->next; - } - - arg2 = b->args; - if ((b->flags & FUNC_METHOD) && !TYPE_METHOD(b)->is_static) { - CError_ASSERT(1814, arg2); - arg2 = arg2->next; - } - - return is_arglistsame(arg1, arg2); -} - -Object *CTempl_TemplateFunctionCheck(DeclInfo *di, NameSpaceObjectList *nsol) { - TemplArg *arg; - TemplFuncInstance *inst; - Object *object; - - for (arg = di->expltargs; arg; arg = arg->next) { - switch (arg->pid.type) { - case TPT_TYPE: - if (CTemplTool_IsTemplateArgumentDependentType(arg->data.typeparam.type)) - break; - continue; - case TPT_NONTYPE: - if (CTemplTool_IsTemplateArgumentDependentExpression(arg->data.paramdecl.expr)) - break; - continue; - default: - CError_FATAL(1844); - } - - break; - } - - if (arg) { - while (nsol) { - object = OBJECT(nsol->object); - if ( - object->otype == OT_OBJECT && - IS_TEMPL_FUNC(object->type) && - CTemplTool_IsSameTemplate(CTemplTool_GetFuncTempl(object)->params, di->expltargs) && - CTemplFunc_SameFuncType(TYPE_FUNC(OBJECT(nsol->object)->type), TYPE_FUNC(di->thetype)) - ) - return OBJECT(nsol->object); - - nsol = nsol->next; - } - } else { - while (nsol) { - object = OBJECT(nsol->object); - if ( - object->otype == OT_OBJECT && - IS_TEMPL_FUNC(object->type) && - (inst = CTempl_DeduceFunc(object, TYPE_FUNC(di->thetype), di->expltargs, NULL, 1)) - ) - { - if (di->x3C) { - if (!(di->qual & Q_INLINE)) { - if (!inst->is_specialized) - inst->object->qual &= ~Q_INLINE; - } else { - inst->object->qual |= Q_INLINE; - } - - if (!inst->is_specialized && inst->is_instantiated) - CError_Error(CErrorStr335); - - if (di->x3C != (CTemplFunc_TemplateNestLevel(inst->object->nspace) + 1)) - CError_Warning(CErrorStr335); - - inst->is_specialized = 1; - di->x3C = 0; - } - - CTemplTool_MergeArgNames(TYPE_FUNC(di->thetype), TYPE_FUNC(inst->object->type)); - di->x38 = CTemplTool_GetFuncTempl(OBJECT(nsol->object)); - return inst->object; - } - nsol = nsol->next; - } - } - - CError_ResetErrorSkip(); - CError_Error(CErrorStr335); - di->x3C = 0; - return NULL; -} diff --git a/compiler_and_linker/unsorted/CTemplateNew.c b/compiler_and_linker/unsorted/CTemplateNew.c deleted file mode 100644 index c33534a..0000000 --- a/compiler_and_linker/unsorted/CTemplateNew.c +++ /dev/null @@ -1,1880 +0,0 @@ -#include "compiler/CTemplateNew.h" -#include "compiler/CBrowse.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInit.h" -#include "compiler/CInline.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CScope.h" -#include "compiler/CTemplateClass.h" -#include "compiler/CTemplateTools.h" -#include "compiler/CompilerTools.h" -#include "compiler/ObjGenMachO.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/templates.h" - -TemplClass *ctempl_templates; -TemplateFunction *ctempl_templatefuncs; -TemplStack *ctempl_curinstance; -static jmp_buf ctempl_parseparse; -static Boolean ctempl_scanfuncparams; - -// forward decls -static TemplParam *CTempl_ParseParamList(NameSpace *nspace, UInt8 nindex); -static Boolean CTempl_GenClassInstance(TemplClassInst *inst, Boolean flag); - -void CTempl_Setup(void) { - ctempl_curinstance = NULL; - ctempl_templates = NULL; - ctempl_templatefuncs = NULL; - ctempl_instdepth = 0; - ctempl_scanfuncparams = 0; -} - -void CTempl_Cleanup(void) { -} - -static short CTempl_MemberParseLex(void) { - switch ((tk = lex())) { - case ';': - case '=': - case '{': - case '}': - longjmp(ctempl_parseparse, 1); - } - - return tk; -} - -static void CTempl_MemberParseTemplArgList(void) { - struct { - char ch; - char flag; - } stack[256]; - int pos; - - stack[0].ch = '>'; - stack[0].flag = 1; - pos = 0; - while (1) { - switch (CTempl_MemberParseLex()) { - case '<': - if (stack[pos].flag) { - if (pos >= 255) - longjmp(ctempl_parseparse, 1); - stack[++pos].ch = '>'; - stack[pos].flag = 1; - } - continue; - case '(': - if (pos >= 255) - longjmp(ctempl_parseparse, 1); - stack[++pos].ch = ')'; - stack[pos].flag = 0; - continue; - case '[': - if (pos >= 255) - longjmp(ctempl_parseparse, 1); - stack[++pos].ch = ']'; - stack[pos].flag = 0; - continue; - case '>': - if (!(stack[pos].flag)) - continue; - case ')': - case ']': - break; - default: - continue; - } - - if (tk != stack[pos].ch) - longjmp(ctempl_parseparse, 1); - if (--pos < 0) - break; - } -} - -static Type *CTempl_MemberParseTempl(HashNameNode *name) { - Type *type; - - type = CScope_GetTagType(cscope_current, name); - if (!type || !IS_TEMPL_CLASS(type)) - longjmp(ctempl_parseparse, 1); - - CTempl_MemberParseTemplArgList(); - if (lookahead() != TK_COLON_COLON) - return NULL; - CTempl_MemberParseLex(); - - while (1) { - switch (CTempl_MemberParseLex()) { - case TK_IDENTIFIER: - switch (lookahead()) { - case '(': - case ')': - case ';': - case '=': - case '[': - return type; - case TK_COLON_COLON: - CTempl_MemberParseLex(); - continue; - default: - return NULL; - } - break; - case '~': - case TK_OPERATOR: - return type; - default: - return NULL; - } - } -} - -static Boolean CTempl_ParseTemplateMember(void) { - HashNameNode *name; - SInt32 state; - - CPrep_UnLex(); - CPrep_TokenStreamGetState(&state); - - if (setjmp(ctempl_parseparse) == 0) { - while (1) { - switch (CTempl_MemberParseLex()) { - case TK_IDENTIFIER: - name = tkidentifier; - switch (lookahead()) { - case '<': - CTempl_MemberParseLex(); - if (CTempl_MemberParseTempl(name)) { - CError_FATAL(228); - return 1; - } - break; - case TK_COLON_COLON: - CTempl_MemberParseLex(); - while (1) { - if (CTempl_MemberParseLex() != TK_IDENTIFIER) - break; - if (lookahead() != TK_COLON_COLON) - break; - CTempl_MemberParseLex(); - } - break; - } - break; - case 0: - return 0; - default: - continue; - } - break; - } - - while (1) { - switch (CTempl_MemberParseLex()) { - case TK_IDENTIFIER: - name = tkidentifier; - if (CTempl_MemberParseLex() == '<') { - if (CTempl_MemberParseTempl(name)) { - CError_FATAL(265); - return 1; - } - } - break; - case 0: - return 0; - default: - continue; - } - break; - } - } - - CPrep_TokenStreamSetState(&state); - tk = lex(); - return 0; -} - -static Type *CTempl_ParseTemplArgType(UInt32 *resultQual) { - DeclInfo di; - - memclrw(&di, sizeof(di)); - CParser_GetDeclSpecs(&di, 0); - - if (di.storageclass) - CError_Error(CErrorStr177); - if (di.x48) - CError_Error(CErrorStr121); - - CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_REFERENCE | Q_ALIGNED_MASK)); - - scandeclarator(&di); - if (di.name) - CError_Error(CErrorStr121); - - CTemplTool_CheckTemplArgType(di.thetype); - - *resultQual = di.qual; - return di.thetype; -} - -static ENode *CTempl_ParseTemplArgExpr(Type *type, UInt32 qual) { - ENode *expr; - ENode *copy; - - disallowgreaterthan = 1; - if (copts.old_argmatch) - expr = conv_assignment_expression(); - else - expr = assignment_expression(); - disallowgreaterthan = 0; - - if (type && !CTemplTool_IsTemplateArgumentDependentType(type) && !IS_TYPE_TEMPLDEPEXPR(expr->rtype)) { - expr = argumentpromotion(expr, type, qual, 1); - if (IS_TYPE_POINTER_ONLY(type)) { - if (ENODE_IS(expr, ETYPCON) && ENODE_IS(expr->data.monadic, EINTCONST)) - expr = expr->data.monadic; - if (ENODE_IS(expr, EINTCONST)) - expr->rtype = type; - } - } - - if (!IS_TYPE_TEMPLDEPEXPR(expr->rtype)) { - if (!copts.old_argmatch) - expr = pointer_generation(expr); - - switch (expr->type) { - case EINTCONST: - break; - case EOBJREF: - if (CParser_HasInternalLinkage2(expr->data.objref)) - CError_Error(CErrorStr357); - break; - case EOBJLIST: - CError_Error(CErrorStr199); - expr = nullnode(); - break; - default: - CError_Error(CErrorStr371); - expr = nullnode(); - } - - copy = galloc(sizeof(ENode)); - *copy = *expr; - return copy; - } else { - return CInline_CopyExpression(expr, CopyMode1); - } -} - -static Type *CTempl_ParseTemplArgTempl(TemplParam *params) { - NameResult pr; - - if ( - (tk != TK_IDENTIFIER && tk != TK_COLON_COLON) || - !CScope_ParseDeclName(&pr) || - !pr.type - ) - { - CError_Error(CErrorStr121); - tk = lex(); - return NULL; - } - - if (IS_TEMPL_CLASS(pr.type)) { - if (params && !CTemplTool_EqualParams(params->data.templparam.plist, TEMPL_CLASS(pr.type)->templ__params, 0)) { - CError_Error(CErrorStr235); - tk = lex(); - return NULL; - } - } else { - if (!CTemplTool_IsTemplateArgumentDependentType(pr.type)) - CError_Error(CErrorStr146); - } - - tk = lex(); - return pr.type; -} - -static UInt8 CTempl_GetTemplateNestIndex(NameSpace *nspace) { - UInt8 count = 0; - - while (nspace) { - if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL_ANY)) - count++; - nspace = nspace->parent; - } - - return count; -} - -static TemplParam *CTempl_ParseParam(NameSpace *nspace, TemplParam *param, UInt16 index, UInt8 nindex) { - DeclInfo di; - SInt32 savedState; - short startToken; - - param = galloc(sizeof(TemplParam)); - memclrw(param, sizeof(TemplParam)); - - param->pid.index = index; - param->pid.nindex = nindex; - - CPrep_TokenStreamGetState(&savedState); - - switch ((startToken = tk)) { - case TK_CLASS: - case TK_TYPENAME: - if ((tk = lex()) == TK_IDENTIFIER) { - param->name = tkidentifier; - tk = lex(); - } - - switch (tk) { - case ',': - case '>': - break; - case '=': - tk = lex(); - param->data.typeparam.type = CTempl_ParseTemplArgType(¶m->data.typeparam.qual); - break; - default: - param->name = NULL; - CPrep_TokenStreamSetState(&savedState); - tk = startToken; - goto defaultProc; - } - - param->pid.type = TPT_TYPE; - break; - - case TK_TEMPLATE: - if ((tk = lex()) != '<') { - CError_Error(CErrorStr230); - return NULL; - } - - tk = lex(); - param->data.templparam.plist = CTempl_ParseParamList(nspace, 0); - - if (tk == '>') - tk = lex(); - else - CError_Error(CErrorStr231); - - if (tk == TK_CLASS) - tk = lex(); - else - CError_Error(CErrorStr121); - - if (tk == TK_IDENTIFIER) { - param->name = tkidentifier; - tk = lex(); - } - - if (tk == '=') { - tk = lex(); - param->data.templparam.defaultarg = CTempl_ParseTemplArgTempl(param); - } - - param->pid.type = TPT_TEMPLATE; - break; - - default: - defaultProc: - memclrw(&di, sizeof(di)); - CParser_GetDeclSpecs(&di, 0); - - if (di.storageclass) - CError_Error(CErrorStr177); - - CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_REFERENCE | Q_ALIGNED_MASK)); - - scandeclarator(&di); - - switch (di.thetype->type) { - case TYPEARRAY: - di.thetype = CDecl_NewPointerType(TPTR_TARGET(di.thetype)); - break; - case TYPEFUNC: - di.thetype = CDecl_NewPointerType(di.thetype); - break; - case TYPEMEMBERPOINTER: - CError_Error(CErrorStr190); - di.thetype = TYPE(&stsignedint); - break; - case TYPEINT: - case TYPEENUM: - case TYPETEMPLATE: - case TYPEPOINTER: - break; - default: - CError_Error(CErrorStr229); - di.thetype = TYPE(&stsignedint); - } - - di.thetype = CParser_RemoveTopMostQualifiers(di.thetype, &di.qual); - param->name = di.name; - param->data.paramdecl.type = di.thetype; - param->data.paramdecl.qual = di.qual; - if (tk == '=') { - tk = lex(); - param->data.paramdecl.defaultarg = CTempl_ParseTemplArgExpr(di.thetype, di.qual); - } - - param->pid.type = TPT_NONTYPE; - break; - } - - if (param->name) - CTemplTool_InsertTemplateParameter(nspace, param); - - return param; -} - -static TemplParam *CTempl_ParseParamList(NameSpace *nspace, UInt8 nindex) { - TemplParam *params; - TemplParam **ptr; - TemplParam *param; - TemplParam *scan; - UInt16 index; - - params = NULL; - index = 0; - ptr = ¶ms; - - while (1) { - param = CTempl_ParseParam(nspace, params, index, nindex); - if (!param) - break; - - if (param->name) { - for (scan = params; scan; scan = scan->next) { - if (scan->name == param->name) - CError_Error(CErrorStr122, param->name->name); - } - } - - *ptr = param; - ptr = ¶m->next; - - if (tk != ',') - break; - - tk = lex(); - index++; - } - - if (!params) - CError_Error(CErrorStr229); - - return params; -} - -TemplArg *CTempl_ParseUncheckTemplArgs(TemplParam *params, Boolean is_global) { - TemplArg *args; - TemplArg *last; - UInt16 index; - - if (tk != '<') { - CError_Error(CErrorStr230); - return NULL; - } - - if ((tk = lex()) == '>') - return NULL; - - args = NULL; - index = 0; - while (1) { - if (is_global) { - if (args) { - last->next = galloc(sizeof(TemplArg)); - last = last->next; - } else { - last = galloc(sizeof(TemplArg)); - args = last; - } - } else { - if (args) { - last->next = lalloc(sizeof(TemplArg)); - last = last->next; - } else { - last = galloc(sizeof(TemplArg)); - args = last; - } - } - - last->next = NULL; - - if (!params) { - Type *type; - UInt32 qual; - Boolean flag; - - last->pid.index = index; - last->pid.nindex = 0; - - if ((type = CParser_ParseTypeID(&qual, &flag))) { - if (flag) { - last->data.ttargtype = type; - last->pid.type = TPT_TEMPLATE; - } else { - last->data.typeparam.type = type; - last->data.typeparam.qual = qual; - last->pid.type = TPT_TYPE; - } - } else { - last->data.paramdecl.expr = CTempl_ParseTemplArgExpr(NULL, 0); - last->pid.type = TPT_NONTYPE; - } - } else { - last->pid = params->pid; - switch (last->pid.type) { - case TPT_TYPE: - last->data.typeparam.type = CTempl_ParseTemplArgType(&last->data.typeparam.qual); - break; - case TPT_NONTYPE: - last->data.paramdecl.expr = CTempl_ParseTemplArgExpr(NULL, 0); - break; - case TPT_TEMPLATE: - if (!(last->data.ttargtype = CTempl_ParseTemplArgTempl(params))) - return NULL; - break; - default: - CError_FATAL(674); - } - params = params->next; - } - - if (tk == '>') - return args; - - if (tk != ',') { - CError_Error(CErrorStr116); - return NULL; - } - - tk = lex(); - index++; - } -} - -static TemplArg *CTempl_ParseTemplArgs(TemplClass **resultTempl, TemplArg **resultArgs) { - TemplParam *param; - TemplParam *params; - TemplArg *args; - TemplArg **ptr; - TemplArg *arg; - - params = (*resultTempl)->templ__params; - *resultArgs = NULL; - - if (tk != '<') { - CError_Error(CErrorStr230); - return NULL; - } - - tk = lex(); - - param = params; - args = NULL; - ptr = &args; - - while (param) { - arg = galloc(sizeof(TemplArg)); - memclrw(arg, sizeof(TemplArg)); - - *ptr = arg; - ptr = &arg->next; - - arg->pid = param->pid; - - if (tk != '>') { - switch (arg->pid.type) { - case TPT_TYPE: - arg->data.typeparam.type = CTempl_ParseTemplArgType(&arg->data.typeparam.qual); - break; - - case TPT_NONTYPE: - if (CTemplTool_IsTemplateArgumentDependentType(param->data.paramdecl.type)) { - Type *type; - UInt32 qual; - - type = CTemplTool_DeduceArgDepType(args, param->data.paramdecl.type, param->data.paramdecl.qual, &qual); - arg->data.paramdecl.expr = CTempl_ParseTemplArgExpr(type, qual); - } else { - arg->data.paramdecl.expr = CTempl_ParseTemplArgExpr(param->data.paramdecl.type, param->data.paramdecl.qual); - } - break; - - case TPT_TEMPLATE: - if (!(arg->data.ttargtype = CTempl_ParseTemplArgTempl(param))) - return NULL; - break; - - default: - CError_FATAL(742); - } - - if (tk != '>') { - if (tk != ',') { - CError_Error(CErrorStr232); - return NULL; - } - - if ((tk = lex()) == '>') { - CError_Error(CErrorStr232); - return NULL; - } - } - } else { - switch (arg->pid.type) { - case TPT_TYPE: - if (!param->data.typeparam.type) { - CError_Error(CErrorStr232); - return NULL; - } - - arg->data.typeparam.type = param->data.typeparam.type; - arg->data.typeparam.qual = param->data.typeparam.qual; - - if (CTemplTool_IsTemplateArgumentDependentType(param->data.typeparam.type)) { - TypeDeduce deduce; - memclrw(&deduce, sizeof(deduce)); - deduce.tmclass = *resultTempl; - deduce.inst = NULL; - deduce.params = params; - deduce.args = args; - - arg->data.typeparam.qual = param->data.typeparam.qual; - arg->data.typeparam.type = CTemplTool_DeduceTypeCopy(&deduce, arg->data.typeparam.type, &arg->data.typeparam.qual); - } - break; - - case TPT_NONTYPE: - if (!param->data.paramdecl.defaultarg) { - CError_Error(CErrorStr232); - return NULL; - } - - if (IS_TYPE_TEMPLDEPEXPR(param->data.paramdecl.defaultarg->rtype)) { - TypeDeduce deduce; - memclrw(&deduce, sizeof(deduce)); - deduce.tmclass = *resultTempl; - deduce.inst = NULL; - deduce.params = params; - deduce.args = args; - - arg->data.paramdecl.expr = CInline_CopyExpression( - CTemplTool_DeduceExpr(&deduce, param->data.paramdecl.defaultarg), CopyMode1); - } else { - arg->data.paramdecl.expr = param->data.paramdecl.defaultarg; - } - break; - - case TPT_TEMPLATE: - if (!param->data.templparam.defaultarg) { - CError_Error(CErrorStr232); - return NULL; - } - - if (IS_TEMPL_CLASS(param->data.templparam.defaultarg)) { - arg->data.ttargtype = param->data.templparam.defaultarg; - break; - } - - if (CTemplTool_IsTemplateArgumentDependentType(param->data.templparam.defaultarg)) { - CError_Error(CErrorStr190); - return NULL; - } - - CError_FATAL(817); - - default: - CError_FATAL(820); - } - } - - param = param->next; - } - - if (tk != '>') { - CError_Error(CErrorStr231); - return NULL; - } - - if ((*resultTempl)->pspecs) - return args; - - return args; -} - -Type *CTempl_ParseTemplTemplParam(TypeTemplDep *type) { - TemplArg *args; - Type *newType; - - tk = lex(); - if (!(args = CTempl_ParseUncheckTemplArgs(NULL, 1))) { - CError_Error(CErrorStr121); - return TYPE(&stsignedint); - } - - newType = CDecl_NewTemplDepType(TEMPLDEP_QUALTEMPL); - TYPE_TEMPLATE(newType)->u.qualtempl.type = type; - TYPE_TEMPLATE(newType)->u.qualtempl.args = args; - return newType; -} - -Type *CTempl_ClassGetType(TemplClass *templ) { - TemplClass *owner; - TemplArg *ownerArgs; - TemplArg *args; - Type *type; - - owner = templ; - if (templ->pspec_owner) - owner = templ->pspec_owner; - - if (!(args = CTempl_ParseTemplArgs(&owner, &ownerArgs))) - return &stvoid; - - if ((type = CTemplTool_IsDependentTemplate(owner, args))) - return type; - - return TYPE(CTemplClass_GetInstance(owner, args, ownerArgs)); -} - -static void CTempl_SetupClassParamNameSpace(DeclFucker *what_is_this, TypeClass *tclass) { - cscope_current = tclass->nspace; -} - -Boolean CTempl_IsQualifiedMember(DeclInfo *di, Type *type, NameSpace **resultnspace) { - if ( - TYPE_TEMPLATE(type)->dtype == TEMPLDEP_QUALNAME && - (type = CTemplTool_GetSelfRefTemplate(TYPE(TYPE_TEMPLATE(type)->u.qual.type))) - ) - { - *resultnspace = TYPE_CLASS(type)->nspace; - CError_ASSERT(948, di->fucker34 && (*resultnspace)->theclass); - - CTempl_SetupClassParamNameSpace(di->fucker34, (*resultnspace)->theclass); - di->fucker34 = NULL; - return 1; - } - - return 0; -} - -static void *CTempl_ParseMemberFunction(int unk1, int unk2, int unk3, Object *func) { - // no idea what should've been here, it's not called - - CError_ASSERT(974, TYPE_FUNC(func->type)->flags & FUNC_METHOD); - - return NULL; -} - -static void CTempl_ParseMember(TemplParam *params, TemplClass *templ, DeclInfo *di, SInt32 *startOffset) { - Object *object; - NameSpaceObjectList *nsol; - TokenStream stream; - CPrepFileInfo *file; - SInt32 offset; - Boolean saveForceLoc; - TemplateMember *member; - - if (templ->theclass.flags & CLASS_IS_TEMPL) - di->thetype = CTemplTool_ResolveMemberSelfRefs(templ, di->thetype, &di->qual); - - if (IS_TYPE_FUNC(di->thetype)) { - Boolean flag; - if (!(object = CDecl_GetFunctionObject(di, NULL, &flag, 0))) { - CError_Error(CErrorStr140, di->name->name); - return; - } - - if (tk != '{' && tk != TK_TRY && tk != ':') { - if (tk != ';') - CError_Error(CErrorStr123); - else - tk = lex(); - return; - } - - if ( - (TYPE_FUNC(object->type)->flags & FUNC_DEFINED) && - (!(TYPE_FUNC(object->type)->flags & FUNC_IS_TEMPL) || object->u.func.u.templ->instances) - ) - CError_Error(CErrorStr333, object); - - TYPE_FUNC(object->type)->flags |= FUNC_IS_TEMPL_INSTANCE | FUNC_DEFINED; - - CPrep_StreamGetBlock(&stream, NULL, 1); - saveForceLoc = gForceSourceLoc; - gForceSourceLoc = 1; - CPrep_BrowserFilePosition(&file, &offset); - gForceSourceLoc = saveForceLoc; - - if (file && file->recordbrowseinfo && *startOffset >= 0 && offset > *startOffset) - CBrowse_NewFunction(object, file, file, *startOffset, offset + 1); - } else { - if (!(nsol = CScope_GetLocalObject(templ->theclass.nspace, di->name))) { - CError_Error(CErrorStr140, di->name->name); - return; - } - - object = OBJECT(nsol->object); - if (object->otype != OT_OBJECT) { - CError_Error(CErrorStr122, di->name->name); - return; - } - - if ( - !is_typesame(di->thetype, object->type) || - (object->qual & (Q_CONST | Q_VOLATILE | Q_PASCAL)) != (di->qual & (Q_CONST | Q_VOLATILE | Q_PASCAL)) - ) - { - CError_Error(CErrorStr249, CError_GetObjectName(object), object->type, object->qual, di->thetype, di->qual); - return; - } - - CError_ASSERT(1070, object->datatype == DDATA); - - CPrep_StreamGetSemicolon(&stream, NULL); - } - - if (stream.tokens) { - if (IS_TEMPL_FUNC(object->type) != 0) { - if (!CTemplTool_EqualParams(object->u.func.u.templ->params, params, 0)) - CError_Error(CErrorStr235); - - object->u.func.u.templ->stream = stream; - } else { - if (!(templ->theclass.flags & CLASS_IS_TEMPL)) { - CError_Error(CErrorStr190); - return; - } - - member = CTemplClass_DefineMember(templ, object, &cparser_fileoffset, &stream); - if (templ->templ__params) { - if (!CTemplTool_EqualParams(templ->templ__params, params, 0)) { - CError_Error(CErrorStr235); - return; - } - - member->params = params; - } - } - } -} - -static TemplateFunction *CTempl_DeclareTemplateFunction(DeclInfo *di, TemplParam *params, TypeClass *tclass, AccessType access, Boolean flag) { - TemplateFunction *templ; - Object *object; - - if (tclass) { - CError_ASSERT(1122, cscope_current->theclass); - di->thetype = TYPE(CDecl_MakeTypeMemberFunc(TYPE_FUNC(di->thetype), cscope_current->theclass, flag)); - } else { - access = ACCESSPUBLIC; - } - - templ = galloc(sizeof(TemplateFunction)); - memclrw(templ, sizeof(TemplateFunction)); - - templ->next = ctempl_templatefuncs; - ctempl_templatefuncs = templ; - - templ->params = params; - templ->name = di->name; - templ->deftoken = symdecltoken; - - object = CParser_NewFunctionObject(NULL); - object->access = access; - object->name = di->name; - object->u.func.linkname = CParser_GetUniqueName(); - object->type = di->thetype; - object->qual = di->qual | Q_MANGLE_NAME; - object->sclass = di->storageclass; - TYPE_FUNC(object->type)->flags |= FUNC_IS_TEMPL; - object->u.func.u.templ = templ; - - if (di->qual & Q_INLINE) - object->sclass = TK_STATIC; - - templ->tfunc = object; - CScope_AddObject(cscope_current, di->name, OBJ_BASE(object)); - - return templ; -} - -static void CTempl_ParseTemplateFunction(TemplateFunction *templ, TypeClass *tclass, SInt32 *startOffset) { - Object *object; - CPrepFileInfo *file; - SInt32 offset; - Boolean saveForceLoc; - - object = templ->tfunc; - - if (tk == '{' || tk == ':' || tk == TK_TRY) { - if (tclass) { - object->qual |= Q_INLINE; - object->sclass = TK_STATIC; - } - - if (TYPE_FUNC(object->type)->flags & FUNC_DEFINED) - CError_Error(CErrorStr333, object); - - TYPE_FUNC(object->type)->flags |= FUNC_DEFINED | FUNC_IS_TEMPL_INSTANCE; - - CPrep_StreamGetBlock(&templ->stream, NULL, 0); - - if (lookahead() == ';') - tk = lex(); - else - tk = ';'; - - saveForceLoc = gForceSourceLoc; - gForceSourceLoc = 1; - CPrep_BrowserFilePosition(&file, &offset); - gForceSourceLoc = saveForceLoc; - - if (file && *startOffset >= 0 && offset > *startOffset) { - templ->srcfile = file; - templ->startoffset = *startOffset; - templ->endoffset = offset + 1; - if (cparamblkptr->browseoptions.recordTemplates && file->recordbrowseinfo) - CBrowse_NewTemplateFunc(templ); - } - - } else { - if (tk != ';') - CError_Error(CErrorStr121); - } -} - -static HashNameNode *CTempl_FindConversionFuncName(TypeClass *tclass, Type *type, UInt32 qual) { - Object *object; - CScopeObjectIterator iter; - - CScope_InitObjectIterator(&iter, tclass->nspace); - do { - if (!(object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) - return NULL; - } while ( - !IS_TYPE_FUNC(object->type) || - !(TYPE_FUNC(object->type)->flags & FUNC_CONVERSION) || - (TYPE_FUNC(object->type)->qual & (Q_CONST | Q_VOLATILE)) != (qual & (Q_CONST | Q_VOLATILE)) || - !is_typesame(TYPE_FUNC(object->type)->functype, type) - ); - - return object->name; -} - -static void CTempl_ParseConversionFunctionTemplate(DeclInfo *di, DeclFucker *what_is_this, TemplParam *params, TypeClass *tclass, SInt32 *startOffset, AccessType access) { - tk = lex(); - if (!tclass) { - CError_Error(CErrorStr121); - return; - } - - tclass->flags = tclass->flags | CLASS_IS_CONVERTIBLE; - CError_QualifierCheck(di->qual & ~Q_INLINE); - - conversion_type_name(di); - CDecl_NewConvFuncType(di); - - if (cscope_current->is_templ) { - CError_ASSERT(1260, cscope_current == what_is_this->nspace); - cscope_current = what_is_this->nspace->parent; - } - - CTempl_ParseTemplateFunction(CTempl_DeclareTemplateFunction(di, params, tclass, access, 0), tclass, startOffset); -} - -static void CTempl_ParseFunctionOrMemberTemplate(DeclFucker *what_is_this, TemplParam *params, TypeClass *tclass, SInt32 *startOffset, AccessType access, Boolean mysteryFlag) { - NameSpaceObjectList *nsol; - Object *object; - TemplParam *param; - TemplateFunction *templfunc; - Boolean disallowCVFlag; - TypeClass *tclass2; - Type *type; - UInt32 qual; - DeclInfo di; - - for (param = params; param; param = param->next) { - switch (param->pid.type) { - case TPT_TYPE: - if (param->data.typeparam.type) { - CError_Error(CErrorStr378); - param->data.typeparam.type = NULL; - } - break; - case TPT_NONTYPE: - if (param->data.paramdecl.defaultarg) { - CError_Error(CErrorStr378); - param->data.paramdecl.defaultarg = NULL; - } - break; - case TPT_TEMPLATE: - if (param->data.templparam.defaultarg) { - CError_Error(CErrorStr378); - param->data.templparam.defaultarg = NULL; - } - break; - default: - CError_FATAL(1317); - } - } - - disallowCVFlag = 0; - ctempl_scanfuncparams = 1; - - memclrw(&di, sizeof(di)); - di.x51 = mysteryFlag; - - if (tk == TK_OPERATOR) { - CTempl_ParseConversionFunctionTemplate(&di, what_is_this, params, tclass, startOffset, access); - return; - } - - CParser_GetDeclSpecs(&di, 1); - if (tk == ';' && IS_TEMPL_CLASS(di.thetype)) - return; - - if (di.x10 || di.x14) { - TypeFunc *tfunc; - - if (di.x14) { - di.x10 = OBJECT(di.x14->object); - CError_ASSERT(1342, di.x10->otype == OT_OBJECT); - } - - CError_ASSERT(1344, IS_TYPE_FUNC(di.x10->type)); - - tfunc = TYPE_FUNC(di.x10->type); - if (tfunc->flags & FUNC_CONVERSION) { - di.thetype = tfunc->functype; - di.qual |= tfunc->qual; - di.nspace = di.x10->nspace; - di.name = di.x10->name; - } else if (tfunc->flags & FUNC_IS_CTOR) { - di.thetype = TYPE(&void_ptr); - di.nspace = di.x10->nspace; - di.name = di.x10->name; - } else { - CError_Error(CErrorStr121); - return; - } - - if ((tk = lex()) == '(') { - tk = lex(); - CDecl_ParseDirectFuncDecl(&di); - if (IS_TYPE_FUNC(di.thetype)) - goto skipPastStuff; - } else { - CError_Error(CErrorStr114); - } - } - - if (di.storageclass) { - if (tclass) { - if (di.storageclass == TK_STATIC) - disallowCVFlag = 1; - else - CError_Error(CErrorStr177); - di.storageclass = 0; - } else { - if (di.storageclass != TK_STATIC && di.storageclass != TK_EXTERN) { - CError_Error(CErrorStr177); - di.storageclass = 0; - } - } - } - - CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_ASM | Q_PASCAL | Q_INLINE | Q_EXPLICIT | Q_20000 | Q_WEAK | Q_ALIGNED_MASK)); - - if (tk == TK_OPERATOR && di.x4A) { - CTempl_ParseConversionFunctionTemplate(&di, what_is_this, params, tclass, startOffset, access); - return; - } - - if (!di.x53) { - if (tclass && IS_TYPE_CLASS(di.thetype) && TYPE_CLASS(di.thetype) == tclass && tk == '(') { - CError_ASSERT(1418, cscope_current == tclass->nspace); - CError_QualifierCheck(di.qual & ~(Q_INLINE | Q_EXPLICIT)); - - di.thetype = TYPE(&void_ptr); - di.x4B = 1; - - tk = lex(); - CDecl_ParseDirectFuncDecl(&di); - - if (IS_TYPE_FUNC(di.thetype)) { - if (TYPE_FUNC(di.thetype)->args && !TYPE_FUNC(di.thetype)->args->next && TYPE_FUNC(di.thetype)->args->type == TYPE(tclass)) { - CError_Error(CErrorStr239); - TYPE_FUNC(di.thetype)->args = NULL; - } - - if (tclass->flags & CLASS_HAS_VBASES) - CDecl_AddArgument(TYPE_FUNC(di.thetype), TYPE(&stsignedshort)); - - TYPE_FUNC(di.thetype)->flags |= FUNC_IS_CTOR; - di.name = constructor_name_node; - - what_is_this->nspace->tparams = NULL; - - CTempl_ParseTemplateFunction( - CTempl_DeclareTemplateFunction(&di, params, tclass, access, disallowCVFlag), - tclass, startOffset); - - return; - } else { - CError_Error(CErrorStr241); - } - } - - if (IS_TYPE_TEMPLATE(di.thetype)) { - if ( - tk == '(' && - TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_QUALNAME && - (tclass2 = TYPE_CLASS(CTemplTool_GetSelfRefTemplate(TYPE(TYPE_TEMPLATE(di.thetype)->u.qual.type)))) && - TYPE_TEMPLATE(di.thetype)->u.qual.name == tclass2->classname - ) - { - if (tclass) - CError_Error(CErrorStr229); - - di.thetype = TYPE(&void_ptr); - di.x4B = 1; - - CTempl_SetupClassParamNameSpace(what_is_this, tclass2); - - tk = lex(); - CDecl_ParseDirectFuncDecl(&di); - - if (IS_TYPE_FUNC(di.thetype)) { - di.name = constructor_name_node; - if (tclass2->flags & CLASS_HAS_VBASES) - CDecl_AddArgument(TYPE_FUNC(di.thetype), TYPE(&stsignedshort)); - - TYPE_FUNC(di.thetype)->flags |= FUNC_IS_CTOR; - CTempl_ParseMember(params, TEMPL_CLASS(tclass2), &di, startOffset); - } else { - CError_Error(CErrorStr241); - } - - return; - } - - if ( - tk == TK_COLON_COLON && - TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_TEMPLATE && - (tclass2 = TYPE_CLASS(CTemplTool_GetSelfRefTemplate(di.thetype))) - ) - { - if (tclass) - CError_Error(CErrorStr229); - - if ((tk = lex()) == '~') { - if ( - (tk = lex()) != TK_IDENTIFIER || - tkidentifier != tclass2->classname || - (tk = lex()) != '(' - ) - { - if (tk == '<') { - DeclInfo di2; - - CPrep_UnLex(); - tk = TK_IDENTIFIER; - tkidentifier = tclass2->classname; - - memclrw(&di2, sizeof(di2)); - CParser_GetDeclSpecs(&di2, 0); - if (tk != '(') - CError_Error(CErrorStr241); - - if (di2.thetype != TYPE(tclass2) && (!IS_TYPE_TEMPLATE(di2.thetype) || CTemplTool_IsTemplate( - TYPE_TEMPLATE(di2.thetype)) != TEMPL_CLASS(tclass2))) - { - CError_Error(CErrorStr241); - } - } else { - CError_Error(CErrorStr241); - } - } - - di.thetype = TYPE(&void_ptr); - - CTempl_SetupClassParamNameSpace(what_is_this, tclass2); - tk = lex(); - CDecl_ParseDirectFuncDecl(&di); - - if (IS_TYPE_FUNC(di.thetype)) { - if (tclass2->sominfo) - di.qual |= Q_VIRTUAL; - else - CDecl_AddArgument(TYPE_FUNC(di.thetype), TYPE(&stsignedshort)); - - di.name = destructor_name_node; - TYPE_FUNC(di.thetype)->flags |= FUNC_IS_DTOR; - CTempl_ParseMember(params, TEMPL_CLASS(tclass2), &di, startOffset); - } else { - CError_Error(CErrorStr241); - } - } else if (tk == TK_OPERATOR) { - CTempl_SetupClassParamNameSpace(what_is_this, tclass2); - if (CMangler_OperatorName((tk = lex()))) { - CError_Error(CErrorStr349); - return; - } - - CError_QualifierCheck(di.qual & ~(Q_INLINE | Q_VIRTUAL)); - conversion_type_name(&di); - - type = di.thetype; - qual = di.qual; - CDecl_NewConvFuncType(&di); - - if (CTemplTool_IsTemplateArgumentDependentType(type)) { - di.name = CTempl_FindConversionFuncName(tclass2, type, qual); - if (!di.name) { - CError_Error(CErrorStr150, "conversion function"); - return; - } - } - CTempl_ParseMember(params, TEMPL_CLASS(tclass2), &di, startOffset); - } else { - CError_Error(CErrorStr121); - } - - return; - } - - if (TYPE_TEMPLATE(di.thetype)->dtype == TEMPLDEP_QUALNAME && !di.x49) - CError_Warning(CErrorStr355); - } - } - - di.x30 = params; - di.fucker34 = what_is_this; - scandeclarator(&di); - ctempl_scanfuncparams = 0; - -skipPastStuff: - if (cscope_current->is_templ) { - CError_ASSERT(1589, cscope_current == what_is_this->nspace); - what_is_this->nspace->tparams = NULL; - } - - if (!di.name) { - CError_Error(CErrorStr229); - return; - } - - if (di.nspace) { - if (di.nspace->theclass) { - if (tclass) - CError_Error(CErrorStr229); - CTempl_ParseMember(params, TEMPL_CLASS(di.nspace->theclass), &di, startOffset); - return; - } - - if (!IS_TYPE_FUNC(di.thetype)) { - CError_Error(CErrorStr229); - return; - } - - CScope_FindName(di.nspace, di.name); - } else { - if (!IS_TYPE_FUNC(di.thetype)) { - CError_Error(CErrorStr229); - return; - } - - CScope_FindName(cscope_current, di.name); - } - - nsol = CScope_FindName(di.nspace ? di.nspace : cscope_current, di.name); - while (nsol) { - object = OBJECT(nsol->object); - if (object->otype == OT_OBJECT && IS_TEMPL_FUNC(object->type)) { - templfunc = CTemplTool_GetFuncTempl(object); - if (CTemplTool_EqualParams(templfunc->params, params, 0) && is_typesame(object->type, di.thetype)) { - if (tk != ';' && templfunc->stream.tokens) - CError_Error(CErrorStr234); - - if (tk == '{' || tk == ':' || tk == TK_TRY) - CError_ASSERT(1654, CTemplTool_EqualParams(templfunc->params, params, 1)); - - if (di.qual & Q_INLINE) - object->qual |= Q_INLINE; - TYPE_FUNC(object->type)->args = TYPE_FUNC(di.thetype)->args; - break; - } - } - nsol = nsol->next; - } - - if (!nsol) { - if (di.nspace) - CError_Error(CErrorStr229); - templfunc = CTempl_DeclareTemplateFunction(&di, params, tclass, access, disallowCVFlag); - } - - CTempl_ParseTemplateFunction(templfunc, tclass, startOffset); -} - -static void CTempl_ExplicitInstantiation(void) { - Boolean flag; - short saveToken; - Object *object; - DeclInfo di; - - memclrw(&di, sizeof(di)); - di.x51 = 1; - flag = 1; - - if (tk == TK_IDENTIFIER && !strcmp(tkidentifier->name, "__dont_instantiate")) { - flag = 0; - tk = lex(); - } - - switch (tk) { - case TK_STRUCT: - case TK_UNION: - case TK_CLASS: - memclrw(&di, sizeof(di)); - CParser_GetDeclSpecs(&di, 0); - if (tk == ';') { - if (IS_TEMPL_CLASS_INST(di.thetype)) { - CTempl_InstantiateTemplateClass(TYPE_CLASS(di.thetype)); - if ((TYPE_CLASS(di.thetype)->flags & CLASS_COMPLETED) && !(TYPE_CLASS(di.thetype)->eflags & CLASS_EFLAGS_IMPORT)) { - if (flag) - CTempl_GenClassInstance(TEMPL_CLASS_INST(di.thetype), 1); - else - TEMPL_CLASS_INST(di.thetype)->is_extern = 1; - } else { - CError_Error(CErrorStr136, TYPE_CLASS(di.thetype), 0); - } - } else { - CError_Error(CErrorStr238); - } - return; - } - break; - default: - memclrw(&di, sizeof(di)); - CParser_GetDeclSpecs(&di, 0); - } - - di.x51 = 1; - - scandeclarator(&di); - - saveToken = tk; - - di.x38 = NULL; - if ( - di.name && - IS_TYPE_FUNC(di.thetype) && - (object = CDecl_GetFunctionObject(&di, di.nspace, NULL, 1)) && - IS_TYPE_FUNC(object->type) && - object->u.func.inst && - di.x38 - ) - { - if (!flag) - object->u.func.inst->is_extern = 1; - else - CTempl_GenFuncInstance(di.x38, object->u.func.inst, 1); - } else { - CError_Error(CErrorStr238); - } - - if (saveToken != ';') - CError_Error(CErrorStr123); -} - -static void CTempl_ExplicitSpecialization(void) { - Boolean flag; - TemplParam *params; - int counter; - DeclFucker what_is_this; - DeclInfo di; - - flag = 0; - counter = 1; - while (tk == TK_TEMPLATE) { - if ((tk = lex()) != '<') { - CError_Error(CErrorStr230); - break; - } - - if ((tk = lex()) != '>') { - if (!flag) { - what_is_this.nspace = cscope_current; - what_is_this.mystery4 = NULL; - cscope_current->tparams = NULL; - flag = 1; - } - - params = CTempl_ParseParamList(what_is_this.nspace, counter); - if (tk != '>') - CError_Error(CErrorStr231); - } else { - if (flag) - CError_Error(CErrorStr335); - } - - counter++; - tk = lex(); - } - - if (flag) { - SInt32 startOffset = -1; - CTempl_ParseFunctionOrMemberTemplate(&what_is_this, params, NULL, &startOffset, ACCESSPUBLIC, 1); - return; - } - - memclrw(&di, sizeof(di)); - di.x3C = counter; - di.x51 = 1; - CParser_GetDeclSpecs(&di, 1); - - if (tk == ';') { - if (IS_TEMPL_CLASS_INST(di.thetype)) - TEMPL_CLASS_INST(di.thetype)->is_specialized = 1; - else - CError_Error(CErrorStr335); - } else { - scandeclaratorlist(&di); - if ((tk != ';' && tk != '}') || di.x3C) - CError_Error(CErrorStr335); - } - - if (flag) - what_is_this.nspace->tparams = NULL; -} - -void CTempl_Parse(TemplClass *templ, AccessType access) { - TemplParam *params; - UInt8 i; - short mode; - Boolean flag; - UInt8 classDeclSpec; - SInt32 startOffset; - SInt32 savedState; - CScopeSave savedScope; - DeclFucker what_is_this; - - startOffset = CPrep_BrowserFileOffset(); - CScope_GetScope(&savedScope); - - if ((tk = lex()) != '<') { - if (templ) - CError_Error(CErrorStr238); - CTempl_ExplicitInstantiation(); - CScope_RestoreScope(&savedScope); - return; - } - - if ((tk = lex()) == '>') { - if (templ) - CError_Error(CErrorStr335); - tk = lex(); - CTempl_ExplicitSpecialization(); - CScope_RestoreScope(&savedScope); - return; - } - - what_is_this.nspace = cscope_current; - what_is_this.mystery4 = NULL; - cscope_current->tparams = NULL; - i = CTempl_GetTemplateNestIndex(what_is_this.nspace); - - while (1) { - params = CTempl_ParseParamList(what_is_this.nspace, i); - if (tk != '>') - CError_Error(CErrorStr231); - - if ((tk = lex()) != TK_TEMPLATE) - break; - - if (templ) - CError_Error(CErrorStr121); - - if ((tk = lex()) != '<') - CError_Error(CErrorStr230); - else - tk = lex(); - - i++; - } - - switch (tk) { - case TK_CLASS: - mode = CLASS_MODE_CLASS; - break; - case TK_UNION: - mode = CLASS_MODE_UNION; - break; - case TK_STRUCT: - mode = CLASS_MODE_STRUCT; - break; - default: - mode = -1; - } - - if (mode >= 0) { - classDeclSpec = 0; - flag = 0; - - CPrep_TokenStreamGetState(&savedState); - if ((tk = lex()) == TK_UU_DECLSPEC) - CDecl_ParseClassDeclSpec(&classDeclSpec); - - if (tk == TK_IDENTIFIER) { - if ((tk = lex()) == '<') { - if (setjmp(ctempl_parseparse) == 0) { - CTempl_MemberParseTemplArgList(); - flag = 1; - tk = lex(); - } - } - - switch (tk) { - case ':': - case ';': - case '{': - CPrep_TokenStreamSetCurState(&savedState); - if (flag) - CTemplClass_ParsePartialSpecialization(&what_is_this, params, mode, &startOffset); - else - CTemplClass_ParseClass(&what_is_this, params, mode, &startOffset); - goto done; - } - } - - CPrep_TokenStreamSetCurState(&savedState); - } - - CTempl_ParseFunctionOrMemberTemplate(&what_is_this, params, TYPE_CLASS(templ), &startOffset, access, 0); - -done: - what_is_this.nspace->tparams = NULL; - CScope_RestoreScope(&savedScope); -} - -void CTempl_ParseInstanceScopeFunction(Object *funcobj, TemplClassInst *inst, TypeClass *tclass) { - TemplParam *params; - NameSpace *nspace; - TemplateMember *member; - Object *parent; - DeclInfo di; - CScopeSave savedScope; - TemplStack stack; - - params = inst->templ->templ__params; - if (funcobj->qual & Q_IS_TEMPLATED) { - for (member = CTemplClass_GetMasterTemplate(inst->templ)->members, parent = OBJECT_TEMPL(funcobj)->parent; member; member = member->next) { - if (member->object == parent) { - if (member->params) - params = member->params; - break; - } - } - } - - CTemplTool_PushInstance(&stack, NULL, funcobj); - nspace = CTemplTool_InsertTemplateArgumentNameSpace(params, inst, &savedScope); - if (tclass) - cscope_current = tclass->nspace; - - memclrw(&di, sizeof(di)); - CFunc_ParseFuncDef(funcobj, &di, NULL, 0, 0, tclass ? cscope_current : NULL); - - CTemplTool_RemoveTemplateArgumentNameSpace(nspace, inst, &savedScope); - CTemplTool_PopInstance(&stack); -} - -Boolean CTempl_GenFuncInstance(TemplateFunction *templ, TemplFuncInstance *inst, Boolean flag) { - Boolean saveDebugInfo; - NameSpace *nspace; - SInt32 streamState; - TemplStack stack; - DeclInfo di; - - if (!flag && copts.no_implicit_templates && inst->object->sclass != TK_STATIC) - return 0; - - if (inst->is_extern && !flag) - return 0; - - while (1) { - if (templ->stream.tokens) - break; - if (!templ->unk4) - break; - templ = templ->unk4; - } - - if (!templ->stream.tokens) { - if (flag) { - CError_SetErrorToken(&templ->deftoken); - CError_Error(CErrorStr233, inst->object); - } - return 0; - } - - inst->is_instantiated = 1; - - CPrep_StreamInsert(&templ->stream, &streamState); - - saveDebugInfo = copts.filesyminfo; - if (copts.nosyminline || !templ->deftoken.tokenfile) - copts.filesyminfo = 0; - - CError_ASSERT(2112, (tk = lex()) == '{' || tk == ':' || tk == TK_TRY); - - symdecltoken = *CPrep_CurStreamElement(); - - if (copts.filesyminfo) { - CPrep_NewFileOffsetInfo(&cparser_fileoffset, &templ->deftoken); - symdecloffset = cparser_fileoffset.tokenline; - } - - if (inst->object->sclass != TK_STATIC) - inst->object->qual |= Q_WEAK; - - memclrw(&di, sizeof(di)); - di.file2 = templ->srcfile; - di.file = CPrep_BrowserCurrentFile(); - di.sourceoffset = templ->startoffset; - - CTemplTool_PushInstance(&stack, NULL, inst->object); - CTemplTool_MergeArgNames(TYPE_FUNC(templ->tfunc->type), TYPE_FUNC(inst->object->type)); - - nspace = CTemplTool_SetupTemplateArgumentNameSpace(templ->params, inst->args, 0); - nspace->parent = inst->object->nspace; - inst->object->nspace = nspace; - - CTemplTool_SetupOuterTemplateArgumentNameSpace(nspace); - CFunc_ParseFuncDef(inst->object, &di, NULL, 0, 0, nspace); - CTemplTool_RemoveOuterTemplateArgumentNameSpace(nspace); - - inst->object->nspace = nspace->parent; - - CTemplTool_PopInstance(&stack); - - CPrep_StreamRemove(&templ->stream, &streamState); - copts.filesyminfo = saveDebugInfo; - - if (di.file->recordbrowseinfo) - CBrowse_NewFunction(inst->object, di.file, di.file2, di.sourceoffset, templ->endoffset); - - return 1; -} - -void CTempl_InstantiateMember(TemplClass *templ, TemplClassInst *inst, TemplateMember *tmemb, Object *object, Boolean flag) { - Boolean saveDebugInfo; - NameSpace *nspace; - Boolean saveSourceLoc; - - DeclInfo di; - CScopeSave savedScope; - TemplStack stack; - SInt32 savedState; - - if (!flag && copts.no_implicit_templates) - return; - - CTemplTool_PushInstance(&stack, NULL, object); - nspace = CTemplTool_InsertTemplateArgumentNameSpace( - tmemb->params ? tmemb->params : templ->templ__params, inst, &savedScope); - CPrep_StreamInsert(&tmemb->stream, &savedState); - - saveSourceLoc = gForceSourceLoc; - gForceSourceLoc = 1; - symdecltoken.tokenoffset = tmemb->startoffset; - tk = lex(); - - symdecltoken = *CPrep_CurStreamElement(); - - saveDebugInfo = copts.filesyminfo; - if (copts.filesyminfo) { - CPrep_NewFileOffsetInfo(&cparser_fileoffset, &symdecltoken); - symdecloffset = cparser_fileoffset.tokenline; - } - - if (object->sclass != TK_STATIC) - object->qual |= Q_WEAK; - - memclrw(&di, sizeof(di)); - di.file2 = tmemb->srcfile; - di.file = CPrep_BrowserCurrentFile(); - di.sourceoffset = tmemb->startoffset; - - switch (object->datatype) { - case DFUNC: - case DVFUNC: - CTemplTool_MergeArgNames(TYPE_FUNC(tmemb->object->type), TYPE_FUNC(object->type)); - CFunc_ParseFuncDef(object, &di, TYPE_CLASS(inst), 0, 0, NULL); - break; - - case DDATA: - CDecl_CompleteType(object->type); - CInit_InitializeData(object); - break; - - default: - CError_FATAL(2227); - } - - CTemplTool_PopInstance(&stack); - CTemplTool_RemoveTemplateArgumentNameSpace(nspace, inst, &savedScope); - CPrep_StreamRemove(&tmemb->stream, &savedState); - copts.filesyminfo = saveDebugInfo; - gForceSourceLoc = saveSourceLoc; -} - -static Boolean CTempl_GenMemberInstance(TemplClassInst *inst, ObjectTemplated *objtempl, Boolean flag) { - TemplateMember *member; - Object *parent = objtempl->parent; - - for (member = CTemplClass_GetMasterTemplate(inst->templ)->members; member; member = member->next) { - if (member->object == parent) { - CTempl_InstantiateMember(inst->templ, inst, member, OBJECT(objtempl), flag); - return 1; - } - } - - if (flag) - CError_Warning(CErrorStr233, objtempl); - return 0; -} - -static Boolean CTempl_GenClassInstance(TemplClassInst *inst, Boolean flag) { - Object *object; - Boolean result; - CScopeObjectIterator iter; - - result = 0; - - if (!flag && copts.no_implicit_templates) - return 0; - if (!flag && inst->is_extern) - return 0; - - CScope_InitObjectIterator(&iter, inst->theclass.nspace); - while ((object = OBJECT(CScope_NextObjectIteratorObject(&iter)))) { - if (IS_TYPE_FUNC(object->type) && object->datatype != DALIAS) { - if ( - (flag || (object->flags & OBJECT_FLAGS_2)) && - !(TYPE_FUNC(object->type)->flags & (FUNC_DEFINED | FUNC_AUTO_GENERATED)) && - CTempl_GenMemberInstance(inst, OBJECT_TEMPL(object), flag) && - (TYPE_FUNC(object->type)->flags & FUNC_DEFINED) - ) - result = 1; - } else { - if ( - !inst->static_instantiated && - object->datatype == DDATA && - !(object->qual & Q_INLINE_DATA) && - !(object->flags & OBJECT_DEFINED) && - CTempl_GenMemberInstance(inst, OBJECT_TEMPL(object), flag) - ) - result = 1; - } - } - - inst->static_instantiated = 1; - return result; -} - -Boolean CTempl_Instantiate(void) { - Boolean result = 0; - TemplClass *templ; - TemplClassInst *inst; - TemplPartialSpec *pspec; - TemplFuncInstance *instf; - TemplateFunction *templf; - - for (templ = ctempl_templates; templ; templ = templ->next) { - for (inst = templ->instances; inst; inst = inst->next) { - if ( - (inst->theclass.flags & CLASS_IS_TEMPL_INST) && - !inst->is_specialized && - CTempl_GenClassInstance(inst, 0) - ) - result = 1; - } - - for (pspec = templ->pspecs; pspec; pspec = pspec->next) { - for (inst = pspec->templ->instances; inst; inst = inst->next) { - if ( - (inst->theclass.flags & CLASS_IS_TEMPL_INST) && - !inst->is_specialized && - CTempl_GenClassInstance(inst, 0) - ) - result = 1; - } - } - } - - for (templf = ctempl_templatefuncs; templf; templf = templf->next) { - for (instf = templf->instances; instf; instf = instf->next) { - if ( - !instf->is_instantiated && - !instf->is_specialized && - (instf->object->flags & OBJECT_FLAGS_2) && - !(TYPE_FUNC(instf->object->type)->flags & FUNC_DEFINED) - ) - { - instf->is_instantiated = 1; - if (CTempl_GenFuncInstance(templf, instf, 0)) - result = 1; - } - } - } - - return result; -} - -Boolean CTempl_InlineFunctionCheck(Object *funcobj) { - TemplClassInst *inst; - TemplateMember *member; - Object *parent; - - CError_ASSERT(2422, IS_TYPE_FUNC(funcobj->type) && (funcobj->qual & Q_IS_TEMPLATED)); - - if (!(TYPE_FUNC(funcobj->type)->flags & FUNC_DEFINED)) { - inst = TEMPL_CLASS_INST(TYPE_METHOD(funcobj->type)->theclass); - if (!inst->is_specialized) { - parent = OBJECT_TEMPL(funcobj)->parent; - if (parent->qual & Q_INLINE) { - for (member = CTemplClass_GetMasterTemplate(inst->templ)->members; member; member = member->next) { - funcobj->qual |= Q_INLINE; - if (member->object == parent) { - CTemplTool_MergeArgNames(TYPE_FUNC(member->object->type), TYPE_FUNC(funcobj->type)); - CInline_AddInlineFunctionAction(funcobj, TYPE_CLASS(inst), &member->fileoffset, &member->stream, 0); - return 1; - } - } - } - } - } - - return 0; -} diff --git a/compiler_and_linker/unsorted/CTemplateTools.c b/compiler_and_linker/unsorted/CTemplateTools.c deleted file mode 100644 index 0e77e74..0000000 --- a/compiler_and_linker/unsorted/CTemplateTools.c +++ /dev/null @@ -1,1962 +0,0 @@ -#include "compiler/CTemplateTools.h" -#include "compiler/CABI.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInline.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/CScope.h" -#include "compiler/CTemplateClass.h" -#include "compiler/CTemplateNew.h" -#include "compiler/CompilerTools.h" -#include "compiler/enode.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/templates.h" -#include "compiler/types.h" - -short ctempl_instdepth; - -void CTemplTool_PushInstance(TemplStack *stack, TypeClass *tmclass, Object *func) { - if (tmclass) { - stack->u.theclass = tmclass; - stack->is_func = 0; - } else { - stack->u.func = func; - stack->is_func = 1; - } - stack->next = ctempl_curinstance; - ctempl_curinstance = stack; - - if (++ctempl_instdepth >= 64) - CError_ErrorTerm(CErrorStr314); -} - -void CTemplTool_PopInstance(TemplStack *stack) { - CError_ASSERT(53, ctempl_curinstance == stack); - - ctempl_curinstance = stack->next; - if (--ctempl_instdepth < 0) - ctempl_instdepth = 0; -} - -ENode *CTempTool_GetPTMTemplArgExpr(ENode *expr, Type *type) { - NameSpaceObjectList *list; - - CError_ASSERT(69, ENODE_IS(expr, EMEMBER)); - CError_ASSERT(70, IS_TYPE_MEMBERPOINTER(type)); - - if (!copts.cpp_extensions) { - if (!expr->data.emember->x11 || !expr->data.emember->pr_1D) - CError_Warning(CErrorStr331); - } - - type = TYPE_MEMBER_POINTER(type)->ty1; - for (list = expr->data.emember->list; list; list = list->next) { - if (list->object->otype == OT_MEMBERVAR) { - if (!is_typeequal(OBJ_MEMBER_VAR(list->object)->type, type)) - CError_Error(CErrorStr146); - return expr; - } - - if (list->object->otype == OT_OBJECT && is_memberpointerequal(OBJECT(list->object)->type, type)) { - if (expr->data.emember->list != list || list->next) { - // rewrite the EMEMBER to contain just one node - expr->data.emember->list = galloc(sizeof(NameSpaceObjectList)); - *expr->data.emember->list = *list; - expr->data.emember->list->next = NULL; - } - break; - } - } - - if (!list) - CError_Error(CErrorStr146); - - return expr; -} - -Boolean CTemplTool_InitDeduceInfo(DeduceInfo *info, TemplParam *params, TemplArg *args, Boolean flag) { - int i; - TemplArg *buffer; - TemplParam *param; - - if (!params) { - info->args = info->argBuffer; - info->maxCount = 0; - info->x12C = 0xFF; - return 1; - } - - memclrw(info, sizeof(DeduceInfo)); - - i = 0; - param = params; - while (param) { - param = param->next; - i++; - } - - if (i > 16) { - buffer = lalloc(i * sizeof(TemplArg)); - memclrw(buffer, i * sizeof(TemplArg)); - } else { - buffer = info->argBuffer; - } - info->args = buffer; - info->maxCount = i; - info->x12C = params->pid.nindex; - - for (param = params, i = 0; param; param = param->next, i++) - buffer[i].pid = param->pid; - - i = 0; - param = params; - while (args) { - if (!param || param->pid.type != args->pid.type) - return 0; - - buffer[i].data = args->data; - if (i > 0) - buffer[i - 1].next = &buffer[i]; - buffer[i].next = NULL; - buffer[i].is_deduced = 1; - info->count++; - - if (param->pid.type == TPT_NONTYPE && !CTemplTool_IsTemplateArgumentDependentType(param->data.paramdecl.type)) { - if (CExpr_CanImplicitlyConvert(buffer[i].data.paramdecl.expr, param->data.paramdecl.type, param->data.paramdecl.qual)) { - buffer[i].data.paramdecl.expr = CExpr_AssignmentPromotion( - buffer[i].data.paramdecl.expr, param->data.paramdecl.type, param->data.paramdecl.qual, 0); - } else { - return 0; - } - } - - args = args->next; - param = param->next; - i++; - } - - if (flag) { - for (param = params, i = 0; param; param = param->next, i++) { - if (!buffer[i].is_deduced && !param->name) { - switch (param->pid.type) { - case TPT_TYPE: - buffer[i].data.typeparam.type = &stvoid; - break; - case TPT_NONTYPE: - buffer[i].data.paramdecl.expr = nullnode(); - break; - case TPT_TEMPLATE: - default: - CError_FATAL(208); - } - buffer[i].is_deduced = 1; - } - } - } - - return 1; -} - -void CTemplTool_InsertTemplateParameter(NameSpace *nspace, TemplParam *param) { - Type *type; - ObjType *obj; - NameSpaceName *nsn; - - type = CDecl_NewTemplDepType(TEMPLDEP_ARGUMENT); - TYPE_TEMPLATE(type)->u.pid = param->pid; - - obj = galloc(sizeof(ObjType)); - memclrw(obj, sizeof(ObjType)); - obj->otype = OT_TYPE; - obj->access = ACCESSPUBLIC; - obj->type = type; - - for (nsn = nspace->tparams; nsn; nsn = nsn->next) { - if (nsn->name == param->name) { - CError_Error(CErrorStr122, param->name->name); - return; - } - } - - nsn = galloc(sizeof(NameSpaceName)); - memclrw(nsn, sizeof(NameSpaceName)); - - nsn->name = param->name; - nsn->first.object = OBJ_BASE(obj); - - nsn->next = nspace->tparams; - nspace->tparams = nsn; -} - -TemplArg *CTemplTool_MakeTemplArgList(DeduceInfo *info) { - TemplArg *args; - TemplArg *last; - int i; - - for (i = 0; i < info->maxCount; i++) { - if (i) { - last->next = galloc(sizeof(TemplArg)); - last = last->next; - } else { - args = last = galloc(sizeof(TemplArg)); - } - - *last = info->args[i]; - } - - last->next = NULL; - return args; -} - -Boolean CTemplTool_IsIdenticalTemplArgList(TemplArg *args, TemplParam *params) { - while (args) { - if (!params) - return 0; - - CError_ASSERT(297, params->pid.type == args->pid.type); - - switch (args->pid.type) { - case TPT_TYPE: - if ( - !IS_TYPE_TEMPLATE(args->data.typeparam.type) || - TYPE_TEMPLATE(args->data.typeparam.type)->dtype != TEMPLDEP_ARGUMENT || - TYPE_TEMPLATE(args->data.typeparam.type)->u.pid.index != params->pid.index || - TYPE_TEMPLATE(args->data.typeparam.type)->u.pid.nindex != params->pid.nindex - ) - return 0; - break; - case TPT_NONTYPE: - if ( - !ENODE_IS(args->data.paramdecl.expr, ETEMPLDEP) || - args->data.paramdecl.expr->data.templdep.subtype != TDE_PARAM || - args->data.paramdecl.expr->data.templdep.u.pid.index != params->pid.index || - args->data.paramdecl.expr->data.templdep.u.pid.nindex != params->pid.nindex - ) - return 0; - break; - case TPT_TEMPLATE: - if ( - !IS_TYPE_TEMPLATE(args->data.ttargtype) || - TYPE_TEMPLATE(args->data.ttargtype)->dtype != TEMPLDEP_ARGUMENT || - TYPE_TEMPLATE(args->data.ttargtype)->u.pid.index != params->pid.index || - TYPE_TEMPLATE(args->data.ttargtype)->u.pid.nindex != params->pid.nindex - ) - return 0; - break; - default: - CError_FATAL(331); - } - - args = args->next; - params = params->next; - } - - return !params; -} - -Type *CTemplTool_GetSelfRefTemplate(Type *type) { - TemplClass *templ; - TemplArg *args; - - CError_ASSERT(347, IS_TYPE_TEMPLATE(type)); - - if (TYPE_TEMPLATE(type)->dtype == TEMPLDEP_TEMPLATE) { - if (CTemplTool_IsIdenticalTemplArgList( - TYPE_TEMPLATE(type)->u.templ.args, - TYPE_TEMPLATE(type)->u.templ.templ->templ__params)) - return TYPE(TYPE_TEMPLATE(type)->u.templ.templ); - - if (TYPE_TEMPLATE(type)->u.templ.templ->pspecs) { - templ = TYPE_TEMPLATE(type)->u.templ.templ; - if ( - CTemplClass_FindPartialTemplate(TYPE_TEMPLATE(type)->u.templ.args, &templ, &args) && - CTemplTool_IsIdenticalTemplArgList(args, templ->templ__params) - ) - return TYPE(templ); - } - - return NULL; - } - - if (TYPE_TEMPLATE(type)->dtype == TEMPLDEP_QUALNAME) { - Type *t = CTemplTool_GetSelfRefTemplate(TYPE(TYPE_TEMPLATE(type)->u.qual.type)); - if ( - t && - (t = CScope_GetLocalTagType(TYPE_CLASS(t)->nspace, TYPE_TEMPLATE(type)->u.qual.name)) && - IS_TEMPL_CLASS(t) && - !TEMPL_CLASS(t)->templ__params - ) - return t; - - return NULL; - } - - if (TYPE_TEMPLATE(type)->dtype == TEMPLDEP_QUALTEMPL) { - Type *t; - - CError_ASSERT(389, TYPE_TEMPLATE(TYPE_TEMPLATE(type)->u.qualtempl.type)->dtype == TEMPLDEP_QUALNAME); - - t = CTemplTool_GetSelfRefTemplate(TYPE(TYPE_TEMPLATE(TYPE_TEMPLATE(type)->u.qualtempl.type)->u.qual.type)); - if ( - t && - (t = CScope_GetLocalTagType(TYPE_CLASS(t)->nspace, TYPE_TEMPLATE(TYPE_TEMPLATE(type)->u.qualtempl.type)->u.qual.name)) && - IS_TEMPL_CLASS(t) - ) - { - TemplClass *tm = TEMPL_CLASS(t); - if (CTemplTool_IsIdenticalTemplArgList(TYPE_TEMPLATE(type)->u.qualtempl.args, tm->templ__params)) - return TYPE(tm); - } - } - - return NULL; -} - -TemplateFunction *CTemplTool_GetFuncTempl(Object *object) { - while (object->datatype == DALIAS) - object = object->u.alias.object; - - CError_ASSERT(416, IS_TEMPL_FUNC(object->type)); - return object->u.func.u.templ; -} - -Boolean CTemplTool_ParamHasDefaultArg(TemplParam *param) { - switch (param->pid.type) { - case TPT_TYPE: - return param->data.typeparam.type != NULL; - case TPT_NONTYPE: - return param->data.paramdecl.defaultarg != NULL; - case TPT_TEMPLATE: - default: - CError_FATAL(438); - return 0; - } -} - -void CTemplTool_MergeDefaultArgs(TemplParam *dest, TemplParam *src) { - while (1) { - if (!dest) { - CError_ASSERT(455, !src); - return; - } - - CError_ASSERT(458, src); - CError_ASSERT(459, dest->pid.type == src->pid.type); - - switch (dest->pid.type) { - case TPT_TYPE: - if (!dest->data.typeparam.type && src->data.typeparam.type) - dest->data = src->data; - break; - case TPT_NONTYPE: - if (!dest->data.paramdecl.defaultarg && src->data.paramdecl.defaultarg) - dest->data = src->data; - break; - case TPT_TEMPLATE: - if (!dest->data.templparam.defaultarg && src->data.templparam.defaultarg) - dest->data = src->data; - break; - default: - CError_FATAL(484); - } - - dest = dest->next; - src = src->next; - } -} - -static FuncArg *CTemplTool_GetFirstRealArg(TypeFunc *tfunc) { - FuncArg *arg = tfunc->args; - - if (IS_TYPEFUNC_NONSTATIC_METHOD(tfunc)) { - CError_ASSERT(502, arg); - arg = arg->next; - if ((tfunc->flags & FUNC_IS_CTOR) && (TYPE_METHOD(tfunc)->theclass->flags & CLASS_HAS_VBASES)) { - CError_ASSERT(507, arg); - arg = arg->next; - } - } - - return arg; -} - -void CTemplTool_MergeArgNames(TypeFunc *src, TypeFunc *dest) { - FuncArg *destArg; - FuncArg *srcArg; - - CError_ASSERT(524, IS_TYPE_FUNC(dest) && IS_TYPE_FUNC(src)); - - srcArg = CTemplTool_GetFirstRealArg(src); - destArg = CTemplTool_GetFirstRealArg(dest); - - while (1) { - if (!srcArg || !destArg || srcArg == &elipsis || destArg == &elipsis) { - CError_ASSERT(531, srcArg == destArg); - break; - } - - destArg->name = srcArg->name; - srcArg = srcArg->next; - destArg = destArg->next; - } - - if (IS_TYPEFUNC_NONSTATIC_METHOD(dest)) { - CError_ASSERT(538, destArg = dest->args); - if (!destArg->name) - destArg->name = this_name_node; - } -} - -Boolean CTemplTool_EqualParams(TemplParam *a, TemplParam *b, Boolean copyNames) { - while (1) { - if (!a) - return !b; - if (!b) - return 0; - - if (a->pid.type != b->pid.type) - return 0; - - if (copyNames) - a->name = b->name; - - switch (a->pid.type) { - case TPT_TYPE: - break; - case TPT_NONTYPE: - if ( - !is_typesame(a->data.paramdecl.type, b->data.paramdecl.type) || - a->data.paramdecl.qual != b->data.paramdecl.qual - ) - return 0; - break; - case TPT_TEMPLATE: - break; - default: - CError_FATAL(576); - } - - a = a->next; - b = b->next; - } -} - -NameSpace *CTemplTool_SetupTemplateArgumentNameSpace(TemplParam *params, TemplArg *args, Boolean is_global) { - NameSpace *nspace; - Boolean clear_global; - ObjType *objType; - Object *object; - - clear_global = 0; - if (!is_global && trychain) { - clear_global = 1; - is_global = 1; - } - - nspace = CScope_NewListNameSpace(NULL, is_global); - nspace->is_templ = 1; - - if (clear_global) - nspace->is_global = 0; - - if (!params) - return nspace; - - while (params) { - CError_ASSERT(607, args); - - if (params->name) { - switch (args->pid.type) { - case TPT_TYPE: - if (is_global) { - objType = galloc(sizeof(ObjType)); - memclrw(objType, sizeof(ObjType)); - } else { - objType = lalloc(sizeof(ObjType)); - memclrw(objType, sizeof(ObjType)); - } - objType->otype = OT_TYPE; - objType->access = ACCESSPUBLIC; - objType->type = args->data.typeparam.type; - objType->qual = args->data.typeparam.qual; - CScope_AddObject(nspace, params->name, OBJ_BASE(objType)); - break; - case TPT_NONTYPE: - if (is_global) { - object = galloc(sizeof(Object)); - memclrw(object, sizeof(Object)); - } else { - object = lalloc(sizeof(Object)); - memclrw(object, sizeof(Object)); - } - object->otype = OT_OBJECT; - object->access = ACCESSPUBLIC; - object->nspace = nspace; - object->name = params->name; - object->type = args->data.paramdecl.expr->rtype; - object->qual = ENODE_QUALS(args->data.paramdecl.expr); - object->datatype = DEXPR; - object->u.expr = args->data.paramdecl.expr; - if (IS_TYPE_REFERENCE(params->data.paramdecl.type)) { - CError_ASSERT(652, IS_TYPE_POINTER_ONLY(object->u.expr->rtype)); - object->u.expr = makemonadicnode(object->u.expr, EINDIRECT); - object->u.expr->rtype = TPTR_TARGET(params->data.paramdecl.type); - } - if (is_global) - object->u.expr = CInline_CopyExpression(object->u.expr, CopyMode1); - CScope_AddObject(nspace, params->name, OBJ_BASE(object)); - break; - case TPT_TEMPLATE: - if (is_global) { - objType = galloc(sizeof(ObjType)); - memclrw(objType, sizeof(ObjType)); - } else { - objType = lalloc(sizeof(ObjType)); - memclrw(objType, sizeof(ObjType)); - } - objType->otype = OT_TYPE; - objType->access = ACCESSPUBLIC; - objType->type = args->data.ttargtype; - objType->qual = 0; - CScope_AddObject(nspace, params->name, OBJ_BASE(objType)); - break; - default: - CError_FATAL(681); - } - } - - params = params->next; - args = args->next; - } - - CError_ASSERT(685, !args); - - return nspace; -} - -void CTemplTool_SetupOuterTemplateArgumentNameSpace(NameSpace *nspace) { - NameSpace *newns; - - while (nspace) { - if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL_INST)) { - newns = CTemplTool_SetupTemplateArgumentNameSpace( - TEMPL_CLASS_INST(nspace->theclass)->templ->templ__params, - TEMPL_CLASS_INST(nspace->theclass)->inst_args, - 0); - newns->parent = nspace->parent; - nspace->parent = newns; - } - - nspace = nspace->parent; - } -} - -NameSpace *CTemplTool_InsertTemplateArgumentNameSpace(TemplParam *params, TemplClassInst *inst, CScopeSave *save) { - NameSpace *nspace = CTemplTool_SetupTemplateArgumentNameSpace(params, inst->inst_args, 0); - - nspace->parent = inst->theclass.nspace->parent; - inst->theclass.nspace->parent = nspace; - - CTemplTool_SetupOuterTemplateArgumentNameSpace(nspace); - CScope_SetNameSpaceScope(inst->theclass.nspace, save); - - return nspace; -} - -void CTemplTool_RemoveOuterTemplateArgumentNameSpace(NameSpace *nspace) { - while (nspace->parent) { - if (nspace->theclass && (nspace->theclass->flags & CLASS_IS_TEMPL_INST) && nspace->parent->is_templ) - nspace->parent = nspace->parent->parent; - nspace = nspace->parent; - } -} - -void CTemplTool_RemoveTemplateArgumentNameSpace(NameSpace *nspace, TemplClassInst *inst, CScopeSave *save) { - CTemplTool_RemoveOuterTemplateArgumentNameSpace(inst->theclass.nspace); - CScope_RestoreScope(save); -} - -Boolean CTemplTool_IsTemplateArgumentDependentType(Type *type) { - FuncArg *arg; - - while (1) { - switch (type->type) { - case TYPETEMPLATE: - return 1; - case TYPEVOID: - case TYPEINT: - case TYPEFLOAT: - case TYPEENUM: - case TYPESTRUCT: - return 0; - case TYPECLASS: - return (TYPE_CLASS(type)->flags & CLASS_IS_TEMPL) ? 1 : 0; - case TYPEMEMBERPOINTER: - if (CTemplTool_IsTemplateArgumentDependentType(TYPE_MEMBER_POINTER(type)->ty1)) - return 1; - type = TYPE_MEMBER_POINTER(type)->ty2; - continue; - case TYPEPOINTER: - case TYPEARRAY: - type = TPTR_TARGET(type); - continue; - case TYPEFUNC: - for (arg = TYPE_FUNC(type)->args; arg && arg != &elipsis && arg != &oldstyle; arg = arg->next) { - if (CTemplTool_IsTemplateArgumentDependentType(arg->type)) - return 1; - } - type = TYPE_FUNC(type)->functype; - continue; - case TYPEBITFIELD: - type = TYPE_BITFIELD(type)->bitfieldtype; - continue; - case TYPETEMPLDEPEXPR: - return 1; - default: - CError_FATAL(822); - } - } -} - -Boolean CTemplTool_IsTemplateArgumentDependentExpression(ENode *expr) { - if (!expr) - return 0; - - if (IS_TYPE_TEMPLDEPEXPR(expr->rtype)) - return 1; - - return 0; -} - -Boolean CTemplTool_IsSameTemplate(TemplParam *params, TemplArg *args) { - while (1) { - if (!args) { - CError_ASSERT(850, !params); - return 1; - } - - CError_ASSERT(853, params && args->pid.type == params->pid.type); - - switch (args->pid.type) { - case TPT_TYPE: - if ( - !IS_TYPE_TEMPLATE(args->data.typeparam.type) || - TYPE_TEMPLATE(args->data.typeparam.type)->dtype != TEMPLDEP_ARGUMENT || - TYPE_TEMPLATE(args->data.typeparam.type)->u.pid.nindex != params->pid.nindex || - TYPE_TEMPLATE(args->data.typeparam.type)->u.pid.index != params->pid.index || - args->data.typeparam.qual != 0 - ) - return 0; - break; - case TPT_NONTYPE: - if ( - !ENODE_IS(args->data.paramdecl.expr, ETEMPLDEP) || - args->data.paramdecl.expr->data.templdep.subtype != TDE_PARAM || - args->data.paramdecl.expr->data.templdep.u.pid.nindex != params->pid.nindex || - args->data.paramdecl.expr->data.templdep.u.pid.index != params->pid.index - ) - return 0; - break; - case TPT_TEMPLATE: - if (!IS_TYPE_TEMPLATE(args->data.ttargtype)) - return 0; - break; - default: - CError_FATAL(886); - } - - args = args->next; - params = params->next; - } -} - -TemplClass *CTemplTool_IsTemplate(TypeTemplDep *ttd) { - if (ttd->dtype == TEMPLDEP_QUALNAME && ttd->u.qual.type->dtype == TEMPLDEP_TEMPLATE) - ttd = ttd->u.qual.type; - else if (ttd->dtype != TEMPLDEP_TEMPLATE) - return NULL; - - if (CTemplTool_IsSameTemplate(ttd->u.templ.templ->templ__params, ttd->u.templ.args)) - return ttd->u.templ.templ; - else - return NULL; -} - -Type *CTemplTool_IsDependentTemplate(TemplClass *tmclass, TemplArg *args) { - TemplParam *param; - TemplArg *arg; - Type *type; - - if (!tmclass->templ_parent || tmclass->inst_parent) { - arg = args; - param = tmclass->templ__params; - while (1) { - if (!arg) { - CError_ASSERT(988, !param); - return NULL; - } - - CError_ASSERT(991, param && arg->pid.type == param->pid.type); - - switch (arg->pid.type) { - case TPT_TYPE: - if (CTemplTool_IsTemplateArgumentDependentType(arg->data.typeparam.type)) - goto done; - break; - case TPT_NONTYPE: - if (CTemplTool_IsTemplateArgumentDependentExpression(arg->data.paramdecl.expr)) - goto done; - break; - case TPT_TEMPLATE: - if (!IS_TYPE_CLASS(arg->data.ttargtype) && CTemplTool_IsTemplateArgumentDependentType(arg->data.ttargtype)) - goto done; - break; - default: - CError_FATAL(1008); - goto done; - } - - arg = arg->next; - param = param->next; - } - } -done: - if (cscope_current->theclass == TYPE_CLASS(tmclass) && CTemplTool_IsSameTemplate(tmclass->templ__params, args)) - return TYPE(tmclass); - - type = CDecl_NewTemplDepType(TEMPLDEP_TEMPLATE); - TYPE_TEMPLATE(type)->u.templ.templ = tmclass; - TYPE_TEMPLATE(type)->u.templ.args = args; - return type; -} - -Boolean CTemplTool_EqualExprTypes(ENode *a, ENode *b) { - Object *objA; - Object *objB; - - if (!a || !b) - return 0; - if (a->type != b->type) - return 0; - - switch (a->type) { - case EINTCONST: - return CInt64_Equal(a->data.intval, b->data.intval); - case EOBJREF: - objA = a->data.objref; - while (objA->datatype == DALIAS) - objA = objA->u.alias.object; - objB = b->data.objref; - while (objB->datatype == DALIAS) - objB = objB->u.alias.object; - return objA == objB; - case EMEMBER: - return a->data.emember->list == b->data.emember->list; - case ETEMPLDEP: - if (a->data.templdep.subtype != b->data.templdep.subtype) - return 0; - - switch (a->data.templdep.subtype) { - case TDE_PARAM: - return a->data.templdep.u.pid.nindex == b->data.templdep.u.pid.nindex && - a->data.templdep.u.pid.index == b->data.templdep.u.pid.index; - case TDE_SIZEOF: - case TDE_ALIGNOF: - return is_typesame(a->data.templdep.u.typeexpr.type, b->data.templdep.u.typeexpr.type); - case TDE_CAST: - return is_typesame(a->data.templdep.u.cast.type, b->data.templdep.u.cast.type) && - a->data.templdep.u.cast.qual == b->data.templdep.u.cast.qual; - case TDE_QUALNAME: - return is_typesame(TYPE(a->data.templdep.u.qual.type), TYPE(b->data.templdep.u.qual.type)) && - a->data.templdep.u.qual.name == b->data.templdep.u.qual.name; - case TDE_OBJ: - return a->data.templdep.u.obj == b->data.templdep.u.obj; - case TDE_ADDRESS_OF: - return CTemplTool_EqualExprTypes(a->data.templdep.u.monadic, b->data.templdep.u.monadic); - default: - CError_FATAL(1086); - } - case EMUL: - case EDIV: - case EMODULO: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case ELAND: - case ELOR: - case EROTL: - case EROTR: - return CTemplTool_EqualExprTypes(a->data.diadic.left, b->data.diadic.left) && - CTemplTool_EqualExprTypes(a->data.diadic.right, b->data.diadic.right); - case EMONMIN: - case EBINNOT: - case ELOGNOT: - return CTemplTool_EqualExprTypes(a->data.monadic, b->data.monadic); - case ECOND: - return CTemplTool_EqualExprTypes(a->data.cond.cond, b->data.cond.cond) && - CTemplTool_EqualExprTypes(a->data.cond.expr1, b->data.cond.expr1) && - CTemplTool_EqualExprTypes(a->data.cond.expr2, b->data.cond.expr2); - default: - CError_FATAL(1122); - return 0; - } -} - -ENode *CTempl_MakeTemplDepExpr(ENode *left, ENodeType nt, ENode *right) { - if (!IS_TYPE_TEMPLDEPEXPR(right->rtype)) { - right = pointer_generation(right); - if (!ENODE_IS(right, EINTCONST)) { - CError_Error(CErrorStr348); - right = nullnode(); - } - } - - if (left) { - if (!IS_TYPE_TEMPLDEPEXPR(left->rtype)) { - left = pointer_generation(left); - if (!ENODE_IS(left, EINTCONST)) { - CError_Error(CErrorStr348); - left = nullnode(); - } - } - - left = makediadicnode(left, right, nt); - } else { - left = makemonadicnode(right, nt); - } - - left->rtype = &sttemplexpr; - return left; -} - -void CTemplTool_CheckTemplArgType(Type *type) { - while (IS_TYPE_POINTER_ONLY(type)) - type = TPTR_TARGET(type); - - if (IS_TYPE_CLASS(type)) { - if (IsTempName(TYPE_CLASS(type)->classname) || CScope_IsInLocalNameSpace(TYPE_CLASS(type)->nspace)) - CError_Error(CErrorStr232); - } -} - -Boolean CTemplTool_EqualArgs(TemplArg *a, TemplArg *b) { - while (a) { - if (!b || a->pid.type != b->pid.type) - return 0; - - switch (a->pid.type) { - case TPT_TYPE: - if ( - !is_typesame(a->data.typeparam.type, b->data.typeparam.type) || - a->data.typeparam.qual != b->data.typeparam.qual - ) - return 0; - break; - case TPT_NONTYPE: - if (!CTemplTool_EqualExprTypes(a->data.paramdecl.expr, b->data.paramdecl.expr)) - return 0; - break; - case TPT_TEMPLATE: - if (!is_typesame(a->data.ttargtype, b->data.ttargtype)) - return 0; - break; - default: - CError_FATAL(1215); - } - - a = a->next; - b = b->next; - } - - if (b) - return 0; - - return 1; -} - -TemplArg *CTemplTool_MakeGlobalTemplArgCopy(TemplArg *args) { - TemplArg *firstCopy; - TemplArg *copy; - - firstCopy = NULL; - while (args) { - if (firstCopy) { - copy->next = galloc(sizeof(TemplArg)); - copy = copy->next; - } else { - copy = galloc(sizeof(TemplArg)); - firstCopy = copy; - } - - *copy = *args; - if (copy->pid.type == TPT_NONTYPE && copy->data.paramdecl.expr) - copy->data.paramdecl.expr = CInline_CopyExpression(copy->data.paramdecl.expr, CopyMode1); - - args = args->next; - } - - return firstCopy; -} - -Boolean CTemplTool_TemplDepTypeCompare(TypeTemplDep *a, TypeTemplDep *b) { - if (a == b) - return 1; - if (a->dtype != b->dtype) - return 0; - - switch (a->dtype) { - case TEMPLDEP_ARGUMENT: - return a->u.pid.nindex == b->u.pid.nindex && - a->u.pid.index == b->u.pid.index; - case TEMPLDEP_QUALNAME: - return CTemplTool_TemplDepTypeCompare(a->u.qual.type, b->u.qual.type) && - a->u.qual.name == b->u.qual.name; - case TEMPLDEP_TEMPLATE: - return a->u.templ.templ == b->u.templ.templ && - CTemplTool_EqualArgs(a->u.templ.args, b->u.templ.args); - case TEMPLDEP_ARRAY: - return is_typesame(a->u.array.type, b->u.array.type) && - CTemplTool_EqualExprTypes(a->u.array.index, b->u.array.index); - case TEMPLDEP_QUALTEMPL: - return CTemplTool_TemplDepTypeCompare(a->u.qualtempl.type, b->u.qualtempl.type) && - CTemplTool_EqualArgs(a->u.qualtempl.args, b->u.qualtempl.args); - case TEMPLDEP_BITFIELD: - return is_typesame(a->u.bitfield.type, b->u.bitfield.type) && - CTemplTool_EqualExprTypes(a->u.bitfield.size, b->u.bitfield.size); - default: - CError_FATAL(1286); - return 0; - } -} - -Type *CTemplTool_DeduceArgDepType(TemplArg *args, Type *type, UInt32 qual, UInt32 *resultQual) { - TemplArg *arg; - - *resultQual = qual; - - if (IS_TYPE_TEMPLATE(type) && TYPE_TEMPLATE(type)->dtype == TEMPLDEP_ARGUMENT) { - arg = args; - while (1) { - if (!arg) - return NULL; - - if ( - arg->pid.index == TYPE_TEMPLATE(type)->u.pid.index && - arg->pid.nindex == TYPE_TEMPLATE(type)->u.pid.nindex - ) - break; - - arg = arg->next; - } - - CError_ASSERT(1314, arg->pid.type == TPT_TYPE); - *resultQual |= arg->data.typeparam.qual; - return arg->data.typeparam.type; - } - - return NULL; -} - -static TemplClassInst *CTemplTool_FindNestedClassInstance(TemplClass *a, TemplClass *b, TemplClassInst *c) { - TemplClass *array[32]; - TemplClassInst *inst; - int i; - - array[0] = a; - i = 0; - while (1) { - CError_ASSERT(1338, i < 32); - CError_ASSERT(1339, a = a->templ_parent); - - if (a == b) - break; - - CError_ASSERT(1341, a->templ__params == NULL); - - array[++i] = a; - } - - while (1) { - inst = array[i--]->instances; - while (1) { - CError_ASSERT(1350, inst); - if (inst->parent == c) - break; - inst = inst->next; - } - - c = inst; - if (i < 0) - break; - - if ((inst->theclass.flags & (CLASS_COMPLETED | CLASS_IS_TEMPL_INST)) == CLASS_IS_TEMPL_INST) - CTempl_InstantiateTemplateClass(TYPE_CLASS(inst)); - } - - return inst; -} - -static TemplClassInst *CTemplTool_FindNestedClass(TemplClass *a, TemplClassInst *b, TemplClass *c) { - TemplClass *scan; - - while (1) { - for (scan = c->templ_parent; scan; scan = scan->templ_parent) { - if (scan == a) - return CTemplTool_FindNestedClassInstance(c, a, b); - } - - a = a->templ_parent; - if (!a) - break; - - b = b->parent; - CError_ASSERT(1377, b); - } - - return NULL; -} - -static Type *CTemplTool_FindTemplateInstance(TypeDeduce *deduce, TemplClass *templ) { - TemplClass *scantempl; - TemplClass *dtempl; - TemplClassInst *scaninst; - TemplClassInst *dinst; - - dtempl = deduce->tmclass; - CError_ASSERT(1393, dtempl); - - dinst = deduce->inst; - if (!dinst) { - if (!dtempl->templ_parent || !dtempl->inst_parent) - return TYPE(templ); - - dtempl = dtempl->templ_parent; - dinst = deduce->tmclass->inst_parent; - } - - scantempl = dtempl; - scaninst = dinst; - while (1) { - if (scantempl == templ) - return TYPE(scaninst); - - if (!scantempl->templ_parent && scantempl->pspec_owner) - scantempl = scantempl->pspec_owner; - - scantempl = scantempl->templ_parent; - if (!scantempl) - break; - - CError_ASSERT(1416, scaninst = scaninst->parent); - } - - if (dtempl->flags & TEMPLCLASS_FLAGS_2) { - scantempl = TEMPL_CLASS(dtempl->theclass.nspace->theclass); - CError_ASSERT(1422, scantempl->theclass.flags & CLASS_IS_TEMPL); - scaninst = dinst; - - while (1) { - if (scantempl == templ) - return TYPE(scaninst); - - scantempl = scantempl->templ_parent; - if (!scantempl) - break; - - CError_ASSERT(1430, scaninst = scaninst->parent); - } - } - - if (!templ->templ__params && (scaninst = CTemplTool_FindNestedClass(dtempl, dinst, templ))) - return TYPE(scaninst); - - CError_FATAL(1477); - return NULL; -} - -static ENode *CTemplTool_DeduceExprCheck(ENode *expr) { - if (expr->type != EINTCONST) { - CError_Error(CErrorStr348); - expr = nullnode(); - } - - return expr; -} - -static ENodeList *CTemplTool_DeduceExprList(TypeDeduce *deduce, ENodeList *list) { - ENodeList *resultList; - ENodeList *last; - - resultList = NULL; - while (list) { - if (resultList) { - last->next = lalloc(sizeof(ENodeList)); - last = last->next; - } else { - last = lalloc(sizeof(ENodeList)); - resultList = last; - } - - *last = *list; - last->node = CTemplTool_DeduceExpr(deduce, last->node); - - list = list->next; - } - - return resultList; -} - -ENode *CTemplTool_DeduceExpr(TypeDeduce *deduce, ENode *expr) { - TemplArg *arg; - TemplClassInst *inst; - ENode *newExpr; - NameSpaceObjectList *nsObjectList; - TStreamElement *saved; - NameResult pr; - Type *type; - UInt32 qual; - - if (!CTemplTool_IsTemplateArgumentDependentExpression(expr)) { - newExpr = lalloc(sizeof(ENode)); - *newExpr = *expr; - return newExpr; - } - - switch (expr->type) { - case ETEMPLDEP: - switch (expr->data.templdep.subtype) { - case TDE_PARAM: - if (deduce->x15 && expr->data.templdep.u.pid.nindex == deduce->nindex) { - newExpr = lalloc(sizeof(ENode)); - *newExpr = *expr; - return newExpr; - } - - for (arg = deduce->args; arg; arg = arg->next) { - if ( - arg->pid.index == expr->data.templdep.u.pid.index && - arg->pid.nindex == expr->data.templdep.u.pid.nindex - ) - { - CError_ASSERT(1562, arg->pid.type == TPT_NONTYPE && arg->data.paramdecl.expr); - newExpr = lalloc(sizeof(ENode)); - *newExpr = *arg->data.paramdecl.expr; - return newExpr; - } - } - - for (inst = deduce->inst; inst; inst = inst->parent) { - for (arg = inst->inst_args; arg; arg = arg->next) { - if ( - arg->pid.index == expr->data.templdep.u.pid.index && - arg->pid.nindex == expr->data.templdep.u.pid.nindex - ) - { - CError_ASSERT(1575, arg->pid.type == TPT_NONTYPE && arg->data.paramdecl.expr); - newExpr = lalloc(sizeof(ENode)); - *newExpr = *arg->data.paramdecl.expr; - return newExpr; - } - } - } - - CError_FATAL(1582); - - case TDE_SIZEOF: - qual = 0; - type = CTemplTool_DeduceTypeCopy(deduce, TYPE(expr->data.templdep.u.typeexpr.type), &qual); - CDecl_CompleteType(type); - - if (CTemplTool_IsTemplateArgumentDependentType(type)) { - newExpr = lalloc(sizeof(ENode)); - *newExpr = *expr; - newExpr->data.templdep.u.typeexpr.type = type; - return newExpr; - } - - return intconstnode(CABI_GetSizeTType(), type->size); - - case TDE_ALIGNOF: - qual = 0; - type = CTemplTool_DeduceTypeCopy(deduce, TYPE(expr->data.templdep.u.typeexpr.type), &qual); - CDecl_CompleteType(type); - - if (CTemplTool_IsTemplateArgumentDependentType(type)) { - newExpr = lalloc(sizeof(ENode)); - *newExpr = *expr; - newExpr->data.templdep.u.typeexpr.type = type; - return newExpr; - } - - return intconstnode(CABI_GetSizeTType(), CMach_GetTypeAlign(type)); - - case TDE_CAST: - qual = expr->data.templdep.u.cast.qual; - type = CTemplTool_DeduceTypeCopy(deduce, expr->data.templdep.u.cast.type, &qual); - return CExpr_DoExplicitConversion(type, qual, CTemplTool_DeduceExprList(deduce, expr->data.templdep.u.cast.args)); - - case TDE_QUALNAME: - qual = 0; - type = CTemplTool_DeduceTypeCopy(deduce, TYPE(expr->data.templdep.u.qual.type), &qual); - - if (IS_TYPE_CLASS(type)) { - CDecl_CompleteType(type); - if (CScope_FindQualifiedClassMember(&pr, TYPE_CLASS(type), expr->data.templdep.u.qual.name)) - return pointer_generation(CExpr_MakeNameLookupResultExpr(&pr)); - - CError_Error(CErrorStr150, expr->data.templdep.u.qual.name->name); - } else if (IS_TYPE_TEMPLATE(type) && !deduce->inst) { - newExpr = lalloc(sizeof(ENode)); - *newExpr = *expr; - newExpr->data.templdep.u.qual.type = TYPE_TEMPLATE(type); - return newExpr; - } else { - CError_Error(CErrorStr340, expr->data.templdep.u.qual.name->name); - } - - return nullnode(); - - case TDE_OBJ: - type = CTemplTool_FindTemplateInstance(deduce, TEMPL_CLASS(expr->data.templdep.u.obj->nspace->theclass)); - CError_ASSERT(1651, type && IS_TYPE_CLASS(type)); - - nsObjectList = CScope_GetLocalObject(TYPE_CLASS(type)->nspace, expr->data.templdep.u.obj->name); - CError_ASSERT(1654, nsObjectList); - - memclrw(&pr, sizeof(pr)); - pr.obj_10 = nsObjectList->object; - return pointer_generation(CExpr_MakeNameLookupResultExpr(&pr)); - - case TDE_SOURCEREF: - CError_LockErrorPos(expr->data.templdep.u.sourceref.token, &saved); - newExpr = CTemplTool_DeduceExpr(deduce, expr->data.templdep.u.sourceref.expr); - CError_UnlockErrorPos(&saved); - return newExpr; - - case TDE_ADDRESS_OF: - return getnodeaddress(CTemplTool_DeduceExpr(deduce, expr->data.templdep.u.monadic), 1); - - default: - CError_FATAL(1671); - } - case EFUNCCALL: - newExpr = CExpr_PointerGeneration(CTemplTool_DeduceExpr(deduce, expr->data.funccall.funcref)); - return CExpr_MakeFunctionCall(newExpr, CTemplTool_DeduceExprList(deduce, expr->data.funccall.args)); - case ELOGNOT: - return CExpr_New_ELOGNOT_Node(CTemplTool_DeduceExpr(deduce, expr->data.monadic)); - case EMONMIN: - return CExpr_New_EMONMIN_Node(CTemplTool_DeduceExpr(deduce, expr->data.monadic)); - case EBINNOT: - return CExpr_New_EBINNOT_Node(CTemplTool_DeduceExpr(deduce, expr->data.monadic)); - case EMUL: - case EDIV: - case EMODULO: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case ELAND: - case ELOR: - case EROTL: - case EROTR: - return CExpr_NewDyadicNode( - CTemplTool_DeduceExpr(deduce, expr->data.diadic.left), - expr->type, - CTemplTool_DeduceExpr(deduce, expr->data.diadic.right)); - case ECOND: - return CExpr_New_ECOND_Node( - CTemplTool_DeduceExpr(deduce, expr->data.cond.cond), - CTemplTool_DeduceExpr(deduce, expr->data.cond.expr1), - CTemplTool_DeduceExpr(deduce, expr->data.cond.expr2)); - default: - CError_FATAL(1727); - case EINTCONST: - newExpr = lalloc(sizeof(ENode)); - *newExpr = *expr; - return newExpr; - } -} - -ENode *CTemplTool_DeduceDefaultArg(Object *func, ENode *expr) { - TypeDeduce deduce; - - memclrw(&deduce, sizeof(deduce)); - CError_ASSERT(1747, IS_TYPE_FUNC(func->type)); - - if (func->u.func.inst) - deduce.args = func->u.func.inst->args; - - if ((TYPE_FUNC(func->type)->flags & FUNC_METHOD) && (TYPE_METHOD(func->type)->theclass->flags & CLASS_IS_TEMPL_INST)) { - deduce.inst = TEMPL_CLASS_INST(TYPE_METHOD(func->type)->theclass); - deduce.tmclass = TEMPL_CLASS_INST(TYPE_METHOD(func->type)->theclass)->templ; - } - - return CTemplTool_DeduceExpr(&deduce, expr); -} - -static TemplClass *CTemplTool_FindNestedTemplateInstance(TypeDeduce *deduce, TemplClass *templ) { - TemplClass *dtempl; - TemplClassInst *dinst; - Type *type; - - if (templ->inst_parent) - return templ; - - CError_ASSERT(1776, (dtempl = deduce->tmclass) && (dinst = deduce->inst)); - - while (1) { - if ( - templ->templ_parent == dtempl && - (type = CScope_GetLocalTagType(dinst->theclass.nspace, templ->theclass.classname)) && - IS_TEMPL_CLASS(type) && - TEMPL_CLASS(type)->templ_parent == templ->templ_parent - ) - return TEMPL_CLASS(type); - - dtempl = dtempl->templ_parent; - if (!dtempl) - break; - - dinst = dinst->parent; - CError_ASSERT(1790, dinst); - } - - return templ; -} - -static Type *CTemplTool_DeduceClassInstanceCopy(TypeDeduce *deduce, TemplClass *templ, TemplArg *args) { - TemplArg *arg; - TemplArg *deducedArgs; - TemplArg *last; - TemplParam *param; - UInt32 qual; - Type *type; - - if (templ->templ_parent) - templ = CTemplTool_FindNestedTemplateInstance(deduce, templ); - - arg = args; - deducedArgs = NULL; - param = templ->templ__params; - - while (arg) { - if (deducedArgs) { - last->next = galloc(sizeof(TemplArg)); - last = last->next; - } else { - last = galloc(sizeof(TemplArg)); - deducedArgs = last; - } - - *last = *arg; - - if (!param || param->pid.type != last->pid.type) { - CError_Error(CErrorStr374); - return &stvoid; - } - - last->pid = param->pid; - param = param->next; - - switch (last->pid.type) { - case TPT_TYPE: - last->data.typeparam.type = CTemplTool_DeduceTypeCopy(deduce, last->data.typeparam.type, &last->data.typeparam.qual); - break; - - case TPT_NONTYPE: - if (!last->data.paramdecl.expr) { - CError_FATAL(1873); - } else if (CTemplTool_IsTemplateArgumentDependentExpression(last->data.paramdecl.expr)) { - last->data.paramdecl.expr = pointer_generation(CTemplTool_DeduceExpr(deduce, last->data.paramdecl.expr)); - last->data.paramdecl.expr = CInline_CopyExpression(last->data.paramdecl.expr, CopyMode1); - } - break; - - case TPT_TEMPLATE: - qual = 0; - last->data.ttargtype = CTemplTool_DeduceTypeCopy(deduce, last->data.ttargtype, &qual); - break; - - default: - CError_FATAL(1891); - } - - arg = arg->next; - } - - for (arg = deducedArgs; arg; arg = arg->next) { - switch (arg->pid.type) { - case TPT_TYPE: - if (CTemplTool_IsTemplateArgumentDependentType(arg->data.typeparam.type)) - break; - continue; - - case TPT_NONTYPE: - if (CTemplTool_IsTemplateArgumentDependentExpression(arg->data.paramdecl.expr)) - break; - - switch (arg->data.paramdecl.expr->type) { - case EINTCONST: - case EOBJLIST: - case EMEMBER: - break; - case EOBJREF: - if (CParser_HasInternalLinkage2(arg->data.paramdecl.expr->data.objref)) - CError_Error(CErrorStr357); - break; - default: - CError_Error(CErrorStr371); - arg->data.paramdecl.expr = nullnode(); - break; - } - continue; - - case TPT_TEMPLATE: - if (!IS_TYPE_CLASS(arg->data.ttargtype) && CTemplTool_IsTemplateArgumentDependentType(arg->data.ttargtype)) - break; - continue; - - default: - CError_FATAL(1937); - } - - break; - } - - if (arg) { - type = CDecl_NewTemplDepType(TEMPLDEP_TEMPLATE); - TYPE_TEMPLATE(type)->u.templ.templ = templ; - TYPE_TEMPLATE(type)->u.templ.args = deducedArgs; - return type; - } - - if ((type = CTemplTool_IsDependentTemplate(templ, deducedArgs))) - return type; - - return TYPE(CTemplClass_GetInstance(templ, deducedArgs, NULL)); -} - -static TemplArg *CTemplTool_FindTemplArg(TemplArg *args, TemplParamID pid) { - while (args) { - if (args->pid.index == pid.index && args->pid.nindex == pid.nindex) { - CError_ASSERT(1984, pid.type == args->pid.type); - return args; - } - args = args->next; - } - - return NULL; -} - -static TemplArg *CTemplTool_DeduceTemplArg(TypeDeduce *deduce, TemplParamID pid) { - TemplClass *tmclass; - TemplClassInst *inst; - TemplArg *arg; - - if ((arg = CTemplTool_FindTemplArg(deduce->args, pid))) - return arg; - - tmclass = deduce->tmclass; - CError_ASSERT(2008, tmclass); - - inst = deduce->inst; - if (!inst) { - CError_ASSERT(2011, tmclass->templ_parent && tmclass->inst_parent); - inst = deduce->tmclass->inst_parent; - } - - while (1) { - if ((arg = CTemplTool_FindTemplArg(inst->inst_args, pid))) - return arg; - - inst = inst->parent; - CError_ASSERT(2022, inst); - } -} - -static Type *CTemplTool_DeduceArrayCopy(TypeDeduce *deduce, Type *type, ENode *index, UInt32 *resultQual) { - if (CTemplTool_IsTemplateArgumentDependentType(type)) - type = CTemplTool_DeduceTypeCopy(deduce, type, resultQual); - - index = CTemplTool_DeduceExpr(deduce, index); - - if (ENODE_IS(index, EINTCONST)) { - if (CInt64_IsNegative(&index->data.intval)) { - CError_Error(CErrorStr124); - index->data.intval = cint64_one; - } - - if (!CDecl_CheckArrayIntegr(type)) - type = TYPE(&stsignedchar); - - type = CDecl_NewArrayType(type, type->size * CInt64_GetULong(&index->data.intval)); - } else { - if (!deduce->x16) - CError_Error(CErrorStr124); - } - - return type; -} - -static Type *CTemplTool_DeduceBitfieldCopy(TypeDeduce *deduce, Type *type, ENode *size, UInt32 *resultQual) { - TypeBitfield *tbitfield; - short sizeval; - short maxsize; - - if (CTemplTool_IsTemplateArgumentDependentType(type)) { - UInt32 qual = 0; - type = CTemplTool_DeduceTypeCopy(deduce, type, &qual); - } - - if (!IS_TYPE_INT_OR_ENUM(type)) { - CError_Error(CErrorStr138); - type = TYPE(&stunsignedint); - } - - switch (type->size) { - case 1: - maxsize = 8; - break; - case 2: - maxsize = 16; - break; - case 4: - maxsize = 32; - break; - default: - CError_Error(CErrorStr138); - return type; - } - - if (!ENODE_IS(size, EINTCONST)) { - size = CTemplTool_DeduceExpr(deduce, size); - if (!ENODE_IS(size, EINTCONST)) { - CError_Error(CErrorStr124); - return type; - } - } - - sizeval = CInt64_GetULong(&size->data.intval); - if (sizeval > maxsize || CInt64_IsNegative(&size->data.intval)) { - CError_Error(CErrorStr138); - sizeval = 1; - } - - tbitfield = galloc(sizeof(TypeBitfield)); - memclrw(tbitfield, sizeof(TypeBitfield)); - - tbitfield->type = TYPEBITFIELD; - tbitfield->size = type->size; - tbitfield->bitfieldtype = type; - tbitfield->bitlength = sizeval; - - return TYPE(tbitfield); -} - -static Type *CTemplTool_DeduceTemplDepType(TypeDeduce *deduce, TypeTemplDep *tdt, UInt32 *resultQual) { - Type *type; - UInt32 qual; - TemplArg *arg; - - qual = 0; - - if (deduce->x14) { - type = CTemplTool_GetSelfRefTemplate(TYPE(tdt)); - if (type && type == TYPE(deduce->tmclass)) - return type; - - switch (tdt->dtype) { - case TEMPLDEP_ARGUMENT: - return TYPE(tdt); - - case TEMPLDEP_QUALNAME: - type = CTemplTool_DeduceTypeCopy(deduce, TYPE(tdt->u.qual.type), &qual); - if (type == TYPE(tdt->u.qual.type)) - return TYPE(tdt); - - if (!IS_TYPE_CLASS(type)) { - TypeTemplDep *tdtCopy; - CError_ASSERT(2157, IS_TYPE_TEMPLATE(type)); - tdtCopy = galloc(sizeof(TypeTemplDep)); - *tdtCopy = *tdt; - tdtCopy->u.qual.type = TYPE_TEMPLATE(type); - return TYPE(tdtCopy); - } else if ((type = CScope_GetType(TYPE_CLASS(type)->nspace, tdt->u.qual.name, resultQual))) { - return type; - } else { - CError_Error(CErrorStr150, tdt->u.qual.name->name); - return TYPE(tdt); - } - - case TEMPLDEP_TEMPLATE: - for (arg = tdt->u.templ.args; arg; arg = arg->next) { - if (arg->pid.type == TPT_TYPE) - arg->data.typeparam.type = CTemplTool_DeduceTypeCopy(deduce, arg->data.typeparam.type, &arg->data.typeparam.qual); - } - return TYPE(tdt); - - case TEMPLDEP_ARRAY: - tdt->u.array.type = CTemplTool_DeduceTypeCopy(deduce, tdt->u.array.type, &qual); - return TYPE(tdt); - - case TEMPLDEP_QUALTEMPL: - tdt->u.qualtempl.type = TYPE_TEMPLATE(CTemplTool_DeduceTemplDepType(deduce, tdt->u.qualtempl.type, &qual)); - for (arg = tdt->u.qualtempl.args; arg; arg = arg->next) { - if (arg->pid.type == TPT_TYPE) - arg->data.typeparam.type = CTemplTool_DeduceTypeCopy(deduce, arg->data.typeparam.type, &arg->data.typeparam.qual); - } - return TYPE(tdt); - - case TEMPLDEP_BITFIELD: - tdt->u.bitfield.type = CTemplTool_DeduceTypeCopy(deduce, tdt->u.bitfield.type, &qual); - return TYPE(tdt); - } - } else { - switch (tdt->dtype) { - case TEMPLDEP_ARGUMENT: - if (deduce->x15 && tdt->u.pid.nindex == deduce->nindex) - return TYPE(tdt); - - arg = CTemplTool_DeduceTemplArg(deduce, tdt->u.pid); - if (arg->pid.type == TPT_TEMPLATE) { - CError_ASSERT(2222, IS_TEMPL_CLASS(arg->data.typeparam.type)); - *resultQual = arg->data.typeparam.qual; - return arg->data.typeparam.type; - } - - CError_ASSERT(2226, arg->pid.type == TPT_TYPE); - *resultQual = arg->data.typeparam.qual; - return arg->data.typeparam.type; - - case TEMPLDEP_QUALNAME: - type = CTemplTool_DeduceTypeCopy(deduce, TYPE(tdt->u.qual.type), &qual); - if (IS_TYPE_CLASS(type)) { - CDecl_CompleteType(type); - if ((type = CScope_GetType(TYPE_CLASS(type)->nspace, tdt->u.qual.name, resultQual))) { - return type; - } else { - CError_Error(CErrorStr150, tdt->u.qual.name->name); - } - } else { - if ((deduce->x15 || !deduce->inst) && IS_TYPE_TEMPLATE(type)) { - TypeTemplDep *tdtCopy = galloc(sizeof(TypeTemplDep)); - *tdtCopy = *tdt; - tdtCopy->u.qual.type = TYPE_TEMPLATE(type); - return TYPE(tdtCopy); - } else { - CError_Error(CErrorStr340, tdt->u.qual.name->name); - } - } - return TYPE(&stsignedint); - - case TEMPLDEP_TEMPLATE: - return CTemplTool_DeduceClassInstanceCopy(deduce, tdt->u.templ.templ, tdt->u.templ.args); - - case TEMPLDEP_ARRAY: - return CTemplTool_DeduceArrayCopy(deduce, tdt->u.array.type, tdt->u.array.index, resultQual); - - case TEMPLDEP_QUALTEMPL: - type = CTemplTool_DeduceTypeCopy(deduce, TYPE(tdt->u.qualtempl.type), &qual); - if (!IS_TEMPL_CLASS(type)) { - CError_Error(CErrorStr121); - return TYPE(&stsignedint); - } - return CTemplTool_DeduceClassInstanceCopy(deduce, TEMPL_CLASS(type), tdt->u.qualtempl.args); - - case TEMPLDEP_BITFIELD: - return CTemplTool_DeduceBitfieldCopy(deduce, tdt->u.bitfield.type, tdt->u.bitfield.size, resultQual); - } - } - - CError_FATAL(2275); - return NULL; -} - -static Type *CTemplTool_DeduceTypeQualCopy(TypeDeduce *deduce, Type *type, UInt32 *resultQual) { - Type *innerType; - UInt32 qual; - UInt32 innerQual; - TypePointer *newPtr; - - qual = *resultQual; - - if (IS_TYPE_POINTER_ONLY(type) && IS_TYPE_TEMPLATE(TPTR_TARGET(type))) { - innerQual = 0; - innerType = CTemplTool_DeduceTemplDepType(deduce, TYPE_TEMPLATE(TPTR_TARGET(type)), &innerQual); - - newPtr = galloc(sizeof(TypePointer)); - *newPtr = *TYPE_POINTER(type); - - if (IS_TYPE_POINTER_ONLY(innerType)) { - newPtr->target = galloc(sizeof(TypePointer)); - *TYPE_POINTER(newPtr->target) = *TYPE_POINTER(innerType); - *resultQual = innerQual & (Q_CONST | Q_VOLATILE); - TPTR_QUAL(newPtr->target) |= qual & (Q_CONST | Q_VOLATILE); - } else if (IS_TYPE_MEMBERPOINTER(innerType)) { - newPtr->target = galloc(sizeof(TypeMemberPointer)); - *TYPE_MEMBER_POINTER(newPtr->target) = *TYPE_MEMBER_POINTER(innerType); - *resultQual = innerQual & (Q_CONST | Q_VOLATILE); - TYPE_MEMBER_POINTER(newPtr->target)->qual |= qual & (Q_CONST | Q_VOLATILE); - } else { - newPtr->target = innerType; - *resultQual = (qual | innerQual) & (Q_CONST | Q_VOLATILE); - } - - return TYPE(newPtr); - } - - return CTemplTool_DeduceTypeCopy(deduce, type, resultQual); -} - -FuncArg *CTemplTool_DeduceArgCopy(TypeDeduce *deduce, FuncArg *args) { - FuncArg *resultArgs; - FuncArg *last; - - if (args == &oldstyle || args == &elipsis) - return args; - - resultArgs = NULL; - - while (args) { - if (args == &elipsis) { - last->next = args; - break; - } - - if (resultArgs) { - last->next = galloc(sizeof(FuncArg)); - last = last->next; - } else { - last = galloc(sizeof(FuncArg)); - resultArgs = last; - } - - *last = *args; - last->type = CTemplTool_DeduceTypeQualCopy(deduce, last->type, &last->qual); - CanCreateObject(last->type); - - args = args->next; - } - - return resultArgs; -} - -static ExceptSpecList *CTemplTool_DeduceExSpecCopy(TypeDeduce *deduce, ExceptSpecList *exspec) { - ExceptSpecList *copy; - - copy = galloc(sizeof(ExceptSpecList)); - *copy = *exspec; - - if (copy->type && CTemplTool_IsTemplateArgumentDependentType(copy->type)) - copy->type = CTemplTool_DeduceTypeCopy(deduce, copy->type, ©->qual); - - if (copy->next) - copy->next = CTemplTool_DeduceExSpecCopy(deduce, copy->next); - - return copy; -} - -Type *CTemplTool_DeduceTypeCopy(TypeDeduce *deduce, Type *type, UInt32 *resultQual) { - TemplClassInst *inst; - Type *deduced; - UInt32 qual2; - UInt32 qual; - - switch (type->type) { - case TYPETEMPLATE: - qual = 0; - deduced = CTemplTool_DeduceTemplDepType(deduce, TYPE_TEMPLATE(type), &qual); - if (*resultQual & (Q_CONST | Q_VOLATILE)) { - if (IS_TYPE_POINTER_ONLY(deduced)) { - TypePointer *newPtr = galloc(sizeof(TypePointer)); - *newPtr = *TYPE_POINTER(deduced); - newPtr->qual |= *resultQual & (Q_CONST | Q_VOLATILE); - *resultQual &= ~(Q_CONST | Q_VOLATILE); - deduced = TYPE(newPtr); - } else if (IS_TYPE_MEMBERPOINTER(deduced)) { - TypeMemberPointer *newPtr = galloc(sizeof(TypeMemberPointer)); - *newPtr = *TYPE_MEMBER_POINTER(deduced); - newPtr->qual |= *resultQual & (Q_CONST | Q_VOLATILE); - *resultQual &= ~(Q_CONST | Q_VOLATILE); - deduced = TYPE(newPtr); - } - } - *resultQual |= qual; - return deduced; - - case TYPEVOID: - case TYPEINT: - case TYPEFLOAT: - case TYPESTRUCT: - return type; - - case TYPEENUM: - if ( - TYPE_ENUM(type)->nspace->theclass && - (TYPE_ENUM(type)->nspace->theclass->flags & CLASS_IS_TEMPL) && - !deduce->x14 - ) - { - CError_ASSERT(2471, TYPE_ENUM(type)->enumname); - inst = TEMPL_CLASS_INST(CTemplTool_FindTemplateInstance(deduce, TEMPL_CLASS(TYPE_ENUM(type)->nspace->theclass))); - CError_ASSERT(2473, inst && inst->theclass.type == TYPECLASS); - - CDecl_CompleteType(TYPE(inst)); - type = CScope_GetLocalTagType(inst->theclass.nspace, TYPE_ENUM(type)->enumname); - CError_ASSERT(2477, type); - return type; - } - return type; - - case TYPECLASS: - if (!deduce->x14) { - if (TYPE_CLASS(type)->flags & CLASS_IS_TEMPL) - return CTemplTool_FindTemplateInstance(deduce, TEMPL_CLASS(type)); - - if (TYPE_CLASS(type)->nspace->theclass && (TYPE_CLASS(type)->nspace->theclass->flags & CLASS_IS_TEMPL)) { - CError_ASSERT(2492, deduce->inst); - CError_ASSERT(2493, TYPE_CLASS(type)->classname); - - type = CScope_GetLocalTagType(deduce->inst->theclass.nspace, TYPE_CLASS(type)->classname); - CError_ASSERT(2496, type); - return type; - } - } - - return type; - - case TYPEARRAY: { - SInt32 elements; - - elements = TPTR_TARGET(type)->size; - if (elements > 0) - elements = type->size / elements; - - deduced = galloc(sizeof(TypePointer)); - *TYPE_POINTER(deduced) = *TYPE_POINTER(type); - TPTR_TARGET(deduced) = CTemplTool_DeduceTypeCopy(deduce, TPTR_TARGET(type), resultQual); - - do { - type = TPTR_TARGET(type); - } while (IS_TYPE_ARRAY(type)); - - if (IS_TYPE_TEMPLATE(type)) { - CDecl_CompleteType(TPTR_TARGET(deduced)); - deduced->size = TPTR_TARGET(deduced)->size * elements; - } - - return deduced; - } - - case TYPEPOINTER: - deduced = galloc(sizeof(TypePointer)); - *TYPE_POINTER(deduced) = *TYPE_POINTER(type); - TPTR_TARGET(deduced) = CTemplTool_DeduceTypeCopy(deduce, TPTR_TARGET(type), resultQual); - return deduced; - - case TYPEBITFIELD: - deduced = galloc(sizeof(TypeBitfield)); - *TYPE_BITFIELD(deduced) = *TYPE_BITFIELD(type); - TYPE_BITFIELD(deduced)->bitfieldtype = CTemplTool_DeduceTypeCopy(deduce, TYPE_BITFIELD(type)->bitfieldtype, resultQual); - return deduced; - - case TYPEMEMBERPOINTER: - deduced = galloc(sizeof(TypeMemberPointer)); - *TYPE_MEMBER_POINTER(deduced) = *TYPE_MEMBER_POINTER(type); - TYPE_MEMBER_POINTER(deduced)->ty1 = CTemplTool_DeduceTypeCopy(deduce, TYPE_MEMBER_POINTER(type)->ty1, resultQual); - qual2 = 0; - TYPE_MEMBER_POINTER(deduced)->ty2 = CTemplTool_DeduceTypeCopy(deduce, TYPE_MEMBER_POINTER(type)->ty2, &qual2); - - if ( - !IS_TYPE_CLASS(TYPE_MEMBER_POINTER(deduced)->ty2) && - !deduce->x14 && - !deduce->x15 && - !deduce->x16 - ) - { - CError_Error(CErrorStr232); - return TYPE_MEMBER_POINTER(deduced)->ty1; - } - return deduced; - - case TYPEFUNC: - if (TYPE_FUNC(type)->flags & FUNC_METHOD) { - qual2 = 0; - deduced = galloc(sizeof(TypeMemberFunc)); - *TYPE_METHOD(deduced) = *TYPE_METHOD(type); - TYPE_METHOD(deduced)->funcid = 0; - TYPE_METHOD(deduced)->theclass = TYPE_CLASS(CTemplTool_DeduceTypeQualCopy(deduce, TYPE(TYPE_METHOD(type)->theclass), &qual2)); - CError_ASSERT(2556, IS_TYPE_CLASS(TYPE_METHOD(deduced)->theclass)); - } else { - deduced = galloc(sizeof(TypeFunc)); - *TYPE_FUNC(deduced) = *TYPE_FUNC(type); - } - - TYPE_FUNC(deduced)->flags &= ~FUNC_IS_TEMPL; - - qual2 = TYPE_FUNC(type)->qual; - TYPE_FUNC(deduced)->functype = CTemplTool_DeduceTypeQualCopy(deduce, TYPE_FUNC(type)->functype, &qual2); - TYPE_FUNC(deduced)->qual = qual2; - - TYPE_FUNC(deduced)->args = CTemplTool_DeduceArgCopy(deduce, TYPE_FUNC(type)->args); - if (TYPE_FUNC(type)->exspecs) - TYPE_FUNC(deduced)->exspecs = CTemplTool_DeduceExSpecCopy(deduce, TYPE_FUNC(type)->exspecs); - - CDecl_SetResultReg(TYPE_FUNC(deduced)); - return deduced; - - case TYPETEMPLDEPEXPR: - CError_Error(CErrorStr190); - return &stvoid; - - default: - CError_FATAL(2580); - return NULL; - } -} - -Type *CTemplTool_ResolveMemberSelfRefs(TemplClass *templ, Type *type, UInt32 *resultQual) { - TypeDeduce deduce; - - memclrw(&deduce, sizeof(deduce)); - deduce.tmclass = templ; - deduce.x14 = 1; - - if (IS_TYPE_FUNC(type)) { - TYPE_FUNC(type)->functype = CTemplTool_DeduceTypeCopy(&deduce, TYPE_FUNC(type)->functype, &TYPE_FUNC(type)->qual); - TYPE_FUNC(type)->args = CTemplTool_DeduceArgCopy(&deduce, TYPE_FUNC(type)->args); - CDecl_SetResultReg(TYPE_FUNC(type)); - } else { - type = CTemplTool_DeduceTypeCopy(&deduce, type, resultQual); - } - - return type; -} - -Boolean CTemplTool_IsSameTemplateType(Type *a, Type *b) { - return CTemplTool_GetSelfRefTemplate(b) == a; -} diff --git a/compiler_and_linker/unsorted/CodeGen.c b/compiler_and_linker/unsorted/CodeGen.c deleted file mode 100644 index 986bddc..0000000 --- a/compiler_and_linker/unsorted/CodeGen.c +++ /dev/null @@ -1,2437 +0,0 @@ -#include "compiler/CodeGen.h" -#include "compiler/CCompiler.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/COptimizer.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/Coloring.h" -#include "compiler/CompilerTools.h" -#include "compiler/uDump.h" -#include "compiler/Exceptions.h" -#include "compiler/InlineAsmPPC.h" -#include "compiler/Intrinsics.h" -#include "compiler/InstrSelection.h" -#include "compiler/GlobalOptimizer.h" -#include "compiler/ObjGenMachO.h" -#include "compiler/Operands.h" -#include "compiler/PCode.h" -#include "compiler/PCodeAssembly.h" -#include "compiler/PCodeInfo.h" -#include "compiler/PCodeListing.h" -#include "compiler/PCodeUtilities.h" -#include "compiler/Peephole.h" -#include "compiler/PPCError.h" -#include "compiler/RegisterInfo.h" -#include "compiler/Scheduler.h" -#include "compiler/StackFrame.h" -#include "compiler/Switch.h" -#include "compiler/TOC.h" -#include "compiler/ValueNumbering.h" -#include "compiler/enode.h" -#include "compiler/objc.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/tokens.h" -#include "compiler/types.h" - -static Macro powcM; -static Macro __powcM; -static Macro ppc_cpu; -static Macro profM; -static Macro hostM; -static Macro bendM; -static Macro _ppc_M; -static Macro longI; -static Macro IEEED; -Macro vecM; -Macro altivecM; -static Macro macM2; -static Macro appleM; -static Macro optM; -static Macro alignM; -static Macro _machM; -static Macro archM; -static Macro dynM; -static Macro ppcM; -Object *gFunction; -static ObjectList *temps; -CLabel *returnlabel; -CLabel *cleanreturnlabel; -Boolean needs_cleanup; -Statement *current_statement; -int has_catch_blocks; -int disable_optimizer; -SInt32 current_linenumber; -Boolean has_altivec_arrays; -short high_reg; -short low_reg; -short high_offset; -short low_offset; -short low_reg2; -short high_reg2; -PCodeLabel *pic_base_pcodelabel; -Object *dyld_stub_binding_helper; -Object *rt_cvt_fp2unsigned; -Object *rt_profile_entry; -Object *rt_profile_exit; -Object *rt_div2i; -Object *rt_div2u; -Object *rt_mod2i; -Object *rt_mod2u; -Object *rt_shr2i; -Object *rt_shr2u; -Object *rt_shl2i; -Object *rt_cvt_ull_dbl; -Object *rt_cvt_sll_dbl; -Object *rt_cvt_ull_flt; -Object *rt_cvt_sll_flt; -Object *rt_cvt_dbl_usll; -static heaperror_t saveheaperror; - -enum { - GPRLimit = 10, - FPRLimit = 13, - VRLimit = 13 -}; - -// forward decls -static void CodeGen_heaperror(void); - -VarInfo *CodeGen_GetNewVarInfo(void) { - VarInfo *vi; - - vi = lalloc(sizeof(VarInfo)); - memclrw(vi, sizeof(VarInfo)); - - vi->deftoken = *CPrep_CurStreamElement(); - vi->varnumber = localcount++; - - return vi; -} - -Object *maketemporary(Type *type) { - ObjectList *list; - Object *obj; - - for (list = temps; list; list = list->next) { - obj = list->object; - if (obj->u.var.uid == 0 && obj->type == type) { - obj->u.var.uid = 1; - return obj; - } - } - - obj = lalloc(sizeof(Object)); - memclrw(obj, sizeof(Object)); - obj->otype = OT_OBJECT; - obj->access = ACCESSPUBLIC; - obj->datatype = DLOCAL; - obj->type = type; - obj->name = CParser_GetUniqueName(); - obj->u.var.info = CodeGen_GetNewVarInfo(); - obj->u.var.uid = 1; - - list = lalloc(sizeof(ObjectList)); - memclrw(list, sizeof(ObjectList)); - list->next = temps; - list->object = obj; - temps = list; - - return obj; -} - -static void free_temporaries(void) { - ObjectList *list; - - for (list = temps; list; list = list->next) - list->object->u.var.uid = 0; -} - -static void allocate_temporaries(void) { - ObjectList *list; - - for (list = temps; list; list = list->next) - assign_local_memory(list->object); -} - -void process_arguments(ArgumentProcessor func, Boolean flag) { - short gpr = 3; - short fpr = 1; - short vr = 2; - Type *type; - ObjectList *list; - - for (list = arguments; list; list = list->next) { - type = list->object->type; - if (IS_TYPE_FLOAT(type)) { - func(list->object, (fpr <= FPRLimit) ? fpr : 0); - fpr++; - if (type->size == 4) - gpr++; - else - gpr += 2; - } else if (IS_TYPE_VECTOR(type)) { - func(list->object, (vr <= VRLimit) ? vr : 0); - vr++; - if (flag) { - if ((vr - 1) == 2) - gpr = 9; - else if ((vr - 1) > 2) - gpr = 11; - } - } else { - func(list->object, (gpr <= GPRLimit) ? gpr : 0); - if (TYPE_FITS_IN_REGISTER(type)) { - if (type->size <= 4) - gpr += 1; - else - gpr += 2; - } else { - gpr += (type->size >> 2); - if (type->size & 3) - gpr++; - } - } - } - - last_argument_register[RegClass_GPR] = gpr - 1; - last_argument_register[RegClass_FPR] = fpr - 1; - last_argument_register[RegClass_VR] = vr - 1; - if (flag) - move_varargs_to_memory(); -} - -static void retain_argument_register(Object *obj, short reg) { - VarInfo *vi = Registers_GetVarInfo(obj); - Type *type = obj->type; - - if (reg && !vi->noregister && vi->used) { - if (TYPE_FITS_IN_REGISTER(type)) { - if (type->size <= 4) { - retain_register(obj, RegClass_GPR, reg); - } else if (reg < GPRLimit) { - if (copts.littleendian) - retain_GPR_pair(obj, reg, reg + 1); - else - retain_GPR_pair(obj, reg + 1, reg); - } - } else if (IS_TYPE_FLOAT(type)) { - retain_register(obj, RegClass_FPR, reg); - } else if (IS_TYPE_VECTOR(type)) { - retain_register(obj, RegClass_VR, reg); - } - } -} - -static void allocate_local_vregs(void) { - ObjectList *list; - Object *obj; - VarInfo *vi; - - if (copts.codegen_pic && uses_globals && assignable_registers[RegClass_GPR]) { - if (assignable_registers[RegClass_GPR]) { - vi = pic_base.u.var.info; - vi->reg = 0; - assign_register_by_type(&pic_base); - pic_base_reg = vi->reg; - CError_ASSERT(497, pic_base_reg); - } else { - CError_FATAL(500); - } - } else { - pic_base_reg = 0; - } - - for (list = exceptionlist; list; list = list->next) { - obj = list->object; - vi = Registers_GetVarInfo(obj); - - if (vi->used && !vi->noregister) { - if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg) - assign_register_by_type(obj); - } - } - - set_last_exception_registers(); - - for (list = arguments; list; list = list->next) { - obj = list->object; - vi = Registers_GetVarInfo(obj); - - if (vi->used && !vi->noregister) { - if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg) - assign_register_by_type(obj); - } - } - - for (list = locals; list; list = list->next) { - obj = list->object; - if (!IsTempName(obj->name)) { - vi = Registers_GetVarInfo(obj); - - if (vi->used && !vi->noregister) { - if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg) - assign_register_by_type(obj); - } - } - } - - open_fe_temp_registers(); - - for (list = locals; list; list = list->next) { - obj = list->object; - if (IsTempName(obj->name)) { - vi = Registers_GetVarInfo(obj); - - if (vi->used && !vi->noregister) { - if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg) - assign_register_by_type(obj); - } - } - } - - for (list = toclist; list; list = list->next) { - obj = list->object; - vi = Registers_GetVarInfo(obj); - - if (!vi->reg && vi->used && vi->usage > 1) - assign_register_by_type(obj); - } -} - -static void allocate_local_GPRs(void) { - ObjectList *list; - Object *obj; - Object *winning_obj; - SInt32 winning_usage; - VarInfo *vi; - Type *type; - - if (copts.codegen_pic && uses_globals && assignable_registers[RegClass_GPR]) { - vi = pic_base.u.var.info; - vi->reg = 0; - assign_register_by_type(&pic_base); - pic_base_reg = vi->reg; - CError_ASSERT(605, pic_base_reg); - } else { - pic_base_reg = 0; - } - - while (assignable_registers[RegClass_GPR]) { - winning_obj = NULL; - winning_usage = -1; - if (!(disable_optimizer & 2)) { - for (list = arguments; list; list = list->next) { - obj = list->object; - vi = Registers_GetVarInfo(obj); - type = obj->type; - if (vi->flags & VarInfoFlag40) - vi->usage = 100000; - if (!vi->reg && vi->used && !vi->noregister) { - if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { - if (TYPE_FITS_IN_REGISTER(type) && (!TYPE_IS_8BYTES(type) || assignable_registers[RegClass_GPR] >= 2)) { - winning_obj = obj; - winning_usage = vi->usage; - } - } - } - } - } - if (!(disable_optimizer & 2)) { - for (list = locals; list; list = list->next) { - obj = list->object; - vi = Registers_GetVarInfo(obj); - type = obj->type; - if (vi->flags & VarInfoFlag40) - vi->usage = 100000; - if (!vi->reg && vi->used && !vi->noregister) { - if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { - if (TYPE_FITS_IN_REGISTER(type) && (!TYPE_IS_8BYTES(type) || assignable_registers[RegClass_GPR] >= 2)) { - winning_obj = obj; - winning_usage = vi->usage; - } - } - } - } - } - for (list = toclist; list; list = list->next) { - obj = list->object; - vi = Registers_GetVarInfo(obj); - if (vi->flags & VarInfoFlag40) - vi->usage = 100000; - if (!vi->reg && vi->used) { - if (vi->usage >= winning_usage && vi->usage >= 3) { - winning_obj = obj; - winning_usage = vi->usage; - } - } - } - - if (!winning_obj) - break; - - assign_register_by_type(winning_obj); - CError_ASSERT(698, Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2); - } -} - -static void allocate_local_FPRs(void) { - ObjectList *list; - Object *obj; - Object *winning_obj; - SInt32 winning_usage; - VarInfo *vi; - Type *type; - - while (assignable_registers[RegClass_FPR]) { - winning_obj = NULL; - winning_usage = -1; - if (!(disable_optimizer & 2)) { - for (list = arguments; list; list = list->next) { - obj = list->object; - type = obj->type; - vi = Registers_GetVarInfo(obj); - if (vi->flags & VarInfoFlag40) - vi->usage = 100000; - if (!vi->reg && vi->used && !vi->noregister) { - if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { - if (IS_TYPE_FLOAT(type)) { - winning_obj = obj; - winning_usage = vi->usage; - } - } - } - } - } - if (!(disable_optimizer & 2)) { - for (list = locals; list; list = list->next) { - obj = list->object; - vi = Registers_GetVarInfo(obj); - if (vi->flags & VarInfoFlag40) - vi->usage = 100000; - if (!vi->reg && vi->used && !vi->noregister) { - if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { - if (IS_TYPE_FLOAT(obj->type)) { - winning_obj = obj; - winning_usage = vi->usage; - } - } - } - } - } - - if (!winning_obj) - break; - - assign_register_by_type(winning_obj); - CError_ASSERT(782, Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2); - } -} - -static void allocate_local_VRs(void) { - ObjectList *list; - Object *obj; - Object *winning_obj; - SInt32 winning_usage; - VarInfo *vi; - - while (assignable_registers[RegClass_VR]) { - winning_obj = NULL; - winning_usage = -1; - if (!(disable_optimizer & 2)) { - for (list = arguments; list; list = list->next) { - obj = list->object; - vi = Registers_GetVarInfo(obj); - if (vi->flags & VarInfoFlag40) - vi->usage = 100000; - if (!vi->reg && vi->used && !vi->noregister) { - if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { - if (IS_TYPE_VECTOR(obj->type)) { - winning_obj = obj; - winning_usage = vi->usage; - } - } - } - } - } - if (!(disable_optimizer & 2)) { - for (list = locals; list; list = list->next) { - obj = list->object; - vi = Registers_GetVarInfo(obj); - if (vi->flags & VarInfoFlag40) - vi->usage = 100000; - if (!vi->reg && vi->used && !vi->noregister) { - if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) { - if (IS_TYPE_VECTOR(obj->type)) { - winning_obj = obj; - winning_usage = vi->usage; - } - } - } - } - } - - if (!winning_obj) - break; - - assign_register_by_type(winning_obj); - CError_ASSERT(846, Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2); - } -} - -static void allocate_locals(void) { - has_altivec_arrays = 0; - - if (!requires_frame && !optimizing) - process_arguments(retain_argument_register, 0); - - if (optimizing) { - allocate_local_vregs(); - } else { - allocate_local_GPRs(); - allocate_local_FPRs(); - allocate_local_VRs(); - } - - assign_locals_to_memory(locals); -} - -void move_assigned_argument(Object *obj, short reg) { - VarInfo *vi; - Type *type; - SInt32 bytesLeft; - SInt32 offset; - - vi = Registers_GetVarInfo(obj); - type = obj->type; - CError_ASSERT(901, obj->datatype == DLOCAL); - - if (!vi->used) - return; - - if (reg) { - if (vi->reg) { - if (TYPE_IS_8BYTES(type)) { - if (copts.littleendian) { - if (vi->reg != reg) - emitpcode(PC_MR, vi->reg, reg); - if (reg < GPRLimit) { - CError_FAIL(916, (vi->regHi == reg) || (vi->reg == (reg + 1))); - if (vi->regHi != (reg + 1)) - emitpcode(PC_MR, vi->regHi, reg + 1); - } else { - load_store_register(PC_LWZ, vi->regHi, local_base_register(obj), obj, high_offset); - } - } else { - if (vi->regHi != reg) - emitpcode(PC_MR, vi->regHi, reg); - if (reg < GPRLimit) { - CError_FAIL(931, (vi->reg == reg) || (vi->regHi == (reg + 1))); - if (vi->reg != (reg + 1)) - emitpcode(PC_MR, vi->reg, reg + 1); - } else { - load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, low_offset); - } - } - } else if (vi->reg != reg) { - if (IS_TYPE_FLOAT(type)) { - emitpcode(PC_FMR, vi->reg, reg); - } else if (IS_TYPE_VECTOR(type)) { - emitpcode(PC_VMR, vi->reg, reg); - } else { - emitpcode(PC_MR, vi->reg, reg); - } - } - } else { - if (IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)) { - load_store_register(PC_STW, reg, local_base_register(obj), obj, 0); - } else if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) { - switch (type->size) { - case 1: - load_store_register(PC_STB, reg, local_base_register(obj), obj, 0); - break; - case 2: - load_store_register(PC_STH, reg, local_base_register(obj), obj, 0); - break; - case 4: - load_store_register(PC_STW, reg, local_base_register(obj), obj, 0); - break; - case 8: - load_store_register(PC_STW, reg, local_base_register(obj), obj, 0); - if (reg < GPRLimit) - load_store_register(PC_STW, reg + 1, local_base_register(obj), obj, 4); - break; - default: - CError_FATAL(993); - } - } else if (IS_TYPE_FLOAT(type)) { - load_store_register((type->size == 4) ? PC_STFS : PC_STFD, reg, local_base_register(obj), obj, 0); - } else if (IS_TYPE_VECTOR(type)) { - load_store_register(PC_STVX, reg, local_base_register(obj), obj, 0); - } else { - bytesLeft = (11 - reg) * 4; - if (bytesLeft > obj->type->size) - bytesLeft = obj->type->size; - offset = 0; - while (bytesLeft > 0) { - load_store_register(PC_STW, reg, local_base_register(obj), obj, offset); - reg++; - offset += 4; - bytesLeft -= 4; - } - } - } - } else { - if (vi->reg) { - if (IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)) { - load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, 0); - } else if (IS_TYPE_FLOAT(type)) { - load_store_register((type->size == 4) ? PC_LFS : PC_LFD, vi->reg, local_base_register(obj), obj, 0); - } else if (IS_TYPE_VECTOR(type)) { - load_store_register(PC_LVX, vi->reg, local_base_register(obj), obj, 0); - } else { - switch (type->size) { - case 1: - load_store_register(PC_LBZ, vi->reg, local_base_register(obj), obj, 0); - break; - case 2: - load_store_register(is_unsigned(type) ? PC_LHZ : PC_LHA, vi->reg, local_base_register(obj), obj, 0); - break; - case 4: - load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, 0); - break; - case 8: - load_store_register(PC_LWZ, vi->regHi, local_base_register(obj), obj, high_offset); - load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, low_offset); - break; - default: - CError_FATAL(1095); - } - } - } else if (!optimizing) { - local_base_register(obj); - } - } -} - -static void load_TOC_pointers(void) { - VarInfo *vi; - Object *obj; - ObjectList *list; - PCode *pc; - Operand opnd; - - if (uses_globals && pic_base_reg) { - pic_base_pcodelabel = makepclabel(); - pc = makepcode(PC_BC, 20, 7, 3, pic_base_pcodelabel); - pcsetlinkbit(pc); - pcsetsideeffects(pc); - appendpcode(pclastblock, pc); - pcbranch(pclastblock, pic_base_pcodelabel); - makepcblock(); - pclabel(pclastblock, pic_base_pcodelabel); - emitpcode(PC_MFLR, pic_base_reg); - } - - memclrw(&opnd, sizeof(Operand)); - for (list = toclist; list; list = list->next) { - obj = list->object; - if ((vi = Registers_GetVarInfo(obj)) && (vi->flags & VarInfoFlag2)) { - switch (obj->datatype) { - case DNONLAZYPTR: - symbol_operand(&opnd, obj); - opnd.optype = OpndType_IndirectSymbol; - if (opnd.optype) - Coerce_to_register(&opnd, TYPE(&void_ptr), vi->reg); - if (opnd.reg != vi->reg) - emitpcode(PC_MR, vi->reg, opnd.reg); - break; - default: - CError_FATAL(1206); - } - } - } -} - -static int has_vararglist(Object *funcobj) { - FuncArg *arg; - - arg = TYPE_FUNC(funcobj->type)->args; - while (arg && arg != &elipsis) - arg = arg->next; - - return (arg == &elipsis); -} - -void assign_labels(Statement *stmt) { - Statement *last; - - last = NULL; - while (stmt) { - if (stmt->type == ST_LABEL && !stmt->label->pclabel) { - if (last && last->type == ST_LABEL) - stmt->label->pclabel = last->label->pclabel; - else - stmt->label->pclabel = makepclabel(); - } - - last = stmt; - stmt = stmt->next; - } -} - -static Boolean islaststatement(Statement *stmt) { - for (stmt = stmt->next; stmt; stmt = stmt->next) { - if (stmt->type > ST_LABEL) - return 0; - } - return 1; -} - -static void newstatement(SInt32 sourceoffset, SInt32 value, int flag) { - PCodeBlock *block = pclastblock; - - pcloopweight = value; - if (!block->pcodeCount) - block->loopWeight = value; - - if (block->pcodeCount > 100) - branch_label(makepclabel()); - - if (flag) - block->flags |= fPCBlockFlag4000; -} - -static void expressionstatement(ENode *expr) { - Operand opnd; - - memclrw(&opnd, sizeof(Operand)); - cgdispatch[expr->type](expr, 0, 0, &opnd); - - if (ENODE_IS(expr, EINDIRECT) && (opnd.flags & OpndFlags_Volatile)) { - if (TYPE_FITS_IN_REGISTER_2(expr->rtype)) { - if (opnd.optype != OpndType_GPR) - Coerce_to_register(&opnd, expr->rtype, 0); - } else if (IS_TYPE_FLOAT(expr->rtype)) { - if (opnd.optype != OpndType_FPR) - Coerce_to_fp_register(&opnd, expr->rtype, 0); - } else if (IS_TYPE_VECTOR(expr->rtype)) { - if (opnd.optype != OpndType_VR) - Coerce_to_v_register(&opnd, expr->rtype, 0); - } - } -} - -static void labelstatement(CLabel *label) { - if (!label->pclabel) - label->pclabel = makepclabel(); - if (!label->pclabel->resolved) - branch_label(label->pclabel); - free_temporaries(); -} - -static void gotostatement(CLabel *label) { - if (!label->pclabel) - label->pclabel = makepclabel(); - branch_always(label->pclabel); - free_temporaries(); -} - -static void gotoexpression(ENode *expr) { - Operand opnd; - CodeLabelList *list; - - memclrw(&opnd, sizeof(Operand)); - cgdispatch[expr->type](expr, 0, 0, &opnd); - - if (opnd.optype != OpndType_GPR) - Coerce_to_register(&opnd, TYPE(&void_ptr), 0); - CError_ASSERT(1397, opnd.optype == OpndType_GPR); - - for (list = codelabellist; list; list = list->next) - pcbranch(pclastblock, list->label->pclabel); - - emitpcode(PC_MTCTR, opnd.reg); - branch_indirect(NULL); -} - -static void conditionalstatement(ENode *cond, CLabel *label, short truthy) { - Operand opnd; - memclrw(&opnd, sizeof(Operand)); - - cond = evaluate_and_skip_comma(cond); - if (!label->pclabel) - label->pclabel = makepclabel(); - - if (TYPE_IS_8BYTES(cond->data.diadic.right->rtype) || TYPE_IS_8BYTES(cond->data.diadic.left->rtype)) - I8_gen_condition(cond, &opnd, 0); - else - gen_condition(cond, &opnd); - - branch_conditional(opnd.reg, opnd.regOffset, truthy, label->pclabel); - free_temporaries(); -} - -static void returnstatement(ENode *expr, Boolean dont_branch) { - Operand opnd; - Type *type; - memclrw(&opnd, sizeof(Operand)); - - if (expr) { - type = expr->rtype; - if (TYPE_FITS_IN_REGISTER(type)) { - if (TYPE_IS_8BYTES(type)) { - cgdispatch[expr->type](expr, low_reg, high_reg, &opnd); - coerce_to_register_pair(&opnd, type, low_reg, high_reg); - } else { - cgdispatch[expr->type](expr, 3, 0, &opnd); - if (opnd.optype != OpndType_GPR) - Coerce_to_register(&opnd, type, 3); - if (opnd.reg != 3) - emitpcode(PC_MR, 3, opnd.reg); - } - } else if (IS_TYPE_FLOAT(type)) { - cgdispatch[expr->type](expr, 1, 0, &opnd); - if (opnd.optype != OpndType_FPR) - Coerce_to_fp_register(&opnd, type, 1); - if (opnd.reg != 1) - emitpcode(PC_FMR, 1, opnd.reg); - } else if (IS_TYPE_VECTOR(type)) { - cgdispatch[expr->type](expr, 2, 0, &opnd); - if (opnd.optype != OpndType_VR) - Coerce_to_v_register(&opnd, type, 2); - if (opnd.reg != 2) - emitpcode(PC_VMR, 2, opnd.reg); - } else { - cgdispatch[expr->type](expr, 0, 0, &opnd); - } - } - - if (!dont_branch) { - if (!returnlabel->pclabel) - returnlabel->pclabel = makepclabel(); - branch_always(returnlabel->pclabel); - free_temporaries(); - } -} - -static void capturestackpointer(Object *obj) { - branch_label(makepclabel()); - CError_ASSERT(1568, obj->datatype == DLOCAL); - - load_store_register(PC_STW, 1, local_base_register(obj), obj, 20); - branch_label(makepclabel()); -} - -static void resetstackpointer(Object *obj) { - PCode *pc; - - CError_ASSERT(1595, obj->datatype == DLOCAL); - - branch_label(makepclabel()); - - load_store_register(PC_LWZ, 0, 1, NULL, 0); - - pc = makepcode(PC_LWZ, 1, local_base_register(obj), obj, 20); - pcsetsideeffects(pc); - appendpcode(pclastblock, pc); - - load_store_register(PC_STW, 0, 1, NULL, 0); - - branch_label(makepclabel()); -} - -static void callprofiler(char *name) { - UInt32 masks[RegClassMax] = {0, 0, 0, 0, 0}; - load_store_register(PC_LWZ, 3, 1, NULL, 0); - load_store_register(PC_LWZ, 3, 3, NULL, 8); - masks[RegClass_GPR] |= (1 << 3); - branch_subroutine(rt_profile_entry, 1, masks); -} - -static void exitprofiler(void) { -} - -void CodeGen_Generator(Statement *statements, Object *func, UInt8 mysteryFlag, Boolean callOnModuleBind) { - Statement *stmt; - Boolean has_varargs; - PCodeBlock *tmp; - SInt32 size; - - CodeGen_InitialSanityCheck(); - if (!saveheaperror) { - saveheaperror = getheaperror(); - setheaperror(CodeGen_heaperror); - } - - if (cparamblkptr->precompile == 1) - CError_Error(CErrorStr180); - - if (!func) { - func = createstaticinitobject(); - } else { -#ifdef CW_CLT - if (func && func->name) - PrintProgressFunction(func->name->name); -#endif - } - - gFunction = func; - has_varargs = has_vararglist(func); - init_endian(); - init_stack_globals(func); - assign_arguments_to_memory(func, mysteryFlag, has_varargs); - - needs_cleanup = 0; - disable_optimizer = 0; - has_catch_blocks = 0; - current_statement = NULL; - current_linenumber = 0; - precomputedoperands = NULL; - switchtables = NULL; - temps = NULL; - initializeexceptiontables(); - returnlabel = cleanreturnlabel = newlabel(); - - if (copts.debuglisting) - DumpIR(statements, func); - - statements = COpt_Optimizer(func, statements); - if (copts.debuglisting) - DumpIR(statements, func); - - resetTOCvarinfo(); - init_registers(); - expandTOCreferences(&statements->next); - if (copts.debuglisting) - DumpIR(statements, func); - - if (copts.profile) { - makes_call = 1; - requires_frame = 1; - } - - initpcode(); - - pclabel(prologue = makepcblock(), makepclabel()); - prologue->flags |= fIsProlog; - - pclabel(tmp = makepcblock(), makepclabel()); - pcbranch(prologue, tmp->labels); - - init_frame_sizes(has_varargs); - allocate_locals(); - process_arguments(move_assigned_argument, has_varargs); - - if (copts.schedule_factor || copts.altivec_model) - branch_label(makepclabel()); - - load_TOC_pointers(); - - if (copts.profile) - callprofiler(CMangler_GetLinkName(func)->name); - - assign_labels(statements->next); - open_temp_registers(); - - for (stmt = statements->next; stmt; stmt = stmt->next) { - current_statement = stmt; - current_linenumber = stmt->sourceoffset; - switch (stmt->type) { - case ST_NOP: - break; - case ST_EXPRESSION: - newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0); - expressionstatement(stmt->expr); - break; - case ST_LABEL: - labelstatement(stmt->label); - break; - case ST_IFGOTO: - newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0); - conditionalstatement(stmt->expr, stmt->label, 1); - break; - case ST_IFNGOTO: - newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0); - conditionalstatement(stmt->expr, stmt->label, 0); - break; - case ST_GOTOEXPR: - newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0); - gotoexpression(stmt->expr); - break; - case ST_GOTO: - newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0); - gotostatement(stmt->label); - break; - case ST_RETURN: - newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0); - returnstatement(stmt->expr, islaststatement(stmt)); - break; - case ST_SWITCH: - newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0); - switchstatement(stmt->expr, (SwitchInfo *) stmt->label); - break; - case ST_BEGINCATCH: - capturestackpointer(stmt->expr->data.objref); - break; - case ST_ENDCATCHDTOR: - CError_ASSERT(2056, stmt->expr->data.objref->datatype == DLOCAL); - add_immediate(3, local_base_register(stmt->expr->data.objref), stmt->expr->data.objref, 0); - { - UInt32 masks[RegClassMax] = {0, 0, 0, 0, 0}; - masks[RegClass_GPR] |= 1 << 3; - branch_subroutine(Xecth_func, 1, masks); - } - case ST_ENDCATCH: - resetstackpointer(stmt->expr->data.objref); - break; - case ST_ASM: - if (stmt->expr) { - if (((InlineAsm *) stmt->expr)->flags & IAFlag1) { - CError_FATAL(2076); - } else { - branch_label(makepclabel()); - InlineAsm_TranslateIRtoPCode(stmt); - } - } - break; - case ST_BEGINLOOP: - CError_FATAL(2086); - break; - case ST_ENDLOOP: - CError_FATAL(2090); - break; - default: - CError_FATAL(2094); - } - check_temp_registers(); - } - - close_temp_registers(); - labelstatement(returnlabel); - - current_statement = NULL; - - epilogue = pclastblock; - pclastblock->flags |= fIsEpilogue; - - pccomputepredecessors(); - deleteunreachableblocks(); - - if (copts.report_heap_info > 0) - CodeGen_reportheapinfo(0, CMangler_GetLinkName(func)->name, "before optimization"); - - if (copts.optimizationlevel > 0 && !disable_optimizer) - globallyoptimizepcode(func); - else - pclistblocks(CMangler_GetLinkName(func)->name, "INITIAL CODE"); - - if (copts.schedule_factor == 2) { - if (copts.peephole) - peepholemergeblocks(func, 0); - if (copts.debuglisting) - pclistblocks_start_scheduler(CMangler_GetLinkName(func)->name, "BEFORE SCHEDULING"); - scheduleinstructions(0); - if (copts.debuglisting) - pclistblocks_end_scheduler(); - if (copts.debuglisting) - pclistblocks(CMangler_GetLinkName(func)->name, "AFTER INSTRUCTION SCHEDULING"); - } - - if (copts.peephole) { - if (copts.schedule_factor == 0 && copts.optimizationlevel > 1) - peepholemergeblocks(func, 0); - peepholeoptimizeforward(func); - if (copts.debuglisting) - pclistblocks(CMangler_GetLinkName(func)->name, "AFTER PEEPHOLE FORWARD"); - } - - allocate_temporaries(); - colorinstructions(func); - if (copts.debuglisting) - pclistblocks(CMangler_GetLinkName(func)->name, "AFTER REGISTER COLORING"); - - if (copts.optimizationlevel > 1 && !disable_optimizer) { - removecommonsubexpressions(func, 1); - if (removedcommonsubexpressions && copts.debuglisting) - pclistblocks(CMangler_GetLinkName(func)->name, "AFTER VALUE NUMBERING (POST COLORING)"); - } - - compute_frame_sizes(); - generate_prologue(prologue, has_varargs); - if (copts.profile) - exitprofiler(); - generate_epilogue(epilogue, 1); - - if (copts.debuglisting) - pclistblocks(CMangler_GetLinkName(func)->name, "AFTER GENERATING EPILOGUE, PROLOGUE"); - - if (copts.peephole) { - if (copts.schedule_factor) { - peepholemergeblocks(func, 1); - if (copts.debuglisting) - pclistblocks(CMangler_GetLinkName(func)->name, "AFTER MERGING EPILOGUE, PROLOGUE"); - } - peepholeoptimizepcode(func); - if (copts.debuglisting) - pclistblocks(CMangler_GetLinkName(func)->name, "AFTER PEEPHOLE OPTIMIZATION"); - } - - if (copts.schedule_factor) { - if (copts.debuglisting) - pclistblocks_start_scheduler(CMangler_GetLinkName(func)->name, "BEFORE SCHEDULING"); - scheduleinstructions(1); - if (copts.debuglisting) - pclistblocks_end_scheduler(); - if (copts.debuglisting) - pclistblocks(CMangler_GetLinkName(func)->name, "FINAL CODE AFTER INSTRUCTION SCHEDULING"); - } else { - if (copts.debuglisting) - pclistblocks(CMangler_GetLinkName(func)->name, "FINAL CODE"); - } - - size = assemblefunction(func, NULL); - dumpswitchtables(func); - dumpcodelabels(func); - if (callOnModuleBind) - ObjGen_DeclareInitFunction(func); - - pic_base_pcodelabel = NULL; - pic_base_reg = 0; - if (copts.exceptions && requires_frame) - dumpexceptiontables(func, size); - - if (copts.report_heap_info > 0) - CodeGen_reportheapinfo(0, CMangler_GetLinkName(func)->name, "finished"); - - if (saveheaperror) - setheaperror(saveheaperror); -} - -enum { - reg3 = 3, - reg4 = 4 -}; - -void CodeGen_GenVDispatchThunk(Object *thunkobj, Object *obj, SInt32 a, SInt32 b, SInt32 c) { - Boolean save_debug; - Boolean save_peephole; - Boolean save_traceback; - char reg; - - save_debug = copts.filesyminfo; - save_peephole = copts.peephole; - save_traceback = copts.traceback; - - CodeGen_InitialSanityCheck(); - CError_ASSERT(2270, b == 0); - - initpcode(); - makepcblock(); - - if (a) { - reg = CMach_PassResultInHiddenArg(TYPE_FUNC(obj->type)->functype) ? reg4 : reg3; - - if (c >= 0) { - if (!FITS_IN_SHORT(c)) { - emitpcode(PC_ADDIS, 11, 0, 0, HIGH_PART(c)); - if (c) - emitpcode(PC_ADDI, 11, 11, 0, LOW_PART(c)); - } else { - emitpcode(PC_ADDI, 11, 0, 0, c); - } - emitpcode(PC_LWZX, 11, reg, 11); - emitpcode(PC_ADD, reg, reg, 11); - } - - if (!FITS_IN_SHORT(a)) { - emitpcode(PC_ADDIS, reg, reg, 0, HIGH_PART(a)); - if (a) - emitpcode(PC_ADDI, reg, reg, 0, LOW_PART(a)); - } else { - emitpcode(PC_ADDI, reg, reg, 0, a); - } - } - - emitpcode(PC_B, 0, obj); - - copts.filesyminfo = 0; - copts.peephole = 0; - copts.traceback = 0; - assemblefunction(thunkobj, NULL); - copts.filesyminfo = save_debug; - copts.peephole = save_peephole; - copts.traceback = save_traceback; -} - -void CodeGen_SetupRuntimeObjects(void) { - setupaddressing(); - dyld_stub_binding_helper = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - rt_cvt_fp2unsigned = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - rt_profile_entry = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - rt_profile_exit = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - rt_div2i = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - rt_div2u = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - rt_mod2i = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - rt_mod2u = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - rt_shr2i = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - rt_shr2u = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - rt_shl2i = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - rt_cvt_ull_dbl = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - rt_cvt_sll_dbl = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - rt_cvt_ull_flt = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - rt_cvt_sll_flt = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - rt_cvt_dbl_usll = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - Intrinsics_SetupRuntimeObjects(); -} - -Boolean CodeGen_ReInitRuntimeObjects(Boolean is_precompiler) { - dyld_stub_binding_helper->name = GetHashNameNodeExport("dyld_stub_binding_helper"); - dyld_stub_binding_helper->u.func.linkname = dyld_stub_binding_helper->name; - - rt_cvt_fp2unsigned->name = GetHashNameNodeExport("__cvt_fp2unsigned"); - - rt_profile_entry->name = GetHashNameNodeExport("mcount"); - rt_profile_entry->u.func.linkname = rt_profile_entry->name; - - rt_profile_exit->name = GetHashNameNodeExport("profile_exit"); - - rt_div2i->name = GetHashNameNodeExport("__div2i"); - rt_div2u->name = GetHashNameNodeExport("__div2u"); - rt_mod2i->name = GetHashNameNodeExport("__mod2i"); - rt_mod2u->name = GetHashNameNodeExport("__mod2u"); - rt_shr2i->name = GetHashNameNodeExport("__shr2i"); - rt_shr2u->name = GetHashNameNodeExport("__shr2u"); - rt_shl2i->name = GetHashNameNodeExport("__shl2i"); - - rt_cvt_ull_dbl->name = GetHashNameNodeExport("__cvt_ull_dbl"); - rt_cvt_sll_dbl->name = GetHashNameNodeExport("__cvt_sll_dbl"); - rt_cvt_ull_flt->name = GetHashNameNodeExport("__cvt_ull_flt"); - rt_cvt_sll_flt->name = GetHashNameNodeExport("__cvt_sll_flt"); - rt_cvt_dbl_usll->name = GetHashNameNodeExport("__cvt_dbl_usll"); - - CMach_ReInitRuntimeObjects(); - return Intrinsics_ReInitRuntimeObjects(is_precompiler); -} - -Boolean CodeGen_IsPublicRuntimeObject(Object *obj) { - return Intrinsics_IsPublicRuntimeObject(obj); -} - -void CodeGen_SOMStub(Object *a, Object *b, Object *c, SInt32 offset) { - Boolean save_debug; - Boolean save_peephole; - Boolean save_traceback; - Object *tmp; - Operand opnd; - - save_debug = copts.filesyminfo; - save_peephole = copts.peephole; - save_traceback = copts.traceback; - - CodeGen_InitialSanityCheck(); - memclrw(&opnd, sizeof(Operand)); - CError_ASSERT(2528, offset <= 0x7FFF); - - initpcode(); - makepcblock(); - - tmp = createIndirect(c, 1, 1); - if (tmp) { - opnd.optype = OpndType_Symbol; - opnd.object = tmp; - indirect(&opnd, NULL); - } else { - opnd.optype = OpndType_Symbol; - opnd.object = c; - } - - if (opnd.optype != OpndType_GPR) - Coerce_to_register(&opnd, TYPE(&void_ptr), 12); - - if (opnd.optype != OpndType_GPR) { - CError_FATAL(2562); - } else if (opnd.reg != 12) { - emitpcode(PC_MR, 12, opnd.reg); - } - - load_store_register(PC_LWZ, 12, 12, NULL, (short) offset); - emitpcode(PC_B, 0, b); - - copts.filesyminfo = 0; - copts.peephole = 0; - copts.traceback = 0; - assemblefunction(a, NULL); - copts.filesyminfo = save_debug; - copts.peephole = save_peephole; - copts.traceback = save_traceback; -} - -void CodeGen_ParseDeclSpec(HashNameNode *identifier, DeclInfo *declinfo) { - if (!strcmp(identifier->name, "private_extern")) { - declinfo->storageclass = TK_EXTERN; - declinfo->exportflags = EXPORT_FLAGS_INTERNAL; - } else { - CError_Error(CErrorStr176); - } -} - -static void CodeGen_EOLCheck(void) { - short t; - - if (plex() != TK_EOL) { - CPrep_Error(CErrorStr113); - do { - t = plex(); - } while (t != TK_EOL && t != 0); - } -} - -static void schedule_for(int what) { - CPrep_PushOption(OPT_OFFSET(scheduling), what); - if (copts.schedule_factor == 0) - CPrep_PushOption(OPT_OFFSET(schedule_factor), 2); -} - -static void pragma_scheduling(void) { - Boolean *flag; - int cpu; - - tk = plex(); - if (tk == TK_IDENTIFIER) { - flag = &copts.altivec_model; - if (!strcmp(tkidentifier->name, "vger")) { - schedule_for(10); - return; - } else if (!strcmp(tkidentifier->name, "altivec")) { - schedule_for(7); - return; - } else if (!strcmp(tkidentifier->name, "reset")) { - CPrep_PopOption(OPT_OFFSET(scheduling)); - CPrep_PopOption(OPT_OFFSET(schedule_factor)); - return; - } else if (!strcmp(tkidentifier->name, "off")) { - CPrep_PushOption(OPT_OFFSET(schedule_factor), 0); - return; - } else if (!strcmp(tkidentifier->name, "once")) { - CPrep_PushOption(OPT_OFFSET(schedule_factor), 1); - return; - } else if (!strcmp(tkidentifier->name, "twice")) { - CPrep_PushOption(OPT_OFFSET(schedule_factor), 2); - return; - } else if (!strcmp(tkidentifier->name, "on")) { - CPrep_PushOption(OPT_OFFSET(schedule_factor), 2); - return; - } else if (!*flag) { - if (!strcmp(tkidentifier->name, "603e")) { - schedule_for(5); - return; - } else if (!strcmp(tkidentifier->name, "604e")) { - schedule_for(6); - return; - } else if (!strcmp(tkidentifier->name, "PPC603e")) { - schedule_for(5); - return; - } else if (!strcmp(tkidentifier->name, "PPC604e")) { - schedule_for(6); - return; - } - } else { - PPCError_Error(PPCErrorStr115); - return; - } - CPrep_Error(CErrorStr186); - return; - } - - if (tk == TK_INTCONST) { - switch (CInt64_GetULong(&tkintconst)) { - case 601: - cpu = 1; - break; - case 603: - cpu = 2; - break; - case 604: - cpu = 3; - break; - case 750: - cpu = 4; - break; - case 7400: - cpu = 7; - break; - case 7450: - cpu = 10; - break; - case 8240: - case 8260: - cpu = 5; - break; - case 801: - case 821: - case 823: - case 850: - case 860: - cpu = 9; - break; - default: - CPrep_Error(CErrorStr186); - return; - } - schedule_for(cpu); - return; - } - - if (copts.warn_illpragma) - CPrep_Warning(CErrorStr186); -} - -static SInt32 CodeGen_ParseLongIntegerORonORoff(void) { - SInt32 result; - short t; - - result = 0; - t = plex(); - if (t == TK_INTCONST) { - if (!tkintconst.hi) - result = CInt64_GetULong(&tkintconst); - else - CPrep_Error(CErrorStr154); - CodeGen_EOLCheck(); - } else if (t == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "on")) { - CodeGen_EOLCheck(); - return 1; - } - if (!strcmp(tkidentifier->name, "off")) { - CodeGen_EOLCheck(); - return 0; - } - if (copts.warn_illpragma) - CPrep_Warning(CErrorStr186); - return 0; - } else { - if (copts.warn_illpragma) - CPrep_Warning(CErrorStr186); - } - - return result; -} - -void CodeGen_ParsePragma(HashNameNode *name) { - short t; - SInt32 value; - char *str; - NameSpace *nspace; - NameSpaceObjectList *list; - - if (!strcmp(name->name, "debuglisting")) { - copts.debuglisting = CodeGen_ParseLongIntegerORonORoff(); - return; - } - - if (!strcmp(name->name, "report_heap_info")) { - t = plex(); - if (t == TK_INTCONST) { - copts.report_heap_info = CInt64_GetULong(&tkintconst); - if (copts.report_heap_info < 0) { - copts.report_heap_info = 0; - CError_Error(CErrorStr186); - } - } else if (t == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "off")) { - copts.report_heap_info = 0; - } else if (!strcmp(tkidentifier->name, "on")) { - copts.report_heap_info = 1; - } else { - CError_Error(CErrorStr186); - return; - } - } else { - CError_Error(CErrorStr186); - } - CodeGen_EOLCheck(); - return; - } - - if (!strcmp(name->name, "scheduling")) { - pragma_scheduling(); - CodeGen_EOLCheck(); - return; - } - - if (!strcmp(name->name, "ppc_unroll_speculative")) { - if (plex() == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "off")) { - copts.unroll_speculative = 0; - } else if (!strcmp(tkidentifier->name, "on")) { - copts.unroll_speculative = 1; - } else { - CError_Error(CErrorStr186); - return; - } - } else { - CError_Error(CErrorStr186); - } - CodeGen_EOLCheck(); - return; - } - - if (!strcmp(name->name, "ppc_unroll_instructions_limit")) { - t = plex(); - if (t == TK_INTCONST) { - copts.unroll_instr_limit = CInt64_GetULong(&tkintconst); - if (copts.unroll_instr_limit < 0) { - copts.unroll_instr_limit = 0; - CError_Error(CErrorStr186); - } - } else if (t == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "off")) { - copts.unroll_instr_limit = 0; - } else if (!strcmp(tkidentifier->name, "on")) { - copts.unroll_instr_limit = 70; - } else { - CError_Error(CErrorStr186); - return; - } - } else { - CError_Error(CErrorStr186); - } - CodeGen_EOLCheck(); - return; - } - - if (!strcmp(name->name, "gen_fsel")) { - t = plex(); - if (t == TK_INTCONST) { - value = CInt64_GetULong(&tkintconst); - if (value < 0) { - copts.gen_fsel = 0; - CError_Error(CErrorStr186); - } else if (value > 255) { - copts.gen_fsel = 255; - CError_Error(CErrorStr186); - } else { - copts.gen_fsel = value; - } - } else if (t == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "off")) { - copts.gen_fsel = 0; - } else if (!strcmp(tkidentifier->name, "on")) { - copts.gen_fsel = 10; - } else if (!strcmp(tkidentifier->name, "always")) { - copts.gen_fsel = 255; - } else { - CError_Error(CErrorStr186); - return; - } - } else { - CError_Error(CErrorStr186); - } - CodeGen_EOLCheck(); - return; - } - - if (!strcmp(name->name, "ppc_unroll_factor_limit")) { - t = plex(); - if (t == TK_INTCONST) { - copts.unroll_factor_limit = CInt64_GetULong(&tkintconst); - if (copts.unroll_factor_limit < 0) { - copts.unroll_factor_limit = 0; - CError_Error(CErrorStr186); - } - } else if (t == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "off")) { - copts.unroll_factor_limit = 0; - } else if (!strcmp(tkidentifier->name, "on")) { - copts.unroll_factor_limit = 10; - } else { - CError_Error(CErrorStr186); - return; - } - } else { - CError_Error(CErrorStr186); - } - CodeGen_EOLCheck(); - return; - } - - if (!strcmp(name->name, "altivec_model")) { - if (plex() == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "off")) { - copts.altivec_model = 0; - } else if (!strcmp(tkidentifier->name, "on")) { - copts.altivec_model = 1; - } else { - CError_Error(CErrorStr186); - return; - } - } else { - CError_Error(CErrorStr186); - } - CodeGen_EOLCheck(); - return; - } - - if (!strcmp(name->name, "altivec_vrsave")) { - if (plex() == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "off")) { - CPrep_PushOption(OPT_OFFSET(altivec_vrsave), 0); - } else if (!strcmp(tkidentifier->name, "on")) { - CPrep_PushOption(OPT_OFFSET(altivec_vrsave), 1); - } else if (!strcmp(tkidentifier->name, "allon")) { - CPrep_PushOption(OPT_OFFSET(altivec_vrsave), 2); - } else if (!strcmp(tkidentifier->name, "reset")) { - CPrep_PopOption(OPT_OFFSET(altivec_vrsave)); - } else { - CError_Error(CErrorStr186); - return; - } - } else { - CError_Error(CErrorStr186); - } - CodeGen_EOLCheck(); - return; - } - - if (!strcmp(name->name, "function_align")) { - t = plex(); - if (t == TK_INTCONST) { - value = CInt64_GetULong(&tkintconst); - switch (value) { - case 4: - case 8: - case 16: - case 32: - case 64: - case 128: - CPrep_PushOption(OPT_OFFSET(function_align), value); - break; - default: - PPCError_Warning(PPCErrorStr161); - CodeGen_EOLCheck(); - return; - } - } else if (t == TK_IDENTIFIER && !strcmp(tkidentifier->name, "reset")) { - CPrep_PopOption(OPT_OFFSET(function_align)); - } else { - PPCError_Warning(PPCErrorStr161); - } - CodeGen_EOLCheck(); - return; - } - - if (!strcmp(name->name, "processor")) { - if (cscope_currentfunc) { - PPCError_Warning(PPCErrorStr156, "pragma processor"); - return; - } - t = plex(); - if (t == TK_INTCONST) { - switch (CInt64_GetULong(&tkintconst)) { - case 401: - copts.processor = 0; - break; - case 403: - copts.processor = 1; - break; - case 505: - copts.processor = 2; - break; - case 509: - copts.processor = 3; - break; - case 555: - copts.processor = 4; - break; - case 556: - copts.processor = 25; - break; - case 565: - copts.processor = 26; - break; - case 601: - copts.processor = 5; - break; - case 602: - copts.processor = 6; - break; - case 8240: - copts.processor = 18; - break; - case 8260: - copts.processor = 19; - break; - case 603: - copts.processor = 7; - break; - case 604: - copts.processor = 9; - break; - case 740: - copts.processor = 11; - break; - case 750: - copts.processor = 12; - break; - case 801: - copts.processor = 13; - break; - case 821: - copts.processor = 14; - break; - case 823: - copts.processor = 15; - break; - case 850: - copts.processor = 16; - break; - case 860: - copts.processor = 17; - break; - case 7400: - copts.processor = 21; - break; - default: - PPCError_Warning(PPCErrorStr208); - CodeGen_EOLCheck(); - return; - } - } else if (t == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "generic")) - copts.processor = 20; - else if (!strcmp(tkidentifier->name, "603e")) - copts.processor = 8; - else if (!strcmp(tkidentifier->name, "604e")) - copts.processor = 10; - else if (!strcmp(tkidentifier->name, "PPC603e")) - copts.processor = 8; - else if (!strcmp(tkidentifier->name, "PPC604e")) - copts.processor = 10; - else - PPCError_Warning(PPCErrorStr208); - } else { - PPCError_Warning(PPCErrorStr208); - } - - if ((str = CMach_GetCPU())) - CPrep_InsertSpecialMacro(&ppc_cpu, str); - - CodeGen_EOLCheck(); - return; - } - - if (!strcmp(name->name, "min_struct_alignment")) { - t = plex(); - if (t == TK_INTCONST) { - value = CInt64_GetULong(&tkintconst); - switch (value) { - case 4: - case 8: - case 16: - case 32: - case 64: - case 128: - CPrep_PushOption(OPT_OFFSET(min_struct_alignment), value); - break; - default: - PPCError_Warning(PPCErrorStr191); - CodeGen_EOLCheck(); - return; - } - } else if (t == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "reset")) - CPrep_PopOption(OPT_OFFSET(min_struct_alignment)); - else if (!strcmp(tkidentifier->name, "on")) - CPrep_PushOption(OPT_OFFSET(min_struct_alignment), 4); - else if (!strcmp(tkidentifier->name, "off")) - CPrep_PushOption(OPT_OFFSET(min_struct_alignment), 1); - } else { - PPCError_Warning(PPCErrorStr161); - } - - CodeGen_EOLCheck(); - return; - } - - if (!strcmp(name->name, "tvectors")) { - if (plex() == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "off")) { - no_descriptors = 1; - } else if (!strcmp(tkidentifier->name, "on")) { - no_descriptors = 0; - } else { - CError_Error(CErrorStr186); - return; - } - } else { - CError_Error(CErrorStr186); - } - - CodeGen_EOLCheck(); - return; - } - - if (!strcmp(name->name, "dynamic")) { - if (plex() == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "off")) { - copts.codegen_dynamic = 0; - copts.codegen_pic = 0; - } else if (!strcmp(tkidentifier->name, "on")) { - copts.codegen_dynamic = 1; - } else { - CError_Error(CErrorStr186); - return; - } - } else { - CError_Error(CErrorStr186); - } - - CodeGen_EOLCheck(); - return; - } - - if (!strcmp(name->name, "pic")) { - if (plex() == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "off")) { - copts.codegen_pic = 0; - } else if (!strcmp(tkidentifier->name, "on")) { - copts.codegen_pic = 1; - if (!copts.codegen_dynamic) { - PPCError_Error(PPCErrorStr189); - copts.codegen_pic = 0; - } - } else { - CError_Error(CErrorStr186); - return; - } - } else { - CError_Error(CErrorStr186); - } - - CodeGen_EOLCheck(); - return; - } - - if (!strcmp(name->name, "implicit_templates")) { - if (plex() == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "off")) { - copts.no_implicit_templates = 1; - } else if (!strcmp(tkidentifier->name, "on")) { - copts.no_implicit_templates = 0; - } else { - CError_Error(CErrorStr186); - return; - } - } else { - CError_Error(CErrorStr186); - } - - CodeGen_EOLCheck(); - return; - } - - if (!strcmp(name->name, "common")) { - if (plex() == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "off")) { - copts.no_common = 1; - } else if (!strcmp(tkidentifier->name, "on")) { - copts.no_common = 0; - } else { - CError_Error(CErrorStr186); - return; - } - } else { - CError_Error(CErrorStr186); - } - - CodeGen_EOLCheck(); - return; - } - - if (!strcmp(name->name, "CALL_ON_MODULE_BIND")) { - if (plex() == TK_IDENTIFIER) { - for (nspace = cscope_current; nspace; nspace = nspace->parent) { - list = CScope_GetLocalObject(nspace, tkidentifier); - if (list && list->object->otype == OT_OBJECT && OBJECT(list->object)->datatype == DFUNC) { - ObjGen_DeclareInitFunction(OBJECT(list->object)); - break; - } - } - } else { - CError_Error(CErrorStr186); - } - - CodeGen_EOLCheck(); - return; - } - - if (copts.warn_illpragma) - CPrep_Warning(CErrorStr186); - - if (plex() != TK_EOL) { - do { - t = plex(); - } while (t != TK_EOL && t != 0); - } -} - -void CodeGen_UpdateObject(Object *object) { - if (object->datatype == DDATA && object->section == SECT_DEFAULT && object == rt_ptmf_null) - object->sclass = TK_EXTERN; -} - -void CodeGen_UpdateBackEndOptions(void) { - copts.globaloptimizer = 1; -} - -SInt32 CodeGen_objc_method_self_offset(ObjCMethod *meth) { - SInt32 size; - - if (!meth->return_type) { - size = 4; - } else if ( - IS_TYPE_ARRAY(meth->return_type) || - IS_TYPE_NONVECTOR_STRUCT(meth->return_type) || - IS_TYPE_CLASS(meth->return_type) || - IS_TYPE_12BYTES_MEMBERPOINTER(meth->return_type) - ) - { - size = 8; - } else { - size = meth->return_type->size; - } - - if (size == 0) - size = 1; - - return (size + 3) & ~3; -} - -SInt32 CodeGen_objc_method_sel_offset(ObjCMethod *meth) { - return (CodeGen_objc_method_self_offset(meth) + 7) & ~3; -} - -SInt32 CodeGen_objc_method_arg_offset(ObjCMethod *meth, ObjCMethodArg *arg) { - SInt32 pos; - ObjCMethodArg *scan; - - pos = CodeGen_objc_method_sel_offset(meth) + 4; - for (scan = meth->selector_args; scan; scan = scan->next) { - if (scan == arg) - return pos; - - if (scan->type == NULL) - pos += 4; - else - pos += scan->type->size; - - pos = (pos + 3) & ~3; - } - - return 0; -} - -SInt32 CodeGen_objc_method_args_size(ObjCMethod *meth) { - SInt32 size; - ObjCMethodArg *scan; - - size = CodeGen_objc_method_self_offset(meth); - for (scan = meth->selector_args; scan; scan = scan->next) { - if (scan->next == NULL && scan->type == NULL) - return size; - - size = (size + 3) & ~3; - if (scan->type == NULL) - size += 4; - else - size += scan->type->size; - } - - return size; -} - -ENode *CodeGen_HandleIntrinsicCall(Object *func, ENodeList *arg_exprs) { - return Intrinsics_HandleIntrinsicCall(func, arg_exprs); -} - -ENode *CodeGen_HandleTypeCast(ENode *expr, Type *type, UInt32 qual) { - short flags; - - if (copts.altivec_model) { - flags = qual & ENODE_FLAG_QUALS; - if (IS_TYPE_STRUCT(type) && IS_TYPE_STRUCT(expr->rtype) && expr->flags == flags) { - switch (TYPE_STRUCT(type)->stype) { - case STRUCT_VECTOR_UCHAR: - case STRUCT_VECTOR_SCHAR: - case STRUCT_VECTOR_BCHAR: - case STRUCT_VECTOR_USHORT: - case STRUCT_VECTOR_SSHORT: - case STRUCT_VECTOR_BSHORT: - case STRUCT_VECTOR_UINT: - case STRUCT_VECTOR_SINT: - case STRUCT_VECTOR_BINT: - case STRUCT_VECTOR_FLOAT: - case STRUCT_VECTOR_PIXEL: - expr = makemonadicnode(expr, ETYPCON); - expr->rtype = type; - expr->flags = flags; - return expr; - } - } - } - - return NULL; -} - -short CodeGen_AssignCheck(const ENode *expr, const Type *type, Boolean flag1, Boolean flag2) { - short result; - const Type *exprtype = expr->rtype; - - if ( - copts.altivec_model && - IS_TYPE_VECTOR(type) && - IS_TYPE_VECTOR(exprtype) && - TYPE_STRUCT(type)->stype == TYPE_STRUCT(exprtype)->stype - ) - result = CheckResult3; - else - result = CheckResult0; - return result; -} - -Boolean CodeGen_CollapseVectorExpression(ENode *expr, MWVector128 *vec, Type *type) { - // this function is a mess and needs lots of fixing - Boolean result; - //int count; - int i; - ENode *escan; - - result = 0; - for (i = 0; i < 4; i++) - vec->ul[i] = 0; - - if (ENODE_IS(expr, ECOMMA)) { - i = 0; - escan = expr; - while (ENODE_IS(escan, ECOMMA)) { - i++; - escan = escan->data.diadic.left; - } - switch (TYPE_STRUCT(type)->stype) { - case STRUCT_VECTOR_UCHAR: - case STRUCT_VECTOR_SCHAR: - case STRUCT_VECTOR_BCHAR: - if (i < 15) { - PPCError_Error(PPCErrorStr110, type, 0); - } else if (i > 15) { - PPCError_Error(PPCErrorStr111, type, 0); - } else { - escan = expr; - i = 15; - while (ENODE_IS(escan, ECOMMA)) { - CInt64 v; - expr = escan->data.diadic.right; - v = expr->data.intval; - if (!ENODE_IS(expr, EINTCONST)) { - PPCError_Error(PPCErrorStr112); - break; - } - - if (copts.pedantic) { - if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UCHAR) { - if (!CInt64_IsInURange(v, 1)) - PPCError_Warning(PPCErrorStr113, type, 0); - } else { - if (!CInt64_IsInRange(v, 1)) - PPCError_Warning(PPCErrorStr113, type, 0); - } - } - - vec->uc[i--] = (UInt8) v.lo; - escan = escan->data.diadic.left; - } - - if (ENODE_IS(escan, EINTCONST)) { - CInt64 v = escan->data.intval; - if (copts.pedantic) { - if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UCHAR) { - if (!CInt64_IsInURange(v, 1)) - PPCError_Warning(PPCErrorStr113, type, 0); - } else { - if (!CInt64_IsInRange(v, 1)) - PPCError_Warning(PPCErrorStr113, type, 0); - } - } - vec->uc[0] = (UInt8) v.lo; - } else { - PPCError_Error(PPCErrorStr112); - break; - } - result = 1; - } - break; - - case STRUCT_VECTOR_USHORT: - case STRUCT_VECTOR_SSHORT: - case STRUCT_VECTOR_BSHORT: - case STRUCT_VECTOR_PIXEL: - if (i < 7) { - PPCError_Error(PPCErrorStr110, type, 0); - } else if (i > 7) { - PPCError_Error(PPCErrorStr111, type, 0); - } else { - escan = expr; - i = 7; - while (ENODE_IS(escan, ECOMMA)) { - ENode *e = escan->data.diadic.right; - CInt64 v = e->data.intval; - if (!ENODE_IS(e, EINTCONST)) { - PPCError_Error(PPCErrorStr112); - break; - } - - if (copts.pedantic) { - if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_USHORT || TYPE_STRUCT(type)->stype == STRUCT_VECTOR_PIXEL) { - if (!CInt64_IsInURange(v, 2)) - PPCError_Warning(PPCErrorStr113, type, 0); - } else { - if (!CInt64_IsInRange(v, 2)) - PPCError_Warning(PPCErrorStr113, type, 0); - } - } - - vec->us[i--] = (UInt16) e->data.intval.lo; - escan = escan->data.diadic.left; - } - - if (ENODE_IS(escan, EINTCONST)) { - CInt64 v = escan->data.intval; - if (copts.pedantic) { - if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_USHORT || TYPE_STRUCT(type)->stype == STRUCT_VECTOR_PIXEL) { - if (!CInt64_IsInURange(v, 2)) - PPCError_Warning(PPCErrorStr113, type, 0); - } else { - if (!CInt64_IsInRange(v, 2)) - PPCError_Warning(PPCErrorStr113, type, 0); - } - } - vec->us[0] = (UInt16) v.lo; - } else { - PPCError_Error(PPCErrorStr112); - break; - } - result = 1; - } - break; - - case STRUCT_VECTOR_UINT: - case STRUCT_VECTOR_SINT: - case STRUCT_VECTOR_BINT: - if (i < 3) { - PPCError_Error(PPCErrorStr110, type, 0); - } else if (i > 3) { - PPCError_Error(PPCErrorStr111, type, 0); - } else { - escan = expr; - i = 3; - while (ENODE_IS(escan, ECOMMA)) { - CInt64 v; - expr = escan->data.diadic.right; - v = expr->data.intval; - if (!ENODE_IS(expr, EINTCONST)) { - PPCError_Error(PPCErrorStr112); - break; - } - - if (copts.pedantic) { - if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UINT) { - if (!CInt64_IsInURange(v, 4)) - PPCError_Warning(PPCErrorStr113, type, 0); - } else { - if (!CInt64_IsInRange(v, 4)) - PPCError_Warning(PPCErrorStr113, type, 0); - } - } - - vec->ul[i--] = expr->data.intval.lo; - escan = escan->data.diadic.left; - } - - if (ENODE_IS(escan, EINTCONST)) { - CInt64 v = escan->data.intval; - if (copts.pedantic) { - if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UINT) { - if (!CInt64_IsInURange(v, 4)) - PPCError_Warning(PPCErrorStr113, type, 0); - } else { - if (!CInt64_IsInRange(v, 4)) - PPCError_Warning(PPCErrorStr113, type, 0); - } - } - vec->ul[0] = v.lo; - } else { - PPCError_Error(PPCErrorStr112); - break; - } - result = 1; - } - break; - - case STRUCT_VECTOR_FLOAT: - if (i < 3) { - PPCError_Error(PPCErrorStr110, type, 0); - } else if (i > 3) { - PPCError_Error(PPCErrorStr111, type, 0); - } else { - Float fv; - escan = expr; - i = 3; - while (ENODE_IS(escan, ECOMMA)) { - expr = escan->data.diadic.right; - if (ENODE_IS(expr, EFLOATCONST)) { - fv = expr->data.floatval; - } else if (ENODE_IS(escan->data.diadic.right, EINTCONST)) { - fv = CMach_CalcFloatConvertFromInt(expr->rtype, - expr->data.intval); - } else { - PPCError_Error(PPCErrorStr112); - break; - } - - CMach_InitFloatMem(TYPE(&stfloat), fv, &vec->f[i]); - i--; - escan = escan->data.diadic.left; - } - - if (ENODE_IS(escan, EFLOATCONST)) { - fv = escan->data.floatval; - } else if (ENODE_IS(escan, EINTCONST)) { - fv = CMach_CalcFloatConvertFromInt(escan->rtype, escan->data.intval); - } else { - PPCError_Error(PPCErrorStr112); - break; - } - - CMach_InitFloatMem(TYPE(&stfloat), fv, &vec->f[0]); - result = 1; - } - break; - } - } else if (ENODE_IS(expr, EINTCONST)) { - int i = 0; - switch (TYPE_STRUCT(type)->stype) { - case STRUCT_VECTOR_UCHAR: - case STRUCT_VECTOR_SCHAR: - case STRUCT_VECTOR_BCHAR: - { - CInt64 v = expr->data.intval; - if (copts.pedantic) { - if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UCHAR) { - if (!CInt64_IsInURange(v, 1)) - PPCError_Warning(PPCErrorStr113, type, 0); - } else { - if (!CInt64_IsInRange(v, 1)) - PPCError_Warning(PPCErrorStr113, type, 0); - } - } - while (i < 16) - vec->uc[i++] = (UInt8) v.lo; - result = 1; - break; - } - case STRUCT_VECTOR_USHORT: - case STRUCT_VECTOR_SSHORT: - case STRUCT_VECTOR_BSHORT: - case STRUCT_VECTOR_PIXEL: - { - CInt64 v = expr->data.intval; - if (copts.pedantic) { - if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_USHORT || TYPE_STRUCT(type)->stype == STRUCT_VECTOR_PIXEL) { - if (!CInt64_IsInURange(v, 2)) - PPCError_Warning(PPCErrorStr113, type, 0); - } else { - if (!CInt64_IsInRange(v, 2)) - PPCError_Warning(PPCErrorStr113, type, 0); - } - } - while (i < 8) - vec->us[i++] = (UInt16) v.lo; - result = 1; - break; - } - case STRUCT_VECTOR_UINT: - case STRUCT_VECTOR_SINT: - case STRUCT_VECTOR_BINT: - { - CInt64 v = expr->data.intval; - if (copts.pedantic) { - if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UINT) { - if (!CInt64_IsInURange(v, 4)) - PPCError_Warning(PPCErrorStr113, type, 0); - } else { - if (!CInt64_IsInRange(v, 4)) - PPCError_Warning(PPCErrorStr113, type, 0); - } - } - while (i < 4) - vec->ul[i++] = v.lo; - result = 1; - break; - } - case STRUCT_VECTOR_FLOAT: - { - Float fv; - if (!CInt64_IsInRange(expr->data.intval, 4)) { - PPCError_Error(PPCErrorStr112); - break; - } - fv = CMach_CalcFloatConvertFromInt(expr->rtype, expr->data.intval); - for (; i < 4; i++) - CMach_InitFloatMem(TYPE(&stfloat), fv, &vec->f[i]); - result = 1; - break; - } - default: - PPCError_Error(PPCErrorStr112); - } - } else if (ENODE_IS(expr, EFLOATCONST)) { - switch (TYPE_STRUCT(type)->stype) { - default: - PPCError_Error(PPCErrorStr112); - break; - case STRUCT_VECTOR_FLOAT: - { - Float fv; - i = 0; - fv = expr->data.floatval; - CMach_InitFloatMem(TYPE(&stfloat), fv, &vec->f[0]); - while (i < 4) - CMach_InitFloatMem(TYPE(&stfloat), fv, &vec->f[i++]); - result = 1; - break; - } - } - } else if (ENODE_IS2(expr, EINDIRECT, EFUNCCALL)) { - if (!IS_TYPE_STRUCT(expr->rtype)) - PPCError_Error(PPCErrorStr112); - } else if (!ENODE_IS(expr, EVECTOR128CONST)) { - PPCError_Error(PPCErrorStr112); - } - - return result; -} - -void CodeGen_InsertSpecialMacros(void) { - char *str; - - CPrep_InsertSpecialMacro(&vecM, "__VEC__"); - CPrep_InsertSpecialMacro(&altivecM, "__ALTIVEC__"); - CPrep_InsertSpecialMacro(&powcM, "powerc"); - CPrep_InsertSpecialMacro(&__powcM, "__powerc"); - CPrep_InsertSpecialMacro(&hostM, "__POWERPC__"); - CPrep_InsertSpecialMacro(&_ppc_M, "__ppc__"); - - CPrep_InsertSpecialMacro(&bendM, "__BIG_ENDIAN__"); - - if ((str = CMach_GetCPU())) - CPrep_InsertSpecialMacro(&ppc_cpu, str); - - CPrep_InsertSpecialMacro(&profM, "__profile__"); - CPrep_InsertSpecialMacro(&longI, "__fourbyteints__"); - CPrep_InsertSpecialMacro(&IEEED, "__IEEEdoubles__"); - CPrep_InsertSpecialMacro(&macM2, "__MACOS__"); - CPrep_InsertSpecialMacro(&appleM, "__APPLE__"); - CPrep_InsertSpecialMacro(&_machM, "__MACH__"); - CPrep_InsertSpecialMacro(&archM, "__ARCHITECTURE__"); - - if (copts.optimizationlevel > 0) - CPrep_InsertSpecialMacro(&optM, "__OPTIMIZE__"); - - if (copts.codegen_dynamic) - CPrep_InsertSpecialMacro(&dynM, "__DYNAMIC__"); - if (!copts.codegen_dynamic) - CPrep_InsertSpecialMacro(&dynM, "__STATIC__"); - - if (copts.oldalignment && copts.structalignment == AlignMode2_PPC) - CPrep_InsertSpecialMacro(&alignM, "__NATURAL_ALIGNMENT__"); - - if (!copts.ANSIstrict) - CPrep_InsertSpecialMacro(&ppcM, "ppc"); -} - -char *CodeGen_ExpandSpecialMacro(Macro *macro) { - if (macro == &vecM) return "10205"; - if (macro == &altivecM) return "100000000"; - if (macro == &powcM) return "1"; - if (macro == &__powcM) return "1"; - if (macro == &hostM) return "1"; - if (macro == &bendM) return "1"; - if (macro == &_ppc_M) return "1"; - if (CMach_GetCPU() && macro == &ppc_cpu) return "1"; - if (macro == &profM) return copts.profile ? "1" : "0"; - if (macro == &longI) return "1"; - if (macro == &IEEED) return "1"; - if (macro == &macM2) return "1"; - if (macro == &appleM) return "1"; - if (macro == &alignM) return "1"; - - if (macro == &optM) { - switch (copts.optimizationlevel) { - case 1: return "1"; - case 2: return "2"; - case 3: return "3"; - case 4: return "4"; - case 0: return "0"; - default: return "9"; - } - } - - if (macro == &_machM) return "1"; - if (macro == &archM) return "ppc"; - if (macro == &dynM) return "1"; - if (!copts.ANSIstrict && macro == &ppcM) return "1"; - if (macro == &_ppc_M) return "1"; - - CError_FATAL(4801); - return "0"; -} - -void CodeGen_reportheapinfo(Boolean release_flag, char *name, char *text) { - HeapInfo o; - HeapInfo all; - - CTool_GetHeapInfo(&o, 3); - CTool_GetHeapInfo(&all, 5); - - if (release_flag) - releaseoheap(); - - PPCError_Message( - "%n:%u HEAP STATUS\n" - " optimizer: %i blocks, used: %i, free: %i, total: %i, largest free: %i\n" - " all: %i blocks, used: %i, free: %i, total: %i, largest free: %i", - name, text, - o.blocks, o.total_size - o.total_free, o.total_free, o.total_size, o.largest_free_block, - all.blocks, all.total_size - all.total_free, all.total_free, all.total_size, all.largest_free_block - ); -} - -static void CodeGen_heaperror(void) { - CodeGen_reportheapinfo(1, "?", "out of memory"); - if (saveheaperror) { - setheaperror(saveheaperror); - saveheaperror(); - } -} - -void CodeGen_InitialSanityCheck(void) { -} diff --git a/compiler_and_linker/unsorted/CodeMotion.c b/compiler_and_linker/unsorted/CodeMotion.c deleted file mode 100644 index 8ce2962..0000000 --- a/compiler_and_linker/unsorted/CodeMotion.c +++ /dev/null @@ -1,906 +0,0 @@ -#include "compiler/CodeMotion.h" -#include "compiler/Alias.h" -#include "compiler/BitVectors.h" -#include "compiler/LoopDetection.h" -#include "compiler/LoopOptimization.h" -#include "compiler/CompilerTools.h" -#include "compiler/PCode.h" -#include "compiler/UseDefChains.h" -#include "compiler/RegisterInfo.h" - -int movedloopinvariantcode; -int unswitchedinvariantcode; - -static int isloopinvariant(PCode *pcode, Loop *loop, UInt32 *vec, int flag1, int flag2) { - PCodeArg *op; - RegUseOrDef *list; - int i; - - if (pcode->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) { - if (pcode->alias) { - if (pcode->alias->type == AliasType2 || (pcode->flags & (fIsVolatile | fSideEffects))) - return 0; - - if (pcode->flags & fIsRead) { - for (list = findobjectusedef(pcode->alias->object)->defs; list; list = list->next) { - if ( - may_alias(pcode, Defs[list->id].pcode) && - bitvectorgetbit(list->id, vec) && - bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) - ) - return 0; - } - } - - if (pcode->flags & fIsWrite) { - for (list = findobjectusedef(pcode->alias->object)->uses; list; list = list->next) { - if ( - may_alias(pcode, Uses[list->id].pcode) && - bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) - ) - return 0; - } - } - } else { - return 0; - } - } - - if ((pcode->flags & fIsWrite) && !bitvectorgetbit(pcode->block->blockIndex, loop->vec2C)) - return 0; - - op = pcode->args; - i = pcode->argCount; - while (i--) { - switch (op->kind) { - case PCOp_MEMORY: - if ((pcode->flags & fIsRead) && ((pcode->flags == 0) & 0x40)) { - for (list = findobjectusedef(op->data.mem.obj)->defs; list; list = list->next) { - if ( - may_alias(pcode, Defs[list->id].pcode) && - bitvectorgetbit(list->id, vec) && - bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) - ) - return 0; - } - } - if (pcode->flags & fIsWrite) { - for (list = findobjectusedef(op->data.mem.obj)->uses; list; list = list->next) { - if ( - may_alias(pcode, Uses[list->id].pcode) && - bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) - ) - return 0; - } - } - break; - case PCOp_REGISTER: - if (op->data.reg.effect & (EffectRead | EffectWrite)) { - if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) { - if (op->data.reg.reg == _FP_) - break; - if (op->data.reg.reg == _CALLER_SP_) - break; - if (op->data.reg.reg == 2) - break; - } - if (op->data.reg.reg < n_real_registers[op->arg]) { - if (op->arg == RegClass_CRFIELD) { - if (!flag2 || (op->data.reg.effect & EffectRead)) - return 0; - } else if (op->arg == RegClass_SPR) { - if (!flag1) - return 0; - } else { - return 0; - } - } else if (op->data.reg.effect & EffectRead) { - if (flag1 && op->kind == PCOp_REGISTER && op->arg == RegClass_SPR) - break; - if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) { - if (op->data.reg.reg == _FP_) - break; - if (op->data.reg.reg == _CALLER_SP_) - break; - if (op->data.reg.reg == 2) - break; - } - - for (list = reg_Defs[op->arg][op->data.reg.reg]; list; list = list->next) { - if ( - bitvectorgetbit(list->id, vec) && - bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) - ) - return 0; - } - } - } - break; - } - op++; - } - - return 1; -} - -static int isuniquedefinition(PCode *pcode, Loop *loop) { - RegUseOrDef *list; - int defID; - UseOrDef *def; - - defID = pcode->defID; - def = &Defs[defID]; - if (defID >= number_of_Defs) - return 0; - if (def->pcode != pcode) - return 0; - if ((defID + 1) < number_of_Defs && def[1].pcode == pcode) - return 0; - - if (def->v.kind == PCOp_REGISTER) { - for (list = reg_Defs[def->v.arg][def->v.u.reg]; list; list = list->next) { - if ( - bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) && - list->id != defID - ) - return 0; - } - } else if (def->v.kind == PCOp_MEMORY) { - for (list = findobjectusedef(def->v.u.object)->defs; list; list = list->next) { - if ( - may_alias(pcode, Defs[list->id].pcode) && - bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) && - list->id != defID - ) - return 0; - } - } else { - CError_FATAL(292); - } - - return 1; -} - -static int uniquelyreachesuse(int defID, int useID) { - UseOrDef *def; - UseOrDef *use; - RegUseOrDef *list; - PCode *pcode; - - def = &Defs[defID]; - use = &Uses[useID]; - if (def->v.kind == PCOp_REGISTER) { - for (list = reg_Defs[def->v.arg][def->v.u.reg]; list; list = list->next) { - if ( - list->id != defID && - bitvectorgetbit(list->id, usedefinfo[use->pcode->block->blockIndex].defvec8) - ) - break; - } - } else if (def->v.kind == PCOp_MEMORY) { - for (list = findobjectusedef(def->v.u.object)->defs; list; list = list->next) { - if ( - may_alias(def->pcode, Defs[list->id].pcode) && - list->id != defID && - bitvectorgetbit(list->id, usedefinfo[use->pcode->block->blockIndex].defvec8) - ) - break; - } - } - - if (!list) - return 1; - - if (def->pcode->block == use->pcode->block) { - for (pcode = use->pcode->prevPCode; pcode; pcode = pcode->prevPCode) { - if (pcode == def->pcode) - return 1; - } - } - - return 0; -} - -static int uniquelyreachesalluses(int defID, Loop *loop) { - UseOrDef *def; - RegUseOrDef *list; - - def = &Defs[defID]; - - if (def->v.kind == PCOp_REGISTER) { - for (list = reg_Uses[def->v.arg][def->v.u.reg]; list; list = list->next) { - if ( - bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].usevec1C) || - (bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) && !uniquelyreachesuse(defID, list->id)) - ) - return 0; - } - } else if (def->v.kind == PCOp_MEMORY) { - for (list = findobjectusedef(def->v.u.object)->uses; list; list = list->next) { - if (may_alias(def->pcode, Uses[list->id].pcode)) { - if ( - bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].usevec1C) || - (bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) && !uniquelyreachesuse(defID, list->id)) - ) - return 0; - } - } - } else { - CError_FATAL(382); - } - - return 1; -} - -static int isliveonexit(TinyValue *v, Loop *loop) { - RegUseOrDef *list; - UInt32 *vec; - - vec = usedefinfo[loop->preheader->blockIndex].usevec1C; - - if (v->kind == PCOp_REGISTER) { - for (list = reg_Uses[v->arg][v->u.reg]; list; list = list->next) { - if ( - bitvectorgetbit(list->id, vec) && - !bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) - ) - return 1; - } - } else if (v->kind == PCOp_MEMORY) { - for (list = findobjectusedef(v->u.object)->uses; list; list = list->next) { - if ( - bitvectorgetbit(list->id, vec) && - !bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks) - ) - return 1; - } - } - - return 0; -} - -static int dominatesallexits(PCode *pcode, Loop *loop) { - return bitvectorgetbit(pcode->block->blockIndex, loop->vec28) != 0; -} - -static int maymove(PCode *pcode, Loop *loop) { - short reg; - - if (!isuniquedefinition(pcode, loop)) - return 0; - if (!uniquelyreachesalluses(pcode->defID, loop)) - return 0; - if (!dominatesallexits(pcode, loop) && isliveonexit(&Defs[pcode->defID].v, loop)) - return 0; - - if (loop->bodySize > 25) { - switch (pcode->op) { - case PC_LI: - if ( - pcode->nextPCode && - pcode->nextPCode->op == PC_LVX && - (pcode->nextPCode->flags & fIsConst) - ) { - reg = pcode->args[0].data.reg.reg; - if (pcode->nextPCode->args[1].data.reg.reg == reg || - pcode->nextPCode->args[2].data.reg.reg == reg) - return 1; - } - case PC_VSPLTISB: - case PC_VSPLTISH: - case PC_VSPLTISW: - return 0; - default: - if (!bitvectorgetbit(pcode->block->blockIndex, loop->vec2C)) - return 0; - } - } - - return 1; -} - -static void moveinvariantcomputation(PCode *pcode, Loop *loop) { - ObjectUseDef *oud; - BlockList *blocklist; - RegUseOrDef *list; - UseOrDef *def; - int defID; - - defID = pcode->defID; - def = &Defs[defID]; - deletepcode(pcode); - insertpcodebefore(loop->preheader->lastPCode, pcode); - loop->bodySize--; - movedloopinvariantcode = 1; - - if (def->v.kind == PCOp_REGISTER) { - for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { - for (list = reg_Defs[def->v.arg][def->v.u.reg]; list; list = list->next) - bitvectorclearbit(list->id, usedefinfo[blocklist->block->blockIndex].defvec8); - bitvectorsetbit(defID, usedefinfo[blocklist->block->blockIndex].defvec8); - } - } else if (def->v.kind == PCOp_MEMORY) { - oud = findobjectusedef(def->v.u.object); - for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { - for (list = oud->defs; list; list = list->next) { - if (uniquely_aliases(pcode, Defs[list->id].pcode)) - bitvectorclearbit(list->id, usedefinfo[blocklist->block->blockIndex].defvec8); - } - bitvectorsetbit(defID, usedefinfo[blocklist->block->blockIndex].defvec8); - } - } else { - CError_FATAL(545); - } -} - -static int srawi_addze_maymove(PCode *pcode, Loop *loop) { - RegUseOrDef *list; - UseOrDef *def; - int defID; - int nextDefID; - - defID = pcode->defID; - nextDefID = pcode->nextPCode->defID; - - def = &Defs[defID]; - if (defID >= number_of_Defs) - return 0; - if (def->pcode != pcode) - return 0; - if ((defID + 1) < number_of_Defs && def[1].pcode == pcode) - return 0; - - if (def->v.kind == PCOp_REGISTER && def->v.arg == RegClass_GPR) { - for (list = reg_Defs[RegClass_GPR][def->v.u.reg]; list; list = list->next) { - if ( - bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks) && - list->id != defID && - list->id != nextDefID - ) - return 0; - } - } else { - CError_FATAL(582); - } - - if (!uniquelyreachesalluses(pcode->defID, loop)) - return 0; - if (!dominatesallexits(pcode, loop) && isliveonexit(&Defs[pcode->defID].v, loop)) - return 0; - if (!dominatesallexits(pcode->nextPCode, loop) && isliveonexit(&Defs[pcode->nextPCode->defID].v, loop)) - return 0; - - return 1; -} - -static int srawi_addze_isloopinvariant(PCode *pcode, Loop *loop, UInt32 *vec) { - static PCode *oldNextInstr; - PCode *nextInstr; - - nextInstr = pcode->nextPCode; - if ( - pcode->op == PC_ADDZE && - oldNextInstr == pcode - ) { - oldNextInstr = NULL; - return 1; - } else if ( - pcode->op == PC_SRAWI && - nextInstr && - nextInstr->op == PC_ADDZE && - pcode->args[0].data.reg.reg == nextInstr->args[0].data.reg.reg && - nextInstr->args[0].data.reg.reg == nextInstr->args[1].data.reg.reg && - !(pcode->flags & (fIsCall | fIsPtrOp | fIsVolatile | fSideEffects)) && - !(nextInstr->flags & (fIsCall | fIsPtrOp | fIsVolatile | fSideEffects)) && - isloopinvariant(pcode, loop, vec, 1, 0) && - srawi_addze_maymove(pcode, loop) - ) { - oldNextInstr = nextInstr; - return 1; - } else { - oldNextInstr = NULL; - return 0; - } -} - -static void removeblockfromloop(Loop *loop, PCodeBlock *block) { - BlockList *list; - BlockList **ptr; - - bitvectorclearbit(block->blockIndex, loop->memberblocks); - bitvectorclearbit(block->blockIndex, loop->vec24); - bitvectorclearbit(block->blockIndex, loop->vec28); - bitvectorclearbit(block->blockIndex, loop->vec2C); - loop->bodySize -= block->pcodeCount; - - ptr = &loop->blocks; - while ((list = *ptr)) { - if (list->block == block) - *ptr = list->next; - else - ptr = &list->next; - } -} - -static void changesuccessor(PCodeBlock *block, PCodeBlock *from, PCodeBlock *to) { - PCLink **ptr; - PCLink *link; - - for (link = block->successors; link; link = link->nextLink) { - if (link->block == from) - link->block = to; - } - - ptr = &from->predecessors; - while ((link = *ptr)) { - if (link->block == block) { - *ptr = link->nextLink; - link->nextLink = to->predecessors; - to->predecessors = link; - } else { - ptr = &link->nextLink; - } - } -} - -static void movesuccessor(PCodeBlock *to, PCodeBlock *from, PCodeBlock *block) { - PCLink **ptr; - PCLink *link; - - for (link = block->predecessors; link; link = link->nextLink) { - if (link->block == from) - link->block = to; - } - - ptr = &from->successors; - while ((link = *ptr)) { - if (link->block == block) { - *ptr = link->nextLink; - link->nextLink = to->successors; - to->successors = link; - } else { - ptr = &link->nextLink; - } - } -} - -static void movecmptopreheader(Loop *loop, PCodeBlock *block, PCode *pc1, PCode *pc2, PCodeArg *op) { - PCodeBlock *preheader; - PCode *pc3; - - preheader = loop->preheader; - if (PCODE_FLAG_SET_F(pc1) & fRecordBit) { - moveinvariantcomputation(pc1, loop); - } else { - deletepcode(pc1); - insertpcodebefore(loop->preheader->lastPCode, pc1); - loop->bodySize--; - movedloopinvariantcode = 1; - } - loop->preheader = NULL; - - insertpreheaderblock(loop); - - pc3 = preheader->lastPCode; - CError_ASSERT(775, pc3->op == PC_B); - deletepcode(pc3); - deletepcode(pc2); - appendpcode(preheader, pc2); - movesuccessor(preheader, block, op->data.label.label->block); -} - -static PCodeBlock *appendheadercopy(Loop *loop, PCodeBlock *block1, PCodeBlock *block2, PCodeBlock *block3) { - PCodeBlock *newblock1; - PCodeBlock *newblock2; - PCLink *link; - PCode *scan; - - newblock1 = lalloc(sizeof(PCodeBlock)); - newblock2 = lalloc(sizeof(PCodeBlock)); - - newblock1->labels = NULL; - newblock1->predecessors = newblock1->successors = NULL; - newblock1->firstPCode = newblock1->lastPCode = NULL; - newblock1->pcodeCount = 0; - newblock1->loopWeight = loop->body->loopWeight; - newblock1->flags = 0; - newblock1->blockIndex = pcblockcount++; - - newblock2->labels = NULL; - newblock2->predecessors = newblock2->successors = NULL; - newblock2->firstPCode = newblock2->lastPCode = NULL; - newblock2->pcodeCount = 0; - newblock2->loopWeight = loop->body->loopWeight; - newblock2->flags = 0; - newblock2->blockIndex = pcblockcount++; - - newblock1->nextBlock = newblock2; - newblock2->prevBlock = newblock1; - newblock1->prevBlock = block1; - newblock2->nextBlock = block1->nextBlock; - block1->nextBlock = newblock1; - newblock2->nextBlock->prevBlock = newblock2; - - pclabel(newblock1, makepclabel()); - pclabel(newblock2, makepclabel()); - - changesuccessor(block1, block1->successors->block, newblock1); - - link = lalloc(sizeof(PCLink)); - link->block = newblock2; - link->nextLink = newblock1->successors; - newblock1->successors = link; - - link = lalloc(sizeof(PCLink)); - link->block = newblock1; - link->nextLink = newblock2->predecessors; - newblock2->predecessors = link; - - appendpcode(newblock2, makepcode(PC_B, block2->nextBlock->labels)); - pcbranch(newblock2, block2->nextBlock->labels); - pccomputepredecessors1(newblock2); - - for (scan = block2->firstPCode; scan; scan = scan->nextPCode) - appendpcode(newblock1, copypcode(scan)); - - pcbranch(newblock1, block3->labels); - - link = lalloc(sizeof(PCLink)); - link->block = newblock1; - link->nextLink = block3->predecessors; - block3->predecessors = link; - - addblocktoloop(loop, newblock1); - if (bitvectorgetbit(block2->blockIndex, loop->vec28)) - bitvectorsetbit(newblock1->blockIndex, loop->vec28); - if (bitvectorgetbit(block2->blockIndex, loop->vec2C)) - bitvectorsetbit(newblock1->blockIndex, loop->vec2C); - - for (loop = loop->parent; loop; loop = loop->parent) { - addblocktoloop(loop, newblock1); - if (bitvectorgetbit(block2->blockIndex, loop->vec28)) - bitvectorsetbit(newblock1->blockIndex, loop->vec28); - if (bitvectorgetbit(block2->blockIndex, loop->vec2C)) - bitvectorsetbit(newblock1->blockIndex, loop->vec2C); - - addblocktoloop(loop, newblock2); - if (bitvectorgetbit(block2->blockIndex, loop->vec28)) - bitvectorsetbit(newblock2->blockIndex, loop->vec28); - if (bitvectorgetbit(block2->blockIndex, loop->vec2C)) - bitvectorsetbit(newblock2->blockIndex, loop->vec2C); - } - - return newblock1; -} - -static BlockList *findswitchpath(Loop *loop, PCodeBlock *block) { - BlockList *head; - BlockList *tail; - BlockList *node; - PCodeBlock *scan; - - head = NULL; - tail = NULL; - - for (scan = block; scan && scan != loop->body; scan = scan->successors->block) { - if (!bitvectorgetbit(scan->blockIndex, loop->memberblocks)) - return NULL; - if (scan->successors && scan->successors->nextLink) - return NULL; - - node = oalloc(sizeof(BlockList)); - node->block = scan; - node->next = NULL; - if (head) { - tail->next = node; - tail = node; - } else { - head = node; - tail = node; - } - } - - return head; -} - -static void simpleunswitchloop(Loop *loop) { - PCode *pc29; - PCodeArg *op27; - UInt32 *myvec; - PCodeBlock *block26; - PCode *pc25; // r25 - BlockList *path2_24; - PCodeArg *op23; - PCode *pc23; // r23 - BlockList *scanlist; // r23 - BlockList *bestpath1; // r23 - BlockList *bestpath2; // r22 - PCodeBlock *headercopy; // r22 - Loop *newloop; // r21 - PCodeBlock *preheader21; - BlockList *path20; - PCode *scan20; - PCode *lastpcode; - int i; - BlockList *pathiter1; - BlockList *pathiter2; - - if (!(lastpcode = loop->body->lastPCode)) - return; - if (lastpcode->op != PC_BT && lastpcode->op != PC_BF) - return; - if (lastpcode->args[2].kind != PCOp_LABEL) - return; - if (!bitvectorgetbit(lastpcode->args[2].data.label.label->block->blockIndex, loop->memberblocks)) - return; - if (loop->x57) - return; - if (loop->x4D) - return; - if (bitvectorgetbit(loop->body->nextBlock->blockIndex, loop->memberblocks)) - return; - - for (block26 = pcbasicblocks; block26; block26 = block26->nextBlock) { - if (bitvectorgetbit(block26->blockIndex, loop->memberblocks)) - break; - } - - if (!block26) - return; - - myvec = oalloc(4 * ((number_of_Defs + 31) >> 5)); - bitvectorcopy(myvec, usedefinfo[block26->blockIndex].defvec8, number_of_Defs); - for (pc25 = loop->preheader->nextBlock->firstPCode; pc25; pc25 = pc25->nextPCode) { - if (!(PCODE_FLAG_SET_F(pc25) & (fIsCall | fIsPtrOp | fIsVolatile | fSideEffects | fRecordBit))) { - if (isloopinvariant(pc25, loop, myvec, 0, 1)) - break; - } - } - - if (!pc25 || pc25->argCount < 1) - return; - - if ( - pc25->argCount < 1 || - pc25->args[0].kind != PCOp_REGISTER || - pc25->args[0].arg != RegClass_CRFIELD - ) - return; - - pc29 = pc25->block->lastPCode; - if ( - !pc29 || - !(pc29->flags & fIsBranch) || - pc29->args[0].kind != PCOp_REGISTER || - pc29->args[0].arg != RegClass_CRFIELD - ) - return; - - if (pc29->args[0].data.reg.reg != pc25->args[0].data.reg.reg) - return; - - op27 = NULL; - for (i = 0; i < pc29->argCount; i++) { - if (pc29->args[i].kind == PCOp_LABEL) - op27 = &pc29->args[i]; - } - - if (op27) { - preheader21 = loop->preheader; - - path20 = findswitchpath(loop, block26->nextBlock); - if (!path20) - return; - - path2_24 = findswitchpath(loop, op27->data.label.label->block); - if (!path2_24) - return; - - bestpath1 = NULL; - bestpath2 = NULL; - for (pathiter1 = path20; pathiter1; pathiter1 = pathiter1->next) { - for (pathiter2 = path2_24; pathiter2; pathiter2 = pathiter2->next) { - if (pathiter1->block == pathiter2->block) { - bestpath1 = pathiter1; - break; - } - } - if (bestpath1) - break; - bestpath2 = pathiter1; - } - - CError_ASSERT(1192, bestpath2->block); - - if (bestpath2->block->lastPCode && bestpath2->block->lastPCode->op == PC_B) - deletepcode(bestpath2->block->lastPCode); - - while (bestpath1) { - for (scan20 = bestpath1->block->firstPCode; scan20; scan20 = scan20->nextPCode) { - if (scan20->op != PC_B) - appendpcode(bestpath2->block, copypcode(scan20)); - } - bestpath1 = bestpath1->next; - } - - headercopy = appendheadercopy(loop, bestpath2->block, loop->body, block26); - movecmptopreheader(loop, block26, pc25, pc29, op27); - - if (block26->pcodeCount) { - if (path2_24->block->firstPCode) { - pc23 = path2_24->block->firstPCode; - for (scan20 = block26->firstPCode; scan20; scan20 = scan20->nextPCode) { - if (scan20->op != PC_B) - insertpcodebefore(pc23, copypcode(scan20)); - } - } else { - for (scan20 = block26->firstPCode; scan20; scan20 = scan20->nextPCode) { - if (scan20->op != PC_B) - appendpcode(path2_24->block, copypcode(scan20)); - } - } - } - - op23 = NULL; - for (i = 0; i < loop->body->lastPCode->argCount; i++) { - if (loop->body->lastPCode->args[i].kind == PCOp_LABEL) - op23 = &loop->body->lastPCode->args[i]; - } - - CError_ASSERT(1250, op23 != NULL); - - changesuccessor(loop->body, op23->data.label.label->block, path2_24->block); - op23->data.label.label = path2_24->block->labels; - - op23 = NULL; - for (i = 0; i < preheader21->lastPCode->argCount; i++) { - if (preheader21->lastPCode->args[i].kind == PCOp_LABEL) - op23 = &preheader21->lastPCode->args[i]; - } - - CError_ASSERT(1267, op23 != NULL); - - changesuccessor(preheader21, op23->data.label.label->block, loop->body); - op23->data.label.label = loop->body->labels; - - op23 = NULL; - for (i = 0; i < loop->preheader->lastPCode->argCount; i++) { - if (loop->preheader->lastPCode->args[i].kind == PCOp_LABEL) - op23 = &loop->preheader->lastPCode->args[i]; - } - - CError_ASSERT(1284, op23 != NULL); - - changesuccessor(loop->preheader, op23->data.label.label->block, headercopy); - op23->data.label.label = headercopy->labels; - - newloop = lalloc(sizeof(Loop)); - newloop->parent = loop->parent; - newloop->children = NULL; - newloop->nextSibling = loop->nextSibling; - loop->nextSibling = newloop; - newloop->body = loop->body; - newloop->preheader = NULL; - newloop->blocks = NULL; - newloop->basicInductionVars = NULL; - newloop->footer = NULL; - newloop->pc18 = NULL; - newloop->loopWeight = loop->loopWeight; - - bitvectorinitialize(newloop->memberblocks = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); - bitvectorinitialize(newloop->vec24 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); - bitvectorinitialize(newloop->vec28 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); - bitvectorinitialize(newloop->vec2C = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); - - removeblockfromloop(loop, newloop->body); - addblocktoloop(newloop, newloop->body); - - bitvectorsetbit(newloop->body->blockIndex, newloop->vec24); - bitvectorsetbit(newloop->body->blockIndex, newloop->vec2C); - bitvectorsetbit(newloop->body->blockIndex, newloop->vec28); - - for (scanlist = path2_24; scanlist; scanlist = scanlist->next) { - removeblockfromloop(loop, scanlist->block); - addblocktoloop(newloop, scanlist->block); - bitvectorsetbit(scanlist->block->blockIndex, newloop->vec2C); - } - - newloop->preheader = NULL; - insertpreheaderblock(newloop); - analyzeloop(newloop); - - loop->body = headercopy; - - for (scanlist = loop->blocks; scanlist; scanlist = scanlist->next) - bitvectorsetbit(scanlist->block->blockIndex, loop->vec2C); - - bitvectorsetbit(headercopy->blockIndex, loop->vec24); - analyzeloop(loop); - - unswitchedinvariantcode = 1; - } -} - -static void simpleunswitchloops(Loop *loop) { - while (loop) { - if (loop->children) - simpleunswitchloops(loop->children); - else if (!loop->x4F) - simpleunswitchloop(loop); - loop = loop->nextSibling; - } -} - -static void moveinvariantsfromloop(Loop *loop) { - RegUseOrDef *list; - BlockList *blocklist; - PCode *instr; - PCode *nextInstr; - UInt32 *myvec; - UseOrDef *def; - int defID; - int flag; - PCodeBlock *block; - - myvec = oalloc(4 * ((number_of_Defs + 31) >> 5)); - do { - flag = 0; - for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { - block = blocklist->block; - bitvectorcopy(myvec, usedefinfo[block->blockIndex].defvec8, number_of_Defs); - for (instr = block->firstPCode; instr; instr = nextInstr) { - nextInstr = instr->nextPCode; - if (!(instr->flags & fIsBranch) && instr->argCount) { - if ( - !(instr->flags & (fIsCall | fIsPtrOp | fIsVolatile | fSideEffects)) && - isloopinvariant(instr, loop, myvec, 0, 0) && - maymove(instr, loop) - ) { - moveinvariantcomputation(instr, loop); - flag = 1; - } else if (srawi_addze_isloopinvariant(instr, loop, myvec)) { - moveinvariantcomputation(instr, loop); - flag = 1; - } - - for (def = &Defs[defID = instr->defID]; defID < number_of_Defs && def->pcode == instr; def++, defID++) { - if (def->v.kind == PCOp_REGISTER) { - for (list = reg_Defs[def->v.arg][def->v.u.reg]; list; list = list->next) - bitvectorclearbit(list->id, myvec); - } else if (def->v.kind == PCOp_MEMORY) { - if (def->v.arg == PCOpMemory0) { - for (list = findobjectusedef(def->v.u.object)->defs; list; list = list->next) { - if (uniquely_aliases(instr, Defs[list->id].pcode)) - bitvectorclearbit(list->id, myvec); - } - } - } else { - CError_FATAL(1434); - } - - bitvectorsetbit(defID, myvec); - } - } - } - } - } while (flag); -} - -static void moveinvariantsfromloops(Loop *loop) { - while (loop) { - if (loop->children) - moveinvariantsfromloops(loop->children); - moveinvariantsfromloop(loop); - loop = loop->nextSibling; - } -} - -void moveloopinvariantcode(void) { - unswitchedinvariantcode = 0; - movedloopinvariantcode = 0; - if (loopsinflowgraph) { - moveinvariantsfromloops(loopsinflowgraph); - simpleunswitchloops(loopsinflowgraph); - } - freeoheap(); -} diff --git a/compiler_and_linker/unsorted/Coloring.c b/compiler_and_linker/unsorted/Coloring.c deleted file mode 100644 index 8036435..0000000 --- a/compiler_and_linker/unsorted/Coloring.c +++ /dev/null @@ -1,268 +0,0 @@ -#include "compiler/Coloring.h" -#include "compiler/CFunc.h" -#include "compiler/CompilerTools.h" -#include "compiler/InterferenceGraph.h" -#include "compiler/PCode.h" -#include "compiler/PPCError.h" -#include "compiler/Registers.h" -#include "compiler/RegisterInfo.h" -#include "compiler/SpillCode.h" -#include "compiler/StackFrame.h" -#include "compiler/objects.h" - -RegClass coloring_class; -static short used_regs_before_coloring; - -static void markspecialregisters(RegClass rclass) { - ObjectList *list; - Object *object; - VarInfo *vi; - UInt32 i; - - for (i = 0; i < n_real_registers[rclass]; i++) - interferencegraph[i]->x14 = i; - - for (list = arguments; list; list = list->next) { - object = list->object; - vi = Registers_GetVarInfo(object); - if ((vi->flags & VarInfoFlag2) && vi->rclass == rclass) { - interferencegraph[vi->reg]->spillTemporary = object; - if (vi->flags & VarInfoFlag4) { - interferencegraph[vi->reg]->flags |= fPairLow; - interferencegraph[vi->regHi]->flags |= fPairHigh; - interferencegraph[vi->regHi]->spillTemporary = object; - } - } - } - - for (list = locals; list; list = list->next) { - object = list->object; - vi = Registers_GetVarInfo(object); - if ((vi->flags & VarInfoFlag2) && vi->rclass == rclass) { - interferencegraph[vi->reg]->spillTemporary = object; - if (vi->flags & VarInfoFlag4) { - interferencegraph[vi->reg]->flags |= fPairLow; - interferencegraph[vi->regHi]->flags |= fPairHigh; - interferencegraph[vi->regHi]->spillTemporary = object; - } - } - } -} - -static IGNode *simplifygraph(void) { - int availableRegs; - IGNode *spilledNodes; - IGNode *pushedNodes; - IGNode *best; - IGNode *node; - UInt32 i; - UInt32 j; - int flag; - float bestScore; - float score; - - availableRegs = available_registers(coloring_class); - pushedNodes = NULL; - - do { - spilledNodes = NULL; - flag = 0; - for (i = n_real_registers[coloring_class]; i < used_virtual_registers[coloring_class]; i++) { - node = interferencegraph[i]; - if (!(node->flags & (fPushed | fCoalesced))) { - if (node->x12 < availableRegs) { - for (j = 0; j < node->arraySize; j++) - interferencegraph[node->array[j]]->x12--; - node->flags |= fPushed; - node->next = pushedNodes; - pushedNodes = node; - flag = 1; - } else { - node->next = spilledNodes; - spilledNodes = node; - } - } - } - } while (flag); - - if (spilledNodes) - estimatespillcosts(); - - while (spilledNodes) { - best = spilledNodes; - bestScore = (spilledNodes->x10 >= used_regs_before_coloring) ? FLT_MAX : ((float) spilledNodes->spillCost / (float) spilledNodes->x12); - - for (node = spilledNodes->next; node; node = node->next) { - score = (node->x10 >= used_regs_before_coloring) ? FLT_MAX : ((float) node->spillCost / (float) node->x12); - if (score < bestScore) { - best = node; - bestScore = score; - } - } - - for (i = 0; i < best->arraySize; i++) - interferencegraph[best->array[i]]->x12--; - - best->flags |= fPushed; - best->next = pushedNodes; - pushedNodes = best; - - do { - spilledNodes = NULL; - flag = 0; - for (i = n_real_registers[coloring_class]; i < used_virtual_registers[coloring_class]; i++) { - node = interferencegraph[i]; - if (!(node->flags & (fPushed | fCoalesced))) { - if (node->x12 < availableRegs) { - for (j = 0; j < node->arraySize; j++) - interferencegraph[node->array[j]]->x12--; - node->flags |= fPushed; - node->next = pushedNodes; - pushedNodes = node; - flag = 1; - } else { - node->next = spilledNodes; - spilledNodes = node; - } - } - } - } while (flag); - } - - return pushedNodes; -} - -static int colorgraph(IGNode *node) { - UInt32 volatileRegs; - int result; - IGNode *otherNode; - int reg; - UInt32 workingMask; - int i; - short *array; - - result = 1; - - reset_nonvolatile_registers(coloring_class); - volatileRegs = volatile_registers(coloring_class); - - while (node) { - workingMask = volatileRegs; - for (array = node->array, i = 0; i < node->arraySize; i++) { - otherNode = interferencegraph[*(array++)]; - reg = otherNode->x14; - if (reg != -1 && reg < n_real_registers[coloring_class]) - workingMask &= ~(1 << reg); - } - - if (workingMask) { - for (i = 0; i < n_real_registers[coloring_class]; i++) { - if (workingMask & (1 << i)) { - node->x14 = i; - break; - } - } - } else { - reg = obtain_nonvolatile_register(coloring_class); - if (reg != -1) { - volatileRegs |= 1 << (node->x14 = reg); - } else { - node->flags |= fSpilled; - result = 0; - } - } - - node = node->next; - } - - return result; -} - -static void rewritepcode(void) { - PCodeBlock *block; - PCode *instr; - PCodeArg *op; - UInt32 i; - IGNode *node; - int reg; - - for (block = pcbasicblocks; block; block = block->nextBlock) { - for (instr = block->firstPCode; instr; instr = instr->nextPCode) { - op = instr->args; - i = instr->argCount; - while (i--) { - if (PC_OP_IS_ANY_REGISTER(op, coloring_class)) - op->data.reg.reg = interferencegraph[op->data.reg.reg]->x14; - op++; - } - - if ( - (instr->flags & fIsMove) && - (instr->args[1].arg == coloring_class) && - instr->args[1].data.reg.reg == instr->args[0].data.reg.reg - ) - deletepcode(instr); - } - } - - for (i = n_real_registers[coloring_class]; i < used_virtual_registers[coloring_class]; i++) { - node = interferencegraph[i]; - if (node->spillTemporary && !(node->flags & fSpilled)) { - if (node->flags & fCoalesced) { - reg = node->x14; - while (reg >= n_real_registers[coloring_class]) { - reg = interferencegraph[reg]->x14; - if (reg < 0) - break; - } - node->x14 = reg; - } - - if (node->flags & fPairHigh) { - reg = node->x14; - Registers_GetVarInfo(node->spillTemporary)->regHi = reg; - } else { - reg = node->x14; - Registers_GetVarInfo(node->spillTemporary)->reg = reg; - } - } - } -} - -void colorinstructions(Object *proc) { - RegClass rclass; - int flag; - - for (rclass = 0; rclass < RegClassMax; rclass++) { - coloring_class = rclass; - - if (rclass == RegClass_GPR) - check_dynamic_aligned_frame(); - - if (used_virtual_registers[rclass] > n_real_registers[rclass]) { - save_before_coloring_nonvolatile_registers(rclass); - used_regs_before_coloring = used_virtual_registers[rclass]; - if (!available_registers(rclass)) { - PPCError_Error(PPCErrorStr102, register_class_name[rclass]); - return; - } - - flag = 1; - while (flag && used_virtual_registers[rclass] > n_real_registers[rclass]) { - buildinterferencegraph(proc); - markspecialregisters(rclass); - flag = colorgraph(simplifygraph()) ? 0 : 1; - - if (flag) - insertspillcode(); - else - rewritepcode(); - freeoheap(); - } - } - - used_virtual_registers[rclass] = n_real_registers[rclass]; - } - - coloring = 0; -} diff --git a/compiler_and_linker/unsorted/ConstantPropagation.c b/compiler_and_linker/unsorted/ConstantPropagation.c deleted file mode 100644 index 2b40453..0000000 --- a/compiler_and_linker/unsorted/ConstantPropagation.c +++ /dev/null @@ -1,643 +0,0 @@ -#include "compiler/ConstantPropagation.h" -#include "compiler/Alias.h" -#include "compiler/BitVectors.h" -#include "compiler/CompilerTools.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" -#include "compiler/RegisterInfo.h" -#include "compiler/StackFrame.h" -#include "compiler/UseDefChains.h" -#include "compiler/objects.h" - -int propagatedconstants; -static int changed; -static PCode **defininginstruction; -static PCode **vrdefininginstruction; - -static void computedefininginstructions(PCodeBlock *block) { - RegUseOrDef *list; - PCode *instr; - int i; - - for (i = 0; i < used_virtual_registers[RegClass_GPR]; i++) { - instr = NULL; - for (list = reg_Defs[RegClass_GPR][i]; list; list = list->next) { - if (bitvectorgetbit(list->id, usedefinfo[block->blockIndex].defvec8)) { - if (instr == NULL) { - instr = Defs[list->id].pcode; - } else { - instr = NULL; - break; - } - } - } - defininginstruction[i] = instr; - } - - for (i = 0; i < used_virtual_registers[RegClass_VR]; i++) { - instr = NULL; - for (list = reg_Defs[RegClass_VR][i]; list; list = list->next) { - if (bitvectorgetbit(list->id, usedefinfo[block->blockIndex].defvec8)) { - if (instr == NULL) { - instr = Defs[list->id].pcode; - } else { - instr = NULL; - break; - } - } - } - vrdefininginstruction[i] = instr; - } -} - -static PCode *isstackoperand(PCodeArg *op, SInt16 *resultValue, SInt16 addend) { - PCode *instr; - - if ((instr = defininginstruction[op->data.reg.reg]) && instr->op == PC_ADDI) { - if ( - instr->args[2].kind == PCOp_MEMORY && - (instr->args[1].data.reg.reg == _FP_ || instr->args[1].data.reg.reg == _CALLER_SP_) && - instr->args[2].data.mem.obj->datatype == DLOCAL - ) - { - if (can_add_displ_to_local(instr->args[2].data.mem.obj, addend)) { - *resultValue = instr->args[2].data.mem.offset; - return instr; - } else { - return NULL; - } - } else { - return NULL; - } - } else { - return NULL; - } -} - -static int isconstantoperand(PCodeArg *op, SInt16 *resultValue) { - PCode *instr; - - if ( - (instr = defininginstruction[op->data.reg.reg]) && - instr->op == PC_LI && - instr->args[1].kind == PCOp_IMMEDIATE - ) - { - *resultValue = instr->args[1].data.imm.value; - return 1; - } else { - return 0; - } -} - -static int isuint16constantoperand(PCodeArg *op, SInt16 *resultValue) { - PCode *instr; - - if ( - (instr = defininginstruction[op->data.reg.reg]) && - instr->op == PC_LI && - instr->args[1].kind == PCOp_IMMEDIATE && - FITS_IN_USHORT(instr->args[1].data.imm.value) - ) - { - *resultValue = instr->args[1].data.imm.value; - return 1; - } else { - return 0; - } -} - -static int isvectorconstantoperand(PCodeArg *op, SInt16 *resultValue, Opcode *resultNewOp) { - PCode *instr; - - if ( - (instr = vrdefininginstruction[op->data.reg.reg]) && - (instr->op == PC_VSPLTISB || instr->op == PC_VSPLTISH || instr->op == PC_VSPLTISW) && - instr->args[1].kind == PCOp_IMMEDIATE - ) - { - *resultValue = instr->args[1].data.imm.value; - *resultNewOp = instr->op; - return 1; - } else { - return 0; - } -} - -static int isunsignedloadoperand(PCodeArg *op) { - PCode *instr; - - if ((instr = defininginstruction[op->data.reg.reg])) { - if (instr->flags & fIsRead) { - if (instr->op >= PC_LHZ && instr->op <= PC_LHZUX) - return 2; - if (instr->op >= PC_LBZ && instr->op <= PC_LBZUX) - return 1; - } else if (instr->op == PC_RLWINM) { - int var3 = instr->args[3].data.imm.value; - int var4 = instr->args[4].data.imm.value; - if (var4 == 31) { - if (var3 == 24) - return 1; - if (var3 == 16) - return 2; - } - } - } - - return 0; -} - -static int ismaskedoperand(PCodeArg *op, UInt32 *resultMask) { - PCode *instr; - UInt32 mask; - - if ((instr = defininginstruction[op->data.reg.reg]) && instr->op == PC_RLWINM) { - if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) { - mask = - ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFU >> instr->args[3].data.imm.value)) & - ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFU >> (instr->args[4].data.imm.value + 1))); - } else { - mask = - ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFU >> instr->args[3].data.imm.value)) | - ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFU >> (instr->args[4].data.imm.value + 1))); - } - *resultMask = mask; - return 1; - } - - return 0; -} - -static int issignedloadoperand(PCodeArg *op) { - PCode *instr; - - if ((instr = defininginstruction[op->data.reg.reg])) { - if (instr->flags & fIsRead) { - if (instr->op >= PC_LHA && instr->op <= PC_LHAUX) - return 2; - } else if (instr->op == PC_EXTSB) { - return 1; - } else if (instr->op == PC_EXTSH) { - return 2; - } - } - - return 0; -} - -static void propagateconstantstoblock(PCodeBlock *block) { - PCode *instr; - SInt16 immAddend; - SInt16 value1; - SInt16 valueU16; - Opcode newOpcode; - SInt16 value2; - UInt32 mask; - UInt32 mask2; - int loadSize; - PCodeArg *op; - int i; - - for (instr = block->firstPCode; instr; instr = instr->nextPCode) { - switch (instr->op) { - case PC_MR: - if (isconstantoperand(&instr->args[1], &value1)) { - change_opcode(instr, PC_LI); - instr->args[1].kind = PCOp_IMMEDIATE; - instr->args[1].data.imm.value = value1; - instr->args[1].data.imm.obj = NULL; - propagatedconstants = 1; - changed = 1; - } - break; - case PC_VMR: - if (isvectorconstantoperand(&instr->args[1], &value1, &newOpcode)) { - change_opcode(instr, newOpcode); - instr->args[1].kind = PCOp_IMMEDIATE; - instr->args[1].data.imm.value = value1; - instr->args[1].data.imm.obj = NULL; - propagatedconstants = 1; - changed = 1; - } - break; - case PC_RLWINM: - if ( - !(PCODE_FLAG_SET_F(instr) & fRecordBit) && - instr->args[2].data.imm.value == 0 && - instr->args[4].data.imm.value == 31 - ) - { - if (isconstantoperand(&instr->args[1], &value1)) { - if ( - (instr->args[3].data.imm.value == 16 && value1 == (value1 & 0x7FFF)) || - (instr->args[3].data.imm.value == 24 && value1 == (value1 & 0xFF)) - ) - { - change_opcode(instr, PC_LI); - instr->args[1].kind = PCOp_IMMEDIATE; - instr->args[1].data.imm.value = value1; - instr->args[1].data.imm.obj = NULL; - change_num_operands(instr, 2); - propagatedconstants = 1; - changed = 1; - break; - } - } - - loadSize = isunsignedloadoperand(&instr->args[1]); - if ( - (loadSize == 2 && instr->args[3].data.imm.value <= 16) || - (loadSize == 1 && instr->args[3].data.imm.value <= 24) - ) - { - change_opcode(instr, PC_MR); - change_num_operands(instr, 2); - propagatedconstants = 1; - changed = 1; - break; - } - - if (ismaskedoperand(&instr->args[1], &mask)) { - if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) { - mask2 = - ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFU >> instr->args[3].data.imm.value)) & - ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFU >> (instr->args[4].data.imm.value + 1))); - } else { - mask2 = - ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFU >> instr->args[3].data.imm.value)) | - ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFU >> (instr->args[4].data.imm.value + 1))); - } - if (mask == (mask & mask2)) { - change_opcode(instr, PC_MR); - change_num_operands(instr, 2); - propagatedconstants = 1; - changed = 1; - } - } - } - break; - - case PC_EXTSH: - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - break; - - if (isconstantoperand(&instr->args[1], &value1)) { - change_opcode(instr, PC_LI); - instr->args[1].kind = PCOp_IMMEDIATE; - instr->args[1].data.imm.value = value1; - instr->args[1].data.imm.obj = NULL; - change_num_operands(instr, 2); - propagatedconstants = 1; - changed = 1; - break; - } - - loadSize = issignedloadoperand(&instr->args[1]); - if (loadSize == 1 || loadSize == 2) { - change_opcode(instr, PC_MR); - change_num_operands(instr, 2); - propagatedconstants = 1; - changed = 1; - } - break; - - case PC_EXTSB: - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - break; - - if ( - isconstantoperand(&instr->args[1], &value1) && - value1 >= -128 && - value1 <= 127 - ) - { - change_opcode(instr, PC_LI); - instr->args[1].kind = PCOp_IMMEDIATE; - instr->args[1].data.imm.value = value1; - instr->args[1].data.imm.obj = NULL; - change_num_operands(instr, 2); - propagatedconstants = 1; - changed = 1; - break; - } - - loadSize = issignedloadoperand(&instr->args[1]); - if (loadSize == 1) { - change_opcode(instr, PC_MR); - change_num_operands(instr, 2); - propagatedconstants = 1; - changed = 1; - } - break; - - case PC_ADDI: - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - break; - - immAddend = instr->args[2].data.imm.value; - if ( - isconstantoperand(&instr->args[1], &value1) && - FITS_IN_SHORT(immAddend + value1) - ) - { - change_opcode(instr, PC_LI); - instr->args[1].kind = PCOp_IMMEDIATE; - instr->args[1].data.imm.value = immAddend + value1; - instr->args[1].data.imm.obj = NULL; - change_num_operands(instr, 2); - propagatedconstants = 1; - changed = 1; - } - break; - - case PC_ADD: - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - break; - - if (isconstantoperand(&instr->args[2], &value1)) { - if (value1 == 0) { - change_opcode(instr, PC_MR); - change_num_operands(instr, 2); - } else { - change_opcode(instr, PC_ADDI); - instr->args[2].kind = PCOp_IMMEDIATE; - instr->args[2].data.imm.value = value1; - instr->args[2].data.imm.obj = NULL; - } - propagatedconstants = 1; - changed = 1; - immAddend = value1; - } - - if (isconstantoperand(&instr->args[1], &value1)) { - if (instr->op == PC_ADDI || instr->op == PC_MR) { - if (FITS_IN_SHORT(immAddend + value1)) { - change_opcode(instr, PC_LI); - instr->args[1].kind = PCOp_IMMEDIATE; - instr->args[1].data.imm.value = immAddend + value1; - instr->args[1].data.imm.obj = NULL; - change_num_operands(instr, 2); - propagatedconstants = 1; - changed = 1; - } - } else { - instr->args[1] = instr->args[2]; - if (value1 == 0) { - change_opcode(instr, PC_MR); - change_num_operands(instr, 2); - } else { - change_opcode(instr, PC_ADDI); - instr->args[2].kind = PCOp_IMMEDIATE; - instr->args[2].data.imm.value = value1; - instr->args[2].data.imm.obj = NULL; - } - propagatedconstants = 1; - changed = 1; - } - } - - if (changed) { - if (instr->op == PC_MR) { - PCode *stackInstr; - if ((stackInstr = isstackoperand(&instr->args[1], &value1, 0))) { - change_opcode(instr, PC_ADDI); - instr->flags = stackInstr->flags; - instr->args[1] = stackInstr->args[1]; - instr->args[2] = stackInstr->args[2]; - change_num_operands(instr, 3); - propagatedconstants = 1; - changed = 1; - } - } else if (instr->op == PC_ADDI && instr->args[2].kind == PCOp_IMMEDIATE) { - PCode *stackInstr; - SInt16 addend = instr->args[2].data.imm.value; - if ((stackInstr = isstackoperand(&instr->args[1], &value1, addend))) { - change_opcode(instr, PC_ADDI); - instr->flags = stackInstr->flags; - instr->args[1] = stackInstr->args[1]; - instr->args[2] = stackInstr->args[2]; - instr->args[2].data.imm.value = value1 + addend; - if (instr->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) - instr->alias = make_alias(instr->args[2].data.imm.obj, instr->args[2].data.imm.value, 1); - propagatedconstants = 1; - changed = 1; - } - } - } - break; - - case PC_OR: - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - break; - - value1 = 0; - immAddend = 0; - if (isconstantoperand(&instr->args[2], &value1)) { - if (isuint16constantoperand(&instr->args[2], &valueU16)) { - if (valueU16 != 0) { - change_opcode(instr, PC_ORI); - instr->args[2].kind = PCOp_IMMEDIATE; - instr->args[2].data.imm.value = valueU16; - instr->args[2].data.imm.obj = NULL; - propagatedconstants = 1; - changed = 1; - } else { - change_opcode(instr, PC_MR); - change_num_operands(instr, 2); - propagatedconstants = 1; - changed = 1; - } - value1 = valueU16; - } else if (value1 == 0) { - change_opcode(instr, PC_MR); - change_num_operands(instr, 2); - propagatedconstants = 1; - changed = 1; - } - immAddend = value1; - } - - if (isconstantoperand(&instr->args[1], &value1)) { - if (instr->op == PC_ORI || instr->op == PC_MR) { - change_opcode(instr, PC_LI); - instr->args[1].kind = PCOp_IMMEDIATE; - instr->args[1].data.imm.value = immAddend | value1; - instr->args[1].data.imm.obj = NULL; - change_num_operands(instr, 2); - propagatedconstants = 1; - changed = 1; - } else if (isuint16constantoperand(&instr->args[1], &valueU16)) { - if (valueU16 != 0) { - change_opcode(instr, PC_ORI); - instr->args[1] = instr->args[2]; - instr->args[2].kind = PCOp_IMMEDIATE; - instr->args[2].data.imm.value = valueU16; - instr->args[2].data.imm.obj = NULL; - propagatedconstants = 1; - changed = 1; - } else { - change_opcode(instr, PC_MR); - instr->args[1] = instr->args[2]; - change_num_operands(instr, 2); - propagatedconstants = 1; - changed = 1; - } - } else if (value1 == 0) { - change_opcode(instr, PC_MR); - instr->args[1] = instr->args[2]; - change_num_operands(instr, 2); - propagatedconstants = 1; - changed = 1; - } - } - break; - - case PC_SUBF: - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - break; - - if (isconstantoperand(&instr->args[1], &value1) && FITS_IN_SHORT(-value1)) { - if (isconstantoperand(&instr->args[2], &value2) && FITS_IN_SHORT(value2 - value1)) { - change_opcode(instr, PC_LI); - instr->args[1].kind = PCOp_IMMEDIATE; - instr->args[1].data.imm.value = value2 - value1; - instr->args[1].data.imm.obj = NULL; - change_num_operands(instr, 2); - } else if (value1 == 0) { - change_opcode(instr, PC_MR); - instr->args[1] = instr->args[2]; - change_num_operands(instr, 2); - } else { - change_opcode(instr, PC_ADDI); - instr->args[1] = instr->args[2]; - instr->args[2].kind = PCOp_IMMEDIATE; - instr->args[2].data.imm.value = -value1; - instr->args[2].data.imm.obj = NULL; - } - propagatedconstants = 1; - changed = 1; - value2 = value1; - } else if (isconstantoperand(&instr->args[2], &value1) && FITS_IN_SHORT(-value1)) { - if (value1 == 0) { - change_opcode(instr, PC_NEG); - change_num_operands(instr, 2); - } else { - instr->flags = opcodeinfo[PC_SUBFIC].flags | (instr->flags & ~opcodeinfo[PC_SUBF].flags); - change_opcode(instr, PC_SUBFIC); - instr->args[2].kind = PCOp_IMMEDIATE; - instr->args[2].data.imm.value = value1; - instr->args[2].data.imm.obj = NULL; - instr->args[3].kind = PCOp_REGISTER; - instr->args[3].arg = RegClass_SPR; - instr->args[3].data.reg.reg = 0; - instr->args[3].data.reg.effect = EffectWrite; - change_num_operands(instr, 4); - } - propagatedconstants = 1; - changed = 1; - } - - break; - - case PC_LBZ: - case PC_LHZ: - case PC_LHA: - case PC_LWZ: - case PC_STB: - case PC_STH: - case PC_STW: - case PC_LFS: - case PC_LFD: - case PC_STFS: - case PC_STFD: - if (instr->args[2].kind == PCOp_IMMEDIATE) { - PCode *stackInstr; - SInt16 addend = instr->args[2].data.imm.value; - - if ((stackInstr = isstackoperand(&instr->args[1], &value1, addend))) { - instr->args[1] = stackInstr->args[1]; - instr->args[2] = stackInstr->args[2]; - instr->args[2].data.imm.value = value1 + addend; - if (instr->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) - instr->alias = make_alias(instr->args[2].data.imm.obj, instr->args[2].data.imm.value, - nbytes_loaded_or_stored_by(instr)); - propagatedconstants = 1; - changed = 1; - } - } - break; - - case PC_LBZX: - case PC_LHZX: - case PC_LHAX: - case PC_LWZX: - case PC_STBX: - case PC_STHX: - case PC_STWX: - case PC_LFSX: - case PC_LFDX: - case PC_STFSX: - case PC_STFDX: - if (isconstantoperand(&instr->args[2], &value1)) { - instr->op -= 2; - instr->args[2].kind = PCOp_IMMEDIATE; - instr->args[2].data.imm.value = value1; - instr->args[2].data.imm.obj = NULL; - propagatedconstants = 1; - changed = 1; - } else if (isconstantoperand(&instr->args[1], &value1)) { - instr->op -= 2; - instr->args[1] = instr->args[2]; - instr->args[2].kind = PCOp_IMMEDIATE; - instr->args[2].data.imm.value = value1; - instr->args[2].data.imm.obj = NULL; - propagatedconstants = 1; - changed = 1; - } - - break; - } - - for (i = 0, op = instr->args; i < instr->argCount; i++, op++) { - if ( - op->kind == PCOp_REGISTER && - op->arg == RegClass_GPR && - (op->data.reg.effect & EffectWrite) - ) - { - defininginstruction[op->data.reg.reg] = instr; - } - else if ( - op->kind == PCOp_REGISTER && - op->arg == RegClass_VR && - (op->data.reg.effect & EffectWrite) - ) - { - vrdefininginstruction[op->data.reg.reg] = instr; - } - } - } -} - -void propagateconstants(void) { - PCodeBlock *block; - int i; - - propagatedconstants = 0; - computeusedefchains(0); - defininginstruction = galloc(sizeof(PCode *) * used_virtual_registers[RegClass_GPR]); - vrdefininginstruction = galloc(sizeof(PCode *) * used_virtual_registers[RegClass_VR]); - - do { - changed = 0; - for (i = 0; i < pcblockcount; i++) { - if ((block = depthfirstordering[i])) { - computedefininginstructions(block); - propagateconstantstoblock(block); - } - } - } while (changed); - - freeoheap(); -} diff --git a/compiler_and_linker/unsorted/DumpIR.c b/compiler_and_linker/unsorted/DumpIR.c new file mode 100644 index 0000000..5f6eea4 --- /dev/null +++ b/compiler_and_linker/unsorted/DumpIR.c @@ -0,0 +1,729 @@ +#include "compiler/DumpIR.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CMachine.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/Exceptions.h" +#include "compiler/Switch.h" +#include "compiler/enode.h" +#include "compiler/objects.h" +#include "compiler/types.h" + +static FILE *outfile; + +// forward decls +static void spell(Type *type, char *buf); + +static void WritePString(FILE *file, char *str, int len) { + while (len--) { + switch (*str) { + case 0: + fputs("\\x00", file); + break; + case 7: + fputs("\\a", file); + break; + case 8: + fputs("\\b", file); + break; + case 12: + fputs("\\f", file); + break; + case 10: + fputs("\\n", file); + break; + case 13: + fputs("\\r", file); + break; + case 9: + fputs("\\t", file); + break; + case 11: + fputs("\\v", file); + break; + case '"': + case '\'': + case '?': + case '\\': + fputc('\\', file); + default: + fputc(*str, file); + break; + } + str++; + } +} + +static void WriteCString(FILE *file, char *str) { + WritePString(file, str, strlen(str)); +} + +static void StaticSetupDumpIR(void) { +} + +void SetupDumpIR(void) { + // unknown args + StaticSetupDumpIR(); +} + +void CleanupDumpIR(void) { +#ifdef CW_ENABLE_PCODE_DEBUG + // this code is not based on the original as we don't have it + if (outfile) { + fclose(outfile); + outfile = NULL; + } +#endif +} + +void DumpIR(Statement *statements, Object *func) { +#ifdef CW_ENABLE_PCODE_DEBUG + // this code is not based on the original as we don't have it + if (copts.debuglisting) { + if (!outfile) + outfile = fopen("irdump.txt", "a"); + + fputs("--- BEGIN IR DUMP ---\r", outfile); + while (statements) { + switch (statements->type) { + case ST_NOP: + fputs("ST_NOP\r", outfile); + break; + case ST_LABEL: + fputs("ST_LABEL\r", outfile); + break; + case ST_GOTO: + fputs("ST_GOTO\r", outfile); + break; + case ST_EXPRESSION: + fputs("ST_EXPRESSION\r", outfile); + DumpExpression(statements->expr, 1); + break; + case ST_SWITCH: + fputs("ST_SWITCH\r", outfile); + DumpExpression(statements->expr, 1); + break; + case ST_IFGOTO: + fputs("ST_IFGOTO\r", outfile); + DumpExpression(statements->expr, 1); + break; + case ST_IFNGOTO: + fputs("ST_IFNGOTO\r", outfile); + DumpExpression(statements->expr, 1); + break; + case ST_RETURN: + fputs("ST_RETURN\r", outfile); + if (statements->expr) + DumpExpression(statements->expr, 1); + break; + case ST_OVF: + fputs("ST_OVF\r", outfile); + break; + case ST_EXIT: + fputs("ST_EXIT\r", outfile); + break; + case ST_ENTRY: + fputs("ST_ENTRY\r", outfile); + break; + case ST_BEGINCATCH: + fputs("ST_BEGINCATCH\r", outfile); + break; + case ST_ENDCATCH: + fputs("ST_ENDCATCH\r", outfile); + break; + case ST_ENDCATCHDTOR: + fputs("ST_ENDCATCHDTOR\r", outfile); + break; + case ST_GOTOEXPR: + fputs("ST_GOTOEXPR\r", outfile); + break; + case ST_ASM: + fputs("ST_ASM\r", outfile); + break; + case ST_BEGINLOOP: + fputs("ST_BEGINLOOP\r", outfile); + break; + case ST_ENDLOOP: + fputs("ST_ENDLOOP\r", outfile); + break; + } + statements = statements->next; + } + fputs("--- END IR DUMP ---\r", outfile); + fflush(outfile); + } +#endif +} + +void DumpExpression(ENode *expr, int indent) { + static int bt; + static int i; + static char *nodenames[] = { + "EPOSTINC", + "EPOSTDEC", + "EPREINC", + "EPREDEC", + "EINDIRECT", + "EMONMIN", + "EBINNOT", + "ELOGNOT", + "EFORCELOAD", + "EMUL", + "EMULV", + "EDIV", + "EMODULO", + "EADDV", + "ESUBV", + "EADD", + "ESUB", + "ESHL", + "ESHR", + "ELESS", + "EGREATER", + "ELESSEQU", + "EGREATEREQU", + "EEQU", + "ENOTEQU", + "EAND", + "EXOR", + "EOR", + "ELAND", + "ELOR", + "EASS", + "EMULASS", + "EDIVASS", + "EMODASS", + "EADDASS", + "ESUBASS", + "ESHLASS", + "ESHRASS", + "EANDASS", + "EXORASS", + "EORASS", + "ECOMMA", + "EPMODULO", + "EROTL", + "EROTR", + "EBCLR", + "EBTST", + "EBSET", + "ETYPCON", + "EBITFIELD", + "EINTCONST", + "EFLOATCONST", + "ESTRINGCONST", + "ECOND", + "EFUNCCALL", + "EFUNCCALLP", + "EOBJREF", + "EMFPOINTER", + "ENULLCHECK", + "EPRECOMP", + "ETEMP", + "EARGOBJ", + "ELOCOBJ", + "ELABEL", + "ESETCONST", + "ENEWEXCEPTION", + "ENEWEXCEPTIONARRAY", + "EINITTRYCATCH", + "EOBJLIST", + "EMEMBER", + "ETEMPLDEP", + "EINSTRUCTION", + "EDEFINE", + "EREUSE", + "EASSBLK", + "EVECTOR128CONST", + "ECONDASS", + NULL + }; + char buf[64]; + ENodeList *list; + + while (1) { + for (i = 0; i < indent; i++) + fputc('\t', outfile); + + if (expr->flags) + fprintf(outfile, "%s {%02X}", nodenames[expr->type], expr->flags); + else + fprintf(outfile, "%s", nodenames[expr->type]); + + switch (expr->type) { + case EINTCONST: + if (expr->rtype->size > 4) { + fprintf(outfile, + "[0x%.8" PRIX32 "%.8" PRIX32 "]", + expr->data.intval.hi, expr->data.intval.lo); + } else { + fprintf(outfile, + "[%" PRId32 "]", + expr->data.intval.lo); + } + DumpType(expr->rtype); + fprintf(outfile, "\r"); + return; + + case EFLOATCONST: + CMach_PrintFloat(buf, expr->data.floatval); + fprintf(outfile, "[%s]", buf); + DumpType(expr->rtype); + fprintf(outfile, "\r"); + return; + + case ESTRINGCONST: + if (expr->data.string.ispascal) { + fputs("[\"", outfile); + WritePString(outfile, expr->data.string.data, expr->data.string.size); + fputs("\"]", outfile); + } else { + fputs("[\"", outfile); + WriteCString(outfile, expr->data.string.data); + fputs("\"]", outfile); + } + DumpType(expr->rtype); + fprintf(outfile, "\r"); + return; + + case EVECTOR128CONST: + fprintf(outfile, + "[0x%.8" PRIX32 "%.8" PRIX32 "%.8" PRIX32 "%.8" PRIX32 "]", + expr->data.vector128val.ul[0], + expr->data.vector128val.ul[1], + expr->data.vector128val.ul[2], + expr->data.vector128val.ul[3]); + DumpType(expr->rtype); + fprintf(outfile, "\r"); + return; + + case ECOND: + case ECONDASS: + DumpType(expr->rtype); + fprintf(outfile, "\r"); + DumpExpression(expr->data.cond.cond, indent + 1); + DumpExpression(expr->data.cond.expr1, indent + 1); + expr = expr->data.cond.expr2; + indent++; + break; + + case EFUNCCALL: + case EFUNCCALLP: + DumpType(expr->rtype); + fprintf(outfile, "\r"); + DumpExpression(expr->data.funccall.funcref, indent + 1); + for (list = expr->data.funccall.args; list; list = list->next) + DumpExpression(list->node, indent + 1); + return; + + case EOBJREF: + switch (expr->data.objref->datatype) { + case DFUNC: + fprintf(outfile, "[%s{PR}]", CMangler_GetLinkName(expr->data.objref)->name); + break; + case DDATA: + fprintf(outfile, "[%s{RW}]", CMangler_GetLinkName(expr->data.objref)->name); + break; + case DNONLAZYPTR: + fprintf(outfile, "[%s{NL}]", CMangler_GetLinkName(expr->data.objref)->name); + break; + default: + fprintf(outfile, "[%s]", expr->data.objref->name->name); + break; + } + DumpType(expr->rtype); + fprintf(outfile, "\r"); + return; + + ENODE_CASE_DIADIC_1: + case ELAND: + case ELOR: + ENODE_CASE_ASSIGN: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBTST: + DumpType(expr->rtype); + fprintf(outfile, "\r"); + DumpExpression(expr->data.diadic.left, indent + 1); + expr = expr->data.diadic.right; + indent++; + break; + + ENODE_CASE_MONADIC: + DumpType(expr->rtype); + fprintf(outfile, "\r"); + expr = expr->data.monadic; + indent++; + break; + + case EMFPOINTER: + DumpType(expr->rtype); + fprintf(outfile, "\r"); + DumpExpression(expr->data.mfpointer.accessnode, indent + 1); + expr = expr->data.mfpointer.mfpointer; + indent++; + break; + + case ENULLCHECK: + fprintf(outfile, " unique [%" PRId32 "]", expr->data.nullcheck.precompid); + DumpType(expr->rtype); + fprintf(outfile, "\r"); + DumpExpression(expr->data.nullcheck.nullcheckexpr, indent + 1); + expr = expr->data.nullcheck.condexpr; + indent++; + break; + + case EPRECOMP: + fprintf(outfile, " unique [%" PRId32 "]", expr->data.precompid); + DumpType(expr->rtype); + fprintf(outfile, "\r"); + return; + + case ELABEL: + fprintf(outfile, "[%s]", expr->data.label->uniquename->name); + DumpType(expr->rtype); + fprintf(outfile, "\r"); + return; + + case ETEMP: + DumpType(expr->data.temp.type); + fprintf(outfile, "\r"); + return; + + case EINITTRYCATCH: + DumpType(expr->rtype); + fprintf(outfile, "\r"); + if (expr->data.itc.initexpr) + DumpExpression(expr->data.itc.initexpr, indent + 1); + if (expr->data.itc.tryexpr) + DumpExpression(expr->data.itc.tryexpr, indent + 1); + if (expr->data.itc.catchexpr) + DumpExpression(expr->data.itc.catchexpr, indent + 1); + if (expr->data.itc.result) + DumpExpression(expr->data.itc.result, indent + 1); + return; + + case EDEFINE: + fprintf(outfile, "[%.8" PRIX32 "]", expr); + DumpType(expr->rtype); + fputs("\r", outfile); + expr = expr->data.monadic; + indent++; + break; + + case EREUSE: + fprintf(outfile, "[%.8" PRIX32 "]", expr->data.monadic); + DumpType(expr->rtype); + fputs("\r", outfile); + return; + + default: + return; + } + } +} + +void DumpSwitch(SwitchInfo *info) { + char buf[32]; + SwitchCase *cs; + + for (cs = info->cases; cs; cs = cs->next) { + CInt64_PrintDec(buf, cs->min); + CInt64_PrintDec(buf, cs->min); + fprintf(outfile, "\t\t%11s: %s\r", buf, cs->label->uniquename->name); + } + + fprintf(outfile, "\t\t default: %s\r", info->defaultlabel->uniquename->name); +} + +void DumpType(Type *type) { + char buf[256]; + + spell(type, buf); + fprintf(outfile, " (%s)", buf); +} + +static void spell(Type *type, char *buf) { + char mybuf[256]; + char mybuf2[256]; + + switch (type->type) { + case TYPEVOID: + strcpy(buf, "void"); + break; + case TYPEINT: + switch (TYPE_INTEGRAL(type)->integral) { + case IT_BOOL: + strcpy(buf, "bool"); + break; + case IT_CHAR: + strcpy(buf, "char"); + break; + case IT_WCHAR_T: + strcpy(buf, "wchar_t"); + break; + case IT_SCHAR: + strcpy(buf, "signed char"); + break; + case IT_UCHAR: + strcpy(buf, "unsigned char"); + break; + case IT_SHORT: + strcpy(buf, "short"); + break; + case IT_USHORT: + strcpy(buf, "unsigned short"); + break; + case IT_INT: + strcpy(buf, "int"); + break; + case IT_UINT: + strcpy(buf, "unsigned int"); + break; + case IT_LONG: + strcpy(buf, "long"); + break; + case IT_ULONG: + strcpy(buf, "unsigned long"); + break; + case IT_LONGLONG: + strcpy(buf, "long long"); + break; + case IT_ULONGLONG: + strcpy(buf, "unsigned long long"); + break; + } + break; + case TYPEFLOAT: + switch (TYPE_INTEGRAL(type)->integral) { + case IT_FLOAT: + strcpy(buf, "float"); + break; + case IT_SHORTDOUBLE: + strcpy(buf, "short double"); + break; + case IT_DOUBLE: + strcpy(buf, "double"); + break; + case IT_LONGDOUBLE: + strcpy(buf, "long double"); + break; + } + break; + case TYPEENUM: + strcpy(buf, "enum "); + if (TYPE_ENUM(type)->enumname) + strcat(buf, TYPE_ENUM(type)->enumname->name); + break; + case TYPESTRUCT: + if (IS_TYPESTRUCT_VECTOR(TYPE_STRUCT(type))) { + switch (TYPE_STRUCT(type)->stype) { + case STRUCT_VECTOR_UCHAR: + strcpy(buf, "vector unsigned char "); + break; + case STRUCT_VECTOR_SCHAR: + strcpy(buf, "vector signed char "); + break; + case STRUCT_VECTOR_BCHAR: + strcpy(buf, "vector bool char "); + break; + case STRUCT_VECTOR_USHORT: + strcpy(buf, "vector unsigned short "); + break; + case STRUCT_VECTOR_SSHORT: + strcpy(buf, "vector signed short "); + break; + case STRUCT_VECTOR_BSHORT: + strcpy(buf, "vector bool short "); + break; + case STRUCT_VECTOR_UINT: + strcpy(buf, "vector unsigned int "); + break; + case STRUCT_VECTOR_SINT: + strcpy(buf, "vector signed int "); + break; + case STRUCT_VECTOR_BINT: + strcpy(buf, "vector bool int "); + break; + case STRUCT_VECTOR_FLOAT: + strcpy(buf, "vector float "); + break; + case STRUCT_VECTOR_PIXEL: + strcpy(buf, "vector pixel "); + break; + } + } else { + strcpy(buf, "struct "); + if (TYPE_STRUCT(type)->name) + strcat(buf, TYPE_STRUCT(type)->name->name); + } + break; + case TYPECLASS: + strcpy(buf, "class "); + if (TYPE_CLASS(type)->classname) + strcat(buf, TYPE_CLASS(type)->classname->name); + break; + case TYPEFUNC: + spell(TYPE_FUNC(type)->functype, mybuf); + strcpy(buf, "freturns("); + strcat(buf, mybuf); + strcat(buf, ")"); + break; + case TYPEBITFIELD: + spell(TYPE_BITFIELD(type)->bitfieldtype, mybuf); + sprintf(buf, + "bitfield(%s){%d:%d}", + mybuf, + TYPE_BITFIELD(type)->offset, + TYPE_BITFIELD(type)->bitlength); + break; + case TYPELABEL: + strcpy(buf, "label"); + break; + case TYPEPOINTER: + spell(TPTR_TARGET(type), mybuf); + strcpy(buf, "pointer("); + strcat(buf, mybuf); + strcat(buf, ")"); + break; + case TYPEARRAY: + spell(TPTR_TARGET(type), mybuf); + strcpy(buf, "array("); + strcat(buf, mybuf); + strcat(buf, ")"); + break; + case TYPEMEMBERPOINTER: + spell(TYPE_MEMBER_POINTER(type)->ty2, mybuf); + spell(TYPE_MEMBER_POINTER(type)->ty1, mybuf2); + strcpy(buf, "memberpointer("); + strcat(buf, mybuf); + strcat(buf, ","); + strcat(buf, mybuf2); + strcat(buf, ")"); + break; + } +} + +void DumpStack(ExceptionAction *act) { + while (act) { + fprintf(outfile, "\t\t:"); + switch (act->type) { + case EAT_DESTROYLOCAL: + fprintf(outfile, + "EAT_DESTROYLOCAL %s(&%s)%s", + CMangler_GetLinkName(act->data.destroy_local.dtor)->name, + act->data.destroy_local.local->name->name, + "\r"); + break; + case EAT_DESTROYLOCALCOND: + fprintf(outfile, + "EAT_DESTROYLOCALCOND%s", + "\r"); + break; + case EAT_DESTROYLOCALOFFSET: + fprintf(outfile, + "EAT_DESTROYLOCALOFFSET %s(&%s+%" PRId32 ")%s", + CMangler_GetLinkName(act->data.destroy_local_offset.dtor)->name, + act->data.destroy_local_offset.local->name->name, + act->data.destroy_local_offset.offset, + "\r"); + break; + case EAT_DESTROYLOCALPOINTER: + fprintf(outfile, + "EAT_DESTROYLOCALPOINTER%s", + "\r"); + break; + case EAT_DESTROYLOCALARRAY: + fprintf(outfile, + "EAT_DESTROYLOCALARRAY%s", + "\r"); + break; + case EAT_DESTROYBASE: + fprintf(outfile, + "EAT_DESTROYBASE %s(this+%" PRId32 ")%s", + CMangler_GetLinkName(act->data.destroy_base.dtor)->name, + act->data.destroy_base.offset, + "\r"); + break; + case EAT_DESTROYMEMBER: + fprintf(outfile, + "EAT_DESTROYMEMBER %s(%s+%" PRId32 ")%s", + CMangler_GetLinkName(act->data.destroy_member.dtor)->name, + act->data.destroy_member.objectptr->name->name, + act->data.destroy_member.offset, + "\r"); + break; + case EAT_DESTROYMEMBERCOND: + fprintf(outfile, + "EAT_DESTROYMEMBERCOND if(%s) %s(this+%" PRId32 ")%s", + act->data.destroy_member_cond.cond->name->name, + CMangler_GetLinkName(act->data.destroy_member_cond.dtor)->name, + act->data.destroy_member_cond.offset, + "\r"); + break; + case EAT_DESTROYMEMBERARRAY: + fprintf(outfile, + "EAT_DESTROYMEMBERARRAY %s(this+%" PRId32 ")[%" PRId32 "] size: %" PRId32 "%s", + CMangler_GetLinkName(act->data.destroy_member_array.dtor)->name, + act->data.destroy_member_array.offset, + act->data.destroy_member_array.elements, + act->data.destroy_member_array.element_size, + "\r"); + break; + case EAT_DELETEPOINTER: + fprintf(outfile, + "EAT_DELETEPOINTER(%s)%s", + act->data.delete_pointer.pointerobject->name->name, + "\r"); + break; + case EAT_DELETELOCALPOINTER: + fprintf(outfile, + "EAT_DELETELOCALPOINTER(%s)%s", + act->data.delete_pointer.pointerobject->name->name, + "\r"); + break; + case EAT_DELETEPOINTERCOND: + fprintf(outfile, + "EAT_DELETEPOINTERCOND if (%s)(%s)%s", + act->data.delete_pointer_cond.cond->name->name, + act->data.delete_pointer_cond.pointerobject->name->name, + "\r"); + break; + case EAT_CATCHBLOCK: + fprintf(outfile, "EAT_CATCHBLOCK "); + if (act->data.catch_block.catch_type) { + if (act->data.catch_block.catch_object) + fprintf(outfile, "[%s]", act->data.catch_block.catch_object->name->name); + else + fprintf(outfile, "[]"); + DumpType(act->data.catch_block.catch_type); + } else { + fprintf(outfile, "[...] "); + } + fprintf(outfile, + " Label: %s%s", + act->data.catch_block.catch_label->uniquename->name, + "\r"); + break; + case EAT_SPECIFICATION: + fprintf(outfile, + "EAT_SPECIFICATION%s", + "\r"); + break; + case EAT_ACTIVECATCHBLOCK: + fprintf(outfile, + "EAT_ACTIVECATCHBLOCK%s", + "\r"); + break; + case EAT_TERMINATE: + fprintf(outfile, + "EAT_TERMINATE%s", + "\r"); + break; + } + act = act->prev; + } +} diff --git a/compiler_and_linker/unsorted/Exceptions.c b/compiler_and_linker/unsorted/Exceptions.c deleted file mode 100644 index 14627cf..0000000 --- a/compiler_and_linker/unsorted/Exceptions.c +++ /dev/null @@ -1,857 +0,0 @@ -#include "compiler/Exceptions.h" -#include "compiler/CError.h" -#include "compiler/CException.h" -#include "compiler/CInit.h" -#include "compiler/CFunc.h" -#include "compiler/CParser.h" -#include "compiler/CompilerTools.h" -#include "compiler/ObjGenMachO.h" -#include "compiler/PCode.h" -#include "compiler/PCodeUtilities.h" -#include "compiler/RegisterInfo.h" -#include "compiler/StackFrame.h" -#include "compiler/objects.h" - -static PCAction *pc_actions; -static PCAction *last_pc_action; -EANode *DAG[EAT_NACTIONS]; -static GList exceptmodule; -static OLinkList *except_refs; -static OLinkList *last_except_ref; - -static EANode *makeEAnode(ExceptionAction *ea) { - EANode *prev; - EANode *node; - - for (node = DAG[ea->type]; node; node = node->dagListNext) { - if (node->action == ea) - return node; - } - - if (ea->prev) - prev = makeEAnode(ea->prev); - else - prev = NULL; - - for (node = DAG[ea->type]; node; node = node->dagListNext) { - if (node->prev == prev && CExcept_ActionCompare(node->action, ea)) - return node; - } - - node = lalloc(sizeof(EANode)); - node->prev = prev; - node->action = ea; - node->count = 0; - node->xE = 0; - - node->dagListNext = DAG[ea->type]; - DAG[ea->type] = node; - - if (prev) - prev->count++; - return node; -} - -static void addrelocation(Object *obj, SInt32 offset) { - OLinkList *ref; - - ref = lalloc(sizeof(OLinkList)); - ref->next = NULL; - ref->obj = obj; - ref->offset = offset; - ref->somevalue = 0; - if (except_refs) - last_except_ref->next = ref; - else - except_refs = ref; - last_except_ref = ref; -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct AABC { - UInt8 a; - UInt8 b; - UInt16 c; - UInt32 d; -} AABC; - -typedef struct AACC { - UInt8 a; - UInt8 b; - UInt32 c; - UInt32 d; -} AACC; - -typedef struct AABBC { - UInt8 a; - UInt8 b; - UInt16 c; - UInt16 d; - UInt32 e; -} AABBC; - -typedef struct AABCC { - UInt8 a; - UInt8 b; - UInt16 c; - UInt32 d; - UInt32 e; -} AABCC; - -typedef struct AACCC { - UInt8 a; - UInt8 b; - UInt32 c; - UInt32 d; - UInt32 e; -} AACCC; - -typedef struct AABBBC { - UInt8 a; - UInt8 b; - UInt16 c; - UInt16 d; - UInt16 e; - UInt32 f; -} AABBBC; - -typedef struct AABBCC { - UInt8 a; - UInt8 b; - UInt16 c; - UInt16 d; - UInt32 e; - UInt32 f; -} AABBCC; - -typedef struct AACCCC { - UInt8 a; - UInt8 b; - UInt32 c; - UInt32 d; - UInt32 e; - UInt32 f; -} AACCCC; - -typedef struct AABCCCC { - UInt8 a; - UInt8 b; - UInt16 c; - UInt32 d; - UInt32 e; - UInt32 f; - UInt32 g; -} AABCCCC; - -typedef struct AACCCCC { - UInt8 a; - UInt8 b; - UInt32 c; - UInt32 d; - UInt32 e; - UInt32 f; - UInt32 g; -} AACCCCC; - -typedef struct AAB { - UInt8 a; - UInt8 b; - UInt16 c; -} AAB; - -typedef struct AAC { - UInt8 a; - UInt8 b; - UInt32 c; -} AAC; - -typedef struct AA { - UInt8 a; - UInt8 b; -} AA; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void allocateactioninfo(EANode *node) { - ExceptionAction *ea; - SInt32 offset; - UInt32 flag26; - int reg; - int reg2; - - while (node && (node->xE == 0 || node->prev == NULL)) { - offset = exceptmodule.size; - if (node->xE == 0) - node->xE = offset; - - flag26 = node->prev ? 0 : 0x80; - - ea = node->action; - - switch (ea->type) { - case EAT_NOP: - CError_FATAL(146); - break; - case EAT_DESTROYLOCAL: { - if (local_is_16bit_offset(ea->data.destroy_local.local)) { - AABC e; - e.a = flag26 | 2; - e.b = 0; - e.c = CTool_EndianConvertWord16(local_offset_16(ea->data.destroy_local.local)); - e.d = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_local.dtor, offset + 4); - } else { - AACC e; - e.a = flag26 | 0x11; - e.b = 0; - e.c = CTool_EndianConvertWord32(local_offset_32(ea->data.destroy_local.local)); - e.d = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_local.dtor, offset + 6); - } - break; - } - case EAT_DESTROYLOCALCOND: { - reg = OBJECT_REG(ea->data.destroy_local_cond.cond); - if ( - (reg || local_is_16bit_offset(ea->data.destroy_local_cond.cond)) && - local_is_16bit_offset(ea->data.destroy_local_cond.local) - ) - { - AABBC e; - e.a = flag26 | 3; - e.b = (reg != 0) << 7; - e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_local_cond.cond)); - e.d = CTool_EndianConvertWord16(local_offset_16(ea->data.destroy_local_cond.local)); - e.e = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_local_cond.dtor, offset + 6); - } else { - AACCC e; - e.a = flag26 | 0x12; - e.b = (reg != 0) << 7; - e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_local_cond.cond)); - e.d = CTool_EndianConvertWord32(local_offset_32(ea->data.destroy_local_cond.local)); - e.e = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_local_cond.dtor, offset + 10); - } - break; - } - case EAT_DESTROYLOCALOFFSET: { - if (local_is_16bit_offset(ea->data.destroy_local_offset.local)) { - AABC e; - e.a = flag26 | 2; - e.b = 0; - e.c = CTool_EndianConvertWord16(ea->data.destroy_local_offset.offset + local_offset_16(ea->data.destroy_local_offset.local)); - e.d = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_local_offset.dtor, offset + 4); - } else { - AACC e; - e.a = flag26 | 0x11; - e.b = 0; - e.c = CTool_EndianConvertWord32(ea->data.destroy_local_offset.offset + local_offset_32(ea->data.destroy_local_offset.local)); - e.d = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_local_offset.dtor, offset + 6); - } - break; - } - case EAT_DESTROYLOCALPOINTER: { - reg = OBJECT_REG(ea->data.destroy_local_pointer.pointer); - if (reg || local_is_16bit_offset(ea->data.destroy_local_pointer.pointer)) { - AABC e; - e.a = flag26 | 4; - e.b = (reg != 0) << 7; - e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_local_pointer.pointer)); - e.d = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_local_pointer.dtor, offset + 4); - } else { - AACC e; - e.a = flag26 | 0x13; - e.b = (reg != 0) << 7; - e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_local_pointer.pointer)); - e.d = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_local_pointer.dtor, offset + 6); - } - break; - } - case EAT_DESTROYLOCALARRAY: { - if (local_is_16bit_offset(ea->data.destroy_local_array.localarray)) { - AABBBC e; - e.a = flag26 | 5; - e.b = 0; - e.c = CTool_EndianConvertWord16(local_offset_16(ea->data.destroy_local_array.localarray)); - e.d = CTool_EndianConvertWord16(ea->data.destroy_local_array.elements); - e.e = CTool_EndianConvertWord16(ea->data.destroy_local_array.element_size); - e.f = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_local_array.dtor, offset + 8); - } else { - AACCCC e; - e.a = flag26 | 0x14; - e.b = 0; - e.c = CTool_EndianConvertWord32(local_offset_32(ea->data.destroy_local_array.localarray)); - e.d = CTool_EndianConvertWord32(ea->data.destroy_local_array.elements); - e.e = CTool_EndianConvertWord32(ea->data.destroy_local_array.element_size); - e.f = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_local_array.dtor, offset + 14); - } - break; - } - case EAT_DESTROYMEMBER: { - reg = OBJECT_REG(ea->data.destroy_member.objectptr); - if (reg || local_is_16bit_offset(ea->data.destroy_member.objectptr)) { - AABCC e; - e.a = flag26 | 7; - e.b = (reg != 0) << 7; - e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member.objectptr)); - e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset); - e.e = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_member.dtor, offset + 8); - } else { - AACCC e; - e.a = flag26 | 0x16; - e.b = (reg != 0) << 7; - e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member.objectptr)); - e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset); - e.e = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_member.dtor, offset + 10); - } - break; - } - case EAT_DESTROYBASE: { - reg = OBJECT_REG(ea->data.destroy_member.objectptr); - if (reg || local_is_16bit_offset(ea->data.destroy_member.objectptr)) { - AABCC e; - e.a = flag26 | 6; - e.b = (reg != 0) << 7; - e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member.objectptr)); - e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset); - e.e = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_member.dtor, offset + 8); - } else { - AACCC e; - e.a = flag26 | 0x15; - e.b = (reg != 0) << 7; - e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member.objectptr)); - e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset); - e.e = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_member.dtor, offset + 10); - } - break; - } - case EAT_DESTROYMEMBERCOND: { - reg = OBJECT_REG(ea->data.destroy_member_cond.cond); - reg2 = OBJECT_REG(ea->data.destroy_member_cond.objectptr); - if ( - (reg || local_is_16bit_offset(ea->data.destroy_member_cond.cond)) && - (reg2 || local_is_16bit_offset(ea->data.destroy_member_cond.objectptr)) - ) - { - AABBCC e; - e.a = flag26 | 8; - e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6); - e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member_cond.cond)); - e.d = CTool_EndianConvertWord16(reg2 ? reg2 : local_offset_16(ea->data.destroy_member_cond.objectptr)); - e.e = CTool_EndianConvertWord32(ea->data.destroy_member_cond.offset); - e.f = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_member_cond.dtor, offset + 10); - } else { - AACCCC e; - e.a = flag26 | 0x17; - e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6); - e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member_cond.cond)); - e.d = CTool_EndianConvertWord32(reg2 ? reg2 : local_offset_32(ea->data.destroy_member_cond.objectptr)); - e.e = CTool_EndianConvertWord32(ea->data.destroy_member_cond.offset); - e.f = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_member_cond.dtor, offset + 14); - } - break; - } - case EAT_DESTROYMEMBERARRAY: { - reg = OBJECT_REG(ea->data.destroy_member_array.objectptr); - if (reg || local_is_16bit_offset(ea->data.destroy_member_array.objectptr)) { - AABCCCC e; - e.a = flag26 | 9; - e.b = (reg != 0) << 7; - e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member_array.objectptr)); - e.d = CTool_EndianConvertWord32(ea->data.destroy_member_array.offset); - e.e = CTool_EndianConvertWord32(ea->data.destroy_member_array.elements); - e.f = CTool_EndianConvertWord32(ea->data.destroy_member_array.element_size); - e.g = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_member_array.dtor, offset + 16); - } else { - AACCCCC e; - e.a = flag26 | 0x18; - e.b = (reg != 0) << 7; - e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member_array.objectptr)); - e.d = CTool_EndianConvertWord32(ea->data.destroy_member_array.offset); - e.e = CTool_EndianConvertWord32(ea->data.destroy_member_array.elements); - e.f = CTool_EndianConvertWord32(ea->data.destroy_member_array.element_size); - e.g = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.destroy_member_array.dtor, offset + 18); - } - break; - } - case EAT_DELETEPOINTER: - case EAT_DELETELOCALPOINTER: { - reg = OBJECT_REG(ea->data.delete_pointer.pointerobject); - if (reg || local_is_16bit_offset(ea->data.delete_pointer.pointerobject)) { - AABC e; - e.a = flag26 | 0xA; - e.b = (reg != 0) << 7; - e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.delete_pointer.pointerobject)); - e.d = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.delete_pointer.deletefunc, offset + 4); - } else { - AACC e; - e.a = flag26 | 0x19; - e.b = (reg != 0) << 7; - e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.delete_pointer.pointerobject)); - e.d = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.delete_pointer.deletefunc, offset + 6); - } - break; - } - case EAT_DELETEPOINTERCOND: { - reg = OBJECT_REG(ea->data.delete_pointer_cond.cond); - reg2 = OBJECT_REG(ea->data.delete_pointer_cond.pointerobject); - if ( - (reg || local_is_16bit_offset(ea->data.delete_pointer_cond.cond)) && - (reg2 || local_is_16bit_offset(ea->data.delete_pointer_cond.pointerobject)) - ) - { - AABBC e; - e.a = flag26 | 0xB; - e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6); - e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.delete_pointer_cond.cond)); - e.d = CTool_EndianConvertWord16(reg2 ? reg2 : local_offset_16(ea->data.delete_pointer_cond.pointerobject)); - e.e = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.delete_pointer_cond.deletefunc, offset + 6); - } else { - AACCC e; - e.a = flag26 | 0x1A; - e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6); - e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.delete_pointer_cond.cond)); - e.d = CTool_EndianConvertWord32(reg2 ? reg2 : local_offset_32(ea->data.delete_pointer_cond.pointerobject)); - e.e = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - addrelocation(ea->data.delete_pointer_cond.deletefunc, offset + 10); - } - break; - } - case EAT_CATCHBLOCK: { - AACCC e; - e.a = flag26 | 0x10; - e.b = 0; - e.c = 0; - if (ea->data.catch_block.catch_label->pclabel) - e.d = CTool_EndianConvertWord32(ea->data.catch_block.catch_label->pclabel->block->codeOffset); - else - e.d = 0; - e.e = CTool_EndianConvertWord32(local_offset_16(ea->data.catch_block.catch_info_object)); - AppendGListData(&exceptmodule, &e, sizeof(e)); - if (ea->data.catch_block.catch_typeid) - addrelocation(ea->data.catch_block.catch_typeid, offset + 2); - break; - } - case EAT_ACTIVECATCHBLOCK: { - if (local_is_16bit_offset(ea->data.active_catch_block.catch_info_object)) { - AAB e; - e.a = flag26 | 0xD; - e.b = 0; - e.c = CTool_EndianConvertWord16(local_offset_16(ea->data.active_catch_block.catch_info_object)); - AppendGListData(&exceptmodule, &e, sizeof(e)); - } else { - AAC e; - e.a = flag26 | 0x1B; - e.b = 0; - e.c = CTool_EndianConvertWord32(local_offset_32(ea->data.active_catch_block.catch_info_object)); - AppendGListData(&exceptmodule, &e, sizeof(e)); - } - break; - } - case EAT_SPECIFICATION: { - AABCC e; - int i; - - e.a = flag26 | 0xF; - e.b = 0; - e.c = CTool_EndianConvertWord16(ea->data.specification.unexp_ids); - if (ea->data.specification.unexp_label->pclabel) - e.d = CTool_EndianConvertWord32(ea->data.specification.unexp_label->pclabel->block->codeOffset); - e.e = CTool_EndianConvertWord32(local_offset_16(ea->data.specification.unexp_info_object)); - AppendGListData(&exceptmodule, &e, sizeof(e)); - - for (i = 0; i < ea->data.specification.unexp_ids; i++) { - addrelocation(ea->data.specification.unexp_id[i], 12 + i * 4 + offset); - AppendGListLong(&exceptmodule, 0); - } - break; - } - case EAT_TERMINATE: { - AA e; - e.a = flag26 | 0xE; - e.b = 0; - AppendGListData(&exceptmodule, &e, sizeof(e)); - break; - } - default: - CError_FATAL(671); - } - - node = node->prev; - } - - if (node) { - AAB e; - e.a = 1; - e.b = 0; - e.c = CTool_EndianConvertWord16(node->xE); - AppendGListData(&exceptmodule, &e, sizeof(e)); - } -} - -static UInt32 findPC(PCode *instr) { - UInt32 pc = instr->block->codeOffset; - instr = instr->prevPCode; - while (instr) { - instr = instr->prevPCode; - pc += 4; - } - CError_ASSERT(704, FITS_IN_USHORT(pc)); - return pc; -} - -static UInt32 findPC_long(PCode *instr) { - UInt32 pc = instr->block->codeOffset; - instr = instr->prevPCode; - while (instr) { - instr = instr->prevPCode; - pc += 4; - } - return pc; -} - -void initializeexceptiontables(void) { - int i; - - for (i = 0; i < EAT_NACTIONS; i++) - DAG[i] = NULL; - - pc_actions = last_pc_action = NULL; - except_refs = last_except_ref = NULL; -} - -int countexceptionactionregisters(ExceptionAction *actions) { - int count = 0; - - while (actions) { - switch (actions->type) { - case EAT_DESTROYLOCALCOND: - if (OBJECT_REG(actions->data.destroy_local_cond.cond)) - count++; - break; - case EAT_DESTROYLOCALPOINTER: - if (OBJECT_REG(actions->data.destroy_local_pointer.pointer)) - count++; - break; - case EAT_DESTROYMEMBER: - if (OBJECT_REG(actions->data.destroy_member.objectptr)) - count++; - break; - case EAT_DESTROYBASE: - if (OBJECT_REG(actions->data.destroy_base.objectptr)) - count++; - break; - case EAT_DESTROYMEMBERCOND: - if (OBJECT_REG(actions->data.destroy_member_cond.cond)) - count++; - if (OBJECT_REG(actions->data.destroy_member_cond.objectptr)) - count++; - break; - case EAT_DESTROYMEMBERARRAY: - if (OBJECT_REG(actions->data.destroy_member_array.objectptr)) - count++; - break; - case EAT_DELETEPOINTER: - case EAT_DELETELOCALPOINTER: - if (OBJECT_REG(actions->data.delete_pointer.pointerobject)) - count++; - break; - case EAT_DELETEPOINTERCOND: - if (OBJECT_REG(actions->data.delete_pointer_cond.cond)) - count++; - if (OBJECT_REG(actions->data.delete_pointer_cond.pointerobject)) - count++; - break; - } - actions = actions->prev; - } - - return count; -} - -void noteexceptionactionregisters(ExceptionAction *actions, PCodeArg *ops) { - Object *obj; - int reg; - - while (actions) { - switch (actions->type) { - case EAT_DESTROYLOCALCOND: - if ((reg = OBJECT_REG(obj = actions->data.destroy_local_cond.cond))) { - ops->kind = PCOp_REGISTER; - ops->arg = obj->u.var.info->rclass; - ops->data.reg.reg = reg; - ops->data.reg.effect = EffectRead | Effect8; - ops++; - } - break; - case EAT_DESTROYLOCALPOINTER: - if ((reg = OBJECT_REG(obj = actions->data.destroy_local_pointer.pointer))) { - ops->kind = PCOp_REGISTER; - ops->arg = obj->u.var.info->rclass; - ops->data.reg.reg = reg; - ops->data.reg.effect = EffectRead | Effect8; - ops++; - } - break; - case EAT_DESTROYMEMBER: - if ((reg = OBJECT_REG(obj = actions->data.destroy_member.objectptr))) { - ops->kind = PCOp_REGISTER; - ops->arg = obj->u.var.info->rclass; - ops->data.reg.reg = reg; - ops->data.reg.effect = EffectRead | Effect8; - ops++; - } - break; - case EAT_DESTROYBASE: - if ((reg = OBJECT_REG(obj = actions->data.destroy_base.objectptr))) { - ops->kind = PCOp_REGISTER; - ops->arg = obj->u.var.info->rclass; - ops->data.reg.reg = reg; - ops->data.reg.effect = EffectRead | Effect8; - ops++; - } - break; - case EAT_DESTROYMEMBERCOND: - if ((reg = OBJECT_REG(obj = actions->data.destroy_member_cond.cond))) { - ops->kind = PCOp_REGISTER; - ops->arg = obj->u.var.info->rclass; - ops->data.reg.reg = reg; - ops->data.reg.effect = EffectRead | Effect8; - ops++; - } - if ((reg = OBJECT_REG(obj = actions->data.destroy_member_cond.objectptr))) { - ops->kind = PCOp_REGISTER; - ops->arg = obj->u.var.info->rclass; - ops->data.reg.reg = reg; - ops->data.reg.effect = EffectRead | Effect8; - ops++; - } - break; - case EAT_DESTROYMEMBERARRAY: - if ((reg = OBJECT_REG(obj = actions->data.destroy_member_array.objectptr))) { - ops->kind = PCOp_REGISTER; - ops->arg = obj->u.var.info->rclass; - ops->data.reg.reg = reg; - ops->data.reg.effect = EffectRead | Effect8; - ops++; - } - break; - case EAT_DELETEPOINTER: - case EAT_DELETELOCALPOINTER: - if ((reg = OBJECT_REG(obj = actions->data.delete_pointer.pointerobject))) { - ops->kind = PCOp_REGISTER; - ops->arg = obj->u.var.info->rclass; - ops->data.reg.reg = reg; - ops->data.reg.effect = EffectRead | Effect8; - ops++; - } - break; - case EAT_DELETEPOINTERCOND: - if ((reg = OBJECT_REG(obj = actions->data.delete_pointer_cond.cond))) { - ops->kind = PCOp_REGISTER; - ops->arg = obj->u.var.info->rclass; - ops->data.reg.reg = reg; - ops->data.reg.effect = EffectRead | Effect8; - ops++; - } - if ((reg = OBJECT_REG(obj = actions->data.delete_pointer_cond.pointerobject))) { - ops->kind = PCOp_REGISTER; - ops->arg = obj->u.var.info->rclass; - ops->data.reg.reg = reg; - ops->data.reg.effect = EffectRead | Effect8; - ops++; - } - break; - } - actions = actions->prev; - } -} - -void recordexceptionactions(PCode *instr, ExceptionAction *actions) { - PCAction *pca; - - if (!actions && (!last_pc_action || !last_pc_action->actions)) - return; - - pca = lalloc(sizeof(PCAction)); - pca->next = NULL; - pca->firstInstr = pca->lastInstr = instr; - pca->actions = actions; - pca->prev = last_pc_action; - if (last_pc_action) - last_pc_action->next = pca; - else - pc_actions = pca; - last_pc_action = pca; - - branch_label(makepclabel()); - while (actions) { - if (actions->type == EAT_CATCHBLOCK && actions->data.catch_block.catch_label->pclabel) - pcbranch(instr->block, actions->data.catch_block.catch_label->pclabel); - else if (actions->type == EAT_SPECIFICATION && actions->data.specification.unexp_label->pclabel) - pcbranch(instr->block, actions->data.specification.unexp_label->pclabel); - actions = actions->prev; - } -} - -static void deleteexceptionaction(PCAction *pca) { - if (pca->prev) - pca->prev->next = pca->next; - else - pc_actions = pca->next; - - if (pca->next) - pca->next->prev = pca->prev; -} - -static int mergeexceptionactions(void) { - int count; - PCAction *pca; - PCAction *prev; - - if (!pc_actions) - return 0; - - for (pca = pc_actions; pca; pca = pca->next) { - if (pca->firstInstr->block->flags & fDeleted) - deleteexceptionaction(pca); - } - - if (!(pca = pc_actions)) - return 0; - - while (pca) { - pca->node = pca->actions ? makeEAnode(pca->actions) : NULL; - pca = pca->next; - } - - prev = pc_actions; - for (pca = pc_actions->next; pca; pca = pca->next) { - if (pca->node == prev->node) { - prev->lastInstr = pca->lastInstr; - deleteexceptionaction(pca); - } else { - prev = pca; - } - } - - count = 0; - for (pca = pc_actions; pca; pca = pca->next) { - if (!pca->actions) - deleteexceptionaction(pca); - else - count++; - } - - return count; -} - -typedef struct ExceptionThing { - UInt32 x0; - UInt16 x4; - UInt16 x6; -} ExceptionThing; - -void dumpexceptiontables(Object *function, SInt32 codesize) { - PCAction *pca; - UInt32 insn_start; - UInt32 insn_count; - UInt16 *sh; - ExceptionThing *thing; - int count; - - count = mergeexceptionactions(); - InitGList(&exceptmodule, 256); - AppendGListNoData(&exceptmodule, 8 * count + 4); - AppendGListLong(&exceptmodule, 0); - - for (pca = pc_actions; pca; pca = pca->next) { - if (pca->node->count == 0 && pca->node->xE == 0) - allocateactioninfo(pca->node); - } - - sh = (UInt16 *) *exceptmodule.data; - if (copts.altivec_model && used_nonvolatile_registers[RegClass_VR]) { - sh[0] = - CTool_EndianConvertWord16( - (used_nonvolatile_registers[RegClass_GPR] << 11) | - ((used_nonvolatile_registers[RegClass_FPR] & 0x1F) << 6) | - (((used_nonvolatile_registers[RegClass_CRFIELD] != 0) & 1) << 5) | - ((dynamic_stack & 1) << 4) | - 8); - sh[0] |= 4; - if (copts.altivec_vrsave) - sh[1] = CTool_EndianConvertWord16((used_nonvolatile_registers[RegClass_VR] << 11) | 0x400); - else - sh[1] = CTool_EndianConvertWord16((used_nonvolatile_registers[RegClass_VR] & 0x1F) << 11); - } else { - sh[0] = - CTool_EndianConvertWord16( - (used_nonvolatile_registers[RegClass_GPR] << 11) | - ((used_nonvolatile_registers[RegClass_FPR] & 0x1F) << 6) | - (((used_nonvolatile_registers[RegClass_CRFIELD] != 0) & 1) << 5) | - ((dynamic_stack & 1) << 4) | - 8); - sh[1] = 0; - } - - thing = (ExceptionThing *) (sh + 2); - pca = pc_actions; - while (pca) { - insn_start = findPC_long(pca->firstInstr); - insn_count = (findPC_long(pca->lastInstr) - insn_start) / 4; - CError_ASSERT(1203, (insn_count & 0xFFFF0000) == 0); - thing->x0 = CTool_EndianConvertWord32(insn_start + 4); - thing->x4 = CTool_EndianConvertWord16(insn_count); - thing->x6 = CTool_EndianConvertWord16(pca->node->xE); - pca = pca->next; - thing++; - } - - LockGList(&exceptmodule); - ObjGen_DeclareExceptionTables(function, codesize, *exceptmodule.data, exceptmodule.size, except_refs); - FreeGList(&exceptmodule); -} diff --git a/compiler_and_linker/unsorted/FuncLevelAsmPPC.c b/compiler_and_linker/unsorted/FuncLevelAsmPPC.c deleted file mode 100644 index 27528b8..0000000 --- a/compiler_and_linker/unsorted/FuncLevelAsmPPC.c +++ /dev/null @@ -1,393 +0,0 @@ -#include "compiler/FuncLevelAsmPPC.h" -#include "compiler/CCompiler.h" -#include "compiler/CError.h" -#include "compiler/CFunc.h" -#include "compiler/CMangler.h" -#include "compiler/CParser.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CodeGen.h" -#include "compiler/Coloring.h" -#include "compiler/CompilerTools.h" -#include "compiler/uDump.h" -#include "compiler/InlineAsmPPC.h" -#include "compiler/InlineAsmRegisters.h" -#include "compiler/ObjGenMachO.h" -#include "compiler/PCode.h" -#include "compiler/PCodeAssembly.h" -#include "compiler/PCodeListing.h" -#include "compiler/PCodeUtilities.h" -#include "compiler/PPCError.h" -#include "compiler/RegisterInfo.h" -#include "compiler/StackFrame.h" -#include "compiler/TOC.h" -#include "compiler/objects.h" - -static EntryPoint *entrypoints_head; -static EntryPoint **entrypoints_tail; - -void setup_assembly_argument(Object *obj, short reg) { - VarInfo *vi; - Type *type; - - vi = Registers_GetVarInfo(obj); - type = obj->type; - vi->used = 1; - - if (!requires_frame) { - if (is_register_object(obj)) { - if (!reg) - CError_Error(CErrorStr263, obj->name->name); - - if (TYPE_IS_8BYTES(type)) { - short regLo; - short regHi; - if (reg < 10) { - if (copts.littleendian) { - regLo = reg; - regHi = reg + 1; - } else { - regLo = reg + 1; - regHi = reg; - } - retain_GPR_pair(obj, regLo, regHi); - InlineAsm_InsertRegister(obj->name->name, RegClass_GPR, regLo, obj); - } - } else if (IS_TYPE_FLOAT(type)) { - retain_register(obj, RegClass_FPR, reg); - InlineAsm_InsertRegister(obj->name->name, RegClass_FPR, reg, obj); - } else if (IS_TYPE_VECTOR(type)) { - retain_register(obj, RegClass_VR, reg); - InlineAsm_InsertRegister(obj->name->name, RegClass_VR, reg, obj); - } else { - retain_register(obj, RegClass_GPR, reg); - InlineAsm_InsertRegister(obj->name->name, RegClass_GPR, reg, obj); - } - } - } else { - if (is_register_object(obj)) { - vi = Registers_GetVarInfo(obj); - if (!vi->reg) { - assign_register_by_type(obj); - if (!(vi->flags & VarInfoFlag2)) - CError_Error(CErrorStr263, obj->name->name); - else - InlineAsm_InsertRegister(obj->name->name, vi->rclass, vi->reg, obj); - } - } - } -} - -void assign_local_addresses(void) { - VarInfo *vi; - ObjectList *list; - Object *object; - - for (list = locals; list; list = list->next) { - vi = CodeGen_GetNewVarInfo(); - list->object->u.var.info = vi; - list->object->flags |= OBJECT_USED; - vi->used = 1; - } - - for (list = locals; list; list = list->next) { - object = list->object; - if (is_register_object(object)) { - vi = Registers_GetVarInfo(object); - if (!vi->reg) { - assign_register_by_type(object); - if (!(vi->flags & VarInfoFlag2)) - CError_Error(CErrorStr263, object->name->name); - else - InlineAsm_InsertRegister(object->name->name, vi->rclass, vi->reg, object); - } - } - } - - for (list = locals; list; list = list->next) { - object = list->object; - if (OBJECT_REG(object) == 0) - assign_local_memory(object); - } -} - -static void FuncAsm_PreScanDirectives(void) { - SInt32 directive; - Boolean save_eoltokens; - - in_assembler = 1; - save_eoltokens = cprep_eoltokens; - cprep_eoltokens = 1; - - if (setjmp(InlineAsm_assemblererror) == 0) { - while (tk == TK_IDENTIFIER && (directive = InlineAsm_IsDirective(AssemblerType_1))) { - InlineAsm_ProcessDirective(directive); - - if (tk == ';' || tk == TK_EOL) { - CPrep_TokenStreamFlush(); - tk = lex(); - } else { - InlineAsm_SyntaxError(CErrorStr113); - } - - if (directive == IADirective_FrAlloc) { - requires_frame = 1; - break; - } else if (directive == IADirective_NoFrAlloc) { - user_responsible_for_frame = 1; - break; - } - } - } - - in_assembler = 0; - cprep_eoltokens = save_eoltokens; -} - -static void FuncAsm_AddEntryPoint(Statement *stmt, PCodeBlock *block) { - EntryPoint *ep; - IAEntryPoint *ia_ep; - - ia_ep = (IAEntryPoint *) stmt->expr; - ep = lalloc(sizeof(EntryPoint)); - memclrw(ep, sizeof(EntryPoint)); - - ep->object = ia_ep->x8; - ep->block = block; - - *entrypoints_tail = ep; - entrypoints_tail = &ep->next; - - block->flags |= fPCBlockFlag8000; -} - -void Assembler(Object *func) { - PCodeBlock *block; - Statement *stmt; - Boolean flag17; - Boolean flag16; - char *name; - InlineAsm *ia; - Boolean save_unusedvar; - Boolean save_unusedarg; - - flag17 = 0; - flag16 = 0; - - init_endian(); - init_stack_globals(func); - memclrw(asm_alloc_flags, sizeof(asm_alloc_flags)); - fralloc_parameter_area_size = 0; - user_responsible_for_frame = 0; - assembledinstructions = 0; - - entrypoints_head = NULL; - entrypoints_tail = &entrypoints_head; - - stmt = curstmt; - - if (func && func->name) - PrintProgressFunction(func->name->name); - - CodeGen_InitialSanityCheck(); - - if (func->qual & Q_INLINE) - PPCError_Warning(PPCErrorStr173); - - CheckCLabels(); - - if (fatalerrors) - return; - - if (copts.filesyminfo) - CPrep_SetSourceFile(&cparser_fileoffset); - - sm_section = SECT_TEXT; - - initpcode(); - - pclabel(prologue = makepcblock(), makepclabel()); - pclabel(block = makepcblock(), makepclabel()); - pcbranch(prologue, block->labels); - - resetTOCvarinfo(); - InlineAsm_InitializePPC(); - FuncAsm_PreScanDirectives(); - - disable_optimizer = 1; - - init_registers(); - assign_arguments_to_memory(func, 0, 0); - init_frame_sizes(0); - - if (copts.debuglisting) - DumpIR(stmt, func); - - cprep_eoltokens = 1; - in_assembler = 1; - - save_unusedvar = copts.warn_unusedvar; - save_unusedarg = copts.warn_unusedarg; - copts.warn_unusedvar = 0; - copts.warn_unusedarg = 0; - - InlineAsm_ScanFunction('}'); - - expandTOCreferences(&stmt->next); - - if (!anyerrors && copts.debuglisting) - DumpIR(stmt, func); - - in_assembler = 0; - cprep_eoltokens = 0; - - name = CMangler_GetLinkName(func)->name; - func->flags |= OBJECT_DEFINED; - - if (fralloc_parameter_area_size) - update_out_param_size(fralloc_parameter_area_size); - if (!user_responsible_for_frame) - process_arguments(move_assigned_argument, 0); - - branch_label(makepclabel()); - assign_labels(stmt->next); - - copts.warn_unusedvar = save_unusedvar; - copts.warn_unusedarg = save_unusedarg; - - for (stmt = stmt->next; stmt; stmt = stmt->next) { - current_statement = stmt; - switch (stmt->type) { - case ST_ASM: - if ((ia = (InlineAsm *) stmt->expr)) { - if (ia->flags & IAFlag1) { - if (ia->opcode == IADirective_Entry) { - branch_label(makepclabel()); - FuncAsm_AddEntryPoint(stmt, pclastblock); - } else if (ia->opcode == IADirective_FrFree) { - if (flag16) - PPCError_Error(PPCErrorStr188); - else - flag16 = 1; - - asm_alloc_flags[3] = 1; - asm_alloc_flags[4] = 1; - branch_label(makepclabel()); - - epilogue = pclastblock; - pclastblock->flags |= fIsEpilogue; - - CheckCLabels(); - if (fatalerrors) - return; - - pccomputepredecessors(); - if (copts.debuglisting) - pclistblocks(name, "[FUNCTION-LEVEL ASM] INITIAL CODE"); - colorinstructions(func); - if (copts.debuglisting) - pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER REGISTER COLORING"); - compute_frame_sizes(); - generate_prologue(prologue, 0); - epilogue = pclastblock; - generate_epilogue(epilogue, 0); - if (copts.debuglisting) - pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER PROLOGUE/EPILOGUE CREATION"); - - flag17 = 1; - } - } else { - branch_label(makepclabel()); - asm_alloc_flags[6] = 0; - asm_alloc_flags[7] = 0; - InlineAsm_TranslateIRtoPCode(stmt); - asm_alloc_flags[4] = 0; - } - } - break; - case ST_LABEL: - if (!stmt->label->pclabel->resolved) - branch_label(stmt->label->pclabel); - break; - default: - CError_FATAL(525); - } - } - - current_statement = NULL; - - if (fatalerrors) - return; - CheckCLabels(); - if (fatalerrors) - return; - - if (!flag17) { - branch_label(makepclabel()); - - epilogue = pclastblock; - pclastblock->flags |= fIsEpilogue; - - pccomputepredecessors(); - if (copts.debuglisting) - pclistblocks(name, "[FUNCTION-LEVEL ASM] INITIAL CODE"); - - if (!asm_alloc_flags[1]) { - colorinstructions(func); - if (fatalerrors) - return; - - if (copts.debuglisting) - pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER REGISTER COLORING"); - } - - compute_frame_sizes(); - if (asm_alloc_flags[1]) - no_frame_for_asm(); - - if (fatalerrors) - return; - - if (!asm_alloc_flags[1]) { - generate_prologue(prologue, 0); - generate_epilogue(epilogue, !asm_alloc_flags[6] && !asm_alloc_flags[7]); - } - - if (copts.debuglisting) - pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER PROLOGUE/EPILOGUE CREATION"); - } - - if (fatalerrors) - return; - - if (!asm_alloc_flags[1] && needs_frame()) { - if (asm_alloc_flags[3]) { - if (!asm_alloc_flags[5] || !asm_alloc_flags[6]) - PPCError_Warning(PPCErrorStr187, "blr"); - if (asm_alloc_flags[8]) - PPCError_Warning(PPCErrorStr186); - } else { - PPCError_Warning(PPCErrorStr185, "blr"); - } - } - - func->section = sm_section; - - if (copts.filesyminfo) - symdeclend = CPrep_GetFileOffsetInfo(&cparser_fileoffset); - - copts.peephole = 0; - if (pic_base_label) - pic_base_pcodelabel = pic_base_label->pclabel; - assemblefunction(func, entrypoints_head); - - if (copts.debuglisting) - pclistblocks(CMangler_GetLinkName(func)->name, "[FUNCTION-LEVEL ASM] FINAL CODE"); - - CFunc_WarnUnused(); -} - -void SetupAssembler(void) { -} - -void CleanupAssembler(void) { -} diff --git a/compiler_and_linker/unsorted/FunctionCalls.c b/compiler_and_linker/unsorted/FunctionCalls.c deleted file mode 100644 index 67d7443..0000000 --- a/compiler_and_linker/unsorted/FunctionCalls.c +++ /dev/null @@ -1,642 +0,0 @@ -#include "compiler/FunctionCalls.h" -#include "compiler/CError.h" -#include "compiler/CFunc.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/CodeGen.h" -#include "compiler/CompilerTools.h" -#include "compiler/InstrSelection.h" -#include "compiler/Operands.h" -#include "compiler/PCode.h" -#include "compiler/PCodeUtilities.h" -#include "compiler/Registers.h" -#include "compiler/StackFrame.h" -#include "compiler/StructMoves.h" -#include "compiler/types.h" - -enum { - AIF_PassInGPR = 1, - AIF_PassInFPR = 2, - AIF_PassOnStack = 4, - AIF_ExtendTo32Bits = 8, - AIF_ForceDoublePrecision = 0x10, - AIF_PassInVR = 0x20, - AIF_PassMask = AIF_PassInGPR | AIF_PassInFPR | AIF_PassOnStack | AIF_PassInVR -}; - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct ArgInfo { - struct ArgInfo *next; - ENode *expr; - Operand opnd; - SInt32 offset; - short gpr; - short gprHi; - short fpr; - short vr; - short evaluated; - short flags; -} ArgInfo; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -// forward decls -static void branch_subroutine_indirect_ctr(Operand *addrOpnd, UInt32 *used_regs); - -static ArgInfo *make_arginfo(ENode *expr) { - ArgInfo *info = lalloc(sizeof(ArgInfo)); - memclrw(info, sizeof(ArgInfo)); - - info->next = NULL; - info->expr = expr; - info->offset = -1; - info->gpr = -1; - info->gprHi = -1; - info->fpr = -1; - info->vr = -1; - info->evaluated = 0; - info->flags = 0; - - return info; -} - -static ArgInfo *analyze_arguments(ENode *funcref, ENodeList *arg_expr, FuncArg *arg, UInt32 *used_regs, Boolean *resultHasFloats, char has_varargs) { - ArgInfo *infos; - ArgInfo *info; - SInt32 displ; - SInt32 arg_size; - int gpr_counter; - int fpr_counter; - int vr_counter; - Type *type; - RegClass rclass; - Boolean spilledVectorFlag; - - infos = NULL; - displ = 0; - gpr_counter = 3; - fpr_counter = 1; - vr_counter = 2; - - for (rclass = 0; rclass < RegClassMax; rclass++) - used_regs[rclass] = 0; - *resultHasFloats = 0; - - while (arg_expr) { - if (arg_expr->node == funcref) { - arg_expr = arg_expr->next; - arg = arg->next; - continue; - } - - type = arg_expr->node->rtype; - if (infos) { - info->next = make_arginfo(arg_expr->node); - info = info->next; - } else { - infos = info = make_arginfo(arg_expr->node); - } - - arg_size = 0; - if (IS_TYPE_VECTOR(type)) { - if (arg == &elipsis) { - spilledVectorFlag = 1; - info->flags |= AIF_PassOnStack; - } else { - spilledVectorFlag = 0; - if (vr_counter <= 13) { - info->flags |= AIF_PassInVR; - info->vr = vr_counter; - used_regs[RegClass_VR] |= 1 << vr_counter; - } else { - spilledVectorFlag = 1; - info->flags |= AIF_PassOnStack; - } - } - - if (has_varargs) { - if (gpr_counter < 10) { - gpr_counter = ((gpr_counter - 2) & ~3) + 5; - if (arg == &elipsis && gpr_counter < 10) { - info->flags |= AIF_PassInGPR; - info->gpr = gpr_counter; - used_regs[RegClass_GPR] |= (15 << gpr_counter) & 0x7E0; - } - gpr_counter += 4; - } - spilledVectorFlag = 1; - } - - if (spilledVectorFlag) - arg_size = 16; - vr_counter++; - } else if (IS_TYPE_FLOAT(type)) { - *resultHasFloats = 1; - if (!arg || arg == &oldstyle) { - if (fpr_counter <= 13) { - info->flags |= AIF_PassInFPR; - info->fpr = fpr_counter; - used_regs[RegClass_FPR] |= 1 << fpr_counter; - } else { - info->flags |= AIF_PassOnStack | AIF_ForceDoublePrecision; - } - arg_size = 8; - fpr_counter++; - gpr_counter += 2; - } else if (arg == &elipsis) { - if (gpr_counter < 10) { - info->flags |= AIF_PassInGPR; - info->gpr = gpr_counter; - used_regs[RegClass_GPR] |= 3 << gpr_counter; - } else if (gpr_counter == 10) { - info->flags |= AIF_PassInGPR | AIF_PassOnStack | AIF_ForceDoublePrecision; - info->gpr = gpr_counter; - used_regs[RegClass_GPR] |= 3 << gpr_counter; - } else { - info->flags |= AIF_PassOnStack | AIF_ForceDoublePrecision; - } - arg_size = 8; - fpr_counter++; - gpr_counter += 2; - } else { - if (fpr_counter <= 13) { - info->flags |= AIF_PassInFPR; - info->fpr = fpr_counter; - used_regs[RegClass_FPR] |= 1 << fpr_counter; - } else { - info->flags |= AIF_PassOnStack; - } - - if (type->size == 4) { - arg_size = 4; - gpr_counter++; - } else { - arg_size = 8; - gpr_counter += 2; - } - - fpr_counter++; - } - } else if (TYPE_IS_8BYTES(type)) { - if (gpr_counter <= 10) { - info->flags |= AIF_PassInGPR; - if (copts.littleendian) { - info->gpr = gpr_counter; - info->gprHi = gpr_counter + 1; - } else { - info->gpr = gpr_counter + 1; - info->gprHi = gpr_counter; - } - used_regs[RegClass_GPR] |= 1 << gpr_counter; - if ((gpr_counter + 1) <= 10) - used_regs[RegClass_GPR] |= 1 << (gpr_counter + 1); - } else { - info->flags |= AIF_PassOnStack; - } - - arg_size = 8; - gpr_counter += 2; - } else if (TYPE_FITS_IN_REGISTER(type)) { - if ((!arg || arg == &elipsis || arg == &oldstyle) && type->size < 4) - info->flags |= AIF_ExtendTo32Bits; - - if (gpr_counter <= 10) { - info->flags |= AIF_PassInGPR; - info->gpr = gpr_counter; - used_regs[RegClass_GPR] |= 1 << gpr_counter; - } else { - info->flags |= AIF_PassOnStack; - } - - arg_size = 4; - gpr_counter++; - } else if (IS_TYPE_ARRAY(type) || IS_TYPE_NONVECTOR_STRUCT(type) || IS_TYPE_CLASS(type) || - IS_TYPE_12BYTES_MEMBERPOINTER(type)) { - SInt32 gprs_needed = (type->size >> 2) + ((type->size & 3) != 0); - if (gpr_counter <= 10) { - if ((gpr_counter + gprs_needed - 1) <= 10) { - info->flags |= AIF_PassInGPR; - info->gpr = gpr_counter; - used_regs[RegClass_GPR] |= ((1 << gprs_needed) - 1) << gpr_counter; - } else { - info->flags |= AIF_PassInGPR | AIF_PassOnStack; - info->gpr = gpr_counter; - used_regs[RegClass_GPR] |= ((1 << (11 - gpr_counter)) - 1) << gpr_counter; - } - } else { - info->flags |= AIF_PassOnStack; - } - - gpr_counter += gprs_needed; - arg_size = type->size; - } else { - CError_FATAL(421); - } - - displ = set_out_param_displ(displ, type, info->flags & AIF_PassOnStack, &info->offset, arg_size); - - arg_expr = arg_expr->next; - if (arg && arg != &elipsis && arg != &oldstyle) - arg = arg->next; - } - - update_out_param_size(displ); - - return infos; -} - -static void pass_in_memory(ArgInfo *info) { - Type *type; - Operand opnd; - - type = info->expr->rtype; - memclrw(&opnd, sizeof(Operand)); - - if (TYPE_FITS_IN_REGISTER(type)) { - if (TYPE_IS_8BYTES(type)) { - if (!info->evaluated) - GEN_NODE(info->expr, &info->opnd); - coerce_to_register_pair(&info->opnd, type, 0, 0); - - load_store_register( - PC_STW, info->opnd.reg, 1, - NULL, low_offset + out_param_displ_to_offset(info->offset)); - load_store_register( - PC_STW, info->opnd.regHi, 1, - NULL, high_offset + out_param_displ_to_offset(info->offset)); - } else { - if (!info->evaluated) - GEN_NODE(info->expr, &info->opnd); - if (info->flags & AIF_ExtendTo32Bits) - extend32(&info->opnd, type, 0); - ENSURE_GPR(&info->opnd, type, 0); - - load_store_register( - PC_STW, info->opnd.reg, 1, - NULL, out_param_displ_to_offset(info->offset)); - } - } else if (IS_TYPE_FLOAT(type)) { - if (!info->evaluated) - GEN_NODE(info->expr, &info->opnd); - ENSURE_FPR(&info->opnd, type, 0); - - if (type->size == 4 && !(info->flags & AIF_ForceDoublePrecision)) { - load_store_register( - PC_STFS, info->opnd.reg, 1, - NULL, out_param_displ_to_offset(info->offset)); - } else { - load_store_register( - PC_STFD, info->opnd.reg, 1, - NULL, out_param_displ_to_offset(info->offset)); - } - } else if (IS_TYPE_VECTOR(type)) { - if (!info->evaluated) - GEN_NODE(info->expr, &info->opnd); - ENSURE_VR(&info->opnd, type, 0); - - load_store_register( - PC_STVX, info->opnd.reg, 1, - NULL, out_param_displ_to_offset(info->offset)); - } else { - opnd.optype = OpndType_IndirectGPR_ImmOffset; - opnd.reg = 1; - opnd.object = NULL; - opnd.immOffset = out_param_displ_to_offset(info->offset); - - if (!info->evaluated) - GEN_NODE(info->expr, &info->opnd); - - move_block(&opnd, &info->opnd, type->size, CMach_ArgumentAlignment(type)); - } -} - -static void pass_in_register(ArgInfo *info) { - Type *type; - - type = info->expr->rtype; - - if ((info->flags & AIF_PassMask) == AIF_PassInFPR) { - if (!info->evaluated) - GEN_NODE_TO_REG(info->expr, info->fpr, 0, &info->opnd); - ENSURE_FPR(&info->opnd, type, info->fpr); - if (info->opnd.reg != info->fpr) - emitpcode(PC_FMR, info->fpr, info->opnd.reg); - } else if ((info->flags & AIF_PassMask) == AIF_PassInVR) { - if (!info->evaluated) - GEN_NODE_TO_REG(info->expr, info->vr, 0, &info->opnd); - ENSURE_VR(&info->opnd, type, info->vr); - if (info->opnd.reg != info->vr) - emitpcode(PC_VMR, info->vr, info->opnd.reg); - } else if (TYPE_FITS_IN_REGISTER(type)) { - if (TYPE_IS_8BYTES(type)) { - if (!info->evaluated) - GEN_NODE_TO_REG(info->expr, info->gpr, info->gprHi, &info->opnd); - coerce_to_register_pair(&info->opnd, type, info->gpr, info->gprHi); - if (copts.littleendian) { - if (info->gprHi > 10) { - load_store_register( - PC_STW, info->opnd.regHi, 1, - NULL, high_offset + out_param_displ_to_offset(info->offset)); - } - } else { - if (info->gpr > 10) { - load_store_register( - PC_STW, info->opnd.reg, 1, - NULL, low_offset + out_param_displ_to_offset(info->offset)); - } - } - } else { - if (!info->evaluated) - GEN_NODE_TO_REG(info->expr, info->gpr, 0, &info->opnd); - if (info->flags & AIF_ExtendTo32Bits) - extend32(&info->opnd, type, info->gpr); - ENSURE_GPR(&info->opnd, type, info->gpr); - if (info->opnd.reg != info->gpr) - emitpcode(PC_MR, info->gpr, info->opnd.reg); - } - } else if (IS_TYPE_FLOAT(type)) { - if (!info->evaluated) - GEN_NODE(info->expr, &info->opnd); - - if (type->size != 4 && info->opnd.optype == OpndType_IndirectGPR_ImmOffset) { - load_store_register( - PC_LWZ, info->gpr, info->opnd.reg, - info->opnd.object, info->opnd.immOffset); - load_store_register( - PC_LWZ, info->gpr + 1, info->opnd.reg, - info->opnd.object, info->opnd.immOffset + 4); - } else { - ENSURE_FPR(&info->opnd, type, 0); - load_store_register( - PC_STFD, info->opnd.reg, 1, - NULL, out_param_displ_to_offset(info->offset)); - load_store_register( - PC_LWZ, info->gpr, 1, - NULL, out_param_displ_to_offset(info->offset)); - load_store_register( - PC_LWZ, info->gpr + 1, 1, - NULL, out_param_displ_to_offset(info->offset) + 4); - } - } else if (IS_TYPE_VECTOR(type)) { - if (!info->evaluated) - GEN_NODE(info->expr, &info->opnd); - - if (info->opnd.optype == OpndType_IndirectGPR_ImmOffset) { - load_store_register( - PC_LWZ, info->gpr, info->opnd.reg, - info->opnd.object, info->opnd.immOffset); - load_store_register( - PC_LWZ, info->gpr + 1, info->opnd.reg, - info->opnd.object, info->opnd.immOffset + 4); - if ((info->gpr + 2) < 10) { - load_store_register( - PC_LWZ, info->gpr + 2, info->opnd.reg, - info->opnd.object, info->opnd.immOffset + 8); - load_store_register( - PC_LWZ, info->gpr + 3, info->opnd.reg, - info->opnd.object, info->opnd.immOffset + 12); - } - } else { - ENSURE_VR(&info->opnd, type, 0); - load_store_register( - PC_STVX, info->opnd.reg, 1, - NULL, out_param_displ_to_offset(info->offset)); - load_store_register( - PC_LWZ, info->gpr, 1, - NULL, out_param_displ_to_offset(info->offset)); - load_store_register( - PC_LWZ, info->gpr + 1, 1, - NULL, out_param_displ_to_offset(info->offset) + 4); - if ((info->gpr + 2) < 10) { - load_store_register( - PC_LWZ, info->gpr + 2, 1, - NULL, out_param_displ_to_offset(info->offset) + 8); - load_store_register( - PC_LWZ, info->gpr + 3, 1, - NULL, out_param_displ_to_offset(info->offset) + 12); - } - } - } else { - if (!info->evaluated) - GEN_NODE(info->expr, &info->opnd); - - if (type->size <= 4) { - if (info->opnd.optype == OpndType_IndirectSymbol) - coerce_to_addressable(&info->opnd); - - if (info->opnd.optype == OpndType_IndirectGPR_ImmOffset) { - load_store_register( - PC_LWZ, info->gpr, info->opnd.reg, - info->opnd.object, info->opnd.immOffset); - } else if (info->opnd.optype == OpndType_IndirectGPR_Indexed) { - emitpcode( - PC_LWZX, info->gpr, info->opnd.reg, - info->opnd.regOffset); - } - } else { - SInt32 gprs_needed = (type->size >> 2) + ((type->size & 3) != 0); - SInt32 i; - - make_addressable(&info->opnd, gprs_needed * 4, 12); - for (i = 0; i < gprs_needed; i++) { - if (info->opnd.reg != (info->gpr + i)) { - load_store_register( - PC_LWZ, info->gpr + i, info->opnd.reg, - info->opnd.object, info->opnd.immOffset + i * 4); - } - } - - if (info->opnd.reg >= info->gpr && info->opnd.reg < (info->gpr + gprs_needed)) { - load_store_register( - PC_LWZ, info->opnd.reg, info->opnd.reg, - info->opnd.object, info->opnd.immOffset + (info->opnd.reg - info->gpr) * 4); - } - } - } -} - -static void pass_in_register_and_memory(ArgInfo *info) { - Type *type; - int gpr; - SInt32 offset; - - type = info->expr->rtype; - gpr = info->gpr; - offset = 0; - while (offset < type->size && gpr <= 10) { - load_store_register( - PC_LWZ, gpr, 1, - NULL, offset + out_param_displ_to_offset(info->offset)); - gpr++; - offset += 4; - } -} - -static Boolean needs_TOC_reload(Object *func) { - return 0; -} - -static void load_virtual_function(TypeClass *tclass, SInt32 offset, int reg, Operand *opnd) { - if (tclass->flags & CLASS_HANDLEOBJECT) { - load_store_register(PC_LWZ, 12, reg, NULL, 0); - load_store_register(PC_LWZ, 12, 12, NULL, tclass->vtable->offset); - } else { - load_store_register(PC_LWZ, 12, reg, NULL, tclass->vtable->offset); - } - load_store_register(PC_LWZ, 12, 12, NULL, offset); - opnd->optype = OpndType_GPR; - opnd->reg = 12; -} - -static void branch_subroutine_indirect(Object *func, Operand *addrOpnd, UInt32 *used_regs) { - if (addrOpnd->reg != 12) - emitpcode(PC_MR, 12, addrOpnd->reg); - - used_regs[RegClass_GPR] |= 1 << 12; - branch_subroutine(func, 1, used_regs); -} - -static void evaluate_nested_function_calls(ArgInfo *info) { - ArgInfo *scan; - - scan = info->next; - while (scan && !scan->expr->hascall) - scan = scan->next; - - if (scan) - evaluate_nested_function_calls(scan); - - if (info->expr->hascall) { - GEN_NODE(info->expr, &info->opnd); - info->evaluated = 1; - } -} - -void call_function(ENode *expr, Operand *output) { - ArgInfo *infos; // r31 - ENode *funcref = expr->data.funccall.funcref; // r27 - Type *resultType = expr->data.funccall.functype->functype; // r26 - ENode *node = NULL; // r25 - char has_varargs; // r24 - ArgInfo *info; // r22 - Operand opnd; - UInt32 used_regs[RegClassMax] = {0}; - Boolean has_floats; - FuncArg *arg; - - memclrw(&opnd, sizeof(Operand)); - - has_varargs = 0; - for (arg = expr->data.funccall.functype->args; arg; arg = arg->next) { - if (arg == &elipsis) { - has_varargs = 1; - break; - } - } - - if (expr->data.funccall.functype->flags & FUNC_FLAGS_80) { - if (CMach_PassResultInHiddenArg(resultType)) - node = expr->data.funccall.args->next->node; - else - node = expr->data.funccall.args->node; - } - - infos = analyze_arguments( - node, - expr->data.funccall.args, - expr->data.funccall.functype->args, - used_regs, - &has_floats, - has_varargs); - - if (infos) - evaluate_nested_function_calls(infos); - - if (funcref->hascall) { - GEN_NODE_TO_GPR(funcref, &opnd, TYPE(&void_ptr), 0); - } else if (node && node->hascall) { - GEN_NODE_TO_GPR(node, &opnd, TYPE(&void_ptr), 0); - } - - for (info = infos; info; info = info->next) { - if (info->flags & AIF_PassOnStack) - pass_in_memory(info); - } - for (info = infos; info; info = info->next) { - if ((info->flags & AIF_PassMask) == (AIF_PassInGPR | AIF_PassOnStack)) - pass_in_register_and_memory(info); - } - for (info = infos; info; info = info->next) { - int flag = info->flags & AIF_PassMask; - if ( - flag == AIF_PassInGPR || - flag == AIF_PassInFPR || - flag == AIF_PassInVR - ) - pass_in_register(info); - } - - if (funcref->type == EOBJREF) { - TypeClass *tclass; - SInt32 vfOffset; - if (CParser_IsVirtualFunction(funcref->data.objref, &tclass, &vfOffset)) { - load_virtual_function( - tclass, - vfOffset, - CMach_PassResultInHiddenArg(resultType) ? Register4 : Register3, - &opnd - ); - branch_subroutine_indirect_ctr(&opnd, used_regs); - } else if (node) { - if (!node->hascall) { - GEN_NODE_TO_REG(node, 12, 0, &opnd); - ENSURE_GPR(&opnd, TYPE(&void_ptr), 12); - } - branch_subroutine_indirect(funcref->data.objref, &opnd, used_regs); - } else { - branch_subroutine(funcref->data.objref, needs_TOC_reload(funcref->data.objref), used_regs); - } - } else { - if (!funcref->hascall) - GEN_NODE_TO_REG(funcref, 12, 0, &opnd); - ENSURE_GPR(&opnd, TYPE(&void_ptr), 12); - branch_subroutine_indirect_ctr(&opnd, used_regs); - } - - if (IS_TYPE_FLOAT(resultType)) { - output->optype = OpndType_FPR; - output->reg = used_virtual_registers[RegClass_FPR]++; - emitpcode(PC_FMR, output->reg, 1); - } else if (IS_TYPE_VECTOR(resultType)) { - output->optype = OpndType_VR; - output->reg = used_virtual_registers[RegClass_VR]++; - emitpcode(PC_VMR, output->reg, 2); - } else if (TYPE_FITS_IN_REGISTER(resultType)) { - if (resultType->size > 4) { - output->optype = OpndType_GPRPair; - output->reg = used_virtual_registers[RegClass_GPR]++; - output->regHi = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_MR, output->reg, low_reg); - emitpcode(PC_MR, output->regHi, high_reg); - } else { - output->optype = OpndType_GPR; - output->reg = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_MR, output->reg, 3); - } - } else { - output->optype = OpndType_Absolute; - output->immediate = 0; - } -} - -static void branch_subroutine_indirect_ctr(Operand *addrOpnd, UInt32 *used_regs) { - if (addrOpnd->reg != 12) - emitpcode(PC_MR, 12, addrOpnd->reg); - - emitpcode(PC_MTCTR, 12); - used_regs[RegClass_GPR] |= 1 << 12; - branch_subroutine_ctr(used_regs); -} diff --git a/compiler_and_linker/unsorted/GCCInlineAsm.c b/compiler_and_linker/unsorted/GCCInlineAsm.c deleted file mode 100644 index 897df9b..0000000 --- a/compiler_and_linker/unsorted/GCCInlineAsm.c +++ /dev/null @@ -1,230 +0,0 @@ -#include "compiler/GCCInlineAsm.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInt64.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/InlineAsm.h" -#include "compiler/objects.h" - -Statement *first_ST_ASM; -IALookupResult gcc_name_list[20]; -int gcc_name_list_index; - -void InlineAsm_SkipComment(void) { - while (1) { - if (tk != '/') - break; - if (lookahead() != '*') - break; - - tk = lex(); - while (!((tk = lex()) == '*' && (tk = lex()) == '/')) { - // nothing - } - tk = lex(); - } -} - -static char gcc_parse_attribute(void) { - char ch; - - while (tk == TK_EOL) - tk = lex(); - - if (tk != '"') - CError_Error(CErrorStr105); - - while ((tk = lex()) != TK_IDENTIFIER) { - // nothing - } - - ch = tkidentifier->name[0]; - - if ((tk = lex()) != '"') - CError_Error(CErrorStr105); - tk = lex(); - - return ch; -} - -static void gcc_parse_name(Boolean flag, char attribute) { - IALookupResult *nameentry; - ENode *expr; - Object *tempobj; - ENode *tempexpr; - Statement *stmt; - - while (tk == TK_EOL) - tk = lex(); - - if (tk != '(') - CError_Error(CErrorStr114); - - tk = lex(); - - if (flag) { - if (tk != TK_IDENTIFIER) - CError_Error(CErrorStr105); - - InlineAsm_LookupSymbol(tkidentifier, &gcc_name_list[++gcc_name_list_index]); - if (gcc_name_list[gcc_name_list_index].object && gcc_name_list[gcc_name_list_index].object->u.var.info) - gcc_name_list[gcc_name_list_index].object->u.var.info->used = 1; - - tk = lex(); - } else { - in_assembler = 0; - cprep_nostring = 0; - nameentry = &gcc_name_list[++gcc_name_list_index]; - - expr = expression(); - if (attribute == 'i' || attribute == 'I') { - if (!ENODE_IS(expr, EINTCONST)) - CError_Error(CErrorStr144); - nameentry->value = CInt64_GetULong(&expr->data.intval); - nameentry->has_value = 1; - } else { - tempobj = create_temp_object(expr->rtype); - tempexpr = create_objectnode(tempobj); - if (tempobj->u.var.info) - tempobj->u.var.info->used = 1; - expr = makediadicnode(tempexpr, expr, EASS); - - stmt = CFunc_InsertBeforeStatement(ST_EXPRESSION, first_ST_ASM); - first_ST_ASM = stmt->next; - if (!first_ST_ASM->next) - curstmt = first_ST_ASM; - stmt->expr = expr; - - nameentry->name = tempobj->name; - nameentry->object = tempobj; - nameentry->label = NULL; - nameentry->type = NULL; - nameentry->has_value = 0; - } - } - - cprep_nostring = 1; - in_assembler = 1; - - if (tk != ')') - CError_Error(CErrorStr115); - tk = lex(); -} - -static void gcc_parse_expression(Boolean flag) { - while (1) { - gcc_parse_name(flag, gcc_parse_attribute()); - if (tk != ',') - break; - tk = lex(); - } -} - -static void gcc_parse_input(void) { - if (tk == ':') { - if ((tk = lex()) == ':' || tk == ')' || tk == '}') - return; - gcc_parse_expression(0); - } -} - -static void gcc_parse_output(void) { - if (tk == ':') { - if ((tk = lex()) == ':' || tk == ')' || tk == '}') - return; - gcc_parse_expression(1); - } -} - -static void gcc_parse_killed(void) { - if (tk == ':') { - while (1) { - if ((tk = lex()) != '"') - return; - - tk = lex(); - while (1) { - if (tk == '"') { - if (lookahead() == ',') { - tk = lex(); - break; - } - tk = lex(); - return; - } - tk = lex(); - } - } - } -} - -static void gcc_replace_arg_st_asm(Statement *stmt) { - InlineAsm *ia; - int i; - IAOperand *op; - short effect; - short rclass; - SInt32 num; - - if ((ia = (InlineAsm *) stmt->expr)) { - for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { - switch (op->type) { - case IAOpnd_Imm: - case IAOpnd_Reg: - case IAOpnd_3: - case IAOpnd_4: - case IAOpnd_Lab: - break; - - case IAOpnd_6: - if (op->u.unk6.unk4 == 2) { - effect = op->u.unk6.effect; - rclass = op->u.unk6.rclass; - num = op->u.unk6.num; - op->type = IAOpnd_Reg; - op->u.reg.effect = effect; - op->u.reg.rclass = rclass; - op->u.reg.object = NULL; - if (num <= gcc_name_list_index) - op->u.reg.object = gcc_name_list[num].object; - else - CError_Error(CErrorStr144); - op->u.reg.num = 0; - } else { - CError_FATAL(365); - } - break; - - case IAOpnd_7: - op->type = IAOpnd_Imm; - op->u.imm.value = gcc_name_list[op->u.unk7.value].value; - break; - } - } - } -} - -static void gcc_replace_arg(void) { - Statement *stmt; - - for (stmt = first_ST_ASM; stmt; stmt = stmt->next) { - if (stmt->type == ST_ASM) - gcc_replace_arg_st_asm(stmt); - } -} - -void InlineAsm_gcc_parse(void) { - gcc_name_list_index = -1; - cprep_eoltokens = 0; - - if (tk == TK_EOL) - tk = lex(); - - gcc_parse_output(); - gcc_parse_input(); - gcc_parse_killed(); - gcc_replace_arg(); -} diff --git a/compiler_and_linker/unsorted/IROUseDef.c b/compiler_and_linker/unsorted/IROUseDef.c deleted file mode 100644 index 19d39ff..0000000 --- a/compiler_and_linker/unsorted/IROUseDef.c +++ /dev/null @@ -1,1432 +0,0 @@ -#include "compiler/IROUseDef.h" -#include "compiler/IRODump.h" -#include "compiler/IROVars.h" -#include "compiler/IroFlowgraph.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroMalloc.h" -#include "compiler/IroPointerAnalysis.h" -#include "compiler/IroTransform.h" -#include "compiler/IroUtil.h" -#include "compiler/CompilerTools.h" -#include "compiler/CError.h" -#include "compiler/CFunc.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/objects.h" -#include "compiler/types.h" -#include "compiler/InlineAsm.h" -#include "compiler/InlineAsmPPC.h" - -ENodeType IRO_NonAssignmentOp[MAXEXPR]; -typedef CInt64 (*AssignmentFoldingFunc)(CInt64, CInt64); -static AssignmentFoldingFunc AssignmentFoldingFunction[MAXEXPR]; -static SInt32 NumDefs; -static IRODef *FirstDef; -static IRODef *LastDef; -static SInt32 NumUses; -static BitVector *Reaches; -static BitVector *MightReachAnyUse; -static BitVector *alldefs; -static BitVector *alluses; -static BitVector *defset; -static BitVector *useset; -IROUse *IRO_FirstVarUse; -IROUse *IRO_LastVarUse; - -// forward decls -static void AddDefToRange(IRODef *def); - -static void MakeDef(VarRecord *var, IROLinear *linear, IRONode *node, Boolean flag) { - IRODef *def = oalloc(sizeof(IRODef)); - - def->index = NumDefs++; - def->node = node; - def->linear = linear; - def->var = var; - def->globalnext = NULL; - def->x18 = 0; - def->x1A = Inline_IsObjectData(var->object); - def->x1B = var->xB; - def->x1C = flag; - def->x1D = 0; - - if (FirstDef) - LastDef->globalnext = def; - else - FirstDef = def; - LastDef = def; - - def->varnext = var->defs; - var->defs = def; -} - -static void MakeUse(VarRecord *var, IROLinear *linear, IRONode *node) { - IROUse *use = oalloc(sizeof(IROUse)); - - use->index = NumUses++; - use->node = node; - use->linear = linear; - use->var = var; - use->globalnext = NULL; - use->x1C = 0; - - if (IRO_FirstVarUse) - IRO_LastVarUse->globalnext = use; - else - IRO_FirstVarUse = use; - IRO_LastVarUse = use; - - use->varnext = var->uses; - var->uses = use; -} - -static void FindDefsAndUses(void) { - VarRecord *var; - IROLinear *linear; - IRONode *node; - - NumDefs = 0; - NumUses = 0; - IRO_FirstVarUse = NULL; - FirstDef = NULL; - - for (var = IRO_FirstVar; var; var = var->next) { - var->defs = NULL; - var->uses = NULL; - var->xC = 0; - } - - for (node = IRO_FirstNode; node; node = node->nextnode) { - for (linear = node->first; linear; linear = linear->next) { - if (IS_LINEAR_ENODE(linear, EOBJREF)) { - Object *obj = linear->u.node->data.objref; - if ((linear->flags & IROLF_Ind) && (!(linear->flags & IROLF_Assigned) || (linear->flags & IROLF_Used))) { - if ((var = IRO_FindVar(obj, 0, 1))) - MakeUse(var, linear, node); - } - } - - if (IRO_IsAssignment(linear) && (var = IRO_FindAssigned(linear))) { - MakeDef( - var, - linear, - node, - (linear->rtype->size == var->object->type->size) && !IRO_IsBitField - ); - } - - if (linear->type == IROLinearAsm) { - IAEffects effects; - int i; - CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); - - for (i = 0; i < effects.numoperands; i++) { - var = IRO_FindVar(effects.operands[i].object, 0, 1); - switch (effects.operands[i].type) { - case IAEffect_0: - MakeUse(var, linear, node); - break; - case IAEffect_1: - MakeDef( - var, - linear, - node, - (effects.operands[i].offset == 0) && (effects.operands[i].size == var->object->type->size) - ); - break; - case IAEffect_2: - MakeDef(var, linear, node, 0); - break; - case IAEffect_4: - MakeUse(var, linear, node); - MakeDef( - var, - linear, - node, - (effects.operands[i].offset == 0) && (effects.operands[i].size == var->object->type->size) - ); - break; - } - } - } - - if (linear == node->last) - break; - } - } - - for (var = IRO_FirstVar; var; var = var->next) - MakeDef(var, NULL, NULL, 1); -} - -static void MarkUses(Object *obj) { - VarRecord *var; - IRODef *def; - - if ((var = IRO_FindVar(obj, 0, 1))) { - for (def = var->defs; def; def = def->varnext) { - if (Bv_IsBitSet(def->index, Reaches)) { - Bv_SetBit(def->index, MightReachAnyUse); - def->x18++; - } - } - - var->xC = 1; - } -} - -static Boolean IsIncOrDec(IROLinear *linear) { - switch (linear->type) { - case IROLinearOp1Arg: - if (linear->nodetype == EPOSTINC || linear->nodetype == EPOSTDEC || linear->nodetype == EPREINC || linear->nodetype == EPREDEC) { - if (!(linear->u.monadic->flags & IROLF_BitfieldIndirect)) - return 1; - } - break; - case IROLinearOp2Arg: - if (linear->nodetype == EADDASS || linear->nodetype == ESUBASS) { - if (IRO_IsIntConstant(linear->u.diadic.right) && !(linear->u.diadic.left->flags & IROLF_BitfieldIndirect)) - return 1; - } - break; - } - - return 0; -} - -static Boolean IsOtherSelfAssignment(IROLinear *linear) { - switch (linear->type) { - case IROLinearOp2Arg: - switch (linear->nodetype) { - case EMULASS: - case EDIVASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - if (IRO_IsIntConstant(linear->u.diadic.right)) - return 1; - break; - } - break; - } - - return 0; -} - -CInt64 IRO_GetSelfAssignmentVal(IROLinear *linear) { - CInt64 result; - - if (linear->type == IROLinearOp1Arg) { - switch (linear->nodetype) { - case EPOSTINC: - case EPREINC: - CInt64_SetLong(&result, 1); - break; - case EPOSTDEC: - case EPREDEC: - CInt64_SetLong(&result, -1); - break; - default: - CError_FATAL(445); - } - - if (IS_TYPE_POINTER_ONLY(linear->rtype)) { - CInt64 mul; - CInt64_SetLong(&mul, TPTR_TARGET(linear->rtype)->size); - result = CInt64_Mul(result, mul); - } - } else if (linear->type == IROLinearOp2Arg) { - switch (linear->nodetype) { - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - result = linear->u.diadic.right->u.node->data.intval; - break; - case ESUBASS: - result = linear->u.diadic.right->u.node->data.intval; - result = CInt64_Neg(result); - break; - default: - CError_FATAL(491); - } - } else { - CError_FATAL(496); - } - - return result; -} - -static void UpdateUse(IROLinear *linear, CInt64 val, Type *type) { - IROLinear *father; - IROLinear *repl; - IROLinear *newdiadic; - - if ((father = IRO_LocateFather(linear))) { - switch (father->type) { - case IROLinearOp1Arg: - switch (father->nodetype) { - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - val = CInt64_Add(val, IRO_GetSelfAssignmentVal(father)); - father->nodetype = EADDASS; - father->type = IROLinearOp2Arg; - repl = IRO_NewIntConst(val, type); - father->u.diadic.right = repl; - IRO_PasteAfter(repl, repl, linear); - return; - } - break; - case IROLinearOp2Arg: - if (IRO_IsIntConstant(father->u.diadic.right)) { - switch (father->nodetype) { - case EADD: - case EADDASS: - father->u.diadic.right->u.node->data.intval = CInt64_Add( - father->u.diadic.right->u.node->data.intval, val); - return; - case ESUB: - case ESUBASS: - father->u.diadic.right->u.node->data.intval = CInt64_Sub( - father->u.diadic.right->u.node->data.intval, val); - return; - } - } - break; - } - } - - repl = IRO_NewIntConst(val, type); - newdiadic = IRO_NewLinear(IROLinearOp2Arg); - newdiadic->index = ++IRO_NumLinear; - newdiadic->nodetype = EADD; - newdiadic->u.diadic.left = linear; - newdiadic->u.diadic.right = repl; - newdiadic->rtype = linear->rtype; - repl->next = newdiadic; - IRO_LocateFather_Cut_And_Paste_Without_Nopping(linear, newdiadic); - IRO_PasteAfter(repl, newdiadic, linear); -} - -void IRO_InitializeNonAssignmentOpArray(void) { - int i; - - for (i = 0; i < MAXEXPR; i++) - IRO_NonAssignmentOp[i] = MAXEXPR; - - IRO_NonAssignmentOp[EPOSTINC] = MAXEXPR; - IRO_NonAssignmentOp[EPOSTDEC] = MAXEXPR; - IRO_NonAssignmentOp[EPREINC] = MAXEXPR; - IRO_NonAssignmentOp[EPREDEC] = MAXEXPR; - IRO_NonAssignmentOp[EINDIRECT] = MAXEXPR; - IRO_NonAssignmentOp[EMONMIN] = MAXEXPR; - IRO_NonAssignmentOp[EBINNOT] = MAXEXPR; - IRO_NonAssignmentOp[ELOGNOT] = MAXEXPR; - IRO_NonAssignmentOp[EFORCELOAD] = MAXEXPR; - IRO_NonAssignmentOp[EMUL] = MAXEXPR; - IRO_NonAssignmentOp[EMULV] = MAXEXPR; - IRO_NonAssignmentOp[EDIV] = MAXEXPR; - IRO_NonAssignmentOp[EMODULO] = MAXEXPR; - IRO_NonAssignmentOp[EADDV] = MAXEXPR; - IRO_NonAssignmentOp[ESUBV] = MAXEXPR; - IRO_NonAssignmentOp[EADD] = MAXEXPR; - IRO_NonAssignmentOp[ESUB] = MAXEXPR; - IRO_NonAssignmentOp[ESHL] = MAXEXPR; - IRO_NonAssignmentOp[ESHR] = MAXEXPR; - IRO_NonAssignmentOp[ELESS] = MAXEXPR; - IRO_NonAssignmentOp[EGREATER] = MAXEXPR; - IRO_NonAssignmentOp[ELESSEQU] = MAXEXPR; - IRO_NonAssignmentOp[EGREATEREQU] = MAXEXPR; - IRO_NonAssignmentOp[EEQU] = MAXEXPR; - IRO_NonAssignmentOp[ENOTEQU] = MAXEXPR; - IRO_NonAssignmentOp[EAND] = MAXEXPR; - IRO_NonAssignmentOp[EXOR] = MAXEXPR; - IRO_NonAssignmentOp[EOR] = MAXEXPR; - IRO_NonAssignmentOp[ELAND] = MAXEXPR; - IRO_NonAssignmentOp[ELOR] = MAXEXPR; - IRO_NonAssignmentOp[EASS] = MAXEXPR; - IRO_NonAssignmentOp[EMULASS] = EMUL; - IRO_NonAssignmentOp[EDIVASS] = EDIV; - IRO_NonAssignmentOp[EMODASS] = EMODULO; - IRO_NonAssignmentOp[EADDASS] = EADD; - IRO_NonAssignmentOp[ESUBASS] = ESUB; - IRO_NonAssignmentOp[ESHLASS] = ESHL; - IRO_NonAssignmentOp[ESHRASS] = ESHR; - IRO_NonAssignmentOp[EANDASS] = EAND; - IRO_NonAssignmentOp[EXORASS] = EXOR; - IRO_NonAssignmentOp[EORASS] = EOR; - IRO_NonAssignmentOp[ECOMMA] = MAXEXPR; - IRO_NonAssignmentOp[EPMODULO] = MAXEXPR; - IRO_NonAssignmentOp[EROTL] = MAXEXPR; - IRO_NonAssignmentOp[EROTR] = MAXEXPR; - IRO_NonAssignmentOp[EBCLR] = MAXEXPR; - IRO_NonAssignmentOp[EBTST] = MAXEXPR; - IRO_NonAssignmentOp[EBSET] = MAXEXPR; - IRO_NonAssignmentOp[ETYPCON] = MAXEXPR; - IRO_NonAssignmentOp[EBITFIELD] = MAXEXPR; - IRO_NonAssignmentOp[EINTCONST] = MAXEXPR; - IRO_NonAssignmentOp[EFLOATCONST] = MAXEXPR; - IRO_NonAssignmentOp[ESTRINGCONST] = MAXEXPR; - IRO_NonAssignmentOp[ECOND] = MAXEXPR; - IRO_NonAssignmentOp[EFUNCCALL] = MAXEXPR; - IRO_NonAssignmentOp[EFUNCCALLP] = MAXEXPR; - IRO_NonAssignmentOp[EOBJREF] = MAXEXPR; - IRO_NonAssignmentOp[EMFPOINTER] = MAXEXPR; - IRO_NonAssignmentOp[ENULLCHECK] = MAXEXPR; - IRO_NonAssignmentOp[EPRECOMP] = MAXEXPR; - IRO_NonAssignmentOp[ETEMP] = MAXEXPR; - IRO_NonAssignmentOp[EARGOBJ] = MAXEXPR; - IRO_NonAssignmentOp[ELOCOBJ] = MAXEXPR; - IRO_NonAssignmentOp[ELABEL] = MAXEXPR; - IRO_NonAssignmentOp[ESETCONST] = MAXEXPR; - IRO_NonAssignmentOp[ENEWEXCEPTION] = MAXEXPR; - IRO_NonAssignmentOp[ENEWEXCEPTIONARRAY] = MAXEXPR; - IRO_NonAssignmentOp[EOBJLIST] = MAXEXPR; - IRO_NonAssignmentOp[EMEMBER] = MAXEXPR; - IRO_NonAssignmentOp[ETEMPLDEP] = MAXEXPR; - IRO_NonAssignmentOp[EINSTRUCTION] = MAXEXPR; - IRO_NonAssignmentOp[EDEFINE] = MAXEXPR; - IRO_NonAssignmentOp[EREUSE] = MAXEXPR; - IRO_NonAssignmentOp[EASSBLK] = MAXEXPR; - IRO_NonAssignmentOp[EVECTOR128CONST] = MAXEXPR; - IRO_NonAssignmentOp[ECONDASS] = MAXEXPR; -} - -void IRO_InitializeAssignmentFoldingFunctionArray(void) { - int i; - - for (i = 0; i < MAXEXPR; i++) - AssignmentFoldingFunction[i] = NULL; - - AssignmentFoldingFunction[EPOSTINC] = NULL; - AssignmentFoldingFunction[EPOSTDEC] = NULL; - AssignmentFoldingFunction[EPREINC] = NULL; - AssignmentFoldingFunction[EPREDEC] = NULL; - AssignmentFoldingFunction[EINDIRECT] = NULL; - AssignmentFoldingFunction[EMONMIN] = NULL; - AssignmentFoldingFunction[EBINNOT] = NULL; - AssignmentFoldingFunction[ELOGNOT] = NULL; - AssignmentFoldingFunction[EFORCELOAD] = NULL; - AssignmentFoldingFunction[EMUL] = NULL; - AssignmentFoldingFunction[EMULV] = NULL; - AssignmentFoldingFunction[EDIV] = NULL; - AssignmentFoldingFunction[EMODULO] = NULL; - AssignmentFoldingFunction[EADDV] = NULL; - AssignmentFoldingFunction[ESUBV] = NULL; - AssignmentFoldingFunction[EADD] = NULL; - AssignmentFoldingFunction[ESUB] = NULL; - AssignmentFoldingFunction[ESHL] = NULL; - AssignmentFoldingFunction[ESHR] = NULL; - AssignmentFoldingFunction[ELESS] = NULL; - AssignmentFoldingFunction[EGREATER] = NULL; - AssignmentFoldingFunction[ELESSEQU] = NULL; - AssignmentFoldingFunction[EGREATEREQU] = NULL; - AssignmentFoldingFunction[EEQU] = NULL; - AssignmentFoldingFunction[ENOTEQU] = NULL; - AssignmentFoldingFunction[EAND] = NULL; - AssignmentFoldingFunction[EXOR] = NULL; - AssignmentFoldingFunction[EOR] = NULL; - AssignmentFoldingFunction[ELAND] = NULL; - AssignmentFoldingFunction[ELOR] = NULL; - AssignmentFoldingFunction[EASS] = NULL; - AssignmentFoldingFunction[EMULASS] = CInt64_Mul; - AssignmentFoldingFunction[EDIVASS] = CInt64_Mul; - AssignmentFoldingFunction[EMODASS] = NULL; - AssignmentFoldingFunction[EADDASS] = CInt64_Add; - AssignmentFoldingFunction[ESUBASS] = CInt64_Add; - AssignmentFoldingFunction[ESHLASS] = CInt64_Add; - AssignmentFoldingFunction[ESHRASS] = CInt64_Add; - AssignmentFoldingFunction[EANDASS] = CInt64_And; - AssignmentFoldingFunction[EXORASS] = CInt64_Xor; - AssignmentFoldingFunction[EORASS] = CInt64_Or; - AssignmentFoldingFunction[ECOMMA] = NULL; - AssignmentFoldingFunction[EPMODULO] = NULL; - AssignmentFoldingFunction[EROTL] = NULL; - AssignmentFoldingFunction[EROTR] = NULL; - AssignmentFoldingFunction[EBCLR] = NULL; - AssignmentFoldingFunction[EBTST] = NULL; - AssignmentFoldingFunction[EBSET] = NULL; - AssignmentFoldingFunction[ETYPCON] = NULL; - AssignmentFoldingFunction[EBITFIELD] = NULL; - AssignmentFoldingFunction[EINTCONST] = NULL; - AssignmentFoldingFunction[EFLOATCONST] = NULL; - AssignmentFoldingFunction[ESTRINGCONST] = NULL; - AssignmentFoldingFunction[ECOND] = NULL; - AssignmentFoldingFunction[EFUNCCALL] = NULL; - AssignmentFoldingFunction[EFUNCCALLP] = NULL; - AssignmentFoldingFunction[EOBJREF] = NULL; - AssignmentFoldingFunction[EMFPOINTER] = NULL; - AssignmentFoldingFunction[ENULLCHECK] = NULL; - AssignmentFoldingFunction[EPRECOMP] = NULL; - AssignmentFoldingFunction[ETEMP] = NULL; - AssignmentFoldingFunction[EARGOBJ] = NULL; - AssignmentFoldingFunction[ELOCOBJ] = NULL; - AssignmentFoldingFunction[ELABEL] = NULL; - AssignmentFoldingFunction[ESETCONST] = NULL; - AssignmentFoldingFunction[ENEWEXCEPTION] = NULL; - AssignmentFoldingFunction[ENEWEXCEPTIONARRAY] = NULL; - AssignmentFoldingFunction[EOBJLIST] = NULL; - AssignmentFoldingFunction[EMEMBER] = NULL; - AssignmentFoldingFunction[ETEMPLDEP] = NULL; - AssignmentFoldingFunction[EINSTRUCTION] = NULL; - AssignmentFoldingFunction[EDEFINE] = NULL; - AssignmentFoldingFunction[EREUSE] = NULL; - AssignmentFoldingFunction[EASSBLK] = NULL; - AssignmentFoldingFunction[EVECTOR128CONST] = NULL; - AssignmentFoldingFunction[ECONDASS] = NULL; -} - -static void UpdateUseForOtherSelfAssignment(IROLinear *a, IROLinear *b, Type *type) { - CInt64 val; - IROLinear *father; - IROLinear *repl; - IROLinear *newdiadic; - - val = IRO_GetSelfAssignmentVal(b); - if ((father = IRO_LocateFather(a)) && father->type == IROLinearOp2Arg && IRO_IsIntConstant(father->u.diadic.right)) { - CInt64 var_30 = father->u.diadic.right->u.node->data.intval; - if (AssignmentFoldingFunction[b->nodetype] && ((father->nodetype == b->nodetype) || (father->nodetype == IRO_NonAssignmentOp[b->nodetype]))) { - CInt64 v; - CInt64 folded; - CInt64_SetLong(&v, b->rtype->size * 8); - folded = AssignmentFoldingFunction[b->nodetype](var_30, val); - if (b->nodetype == ESHRASS && !is_unsigned(b->rtype)) { - if (CInt64_LessU(var_30, v) && CInt64_LessU(val, v)) { - if (CInt64_GreaterEqualU(folded, v)) - folded = CInt64_Sub(v, cint64_one); - father->u.diadic.right->u.node->data.intval = folded; - return; - } - } else { - father->u.diadic.right->u.node->data.intval = folded; - return; - } - } else { - switch (b->nodetype) { - case EMULASS: - if (father->nodetype == ESHL || father->nodetype == ESHLASS) { - SInt32 powvalue; - if (IRO_IsPow2(b->u.diadic.right, &powvalue)) { - if (powvalue > 0) { - CInt64 v; - CInt64_SetLong(&v, powvalue); - father->u.diadic.right->u.node->data.intval = CInt64_Add(v, var_30); - } - } else { - father->nodetype = (father->nodetype == ESHL) ? EMUL : EMULASS; - var_30 = CInt64_Shl(cint64_one, var_30); - father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val); - } - return; - } - break; - case EDIVASS: - if ((father->nodetype == ESHR || father->nodetype == ESHRASS) && is_unsigned(father->rtype)) { - SInt32 powvalue; - if (IRO_IsPow2(b->u.diadic.right, &powvalue)) { - if (powvalue > 0) { - CInt64 v; - CInt64_SetLong(&v, powvalue); - father->u.diadic.right->u.node->data.intval = CInt64_Add(v, var_30); - } - } else { - father->nodetype = (father->nodetype == ESHR) ? EDIV : EDIVASS; - var_30 = CInt64_Shl(cint64_one, var_30); - father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val); - } - return; - } - break; - case ESHLASS: - if (father->nodetype == EMUL || father->nodetype == EMULASS) { - SInt32 powvalue; - if (IRO_IsPow2(father->u.diadic.right, &powvalue)) { - if (powvalue > 0) { - CInt64 v; - father->nodetype = (father->nodetype == EMUL) ? ESHL : ESHLASS; - CInt64_SetLong(&v, powvalue); - father->u.diadic.right->u.node->data.intval = CInt64_Add(v, val); - } - } else { - val = CInt64_Shl(cint64_one, val); - father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val); - } - return; - } else if (father->nodetype == ESHR || father->nodetype == ESHRASS) { - if (CInt64_Equal(var_30, val) && is_unsigned(father->rtype)) { - father->nodetype = (father->nodetype == ESHR) ? EAND : EANDASS; - if (father->rtype->size < 8) { - CInt64 v; - CInt64_SetLong(&v, 64 - (father->rtype->size * 8)); - val = CInt64_Add(val, v); - } - father->u.diadic.right->u.node->data.intval = CInt64_ShrU(cint64_negone, val); - return; - } - } - break; - case ESHRASS: - if ((father->nodetype == EDIV || father->nodetype == EDIVASS) && is_unsigned(father->rtype)) { - SInt32 powvalue; - if (IRO_IsPow2(father->u.diadic.right, &powvalue)) { - if (powvalue > 0) { - CInt64 v; - father->nodetype = (father->nodetype == EDIV) ? ESHR : ESHRASS; - CInt64_SetLong(&v, powvalue); - father->u.diadic.right->u.node->data.intval = CInt64_Add(v, val); - } - } else { - val = CInt64_Shl(cint64_one, val); - father->u.diadic.right->u.node->data.intval = CInt64_Mul(var_30, val); - } - return; - } else if (father->nodetype == ESHL || father->nodetype == ESHLASS) { - if (CInt64_Equal(var_30, val)) { - father->nodetype = (father->nodetype == ESHL) ? EAND : EANDASS; - father->u.diadic.right->u.node->data.intval = CInt64_Shl(cint64_negone, val); - return; - } - } - break; - } - } - } - - repl = IRO_NewIntConst(val, type); - newdiadic = IRO_NewLinear(IROLinearOp2Arg); - newdiadic->index = ++IRO_NumLinear; - newdiadic->nodetype = IRO_NonAssignmentOp[b->nodetype]; - newdiadic->u.diadic.left = a; - newdiadic->u.diadic.right = repl; - newdiadic->rtype = a->rtype; - repl->next = newdiadic; - IRO_LocateFather_Cut_And_Paste_Without_Nopping(a, newdiadic); - IRO_PasteAfter(repl, newdiadic, a); -} - -static Boolean PropagateIncsAndDecs(void) { - IRODef *def; - Boolean result; - - result = 0; - def = FirstDef; - while (def) { - if ( - def->linear && - def->x1C && - IsIncOrDec(def->linear) && - !(def->linear->flags & IROLF_Reffed) && - (IS_TYPE_INT_OR_ENUM(def->linear->rtype) || IS_TYPE_POINTER_ONLY(def->linear->rtype)) && - IRO_TypesEqual(def->linear->rtype, def->var->object->type) && - !is_volatile_object(def->var->object) - ) { - IROUse *use; - IROUse *use2; - IROLinear *father; - CInt64 val; - SInt32 i; - Type *type; - - for (use = def->var->uses, i = 0; use; use = use->varnext) { - if (Bv_IsBitSet(def->index, use->x18)) { - if ( - use->x1C == 1 && - use->linear->type == IROLinearOperand && - (father = IRO_LocateFather(use->linear)) && - IRO_IsVariable(father) && - IRO_TypesEqual(def->linear->rtype, father->rtype) - ) { - if (use->linear->flags & IROLF_Assigned) { - if (!((father = IRO_LocateFather(father)) && IsIncOrDec(father) && !(father->flags & IROLF_Reffed))) - goto nextDef; - } - i++; - } else { - goto nextDef; - } - } - } - - if (i == def->x18) { - for (use = def->var->uses; use; use = use->varnext) { - if (Bv_IsBitSet(def->index, use->x18)) { - IRO_Dump("Propagating inc/dec from %d to %d\n", def->linear->index, use->linear->index); - father = IRO_LocateFather(use->linear); - val = IRO_GetSelfAssignmentVal(def->linear); - type = def->linear->rtype; - if (IS_TYPE_POINTER_ONLY(def->linear->rtype)) - type = TYPE(&stunsignedlong); - UpdateUse(father, val, type); - - result = 1; - for (use2 = def->var->uses; use2; use2 = use2->varnext) { - if (use2->linear == def->linear->u.monadic->u.diadic.left) { - use->x1C = use2->x1C; - Bv_Copy(use2->x18, use->x18); - break; - } - } - } - } - def->x18 = 0; - IRO_NopNonSideEffects(def->linear, -1); - def->linear->type = IROLinearNop; - IRO_Dump("Removing deadddd assignment %d\n", def->linear->index); - } - } - nextDef: - def = def->globalnext; - } - - return result; -} - -static Boolean PropagateOtherSelfAssignments(void) { - IRODef *def; - Boolean result; - - result = 0; - - def = FirstDef; - while (def) { - if ( - def->linear && - def->x1C && - IsOtherSelfAssignment(def->linear) && - !(def->linear->flags & IROLF_Reffed) && - IS_TYPE_INT_OR_ENUM(def->linear->rtype) && - IRO_TypesEqual(def->linear->rtype, def->var->object->type) && - !is_volatile_object(def->var->object) - ) - { - IROUse *use; - IROUse *use2; - IROLinear *father; - SInt32 i; - Type *type; - - for (use = def->var->uses, i = 0; use; use = use->varnext) { - if (Bv_IsBitSet(def->index, use->x18)) { - if ( - use->x1C == 1 && - use->linear->type == IROLinearOperand && - (father = IRO_LocateFather(use->linear)) && - IRO_IsVariable(father) && - IRO_TypesEqual(def->linear->rtype, father->rtype) - ) { - if (use->linear->flags & IROLF_Assigned) { - if (!((father = IRO_LocateFather(father)) && IsOtherSelfAssignment(father) && (father->nodetype == def->linear->nodetype) && !(father->flags & IROLF_Reffed))) - goto nextDef; - } - i++; - } else { - goto nextDef; - } - } - } - - if (i == def->x18) { - for (use = def->var->uses; use; use = use->varnext) { - if (Bv_IsBitSet(def->index, use->x18)) { - IRO_Dump("Propagating self assignment from %d to %d\n", def->linear->index, use->linear->index); - father = IRO_LocateFather(use->linear); - UpdateUseForOtherSelfAssignment(father, def->linear, def->linear->rtype); - - result = 1; - for (use2 = def->var->uses; use2; use2 = use2->varnext) { - if (use2->linear == def->linear->u.monadic->u.diadic.left) { - use->x1C = use2->x1C; - Bv_Copy(use2->x18, use->x18); - break; - } - } - } - } - def->x18 = 0; - IRO_NopNonSideEffects(def->linear, -1); - def->linear->type = IROLinearNop; - IRO_Dump("Removing deadddd assignment %d\n", def->linear->index); - } - } - nextDef: - def = def->globalnext; - } - - return result; -} - -static void MarkUsesByIndirect(IROLinear *linear, BitVector *a, BitVector *b) { - IROListNode *list; - IROLinear *nd; - Object *obj; - VarRecord *var; - Boolean foundObjRef; - IROListNode *scan; - IRODef *def; - Boolean found; - - found = 0; - - if (linear && copts.opt_pointer_analysis && linear->pointsToFunction && FunctionName) { - IROListNode *resultList; - resultList = NULL; - PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, linear, &resultList); - if ((list = resultList)) { - for (scan = list; scan; scan = scan->nextList) { - if (!scan->list.head || !scan->list.tail) { - found = 1; - break; - } - - foundObjRef = 0; - for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { - if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { - foundObjRef = 1; - break; - } - } - - if (!foundObjRef) { - found = 1; - break; - } - } - - if (!found) { - while (list) { - for (nd = list->list.head; nd != list->list.tail->next; nd = nd->next) { - if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { - obj = nd->u.node->data.objref; - CError_ASSERT(1422, obj != NULL); - var = IRO_FindVar(obj, 1, 1); - CError_ASSERT(1424, var != NULL); - - for (def = var->defs; def; def = def->varnext) { - if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) { - def->x18++; - Bv_SetBit(def->index, MightReachAnyUse); - } - } - } - } - list = list->nextList; - } - } - - while (resultList) { - IROListNode *next = resultList->nextList; - IRO_free(resultList); - resultList = next; - } - } else { - found = 1; - } - } else { - found = 1; - } - - if (found) { - Bv_Copy(Reaches, a); - Bv_And(b, a); - Bv_Or(a, MightReachAnyUse); - for (def = FirstDef; def; def = def->globalnext) { - if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) - def->x18++; - } - } -} - -static void MarkUsesByFunctionCall(IROLinear *linear, BitVector *a, BitVector *b) { - ObjectList *olist; - IROLinear *funcnd; - IROListNode *list; - IROLinear *nd; - Object *obj; - VarRecord *var; - Boolean foundObjRef; - IROListNode *scan; - IRODef *def; - Boolean found; - - found = 0; - - if ((funcnd = linear->u.funccall.linear8) && copts.opt_pointer_analysis && funcnd->pointsToFunction && FunctionName) { - IROListNode *resultList; - ObjectList *depsList; - - resultList = NULL; - PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, funcnd, &resultList); - if (resultList) { - for (scan = resultList; scan; scan = scan->nextList) { - if (!scan->list.head || !scan->list.tail) { - found = 1; - break; - } - - foundObjRef = 0; - for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { - if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { - foundObjRef = 1; - obj = nd->u.node->data.objref; - CError_ASSERT(1522, obj != NULL); - - depsList = NULL; - PointerAnalysis_GetFunctionDependencies(obj, linear, &depsList); - for (olist = depsList; olist; olist = olist->next) { - if (!olist->object) { - found = 1; - break; - } - } - - while (depsList) { - olist = depsList->next; - IRO_free(depsList); - depsList = olist; - } - - if (found) - break; - } - } - - if (!foundObjRef) - found = 1; - if (found) - break; - } - - if (!found) { - for (list = resultList; list; list = list->nextList) { - for (nd = list->list.head; nd != list->list.tail->next; nd = nd->next) { - if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { - obj = nd->u.node->data.objref; - depsList = NULL; - PointerAnalysis_GetFunctionDependencies(obj, linear, &depsList); - - for (olist = depsList; olist; olist = olist->next) { - var = IRO_FindVar(olist->object, 1, 1); - CError_ASSERT(1573, var != NULL); - - for (def = var->defs; def; def = def->varnext) { - if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) { - def->x18++; - Bv_SetBit(def->index, MightReachAnyUse); - } - } - } - - while (depsList) { - olist = depsList->next; - IRO_free(depsList); - depsList = olist; - } - } - } - } - } - - while (resultList) { - IROListNode *next = resultList->nextList; - IRO_free(resultList); - resultList = next; - } - } else { - found = 1; - } - } else { - found = 1; - } - - if (found) { - Bv_Copy(Reaches, a); - Bv_And(b, a); - Bv_Or(a, MightReachAnyUse); - for (def = FirstDef; def; def = def->globalnext) { - if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) - def->x18++; - } - } - - if (linear->stmt && IRO_FunctionCallMightThrowException(linear)) - IRO_WalkExcActions(linear->stmt->dobjstack, MarkUses); -} - -static Boolean UseOfVarIsInsideASimpleDefOfVar(IROUse *use) { - VarRecord *var; - VarRecord *varAss; - IROLinear *nd; - IROLinear *nd2; - - if ((var = use->var)) { - if ((nd = use->linear) && (nd->flags & IROLF_4000)) - return 0; - - while (nd && (nd->flags & IROLF_Reffed)) - nd = nd->next; - - if ( - nd && - IRO_IsAssignment(nd) && - (varAss = IRO_FindAssigned(nd)) && - varAss == var && - !IRO_HasSideEffect((nd->type == IROLinearOp1Arg) ? nd->u.monadic : nd->u.diadic.left) && - (!(nd2 = (nd->type == IROLinearOp1Arg) ? NULL : nd->u.diadic.right) || !IRO_HasSideEffect(nd2)) - ) { - return 1; - } - } - - return 0; -} - -static Boolean AllLoopDefUsesAreInSimpleLoopDefs(IRODef *def) { - VarRecord *var; - IRODef *scan; - IROUse *use; - - if ((var = def->var)) { - for (scan = var->defs; scan; scan = scan->varnext) { - if (scan->node && scan->node->loopdepth) { - for (use = var->uses; use; use = use->varnext) { - if (Bv_IsBitSet(scan->index, use->x18)) { - if (!use->node || !use->node->loopdepth || !UseOfVarIsInsideASimpleDefOfVar(use)) - return 0; - } - } - } - } - return 1; - } else { - return 0; - } -} - -static void MarkRemovableLoopDefs(void) { - IRODef *def; - IRODef *scan; - - for (def = FirstDef; def; def = def->globalnext) { - if (!def->x1A && !def->x1B && def->node && def->node->loopdepth && !def->x1D && - AllLoopDefUsesAreInSimpleLoopDefs(def) && def->var) { - for (scan = def->var->defs; scan; scan = scan->varnext) { - if (scan->node && scan->node->loopdepth) - scan->x1D = 1; - } - } - } -} - -static Boolean EliminateReffedDeadStore(IRODef *def) { - Boolean isPostIncOrDec; - IROLinear *nd; - Boolean result; - - nd = def->linear; - isPostIncOrDec = (nd->type == IROLinearOp1Arg) && (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC); - - result = IRO_LocateFather(nd) != NULL; - if (result && IRO_IsAssignment(nd) && IRO_IsModifyOp[nd->nodetype]) - result = IRO_TransformSelfAssignmentToAssignment(nd); - result = result && (nd->type == IROLinearOp2Arg) && (nd->nodetype == EASS); - - if (result) { - def->x18 = 0; - IRO_Dump("Removing referenced dead assignment %d\n", nd->index); - - if (isPostIncOrDec) { - IRO_NopNonSideEffects(nd->u.diadic.right, 0); - nd->type = IROLinearNop; - IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, nd->u.diadic.left); - } else { - IRO_NopNonSideEffects(nd->u.diadic.left, 0); - nd->type = IROLinearNop; - IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, nd->u.diadic.right); - } - } - - return result; -} - -Boolean IRO_UseDef(Boolean optDeadAssignments, Boolean optPropagation) { - Boolean result; - IRODef *gdef; - IROUse *guse; - IRODef *def; - IROUse *use; - IRONode *node; - IROLinear *nd; - VarRecord *var; - Boolean flag; - BitVector *bv3; - BitVector *bv2; - BitVector *bv; - int i; - - FindDefsAndUses(); - - IRO_CheckForUserBreak(); - - for (use = IRO_FirstVarUse; use; use = use->globalnext) - Bv_AllocVector(&use->x18, NumDefs); - Bv_AllocVector(&MightReachAnyUse, NumDefs); - Bv_AllocVector(&bv, NumDefs); - - IRO_CheckForUserBreak(); - - for (def = FirstDef; def; def = def->globalnext) { - if (def->x1A || def->x1B) - Bv_SetBit(def->index, bv); - } - - Bv_AllocVector(&bv2, NumDefs); - gdef = FirstDef; - for (node = IRO_FirstNode; node; node = node->nextnode) { - Bv_AllocVector(&node->x16, NumDefs); - Bv_AllocVector(&node->x1E, NumDefs); - Bv_AllocVector(&node->x22, NumDefs); - Bv_AllocVector(&node->x1A, NumDefs); - - for (nd = node->first; nd; nd = nd->next) { - while (gdef && gdef->linear == nd) { - Bv_SetBit(gdef->index, node->x1E); - if (gdef->x1C) { - for (def = gdef->var->defs; def; def = def->varnext) { - if (def != gdef) { - Bv_SetBit(def->index, node->x22); - Bv_ClearBit(def->index, node->x1E); - } - } - } - gdef = gdef->globalnext; - } - if (nd == node->last) - break; - } - - if (node->numpred) - Bv_Set(node->x16); - Bv_Copy(node->x1E, node->x1A); - IRO_CheckForUserBreak(); - } - - Bv_AllocVector(&bv3, NumDefs); - - do { - flag = 0; - for (node = IRO_FirstNode; node; node = node->nextnode) { - Bv_Clear(node->x16); - if (node->numpred) { - for (i = 0; i < node->numpred; i++) - Bv_Or(IRO_NodeTable[node->pred[i]]->x1A, node->x16); - } else if (node == IRO_FirstNode) { - for (var = IRO_FirstVar; var; var = var->next) - Bv_SetBit(var->defs->index, node->x16); - } - Bv_Copy(node->x16, bv3); - Bv_Minus(node->x22, bv3); - Bv_Or(node->x1E, bv3); - if (!Bv_Compare(bv3, node->x1A)) { - Bv_Copy(bv3, node->x1A); - flag = 1; - } - } - - IRO_CheckForUserBreak(); - } while (flag); - - gdef = FirstDef; - guse = IRO_FirstVarUse; - Bv_AllocVector(&Reaches, NumDefs); - - for (node = IRO_FirstNode; node; node = node->nextnode) { - Bv_Copy(node->x16, Reaches); - nd = node->first; - while (1) { - while (guse && guse->linear == nd) { - for (def = guse->var->defs; def; def = def->varnext) { - if (Bv_IsBitSet(def->index, Reaches)) { - Bv_SetBit(def->index, guse->x18); - Bv_SetBit(def->index, MightReachAnyUse); - def->x18++; - guse->x1C++; - } - } - guse = guse->globalnext; - } - - if (nd->type == IROLinearFunccall) { - MarkUsesByFunctionCall(nd, bv2, bv); - } else if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT && !IRO_IsVariable(nd)) { - MarkUsesByIndirect(nd, bv2, bv); - } else if ((nd->type == IROLinearFunccall) || - (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT && !IRO_IsVariable(nd))) { - Bv_Copy(Reaches, bv2); - Bv_And(bv, bv2); - Bv_Or(bv2, MightReachAnyUse); - for (def = FirstDef; def; def = def->globalnext) { - if (def->x1A || (def->x1B && Bv_IsBitSet(def->index, Reaches))) - def->x18++; - } - if (nd->type == IROLinearFunccall && nd->stmt && IRO_FunctionCallMightThrowException(nd)) - IRO_WalkExcActions(nd->stmt->dobjstack, MarkUses); - } - - if (nd->type == IROLinearAsm) { - IAEffects effects; - CodeGen_GetAsmEffects(nd->u.asm_stmt, &effects); - if (effects.x2) { - Bv_Copy(Reaches, bv2); - Bv_And(bv, bv2); - Bv_Or(bv2, MightReachAnyUse); - } - } - - if (nd->type == IROLinearReturn || nd->type == IROLinearEnd) { - for (def = FirstDef; def; def = def->globalnext) { - if (def->x1A && Bv_IsBitSet(def->index, Reaches)) { - Bv_SetBit(def->index, MightReachAnyUse); - def->x18++; - } - } - } - - while (gdef && gdef->linear == nd) { - if (gdef->x1C) { - for (def = gdef->var->defs; def; def = def->varnext) - Bv_ClearBit(def->index, Reaches); - } - Bv_SetBit(gdef->index, Reaches); - gdef = gdef->globalnext; - } - - if (nd == node->last) - break; - nd = nd->next; - } - } - - IRO_CheckForUserBreak(); - - result = 0; - - if (optDeadAssignments) { - MarkRemovableLoopDefs(); - for (def = FirstDef; def; def = def->globalnext) { - if (def->linear && - (!Bv_IsBitSet(def->index, MightReachAnyUse) || def->x1D) && - (copts.opt_pointer_analysis || !def->x1B) && - def->linear->type != IROLinearAsm && - (!def->linear->rtype || !CParser_IsVolatile(def->linear->rtype, def->linear->nodeflags & ENODE_FLAG_QUALS)) && - !is_volatile_object(def->var->object) - ) { - if (!(def->linear->flags & IROLF_Reffed)) { - def->x18 = 0; - IRO_NopNonSideEffects(def->linear, -1); - def->linear->type = IROLinearNop; - IRO_Dump("Removing dead assignment %d\n", def->linear->index); - result = 1; - } else { - result = EliminateReffedDeadStore(def); - } - } - } - } - - IRO_CheckForUserBreak(); - - if (optPropagation) { - while (1) { - if (PropagateIncsAndDecs() || PropagateOtherSelfAssignments()) - result = 1; - else - break; - } - } - - IRO_CheckForUserBreak(); - - return result; -} - -static IROLinear *GetOperand(IROLinear *nd) { - IROLinear *inner; - - if (nd->type == IROLinearOperand) - return nd; - - if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD) { - inner = GetOperand(nd->u.diadic.left); - if (!inner) - inner = GetOperand(nd->u.diadic.right); - return inner; - } - - return NULL; -} - -static IROLinear *GetAssigned(IROLinear *nd) { - if (!nd) - return NULL; - - if (nd->type == IROLinearOp2Arg) - nd = nd->u.diadic.left; - else if (nd->type == IROLinearOp1Arg) - nd = nd->u.monadic; - else - CError_FATAL(2338); - - if (nd->type != IROLinearOp1Arg || nd->nodetype != EINDIRECT) - CError_FATAL(2351); - - nd = nd->u.monadic; - - if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD) - nd = GetOperand(nd); - - return nd; -} - -static void AddUseToRange(IROUse *use) { - IRODef *def; - - Bv_SetBit(use->index, useset); - Bv_ClearBit(use->index, alluses); - - for (def = use->var->defs; def; def = def->varnext) { - if (Bv_IsBitSet(def->index, alldefs) && (Bv_IsBitSet(def->index, use->x18) || GetAssigned(def->linear) == use->linear)) - AddDefToRange(def); - } -} - -static void AddDefToRange(IRODef *def) { - IROUse *use; - IROLinear *assigned; - - Bv_SetBit(def->index, defset); - Bv_ClearBit(def->index, alldefs); - - for (use = def->var->uses, assigned = GetAssigned(def->linear); use; use = use->varnext) { - if (Bv_IsBitSet(use->index, alluses) && (Bv_IsBitSet(def->index, use->x18) || assigned == use->linear)) - AddUseToRange(use); - } -} - -static void ReplaceAssigned(IROLinear *nd, Object *from, Object *to) { - IROLinear *assigned; - - if ( - !(assigned = GetAssigned(nd)) || - assigned->type != IROLinearOperand || - assigned->u.node->type != EOBJREF || - assigned->u.node->data.objref != from - ) - CError_FATAL(2459); - - assigned->u.node->data.objref = to; -} - -static void ReplaceUsed(IROLinear *nd, Object *from, Object *to) { - CError_ASSERT(2482, nd->type == IROLinearOperand && nd->u.node->type == EOBJREF); - - if (nd->u.node->data.objref == from) - nd->u.node->data.objref = to; - else if (nd->u.node->data.objref != to) - CError_FATAL(2494); -} - -static void SplitOffRange(VarRecord *var) { - Object *newObj; - IRODef *def; - IROUse *use; - - IRO_Dump("Splitting range for variable: %d\n", var->index); - IRO_DumpBits("Def set: ", defset); - IRO_DumpBits("Use set: ", useset); - IRO_DumpBits("All defs: ", alldefs); - IRO_DumpBits("All uses: ", alluses); - - newObj = create_temp_object(var->object->type); - IRO_FindVar(newObj, 1, 1); - - for (def = var->defs; def; def = def->varnext) { - if (Bv_IsBitSet(def->index, defset) && def->linear) - ReplaceAssigned(def->linear, var->object, newObj); - } - - for (use = var->uses; use; use = use->varnext) { - if (Bv_IsBitSet(use->index, useset)) - ReplaceUsed(use->linear, var->object, newObj); - } -} - -void IRO_SplitLifetimes(void) { - VarRecord *var; - SInt32 numVars; - IRODef *def; - IROUse *use; - Boolean flag; - - Bv_AllocVector(&alldefs, NumDefs); - Bv_AllocVector(&alluses, NumUses); - Bv_AllocVector(&defset, NumDefs); - Bv_AllocVector(&useset, NumUses); - - var = IRO_FirstVar; - numVars = IRO_NumVars; - - while (var && var->index <= numVars) { - if (var->object->datatype == DLOCAL && !is_volatile_object(var->object) && !var->xC && !var->xB && !var->x1E) { - Bv_Clear(alldefs); - Bv_Clear(alluses); - - for (def = var->defs; def; def = def->varnext) { - if (def->linear && def->linear->type == IROLinearAsm) - goto skipThisVar; - Bv_SetBit(def->index, alldefs); - } - - for (use = var->uses; use; use = use->varnext) { - if (use->linear && use->linear->type == IROLinearAsm) - goto skipThisVar; - Bv_SetBit(use->index, alluses); - } - - flag = 1; - while (1) { - Bv_Clear(defset); - Bv_Clear(useset); - - def = var->defs; - while (def && !Bv_IsBitSet(def->index, alldefs)) - def = def->varnext; - - if (!def) - break; - - AddDefToRange(def); - if (Bv_IsEmpty(alldefs)) - break; - - if (!flag) - SplitOffRange(var); - flag = 0; - } - } - - skipThisVar: - var = var->next; - } - - IRO_CheckForUserBreak(); -} diff --git a/compiler_and_linker/unsorted/InlineAsm.c b/compiler_and_linker/unsorted/InlineAsm.c deleted file mode 100644 index 46a95d2..0000000 --- a/compiler_and_linker/unsorted/InlineAsm.c +++ /dev/null @@ -1,680 +0,0 @@ -#include "compiler/InlineAsm.h" -#include "compiler/InlineAsmPPC.h" -#include "compiler/GCCInlineAsm.h" -#include "compiler/CompilerTools.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInit.h" -#include "compiler/CInline.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/COptimizer.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CScope.h" -#include "compiler/PCode.h" -#include "compiler/Registers.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/types.h" - -int allow_array_expressions = 1; - -int backtracking; -jmp_buf backtrack; -jmp_buf InlineAsm_assemblererror; -static int ASMstmtnb; - -void AssemblerError(void) { - longjmp(InlineAsm_assemblererror, 1); -} - -void InlineAsm_SyntaxError(short code) { - if (backtracking) - longjmp(backtrack, 1); - - if (tk == TK_EOL || tk == ';') - code = CErrorStr112; - CError_Error(code); -} - -CLabel *InlineAsm_LookupLabel(HashNameNode *name) { - CLabel *label; - - for (label = Labels; label; label = label->next) { - if (name == label->name) - break; - } - - return label; -} - -CLabel *InlineAsm_DeclareLabel(HashNameNode *name) { - CLabel *label = newlabel(); - label->name = name; - label->next = Labels; - Labels = label; - return label; -} - -static void InlineAsm_DefineLabel(HashNameNode *name) { - CLabel *label; - Statement *stmt; - - label = InlineAsm_LookupLabel(name); - if (!label) { - label = InlineAsm_DeclareLabel(name); - } else { - if (label->stmt) - CError_Error(CErrorStr171, name->name); - } - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = label; - label->stmt = stmt; -} - -Boolean InlineAsm_LookupSymbolOrTag(HashNameNode *name, IALookupResult *result, Boolean allow_tag) { - ObjBase *obj; - NameSpace *nspace; - NameSpaceObjectList *list; - - result->name = name; - result->object = NULL; - result->label = NULL; - result->type = NULL; - result->has_value = 0; - - if ((result->label = InlineAsm_LookupLabel(name))) - return 1; - - for (nspace = cscope_current; nspace; nspace = nspace->parent) { - if ((list = CScope_FindName(nspace, name))) { - obj = list->object; - switch (obj->otype) { - case OT_ENUMCONST: - result->has_value = 1; - result->value = OBJ_ENUM_CONST(list->object)->val.lo; - return 1; - case OT_OBJECT: - if (OBJECT(obj)->datatype == DABSOLUTE) { - result->has_value = 1; - result->value = OBJECT(obj)->u.address; - } else { - if (OBJECT(obj)->datatype == DDATA && (OBJECT(obj)->qual & Q_INLINE_DATA)) - CInit_ExportConst(OBJECT(obj)); - result->object = OBJECT(obj); - } - return 1; - case OT_TYPE: - result->type = OBJ_TYPE(obj)->type; - return 1; - case OT_TYPETAG: - if (allow_tag) { - result->type = OBJ_TYPE_TAG(obj)->type; - return 1; - } - case OT_NAMESPACE: - case OT_MEMBERVAR: - return 0; - default: - CError_FATAL(245); - } - } - } - - return 0; -} - -Boolean InlineAsm_LookupSymbol(HashNameNode *name, IALookupResult *result) { - return InlineAsm_LookupSymbolOrTag(name, result, 0); -} - -static ObjMemberVar *isclassmember(TypeClass *tclass, HashNameNode *name) { - NameSpaceObjectList *list; - - list = CScope_FindName(tclass->nspace, name); - return (list && list->object->otype == OT_MEMBERVAR) ? OBJ_MEMBER_VAR(list->object) : NULL; -} - -SInt32 InlineAsm_StructMemberOffset(Type *type) { - StructMember *member; - ObjMemberVar *ivar; - SInt32 offset = 0; - - do { - if (IS_TYPE_STRUCT(type)) { - tk = lex(); - if (tk != TK_IDENTIFIER) - InlineAsm_SyntaxError(CErrorStr107); - member = ismember(TYPE_STRUCT(type), tkidentifier); - if (!member) - CError_Error(CErrorStr150, tkidentifier->name); - offset += member->offset; - type = member->type; - tk = lex(); - } else if (IS_TYPE_CLASS(type)) { - tk = lex(); - if (tk != TK_IDENTIFIER) - InlineAsm_SyntaxError(CErrorStr107); - ivar = isclassmember(TYPE_CLASS(type), tkidentifier); - if (!ivar) - CError_Error(CErrorStr150, tkidentifier->name); - offset += ivar->offset; - type = ivar->type; - tk = lex(); - } else { - CError_Error(CErrorStr149); - } - } while (tk == '.'); - - return offset; -} - -SInt32 InlineAsm_StructArrayMemberOffset(Type *type) { - StructMember *member; - ObjMemberVar *ivar; - SInt32 offset = 0; - - do { - if (tk == '.') { - if (IS_TYPE_STRUCT(type)) { - tk = lex(); - if (tk != TK_IDENTIFIER) - InlineAsm_SyntaxError(CErrorStr107); - member = ismember(TYPE_STRUCT(type), tkidentifier); - if (!member) - CError_Error(CErrorStr150, tkidentifier->name); - offset += member->offset; - type = member->type; - tk = lex(); - } else if (IS_TYPE_CLASS(type)) { - tk = lex(); - if (tk != TK_IDENTIFIER) - InlineAsm_SyntaxError(CErrorStr107); - ivar = isclassmember(TYPE_CLASS(type), tkidentifier); - if (!ivar) - CError_Error(CErrorStr150, tkidentifier->name); - offset += ivar->offset; - type = ivar->type; - tk = lex(); - } else { - CError_Error(CErrorStr149); - } - } else { - if (IS_TYPE_ARRAY(type)) { - type = TPTR_TARGET(type); - tk = lex(); - offset += type->size * InlineAsm_ConstantExpression(); - if (tk != ']') - InlineAsm_SyntaxError(125); - tk = lex(); - } else { - CError_Error(CErrorStr148); - } - } - } while (tk == '.' || tk == '['); - - return offset; -} - -SInt32 InlineAsm_StructPointerMemberOffset(Type *type) { - StructMember *member; - ObjMemberVar *ivar; - SInt32 offset; - - tk = lex(); - if (tk != TK_IDENTIFIER) - InlineAsm_SyntaxError(107); - - if (IS_TYPE_STRUCT(type)) { - member = ismember(TYPE_STRUCT(type), tkidentifier); - if (!member) - CError_Error(CErrorStr150, tkidentifier->name); - offset = member->offset; - type = member->type; - } else { - ivar = isclassmember(TYPE_CLASS(type), tkidentifier); - if (!ivar) - CError_Error(CErrorStr150, tkidentifier->name); - offset = ivar->offset; - type = ivar->type; - } - - tk = lex(); - if (tk == '.' || tk == '[') - offset += InlineAsm_StructArrayMemberOffset(type); - - return offset; -} - -static SInt32 DiadicOperator(SInt32 left, short op, SInt32 right) { - CInt64 left64; - CInt64 right64; - CInt64_SetLong(&left64, left); - CInt64_SetLong(&right64, right); - right64 = CMach_CalcIntDiadic(TYPE(&stsignedint), left64, op, right64); - return CInt64_GetULong(&right64); -} - -static SInt32 PrimaryExpression(void) { - IALookupResult result; - SInt32 value; - - switch (tk) { - case TK_IDENTIFIER: - if (InlineAsm_LookupSymbol(tkidentifier, &result)) { - if (result.has_value) { - tk = lex(); - return result.value; - } - - if (result.type && (IS_TYPE_STRUCT(result.type) || IS_TYPE_CLASS(result.type))) { - tk = lex(); - if (tk != '.') - InlineAsm_SyntaxError(120); - if (allow_array_expressions) - return InlineAsm_StructArrayMemberOffset(result.type); - else - return InlineAsm_StructMemberOffset(result.type); - } else { - InlineAsm_SyntaxError(124); - } - } else { - InlineAsm_SyntaxError(124); - } - break; - case TK_INTCONST: - value = tkintconst.lo; - tk = lex(); - return value; - case TK_SIZEOF: - return scansizeof(); - case '+': - tk = lex(); - return PrimaryExpression(); - case '-': - tk = lex(); - return -PrimaryExpression(); - case '!': - tk = lex(); - return PrimaryExpression() == 0; - case '~': - tk = lex(); - return ~PrimaryExpression(); - case '(': - tk = lex(); - value = InlineAsm_ConstantExpression(); - if (tk != ')') - InlineAsm_SyntaxError(115); - tk = lex(); - return value; - default: - InlineAsm_SyntaxError(120); - } - - return 0; -} - -static SInt32 ConstantExpressionTail(SInt32 value) { - SInt32 right; - short left_token; - short right_prec; - - while (1) { - left_token = tk; - tk = lex(); - right = PrimaryExpression(); - - right_prec = GetPrec(tk); - if (right_prec == 0) - return DiadicOperator(value, left_token, right); - - if (GetPrec(left_token) >= right_prec) { - value = DiadicOperator(value, left_token, right); - } else { - value = DiadicOperator(value, left_token, ConstantExpressionTail(right)); - if (GetPrec(tk) == 0) - return value; - } - } -} - -SInt32 InlineAsm_ConstantExpression(void) { - SInt32 value = PrimaryExpression(); - - if (GetPrec(tk) == 0) - return value; - else - return ConstantExpressionTail(value); -} - -HashNameNode *MakeLocalLabel(CInt64 num) { - char buf[80]; - sprintf(buf, "@%i_%i", ASMstmtnb, CInt64_GetULong(&num)); - return GetHashNameNodeExport(buf); -} - -static void ScanOptionalLabel(void) { - if (tk == TK_INTCONST) { - if (lookahead() == ':') { - InlineAsm_DefineLabel(MakeLocalLabel(tkintconst)); - tk = lex(); - tk = lex(); - } - } else { - if (tkidentifier->name[0] == '@') { - InlineAsm_DefineLabel(tkidentifier); - tk = lex(); - if (tk == ':') - tk = lex(); - } else { - HashNameNode *name = tkidentifier; - short t = lookahead(); - tkidentifier = name; - if (t == ':') { - InlineAsm_DefineLabel(name); - tk = lex(); - tk = lex(); - } - } - } -} - -static void ScanStatements(volatile short endToken, AssemblerType mode) { - if (setjmp(InlineAsm_assemblererror)) { - while (tk != TK_EOL && tk != endToken && tk != '}' && tk) - tk = lex(); - if (tk == ';' || tk == TK_EOL) - tk = lex(); - } else { - InlineAsm_Initialize(mode); - InlineAsm_gccmode = 0; - if (setjmp(InlineAsm_assemblererror)) { - while (tk != ';' && tk != TK_EOL && tk != endToken && tk != '}' && tk) - tk = lex(); - if (tk == ';' || tk == TK_EOL) - tk = lex(); - } - - while (tk && tk != endToken) { - backtracking = 0; - sourceoffset = CPrep_GetFileOffsetInfo(&cparser_fileoffset); - if (tk == '"') { - if (InlineAsm_gccmode) { - tk = lex(); - InlineAsm_gcc_parse(); - } else { - InlineAsm_gccmode = 1; - copts.cplusplus = 0; - copts.asmpoundcomment = 1; - tk = lex(); - } - } - - if (tk == '.') { - InlineAsm_ScanAssemblyDirective(); - } else if (tk == TK_IDENTIFIER) { - ScanOptionalLabel(); - if (tk == TK_IDENTIFIER) - InlineAsm_ScanAssemblyInstruction(); - } else if (tk == TK_INTCONST) { - ScanOptionalLabel(); - if (tk == TK_IDENTIFIER) - InlineAsm_ScanAssemblyInstruction(); - } - - if (InlineAsm_gccmode && tk == '"') { - tk = lex(); - InlineAsm_gcc_parse(); - } - - if (tk == ';' || tk == TK_EOL) { - CPrep_TokenStreamFlush(); - tk = lex(); - } else if (tk != endToken) { - if (endToken == ')') - CError_Error(CErrorStr115); - else - CError_Error(CErrorStr113); - } - } - } -} - -void InlineAsm_ScanStatements(volatile short endToken) { - ScanStatements(endToken, AssemblerType_0); -} - -void InlineAsm_ScanFunction(volatile short endToken) { - ScanStatements(endToken, AssemblerType_1); -} - -void InlineAsm_Assemble(void) { - short token = (tk == '(') ? ')' : '}'; - char save_pc = copts.asmpoundcomment; - char save_cpp = copts.cplusplus; - - cprep_nostring = 1; - CFunc_AppendStatement(ST_NOP); - first_ST_ASM = curstmt; - ASMstmtnb++; - - cprep_eoltokens = 1; - in_assembler = 1; - tk = lex(); - InlineAsm_ScanStatements(token); - in_assembler = 0; - cprep_eoltokens = 0; - cprep_nostring = 0; - - copts.asmpoundcomment = save_pc; - copts.cplusplus = save_cpp; -} - -void InlineAsm_PackAsmStatement(Statement *stmt, Statement *first, void **output, SInt32 *outsize) { - InlineAsm *src; - InlineAsm *dest; - IAOperand *op; - SInt32 i; - SInt32 size; - - src = (InlineAsm *) stmt->expr; - size = sizeof(InlineAsm) + sizeof(IAOperand) * src->argcount; - dest = galloc(size); - memcpy(dest, src, size); - - for (i = 0, op = dest->args; i < dest->argcount; i++, op++) { - switch (op->type) { - case IAOpnd_0: - break; - case IAOpnd_Reg: - case IAOpnd_4: - op->u.reg.object = (Object *) CInline_GetLocalID(op->u.reg.object); - break; - case IAOpnd_Lab: - op->u.lab.label = (CLabel *) CInline_GetStatementNumber(first, op->u.lab.label->stmt); - break; - case IAOpnd_LabDiff: - op->u.labdiff.label1 = (CLabel *) CInline_GetStatementNumber(first, op->u.labdiff.label1->stmt); - op->u.labdiff.label2 = (CLabel *) CInline_GetStatementNumber(first, op->u.labdiff.label2->stmt); - break; - } - } - - *output = dest; - *outsize = size; -} - -void InlineAsm_UnpackAsmStatement(Statement *stmt, CLabel **labelArray, Boolean flag, void *data, SInt32 size) { - InlineAsm *ia; - IAOperand *op; - SInt32 i; - - ia = galloc(size); - memcpy(ia, data, size); - - for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { - switch (op->type) { - case IAOpnd_0: - break; - case IAOpnd_Reg: - case IAOpnd_4: - op->u.reg.object = CInline_GetLocalObj((SInt32) op->u.reg.object, flag); - break; - case IAOpnd_Lab: - op->u.lab.label = labelArray[(SInt16) op->u.lab.label]; - break; - case IAOpnd_LabDiff: - op->u.labdiff.label1 = labelArray[(SInt16) op->u.labdiff.label1]; - op->u.labdiff.label2 = labelArray[(SInt16) op->u.labdiff.label2]; - break; - } - } - - stmt->expr = (ENode *) ia; -} - -void InlineAsm_CheckLocalUsage(Statement *stmt) { - InlineAsm *ia = (InlineAsm *) stmt->expr; - IAOperand *op; - SInt32 i; - - for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { - switch (op->type) { - case IAOpnd_Reg: - if (op->u.reg.object) - SetVarUsage(op->u.reg.object, 0); - break; - case IAOpnd_4: - SetVarUsage(op->u.obj.obj, 1); - break; - } - } -} - -CLabel *InlineAsm_GetReferencedLabel(Statement *stmt) { - InlineAsm *ia = (InlineAsm *) stmt->expr; - IAOperand *op; - SInt32 i; - - for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { - if (op->type == IAOpnd_Lab) - return op->u.lab.label; - if (op->type == IAOpnd_LabDiff) - return op->u.labdiff.label1; - } - - return NULL; -} - -CLabel *InlineAsm_GetReferencedLabel2(Statement *stmt) { - InlineAsm *ia = (InlineAsm *) stmt->expr; - IAOperand *op; - SInt32 i; - - for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { - if (op->type == IAOpnd_LabDiff) - return op->u.labdiff.label2; - } - - return NULL; -} - -Object *InlineAsm_GetObjectOffset(InlineAsm *ia, SInt32 index, SInt32 *offset) { - IAOperand *op; - SInt32 i; - SInt32 counter; - - for (i = 0, counter = 0, op = ia->args; i < ia->argcount; i++, op++) { - if (op->type == IAOpnd_3) { - if (counter++ == index) { - *offset = ((intptr_t) &op->u.obj.obj) - ((intptr_t) ia); - return op->u.obj.obj; - } - } - } - - return NULL; -} - -char *InlineAsm_DumpStatement(Statement *stmt) { - static char buffer[1024]; - InlineAsm *ia; - IAOperand *arg; - int i; - char ch; - SInt32 offset; - - ia = (InlineAsm *) stmt->expr; - - strcpy(buffer, "\""); - strcat(buffer, InlineAsm_GetMnemonic(ia)); - strcat(buffer, "\""); - - for (i = 0, arg = ia->args; i < ia->argcount; i++, arg++) { - char argbuf[1024]; - - switch (arg->type) { - case IAOpnd_Imm: - sprintf(argbuf, " imm(%ld)", arg->u.imm.value); - break; - case IAOpnd_Reg: - ch = ' '; - if (arg->u.reg.effect & EffectWrite) { - if (arg->u.reg.effect & EffectRead) - ch = '+'; - else - ch = '='; - } else { - if (!(arg->u.reg.effect & EffectRead)) - ch = '0'; - } - - if (arg->u.reg.object) { - sprintf(argbuf, - "%creg(%s)", - ch, - arg->u.reg.object->name->name); - } else { - sprintf(argbuf, - "%creg(%s%d)", - ch, - register_class_name[arg->u.reg.rclass], - arg->u.reg.num); - } - break; - - case IAOpnd_3: - case IAOpnd_4: - if (arg->u.obj.offset > 0) - sprintf(argbuf, " obj(%s+%ld)", arg->u.obj.obj->name->name, arg->u.obj.offset); - else if (arg->u.obj.offset < 0) - sprintf(argbuf, " obj(%s-%ld)", arg->u.obj.obj->name->name, -arg->u.obj.offset); - else - sprintf(argbuf, " obj(%s)", arg->u.obj.obj->name->name); - break; - - case IAOpnd_Lab: - sprintf(argbuf, " lab(%s)", arg->u.lab.label->uniquename->name); - break; - - case IAOpnd_LabDiff: - offset = !arg->negated ? 0 : arg->u.labdiff.offset; - sprintf(argbuf, - " labdiff(%s-%s%c%d)", - arg->u.labdiff.label1->uniquename->name, - arg->u.labdiff.label2->uniquename->name, - (arg->negated == 1) ? '-' : '+', - offset - ); - break; - } - - strcat(buffer, argbuf); - } - - return buffer; -} diff --git a/compiler_and_linker/unsorted/InlineAsmPPC.c b/compiler_and_linker/unsorted/InlineAsmPPC.c deleted file mode 100644 index 464f9f9..0000000 --- a/compiler_and_linker/unsorted/InlineAsmPPC.c +++ /dev/null @@ -1,2586 +0,0 @@ -#include "compiler/InlineAsmPPC.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CInt64.h" -#include "compiler/CFunc.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/Alias.h" -#include "compiler/CodeGen.h" -#include "compiler/CodeGenOptPPC.h" -#include "compiler/CompilerTools.h" -#include "compiler/Exceptions.h" -#include "compiler/FuncLevelAsmPPC.h" -#include "compiler/InlineAsm.h" -#include "compiler/InlineAsmMnemonicsPPC.h" -#include "compiler/InlineAsmRegisters.h" -#include "compiler/InlineAsmRegistersPPC.h" -#include "compiler/PCode.h" -#include "compiler/PCodeUtilities.h" -#include "compiler/PPCError.h" -#include "compiler/RegisterInfo.h" -#include "compiler/StackFrame.h" -#include "compiler/TOC.h" -#include "compiler/objects.h" - -char asm_alloc_flags[10]; -Section sm_section; -UInt32 cpu; -SInt32 fralloc_parameter_area_size; -Boolean user_responsible_for_frame; -Boolean supports_hardware_fpu; -UInt32 assembledinstructions; -AssemblerType assembler_type; -char volatileasm; -Boolean InlineAsm_gccmode; -Boolean InlineAsm_labelref; -CLabel *pic_base_label; - -// forward decls -static SInt32 InlineAsm_ConstantExpressionPPC(SInt32 value); -static Object *isvariableoperand(void); -static Object *isregisterstructpointeroperand(void); -static void registeroperand(IAOperand *op, char rclass, short effect); -static void DiadicOperatorPPC(IAExpr *left, short token, IAExpr *right); -static void InlineAsm_ExpressionPPC(IAExpr *expr, SInt32 value); -static void savepicbase(short reg, HashNameNode *name); - -CW_INLINE SInt32 ExtractValue(CInt64 value) { - return (SInt32) CInt64_GetULong(&value); -} - -static void IllegalObjectOperator(HashNameNode *name1, HashNameNode *name2, short token) { - char *opstr; - switch (token) { - case '*': opstr = "*"; break; - case '/': opstr = "/"; break; - case '%': opstr = "%"; break; - case '+': opstr = "+"; break; - case '-': opstr = "-"; break; - case TK_SHL: opstr = "<<"; break; - case TK_SHR: opstr = ">>"; break; - case '<': opstr = "<"; break; - case '>': opstr = ">"; break; - // bug? these two seem swapped - case TK_LESS_EQUAL: opstr = ">="; break; - case TK_GREATER_EQUAL: opstr = "<="; break; - case TK_LOGICAL_EQ: opstr = "=="; break; - case TK_LOGICAL_NE: opstr = "!="; break; - case '&': opstr = "&"; break; - case '^': opstr = "^"; break; - case '|': opstr = "|"; break; - case TK_LOGICAL_AND: opstr = "&&"; break; - case TK_LOGICAL_OR: opstr = "||"; break; - default: opstr = "???"; - } - - if (!name2) { - PPCError_Error(PPCErrorStr119, opstr, name1->name); - } else if (!name1) { - PPCError_Error(PPCErrorStr120, opstr, name2->name); - } else { - PPCError_Error(PPCErrorStr118, name1->name, opstr, name2->name); - } -} - -static void IllegalObjectInConst(IAExpr *expr) { - if (expr->xC) { - PPCError_Error(PPCErrorStr122, expr->xC->name->name); - } else if (expr->object) { - PPCError_Error(PPCErrorStr122, expr->object->name->name); - } else if (expr->label) { - PPCError_Error(PPCErrorStr166, expr->label->name->name); - } -} - -static void NotInRegisterError(char *name, char rclass) { - PPCError_Error(PPCErrorStr167, name, register_class_name[rclass]); -} - -static int isregisteroperand(char rclass) { - IARegister *reg; - - return (tk == TK_IDENTIFIER && (reg = InlineAsm_LookupRegisterPPCName(tkidentifier)) && reg->rclass == rclass); -} - -static SInt32 getcroperand(char rclass) { - SInt32 value; - IARegister *reg; - - value = 0; - if (tk == TK_IDENTIFIER && (reg = InlineAsm_LookupRegisterPPCName(tkidentifier)) && reg->rclass == rclass) { - value = reg->num; - } else { - PPCError_Error(PPCErrorStr167, tkidentifier->name); - } - - tk = lex(); - return value; -} - -static SInt32 getimmediateoperand(SInt32 minimum, SInt32 maximum) { - SInt32 value = InlineAsm_ConstantExpressionPPC(0); - if (value < minimum || value > maximum) - CError_Error(CErrorStr154); - return value; -} - -static void PrimaryExpressionPPC(IAExpr *expr, SInt32 value) { - Object *obj; - IALookupResult result; - IAExpr subexpr; - IAExprType type = IAExpr_0; - SInt32 v; - - switch (tk) { - case TK_IDENTIFIER: - if ((obj = isregisterstructpointeroperand())) { - tk = lex(); - InlineAsm_InitExpr5(expr, InlineAsm_StructPointerMemberOffset(TPTR_TARGET(obj->type))); - expr->object = obj; - return; - } - - if ((obj = isvariableoperand())) { - short reg; - InlineAsm_InitExpr5(expr, 0); - expr->xC = obj; - - if (obj->datatype == DLOCAL) - reg = 1; - else - reg = pic_base_reg; - - tk = lex(); - if (tk == '.' || tk == '[') { - InlineAsm_InitExpr5(&subexpr, InlineAsm_StructArrayMemberOffset(obj->type)); - DiadicOperatorPPC(expr, '+', &subexpr); - } - - if (tk == '+') { - tk = lex(); - InlineAsm_ExpressionPPC(&subexpr, value); - DiadicOperatorPPC(expr, '+', &subexpr); - } else if (tk == '-') { - tk = lex(); - InlineAsm_ExpressionPPC(&subexpr, value); - DiadicOperatorPPC(expr, '-', &subexpr); - } else if (!strcmp(tkidentifier->name, "@loword")) { - tk = lex(); - if (low_offset) { - InlineAsm_InitExpr5(&subexpr, low_offset); - DiadicOperatorPPC(expr, '+', &subexpr); - } - } else if (!strcmp(tkidentifier->name, "@hiword")) { - tk = lex(); - if (high_offset) { - InlineAsm_InitExpr5(&subexpr, high_offset); - DiadicOperatorPPC(expr, '+', &subexpr); - } - } - expr->reg = reg; - return; - } - - if (InlineAsm_LookupSymbolOrTag(tkidentifier, &result, 1)) { - if (result.has_value) { - tk = lex(); - InlineAsm_InitExpr5(expr, result.value); - return; - } - - if (result.type && (IS_TYPE_STRUCT(result.type) || IS_TYPE_CLASS(result.type))) { - tk = lex(); - if (tk != '.') - CError_Error(CErrorStr120); - - if (allow_array_expressions) { - InlineAsm_InitExpr5(expr, InlineAsm_StructArrayMemberOffset(result.type)); - return; - } - - InlineAsm_InitExpr5(expr, InlineAsm_StructMemberOffset(result.type)); - return; - } - - if (result.object && result.object->datatype == DABSOLUTE) { - tk = lex(); - InlineAsm_InitExpr5(expr, result.object->u.address); - return; - } - } else if (value) { - if (isregisteroperand(RegClass_CRFIELD)) { - InlineAsm_InitExpr5(expr, getcroperand(RegClass_CRFIELD)); - return; - } - if (isregisteroperand(RegClass_6)) { - InlineAsm_InitExpr5(expr, getcroperand(RegClass_6)); - return; - } - if (strlen(tkidentifier->name) == 6 && !strncmp(tkidentifier->name, "cr", 2) && tkidentifier->name[3] == '_') { - IARegister *reg; - char regname[4]; - regname[0] = tkidentifier->name[0]; - regname[1] = tkidentifier->name[1]; - regname[2] = tkidentifier->name[2]; - regname[3] = 0; - if ((reg = InlineAsm_LookupRegisterPPC(regname)) && reg->rclass == RegClass_CRFIELD) { - SInt32 v = reg->num * 4; - regname[0] = tkidentifier->name[4]; - regname[1] = tkidentifier->name[5]; - regname[2] = 0; - if ((reg = InlineAsm_LookupRegisterPPC(regname)) && reg->rclass == RegClass_6) { - tk = lex(); - InlineAsm_InitExpr5(expr, v + reg->num); - return; - } - } - } - } - - if (!strcmp("ha16", tkidentifier->name)) - type = IAExpr_8; - else if (!strcmp("hi16", tkidentifier->name)) - type = IAExpr_7; - else if (!strcmp("lo16", tkidentifier->name)) - type = IAExpr_6; - - if (type != IAExpr_0) { - tk = lex(); - if (tk == '(') { - SInt32 v; - tk = lex(); - PrimaryExpressionPPC(expr, value); - expr->type = type; - if (tk != ')') - CError_Error(CErrorStr115); - - tk = lex(); - if (InlineAsm_CheckExpr(expr)) { - expr->value = InlineAsm_GetExprValue(expr); - expr->type = IAExpr_5; - } - return; - } - - CError_Error(CErrorStr114); - } else { - if (!result.label) - result.label = InlineAsm_DeclareLabel(tkidentifier); - - InlineAsm_InitExpr5(expr, 0); - expr->flags |= IAFlag1; - expr->label = result.label; - tk = lex(); - return; - } - break; - - case TK_INTCONST: - v = CInt64_GetULong(&tkintconst); - tk = lex(); - InlineAsm_InitExpr5(expr, v); - return; - - case TK_SIZEOF: - InlineAsm_InitExpr5(expr, scansizeof()); - return; - - case '+': - tk = lex(); - PrimaryExpressionPPC(expr, value); - return; - - case '-': - tk = lex(); - PrimaryExpressionPPC(expr, value); - if (InlineAsm_CheckExpr(expr)) - expr->value = -expr->value; - else - CError_Error(CErrorStr124); - return; - - case '!': - tk = lex(); - PrimaryExpressionPPC(expr, value); - if (InlineAsm_CheckExpr(expr)) - expr->value = !expr->value; - else - CError_Error(CErrorStr124); - return; - - case '~': - tk = lex(); - PrimaryExpressionPPC(expr, value); - if (InlineAsm_CheckExpr(expr)) - expr->value = ~expr->value; - else - CError_Error(CErrorStr124); - return; - - case '(': - tk = lex(); - InlineAsm_ExpressionPPC(expr, value); - if (tk != ')') - CError_Error(CErrorStr115); - tk = lex(); - return; - - default: - CError_Error(CErrorStr120); - } - - InlineAsm_InitExpr5(expr, 0); -} - -static void DiadicOperatorPPC(IAExpr *left, short token, IAExpr *right) { - CInt64 leftval; - CInt64 rightval; - - CInt64_SetLong(&leftval, left->value); - CInt64_SetLong(&rightval, right->value); - rightval = CMach_CalcIntDiadic(TYPE(&stsignedint), leftval, token, rightval); - - if (left->xC) { - if (right->label) - PPCError_Error(PPCErrorStr124, left->xC->name->name, right->label->name->name); - - if (right->xC) { - if (left->x10) { - PPCError_Error(PPCErrorStr121, left->xC->name->name, left->x10->name->name, right->xC->name->name); - } else if (right->x10) { - PPCError_Error(PPCErrorStr121, left->xC->name->name, right->xC->name->name, right->x10->name->name); - } else if (token == '-') { - left->value = CInt64_GetULong(&rightval); - left->x10 = right->xC; - } else { - IllegalObjectOperator(left->xC->name, right->xC->name, token); - } - } else if (token == '-' || token == '+') { - left->value = CInt64_GetULong(&rightval); - } else { - IllegalObjectOperator(left->xC->name, NULL, token); - } - } else if (right->xC) { - if (right->label) - PPCError_Error(PPCErrorStr124, right->xC->name->name, right->label->name->name); - - if (token == '+') { - left->xC = right->xC; - left->x10 = right->x10; - left->value = CInt64_GetULong(&rightval); - } else { - IllegalObjectOperator(NULL, right->xC->name, token); - } - } else if (left->label) { - if (left->xC) - PPCError_Error(PPCErrorStr124, left->label->name->name, left->xC->name->name); - - if (right->label) { - if (left->x18) { - PPCError_Error(PPCErrorStr121, left->label->name->name, left->x18->name->name, right->label->name->name); - } else if (right->x18) { - PPCError_Error(PPCErrorStr121, left->label->name->name, right->label->name->name, right->x18->name->name); - } else if (token == '-') { - left->value = CInt64_GetULong(&rightval); - left->x18 = right->label; - } else { - IllegalObjectOperator(left->label->name, right->label->name, token); - } - } else if (token == '+' || token == '-') { - left->value = CInt64_GetULong(&rightval); - } else { - IllegalObjectOperator(NULL, left->label->name, token); - } - } else if (right->label) { - if (token == '+') { - left->label = right->label; - left->x18 = right->x18; - left->value = CInt64_GetULong(&rightval); - } else { - IllegalObjectOperator(NULL, right->label->name, token); - } - } else { - left->value = CInt64_GetULong(&rightval); - } - - left->flags |= right->flags; - if (left->type == IAOpnd_Lab) { - if (right->type != IAOpnd_Lab) - left->type = right->type; - } else { - if (right->type != IAOpnd_Lab && right->type != left->type) - PPCError_Error(PPCErrorStr126); - } -} - -static void ExpressionTailPPC(IAExpr *left, SInt32 value) { - IAExpr right; - short left_tk; - short right_prec; - - while (1) { - left_tk = tk; - tk = lex(); - - PrimaryExpressionPPC(&right, value); - right_prec = GetPrec(tk); - if (right_prec == 0) { - DiadicOperatorPPC(left, left_tk, &right); - break; - } - - if (GetPrec(left_tk) >= right_prec) { - DiadicOperatorPPC(left, left_tk, &right); - } else { - ExpressionTailPPC(&right, value); - DiadicOperatorPPC(left, left_tk, &right); - if (GetPrec(tk) == 0) - break; - } - } -} - -static void immediateoperand(IAOperand *op, SInt32 minval, SInt32 maxval) { - SInt32 value; - if (InlineAsm_gccmode && tk == '%') { - tk = lex(); - if (tk != TK_INTCONST) { - CError_Error(CErrorStr144); - } else { - CInt64 c = tkintconst; - value = CInt64_GetULong(&c); - if (value < 0) - CError_Error(CErrorStr144); - } - op->type = IAOpnd_7; - op->u.unk7.value = value; - op->u.unk7.unk1 = 1; - op->u.unk7.unk2 = 0; - op->u.unk7.unk3 = 0; - tk = lex(); - } else { - value = InlineAsm_ConstantExpressionPPC(0); - if (value < minval || value > maxval) - CError_Error(CErrorStr154); - op->type = IAOpnd_Imm; - op->u.imm.value = value; - } -} - -static SInt32 immediatevalue(IAOperand *op, SInt32 minval, SInt32 maxval) { - SInt32 value; - if (InlineAsm_gccmode && tk == '%') { - CError_Error(CErrorStr144); - return 0; - } else { - value = InlineAsm_ConstantExpressionPPC(0); - if (value < minval || value > maxval) - CError_Error(CErrorStr154); - op->type = IAOpnd_Imm; - op->u.imm.value = value; - return value; - } -} - -static void InlineAsm_ExpressionPPC(IAExpr *expr, SInt32 value) { - PrimaryExpressionPPC(expr, value); - if (GetPrec(tk)) - ExpressionTailPPC(expr, value); - if (GetPrec(tk)) - ExpressionTailPPC(expr, value); - - if (expr->type == IAExpr_5 && tk == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "@l")) { - expr->type = IAExpr_6; - tk = lex(); - } else if (!strcmp(tkidentifier->name, "@ha")) { - expr->type = IAExpr_8; - tk = lex(); - } else if (!strcmp(tkidentifier->name, "@h")) { - expr->type = IAExpr_7; - tk = lex(); - } - } -} - -static SInt32 InlineAsm_ConstantExpressionPPC(SInt32 value) { - IAExpr expr; - - InlineAsm_ExpressionPPC(&expr, value); - if (!InlineAsm_CheckExpr(&expr)) { - IllegalObjectInConst(&expr); - return 0; - } else { - return InlineAsm_GetExprValue(&expr); - } -} - -static SInt32 crbitoperand(void) { - SInt32 value = InlineAsm_ConstantExpressionPPC(1); - if (value < 0 || value > 31) - CError_Error(CErrorStr154); - return value; -} - -static void floatoperand(IAOperand *op, InlineAsm *ia, Type *type) { - Object *obj; - - obj = createfloatconstant(type, &tkfloatconst); - op[0].type = IAOpnd_Reg; - op[0].u.reg.rclass = RegClass_GPR; - op[0].u.reg.object = NULL; - op[0].u.reg.effect = EffectRead; - op[0].u.reg.num = pic_base_reg; - - ia->argcount++; - op[1].type = IAOpnd_4; - op[1].u.obj.obj = obj; - PPCError_Error(PPCErrorStr179); - op[1].u.obj.unk = IAExpr_2; - op[1].u.obj.offset = 0; - tk = lex(); -} - -static Object *isvariableoperand(void) { - IALookupResult result; - Object *obj; - - if (tk == TK_IDENTIFIER) { - InlineAsm_LookupSymbol(tkidentifier, &result); - if ((obj = result.object)) { - if (obj->datatype == DLOCAL) { - if (OBJECT_REG(obj)) - return NULL; - return obj; - } - - if (obj->datatype == DFUNC || obj->datatype == DVFUNC) - return obj; - - if (obj->datatype == DDATA) { - createIndirect(obj, 0, 0); - return obj; - } - } - } - - return NULL; -} - -static Object *isregisterstructpointeroperand(void) { - IALookupResult result; - Object *obj; - - if (tk != TK_IDENTIFIER) - return NULL; - - InlineAsm_LookupSymbol(tkidentifier, &result); - if ((obj = result.object)) { - if (obj->datatype != DLOCAL) - return NULL; - if (!OBJECT_REG(obj) && !is_register_object(obj)) - return NULL; - if (!IS_TYPE_POINTER(obj->type)) - return NULL; - if (!IS_TYPE_STRUCT(TPTR_TARGET(obj->type)) && !IS_TYPE_CLASS(TPTR_TARGET(obj->type))) - return NULL; - return obj; - } - - return NULL; -} - -static void memoryoperand(IAOperand *op, InlineAsm *ia, Boolean flag, short effect) { - IAExpr expr; - - InlineAsm_ExpressionPPC(&expr, 0); - if (expr.object) { - if (!flag) - CError_Error(CErrorStr155); - if (expr.xC) - PPCError_Error(PPCErrorStr122, expr.xC); - - op[0].type = IAOpnd_Reg; - op[0].u.reg.rclass = RegClass_GPR; - op[0].u.reg.object = expr.object; - op[0].u.reg.num = 0; - op[0].u.reg.effect = effect; - if (expr.object || expr.reg) - op[0].u.reg.effect = effect; - else - op[0].u.reg.effect = 0; - - ia->argcount++; - op[1].type = IAOpnd_Imm; - switch (expr.type) { - case IAExpr_5: - expr.type = IAExpr_6; - if (expr.object->datatype != DLOCAL || !OBJECT_REG(expr.object)) - PPCError_Error(PPCErrorStr180); - case IAExpr_2: - case IAExpr_6: - case IAExpr_7: - case IAExpr_8: - op[1].u.imm.value = InlineAsm_GetExprValue(&expr); - break; - default: - CError_Error(CErrorStr155); - } - - expr.object->flags |= OBJECT_USED; - return; - } - - if (expr.xC) { - if (expr.x10) - PPCError_Error(PPCErrorStr123, expr.xC->name->name, expr.x10->name->name); - - if (flag) { - if (tk == '(') { - if (flag) { - tk = lex(); - registeroperand(op, RegClass_GPR, effect); - if ((expr.type == IAExpr_8 || expr.type == IAExpr_7) && copts.codegen_pic && pic_base_reg) - CError_Error(CErrorStr155); - if (tk != ')') - CError_Error(CErrorStr115); - tk = lex(); - } - } else { - op[0].type = IAOpnd_Reg; - op[0].u.reg.rclass = RegClass_GPR; - op[0].u.reg.object = expr.object; - op[0].u.reg.num = expr.reg; - } - - if (expr.object || expr.reg) - op[0].u.reg.effect = effect; - else - op[0].u.reg.effect = 0; - - ia->argcount++; - op++; - } - - if (expr.xC->datatype == DLOCAL) { - op[0].type = IAOpnd_4; - op[0].u.obj.unk = IAExpr_1; - } else { - op[0].type = IAOpnd_3; - if (expr.type == IAExpr_5) { - expr.type = IAExpr_6; - PPCError_Error(PPCErrorStr180); - } - op[0].u.obj.unk = expr.type; - } - - op[0].u.obj.obj = expr.xC; - op[0].u.obj.offset = expr.value; - expr.xC->flags |= OBJECT_USED; - return; - } - - if (flag) { - if (tk == '(') { - tk = lex(); - registeroperand(op, RegClass_GPR, effect); - ia->argcount++; - op++; - if (tk != ')') - CError_Error(CErrorStr115); - tk = lex(); - } else { - op->type = IAOpnd_Reg; - op->u.reg.rclass = RegClass_GPR; - op->u.reg.object = expr.object; - op->u.reg.num = expr.reg; - ia->argcount++; - op++; - } - } - - if (expr.label) { - if (expr.x18) { - op->type = IAOpnd_LabDiff; - op->negated = 0; - op->u.labdiff.label1 = expr.label; - op->u.labdiff.label2 = expr.x18; - op->u.labdiff.offset = expr.value; - } else { - PPCError_Error(PPCErrorStr125, expr.label->name->name); - } - } else { - op->type = IAOpnd_Imm; - op->u.imm.value = InlineAsm_GetExprValue(&expr); - } -} - -static void registeroperand(IAOperand *op, char rclass, short effect) { - IARegister *reg; - Object *obj; - - if (tk == TK_IDENTIFIER && (reg = InlineAsm_LookupRegisterPPCName(tkidentifier)) && reg->rclass == rclass) { - SInt32 num; - obj = reg->object; - num = reg->num; - op->type = IAOpnd_Reg; - op->u.reg.rclass = rclass; - op->u.reg.object = obj; - op->u.reg.num = num; - op->u.reg.effect = effect; - if (obj) { - reg->object->flags |= OBJECT_USED; - Registers_GetVarInfo(obj)->flags |= VarInfoFlag40; - } - } else if (rclass == RegClass_CRFIELD) { - op->type = IAOpnd_Reg; - op->u.reg.rclass = RegClass_CRFIELD; - op->u.reg.object = NULL; - op->u.reg.num = getimmediateoperand(0, 7); - op->u.reg.effect = effect; - return; - } else if (rclass == RegClass_SPR) { - op->type = IAOpnd_Reg; - op->u.reg.rclass = RegClass_SPR; - op->u.reg.object = NULL; - op->u.reg.num = getimmediateoperand(0, 1024); - op->u.reg.effect = effect; - return; - } else if (tk == '%' && InlineAsm_gccmode) { - SInt32 num; - tk = lex(); - if (tk != TK_INTCONST) { - CError_Error(CErrorStr144); - } else { - num = ExtractValue(tkintconst); - if (num < 0) - CError_Error(CErrorStr144); - } - - op->type = IAOpnd_6; - op->u.unk6.num = num; - op->u.unk6.unk4 = 2; - op->u.unk6.effect = effect; - op->u.unk6.rclass = rclass; - tk = lex(); - return; - } else if (tk == TK_IDENTIFIER) { - NotInRegisterError(tkidentifier->name, rclass); - } else { - PPCError_Error(PPCErrorStr171); - } - - tk = lex(); - if (!strcmp(tkidentifier->name, "@loword")) { - tk = lex(); - } else if (!strcmp(tkidentifier->name, "@hiword")) { - if (reg->object) - op->u.reg.num = 1; - else - PPCError_Error(PPCErrorStr168); - tk = lex(); - } else if (rclass == RegClass_GPR) { - if (reg->object && reg->object->type->size == 8) { - HashNameNode *name = reg->object->name; - PPCError_Error(PPCErrorStr127, name->name, name->name, name->name); - } - } -} - -static void cr0_operand(IAOperand *op, short effect) { - IARegister *reg; - - if ((reg = InlineAsm_LookupRegisterPPC("cr0"))) { - op->type = IAOpnd_Reg; - op->u.reg.rclass = RegClass_CRFIELD; - op->u.reg.object = reg->object; - op->u.reg.num = reg->num; - op->u.reg.effect = effect; - } else { - NotInRegisterError("cr0", RegClass_CRFIELD); - } -} - -static void r0_operand(IAOperand *op) { - IARegister *reg; - - if ((reg = InlineAsm_LookupRegisterPPC("r0"))) { - op->type = IAOpnd_Reg; - op->u.reg.rclass = RegClass_GPR; - op->u.reg.object = reg->object; - op->u.reg.num = reg->num; - op->u.reg.effect = 0; - tk = lex(); - } else { - NotInRegisterError("r0", RegClass_GPR); - } -} - -static void labeloperand(InlineAsm *ia, IAOperand *op, Boolean flag1, Boolean flag2, Boolean flag3) { - IALookupResult result; - - if (tk == TK_IDENTIFIER) { - if (!InlineAsm_LookupSymbol(tkidentifier, &result)) - result.label = InlineAsm_DeclareLabel(tkidentifier); - - if (result.label) { - op->type = IAOpnd_Lab; - op->u.lab.label = result.label; - } else if (result.object && result.object->datatype == DFUNC) { - if (flag3) - ia->flags |= IAFlag2; - op->type = IAOpnd_3; - op->u.obj.obj = result.object; - op->u.obj.offset = 0; - - if (flag1) { - op->u.obj.unk = IAExpr_4; - if (flag2) - CError_Error(CErrorStr261); - } else { - op->u.obj.unk = IAExpr_2; - if (flag2) - op->u.obj.unk = IAExpr_10; - op->u.obj.unk = IAExpr_6; - PPCError_Error(PPCErrorStr180); - } - } else { - CError_Error(CErrorStr144); - } - - tk = lex(); - } else if (tk == '*') { - if (!flag2) { - tk = lex(); - if (tk == '+') { - tk = lex(); - if (flag1) - immediateoperand(op, -0x2000000, 0x1FFFFFF); - else - immediateoperand(op, -0x8000, 0xFFFF); - } else if (tk == '-') { - tk = lex(); - op->u.imm.value = flag1 ? -immediatevalue(op, -0x1FFFFFF, 0x2000000) : -immediatevalue(op, -0x7FFF, 0x10000); - } else { - CError_Error(CErrorStr144); - } - } else { - CError_Error(CErrorStr144); - } - } else { - if (flag2) { - if (flag1) - immediateoperand(op, -0x2000000, 0x1FFFFFF); - else - immediateoperand(op, -0x8000, 0xFFFF); - } else { - CError_Error(CErrorStr144); - } - } -} - -static void imm_or_labeldiff_operand(InlineAsm *ia, IAOperand *op, SInt32 minimum, SInt32 maximum, Boolean negate) { - IAExpr expr; - Object *obj; - SInt32 value; - - InlineAsm_ExpressionPPC(&expr, 0); - - if ((obj = expr.xC) && !expr.x10 && expr.type == IAExpr_5 && obj->datatype == DDATA && IS_TYPE_INT_OR_ENUM(obj->type) && (obj->qual & Q_INLINE_DATA)) { - switch (ia->opcode) { - case PC_ADDI: - case PC_ADDIC: - case PC_ADDICR: - case PC_ADDIS: - case PC_ORI: - case PC_ORIS: - if (ia->args[1].u.imm.value) { - SInt32 cmp; - if (obj->datatype != DLOCAL) { - cmp = copts.codegen_pic ? INVALID_PIC_REG : NO_REG; - } else { - cmp = local_base_register(obj); - } - if (ia->args[1].u.imm.value == cmp) - break; - } - case PC_LI: - case PC_LIS: - case PC_TWI: - case PC_OPWORD: - InlineAsm_InitExpr5(&expr, expr.value + CInt64_GetULong(&obj->u.data.u.intconst)); - break; - } - } - - if (expr.label) { - if (expr.x18) { - op->type = IAOpnd_LabDiff; - if (negate) - op->negated = 1; - else - op->negated = 0; - op->u.labdiff.label1 = expr.label; - op->u.labdiff.label2 = expr.x18; - op->u.labdiff.offset = expr.value; - } else { - PPCError_Error(PPCErrorStr125, expr.label->name->name); - } - return; - } - - if (expr.xC) { - if (!expr.x10) { - if (ia->opcode != PC_OPWORD && expr.type == IAExpr_5) { - IllegalObjectInConst(&expr); - return; - } - - if (expr.xC->datatype == DLOCAL) { - op->type = IAOpnd_4; - op->u.obj.unk = IAExpr_1; - } else { - op->type = IAOpnd_3; - if (expr.type == IAExpr_5) { - expr.type = IAExpr_6; - PPCError_Error(PPCErrorStr180); - } - op->u.obj.unk = expr.type; - } - op->u.obj.obj = expr.xC; - op->u.obj.offset = expr.value; - } else { - PPCError_Error(PPCErrorStr123, expr.xC->name->name, expr.x10->name->name); - } - return; - } - - value = InlineAsm_GetExprValue(&expr); - if (value < minimum || value > maximum) - CError_Error(CErrorStr154); - - op->type = IAOpnd_Imm; - if (negate) - op->u.imm.value = -value; - else - op->u.imm.value = value; -} - -static void eatcommatoken(void) { - if (tk == ',') - tk = lex(); - else - CError_Error(CErrorStr116); -} - -static InlineAsm *InlineAsm_ScanAssemblyOperands(IAMnemonic *mnemonic) { - OpcodeInfo *info; - InlineAsm *ia; - SInt32 buffersize; - IAOperand *op; - int argcount; - char *format; - IARegister *reg; - - char code; - short effect; - Boolean has_excl; - Boolean has_question; - Boolean negate; - UInt32 t; - - info = &opcodeinfo[mnemonic->x4]; - argcount = info->x8; - if (PCODE_FLAG_SET_F(info) & fCanSetRecordBit) - argcount++; - if (!(PCODE_FLAG_SET_F(info) & fSetsCarry) && (PCODE_FLAG_SET_F(info) & fCanSetCarry)) - argcount++; - if (PCODE_FLAG_SET_T(info) & fCanLink) - argcount++; - - buffersize = sizeof(InlineAsm) + sizeof(IAOperand) * argcount; - ia = galloc(buffersize); - memset(ia, 0, buffersize); - - ia->opcode = mnemonic->x4; - ia->flags = 0; - ia->argcount = 0; - - op = ia->args; - for (format = mnemonic->format; *format; format++) { - CError_ASSERT(1664, ia->argcount < argcount); - - if (*format == ',') { - eatcommatoken(); - format++; - } else if (*format == ';') { - format++; - } - - if (*format == '[' || *format == '(') - format++; - - effect = EffectRead; - has_excl = 0; - has_question = 0; - negate = 0; - if (*format == '=') { - effect = EffectWrite; - format++; - } else if (*format == '+') { - effect = EffectRead | EffectWrite; - format++; - } - - if (*format == '-') { - negate = 1; - format++; - } - - if (*format == '?') { - has_question = 1; - format++; - } - - if (*format == '!') { - has_excl = 1; - format++; - } - - switch (*format) { - case 'p': - continue; - case '&': - if (format[1] == '2') { - op[0] = op[-2]; - format++; - if (op->type == IAOpnd_Reg) - op->u.reg.effect = effect; - ia->argcount++; - - op[1] = op[-1]; - op++; - if (op->type == IAOpnd_Reg) - op->u.reg.effect = effect; - } else { - op[0] = op[-1]; - if (op->type == IAOpnd_Reg) - op->u.reg.effect = effect; - } - break; - - case '%': { - SInt32 value; - format += pcode_const_from_format(format + 1, &value); - op->type = IAOpnd_Imm; - op->u.imm.value = value; - break; - } - - case 'b': - if (!isregisteroperand(RegClass_GPR)) { - if (tk == TK_INTCONST && tkintconst.lo == 0) - r0_operand(op); - } else { - registeroperand(op, RegClass_GPR, effect); - if (op->u.reg.object == NULL && op->u.reg.num == 0) - op->u.reg.effect = 0; - } - break; - - case 'r': - registeroperand(op, RegClass_GPR, effect); - break; - - case 'B': - case 'a': - case 'i': - case 't': - case 'u': - case 'x': - { - SInt32 value, hi, lo; - code = *format; - value = 16; - if (code == 'a') { - if (isdigit(format[1])) - code = *(++format); - else - CError_FATAL(1804); - } - - if (isdigit(format[1])) { - format += pcode_const_from_format(format + 1, &value); - } else if (code == 't' || code == 'B') { - code = 'u'; - value = 5; - } - - pcode_get_hi_lo(value, code, &hi, &lo); - if (!has_question || tk == ',') { - if (has_question) - tk = lex(); - if (has_excl) - getimmediateoperand(lo, hi); - else - immediateoperand(op, lo, hi); - } else { - op->type = IAOpnd_Imm; - op->u.imm.value = 0; - } - - if (code == 'i' && value == 16) - op->u.imm.value = (short) op->u.imm.value; - if (negate) - op->u.imm.value = -op->u.imm.value; - - if (pcode_check_imm_bits(op->u.imm.value, value, code)) - CError_FATAL(1838); - - break; - } - - case 'O': - if (tk == TK_INTCONST && tkintconst.lo == 0) { - getimmediateoperand(0, 0); - eatcommatoken(); - } - continue; - - case 'f': - registeroperand(op, RegClass_FPR, effect); - break; - - case 'v': - registeroperand(op, RegClass_VR, effect); - break; - - case 'T': - if (!has_question || tk == ',') { - if (has_question) - tk = lex(); - - immediateoperand(op, 268, 269); - if (op->u.reg.num == 268) - op->u.reg.num = 284; - else - op->u.reg.num = 285; - } else { - op->u.reg.num = 284; - } - - op->type = IAOpnd_Reg; - op->u.reg.rclass = RegClass_SPR; - op->u.reg.effect = effect; - break; - - case 'S': - { - SInt32 value; - format += pcode_const_from_format(format + 1, &value); - op->type = IAOpnd_Reg; - op->u.reg.rclass = RegClass_SPR; - op->u.reg.num = value; - op->u.reg.effect = effect; - break; - } - - case 'c': - if (has_question) { - if (isregisteroperand(RegClass_CRFIELD) || tk == TK_INTCONST) { - registeroperand(op, RegClass_CRFIELD, effect); - } else { - cr0_operand(op, effect); - if (format[1] == ',') - format++; - } - } else { - registeroperand(op, RegClass_CRFIELD, effect); - } - break; - - case 'l': - switch (ia->opcode) { - case PC_B: - case PC_BL: - labeloperand(ia, op, 1, mnemonic->x10 & 2, mnemonic->x10 & 1); - break; - default: - labeloperand(ia, op, 0, mnemonic->x10 & 2, mnemonic->x10 & 1); - break; - } - break; - - case 'w': - imm_or_labeldiff_operand(ia, op, -0x80000000, 0x7FFFFFFF, negate); - break; - - case 'M': - case 'm': - case 'n': - imm_or_labeldiff_operand(ia, op, -0x8000, 0xFFFF, negate); - break; - - case 'Q': - { - SInt32 cr = crbitoperand(); - op->type = IAOpnd_Reg; - op->u.reg.num = cr >> 2; - op->u.reg.rclass = RegClass_CRFIELD; - op->u.reg.effect = effect; - - ia->argcount++; - op[1].type = IAOpnd_Imm; - op[1].u.imm.value = cr % 4; - op++; - break; - } - - case 'd': { - short effect2; - CError_ASSERT(1971, format[1] == '('); - format++; - effect2 = EffectRead; - if (format[1] == '=') { - effect2 = EffectWrite; - format++; - } else if (format[1] == '+') { - effect2 = EffectRead | EffectWrite; - format++; - } - - CError_ASSERT(1983, format[1] == 'b'); - CError_ASSERT(1985, format[2] == ')'); - format += 2; - - switch (ia->opcode) { - case PC_LFS: - if (tk == TK_FLOATCONST) - floatoperand(op, ia, TYPE(&stfloat)); - else - memoryoperand(op, ia, 1, effect2); - break; - case PC_LFD: - if (tk == TK_FLOATCONST) - floatoperand(op, ia, TYPE(&stdouble)); - else - memoryoperand(op, ia, 1, effect2); - break; - default: - memoryoperand(op, ia, 1, effect2); - } - - break; - } - - case 'N': - immediateoperand(op, 1, 32); - break; - - case 's': - registeroperand(op, RegClass_SPR, effect); - break; - - case 'D': - if (tk == TK_IDENTIFIER && (reg = InlineAsm_LookupDCRRegister(tkidentifier->name))) { - op->type = IAOpnd_Imm; - op->u.imm.value = reg->num; - } else { - immediateoperand(op, 0, 1023); - } - break; - - case 'Y': - { - SInt32 mask = 255; - SInt32 i; - if (ia->opcode == PC_MTCRF) { - if (ia->args[0].type != IAOpnd_Imm) - CError_Error(CErrorStr144); - mask = ia->args[0].u.imm.value; - } - for (i = 0; i < 8; i++) { - if ((0x80 >> i) & mask) { - op->type = IAOpnd_Reg; - op->u.reg.num = i; - op->u.reg.rclass = RegClass_CRFIELD; - op->u.reg.effect = effect; - ia->argcount++; - op++; - } - } - ia->argcount--; - op--; - break; - } - - case 'P': - op->type = IAOpnd_Reg; - op->u.reg.rclass = RegClass_SPR; - op->u.reg.object = NULL; - if (format[1] == '3') { - format++; - op->u.reg.num = getimmediateoperand(0, 7); - } else { - op->u.reg.num = getimmediateoperand(0, 3); - } - op->u.reg.effect = effect; - break; - - case 'C': - op->type = IAOpnd_Reg; - op->u.reg.rclass = RegClass_SPR; - op->u.reg.object = NULL; - op->u.reg.num = 9; - op->u.reg.effect = effect; - break; - - case 'L': - op->type = IAOpnd_Reg; - op->u.reg.rclass = RegClass_SPR; - op->u.reg.object = NULL; - op->u.reg.num = 8; - op->u.reg.effect = effect; - break; - - case 'X': - op->type = IAOpnd_Reg; - op->u.reg.rclass = RegClass_SPR; - op->u.reg.object = NULL; - op->u.reg.num = 1; - op->u.reg.effect = effect; - break; - - case 'Z': - op->type = IAOpnd_Reg; - op->u.reg.rclass = RegClass_CRFIELD; - op->u.reg.object = NULL; - t = info->flags & 0xC0000000; - if (t == 0x40000000) { - op->u.reg.num = 1; - } else if (t == 0xC0000000) { - op->u.reg.num = 6; - } else { - op->u.reg.num = 0; - } - op->u.reg.effect = effect; - break; - - default: - CError_FATAL(2266); - } - - while (format[1] && strchr("/<>|*", format[1])) { - int index; - SInt32 value; - SInt32 value2; - IAOperand tmp; - switch ((code = *(++format))) { - case '/': - index = -1; - if (format[1] == '2') { - index = -2; - format++; - } - - tmp = op[index]; - op[index] = op[0]; - op[0] = tmp; - break; - case '*': - case '<': - case '>': - case '|': - if (op->type == IAOpnd_Imm) - value = op->u.imm.value; - else if (op->type == IAOpnd_Reg) - value = op->u.reg.num; - else - CError_FATAL(2312); - - if (format[1] == 'p') { - format++; - if (op[-1].type == IAOpnd_Imm) - value2 = op[-1].u.imm.value; - else if (op[-1].type == IAOpnd_Reg) - value2 = op[-1].u.reg.num; - else - CError_FATAL(2322); - } else if (isdigit(format[1])) { - format += pcode_const_from_format(format + 1, &value2); - } else { - CError_FATAL(2327); - } - - switch (code) { - case '<': - value = value2 - value; - break; - case '>': - value = value - value2; - break; - case '|': - value = value + value2; - break; - case '*': - value = value * value2; - break; - default: - CError_FATAL(2348); - } - - if (op->type == IAOpnd_Imm) - op->u.imm.value = value; - else if (op->type == IAOpnd_Reg) - op->u.reg.num = value; - else - CError_FATAL(2355); - break; - } - } - - ia->argcount++; - op++; - if (format[1] == ']' || format[1] == ')') - format++; - } - - return ia; -} - -static int mnemonic_has_overflow(char *buf) { - int result = 0; - - if (buf[strlen(buf) - 1] == 'o') { - if (!strcmp(buf, "bso")) - return 0; - if (!strcmp(buf, "fcmpo")) - return 0; - if (!strcmp(buf, "eieio")) - return 0; - if (!strcmp(buf, "vslo")) - return 0; - if (!strcmp(buf, "vsro")) - return 0; - result = 1; - } - - return result; -} - -static int mnemonic_has_absolute(const char *buf) { - int result = 0; - char last = buf[strlen(buf) - 1]; - - if (buf[0] == 'b' && last == 'a') - result = 1; - - return result; -} - -static int mnemonic_has_linkregister(const char *buf) { - int result = 0; - char last = buf[strlen(buf) - 1]; - - if (buf[0] == 'b' && last == 'l') - result = 1; - - return result; -} - -static int mnemonic_has_record(char *buf) { - int result = 0; - - if (lookahead() == '.') { - tk = lex(); - result = 1; - strcat(buf, "."); - } - - return result; -} - -static void installregistervariables(void) { -} - -void InlineAsm_InitializePPC(void) { - Test_Version_Numbers(); - allow_array_expressions = 1; - supports_hardware_fpu = 1; - assembledinstructions = 0; - - switch (copts.processor) { - case CPU_PPC401: cpu = CPUMask_401; break; - case CPU_PPC403: cpu = CPUMask_403; break; - case CPU_PPC505: cpu = CPUMask_50x; break; - case CPU_PPC509: cpu = CPUMask_50x; break; - case CPU_PPC555: cpu = CPUMask_55x_56x; break; - case CPU_PPC556: cpu = CPUMask_55x_56x; break; - case CPU_PPC565: cpu = CPUMask_55x_56x; break; - case CPU_PPC601: cpu = CPUMask_601; break; - case CPU_PPC602: cpu = CPUMask_602; break; - case CPU_PPC8240: cpu = CPUMask_8240; break; - case CPU_PPC8260: cpu = CPUMask_8260; break; - case CPU_PPC603: cpu = CPUMask_603; break; - case CPU_PPC603e: cpu = CPUMask_603; break; - case CPU_PPC604: cpu = CPUMask_604; break; - case CPU_PPC604e: cpu = CPUMask_604; break; - case CPU_PPC740: cpu = CPUMask_740_750; break; - case CPU_PPC750: cpu = CPUMask_740_750; break; - case CPU_PPC801: cpu = CPUMask_801_821_860; break; - case CPU_PPC821: cpu = CPUMask_801_821_860; break; - case CPU_PPC823: cpu = CPUMask_823_850; break; - case CPU_PPC850: cpu = CPUMask_823_850; break; - case CPU_PPC860: cpu = CPUMask_801_821_860; break; - case CPU_PPC7400: case CPU_PPC7450: cpu = CPUMask_74xx; break; - case CPU_Generic: cpu = CPUMask_Generic; break; - default: - CError_FATAL(2613); - } - - if (copts.altivec_model) - cpu |= 0x40000000; -} - -void InlineAsm_Initialize(AssemblerType assemblertype) { - assembler_type = assemblertype; - - if (assembler_type == 0) { - InlineAsm_InitializePPC(); - pic_base_reg = INVALID_PIC_REG; - } else { - pic_base_reg = 0; - pic_base_label = NULL; - } - - InlineAsm_InitializeMnemonicsPPC(); - InlineAsm_InitializeRegisters(); - InlineAsm_InitializeRegistersPPC(); - - if (assembler_type == 0) { - installregistervariables(); - } else { - process_arguments(setup_assembly_argument, 0); - assign_local_addresses(); - } -} - -static IAEntryPoint *InlineAsm_CreateEntryPoint(HashNameNode *name, Boolean flag) { - Object *obj; - IAEntryPoint *ep; - IALookupResult result; - - if (InlineAsm_LookupSymbol(name, &result) && (obj = result.object)) { - if (!(obj->datatype == DFUNC && !(obj->flags & OBJECT_DEFINED))) - CError_Error(CErrorStr122, name->name); - - obj->flags |= OBJECT_DEFINED; - obj->sclass = flag ? TK_STATIC : TK_EXTERN; - - ep = lalloc(sizeof(IAEntryPoint)); - memclrw(ep, sizeof(IAEntryPoint)); - ep->x0 = IADirective_Entry; - ep->x2 = 1; - ep->x8 = obj; - ep->size = assembledinstructions * 4; - } else { - CError_Error(CErrorStr140, name->name); - } - - return ep; -} - -static InlineAsm *InlineAsm_CreateFrFree(void) { - InlineAsm *ia = lalloc(sizeof(InlineAsm)); - memclrw(ia, sizeof(InlineAsm)); - ia->opcode = IADirective_FrFree; - ia->flags = IAFlag1; - return ia; -} - -SInt32 InlineAsm_IsDirective(AssemblerType assemblertype) { - char *name; - SInt32 directive = IADirective_Null; - - if (tk == '.') - tk = lex(); - - if (tk == TK_IDENTIFIER) { - name = tkidentifier->name; - if (!strcmp(name, "machine")) { - directive = IADirective_Machine; - } else if (assemblertype == AssemblerType_1) { - if (!strcmp(name, "entry")) { - directive = IADirective_Entry; - } else if (!strcmp(name, "fralloc")) { - directive = IADirective_FrAlloc; - } else if (!strcmp(name, "nofralloc")) { - directive = IADirective_NoFrAlloc; - } else if (!strcmp(name, "frfree")) { - directive = IADirective_FrFree; - } else if (!strcmp(name, "smclass")) { - directive = IADirective_SmClass; - } else if (!strcmp(name, "picbase")) { - directive = IADirective_PicBase; - } else { - directive = IADirective_Null; - } - } - } - - return directive; -} - -void InlineAsm_ProcessDirective(SInt32 directive) { - Boolean flag; - Statement *stmt; - IAOperand op; - - switch (directive) { - case IADirective_Entry: - flag = 0; - tk = lex(); - if (tk == TK_STATIC) { - flag = 1; - tk = lex(); - } else if (tk == TK_EXTERN) { - tk = lex(); - } - - if (tk != TK_IDENTIFIER) - CError_Error(CErrorStr107); - - stmt = CFunc_AppendStatement(ST_ASM); - stmt->expr = NULL; - stmt->expr = (ENode *) InlineAsm_CreateEntryPoint(tkidentifier, flag); - stmt->sourceoffset = -1; - tk = lex(); - break; - - case IADirective_FrAlloc: - if (assembledinstructions) - CError_Error(CErrorStr166); - if (asm_alloc_flags[0]) - CError_Error(CErrorStr165); - if (asm_alloc_flags[1] || asm_alloc_flags[2]) - CError_Error(CErrorStr166); - - tk = lex(); - if (tk != TK_EOL && tk != ';') - fralloc_parameter_area_size = getimmediateoperand(0x20, 0x7FFE); - - requires_frame = 1; - asm_alloc_flags[0] = 1; - break; - - case IADirective_NoFrAlloc: - if (asm_alloc_flags[0] || asm_alloc_flags[1]) - CError_Error(CErrorStr165); - if (asm_alloc_flags[2]) - CError_Error(CErrorStr166); - if (assembledinstructions) - CError_Error(CErrorStr166); - tk = lex(); - - asm_alloc_flags[1] = 1; - user_responsible_for_frame = 1; - break; - - case IADirective_FrFree: - if (asm_alloc_flags[1] || asm_alloc_flags[2]) - CError_Error(CErrorStr166); - - asm_alloc_flags[2] = 1; - stmt = CFunc_AppendStatement(ST_ASM); - stmt->expr = NULL; - stmt->expr = (ENode *) InlineAsm_CreateFrFree(); - if (copts.filesyminfo) - stmt->sourceoffset = CPrep_GetFileOffsetInfo(&cparser_fileoffset); - else - stmt->sourceoffset = -1; - tk = lex(); - break; - - case IADirective_Machine: - tk = lex(); - if (tk == TK_INTCONST) { - switch (tkintconst.lo) { - case 401: cpu = CPUMask_401; break; - case 403: cpu = CPUMask_403; break; - case 505: cpu = CPUMask_50x; break; - case 509: cpu = CPUMask_50x; break; - case 555: cpu = CPUMask_55x_56x; break; - case 556: cpu = CPUMask_55x_56x; break; - case 565: cpu = CPUMask_55x_56x; break; - case 601: cpu = CPUMask_601; break; - case 602: cpu = CPUMask_602; break; - case 8240: cpu = CPUMask_8240; break; - case 8260: cpu = CPUMask_8260; break; - case 603: cpu = CPUMask_603; break; - case 604: cpu = CPUMask_604; break; - case 740: cpu = CPUMask_740_750; break; - case 750: cpu = CPUMask_740_750; break; - case 801: cpu = CPUMask_801_821_860; break; - case 821: cpu = CPUMask_801_821_860; break; - case 823: cpu = CPUMask_823_850; break; - case 850: cpu = CPUMask_823_850; break; - case 860: cpu = CPUMask_801_821_860; break; - case 7400: cpu = CPUMask_74xx; break; - default: - CError_Error(CErrorStr144); - } - } else if (tk == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "all")) { - cpu = CPUMask_All; - } else if (!strcmp(tkidentifier->name, "generic")) { - cpu = CPUMask_Generic; - } else if (!strcmp(tkidentifier->name, "603e")) { - cpu = CPUMask_603; - } else if (!strcmp(tkidentifier->name, "604e")) { - cpu = CPUMask_604; - } else if (!strcmp(tkidentifier->name, "PPC603e")) { - cpu = CPUMask_603; - } else if (!strcmp(tkidentifier->name, "PPC604e")) { - cpu = CPUMask_604; - } else if (!strcmp(tkidentifier->name, "altivec")) { - cpu = CPUMask_74xx; - } else { - CError_Error(CErrorStr144); - } - } else { - CError_Error(CErrorStr144); - } - tk = lex(); - break; - - case IADirective_SmClass: - tk = lex(); - if (tk == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "PR")) - sm_section = SECT_TEXT; - else - CError_Error(CErrorStr144); - } else { - CError_Error(CErrorStr144); - } - tk = lex(); - break; - - case IADirective_PicBase: - tk = lex(); - registeroperand(&op, RegClass_GPR, EffectRead); - - if (!(op.type == IAOpnd_Reg && op.u.reg.object == NULL)) - CError_Error(CErrorStr144); - - tk = lex(); - if (tk == TK_IDENTIFIER) { - savepicbase(op.u.reg.num, tkidentifier); - tk = lex(); - } else { - CError_Error(CErrorStr144); - } - break; - - default: - CError_Error(CErrorStr261); - } -} - -void InlineAsm_ScanAssemblyDirective(void) { - SInt32 directive; - - if ((directive = InlineAsm_IsDirective(assembler_type)) != IADirective_Null) - InlineAsm_ProcessDirective(directive); -} - -void InlineAsm_ScanAssemblyInstruction(void) { - Statement *stmt; - InlineAsm *ia; - IAMnemonic *mnemonic; - Boolean record_flag; - Boolean flag3; - Boolean flag4; - Boolean flag5; - Boolean flag1; - Boolean flag2; - SInt32 directive; - OpcodeInfo *info; - char buf[20]; - - flag1 = 0; - flag2 = 0; - if ((directive = InlineAsm_IsDirective(assembler_type)) != IADirective_Null) { - InlineAsm_ProcessDirective(directive); - return; - } - - stmt = CFunc_AppendStatement(ST_ASM); - stmt->expr = NULL; - if (copts.filesyminfo) - stmt->sourceoffset = CPrep_GetFileOffsetInfo(&cparser_fileoffset); - else - stmt->sourceoffset = -1; - - strncpy(buf, tkidentifier->name, sizeof(buf)); - record_flag = mnemonic_has_record(buf); - mnemonic = InlineAsm_LookupMnemonicPPC(buf); - if (!mnemonic) - CError_Error(CErrorStr261); - - info = &opcodeinfo[mnemonic->x4]; - flag3 = (FLAG_SET_F(info->flags) & fCanSetCarry) && (mnemonic->x10 & 0x400); - flag4 = (FLAG_SET_T(info->flags) & fCanBeAbsolute) && (mnemonic->x10 & 2); - flag5 = (FLAG_SET_T(info->flags) & fCanLink) && (mnemonic->x10 & 1); - - if ((cpu == CPUMask_Generic) && (cpu & CPUFLAG_LOW_MASK) != ((cpu & mnemonic->cpu) & CPUFLAG_LOW_MASK)) { - CError_Error(CErrorStr152); - } else if (((cpu & mnemonic->cpu) & CPUFLAG_LOW_MASK) == 0) { - CError_Error(CErrorStr152); - } else if ((mnemonic->cpu & CPUFLAG_10000000) && !(cpu & CPUFLAG_10000000)) { - CError_Error(CErrorStr152); - } else if ((mnemonic->cpu & CPUFLAG_8000000) && !(cpu & CPUFLAG_8000000)) { - CError_Error(CErrorStr152); - } else if ((mnemonic->cpu & CPUFLAG_2000000) && !(cpu & CPUFLAG_2000000)) { - CError_Error(CErrorStr152); - } else if ((mnemonic->cpu & CPUFLAG_4000000) && !(cpu & CPUFLAG_4000000)) { - CError_Error(CErrorStr152); - } else if ((mnemonic->cpu & CPUFLAG_1000000) && !(cpu & CPUFLAG_1000000)) { - CError_Error(CErrorStr152); - } else if ((mnemonic->cpu & CPUFLAG_40000000) && !(cpu & CPUFLAG_40000000)) { - CError_Error(CErrorStr152); - } else if ((mnemonic->cpu & CPUFLAG_20000000) && !(cpu & CPUFLAG_20000000)) { - CError_Error(CErrorStr152); - } else if ((mnemonic->cpu & CPUFLAG_800000) && !(cpu & CPUFLAG_800000)) { - CError_Error(CErrorStr152); - } - - tk = lex(); - if (tk == '+' || tk == '-') { - if ( - ((OPCODE_PART_1(mnemonic->x10) == 16) && (OPCODE_PART_2(mnemonic->x10) != 20)) || - ((OPCODE_PART_1(mnemonic->x10) == 19) && (OPCODE_PART_3(mnemonic->x10) == 528) && (OPCODE_PART_2(mnemonic->x10) != 20)) || - ((OPCODE_PART_1(mnemonic->x10) == 19) && (OPCODE_PART_3(mnemonic->x10) == 16) && (OPCODE_PART_2(mnemonic->x10) != 20)) - ) { - if (tk == '+') - flag1 = 1; - else if (tk == '-') - flag2 = 1; - tk = lex(); - } else { - CError_Error(CErrorStr120); - } - } - - stmt->expr = (ENode *) InlineAsm_ScanAssemblyOperands(mnemonic); - - ia = (InlineAsm *) stmt->expr; - if (record_flag) - ia->flags2 |= IAFlagsB_1; - if (flag3) - ia->flags2 |= IAFlagsB_2; - if (flag4) - ia->flags2 |= IAFlagsB_4; - if (flag5) - ia->flags2 |= IAFlagsB_8; - if (flag1) - ia->flags2 |= IAFlagsB_10; - if (flag2) - ia->flags2 |= IAFlagsB_20; - if (volatileasm) - ia->flags2 |= IAFlagsB_40; - - ++assembledinstructions; -} - -static PCode *InlineAsm_TranslateIRtoPCodePPC(InlineAsm *ia, int argcount, AssemblerType assemblertype) { - PCode *pc; - int index; - int extra_args; - int reg; - int newargcount; - SInt32 buffersize; - IAOperand *src; - PCodeArg *dest; - OpcodeInfo *info; - - info = &opcodeinfo[ia->opcode]; - index = 0; - extra_args = 0; - reg = 0; - - if ((PCODE_FLAG_SET_F(info) & fCanSetRecordBit) && !(PCODE_FLAG_SET_F(info) & fRecordBit)) - extra_args++; - - if (!(PCODE_FLAG_SET_F(info) & fSetsCarry) && (PCODE_FLAG_SET_F(info) & fCanSetCarry)) - extra_args++; - - if (argcount < ia->argcount) { - if ((argcount + extra_args) >= ia->argcount) { - extra_args -= (ia->argcount - argcount); - argcount = ia->argcount; - } else { - CError_FATAL(3317); - } - } - - if (ia->opcode == PC_B && ia->args[0].type == IAOpnd_Imm) - ia->flags2 |= IAFlagsB_40; - - if (ia->opcode == PC_TWI || ia->opcode == PC_TW || ia->opcode == PC_TRAP || ia->opcode == PC_SC) - ia->flags |= IAFlag2; - - if (ia->flags & IAFlag2) { - newargcount = argcount + branch_count_volatiles(); - if (copts.exceptions && current_statement && assembler_type == 0) - newargcount += countexceptionactionregisters(current_statement->dobjstack); - - buffersize = sizeof(PCode) + sizeof(PCodeArg) * (newargcount + extra_args); - pc = lalloc(buffersize); - memset(pc, 0, buffersize); - pc->argCount = newargcount; - } else if (ia->opcode == PC_STMW || ia->opcode == PC_LMW) { - reg = ia->args[0].u.reg.object ? OBJECT_REG(ia->args[0].u.reg.object) : ia->args[0].u.reg.num; - newargcount = argcount + (32 - reg); - - buffersize = sizeof(PCode) + sizeof(PCodeArg) * newargcount; - pc = lalloc(buffersize); - memset(pc, 0, buffersize); - pc->argCount = newargcount; - } else { - buffersize = sizeof(PCode) + sizeof(PCodeArg) * (argcount + extra_args); - pc = lalloc(buffersize); - memset(pc, 0, buffersize); - pc->argCount = (ia->argcount > argcount) ? ia->argcount : argcount; - } - - pc->op = ia->opcode; - pc->flags = info->flags; - pc->sourceoffset = current_statement ? current_statement->sourceoffset : -1; - - dest = pc->args; - src = ia->args; - argcount += extra_args; - while (index < argcount) { - if (index >= ia->argcount) { - dest->kind = PCOp_PLACEHOLDEROPERAND; - } else { - switch (src->type) { - case IAOpnd_0: - dest->kind = PCOp_PLACEHOLDEROPERAND; - break; - - case IAOpnd_Imm: - dest->kind = PCOp_IMMEDIATE; - dest->data.imm.value = src->u.imm.value; - if (pc->flags & (fIsRead | fIsWrite)) - pc->flags |= fIsPtrOp; - dest->data.imm.obj = NULL; - break; - - case IAOpnd_Reg: { - int r20; - r20 = 0; - if (src->u.reg.object) { - if (Registers_GetVarInfo(src->u.reg.object)->flags & VarInfoFlag2) { - if (src->u.reg.num == 1) - r20 = OBJECT_REG_HI(src->u.reg.object); - else - r20 = OBJECT_REG(src->u.reg.object); - } else { - if (Registers_GetVarInfo(src->u.reg.object)->flags & VarInfoFlag40) - PPCError_Error(PPCErrorStr172, src->u.reg.object->name->name); - else - PPCError_Error(PPCErrorStr167, src->u.reg.object->name->name); - } - } else if (src->u.reg.num == INVALID_PIC_REG) { - r20 = pic_base_reg; - } else { - r20 = src->u.reg.num; - } - - dest->kind = PCOp_REGISTER; - dest->arg = src->u.reg.rclass; - dest->data.reg.reg = r20; - dest->data.reg.effect = src->u.reg.effect; - if (pc->op == PC_RLWIMI && (dest->data.reg.effect & EffectWrite) && dest->arg == RegClass_GPR && !(dest->data.reg.effect & EffectRead)) - CError_FATAL(3442); - - if (dest->arg == RegClass_SPR) { - int i; - dest->kind = PCOp_SYSREG; - for (i = 0; i < 4; i++) { - if (dest->data.reg.reg == spr_to_sysreg[i]) { - dest->kind = PCOp_REGISTER; - dest->arg = RegClass_SPR; - dest->data.reg.reg = i; - break; - } - } - pcsetsideeffects(pc); - } else if (dest->arg == RegClass_6 || dest->arg == RegClass_DCR) { - short save = dest->data.reg.reg; - dest->kind = PCOp_IMMEDIATE; - dest->data.imm.value = save; - dest->data.imm.obj = NULL; - break; - } - - if ((src->u.reg.effect & EffectWrite) && dest->data.reg.reg < n_real_registers[dest->arg]) { - if (src->u.reg.object) { - if (Registers_GetVarInfo(src->u.reg.object)->flags & VarInfoFlag4) { - int reg, regHi; - CError_ASSERT(3474, dest->arg == RegClass_GPR); - - regHi = OBJECT_REG_HI(src->u.reg.object); - reg = OBJECT_REG(src->u.reg.object); - retain_GPR_pair(src->u.reg.object, reg, regHi); - } else { - retain_register(src->u.reg.object, dest->arg, dest->data.reg.reg); - } - } else { - retain_register(NULL, dest->arg, dest->data.reg.reg); - } - } - - break; - } - - case IAOpnd_Lab: - if (!src->u.lab.label->pclabel) - src->u.lab.label->pclabel = makepclabel(); - dest->kind = PCOp_LABEL; - dest->data.label.label = src->u.lab.label->pclabel; - break; - - case IAOpnd_3: - case IAOpnd_4: - dest->kind = PCOp_MEMORY; - dest->arg = src->u.obj.unk; - dest->data.mem.obj = src->u.obj.obj; - dest->data.mem.offset = src->u.obj.offset; - if (pc->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) { - pc->alias = make_alias(dest->data.mem.obj, dest->data.mem.offset, nbytes_loaded_or_stored_by(pc)); - if (is_volatile_object(dest->data.mem.obj)) - pc->flags |= fIsVolatile; - if (OBJ_GET_TARGET_CONST(dest->data.mem.obj)) - pc->flags |= fIsConst; - } - break; - - case IAOpnd_LabDiff: - if (src->u.labdiff.label1->pclabel == NULL) - src->u.labdiff.label1->pclabel = makepclabel(); - if (src->u.labdiff.label2->pclabel == NULL) - src->u.labdiff.label2->pclabel = makepclabel(); - if (pc->flags & (fIsRead | fIsWrite)) - pc->flags |= fIsPtrOp; - dest->kind = PCOp_LABELDIFF; - dest->data.labeldiff.labelA = src->u.labdiff.label1->pclabel; - dest->data.labeldiff.labelB = src->u.labdiff.label2->pclabel; - dest->arg = src->negated; - dest->data.labeldiff.offset = src->u.labdiff.offset; - break; - - default: - CError_FATAL(3528); - } - } - - index++; - dest++; - src++; - } - - if (ia->opcode == PC_STMW || ia->opcode == PC_LMW) { - int i; - for (i = reg; i < 32; i++, dest++) { - dest->kind = PCOp_REGISTER; - dest->arg = RegClass_GPR; - dest->data.reg.reg = i; - dest->data.reg.effect = ((ia->opcode == PC_LMW) ? EffectWrite : EffectRead); - } - } - - if (ia->flags & IAFlag2) { - UInt32 masks[5] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; - branch_record_volatiles(dest, masks); - if (copts.exceptions && current_statement && assembler_type == 0) - noteexceptionactionregisters(current_statement->dobjstack, dest); - } - - return pc; -} - -void InlineAsm_TranslateIRtoPCode(Statement *stmt) { - InlineAsm *ia; - PCode *pc; - - ia = (InlineAsm *) stmt->expr; - pc = InlineAsm_TranslateIRtoPCodePPC(ia, opcodeinfo[ia->opcode].x8, assembler_type); - appendpcode(pclastblock, pc); - - if ((ia->flags2 & IAFlagsB_40) || !copts.optimizewithasm) - setpcodeflags(fSideEffects); - - if (ia->flags2 & IAFlagsB_1) { - if (PCODE_FLAG_SET_F(pc) & fCanSetRecordBit) - pcsetrecordbit(pclastblock->lastPCode); - else - CError_Error(CErrorStr261); - } - - if (ia->flags2 & IAFlagsB_2) { - if (PCODE_FLAG_SET_F(pc) & fCanSetCarry) - setpcodeflags(fOverflow); // idk? - else - CError_Error(CErrorStr261); - } - - if (ia->flags2 & IAFlagsB_4) { - if (PCODE_FLAG_SET_T(pc) & fCanBeAbsolute) { - int i; - for (i = 0; i < pc->argCount; i++) { - if (pc->args[i].kind == PCOp_LABEL || pc->args[i].kind == PCOp_MEMORY) { - PPCError_Error(PPCErrorStr177); - break; - } - } - setpcodeflags(fAbsolute); - } else { - CError_Error(CErrorStr261); - } - } - - if (ia->flags2 & IAFlagsB_8) { - if (PCODE_FLAG_SET_T(pc) & fCanLink) { - pcsetlinkbit(pclastblock->lastPCode); - if (!(ia->flags & IAFlag2)) { - pclastblock->lastPCode->flags &= ~fIsCall; - pclastblock->lastPCode->flags |= fIsBranch; - } - makes_call = 1; - } else { - CError_Error(CErrorStr261); - } - } - - if (ia->flags2 & IAFlagsB_10) - setpcodeflags(fCanSetRecordBit); - if (ia->flags2 & IAFlagsB_20) - setpcodeflags(fCanSetCarry); - - if (OPCODE_PART_1(opcodeinfo[pc->op].insn) == 16) { - PCodeLabel *dest = NULL; - PCodeLabel *src = makepclabel(); - switch (pc->op) { - case PC_BC: - if (pc->args[3].kind == PCOp_LABEL) - dest = pc->args[3].data.label.label; - break; - case PC_BT: - case PC_BF: - case PC_BDNZT: - case PC_BDNZF: - case PC_BDZT: - case PC_BDZF: - if (pc->args[2].kind == PCOp_LABEL) - dest = pc->args[2].data.label.label; - break; - case PC_BDNZ: - case PC_BDZ: - if (pc->args[0].kind == PCOp_LABEL) - dest = pc->args[0].data.label.label; - break; - default: - CError_FATAL(3715); - } - - if (dest) { - pcbranch(pclastblock, dest); - pcbranch(pclastblock, src); - makepcblock(); - pclabel(pclastblock, src); - } - return; - } - - if (OPCODE_PART_1(opcodeinfo[pc->op].insn) == 18) { - PCodeLabel *label; - if (ia->flags2 & IAFlagsB_8) { - label = makepclabel(); - pcbranch(pclastblock, label); - } - if (pc->args[0].kind == PCOp_LABEL) - pcbranch(pclastblock, pc->args[0].data.label.label); - makepcblock(); - if (ia->flags2 & IAFlagsB_8) { - pclabel(pclastblock, label); - } - return; - } - - if (OPCODE_PART_1(opcodeinfo[pc->op].insn) == 19) { - switch (pc->op) { - case PC_BLR: - case PC_RFI: - if (asm_alloc_flags[3]) - asm_alloc_flags[9] = 1; - else - asm_alloc_flags[8] = 1; - - if (asm_alloc_flags[4]) - asm_alloc_flags[5] = 1; - - if (pc->op == PC_BLR) - asm_alloc_flags[6] = 1; - else - asm_alloc_flags[7] = 1; - break; - } - } -} - -const char *InlineAsm_GetMnemonic(InlineAsm *ia) { - return opcodeinfo[ia->opcode].name; -} - -static void savepicbase(short reg, HashNameNode *name) { - IALookupResult result; - - if (!InlineAsm_LookupSymbol(name, &result)) - result.label = InlineAsm_DeclareLabel(name); - - pic_base_label = result.label; - pic_base_reg = reg; - uses_globals = 1; -} - -static SInt32 InlineAsm_OpcodeSize(InlineAsm *ia) { - if (opcodeinfo[ia->opcode].flags & (fIsRead | fIsWrite)) { - switch (ia->opcode) { - case PC_LBZ: - case PC_LBZU: - case PC_LBZX: - case PC_LBZUX: - case PC_STB: - case PC_STBU: - case PC_STBX: - case PC_STBUX: - return 1; - case PC_LHZ: - case PC_LHZU: - case PC_LHZX: - case PC_LHZUX: - case PC_LHA: - case PC_LHAU: - case PC_LHAX: - case PC_LHAUX: - case PC_LHBRX: - case PC_STH: - case PC_STHU: - case PC_STHX: - case PC_STHUX: - case PC_STHBRX: - return 2; - case PC_LWZ: - case PC_LWZU: - case PC_LWZX: - case PC_LWZUX: - case PC_LWBRX: - case PC_STW: - case PC_STWU: - case PC_STWX: - case PC_STWUX: - case PC_STWBRX: - case PC_LFS: - case PC_LFSU: - case PC_LFSX: - case PC_LFSUX: - case PC_STFS: - case PC_STFSU: - case PC_STFSX: - case PC_STFSUX: - case PC_LWARX: - case PC_STFIWX: - case PC_STWCX: - case PC_ECIWX: - case PC_ECOWX: - case PC_MFROM: - case PC_LSCBX: - return 4; - case PC_LMW: - case PC_STMW: - if (ia->args[0].type == IAOpnd_Reg && ia->args[0].u.reg.object == NULL) - return (32 - ia->args[0].u.reg.num) * 4; - else - return 128; - case PC_LFD: - case PC_LFDU: - case PC_LFDX: - case PC_LFDUX: - case PC_STFD: - case PC_STFDU: - case PC_STFDX: - case PC_STFDUX: - return 8; - case PC_LSWI: - case PC_STSWI: - return ia->args[2].u.imm.value; - case PC_LSWX: - case PC_STSWX: - return 128; - case PC_LVEBX: - case PC_STVEBX: - return 1; - case PC_LVEHX: - case PC_STVEHX: - return 2; - case PC_LVEWX: - case PC_STVEWX: - return 4; - case PC_LVSL: - case PC_LVSR: - case PC_LVX: - case PC_LVXL: - case PC_STVX: - case PC_STVXL: - return 16; - default: - CError_FATAL(3924); - } - } else { - if (opcodeinfo[ia->opcode].flags & fOpTypeGPR) - return 4; - if (opcodeinfo[ia->opcode].flags & fOpTypeFPR) - return 8; - if (opcodeinfo[ia->opcode].flags & fOpTypeVR) - return 16; - - if (opcodeinfo[ia->opcode].flags & fSideEffects) { - switch (ia->opcode) { - case PC_TLBIE: - case PC_TLBLD: - case PC_TLBLI: - return 4; - default: - CError_FATAL(3941); - } - } - } - - CError_FATAL(3944); - return 0; -} - -void CodeGen_GetAsmEffects(Statement *stmt, IAEffects *effects) { - InlineAsm *ia; - OpcodeInfo *info; - int i; - IAOperand *op; - VarInfo *vi; - - ia = (InlineAsm *) stmt->expr; - info = &opcodeinfo[ia->opcode]; - - effects->numoperands = 0; - effects->numlabels = 0; - effects->x1 = 0; - effects->x2 = 0; - effects->x3 = 0; - effects->x4 = 0; - effects->x0 = 0; - effects->x5 = 0; - - if (info->flags & fIsPtrOp) { - if (info->flags & fIsRead) - effects->x1 = 1; - if (info->flags & fIsWrite) - effects->x2 = 1; - } - - if (PCODE_FLAG_SET_T(info) & fCanLink) { - if (ia->flags2 & IAFlagsB_8) - effects->x4 = 1; - else if ((info->flags & fIsCall) || (info->flags & fIsWrite)) - effects->x3 = 1; - - if (ia->opcode == PC_B) { - if (ia->args[0].type == IAOpnd_Imm) - effects->x0 = 1; - effects->x5 = 1; - } - } - - if (info->flags & fSideEffects) - effects->x0 = 1; - - if (ia->opcode == PC_BC && (ia->flags2 & IAFlagsB_8)) - effects->x4 = 1; - - for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { - switch (op->type) { - case IAOpnd_0: - case IAOpnd_Imm: - break; - case IAOpnd_Reg: - if (op->u.reg.object) { - if ((vi = Registers_GetVarInfo(op->u.reg.object))) - vi->flags |= VarInfoFlag40; - if (op->u.reg.effect & EffectRead) { - if ( - TYPE_FITS_IN_REGISTER(op->u.reg.object->type) || - IS_TYPE_FLOAT(op->u.reg.object->type) || - IS_TYPE_VECTOR(op->u.reg.object->type) - ) { - effects->operands[effects->numoperands].type = IAEffect_0; - effects->operands[effects->numoperands].object = op->u.reg.object; - effects->operands[effects->numoperands].offset = 0; - effects->operands[effects->numoperands].size = op->u.reg.object->type->size; - effects->numoperands++; - } else { - CError_FATAL(4051); - } - } - } - break; - case IAOpnd_3: - case IAOpnd_4: - if (op->u.obj.obj) { - if (info->flags & fIsRead) { - effects->operands[effects->numoperands].type = IAEffect_0; - effects->operands[effects->numoperands].object = op->u.obj.obj; - effects->operands[effects->numoperands].offset = op->u.obj.offset; - effects->operands[effects->numoperands].size = InlineAsm_OpcodeSize(ia); - effects->numoperands++; - } else if (!(info->flags & (fIsBranch | fIsCall))) { - effects->operands[effects->numoperands].type = IAEffect_3; - effects->operands[effects->numoperands].object = op->u.obj.obj; - effects->operands[effects->numoperands].offset = op->u.obj.offset; - effects->operands[effects->numoperands].size = InlineAsm_OpcodeSize(ia); - effects->numoperands++; - } - } - break; - case IAOpnd_Lab: - effects->labels[effects->numlabels] = op->u.lab.label; - effects->numlabels++; - break; - case IAOpnd_LabDiff: - effects->labels[effects->numlabels] = op->u.labdiff.label1; - effects->numlabels++; - effects->labels[effects->numlabels] = op->u.labdiff.label2; - effects->numlabels++; - effects->x3 = 1; - break; - default: - CError_FATAL(4087); - } - - CError_ASSERT(4090, (UInt32) effects->numoperands <= IAMaxOperands); - CError_ASSERT(4093, (UInt32) effects->numlabels <= IAMaxLabels); - } - - for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { - switch (op->type) { - case IAOpnd_Reg: - if (op->u.reg.object) { - if ((vi = Registers_GetVarInfo(op->u.reg.object))) - vi->flags |= VarInfoFlag40; - if (op->u.reg.effect & EffectWrite) { - if ( - TYPE_FITS_IN_REGISTER(op->u.reg.object->type) || - IS_TYPE_FLOAT(op->u.reg.object->type) || - IS_TYPE_VECTOR(op->u.reg.object->type) - ) { - effects->operands[effects->numoperands].type = IAEffect_1; - effects->operands[effects->numoperands].object = op->u.reg.object; - effects->operands[effects->numoperands].offset = 0; - effects->operands[effects->numoperands].size = op->u.reg.object->type->size; - effects->numoperands++; - } else { - CError_FATAL(4132); - } - } - } - break; - case IAOpnd_3: - case IAOpnd_4: - if (op->u.obj.obj) { - if (info->flags & fIsWrite) { - effects->operands[effects->numoperands].type = IAEffect_1; - effects->operands[effects->numoperands].object = op->u.obj.obj; - effects->operands[effects->numoperands].offset = op->u.obj.offset; - effects->operands[effects->numoperands].size = InlineAsm_OpcodeSize(ia); - effects->numoperands++; - } - } - break; - } - - CError_ASSERT(4151, (UInt32) effects->numoperands <= IAMaxOperands); - } - - if ((info->flags & (fIsBranch | fIsCall)) && (SInt32)effects->numlabels == 0) - effects->x3 = 1; -} - -void CodeGen_PropagateIntoAsm(Statement *stmt, Object *obj, ENode *expr) { - InlineAsm *ia; - Object *newobj; - - ia = (InlineAsm *) stmt->expr; - if (ENODE_IS(expr, EOBJREF)) { - newobj = expr->data.objref; - if (obj->otype == newobj->otype && obj->datatype == newobj->datatype) { - int i; - for (i = 0; i < ia->argcount; i++) { - switch (ia->args[i].type) { - case IAOpnd_Reg: - if (ia->args[i].u.reg.object == obj && - (ia->args[i].u.reg.effect & (EffectRead | EffectWrite)) == EffectRead) { - if (TYPE_FITS_IN_REGISTER(newobj->type) && - ia->args[i].u.reg.rclass == RegClass_GPR) { - ia->args[i].u.reg.object = newobj; - } else if (IS_TYPE_FLOAT(newobj->type) && - ia->args[i].u.reg.rclass == RegClass_FPR) { - ia->args[i].u.reg.object = newobj; - } else if (IS_TYPE_VECTOR(newobj->type) && - ia->args[i].u.reg.rclass == RegClass_VR) { - ia->args[i].u.reg.object = newobj; - } - } - break; - case IAOpnd_3: - case IAOpnd_4: - if (!(opcodeinfo[ia->opcode].flags & (fIsWrite | fPCodeFlag40000)) && - ia->args[i].u.obj.obj == obj) - ia->args[i].u.obj.obj = newobj; - break; - } - } - } - } -} - -Statement *CodeGen_CopyAsmStat(Statement *stmt) { - Statement *copy; - SInt32 size; - InlineAsm *ia; - InlineAsm *iacopy; - - copy = galloc(sizeof(Statement)); - *copy = *stmt; - - ia = (InlineAsm *) stmt->expr; - size = sizeof(InlineAsm) + sizeof(IAOperand) * ia->argcount; - iacopy = galloc(size); - memcpy(iacopy, ia, size); - copy->expr = (ENode *) iacopy; - - return copy; -} - diff --git a/compiler_and_linker/unsorted/InstrSelection.c b/compiler_and_linker/unsorted/InstrSelection.c deleted file mode 100644 index 359c980..0000000 --- a/compiler_and_linker/unsorted/InstrSelection.c +++ /dev/null @@ -1,5348 +0,0 @@ -#include "compiler/InstrSelection.h" -#include "compiler/CError.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/CodeGen.h" -#include "compiler/CompilerTools.h" -#include "compiler/FunctionCalls.h" -#include "compiler/Intrinsics.h" -#include "compiler/Operands.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" -#include "compiler/PCodeUtilities.h" -#include "compiler/RegisterInfo.h" -#include "compiler/StructMoves.h" -#include "compiler/TOC.h" -#include "compiler/enode.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -PrecomputedOperand *precomputedoperands; -void (*cgdispatch[MAXEXPR + 1])(ENode *, short, short, Operand *); - -// forward decls -static int ispowerof2(SInt32 val); -static void binary_immediate(Opcode opcode, ENode *left, SInt32 value, short outputReg, Operand *output); -static void shift_left_immediate(ENode *expr, short shift, short negate, short outputReg, Operand *output); -static void shift_right_immediate(ENode *expr, Type *type, short shift, short outputReg, Operand *output); -static void or_xor_immediate(Opcode opcode, ENode *expr, SInt32 value, short outputReg, Operand *output); -static void signed_divide_by_power_of_2(ENode *expr, int shift, int negate, short outputReg, Operand *output); -static void signed_mod_by_power_of_2(ENode *expr, int shift, int negate, short outputReg, Operand *output); -static void fp_binary_operator(Opcode opcode, ENode *left, ENode *right, short outputReg, Operand *output); -static void logical_expression_nobranch(ENode *cond, Boolean invert, Operand *output); -static void shift_and_mask(ENode *expr, short a, short b, short c, short outputReg, Operand *output); -static ENodeType invert_relop(ENodeType nt); - -#define IS_INT_CONST(node) ( ENODE_IS((node), EINTCONST) && IS_TYPE_INT((node)->rtype) && (node)->rtype->size <= 4 ) -#define IS_INT_CONST_ZERO(node) ( IS_INT_CONST(node) && (node)->data.intval.lo == 0 ) - -void init_cgdispatch(void) { - ENodeType t; - - for (t = 0; t <= MAXEXPR; t++) - cgdispatch[t] = gen_UNEXPECTED; - - cgdispatch[EPOSTINC] = gen_POSTINCDEC; - cgdispatch[EPOSTDEC] = gen_POSTINCDEC; - cgdispatch[EINDIRECT] = gen_INDIRECT; - cgdispatch[EMONMIN] = gen_MONMIN; - cgdispatch[EBINNOT] = gen_BINNOT; - cgdispatch[ELOGNOT] = gen_LOGICAL; - cgdispatch[EFORCELOAD] = gen_FORCELOAD; - cgdispatch[EMUL] = gen_MUL; - cgdispatch[EDIV] = gen_DIV; - cgdispatch[EMODULO] = gen_MODULO; - cgdispatch[EADD] = gen_ADD; - cgdispatch[ESUB] = gen_SUB; - cgdispatch[ESHL] = gen_SHL; - cgdispatch[ESHR] = gen_SHR; - cgdispatch[ELESS] = gen_COMPARE; - cgdispatch[EGREATER] = gen_COMPARE; - cgdispatch[ELESSEQU] = gen_COMPARE; - cgdispatch[EGREATEREQU] = gen_COMPARE; - cgdispatch[EEQU] = gen_COMPARE; - cgdispatch[ENOTEQU] = gen_COMPARE; - cgdispatch[EAND] = gen_AND; - cgdispatch[EXOR] = gen_XOR; - cgdispatch[EOR] = gen_OR; - cgdispatch[ELAND] = gen_LOGICAL; - cgdispatch[ELOR] = gen_LOGICAL; - cgdispatch[EASS] = gen_ASS; - cgdispatch[ECOMMA] = gen_COMMA; - cgdispatch[ETYPCON] = gen_TYPCON; - cgdispatch[EBITFIELD] = gen_BITFIELD; - cgdispatch[EINTCONST] = gen_INTCONST; - cgdispatch[EFLOATCONST] = gen_FLOATCONST; - cgdispatch[ESTRINGCONST] = gen_STRINGCONST; - cgdispatch[ECOND] = gen_COND; - cgdispatch[EFUNCCALL] = gen_FUNCCALL; - cgdispatch[EFUNCCALLP] = gen_FUNCCALL; - cgdispatch[EOBJREF] = gen_OBJREF; - cgdispatch[ENULLCHECK] = gen_NULLCHECK; - cgdispatch[EPRECOMP] = gen_PRECOMP; - cgdispatch[EDEFINE] = gen_DEFINE; - cgdispatch[EREUSE] = gen_REUSE; - cgdispatch[EVECTOR128CONST] = gen_VECTOR128CONST; - cgdispatch[ECONDASS] = gen_CONDASS; -} - -void gen_DEFINE(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - Operand *op; - - if (!expr->data.diadic.right) { - op = lalloc(sizeof(Operand)); - memclrw(op, sizeof(Operand)); - expr->data.diadic.right = (ENode *) op; - GEN_NODE(expr->data.diadic.left, op); - } - - op = (Operand *) expr->data.diadic.right; - *output = *op; -} - -void gen_REUSE(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *inner = expr->data.monadic; - CError_ASSERT(250, ENODE_IS(inner, EDEFINE)); - gen_DEFINE(inner, outputReg, outputRegHi, output); -} - -void gen_POSTINCDEC(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - TypeBitfield *tbitfield; - ENode *inner; - Type *type; - Operand a; - Operand b; - Operand c; - Float fval; - int objReg; - int constReg; - int finalReg; - SInt32 incval; - - inner = expr->data.monadic->data.monadic; - type = expr->rtype; - tbitfield = NULL; - - memclrw(&a, sizeof(Operand)); - memclrw(&b, sizeof(Operand)); - memclrw(&c, sizeof(Operand)); - - if (TYPE_IS_8BYTES(type)) { - I8_gen_POSTINCDEC(expr, outputReg, outputRegHi, output); - return; - } - - if (IS_TYPE_FLOAT(type)) { - if (ENODE_IS(inner, EOBJREF) && (objReg = OBJECT_REG(inner->data.objref))) { - output->optype = OpndType_FPR; - output->reg = (outputReg && outputReg != objReg) ? outputReg : ALLOC_FPR(); - emitpcode(PC_FMR, output->reg, objReg); - fval = one_point_zero; - load_floating_constant(constReg = ALLOC_FPR(), type, &fval); - - if (ENODE_IS(expr, EPOSTINC)) { - emitpcode((type->size == 4) ? PC_FADDS : PC_FADD, objReg, objReg, constReg); - } else { - emitpcode((type->size == 4) ? PC_FSUBS : PC_FSUB, objReg, objReg, constReg); - } - } else { - GEN_NODE(inner, &a); - indirect(&a, inner); - b = a; - ENSURE_FPR(&b, type, 0); - - output->optype = OpndType_FPR; - output->reg = ALLOC_FPR(); - emitpcode(PC_FMR, output->reg, b.reg); - - fval = one_point_zero; - load_floating_constant(constReg = ALLOC_FPR(), type, &fval); - - finalReg = ALLOC_FPR(); - if (ENODE_IS(expr, EPOSTINC)) - emitpcode((type->size == 4) ? PC_FADDS : PC_FADD, finalReg, b.reg, constReg); - else - emitpcode((type->size == 4) ? PC_FSUBS : PC_FSUB, finalReg, b.reg, constReg); - - store_fp(finalReg, &a, type); - } - } else { - if (IS_TYPE_POINTER(type)) { - if (ENODE_IS(expr, EPOSTINC)) - incval = TPTR_TARGET(type)->size; - else - incval = -TPTR_TARGET(type)->size; - } else { - if (ENODE_IS(expr, EPOSTINC)) - incval = 1; - else - incval = -1; - } - - if (ENODE_IS(inner, EOBJREF) && (objReg = OBJECT_REG(inner->data.objref))) { - output->optype = OpndType_GPR; - output->reg = (outputReg && outputReg != objReg) ? outputReg : ALLOC_GPR(); - emitpcode(PC_MR, output->reg, objReg); - add_register_immediate(objReg, objReg, incval); - } else { - if (ENODE_IS(inner, EBITFIELD)) { - tbitfield = TYPE_BITFIELD(TPTR_TARGET(inner)); - inner = inner->data.monadic; - } - GEN_NODE(inner, &a); - indirect(&a, inner); - b = a; - ENSURE_GPR(&b, type, 0); - - if (tbitfield) { - c = b; - extract_bitfield(&c, tbitfield, 0, &b); - } - output->optype = OpndType_GPR; - - output->reg = ALLOC_GPR(); - emitpcode(PC_MR, output->reg, b.reg); - - finalReg = ALLOC_GPR(); - add_register_immediate(finalReg, b.reg, incval); - - if (tbitfield) { - insert_bitfield(finalReg, &c, tbitfield); - finalReg = c.reg; - } - - store(finalReg, &a, type); - } - } -} - -void gen_INDIRECT(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - Type *type; - ENode *inner; - VarInfo *vi; - SInt32 postincvalue; - Operand op; - - type = expr->rtype; - inner = expr->data.monadic; - - if (TYPE_IS_8BYTES(type)) { - I8_gen_INDIRECT(expr, outputReg, outputRegHi, output); - return; - } - - memclrw(&op, sizeof(Operand)); - if (ENODE_IS(inner, EOBJREF) && OBJECT_REG(inner->data.objref)) { - vi = Registers_GetVarInfo(inner->data.objref); - switch (vi->rclass) { - case RegClass_GPR: - output->optype = OpndType_GPR; - break; - case RegClass_FPR: - output->optype = OpndType_FPR; - break; - case RegClass_VR: - output->optype = OpndType_VR; - break; - case RegClass_CRFIELD: - output->optype = OpndType_CRField; - break; - default: - CError_FATAL(456); - } - output->reg = vi->reg; - output->object = NULL; - return; - } - - if (ENODE_IS(inner, EBITFIELD)) { - GEN_NODE(inner->data.monadic, &op); - indirect(&op, expr); - ENSURE_GPR(&op, type, 0); - extract_bitfield(&op, TYPE_BITFIELD(inner->rtype), outputReg, output); - return; - } - - if (ispostincrementopportunity(inner, &op, &postincvalue) && (TYPE_FITS_IN_REGISTER(type) || IS_TYPE_FLOAT(type) || IS_TYPE_VECTOR(type))) { - indirect(&op, expr); - *output = op; - if (TYPE_FITS_IN_REGISTER(type)) { - ENSURE_GPR(output, type, outputReg); - } else if (IS_TYPE_FLOAT(type)) { - ENSURE_FPR(output, type, outputReg); - } else { - ENSURE_VR(output, type, outputReg); - } - - add_register_immediate(op.reg, op.reg, postincvalue); - return; - } - - GEN_NODE(inner, output); - indirect(output, expr); -} - -void gen_MONMIN(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *inner; - Type *type; - ENode *scan; - - inner = expr->data.monadic; - type = expr->rtype; - - if (TYPE_IS_8BYTES(type)) { - I8_gen_MONMIN(expr, outputReg, outputRegHi, output); - return; - } - - if (IS_TYPE_FLOAT(type)) { - if (ENODE_IS(inner, EADD) && ENODE_IS(inner->data.diadic.left, EMUL) && copts.fp_contract) { - fp_multiply_add( - (type->size == 4) ? PC_FNMADDS : PC_FNMADD, - inner->data.diadic.left->data.diadic.left, - inner->data.diadic.left->data.diadic.right, - inner->data.diadic.right, - outputReg, - output); - } else if (ENODE_IS(inner, EADD) && ENODE_IS(inner->data.diadic.right, EMUL) && copts.fp_contract) { - fp_multiply_add( - (type->size == 4) ? PC_FNMADDS : PC_FNMADD, - inner->data.diadic.right->data.diadic.left, - inner->data.diadic.right->data.diadic.right, - inner->data.diadic.left, - outputReg, - output); - } else if (ENODE_IS(inner, ESUB) && ENODE_IS(inner->data.diadic.left, EMUL) && copts.fp_contract) { - fp_multiply_add( - (type->size == 4) ? PC_FNMSUBS : PC_FNMSUB, - inner->data.diadic.left->data.diadic.left, - inner->data.diadic.left->data.diadic.right, - inner->data.diadic.right, - outputReg, - output); - } else { - fp_unary_operator(PC_FNEG, inner, outputReg, output); - } - return; - } - - scan = inner; - while (ENODE_IS(scan, ETYPCON) && IS_TYPE_INT_OR_ENUM(type) && !is_unsigned(type)) - scan = scan->data.monadic; - - switch (scan->type) { - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - if (TYPE_FITS_IN_REGISTER(scan->data.diadic.left->rtype) && TYPE_FITS_IN_REGISTER(scan->data.diadic.right->rtype)) { - gen_negated_condition_gpr(scan, output, outputReg); - return; - } - } - unary_operator(PC_NEG, inner, outputReg, output); -} - -void gen_BINNOT(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *inner; - Type *type; - - inner = expr->data.monadic; - type = expr->rtype; - - if (TYPE_IS_8BYTES(type)) { - I8_gen_BINNOT(expr, outputReg, outputRegHi, output); - return; - } - - if (ENODE_IS(inner, EAND)) - binary_operator(PC_NAND, inner->data.diadic.left, inner->data.diadic.right, outputReg, output); - else if (ENODE_IS(inner, EOR)) - binary_operator(PC_NOR, inner->data.diadic.left, inner->data.diadic.right, outputReg, output); - else if (ENODE_IS(inner, EXOR)) - binary_operator(PC_EQV, inner->data.diadic.left, inner->data.diadic.right, outputReg, output); - else - unary_operator(PC_NOT, inner, outputReg, output); -} - -void gen_FORCELOAD(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *inner; - - inner = expr->data.monadic; - GEN_NODE(inner, output); - - if (IS_TYPE_FLOAT(inner->rtype)) { - ENSURE_FPR(output, inner->rtype, outputReg); - } else if (IS_TYPE_VECTOR(inner->rtype)) { - ENSURE_VR(output, inner->rtype, outputReg); - } else if (TYPE_FITS_IN_REGISTER(inner->rtype)) { - if (TYPE_IS_8BYTES(inner->rtype)) - coerce_to_register_pair(output, inner->rtype, outputReg, outputRegHi); - else - ENSURE_GPR(output, inner->rtype, outputReg); - } else if (!IS_TYPE_VOID(inner->rtype)) { - CError_FATAL(681); - } -} - -void gen_MUL(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *left; - ENode *right; - Type *type; - int tmp; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - type = expr->rtype; - - if (TYPE_IS_8BYTES(type)) { - I8_gen_MUL(expr, outputReg, outputRegHi, output); - return; - } - - if (IS_TYPE_FLOAT(type)) { - fp_binary_operator((type->size == 4) ? PC_FMULS : PC_FMUL, left, right, outputReg, output); - return; - } - - if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(right->data.intval.lo))) { - shift_left_immediate(left, tmp, 0, outputReg, output); - } else if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(-right->data.intval.lo))) { - shift_left_immediate(left, tmp, 1, outputReg, output); - } else if (ENODE_IS(left, EINTCONST) && (tmp = ispowerof2(left->data.intval.lo))) { - shift_left_immediate(right, tmp, 0, outputReg, output); - } else if (ENODE_IS(left, EINTCONST) && (tmp = ispowerof2(-left->data.intval.lo))) { - shift_left_immediate(right, tmp, 1, outputReg, output); - } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT(right->data.intval.lo)) { - binary_immediate(PC_MULLI, left, right->data.intval.lo, outputReg, output); - } else if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT(left->data.intval.lo)) { - binary_immediate(PC_MULLI, right, left->data.intval.lo, outputReg, output); - } else { - binary_operator(PC_MULLW, left, right, outputReg, output); - } -} - -struct ms { - SInt32 m; - int s; -}; -static void create_signed_magic(SInt32 val, struct ms *output) { - // PowerPC CWG page 57-58 - int p; - UInt32 ad, anc, delta, q1, r1, q2, r2, t; - - ad = abs(val); - t = 0x80000000U + ((UInt32) val >> 31); - anc = t - 1 - t % ad; - p = 31; - q1 = 0x80000000U / anc; - r1 = 0x80000000U - q1 * anc; - q2 = 0x80000000U / ad; - r2 = 0x80000000U - q2 * ad; - - do { - p = p + 1; - q1 = 2 * q1; - r1 = 2 * r1; - if (r1 >= anc) { - q1 = q1 + 1; - r1 = r1 - anc; - } - q2 = 2 * q2; - r2 = 2 * r2; - if (r2 >= ad) { - q2 = q2 + 1; - r2 = r2 - ad; - } - delta = ad - r2; - } while (q1 < delta || (q1 == delta && r1 == 0)); - - // after loop - output->m = q2 + 1; - if (val < 0) - output->m = -output->m; - output->s = p - 32; -} - -struct mu { - UInt32 m; - int a; - int s; -}; -static void create_unsigned_magic(UInt32 val, struct mu *output) { - // PowerPC CWG page 58-59 - int p; - UInt32 nc, delta, q1, r1, q2, r2; - - output->a = 0; - nc = - 1 - (-val) % val; - p = 31; - q1 = 0x80000000U / nc; - r1 = 0x80000000U - q1 * nc; - q2 = 0x7FFFFFFFU / val; - r2 = 0x7FFFFFFFU - q2 * val; - do { - p = p + 1; - if (r1 >= nc - r1) { - q1 = 2 * q1 + 1; - r1 = 2 * r1 - nc; - } else { - q1 = 2 * q1; - r1 = 2 * r1; - } - if (r2 + 1 >= val - r2) { - if (q2 >= 0x7FFFFFFFU) - output->a = 1; - q2 = 2 * q2 + 1; - r2 = 2 * r2 + 1 - val; - } else { - if (q2 >= 0x80000000U) - output->a = 1; - q2 = 2 * q2; - r2 = 2 * r2 + 1; - } - delta = val - 1 - r2; - } while (p < 64 && (q1 < delta || (q1 == delta && r1 == 0))); - - output->m = q2 + 1; - output->s = p - 32; -} - -void gen_DIV(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *left; - ENode *right; - Type *type; - int tmp; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - type = expr->rtype; - - if (TYPE_IS_8BYTES(type)) { - I8_gen_DIV_MOD(expr, outputReg, outputRegHi, output); - return; - } - - if (IS_TYPE_FLOAT(type)) { - fp_binary_operator((type->size == 4) ? PC_FDIVS : PC_FDIV, left, right, outputReg, output); - return; - } - - if (is_unsigned(type)) { - if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(right->data.intval.lo))) { - shift_right_immediate(left, type, tmp, outputReg, output); - } else if (!copts.optimizesize && ENODE_IS(right, EINTCONST) && right->data.intval.lo != 1) { - SInt32 value; - int tmpreg1; - int tmpreg2; - int tmpreg3; - int tmpreg4; - int tmpreg5; - int tmpreg6; - int finalReg; - struct mu u_magicoutput; - Operand op1; - value = right->data.intval.lo; - tmpreg1 = ALLOC_GPR(); - tmpreg2 = ALLOC_GPR(); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - - memclrw(&op1, sizeof(Operand)); - GEN_NODE(left, &op1); - ENSURE_GPR(&op1, left->rtype, 0); - - tmpreg3 = op1.reg; - create_unsigned_magic(value, &u_magicoutput); - load_immediate(tmpreg2, u_magicoutput.m); - emitpcode(PC_MULHWU, tmpreg1, tmpreg2, tmpreg3); - if (u_magicoutput.a == 0) { - if (u_magicoutput.s) - emitpcode(PC_RLWINM, finalReg, tmpreg1, (32 - u_magicoutput.s) & 31, u_magicoutput.s, 31); - else - emitpcode(PC_MR, finalReg, tmpreg1); - } else if (u_magicoutput.a == 1) { - tmpreg4 = ALLOC_GPR(); - if (copts.optimizationlevel > 1) { - tmpreg5 = ALLOC_GPR(); - tmpreg6 = ALLOC_GPR(); - } else { - tmpreg5 = tmpreg4; - tmpreg6 = tmpreg4; - } - - emitpcode(PC_SUBF, tmpreg4, tmpreg1, tmpreg3); - emitpcode(PC_RLWINM, tmpreg5, tmpreg4, 31, 1, 31); - emitpcode(PC_ADD, tmpreg6, tmpreg5, tmpreg1); - emitpcode(PC_RLWINM, finalReg, tmpreg6, (32 - (u_magicoutput.s - 1)) & 31, u_magicoutput.s - 1, 31); - } - - output->optype = OpndType_GPR; - output->reg = finalReg; - } else { - binary_operator(PC_DIVWU, left, right, outputReg, output); - } - } else { - SInt32 value; - if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(right->data.intval.lo))) { - signed_divide_by_power_of_2(left, tmp, 0, outputReg, output); - } else if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(-right->data.intval.lo))) { - signed_divide_by_power_of_2(left, tmp, 1, outputReg, output); - } else if (!copts.optimizesize && ENODE_IS(right, EINTCONST) && (value = right->data.intval.lo) != 1u && value != -1) { - int tmpreg2; - int tmpreg3; - int tmpreg1; - int tmpreg4; - int finalReg; - struct ms s_magicoutput; - Operand op2; - value = right->data.intval.lo; - tmpreg1 = ALLOC_GPR(); - tmpreg2 = ALLOC_GPR(); - tmpreg3 = ALLOC_GPR(); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - - memclrw(&op2, sizeof(Operand)); - GEN_NODE(left, &op2); - ENSURE_GPR(&op2, left->rtype, 0); - - tmpreg4 = op2.reg; - create_signed_magic(value, &s_magicoutput); - load_immediate(tmpreg2, s_magicoutput.m); - emitpcode(PC_MULHW, tmpreg1, tmpreg2, tmpreg4); - if (value > 0 && s_magicoutput.m < 0) { - int t = ALLOC_GPR(); - emitpcode(PC_ADD, t, tmpreg1, tmpreg4); - tmpreg1 = t; - } else if (value < 0 && s_magicoutput.m > 0) { - int t = ALLOC_GPR(); - emitpcode(PC_SUBF, t, tmpreg4, tmpreg1); - tmpreg1 = t; - } - - if (s_magicoutput.s) { - int t = ALLOC_GPR(); - emitpcode(PC_SRAWI, t, tmpreg1, s_magicoutput.s); - tmpreg1 = t; - } - - emitpcode(PC_RLWINM, tmpreg3, tmpreg1, 1, 31, 31); - emitpcode(PC_ADD, finalReg, tmpreg1, tmpreg3); - - output->optype = OpndType_GPR; - output->reg = finalReg; - } else { - binary_operator(PC_DIVW, left, right, outputReg, output); - } - } -} - -void gen_MODULO(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *left; - ENode *right; - int tmp; - struct mu u_magicoutput; - struct ms s_magicoutput; - Operand op1; - Operand op2; - SInt32 value; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - memclrw(&op1, sizeof(Operand)); - memclrw(&op2, sizeof(Operand)); - - if (TYPE_IS_8BYTES(expr->rtype)) { - I8_gen_DIV_MOD(expr, outputReg, outputRegHi, output); - return; - } - - if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(right->data.intval.lo))) { - if (is_unsigned(expr->rtype)) - shift_and_mask(left, 0, 32 - tmp, 31, outputReg, output); - else - signed_mod_by_power_of_2(left, tmp, 0, outputReg, output); - } else if (!copts.optimizesize && ENODE_IS(right, EINTCONST) && (value = right->data.intval.lo) != 1u && value != -1) { - GEN_NODE(left, &op1); - ENSURE_GPR(&op1, left->rtype, 0); - - if (is_unsigned(expr->rtype)) { - int tmpreg1; - int tmpreg2; - int tmpreg3; - int tmpreg4; - int tmpreg5; - int tmpreg6; - int tmpreg7; - int tmpreg8; - int finalReg; - - tmpreg1 = op1.reg; - tmpreg2 = ALLOC_GPR(); - tmpreg3 = ALLOC_GPR(); - tmpreg4 = ALLOC_GPR(); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - - create_unsigned_magic(right->data.intval.lo, &u_magicoutput); - load_immediate(tmpreg3, u_magicoutput.m); - emitpcode(PC_MULHWU, tmpreg2, tmpreg3, tmpreg1); - - if (u_magicoutput.a == 0 && u_magicoutput.s != 0) - emitpcode(PC_RLWINM, tmpreg2, tmpreg2, (32 - u_magicoutput.s) & 31, u_magicoutput.s, 31); - - if (u_magicoutput.a == 1) { - tmpreg5 = ALLOC_GPR(); - if (copts.optimizationlevel > 1) { - tmpreg6 = ALLOC_GPR(); - tmpreg7 = ALLOC_GPR(); - tmpreg8 = ALLOC_GPR(); - } else { - tmpreg6 = tmpreg5; - tmpreg7 = tmpreg5; - tmpreg8 = tmpreg5; - } - emitpcode(PC_SUBF, tmpreg5, tmpreg2, tmpreg1); - emitpcode(PC_RLWINM, tmpreg6, tmpreg5, 31, 1, 31); - emitpcode(PC_ADD, tmpreg7, tmpreg6, tmpreg2); - emitpcode(PC_RLWINM, tmpreg8, tmpreg7, (32 - (u_magicoutput.s - 1)) & 31, u_magicoutput.s - 1, 31); - tmpreg2 = tmpreg8; - } - - if (value > 0 && value < 0x7FFF) { - emitpcode(PC_MULLI, tmpreg4, tmpreg2, value); - } else { - GEN_NODE(right, &op2); - ENSURE_GPR(&op2, right->rtype, 0); - emitpcode(PC_MULLW, tmpreg4, tmpreg2, op2.reg); - } - - emitpcode(PC_SUBF, finalReg, tmpreg4, tmpreg1); - output->optype = OpndType_GPR; - output->reg = finalReg; - } else { - int tmpreg1; - int tmpreg2; - int tmpreg3; - int tmpreg4; - int tmpreg5; - int tmpreg6; - int finalReg; - - tmpreg1 = op1.reg; - tmpreg2 = ALLOC_GPR(); - tmpreg3 = ALLOC_GPR(); - tmpreg4 = ALLOC_GPR(); - tmpreg5 = ALLOC_GPR(); - tmpreg6 = ALLOC_GPR(); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - - create_signed_magic(right->data.intval.lo, &s_magicoutput); - load_immediate(tmpreg3, s_magicoutput.m); - emitpcode(PC_MULHW, tmpreg2, tmpreg3, tmpreg1); - - if (value > 0 && s_magicoutput.m < 0) { - int tmp = ALLOC_GPR(); - emitpcode(PC_ADD, tmp, tmpreg2, tmpreg1); - tmpreg2 = tmp; - } else if (value < 0 && s_magicoutput.m > 0) { - int tmp = ALLOC_GPR(); - emitpcode(PC_SUBF, tmp, tmpreg1, tmpreg2); - tmpreg2 = tmp; - } - - if (s_magicoutput.s != 0) { - int tmp = ALLOC_GPR(); - emitpcode(PC_SRAWI, tmp, tmpreg2, s_magicoutput.s); - tmpreg2 = tmp; - } - - emitpcode(PC_RLWINM, tmpreg4, tmpreg2, 1, 31, 31); - emitpcode(PC_ADD, tmpreg5, tmpreg2, tmpreg4); - - if (value < 0x7FFF && value > -0x4000) { - emitpcode(PC_MULLI, tmpreg6, tmpreg5, value); - } else { - GEN_NODE(right, &op2); - ENSURE_GPR(&op2, right->rtype, 0); - - emitpcode(PC_MULLW, tmpreg6, tmpreg5, op2.reg); - } - - emitpcode(PC_SUBF, finalReg, tmpreg6, tmpreg1); - output->optype = OpndType_GPR; - output->reg = finalReg; - } - } else { - int tmpreg1; - int tmpreg2; - int finalReg; - - if (right->hascall) { - GEN_NODE(right, &op2); - ENSURE_GPR(&op2, right->rtype, 0); - GEN_NODE(left, &op1); - ENSURE_GPR(&op1, left->rtype, 0); - } else { - GEN_NODE(left, &op1); - ENSURE_GPR(&op1, left->rtype, 0); - GEN_NODE(right, &op2); - ENSURE_GPR(&op2, right->rtype, 0); - } - - tmpreg1 = ALLOC_GPR(); - tmpreg2 = ALLOC_GPR(); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - - emitpcode(is_unsigned(expr->rtype) ? PC_DIVWU : PC_DIVW, tmpreg1, op1.reg, op2.reg); - emitpcode(PC_MULLW, tmpreg2, tmpreg1, op2.reg); - emitpcode(PC_SUBF, finalReg, tmpreg2, op1.reg); - - output->optype = OpndType_GPR; - output->reg = finalReg; - } -} - -void gen_ADD(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *left; - ENode *right; - Type *type; - Operand opleft; - Operand opright; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - type = expr->rtype; - - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - - if (TYPE_IS_8BYTES(type)) { - I8_gen_ADD(expr, outputReg, outputRegHi, output); - return; - } - - if (IS_TYPE_FLOAT(type)) { - if (ENODE_IS(left, EMUL) && copts.fp_contract) { - fp_multiply_add( - (type->size == 4) ? PC_FMADDS : PC_FMADD, - left->data.diadic.left, - left->data.diadic.right, - right, - outputReg, output); - } else if (ENODE_IS(right, EMUL) && copts.fp_contract) { - fp_multiply_add( - (type->size == 4) ? PC_FMADDS : PC_FMADD, - right->data.diadic.left, - right->data.diadic.right, - left, - outputReg, output); - } else { - fp_binary_operator( - (type->size == 4) ? PC_FADDS : PC_FADD, - left, right, - outputReg, output); - } - return; - } - - if (right->hascall) { - GEN_NODE(right, &opright); - if (opright.optype >= OpndType_IndirectGPR_ImmOffset) - ENSURE_GPR(&opright, right->rtype, 0); - - GEN_NODE(left, &opleft); - if (opleft.optype >= OpndType_IndirectGPR_ImmOffset) - ENSURE_GPR(&opleft, left->rtype, 0); - } else { - GEN_NODE(left, &opleft); - if (opleft.optype >= OpndType_IndirectGPR_ImmOffset) - ENSURE_GPR(&opleft, left->rtype, 0); - - GEN_NODE(right, &opright); - if (opright.optype >= OpndType_IndirectGPR_ImmOffset) - ENSURE_GPR(&opright, right->rtype, 0); - } - - if (IS_TYPE_POINTER(expr->rtype)) { - if (TYPE_IS_8BYTES(expr->data.diadic.left->rtype)) { - opleft.optype = OpndType_GPR; - opleft.regHi = 0; - } - if (TYPE_IS_8BYTES(expr->data.diadic.right->rtype)) { - opright.optype = OpndType_GPR; - opright.regHi = 0; - } - } - - combine(&opleft, &opright, outputReg, output); -} - -void gen_SUB(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *left; - ENode *right; - Type *type; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - type = expr->rtype; - - if (TYPE_IS_8BYTES(type)) { - I8_gen_SUB(expr, outputReg, outputRegHi, output); - return; - } - - if (IS_TYPE_FLOAT(type)) { - if (ENODE_IS(left, EMUL) && copts.fp_contract) { - fp_multiply_add( - (type->size == 4) ? PC_FMSUBS : PC_FMSUB, - left->data.diadic.left, - left->data.diadic.right, - right, - outputReg, output); - } else if (ENODE_IS(right, EMUL) && copts.fp_contract) { - fp_multiply_add( - (type->size == 4) ? PC_FNMSUBS : PC_FNMSUB, - right->data.diadic.left, - right->data.diadic.right, - left, - outputReg, output); - } else { - fp_binary_operator( - (type->size == 4) ? PC_FSUBS : PC_FSUB, - left, right, - outputReg, output); - } - return; - } - - if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT(left->data.intval.lo)) - binary_immediate(PC_SUBFIC, right, left->data.intval.lo, outputReg, output); - else - binary_operator(PC_SUBF, right, left, outputReg, output); -} - -void gen_SHL(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - Type *type; - ENode *left; - ENode *right; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - type = expr->rtype; - - if (TYPE_IS_8BYTES(type)) { - I8_gen_SHL_SHR(expr, outputReg, outputRegHi, output); - return; - } - - if (ENODE_IS(right, EINTCONST)) - shift_left_immediate(left, right->data.intval.lo, 0, outputReg, output); - else - binary_operator(PC_SLW, left, right, outputReg, output); -} - -void gen_SHR(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - Type *type; - ENode *left; - ENode *right; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - type = expr->rtype; - - if (TYPE_IS_8BYTES(type)) { - I8_gen_SHL_SHR(expr, outputReg, outputRegHi, output); - return; - } - - if (ENODE_IS(right, EINTCONST)) - shift_right_immediate(left, type, right->data.intval.lo, outputReg, output); - else - binary_operator(is_unsigned(type) ? PC_SRW : PC_SRAW, left, right, outputReg, output); -} - -void gen_AND(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - Type *type; - ENode *left; - ENode *right; - short first; - short last; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - type = expr->rtype; - - if (TYPE_IS_8BYTES(type)) { - I8_gen_AND(expr, outputReg, outputRegHi, output); - return; - } - - if (ENODE_IS(right, EINTCONST) && ismaskconstant(right->data.intval.lo, &first, &last)) { - if (ENODE_IS(left, ESHL) && ENODE_IS(left->data.diadic.right, EINTCONST) && (int)(left->data.diadic.right->data.intval.lo + last) < 32) { - shift_and_mask( - left->data.diadic.left, - left->data.diadic.right->data.intval.lo, - first, last, - outputReg, output); - } else if (ENODE_IS(left, ESHR) && ENODE_IS(left->data.diadic.right, EINTCONST) && (int)left->data.diadic.right->data.intval.lo <= first && last >= first) { - if (left->data.diadic.right->data.intval.lo == 0) - shift_and_mask(left->data.diadic.left, 0, first, last, outputReg, output); - else - shift_and_mask(left->data.diadic.left, 32 - left->data.diadic.right->data.intval.lo, first, last, outputReg, output); - } else { - shift_and_mask(left, 0, first, last, outputReg, output); - } - return; - } - - if (ENODE_IS(right, EINTCONST) && FITS_IN_USHORT(right->data.intval.lo)) { - binary_immediate(PC_ANDI, left, right->data.intval.lo, outputReg, output); - return; - } - if (ENODE_IS(right, EINTCONST) && FITS_IN_HI_SHORT(right->data.intval.lo)) { - binary_immediate(PC_ANDIS, left, right->data.intval.lo >> 16, outputReg, output); - return; - } - - if (ENODE_IS(left, EINTCONST) && ismaskconstant(left->data.intval.lo, &first, &last)) { - if (ENODE_IS(right, ESHL) && ENODE_IS(right->data.diadic.right, EINTCONST) && (int)(right->data.diadic.right->data.intval.lo + last) < 32) { - shift_and_mask( - right->data.diadic.left, - right->data.diadic.right->data.intval.lo, - first, last, - outputReg, output); - } else if (ENODE_IS(right, ESHR) && ENODE_IS(right->data.diadic.right, EINTCONST) && (int)right->data.diadic.right->data.intval.lo <= first) { - if (right->data.diadic.right->data.intval.lo == 0) - shift_and_mask(right->data.diadic.left, 0, first, last, outputReg, output); - else - shift_and_mask(right->data.diadic.left, 32 - right->data.diadic.right->data.intval.lo, first, last, outputReg, output); - } else { - shift_and_mask(right, 0, first, last, outputReg, output); - } - return; - } - - if (ENODE_IS(left, EINTCONST) && FITS_IN_USHORT(left->data.intval.lo)) { - binary_immediate(PC_ANDI, right, left->data.intval.lo, outputReg, output); - return; - } - if (ENODE_IS(left, EINTCONST) && FITS_IN_HI_SHORT(left->data.intval.lo)) { - binary_immediate(PC_ANDIS, right, left->data.intval.lo >> 16, outputReg, output); - return; - } - - if (ENODE_IS(right, EBINNOT)) - binary_operator(PC_ANDC, left, right->data.monadic, outputReg, output); - else if (ENODE_IS(left, EBINNOT)) - binary_operator(PC_ANDC, right, left->data.monadic, outputReg, output); - else - binary_operator(PC_AND, left, right, outputReg, output); -} - -void gen_XOR(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - Type *type; - ENode *left; - ENode *right; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - type = expr->rtype; - - if (TYPE_IS_8BYTES(type)) { - I8_gen_XOR(expr, outputReg, outputRegHi, output); - return; - } - - if (ENODE_IS(left, EINTCONST)) - or_xor_immediate(PC_XORI, right, left->data.intval.lo, outputReg, output); - else if (ENODE_IS(right, EINTCONST)) - or_xor_immediate(PC_XORI, left, right->data.intval.lo, outputReg, output); - else if (ENODE_IS(right, EBINNOT)) - binary_operator(PC_EQV, left, right->data.monadic, outputReg, output); - else if (ENODE_IS(left, EBINNOT)) - binary_operator(PC_EQV, left->data.monadic, right, outputReg, output); - else - binary_operator(PC_XOR, left, right, outputReg, output); -} - -void gen_OR(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - Type *type; - ENode *left; - ENode *right; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - type = expr->rtype; - - if (TYPE_IS_8BYTES(type)) { - I8_gen_OR(expr, outputReg, outputRegHi, output); - return; - } - - if (ENODE_IS(left, EINTCONST)) - or_xor_immediate(PC_ORI, right, left->data.intval.lo, outputReg, output); - else if (ENODE_IS(right, EINTCONST)) - or_xor_immediate(PC_ORI, left, right->data.intval.lo, outputReg, output); - else if (ENODE_IS(right, EBINNOT)) - binary_operator(PC_ORC, left, right->data.monadic, outputReg, output); - else if (ENODE_IS(left, EBINNOT)) - binary_operator(PC_ORC, right, left->data.monadic, outputReg, output); - else - binary_operator(PC_OR, left, right, outputReg, output); -} - -void gen_ASS(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - Type *type; - ENode *left; - ENode *right; - Operand opleft; - Operand opright; - Operand op2; - VarInfo *vi; - SInt32 incval; - short align; - short align2; - - type = expr->rtype; - if (ENODE_IS(expr, ECONDASS)) { - left = expr->data.cond.expr1; - if (ENODE_IS(left, EINDIRECT)) { - left = left->data.monadic; - } else { - CError_FATAL(1759); - } - right = expr->data.cond.expr2; - } else { - left = expr->data.diadic.left; - right = expr->data.diadic.right; - } - - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - memclrw(&op2, sizeof(Operand)); - - if (TYPE_IS_8BYTES(type)) { - I8_gen_ASS(expr, outputReg, outputRegHi, output); - return; - } - - if (ENODE_IS(left, EOBJREF) && OBJECT_REG(left->data.objref)) { - vi = Registers_GetVarInfo(left->data.objref); - GEN_NODE_TO_REG(right, vi->reg, 0, &opright); - switch (vi->rclass) { - case RegClass_GPR: - ENSURE_GPR(&opright, type, vi->reg); - output->optype = OpndType_GPR; - break; - case RegClass_FPR: - ENSURE_FPR(&opright, type, vi->reg); - output->optype = OpndType_FPR; - break; - case RegClass_VR: - ENSURE_VR(&opright, type, vi->reg); - output->optype = OpndType_VR; - break; - default: - CError_FATAL(1810); - } - if (opright.reg != vi->reg) { - PCodeArg a, b; - a.kind = PCOp_REGISTER; - a.arg = vi->rclass; - a.data.reg.reg = vi->reg; - a.data.reg.effect = EffectWrite; - b.kind = PCOp_REGISTER; - b.arg = vi->rclass; - b.data.reg.reg = opright.reg; - b.data.reg.effect = EffectRead; - appendpcode(pclastblock, makecopyinstruction(&b, &a)); - } - output->reg = vi->reg; - return; - } - - if (IS_TYPE_FLOAT(type)) { - GEN_NODE_TO_FPR(right, &opright, right->rtype, 0); - if (ispostincrementopportunity(left, &opleft, &incval)) { - indirect(&opleft, expr); - store_fp(opright.reg, &opleft, type); - add_register_immediate(opleft.reg, opleft.reg, incval); - } else { - GEN_NODE(left, &opleft); - indirect(&opleft, expr); - store_fp(opright.reg, &opleft, type); - } - output->optype = OpndType_FPR; - output->reg = opright.reg; - return; - } - - if (IS_TYPE_VECTOR(type)) { - GEN_NODE(right, &opright); - if (opright.optype == OpndType_Absolute) - ENSURE_VR(&opright, type, 0); - else - ENSURE_VR(&opright, right->rtype, 0); - - if (ispostincrementopportunity(left, &opleft, &incval)) { - indirect(&opleft, expr); - store_v(opright.reg, &opleft, type); - add_register_immediate(opleft.reg, opleft.reg, incval); - } else { - GEN_NODE(left, &opleft); - indirect(&opleft, expr); - store_v(opright.reg, &opleft, type); - } - output->optype = OpndType_VR; - output->reg = opright.reg; - return; - } - - if (TYPE_FITS_IN_REGISTER(type)) { - GEN_NODE_TO_GPR(right, &opright, right->rtype, 0); - - if (ENODE_IS(left, EBITFIELD)) { - GEN_NODE(left->data.monadic, &opleft); - indirect(&opleft, expr); - - op2 = opleft; - ENSURE_GPR(&op2, type, 0); - insert_bitfield(opright.reg, &op2, TYPE_BITFIELD(left->rtype)); - store(op2.reg, &opleft, type); - - if (!expr->ignored) - extract_bitfield(&op2, TYPE_BITFIELD(left->rtype), opright.reg, &opleft); - } else if (ispostincrementopportunity(left, &opleft, &incval)) { - indirect(&opleft, expr); - store(opright.reg, &opleft, type); - add_register_immediate(opleft.reg, opleft.reg, incval); - } else { - GEN_NODE(left, &opleft); - indirect(&opleft, expr); - store(opright.reg, &opleft, type); - } - - output->optype = OpndType_GPR; - output->reg = opright.reg; - return; - } - - GEN_NODE(right, &opright); - GEN_NODE(left, output); - - indirect(output, expr); - if (output->object) { - if (output->object->datatype == DLOCAL && (output->object->u.var.info->flags & VarInfoFlag1)) - align = CMach_ArgumentAlignment(type); - else - align = CMach_AllocationAlignment(type, output->object->qual); - } else { - align = CMach_AllocationAlignment(type, 0); - } - if (opright.object) { - if (opright.object->datatype == DLOCAL && (opright.object->u.var.info->flags & VarInfoFlag1)) - align2 = CMach_ArgumentAlignment(type); - else - align2 = CMach_AllocationAlignment(type, opright.object->qual); - } else { - align2 = CMach_AllocationAlignment(type, 0); - } - - if (align2 < align) - align = align2; - - move_block(output, &opright, type->size, align); -} - -ENode *evaluate_and_skip_comma(ENode *expr) { - Operand op; - ENode *inner; - - memclrw(&op, sizeof(Operand)); - while (ENODE_IS(expr, ECOMMA)) { - inner = expr->data.diadic.left; - GEN_NODE(inner, &op); - if (ENODE_IS(inner, EINDIRECT) && (op.flags & OpndFlags_Volatile)) { - if (TYPE_FITS_IN_REGISTER_2(inner->rtype)) { - ENSURE_GPR(&op, inner->rtype, 0); - } else if (IS_TYPE_FLOAT(inner->rtype)) { - ENSURE_FPR(&op, inner->rtype, 0); - } - } - expr = expr->data.diadic.right; - } - return expr; -} - -void gen_COMMA(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *left; - ENode *right; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - GEN_NODE(left, output); - - if (ENODE_IS(left, EINDIRECT) && (output->flags & OpndFlags_Volatile)) { - if (TYPE_FITS_IN_REGISTER_2(left->rtype)) { - ENSURE_GPR(output, left->rtype, 0); - } else if (IS_TYPE_FLOAT(left->rtype)) { - ENSURE_FPR(output, left->rtype, 0); - } - } - - GEN_NODE_TO_REG(right, outputReg, 0, output); -} - -void gen_TYPCON(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *inner; - Type *srctype; - Type *dsttype; - - inner = expr->data.monadic; - srctype = inner->rtype; - dsttype = expr->rtype; - - if (TYPE_IS_8BYTES(srctype) || TYPE_IS_8BYTES(dsttype)) { - I8_gen_TYPCON(expr, outputReg, outputRegHi, output); - return; - } - - if (IS_TYPE_VOID(dsttype)) { - GEN_NODE(inner, output); - if (ENODE_IS(inner, EINDIRECT) && (output->flags & OpndFlags_Volatile)) { - if (TYPE_FITS_IN_REGISTER_2(srctype)) { - ENSURE_GPR(output, srctype, 0); - } else if (IS_TYPE_FLOAT(srctype)) { - ENSURE_FPR(output, srctype, 0); - } - } - } else if (IS_TYPE_INT_OR_ENUM(srctype)) { - if (IS_TYPE_FLOAT(dsttype)) { - GEN_NODE(inner, output); - if (srctype->size < 4) - extend32(output, srctype, 0); - ENSURE_GPR(output, srctype, 0); - - if (is_unsigned(srctype)) - convert_unsigned_to_floating(output, dsttype->size == 4, outputReg); - else - convert_integer_to_floating(output, dsttype->size == 4, outputReg); - } else if (IS_TYPE_VECTOR(dsttype)) { - GEN_NODE_TO_REG(inner, outputReg, 0, output); - ENSURE_VR(output, dsttype, outputReg); - } else if ( - srctype->size < dsttype->size && - !ENODE_IS_INDIRECT_TO(inner, EBITFIELD) && - !ENODE_IS_ASSIGN_TO(inner, EBITFIELD) && - !(ENODE_IS_RANGE(inner, EPOSTINC, EPREDEC) && ENODE_IS(inner->data.monadic->data.monadic, EBITFIELD)) - ) { - GEN_NODE(inner, output); - extend32(output, srctype, outputReg); - } else if (dsttype->size < srctype->size || dsttype->size < 4) { - GEN_NODE(inner, output); - ENSURE_GPR(output, srctype, 0); - extend32(output, dsttype, outputReg); - } else { - GEN_NODE_TO_REG(inner, outputReg, 0, output); - } - } else if (IS_TYPE_POINTER(srctype)) { - GEN_NODE_TO_REG(inner, outputReg, 0, output); - if (dsttype->size < srctype->size) - ENSURE_GPR(output, srctype, outputReg); - } else if (IS_TYPE_FLOAT(srctype)) { - if (IS_TYPE_FLOAT(dsttype)) { - GEN_NODE_TO_REG(inner, outputReg, 0, output); - ENSURE_FPR(output, srctype, outputReg); - - if (dsttype->size == 4 && srctype->size != 4) { - int tmp = outputReg ? outputReg : ALLOC_FPR(); - emitpcode(PC_FRSP, tmp, output->reg); - output->optype = OpndType_FPR; - output->reg = tmp; - } - } else if (is_unsigned(dsttype) && dsttype->size == 4) { - GEN_NODE_TO_REG(inner, 1, 0, output); - ENSURE_FPR(output, srctype, 1); - convert_floating_to_unsigned(output, outputReg); - } else { - GEN_NODE_TO_REG(inner, 0, 0, output); - ENSURE_FPR(output, srctype, 0); - convert_floating_to_integer(output, outputReg); - } - } else if (IS_TYPE_VECTOR(srctype) && IS_TYPE_VECTOR(dsttype)) { - GEN_NODE_TO_REG(inner, outputReg, 0, output); - ENSURE_VR(output, srctype, outputReg); - } else if (srctype->size == dsttype->size) { - GEN_NODE_TO_REG(inner, outputReg, 0, output); - } else { - CError_FATAL(2224); - } -} - -void gen_BITFIELD(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - CError_FATAL(2238); -} - -void gen_INTCONST(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - if (TYPE_IS_8BYTES(expr->rtype)) { - I8_gen_INTCONST(expr, outputReg, outputRegHi, output); - return; - } - - output->optype = OpndType_Absolute; - output->immediate = CInt64_GetULong(&expr->data.intval); -} - -void gen_FLOATCONST(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - CError_FATAL(2294); -} - -void gen_STRINGCONST(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - CError_FATAL(2308); -} - -static Boolean COND_is_ABS_MatchNodes(ENode *cond, ENode *expr1, ENode *expr2) { - if (cond->type != expr1->type || cond->type != expr2->type) - return 0; - - if (!(TYPE_FITS_IN_REGISTER(cond->rtype) && TYPE_FITS_IN_REGISTER(expr1->rtype) && TYPE_FITS_IN_REGISTER(expr2->rtype))) - return 0; - - if (cond->rtype->size != expr1->rtype->size || cond->rtype->size != expr2->rtype->size) - return 0; - - switch (cond->type) { - case EOBJREF: - if (cond->data.objref != expr1->data.objref || cond->data.objref != expr2->data.objref) - return 0; - return 1; - case EINDIRECT: - case ETYPCON: - return COND_is_ABS_MatchNodes(cond->data.monadic, expr1->data.monadic, expr2->data.monadic); - default: - return 0; - } -} - -static ENode *COND_is_ABS(ENode *cond, ENode *expr1, ENode *expr2) { - ENode *tmp; - - int parity = 0; - while (ENODE_IS(cond, ELOGNOT)) { - parity = (parity + 1) & 1; - cond = cond->data.monadic; - } - - if (parity) { - tmp = expr1; - expr1 = expr2; - expr2 = tmp; - } - - switch (cond->type) { - case ELESS: - case ELESSEQU: - tmp = expr1; - expr1 = expr2; - expr2 = tmp; - break; - case EGREATER: - case EGREATEREQU: - break; - default: - return NULL; - } - - if (IS_INT_CONST_ZERO(cond->data.diadic.right)) { - cond = cond->data.diadic.left; - } else if (IS_INT_CONST_ZERO(cond->data.diadic.left)) { - cond = cond->data.diadic.left; - tmp = expr1; - expr1 = expr2; - expr2 = tmp; - } else { - return NULL; - } - - if (ENODE_IS(expr1, EADD) && ENODE_IS(expr2, ESUB)) { - if (COND_is_ABS_MatchNodes(cond, expr1->data.diadic.right, expr2->data.diadic.right)) - return expr1; - else - return NULL; - } - - if (!ENODE_IS(expr2, EMONMIN)) - return NULL; - - expr2 = expr2->data.monadic; - if (COND_is_ABS_MatchNodes(cond, expr1, expr2)) - return expr1; - - return NULL; -} - -static int COND_has_const(ENode *expr1, ENode *expr2) { - SInt32 diff; - int result = 0; - - if (IS_INT_CONST(expr1)) - result += 1; - if (IS_INT_CONST(expr2)) - result += 2; - - if (result & 1) { - if (IS_INT_CONST_ZERO(expr1)) - return 5; - } - if (result & 2) { - if (IS_INT_CONST_ZERO(expr2)) - return 6; - } - - if (result == 3) { - diff = expr1->data.intval.lo - expr2->data.intval.lo; - if (diff == 1 || diff == -1) - return 4; - } - - return result; -} - -static Boolean COND_is_COMPARE(ENode *cond, ENode *expr1, ENode *expr2, short outputReg, Operand *output) { - SInt32 left; - SInt32 right; - int parity; - int negate; - ENodeType nt; - - while (ENODE_IS(expr1, ETYPCON) && TYPE_FITS_IN_REGISTER(expr1->rtype)) - expr1 = expr1->data.monadic; - while (ENODE_IS(expr2, ETYPCON) && TYPE_FITS_IN_REGISTER(expr2->rtype)) - expr2 = expr2->data.monadic; - - if (!(ENODE_IS(expr1, EINTCONST) && TYPE_FITS_IN_REGISTER(expr1->rtype) && CInt64_IsInRange(expr1->data.intval, 4))) - return 0; - if (!(ENODE_IS(expr2, EINTCONST) && TYPE_FITS_IN_REGISTER(expr2->rtype) && CInt64_IsInRange(expr2->data.intval, 4))) - return 0; - - left = CInt64_GetULong(&expr1->data.intval); - right = CInt64_GetULong(&expr2->data.intval); - parity = 0; - negate = 0; - switch (left) { - case 1: - if (right != 0) - return 0; - break; - case 0: - parity = 1; - if (right == -1) - negate = 1; - else if (right != 1) - return 0; - break; - case -1: - if (right != 0) - return 0; - negate = 1; - break; - default: - return 0; - } - - while (ENODE_IS(cond, ELOGNOT)) { - parity = (parity + 1) & 1; - cond = cond->data.monadic; - } - - if (parity) { - nt = invert_relop(cond->type); - if (nt == cond->type) - return 0; - cond->type = nt; - } - - if (negate) - gen_negated_condition_gpr(cond, output, outputReg); - else - gen_condition_gpr(cond, output, outputReg); - - return 1; -} - -void gen_COND(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *cond; - ENode *expr1; - ENode *expr2; - Type *type; - PCodeLabel *label1; - PCodeLabel *label2; - PCodeLabel *label3; - Operand op1; - Operand op2; - int has_const; - int reg1; - int reg2; - int reg3; - short align; - short max_align; - - expr1 = expr->data.cond.expr1; - expr2 = expr->data.cond.expr2; - type = expr->rtype; - - label1 = makepclabel(); - label2 = makepclabel(); - label3 = makepclabel(); - - memclrw(&op1, sizeof(Operand)); - memclrw(&op2, sizeof(Operand)); - - cond = evaluate_and_skip_comma(expr->data.cond.cond); - - if (TOC_use_fsel(expr)) { - ENode *left; - ENode *right; - ENode *tmp; - ENodeType nt; - Boolean flag; - Operand op; - int fneg_reg; - int fneg_reg2; - int fneg_reg3; - int fsel_reg; - int final_reg; - - left = cond->data.diadic.left; - right = cond->data.diadic.right; - nt = cond->type; - flag = 0; - memclrw(&op, sizeof(Operand)); - - switch (nt) { - case EGREATEREQU: - case EEQU: - break; - case EGREATER: - tmp = left; - left = right; - right = tmp; - case ELESS: - case ENOTEQU: - tmp = expr1; - expr1 = expr2; - expr2 = tmp; - break; - case ELESSEQU: - tmp = left; - left = right; - right = tmp; - break; - default: - CError_FATAL(2780); - } - - if (ENODE_IS(left, EFLOATCONST) && CMach_FloatIsZero(left->data.floatval)) { - GEN_NODE(right, &op); - ENSURE_FPR(&op, right->rtype, 0); - flag = 1; - } else if (ENODE_IS(right, EFLOATCONST) && CMach_FloatIsZero(right->data.floatval)) { - GEN_NODE(left, &op); - ENSURE_FPR(&op, left->rtype, 0); - } else { - fp_binary_operator((type->size == 4) ? PC_FSUBS : PC_FSUB, left, right, 0, &op); - } - - switch (cond->type) { - case EEQU: - case ENOTEQU: - if (flag) { - GEN_NODE_TO_FPR(expr1, &op1, expr1->rtype, 0); - GEN_NODE_TO_FPR(expr2, &op2, expr2->rtype, 0); - - fneg_reg = ALLOC_FPR(); - emitpcode(PC_FNEG, fneg_reg, op.reg); - fsel_reg = ALLOC_FPR(); - emitpcode(PC_FSEL, fsel_reg, op.reg, op1.reg, op2.reg); - final_reg = outputReg ? outputReg : ALLOC_FPR(); - emitpcode(PC_FSEL, final_reg, fneg_reg, fsel_reg, op2.reg); - } else { - GEN_NODE_TO_FPR(expr1, &op1, expr1->rtype, 0); - GEN_NODE_TO_FPR(expr2, &op2, expr2->rtype, 0); - - fneg_reg2 = ALLOC_FPR(); - emitpcode(PC_FNEG, fneg_reg2, op.reg); - fsel_reg = ALLOC_FPR(); - emitpcode(PC_FSEL, fsel_reg, op.reg, op1.reg, op2.reg); - final_reg = outputReg ? outputReg : ALLOC_FPR(); - emitpcode(PC_FSEL, final_reg, fneg_reg2, fsel_reg, op2.reg); - } - break; - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - GEN_NODE_TO_FPR(expr1, &op1, expr1->rtype, 0); - GEN_NODE_TO_FPR(expr2, &op2, expr2->rtype, 0); - - fneg_reg3 = op.reg; - if (flag) { - fneg_reg3 = ALLOC_FPR(); - emitpcode(PC_FNEG, fneg_reg3, op.reg); - } - - final_reg = outputReg ? outputReg : ALLOC_FPR(); - emitpcode(PC_FSEL, final_reg, fneg_reg3, op1.reg, op2.reg); - break; - default: - CError_FATAL(2862); - } - - output->optype = OpndType_FPR; - output->reg = final_reg; - return; - } - - if (TOC_use_isel(expr, 1)) { - Operand isel_op1; - Operand isel_op2; - ENode *x; - ENode *y; - ENode *abs_expr; - - memclrw(&isel_op1, sizeof(Operand)); - memclrw(&isel_op2, sizeof(Operand)); - - if (COND_is_COMPARE(cond, expr1, expr2, outputReg, output)) - return; - - if ((abs_expr = COND_is_ABS(cond, expr1, expr2))) { - if (ENODE_IS(expr1, EADD) && ENODE_IS(expr2, ESUB)) { - x = expr1->data.diadic.left; - y = expr2->data.diadic.right; - if (y->hascall) { - GEN_NODE(y, &op2); - ENSURE_GPR(&op2, y->rtype, 0); - - GEN_NODE(x, &op1); - if (op1.optype >= OpndType_IndirectGPR_ImmOffset) - ENSURE_GPR(&op1, x->rtype, 0); - } else { - GEN_NODE(x, &op1); - if (op1.optype >= OpndType_IndirectGPR_ImmOffset) - ENSURE_GPR(&op1, x->rtype, 0); - - GEN_NODE(y, &op2); - ENSURE_GPR(&op2, y->rtype, 0); - } - - reg1 = ALLOC_GPR(); - emitpcode(PC_SRAWI, reg1, op2.reg, 31); - reg2 = ALLOC_GPR(); - emitpcode(PC_XOR, reg2, reg1, op2.reg); - reg3 = ALLOC_GPR(); - emitpcode(PC_SUBF, reg3, reg1, reg2); - op2.optype = OpndType_GPR; - op2.reg = reg3; - combine(&op1, &op2, outputReg, output); - } else { - GEN_NODE(abs_expr, output); - ENSURE_GPR(output, abs_expr->rtype, 0); - - reg1 = ALLOC_GPR(); - emitpcode(PC_SRAWI, reg1, output->reg, 31); - reg2 = ALLOC_GPR(); - emitpcode(PC_XOR, reg2, reg1, output->reg); - reg3 = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SUBF, reg3, reg1, reg2); - output->optype = OpndType_GPR; - output->reg = reg3; - } - return; - } - - if ((has_const = COND_has_const(expr1, expr2))) { - switch (COND_has_const(expr1, expr2)) { - case 0: - case 2: - break; - case 3: - case 4: - if (has_const == 4) { - if (expr1->data.intval.lo < expr2->data.intval.lo) - gen_negated_condition_gpr(cond, &isel_op1, 0); - else - gen_condition_gpr(cond, &isel_op1, 0); - - GEN_NODE(expr1, &op1); - GEN_NODE(expr2, &op2); - reg1 = ALLOC_GPR(); - ENSURE_GPR(&op2, expr2->rtype, reg1); - emitpcode(PC_ADD, reg1, isel_op1.reg, op2.reg); - if (outputReg) { - emitpcode(PC_MR, reg2 = outputReg, reg1); - reg1 = reg2; - } - output->optype = OpndType_GPR; - output->reg = reg1; - return; - } - break; - case 5: - case 6: - gen_negated_condition_gpr(cond, &isel_op1, 0); - ENSURE_GPR(&isel_op1, TYPE(&stunsignedint), 0); - GEN_NODE(expr1, &op1); - GEN_NODE(expr2, &op2); - - reg1 = outputReg ? outputReg : ALLOC_GPR(); - if (op1.optype == OpndType_Absolute && op1.immediate == 0) { - ENSURE_GPR(&op2, expr2->rtype, 0); - emitpcode(PC_ANDC, reg1, op2.reg, isel_op1.reg); - } else if (op2.optype == OpndType_Absolute && op2.immediate == 0) { - ENSURE_GPR(&op1, expr1->rtype, 0); - emitpcode(PC_AND, reg1, op1.reg, isel_op1.reg); - } else { - CError_FATAL(3119); - } - - output->optype = OpndType_GPR; - output->reg = reg1; - return; - case 1: - reg2 = ALLOC_GPR(); - reg1 = reg2; - logical_expression_nobranch(cond, 0, &isel_op2); - - GEN_NODE_TO_REG(expr1, reg1, 0, &op1); - ENSURE_GPR(&op1, expr1->rtype, reg1); - if (op1.reg != reg1) - emitpcode(PC_MR, reg1, op1.reg); - - branch_conditional(isel_op2.reg, isel_op2.regOffset, 1, label2); - branch_label(label1); - - GEN_NODE_TO_REG(expr2, reg1, 0, &op2); - ENSURE_GPR(&op2, expr2->rtype, reg1); - if (op2.reg != reg1) - emitpcode(PC_MR, reg1, op2.reg); - - branch_label(label2); - - if (outputReg) { - emitpcode(PC_MR, reg2 = outputReg, reg1); - reg1 = reg2; - } - - output->optype = OpndType_GPR; - output->reg = reg1; - return; - - default: - CError_FATAL(3168); - } - } - - reg1 = ALLOC_GPR(); - logical_expression_nobranch(cond, 0, &isel_op2); - - GEN_NODE_TO_REG(expr2, reg1, 0, &op2); - ENSURE_GPR(&op2, expr2->rtype, reg1); - if (op2.reg != reg1) - emitpcode(PC_MR, reg1, op2.reg); - - branch_conditional(isel_op2.reg, isel_op2.regOffset, 0, label2); - branch_label(label1); - - GEN_NODE_TO_REG(expr1, reg1, 0, &op1); - ENSURE_GPR(&op1, expr1->rtype, reg1); - if (op1.reg != reg1) - emitpcode(PC_MR, reg1, op1.reg); - - branch_label(label2); - - if (outputReg) { - emitpcode(PC_MR, reg2 = outputReg, reg1); - reg1 = reg2; - } - - output->optype = OpndType_GPR; - output->reg = reg1; - return; - } - - logical_expression(cond, label1, label2, label1); - branch_label(label1); - - if (IS_TYPE_VOID(type) || expr->ignored) { - GEN_NODE(expr1, &op1); - branch_always(label3); - branch_label(label2); - GEN_NODE(expr2, &op2); - } else if (IS_TYPE_FLOAT(type)) { - if (expr1->hascall || expr2->hascall) - reg1 = ALLOC_FPR(); - else - reg1 = outputReg ? outputReg : ALLOC_FPR(); - - GEN_NODE_TO_REG(expr1, reg1, 0, &op1); - ENSURE_FPR(&op1, expr1->rtype, reg1); - if (op1.reg != reg1) - emitpcode(PC_FMR, reg1, op1.reg); - - branch_always(label3); - branch_label(label2); - - GEN_NODE_TO_REG(expr2, reg1, 0, &op2); - ENSURE_FPR(&op2, expr2->rtype, reg1); - if (op2.reg != reg1) - emitpcode(PC_FMR, reg1, op2.reg); - - output->optype = OpndType_FPR; - output->reg = reg1; - } else if (TYPE_IS_8BYTES(type)) { - if (expr1->hascall || expr2->hascall) { - reg1 = ALLOC_GPR(); - reg3 = ALLOC_GPR(); - reg2 = reg3; - } else { - reg1 = outputReg ? outputReg : ALLOC_GPR(); - reg3 = outputRegHi ? outputRegHi : ALLOC_GPR(); - reg2 = reg3; - } - - GEN_NODE_TO_REG(expr1, reg1, reg2, &op1); - coerce_to_register_pair(&op1, expr1->rtype, reg1, reg2); - - branch_always(label3); - branch_label(label2); - - GEN_NODE_TO_REG(expr2, reg1, reg2, &op2); - coerce_to_register_pair(&op2, expr2->rtype, reg1, reg2); - - output->optype = OpndType_GPRPair; - output->reg = reg1; - output->regHi = reg2; - } else if (TYPE_FITS_IN_REGISTER(type)) { - if (expr1->hascall || expr2->hascall) - reg1 = ALLOC_GPR(); - else - reg1 = outputReg ? outputReg : ALLOC_GPR(); - - GEN_NODE_TO_REG(expr1, reg1, 0, &op1); - ENSURE_GPR(&op1, expr1->rtype, reg1); - if (op1.reg != reg1) - emitpcode(PC_MR, reg1, op1.reg); - - branch_always(label3); - branch_label(label2); - - GEN_NODE_TO_REG(expr2, reg1, 0, &op2); - ENSURE_GPR(&op2, expr2->rtype, reg1); - if (op2.reg != reg1) - emitpcode(PC_MR, reg1, op2.reg); - - output->optype = OpndType_GPR; - output->reg = reg1; - } else if (IS_TYPE_VECTOR(type)) { - if (expr1->hascall || expr2->hascall) - reg1 = ALLOC_VR(); - else - reg1 = outputReg ? outputReg : ALLOC_VR(); - - GEN_NODE_TO_REG(expr1, reg1, 0, &op1); - ENSURE_VR(&op1, expr1->rtype, reg1); - if (op1.reg != reg1) - emitpcode(PC_VMR, reg1, op1.reg); - - branch_always(label3); - branch_label(label2); - - GEN_NODE_TO_REG(expr2, reg1, 0, &op2); - ENSURE_VR(&op2, expr2->rtype, reg1); - if (op2.reg != reg1) - emitpcode(PC_VMR, reg1, op2.reg); - - output->optype = OpndType_VR; - output->reg = reg1; - } else { - symbol_operand(output, maketemporary(type)); - indirect(output, NULL); - coerce_to_addressable(output); - - GEN_NODE(expr1, &op1); - - if (op1.object) { - if (op1.object->datatype == DLOCAL && (op1.object->u.var.info->flags & VarInfoFlag1)) - align = CMach_ArgumentAlignment(type); - else - align = CMach_AllocationAlignment(type, op1.object->qual); - } else { - align = CMach_AllocationAlignment(type, 0); - } - - max_align = CMach_AllocationAlignment(type, 0); - if (align > max_align) - align = max_align; - - move_block(output, &op1, type->size, align); - - branch_always(label3); - branch_label(label2); - - GEN_NODE(expr2, &op2); - - if (op2.object) { - if (op2.object->datatype == DLOCAL && (op2.object->u.var.info->flags & VarInfoFlag1)) - align = CMach_ArgumentAlignment(type); - else - align = CMach_AllocationAlignment(type, op2.object->qual); - } else { - align = CMach_AllocationAlignment(type, 0); - } - - if (align > max_align) - align = max_align; - - move_block(output, &op2, type->size, align); - } - - branch_label(label3); -} - -static Boolean CONDASS_is_ABS(ENode *cond, ENode *expr1, ENode *expr2) { - ENode *inner; - - int parity = 0; - while (ENODE_IS(cond, ELOGNOT)) { - parity = (parity + 1) & 1; - cond = cond->data.monadic; - } - - if (IS_INT_CONST_ZERO(cond->data.diadic.right)) { - inner = cond->data.diadic.left; - } else if (IS_INT_CONST_ZERO(cond->data.diadic.left)) { - inner = cond->data.diadic.left; - parity = (parity + 1) & 1; - } else { - return 0; - } - - switch (cond->type) { - case EGREATER: - case EGREATEREQU: - if (!parity) - return 0; - break; - case ELESS: - case ELESSEQU: - if (parity) - return 0; - break; - default: - return 0; - } - - if (!ENODE_IS(expr2, EMONMIN)) - return 0; - - expr2 = expr2->data.monadic; - if (ENODE_IS(inner, EASS)) { - inner = inner->data.diadic.left; - if (!ENODE_IS(expr2, EINDIRECT)) - return 0; - expr2 = expr2->data.monadic; - if (!ENODE_IS(expr1, EINDIRECT)) - return 0; - expr1 = expr1->data.monadic; - } - - return COND_is_ABS_MatchNodes(inner, expr1, expr2); -} - -static int CONDASS_is_OPASS_One(ENode *a, ENode *b, SInt32 *value, ENodeType *nodetype) { - Type *type; - - type = a->rtype; - if (!ENODE_IS(a, EINDIRECT)) - return 0; - a = a->data.monadic; - if (!ENODE_IS(a, EOBJREF)) - return 0; - - if (ENODE_IS(b, ETYPCON) && b->rtype == type) - b = b->data.monadic; - - if (b->type != EOR && b->type != EADD && b->type != ESUB) - return 0; - - *nodetype = b->type; - if (!IS_INT_CONST(b->data.diadic.right)) - return 0; - *value = b->data.diadic.right->data.intval.lo; - - if (*value != 1 && *value != -1) - return 0; - - b = b->data.diadic.left; - if (ENODE_IS(b, ETYPCON) && TYPE_FITS_IN_REGISTER(b->rtype)) - b = b->data.monadic; - - if (!ENODE_IS(b, EINDIRECT)) - return 0; - b = b->data.monadic; - if (!ENODE_IS(b, EOBJREF)) - return 0; - - if (a->data.objref == b->data.objref) - return 1; - return 0; -} - -void gen_CONDASS(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *cond; - ENode *expr1; - ENode *expr2; - Type *type; - PCodeLabel *label1; - PCodeLabel *label2; - Operand op1; - Operand op2; - Operand op3; - int reg1; - int reg2; - - expr1 = expr->data.cond.expr1; - expr2 = expr->data.cond.expr2; - type = expr->rtype; - - label1 = makepclabel(); - label2 = makepclabel(); - - memclrw(&op1, sizeof(Operand)); - memclrw(&op2, sizeof(Operand)); - memclrw(&op3, sizeof(Operand)); - - cond = evaluate_and_skip_comma(expr->data.cond.cond); - - if (TOC_use_fsel(expr)) { - ENode *left; - ENode *right; - ENode *tmp; - ENodeType nt; - Boolean flag; - Boolean flag2; - Operand op; - int tmpreg; - int fneg_reg; - int fsel_reg; - int final_reg; - - left = cond->data.diadic.left; - right = cond->data.diadic.right; - nt = cond->type; - flag = 0; - memclrw(&op, sizeof(Operand)); - - CError_ASSERT(3704, ENODE_IS(expr1, EINDIRECT)); - CError_ASSERT(3705, ENODE_IS(expr1->data.monadic, EOBJREF)); - - tmpreg = OBJECT_REG(expr1->data.monadic->data.objref); - final_reg = outputReg ? tmpreg : ALLOC_FPR(); - - switch (nt) { - case EGREATER: - tmp = left; - left = right; - right = tmp; - case ELESS: - case ENOTEQU: - tmp = expr1; - expr1 = expr2; - expr2 = tmp; - flag2 = 1; - break; - case ELESSEQU: - tmp = left; - left = right; - right = tmp; - flag2 = 0; - break; - case EGREATEREQU: - case EEQU: - flag2 = 0; - break; - default: - CError_FATAL(3744); - } - - if (ENODE_IS(left, EFLOATCONST) && CMach_FloatIsZero(left->data.floatval)) { - GEN_NODE(right, &op); - ENSURE_FPR(&op, right->rtype, 0); - flag = 1; - } else if (ENODE_IS(right, EFLOATCONST) && CMach_FloatIsZero(right->data.floatval)) { - GEN_NODE(left, &op); - ENSURE_FPR(&op, left->rtype, 0); - } else { - fp_binary_operator((type->size == 4) ? PC_FSUBS : PC_FSUB, left, right, 0, &op); - } - - switch (cond->type) { - case EEQU: - case ENOTEQU: - if (flag) { - GEN_NODE(expr1, &op1); - op3 = op1; - ENSURE_FPR(&op1, expr1->rtype, 0); - - GEN_NODE_TO_FPR(expr2, &op2, expr2->rtype, 0); - - fneg_reg = ALLOC_FPR(); - emitpcode(PC_FNEG, fneg_reg, op.reg); - fsel_reg = ALLOC_FPR(); - emitpcode(PC_FSEL, fsel_reg, op.reg, op2.reg, op1.reg); - emitpcode(PC_FSEL, final_reg, fneg_reg, op2.reg, fsel_reg); - } else { - GEN_NODE(expr1, &op1); - op3 = op1; - ENSURE_FPR(&op1, expr1->rtype, 0); - - GEN_NODE_TO_FPR(expr2, &op2, expr2->rtype, 0); - - fneg_reg = ALLOC_FPR(); - emitpcode(PC_FNEG, fneg_reg, op.reg); - fsel_reg = ALLOC_FPR(); - emitpcode(PC_FSEL, fsel_reg, op.reg, op2.reg, op1.reg); - emitpcode(PC_FSEL, final_reg, fneg_reg, op2.reg, fsel_reg); - } - break; - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - GEN_NODE(expr1, &op1); - GEN_NODE(expr2, &op2); - op3 = flag2 ? op2 : op1; - - ENSURE_FPR(&op1, expr1->rtype, 0); - ENSURE_FPR(&op2, expr2->rtype, 0); - - fneg_reg = op.reg; - if (flag) { - fneg_reg = ALLOC_FPR(); - emitpcode(PC_FNEG, fneg_reg, op.reg); - } - - emitpcode(PC_FSEL, final_reg, fneg_reg, op2.reg, op1.reg); - break; - default: - CError_FATAL(2862); - } - - if (op3.optype != OpndType_FPR) - store_fp(final_reg, &op3, type); - - output->optype = OpndType_FPR; - output->reg = final_reg; - return; - } - - if (TOC_use_isel(expr, 1)) { - Operand isel_op; - ENode *x; - ENode *y; - ENode *abs_expr; - - memclrw(&isel_op, sizeof(Operand)); - CError_ASSERT(3966, ENODE_IS(expr1, EINDIRECT)); - CError_ASSERT(3968, ENODE_IS(expr1->data.monadic, EOBJREF)); - - if (CONDASS_is_ABS(cond, expr1, expr2)) { - if (ENODE_IS(cond->data.diadic.left, EASS)) - GEN_NODE(cond->data.diadic.left, &isel_op); - else if (ENODE_IS(cond->data.diadic.right, EASS)) - GEN_NODE(cond->data.diadic.right, &isel_op); - - outputReg = OBJECT_REG(expr1->data.monadic->data.objref); - CError_ASSERT(3979, outputReg); - - GEN_NODE(expr1, &op1); - op3 = op1; - - CError_ASSERT(3986, op3.optype == OpndType_GPR && op3.reg == outputReg); - - ENSURE_GPR(&op1, expr1->rtype, 0); - if (expr1->rtype->size < 4) - extend32(output, expr1->rtype, op3.reg); - - reg1 = ALLOC_GPR(); - reg2 = ALLOC_GPR(); - emitpcode(PC_SRAWI, reg1, op1.reg, 31); - emitpcode(PC_XOR, reg2, reg1, op1.reg); - emitpcode(PC_SUBF, outputReg, reg1, reg2); - output->optype = OpndType_GPR; - output->reg = op3.reg; - - if (expr1->rtype->size < 4) - extend32(output, expr1->rtype, op3.reg); - - return; - } - } - - logical_expression(cond, label1, label2, label1); - branch_label(label1); - gen_ASS(expr, outputReg, outputRegHi, output); - branch_label(label2); -} - -void gen_FUNCCALL(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - if (is_intrinsic_function_call(expr)) - call_intrinsic_function(expr, outputReg, output); - else - call_function(expr, output); -} - -void gen_OBJREF(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - symbol_operand(output, expr->data.objref); -} - -void gen_UNEXPECTED(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - CError_FATAL(4160); -} - -static int small(ENode *expr) { - Type *type; - - type = expr->rtype; - if (!ENODE_IS(expr, ETYPCON)) - return 0; - - do { - expr = expr->data.monadic; - } while (ENODE_IS(expr, ETYPCON) && (type = expr->rtype)->size == 4); - - return IS_TYPE_INT_OR_ENUM(type) && ((type->size < 2) || (type->size == 2 && !is_unsigned(type))); -} - -void binary_operator(Opcode opcode, ENode *left, ENode *right, short outputReg, Operand *output) { - Operand opleft; - Operand opright; - int reg; - - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - - if (right->hascall) { - GEN_NODE_TO_GPR(right, &opright, right->rtype, 0); - GEN_NODE_TO_GPR(left, &opleft, left->rtype, 0); - } else { - GEN_NODE_TO_GPR(left, &opleft, left->rtype, 0); - GEN_NODE_TO_GPR(right, &opright, right->rtype, 0); - } - - reg = outputReg ? outputReg : ALLOC_GPR(); - - if (opcode == PC_MULLW && small(left)) - emitpcode(opcode, reg, opright.reg, opleft.reg); - else - emitpcode(opcode, reg, opleft.reg, opright.reg); - - output->optype = OpndType_GPR; - output->reg = reg; -} - -static void binary_immediate(Opcode opcode, ENode *left, SInt32 value, short outputReg, Operand *output) { - Operand opleft; - int reg; - - memclrw(&opleft, sizeof(Operand)); - GEN_NODE_TO_GPR(left, &opleft, left->rtype, 0); - - reg = outputReg ? outputReg : ALLOC_GPR(); - - if (opcode == PC_MULLI && value == 0) - emitpcode(PC_LI, reg, 0); - else if (opcode == PC_MULLI && value == 1) - emitpcode(PC_MR, reg, opleft.reg); - else - emitpcode(opcode, reg, opleft.reg, value); - - output->optype = OpndType_GPR; - output->reg = reg; -} - -void unary_operator(Opcode opcode, ENode *expr, short outputReg, Operand *output) { - Operand op; - int reg; - - memclrw(&op, sizeof(Operand)); - GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); - - reg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(opcode, reg, op.reg); - - output->optype = OpndType_GPR; - output->reg = reg; -} - -static void or_xor_immediate(Opcode opcode, ENode *expr, SInt32 value, short outputReg, Operand *output) { - Operand op; - int reg; - - memclrw(&op, sizeof(Operand)); - GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); - - reg = outputReg ? outputReg : ALLOC_GPR(); - - if (expr->rtype->size > 2 && value != (value & 0xFFFF)) { - if (value & 0xFFFF) { - emitpcode((opcode == PC_ORI) ? PC_ORIS : PC_XORIS, reg, op.reg, value >> 16); - emitpcode(opcode, reg, reg, value & 0xFFFF); - } else { - emitpcode((opcode == PC_ORI) ? PC_ORIS : PC_XORIS, reg, op.reg, value >> 16); - } - } else { - emitpcode(opcode, reg, op.reg, value & 0xFFFF); - } - - output->optype = OpndType_GPR; - output->reg = reg; -} - -static void shift_left_immediate(ENode *expr, short shift, short negate, short outputReg, Operand *output) { - Operand op; - int reg; - - memclrw(&op, sizeof(Operand)); - GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); - - if (negate) - reg = ALLOC_GPR(); - else - reg = outputReg ? outputReg : ALLOC_GPR(); - - emitpcode(PC_RLWINM, reg, op.reg, shift & 31, 0, 31 - (shift & 31)); - - if (negate) { - int tmp = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_NEG, tmp, reg); - reg = tmp; - } - - output->optype = OpndType_GPR; - output->reg = reg; -} - -static void shift_right_immediate(ENode *expr, Type *type, short shift, short outputReg, Operand *output) { - Operand op; - int reg; - - memclrw(&op, sizeof(Operand)); - GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); - - reg = outputReg ? outputReg : ALLOC_GPR(); - - if (is_unsigned(type)) - emitpcode(PC_RLWINM, reg, op.reg, (32 - (shift & 31)) & 31, (shift & 31) + (32 - (type->size * 8)), 31); - else - emitpcode(PC_SRAWI, reg, op.reg, shift & 31); - - output->optype = OpndType_GPR; - output->reg = reg; -} - -static void signed_divide_by_power_of_2(ENode *expr, int shift, int negate, short outputReg, Operand *output) { - Operand op; - int reg; - int tmpreg1; - int tmpreg2; - - memclrw(&op, sizeof(Operand)); - GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); - - if (!copts.optimizesize && shift == 1) { - tmpreg1 = ALLOC_GPR(); - emitpcode(PC_RLWINM, tmpreg1, op.reg, 1, 31, 31); - tmpreg2 = ALLOC_GPR(); - emitpcode(PC_ADD, tmpreg2, tmpreg1, op.reg); - reg = (outputReg && !negate) ? outputReg : ALLOC_GPR(); - emitpcode(PC_SRAWI, reg, tmpreg2, 1); - } else { - tmpreg1 = ALLOC_GPR(); - emitpcode(PC_SRAWI, tmpreg1, op.reg, shift); - reg = (outputReg && !negate) ? outputReg : ALLOC_GPR(); - emitpcode(PC_ADDZE, reg, tmpreg1); - } - - if (negate) { - int prevreg = reg; - reg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_NEG, reg, prevreg); - } - - output->optype = OpndType_GPR; - output->reg = reg; -} - -static void signed_mod_by_power_of_2(ENode *expr, int shift, int negate, short outputReg, Operand *output) { - Operand op; - int reg; - int tmpreg1; - int tmpreg2; - int tmpreg3; - int tmpreg4; - - memclrw(&op, sizeof(Operand)); - GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); - - reg = outputReg ? outputReg : ALLOC_GPR(); - tmpreg1 = ALLOC_GPR(); - tmpreg2 = ALLOC_GPR(); - tmpreg3 = ALLOC_GPR(); - - if (shift == 1) { - emitpcode(PC_RLWINM, tmpreg1, op.reg, 1, 31, 31); - emitpcode(PC_RLWINM, tmpreg2, op.reg, 0, 31, 31); - emitpcode(PC_XOR, tmpreg3, tmpreg2, tmpreg1); - emitpcode(PC_SUBF, reg, tmpreg1, tmpreg3); - } else { - tmpreg4 = ALLOC_GPR(); - emitpcode(PC_RLWINM, tmpreg1, op.reg, 32 - shift, 0, 31 - (32 - shift)); - emitpcode(PC_RLWINM, tmpreg2, op.reg, 1, 31, 31); - emitpcode(PC_SUBF, tmpreg3, tmpreg2, tmpreg1); - emitpcode(PC_RLWINM, tmpreg4, tmpreg3, shift, 0, 31); - emitpcode(PC_ADD, reg, tmpreg4, tmpreg2); - } - - output->optype = OpndType_GPR; - output->reg = reg; -} - -static void fp_binary_operator(Opcode opcode, ENode *left, ENode *right, short outputReg, Operand *output) { - Operand opleft; - Operand opright; - int reg; - - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - - if (right->hascall) { - GEN_NODE_TO_FPR(right, &opright, right->rtype, 0); - GEN_NODE_TO_FPR(left, &opleft, left->rtype, 0); - } else { - GEN_NODE_TO_FPR(left, &opleft, left->rtype, 0); - GEN_NODE_TO_FPR(right, &opright, right->rtype, 0); - } - - reg = outputReg ? outputReg : ALLOC_FPR(); - emitpcode(opcode, reg, opleft.reg, opright.reg); - - output->optype = OpndType_FPR; - output->reg = reg; -} - -void fp_unary_operator(Opcode opcode, ENode *expr, short outputReg, Operand *output) { - Operand op; - int reg; - - memclrw(&op, sizeof(Operand)); - GEN_NODE_TO_FPR(expr, &op, expr->rtype, 0); - - reg = outputReg ? outputReg : ALLOC_FPR(); - emitpcode(opcode, reg, op.reg); - - output->optype = OpndType_FPR; - output->reg = reg; -} - -void fp_multiply_add(Opcode opcode, ENode *a, ENode *b, ENode *c, short outputReg, Operand *output) { - Operand opA; - Operand opB; - Operand opC; - int reg; - - memclrw(&opA, sizeof(Operand)); - memclrw(&opB, sizeof(Operand)); - memclrw(&opC, sizeof(Operand)); - - if (c->hascall) { - GEN_NODE_TO_FPR(c, &opC, c->rtype, 0); - if (b->hascall) { - GEN_NODE_TO_FPR(b, &opB, b->rtype, 0); - GEN_NODE_TO_FPR(a, &opA, a->rtype, 0); - } else { - GEN_NODE_TO_FPR(a, &opA, a->rtype, 0); - GEN_NODE_TO_FPR(b, &opB, b->rtype, 0); - } - } else { - if (b->hascall) { - GEN_NODE_TO_FPR(b, &opB, b->rtype, 0); - GEN_NODE_TO_FPR(a, &opA, a->rtype, 0); - GEN_NODE_TO_FPR(c, &opC, c->rtype, 0); - } else { - GEN_NODE_TO_FPR(a, &opA, a->rtype, 0); - GEN_NODE_TO_FPR(b, &opB, b->rtype, 0); - GEN_NODE_TO_FPR(c, &opC, c->rtype, 0); - } - } - - reg = outputReg ? outputReg : ALLOC_FPR(); - emitpcode(opcode, reg, opA.reg, opB.reg, opC.reg); - - output->optype = OpndType_FPR; - output->reg = reg; -} - -void gen_COMPARE(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - expr = evaluate_and_skip_comma(expr); - if (TYPE_IS_8BYTES(expr->data.diadic.right->rtype) || TYPE_IS_8BYTES(expr->data.diadic.left->rtype)) - I8_gen_condition(expr, output, 1); - else - gen_condition_gpr(expr, output, outputReg); -} - -void gen_LOGICAL(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *inner; - ENodeType op; - - expr = evaluate_and_skip_comma(expr); - inner = evaluate_and_skip_comma(expr->data.monadic); - expr->data.monadic = inner; - - if (ENODE_IS(expr, ELOGNOT) && !ENODE_IS2(inner, ELAND, ELOR)) { - op = inner->type; - if (ENODE_IS(inner, ELOGNOT)) { - switch (inner->data.monadic->type) { - case ELOGNOT: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case ELAND: - case ELOR: - GEN_NODE(inner->data.monadic, output); - if (expr->data.monadic->rtype->size < 4) - extend32(output, expr->data.monadic->rtype, 0); - ENSURE_GPR(output, expr->data.monadic->rtype, 0); - return; - } - } - - if (ENODE_IS(inner, ENOTEQU) && !TYPE_IS_8BYTES(inner->data.diadic.left->rtype) && ENODE_IS(inner->data.diadic.right, EINTCONST) && inner->data.diadic.right->data.intval.lo == 0) { - int tmpreg1; - int tmpreg2; - GEN_NODE(inner->data.diadic.left, output); - if (inner->data.diadic.left->rtype->size < 4) - extend32(output, inner->data.diadic.left->rtype, 0); - ENSURE_GPR(output, inner->data.diadic.left->rtype, 0); - - tmpreg1 = ALLOC_GPR(); - tmpreg2 = ALLOC_GPR(); - CError_ASSERT(4853, output->optype == OpndType_GPR); - - emitpcode(PC_CNTLZW, tmpreg2, output->reg); - emitpcode(PC_RLWINM, tmpreg1, tmpreg2, 27, 5, 31); - output->optype = OpndType_GPR; - output->reg = tmpreg1; - } else { - int tmpreg1; - int tmpreg2; - ENodeType inverted; - - inverted = invert_relop(op); - if (op != inverted && !IS_TYPE_FLOAT(inner->data.diadic.left->rtype)) { - inner->type = inverted; - gen_COMPARE(inner, 0, 0, output); - inner->type = inverted; - return; - } - - GEN_NODE(inner, output); - if (inner->rtype->size < 4) - extend32(output, inner->rtype, 0); - ENSURE_GPR(output, inner->rtype, 0); - - tmpreg1 = ALLOC_GPR(); - tmpreg2 = ALLOC_GPR(); - CError_ASSERT(4883, output->optype == OpndType_GPR); - - emitpcode(PC_CNTLZW, tmpreg2, output->reg); - emitpcode(PC_RLWINM, tmpreg1, tmpreg2, 27, 5, 31); - output->optype = OpndType_GPR; - output->reg = tmpreg1; - } - } else { - PCodeLabel *label1; - PCodeLabel *label2; - int tmpreg; - - label1 = makepclabel(); - label2 = makepclabel(); - - tmpreg = ALLOC_GPR(); - emitpcode(PC_LI, tmpreg, 0); - logical_expression(expr, label1, label2, label1); - branch_label(label1); - emitpcode(PC_LI, tmpreg, 1); - branch_label(label2); - output->optype = OpndType_GPR; - output->reg = tmpreg; - } -} - -void gen_NULLCHECK(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *left; - ENode *right; - Operand opleft; - Operand opright; - PrecomputedOperand *precomp; - int flag; - int reg; - PCodeLabel *label; - - left = expr->data.nullcheck.nullcheckexpr; - right = expr->data.nullcheck.condexpr; - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - flag = !IS_TYPE_VOID(expr->rtype) && !expr->ignored; - - GEN_NODE(left, &opleft); - if (left->rtype->size < 4) - extend32(&opleft, left->rtype, 0); - ENSURE_GPR(&opleft, left->rtype, 0); - - precomp = lalloc(sizeof(PrecomputedOperand)); - precomp->precompid = expr->data.nullcheck.precompid; - precomp->operand = opleft; - precomp->next = precomputedoperands; - precomputedoperands = precomp; - - emitpcode(PC_CMPI, 0, opleft.reg, 0); - if (flag) { - emitpcode(PC_MR, reg = ALLOC_GPR(), opleft.reg); - } - - label = makepclabel(); - branch_conditional(0, EEQU, 1, label); - GEN_NODE(right, &opright); - precomputedoperands = precomputedoperands->next; - - if (flag) { - ENSURE_GPR(&opright, right->rtype, reg); - if (opright.reg != reg) - emitpcode(PC_MR, reg, opright.reg); - output->optype = OpndType_GPR; - output->reg = reg; - } - - branch_label(label); -} - -void gen_PRECOMP(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - PrecomputedOperand *precomp; - - for (precomp = precomputedoperands; precomp; precomp = precomp->next) { - if (precomp->precompid == expr->data.precompid) - break; - } - - *output = precomp->operand; -} - -void logical_expression(ENode *cond, PCodeLabel *if_true, PCodeLabel *if_false, PCodeLabel *end) { - PCodeLabel *label; - Operand op; - memclrw(&op, sizeof(Operand)); - - cond = evaluate_and_skip_comma(cond); - switch (cond->type) { - case ELAND: - label = makepclabel(); - logical_expression(cond->data.diadic.left, label, if_false, label); - branch_label(label); - logical_expression(cond->data.diadic.right, if_true, if_false, end); - break; - case ELOR: - label = makepclabel(); - logical_expression(cond->data.diadic.left, if_true, label, label); - branch_label(label); - logical_expression(cond->data.diadic.right, if_true, if_false, end); - break; - case ELOGNOT: - logical_expression(cond->data.monadic, if_false, if_true, end); - break; - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - if (TYPE_IS_8BYTES(cond->data.diadic.right->rtype) || TYPE_IS_8BYTES(cond->data.diadic.left->rtype)) - I8_gen_condition(cond, &op, 0); - else - gen_condition(cond, &op); - - if (end == if_true) - branch_conditional(op.reg, op.regOffset, 0, if_false); - else - branch_conditional(op.reg, op.regOffset, 1, if_true); - break; - default: - CError_FATAL(5160); - } -} - -static void logical_expression_nobranch(ENode *cond, Boolean invert, Operand *output) { - cond = evaluate_and_skip_comma(cond); - switch (cond->type) { - case ELOGNOT: - logical_expression_nobranch(cond->data.monadic, 1, output); - break; - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - if (invert) { - ENodeType nt = invert_relop(cond->type); - CError_ASSERT(5190, nt != cond->type); - cond->type = nt; - } - - if (TYPE_IS_8BYTES(cond->data.diadic.right->rtype) || TYPE_IS_8BYTES(cond->data.diadic.left->rtype)) - I8_gen_condition(cond, output, 0); - else - gen_condition(cond, output); - - break; - default: - CError_FATAL(5206); - } -} - -static ENodeType invert_relop(ENodeType nt) { - switch (nt) { - case ELESS: return EGREATEREQU; - case EGREATER: return ELESSEQU; - case ELESSEQU: return EGREATER; - case EGREATEREQU: return ELESS; - case EEQU: return ENOTEQU; - case ENOTEQU: return EEQU; - default: return nt; - } -} - -static int reverse_relop(int nt) { - switch (nt) { - case ELESS: return EGREATER; - case EGREATER: return ELESS; - case ELESSEQU: return EGREATEREQU; - case EGREATEREQU: return ELESSEQU; - default: return nt; - } -} - -void gen_condition(ENode *cond, Operand *output) { - ENode *left; - ENode *right; - - left = cond->data.diadic.left; - right = cond->data.diadic.right; - if (IS_TYPE_FLOAT(left->rtype)) { - compare_floating(cond->type, left, right, output); - return; - } - - if (ENODE_IS(right, EINTCONST)) { - if (is_unsigned(left->rtype)) { - UInt32 val = right->data.intval.lo; - if (FITS_IN_USHORT(val)) { - compare_immediate(cond->type, left, val, output); - return; - } else if (ENODE_IS2(cond, EEQU, ENOTEQU)) { - compare_immediate_long(cond->type, left, val, output); - return; - } - } else { - UInt32 val = right->data.intval.lo; - if (FITS_IN_SHORT(val)) { - compare_immediate(cond->type, left, val, output); - return; - } else if (ENODE_IS2(cond, EEQU, ENOTEQU)) { - compare_immediate_long(cond->type, left, val, output); - return; - } - } - } else if (ENODE_IS(left, EINTCONST)) { - if (is_unsigned(right->rtype)) { - UInt32 val = left->data.intval.lo; - if (FITS_IN_USHORT(val)) { - compare_immediate(reverse_relop(cond->type), right, val, output); - return; - } else if (ENODE_IS2(cond, EEQU, ENOTEQU)) { - compare_immediate_long(reverse_relop(cond->type), right, val, output); - return; - } - } else { - UInt32 val = left->data.intval.lo; - if (FITS_IN_SHORT(val)) { - compare_immediate(reverse_relop(cond->type), right, val, output); - return; - } else if (ENODE_IS2(cond, EEQU, ENOTEQU)) { - compare_immediate_long(reverse_relop(cond->type), right, val, output); - return; - } - } - } - - compare_integer(cond->type, left, right, output); -} - -void gen_condition_gpr(ENode *cond, Operand *output, short outputReg) { - ENode *left; - ENode *right; - Operand condOp; - int finalReg; - int tmpReg; - int tmpReg2; - int tmpReg3; - int tmpReg4; - int a; - int b; - - left = cond->data.diadic.left; - right = cond->data.diadic.right; - memclrw(&condOp, sizeof(Operand)); - - if (!IS_TYPE_FLOAT(left->rtype)) { - Operand op1; - Operand op2; - Operand opTmp; - memclrw(&op1, sizeof(Operand)); - memclrw(&op2, sizeof(Operand)); - memclrw(&opTmp, sizeof(Operand)); - - if (right->hascall) { - GEN_NODE(right, &op2); - if (!IS_INT_CONST_ZERO(right)) { - if (right->rtype->size < 4) - extend32(&op2, right->rtype, 0); - ENSURE_GPR(&op2, right->rtype, 0); - } - - GEN_NODE(left, &op1); - if (left->rtype->size < 4) - extend32(&op1, left->rtype, 0); - ENSURE_GPR(&op1, left->rtype, 0); - } else { - GEN_NODE(left, &op1); - ENSURE_GPR(&op1, left->rtype, 0); - if (left->rtype->size < 4) - extend32(&op1, left->rtype, 0); - - GEN_NODE(right, &op2); - if (!IS_INT_CONST_ZERO(right)) { - if (right->rtype->size < 4) - extend32(&op2, right->rtype, 0); - ENSURE_GPR(&op2, right->rtype, 0); - } - } - - switch (cond->type) { - case EEQU: - if ( - copts.peephole && - IS_INT_CONST(right) && - pclastblock->pcodeCount > 0 && - pclastblock->lastPCode->op == PC_RLWINM && - pclastblock->lastPCode->args[0].data.reg.reg == op1.reg - ) - { - PCode *pc = pclastblock->lastPCode; - SInt32 a = pc->args[2].data.imm.value; - SInt32 b = pc->args[3].data.imm.value; - SInt32 value = right->data.intval.lo; - if (b == pc->args[4].data.imm.value) { - finalReg = outputReg ? outputReg : ALLOC_GPR(); - - if (value != (value & 1)) { - emitpcode(PC_LI, finalReg, 0); - } else if (value == 0) { - tmpReg = ALLOC_GPR(); - emitpcode( - PC_RLWINM, tmpReg, - pc->args[1].data.reg.reg, - (a + b + 1) & 31, 31, 31); - emitpcode(PC_XORI, finalReg, tmpReg, 1); - } else if (value == 1) { - emitpcode( - PC_RLWINM, finalReg, - pc->args[1].data.reg.reg, - (a + b + 1) & 31, 31, 31); - } else { - CError_FATAL(5434); - } - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - } - - if (IS_INT_CONST_ZERO(right)) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_CNTLZW, tmpReg, op1.reg, 0); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_RLWINM, finalReg, tmpReg, 27, 5, 31); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } else { - tmpReg = ALLOC_GPR(); - emitpcode(PC_SUBF, tmpReg, op1.reg, op2.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_CNTLZW, tmpReg2, tmpReg); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_RLWINM, finalReg, tmpReg2, 27, 5, 31); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - case ENOTEQU: - if ( - copts.peephole && - IS_INT_CONST(right) && - pclastblock->pcodeCount > 0 && - pclastblock->lastPCode->op == PC_RLWINM && - pclastblock->lastPCode->args[0].data.reg.reg == op1.reg - ) - { - PCode *pc = pclastblock->lastPCode; - SInt32 a = pc->args[2].data.imm.value; - SInt32 b = pc->args[3].data.imm.value; - SInt32 value = right->data.intval.lo; - if (b == pc->args[4].data.imm.value) { - finalReg = outputReg ? outputReg : ALLOC_GPR(); - - if (value != (value & 1)) { - emitpcode(PC_LI, finalReg, 1); - } else if (value == 0) { - emitpcode( - PC_RLWINM, finalReg, - pc->args[1].data.reg.reg, - (a + b + 1) & 31, 31, 31); - } else if (value == 1) { - tmpReg = ALLOC_GPR(); - emitpcode( - PC_RLWINM, tmpReg, - pc->args[1].data.reg.reg, - (a + b + 1) & 31, 31, 31); - emitpcode(PC_XORI, finalReg, tmpReg, 1); - } else { - CError_FATAL(5503); - } - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - } - - if (IS_INT_CONST_ZERO(right)) { - if (copts.optimizesize) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_ADDIC, tmpReg, op1.reg, -1); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SUBFE, finalReg, tmpReg, op1.reg); - } else { - tmpReg = ALLOC_GPR(); - emitpcode(PC_NEG, tmpReg, op1.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_OR, tmpReg2, tmpReg, op1.reg); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_RLWINM, finalReg, tmpReg2, 1, 31, 31); - } - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - if (copts.optimizesize) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_SUBF, tmpReg, op1.reg, op2.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_ADDIC, tmpReg2, tmpReg, -1); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SUBFE, finalReg, tmpReg2, tmpReg); - } else { - tmpReg = ALLOC_GPR(); - emitpcode(PC_SUBF, tmpReg, op1.reg, op2.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_SUBF, tmpReg2, op2.reg, op1.reg); - tmpReg3 = ALLOC_GPR(); - emitpcode(PC_OR, tmpReg3, tmpReg, tmpReg2); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_RLWINM, finalReg, tmpReg3, 1, 31, 31); - } - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - - case EGREATEREQU: - if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_RLWINM, tmpReg, op1.reg, 1, 31, 31); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_XORI, finalReg, tmpReg, 1); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - opTmp = op2; - op2 = op1; - op1 = opTmp; - - case ELESSEQU: - if (is_unsigned(left->rtype)) { - if (copts.optimizesize) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_LI, tmpReg, -1); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_SUBFC, tmpReg2, op1.reg, op2.reg); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SUBFZE, finalReg, tmpReg); - } else { - tmpReg = ALLOC_GPR(); - emitpcode(PC_SUBF, tmpReg, op1.reg, op2.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_ORC, tmpReg2, op2.reg, op1.reg); - tmpReg3 = ALLOC_GPR(); - emitpcode(PC_RLWINM, tmpReg3, tmpReg, 31, 1, 31); - tmpReg4 = ALLOC_GPR(); - emitpcode(PC_SUBF, tmpReg4, tmpReg3, tmpReg2); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_RLWINM, finalReg, tmpReg4, 1, 31, 31); - } - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - if (IS_INT_CONST_ZERO(right)) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_LI, tmpReg, 1); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_CNTLZW, tmpReg2, op1.reg); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_RLWNM, finalReg, tmpReg, tmpReg2, 31, 31); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_SRAWI, tmpReg2, op2.reg, 31); - tmpReg = ALLOC_GPR(); - emitpcode(PC_RLWINM, tmpReg, op1.reg, 1, 31, 31); - tmpReg3 = ALLOC_GPR(); - emitpcode(PC_SUBFC, tmpReg3, op1.reg, op2.reg); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_ADDE, finalReg, tmpReg2, tmpReg); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - - case EGREATER: - if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_NEG, tmpReg, op1.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_ANDC, tmpReg2, tmpReg, op1.reg); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_RLWINM, finalReg, tmpReg2, 1, 31, 31); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - opTmp = op2; - op2 = op1; - op1 = opTmp; - - case ELESS: - if (is_unsigned(left->rtype)) { - if (left->rtype->size <= 2) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_RLWINM, finalReg, tmpReg, 1, 31, 31); - output->optype = OpndType_GPR; - output->reg = finalReg; - } else { - if (copts.optimizesize) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_SUBFC, tmpReg, op2.reg, op1.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_SUBFE, tmpReg2, tmpReg, tmpReg); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_NEG, finalReg, tmpReg2); - } else { - tmpReg = ALLOC_GPR(); - emitpcode(PC_XOR, tmpReg, op2.reg, op1.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_CNTLZW, tmpReg2, tmpReg); - tmpReg3 = ALLOC_GPR(); - emitpcode(PC_SLW, tmpReg3, op2.reg, tmpReg2); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_RLWINM, finalReg, tmpReg3, 1, 31, 31); - } - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - return; - } - - if (IS_INT_CONST_ZERO(right)) { - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_RLWINM, finalReg, op1.reg, 1, 31, 31); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - tmpReg = ALLOC_GPR(); - emitpcode(PC_XOR, tmpReg, op2.reg, op1.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_SRAWI, tmpReg2, tmpReg, 1); - tmpReg3 = ALLOC_GPR(); - emitpcode(PC_AND, tmpReg3, tmpReg, op2.reg); - tmpReg4 = ALLOC_GPR(); - emitpcode(PC_SUBF, tmpReg4, tmpReg3, tmpReg2); - - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_RLWINM, finalReg, tmpReg4, 1, 31, 31); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - - default: - CError_FATAL(5777); - } - } - - gen_condition(cond, &condOp); - emitpcode(PC_MFCR, tmpReg = used_virtual_registers[RegClass_GPR]++); - a = 0; - b = condOp.reg * 4; - switch (condOp.regOffset) { - case ENOTEQU: - a = 1; - case EEQU: - b += 2; - break; - case EGREATEREQU: - a = 1; - break; - case ELESSEQU: - a = 1; - case EGREATER: - b += 1; - break; - } - - finalReg = outputReg ? outputReg : ALLOC_GPR(); - if (a) { - emitpcode(PC_RLWINM, tmpReg, tmpReg, b + 1, 31, 31); - emitpcode(PC_XORI, finalReg, tmpReg, 1); - } else { - emitpcode(PC_RLWINM, finalReg, tmpReg, b + 1, 31, 31); - } - output->optype = OpndType_GPR; - output->reg = finalReg; -} - -void gen_negated_condition_gpr(ENode *cond, Operand *output, short outputReg) { - ENode *left; - ENode *right; - Operand op1; - Operand op2; - Operand opTmp; - int finalReg; - int tmpReg; - int tmpReg2; - int tmpReg3; - - left = cond->data.diadic.left; - right = cond->data.diadic.right; - CError_ASSERT(5843, TYPE_FITS_IN_REGISTER(left->rtype) && TYPE_FITS_IN_REGISTER(right->rtype)); - - memclrw(&op1, sizeof(Operand)); - memclrw(&op2, sizeof(Operand)); - memclrw(&opTmp, sizeof(Operand)); - - if (right->hascall) { - GEN_NODE(right, &op2); - if (!IS_INT_CONST_ZERO(right)) { - if (right->rtype->size < 4) - extend32(&op2, right->rtype, 0); - ENSURE_GPR(&op2, right->rtype, 0); - } - - GEN_NODE(left, &op1); - if (left->rtype->size < 4) - extend32(&op1, left->rtype, 0); - ENSURE_GPR(&op1, left->rtype, 0); - } else { - GEN_NODE(left, &op1); - ENSURE_GPR(&op1, left->rtype, 0); - if (left->rtype->size < 4) - extend32(&op1, left->rtype, 0); - - GEN_NODE(right, &op2); - if (!IS_INT_CONST_ZERO(right)) { - if (right->rtype->size < 4) - extend32(&op2, right->rtype, 0); - ENSURE_GPR(&op2, right->rtype, 0); - } - } - - switch (cond->type) { - case EEQU: - if ( - copts.peephole && - IS_INT_CONST(right) && - pclastblock->pcodeCount > 0 && - pclastblock->lastPCode->op == PC_RLWINM && - pclastblock->lastPCode->args[0].data.reg.reg == op1.reg - ) - { - PCode *pc = pclastblock->lastPCode; - SInt32 a = pc->args[2].data.imm.value; - SInt32 b = pc->args[3].data.imm.value; - SInt32 value = right->data.intval.lo; - if (b == pc->args[4].data.imm.value) { - finalReg = outputReg ? outputReg : ALLOC_GPR(); - - if (value != (value & 1)) { - emitpcode(PC_LI, finalReg, 0); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - if (value == 0) { - tmpReg = ALLOC_GPR(); - emitpcode( - PC_RLWINM, tmpReg, - pc->args[1].data.reg.reg, - (a + b + 1) & 31, 31, 31); - emitpcode(PC_ADDI, finalReg, tmpReg, 0, -1); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - if (value == 1) { - tmpReg = ALLOC_GPR(); - emitpcode( - PC_RLWINM, - tmpReg, - pc->args[1].data.reg.reg, - (a + b + 1) & 31, - 31, - 31); - emitpcode(PC_NEG, finalReg, tmpReg); - output->optype = OpndType_GPR; - output->reg = tmpReg; // bug??? - return; - } - - CError_FATAL(5923); - } - } - - if (IS_INT_CONST_ZERO(right)) { - if (copts.optimizesize) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_ADDIC, tmpReg, op1.reg, -1); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SUBFE, finalReg, tmpReg, tmpReg); - } else { - tmpReg = ALLOC_GPR(); - emitpcode(PC_CNTLZW, tmpReg, op1.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_RLWINM, tmpReg2, tmpReg, 27, 31, 31); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_NEG, finalReg, tmpReg2); - } - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - if (copts.optimizesize) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_ADDIC, tmpReg2, tmpReg, -1); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SUBFE, finalReg, tmpReg2, tmpReg2); - } else { - tmpReg = ALLOC_GPR(); - emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_SUBF, tmpReg2, op1.reg, op2.reg); - tmpReg3 = ALLOC_GPR(); - emitpcode(PC_NOR, tmpReg3, tmpReg, tmpReg2); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SRAWI, finalReg, tmpReg3, 31); - } - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - - case ENOTEQU: - if ( - copts.peephole && - IS_INT_CONST(right) && - pclastblock->pcodeCount > 0 && - pclastblock->lastPCode->op == PC_RLWINM && - pclastblock->lastPCode->args[0].data.reg.reg == op1.reg - ) - { - PCode *pc = pclastblock->lastPCode; - SInt32 a = pc->args[2].data.imm.value; - SInt32 b = pc->args[3].data.imm.value; - SInt32 value = right->data.intval.lo; - if (b == pc->args[4].data.imm.value) { - finalReg = outputReg ? outputReg : ALLOC_GPR(); - - if (value != (value & 1)) { - emitpcode(PC_LI, finalReg, -1); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - if (value == 0) { - tmpReg = ALLOC_GPR(); - emitpcode( - PC_RLWINM, tmpReg, - pc->args[1].data.reg.reg, - (a + b + 1) & 31, 31, 31); - emitpcode(PC_NEG, finalReg, tmpReg); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - if (value == 1) { - tmpReg = ALLOC_GPR(); - emitpcode( - PC_RLWINM, tmpReg, - pc->args[1].data.reg.reg, - (a + b + 1) & 31, 31, 31); - emitpcode(PC_ADDI, finalReg, tmpReg, 0, -1); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - CError_FATAL(6031); - } - } - - if (IS_INT_CONST_ZERO(right)) { - if (copts.optimizesize) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_SUBFIC, tmpReg, op1.reg, 0); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SUBFE, finalReg, tmpReg, tmpReg); - } else { - tmpReg = ALLOC_GPR(); - emitpcode(PC_NEG, tmpReg, op1.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_OR, tmpReg2, tmpReg, op1.reg); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SRAWI, finalReg, tmpReg2, 31); - } - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - if (copts.optimizesize) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_SUBFIC, tmpReg2, tmpReg, 0); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SUBFE, finalReg, tmpReg2, tmpReg2); - } else { - tmpReg = ALLOC_GPR(); - emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_SUBF, tmpReg2, op1.reg, op2.reg); - tmpReg3 = ALLOC_GPR(); - emitpcode(PC_OR, tmpReg3, tmpReg, tmpReg2); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SRAWI, finalReg, tmpReg3, 31); - } - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - - case EGREATEREQU: - if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_RLWINM, tmpReg, op1.reg, 1, 31, 31); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_ADDI, finalReg, tmpReg, 0, -1); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - opTmp = op2; - op2 = op1; - op1 = opTmp; - - case ELESSEQU: - if (is_unsigned(left->rtype)) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_SUBFC, tmpReg, op1.reg, op2.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_ADDZE, tmpReg2, op1.reg); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SUBF, finalReg, tmpReg2, op1.reg); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - if (IS_INT_CONST_ZERO(right)) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_NEG, tmpReg, op1.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_ORC, tmpReg2, op1.reg, tmpReg); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SRAWI, finalReg, tmpReg2, 31); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - tmpReg = ALLOC_GPR(); - emitpcode(PC_XORIS, tmpReg, op1.reg, 0x8000); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_SUBF, tmpReg2, op1.reg, op2.reg); - tmpReg3 = ALLOC_GPR(); - emitpcode(PC_ADDC, tmpReg3, tmpReg2, tmpReg); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SUBFE, finalReg, tmpReg3, tmpReg3); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - - case EGREATER: - if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_NEG, tmpReg, op1.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_ANDC, tmpReg2, tmpReg, op1.reg); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SRAWI, finalReg, tmpReg2, 31); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - opTmp = op2; - op2 = op1; - op1 = opTmp; - - case ELESS: - if (is_unsigned(left->rtype)) { - tmpReg = ALLOC_GPR(); - emitpcode(PC_SUBFC, tmpReg, op2.reg, op1.reg); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SUBFE, finalReg, tmpReg, tmpReg); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - if (IS_INT_CONST_ZERO(right)) { - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SRAWI, finalReg, op1.reg, 31); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - } - - tmpReg = ALLOC_GPR(); - emitpcode(PC_SUBFC, tmpReg, op2.reg, op1.reg); - tmpReg2 = ALLOC_GPR(); - emitpcode(PC_RLWINM, tmpReg2, op2.reg, 1, 31, 31); - tmpReg3 = ALLOC_GPR(); - emitpcode(PC_RLWINM, tmpReg3, op1.reg, 1, 31, 31); - finalReg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_SUBFE, finalReg, tmpReg3, tmpReg2); - output->optype = OpndType_GPR; - output->reg = finalReg; - return; - - default: - CError_FATAL(6240); - } -} - -void compare_floating(short nt, ENode *left, ENode *right, Operand *output) { - Operand opleft; - Operand opright; - - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - - if (right->hascall) { - GEN_NODE_TO_FPR(right, &opright, right->rtype, 0); - GEN_NODE_TO_FPR(left, &opleft, left->rtype, 0); - } else { - GEN_NODE_TO_FPR(left, &opleft, left->rtype, 0); - GEN_NODE_TO_FPR(right, &opright, right->rtype, 0); - } - - emitpcode((nt == EEQU || nt == ENOTEQU) ? PC_FCMPU : PC_FCMPO, 0, opleft.reg, opright.reg); - if (nt == ELESSEQU) { - emitpcode(PC_CROR, 0, 2, 0, 0, 0, 2); - nt = EEQU; - } else if (nt == EGREATEREQU) { - emitpcode(PC_CROR, 0, 2, 0, 1, 0, 2); - nt = EEQU; - } - - output->optype = OpndType_CRField; - output->reg = 0; - output->regOffset = nt; -} - -void compare_integer(short nt, ENode *left, ENode *right, Operand *output) { - Operand opleft; - Operand opright; - - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - - if (right->hascall) { - GEN_NODE(right, &opright); - if (right->rtype->size < 4) - extend32(&opright, right->rtype, 0); - ENSURE_GPR(&opright, right->rtype, 0); - - GEN_NODE(left, &opleft); - if (left->rtype->size < 4) - extend32(&opleft, left->rtype, 0); - ENSURE_GPR(&opleft, left->rtype, 0); - } else { - GEN_NODE(left, &opleft); - ENSURE_GPR(&opleft, left->rtype, 0); - if (left->rtype->size < 4) - extend32(&opleft, left->rtype, 0); - - GEN_NODE(right, &opright); - if (right->rtype->size < 4) - extend32(&opright, right->rtype, 0); - ENSURE_GPR(&opright, right->rtype, 0); - } - - emitpcode(is_unsigned(left->rtype) ? PC_CMPL : PC_CMP, 0, opleft.reg, opright.reg); - - output->optype = OpndType_CRField; - output->reg = 0; - output->regOffset = nt; -} - -void compare_immediate(short nt, ENode *left, SInt32 value, Operand *output) { - int postIncFlag; - short postIncReg; - Operand op; - SInt32 postIncValue; - - memclrw(&op, sizeof(Operand)); - - postIncFlag = ispostincrementopportunity(left, &op, &postIncValue); - if (!postIncFlag) { - GEN_NODE(left, &op); - if (op.optype != OpndType_CRField) { - if (left->rtype->size < 4) - extend32(&op, left->rtype, 0); - else - ENSURE_GPR(&op, left->rtype, 0); - } - } else { - postIncReg = op.reg; - if (left->rtype->size < 4) - extend32(&op, left->rtype, 0); - ENSURE_GPR(&op, left->rtype, 0); - } - - if (op.optype == OpndType_CRField) { - if ( - (nt == EEQU && value == 1) || - (nt == ENOTEQU && value == 0) || - (nt == EGREATER && value == 0) || - (nt == EGREATEREQU && value == 1) - ) - { - *output = op; - return; - } - - if ( - (nt == EEQU && value == 0) || - (nt == ENOTEQU && value == 1) || - (nt == ELESS && value == 1) || - (nt == ELESSEQU && value == 0) - ) - { - *output = op; - switch (op.regOffset) { - case EEQU: - output->regOffset = ENOTEQU; - return; - case ENOTEQU: - output->regOffset = EEQU; - return; - case ELESS: - output->regOffset = EGREATEREQU; - return; - case EGREATER: - output->regOffset = ELESSEQU; - return; - case ELESSEQU: - output->regOffset = EGREATER; - return; - case EGREATEREQU: - output->regOffset = ELESS; - return; - } - } - - ENSURE_GPR(&op, left->rtype, 0); - } - - if ( - copts.peephole && - value == 0 && - pclastblock->pcodeCount > 0 && - pclastblock->lastPCode->op != PC_RLWINM && - (PCODE_FLAG_SET_F(pclastblock->lastPCode) & (fIsMove | fSideEffects | fCanSetRecordBit | fOpTypeGPR)) == (fCanSetRecordBit | fOpTypeGPR) && - pclastblock->lastPCode->args[0].data.reg.reg == op.reg && - (!is_unsigned(left->rtype) || nt == EEQU || nt == ENOTEQU) - ) - { - pcsetrecordbit(pclastblock->lastPCode); - } else { - emitpcode(is_unsigned(left->rtype) ? PC_CMPLI : PC_CMPI, 0, op.reg, value); - } - - if (postIncFlag) - add_register_immediate(postIncReg, postIncReg, postIncValue); - - output->optype = OpndType_CRField; - output->reg = 0; - output->regOffset = nt; -} - -void compare_immediate_long(short nt, ENode *left, SInt32 value, Operand *output) { - int postIncFlag; - short postIncReg; - int outputReg; - Operand op; - SInt32 postIncValue; - - memclrw(&op, sizeof(Operand)); - - postIncFlag = ispostincrementopportunity(left, &op, &postIncValue); - if (!postIncFlag) { - GEN_NODE(left, &op); - } else { - postIncReg = op.reg; - } - - if (left->rtype->size < 4) - extend32(&op, left->rtype, 0); - ENSURE_GPR(&op, left->rtype, 0); - - outputReg = ALLOC_GPR(); - emitpcode(PC_ADDIS, outputReg, op.reg, 0, (SInt16) (~(value >> 16) + 1)); - emitpcode(PC_CMPLI, 0, outputReg, value & 0xFFFF); - - if (postIncFlag) - add_register_immediate(postIncReg, postIncReg, postIncValue); - - output->optype = OpndType_CRField; - output->reg = 0; - output->regOffset = nt; -} - -static int ismask(SInt32 value, short *first, short *last) { - int start, end, bit; - start = end = -1; - for (bit = 31; bit >= 0; bit--) { - if (value & 1) { - if (start != -1) - return 0; - if (end == -1) - end = bit; - } else { - if (end != -1 && start == -1) - start = bit + 1; - } - value >>= 1; - } - - if (end == -1) - return 0; - if (start == -1) - start = 0; - *first = start; - *last = end; - return 1; -} - -int ismaskconstant(SInt32 value, short *first, short *last) { - short my_first; - short my_last; - if (ismask(value, first, last)) - return 1; - - if (value && ismask(~value, &my_first, &my_last)) { - *first = my_last + 1; - *last = my_first - 1; - return 1; - } else { - return 0; - } -} - -static void shift_and_mask(ENode *expr, short a, short b, short c, short outputReg, Operand *output) { - Operand op; - int reg; - - memclrw(&op, sizeof(Operand)); - GEN_NODE(expr, &op); - ENSURE_GPR(&op, expr->rtype, 0); - - reg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_RLWINM, reg, op.reg, a, b, c); - - output->optype = OpndType_GPR; - output->reg = reg; -} - -int ispostincrementopportunity(ENode *expr, Operand *op, SInt32 *value) { - Type *type; - int reg; - - type = expr->rtype; - if (!ENODE_IS2(expr, EPOSTINC, EPOSTDEC)) - return 0; - if (!ENODE_IS(expr->data.monadic, EINDIRECT)) - return 0; - if (!ENODE_IS(expr->data.monadic->data.monadic, EOBJREF)) - return 0; - - reg = OBJECT_REG(expr->data.monadic->data.monadic->data.objref); - if (!reg) - return 0; - - if (IS_TYPE_POINTER(type)) { - if (ENODE_IS(expr, EPOSTINC)) - *value = TPTR_TARGET(type)->size; - else - *value = -TPTR_TARGET(type)->size; - } else { - if (ENODE_IS(expr, EPOSTINC)) - *value = 1; - else - *value = -1; - } - - op->optype = OpndType_GPR; - op->reg = reg; - return 1; -} - -void add_register_immediate(short regA, short regB, SInt32 value) { - if (!FITS_IN_SHORT(value)) { - emitpcode(PC_ADDIS, regA, regB, 0, HIGH_PART(value)); - if (LOW_PART(value)) - emitpcode(PC_ADDI, regA, regA, 0, LOW_PART(value)); - } else { - emitpcode(PC_ADDI, regA, regB, 0, value); - } -} - -static int ispowerof2(SInt32 val) { - int bit = getbit(val); - return (bit > 0 && bit < 31) ? bit : 0; -} - -void I8_gen_ADD(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - int is_uns; - ENode *left; - ENode *right; - short reg; - short regHi; - short tmpreg1; - short tmpreg2; - SInt32 skipleft; - SInt32 skipright; - Operand opleft; - Operand opright; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - - if (right->hascall) { - GEN_NODE(right, &opright); - if (TYPE_IS_8BYTES(right->rtype)) - coerce_to_register_pair(&opright, right->rtype, 0, 0); - else - ENSURE_GPR(&opright, right->rtype, 0); - - GEN_NODE(left, &opleft); - if (TYPE_IS_8BYTES(left->rtype)) - coerce_to_register_pair(&opleft, left->rtype, 0, 0); - else - ENSURE_GPR(&opleft, left->rtype, 0); - } else { - GEN_NODE(left, &opleft); - if (TYPE_IS_8BYTES(left->rtype)) - coerce_to_register_pair(&opleft, left->rtype, 0, 0); - else - ENSURE_GPR(&opleft, left->rtype, 0); - - GEN_NODE(right, &opright); - if (TYPE_IS_8BYTES(right->rtype)) - coerce_to_register_pair(&opright, right->rtype, 0, 0); - else - ENSURE_GPR(&opright, right->rtype, 0); - } - - reg = ALLOC_GPR(); - regHi = ALLOC_GPR(); - is_uns = is_unsigned(expr->rtype) != 0; - skipleft = GetSizeSkip(left); - skipright = GetSizeSkip(right); - - if (skipleft < skipright) { - Operand tmpop; - SInt32 tmp; - - expr->data.diadic.left = right; - expr->data.diadic.right = left; - left = expr->data.diadic.left; - right = expr->data.diadic.right; - - tmpop = opright; - opright = opleft; - opleft = tmpop; - - tmp = skipleft; - skipleft = skipright; - skipright = tmp; - } - - switch (skipleft + skipright) { - case 1 + 1: - case 1 + 2: - case 2 + 2: - if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) { - emitpcode(PC_ADDIC, reg, opright.reg, LOW_PART(left->data.intval.lo)); - } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo)) { - emitpcode(PC_ADDIC, reg, opleft.reg, LOW_PART(right->data.intval.lo)); - } else { - emitpcode(PC_ADDC, reg, opleft.reg, opright.reg); - } - if (is_uns) - emitpcode(PC_LI, regHi, 0); - else - emitpcode(PC_SRAWI, regHi, reg, 31); - break; - case 1 + 4: - case 2 + 4: - case 4 + 4: - if (!is_uns) { - tmpreg1 = ALLOC_GPR(); - tmpreg2 = ALLOC_GPR(); - emitpcode(PC_SRAWI, tmpreg2, opleft.reg, 31); - emitpcode(PC_SRAWI, tmpreg1, opright.reg, 31); - } - if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) { - emitpcode(PC_ADDIC, reg, opright.reg, LOW_PART(left->data.intval.lo)); - } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo)) { - emitpcode(PC_ADDIC, reg, opleft.reg, LOW_PART(right->data.intval.lo)); - } else { - emitpcode(PC_ADDC, reg, opleft.reg, opright.reg); - } - if (is_uns) { - tmpreg1 = ALLOC_GPR(); - emitpcode(PC_LI, tmpreg1, 0); - emitpcode(PC_ADDZE, regHi, tmpreg1); - } else { - emitpcode(PC_ADDE, regHi, tmpreg1, tmpreg2); - } - break; - case 1 + 8: - case 2 + 8: - case 4 + 8: - CError_ASSERT(6933, skipleft == 8); - if (!is_uns) { - tmpreg2 = ALLOC_GPR(); - emitpcode(PC_SRAWI, tmpreg2, opright.reg, 31); - } - if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo) && left->data.intval.hi == 0) { - emitpcode(PC_ADDIC, reg, opright.reg, LOW_PART(left->data.intval.lo)); - } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo) && right->data.intval.hi == 0) { - emitpcode(PC_ADDIC, reg, opleft.reg, LOW_PART(right->data.intval.lo)); - } else { - emitpcode(PC_ADDC, reg, opleft.reg, opright.reg); - } - if (is_uns) - emitpcode(PC_ADDZE, regHi, opleft.regHi); - else - emitpcode(PC_ADDE, regHi, opleft.regHi, tmpreg2); - break; - case 8 + 8: - emitpcode(PC_ADDC, reg, opleft.reg, opright.reg); - emitpcode(PC_ADDE, regHi, opleft.regHi, opright.regHi); - break; - default: - CError_FATAL(6979); - } - - output->optype = OpndType_GPRPair; - output->reg = reg; - output->regHi = regHi; -} - -void I8_gen_INTCONST(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - short reg; - short regHi; - - reg = outputReg ? outputReg : ALLOC_GPR(); - regHi = outputRegHi ? outputRegHi : ALLOC_GPR(); - - load_immediate(reg, expr->data.intval.lo); - load_immediate(regHi, expr->data.intval.hi); - - output->optype = OpndType_GPRPair; - output->reg = reg; - output->regHi = regHi; -} - -void I8_gen_SUB(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - int is_uns; - ENode *left; - ENode *right; - short reg; - short regHi; - short tmpreg1; - short tmpreg2; - short tmpreg3; - SInt32 skipleft; - SInt32 skipright; - Operand opleft; - Operand opright; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - - if (right->hascall) { - GEN_NODE(right, &opright); - if (TYPE_IS_8BYTES(right->rtype)) - coerce_to_register_pair(&opright, right->rtype, 0, 0); - else - ENSURE_GPR(&opright, right->rtype, 0); - - GEN_NODE(left, &opleft); - if (TYPE_IS_8BYTES(left->rtype)) - coerce_to_register_pair(&opleft, left->rtype, 0, 0); - else - ENSURE_GPR(&opleft, left->rtype, 0); - } else { - GEN_NODE(left, &opleft); - if (TYPE_IS_8BYTES(left->rtype)) - coerce_to_register_pair(&opleft, left->rtype, 0, 0); - else - ENSURE_GPR(&opleft, left->rtype, 0); - - GEN_NODE(right, &opright); - if (TYPE_IS_8BYTES(right->rtype)) - coerce_to_register_pair(&opright, right->rtype, 0, 0); - else - ENSURE_GPR(&opright, right->rtype, 0); - } - - reg = ALLOC_GPR(); - regHi = ALLOC_GPR(); - is_uns = is_unsigned(expr->rtype) != 0; - skipleft = GetSizeSkip(left); - skipright = GetSizeSkip(right); - - switch (skipleft + skipright) { - case 1 + 1: - case 1 + 2: - case 2 + 2: - if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) { - emitpcode(PC_SUBFIC, reg, opright.reg, LOW_PART(left->data.intval.lo)); - } else { - emitpcode(PC_SUBFC, reg, opright.reg, opleft.reg); - } - if (is_uns) - emitpcode(PC_LI, regHi, 0); - else - emitpcode(PC_SRAWI, regHi, reg, 31); - break; - case 1 + 4: - case 2 + 4: - case 4 + 4: - if (!is_uns) { - tmpreg1 = ALLOC_GPR(); - tmpreg2 = ALLOC_GPR(); - emitpcode(PC_SRAWI, tmpreg2, opleft.reg, 31); - emitpcode(PC_SRAWI, tmpreg1, opright.reg, 31); - } - if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) { - emitpcode(PC_SUBFIC, reg, opright.reg, LOW_PART(left->data.intval.lo)); - } else { - emitpcode(PC_SUBFC, reg, opright.reg, opleft.reg); - } - if (is_uns) { - tmpreg1 = ALLOC_GPR(); - emitpcode(PC_LI, tmpreg1, 0); - emitpcode(PC_SUBFZE, regHi, tmpreg1); - } else { - emitpcode(PC_SUBFE, regHi, tmpreg1, tmpreg2); - } - break; - case 1 + 8: - case 2 + 8: - case 4 + 8: - if (skipleft < skipright) { - emitpcode(PC_SUBFC, reg, opright.reg, opleft.reg); - emitpcode(PC_SUBFE, regHi, opright.regHi, opleft.regHi); - } else { - if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo) && left->data.intval.hi == 0) { - emitpcode(PC_SUBFIC, reg, opright.reg, LOW_PART(left->data.intval.lo)); - } else { - emitpcode(PC_SUBFC, reg, opright.reg, opleft.reg); - } - tmpreg1 = ALLOC_GPR(); - emitpcode(PC_LI, tmpreg1, 0); - emitpcode(PC_SUBFE, regHi, tmpreg1, opleft.regHi); - } - break; - case 8 + 8: - emitpcode(PC_SUBFC, reg, opright.reg, opleft.reg); - emitpcode(PC_SUBFE, regHi, opright.regHi, opleft.regHi); - break; - default: - CError_FATAL(7211); - } - - output->optype = OpndType_GPRPair; - output->reg = reg; - output->regHi = regHi; -} - -void I8_gen_XOR(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *left; - ENode *right; - short reg; - short regHi; - Operand opleft; - Operand opright; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - - if (right->hascall) { - GEN_NODE(right, &opright); - coerce_to_register_pair(&opright, right->rtype, 0, 0); - - GEN_NODE(left, &opleft); - coerce_to_register_pair(&opleft, left->rtype, 0, 0); - } else { - GEN_NODE(left, &opleft); - coerce_to_register_pair(&opleft, left->rtype, 0, 0); - - GEN_NODE(right, &opright); - coerce_to_register_pair(&opright, right->rtype, 0, 0); - } - - CError_ASSERT(7254, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair); - - reg = outputReg ? outputReg : ALLOC_GPR(); - regHi = outputRegHi ? outputRegHi : ALLOC_GPR(); - - emitpcode(PC_XOR, reg, opleft.reg, opright.reg); - emitpcode(PC_XOR, regHi, opleft.regHi, opright.regHi); - - output->optype = OpndType_GPRPair; - output->reg = reg; - output->regHi = regHi; -} - -void I8_gen_OR(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *left; - ENode *right; - short reg; - short regHi; - Operand opleft; - Operand opright; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - - if (right->hascall) { - GEN_NODE(right, &opright); - coerce_to_register_pair(&opright, right->rtype, 0, 0); - - GEN_NODE(left, &opleft); - coerce_to_register_pair(&opleft, left->rtype, 0, 0); - } else { - GEN_NODE(left, &opleft); - coerce_to_register_pair(&opleft, left->rtype, 0, 0); - - GEN_NODE(right, &opright); - coerce_to_register_pair(&opright, right->rtype, 0, 0); - } - - CError_ASSERT(7304, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair); - - reg = outputReg ? outputReg : ALLOC_GPR(); - regHi = outputRegHi ? outputRegHi : ALLOC_GPR(); - - emitpcode(PC_OR, reg, opleft.reg, opright.reg); - emitpcode(PC_OR, regHi, opleft.regHi, opright.regHi); - - output->optype = OpndType_GPRPair; - output->reg = reg; - output->regHi = regHi; -} - -void I8_gen_AND(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *left; - ENode *right; - short reg; - short regHi; - Operand opleft; - Operand opright; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - - if (right->hascall) { - GEN_NODE(right, &opright); - coerce_to_register_pair(&opright, right->rtype, 0, 0); - - GEN_NODE(left, &opleft); - coerce_to_register_pair(&opleft, left->rtype, 0, 0); - } else { - GEN_NODE(left, &opleft); - coerce_to_register_pair(&opleft, left->rtype, 0, 0); - - GEN_NODE(right, &opright); - coerce_to_register_pair(&opright, right->rtype, 0, 0); - } - - CError_ASSERT(7354, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair); - - reg = outputReg ? outputReg : ALLOC_GPR(); - regHi = outputRegHi ? outputRegHi : ALLOC_GPR(); - - emitpcode(PC_AND, reg, opleft.reg, opright.reg); - emitpcode(PC_AND, regHi, opleft.regHi, opright.regHi); - - output->optype = OpndType_GPRPair; - output->reg = reg; - output->regHi = regHi; -} - -int I8_getbit(UInt64 val) { - switch (val) { - case 0: return -1; - case 1ULL << 0: return 0; - case 1ULL << 1: return 1; - case 1ULL << 2: return 2; - case 1ULL << 3: return 3; - case 1ULL << 4: return 4; - case 1ULL << 5: return 5; - case 1ULL << 6: return 6; - case 1ULL << 7: return 7; - case 1ULL << 8: return 8; - case 1ULL << 9: return 9; - case 1ULL << 10: return 10; - case 1ULL << 11: return 11; - case 1ULL << 12: return 12; - case 1ULL << 13: return 13; - case 1ULL << 14: return 14; - case 1ULL << 15: return 15; - case 1ULL << 16: return 16; - case 1ULL << 17: return 17; - case 1ULL << 18: return 18; - case 1ULL << 19: return 19; - case 1ULL << 20: return 20; - case 1ULL << 21: return 21; - case 1ULL << 22: return 22; - case 1ULL << 23: return 23; - case 1ULL << 24: return 24; - case 1ULL << 25: return 25; - case 1ULL << 26: return 26; - case 1ULL << 27: return 27; - case 1ULL << 28: return 28; - case 1ULL << 29: return 29; - case 1ULL << 30: return 30; - case 1ULL << 31: return 31; - case 1ULL << 32: return 32; - case 1ULL << 33: return 33; - case 1ULL << 34: return 34; - case 1ULL << 35: return 35; - case 1ULL << 36: return 36; - case 1ULL << 37: return 37; - case 1ULL << 38: return 38; - case 1ULL << 39: return 39; - case 1ULL << 40: return 40; - case 1ULL << 41: return 41; - case 1ULL << 42: return 42; - case 1ULL << 43: return 43; - case 1ULL << 44: return 44; - case 1ULL << 45: return 45; - case 1ULL << 46: return 46; - case 1ULL << 47: return 47; - case 1ULL << 48: return 48; - case 1ULL << 49: return 49; - case 1ULL << 50: return 50; - case 1ULL << 51: return 51; - case 1ULL << 52: return 52; - case 1ULL << 53: return 53; - case 1ULL << 54: return 54; - case 1ULL << 55: return 55; - case 1ULL << 56: return 56; - case 1ULL << 57: return 57; - case 1ULL << 58: return 58; - case 1ULL << 59: return 59; - case 1ULL << 60: return 60; - case 1ULL << 61: return 61; - case 1ULL << 62: return 62; - case 1ULL << 63: return 63; - default: return -2; - } -} - -int I8_log2n(UInt64 val) { - int bit = I8_getbit(val); - return (bit > 0 && bit < 63) ? bit : 0; -} - -void I8_ShiftLeftImmediate(Operand opnd, SInt32 value, int is_unsigned, SInt32 size, short reg, short regHi) { - if (opnd.reg == reg || opnd.regHi == regHi || opnd.reg == regHi || opnd.regHi == reg) - CError_FATAL(7703); - - if (value < 32) { - emitpcode(PC_RLWINM, reg, opnd.reg, value, 0, 31 - value); - if (size > 4) { - emitpcode(PC_RLWINM, regHi, opnd.regHi, value, 0, 31 - value); - emitpcode(PC_RLWIMI, regHi, opnd.reg, value, 32 - value, 31); - } else { - emitpcode(PC_RLWINM, regHi, opnd.reg, value, 32 - value, 31); - } - } else if (value <= 63) { - if (value == 32) - emitpcode(PC_MR, regHi, opnd.reg); - else - emitpcode(PC_RLWINM, regHi, opnd.reg, value - 32, 0, 63 - value); - emitpcode(PC_LI, reg, 0); - } else { - CError_FATAL(7732); - } -} - -void I8_ShiftRightImmediate(Operand opnd, SInt32 value, int is_unsigned, short reg, short regHi, int unk) { - short tmpreg1; - short tmpreg2; - short tmpreg3; - short tmpreg4; - - if (opnd.reg == reg || opnd.regHi == regHi || opnd.reg == regHi || opnd.regHi == reg) - CError_FATAL(7756); - - if (value < 32) { - emitpcode(PC_RLWINM, reg, opnd.reg, 32 - value, 0, 31); - emitpcode(PC_RLWIMI, reg, opnd.regHi, 32 - value, 0, value - 1); - if (is_unsigned) { - emitpcode(PC_RLWINM, regHi, opnd.regHi, 32 - value, value, 31); - } else if (unk) { - tmpreg1 = ALLOC_GPR(); - emitpcode(PC_MR, tmpreg1, opnd.regHi); - emitpcode(PC_RLWIMI, tmpreg1, opnd.reg, 0, 31 - (value - 1), 31); - emitpcode(PC_SRAWI, regHi, tmpreg1, value); - } else { - emitpcode(PC_SRAWI, regHi, opnd.regHi, value); - } - } else if (value == 32) { - if (is_unsigned) { - emitpcode(PC_MR, reg, opnd.regHi); - emitpcode(PC_LI, regHi, 0); - } else if (unk) { - tmpreg1 = ALLOC_GPR(); - tmpreg2 = ALLOC_GPR(); - tmpreg3 = ALLOC_GPR(); - emitpcode(PC_NEG, tmpreg1, opnd.reg); - emitpcode(PC_OR, tmpreg2, tmpreg1, opnd.reg); - emitpcode(PC_RLWINM, tmpreg3, tmpreg2, 1, 31, 31); - emitpcode(PC_RLWIMI, tmpreg3, opnd.regHi, 0, 0, 0); - emitpcode(PC_MR, reg, opnd.regHi); - emitpcode(PC_SRAWI, regHi, value, 31); - } else { - emitpcode(PC_MR, reg, opnd.regHi); - emitpcode(PC_SRAWI, regHi, opnd.regHi, 31); - } - } else if (value <= 63) { - if (is_unsigned) { - emitpcode(PC_RLWINM, reg, opnd.regHi, 64 - value, value - 32, 31); - emitpcode(PC_LI, regHi, 0); - } else if (unk) { - tmpreg1 = ALLOC_GPR(); - tmpreg2 = ALLOC_GPR(); - tmpreg3 = ALLOC_GPR(); - tmpreg4 = ALLOC_GPR(); - emitpcode(PC_NEG, tmpreg1, opnd.reg); - emitpcode(PC_OR, tmpreg2, tmpreg1, opnd.reg); - emitpcode(PC_RLWINM, tmpreg3, tmpreg2, 1, 31, 31); - emitpcode(PC_OR, tmpreg4, opnd.regHi, tmpreg3); - emitpcode(PC_SRAWI, regHi, opnd.regHi, 31); - emitpcode(PC_SRAWI, reg, tmpreg4, value - 32); - } else { - emitpcode(PC_SRAWI, reg, opnd.regHi, value - 32); - emitpcode(PC_SRAWI, regHi, opnd.regHi, 31); - } - } else { - CError_FATAL(7866); - } -} - -void I8_gen_MUL(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - int is_uns; - ENode *left; - ENode *right; - short reg; - short regHi; - short tmpreg1; - short tmpreg2; - short tmpreg3; - short tmpreg4; - SInt32 skipleft; - SInt32 skipright; - Operand opleft; - Operand opright; - SInt64 leftval; - SInt64 rightval; - int shift; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - skipleft = GetSizeSkip(left); - skipright = GetSizeSkip(right); - - if (ENODE_IS(right, EINTCONST) && ENODE_IS(left, EINTCONST)) - CError_FATAL(7900); - - if (ENODE_IS(left, EINTCONST)) - leftval = left->data.intval.lo + (((SInt64) ((skipleft < 8) ? 0 : left->data.intval.hi)) << 32); - if (ENODE_IS(right, EINTCONST)) - rightval = right->data.intval.lo + (((SInt64) ((skipright < 8) ? 0 : right->data.intval.hi)) << 32); - - if (right->hascall) { - GEN_NODE(right, &opright); - if (TYPE_IS_8BYTES(right->rtype)) - coerce_to_register_pair(&opright, right->rtype, 0, 0); - else - ENSURE_GPR(&opright, right->rtype, 0); - - if (!(ENODE_IS(left, EINTCONST) && I8_log2n(leftval) > 0)) { - GEN_NODE(left, &opleft); - if (TYPE_IS_8BYTES(left->rtype)) - coerce_to_register_pair(&opleft, left->rtype, 0, 0); - else - ENSURE_GPR(&opleft, left->rtype, 0); - } - } else { - if (!(ENODE_IS(left, EINTCONST) && I8_log2n(leftval) > 0)) { - GEN_NODE(left, &opleft); - if (TYPE_IS_8BYTES(left->rtype)) - coerce_to_register_pair(&opleft, left->rtype, 0, 0); - else - ENSURE_GPR(&opleft, left->rtype, 0); - } - - if (!(ENODE_IS(right, EINTCONST) && I8_log2n(rightval) > 0)) { - GEN_NODE(right, &opright); - if (TYPE_IS_8BYTES(right->rtype)) - coerce_to_register_pair(&opright, right->rtype, 0, 0); - else - ENSURE_GPR(&opright, right->rtype, 0); - } - } - - is_uns = is_unsigned(expr->rtype) != 0; - - if (skipleft < skipright) { - Operand tmpop; - SInt64 tmp64; - SInt32 tmp; - - expr->data.diadic.left = right; - expr->data.diadic.right = left; - left = expr->data.diadic.left; - right = expr->data.diadic.right; - - tmpop = opright; - opright = opleft; - opleft = tmpop; - - tmp64 = leftval; - leftval = rightval; - rightval = tmp64; - - tmp = skipleft; - skipleft = skipright; - skipright = tmp; - } - - reg = ALLOC_GPR(); - regHi = ALLOC_GPR(); - - if (ENODE_IS(left, EINTCONST) && (shift = I8_log2n(leftval)) > 0) { - I8_ShiftLeftImmediate(opright, shift, is_uns, skipright, reg, regHi); - } else if (ENODE_IS(right, EINTCONST) && (shift = I8_log2n(rightval)) > 0) { - I8_ShiftLeftImmediate(opleft, shift, is_uns, skipleft, reg, regHi); - } else { - switch (skipleft + skipright) { - case 1 + 1: - case 1 + 2: - case 2 + 2: - if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) { - emitpcode(PC_MULLI, reg, opright.reg, LOW_PART(left->data.intval.lo)); - } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo)) { - emitpcode(PC_MULLI, reg, opleft.reg, LOW_PART(right->data.intval.lo)); - } else { - emitpcode(PC_MULLW, reg, opleft.reg, opright.reg); - } - if (is_uns) - emitpcode(PC_LI, regHi, 0); - else - emitpcode(PC_SRAWI, regHi, reg, 31); - break; - case 1 + 4: - case 2 + 4: - case 4 + 4: - if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) { - emitpcode(PC_MULLI, reg, opright.reg, LOW_PART(left->data.intval.lo)); - } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo)) { - emitpcode(PC_MULLI, reg, opleft.reg, LOW_PART(right->data.intval.lo)); - } else { - emitpcode(PC_MULLW, reg, opleft.reg, opright.reg); - } - if (is_uns) - emitpcode(PC_MULHWU, regHi, opleft.reg, opright.reg); - else - emitpcode(PC_MULHW, regHi, opleft.reg, opright.reg); - break; - case 1 + 8: - case 2 + 8: - case 4 + 8: - CError_ASSERT(8097, skipleft == 8); - if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo) && left->data.intval.hi == 0) { - emitpcode(PC_MULLI, reg, opright.reg, LOW_PART(left->data.intval.lo)); - if (is_uns) - emitpcode(PC_MULHWU, regHi, opright.reg, opleft.reg); - else - emitpcode(PC_MULHW, regHi, opright.reg, opleft.reg); - } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo) && right->data.intval.hi == 0) { - tmpreg1 = ALLOC_GPR(); - tmpreg2 = ALLOC_GPR(); - if (is_uns) { - emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg); - emitpcode(PC_MULLI, tmpreg1, opleft.regHi, LOW_PART(right->data.intval.lo)); - emitpcode(PC_MULLI, reg, opleft.reg, LOW_PART(right->data.intval.lo)); - emitpcode(PC_ADD, regHi, tmpreg2, tmpreg1); - } else { - tmpreg3 = ALLOC_GPR(); - tmpreg4 = ALLOC_GPR(); - emitpcode(PC_SRAWI, tmpreg4, opright.reg, 31); - emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg); - emitpcode(PC_MULLI, tmpreg1, opleft.regHi, LOW_PART(right->data.intval.lo)); - emitpcode(PC_MULLI, reg, opleft.reg, LOW_PART(right->data.intval.lo)); - emitpcode(PC_MULLW, tmpreg3, opleft.reg, tmpreg4); - emitpcode(PC_ADD, regHi, tmpreg2, tmpreg1); - emitpcode(PC_ADD, regHi, regHi, tmpreg3); - } - } else { - tmpreg1 = ALLOC_GPR(); - tmpreg2 = ALLOC_GPR(); - if (is_uns) { - emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg); - emitpcode(PC_MULLW, tmpreg1, opleft.regHi, opright.reg); - emitpcode(PC_MULLW, reg, opleft.reg, opright.reg); - emitpcode(PC_ADD, regHi, tmpreg2, tmpreg1); - } else { - tmpreg3 = ALLOC_GPR(); - tmpreg4 = ALLOC_GPR(); - emitpcode(PC_SRAWI, tmpreg4, opright.reg, 31); - emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg); - emitpcode(PC_MULLW, tmpreg1, opleft.regHi, opright.reg); - emitpcode(PC_MULLW, reg, opleft.reg, opright.reg); - emitpcode(PC_MULLW, tmpreg3, opleft.reg, tmpreg4); - emitpcode(PC_ADD, regHi, tmpreg2, tmpreg1); - emitpcode(PC_ADD, regHi, regHi, tmpreg3); - } - } - break; - case 8 + 8: - if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo) && left->data.intval.hi == 0) { - tmpreg1 = ALLOC_GPR(); - tmpreg2 = ALLOC_GPR(); - emitpcode(PC_MULHWU, tmpreg1, opright.reg, opleft.reg); - emitpcode(PC_MULLW, tmpreg2, opright.reg, opleft.regHi); - emitpcode(PC_MULLI, reg, opright.reg, LOW_PART(left->data.intval.lo)); - emitpcode(PC_ADD, regHi, tmpreg1, tmpreg2); - } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo) && right->data.intval.hi == 0) { - tmpreg1 = ALLOC_GPR(); - tmpreg2 = ALLOC_GPR(); - emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg); - emitpcode(PC_MULLW, tmpreg1, opleft.regHi, opright.reg); - emitpcode(PC_MULLI, reg, opleft.reg, LOW_PART(right->data.intval.lo)); - emitpcode(PC_ADD, regHi, tmpreg2, tmpreg1); - } else { - tmpreg1 = ALLOC_GPR(); - tmpreg2 = ALLOC_GPR(); - tmpreg3 = ALLOC_GPR(); - tmpreg4 = ALLOC_GPR(); - emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg); - emitpcode(PC_MULLW, tmpreg1, opleft.regHi, opright.reg); - emitpcode(PC_ADD, tmpreg3, tmpreg2, tmpreg1); - emitpcode(PC_MULLW, tmpreg4, opleft.reg, opright.regHi); - emitpcode(PC_MULLW, reg, opleft.reg, opright.reg); - emitpcode(PC_ADD, regHi, tmpreg3, tmpreg4); - } - break; - default: - CError_FATAL(8218); - } - } - - output->optype = OpndType_GPRPair; - output->reg = reg; - output->regHi = regHi; -} - -void I8_gen_BINNOT(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *inner; - Operand op; - int reg; - int regHi; - - inner = expr->data.monadic; - memclrw(&op, sizeof(Operand)); - GEN_NODE(inner, &op); - coerce_to_register_pair(&op, inner->rtype, 0, 0); - - reg = outputReg ? outputReg : ALLOC_GPR(); - regHi = outputRegHi ? outputRegHi : ALLOC_GPR(); - emitpcode(PC_NOR, reg, op.reg, op.reg); - emitpcode(PC_NOR, regHi, op.regHi, op.regHi); - - output->optype = OpndType_GPRPair; - output->reg = reg; - output->regHi = regHi; -} - -void I8_gen_MONMIN(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *inner; - Operand op; - int reg; - int regHi; - - inner = expr->data.monadic; - memclrw(&op, sizeof(Operand)); - GEN_NODE(inner, &op); - coerce_to_register_pair(&op, inner->rtype, 0, 0); - - reg = outputReg ? outputReg : ALLOC_GPR(); - regHi = outputRegHi ? outputRegHi : ALLOC_GPR(); - emitpcode(PC_SUBFIC, reg, op.reg, 0); - emitpcode(PC_SUBFZE, regHi, op.regHi); - - output->optype = OpndType_GPRPair; - output->reg = reg; - output->regHi = regHi; -} - -void I8_gen_ASS(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - Type *type; - ENode *left; - ENode *right; - Operand opleft; - Operand opright; - VarInfo *vi; - - type = expr->rtype; - if (ENODE_IS(expr, ECONDASS)) { - left = expr->data.cond.expr1; - if (ENODE_IS(left, EINDIRECT)) - left = left->data.monadic; - else - CError_FATAL(8328); - right = expr->data.cond.expr2; - } else { - left = expr->data.diadic.left; - right = expr->data.diadic.right; - } - - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - - if (ENODE_IS(left, EOBJREF) && OBJECT_REG(left->data.objref)) { - vi = Registers_GetVarInfo(left->data.objref); - GEN_NODE_TO_REG(right, vi->reg, vi->regHi, &opright); - if (vi->rclass != RegClass_GPR) { - CError_FATAL(8348); - } else { - coerce_to_register_pair(&opright, type, vi->reg, vi->regHi); - *output = opright; - } - return; - } - - if (TYPE_FITS_IN_REGISTER(type)) { - GEN_NODE(right, &opright); - coerce_to_register_pair(&opright, right->rtype, 0, 0); - - if (ENODE_IS(left, EBITFIELD)) { - CError_FATAL(8376); - } else { - GEN_NODE(left, &opleft); - indirect(&opleft, left); - store_pair(opright.reg, opright.regHi, &opleft, type); - } - - output->optype = OpndType_GPRPair; - output->reg = opright.reg; - output->regHi = opright.regHi; - } -} - -void I8_gen_POSTINCDEC(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *inner; - Type *type; - int flag; - int reg; - int regHi; - Operand op1; - Operand op2; - Operand op3; - - inner = expr->data.monadic->data.monadic; - type = expr->rtype; - flag = 0; - memclrw(&op1, sizeof(Operand)); - memclrw(&op2, sizeof(Operand)); - - if (ENODE_IS(inner, EOBJREF) && (reg = OBJECT_REG(inner->data.objref))) { - regHi = Registers_GetVarInfo(inner->data.objref)->regHi; - output->optype = OpndType_GPRPair; - output->reg = (outputReg && outputReg != reg && outputReg != regHi) ? outputReg : ALLOC_GPR(); - output->regHi = (outputRegHi && outputRegHi != regHi && outputRegHi != reg) ? outputRegHi : ALLOC_GPR(); - emitpcode(PC_MR, output->reg, reg); - emitpcode(PC_MR, output->regHi, regHi); - if (ENODE_IS(expr, EPOSTINC)) { - emitpcode(PC_ADDIC, reg, reg, 1); - emitpcode(PC_ADDME, regHi, regHi); - } else { - emitpcode(PC_ADDIC, reg, reg, -1); - emitpcode(PC_ADDZE, regHi, regHi); - } - return; - } - - CError_ASSERT(8446, !ENODE_IS(inner, EBITFIELD)); - - GEN_NODE(inner, &op1); - indirect(&op1, inner); - op2 = op1; - coerce_to_register_pair(&op2, type, 0, 0); - - output->optype = OpndType_GPRPair; - output->reg = ALLOC_GPR(); - output->regHi = ALLOC_GPR(); - - emitpcode(PC_MR, output->reg, op2.reg); - emitpcode(PC_MR, output->regHi, op2.regHi); - - reg = ALLOC_GPR(); - regHi = ALLOC_GPR(); - - if (ENODE_IS(expr, EPOSTINC)) { - emitpcode(PC_ADDIC, reg, op2.reg, 1); - emitpcode(PC_ADDZE, regHi, op2.regHi); - } else { - emitpcode(PC_ADDIC, reg, op2.reg, -1); - emitpcode(PC_ADDME, regHi, op2.regHi); - } - store_pair(reg, regHi, &op1, type); -} - -void I8_gen_INDIRECT(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - ENode *inner; - VarInfo *vi; - - inner = expr->data.monadic; - if (ENODE_IS(inner, EOBJREF) && OBJECT_REG(inner->data.objref)) { - vi = Registers_GetVarInfo(inner->data.objref); - switch (vi->rclass) { - case RegClass_GPR: - output->optype = OpndType_GPRPair; - break; - case RegClass_FPR: - output->optype = OpndType_FPR; - break; - default: - CError_FATAL(8511); - } - - output->reg = vi->reg; - output->regHi = vi->regHi; - output->object = NULL; - return; - } - - if (ENODE_IS(inner, EBITFIELD)) { - CError_FATAL(8529); - return; - } - - GEN_NODE(inner, output); - indirect(output, inner); -} - -void I8_gen_condition(ENode *cond, Operand *output, int write_to_gpr) { - ENode *left; - ENode *right; - Operand opleft; - Operand opright; - Operand tmpop; - int reg1; - int reg2; - int reg3; - int reg4; - int reg5; - - left = cond->data.diadic.left; - right = cond->data.diadic.right; - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - memclrw(&tmpop, sizeof(Operand)); - - if (right->hascall) { - GEN_NODE(right, &opright); - if (right->rtype->size < 4) - extend32(&opright, right->rtype, 0); - ENSURE_GPR(&opright, right->rtype, 0); - - if (right->rtype->size < 8) { - short tmp = ALLOC_GPR(); - if (is_unsigned(right->rtype)) - load_immediate(tmp, 0); - else - emitpcode(PC_SRAWI, tmp, opright.reg, 31); - opright.optype = OpndType_GPRPair; - opright.regHi = tmp; - } - - GEN_NODE(left, &opleft); - if (left->rtype->size < 4) - extend32(&opleft, left->rtype, 0); - ENSURE_GPR(&opleft, left->rtype, 0); - - if (left->rtype->size < 8) { - short tmp = ALLOC_GPR(); - // this looks like a bug??? surely this should check left->rtype - if (is_unsigned(right->rtype)) - load_immediate(tmp, 0); - else - emitpcode(PC_SRAWI, tmp, opleft.reg, 31); - opleft.optype = OpndType_GPRPair; - opleft.regHi = tmp; - } - } else { - GEN_NODE(left, &opleft); - ENSURE_GPR(&opleft, left->rtype, 0); - if (left->rtype->size < 4) - extend32(&opleft, left->rtype, 0); - - if (left->rtype->size < 8) { - short tmp = ALLOC_GPR(); - if (is_unsigned(right->rtype)) - load_immediate(tmp, 0); - else - emitpcode(PC_SRAWI, tmp, opleft.reg, 31); - opleft.optype = OpndType_GPRPair; - opleft.regHi = tmp; - } - - GEN_NODE(right, &opright); - if (right->rtype->size < 4) - extend32(&opright, right->rtype, 0); - ENSURE_GPR(&opright, right->rtype, 0); - - if (right->rtype->size < 8) { - short tmp = ALLOC_GPR(); - if (is_unsigned(right->rtype)) - load_immediate(tmp, 0); - else - emitpcode(PC_SRAWI, tmp, opright.reg, 31); - opright.optype = OpndType_GPRPair; - opright.regHi = tmp; - } - } - - CError_ASSERT(8704, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair); - - switch (cond->type) { - case EEQU: - case ENOTEQU: - reg1 = ALLOC_GPR(); - reg2 = ALLOC_GPR(); - emitpcode(PC_XOR, reg1, opleft.reg, opright.reg); - emitpcode(PC_XOR, reg2, opleft.regHi, opright.regHi); - emitpcode(PC_OR, reg2, reg1, reg2); - if (write_to_gpr) { - if (ENODE_IS(cond, EEQU)) { - emitpcode(PC_CNTLZW, reg2, reg2); - emitpcode(PC_RLWINM, reg2, reg2, 27, 5, 31); - } else { - emitpcode(PC_ADDIC, reg1, reg2, -1); - emitpcode(PC_SUBFE, reg2, reg1, reg2); - } - output->optype = OpndType_GPR; - output->reg = reg2; - output->regHi = 0; - } else { - emitpcode(PC_CMPI, 0, reg2, 0); - output->optype = OpndType_CRField; - output->reg = 0; - output->regOffset = cond->type; - } - break; - case EGREATER: - tmpop = opleft; - opleft = opright; - opright = tmpop; - case ELESS: - reg1 = ALLOC_GPR(); - reg2 = ALLOC_GPR(); - reg3 = ALLOC_GPR(); - if (left->rtype != TYPE(&stunsignedlonglong) && right->rtype != TYPE(&stunsignedlonglong)) { - emitpcode(PC_XORIS, reg1, opleft.regHi, 0x8000); - emitpcode(PC_XORIS, reg2, opright.regHi, 0x8000); - reg4 = reg1; - reg5 = reg2; - } else { - reg4 = opleft.regHi; - reg5 = opright.regHi; - } - emitpcode(PC_SUBFC, reg3, opright.reg, opleft.reg); - emitpcode(PC_SUBFE, reg2, reg5, reg4); - emitpcode(PC_SUBFE, reg2, reg1, reg1); - emitpcode(PC_NEG, reg2, reg2); - if (write_to_gpr) { - output->optype = OpndType_GPR; - output->reg = reg2; - output->regHi = 0; - } else { - emitpcode(PC_CMPI, 0, reg2, 0); - output->optype = OpndType_CRField; - output->reg = 0; - output->regOffset = ENOTEQU; - } - break; - case ELESSEQU: - tmpop = opleft; - opleft = opright; - opright = tmpop; - case EGREATEREQU: - reg1 = ALLOC_GPR(); - reg2 = ALLOC_GPR(); - reg3 = ALLOC_GPR(); - if (left->rtype != TYPE(&stunsignedlonglong) && right->rtype != TYPE(&stunsignedlonglong)) { - emitpcode(PC_XORIS, reg1, opleft.regHi, 0x8000); - emitpcode(PC_XORIS, reg2, opright.regHi, 0x8000); - reg4 = reg1; - reg5 = reg2; - } else { - reg4 = opleft.regHi; - reg5 = opright.regHi; - } - emitpcode(PC_SUBFC, reg3, opright.reg, opleft.reg); - emitpcode(PC_SUBFE, reg2, reg5, reg4); - emitpcode(PC_SUBFE, reg2, reg1, reg1); - emitpcode(PC_NEG, reg2, reg2); - if (write_to_gpr) { - emitpcode(PC_SUBFIC, reg2, reg2, 1); - output->optype = OpndType_GPR; - output->reg = reg2; - output->regHi = 0; - } else { - emitpcode(PC_CMPI, 0, reg2, 0); - output->optype = OpndType_CRField; - output->reg = 0; - output->regOffset = EEQU; - } - break; - default: - CError_FATAL(8814); - } -} - -void I8_gen_SHL_SHR(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - static UInt32 used_regs[RegClassMax] = {0, 0, 0, 0, (1 << 3) | (1 << 4) | (1 << 5)}; - - ENode *left; - ENode *right; - Operand opleft; - Operand opright; - int is_uns; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - - GEN_NODE(left, &opleft); - coerce_to_register_pair(&opleft, left->rtype, 0, 0); - - output->optype = OpndType_GPRPair; - output->reg = ALLOC_GPR(); - output->regHi = ALLOC_GPR(); - - is_uns = is_unsigned(expr->rtype) != 0; - - if (ENODE_IS(right, EINTCONST)) { - if (ENODE_IS(expr, ESHL)) { - I8_ShiftLeftImmediate(opleft, right->data.intval.lo, is_uns, expr->rtype->size, output->reg, output->regHi); - } else { - I8_ShiftRightImmediate(opleft, right->data.intval.lo, is_uns, output->reg, output->regHi, 0); - } - return; - } - - GEN_NODE(right, &opright); - ENSURE_GPR(&opright, right->rtype, 0); - if (opright.optype == OpndType_GPRPair) { - opright.regHi = 0; - opright.optype = OpndType_GPR; - } - - CError_ASSERT(8890, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPR); - - if (opleft.regHi != high_reg) - emitpcode(PC_MR, high_reg, opleft.regHi); - if (opleft.reg != low_reg) - emitpcode(PC_MR, low_reg, opleft.reg); - if (opright.reg != 5) - emitpcode(PC_MR, 5, opright.reg); - - if (ENODE_IS(expr, ESHR)) { - if (is_unsigned(left->rtype)) - branch_subroutine(rt_shr2u, 0, used_regs); - else - branch_subroutine(rt_shr2i, 0, used_regs); - } else if (ENODE_IS(expr, ESHL)) { - branch_subroutine(rt_shl2i, 0, used_regs); - } else { - CError_FATAL(8909); - } - - emitpcode(PC_MR, output->reg, low_reg); - emitpcode(PC_MR, output->regHi, high_reg); -} - -void I8_gen_DIV_MOD(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - static UInt32 used_regs[RegClassMax] = {0, 0, 0, 0, (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6)}; - - int is_uns; - ENode *left; - ENode *right; - Operand opleft; - Operand opright; - SInt64 constval; - int shift; - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - memclrw(&opleft, sizeof(Operand)); - memclrw(&opright, sizeof(Operand)); - - GEN_NODE(left, &opleft); - coerce_to_register_pair(&opleft, left->rtype, 0, 0); - - output->optype = OpndType_GPRPair; - output->reg = ALLOC_GPR(); - output->regHi = ALLOC_GPR(); - - is_uns = is_unsigned(expr->rtype) != 0; - - if (ENODE_IS(right, EINTCONST)) - constval = (((SInt64) right->data.intval.hi) << 32) + right->data.intval.lo; - if (ENODE_IS(right, EINTCONST) && ((shift = I8_log2n(constval)) > 0)) { - CError_ASSERT(8976, opleft.optype == OpndType_GPRPair); - if (ENODE_IS(expr, EDIV)) { - I8_ShiftRightImmediate(opleft, shift, is_uns, output->reg, output->regHi, 1); - if (!is_uns) { - emitpcode(PC_ADDZE, output->reg, output->reg); - emitpcode(PC_ADDZE, output->regHi, output->regHi); - } - } else { - if (is_uns) { - if (shift < 32) { - emitpcode(PC_LI, output->regHi, 0); - emitpcode(PC_RLWINM, output->reg, opleft.reg, 0, 32 - shift, 31); - } else if (shift == 32) { - emitpcode(PC_LI, output->regHi, 0); - emitpcode(PC_MR, output->reg, opleft.reg); - } else if (shift <= 63) { - emitpcode(PC_RLWINM, output->regHi, opleft.regHi, 0, 32 - (shift - 32), 31); - emitpcode(PC_MR, output->reg, opleft.reg); - } else { - CError_FATAL(9018); - } - } else { - short tmpreg1 = ALLOC_GPR(); - short tmpreg2 = ALLOC_GPR(); - I8_ShiftRightImmediate(opleft, shift, is_uns, output->reg, output->regHi, 1); - emitpcode(PC_ADDZE, output->reg, output->reg); - emitpcode(PC_ADDZE, output->regHi, output->regHi); - I8_ShiftLeftImmediate(*output, shift, is_uns, expr->rtype->size, tmpreg1, tmpreg2); - emitpcode(PC_SUBFC, output->reg, tmpreg1, opleft.reg); - emitpcode(PC_SUBFE, output->regHi, tmpreg2, opleft.regHi); - } - } - return; - } - - GEN_NODE(right, &opright); - coerce_to_register_pair(&opright, right->rtype, 0, 0); - - CError_ASSERT(9048, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair); - - if (opleft.regHi != high_reg) - emitpcode(PC_MR, high_reg, opleft.regHi); - if (opleft.reg != low_reg) - emitpcode(PC_MR, low_reg, opleft.reg); - if (opright.regHi != high_reg2) - emitpcode(PC_MR, high_reg2, opright.regHi); - if (opright.reg != low_reg2) - emitpcode(PC_MR, low_reg2, opright.reg); - - if (ENODE_IS(expr, EDIV)) { - if (is_unsigned(left->rtype) || is_unsigned(right->rtype)) - branch_subroutine(rt_div2u, 0, used_regs); - else - branch_subroutine(rt_div2i, 0, used_regs); - } else if (ENODE_IS(expr, EMODULO)) { - if (is_unsigned(left->rtype) || is_unsigned(right->rtype)) - branch_subroutine(rt_mod2u, 0, used_regs); - else - branch_subroutine(rt_mod2i, 0, used_regs); - } else { - CError_FATAL(9074); - } - - emitpcode(PC_MR, output->reg, low_reg); - emitpcode(PC_MR, output->regHi, high_reg); -} - -void I8_gen_TYPCON(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - Type *dsttype; - ENode *inner; - Type *srctype; - short regHi; - short reg; - - static UInt32 used_regs[RegClassMax] = {0, 0, 0, 0, (1 << 3) | (1 << 4)}; - static UInt32 used_regs_f1[RegClassMax] = {0, 0, 0, (1 << 1), 0}; - - inner = expr->data.monadic; - srctype = inner->rtype; - dsttype = expr->rtype; - - if (IS_TYPE_VOID(dsttype)) { - GEN_NODE(inner, output); - if (ENODE_IS(inner, EINDIRECT) && (output->flags & OpndFlags_Volatile)) - coerce_to_register_pair(output, inner->rtype, 0, 0); - output->optype = OpndType_Absolute; - output->immediate = 0; - return; - } - - if (IS_TYPE_INT_OR_ENUM(srctype)) { - if (IS_TYPE_FLOAT(dsttype)) { - GEN_NODE(inner, output); - coerce_to_register_pair(output, srctype, 0, 0); - if (output->regHi != high_reg) - emitpcode(PC_MR, high_reg, output->regHi); - if (output->reg != low_reg) - emitpcode(PC_MR, low_reg, output->reg); - - if (is_unsigned(srctype)) { - branch_subroutine( - (dsttype->size == 4) ? rt_cvt_ull_flt : rt_cvt_ull_dbl, - 0, - used_regs); - } else { - branch_subroutine( - (dsttype->size == 4) ? rt_cvt_sll_flt : rt_cvt_sll_dbl, - 0, - used_regs); - } - - output->optype = OpndType_FPR; - output->reg = ALLOC_FPR(); - emitpcode(PC_FMR, output->reg, 1); - return; - } - - if (srctype->size < dsttype->size) { - CError_ASSERT(9171, TYPE_IS_8BYTES(dsttype)); - - GEN_NODE(inner, output); - if (srctype->size < 4 && - !ENODE_IS_INDIRECT_TO(inner, EBITFIELD) && - !((ENODE_IS_ASSIGN(inner) || ENODE_IS_RANGE(inner, EPOSTINC, EPREDEC)) && ENODE_IS(inner->data.monadic->data.monadic, EBITFIELD)) - ) { - extend32(output, srctype, outputReg); - } - extend64(output, srctype, outputReg, outputRegHi); - } else { - GEN_NODE_TO_REG(inner, outputReg, 0, output); - if (dsttype->size < srctype->size) { - coerce_to_register_pair(output, srctype, outputReg, outputRegHi); - output->optype = OpndType_GPR; - output->regHi = 0; - } - } - return; - } - - if (IS_TYPE_POINTER(srctype)) { - GEN_NODE_TO_REG(inner, outputReg, 0, output); - CError_ASSERT(9200, TYPE_IS_8BYTES(expr->rtype)); - GEN_NODE_TO_REG(inner, outputReg, 0, output); - - regHi = outputRegHi ? outputRegHi : ALLOC_GPR(); - if (regHi == output->reg) { - reg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_MR, reg, output->reg); - output->reg = reg; - } - if (is_unsigned(inner->rtype)) - load_immediate(regHi, 0); - else - emitpcode(PC_SRAWI, regHi, output->reg, 31); - output->optype = OpndType_GPRPair; - output->regHi = regHi; - return; - } - - if (IS_TYPE_FLOAT(srctype)) { - if (IS_TYPE_FLOAT(dsttype)) { - CError_FATAL(9222); - return; - } - - GEN_NODE(inner, output); - ENSURE_FPR(output, srctype, 0); - if (output->reg != 1) - emitpcode(PC_FMR, 1, output->reg); - - branch_subroutine(rt_cvt_dbl_usll, 0, used_regs_f1); - - output->optype = OpndType_GPRPair; - output->reg = ALLOC_GPR(); - output->regHi = ALLOC_GPR(); - emitpcode(PC_MR, output->reg, low_reg); - emitpcode(PC_MR, output->regHi, high_reg); - return; - } - - if (IS_TYPE_STRUCT(srctype)) { - GEN_NODE_TO_REG(inner, outputReg, 0, output); - - if (TYPE_IS_8BYTES(expr->rtype) && dsttype->size == srctype->size) { - coerce_to_register_pair(output, srctype, outputReg, outputRegHi); - } else { - CError_FATAL(9256); - } - return; - } - - CError_FATAL(9261); -} - -void gen_VECTOR128CONST(ENode *expr, short outputReg, short outputRegHi, Operand *output) { - int gpr; - int vr; - COVCResult result; - - vr = outputReg ? outputReg : ALLOC_VR(); - if (!canoptimizevectorconst(&expr->data.vector128val, expr->rtype, &result)) - CError_FATAL(9282); - - if (result.op1 != -1) { - emitpcode(result.op1, vr, result.arg); - output->optype = OpndType_VR; - output->reg = vr; - return; - } - - if (result.op2 != -1) { - gpr = ALLOC_GPR(); - emitpcode(PC_LI, gpr, result.arg); - emitpcode(result.op2, vr, 0, gpr); - output->optype = OpndType_VR; - output->reg = vr; - return; - } - - CError_FATAL(9298); -} diff --git a/compiler_and_linker/unsorted/InterferenceGraph.c b/compiler_and_linker/unsorted/InterferenceGraph.c deleted file mode 100644 index d589502..0000000 --- a/compiler_and_linker/unsorted/InterferenceGraph.c +++ /dev/null @@ -1,364 +0,0 @@ -#include "compiler/InterferenceGraph.h" -#include "compiler/CError.h" -#include "compiler/CParser.h" -#include "compiler/BitVectors.h" -#include "compiler/Coloring.h" -#include "compiler/LiveInfo.h" -#include "compiler/PCode.h" -#include "compiler/PCodeListing.h" -#include "compiler/PCodeUtilities.h" -#include "compiler/Registers.h" -#include "compiler/RegisterInfo.h" -#include "compiler/CompilerTools.h" - -IGNode **interferencegraph; -static UInt32 *interferencematrix; -Boolean coalesced_nregisters; -static SInt16 *coalesced; - -static void makeinterfere(UInt32 a, UInt32 b) { - if (a < b) - bitvectorsetbit(((b * b) / 2) + a, interferencematrix); - else if (a > b) - bitvectorsetbit(((a * a) / 2) + b, interferencematrix); -} - -int interferes(UInt32 a, UInt32 b) { - if (a < b) - return bitvectorgetbit(((b * b) / 2) + a, interferencematrix) > 0; - else if (a > b) - return bitvectorgetbit(((a * a) / 2) + b, interferencematrix) > 0; - else - return 0; -} - -static void buildinterferencematrix(void) { - PCodeBlock *block; // r30 - PCode *instr; // r29 - PCodeArg *op; - UInt32 *vec; // r28 - UInt32 i; - UInt32 j; - - UInt32 regs = used_virtual_registers[coloring_class]; - interferencematrix = oalloc(4 * ((((regs * regs) / 2) + 31) >> 5)); - bitvectorinitialize(interferencematrix, (regs * regs) / 2, 0); - - for (i = 0; i < 32; i++) - for (j = 0; j < 32; j++) - if (i != j) - makeinterfere(i, j); - - vec = oalloc(4 * ((regs + 31) >> 5)); - for (block = pcbasicblocks; block; block = block->nextBlock) { - bitvectorcopy(vec, liveinfo[block->blockIndex].out, regs); - for (instr = block->lastPCode; instr; instr = instr->prevPCode) { - for (op = instr->args, i = instr->argCount; i--; op++) { - if (PC_OP_IS_WRITE_ANY_REGISTER(op, coloring_class)) { - int reg = op->data.reg.reg; - bitvectorclearbit(reg, vec); - for (j = 0; j < regs; j++) { - if (bitvectorgetbit(j, vec)) { - if ( - (instr->flags & fIsMove) && - PC_OP_IS_ANY_REGISTER(&instr->args[0], coloring_class) && - instr->args[1].data.reg.reg == j - ) - continue; - makeinterfere(reg, j); - } - } - } - } - - for (op = instr->args, i = instr->argCount; i--; op++) { - if (PC_OP_IS_READ_ANY_REGISTER(op, coloring_class)) { - int reg = op->data.reg.reg; - if (bitvectorgetbit(op->data.reg.reg, vec) == 0) - op->data.reg.effect |= Effect4; - bitvectorsetbit(reg, vec); - } - } - - if (coloring_class == RegClass_GPR) { - if (PCODE_FLAG_SET_F(instr) & (fIsRead | fIsWrite | fPCodeFlag400000)) { - if (instr->args[1].data.reg.reg >= n_real_registers[coloring_class]) - makeinterfere(0, instr->args[1].data.reg.reg); - if (PCODE_FLAG_SET_F(instr) & fUpdatesPtr) - makeinterfere(instr->args[0].data.reg.reg, instr->args[1].data.reg.reg); - } else { - switch (instr->op) { - case PC_DCBF: - case PC_DCBST: - case PC_DCBT: - case PC_DCBTST: - case PC_DCBZ: - case PC_DCBI: - case PC_ICBI: - case PC_DCCCI: - case PC_ICBT: - case PC_ICCCI: - case PC_ICREAD: - case PC_DCBA: - case PC_DST: - case PC_DSTT: - case PC_DSTST: - case PC_DSTSTT: - if (instr->args[0].data.reg.reg >= n_real_registers[coloring_class]) - makeinterfere(0, instr->args[0].data.reg.reg); - break; - } - } - } - - if (coloring_class == RegClass_GPR && (instr->flags & fIsCall)) { - i = branch_count_volatiles(); - op = instr->args; - CError_ASSERT(219, instr->argCount != 0); - - while (op->kind != PCOp_REGISTER || !(op->data.reg.effect & EffectWrite)) { - i++; - op++; - CError_ASSERT(226, i <= instr->argCount); - } - - for (op = instr->args + i; i < instr->argCount; i++, op++) { - if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) { - for (j = 0; j < n_scratch_registers[coloring_class]; j++) - makeinterfere(op->data.reg.reg, scratch_registers[coloring_class][j]); - } - } - } - } - } -} - -static short coalesced_path(short id) { - while (id != coalesced[id]) - id = coalesced[id]; - return id; -} - -static void coalescenodes(void) { - PCodeArg *op; - UInt32 regs; - PCodeBlock *block; - PCode *instr; - UInt32 i; - short path1; - short path2; - short node1; - short node2; - - regs = used_virtual_registers[coloring_class]; - coalesced = oalloc(sizeof(SInt16) * regs); - - for (i = 0; i < regs; i++) - coalesced[i] = i; - - for (block = pcbasicblocks; block; block = block->nextBlock) { - for (instr = block->firstPCode; instr; instr = instr->nextPCode) { - if ((instr->flags & fIsMove) && !(instr->flags & fSideEffects)) { - if (PCODE_FLAG_SET_F(instr) & fRecordBit) { - CError_FATAL(309); - continue; - } - - if (instr->argCount > 2) { - if (instr->argCount != 3 || instr->args[2].kind != PCOp_PLACEHOLDEROPERAND) { - CError_FATAL(316); - continue; - } - } - - if (PC_OP_IS_ANY_REGISTER(&instr->args[0], coloring_class)) { - path1 = coalesced_path(instr->args[0].data.reg.reg); - path2 = coalesced_path(instr->args[1].data.reg.reg); - if (path1 == path2) { - deletepcode(instr); - continue; - } - - if (!interferes(path1, path2)) { - if (path1 >= n_real_registers[coloring_class] && path2 >= n_real_registers[coloring_class]) { - if (path1 < first_fe_temporary_register[coloring_class]) - continue; - if (path1 > last_temporary_register[coloring_class]) - continue; - if (path2 < first_fe_temporary_register[coloring_class]) - continue; - if (path2 > last_temporary_register[coloring_class]) - continue; - } - - node1 = (path2 < path1) ? path2 : path1; - node2 = (path2 > path1) ? path2 : path1; - - if (coloring_class == RegClass_GPR && node2 == _CALLER_SP_) - continue; - - coalesced[node2] = node1; - for (i = 0; i < regs; i++) { - if (interferes(node2, i)) - makeinterfere(node1, i); - } - - deletepcode(instr); - } - } - } - } - } - - for (block = pcbasicblocks; block; block = block->nextBlock) { - for (instr = block->firstPCode; instr; instr = instr->nextPCode) { - op = instr->args; - i = instr->argCount; - while (i--) { - if (PC_OP_IS_ANY_REGISTER(op, coloring_class) && op->data.reg.reg != coalesced[op->data.reg.reg]) - op->data.reg.reg = coalesced_path(op->data.reg.reg); - op++; - } - } - } -} - -static void buildadjacencyvectors(void) { - IGNode *node; - UInt32 regs; - UInt32 i; - UInt32 counter; - short *array; - short *dest; - short *src; - UInt32 j; - - regs = used_virtual_registers[coloring_class]; - interferencegraph = oalloc(sizeof(IGNode *) * regs); - array = oalloc(sizeof(short) * regs); - - for (i = 0; i < regs; i++) { - counter = 0; - for (j = 0; j < regs; j++) { - if (interferes(i, j)) - array[counter++] = j; - } - - node = interferencegraph[i] = oalloc(sizeof(IGNode) + sizeof(short) * (counter - 1)); - memclrw(node, sizeof(IGNode) + sizeof(short) * (counter - 1)); - - node->x10 = i; - node->x14 = -1; - node->arraySize = counter; - node->x12 = counter; - - dest = node->array; - src = array; - for (j = 0; j < counter; j++) - *(dest++) = *(src++); - - if (i != coalesced[i]) { - node->flags |= fCoalesced; - j = coalesced_path(i); - interferencegraph[j]->flags |= fCoalescedInto; - node->x14 = j; - } - } -} - -static void eliminatedeadcode(void) { - UInt32 regs; - PCodeBlock *block; - PCode *instr; - UInt32 *vec; - UInt32 i; - PCodeArg *op; - - regs = used_virtual_registers[coloring_class]; - vec = oalloc(4 * ((regs + 31) >> 5)); - - for (block = pcbasicblocks; block; block = block->nextBlock) { - bitvectorcopy(vec, liveinfo[block->blockIndex].out, regs); - for (instr = block->lastPCode; instr; instr = instr->prevPCode) { - if (dead(instr, coloring_class, vec)) { - deletepcode(instr); - continue; - } - - op = instr->args; - i = instr->argCount; - while (i--) { - if (PC_OP_IS_WRITE_ANY_REGISTER(op, coloring_class)) - bitvectorclearbit(op->data.reg.reg, vec); - op++; - } - - op = instr->args; - i = instr->argCount; - while (i--) { - if (PC_OP_IS_READ_ANY_REGISTER(op, coloring_class)) { - int reg = op->data.reg.reg; - if (!bitvectorgetbit(reg, vec)) - op->data.reg.effect |= Effect4; - bitvectorsetbit(reg, vec); - } - op++; - } - } - } -} - -static void findrematerializations(void) { - UInt32 regs; - UInt32 i; - PCodeBlock *block; - PCode *instr; - PCodeArg *op; - IGNode *node; - - regs = used_virtual_registers[coloring_class]; - - for (block = pcbasicblocks; block; block = block->nextBlock) { - for (instr = block->lastPCode; instr; instr = instr->prevPCode) { - op = instr->args; - i = instr->argCount; - while (i--) { - if ( - PC_OP_IS_WRITE_ANY_REGISTER(op, coloring_class) && - op->data.reg.reg >= n_real_registers[coloring_class] && - !(interferencegraph[op->data.reg.reg]->flags & (fPairLow | fPairHigh)) && - !(interferencegraph[op->data.reg.reg]->flags & fIGNode40) - ) - { - node = interferencegraph[op->data.reg.reg]; - if (!node->instr8) { - node->instr8 = instr; - } else { - node->instr8 = NULL; - node->flags |= fIGNode40; - } - } - op++; - } - } - } - - for (i = 0; i < regs; i++) { - node = interferencegraph[i]; - if (node->instr8 && !is_location_independent(node->instr8)) - node->instr8 = NULL; - } -} - -void buildinterferencegraph(Object *proc) { - int regs = used_virtual_registers[coloring_class]; - - computelivevariables(proc); - eliminatedeadcode(); - buildinterferencematrix(); - if (copts.debuglisting) - pclistinterferences(register_class_format[coloring_class], regs); - coalescenodes(); - buildadjacencyvectors(); - findrematerializations(); -} diff --git a/compiler_and_linker/unsorted/Intrinsics.c b/compiler_and_linker/unsorted/Intrinsics.c deleted file mode 100644 index 49334b8..0000000 --- a/compiler_and_linker/unsorted/Intrinsics.c +++ /dev/null @@ -1,4894 +0,0 @@ -#include "compiler/Intrinsics.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/CScope.h" -#include "compiler/CompilerTools.h" -#include "compiler/FunctionCalls.h" -#include "compiler/InstrSelection.h" -#include "compiler/PCode.h" -#include "compiler/PCodeUtilities.h" -#include "compiler/PPCError.h" -#include "compiler/RegisterInfo.h" -#include "compiler/StackFrame.h" -#include "compiler/StructMoves.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/types.h" - -Object *__memcpy_object; -static Object *intrinsics[311]; -int VectorConditions; // unused? -static Object *cur_intrinsic_object; - -static TypePointer stvectorunsignedchar_ptr = {TYPEPOINTER, 4, TYPE(&stvectorunsignedchar), 0}; -static TypePointer stvectorsignedchar_ptr = {TYPEPOINTER, 4, TYPE(&stvectorsignedchar), 0}; -static TypePointer stvectorboolchar_ptr = {TYPEPOINTER, 4, TYPE(&stvectorboolchar), 0}; -static TypePointer stvectorunsignedshort_ptr = {TYPEPOINTER, 4, TYPE(&stvectorunsignedshort), 0}; -static TypePointer stvectorsignedshort_ptr = {TYPEPOINTER, 4, TYPE(&stvectorsignedshort), 0}; -static TypePointer stvectorboolshort_ptr = {TYPEPOINTER, 4, TYPE(&stvectorboolshort), 0}; -static TypePointer stvectorunsignedlong_ptr = {TYPEPOINTER, 4, TYPE(&stvectorunsignedlong), 0}; -static TypePointer stvectorsignedlong_ptr = {TYPEPOINTER, 4, TYPE(&stvectorsignedlong), 0}; -static TypePointer stvectorboollong_ptr = {TYPEPOINTER, 4, TYPE(&stvectorboollong), 0}; -static TypePointer stvectorfloat_ptr = {TYPEPOINTER, 4, TYPE(&stvectorfloat), 0}; -static TypePointer stvectorpixel_ptr = {TYPEPOINTER, 4, TYPE(&stvectorpixel), 0}; -static TypePointer stunsignedchar_ptr = {TYPEPOINTER, 4, TYPE(&stunsignedchar), 0}; -static TypePointer stsignedchar_ptr = {TYPEPOINTER, 4, TYPE(&stsignedchar), 0}; -static TypePointer stunsignedshort_ptr = {TYPEPOINTER, 4, TYPE(&stunsignedshort), 0}; -static TypePointer stsignedshort_ptr = {TYPEPOINTER, 4, TYPE(&stsignedshort), 0}; -static TypePointer stunsignedlong_ptr = {TYPEPOINTER, 4, TYPE(&stunsignedlong), 0}; -static TypePointer stsignedlong_ptr = {TYPEPOINTER, 4, TYPE(&stsignedlong), 0}; -static TypePointer stunsignedint_ptr = {TYPEPOINTER, 4, TYPE(&stunsignedint), 0}; -static TypePointer stsignedint_ptr = {TYPEPOINTER, 4, TYPE(&stsignedint), 0}; -static TypePointer stfloat_ptr = {TYPEPOINTER, 4, TYPE(&stfloat), 0}; - -// Verify1VectorArg2Ops -typedef struct TypeTable22 { - Type *rtype; - Type *arg1; - int opcode1; - int opcode2; -} TypeTable22; - -// VerifyNoVectorArgs -typedef struct TypeTable11 { - Type *rtype; - int opcode; -} TypeTable11; - -// Verify1VectorArg -typedef struct TypeTable21 { - Type *rtype; - Type *arg1; - int opcode; -} TypeTable21; - -// Verify2VectorArgs -typedef struct TypeTable31 { - Type *rtype; - Type *arg1; - Type *arg2; - int opcode; -} TypeTable31; - -// Verify3VectorArgs -typedef struct TypeTable41 { - Type *rtype; - Type *arg1; - Type *arg2; - Type *arg3; - int opcode; -} TypeTable41; - -static TypeTable31 vector_add_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VADDUBM, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VADDUBM, - TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VADDUBM, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VADDUBM, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VADDUBM, - TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VADDUBM, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VADDUHM, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VADDUHM, - TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VADDUHM, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VADDUHM, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VADDUHM, - TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VADDUHM, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDUWM, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VADDUWM, - TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VADDUWM, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VADDUWM, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VADDUWM, - TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VADDUWM, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VADDFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_addc_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDCUW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_adds_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VADDUBS, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VADDUBS, - TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VADDUBS, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VADDSBS, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VADDSBS, - TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VADDSBS, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VADDUHS, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VADDUHS, - TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VADDUHS, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VADDSHS, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VADDSHS, - TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VADDSHS, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDUWS, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VADDUWS, - TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VADDUWS, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VADDSWS, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VADDSWS, - TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VADDSWS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_and_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VAND, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VAND, - TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VAND, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VAND, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VAND, - TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VAND, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VAND, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VAND, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VAND, - TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VAND, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VAND, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VAND, - TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VAND, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VAND, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VAND, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VAND, - TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VAND, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VAND, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VAND, - TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VAND, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VAND, - TYPE(&stvectorfloat), TYPE(&stvectorboollong), TYPE(&stvectorfloat), PC_VAND, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VAND, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VAND, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_andc_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VANDC, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VANDC, - TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VANDC, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VANDC, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VANDC, - TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VANDC, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VANDC, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VANDC, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VANDC, - TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VANDC, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VANDC, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VANDC, - TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VANDC, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VANDC, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VANDC, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VANDC, - TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VANDC, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VANDC, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VANDC, - TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VANDC, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VANDC, - TYPE(&stvectorfloat), TYPE(&stvectorboollong), TYPE(&stvectorfloat), PC_VANDC, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VANDC, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VANDC, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_avg_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VAVGUB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VAVGSB, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VAVGUH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VAVGSH, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VAVGUW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VAVGSW, - NULL, NULL, NULL, 0 -}; -static TypeTable22 vector_ceil_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRFIP, PC_B, - NULL, NULL, 0 -}; -static TypeTable31 vector_cmpb_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPBFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_cmpeq_type_table[] = { - TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, - TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, - TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, - TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, - TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, - TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, - TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_cmpge_type_table[] = { - TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_cmpgt_type_table[] = { - TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_ctf_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VCFUX, - TYPE(&stvectorfloat), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VCFSX, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_cts_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VCTSXS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_ctu_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VCTUXS, - NULL, NULL, NULL, 0 -}; -static TypeTable22 vector_dss_type_table[] = { - TYPE(&stvoid), TYPE(&stsignedint), PC_DSS, PC_B, - NULL, NULL, 0 -}; -static TypeTable11 vector_dssall_type_table[] = { - TYPE(&stvoid), PC_DSSALL, - NULL, 0 -}; -static TypeTable41 vector_datastream_type_table[] = { - TYPE(&stvoid), TYPE(&stvectorunsignedchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stvectorsignedchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stvectorboolchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stvectorunsignedshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stvectorsignedshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stvectorboolshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stvectorpixel_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stvectorunsignedlong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stvectorsignedlong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stvectorboollong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stvectorfloat_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stunsignedchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stsignedchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stunsignedshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stsignedshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stunsignedint_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stsignedint_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stunsignedlong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stsignedlong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - TYPE(&stvoid), TYPE(&stfloat_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable22 vector_expte_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VEXPTEFP, PC_B, - NULL, NULL, 0 -}; -static TypeTable22 vector_floor_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRFIM, PC_B, - NULL, NULL, 0 -}; -static TypeTable31 vector_load_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stvectorunsignedchar_ptr), PC_LVX, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVX, - TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stvectorsignedchar_ptr), PC_LVX, - TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVX, - TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stvectorboolchar_ptr), PC_LVX, - TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stvectorunsignedshort_ptr), PC_LVX, - TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVX, - TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stvectorsignedshort_ptr), PC_LVX, - TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVX, - TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stvectorboolshort_ptr), PC_LVX, - TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stvectorpixel_ptr), PC_LVX, - TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stvectorunsignedlong_ptr), PC_LVX, - TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVX, - TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVX, - TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stvectorsignedlong_ptr), PC_LVX, - TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVX, - TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVX, - TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stvectorboollong_ptr), PC_LVX, - TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stvectorfloat_ptr), PC_LVX, - TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVX, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_loade_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVEBX, - TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVEBX, - TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVEHX, - TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVEHX, - TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVEWX, - TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVEWX, - TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVEWX, - TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVEWX, - TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVEWX, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_loadl_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stvectorunsignedchar_ptr), PC_LVXL, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVXL, - TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stvectorsignedchar_ptr), PC_LVXL, - TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVXL, - TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stvectorboolchar_ptr), PC_LVXL, - TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stvectorunsignedshort_ptr), PC_LVXL, - TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVXL, - TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stvectorsignedshort_ptr), PC_LVXL, - TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVXL, - TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stvectorboolshort_ptr), PC_LVXL, - TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stvectorpixel_ptr), PC_LVXL, - TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stvectorunsignedlong_ptr), PC_LVXL, - TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVXL, - TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVXL, - TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stvectorsignedlong_ptr), PC_LVXL, - TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVXL, - TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVXL, - TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stvectorboollong_ptr), PC_LVXL, - TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stvectorfloat_ptr), PC_LVXL, - TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVXL, - NULL, NULL, NULL, 0 -}; -static TypeTable22 vector_loge_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VLOGEFP, PC_B, - NULL, NULL, 0 -}; -static TypeTable31 vector_lvsl_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVSL, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVSL, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVSL, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVSL, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVSL, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVSL, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVSL, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVSL, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVSL, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_lvsr_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVSR, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVSR, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVSR, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVSR, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVSR, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVSR, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVSR, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVSR, - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVSR, - NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_madd_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMADDFP, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_madds_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMHADDSHS, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_max_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMAXUB, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VMAXUB, - TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VMAXUB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMAXSB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VMAXSB, - TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VMAXSB, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMAXUH, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VMAXUH, - TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VMAXUH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMAXSH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VMAXSH, - TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VMAXSH, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMAXUW, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VMAXUW, - TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VMAXUW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMAXSW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VMAXSW, - TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VMAXSW, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMAXFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_mergeh_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGHB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMRGHB, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VMRGHB, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGHH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMRGHH, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VMRGHH, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VMRGHH, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMRGHW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMRGHW, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VMRGHW, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMRGHW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_mergel_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGLB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMRGLB, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VMRGLB, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGLH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMRGLH, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VMRGLH, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VMRGLH, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMRGLW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMRGLW, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VMRGLW, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMRGLW, - NULL, NULL, NULL, 0 -}; -static TypeTable11 vector_mfvscr_type_table[] = { - TYPE(&stvectorunsignedshort), PC_MFVSCR, - NULL, 0 -}; -static TypeTable31 vector_min_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMINUB, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VMINUB, - TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VMINUB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMINSB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VMINSB, - TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VMINSB, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMINUH, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VMINUH, - TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VMINUH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMINSH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VMINSH, - TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VMINSH, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMINUW, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VMINUW, - TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VMINUW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMINSW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VMINSW, - TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VMINSW, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMINFP, - NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_mladd_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMLADDUHM, - TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMLADDUHM, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMLADDUHM, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMLADDUHM, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_mradds_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMHRADDSHS, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_msum_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VMSUMUBM, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VMSUMUHM, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedlong), PC_VMSUMMBM, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VMSUMSHM, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_msums_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VMSUMUHS, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VMSUMSHS, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable21 vector_mtvscr_type_table[] = { - TYPE(&stvoid), TYPE(&stvectorunsignedchar), PC_MTVSCR, - TYPE(&stvoid), TYPE(&stvectorsignedchar), PC_MTVSCR, - TYPE(&stvoid), TYPE(&stvectorboolchar), PC_MTVSCR, - TYPE(&stvoid), TYPE(&stvectorunsignedshort), PC_MTVSCR, - TYPE(&stvoid), TYPE(&stvectorsignedshort), PC_MTVSCR, - TYPE(&stvoid), TYPE(&stvectorboolshort), PC_MTVSCR, - TYPE(&stvoid), TYPE(&stvectorpixel), PC_MTVSCR, - TYPE(&stvoid), TYPE(&stvectorunsignedlong), PC_MTVSCR, - TYPE(&stvoid), TYPE(&stvectorsignedlong), PC_MTVSCR, - TYPE(&stvoid), TYPE(&stvectorboollong), PC_MTVSCR, - NULL, NULL, 0 -}; -static TypeTable31 vector_mule_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMULEUB, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMULESB, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMULEUH, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMULESH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_mulo_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMULOUB, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMULOSB, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMULOUH, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMULOSH, - NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_nmsub_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VNMSUBFP, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_nor_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VNOR, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VNOR, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VNOR, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VNOR, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VNOR, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VNOR, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VNOR, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VNOR, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VNOR, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VNOR, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_or_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VOR, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VOR, - TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VOR, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VOR, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VOR, - TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VOR, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VOR, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VOR, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VOR, - TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VOR, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VOR, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VOR, - TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VOR, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VOR, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VOR, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VOR, - TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VOR, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VOR, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VOR, - TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VOR, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VOR, - TYPE(&stvectorfloat), TYPE(&stvectorboollong), TYPE(&stvectorfloat), PC_VOR, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VOR, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VOR, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_pack_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUM, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKUHUM, - TYPE(&stvectorboolchar), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VPKUHUM, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUM, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKUWUM, - TYPE(&stvectorboolshort), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VPKUWUM, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_packpx_type_table[] = { - TYPE(&stvectorpixel), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKPX, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_packs_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUS, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKSHSS, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUS, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKSWSS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_packsu_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUS, - TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKSHUS, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUS, - TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKSWUS, - NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_perm_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VPERM, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VPERM, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VPERM, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VPERM, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VPERM, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedchar), PC_VPERM, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VPERM, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VPERM, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VPERM, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedchar), PC_VPERM, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorunsignedchar), PC_VPERM, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable22 vector_re_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VREFP, PC_B, - NULL, NULL, 0 -}; -static TypeTable31 vector_rl_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VRLB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VRLB, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VRLH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VRLH, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VRLW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VRLW, - NULL, NULL, NULL, 0 -}; -static TypeTable22 vector_round_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRFIN, PC_B, - NULL, NULL, 0 -}; -static TypeTable22 vector_rsqrte_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRSQRTEFP, PC_B, - NULL, NULL, 0 -}; -static TypeTable41 vector_sel_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSEL, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSEL, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSEL, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSEL, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSEL, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VSEL, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSEL, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSEL, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSEL, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSEL, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSEL, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VSEL, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSEL, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSEL, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSEL, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSEL, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSEL, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VSEL, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorunsignedlong), PC_VSEL, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VSEL, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_sl_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSLB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSLB, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSLH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSLH, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSLW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSLW, - NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_sld_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), PC_VSLDOI, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSLDOI, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), PC_VSLDOI, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSLDOI, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stsignedint), PC_VSLDOI, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VSLDOI, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSLDOI, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VSLDOI, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_sll_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSL, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), PC_VSL, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VSL, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSL, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedshort), PC_VSL, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedlong), PC_VSL, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSL, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedshort), PC_VSL, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedlong), PC_VSL, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VSL, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSL, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VSL, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VSL, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSL, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedlong), PC_VSL, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedchar), PC_VSL, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSL, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedlong), PC_VSL, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VSL, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedshort), PC_VSL, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedlong), PC_VSL, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VSL, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), PC_VSL, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSL, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VSL, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedshort), PC_VSL, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSL, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedchar), PC_VSL, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedshort), PC_VSL, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSL, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_slo_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSLO, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedchar), PC_VSLO, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSLO, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSLO, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VSLO, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedchar), PC_VSLO, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VSLO, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VSLO, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VSLO, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorsignedchar), PC_VSLO, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VSLO, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorsignedchar), PC_VSLO, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VSLO, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), PC_VSLO, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorunsignedchar), PC_VSLO, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorsignedchar), PC_VSLO, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_splat_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), PC_VSPLTB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSPLTB, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stsignedint), PC_VSPLTB, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), PC_VSPLTH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSPLTH, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stsignedint), PC_VSPLTH, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stsignedint), PC_VSPLTH, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VSPLTW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSPLTW, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stsignedint), PC_VSPLTW, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VSPLTW, - NULL, NULL, NULL, 0 -}; -static TypeTable22 vector_splat_s8_type_table[] = { - TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSPLTISB, PC_B, - NULL, NULL, 0 -}; -static TypeTable22 vector_splat_s16_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSPLTISH, PC_B, - NULL, NULL, 0 -}; -static TypeTable22 vector_splat_s32_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSPLTISW, PC_B, - NULL, NULL, 0 -}; -static TypeTable22 vector_splat_u8_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), PC_VSPLTISB, PC_B, - NULL, NULL, 0 -}; -static TypeTable22 vector_splat_u16_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stsignedint), PC_VSPLTISH, PC_B, - NULL, NULL, 0 -}; -static TypeTable22 vector_splat_u32_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VSPLTISW, PC_B, - NULL, NULL, 0 -}; -static TypeTable31 vector_sr_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRB, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSRH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSRH, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSRW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSRW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_sra_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRAB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRAB, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSRAH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSRAH, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSRAW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSRAW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_srl_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSR, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), PC_VSR, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VSR, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSR, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedshort), PC_VSR, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedlong), PC_VSR, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSR, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedshort), PC_VSR, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedlong), PC_VSR, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VSR, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSR, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VSR, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VSR, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSR, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedlong), PC_VSR, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedchar), PC_VSR, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSR, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedlong), PC_VSR, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VSR, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedshort), PC_VSR, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedlong), PC_VSR, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VSR, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), PC_VSR, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSR, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VSR, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedshort), PC_VSR, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSR, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedchar), PC_VSR, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedshort), PC_VSR, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSR, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_sro_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRO, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedchar), PC_VSRO, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRO, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSRO, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VSRO, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedchar), PC_VSRO, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VSRO, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VSRO, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VSRO, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorsignedchar), PC_VSRO, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VSRO, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorsignedchar), PC_VSRO, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VSRO, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), PC_VSRO, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorunsignedchar), PC_VSRO, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorsignedchar), PC_VSRO, - NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_st_type_table[] = { - TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stvectorunsignedchar_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stvectorsignedchar_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stvectorunsignedshort_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stvectorsignedshort_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stvectorunsignedlong_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stvectorsignedlong_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stvectorfloat_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stvectorpixel_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stvectorboolchar_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stvectorboolshort_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stvectorboollong_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVX, - TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVX, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_ste_type_table[] = { - TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVEBX, - TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVEBX, - TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVEHX, - TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, - TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVEWX, - TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVEWX, - TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVEWX, - TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVEWX, - TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_STVEWX, - TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, - TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVEHX, - TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVEBX, - TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVEBX, - TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, - TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVEHX, - TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVEWX, - TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVEWX, - TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVEWX, - TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVEWX, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_stl_type_table[] = { - TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stvectorunsignedchar_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stvectorsignedchar_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stvectorunsignedshort_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stvectorsignedshort_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stvectorunsignedlong_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stvectorsignedlong_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stvectorfloat_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stvectorpixel_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stvectorboolchar_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stvectorboolshort_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stvectorboollong_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVXL, - TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVXL, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_sub_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSUBUBM, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBM, - TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSUBUBM, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBUBM, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBM, - TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VSUBUBM, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSUBUHM, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHM, - TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSUBUHM, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBUHM, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHM, - TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VSUBUHM, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBUWM, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSUBUWM, - TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSUBUWM, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBUWM, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSUBUWM, - TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VSUBUWM, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VSUBFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_subc_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBCUW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_subs_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSUBUBS, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBS, - TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSUBUBS, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBSBS, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSUBSBS, - TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VSUBSBS, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSUBUHS, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHS, - TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSUBUHS, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBSHS, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSUBSHS, - TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VSUBSHS, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBUWS, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSUBUWS, - TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSUBUWS, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBSWS, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSUBSWS, - TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VSUBSWS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_sum4s_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VSUM4UBS, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedlong), PC_VSUM4SBS, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VSUM4SHS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_sum2s_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUM2SWS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_sums_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUMSWS, - NULL, NULL, NULL, 0 -}; -static TypeTable22 vector_trunc_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRFIZ, PC_B, - NULL, NULL, 0 -}; -static TypeTable31 vector_unpack2sh_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGHB, - TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGHH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_unpack2sl_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGLB, - TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGLH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_unpack2uh_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGHB, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGHH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_unpack2ul_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGLB, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGLH, - NULL, NULL, NULL, 0 -}; -static TypeTable21 vector_unpackh_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VUPKHSB, - TYPE(&stvectorboolshort), TYPE(&stvectorboolchar), PC_VUPKHSB, - TYPE(&stvectorunsignedlong), TYPE(&stvectorpixel), PC_VUPKHPX, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), PC_VUPKHSH, - TYPE(&stvectorboollong), TYPE(&stvectorboolshort), PC_VUPKHSH, - NULL, NULL, 0 -}; -static TypeTable21 vector_unpackl_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VUPKLSB, - TYPE(&stvectorboolshort), TYPE(&stvectorboolchar), PC_VUPKLSB, - TYPE(&stvectorunsignedlong), TYPE(&stvectorpixel), PC_VUPKLPX, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), PC_VUPKLSH, - TYPE(&stvectorboollong), TYPE(&stvectorboolshort), PC_VUPKLSH, - NULL, NULL, 0 -}; -static TypeTable31 vector_xor_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VXOR, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VXOR, - TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VXOR, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VXOR, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VXOR, - TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VXOR, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VXOR, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VXOR, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VXOR, - TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VXOR, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VXOR, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VXOR, - TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VXOR, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VXOR, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VXOR, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VXOR, - TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VXOR, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VXOR, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VXOR, - TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VXOR, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VXOR, - TYPE(&stvectorfloat), TYPE(&stvectorboollong), TYPE(&stvectorfloat), PC_VXOR, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VXOR, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VXOR, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_all_eq_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_all_ge_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_all_gt_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_all_in_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPBFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_all_le_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_all_lt_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP -}; -static TypeTable22 vector_all_nan_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorfloat), PC_VCMPEQFP, PC_B, - NULL, NULL, 0 -}; -static TypeTable31 vector_all_ne_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_all_nge_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_all_ngt_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_all_nle_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_all_nlt_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, - NULL, NULL, NULL, 0 -}; -static TypeTable22 vector_all_numeric_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorfloat), PC_VCMPEQFP, PC_B, - NULL, NULL, 0 -}; -static TypeTable31 vector_any_eq_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_any_ge_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_any_gt_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_any_le_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_any_lt_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, - NULL, NULL, NULL, 0 -}; -static TypeTable22 vector_any_nan_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorfloat), PC_VCMPEQFP, PC_B, - NULL, NULL, 0 -}; -static TypeTable31 vector_any_ne_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VCMPEQUB, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VCMPEQUH, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VCMPEQUW, - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_any_nge_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_any_ngt_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_any_nle_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_any_nlt_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, - NULL, NULL, NULL, 0 -}; -static TypeTable22 vector_any_numeric_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorfloat), PC_VCMPEQFP, PC_B, - NULL, NULL, 0 -}; -static TypeTable31 vector_any_out_type_table[] = { - TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPBFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vaddubm_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VADDUBM, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VADDUBM, - TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VADDUBM, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VADDUBM, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VADDUBM, - TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VADDUBM, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vadduhm_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VADDUHM, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VADDUHM, - TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VADDUHM, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VADDUHM, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VADDUHM, - TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VADDUHM, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vadduwm_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDUWM, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VADDUWM, - TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VADDUWM, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VADDUWM, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VADDUWM, - TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VADDUWM, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vaddfp_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VADDFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vaddubs_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VADDUBS, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VADDUBS, - TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VADDUBS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vaddsbs_type_table[] = { - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VADDSBS, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VADDSBS, - TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VADDSBS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vadduhs_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VADDUHS, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VADDUHS, - TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VADDUHS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vaddshs_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VADDSHS, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VADDSHS, - TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VADDSHS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vadduws_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDUWS, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VADDUWS, - TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VADDUWS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vaddsws_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VADDSWS, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VADDSWS, - TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VADDSWS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vavgub_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VAVGUB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vavgsb_type_table[] = { - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VAVGSB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vavguh_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VAVGUH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vavgsh_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VAVGSH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vavguw_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VAVGUW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vavgsw_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VAVGSW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vcmpequb_type_table[] = { - TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB, - TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vcmpequh_type_table[] = { - TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH, - TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vcmpequw_type_table[] = { - TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW, - TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vcmpeqfp_type_table[] = { - TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vcmpgtub_type_table[] = { - TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vcmpgtsb_type_table[] = { - TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vcmpgtuh_type_table[] = { - TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vcmpgtsh_type_table[] = { - TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vcmpgtuw_type_table[] = { - TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vcmpgtsw_type_table[] = { - TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vcmpgtfp_type_table[] = { - TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vcfux_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VCFUX, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vcfsx_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VCFSX, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_lvebx_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVEBX, - TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVEBX, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_lvehx_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVEHX, - TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVEHX, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_lvewx_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVEWX, - TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVEWX, - TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVEWX, - TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVEWX, - TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVEWX, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmaxub_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMAXUB, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VMAXUB, - TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VMAXUB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmaxsb_type_table[] = { - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMAXSB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VMAXSB, - TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VMAXSB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmaxuh_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMAXUH, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VMAXUH, - TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VMAXUH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmaxsh_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMAXSH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VMAXSH, - TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VMAXSH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmaxuw_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMAXUW, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VMAXUW, - TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VMAXUW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmaxsw_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMAXSW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VMAXSW, - TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VMAXSW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmaxfp_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMAXFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmrghb_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGHB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMRGHB, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VMRGHB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmrghh_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGHH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMRGHH, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VMRGHH, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VMRGHH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmrghw_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMRGHW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMRGHW, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VMRGHW, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMRGHW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmrglb_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGLB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMRGLB, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VMRGLB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmrglh_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGLH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMRGLH, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VMRGLH, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VMRGLH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmrglw_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMRGLW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMRGLW, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VMRGLW, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMRGLW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vminub_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMINUB, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VMINUB, - TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VMINUB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vminsb_type_table[] = { - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMINSB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VMINSB, - TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VMINSB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vminuh_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMINUH, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VMINUH, - TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VMINUH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vminsh_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMINSH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VMINSH, - TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VMINSH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vminuw_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMINUW, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VMINUW, - TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VMINUW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vminsw_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMINSW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VMINSW, - TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VMINSW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vminfp_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMINFP, - NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_vmsumubm_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VMSUMUBM, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_vmsumuhm_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VMSUMUHM, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_vmsummbm_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedlong), PC_VMSUMMBM, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_vmsumshm_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VMSUMSHM, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_vmsumuhs_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VMSUMUHS, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_vmsumshs_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VMSUMSHS, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmuleub_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMULEUB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmulesb_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMULESB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmuleuh_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMULEUH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmulesh_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMULESH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmuloub_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMULOUB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmulosb_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMULOSB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmulouh_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMULOUH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vmulosh_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMULOSH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vpkuhum_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUM, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKUHUM, - TYPE(&stvectorboolchar), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VPKUHUM, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vpkuwum_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUM, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKUWUM, - TYPE(&stvectorboolshort), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VPKUWUM, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vpkuhus_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vpkshss_type_table[] = { - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKSHSS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vpkuwus_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vpkswss_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKSWSS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vpkshus_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKSHUS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vpkswus_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKSWUS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vrlb_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VRLB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VRLB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vrlh_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VRLH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VRLH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vrlw_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VRLW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VRLW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vslb_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSLB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSLB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vslh_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSLH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSLH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vslw_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSLW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSLW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vspltb_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), PC_VSPLTB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSPLTB, - TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stsignedint), PC_VSPLTB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsplth_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), PC_VSPLTH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSPLTH, - TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stsignedint), PC_VSPLTH, - TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stsignedint), PC_VSPLTH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vspltw_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VSPLTW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSPLTW, - TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stsignedint), PC_VSPLTW, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VSPLTW, - NULL, NULL, NULL, 0 -}; -static TypeTable22 vector_vspltisb_type_table[] = { - TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSPLTISB, PC_B, - NULL, NULL, 0 -}; -static TypeTable22 vector_vspltish_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSPLTISH, PC_B, - NULL, NULL, 0 -}; -static TypeTable22 vector_vspltisw_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSPLTISW, PC_B, - NULL, NULL, 0 -}; -static TypeTable31 vector_vsrb_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsrh_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSRH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSRH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsrw_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSRW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSRW, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsrab_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRAB, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRAB, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsrah_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSRAH, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSRAH, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsraw_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSRAW, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSRAW, - NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_stvebx_type_table[] = { - TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVEBX, - TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVEBX, - TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVEBX, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_stvehx_type_table[] = { - TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVEHX, - TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, - TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, - TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable41 vector_stvewx_type_table[] = { - TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVEWX, - TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVEWX, - TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVEWX, - TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVEWX, - TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_STVEWX, - TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVEWX, - TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVEWX, - NULL, NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsububm_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSUBUBM, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBM, - TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSUBUBM, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBUBM, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBM, - TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VSUBUBM, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsubuhm_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSUBUHM, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHM, - TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSUBUHM, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBUHM, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHM, - TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VSUBUHM, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsubuwm_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBUWM, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSUBUWM, - TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSUBUWM, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBUWM, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSUBUWM, - TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VSUBUWM, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VSUBFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsubfp_type_table[] = { - TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VSUBFP, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsububs_type_table[] = { - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSUBUBS, - TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBS, - TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSUBUBS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsubsbs_type_table[] = { - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBSBS, - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSUBSBS, - TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VSUBSBS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsubuhs_type_table[] = { - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSUBUHS, - TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHS, - TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSUBUHS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsubshs_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBSHS, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSUBSHS, - TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VSUBSHS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsubuws_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBUWS, - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSUBUWS, - TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSUBUWS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsubsws_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBSWS, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSUBSWS, - TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VSUBSWS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsum4ubs_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VSUM4UBS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsum4sbs_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedlong), PC_VSUM4SBS, - NULL, NULL, NULL, 0 -}; -static TypeTable31 vector_vsum4shs_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VSUM4SHS, - NULL, NULL, NULL, 0 -}; -static TypeTable21 vector_vupkhsb_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VUPKHSB, - TYPE(&stvectorboolshort), TYPE(&stvectorboolchar), PC_VUPKHSB, - NULL, NULL, 0 -}; -static TypeTable21 vector_vupklsb_type_table[] = { - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VUPKLSB, - TYPE(&stvectorboolshort), TYPE(&stvectorboolchar), PC_VUPKLSB, - NULL, NULL, 0 -}; -static TypeTable22 vector_vupkhpx_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorpixel), PC_VUPKHPX, PC_B, - NULL, NULL, 0 -}; -static TypeTable22 vector_vupklpx_type_table[] = { - TYPE(&stvectorunsignedlong), TYPE(&stvectorpixel), PC_VUPKLPX, PC_B, - NULL, NULL, 0 -}; -static TypeTable21 vector_vupkhsh_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), PC_VUPKHSH, - TYPE(&stvectorboollong), TYPE(&stvectorboolshort), PC_VUPKHSH, - NULL, NULL, 0 -}; -static TypeTable21 vector_vupklsh_type_table[] = { - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), PC_VUPKLSH, - TYPE(&stvectorboollong), TYPE(&stvectorboolshort), PC_VUPKLSH, - NULL, NULL, 0 -}; -static TypeTable22 vector_abs_type_table[] = { - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBUBM, PC_VMAXSB, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBUHM, PC_VMAXSH, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBUWM, PC_VMAXSW, - TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VANDC, PC_B, - NULL, NULL, 0 -}; -static TypeTable22 vector_abss_type_table[] = { - TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBSBS, PC_VMAXSB, - TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBSHS, PC_VMAXSH, - TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBSWS, PC_VMAXSW, - NULL, NULL, 0 -}; -static void *typeTable[] = { - vector_add_type_table, - vector_addc_type_table, - vector_adds_type_table, - vector_and_type_table, - vector_andc_type_table, - vector_avg_type_table, - vector_ceil_type_table, - vector_cmpb_type_table, - vector_cmpeq_type_table, - vector_cmpge_type_table, - vector_cmpge_type_table, - vector_cmpgt_type_table, - vector_cmpgt_type_table, - vector_ctf_type_table, - vector_cts_type_table, - vector_ctu_type_table, - vector_dss_type_table, - vector_dssall_type_table, - vector_datastream_type_table, - vector_datastream_type_table, - vector_datastream_type_table, - vector_datastream_type_table, - vector_expte_type_table, - vector_floor_type_table, - vector_load_type_table, - vector_loade_type_table, - vector_loadl_type_table, - vector_loge_type_table, - vector_lvsl_type_table, - vector_lvsr_type_table, - vector_madd_type_table, - vector_madds_type_table, - vector_max_type_table, - vector_mergeh_type_table, - vector_mergel_type_table, - vector_mfvscr_type_table, - vector_min_type_table, - vector_mladd_type_table, - vector_mradds_type_table, - vector_msum_type_table, - vector_msums_type_table, - vector_mtvscr_type_table, - vector_mule_type_table, - vector_mulo_type_table, - vector_nmsub_type_table, - vector_nor_type_table, - vector_or_type_table, - vector_pack_type_table, - vector_packpx_type_table, - vector_packs_type_table, - vector_packsu_type_table, - vector_perm_type_table, - vector_re_type_table, - vector_rl_type_table, - vector_round_type_table, - vector_rsqrte_type_table, - vector_sel_type_table, - vector_sl_type_table, - vector_sld_type_table, - vector_sll_type_table, - vector_slo_type_table, - vector_splat_type_table, - vector_splat_s8_type_table, - vector_splat_s16_type_table, - vector_splat_s32_type_table, - vector_splat_u8_type_table, - vector_splat_u16_type_table, - vector_splat_u32_type_table, - vector_sr_type_table, - vector_sra_type_table, - vector_srl_type_table, - vector_sro_type_table, - vector_st_type_table, - vector_ste_type_table, - vector_stl_type_table, - vector_sub_type_table, - vector_subc_type_table, - vector_subs_type_table, - vector_sum4s_type_table, - vector_sum2s_type_table, - vector_sums_type_table, - vector_trunc_type_table, - vector_unpack2sh_type_table, - vector_unpack2sl_type_table, - vector_unpack2uh_type_table, - vector_unpack2ul_type_table, - vector_unpackh_type_table, - vector_unpackl_type_table, - vector_xor_type_table, - vector_all_eq_type_table, - vector_all_ge_type_table, - vector_all_gt_type_table, - vector_all_in_type_table, - vector_all_le_type_table, - vector_all_lt_type_table, - vector_all_nan_type_table, - vector_all_ne_type_table, - vector_all_nge_type_table, - vector_all_ngt_type_table, - vector_all_nle_type_table, - vector_all_nlt_type_table, - vector_all_numeric_type_table, - vector_any_eq_type_table, - vector_any_ge_type_table, - vector_any_gt_type_table, - vector_any_le_type_table, - vector_any_lt_type_table, - vector_any_nan_type_table, - vector_any_ne_type_table, - vector_any_nge_type_table, - vector_any_ngt_type_table, - vector_any_nle_type_table, - vector_any_nlt_type_table, - vector_any_numeric_type_table, - vector_any_out_type_table, - vector_vaddubm_type_table, - vector_vadduhm_type_table, - vector_vadduwm_type_table, - vector_vaddfp_type_table, - vector_addc_type_table, - vector_vaddubs_type_table, - vector_vaddsbs_type_table, - vector_vadduhs_type_table, - vector_vaddshs_type_table, - vector_vadduws_type_table, - vector_vaddsws_type_table, - vector_and_type_table, - vector_andc_type_table, - vector_vavgub_type_table, - vector_vavgsb_type_table, - vector_vavguh_type_table, - vector_vavgsh_type_table, - vector_vavguw_type_table, - vector_vavgsw_type_table, - vector_ceil_type_table, - vector_cmpb_type_table, - vector_vcmpequb_type_table, - vector_vcmpequh_type_table, - vector_vcmpequw_type_table, - vector_vcmpeqfp_type_table, - vector_cmpge_type_table, - vector_vcmpgtub_type_table, - vector_vcmpgtsb_type_table, - vector_vcmpgtuh_type_table, - vector_vcmpgtsh_type_table, - vector_vcmpgtuw_type_table, - vector_vcmpgtsw_type_table, - vector_vcmpgtfp_type_table, - vector_vcfux_type_table, - vector_vcfsx_type_table, - vector_cts_type_table, - vector_ctu_type_table, - vector_expte_type_table, - vector_floor_type_table, - vector_load_type_table, - vector_lvebx_type_table, - vector_lvehx_type_table, - vector_lvewx_type_table, - vector_loadl_type_table, - vector_loge_type_table, - vector_madd_type_table, - vector_madds_type_table, - vector_vmaxub_type_table, - vector_vmaxsb_type_table, - vector_vmaxuh_type_table, - vector_vmaxsh_type_table, - vector_vmaxuw_type_table, - vector_vmaxsw_type_table, - vector_vmaxfp_type_table, - vector_vmrghb_type_table, - vector_vmrghh_type_table, - vector_vmrghw_type_table, - vector_vmrglb_type_table, - vector_vmrglh_type_table, - vector_vmrglw_type_table, - vector_vminub_type_table, - vector_vminsb_type_table, - vector_vminuh_type_table, - vector_vminsh_type_table, - vector_vminuw_type_table, - vector_vminsw_type_table, - vector_vminfp_type_table, - vector_mladd_type_table, - vector_mradds_type_table, - vector_vmsumubm_type_table, - vector_vmsumuhm_type_table, - vector_vmsummbm_type_table, - vector_vmsumshm_type_table, - vector_vmsumuhs_type_table, - vector_vmsumshs_type_table, - vector_vmuleub_type_table, - vector_vmulesb_type_table, - vector_vmuleuh_type_table, - vector_vmulesh_type_table, - vector_vmuloub_type_table, - vector_vmulosb_type_table, - vector_vmulouh_type_table, - vector_vmulosh_type_table, - vector_nmsub_type_table, - vector_nor_type_table, - vector_or_type_table, - vector_vpkuhum_type_table, - vector_vpkuwum_type_table, - vector_packpx_type_table, - vector_vpkuhus_type_table, - vector_vpkshss_type_table, - vector_vpkuwus_type_table, - vector_vpkswss_type_table, - vector_vpkshus_type_table, - vector_vpkswus_type_table, - vector_perm_type_table, - vector_re_type_table, - vector_vrlb_type_table, - vector_vrlh_type_table, - vector_vrlw_type_table, - vector_round_type_table, - vector_rsqrte_type_table, - vector_sel_type_table, - vector_vslb_type_table, - vector_vslh_type_table, - vector_vslw_type_table, - vector_sld_type_table, - vector_sll_type_table, - vector_slo_type_table, - vector_vspltb_type_table, - vector_vsplth_type_table, - vector_vspltw_type_table, - vector_vspltisb_type_table, - vector_vspltish_type_table, - vector_vspltisw_type_table, - vector_vsrb_type_table, - vector_vsrh_type_table, - vector_vsrw_type_table, - vector_vsrab_type_table, - vector_vsrah_type_table, - vector_vsraw_type_table, - vector_srl_type_table, - vector_sro_type_table, - vector_st_type_table, - vector_stvebx_type_table, - vector_stvehx_type_table, - vector_stvewx_type_table, - vector_stl_type_table, - vector_vsububm_type_table, - vector_vsubuhm_type_table, - vector_vsubuwm_type_table, - vector_vsubfp_type_table, - vector_subc_type_table, - vector_vsububs_type_table, - vector_vsubsbs_type_table, - vector_vsubuhs_type_table, - vector_vsubshs_type_table, - vector_vsubuws_type_table, - vector_vsubsws_type_table, - vector_vsum4ubs_type_table, - vector_vsum4sbs_type_table, - vector_vsum4shs_type_table, - vector_sum2s_type_table, - vector_sums_type_table, - vector_trunc_type_table, - vector_vupkhsb_type_table, - vector_vupklsb_type_table, - vector_vupkhpx_type_table, - vector_vupklpx_type_table, - vector_vupkhsh_type_table, - vector_vupklsh_type_table, - vector_xor_type_table, - vector_abs_type_table, - vector_abss_type_table, - NULL -}; - -int is_intrinsic_function_call(ENode *funccall) { - ENode *funcref = funccall->data.funccall.funcref; - return - ENODE_IS(funcref, EOBJREF) && - funcref->data.objref->datatype == DFUNC && - (TYPE_FUNC(funcref->data.objref->type)->flags & FUNC_INTRINSIC); -} - -static void abs_intrinsic(ENode *expr, short outputReg, Operand *output) { - int reg1; - int reg2; - Operand op; - - memclrw(&op, sizeof(op)); - GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); - - reg1 = ALLOC_GPR(); - emitpcode(PC_SRAWI, reg1, op.reg, 31); - - reg2 = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_XOR, reg2, reg1, op.reg); - emitpcode(PC_SUBF, reg2, reg1, reg2); - - output->optype = OpndType_GPR; - output->reg = reg2; -} - -static void setflm_intrinsic(ENode *expr, short outputReg, Operand *output, int flag) { - int reg; - Operand op; - - memclrw(&op, sizeof(op)); - GEN_NODE_TO_FPR(expr, &op, expr->rtype, 0); - - if (!flag) { - output->optype = OpndType_FPR; - reg = (outputReg && outputReg != op.reg) ? outputReg : ALLOC_FPR(); - emitpcode(PC_MFFS, output->reg = reg); - } - - emitpcode(PC_MTFSF, 255, op.reg); -} - -static void alloca_intrinsic(ENode *expr, short outputReg, Operand *output) { - int reg; - Operand op; - - memclrw(&op, sizeof(op)); - - if (ENODE_IS(expr, EINTCONST)) { - reg = outputReg ? outputReg : ALLOC_GPR(); - allocate_dynamic_stack_space( - 1, reg, ALLOC_GPR(), CInt64_GetULong(&expr->data.intval)); - } else { - GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0); - reg = outputReg ? outputReg : ALLOC_GPR(); - - emitpcode(PC_NEG, reg, op.reg); - emitpcode(PC_RLWINM, reg, reg, 0, 0, get_alloca_alignment()); - allocate_dynamic_stack_space(0, reg, ALLOC_GPR(), 0); - } - - output->optype = OpndType_GPR; - output->reg = reg; -} - -static void load_bytereversed_intrinsic(Opcode opcode, ENode *expr1, ENode *expr2, short outputReg, Operand *output) { - int reg; - Operand op1; - Operand op2; - - reg = outputReg ? outputReg : ALLOC_GPR(); - memclrw(&op1, sizeof(op1)); - memclrw(&op2, sizeof(op2)); - - if (ENODE_IS(expr2, EINTCONST) && expr2->data.intval.lo == 0) { - GEN_NODE(expr1, &op1); - if (op1.optype == OpndType_GPR_Indexed) { - emitpcode(opcode, reg, op1.reg, op1.regOffset); - } else { - ENSURE_GPR(&op1, expr1->rtype, 0); - emitpcode(opcode, reg, 0, op1.reg); - } - } else { - GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); - GEN_NODE_TO_GPR(expr2, &op2, expr2->rtype, 0); - emitpcode(opcode, reg, op1.reg, op2.reg); - } - - setpcodeflags(fSideEffects | ((expr1->flags | expr2->flags | output->flags) & (fIsConst | fIsVolatile))); - output->optype = OpndType_GPR; - output->reg = reg; -} - -static void store_bytereversed_intrinsic(Opcode opcode, ENode *expr1, ENode *expr2, ENode *expr3) { - Operand op1; - Operand op2; - Operand op3; - - memclrw(&op1, sizeof(op1)); - memclrw(&op2, sizeof(op2)); - memclrw(&op3, sizeof(op3)); - - if (ENODE_IS(expr3, EINTCONST) && expr3->data.intval.lo == 0) { - GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); - GEN_NODE(expr2, &op2); - if (op2.optype == OpndType_GPR_Indexed) { - emitpcode(opcode, op1.reg, op2.reg, op2.regOffset); - } else { - ENSURE_GPR(&op2, expr2->rtype, 0); - emitpcode(opcode, op1.reg, 0, op2.reg); - } - } else { - GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); - GEN_NODE_TO_GPR(expr2, &op2, expr2->rtype, 0); - GEN_NODE_TO_GPR(expr3, &op3, expr3->rtype, 0); - emitpcode(opcode, op1.reg, op2.reg, op3.reg); - } - - setpcodeflags(fSideEffects | ((op1.flags | op2.flags | op3.flags) & (fIsConst | fIsVolatile))); -} - -static void data_cache_block_intrinsic(Opcode opcode, ENode *expr1, ENode *expr2) { - Operand op1; - Operand op2; - - memclrw(&op1, sizeof(op1)); - memclrw(&op2, sizeof(op2)); - - if (ENODE_IS(expr2, EINTCONST) && expr2->data.intval.lo == 0) { - GEN_NODE(expr1, &op1); - if (op1.optype == OpndType_GPR_Indexed) { - emitpcode(opcode, op1.reg, op1.regOffset); - } else { - ENSURE_GPR(&op1, expr1->rtype, 0); - emitpcode(opcode, 0, op1.reg); - } - } else { - GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); - GEN_NODE_TO_GPR(expr2, &op2, expr2->rtype, 0); - emitpcode(opcode, op1.reg, op2.reg); - } -} - -static void memcpy_intrinsic(ENode *destexpr, ENode *srcexpr, SInt32 size, Boolean ignored, Operand *output) { - UInt32 qual; - Operand destOp; - Operand srcOp; - - qual = 0; - - memclrw(&destOp, sizeof(destOp)); - memclrw(&srcOp, sizeof(srcOp)); - - GEN_NODE(srcexpr, &srcOp); - indirect(&srcOp, srcexpr); - - GEN_NODE(destexpr, output); - destOp = *output; - indirect(&destOp, destexpr); - - if (destOp.object) - qual = destOp.object->qual; - - move_block(&destOp, &srcOp, size, destexpr->rtype ? CMach_AllocationAlignment(destexpr->rtype, qual) : 1); -} - -static SInt32 checkconstintarg(ENode *expr, char *name, SInt32 min, SInt32 max, int argnum) { - SInt32 value; - - if (!ENODE_IS(expr, EINTCONST)) - PPCError_ErrorTerm(PPCErrorStr210, name, 3, max, argnum); - - value = CInt64_GetULong(&expr->data.intval); - - if (value < min) { - PPCError_Warning(PPCErrorStr211, name, argnum, value, min, max, min); - return min; - } - - if (value > max) { - PPCError_Warning(PPCErrorStr211, name, argnum, value, min, max, value & max); - value = value & max; - } - - return value; -} - -static void rlwimi_intrinsic(ENode *expr1, ENode *expr2, ENode *expr3, ENode *expr4, ENode *expr5, short outputReg, Operand *output) { - SInt32 arg3; - SInt32 arg4; - SInt32 arg5; - Operand op1; - Operand op2; - int reg; - char *name = "__rlwimi"; - - memclrw(&op1, sizeof(op1)); - memclrw(&op2, sizeof(op2)); - - arg3 = checkconstintarg(expr3, name, 0, 31, 3); - arg4 = checkconstintarg(expr4, name, 0, 31, 4); - arg5 = checkconstintarg(expr5, name, 0, 31, 5); - - GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); - - GEN_NODE(expr2, &op2); - if (copts.optimizationlevel > 1) { - reg = ALLOC_GPR(); - emitpcode(PC_MR, reg, op1.reg); - op1.reg = reg; - } - ENSURE_GPR(&op2, expr2->rtype, 0); - - emitpcode(PC_RLWIMI, op1.reg, op2.reg, arg3, arg4, arg5); - - output->optype = OpndType_GPR; - output->reg = op1.reg; -} - -static void rlwinm_intrinsic(ENode *expr1, ENode *expr2, ENode *expr3, ENode *expr4, short outputReg, Operand *output) { - char *name = "__rlwinm"; - short reg; - short arg2; - short arg3; - short arg4; - Operand op1; - - memclrw(&op1, sizeof(op1)); - arg2 = checkconstintarg(expr2, name, 0, 31, 2); - arg3 = checkconstintarg(expr3, name, 0, 31, 3); - arg4 = checkconstintarg(expr4, name, 0, 31, 4); - - GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); - - reg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_RLWINM, reg, op1.reg, arg2, arg3, arg4); - - output->optype = OpndType_GPR; - output->reg = reg; -} - -static void rlwnm_intrinsic(ENode *expr1, ENode *expr2, ENode *expr3, ENode *expr4, short outputReg, Operand *output) { - short reg; - short arg3; - short arg4; - char *name = "__rlwnm"; - Operand op1; - Operand op2; - - memclrw(&op1, sizeof(op1)); - memclrw(&op2, sizeof(op2)); - arg3 = checkconstintarg(expr3, name, 0, 31, 3); - arg4 = checkconstintarg(expr4, name, 0, 31, 4); - - GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0); - GEN_NODE_TO_GPR(expr2, &op2, expr2->rtype, 0); - - reg = outputReg ? outputReg : ALLOC_GPR(); - emitpcode(PC_RLWNM, reg, op1.reg, op2.reg, arg3, arg4); - - output->optype = OpndType_GPR; - output->reg = reg; -} - -static Boolean promotable_types_are_equal(Type *a, Type *b) { - if (a == b) - return 1; - - if (a == TYPE(&stsignedint)) { - if ( - b == TYPE(&stunsignedint) || - b == TYPE(&stsignedchar) || - b == TYPE(&stunsignedchar) || - b == TYPE(&stsignedshort) || - b == TYPE(&stunsignedshort) || - b == TYPE(&stsignedlong) || - b == TYPE(&stunsignedlong) || - b == TYPE(&stbool) - ) - return 1; - } - - return 0; -} - -static int Intrinsics_VerifyParameterCount(int wantedCount, ENodeList *args, HashNameNode *name) { - ENodeList *scan; - int count; - - for (scan = args, count = 0; scan; scan = scan->next) - count++; - - if (count != wantedCount) { - PPCError_Error(PPCErrorStr103, name->name, count, wantedCount); - return 0; - } - - return 1; -} - -static ENode *Intrinsics_CreateIntrinsicFunc(Object *func, ENodeList *args, Type *rtype) { - TypeFunc *tfunc; - ENodeList *scan; - ENode *expr; - - tfunc = TYPE_FUNC(func->type); - CError_ASSERT(3741, IS_TYPE_FUNC(tfunc)); - - for (scan = args; scan; scan = scan->next) { - if (IS_TYPE_ARRAY(scan->node->rtype)) - scan->node = CExpr_PointerGeneration(scan->node); - } - - expr = lalloc(sizeof(ENode)); - expr->type = EFUNCCALL; - expr->cost = 4; - expr->rtype = rtype; - expr->ignored = 0; - expr->flags = tfunc->qual & ENODE_FLAG_QUALS; - expr->data.funccall.funcref = create_objectrefnode(func); - expr->data.funccall.args = args; - expr->data.funccall.functype = tfunc; - return CExpr_AdjustFunctionCall(expr); -} - -static Type *Intrinsics_Verify1VectorArg2Ops(Intrinsics id, ENodeList *args, HashNameNode *name) { - ENode *arg1; - TypeTable22 *table; - Type *typeA; - Type *typeB; - Type *rtype; - - arg1 = args->node; - - for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { - typeB = arg1->rtype; - typeA = table->arg1; - if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) { - typeA = TPTR_TARGET(typeA); - typeB = TPTR_TARGET(typeB); - } - if (promotable_types_are_equal(typeA, typeB)) - break; - } - - rtype = table->rtype; - if (!rtype) { - PPCError_Error(PPCErrorStr104, name->name, name->name, arg1->rtype, 0); - rtype = NULL; - } - return rtype; -} - -static Type *Intrinsics_VerifyNoVectorArgs(Intrinsics id, HashNameNode *name) { - TypeTable11 *table = typeTable[id - Intrinsic_042]; - return table->rtype; -} - -static Type *Intrinsics_Verify1VectorArg(Intrinsics id, ENodeList *args, HashNameNode *name) { - ENode *arg1; - TypeTable21 *table; - Type *typeA; - Type *typeB; - Type *rtype; - - arg1 = args->node; - - for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { - typeB = arg1->rtype; - typeA = table->arg1; - if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) { - typeA = TPTR_TARGET(typeA); - typeB = TPTR_TARGET(typeB); - } - if (promotable_types_are_equal(typeA, typeB)) - break; - } - - switch (id) { - case Intrinsic_104: - case Intrinsic_105: - case Intrinsic_106: - case Intrinsic_107: - case Intrinsic_108: - case Intrinsic_109: - case Intrinsic_269: - case Intrinsic_270: - case Intrinsic_271: - if (ENODE_IS(arg1, EINTCONST)) { - SInt32 val = arg1->data.intval.lo; - if (val > 15 || val < -16) { - PPCError_Error(PPCErrorStr108, name->name, name->name, 5); - return NULL; - } - } else { - PPCError_Error(PPCErrorStr108, name->name, name->name, 5); - return NULL; - } - break; - case Intrinsic_058: - if (ENODE_IS(arg1, EINTCONST)) { - SInt32 val = arg1->data.intval.lo; - if (val > 3 || val < 0) { - PPCError_Error(PPCErrorStr108, name->name, name->name, 2); - return NULL; - } - } else { - PPCError_Error(PPCErrorStr108, name->name, name->name, 2); - return NULL; - } - break; - } - - rtype = table->rtype; - if (!rtype) { - PPCError_Error(PPCErrorStr104, name->name, name->name, arg1->rtype, 0); - rtype = NULL; - } - return rtype; -} - -static Type *Intrinsics_Verify2VectorArgs(Intrinsics id, ENodeList *args, HashNameNode *name) { - ENode *arg1; - ENode *arg2; - TypeTable31 *table; - Type *typeB1; - Type *typeB2; - Type *typeA1; - Type *typeA2; - - arg1 = args->node; - arg2 = args->next->node; - table = typeTable[id - Intrinsic_042]; - - switch (id) { - case Intrinsic_055: - case Intrinsic_056: - case Intrinsic_057: - case Intrinsic_103: - case Intrinsic_190: - case Intrinsic_191: - case Intrinsic_192: - case Intrinsic_193: - case Intrinsic_266: - case Intrinsic_267: - case Intrinsic_268: - if (ENODE_IS(arg2, EINTCONST)) { - if (arg2->data.intval.lo > 31 || arg2->data.intval.hi < 0) { - PPCError_Error(PPCErrorStr108, name->name, name->name, 5); - return NULL; - } - } else { - PPCError_Error(PPCErrorStr108, name->name, name->name, 5); - return NULL; - } - break; - } - - for (; table->rtype; table++) { - typeB1 = arg1->rtype; - typeB2 = arg2->rtype; - typeA1 = table->arg1; - typeA2 = table->arg2; - if (IS_TYPE_POINTER(typeA1) && IS_TYPE_POINTER(typeB1)) { - typeA1 = TPTR_TARGET(typeA1); - typeB1 = TPTR_TARGET(typeB1); - } - if (IS_TYPE_POINTER(typeA2) && IS_TYPE_POINTER(typeB2)) { - typeA2 = TPTR_TARGET(typeA2); - typeB2 = TPTR_TARGET(typeB2); - } - if (promotable_types_are_equal(typeA1, typeB1) && - promotable_types_are_equal(typeA2, typeB2)) - break; - } - - if (!table->rtype) { - PPCError_Error(PPCErrorStr105, name->name, name->name, arg1->rtype, 0, arg2->rtype, 0); - return NULL; - } - - switch (id) { - case Intrinsic_066: - case Intrinsic_067: - case Intrinsic_068: - if (arg2->flags & ENODE_FLAG_VOLATILE) - PPCError_Warning(PPCErrorStr178, name->name); - } - - return table->rtype; -} - -static Type *Intrinsics_Verify3VectorArgs(Intrinsics id, ENodeList *args, HashNameNode *name) { - ENode *arg1; - ENode *arg2; - ENode *arg3; - TypeTable41 *table; - Type *typeB1; - Type *typeB2; - Type *typeB3; - Type *typeA1; - Type *typeA2; - Type *typeA3; - - arg1 = args->node; - arg2 = args->next->node; - arg3 = args->next->next->node; - - for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { - typeB1 = arg1->rtype; - typeB2 = arg2->rtype; - typeB3 = arg3->rtype; - typeA1 = table->arg1; - typeA2 = table->arg2; - typeA3 = table->arg3; - if (IS_TYPE_POINTER(typeA1) && IS_TYPE_POINTER(typeB1)) { - typeA1 = TPTR_TARGET(typeA1); - typeB1 = TPTR_TARGET(typeB1); - } - if (IS_TYPE_POINTER(typeA2) && IS_TYPE_POINTER(typeB2)) { - typeA2 = TPTR_TARGET(typeA2); - typeB2 = TPTR_TARGET(typeB2); - } - if (IS_TYPE_POINTER(typeA3) && IS_TYPE_POINTER(typeB3)) { - typeA3 = TPTR_TARGET(typeA3); - typeB3 = TPTR_TARGET(typeB3); - } - if (promotable_types_are_equal(typeA1, typeB1) && - promotable_types_are_equal(typeA2, typeB2) && - promotable_types_are_equal(typeA3, typeB3)) - break; - } - - switch (id) { - case Intrinsic_060: - case Intrinsic_061: - case Intrinsic_062: - case Intrinsic_063: - if (ENODE_IS(arg3, EINTCONST)) { - SInt32 val = arg3->data.intval.lo; - if (val > 3 || val < 0) { - PPCError_Error(PPCErrorStr108, name->name, name->name, 2); - return NULL; - } - } else { - PPCError_Error(PPCErrorStr108, name->name, name->name, 2); - return NULL; - } - break; - case Intrinsic_100: - case Intrinsic_263: - if (ENODE_IS(arg3, EINTCONST)) { - if (arg3->data.intval.lo > 15 || arg3->data.intval.hi < 0) { - PPCError_Error(PPCErrorStr108, name->name, name->name, 4); - return NULL; - } - } else { - PPCError_Error(PPCErrorStr108, name->name, name->name, 4); - return NULL; - } - break; - } - - if (!table->rtype) { - PPCError_Error(PPCErrorStr106, name->name, name->name, arg1->rtype, 0, arg2->rtype, 0, arg3->rtype, 0); - return NULL; - } - - switch (id) { - case Intrinsic_114: - case Intrinsic_115: - case Intrinsic_116: - if (arg3->flags & ENODE_FLAG_VOLATILE) - PPCError_Warning(PPCErrorStr178, name->name); - } - - return table->rtype; -} - -static Opcode Intrinsics_FindOpcodeNoArgs(Intrinsics id, ENode *funccall) { - TypeTable11 *table = typeTable[id - Intrinsic_042]; - return table->opcode; -} - -static Opcode Intrinsics_FindOpcode1Arg(Intrinsics id, ENode *funccall, ENode *arg1) { - TypeTable21 *table; - Type *typeA; - Type *typeB; - - for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { - typeB = arg1->rtype; - typeA = table->arg1; - if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) { - typeA = TPTR_TARGET(typeA); - typeB = TPTR_TARGET(typeB); - } - if (promotable_types_are_equal(typeA, typeB)) - break; - } - - CError_ASSERT(4105, table->rtype); - return table->opcode; -} - -static Opcode Intrinsics_FindOpcode2Args(Intrinsics id, ENode *funccall, ENode *arg1, ENode *arg2) { - TypeTable31 *table; - Type *typeB1; - Type *typeB2; - Type *typeA1; - Type *typeA2; - - for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { - typeB1 = arg1->rtype; - typeB2 = arg2->rtype; - typeA1 = table->arg1; - typeA2 = table->arg2; - if (IS_TYPE_POINTER(typeA1) && IS_TYPE_POINTER(typeB1)) { - typeA1 = TPTR_TARGET(typeA1); - typeB1 = TPTR_TARGET(typeB1); - } - if (IS_TYPE_POINTER(typeA2) && IS_TYPE_POINTER(typeB2)) { - typeA2 = TPTR_TARGET(typeA2); - typeB2 = TPTR_TARGET(typeB2); - } - if (promotable_types_are_equal(typeA1, typeB1) && - promotable_types_are_equal(typeA2, typeB2)) - break; - } - - CError_ASSERT(4144, table->rtype); - return table->opcode; -} - -static Opcode Intrinsics_FindOpcode3Args(Intrinsics id, ENode *funccall, ENode *arg1, ENode *arg2, ENode *arg3) { - TypeTable41 *table; - Type *typeB1; - Type *typeB2; - Type *typeB3; - Type *typeA1; - Type *typeA2; - Type *typeA3; - - for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { - typeB1 = arg1->rtype; - typeB2 = arg2->rtype; - typeB3 = arg3->rtype; - typeA1 = table->arg1; - typeA2 = table->arg2; - typeA3 = table->arg3; - if (IS_TYPE_POINTER(typeA1) && IS_TYPE_POINTER(typeB1)) { - typeA1 = TPTR_TARGET(typeA1); - typeB1 = TPTR_TARGET(typeB1); - } - if (IS_TYPE_POINTER(typeA2) && IS_TYPE_POINTER(typeB2)) { - typeA2 = TPTR_TARGET(typeA2); - typeB2 = TPTR_TARGET(typeB2); - } - if (IS_TYPE_POINTER(typeA3) && IS_TYPE_POINTER(typeB3)) { - typeA3 = TPTR_TARGET(typeA3); - typeB3 = TPTR_TARGET(typeB3); - } - if (promotable_types_are_equal(typeA1, typeB1) && - promotable_types_are_equal(typeA2, typeB2) && - promotable_types_are_equal(typeA3, typeB3)) - break; - } - - CError_ASSERT(4191, table->rtype); - return table->opcode; -} - -static void vector_intrinsic_no_args(Opcode opcode) { - emitpcode(opcode); -} - -static void vector_intrinsic_mfvscr(short outputReg, Opcode opcode, Operand *output) { - short reg; - - reg = outputReg ? outputReg : ALLOC_VR(); - - emitpcode(opcode, reg); - - output->optype = OpndType_VR; - output->reg = reg; -} - -static void vector_intrinsic_1arg(ENode *arg1, short outputReg, Operand *output, Opcode opcode) { - Operand op1; - short reg; - - memclrw(&op1, sizeof(op1)); - GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); - - reg = outputReg ? outputReg : ALLOC_VR(); - - emitpcode(opcode, reg, op1.reg); - - output->optype = OpndType_VR; - output->reg = reg; -} - -static void vector_intrinsic_splats(ENode *arg1, short outputReg, Operand *output, Opcode opcode) { - Operand op1; - short reg; - - memclrw(&op1, sizeof(op1)); - CError_ASSERT(4253, ENODE_IS(arg1, EINTCONST)); - GEN_NODE(arg1, &op1); - - reg = outputReg ? outputReg : ALLOC_VR(); - - emitpcode(opcode, reg, op1.immediate); - - output->optype = OpndType_VR; - output->reg = reg; -} - -static void vector_intrinsic_splatu8(ENode *arg1, short outputReg, Operand *output, Opcode opcode) { - Operand op1; - short reg; - - memclrw(&op1, sizeof(op1)); - CError_ASSERT(4277, ENODE_IS(arg1, EINTCONST)); - GEN_NODE(arg1, &op1); - - reg = outputReg ? outputReg : ALLOC_VR(); - - emitpcode(opcode, reg, op1.immediate); - - output->optype = OpndType_VR; - output->reg = reg; -} - -static void vector_intrinsic_splatu16(ENode *arg1, short outputReg, Operand *output, Opcode opcode) { - Operand op1; - short reg; - - memclrw(&op1, sizeof(op1)); - CError_ASSERT(4301, ENODE_IS(arg1, EINTCONST)); - GEN_NODE(arg1, &op1); - - reg = outputReg ? outputReg : ALLOC_VR(); - - emitpcode(opcode, reg, op1.immediate); - - output->optype = OpndType_VR; - output->reg = reg; -} - -static void vector_intrinsic_splatu32(ENode *arg1, short outputReg, Operand *output, Opcode opcode) { - Operand op1; - short reg; - - memclrw(&op1, sizeof(op1)); - CError_ASSERT(4325, ENODE_IS(arg1, EINTCONST)); - GEN_NODE(arg1, &op1); - - reg = outputReg ? outputReg : ALLOC_VR(); - - emitpcode(opcode, reg, op1.immediate); - - output->optype = OpndType_VR; - output->reg = reg; -} - -static void vector_intrinsic_dss(ENode *arg1) { - Operand op1; - - memclrw(&op1, sizeof(op1)); - CError_ASSERT(4348, ENODE_IS(arg1, EINTCONST)); - GEN_NODE(arg1, &op1); - - emitpcode(PC_DSS, op1.immediate, 0); -} - -static void vector_intrinsic_2args(ENode *arg1, ENode *arg2, short outputReg, Operand *output, Opcode opcode) { - Operand op1; - Operand op2; - short reg; - - memclrw(&op1, sizeof(op1)); - memclrw(&op2, sizeof(op2)); - GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); - GEN_NODE_TO_VR(arg2, &op2, arg2->rtype, 0); - - reg = outputReg ? outputReg : ALLOC_VR(); - - emitpcode(opcode, reg, op1.reg, op2.reg); - - output->optype = OpndType_VR; - output->reg = reg; -} - -static void vector_intrinsic_2args1const(ENode *arg1, ENode *arg2, short outputReg, Operand *output, Opcode opcode) { - Operand op1; - Operand op2; - short reg; - - memclrw(&op1, sizeof(op1)); - memclrw(&op2, sizeof(op2)); - CError_ASSERT(4393, ENODE_IS(arg2, EINTCONST)); - GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); - GEN_NODE(arg2, &op2); - - reg = outputReg ? outputReg : ALLOC_VR(); - - emitpcode(opcode, reg, op1.reg, op2.immediate); - - output->optype = OpndType_VR; - output->reg = reg; -} - -static void vector_intrinsic_3args(ENode *arg1, ENode *arg2, ENode *arg3, short outputReg, Operand *output, Opcode opcode) { - Operand op1; - Operand op2; - Operand op3; - short reg; - - memclrw(&op1, sizeof(op1)); - memclrw(&op2, sizeof(op2)); - memclrw(&op3, sizeof(op3)); - GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); - GEN_NODE_TO_VR(arg2, &op2, arg2->rtype, 0); - GEN_NODE_TO_VR(arg3, &op3, arg3->rtype, 0); - - reg = outputReg ? outputReg : ALLOC_VR(); - - emitpcode(opcode, reg, op1.reg, op2.reg, op3.reg); - - output->optype = OpndType_VR; - output->reg = reg; -} - -static void vector_intrinsic_datastream(ENode *arg1, ENode *arg2, ENode *arg3, Opcode opcode) { - Operand op1; - Operand op2; - - memclrw(&op1, sizeof(op1)); - memclrw(&op2, sizeof(op2)); - CError_ASSERT(4445, ENODE_IS(arg3, EINTCONST)); - GEN_NODE_TO_GPR(arg1, &op1, arg1->rtype, 0); - GEN_NODE_TO_GPR(arg2, &op2, arg2->rtype, 0); - - switch (opcode) { - case PC_DST: - case PC_DSTST: - emitpcode(opcode, op1.reg, op2.reg, arg3->data.intval.lo, 0); - break; - case PC_DSTT: - case PC_DSTSTT: - emitpcode(opcode, op1.reg, op2.reg, arg3->data.intval.lo); - break; - default: - CError_FATAL(4463); - } -} - -static void vector_intrinsic_sld(ENode *arg1, ENode *arg2, ENode *arg3, short outputReg, Operand *output, Opcode opcode) { - Operand op1; - Operand op2; - short reg; - - memclrw(&op1, sizeof(op1)); - memclrw(&op2, sizeof(op2)); - CError_ASSERT(4479, ENODE_IS(arg3, EINTCONST)); - GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); - GEN_NODE_TO_VR(arg2, &op2, arg2->rtype, 0); - reg = outputReg ? outputReg : ALLOC_VR(); - - emitpcode(opcode, reg, op1.reg, op2.reg, arg3->data.intval.lo); - output->optype = OpndType_VR; - output->reg = reg; -} - -static void vector_intrinsic_load(ENode *arg1, ENode *arg2, short outputReg, Operand *output, Opcode opcode) { - Operand op1; - Operand op2; - short reg; - - memclrw(&op1, sizeof(op1)); - memclrw(&op2, sizeof(op2)); - - GEN_NODE(arg1, &op1); - if (op1.optype == OpndType_Absolute && op1.immediate == 0) { - op1.optype = OpndType_GPR; - op1.reg = 0; - } else { - ENSURE_GPR(&op1, arg1->rtype, 0); - } - - GEN_NODE(arg2, &op2); - if (op2.optype == OpndType_Absolute && op2.immediate == 0 && op1.reg != 0) { - op2 = op1; - op1.optype = OpndType_GPR; - op1.reg = 0; - } else { - ENSURE_GPR(&op2, arg2->rtype, 0); - } - - reg = outputReg ? outputReg : ALLOC_VR(); - - emitpcode(opcode, reg, op1.reg, op2.reg); - output->optype = OpndType_VR; - output->reg = reg; -} - -static void vector_intrinsic_store(ENode *arg1, ENode *arg2, ENode *arg3, short outputReg, Operand *output, Opcode opcode) { - Operand op1; - Operand op2; - Operand op3; - - memclrw(&op1, sizeof(op1)); - memclrw(&op2, sizeof(op2)); - memclrw(&op3, sizeof(op3)); - - GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); - - GEN_NODE(arg2, &op2); - if (op2.optype == OpndType_Absolute && op2.immediate == 0) { - op2.optype = OpndType_GPR; - op2.reg = 0; - } else { - ENSURE_GPR(&op2, arg2->rtype, 0); - } - - GEN_NODE(arg3, &op3); - if (op3.optype == OpndType_Absolute && op3.immediate == 0 && op2.reg != 0) { - op3 = op2; - op2.optype = OpndType_GPR; - op2.reg = 0; - } else { - ENSURE_GPR(&op3, arg3->rtype, 0); - } - - emitpcode(opcode, op1.reg, op2.reg, op3.reg); - output->optype = OpndType_VR; - output->reg = op1.reg; -} - -static void vector_intrinsic_abs(Intrinsics id, ENode *funccall, ENode *arg1, short outputReg, Operand *output) { - TypeTable22 *table; - Type *typeA; - Type *typeB; - short reg1; - short reg2; - short reg3; - Operand op1; - - for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { - typeB = arg1->rtype; - typeA = table->arg1; - if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) { - typeA = TPTR_TARGET(typeA); - typeB = TPTR_TARGET(typeB); - } - if (promotable_types_are_equal(typeA, typeB)) - break; - } - - CError_ASSERT(4617, table->rtype); - - reg1 = ALLOC_VR(); - reg2 = ALLOC_VR(); - reg3 = outputReg ? outputReg : ALLOC_VR(); - - memclrw(&op1, sizeof(op1)); - GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); - - if (arg1->rtype == TYPE(&stvectorfloat)) { - emitpcode(PC_VSPLTISW, reg1, -1); - emitpcode(PC_VSLW, reg2, reg1, reg1); - emitpcode(table->opcode1, reg3, op1.reg, reg2); - } else { - emitpcode(PC_VSPLTISB, reg1, 0); - emitpcode(table->opcode1, reg2, reg1, op1.reg); - emitpcode(table->opcode2, reg3, op1.reg, reg2); - } - - output->optype = OpndType_VR; - output->reg = reg3; -} - -static void vector_intrinsic_abss(Intrinsics id, ENode *funccall, ENode *arg1, short outputReg, Operand *output) { - TypeTable22 *table; - Type *typeA; - Type *typeB; - short reg1; - short reg2; - short reg3; - Operand op1; - - for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) { - typeB = arg1->rtype; - typeA = table->arg1; - if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) { - typeA = TPTR_TARGET(typeA); - typeB = TPTR_TARGET(typeB); - } - if (promotable_types_are_equal(typeA, typeB)) - break; - } - - CError_ASSERT(4683, table->rtype); - - reg1 = ALLOC_VR(); - reg2 = ALLOC_VR(); - reg3 = outputReg ? outputReg : ALLOC_VR(); - - memclrw(&op1, sizeof(op1)); - GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); - - emitpcode(PC_VSPLTISB, reg1, 0); - emitpcode(table->opcode1, reg2, reg1, op1.reg); - emitpcode(table->opcode2, reg3, op1.reg, reg2); - - output->optype = OpndType_VR; - output->reg = reg3; -} - -static void vector_intrinsic_mtvscr(ENode *arg1, Operand *output, Opcode opcode) { - Operand op1; - - memclrw(&op1, sizeof(op1)); - GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); - emitpcode(opcode, op1.reg); -} - -static void vector_predicate_2args(ENode *arg1, ENode *arg2, short outputReg, Operand *output, Opcode opcode, Intrinsics id) { - Operand op1; - Operand op2; - short reg1; - short reg2; - short reg3; - Opcode cond; - - memclrw(&op1, sizeof(op1)); - memclrw(&op2, sizeof(op2)); - - GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); - GEN_NODE_TO_VR(arg2, &op2, arg2->rtype, 0); - - reg1 = ALLOC_VR(); - reg2 = op1.reg; - reg3 = op2.reg; - if ( - ((id == Intrinsic_132 || id == Intrinsic_145) && arg1->rtype != TYPE(&stvectorfloat)) || - ((id == Intrinsic_135 || id == Intrinsic_147) && arg1->rtype == TYPE(&stvectorfloat)) || - id == Intrinsic_136 || - id == Intrinsic_148 || - id == Intrinsic_153 || - id == Intrinsic_141 || - id == Intrinsic_142 || - id == Intrinsic_154 - ) - { - reg3 = op1.reg; - reg2 = op2.reg; - } - emitpcode(opcode, reg1, reg2, reg3); - pcsetrecordbit(pclastblock->lastPCode); - - if (arg1->rtype == TYPE(&stvectorfloat)) { - switch (id) { - case Intrinsic_131: - case Intrinsic_132: - case Intrinsic_133: - case Intrinsic_135: - case Intrinsic_136: - cond = ELESS; - break; - case Intrinsic_150: - case Intrinsic_151: - case Intrinsic_152: - case Intrinsic_153: - case Intrinsic_154: - cond = EGREATEREQU; - break; - case Intrinsic_134: - case Intrinsic_138: - case Intrinsic_139: - case Intrinsic_140: - case Intrinsic_141: - case Intrinsic_142: - cond = EEQU; - break; - case Intrinsic_144: - case Intrinsic_145: - case Intrinsic_146: - case Intrinsic_147: - case Intrinsic_148: - case Intrinsic_156: - cond = ENOTEQU; - break; - default: - CError_FATAL(4805); - } - } else { - switch (id) { - case Intrinsic_131: - case Intrinsic_133: - case Intrinsic_136: - cond = ELESS; - break; - case Intrinsic_144: - case Intrinsic_146: - case Intrinsic_148: - cond = ENOTEQU; - break; - case Intrinsic_132: - case Intrinsic_135: - case Intrinsic_138: - cond = EEQU; - break; - case Intrinsic_145: - case Intrinsic_147: - case Intrinsic_150: - cond = EGREATEREQU; - break; - default: - CError_FATAL(4834); - } - } - - output->optype = OpndType_CRField; - output->reg = 6; - output->regOffset = cond; -} - -static void vector_predicate_1arg(ENode *arg1, short outputReg, Operand *output, Opcode opcode, Intrinsics id) { - Operand op1; - short reg; - Opcode cond; - - memclrw(&op1, sizeof(op1)); - - GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0); - - reg = ALLOC_VR(); - emitpcode(opcode, reg, op1.reg, op1.reg); - pcsetrecordbit(pclastblock->lastPCode); - - switch (id) { - case Intrinsic_143: - cond = ELESS; - break; - case Intrinsic_149: - cond = EGREATEREQU; - break; - case Intrinsic_137: - cond = EEQU; - break; - case Intrinsic_155: - cond = ENOTEQU; - break; - default: - CError_FATAL(4878); - } - - output->optype = OpndType_CRField; - output->reg = 6; - output->regOffset = cond; -} - -ENode *Intrinsics_HandleIntrinsicCall(Object *func, ENodeList *args) { - ENode *callexpr; - Type *rtype; - Intrinsics id; - - callexpr = NULL; - - if (copts.altivec_model) { - id = func->u.func.u.intrinsicid; - switch (id) { - case Intrinsic_060: - case Intrinsic_061: - case Intrinsic_062: - case Intrinsic_063: - case Intrinsic_072: - case Intrinsic_073: - case Intrinsic_079: - case Intrinsic_080: - case Intrinsic_081: - case Intrinsic_082: - case Intrinsic_086: - case Intrinsic_093: - case Intrinsic_098: - case Intrinsic_100: - case Intrinsic_114: - case Intrinsic_115: - case Intrinsic_116: - case Intrinsic_202: - case Intrinsic_203: - case Intrinsic_224: - case Intrinsic_225: - case Intrinsic_226: - case Intrinsic_227: - case Intrinsic_228: - case Intrinsic_229: - case Intrinsic_230: - case Intrinsic_231: - case Intrinsic_240: - case Intrinsic_252: - case Intrinsic_259: - case Intrinsic_263: - case Intrinsic_280: - case Intrinsic_281: - case Intrinsic_282: - case Intrinsic_283: - case Intrinsic_284: - if (Intrinsics_VerifyParameterCount(3, args, func->name)) { - if ((rtype = Intrinsics_Verify3VectorArgs(id, args, func->name))) - callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype); - } - break; - case Intrinsic_042: - case Intrinsic_043: - case Intrinsic_044: - case Intrinsic_045: - case Intrinsic_046: - case Intrinsic_047: - case Intrinsic_049: - case Intrinsic_050: - case Intrinsic_051: - case Intrinsic_052: - case Intrinsic_053: - case Intrinsic_054: - case Intrinsic_055: - case Intrinsic_056: - case Intrinsic_057: - case Intrinsic_066: - case Intrinsic_067: - case Intrinsic_068: - case Intrinsic_070: - case Intrinsic_071: - case Intrinsic_074: - case Intrinsic_075: - case Intrinsic_076: - case Intrinsic_078: - case Intrinsic_084: - case Intrinsic_085: - case Intrinsic_087: - case Intrinsic_088: - case Intrinsic_089: - case Intrinsic_090: - case Intrinsic_091: - case Intrinsic_092: - case Intrinsic_095: - case Intrinsic_099: - case Intrinsic_101: - case Intrinsic_102: - case Intrinsic_103: - case Intrinsic_110: - case Intrinsic_111: - case Intrinsic_112: - case Intrinsic_113: - case Intrinsic_117: - case Intrinsic_118: - case Intrinsic_119: - case Intrinsic_120: - case Intrinsic_121: - case Intrinsic_122: - case Intrinsic_124: - case Intrinsic_125: - case Intrinsic_126: - case Intrinsic_127: - case Intrinsic_130: - case Intrinsic_131: - case Intrinsic_132: - case Intrinsic_133: - case Intrinsic_134: - case Intrinsic_135: - case Intrinsic_136: - case Intrinsic_138: - case Intrinsic_139: - case Intrinsic_140: - case Intrinsic_141: - case Intrinsic_142: - case Intrinsic_144: - case Intrinsic_145: - case Intrinsic_146: - case Intrinsic_147: - case Intrinsic_148: - case Intrinsic_150: - case Intrinsic_151: - case Intrinsic_152: - case Intrinsic_153: - case Intrinsic_154: - case Intrinsic_156: - case Intrinsic_157: - case Intrinsic_158: - case Intrinsic_159: - case Intrinsic_160: - case Intrinsic_161: - case Intrinsic_162: - case Intrinsic_163: - case Intrinsic_164: - case Intrinsic_165: - case Intrinsic_166: - case Intrinsic_167: - case Intrinsic_168: - case Intrinsic_169: - case Intrinsic_170: - case Intrinsic_171: - case Intrinsic_172: - case Intrinsic_173: - case Intrinsic_174: - case Intrinsic_175: - case Intrinsic_177: - case Intrinsic_178: - case Intrinsic_179: - case Intrinsic_180: - case Intrinsic_181: - case Intrinsic_182: - case Intrinsic_183: - case Intrinsic_184: - case Intrinsic_185: - case Intrinsic_186: - case Intrinsic_187: - case Intrinsic_188: - case Intrinsic_189: - case Intrinsic_190: - case Intrinsic_191: - case Intrinsic_192: - case Intrinsic_193: - case Intrinsic_196: - case Intrinsic_197: - case Intrinsic_198: - case Intrinsic_199: - case Intrinsic_200: - case Intrinsic_204: - case Intrinsic_205: - case Intrinsic_206: - case Intrinsic_207: - case Intrinsic_208: - case Intrinsic_209: - case Intrinsic_210: - case Intrinsic_211: - case Intrinsic_212: - case Intrinsic_213: - case Intrinsic_214: - case Intrinsic_215: - case Intrinsic_216: - case Intrinsic_217: - case Intrinsic_218: - case Intrinsic_219: - case Intrinsic_220: - case Intrinsic_221: - case Intrinsic_222: - case Intrinsic_223: - case Intrinsic_232: - case Intrinsic_233: - case Intrinsic_234: - case Intrinsic_235: - case Intrinsic_236: - case Intrinsic_237: - case Intrinsic_238: - case Intrinsic_239: - case Intrinsic_241: - case Intrinsic_242: - case Intrinsic_243: - case Intrinsic_244: - case Intrinsic_245: - case Intrinsic_246: - case Intrinsic_247: - case Intrinsic_248: - case Intrinsic_249: - case Intrinsic_250: - case Intrinsic_251: - case Intrinsic_254: - case Intrinsic_255: - case Intrinsic_256: - case Intrinsic_260: - case Intrinsic_261: - case Intrinsic_262: - case Intrinsic_264: - case Intrinsic_265: - case Intrinsic_266: - case Intrinsic_267: - case Intrinsic_268: - case Intrinsic_272: - case Intrinsic_273: - case Intrinsic_274: - case Intrinsic_275: - case Intrinsic_276: - case Intrinsic_277: - case Intrinsic_278: - case Intrinsic_279: - case Intrinsic_285: - case Intrinsic_286: - case Intrinsic_287: - case Intrinsic_288: - case Intrinsic_289: - case Intrinsic_290: - case Intrinsic_291: - case Intrinsic_292: - case Intrinsic_293: - case Intrinsic_294: - case Intrinsic_295: - case Intrinsic_296: - case Intrinsic_297: - case Intrinsic_298: - case Intrinsic_299: - case Intrinsic_300: - case Intrinsic_308: - if (Intrinsics_VerifyParameterCount(2, args, func->name)) { - if ((rtype = Intrinsics_Verify2VectorArgs(id, args, func->name))) - callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype); - } - break; - case Intrinsic_048: - case Intrinsic_058: - case Intrinsic_064: - case Intrinsic_065: - case Intrinsic_069: - case Intrinsic_083: - case Intrinsic_094: - case Intrinsic_096: - case Intrinsic_097: - case Intrinsic_104: - case Intrinsic_105: - case Intrinsic_106: - case Intrinsic_107: - case Intrinsic_108: - case Intrinsic_109: - case Intrinsic_123: - case Intrinsic_128: - case Intrinsic_129: - case Intrinsic_137: - case Intrinsic_143: - case Intrinsic_149: - case Intrinsic_155: - case Intrinsic_176: - case Intrinsic_194: - case Intrinsic_195: - case Intrinsic_201: - case Intrinsic_253: - case Intrinsic_257: - case Intrinsic_258: - case Intrinsic_269: - case Intrinsic_270: - case Intrinsic_271: - case Intrinsic_301: - case Intrinsic_302: - case Intrinsic_303: - case Intrinsic_304: - case Intrinsic_305: - case Intrinsic_306: - case Intrinsic_307: - if (Intrinsics_VerifyParameterCount(1, args, func->name)) { - if ((rtype = Intrinsics_Verify1VectorArg(id, args, func->name))) - callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype); - } - break; - case Intrinsic_059: - case Intrinsic_077: - if (Intrinsics_VerifyParameterCount(0, args, func->name)) { - if ((rtype = Intrinsics_VerifyNoVectorArgs(id, func->name))) - callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype); - } - break; - case Intrinsic_309: - case Intrinsic_310: - if (Intrinsics_VerifyParameterCount(1, args, func->name)) { - if ((rtype = Intrinsics_Verify1VectorArg2Ops(id, args, func->name))) - callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype); - } - break; - } - } - - return callexpr; -} - -void call_intrinsic_function(ENode *funccall, short outputReg, Operand *output) { - ENodeList *args; - Object *object; - Intrinsics id; - Opcode op; - short reg; - - static Opcode opcode[MaxIntrinsics] = { - /* Intrinsic_000 */ PC_EIEIO, - /* Intrinsic_001 */ PC_SYNC, - /* Intrinsic_002 */ PC_ISYNC, - 0, - 0, - /* Intrinsic_005 */ PC_FABS, - /* Intrinsic_006 */ PC_FNABS, - 0, - 0, - /* Intrinsic_009 */ PC_CNTLZW, - /* Intrinsic_010 */ PC_LHBRX, - /* Intrinsic_011 */ PC_LWBRX, - /* Intrinsic_012 */ PC_STHBRX, - /* Intrinsic_013 */ PC_STWBRX, - /* Intrinsic_014 */ PC_DCBF, - /* Intrinsic_015 */ PC_DCBT, - /* Intrinsic_016 */ PC_DCBST, - /* Intrinsic_017 */ PC_DCBTST, - /* Intrinsic_018 */ PC_DCBZ, - /* Intrinsic_019 */ PC_MULHW, - /* Intrinsic_020 */ PC_MULHWU, - /* Intrinsic_021 */ PC_DIVW, - /* Intrinsic_022 */ PC_DIVWU, - /* Intrinsic_023 */ PC_FMADD, - /* Intrinsic_024 */ PC_FMSUB, - /* Intrinsic_025 */ PC_FNMADD, - /* Intrinsic_026 */ PC_FNMSUB, - /* Intrinsic_027 */ PC_FMADDS, - /* Intrinsic_028 */ PC_FMSUBS, - /* Intrinsic_029 */ PC_FNMADDS, - /* Intrinsic_030 */ PC_FNMSUBS, - /* Intrinsic_031 */ PC_MFFS, - /* Intrinsic_032 */ PC_FRES, - /* Intrinsic_033 */ PC_FRSQRTE, - /* Intrinsic_004 */ PC_FSEL, - 0, - 0, - /* Intrinsic_037 */ PC_RLWIMI, - /* Intrinsic_038 */ PC_RLWINM, - /* Intrinsic_039 */ PC_RLWNM, - /* Intrinsic_040 */ PC_FABS, - /* Intrinsic_041 */ PC_FNABS - }; - - args = funccall->data.funccall.args; - object = funccall->data.funccall.funcref->data.objref; - id = object->u.func.u.intrinsicid; - cur_intrinsic_object = object; - - switch (id) { - case Intrinsic_000: - case Intrinsic_001: - case Intrinsic_002: - appendpcode(pclastblock, makepcode(opcode[id])); - output->optype = OpndType_Absolute; - break; - case Intrinsic_003: - case Intrinsic_004: - abs_intrinsic(args->node, outputReg, output); - break; - case Intrinsic_005: - case Intrinsic_006: - case Intrinsic_032: - case Intrinsic_033: - case Intrinsic_040: - case Intrinsic_041: - fp_unary_operator(opcode[id], args->node, outputReg, output); - break; - case Intrinsic_007: - setflm_intrinsic(args->node, outputReg, output, funccall->ignored); - break; - case Intrinsic_008: - alloca_intrinsic(args->node, outputReg, output); - break; - case Intrinsic_009: - unary_operator(PC_CNTLZW, args->node, outputReg, output); - break; - case Intrinsic_010: - case Intrinsic_011: - load_bytereversed_intrinsic(opcode[id], args->node, args->next->node, outputReg, output); - break; - case Intrinsic_012: - case Intrinsic_013: - store_bytereversed_intrinsic(opcode[id], args->node, args->next->node, args->next->next->node); - output->optype = OpndType_Absolute; - break; - case Intrinsic_014: - case Intrinsic_015: - case Intrinsic_016: - case Intrinsic_017: - case Intrinsic_018: - data_cache_block_intrinsic(opcode[id], args->node, args->next->node); - output->optype = OpndType_Absolute; - break; - case Intrinsic_019: - case Intrinsic_020: - case Intrinsic_021: - case Intrinsic_022: - binary_operator(opcode[id], args->node, args->next->node, outputReg, output); - break; - case Intrinsic_023: - case Intrinsic_024: - case Intrinsic_025: - case Intrinsic_026: - case Intrinsic_027: - case Intrinsic_028: - case Intrinsic_029: - case Intrinsic_030: - case Intrinsic_034: - fp_multiply_add(opcode[id], - args->node, args->next->node, args->next->next->node, - outputReg, output); - break; - case Intrinsic_031: - reg = outputReg ? outputReg : ALLOC_FPR(); - emitpcode(PC_MFFS, output->reg = reg); - output->optype = OpndType_FPR; - break; - case Intrinsic_035: - call_function(funccall, output); - break; - case Intrinsic_036: - if (ENODE_IS(args->next->next->node, EINTCONST)) - memcpy_intrinsic( - args->node, args->next->node, args->next->next->node->data.intval.lo, - funccall->ignored, output); - else - call_function(funccall, output); - break; - case Intrinsic_037: - rlwimi_intrinsic( - args->node, - args->next->node, - args->next->next->node, - args->next->next->next->node, - args->next->next->next->next->node, - outputReg, output); - break; - case Intrinsic_038: - rlwinm_intrinsic( - args->node, - args->next->node, - args->next->next->node, - args->next->next->next->node, - outputReg, output); - break; - case Intrinsic_039: - rlwnm_intrinsic( - args->node, - args->next->node, - args->next->next->node, - args->next->next->next->node, - outputReg, output); - break; - case Intrinsic_072: - case Intrinsic_073: - case Intrinsic_079: - case Intrinsic_080: - case Intrinsic_081: - case Intrinsic_082: - case Intrinsic_086: - case Intrinsic_093: - case Intrinsic_098: - case Intrinsic_202: - case Intrinsic_203: - case Intrinsic_224: - case Intrinsic_225: - case Intrinsic_226: - case Intrinsic_227: - case Intrinsic_228: - case Intrinsic_229: - case Intrinsic_230: - case Intrinsic_231: - case Intrinsic_240: - case Intrinsic_252: - case Intrinsic_259: - op = Intrinsics_FindOpcode3Args(id, funccall, args->node, args->next->node, args->next->next->node); - vector_intrinsic_3args(args->node, args->next->node, args->next->next->node, outputReg, output, op); - break; - case Intrinsic_100: - case Intrinsic_263: - op = Intrinsics_FindOpcode3Args(id, funccall, args->node, args->next->node, args->next->next->node); - vector_intrinsic_sld(args->node, args->next->node, args->next->next->node, outputReg, output, op); - break; - case Intrinsic_042: - case Intrinsic_043: - case Intrinsic_044: - case Intrinsic_045: - case Intrinsic_046: - case Intrinsic_047: - case Intrinsic_049: - case Intrinsic_050: - case Intrinsic_051: - case Intrinsic_053: - case Intrinsic_074: - case Intrinsic_075: - case Intrinsic_076: - case Intrinsic_078: - case Intrinsic_084: - case Intrinsic_085: - case Intrinsic_087: - case Intrinsic_088: - case Intrinsic_089: - case Intrinsic_090: - case Intrinsic_091: - case Intrinsic_092: - case Intrinsic_095: - case Intrinsic_099: - case Intrinsic_101: - case Intrinsic_102: - case Intrinsic_110: - case Intrinsic_111: - case Intrinsic_112: - case Intrinsic_113: - case Intrinsic_117: - case Intrinsic_118: - case Intrinsic_119: - case Intrinsic_120: - case Intrinsic_121: - case Intrinsic_122: - case Intrinsic_124: - case Intrinsic_125: - case Intrinsic_126: - case Intrinsic_127: - case Intrinsic_130: - case Intrinsic_157: - case Intrinsic_158: - case Intrinsic_159: - case Intrinsic_160: - case Intrinsic_161: - case Intrinsic_162: - case Intrinsic_163: - case Intrinsic_164: - case Intrinsic_165: - case Intrinsic_166: - case Intrinsic_167: - case Intrinsic_168: - case Intrinsic_169: - case Intrinsic_170: - case Intrinsic_171: - case Intrinsic_172: - case Intrinsic_173: - case Intrinsic_174: - case Intrinsic_175: - case Intrinsic_177: - case Intrinsic_178: - case Intrinsic_179: - case Intrinsic_180: - case Intrinsic_181: - case Intrinsic_182: - case Intrinsic_183: - case Intrinsic_184: - case Intrinsic_185: - case Intrinsic_186: - case Intrinsic_187: - case Intrinsic_188: - case Intrinsic_189: - case Intrinsic_204: - case Intrinsic_205: - case Intrinsic_206: - case Intrinsic_207: - case Intrinsic_208: - case Intrinsic_209: - case Intrinsic_210: - case Intrinsic_211: - case Intrinsic_212: - case Intrinsic_213: - case Intrinsic_214: - case Intrinsic_215: - case Intrinsic_216: - case Intrinsic_217: - case Intrinsic_218: - case Intrinsic_219: - case Intrinsic_220: - case Intrinsic_221: - case Intrinsic_222: - case Intrinsic_223: - case Intrinsic_232: - case Intrinsic_233: - case Intrinsic_234: - case Intrinsic_235: - case Intrinsic_236: - case Intrinsic_237: - case Intrinsic_238: - case Intrinsic_239: - case Intrinsic_241: - case Intrinsic_242: - case Intrinsic_243: - case Intrinsic_244: - case Intrinsic_245: - case Intrinsic_246: - case Intrinsic_247: - case Intrinsic_248: - case Intrinsic_249: - case Intrinsic_250: - case Intrinsic_251: - case Intrinsic_254: - case Intrinsic_255: - case Intrinsic_256: - case Intrinsic_260: - case Intrinsic_261: - case Intrinsic_262: - case Intrinsic_264: - case Intrinsic_265: - case Intrinsic_272: - case Intrinsic_273: - case Intrinsic_274: - case Intrinsic_275: - case Intrinsic_276: - case Intrinsic_277: - case Intrinsic_278: - case Intrinsic_279: - case Intrinsic_285: - case Intrinsic_286: - case Intrinsic_287: - case Intrinsic_288: - case Intrinsic_289: - case Intrinsic_290: - case Intrinsic_291: - case Intrinsic_292: - case Intrinsic_293: - case Intrinsic_294: - case Intrinsic_295: - case Intrinsic_296: - case Intrinsic_297: - case Intrinsic_298: - case Intrinsic_299: - case Intrinsic_300: - case Intrinsic_308: - op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node); - vector_intrinsic_2args(args->node, args->next->node, outputReg, output, op); - break; - case Intrinsic_048: - case Intrinsic_064: - case Intrinsic_065: - case Intrinsic_069: - case Intrinsic_094: - case Intrinsic_096: - case Intrinsic_097: - case Intrinsic_123: - case Intrinsic_128: - case Intrinsic_129: - case Intrinsic_176: - case Intrinsic_194: - case Intrinsic_195: - case Intrinsic_201: - case Intrinsic_253: - case Intrinsic_257: - case Intrinsic_258: - case Intrinsic_301: - case Intrinsic_302: - case Intrinsic_303: - case Intrinsic_304: - case Intrinsic_305: - case Intrinsic_306: - case Intrinsic_307: - op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); - vector_intrinsic_1arg(args->node, outputReg, output, op); - break; - case Intrinsic_055: - case Intrinsic_056: - case Intrinsic_057: - case Intrinsic_103: - case Intrinsic_190: - case Intrinsic_191: - case Intrinsic_192: - case Intrinsic_193: - case Intrinsic_266: - case Intrinsic_267: - case Intrinsic_268: - op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node); - vector_intrinsic_2args1const(args->node, args->next->node, outputReg, output, op); - break; - case Intrinsic_104: - case Intrinsic_105: - case Intrinsic_106: - case Intrinsic_269: - case Intrinsic_270: - case Intrinsic_271: - op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); - vector_intrinsic_splats(args->node, outputReg, output, op); - break; - case Intrinsic_107: - op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); - vector_intrinsic_splatu8(args->node, outputReg, output, op); - break; - case Intrinsic_108: - op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); - vector_intrinsic_splatu16(args->node, outputReg, output, op); - break; - case Intrinsic_109: - op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); - vector_intrinsic_splatu32(args->node, outputReg, output, op); - break; - case Intrinsic_083: - vector_intrinsic_mtvscr(args->node, output, PC_MTVSCR); - break; - case Intrinsic_077: - op = Intrinsics_FindOpcodeNoArgs(id, funccall); - vector_intrinsic_mfvscr(outputReg, op, output); - break; - case Intrinsic_058: - vector_intrinsic_dss(args->node); - break; - case Intrinsic_059: - op = Intrinsics_FindOpcodeNoArgs(id, funccall); - vector_intrinsic_no_args(op); - break; - case Intrinsic_060: - case Intrinsic_061: - case Intrinsic_062: - case Intrinsic_063: - switch (id) { - case Intrinsic_060: - op = PC_DST; - break; - case Intrinsic_061: - op = PC_DSTST; - break; - case Intrinsic_062: - op = PC_DSTSTT; - break; - case Intrinsic_063: - op = PC_DSTT; - break; - } - vector_intrinsic_datastream(args->node, args->next->node, args->next->next->node, op); - break; - case Intrinsic_066: - case Intrinsic_067: - case Intrinsic_068: - case Intrinsic_070: - case Intrinsic_071: - case Intrinsic_196: - case Intrinsic_197: - case Intrinsic_198: - case Intrinsic_199: - case Intrinsic_200: - op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node); - vector_intrinsic_load(args->node, args->next->node, outputReg, output, op); - break; - case Intrinsic_114: - case Intrinsic_115: - case Intrinsic_116: - case Intrinsic_280: - case Intrinsic_281: - case Intrinsic_282: - case Intrinsic_283: - case Intrinsic_284: - op = Intrinsics_FindOpcode3Args(id, funccall, args->node, args->next->node, args->next->next->node); - vector_intrinsic_store(args->node, args->next->node, args->next->next->node, outputReg, output, op); - break; - case Intrinsic_131: - case Intrinsic_132: - case Intrinsic_133: - case Intrinsic_134: - case Intrinsic_135: - case Intrinsic_136: - case Intrinsic_138: - case Intrinsic_139: - case Intrinsic_140: - case Intrinsic_141: - case Intrinsic_142: - case Intrinsic_144: - case Intrinsic_145: - case Intrinsic_146: - case Intrinsic_147: - case Intrinsic_148: - case Intrinsic_150: - case Intrinsic_151: - case Intrinsic_152: - case Intrinsic_153: - case Intrinsic_154: - case Intrinsic_156: - op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node); - vector_predicate_2args(args->node, args->next->node, outputReg, output, op, id); - break; - case Intrinsic_137: - case Intrinsic_143: - case Intrinsic_149: - case Intrinsic_155: - op = Intrinsics_FindOpcode1Arg(id, funccall, args->node); - vector_predicate_1arg(args->node, outputReg, output, op, id); - break; - case Intrinsic_309: - vector_intrinsic_abs(id, funccall, args->node, outputReg, output); - break; - case Intrinsic_310: - vector_intrinsic_abss(id, funccall, args->node, outputReg, output); - break; - case Intrinsic_052: - case Intrinsic_054: - op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node); - vector_intrinsic_2args(args->node, args->next->node, outputReg, output, op); - break; - default: - CError_FATAL(6152); - } -} - -void Intrinsics_SetupRuntimeObjects(void) { - static TypePointer char_ptr = {TYPEPOINTER, 4, TYPE(&stchar), 0}; - Boolean savecpp; - int i; - - savecpp = copts.cplusplus; - copts.cplusplus = 0; - - for (i = 0; i < MaxIntrinsics; i++) - intrinsics[i] = NULL; - - intrinsics[Intrinsic_000] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__eieio"), 0, 0); - intrinsics[Intrinsic_001] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__sync"), 0, 0); - intrinsics[Intrinsic_002] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__isync"), 0, 0); - intrinsics[Intrinsic_003] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__abs"), 0, 1, &stsignedint); - intrinsics[Intrinsic_004] = CParser_NewRTFunc(TYPE(&stsignedlong), GetHashNameNodeExport("__labs"), 0, 1, &stsignedlong); - intrinsics[Intrinsic_005] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fabs"), 0, 1, &stdouble); - intrinsics[Intrinsic_006] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fnabs"), 0, 1, &stdouble); - intrinsics[Intrinsic_007] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__setflm"), 0, 1, &stdouble); - intrinsics[Intrinsic_033] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__frsqrte"), 0, 1, &stdouble); - intrinsics[Intrinsic_008] = CParser_NewRTFunc(TYPE(&void_ptr), GetHashNameNodeExport("__alloca"), 0, 1, &stunsignedint); - intrinsics[Intrinsic_009] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__cntlzw"), 0, 1, &stunsignedint); - intrinsics[Intrinsic_010] = CParser_NewRTFunc(TYPE(&stunsignedint), GetHashNameNodeExport("__lhbrx"), 0, 2, &void_ptr, &stsignedint); - intrinsics[Intrinsic_011] = CParser_NewRTFunc(TYPE(&stunsignedint), GetHashNameNodeExport("__lwbrx"), 0, 2, &void_ptr, &stsignedint); - intrinsics[Intrinsic_012] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__sthbrx"), 0, 3, &stunsignedshort, &void_ptr, &stsignedint); - intrinsics[Intrinsic_013] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__stwbrx"), 0, 3, &stunsignedint, &void_ptr, &stsignedint); - intrinsics[Intrinsic_014] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbf"), 0, 2, &void_ptr, &stsignedint); - intrinsics[Intrinsic_015] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbt"), 0, 2, &void_ptr, &stsignedint); - intrinsics[Intrinsic_016] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbst"), 0, 2, &void_ptr, &stsignedint); - intrinsics[Intrinsic_017] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbtst"), 0, 2, &void_ptr, &stsignedint); - intrinsics[Intrinsic_018] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbz"), 0, 2, &void_ptr, &stsignedint); - intrinsics[Intrinsic_019] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__mulhw"), 0, 2, &stsignedint, &stsignedint); - intrinsics[Intrinsic_020] = CParser_NewRTFunc(TYPE(&stunsignedint), GetHashNameNodeExport("__mulhwu"), 0, 2, &stunsignedint, &stunsignedint); - intrinsics[Intrinsic_021] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__divw"), 0, 2, &stsignedint, &stsignedint); - intrinsics[Intrinsic_022] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__divwu"), 0, 2, &stsignedint, &stsignedint); - intrinsics[Intrinsic_023] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fmadd"), 0, 3, &stdouble, &stdouble, &stdouble); - intrinsics[Intrinsic_024] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fmsub"), 0, 3, &stdouble, &stdouble, &stdouble); - intrinsics[Intrinsic_025] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fnmadd"), 0, 3, &stdouble, &stdouble, &stdouble); - intrinsics[Intrinsic_026] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fnmsub"), 0, 3, &stdouble, &stdouble, &stdouble); - intrinsics[Intrinsic_034] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fsel"), 0, 3, &stdouble, &stdouble, &stdouble); - intrinsics[Intrinsic_027] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fmadds"), 0, 3, &stfloat, &stfloat, &stfloat); - intrinsics[Intrinsic_028] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fmsubs"), 0, 3, &stfloat, &stfloat, &stfloat); - intrinsics[Intrinsic_029] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fnmadds"), 0, 3, &stfloat, &stfloat, &stfloat); - intrinsics[Intrinsic_030] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fnmsubs"), 0, 3, &stfloat, &stfloat, &stfloat); - intrinsics[Intrinsic_031] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__mffs"), 0, 0); - intrinsics[Intrinsic_032] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fres"), 0, 1, &stfloat); - intrinsics[Intrinsic_040] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fabsf"), 0, 1, &stfloat); - intrinsics[Intrinsic_041] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fnabsf"), 0, 1, &stfloat); - intrinsics[Intrinsic_035] = CParser_NewRTFunc(TYPE(&char_ptr), GetHashNameNodeExport("__strcpy"), 0, 2, &char_ptr, &char_ptr); - TYPE_FUNC(intrinsics[Intrinsic_035]->type)->args->next->qual |= Q_CONST; - intrinsics[Intrinsic_036] = CParser_NewRTFunc(TYPE(&void_ptr), GetHashNameNodeExport("__memcpy"), 0, 3, &void_ptr, &void_ptr, &stunsignedlong); - __memcpy_object = intrinsics[Intrinsic_036]; - TYPE_FUNC(intrinsics[Intrinsic_036]->type)->args->next->qual |= Q_CONST; - intrinsics[Intrinsic_037] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__rlwimi"), 0, 5, &stsignedint, &stsignedint, &stsignedint, &stsignedint, &stsignedint); - intrinsics[Intrinsic_038] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__rlwinm"), 0, 4, &stsignedint, &stsignedint, &stsignedint, &stsignedint); - intrinsics[Intrinsic_039] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__rlwnm"), 0, 4, &stsignedint, &stsignedint, &stsignedint, &stsignedint); - intrinsics[Intrinsic_042] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_add"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_043] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_addc"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_044] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_adds"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_045] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_and"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_046] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_andc"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_047] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_avg"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_048] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ceil"), 0, 1, &stvector); - intrinsics[Intrinsic_049] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmpb"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_050] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmpeq"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_051] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmpge"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_052] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmple"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_053] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmpgt"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_054] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmplt"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_055] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ctf"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_056] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cts"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_057] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ctu"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_058] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dss"), 0, 1, &stsignedint); - intrinsics[Intrinsic_059] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dssall"), 0, 0); - intrinsics[Intrinsic_060] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dst"), 0, 3, &stvector, &stsignedint, &stsignedint); - intrinsics[Intrinsic_061] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dstst"), 0, 3, &stvector, &stsignedint, &stsignedint); - intrinsics[Intrinsic_062] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dststt"), 0, 3, &stvector, &stsignedint, &stsignedint); - intrinsics[Intrinsic_063] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dstt"), 0, 3, &stvector, &stsignedint, &stsignedint); - intrinsics[Intrinsic_064] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_expte"), 0, 1, &stvector); - intrinsics[Intrinsic_065] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_floor"), 0, 1, &stvector); - intrinsics[Intrinsic_066] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ld"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_067] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lde"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_068] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ldl"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_069] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_loge"), 0, 1, &stvector); - intrinsics[Intrinsic_070] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvsl"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_071] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvsr"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_072] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_madd"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_073] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_madds"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_074] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_max"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_075] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mergeh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_076] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mergel"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_077] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mfvscr"), 0, 0); - intrinsics[Intrinsic_078] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_min"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_079] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mladd"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_080] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mradds"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_081] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_msum"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_082] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_msums"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_083] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mtvscr"), 0, 1, &stvector); - intrinsics[Intrinsic_084] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mule"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_085] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mulo"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_086] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_nmsub"), 0, 2, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_087] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_nor"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_088] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_or"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_089] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_pack"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_090] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_packpx"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_091] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_packs"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_092] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_packsu"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_093] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_perm"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_094] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_re"), 0, 1, &stvector); - intrinsics[Intrinsic_095] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_rl"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_096] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_round"), 0, 1, &stvector); - intrinsics[Intrinsic_097] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_rsqrte"), 0, 1, &stvector); - intrinsics[Intrinsic_098] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sel"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_099] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sl"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_100] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sld"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_101] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sll"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_102] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_slo"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_103] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_104] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_s8"), 0, 1, &stvector); - intrinsics[Intrinsic_105] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_s16"), 0, 1, &stvector); - intrinsics[Intrinsic_106] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_s32"), 0, 1, &stvector); - intrinsics[Intrinsic_107] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_u8"), 0, 1, &stvector); - intrinsics[Intrinsic_108] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_u16"), 0, 1, &stvector); - intrinsics[Intrinsic_109] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_u32"), 0, 1, &stvector); - intrinsics[Intrinsic_110] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sr"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_111] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sra"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_112] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_srl"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_113] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sro"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_114] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_st"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_115] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ste"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_116] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stl"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_117] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sub"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_118] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_subc"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_119] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_subs"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_120] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sum4s"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_121] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sum2s"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_122] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sums"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_123] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_trunc"), 0, 1, &stvector); - intrinsics[Intrinsic_124] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpack2sh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_125] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpack2sl"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_126] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpack2uh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_127] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpack2ul"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_128] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpackh"), 0, 1, &stvector); - intrinsics[Intrinsic_129] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpackl"), 0, 1, &stvector); - intrinsics[Intrinsic_130] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_xor"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_131] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_eq"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_132] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_ge"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_133] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_gt"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_134] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_in"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_135] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_le"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_136] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_lt"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_137] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_nan"), 0, 1, &stvector); - intrinsics[Intrinsic_138] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_ne"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_139] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_nge"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_140] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_ngt"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_141] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_nle"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_142] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_nlt"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_143] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_numeric"), 0, 1, &stvector); - intrinsics[Intrinsic_144] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_eq"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_145] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_ge"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_146] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_gt"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_147] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_le"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_148] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_lt"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_149] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_nan"), 0, 1, &stvector); - intrinsics[Intrinsic_150] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_ne"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_151] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_nge"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_152] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_ngt"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_153] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_nle"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_154] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_nlt"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_155] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_numeric"), 0, 1, &stvector); - intrinsics[Intrinsic_156] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_out"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_157] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddubm"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_158] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vadduhm"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_159] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vadduwm"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_160] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddfp"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_161] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddcuw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_162] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddubs"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_163] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddsbs"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_164] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vadduhs"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_165] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddshs"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_166] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vadduws"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_167] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddsws"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_168] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vand"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_169] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vandc"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_170] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavgub"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_171] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavgsb"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_172] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavguh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_173] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavgsh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_174] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavguw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_175] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavgsw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_176] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrfip"), 0, 1, &stvector); - intrinsics[Intrinsic_177] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpbfp"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_178] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpequb"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_179] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpequh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_180] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpequw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_181] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpeqfp"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_182] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgefp"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_183] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtub"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_184] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtsb"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_185] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtuh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_186] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtsh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_187] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtuw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_188] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtsw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_189] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtfp"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_190] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcfux"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_191] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcfsx"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_192] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vctsxs"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_193] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vctuxs"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_194] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vexptefp"), 0, 1, &stvector); - intrinsics[Intrinsic_195] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrfim"), 0, 1, &stvector); - intrinsics[Intrinsic_196] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvx"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_197] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvebx"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_198] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvehx"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_199] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvewx"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_200] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvxl"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_201] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vlogefp"), 0, 1, &stvector); - intrinsics[Intrinsic_202] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaddfp"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_203] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmhaddshs"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_204] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxub"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_205] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxsb"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_206] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxuh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_207] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxsh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_208] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxuw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_209] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxsw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_210] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxfp"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_211] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrghb"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_212] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrghh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_213] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrghw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_214] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrglb"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_215] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrglh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_216] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrglw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_217] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminub"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_218] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminsb"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_219] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminuh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_220] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminsh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_221] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminuw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_222] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminsw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_223] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminfp"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_224] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmladduhm"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_225] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmhraddshs"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_226] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumubm"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_227] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumuhm"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_228] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsummbm"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_229] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumshm"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_230] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumuhs"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_231] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumshs"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_232] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmuleub"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_233] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulesb"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_234] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmuleuh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_235] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulesh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_236] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmuloub"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_237] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulosb"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_238] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulouh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_239] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulosh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_240] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vnmsubfp"), 0, 2, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_241] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vnor"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_242] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vor"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_243] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkuhum"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_244] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkuwum"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_245] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkpx"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_246] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkuhus"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_247] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkshss"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_248] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkuwus"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_249] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkswss"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_250] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkshus"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_251] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkswus"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_252] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vperm"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_253] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrefp"), 0, 1, &stvector); - intrinsics[Intrinsic_254] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrlb"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_255] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrlh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_256] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrlw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_257] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrfin"), 0, 1, &stvector); - intrinsics[Intrinsic_258] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrsqrtefp"), 0, 1, &stvector); - intrinsics[Intrinsic_259] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsel"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_260] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vslb"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_261] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vslh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_262] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vslw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_263] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsldoi"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_264] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsl"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_265] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vslo"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_266] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltb"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_267] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsplth"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_268] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_269] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltisb"), 0, 1, &stvector); - intrinsics[Intrinsic_270] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltish"), 0, 1, &stvector); - intrinsics[Intrinsic_271] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltisw"), 0, 1, &stvector); - intrinsics[Intrinsic_272] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrb"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_273] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrh"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_274] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_275] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrab"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_276] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrah"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_277] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsraw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_278] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsr"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_279] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsro"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_280] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvx"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_281] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvebx"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_282] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvehx"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_283] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvewx"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_284] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvxl"), 0, 3, &stvector, &stvector, &stvector); - intrinsics[Intrinsic_285] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsububm"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_286] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubuhm"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_287] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubuwm"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_288] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubfp"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_289] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubcuw"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_290] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsububs"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_291] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubsbs"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_292] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubuhs"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_293] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubshs"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_294] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubuws"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_295] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubsws"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_296] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsum4ubs"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_297] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsum4sbs"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_298] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsum4shs"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_299] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsum2sws"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_300] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsumsws"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_301] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrfiz"), 0, 1, &stvector); - intrinsics[Intrinsic_302] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupkhsb"), 0, 1, &stvector); - intrinsics[Intrinsic_303] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupklsb"), 0, 1, &stvector); - intrinsics[Intrinsic_304] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupkhpx"), 0, 1, &stvector); - intrinsics[Intrinsic_305] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupklpx"), 0, 1, &stvector); - intrinsics[Intrinsic_306] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupkhsh"), 0, 1, &stvector); - intrinsics[Intrinsic_307] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupklsh"), 0, 1, &stvector); - intrinsics[Intrinsic_308] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vxor"), 0, 2, &stvector, &stvector); - intrinsics[Intrinsic_309] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_abs"), 0, 1, &stvector); - intrinsics[Intrinsic_310] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_abss"), 0, 1, &stvector); - - for (i = 0; i < MaxIntrinsics; i++) { - CError_ASSERT(6600, intrinsics[i]); - intrinsics[i]->u.func.u.intrinsicid = i; - TYPE_FUNC(intrinsics[i]->type)->flags |= FUNC_INTRINSIC; - CScope_AddGlobalObject(intrinsics[i]); - } - - copts.cplusplus = savecpp; -} - -static Object *CheckRuntimeObject(char *name) { - NameSpaceName *nsname = CScope_FindNameSpaceName(cscope_root, GetHashNameNodeExport(name)); - - if (!nsname) - return NULL; - - if (nsname->first.object && nsname->first.next == NULL) - return OBJECT(nsname->first.object); - - return NULL; -} - -Boolean Intrinsics_ReInitRuntimeObjects(Boolean flag) { - if (flag) { - if (!(intrinsics[Intrinsic_000] = CheckRuntimeObject("__eieio"))) return 0; - if (!(intrinsics[Intrinsic_001] = CheckRuntimeObject("__sync"))) return 0; - if (!(intrinsics[Intrinsic_002] = CheckRuntimeObject("__isync"))) return 0; - if (!(intrinsics[Intrinsic_003] = CheckRuntimeObject("__abs"))) return 0; - if (!(intrinsics[Intrinsic_004] = CheckRuntimeObject("__labs"))) return 0; - if (!(intrinsics[Intrinsic_005] = CheckRuntimeObject("__fabs"))) return 0; - if (!(intrinsics[Intrinsic_006] = CheckRuntimeObject("__fnabs"))) return 0; - if (!(intrinsics[Intrinsic_007] = CheckRuntimeObject("__setflm"))) return 0; - if (!(intrinsics[Intrinsic_033] = CheckRuntimeObject("__frsqrte"))) return 0; - if (!(intrinsics[Intrinsic_008] = CheckRuntimeObject("__alloca"))) return 0; - if (!(intrinsics[Intrinsic_009] = CheckRuntimeObject("__cntlzw"))) return 0; - if (!(intrinsics[Intrinsic_010] = CheckRuntimeObject("__lhbrx"))) return 0; - if (!(intrinsics[Intrinsic_011] = CheckRuntimeObject("__lwbrx"))) return 0; - if (!(intrinsics[Intrinsic_012] = CheckRuntimeObject("__sthbrx"))) return 0; - if (!(intrinsics[Intrinsic_013] = CheckRuntimeObject("__stwbrx"))) return 0; - if (!(intrinsics[Intrinsic_014] = CheckRuntimeObject("__dcbf"))) return 0; - if (!(intrinsics[Intrinsic_015] = CheckRuntimeObject("__dcbt"))) return 0; - if (!(intrinsics[Intrinsic_016] = CheckRuntimeObject("__dcbst"))) return 0; - if (!(intrinsics[Intrinsic_017] = CheckRuntimeObject("__dcbtst"))) return 0; - if (!(intrinsics[Intrinsic_018] = CheckRuntimeObject("__dcbz"))) return 0; - if (!(intrinsics[Intrinsic_019] = CheckRuntimeObject("__mulhw"))) return 0; - if (!(intrinsics[Intrinsic_020] = CheckRuntimeObject("__mulhwu"))) return 0; - if (!(intrinsics[Intrinsic_021] = CheckRuntimeObject("__divw"))) return 0; - if (!(intrinsics[Intrinsic_022] = CheckRuntimeObject("__divwu"))) return 0; - if (!(intrinsics[Intrinsic_023] = CheckRuntimeObject("__fmadd"))) return 0; - if (!(intrinsics[Intrinsic_024] = CheckRuntimeObject("__fmsub"))) return 0; - if (!(intrinsics[Intrinsic_025] = CheckRuntimeObject("__fnmadd"))) return 0; - if (!(intrinsics[Intrinsic_026] = CheckRuntimeObject("__fnmsub"))) return 0; - if (!(intrinsics[Intrinsic_034] = CheckRuntimeObject("__fsel"))) return 0; - if (!(intrinsics[Intrinsic_027] = CheckRuntimeObject("__fmadds"))) return 0; - if (!(intrinsics[Intrinsic_028] = CheckRuntimeObject("__fmsubs"))) return 0; - if (!(intrinsics[Intrinsic_029] = CheckRuntimeObject("__fnmadds"))) return 0; - if (!(intrinsics[Intrinsic_030] = CheckRuntimeObject("__fnmsubs"))) return 0; - if (!(intrinsics[Intrinsic_031] = CheckRuntimeObject("__mffs"))) return 0; - if (!(intrinsics[Intrinsic_032] = CheckRuntimeObject("__fres"))) return 0; - if (!(intrinsics[Intrinsic_040] = CheckRuntimeObject("__fabsf"))) return 0; - if (!(intrinsics[Intrinsic_041] = CheckRuntimeObject("__fnabsf"))) return 0; - if (!(intrinsics[Intrinsic_035] = CheckRuntimeObject("__strcpy"))) return 0; - if (!(intrinsics[Intrinsic_037] = CheckRuntimeObject("__rlwimi"))) return 0; - if (!(intrinsics[Intrinsic_038] = CheckRuntimeObject("__rlwinm"))) return 0; - if (!(intrinsics[Intrinsic_039] = CheckRuntimeObject("__rlwnm"))) return 0; - if (!(intrinsics[Intrinsic_042] = CheckRuntimeObject("vec_add"))) return 0; - if (!(intrinsics[Intrinsic_043] = CheckRuntimeObject("vec_addc"))) return 0; - if (!(intrinsics[Intrinsic_044] = CheckRuntimeObject("vec_adds"))) return 0; - if (!(intrinsics[Intrinsic_045] = CheckRuntimeObject("vec_and"))) return 0; - if (!(intrinsics[Intrinsic_046] = CheckRuntimeObject("vec_andc"))) return 0; - if (!(intrinsics[Intrinsic_047] = CheckRuntimeObject("vec_avg"))) return 0; - if (!(intrinsics[Intrinsic_048] = CheckRuntimeObject("vec_ceil"))) return 0; - if (!(intrinsics[Intrinsic_049] = CheckRuntimeObject("vec_cmpb"))) return 0; - if (!(intrinsics[Intrinsic_050] = CheckRuntimeObject("vec_cmpeq"))) return 0; - if (!(intrinsics[Intrinsic_051] = CheckRuntimeObject("vec_cmpge"))) return 0; - if (!(intrinsics[Intrinsic_052] = CheckRuntimeObject("vec_cmple"))) return 0; - if (!(intrinsics[Intrinsic_053] = CheckRuntimeObject("vec_cmpgt"))) return 0; - if (!(intrinsics[Intrinsic_054] = CheckRuntimeObject("vec_cmplt"))) return 0; - if (!(intrinsics[Intrinsic_055] = CheckRuntimeObject("vec_ctf"))) return 0; - if (!(intrinsics[Intrinsic_056] = CheckRuntimeObject("vec_cts"))) return 0; - if (!(intrinsics[Intrinsic_057] = CheckRuntimeObject("vec_ctu"))) return 0; - if (!(intrinsics[Intrinsic_064] = CheckRuntimeObject("vec_expte"))) return 0; - if (!(intrinsics[Intrinsic_065] = CheckRuntimeObject("vec_floor"))) return 0; - if (!(intrinsics[Intrinsic_066] = CheckRuntimeObject("vec_ld"))) return 0; - if (!(intrinsics[Intrinsic_067] = CheckRuntimeObject("vec_lde"))) return 0; - if (!(intrinsics[Intrinsic_068] = CheckRuntimeObject("vec_ldl"))) return 0; - if (!(intrinsics[Intrinsic_069] = CheckRuntimeObject("vec_loge"))) return 0; - if (!(intrinsics[Intrinsic_070] = CheckRuntimeObject("vec_lvsl"))) return 0; - if (!(intrinsics[Intrinsic_071] = CheckRuntimeObject("vec_lvsr"))) return 0; - if (!(intrinsics[Intrinsic_072] = CheckRuntimeObject("vec_madd"))) return 0; - if (!(intrinsics[Intrinsic_073] = CheckRuntimeObject("vec_madds"))) return 0; - if (!(intrinsics[Intrinsic_074] = CheckRuntimeObject("vec_max"))) return 0; - if (!(intrinsics[Intrinsic_075] = CheckRuntimeObject("vec_mergeh"))) return 0; - if (!(intrinsics[Intrinsic_076] = CheckRuntimeObject("vec_mergel"))) return 0; - if (!(intrinsics[Intrinsic_077] = CheckRuntimeObject("vec_mfvscr"))) return 0; - if (!(intrinsics[Intrinsic_078] = CheckRuntimeObject("vec_min"))) return 0; - if (!(intrinsics[Intrinsic_079] = CheckRuntimeObject("vec_mladd"))) return 0; - if (!(intrinsics[Intrinsic_080] = CheckRuntimeObject("vec_mradds"))) return 0; - if (!(intrinsics[Intrinsic_081] = CheckRuntimeObject("vec_msum"))) return 0; - if (!(intrinsics[Intrinsic_082] = CheckRuntimeObject("vec_msums"))) return 0; - if (!(intrinsics[Intrinsic_083] = CheckRuntimeObject("vec_mtvscr"))) return 0; - if (!(intrinsics[Intrinsic_084] = CheckRuntimeObject("vec_mule"))) return 0; - if (!(intrinsics[Intrinsic_085] = CheckRuntimeObject("vec_mulo"))) return 0; - if (!(intrinsics[Intrinsic_086] = CheckRuntimeObject("vec_nmsub"))) return 0; - if (!(intrinsics[Intrinsic_087] = CheckRuntimeObject("vec_nor"))) return 0; - if (!(intrinsics[Intrinsic_088] = CheckRuntimeObject("vec_or"))) return 0; - if (!(intrinsics[Intrinsic_089] = CheckRuntimeObject("vec_pack"))) return 0; - if (!(intrinsics[Intrinsic_090] = CheckRuntimeObject("vec_packpx"))) return 0; - if (!(intrinsics[Intrinsic_091] = CheckRuntimeObject("vec_packs"))) return 0; - if (!(intrinsics[Intrinsic_092] = CheckRuntimeObject("vec_packsu"))) return 0; - if (!(intrinsics[Intrinsic_093] = CheckRuntimeObject("vec_perm"))) return 0; - if (!(intrinsics[Intrinsic_094] = CheckRuntimeObject("vec_re"))) return 0; - if (!(intrinsics[Intrinsic_095] = CheckRuntimeObject("vec_rl"))) return 0; - if (!(intrinsics[Intrinsic_096] = CheckRuntimeObject("vec_round"))) return 0; - if (!(intrinsics[Intrinsic_097] = CheckRuntimeObject("vec_rsqrte"))) return 0; - if (!(intrinsics[Intrinsic_098] = CheckRuntimeObject("vec_sel"))) return 0; - if (!(intrinsics[Intrinsic_099] = CheckRuntimeObject("vec_sl"))) return 0; - if (!(intrinsics[Intrinsic_100] = CheckRuntimeObject("vec_sld"))) return 0; - if (!(intrinsics[Intrinsic_101] = CheckRuntimeObject("vec_sll"))) return 0; - if (!(intrinsics[Intrinsic_102] = CheckRuntimeObject("vec_slo"))) return 0; - if (!(intrinsics[Intrinsic_103] = CheckRuntimeObject("vec_splat"))) return 0; - if (!(intrinsics[Intrinsic_104] = CheckRuntimeObject("vec_splat_s8"))) return 0; - if (!(intrinsics[Intrinsic_105] = CheckRuntimeObject("vec_splat_s16"))) return 0; - if (!(intrinsics[Intrinsic_106] = CheckRuntimeObject("vec_splat_s32"))) return 0; - if (!(intrinsics[Intrinsic_107] = CheckRuntimeObject("vec_splat_u8"))) return 0; - if (!(intrinsics[Intrinsic_108] = CheckRuntimeObject("vec_splat_u16"))) return 0; - if (!(intrinsics[Intrinsic_109] = CheckRuntimeObject("vec_splat_u32"))) return 0; - if (!(intrinsics[Intrinsic_110] = CheckRuntimeObject("vec_sr"))) return 0; - if (!(intrinsics[Intrinsic_111] = CheckRuntimeObject("vec_sra"))) return 0; - if (!(intrinsics[Intrinsic_112] = CheckRuntimeObject("vec_srl"))) return 0; - if (!(intrinsics[Intrinsic_113] = CheckRuntimeObject("vec_sro"))) return 0; - if (!(intrinsics[Intrinsic_114] = CheckRuntimeObject("vec_st"))) return 0; - if (!(intrinsics[Intrinsic_115] = CheckRuntimeObject("vec_ste"))) return 0; - if (!(intrinsics[Intrinsic_116] = CheckRuntimeObject("vec_stl"))) return 0; - if (!(intrinsics[Intrinsic_117] = CheckRuntimeObject("vec_sub"))) return 0; - if (!(intrinsics[Intrinsic_118] = CheckRuntimeObject("vec_subc"))) return 0; - if (!(intrinsics[Intrinsic_119] = CheckRuntimeObject("vec_subs"))) return 0; - if (!(intrinsics[Intrinsic_120] = CheckRuntimeObject("vec_sum4s"))) return 0; - if (!(intrinsics[Intrinsic_121] = CheckRuntimeObject("vec_sum2s"))) return 0; - if (!(intrinsics[Intrinsic_122] = CheckRuntimeObject("vec_sums"))) return 0; - if (!(intrinsics[Intrinsic_123] = CheckRuntimeObject("vec_trunc"))) return 0; - if (!(intrinsics[Intrinsic_124] = CheckRuntimeObject("vec_unpack2sh"))) return 0; - if (!(intrinsics[Intrinsic_125] = CheckRuntimeObject("vec_unpack2sl"))) return 0; - if (!(intrinsics[Intrinsic_126] = CheckRuntimeObject("vec_unpack2uh"))) return 0; - if (!(intrinsics[Intrinsic_127] = CheckRuntimeObject("vec_unpack2ul"))) return 0; - if (!(intrinsics[Intrinsic_128] = CheckRuntimeObject("vec_unpackh"))) return 0; - if (!(intrinsics[Intrinsic_129] = CheckRuntimeObject("vec_unpackl"))) return 0; - if (!(intrinsics[Intrinsic_130] = CheckRuntimeObject("vec_xor"))) return 0; - if (!(intrinsics[Intrinsic_131] = CheckRuntimeObject("vec_all_eq"))) return 0; - if (!(intrinsics[Intrinsic_132] = CheckRuntimeObject("vec_all_ge"))) return 0; - if (!(intrinsics[Intrinsic_133] = CheckRuntimeObject("vec_all_gt"))) return 0; - if (!(intrinsics[Intrinsic_134] = CheckRuntimeObject("vec_all_in"))) return 0; - if (!(intrinsics[Intrinsic_135] = CheckRuntimeObject("vec_all_le"))) return 0; - if (!(intrinsics[Intrinsic_136] = CheckRuntimeObject("vec_all_lt"))) return 0; - if (!(intrinsics[Intrinsic_137] = CheckRuntimeObject("vec_all_nan"))) return 0; - if (!(intrinsics[Intrinsic_138] = CheckRuntimeObject("vec_all_ne"))) return 0; - if (!(intrinsics[Intrinsic_139] = CheckRuntimeObject("vec_all_nge"))) return 0; - if (!(intrinsics[Intrinsic_140] = CheckRuntimeObject("vec_all_ngt"))) return 0; - if (!(intrinsics[Intrinsic_141] = CheckRuntimeObject("vec_all_nle"))) return 0; - if (!(intrinsics[Intrinsic_142] = CheckRuntimeObject("vec_all_nlt"))) return 0; - if (!(intrinsics[Intrinsic_143] = CheckRuntimeObject("vec_all_numeric"))) return 0; - if (!(intrinsics[Intrinsic_144] = CheckRuntimeObject("vec_any_eq"))) return 0; - if (!(intrinsics[Intrinsic_145] = CheckRuntimeObject("vec_any_ge"))) return 0; - if (!(intrinsics[Intrinsic_146] = CheckRuntimeObject("vec_any_gt"))) return 0; - if (!(intrinsics[Intrinsic_147] = CheckRuntimeObject("vec_any_le"))) return 0; - if (!(intrinsics[Intrinsic_148] = CheckRuntimeObject("vec_any_lt"))) return 0; - if (!(intrinsics[Intrinsic_149] = CheckRuntimeObject("vec_any_nan"))) return 0; - if (!(intrinsics[Intrinsic_150] = CheckRuntimeObject("vec_any_ne"))) return 0; - if (!(intrinsics[Intrinsic_151] = CheckRuntimeObject("vec_any_nge"))) return 0; - if (!(intrinsics[Intrinsic_152] = CheckRuntimeObject("vec_any_ngt"))) return 0; - if (!(intrinsics[Intrinsic_153] = CheckRuntimeObject("vec_any_nle"))) return 0; - if (!(intrinsics[Intrinsic_154] = CheckRuntimeObject("vec_any_nlt"))) return 0; - if (!(intrinsics[Intrinsic_155] = CheckRuntimeObject("vec_any_numeric"))) return 0; - if (!(intrinsics[Intrinsic_156] = CheckRuntimeObject("vec_any_out"))) return 0; - if (!(intrinsics[Intrinsic_157] = CheckRuntimeObject("vec_vaddubm"))) return 0; - if (!(intrinsics[Intrinsic_158] = CheckRuntimeObject("vec_vadduhm"))) return 0; - if (!(intrinsics[Intrinsic_159] = CheckRuntimeObject("vec_vadduwm"))) return 0; - if (!(intrinsics[Intrinsic_160] = CheckRuntimeObject("vec_vaddfp"))) return 0; - if (!(intrinsics[Intrinsic_161] = CheckRuntimeObject("vec_vaddcuw"))) return 0; - if (!(intrinsics[Intrinsic_162] = CheckRuntimeObject("vec_vaddubs"))) return 0; - if (!(intrinsics[Intrinsic_163] = CheckRuntimeObject("vec_vaddubs"))) return 0; - if (!(intrinsics[Intrinsic_164] = CheckRuntimeObject("vec_vadduhs"))) return 0; - if (!(intrinsics[Intrinsic_165] = CheckRuntimeObject("vec_vadduhs"))) return 0; - if (!(intrinsics[Intrinsic_166] = CheckRuntimeObject("vec_vadduws"))) return 0; - if (!(intrinsics[Intrinsic_167] = CheckRuntimeObject("vec_vadduws"))) return 0; - if (!(intrinsics[Intrinsic_168] = CheckRuntimeObject("vec_vand"))) return 0; - if (!(intrinsics[Intrinsic_169] = CheckRuntimeObject("vec_vandc"))) return 0; - if (!(intrinsics[Intrinsic_170] = CheckRuntimeObject("vec_vavgub"))) return 0; - if (!(intrinsics[Intrinsic_171] = CheckRuntimeObject("vec_vavgsb"))) return 0; - if (!(intrinsics[Intrinsic_172] = CheckRuntimeObject("vec_vavguh"))) return 0; - if (!(intrinsics[Intrinsic_173] = CheckRuntimeObject("vec_vavgsh"))) return 0; - if (!(intrinsics[Intrinsic_174] = CheckRuntimeObject("vec_vavguw"))) return 0; - if (!(intrinsics[Intrinsic_175] = CheckRuntimeObject("vec_vavgsw"))) return 0; - if (!(intrinsics[Intrinsic_176] = CheckRuntimeObject("vec_vrfip"))) return 0; - if (!(intrinsics[Intrinsic_177] = CheckRuntimeObject("vec_vcmpbfp"))) return 0; - if (!(intrinsics[Intrinsic_178] = CheckRuntimeObject("vec_vcmpequb"))) return 0; - if (!(intrinsics[Intrinsic_179] = CheckRuntimeObject("vec_vcmpequh"))) return 0; - if (!(intrinsics[Intrinsic_180] = CheckRuntimeObject("vec_vcmpequw"))) return 0; - if (!(intrinsics[Intrinsic_181] = CheckRuntimeObject("vec_vcmpeqfp"))) return 0; - if (!(intrinsics[Intrinsic_182] = CheckRuntimeObject("vec_vcmpgefp"))) return 0; - if (!(intrinsics[Intrinsic_183] = CheckRuntimeObject("vec_vcmpgtub"))) return 0; - if (!(intrinsics[Intrinsic_184] = CheckRuntimeObject("vec_vcmpgtsb"))) return 0; - if (!(intrinsics[Intrinsic_185] = CheckRuntimeObject("vec_vcmpgtuh"))) return 0; - if (!(intrinsics[Intrinsic_186] = CheckRuntimeObject("vec_vcmpgtsh"))) return 0; - if (!(intrinsics[Intrinsic_187] = CheckRuntimeObject("vec_vcmpgtuw"))) return 0; - if (!(intrinsics[Intrinsic_188] = CheckRuntimeObject("vec_vcmpgtsw"))) return 0; - if (!(intrinsics[Intrinsic_189] = CheckRuntimeObject("vec_vcmpgtfp"))) return 0; - if (!(intrinsics[Intrinsic_190] = CheckRuntimeObject("vec_vcfux"))) return 0; - if (!(intrinsics[Intrinsic_191] = CheckRuntimeObject("vec_vcfsx"))) return 0; - if (!(intrinsics[Intrinsic_192] = CheckRuntimeObject("vec_vctsxs"))) return 0; - if (!(intrinsics[Intrinsic_193] = CheckRuntimeObject("vec_vctuxs"))) return 0; - if (!(intrinsics[Intrinsic_194] = CheckRuntimeObject("vec_vexptefp"))) return 0; - if (!(intrinsics[Intrinsic_195] = CheckRuntimeObject("vec_vrfim"))) return 0; - if (!(intrinsics[Intrinsic_196] = CheckRuntimeObject("vec_lvx"))) return 0; - if (!(intrinsics[Intrinsic_197] = CheckRuntimeObject("vec_lvebx"))) return 0; - if (!(intrinsics[Intrinsic_198] = CheckRuntimeObject("vec_lvehx"))) return 0; - if (!(intrinsics[Intrinsic_199] = CheckRuntimeObject("vec_lvewx"))) return 0; - if (!(intrinsics[Intrinsic_200] = CheckRuntimeObject("vec_lvxl"))) return 0; - if (!(intrinsics[Intrinsic_201] = CheckRuntimeObject("vec_vlogefp"))) return 0; - if (!(intrinsics[Intrinsic_202] = CheckRuntimeObject("vec_vmaddfp"))) return 0; - if (!(intrinsics[Intrinsic_203] = CheckRuntimeObject("vec_vmhaddshs"))) return 0; - if (!(intrinsics[Intrinsic_204] = CheckRuntimeObject("vec_vmaxub"))) return 0; - if (!(intrinsics[Intrinsic_205] = CheckRuntimeObject("vec_vmaxsb"))) return 0; - if (!(intrinsics[Intrinsic_206] = CheckRuntimeObject("vec_vmaxuh"))) return 0; - if (!(intrinsics[Intrinsic_207] = CheckRuntimeObject("vec_vmaxsh"))) return 0; - if (!(intrinsics[Intrinsic_208] = CheckRuntimeObject("vec_vmaxuw"))) return 0; - if (!(intrinsics[Intrinsic_209] = CheckRuntimeObject("vec_vmaxsw"))) return 0; - if (!(intrinsics[Intrinsic_210] = CheckRuntimeObject("vec_vmaxfp"))) return 0; - if (!(intrinsics[Intrinsic_211] = CheckRuntimeObject("vec_vmrghb"))) return 0; - if (!(intrinsics[Intrinsic_212] = CheckRuntimeObject("vec_vmrghh"))) return 0; - if (!(intrinsics[Intrinsic_213] = CheckRuntimeObject("vec_vmrghw"))) return 0; - if (!(intrinsics[Intrinsic_214] = CheckRuntimeObject("vec_vmrglb"))) return 0; - if (!(intrinsics[Intrinsic_215] = CheckRuntimeObject("vec_vmrglh"))) return 0; - if (!(intrinsics[Intrinsic_216] = CheckRuntimeObject("vec_vmrglw"))) return 0; - if (!(intrinsics[Intrinsic_204] = CheckRuntimeObject("vec_vminub"))) return 0; - if (!(intrinsics[Intrinsic_205] = CheckRuntimeObject("vec_vminsb"))) return 0; - if (!(intrinsics[Intrinsic_206] = CheckRuntimeObject("vec_vminuh"))) return 0; - if (!(intrinsics[Intrinsic_207] = CheckRuntimeObject("vec_vminsh"))) return 0; - if (!(intrinsics[Intrinsic_208] = CheckRuntimeObject("vec_vminuw"))) return 0; - if (!(intrinsics[Intrinsic_209] = CheckRuntimeObject("vec_vminsw"))) return 0; - if (!(intrinsics[Intrinsic_210] = CheckRuntimeObject("vec_vminfp"))) return 0; - if (!(intrinsics[Intrinsic_224] = CheckRuntimeObject("vec_vmladduhm"))) return 0; - if (!(intrinsics[Intrinsic_225] = CheckRuntimeObject("vec_vmhraddshs"))) return 0; - if (!(intrinsics[Intrinsic_226] = CheckRuntimeObject("vec_vmsumubm"))) return 0; - if (!(intrinsics[Intrinsic_227] = CheckRuntimeObject("vec_vmsumuhm"))) return 0; - if (!(intrinsics[Intrinsic_228] = CheckRuntimeObject("vec_vmsummbm"))) return 0; - if (!(intrinsics[Intrinsic_229] = CheckRuntimeObject("vec_vmsumshm"))) return 0; - if (!(intrinsics[Intrinsic_230] = CheckRuntimeObject("vec_vmsumuhs"))) return 0; - if (!(intrinsics[Intrinsic_231] = CheckRuntimeObject("vec_vmsumshs"))) return 0; - if (!(intrinsics[Intrinsic_232] = CheckRuntimeObject("vec_vmuleub"))) return 0; - if (!(intrinsics[Intrinsic_233] = CheckRuntimeObject("vec_vmulesb"))) return 0; - if (!(intrinsics[Intrinsic_234] = CheckRuntimeObject("vec_vmuleuh"))) return 0; - if (!(intrinsics[Intrinsic_235] = CheckRuntimeObject("vec_vmulesh"))) return 0; - if (!(intrinsics[Intrinsic_236] = CheckRuntimeObject("vec_vmuloub"))) return 0; - if (!(intrinsics[Intrinsic_237] = CheckRuntimeObject("vec_vmulosb"))) return 0; - if (!(intrinsics[Intrinsic_238] = CheckRuntimeObject("vec_vmulouh"))) return 0; - if (!(intrinsics[Intrinsic_239] = CheckRuntimeObject("vec_vmulosh"))) return 0; - if (!(intrinsics[Intrinsic_240] = CheckRuntimeObject("vec_vnmsubfp"))) return 0; - if (!(intrinsics[Intrinsic_241] = CheckRuntimeObject("vec_vnor"))) return 0; - if (!(intrinsics[Intrinsic_242] = CheckRuntimeObject("vec_vor"))) return 0; - if (!(intrinsics[Intrinsic_243] = CheckRuntimeObject("vec_vpkuhum"))) return 0; - if (!(intrinsics[Intrinsic_244] = CheckRuntimeObject("vec_vpkuwum"))) return 0; - if (!(intrinsics[Intrinsic_245] = CheckRuntimeObject("vec_vpkpx"))) return 0; - if (!(intrinsics[Intrinsic_246] = CheckRuntimeObject("vec_vpkuhus"))) return 0; - if (!(intrinsics[Intrinsic_247] = CheckRuntimeObject("vec_vpkshss"))) return 0; - if (!(intrinsics[Intrinsic_248] = CheckRuntimeObject("vec_vpkuwus"))) return 0; - if (!(intrinsics[Intrinsic_249] = CheckRuntimeObject("vec_vpkswss"))) return 0; - if (!(intrinsics[Intrinsic_250] = CheckRuntimeObject("vec_vpkshus"))) return 0; - if (!(intrinsics[Intrinsic_251] = CheckRuntimeObject("vec_vpkswus"))) return 0; - if (!(intrinsics[Intrinsic_252] = CheckRuntimeObject("vec_vperm"))) return 0; - if (!(intrinsics[Intrinsic_253] = CheckRuntimeObject("vec_vrefp"))) return 0; - if (!(intrinsics[Intrinsic_254] = CheckRuntimeObject("vec_vrlb"))) return 0; - if (!(intrinsics[Intrinsic_255] = CheckRuntimeObject("vec_vrlh"))) return 0; - if (!(intrinsics[Intrinsic_256] = CheckRuntimeObject("vec_vrlw"))) return 0; - if (!(intrinsics[Intrinsic_257] = CheckRuntimeObject("vec_vrfin"))) return 0; - if (!(intrinsics[Intrinsic_258] = CheckRuntimeObject("vec_vrsqrtefp"))) return 0; - if (!(intrinsics[Intrinsic_259] = CheckRuntimeObject("vec_vsel"))) return 0; - if (!(intrinsics[Intrinsic_260] = CheckRuntimeObject("vec_vslb"))) return 0; - if (!(intrinsics[Intrinsic_261] = CheckRuntimeObject("vec_vslh"))) return 0; - if (!(intrinsics[Intrinsic_262] = CheckRuntimeObject("vec_vslw"))) return 0; - if (!(intrinsics[Intrinsic_263] = CheckRuntimeObject("vec_vsldoi"))) return 0; - if (!(intrinsics[Intrinsic_264] = CheckRuntimeObject("vec_vsl"))) return 0; - if (!(intrinsics[Intrinsic_265] = CheckRuntimeObject("vec_vslo"))) return 0; - if (!(intrinsics[Intrinsic_266] = CheckRuntimeObject("vec_vspltb"))) return 0; - if (!(intrinsics[Intrinsic_267] = CheckRuntimeObject("vec_vsplth"))) return 0; - if (!(intrinsics[Intrinsic_268] = CheckRuntimeObject("vec_vspltw"))) return 0; - if (!(intrinsics[Intrinsic_269] = CheckRuntimeObject("vec_vspltisb"))) return 0; - if (!(intrinsics[Intrinsic_270] = CheckRuntimeObject("vec_vspltish"))) return 0; - if (!(intrinsics[Intrinsic_271] = CheckRuntimeObject("vec_vspltisw"))) return 0; - if (!(intrinsics[Intrinsic_272] = CheckRuntimeObject("vec_vsrb"))) return 0; - if (!(intrinsics[Intrinsic_273] = CheckRuntimeObject("vec_vsrh"))) return 0; - if (!(intrinsics[Intrinsic_274] = CheckRuntimeObject("vec_vsrw"))) return 0; - if (!(intrinsics[Intrinsic_275] = CheckRuntimeObject("vec_vsrab"))) return 0; - if (!(intrinsics[Intrinsic_276] = CheckRuntimeObject("vec_vsrah"))) return 0; - if (!(intrinsics[Intrinsic_277] = CheckRuntimeObject("vec_vsraw"))) return 0; - if (!(intrinsics[Intrinsic_278] = CheckRuntimeObject("vec_vsr"))) return 0; - if (!(intrinsics[Intrinsic_279] = CheckRuntimeObject("vec_vsro"))) return 0; - if (!(intrinsics[Intrinsic_280] = CheckRuntimeObject("vec_stvx"))) return 0; - if (!(intrinsics[Intrinsic_281] = CheckRuntimeObject("vec_stvebx"))) return 0; - if (!(intrinsics[Intrinsic_282] = CheckRuntimeObject("vec_stvehx"))) return 0; - if (!(intrinsics[Intrinsic_283] = CheckRuntimeObject("vec_stvewx"))) return 0; - if (!(intrinsics[Intrinsic_284] = CheckRuntimeObject("vec_stvxl"))) return 0; - if (!(intrinsics[Intrinsic_285] = CheckRuntimeObject("vec_vsububm"))) return 0; - if (!(intrinsics[Intrinsic_286] = CheckRuntimeObject("vec_vsubuhm"))) return 0; - if (!(intrinsics[Intrinsic_287] = CheckRuntimeObject("vec_vsubuwm"))) return 0; - if (!(intrinsics[Intrinsic_288] = CheckRuntimeObject("vec_vsubfp"))) return 0; - if (!(intrinsics[Intrinsic_289] = CheckRuntimeObject("vec_vsubcuw"))) return 0; - if (!(intrinsics[Intrinsic_290] = CheckRuntimeObject("vec_vsububs"))) return 0; - if (!(intrinsics[Intrinsic_291] = CheckRuntimeObject("vec_vsubsbs"))) return 0; - if (!(intrinsics[Intrinsic_292] = CheckRuntimeObject("vec_vsubuhs"))) return 0; - if (!(intrinsics[Intrinsic_293] = CheckRuntimeObject("vec_vsubshs"))) return 0; - if (!(intrinsics[Intrinsic_294] = CheckRuntimeObject("vec_vsubuws"))) return 0; - if (!(intrinsics[Intrinsic_295] = CheckRuntimeObject("vec_vsubsws"))) return 0; - if (!(intrinsics[Intrinsic_296] = CheckRuntimeObject("vec_vsum4ubs"))) return 0; - if (!(intrinsics[Intrinsic_297] = CheckRuntimeObject("vec_vsum4sbs"))) return 0; - if (!(intrinsics[Intrinsic_298] = CheckRuntimeObject("vec_vsum4shs"))) return 0; - if (!(intrinsics[Intrinsic_299] = CheckRuntimeObject("vec_vsum2sws"))) return 0; - if (!(intrinsics[Intrinsic_300] = CheckRuntimeObject("vec_vsumsws"))) return 0; - if (!(intrinsics[Intrinsic_301] = CheckRuntimeObject("vec_vrfiz"))) return 0; - if (!(intrinsics[Intrinsic_302] = CheckRuntimeObject("vec_vupkhsb"))) return 0; - if (!(intrinsics[Intrinsic_303] = CheckRuntimeObject("vec_vupklsb"))) return 0; - if (!(intrinsics[Intrinsic_304] = CheckRuntimeObject("vec_vupkhpx"))) return 0; - if (!(intrinsics[Intrinsic_305] = CheckRuntimeObject("vec_vupklpx"))) return 0; - if (!(intrinsics[Intrinsic_306] = CheckRuntimeObject("vec_vupkhsh"))) return 0; - if (!(intrinsics[Intrinsic_307] = CheckRuntimeObject("vec_vupklsh"))) return 0; - if (!(intrinsics[Intrinsic_308] = CheckRuntimeObject("vec_vxor"))) return 0; - if (!(intrinsics[Intrinsic_309] = CheckRuntimeObject("vec_abs"))) return 0; - if (!(intrinsics[Intrinsic_310] = CheckRuntimeObject("vec_abss"))) return 0; - } - - return 1; -} - -Boolean Intrinsics_IsPublicRuntimeObject(Object *object) { - int i; - - for (i = 0; i < MaxIntrinsics; i++) { - if (object == intrinsics[i]) - return 1; - } - - return 0; -} diff --git a/compiler_and_linker/unsorted/IrOptimizer.c b/compiler_and_linker/unsorted/IrOptimizer.c deleted file mode 100644 index c9544a2..0000000 --- a/compiler_and_linker/unsorted/IrOptimizer.c +++ /dev/null @@ -1,400 +0,0 @@ -#include "compiler/IrOptimizer.h" -#include "compiler/CError.h" -#include "compiler/CParser.h" -#include "compiler/InlineAsmPPC.h" -#include "compiler/IroCSE.h" -#include "compiler/IroDump.h" -#include "compiler/IroEval.h" -#include "compiler/IroFlowgraph.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroSubable.h" -#include "compiler/IroTransform.h" -#include "compiler/IROUseDef.h" -#include "compiler/IroUtil.h" -#include "compiler/IroVars.h" -#include "compiler/objects.h" -#include "compiler/IroPropagate.h" -#include "compiler/IroPointerAnalysis.h" -#include "compiler/IroJump.h" -#include "compiler/IroRangePropagation.h" -#include "compiler/IroEmptyLoop.h" -#include "compiler/IroUnrollLoop.h" -#include "compiler/IroLoop.h" -#include "compiler/IroExprRegeneration.h" - -Boolean DoScalarize; -Boolean DoLinearize; -Boolean EarlyReturn; -Boolean IRO_CPFirstTime; -Boolean VectorPhaseCalledFromUnroll; -Boolean IRO_Log; -static Boolean stIsSetup; - -static void CountRefToObject(Object *object, int depth) { - static unsigned short LoopUsage[] = {1, 4, 16, 64}; - - if (depth > 3) - depth = 3; - - object->u.var.info->usage += LoopUsage[depth]; - object->u.var.info->used = 1; -} - -static void CountARef(IROLinear *node, int depth) { - Object *object; - - object = node->u.node->data.objref; - CError_ASSERT(78, object->datatype != DALIAS); - - if (object->datatype == DLOCAL && object->u.var.info) { - CountRefToObject(object, depth); - if ((node->flags & IROLF_Used) && (node->flags & IROLF_Assigned)) - CountRefToObject(object, depth); - - if (!(node->flags & IROLF_Immind) && !object->u.var.info->noregister) - object->u.var.info->noregister = 2; - } -} - -static void CountDoubleInd(IROLinear *node, int depth) { - if (IRO_IsVariable(node)) { - CountARef(node->u.monadic, depth); - } else if (node->type == IROLinearOp2Arg) { - if (node->nodetype == EADD) { - CountDoubleInd(node->u.diadic.left, depth); - CountDoubleInd(node->u.diadic.right, depth); - } else if (IRO_IsAddressMultiply(node)) { - if (IRO_IsVariable(node->u.diadic.left)) - CountARef(node->u.diadic.left->u.monadic, depth); - } - } -} - -static void CountUsage(void) { - IRONode *fnode = IRO_FirstNode; - IROLinear *node; - - if (IRO_FirstNode) { - for (; fnode; fnode = fnode->nextnode) { - for (node = fnode->first; node; node = node->next) { - if (IS_LINEAR_ENODE(node, EOBJREF)) - CountARef(node, fnode->loopdepth); - else if (IS_LINEAR_MONADIC(node, EINDIRECT)) - CountDoubleInd(node->u.monadic, fnode->loopdepth); - - if (node->type == IROLinearAsm) { - IAEffects effects; - int i; - - CodeGen_GetAsmEffects(node->u.asm_stmt, &effects); - for (i = 0; i < effects.numoperands; i++) { - Object *object = effects.operands[i].object; - if (object->datatype == DLOCAL && object->u.var.info) { - CountRefToObject(object, fnode->loopdepth); - if (effects.operands[i].type == IAOpnd_3 && !object->u.var.info->noregister) - object->u.var.info->noregister = 2; - } - } - } - - if (node == fnode->last) - break; - } - } - } else { - for (node = IRO_FirstLinear; node; node = node->next) { - if (IS_LINEAR_ENODE(node, EOBJREF)) - CountARef(node, 0); - else if (IS_LINEAR_MONADIC(node, EINDIRECT)) - CountDoubleInd(node->u.monadic, 0); - } - } - - IRO_CheckForUserBreak(); -} - -Statement *IRO_Optimizer(Object *func, Statement *statements) { - Boolean changed; - int pass; - int passCount; - - CError_ASSERT(234, stIsSetup); - -#ifdef CW_ENABLE_IRO_DEBUG - if (copts.debuglisting) - IRO_Log = 1; -#endif - - DisableDueToAsm = 0; - FunctionName = func; - DoScalarize = 1; - DoLinearize = 1; - EarlyReturn = 0; - IRO_Depends = NULL; - LoopOptimizerRun = 0; - IRO_IsLeafFunction = 1; - IRO_FunctionHasReturn = 0; - - IRO_SetupForUserBreakChecking(); - - IRO_Dump("Starting function %s\n", func ? func->name->name : "Init-code"); - IRO_Dump("--------------------------------------------------------------------------------\n"); - - if (DoLinearize) - IRO_PreLinearize(statements); - if (copts.optimizationlevel > 0) - IRO_TransformTree(statements); - - VectorPhaseCalledFromUnroll = 0; - - IRO_Linearize(statements); - - CurStat = NULL; - - IRO_FirstExpr = NULL; - IRO_LastExpr = NULL; - IRO_FirstAssign = NULL; - IRO_LastAssign = NULL; - IRO_FirstVarUse = NULL; - IRO_LastVarUse = NULL; - IRO_FirstNode = NULL; - IRO_LastNode = NULL; - - if (copts.optimizationlevel > 0) - IRO_DoTransformations(); - - IRO_BuildFlowgraph(IRO_FirstLinear); - IRO_DumpAfterPhase("IRO_BuildflowGraph", 0); - - IRO_FindAllVars(); - IRO_CheckInit(); - - if (!DisableDueToAsm && copts.optimizationlevel > 0 && copts.opt_pointer_analysis && func) { - IRO_AnalyzePointers(func); - if (copts.propagation && IRO_EvaluateDefinitePointers(func)) { - IRO_UpdateFlagsOnInts(); - IRO_UpdateVars(); - IRO_DumpAfterPhase("IRO_EvaluateDefinitePointers", 0); - } - } - - if (copts.optimizationlevel > 0) { - changed = IRO_EvaluateConditionals(); - - if (!DisableDueToAsm) { - changed |= IRO_RemoveUnreachable(); - IRO_DumpAfterPhase("IRO_RemoveUnreachable", 0); - } - - changed |= IRO_RemoveRedundantJumps(); - IRO_DumpAfterPhase("IRO_RemoveRedundantJumps", 0); - - if (!DisableDueToAsm) { - changed |= IRO_RemoveLabels(); - IRO_DumpAfterPhase("IRO_RemoveLabels()", 0); - } - - if (changed) { - IRO_BuildFlowgraph(IRO_FirstLinear); - IRO_DumpAfterPhase("IRO_BuildflowGraph--1", 0); - } - } - - if (!DisableDueToAsm && copts.optimizationlevel > 0) { - passCount = copts.multiplepasses ? 2 : 1; - IRO_CPFirstTime = 1; - for (pass = 0; pass < passCount; pass++) { - IRO_Dump("*****************\n"); - IRO_Dump("Dumps for pass=%d\n", pass); - IRO_Dump("*****************\n"); - - if (DoScalarize) - IRO_ScalarizeClassDataMembers(); - IRO_DumpAfterPhase("IRO_ScalarizeClassDataMembers", 0); - - if (copts.propagation) { - IRO_CopyAndConstantPropagation(); - IRO_CPFirstTime = 0; - IRO_ExpressionPropagation(); - IRO_DumpAfterPhase("Copy and constant propagation", 0); - - IRO_RangePropagateInFNode(); - IRO_DumpAfterPhase("IRO_RangePropagateInFNode", 0); - IRO_UpdateFlagsOnInts(); - } - - IRO_DumpAfterPhase("IRO_ExpressionPropagation", 0); - - if (copts.deadstore || copts.propagation) - IRO_UseDef(copts.deadstore, copts.propagation); - IRO_DumpAfterPhase("after IRO_UseDef", 0); - - IRO_UpdateVars(); - IRO_ConstantFolding(); - IRO_DumpAfterPhase("IRO_ConstantFolding", 0); - - IRO_EvaluateConditionals(); - IRO_RemoveUnreachable(); - IRO_SimplifyConditionals(); - - if (pass == 1 && copts.optimizationlevel > 2) { - IRO_RenumberInts(); - IRO_DumpAfterPhase("Before IRO_FindEmptyLoops", 0); - IRO_FindEmptyLoops(); - IRO_DumpAfterPhase("After IRO_FindEmptyLoops", 0); - IRO_RenumberInts(); - } - - if (copts.unrolling && !copts.optimizesize && pass == 0) { - IRO_DumpAfterPhase("Before IRO_LoopUnroller", 0); - IRO_LoopUnroller(); - IRO_DumpAfterPhase("After IRO_LoopUnroller", 0); - IRO_RenumberInts(); - } - - VectorPhaseCalledFromUnroll = 0; - - if (pass == 0 && (copts.loopinvariants || copts.strengthreduction)) { - IRO_DumpAfterPhase("Before IRO_FindLoops", 0); - IRO_FindLoops(); - LoopOptimizerRun = 1; - IRO_SetLoopDepth(); - } - IRO_DumpAfterPhase("After IRO_FindLoops", 0); - - if (copts.propagation) { - IRO_CopyAndConstantPropagation(); - IRO_ConstantFolding(); - IRO_EvaluateConditionals(); - } - - IRO_DumpAfterPhase("Second pass:IRO_CopyAndConstantPropagation, IRO_ConstantFolding, IRO_EvaluateConditionals", 0); - - if (copts.commonsubs) - IRO_FindExpressions(NULL, 0); - - if (copts.commonsubs) { - IRO_ComputeAvail(); - IRO_CommonSubs(); - } - IRO_DumpAfterPhase("IRO_CommonSubs", 0); - - IRO_UpdateFlagsOnInts(); - IRO_UpdateVars(); - IRO_DoTransformations(); - IRO_ConstantFolding(); - - do { - IRO_UpdateFlagsOnInts(); - - if (copts.deadcode) - IRO_RemoveUnreachable(); - IRO_DumpAfterPhase("IRO_RemoveUnreachable", 0); - - changed = IRO_RemoveRedundantJumps(); - IRO_DumpAfterPhase("IRO_RemoveRedundantJumps", 0); - - changed |= IRO_RemoveLabels(); - IRO_DumpAfterPhase("IRO_RemoveLabels", 0); - - changed |= IRO_DoJumpChaining(); - IRO_DumpAfterPhase("IRO_DoJumpChaining", 0); - - if (copts.propagation) { - IRO_RenumberInts(); - IRO_DumpAfterPhase("Before IRO_CopyAndConstantPropagation", 0); - changed |= IRO_CopyAndConstantPropagation(); - IRO_DumpAfterPhase("After IRO_CopyAndConstantPropagation", 0); - IRO_ConstantFolding(); - } - - if (copts.deadstore || copts.propagation) - changed |= IRO_UseDef(copts.deadstore, copts.propagation); - IRO_DumpAfterPhase("IRO_UseDef", 0); - - changed |= IRO_EvaluateConditionals(); - IRO_DumpAfterPhase("IRO_EvaluateConditionals", 0); - } while (changed); - } - - if (copts.lifetimes) { - IRO_UseDef(0, 0); - IRO_SplitLifetimes(); - } - - IRO_DoTransformations(); - IRO_DumpAfterPhase("Before RebuildCondExpressions", 0); - } - - IRO_RenumberInts(); - IRO_DumpAfterPhase("before IRO_RewriteBitFieldTemps", 0); - IRO_RewriteBitFieldTemps(); - IRO_DumpAfterPhase("After IRO_RewriteBitFieldTemps", 0); - - CountUsage(); - - if (!DisableDueToAsm) { - IRO_RegenerateExpressions(); - IRO_DumpAfterPhase("IRO_RegenerateExpressions", 0); - } - - IRO_DumpAfterPhase("After IRO_Optimizer", 0); - - statements = IRO_Delinearize(IRO_FirstNode, NULL); - - IRO_ZapVarPtrs(); - freeoheap(); - return statements; -} - -void IRO_Setup(void) { - static Boolean ENodeArraysHaveBeenInitialized; - - if (!stIsSetup) { - IRO_Log = 0; - IRO_SetupDump(); - if (!ENodeArraysHaveBeenInitialized) { - IRO_InitializeNodeNamesArray(); - IRO_InitializeIsAssociativeENodeTypeArray(); - IRO_InitializeIsSubableOpArray(); - IRO_InitializeAssignmentOpArray(); - IRO_InitializeComplementaryOpArray(); - IRO_InitializeComplementaryOpLogicalArray(); - IRO_InitializeNonAssignmentOpArray(); - IRO_InitializeAssignmentFoldingFunctionArray(); - IRO_InitializeIRO_IsModifyOpArray(); - IRO_InitializeIRO_IsAssignOpArray(); - ENodeArraysHaveBeenInitialized = 1; - } - stIsSetup = 1; - } -} - -void IRO_Cleanup(void) { - if (stIsSetup) { - IRO_CleanupDump(); - stIsSetup = 0; - } -} - -void CodeGen_UpdateOptimizerOptions(void) { - Boolean flag; - - flag = copts.optimizationlevel >= 1; - copts.deadcode = flag; - - flag = copts.optimizationlevel >= 2; - copts.propagation = flag; - copts.commonsubs = flag; - - flag = copts.optimizationlevel >= 3; - copts.vectorizeloops = flag; - copts.unrolling = flag; - copts.deadstore = flag; - copts.lifetimes = flag; - copts.strengthreduction = flag; - copts.loopinvariants = flag; - - flag = copts.optimizationlevel >= 4; - copts.multiplepasses = flag; -} diff --git a/compiler_and_linker/unsorted/IroBitVect.c b/compiler_and_linker/unsorted/IroBitVect.c deleted file mode 100644 index 29bc28a..0000000 --- a/compiler_and_linker/unsorted/IroBitVect.c +++ /dev/null @@ -1,112 +0,0 @@ -#include "compiler/BitVector.h" -#include "compiler/CompilerTools.h" - -void Bv_AllocVector(BitVector **bv, UInt32 size) { - UInt32 long_size = (size / 32) + 1; - *bv = oalloc(sizeof(BitVector) + sizeof(UInt32) * long_size); - (*bv)->size = long_size; - Bv_Clear(*bv); -} - -void Bv_AllocVectorLocal(BitVector **bv, UInt32 size) { - UInt32 long_size = (size / 32) + 1; - *bv = lalloc(sizeof(BitVector) + sizeof(UInt32) * long_size); - (*bv)->size = long_size; - Bv_Clear(*bv); -} - -void Bv_ClearBit(UInt32 bit, BitVector *bv) { - if ((bit / 32) < bv->size) - bv->data[bit / 32] &= ~(1 << (bit & 31)); - else - CError_FATAL(73); -} - -void Bv_And(const BitVector *a, BitVector *b) { - UInt32 i; - for (i = 0; i < b->size; i++) - b->data[i] &= a->data[i]; -} - -void Bv_Or(const BitVector *a, BitVector *b) { - UInt32 i, len; - - len = a->size; - if (b->size < len) - len = b->size; - - for (i = 0; i < len; i++) { - b->data[i] |= a->data[i]; - } -} - -Boolean Bv_BitsInCommon(const BitVector *a, const BitVector *b) { - UInt32 len; - UInt32 i; - - len = a->size; - if (b->size < len) - len = b->size; - - for (i = 0; i < len; i++) { - if (a->data[i] & b->data[i]) - return 1; - } - - return 0; -} - -Boolean Bv_Compare(const BitVector *a, const BitVector *b) { - UInt32 i; - for (i = 0; i < a->size; i++) { - if (a->data[i] != b->data[i]) - return 0; - } - - return 1; -} - -void Bv_Minus(const BitVector *a, BitVector *b) { - UInt32 i; - for (i = 0; i < b->size; i++) - b->data[i] &= ~a->data[i]; -} - -void Bv_Copy(const BitVector *src, BitVector *dst) { - memcpy(dst->data, src->data, sizeof(UInt32) * dst->size); -} - -void Bv_Clear(BitVector *bv) { - memset(bv->data, 0, sizeof(UInt32) * bv->size); -} - -void Bv_Set(BitVector *bv) { - memset(bv->data, 0xFF, sizeof(UInt32) * bv->size); -} - -Boolean Bv_IsSubset(const BitVector *a, const BitVector *b) { - UInt32 i; - - for (i = 0; i < a->size; i++) { - if (b->size < i) { - if (a->data[i]) - return 0; - } else { - if (a->data[i] & ~(b->data[i])) - return 0; - } - } - - return 1; -} - -Boolean Bv_IsEmpty(const BitVector *bv) { - UInt32 i; - - for (i = 0; i < bv->size; i++) { - if (bv->data[i]) - return 0; - } - - return 1; -} diff --git a/compiler_and_linker/unsorted/IroCSE.c b/compiler_and_linker/unsorted/IroCSE.c deleted file mode 100644 index 5fa9849..0000000 --- a/compiler_and_linker/unsorted/IroCSE.c +++ /dev/null @@ -1,1038 +0,0 @@ -#include "compiler/IroCSE.h" -#include "compiler/IroDump.h" -#include "compiler/IroFlowgraph.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroMalloc.h" -#include "compiler/IroPointerAnalysis.h" -#include "compiler/IroSubable.h" -#include "compiler/IROUseDef.h" -#include "compiler/IroUtil.h" -#include "compiler/IroVars.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CInt64.h" -#include "compiler/CParser.h" -#include "compiler/CompilerTools.h" -#include "compiler/objects.h" - -BitVector *IRO_Depends; -Boolean IRO_NotSubable; -Boolean IRO_IsVolatile; -Boolean IRO_CouldError; -IROExpr *IRO_FirstExpr; -IROExpr *IRO_LastExpr; -SInt32 IRO_NumExprs; -static Boolean HasVectorOperand; - -// forward decls -static void IRO_DependsOnForDataFlow(IROLinear *linear, Boolean flag); - -static void GetDependsOfIndirect(IROLinear *nd) { - IROListNode *resultList; - IROListNode *next; - IROListNode *list; - IROListNode *scan; - IROLinear *scannd; - Object *obj; - VarRecord *var; - int index; - Boolean result; - Boolean foundObjRef; - - result = 0; - - if (nd && copts.opt_pointer_analysis && nd->pointsToFunction && FunctionName) { - resultList = NULL; - PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, nd, &resultList); - if ((list = resultList)) { - for (scan = list; scan; scan = scan->nextList) { - if (!scan->list.head || !scan->list.tail) { - result = 1; - break; - } - - foundObjRef = 0; - for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { - if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { - foundObjRef = 1; - break; - } - } - - if (!foundObjRef) { - result = 1; - break; - } - } - - if (!result) { - while (list) { - for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { - if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { - obj = scannd->u.node->data.objref; - CError_ASSERT(119, obj != NULL); - var = IRO_FindVar(obj, 1, 1); - CError_ASSERT(121, var != NULL); - index = var->index; - CError_ASSERT(123, index != 0); - - if (is_volatile_object(obj)) { - IRO_IsVolatile = 1; - IRO_NotSubable = 1; - } - Bv_SetBit(index, IRO_Depends); - } - } - list = list->nextList; - } - } - - while (resultList) { - next = resultList->nextList; - IRO_free(resultList); - resultList = next; - } - } else { - result = 1; - } - } else { - result = 1; - } - - if (result) { - nd = nd->u.monadic; - if (nd->type == IROLinearOp1Arg && nd->nodetype == EBITFIELD) - nd = nd->u.monadic; - - if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD) { - IRO_BaseTerms = 0; - IRO_VarTerms = 0; - IRO_DecomposeAddressExpression_Cheap(nd); - if (IRO_BaseTerms != 1) { - IRO_CouldError = 1; - Bv_SetBit(0, IRO_Depends); - Bv_Or(IRO_FuncKills, IRO_Depends); - } - if (IRO_VarTerms) - IRO_CouldError = 1; - } else { - IRO_CouldError = 1; - Bv_SetBit(0, IRO_Depends); - Bv_Or(IRO_FuncKills, IRO_Depends); - } - } -} - -static void GetDependsOfFunctionCallForDataFlow(IROLinear *nd) { - IROLinear *innernd; - IROListNode *resultList; - IROListNode *next; - IROListNode *list; - IROListNode *scan; - IROLinear *scannd; - Object *obj; - VarRecord *var; - int index; - Boolean result; - Boolean foundObjRef; - ObjectList *olist; - ObjectList *depsList; - - result = 0; - innernd = nd->u.funccall.linear8; - - if (innernd && copts.opt_pointer_analysis && innernd->pointsToFunction && FunctionName) { - resultList = NULL; - PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, innernd, &resultList); - if ((list = resultList)) { - for (scan = list; scan; scan = scan->nextList) { - if (!scan->list.head || !scan->list.tail) { - result = 1; - break; - } - - foundObjRef = 0; - for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { - if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { - foundObjRef = 1; - obj = scannd->u.node->data.objref; - CError_ASSERT(234, obj != NULL); - - depsList = NULL; - PointerAnalysis_GetFunctionDependencies(obj, nd, &depsList); - - for (olist = depsList; olist; olist = olist->next) { - if (!olist->object) { - result = 1; - break; - } - } - - while (depsList) { - olist = depsList->next; - IRO_free(depsList); - depsList = olist; - } - - if (result) - break; - } - } - - if (!foundObjRef) - result = 1; - if (result) - break; - } - - if (!result) { - for (list = resultList; list; list = list->nextList) { - for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { - if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { - obj = scannd->u.node->data.objref; - - depsList = NULL; - PointerAnalysis_GetFunctionDependencies(obj, nd, &depsList); - - for (olist = depsList; olist; olist = olist->next) { - var = IRO_FindVar(olist->object, 1, 1); - CError_ASSERT(285, var != NULL); - index = var->index; - CError_ASSERT(287, index != 0); - - if (is_volatile_object(olist->object)) { - IRO_IsVolatile = 1; - IRO_NotSubable = 1; - } - Bv_SetBit(index, IRO_Depends); - } - - while (depsList) { - olist = depsList->next; - IRO_free(depsList); - depsList = olist; - } - } - } - } - } - - while (resultList) { - next = resultList->nextList; - IRO_free(resultList); - resultList = next; - } - } else { - result = 1; - } - } else { - result = 1; - } - - if (result) { - IRO_DependsOnForDataFlow(nd->u.funccall.linear8, 0); - Bv_Or(IRO_FuncKills, IRO_Depends); - - for (index = nd->u.funccall.argCount - 1; index >= 0; index--) - IRO_DependsOnForDataFlow(nd->u.funccall.args[index], 0); - } -} - -static void IRO_DependsOn(IROLinear *linear, Boolean flag) { - VarRecord *var; - IROLinear *inner; - - if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) { - IRO_IsVolatile = 1; - IRO_NotSubable = 1; - } - - if (!IRO_NotSubable) { - switch (linear->type) { - case IROLinearOperand: - if (flag && linear->u.node->type == EOBJREF) { - if ((var = IRO_FindVar(linear->u.node->data.objref, 0, 1))) { - if (is_volatile_object(var->object)) { - IRO_IsVolatile = 1; - IRO_NotSubable = 1; - } - Bv_SetBit(var->index, IRO_Depends); - } else { - IRO_NotSubable = 1; - } - } - break; - case IROLinearOp1Arg: - if (IRO_IsAssignOp[linear->nodetype]) { - IRO_NotSubable = 1; - } else { - inner = linear->u.monadic; - if (linear->nodetype == EINDIRECT) { - if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD) - inner = inner->u.monadic; - if (inner->type != IROLinearOperand || inner->u.node->type != EOBJREF) - GetDependsOfIndirect(linear); - } - - IRO_DependsOn(inner, linear->nodetype == EINDIRECT); - } - break; - case IROLinearOp2Arg: - if (IRO_IsAssignOp[linear->nodetype]) { - IRO_NotSubable = 1; - } else { - if (linear->nodetype == EDIV || linear->nodetype == EMODULO) { - if (IRO_IsIntConstant(linear->u.diadic.right)) { - if (CInt64_Equal(linear->u.diadic.right->u.node->data.intval, cint64_zero)) - IRO_CouldError = 1; - } else { - IRO_CouldError = 1; - } - } - - IRO_DependsOn(linear->u.diadic.left, flag); - IRO_DependsOn(linear->u.diadic.right, flag); - } - break; - case IROLinearOp3Arg: - if (IRO_IsAssignOp[linear->nodetype]) { - IRO_NotSubable = 1; - } else { - IRO_DependsOn(linear->u.args3.a, flag); - IRO_DependsOn(linear->u.args3.b, flag); - IRO_DependsOn(linear->u.args3.c, flag); - } - break; - case IROLinearFunccall: - IRO_NotSubable = 1; - break; - default: - CError_FATAL(479); - } - } -} - -static void IRO_DependsOnForDataFlow(IROLinear *linear, Boolean flag) { - VarRecord *var; - IROLinear *inner; - - if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) { - IRO_IsVolatile = 1; - IRO_NotSubable = 1; - } - - switch (linear->type) { - case IROLinearOperand: - if (flag && linear->u.node->type == EOBJREF) { - if ((var = IRO_FindVar(linear->u.node->data.objref, 0, 1))) { - if (is_volatile_object(var->object)) { - IRO_IsVolatile = 1; - IRO_NotSubable = 1; - } - Bv_SetBit(var->index, IRO_Depends); - } else { - IRO_NotSubable = 1; - } - } - break; - case IROLinearOp1Arg: - if (IRO_IsAssignOp[linear->nodetype]) - IRO_NotSubable = 1; - - inner = linear->u.monadic; - if (linear->nodetype == EINDIRECT) { - if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD) - inner = inner->u.monadic; - if (inner->type != IROLinearOperand || inner->u.node->type != EOBJREF) - GetDependsOfIndirect(linear); - } - - IRO_DependsOnForDataFlow(inner, linear->nodetype == EINDIRECT); - break; - case IROLinearOp2Arg: - if (IRO_IsAssignOp[linear->nodetype]) - IRO_NotSubable = 1; - - if (linear->nodetype == EDIV || linear->nodetype == EMODULO) { - if (IRO_IsIntConstant(linear->u.diadic.right)) { - if (CInt64_Equal(linear->u.diadic.right->u.node->data.intval, cint64_zero)) - IRO_CouldError = 1; - } else { - IRO_CouldError = 1; - } - } - - IRO_DependsOnForDataFlow(linear->u.diadic.left, flag); - IRO_DependsOnForDataFlow(linear->u.diadic.right, flag); - break; - case IROLinearOp3Arg: - if (IRO_IsAssignOp[linear->nodetype]) - IRO_NotSubable = 1; - - IRO_DependsOnForDataFlow(linear->u.args3.a, flag); - IRO_DependsOnForDataFlow(linear->u.args3.b, flag); - IRO_DependsOnForDataFlow(linear->u.args3.c, flag); - break; - case IROLinearFunccall: - IRO_NotSubable = 1; - GetDependsOfFunctionCallForDataFlow(linear); - break; - default: - CError_FATAL(650); - } -} - -void IRO_FindDepends_NoAlloc(IROLinear *linear) { - Bv_Clear(IRO_Depends); - IRO_CouldError = 0; - IRO_NotSubable = 0; - IRO_IsVolatile = 0; - IRO_DependsOnForDataFlow(linear, 0); -} - -void IRO_FindDepends(IROLinear *linear) { - Bv_AllocVector(&IRO_Depends, IRO_NumVars + 1); - IRO_CouldError = 0; - IRO_NotSubable = 0; - IRO_DependsOn(linear, 0); -} - -static void VecAct(IROLinear *linear, Boolean isFirst) { - if (!isFirst && (linear->flags & IROLF_VecOpBase)) - HasVectorOperand = 1; -} - -static Boolean IRO_DoesNotHaveVectorOperand(IROLinear *linear) { - HasVectorOperand = 0; - IRO_WalkTree(linear, VecAct); - return HasVectorOperand == 0; -} - -static void IRO_AddExpression(IROLinear *linear, IRONode *node, Boolean flag) { - IROExpr *expr; - - if ((linear->flags & IROLF_Reffed) && IRO_IsSubableExpression(linear) && IRO_DoesNotHaveVectorOperand(linear)) { - expr = oalloc(sizeof(IROExpr)); - expr->x0 = 0; - expr->index = ++IRO_NumExprs; - expr->linear = linear; - expr->x8 = NULL; - expr->node = node; - IRO_FindDepends(linear); - expr->depends = IRO_Depends; - expr->notSubable = IRO_NotSubable; - expr->couldError = IRO_CouldError; - expr->next = NULL; - expr->x14 = NULL; - if (IRO_FirstExpr) - IRO_LastExpr->next = expr; - else - IRO_FirstExpr = expr; - IRO_LastExpr = expr; - linear->expr = expr; - } -} - -void IRO_FindExpressions(BitVector *bv, Boolean flag) { - IROLinear *nd; - IRONode *fnode; - - IRO_FirstExpr = IRO_LastExpr = NULL; - IRO_NumExprs = 0; - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - if (!bv || Bv_IsBitSet(fnode->index, bv)) { - for (nd = fnode->first; nd; nd = nd->next) { - nd->expr = NULL; - IRO_AddExpression(nd, fnode, flag); - if (nd == fnode->last) - break; - } - } else { - for (nd = fnode->first; nd; nd = nd->next) { - nd->expr = NULL; - if (nd == fnode->last) - break; - } - } - } - - IRO_CheckForUserBreak(); -} - -void IRO_RemoveExpr(IROExpr *expr) { - IROExpr *prev; - IROExpr *scan; - - scan = IRO_FirstExpr; - prev = NULL; - while (scan != expr) { - prev = scan; - scan = scan->next; - CError_ASSERT(809, scan); - } - - expr->linear->expr = NULL; - if (prev) - prev->next = expr->next; - else - IRO_FirstExpr = expr->next; -} - -static void GetExprKillsByIndirectAssignment(IROLinear *linear) { - IROLinear *inner; - IROListNode *resultList; - IROListNode *next; - IROListNode *list; - IROListNode *scan; - IROLinear *scannd; - Object *obj; - VarRecord *var; - int index; - Boolean result; - Boolean foundObjRef; - IROExpr *expr; - - result = 0; - if (linear->type == IROLinearOp2Arg) - linear = linear->u.diadic.left; - else - linear = linear->u.monadic; - - if ( - linear && - linear->type == IROLinearOp1Arg && - linear->nodetype == EINDIRECT && - (inner = linear->u.monadic) && - copts.opt_pointer_analysis && - inner->pointsToFunction && - FunctionName - ) { - resultList = NULL; - PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList); - if ((list = resultList)) { - for (scan = list; scan; scan = scan->nextList) { - if (!scan->list.head || !scan->list.tail) { - result = 1; - break; - } - - foundObjRef = 0; - for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { - if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { - foundObjRef = 1; - break; - } - } - - if (!foundObjRef) { - result = 1; - break; - } - } - - if (!result) { - while (list) { - for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { - if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { - obj = scannd->u.node->data.objref; - CError_ASSERT(893, obj != NULL); - var = IRO_FindVar(obj, 1, 1); - CError_ASSERT(895, var != NULL); - index = var->index; - - for (expr = IRO_FirstExpr; expr; expr = expr->next) { - if (Bv_IsBitSet(index, expr->depends)) - Bv_SetBit(expr->index, IRO_ExprKills); - } - } - } - list = list->nextList; - } - } - - while (resultList) { - next = resultList->nextList; - IRO_free(resultList); - resultList = next; - } - } else { - result = 1; - } - } else { - result = 1; - } - - if (result) { - for (expr = IRO_FirstExpr; expr; expr = expr->next) { - if (Bv_BitsInCommon(expr->depends, IRO_FuncKills)) - Bv_SetBit(expr->index, IRO_ExprKills); - } - } -} - -static void GetExprKillsByFunctionCall(IROLinear *funccall) { - IROLinear *innernd; - IROListNode *resultList; - IROListNode *next; - IROListNode *list; - IROListNode *scan; - IROLinear *scannd; - Object *obj; - VarRecord *var; - int index; - Boolean result; - Boolean foundObjRef; - ObjectList *olist; - ObjectList *depsList; - IROExpr *expr; - - result = 0; - innernd = funccall->u.funccall.linear8; - - if (innernd && copts.opt_pointer_analysis && innernd->pointsToFunction && FunctionName) { - resultList = NULL; - PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, innernd, &resultList); - if ((list = resultList)) { - for (scan = list; scan; scan = scan->nextList) { - if (!scan->list.head || !scan->list.tail) { - result = 1; - break; - } - - foundObjRef = 0; - for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { - if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { - foundObjRef = 1; - obj = scannd->u.node->data.objref; - CError_ASSERT(991, obj != NULL); - - depsList = NULL; - PointerAnalysis_GetFunctionKills(obj, funccall, &depsList); - - for (olist = depsList; olist; olist = olist->next) { - if (!olist->object) { - result = 1; - break; - } - } - - while (depsList) { - olist = depsList->next; - IRO_free(depsList); - depsList = olist; - } - - if (result) - break; - } - } - - if (!foundObjRef) - result = 1; - if (result) - break; - } - - if (!result) { - for (list = resultList; list; list = list->nextList) { - for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { - if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { - obj = scannd->u.node->data.objref; - - depsList = NULL; - PointerAnalysis_GetFunctionKills(obj, funccall, &depsList); - - for (olist = depsList; olist; olist = olist->next) { - var = IRO_FindVar(olist->object, 1, 1); - CError_ASSERT(1042, var != NULL); - index = var->index; - CError_ASSERT(1044, index != 0); - - for (expr = IRO_FirstExpr; expr; expr = expr->next) { - if (Bv_IsBitSet(index, expr->depends)) - Bv_SetBit(expr->index, IRO_ExprKills); - } - } - - while (depsList) { - olist = depsList->next; - IRO_free(depsList); - depsList = olist; - } - } - } - } - } - - while (resultList) { - next = resultList->nextList; - IRO_free(resultList); - resultList = next; - } - } else { - result = 1; - } - } else { - result = 1; - } - - if (result) { - for (expr = IRO_FirstExpr; expr; expr = expr->next) { - if (Bv_BitsInCommon(expr->depends, IRO_FuncKills)) - Bv_SetBit(expr->index, IRO_ExprKills); - } - } -} - -static void IRO_GetExprKills(IROLinear *linear) { - Bv_Clear(IRO_ExprKills); - switch (linear->type) { - case IROLinearOp1Arg: - case IROLinearOp2Arg: - if (IRO_IsAssignOp[linear->nodetype]) { - VarRecord *var; - int index; - - var = IRO_FindAssigned(linear); - index = 0; - if (var) - index = var->index; - if (!index) { - GetExprKillsByIndirectAssignment(linear); - } else { - IROExpr *expr; - for (expr = IRO_FirstExpr; expr; expr = expr->next) { - if (Bv_IsBitSet(index, expr->depends)) - Bv_SetBit(expr->index, IRO_ExprKills); - } - } - } - break; - case IROLinearAsm: { - IROExpr *expr; - IRO_GetKills(linear); - for (expr = IRO_FirstExpr; expr; expr = expr->next) { - if (Bv_BitsInCommon(expr->depends, IRO_VarKills)) - Bv_SetBit(expr->index, IRO_ExprKills); - } - break; - } - case IROLinearFunccall: - GetExprKillsByFunctionCall(linear); - break; - } -} - -void IRO_ComputeAvail(void) { - IRONode *node; - IROLinear *linear; - SInt32 counter; - BitVector *bv; - Boolean flag; - - counter = 0; - node = IRO_FirstNode; - Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); - Bv_AllocVector(&IRO_ExprKills, IRO_NumExprs + 1); - - while (node) { - Bv_AllocVector(&node->x16, IRO_NumExprs); - if (node->numpred) - Bv_Set(node->x16); - Bv_AllocVector(&node->x22, IRO_NumExprs); - Bv_AllocVector(&node->x1E, IRO_NumExprs); - Bv_AllocVector(&node->x1A, IRO_NumExprs); - - for (linear = node->first; linear; linear = linear->next) { - if (linear->expr) - Bv_SetBit(linear->expr->index, node->x1E); - IRO_GetExprKills(linear); - Bv_Or(IRO_ExprKills, node->x22); - Bv_Minus(IRO_ExprKills, node->x1E); - if (linear == node->last) - break; - - if (counter > 250) { - IRO_CheckForUserBreak(); - counter = 0; - } else { - counter++; - } - } - - Bv_Copy(node->x16, node->x1A); - Bv_Minus(node->x22, node->x1A); - Bv_Or(node->x1E, node->x1A); - node = node->nextnode; - } - - IRO_CheckForUserBreak(); - - Bv_AllocVector(&bv, IRO_NumExprs); - do { - flag = 0; - for (node = IRO_FirstNode; node; node = node->nextnode) { - if (!node->numpred) { - Bv_Clear(bv); - } else { - UInt16 i; - Bv_Set(bv); - for (i = 0; i < node->numpred; i++) - Bv_And(IRO_NodeTable[node->pred[i]]->x1A, bv); - } - - if (!Bv_Compare(bv, node->x16)) { - flag = 1; - Bv_Copy(bv, node->x16); - } - - Bv_Copy(node->x16, node->x1A); - Bv_Minus(node->x22, node->x1A); - Bv_Or(node->x1E, node->x1A); - } - IRO_CheckForUserBreak(); - } while (flag); -} - -static void IRO_MakeReplacementEmbedded(IROExpr *expr) { - IROLinear *opnd; - IROLinear *ind; - IROLinear *ass; - - IRO_GetTemp(expr); - - opnd = IRO_NewLinear(IROLinearOperand); - opnd->u.node = create_objectrefnode(expr->x8); - opnd->rtype = opnd->u.node->data.objref->type; - opnd->index = ++IRO_NumLinear; - opnd->flags |= IROLF_Reffed | IROLF_Assigned | IROLF_Ind; - - ind = IRO_NewLinear(IROLinearOp1Arg); - ind->nodetype = EINDIRECT; - ind->rtype = expr->linear->rtype; - ind->u.monadic = opnd; - ind->index = ++IRO_NumLinear; - ind->flags |= IROLF_Reffed | IROLF_Assigned; - - ass = IRO_NewLinear(IROLinearOp2Arg); - ass->nodetype = EASS; - ass->u.diadic.left = ind; - ass->u.diadic.right = expr->linear; - ass->rtype = expr->linear->rtype; - ass->index = ++IRO_NumLinear; - - opnd->next = ind; - ind->next = ass; - IRO_ReplaceReferenceWithNode(expr->linear, ass); - IRO_PasteAfter(opnd, ass, expr->linear); -} - -static void IRO_ActUnmarkSubExpressions(IROLinear *linear, Boolean isFirst) { - if (isFirst) - linear->flags &= ~IROLF_8; -} - -static void CheckCommonSub(IROLinear *linear) { - IROExpr *expr; - - for (expr = IRO_FirstExpr; expr; expr = expr->next) { - if (expr->linear != linear && !expr->x14) { - if (Bv_IsBitSet(expr->index, IRO_Avail) && !expr->notSubable && IRO_ExprsSame(linear, expr->linear)) { - IRO_WalkTree(linear, IRO_ActUnmarkSubExpressions); - linear->flags |= IROLF_8; - linear->expr->x14 = expr; - break; - } - } - } -} - -static void MoveCommonSub(IROExpr *expr) { - SInt32 best; - SInt32 sz1; - SInt32 sz2; - SInt32 i1; - SInt32 i2; - IROLinear *scan; - IROLinear *array1[64]; - IROLinear *array2[64]; - IROExpr *scanexpr; - - sz1 = 0; - scan = expr->linear; - do { - scan = IRO_LocateFather(scan); - if (scan) { - if (sz1 == 64) - return; - array1[sz1++] = scan; - } - } while (scan); - - best = -1; - for (scanexpr = IRO_FirstExpr; scanexpr; scanexpr = scanexpr->next) { - if (scanexpr->x14 == expr) { - sz2 = 0; - scan = scanexpr->linear; - do { - scan = IRO_LocateFather(scan); - if (scan) { - if (sz2 == 64) - return; - array2[sz2++] = scan; - } - } while (scan); - - i1 = sz1; - i2 = sz2; - while (i1 && i2 && array1[i1 - 1] == array2[i2 - 1]) { - i1--; - i2--; - } - - if (i1 != sz1 && i1 > best) - best = i1; - } - } - - if (best < 0) { - IRO_MakeReplacementEmbedded(expr); - } else { - IROLinear *start; - IROLinear *comma; - IRO_Dump("Moving common sub from node %d to %d\n", expr->linear->index, array1[best]->index); - start = IRO_FindStart(array1[best]); - IRO_GetTemp(expr); - IRO_ReplaceReference(expr->linear, expr->x8, expr->linear); - IRO_MoveExpression(expr, start); - - comma = IRO_NewLinear(IROLinearOp2Arg); - comma->nodetype = ECOMMA; - comma->rtype = array1[best]->rtype; - comma->u.diadic.left = IRO_AssignToTemp(expr); - comma->u.diadic.right = array1[best]; - comma->stmt = array1[best]->stmt; - IRO_ReplaceReferenceWithNode(array1[best], comma); - IRO_PasteAfter(comma, comma, array1[best]); - } -} - -static void ReplaceCommonSub(IROLinear *linear) { - IROExpr *expr = linear->expr->x14; - if (!expr->x8) { - MoveCommonSub(expr); - if (!expr->x8) - return; - } - - IRO_Dump("Replacing common sub at %d with %d\n", linear->index, expr->linear->index); - IRO_ReplaceReference(linear, expr->x8, linear); - IRO_RemoveExpr(linear->expr); - IRO_NopOut(linear); -} - -void IRO_CommonSubs(void) { - IRONode *node; - IROLinear *linear; - SInt32 counter; - - counter = 0; - for (node = IRO_FirstNode; node; node = node->nextnode) { - IRO_Avail = node->x16; - linear = node->first; - while (1) { - if (!linear) - break; - if (linear->expr && !linear->expr->notSubable) - CheckCommonSub(linear); - if (linear->expr) - Bv_SetBit(linear->expr->index, IRO_Avail); - IRO_GetExprKills(linear); - Bv_Minus(IRO_ExprKills, IRO_Avail); - if (linear == node->last) - break; - if (counter > 250) { - IRO_CheckForUserBreak(); - counter = 0; - } else { - counter++; - } - linear = linear->next; - } - } - - for (node = IRO_FirstNode; node; node = node->nextnode) { - for (linear = node->first; linear; linear = linear->next) { - if (linear->expr && (linear->flags & IROLF_8) && !IRO_HasSideEffect(linear)) - ReplaceCommonSub(linear); - if (linear == node->last) - break; - if (counter > 250) { - IRO_CheckForUserBreak(); - counter = 0; - } else { - counter++; - } - } - } - - IRO_CheckForUserBreak(); -} - -static Boolean CountThisSubableOperandUse(IROUse *use) { - return use->x1C != 0; -} - -static int GetSubableOperandUseCount(VarRecord *var) { - int count = 0; - IROUse *use; - - if (var->uses) { - for (use = var->uses; use; use = use->varnext) { - if (CountThisSubableOperandUse(use)) - count++; - } - } - - return count; -} - -static void IRO_MakeTopLevelExprForSubableOperand(IROLinear *linear) { - IROLinear *copy = IRO_NewLinear(IROLinearOperand); - memcpy(copy, linear, sizeof(IROLinear)); - copy->index = ++IRO_NumLinear; - - if (IRO_FirstLinear && IRO_FirstLinear->type == IROLinearNop) - IRO_PasteAfter(copy, copy, IRO_FirstLinear); - else - IRO_Paste(copy, copy, IRO_FirstLinear); -} - -void IRO_GenerateTopLevelExprsForSubableOperands(void) { - IROLinear *nd; - IRONode *fnode; - VarRecord *var; - BitVector *bv; - - Bv_AllocVector(&bv, IRO_NumVars + 1); - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - for (nd = fnode->first; nd; nd = nd->next) { - nd->expr = NULL; - if ((nd->flags & IROLF_Reffed) && IRO_IsSubableExpression(nd) && IRO_DoesNotHaveVectorOperand(nd)) { - if (nd->type == IROLinearOperand && nd->u.node && nd->u.node->type == EOBJREF) { - if ((var = IRO_FindVar(nd->u.node->data.objref, 0, 1))) { - if (!Bv_IsBitSet(var->index, bv)) { - IRO_MakeTopLevelExprForSubableOperand(nd); - Bv_SetBit(var->index, bv); - } - } - } - } - - if (nd == fnode->last) - break; - } - } -} diff --git a/compiler_and_linker/unsorted/IroDump.c b/compiler_and_linker/unsorted/IroDump.c deleted file mode 100644 index e7ca940..0000000 --- a/compiler_and_linker/unsorted/IroDump.c +++ /dev/null @@ -1,660 +0,0 @@ -#include "compiler/IroDump.h" -#include "compiler/IroFlowgraph.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroPropagate.h" -#include "compiler/IroUtil.h" -#include "compiler/CFunc.h" -#include "compiler/CInt64.h" -#include "compiler/CParser.h" -#include "compiler/objects.h" -#include "compiler/IroVars.h" -#include "compiler/IroCSE.h" - -static FILE *DumpFile; -static char *nodenames[MAXEXPR]; - -char *IRO_NodeName(ENodeType nodetype) { - return nodenames[nodetype]; -} - -void IRO_InitializeNodeNamesArray(void) { - int i; - for (i = 0; i < MAXEXPR; i++) - nodenames[i] = ""; - - nodenames[EPOSTINC] = "EPOSTINC"; - nodenames[EPOSTDEC] = "EPOSTDEC"; - nodenames[EPREINC] = "EPREINC"; - nodenames[EPREDEC] = "EPREDEC"; - nodenames[EINDIRECT] = "EINDIRECT"; - nodenames[EMONMIN] = "EMONMIN"; - nodenames[EBINNOT] = "EBINNOT"; - nodenames[ELOGNOT] = "ELOGNOT"; - nodenames[EFORCELOAD] = "EFORCELOAD"; - nodenames[EMUL] = "EMUL"; - nodenames[EMULV] = "EMULV"; - nodenames[EDIV] = "EDIV"; - nodenames[EMODULO] = "EMODULO"; - nodenames[EADDV] = "EADDV"; - nodenames[ESUBV] = "ESUBV"; - nodenames[EADD] = "EADD"; - nodenames[ESUB] = "ESUB"; - nodenames[ESHL] = "ESHL"; - nodenames[ESHR] = "ESHR"; - nodenames[ELESS] = "ELESS"; - nodenames[EGREATER] = "EGREATER"; - nodenames[ELESSEQU] = "ELESSEQU"; - nodenames[EGREATEREQU] = "EGREATEREQU"; - nodenames[EEQU] = "EEQU"; - nodenames[ENOTEQU] = "ENOTEQU"; - nodenames[EAND] = "EAND"; - nodenames[EXOR] = "EXOR"; - nodenames[EOR] = "EOR"; - nodenames[ELAND] = "ELAND"; - nodenames[ELOR] = "ELOR"; - nodenames[EASS] = "EASS"; - nodenames[EMULASS] = "EMULASS"; - nodenames[EDIVASS] = "EDIVASS"; - nodenames[EMODASS] = "EMODASS"; - nodenames[EADDASS] = "EADDASS"; - nodenames[ESUBASS] = "ESUBASS"; - nodenames[ESHLASS] = "ESHLASS"; - nodenames[ESHRASS] = "ESHRASS"; - nodenames[EANDASS] = "EANDASS"; - nodenames[EXORASS] = "EXORASS"; - nodenames[EORASS] = "EORASS"; - nodenames[ECOMMA] = "ECOMMA"; - nodenames[EPMODULO] = "EPMODULO"; - nodenames[EROTL] = "EROTL"; - nodenames[EROTR] = "EROTR"; - nodenames[EBCLR] = "EBCLR"; - nodenames[EBTST] = "EBTST"; - nodenames[EBSET] = "EBSET"; - nodenames[ETYPCON] = "ETYPCON"; - nodenames[EBITFIELD] = "EBITFIELD"; - nodenames[EINTCONST] = "EINTCONST"; - nodenames[EFLOATCONST] = "EFLOATCONST"; - nodenames[ESTRINGCONST] = "ESTRINGCONST"; - nodenames[ECOND] = "ECOND"; - nodenames[EFUNCCALL] = "EFUNCCALL"; - nodenames[EFUNCCALLP] = "EFUNCCALLP"; - nodenames[EOBJREF] = "EOBJREF"; - nodenames[EMFPOINTER] = "EMFPOINTER"; - nodenames[ENULLCHECK] = "ENULLCHECK"; - nodenames[EPRECOMP] = "EPRECOMP"; - nodenames[ETEMP] = "ETEMP"; - nodenames[EARGOBJ] = "EARGOBJ"; - nodenames[ELOCOBJ] = "ELOCOBJ"; - nodenames[ELABEL] = "ELABEL"; - nodenames[ESETCONST] = "ESETCONST"; - nodenames[ENEWEXCEPTION] = "ENEWEXCEPTION"; - nodenames[ENEWEXCEPTIONARRAY] = "ENEWEXCEPTIONARRAY"; - nodenames[EOBJLIST] = "EOBJLIST"; - nodenames[EMEMBER] = "EMEMBER"; - nodenames[ETEMPLDEP] = "ETEMPLDEP"; - nodenames[EINSTRUCTION] = "EINSTRUCTION"; - nodenames[EDEFINE] = "EDEFINE"; - nodenames[EREUSE] = "EREUSE"; - nodenames[EASSBLK] = "EASSBLK"; - nodenames[EVECTOR128CONST] = "EVECTOR128CONST"; - nodenames[ECONDASS] = "ECONDASS"; -} - -static void DumpENode(ENode *enode) { - char buf[64]; - - if (IRO_Log) { - switch (enode->type) { - case EOBJREF: - fprintf(DumpFile, "%s", enode->data.objref->name->name); - break; - case EINTCONST: - CInt64_PrintDec(buf, enode->data.intval); - fprintf(DumpFile, "%s", buf); - break; - case EFLOATCONST: - fprintf(DumpFile, "%g", enode->data.floatval.value); - break; - case EVECTOR128CONST: - fprintf(DumpFile, "%.8lX%.8lX%.8lX%.8lX", - enode->data.vector128val.ul[0], - enode->data.vector128val.ul[1], - enode->data.vector128val.ul[2], - enode->data.vector128val.ul[3] - ); - break; - } - } -} - -static void DumpLinearNode(IROLinear *linear) { - int i; - - if (IRO_Log) { - fprintf(DumpFile, "%4d: ", linear->index); - switch (linear->type) { - case IROLinearNop: - fprintf(DumpFile, "Nop"); - break; - case IROLinearOperand: - fprintf(DumpFile, "Operand "); - DumpENode(linear->u.node); - break; - case IROLinearOp1Arg: - fprintf(DumpFile, "%s %d", nodenames[linear->nodetype], linear->u.monadic->index); - break; - case IROLinearOp2Arg: - fprintf(DumpFile, "%s %d %d", nodenames[linear->nodetype], linear->u.diadic.left->index, linear->u.diadic.right->index); - break; - case IROLinearGoto: - fprintf(DumpFile, "Goto %s", linear->u.label.label->name->name); - break; - case IROLinearIf: - fprintf(DumpFile, "If %d %s", linear->u.label.x4->index, linear->u.label.label->name->name); - break; - case IROLinearIfNot: - fprintf(DumpFile, "IfNot %d %s", linear->u.label.x4->index, linear->u.label.label->name->name); - break; - case IROLinearReturn: - fprintf(DumpFile, "Return "); - if (linear->u.monadic) - fprintf(DumpFile, "%d", linear->u.monadic->index); - break; - case IROLinearLabel: - fprintf(DumpFile, "Label %s", linear->u.label.label->name->name); - break; - case IROLinearSwitch: - fprintf(DumpFile, "Switch %d", linear->u.swtch.x4->index); - break; - case IROLinearOp3Arg: - fprintf(DumpFile, "%s %d %d %d", - nodenames[linear->nodetype], - linear->u.args3.a->index, - linear->u.args3.b->index, - linear->u.args3.c->index); - break; - case IROLinearFunccall: - fprintf(DumpFile, "Funccall %d(", linear->u.funccall.linear8->index); - for (i = 0; i < linear->u.funccall.argCount; i++) { - fprintf(DumpFile, "%d", linear->u.funccall.args[i]->index); - if (i < (linear->u.funccall.argCount - 1)) - fprintf(DumpFile, ","); - } - fprintf(DumpFile, ")"); - break; - case IROLinearBeginCatch: - fprintf(DumpFile, "BeginCatch %d", linear->u.ctch.linear->index); - break; - case IROLinearEndCatch: - fprintf(DumpFile, "EndCatch %d", linear->u.monadic->index); - break; - case IROLinearEndCatchDtor: - fprintf(DumpFile, "EndCatchDtor %d", linear->u.monadic->index); - break; - case IROLinearEnd: - fprintf(DumpFile, "End"); - break; - } - - if (linear->flags & IROLF_Assigned) fprintf(DumpFile, " "); - if (linear->flags & IROLF_Used) fprintf(DumpFile, " "); - if (linear->flags & IROLF_Ind) fprintf(DumpFile, " "); - if (linear->flags & IROLF_Subs) fprintf(DumpFile, " "); - if (linear->flags & IROLF_LoopInvariant) fprintf(DumpFile, " "); - if (linear->flags & IROLF_BeginLoop) fprintf(DumpFile, " "); - if (linear->flags & IROLF_EndLoop) fprintf(DumpFile, " "); - if (linear->flags & IROLF_Ris) fprintf(DumpFile, " "); - if (linear->flags & IROLF_Immind) fprintf(DumpFile, " "); - if (linear->flags & IROLF_Reffed) fprintf(DumpFile, " "); - if (linear->flags & IROLF_VecOp) fprintf(DumpFile, " "); - if (linear->flags & IROLF_VecOpBase) fprintf(DumpFile, " "); - if (linear->flags & IROLF_CounterLoop) fprintf(DumpFile, " "); - if (linear->flags & IROLF_BitfieldIndirect) fprintf(DumpFile, " "); - if (linear->flags & IROLF_CouldError) fprintf(DumpFile, " "); - - if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) - fprintf(DumpFile, " "); - - if (IS_LINEAR_ENODE(linear, EOBJREF)) { - VarRecord *var = IRO_FindVar(linear->u.node->data.objref, 0, 1); - if (var && is_volatile_object(var->object)) - fprintf(DumpFile, " "); - } - - fprintf(DumpFile, "\n"); - } -} - -static void DumpAct(IROLinear *linear, Boolean isFirst) { - if (!isFirst) - DumpLinearNode(linear); -} - -void IRO_DumpIntTree(IROLinear *linear) { - IRO_WalkTree(linear, DumpAct); -} - -void IRO_DumpLinearList(IROLinear *linear) { - if (!IRO_Log) - return; - - while (linear) { - DumpLinearNode(linear); - linear = linear->next; - } - fprintf(DumpFile, "\n"); -} - -static void DumpList(int num, UInt16 *list) { - int i; - - if (IRO_Log) { - for (i = 0; i < num; i++) - fprintf(DumpFile, "%d ", list[i]); - fprintf(DumpFile, "\n"); - } -} - -void IRO_DumpBits(char *name, BitVector *bv) { - SInt32 i; - SInt32 rangeStart; - Boolean inRange = 0; - Boolean isFirst = 1; - - if (!IRO_Log) - return; - - fprintf(DumpFile, name); - if (!bv) { - fprintf(DumpFile, "NULL"); - } else { - for (i = 0; i < (bv->size * 32); i++) { - if (Bv_IsBitSet(i, bv)) { - if (!inRange) { - if (!isFirst) - fputc(',', DumpFile); - isFirst = 0; - fprintf(DumpFile, "%d", i); - inRange = 1; - rangeStart = i; - } - } else { - if (inRange) { - inRange = 0; - if (i != (rangeStart + 1)) - fprintf(DumpFile, "-%d", i - 1); - } - } - } - - if (inRange && i != (rangeStart + 1)) - fprintf(DumpFile, "-%d", i - 1); - } - - fprintf(DumpFile, "\n"); -} - -void IRO_DumpAfterPhase(char *str, Boolean flag) { -#ifdef CW_ENABLE_IRO_DEBUG - if (copts.debuglisting) - flag = 1; -#endif - if (flag) { - IRO_Dump("Dumping function %s after %s \n", FunctionName ? FunctionName->name->name : "Init-code", str); - IRO_Dump("--------------------------------------------------------------------------------\n"); - IRO_DumpFlowgraph(); - } -} - -void IRO_LogForFunction(char *name) { - if (FunctionName) { - if (!strcmp(FunctionName->name->name, name)) - IRO_Log = 1; - else - IRO_Log = 0; - } -} - -void IRO_DumpFlowgraph(void) { - IRONode *node; - IROLinear *linear; - - if (IRO_Log && DumpFile) { - fprintf(DumpFile, "\nFlowgraph\n"); - for (node = IRO_FirstNode; node; node = node->nextnode) { - fprintf(DumpFile, "Flowgraph node %d First=%d, Last=%d\n", node->index, node->first->index, node->last->index); - - fprintf(DumpFile, "Succ = "); - DumpList(node->numsucc, node->succ); - fprintf(DumpFile, "Pred = "); - DumpList(node->numpred, node->pred); - - fprintf(DumpFile, "MustReach = %d, MustReach1=%d\n", node->mustreach, node->mustreach1); - fprintf(DumpFile, "LoopDepth = %d\n", node->loopdepth); - - IRO_DumpBits("Dom: ", node->dom); - if ((linear = node->first)) { - while (1) { - DumpLinearNode(linear); - if (linear == node->last) - break; - linear = linear->next; - } - } - - fprintf(DumpFile, "\n\n"); - } - fprintf(DumpFile, "\n"); - fflush(DumpFile); - } -} - -void IRO_DumpNode(IRONode *node) { - IROLinear *linear; - - if (IRO_Log) { - if (!DumpFile) - return; - - while (node) { - fprintf(DumpFile, "Flowgraph node %d First=%d, Last=%d\n", node->index, node->first->index, - node->last->index); - - fprintf(DumpFile, "Succ = "); - DumpList(node->numsucc, node->succ); - fprintf(DumpFile, "Pred = "); - DumpList(node->numpred, node->pred); - - fprintf(DumpFile, "MustReach = %d MustReach1 = %d\n", node->mustreach, node->mustreach1); - fprintf(DumpFile, "LoopDepth = %d\n", node->loopdepth); - - IRO_DumpBits("Dom: ", node->dom); - if ((linear = node->first)) { - while (1) { - DumpLinearNode(linear); - if (linear == node->last) - break; - linear = linear->next; - } - } - - fprintf(DumpFile, "\n\n"); - node = node->nextnode; - } - - fprintf(DumpFile, "\n"); - fflush(DumpFile); - } -} - -void IRO_DumpAssignments(void) { - IROAssign *assign; - - if (IRO_Log) { - fprintf(DumpFile, "\nAssignments\n\n"); - for (assign = IRO_FirstAssign; assign; assign = assign->next) { - fprintf(DumpFile, "%5d ", assign->index); - DumpLinearNode(assign->linear); - fprintf(DumpFile, "\n"); - } - fprintf(DumpFile, "\n"); - } -} - -void IRO_DumpVars(void) { - VarRecord *var; - - if (IRO_Log) { - fprintf(DumpFile, "\nVariables\n"); - for (var = IRO_FirstVar; var; var = var->next) { - fprintf(DumpFile, "%5d %s %s\n", var->index, var->object->name->name, var->xB ? "" : ""); - } - fprintf(DumpFile, "\n"); - } -} - -void IRO_DumpDf(void) { - IRONode *node; - - if (IRO_Log) { - for (node = IRO_FirstNode; node; node = node->nextnode) { - fprintf(DumpFile, "Node %d\n", node->index); - if (node->x16) IRO_DumpBits("In: ", node->x16); - if (node->x1E) IRO_DumpBits("Gen: ", node->x1E); - if (node->x22) IRO_DumpBits("Kill: ", node->x22); - if (node->x1A) IRO_DumpBits("Out: ", node->x1A); - if (node->x2A) IRO_DumpBits("AA: ", node->x2A); - fprintf(DumpFile, "\n"); - } - fprintf(DumpFile, "\n"); - } -} - -void IRO_DumpExprs(void) { - IROExpr *expr; - - if (IRO_Log) { - fprintf(DumpFile, "Expressions\n\n"); - for (expr = IRO_FirstExpr; expr; expr = expr->next) { - fprintf(DumpFile, "%4d: %d FN:%d CE:%d NS:%d ", expr->index, expr->linear->index, expr->node->index, expr->couldError, expr->notSubable); - IRO_DumpBits("Depends: ", expr->depends); - fprintf(DumpFile, "\n"); - } - fprintf(DumpFile, "\n"); - } -} - -void IRO_SetupDump(void) { -#ifdef CW_ENABLE_IRO_DEBUG - IRO_Log = 1; -#endif - - if (IRO_Log) { - if ((DumpFile = fopen("OPT.LOG", "wt")) == NULL) - IRO_Log = 0; - } -} - -void IRO_CleanupDump(void) { - if (DumpFile) - fclose(DumpFile); -} - -void IRO_Dump(char *format, ...) { - va_list va; - if (IRO_Log) { - va_start(va, format); - vfprintf(DumpFile, format, va); - va_end(va); - } -} - -void IRO_DumpAddr(IROAddrRecord *rec) { - IROElmList *list; - - if (IRO_Log && DumpFile) { - fprintf(DumpFile, "\n"); - fprintf(DumpFile, "Address :\n"); - IRO_DumpIntTree(rec->linear); - fprintf(DumpFile, "\n"); - fprintf(DumpFile, "BaseTerms:\n"); - for (list = rec->objRefs; list; list = list->next) { - IRO_DumpIntTree(list->element); - fprintf(DumpFile, "\n"); - } - fprintf(DumpFile, "VarTerms:\n"); - for (list = rec->misc; list; list = list->next) { - IRO_DumpIntTree(list->element); - fprintf(DumpFile, "\n"); - } - fprintf(DumpFile, "ConstTerms:\n"); - for (list = rec->ints; list; list = list->next) { - IRO_DumpIntTree(list->element); - fprintf(DumpFile, "\n"); - } - } -} - -static void IRO_DumpType(Type *type) { - char buf[256]; - IRO_SpellType(type, buf); - fprintf(DumpFile, " (%s)", buf); -} - -void IRO_SpellType(Type *type, char *buf) { - char mybuf[256]; - char mybuf2[256]; - - switch (type->type) { - case TYPEVOID: - strcpy(buf, "void"); - break; - case TYPEINT: - switch (TYPE_INTEGRAL(type)->integral) { - case IT_BOOL: - strcpy(buf, "bool"); - break; - case IT_CHAR: - strcpy(buf, "char"); - break; - case IT_WCHAR_T: - strcpy(buf, "wchar_t"); - break; - case IT_SCHAR: - strcpy(buf, "signed char"); - break; - case IT_UCHAR: - strcpy(buf, "unsigned char"); - break; - case IT_SHORT: - strcpy(buf, "short"); - break; - case IT_USHORT: - strcpy(buf, "unsigned short"); - break; - case IT_INT: - strcpy(buf, "int"); - break; - case IT_UINT: - strcpy(buf, "unsigned int"); - break; - case IT_LONG: - strcpy(buf, "long"); - break; - case IT_ULONG: - strcpy(buf, "unsigned long"); - break; - case IT_LONGLONG: - strcpy(buf, "long long"); - break; - case IT_ULONGLONG: - strcpy(buf, "unsigned long long"); - break; - } - break; - case TYPEFLOAT: - switch (TYPE_INTEGRAL(type)->integral) { - case IT_FLOAT: - strcpy(buf, "float"); - break; - case IT_SHORTDOUBLE: - strcpy(buf, "short double"); - break; - case IT_DOUBLE: - strcpy(buf, "double"); - break; - case IT_LONGDOUBLE: - strcpy(buf, "long double"); - break; - } - break; - case TYPEENUM: - strcpy(buf, "enum "); - if (TYPE_ENUM(type)->enumname) - strcat(buf, TYPE_ENUM(type)->enumname->name); - break; - case TYPESTRUCT: - if (IS_TYPESTRUCT_VECTOR(TYPE_STRUCT(type))) { - switch (TYPE_STRUCT(type)->stype) { - case STRUCT_VECTOR_UCHAR: - strcpy(buf, "vector unsigned char "); - break; - case STRUCT_VECTOR_SCHAR: - strcpy(buf, "vector signed char "); - break; - case STRUCT_VECTOR_BCHAR: - strcpy(buf, "vector bool char "); - break; - case STRUCT_VECTOR_USHORT: - strcpy(buf, "vector unsigned short "); - break; - case STRUCT_VECTOR_SSHORT: - strcpy(buf, "vector signed short "); - break; - case STRUCT_VECTOR_BSHORT: - strcpy(buf, "vector bool short "); - break; - case STRUCT_VECTOR_UINT: - strcpy(buf, "vector unsigned long "); - break; - case STRUCT_VECTOR_SINT: - strcpy(buf, "vector signed long "); - break; - case STRUCT_VECTOR_BINT: - strcpy(buf, "vector bool long "); - break; - case STRUCT_VECTOR_FLOAT: - strcpy(buf, "vector float "); - break; - case STRUCT_VECTOR_PIXEL: - strcpy(buf, "vector pixel "); - break; - } - } else { - strcpy(buf, "struct "); - } - if (TYPE_STRUCT(type)->name) - strcat(buf, TYPE_STRUCT(type)->name->name); - break; - case TYPECLASS: - strcpy(buf, "class "); - if (TYPE_CLASS(type)->classname) - strcat(buf, TYPE_CLASS(type)->classname->name); - break; - case TYPEFUNC: - IRO_SpellType(TYPE_FUNC(type)->functype, mybuf); - strcpy(buf, "freturns("); - strcat(buf, mybuf); - strcat(buf, ")"); - break; - case TYPEBITFIELD: - IRO_SpellType(TYPE_BITFIELD(type)->bitfieldtype, mybuf); - sprintf(buf, "bitfield(%s){%d:%d}", mybuf, TYPE_BITFIELD(type)->offset, TYPE_BITFIELD(type)->bitlength); - break; - case TYPELABEL: - strcpy(buf, "label"); - break; - case TYPEPOINTER: - IRO_SpellType(TPTR_TARGET(type), mybuf); - strcpy(buf, "pointer("); - strcat(buf, mybuf); - strcat(buf, ")"); - break; - case TYPEARRAY: - IRO_SpellType(TPTR_TARGET(type), mybuf); - strcpy(buf, "array("); - strcat(buf, mybuf); - strcat(buf, ")"); - break; - case TYPEMEMBERPOINTER: - IRO_SpellType(TYPE_MEMBER_POINTER(type)->ty2, mybuf); - IRO_SpellType(TYPE_MEMBER_POINTER(type)->ty1, mybuf2); - strcpy(buf, "memberpointer("); - strcat(buf, mybuf); - strcat(buf, ","); - strcat(buf, mybuf2); - strcat(buf, ")"); - break; - } -} - diff --git a/compiler_and_linker/unsorted/IroEmptyLoop.c b/compiler_and_linker/unsorted/IroEmptyLoop.c deleted file mode 100644 index 1e319ab..0000000 --- a/compiler_and_linker/unsorted/IroEmptyLoop.c +++ /dev/null @@ -1,560 +0,0 @@ -#include "compiler/IroEmptyLoop.h" -#include "compiler/IroDump.h" -#include "compiler/IroFlowgraph.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroLoop.h" -#include "compiler/IroUtil.h" -#include "compiler/IroVars.h" -#include "compiler/CInt64.h" - -// forward decls -static Boolean EmptyLoop(IRONode *fnode); -static int CanRemoveRedundantLoop(IROLoop *loop); -static int CanRemoveRedundantLoop1(IROLoop *loop); -static int RedundantLoopCheck(IROLoop *loop); -static int CheckStepOverFlow1_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2); -static int CheckStepOverFlow2_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2); - -void IRO_FindEmptyLoops(void) { - IRONode *fnode; - IRONode *pred; - UInt16 i; - UInt16 x; - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - x = 0; - for (i = 0; i < fnode->numpred; i++) { - pred = IRO_NodeTable[fnode->pred[i]]; - if (Bv_IsBitSet(fnode->index, pred->dom)) { - if (!x) { - Bv_AllocVector(&InLoop, IRO_NumNodes + 1); - Bv_Clear(InLoop); - Bv_SetBit(fnode->index, InLoop); - } - x = 1; - Bv_SetBit(pred->index, InLoop); - if (pred != fnode) - AddPreds(pred); - } - } - - if (x) { - IRO_Dump("IRO_FindEmptyLoops:Found loop with header %d\n", fnode->index); - IRO_DumpBits("Loop includes: ", InLoop); - EmptyLoop(fnode); - IRO_UpdateFlagsOnInts(); - } - } - - IRO_CheckForUserBreak(); -} - -static Boolean EmptyLoop(IRONode *fnode) { - VarRecord *var; - IRONode *bestpred; - IRONode *pred; - UInt16 i; - int flag2; - IRONode *r24; - Boolean flag; - int counter; - int j; - IRONode *succ; - IRONode *bestsucc; - int counter2; - UInt32 counter3; - IROLoop *loop; - IRONode *r21; - IRONode *r20; - IROLinear *constnd; - Type *type20; - ENode *enode; - IROLinear *save; - - flag = 0; - counter = 0; - LoopNode = fnode; - FindMustReach(); - - for (var = IRO_FirstVar; var; var = var->next) - var->xA = 1; - - ComputeLoopKills(); - ComputeLoopInvariance(); - ComputeLoopInduction(); - - LoopNode = fnode; - ConditionalHeaderAtBottom = 0; - - bestpred = NULL; - flag2 = 0; - for (i = 0; i < LoopNode->numpred; i++) { - pred = IRO_NodeTable[LoopNode->pred[i]]; - if (!Bv_IsBitSet(pred->index, InLoop)) { - flag2 = 1; - if (pred->nextnode == fnode) { - CError_ASSERT(173, !bestpred || pred == bestpred); - bestpred = pred; - } - } - } - - if (!flag2) { - IRO_Dump("No predecessor outside the loop\n"); - return 0; - } - - bestsucc = NULL; - for (i = 0; i < LoopNode->numsucc; i++) { - succ = IRO_NodeTable[LoopNode->succ[i]]; - if (Bv_IsBitSet(succ->index, InLoop)) { - bestsucc = succ; - counter++; - } - } - - if (LoopNode == bestsucc && counter == 1) - flag = 1; - - if (LoopNode->last->type != IROLinearIf || LoopNode->last->type != IROLinearIfNot || flag) { - counter2 = 0; - for (j = 0; j < LoopNode->numpred; j++) { - if (Bv_IsBitSet(IRO_NodeTable[LoopNode->pred[j]]->index, InLoop)) { - r21 = IRO_NodeTable[LoopNode->pred[j]]; - counter2++; - } - } - - r24 = NULL; - counter3 = 0; - for (j = 0; j < LoopNode->numpred; j++) { - if (!Bv_IsBitSet(IRO_NodeTable[LoopNode->pred[j]]->index, InLoop)) { - r24 = IRO_NodeTable[LoopNode->pred[j]]; - counter3++; - } - } - - if (counter2 == 1 && counter3 == 1) { - if (r21->last->type == IROLinearIf) { - if ((Bv_IsBitSet(LoopNode->nextnode->index, InLoop) && !Bv_IsBitSet(r21->nextnode->index, InLoop)) || flag) { - IRO_Dump("Standard while loop layout\n"); - loop = ExtractLoopInfo(r21); - if (flag) - loop->flags |= LoopFlags_20000; - FindAssignmenttoInductionVar(loop, r24); - r20 = r24; - while (r20 && !loop->nd14 && r20->numpred == 1 && IRO_NodeTable[r20->pred[0]]->numsucc == 1) { - FindAssignmenttoInductionVar(loop, IRO_NodeTable[r20->pred[0]]); - r20 = IRO_NodeTable[r20->pred[0]]; - } - - if (CanRemoveRedundantLoop(loop)) { - IRO_Dump("EmptyLoop: # of iterations =%" PRId32 ", FinalStoreVal=%" PRId32 "\n", CInt64_GetULong(&loop->x28), CInt64_GetULong(&loop->x30)); - IRO_NopOut(r21->last->u.label.x4); - r21->last->type = IROLinearNop; - type20 = loop->induction->nd->rtype; - constnd = IRO_NewLinear(IROLinearOperand); - constnd->index = ++IRO_NumLinear; - enode = IRO_NewENode(EINTCONST); - enode->rtype = type20; - enode->data.intval = loop->x30; - constnd->u.node = enode; - constnd->rtype = type20; - - if (loop->induction->nd->type == IROLinearOp1Arg) { - save = loop->induction->nd->u.monadic; - loop->induction->nd->type = IROLinearOp2Arg; - loop->induction->nd->nodetype = EASS; - loop->induction->nd->u.diadic.left = save; - loop->induction->nd->u.diadic.right = constnd; - IRO_Paste(constnd, constnd, loop->induction->nd); - } else if (loop->induction->nd->type == IROLinearOp2Arg) { - loop->induction->nd->nodetype = EASS; - IRO_NopOut(loop->induction->nd->u.diadic.right); - loop->induction->nd->u.diadic.right = constnd; - IRO_Paste(constnd, constnd, loop->induction->nd); - } - } else if (CanRemoveRedundantLoop1(loop)) { - IRO_Dump("EmptyLoop: self recursive dowhile(--n ) loop\n"); - - r21->last->type = IROLinearNop; - type20 = loop->induction->nd->rtype; - constnd = IRO_NewLinear(IROLinearOperand); - constnd->index = ++IRO_NumLinear; - enode = IRO_NewENode(EINTCONST); - enode->rtype = type20; - enode->data.intval = cint64_zero; - constnd->u.node = enode; - constnd->rtype = type20; - - save = loop->induction->nd->u.monadic; - loop->induction->nd->type = IROLinearOp2Arg; - loop->induction->nd->nodetype = EASS; - loop->induction->nd->u.diadic.left = save; - loop->induction->nd->u.diadic.right = constnd; - IRO_Paste(constnd, constnd, loop->induction->nd); - } - } else { - IRO_Dump("NonStandard while loop layout\n"); - } - } else { - IRO_Dump("NonStandard while loop layout\n"); - } - } else { - IRO_Dump("Cannot handle Do While Loop with multiple tails\n"); - } - } - - return 0; -} - -static int CanRemoveRedundantLoop(IROLoop *loop) { - IROLinear *inner; - - if (loop->flags & LoopFlags_10000) { - IRO_Dump("CanRemoveRedundantLoop:No because detection of dowhile(n--) loop not supported\n"); - return 0; - } - - if (loop->flags & LP_LOOP_HAS_ASM) { - IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_ASM \n"); - return 0; - } - - if (loop->flags & LP_IFEXPR_NON_CANONICAL) { - IRO_Dump("CanRemoveRedundantLoop:No due to LP_IFEXPR_NON_CANONICAL \n"); - return 0; - } - - if (loop->flags & LP_LOOP_HAS_CALLS) { - IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_CALLS \n"); - return 0; - } - - if (loop->flags & LP_LOOP_HAS_CNTRLFLOW) { - IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HAS_CNTRLFLOW \n"); - return 0; - } - - if (loop->flags & LP_INDUCTION_NOT_FOUND) { - IRO_Dump("CanRemoveRedundantLoop:No due to LP_INDUCTION_NOT_FOUND \n"); - return 0; - } - - if (loop->flags & LP_HAS_MULTIPLE_INDUCTIONS) { - IRO_Dump("CanRemoveRedundantLoop:No due to LP_HAS_MULTIPLE_INDUCTIONS \n"); - return 0; - } - - if (loop->flags & LP_LOOP_HDR_HAS_SIDEEFFECTS) { - IRO_Dump("CanRemoveRedundantLoop:No due to LP_LOOP_HDR_HAS_SIDEEFFECTS \n"); - return 0; - } - - if (!(loop->flags & LoopFlags_200)) { - IRO_Dump("CanRemoveRedundantLoop:No because header does not follow induction update \n"); - return 0; - } - - if (!(loop->flags & LoopFlags_10000)) { - inner = loop->nd18->u.diadic.right; - if (!IRO_IsIntConstant(inner) && !(inner->flags & IROLF_LoopInvariant)) { - IRO_Dump("CanRemoveRedundantLoop:No because Loop Upper Bound is Variant in the loop\n"); - return 0; - } - - if (!loop->nd14) { - IRO_Dump("CanRemoveRedundantLoop:No because there is no initialization of loop index in PreHeader\n"); - return 0; - } - - if (!IRO_IsVariable(loop->nd14->u.diadic.left)) { - IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction stored thru pointer\n"); - return 0; - } - - if (!IRO_IsUnsignedType(loop->nd14->rtype)) { - if (IRO_IsIntConstant(loop->nd14->u.diadic.right)) { - if (!CInt64_GreaterEqual(loop->nd14->u.diadic.right->u.node->data.intval, cint64_zero)) { - IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction is signed but < 0\n"); - return 0; - } - } else { - IRO_Dump("CanRemoveRedundantLoop:No because initial value of induction is signed and not constant\n"); - return 0; - } - } - - if (!(loop->flags & LP_LOOP_STEP_ISPOS) && !(loop->flags & LP_LOOP_STEP_ISNEG)) { - IRO_Dump("CanRemoveRedundantLoop:No because LP_LOOP_STEP_ISPOS/LP_LOOP_STEP_ISNEG is not set\n"); - return 0; - } - - if ((loop->flags & LP_LOOP_STEP_ISPOS) && CheckStepOverFlow1_EmptyLoop(loop, &loop->x28, &loop->x30)) { - IRO_Dump("CanRemoveRedundantLoop:No because Final Value of indution will overflow\n"); - return 0; - } - - if ((loop->flags & LP_LOOP_STEP_ISNEG) && CheckStepOverFlow2_EmptyLoop(loop, &loop->x28, &loop->x30)) { - IRO_Dump("CanRemoveRedundantLoop:No because Final Value of indution will overflow\n"); - return 0; - } - } - - return RedundantLoopCheck(loop) != 0; -} - -static int CanRemoveRedundantLoop1(IROLoop *loop) { - if ((loop->flags & LoopFlags_10000) && (loop->flags & LoopFlags_20000)) { - if (loop->flags & LP_LOOP_HAS_ASM) { - IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_ASM \n"); - return 0; - } - - if (loop->flags & LP_IFEXPR_NON_CANONICAL) { - IRO_Dump("CanRemoveRedundantLoop1:No due to LP_IFEXPR_NON_CANONICAL \n"); - return 0; - } - - if (loop->flags & LP_LOOP_HAS_CALLS) { - IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_CALLS \n"); - return 0; - } - - if (loop->flags & LP_LOOP_HAS_CNTRLFLOW) { - IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HAS_CNTRLFLOW \n"); - return 0; - } - - if (loop->flags & LP_INDUCTION_NOT_FOUND) { - IRO_Dump("CanRemoveRedundantLoop1:No due to LP_INDUCTION_NOT_FOUND \n"); - return 0; - } - - if (loop->flags & LP_HAS_MULTIPLE_INDUCTIONS) { - IRO_Dump("CanRemoveRedundantLoop1:No due to LP_HAS_MULTIPLE_INDUCTIONS \n"); - return 0; - } - - if (loop->flags & LP_LOOP_HDR_HAS_SIDEEFFECTS) { - IRO_Dump("CanRemoveRedundantLoop1:No due to LP_LOOP_HDR_HAS_SIDEEFFECTS \n"); - return 0; - } - - if (!(loop->flags & LoopFlags_200)) { - IRO_Dump("CanRemoveRedundantLoop1:No because header does not follow induction update \n"); - return 0; - } - - if (loop->induction->nd->type == IROLinearOp1Arg && loop->induction->nd->nodetype == EPREDEC) { - if (IRO_IsUnsignedType(loop->induction->nd->rtype)) - return 1; - IRO_Dump("CanRemoveRedundantLoop1:No because induction not of the right type \n"); - return 0; - } - - IRO_Dump("CanRemoveRedundantLoop1:No because induction operator not a predec \n"); - return 0; - } else { - return 0; - } -} - -static int RedundantLoopCheck(IROLoop *loop) { - IRONode *fnode; - IROLinear *nd; - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - if (Bv_IsBitSet(fnode->index, InLoop) && fnode != loop->fnode && (nd = fnode->first)) { - while (1) { - if ((nd->index < loop->index20 || nd->index > loop->index24) && nd->type != IROLinearNop && nd->type != IROLinearLabel) { - if (IS_LINEAR_DIADIC(nd, EASS)) { - if (!(nd->flags & IROLF_Reffed)) { - if (IS_LINEAR_MONADIC(nd->u.diadic.left, EINDIRECT)) { - if (nd->u.diadic.left->rtype && CParser_IsVolatile(nd->u.diadic.left->rtype, nd->u.diadic.left->nodeflags & ENODE_FLAG_QUALS)) { - IRO_Dump(" EASS at %d fail as store to volatile memory \n", nd->index); - return 0; - } - - if ((nd->u.diadic.left->u.monadic->flags & IROLF_LoopInvariant) && (nd->u.diadic.right->flags & IROLF_LoopInvariant)) { - IRO_Dump(" EASS at %d pass\n", nd->index); - } else { - IRO_Dump(" EASS at %d fail, either LHS address or RHS is variant \n", nd->index); - return 0; - } - } else { - IRO_Dump("Found EASS nodes whose lhs root is not a EINDIRECT node\n"); - return 0; - } - } else { - IRO_Dump("Found EASS node that is referenced i.e embedded assignment\n"); - return 0; - } - } else { - if (!(nd->flags & IROLF_Reffed)) { - IRO_Dump("Found non EASS top level node in the loop\n"); - return 0; - } - } - } - - if (nd == fnode->last) - break; - nd = nd->next; - } - } - } - - return 1; -} - -static int CheckStepOverFlow1_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2) { - Boolean isUnsigned; - IROLinear *nd2; - IROLinear *nd1; - CInt64 nd2value; - CInt64 nd1value; - CInt64 addConst; - CInt64 work; - CInt64 neg1; - - nd2 = loop->nd14->u.diadic.right; - nd1 = loop->nd18->u.diadic.right; - isUnsigned = IRO_IsUnsignedType(loop->nd18->u.diadic.right->rtype); - - if (IRO_IsIntConstant(nd2) && IRO_IsIntConstant(nd1)) { - nd2value = nd2->u.node->data.intval; - nd1value = nd1->u.node->data.intval; - if (isUnsigned) { - if (CInt64_LessEqualU(nd1value, nd2value)) - return 1; - } else { - if (CInt64_LessEqual(nd1value, nd2value)) - return 1; - } - - CInt64_SetLong(&addConst, loop->induction->addConst); - CInt64_SetLong(&neg1, -1); - *val1 = CInt64_Sub(nd1value, nd2value); - *val1 = CInt64_Add(*val1, addConst); - if (IS_LINEAR_DIADIC(loop->nd18, ELESS)) - *val1 = CInt64_Add(*val1, neg1); - - CError_ASSERT(855, !CInt64_IsZero(&addConst)); - - if (isUnsigned) - *val1 = CInt64_DivU(*val1, addConst); - else - *val1 = CInt64_Div(*val1, addConst); - - if (CInt64_Equal(*val1, cint64_zero)) - return 1; - - if (isUnsigned) { - if (CInt64_LessEqualU(*val1, cint64_zero)) - CError_FATAL(877); - } else { - if (CInt64_LessEqual(*val1, cint64_zero)) - CError_FATAL(886); - } - - if (isUnsigned) { - *val2 = CInt64_MulU(*val1, addConst); - *val2 = CInt64_Add(*val2, nd2value); - } else { - *val2 = CInt64_Mul(*val1, addConst); - *val2 = CInt64_Add(*val2, nd2value); - } - } else { - return 1; - } - - CInt64_SetLong(&addConst, loop->induction->addConst); - work = CInt64_Add(nd1value, addConst); - - if (isUnsigned) { - if (CInt64_LessU(work, nd1value)) - return 1; - } else { - if (CInt64_Less(work, nd1value)) - return 1; - } - - return 0; -} - -static int CheckStepOverFlow2_EmptyLoop(IROLoop *loop, CInt64 *val1, CInt64 *val2) { - Boolean isUnsigned; - IROLinear *nd2; - IROLinear *nd1; - CInt64 nd2value; - CInt64 nd1value; - CInt64 addConst; - CInt64 work; - CInt64 neg1; - - nd1 = loop->nd14->u.diadic.right; - nd2 = loop->nd18->u.diadic.right; - isUnsigned = IRO_IsUnsignedType(loop->nd18->u.diadic.right->rtype); - - if (IRO_IsIntConstant(nd2) && IRO_IsIntConstant(nd1)) { - nd2value = nd2->u.node->data.intval; - nd1value = nd1->u.node->data.intval; - if (isUnsigned) { - if (CInt64_LessEqualU(nd1value, nd2value)) - return 1; - } else { - if (CInt64_LessEqual(nd1value, nd2value)) - return 1; - } - - CInt64_SetLong(&addConst, loop->induction->addConst); - CInt64_SetLong(&neg1, -1); - *val1 = CInt64_Sub(nd1value, nd2value); - *val1 = CInt64_Add(*val1, addConst); - if (IS_LINEAR_DIADIC(loop->nd18, EGREATER)) - *val1 = CInt64_Add(*val1, neg1); - - CError_ASSERT(995, !CInt64_IsZero(&addConst)); - - if (isUnsigned) - *val1 = CInt64_DivU(*val1, addConst); - else - *val1 = CInt64_Div(*val1, addConst); - - if (CInt64_Equal(*val1, cint64_zero)) - return 1; - - if (isUnsigned) { - if (CInt64_LessEqualU(*val1, cint64_zero)) - return 0; - } else { - if (CInt64_LessEqual(*val1, cint64_zero)) - return 0; - } - - if (isUnsigned) { - *val2 = CInt64_MulU(*val1, addConst); - *val2 = CInt64_Sub(nd1value, *val2); - } else { - *val2 = CInt64_Mul(*val1, addConst); - *val2 = CInt64_Sub(nd1value, *val2); - } - } else { - return 1; - } - - CInt64_SetLong(&addConst, loop->induction->addConst); - work = CInt64_Sub(nd2value, addConst); - - if (isUnsigned) { - if (CInt64_GreaterU(work, nd2value)) - return 1; - } else { - if (CInt64_Greater(work, nd1value)) - return 1; - } - - return 0; -} - diff --git a/compiler_and_linker/unsorted/IroEval.c b/compiler_and_linker/unsorted/IroEval.c deleted file mode 100644 index adf74b8..0000000 --- a/compiler_and_linker/unsorted/IroEval.c +++ /dev/null @@ -1,914 +0,0 @@ -#include "compiler/IroEval.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/IroFlowgraph.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroMalloc.h" -#include "compiler/IroPointerAnalysis.h" -#include "compiler/IroUtil.h" -#include "compiler/IroVars.h" -#include "compiler/enode.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -static Boolean IsAssociativeENodeType[MAXEXPR]; - -void IRO_InitializeIsAssociativeENodeTypeArray(void) { - int i; - - for (i = 0; i < MAXEXPR; i++) - IsAssociativeENodeType[i] = 0; - - IsAssociativeENodeType[EPOSTINC] = 0; - IsAssociativeENodeType[EPOSTDEC] = 0; - IsAssociativeENodeType[EPREINC] = 0; - IsAssociativeENodeType[EPREDEC] = 0; - IsAssociativeENodeType[EINDIRECT] = 0; - IsAssociativeENodeType[EMONMIN] = 0; - IsAssociativeENodeType[EBINNOT] = 0; - IsAssociativeENodeType[ELOGNOT] = 0; - IsAssociativeENodeType[EFORCELOAD] = 0; - IsAssociativeENodeType[EMUL] = 1; - IsAssociativeENodeType[EMULV] = 1; - IsAssociativeENodeType[EDIV] = 0; - IsAssociativeENodeType[EMODULO] = 0; - IsAssociativeENodeType[EADDV] = 1; - IsAssociativeENodeType[ESUBV] = 0; - IsAssociativeENodeType[EADD] = 1; - IsAssociativeENodeType[ESUB] = 0; - IsAssociativeENodeType[ESHL] = 0; - IsAssociativeENodeType[ESHR] = 0; - IsAssociativeENodeType[ELESS] = 0; - IsAssociativeENodeType[EGREATER] = 0; - IsAssociativeENodeType[ELESSEQU] = 0; - IsAssociativeENodeType[EGREATEREQU] = 0; - IsAssociativeENodeType[EEQU] = 0; - IsAssociativeENodeType[ENOTEQU] = 0; - IsAssociativeENodeType[EAND] = 1; - IsAssociativeENodeType[EXOR] = 1; - IsAssociativeENodeType[EOR] = 1; - IsAssociativeENodeType[ELAND] = 0; - IsAssociativeENodeType[ELOR] = 0; - IsAssociativeENodeType[EASS] = 0; - IsAssociativeENodeType[EMULASS] = 0; - IsAssociativeENodeType[EDIVASS] = 0; - IsAssociativeENodeType[EMODASS] = 0; - IsAssociativeENodeType[EADDASS] = 0; - IsAssociativeENodeType[ESUBASS] = 0; - IsAssociativeENodeType[ESHLASS] = 0; - IsAssociativeENodeType[ESHRASS] = 0; - IsAssociativeENodeType[EANDASS] = 0; - IsAssociativeENodeType[EXORASS] = 0; - IsAssociativeENodeType[EORASS] = 0; - IsAssociativeENodeType[ECOMMA] = 0; - IsAssociativeENodeType[EPMODULO] = 0; - IsAssociativeENodeType[EROTL] = 0; - IsAssociativeENodeType[EROTR] = 0; - IsAssociativeENodeType[EBCLR] = 0; - IsAssociativeENodeType[EBTST] = 0; - IsAssociativeENodeType[EBSET] = 0; - IsAssociativeENodeType[ETYPCON] = 0; - IsAssociativeENodeType[EBITFIELD] = 0; - IsAssociativeENodeType[EINTCONST] = 0; - IsAssociativeENodeType[EFLOATCONST] = 0; - IsAssociativeENodeType[ESTRINGCONST] = 0; - IsAssociativeENodeType[ECOND] = 0; - IsAssociativeENodeType[EFUNCCALL] = 0; - IsAssociativeENodeType[EFUNCCALLP] = 0; - IsAssociativeENodeType[EOBJREF] = 0; - IsAssociativeENodeType[EMFPOINTER] = 0; - IsAssociativeENodeType[ENULLCHECK] = 0; - IsAssociativeENodeType[EPRECOMP] = 0; - IsAssociativeENodeType[ETEMP] = 0; - IsAssociativeENodeType[EARGOBJ] = 0; - IsAssociativeENodeType[ELOCOBJ] = 0; - IsAssociativeENodeType[ELABEL] = 0; - IsAssociativeENodeType[ESETCONST] = 0; - IsAssociativeENodeType[ENEWEXCEPTION] = 0; - IsAssociativeENodeType[ENEWEXCEPTIONARRAY] = 0; - IsAssociativeENodeType[EOBJLIST] = 0; - IsAssociativeENodeType[EMEMBER] = 0; - IsAssociativeENodeType[ETEMPLDEP] = 0; - IsAssociativeENodeType[EINSTRUCTION] = 0; - IsAssociativeENodeType[EDEFINE] = 0; - IsAssociativeENodeType[EREUSE] = 0; - IsAssociativeENodeType[EASSBLK] = 0; - IsAssociativeENodeType[EVECTOR128CONST] = 0; - IsAssociativeENodeType[ECONDASS] = 0; -} - -void IRO_TruncateValueToType(CInt64 *val, Type *type) { - if (IRO_IsUnsignedType(type)) { - switch (type->size) { - case 1: - CInt64_ConvertUInt8(val); - break; - case 2: - CInt64_ConvertUInt16(val); - break; - case 4: - CInt64_ConvertUInt32(val); - break; - } - } else { - switch (type->size) { - case 1: - CInt64_ConvertInt8(val); - break; - case 2: - CInt64_ConvertInt16(val); - break; - case 4: - CInt64_ConvertInt32(val); - break; - } - } -} - -void IRO_TruncateBitfieldValueToType(CInt64 *val, Type *type, Type *type2) { - UInt32 limit; - UInt32 i; - UInt32 j; - CInt64 work; - - work = cint64_zero; - limit = TYPE_BITFIELD(type2)->bitlength; - for (i = 0; i < limit; i++) - work = CInt64_Or(work, CInt64_Shl(cint64_one, IRO_MakeULong(i))); - *val = CInt64_And(*val, work); - - if (!IRO_IsUnsignedType(type)) { - work = cint64_zero; - for (j = 0; j <= (i - 1); j++) { - if (j == (i - 1)) - work = CInt64_Or(work, CInt64_Shl(cint64_one, IRO_MakeULong(j))); - } - if (CInt64_NotEqual(CInt64_And(work, *val), cint64_zero)) { - for (j = i - 1; j < 64; j++) - *val = CInt64_Or(*val, CInt64_Shl(cint64_one, IRO_MakeULong(j))); - } - } - - IRO_TruncateValueToType(val, type); -} - -void IRO_ConstantFolding(void) { - IROLinear *nd; - ENode *expr; - int isCompare; - int flag; - CInt64 val; - - for (nd = IRO_FirstLinear; nd; nd = nd->next) { - switch (nd->type) { - case IROLinearOp1Arg: - if (IRO_IsIntConstant(nd->u.monadic)) { - expr = NULL; - flag = 0; - val = nd->u.monadic->u.node->data.intval; - if (nd->nodetype == ETYPCON && IS_TYPE_FLOAT(nd->rtype)) { - expr = IRO_NewENode(EFLOATCONST); - if (!IRO_IsUnsignedType(nd->u.monadic->rtype)) - expr->data.floatval.value = CInt64_ConvertToLongDouble(&val); - else - expr->data.floatval.value = CInt64_ConvertUToLongDouble(&val); - expr->rtype = nd->rtype; - } else { - switch (nd->nodetype) { - case ETYPCON: - flag = 1; - break; - case ELOGNOT: - val = CInt64_Not(val); - flag = 1; - break; - case EBINNOT: - val = CInt64_Inv(val); - flag = 1; - break; - case EMONMIN: - val = CInt64_Neg(val); - flag = 1; - break; - } - - if (flag) { - IRO_TruncateValueToType(&val, nd->rtype); - expr = IRO_NewENode(EINTCONST); - expr->rtype = nd->rtype; - expr->data.intval = val; - } - } - - if (expr) { - nd->u.monadic->type = IROLinearNop; - nd->type = IROLinearOperand; - nd->u.node = expr; - } - } - break; - - case IROLinearOp2Arg: - if (IRO_IsIntConstant(nd->u.diadic.left) && !IRO_IsIntConstant(nd->u.diadic.right) && IsAssociativeENodeType[nd->nodetype]) { - IROLinear *tmp = nd->u.diadic.right; - nd->u.diadic.right = nd->u.diadic.left; - nd->u.diadic.left = tmp; - } - - if (IRO_IsIntConstant(nd->u.diadic.right) && nd->nodetype == ESUB) { - nd->nodetype = EADD; - if (IRO_IsIntConstant(nd->u.diadic.right)) { - CInt64 v; - v = CInt64_Neg(nd->u.diadic.right->u.node->data.intval); - nd->u.diadic.right->u.node->data.intval = v; - } else { - Float f; - f = CMach_CalcFloatMonadic( - nd->u.diadic.right->rtype, - '-', - nd->u.diadic.right->u.node->data.floatval); - nd->u.diadic.right->u.node->data.floatval = f; - } - } - - if ( - IRO_IsIntConstant(nd->u.diadic.right) && - IsAssociativeENodeType[nd->nodetype] && - nd->u.diadic.left->type == IROLinearOp2Arg && - nd->u.diadic.left->nodetype == nd->nodetype && - nd->u.diadic.left->rtype == nd->rtype && - IRO_IsIntConstant(nd->u.diadic.left->u.diadic.right) && - nd->u.diadic.left->u.diadic.right->rtype == nd->u.diadic.right->rtype - ) - { - IROLinear *tmp = nd->u.diadic.left; - nd->u.diadic.left = tmp->u.diadic.left; - tmp->u.diadic.left = tmp->u.diadic.right; - tmp->u.diadic.right = nd->u.diadic.right; - tmp->rtype = tmp->u.diadic.left->rtype; - nd->u.diadic.right = tmp; - nd = tmp; - } - - if (IRO_IsIntConstant(nd->u.diadic.left) && IRO_IsIntConstant(nd->u.diadic.right)) { - CInt64 val1 = nd->u.diadic.left->u.node->data.intval; - CInt64 val2 = nd->u.diadic.right->u.node->data.intval; - flag = 0; - switch (nd->nodetype) { - case EADD: - val = CInt64_Add(val1, val2); - flag = 1; - break; - case ESUB: - val = CInt64_Sub(val1, val2); - flag = 1; - break; - case EMUL: - if (IRO_IsUnsignedType(nd->rtype)) - val = CInt64_MulU(val1, val2); - else - val = CInt64_Mul(val1, val2); - flag = 1; - break; - case EDIV: - if (!CInt64_IsZero(&val2)) { - if (IRO_IsUnsignedType(nd->rtype)) - val = CInt64_DivU(val1, val2); - else - val = CInt64_Div(val1, val2); - flag = 1; - } - break; - case EMODULO: - if (!CInt64_IsZero(&val2)) { - if (IRO_IsUnsignedType(nd->rtype)) - val = CInt64_ModU(val1, val2); - else - val = CInt64_Mod(val1, val2); - flag = 1; - } - break; - case ESHL: - val = CInt64_Shl(val1, val2); - flag = 1; - break; - case ESHR: - if (IRO_IsUnsignedType(nd->rtype)) - val = CInt64_ShrU(val1, val2); - else - val = CInt64_Shr(val1, val2); - flag = 1; - break; - case EAND: - val = CInt64_And(val1, val2); - flag = 1; - break; - case EOR: - val = CInt64_Or(val1, val2); - flag = 1; - break; - case EXOR: - val = CInt64_Xor(val1, val2); - flag = 1; - break; - case ELESS: - if (IRO_IsUnsignedType(nd->u.diadic.left->rtype)) - CInt64_SetULong(&val, CInt64_LessU(val1, val2)); - else - CInt64_SetULong(&val, CInt64_Less(val1, val2)); - flag = 1; - break; - case EGREATER: - if (IRO_IsUnsignedType(nd->u.diadic.left->rtype)) - CInt64_SetULong(&val, CInt64_GreaterU(val1, val2)); - else - CInt64_SetULong(&val, CInt64_Greater(val1, val2)); - flag = 1; - break; - case ELESSEQU: - if (IRO_IsUnsignedType(nd->u.diadic.left->rtype)) - CInt64_SetULong(&val, CInt64_LessEqualU(val1, val2)); - else - CInt64_SetULong(&val, CInt64_LessEqual(val1, val2)); - flag = 1; - break; - case EGREATEREQU: - if (IRO_IsUnsignedType(nd->u.diadic.left->rtype)) - CInt64_SetULong(&val, CInt64_GreaterEqualU(val1, val2)); - else - CInt64_SetULong(&val, CInt64_GreaterEqual(val1, val2)); - flag = 1; - break; - case EEQU: - CInt64_SetULong(&val, CInt64_Equal(val1, val2)); - flag = 1; - break; - case ENOTEQU: - CInt64_SetULong(&val, CInt64_NotEqual(val1, val2)); - flag = 1; - break; - } - - if (flag) { - IRO_TruncateValueToType(&val, nd->rtype); - expr = IRO_NewENode(EINTCONST); - expr->rtype = nd->rtype; - expr->data.intval = val; - nd->u.diadic.left->type = IROLinearNop; - nd->u.diadic.right->type = IROLinearNop; - nd->type = IROLinearOperand; - nd->u.node = expr; - } - } - - if (IRO_IsFloatConstant(nd->u.diadic.left) && IRO_IsFloatConstant(nd->u.diadic.right)) { - Float fval1 = nd->u.diadic.left->u.node->data.floatval; - Float fval2 = nd->u.diadic.right->u.node->data.floatval; - Float fval; - flag = 0; - isCompare = 0; - switch (nd->nodetype) { - case EADD: - fval = CMach_CalcFloatDiadic(nd->rtype, fval1, '+', fval2); - flag = 1; - break; - case ESUB: - fval = CMach_CalcFloatDiadic(nd->rtype, fval1, '-', fval2); - flag = 1; - break; - case EMUL: - fval = CMach_CalcFloatDiadic(nd->rtype, fval1, '*', fval2); - flag = 1; - break; - case EDIV: - fval = CMach_CalcFloatDiadic(nd->rtype, fval1, '/', fval2); - flag = 1; - break; - case ELESS: - CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, '<', fval2)); - flag = 1; - isCompare = 1; - break; - case EGREATER: - CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, '>', fval2)); - flag = 1; - isCompare = 1; - break; - case ELESSEQU: - CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, TK_LESS_EQUAL, fval2)); - flag = 1; - isCompare = 1; - break; - case EGREATEREQU: - CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, TK_GREATER_EQUAL, fval2)); - flag = 1; - isCompare = 1; - break; - case EEQU: - CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, TK_LOGICAL_EQ, fval2)); - flag = 1; - isCompare = 1; - break; - case ENOTEQU: - CInt64_SetULong(&val, CMach_CalcFloatDiadicBool(nd->rtype, fval1, TK_LOGICAL_NE, fval2)); - flag = 1; - isCompare = 1; - break; - } - - if (flag) { - if (isCompare) { - IRO_TruncateValueToType(&val, nd->rtype); - expr = IRO_NewENode(EINTCONST); - expr->rtype = nd->rtype; - expr->data.intval = val; - nd->u.diadic.left->type = IROLinearNop; - nd->u.diadic.right->type = IROLinearNop; - nd->type = IROLinearOperand; - nd->u.node = expr; - } else { - expr = IRO_NewENode(EFLOATCONST); - expr->rtype = nd->rtype; - expr->data.floatval = fval; - nd->u.diadic.left->type = IROLinearNop; - nd->u.diadic.right->type = IROLinearNop; - nd->type = IROLinearOperand; - nd->u.node = expr; - } - } - } - - break; - } - } - - IRO_CheckForUserBreak(); -} - -Boolean IRO_EvaluateConditionals(void) { - IRONode *fnode; - IROLinear *nd; - Boolean changed = 0; - SwitchInfo *switchInfo; - SwitchCase *swcase; - char found; - CInt64 val; - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - nd = fnode->last; - switch (nd->type) { - case IROLinearIf: - case IROLinearIfNot: - if (IRO_IsIntConstant(nd->u.label.x4)) { - Boolean isZero = CInt64_IsZero(&nd->u.label.x4->u.node->data.intval); - IRO_NopOut(nd->u.label.x4); - if ((isZero == 0) == (nd->type == IROLinearIf)) - nd->type = IROLinearGoto; - else - nd->type = IROLinearNop; - changed = 1; - } - break; - - case IROLinearSwitch: - if (IRO_IsIntConstant(nd->u.swtch.x4)) { - val = nd->u.swtch.x4->u.node->data.intval; - switchInfo = nd->u.swtch.info; - swcase = switchInfo->cases; - - IRO_NopOut(nd->u.swtch.x4); - nd->type = IROLinearGoto; - - found = 0; - while (swcase) { - if (CInt64_GreaterEqual(val, swcase->min) && CInt64_LessEqual(val, swcase->max)) { - found = 1; - nd->u.label.label = swcase->label; - break; - } - swcase = swcase->next; - } - - if (!found) - nd->u.label.label = switchInfo->defaultlabel; - changed = 1; - } - break; - } - } - - if (changed) { - IRO_ComputeSuccPred(); - IRO_ComputeDom(); - } - IRO_CheckForUserBreak(); - - return changed; -} - -static int EEquConst(IROLinear *nd) { - return nd && (nd->nodetype == EEQU) && IRO_IsIntConstant(nd->u.diadic.right); -} - -static Object *VEquConst(IROLinear *nd) { - if (EEquConst(nd)) - return IRO_IsVariable(nd->u.diadic.left); - else - return NULL; -} - -static int IsConsecutive(CInt64 a, CInt64 b) { - CInt64 diff; - - if (!CInt64_Equal(a, cint64_min) && !CInt64_Equal(b, cint64_min)) { - diff = CInt64_Sub(b, a); - return CInt64_Equal(diff, cint64_one) || CInt64_Equal(diff, cint64_negone); - } - - return 0; -} - -static IROLinear *findLabel(CLabel *label) { - IROLinear *nd; - - for (nd = IRO_FirstLinear; nd; nd = nd->next) { - if (nd->type == IROLinearLabel && nd->u.label.label == label) - break; - } - - return nd; -} - -static IROLinear *leftLeaveOf(IROLinear *nd) { - switch (nd->type) { - case IROLinearOp1Arg: - return leftLeaveOf(nd->u.monadic); - case IROLinearOp2Arg: - return leftLeaveOf(nd->u.diadic.left); - case IROLinearOperand: - return nd; - default: - return NULL; - } -} - -static int checkNode(IRONode *fnode) { - IROLinear *nd; - - if (fnode->numpred <= 1) { - nd = fnode->first; - while (nd != fnode->last && (nd->type == IROLinearNop || nd->type == IROLinearLabel)) - nd = nd->next; - - if (nd == leftLeaveOf(fnode->last->u.label.x4)) - return 1; - } - - return 0; -} - -static int checkLabel(CLabel *label, IRONode *fnode) { - switch (fnode->last->type) { - case IROLinearIf: - if (label == fnode->last->u.label.label) - return 1; - break; - } - - return 0; -} - -static Object *checkExpr(Object *a, IROLinear *nd) { - Object *b = VEquConst(nd); - - if ((!a || a == b) && !IRO_HasSideEffect(nd)) - return b; - - return NULL; -} - -static int checkStruct(IRONode *fnode1, IRONode *fnode2) { - CLabel *label; - Object *var; - - if (fnode1 == fnode2) - return (int) checkExpr(NULL, fnode1->last->u.label.x4); - - label = fnode1->last->u.label.label; - var = IRO_IsVariable(fnode1->last->u.label.x4->u.monadic); - return checkNode(fnode2) && checkLabel(label, fnode2) && checkExpr(var, fnode2->last->u.label.x4); -} - -typedef struct ReduceInfo { - int x0; - int x4; - Object *x8; - IRONode *fnode; - struct ReduceInfo *next; - CInt64 val; -} ReduceInfo; - -static int MarkPattern1(ReduceInfo *info1, ReduceInfo *info2, CInt64 *val) { - ReduceInfo *scan; - - if (!info2) - return 0; - - if (info2->x0) - return MarkPattern1(info1, info2->next, val); - - for (scan = info1; scan; scan = scan->next) { - if (scan->x0 == 2) { - if (CInt64_Equal(info2->val, scan->val)) { - IRO_NopOut(scan->fnode->last); - IRO_NopOut(scan->fnode->last->u.label.x4); // right union? - scan->x0 = -1; - return MarkPattern1(info1, info2->next, val); - } - - if (IsConsecutive(info2->val, scan->val)) { - info2->x0 = 2; - if (CInt64_Greater(*val, scan->val)) - *val = scan->val; - if (CInt64_Greater(*val, info2->val)) - *val = info2->val; - MarkPattern1(scan->next, info2, val); - MarkPattern1(info1, info1->next, val); - return 1; - } - } - } - - return MarkPattern1(info1, info2->next, val); -} - -static int DoReducible1(ReduceInfo *info, CInt64 val) { - ReduceInfo *last; - ReduceInfo *scan; - IROLinear *right; - IROLinear *left; - IROLinear *typconRight; - IROLinear *typconLeft; - IROLinear *cond; - int count; - - count = 0; - for (scan = info; scan; scan = scan->next) { - if (scan->x0 == 2) { - last = scan; - count++; - } - } - - if (!count) - return 0; - - for (scan = info; scan != last; scan = scan->next) { - if (scan->x0 == 2) { - scan->x0 = -1; - IRO_NopOut(scan->fnode->last); - IRO_NopOut(scan->fnode->last->u.label.x4); - } - } - - last->x0 = -1; - - cond = last->fnode->last; - cond->u.label.x4->nodetype = ELESSEQU; - CInt64_SetULong(&cond->u.label.x4->u.diadic.right->u.node->data.intval, count - 1); - - typconLeft = IRO_NewLinear(IROLinearOp1Arg); - typconLeft->nodetype = ETYPCON; - typconLeft->rtype = IRO_UnsignedType(cond->u.label.x4->u.diadic.left->rtype); - typconLeft->index = ++IRO_NumLinear; - - typconRight = IRO_NewLinear(IROLinearOp1Arg); - *typconRight = *typconLeft; - typconRight->index = ++IRO_NumLinear; - - left = IRO_NewLinear(IROLinearOp2Arg); - left->nodetype = EADD; - left->rtype = cond->u.label.x4->u.diadic.left->rtype; - left->index = ++IRO_NumLinear; - - right = IRO_NewLinear(IROLinearOperand); - right->nodetype = EINTCONST; - right->rtype = cond->u.label.x4->u.diadic.left->rtype; - right->index = ++IRO_NumLinear; - right->u.node = IRO_NewENode(EINTCONST); - right->u.node->data.intval = CInt64_Neg(val); - right->u.node->rtype = right->rtype; - - typconLeft->next = cond->u.label.x4->u.diadic.left->next; - cond->u.label.x4->u.diadic.left->next = right; - right->next = left; - left->next = typconLeft; - - typconRight->next = cond->u.label.x4->u.diadic.right->next; - cond->u.label.x4->u.diadic.right->next = typconRight; - - typconLeft->u.monadic = left; - left->u.diadic.left = cond->u.label.x4->u.diadic.left; - left->u.diadic.right = right; - cond->u.label.x4->u.diadic.left = typconLeft; - typconRight->u.monadic = cond->u.label.x4->u.diadic.right; - cond->u.label.x4->u.diadic.right = typconRight; - - return count; -}; - -static int ReducePattern1(IRONode *startnode, IRONode *endnode) { - ReduceInfo *infos; - ReduceInfo *info; - int changed = 0; - int count; - IRONode *fnode; - int i; - int j; - CInt64 val; - - if (startnode == endnode) - return 0; - - count = 0; - for (fnode = startnode; fnode != endnode; fnode = fnode->nextnode) - count++; - - infos = oalloc(sizeof(ReduceInfo) * ++count); - - fnode = startnode; - for (i = 0; i < count; i++) { - infos[i].x0 = 0; - infos[i].x4 = 0; - infos[i].fnode = fnode; - infos[i].next = NULL; - infos[i].x8 = VEquConst(fnode->last->u.label.x4); - if (infos[i].x8) { - infos[i].val = fnode->last->u.label.x4->u.diadic.right->u.node->data.intval; - infos[i].x4 = 1; - } - fnode = fnode->nextnode; - } - - for (j = 0; j < count; j++) { - if (infos[j].x4 == 1 && infos[j].x8) { - infos[j].x4 = -1; - info = &infos[j]; - for (i = j + 1; i < count; i++) { - if (infos[j].x8 == infos[i].x8) { - info->next = &infos[i]; - info = &infos[i]; - infos[i].x4 = 0; - } - } - } - } - - for (j = 0; j < count; j++) { - if (infos[j].x4 == -1) { - for (info = &infos[j]; info; info = info->next) { - if (info->x0 == 0) { - info->x0 = 2; - val = info->val; - if (MarkPattern1(&infos[j], info->next, &val)) { - changed = 1; - DoReducible1(&infos[j], val); - } else { - info->x0 = -1; - } - } - } - } - } - - return changed; -} - -static int ReduceConsecutiveIf(IRONode *startnode, IRONode *endnode) { - IRONode *node31; - IRONode *node30; - int changed = 0; - - while (startnode != endnode) { - if (checkStruct(startnode, startnode)) - break; - startnode = startnode->nextnode; - } - - node31 = startnode; - if (startnode != endnode) { - node30 = startnode; - node31 = startnode->nextnode; - while (node31 != endnode) { - if (checkStruct(startnode, node31)) { - node30 = node31; - node31 = node31->nextnode; - } else { - node31 = node30; - break; - } - } - - if (node31 == endnode && !checkStruct(startnode, node31)) - node31 = node30; - - if (startnode != node31 && ReducePattern1(startnode, node31)) - changed = 1; - - if (node31 != endnode) - node31 = node31->nextnode; - } - - if (node31 != endnode && ReduceConsecutiveIf(node31, endnode)) - changed = 1; - - return changed; -} - -int IRO_SimplifyConditionals(void) { - IRONode *fnode; - IRONode *start; - IRONode *end; - int changed = 0; - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - if (fnode->last->type == IROLinearIf) { - start = end = fnode; - while (fnode->nextnode && fnode->nextnode->last->type == IROLinearIf) { - end = fnode = fnode->nextnode; - } - if (start != end && ReduceConsecutiveIf(start, end)) - changed = 1; - } - } - - if (changed) { - IRO_ComputeSuccPred(); - IRO_ComputeDom(); - } - IRO_CheckForUserBreak(); - return changed; -} - -Boolean IRO_EvaluateDefinitePointers(Object *func) { - IROLinear *nd; - Boolean result; // r29 - Boolean changed; // r28 - Boolean changed2; // r26 - IROLinear *nd2; // r25 - IROListNode *scan; // r25 - IROListNode *list; - - if (!copts.opt_pointer_analysis) - return 0; - - result = 0; - - do { - changed = 0; - - for (nd = IRO_FirstLinear; nd; nd = nd->next) { - if ( - nd->type == IROLinearOp1Arg && - nd->nodetype == EINDIRECT && - !(nd->flags & IROLF_Assigned) && - nd->pointsToFunction && - !IRO_HasSideEffect(nd) && - PointerAnalysis_IsLinearNodePointerExprDefinite(func, nd) - ) - { - list = NULL; - PointerAnalysis_LookupLinearNodePointerExpr(func, nd, &list); - if (list) { - if (list->list.head && list->list.tail && !list->nextList) { - changed2 = IRO_LocateFather_Cut_And_Paste(nd, list->list.tail) != NULL; - if (changed2) { - IRO_PasteAfter(list->list.head, list->list.tail, nd); - for (nd2 = list->list.head; nd2 != list->list.tail->next; nd2 = nd2->next) { - if (nd2->type == IROLinearOperand && nd2->u.node->type == EOBJREF) { - if (nd2->u.node->data.objref->datatype == DDATA || nd2->u.node->data.objref->datatype == DLOCAL) - IRO_FindVar(nd2->u.node->data.objref, 1, 1); - else - nd2->u.node->data.objref->varptr = NULL; - } - } - } - changed |= changed2; - } - - while (list) { - scan = list->nextList; - IRO_free(list); - list = scan; - } - } - } - } - - result |= changed; - IRO_CheckForUserBreak(); - } while (changed); - - return result; -} diff --git a/compiler_and_linker/unsorted/IroExprRegeneration.c b/compiler_and_linker/unsorted/IroExprRegeneration.c deleted file mode 100644 index f63622a..0000000 --- a/compiler_and_linker/unsorted/IroExprRegeneration.c +++ /dev/null @@ -1,1531 +0,0 @@ -#include "compiler/IroExprRegeneration.h" -#include "compiler/IroCSE.h" -#include "compiler/IroDump.h" -#include "compiler/IroFlowgraph.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroSubable.h" -#include "compiler/IroTransform.h" -#include "compiler/IROUseDef.h" -#include "compiler/IroUtil.h" -#include "compiler/IroVars.h" -#include "compiler/CDecl.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/objects.h" - -// forward decls -static void GetExprUses(IROLinear *linear, Boolean isEntry); -static void RebuildPossibleCondExpression(IRONode *fnode); -static void AddNodeAndSuccessorsRecursively(IRONodes *nodes, IRONode *fnode1, IRONode *fnode2); - -static Boolean FindFlowgraphNodeThatStartsWithLabel(CLabel *label, IRONode **result1, IRONode **result2) { - IRONode *prev; - IRONode *iter; - - prev = IRO_FirstNode; - if (prev != NULL) - iter = prev->nextnode; - - while (iter) { - if (iter->first->type == IROLinearLabel && iter->first->u.label.label == label) { - *result1 = iter; - *result2 = prev; - return 1; - } - - prev = iter; - iter = iter->nextnode; - } - - return 0; -} - -static IROLinear *FindLastDiadicTopLevelAssignmentInFlowgraphNode(IRONode *fnode) { - IROLinear *scan; - IROLinear *result; - - result = NULL; - - for (scan = fnode->first; scan != fnode->last->next; scan = scan->next) { - if (scan->type == IROLinearOp2Arg && scan->nodetype == EASS && !(scan->flags & IROLF_Reffed)) - result = scan; - } - - return result; -} - -static Boolean RewriteUse(IROUse *use, ENode *enode, IROLinear *nd, Boolean flag) { - IROLinear *father; - IROLinear *father2; - - if ( - use && - use->x1C && - use->linear && - use->linear->type == IROLinearOperand && - use->linear->u.node->type == EOBJREF && - use->linear->u.node->data.objref == enode->data.objref && - (father = IRO_LocateFather(use->linear)) && - father->type == IROLinearOp1Arg && - father->nodetype == EINDIRECT && - father->rtype == nd->rtype && - (father2 = IRO_LocateFather(father)) && - ((father2->type != IROLinearOp1Arg && father2->type != IROLinearOp2Arg) || !IRO_IsModifyOp[father2->nodetype]) - ) { - if (flag) - IRO_LocateFather_Cut_And_Paste(father, nd); - return 1; - } - - return 0; -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -static struct { - jmp_buf buf; - UInt16 index; - Boolean flag; -} scuai; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void StatementContainsUseAction(IROLinear *linear, Boolean isFirst) { - if (isFirst && linear->index == scuai.index) { - scuai.flag = 1; - longjmp(scuai.buf, 1); - } -} - -static Boolean StatementContainsUse(IROLinear *a, IROLinear *b) { - memset(&scuai, 0, sizeof(scuai)); - scuai.index = b->index; - scuai.flag = 0; - - if (!setjmp(scuai.buf)) - IRO_WalkInts(a, a, StatementContainsUseAction); - - return scuai.flag; -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -static struct { - jmp_buf buf; - Boolean flag; -} scseai; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void StatementContainsSideEffectAction(IROLinear *linear, Boolean isFirst) { - if (isFirst) { - switch (linear->type) { - case IROLinearOperand: - case IROLinearOp1Arg: - case IROLinearOp2Arg: - case IROLinearOp3Arg: - case IROLinearFunccall: - case IROLinearAsm: - if (IRO_HasSideEffect(linear)) { - scseai.flag = 1; - longjmp(scseai.buf, 1); - } - break; - } - } -} - -static Boolean StatementContainsSideEffect(IROLinear *linear) { - memset(&scseai, 0, sizeof(scseai)); - scseai.flag = 0; - - if (!setjmp(scseai.buf)) - IRO_WalkInts(linear, linear, StatementContainsSideEffectAction); - - return scseai.flag; -} - -static Boolean HasSideEffectsBeforeUse(IRONode *fnode1, IRONode *fnode2, IRONode *fnode3, IROLinear *nd, Boolean flag) { - IRONode *fnode; - IROLinear *scannd; - UInt16 i; - - if (fnode1 != fnode3) { - if (flag) { - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) - fnode->x3C = 0; - } else if (fnode1->x3C) { - return 0; - } - fnode1->x3C = 1; - } - - for (scannd = fnode1->first; scannd && scannd != fnode1->last->next; scannd = scannd->next) { - if (!(scannd->flags & IROLF_Reffed)) { - if (StatementContainsUse(scannd, nd)) - return 0; - if (StatementContainsSideEffect(scannd)) - return 1; - } - } - - if (fnode1 != fnode3) { - for (i = 0; i < fnode1->numsucc; i++) { - if (HasSideEffectsBeforeUse(IRO_NodeTable[fnode1->succ[i]], fnode2, fnode3, nd, 0)) - return 1; - } - } - - return 0; -} - -static Boolean UsesAKilledVarBeforeUse(IRONode *fnode1, IRONode *fnode2, IRONode *fnode3, IROLinear *nd, BitVector *bv, Boolean flag) { - IRONode *fnode; - UInt16 i; - IROLinear *scannd; - - if (fnode1 != fnode3) { - if (flag) { - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) - fnode->x3C = 0; - } else if (fnode1->x3C) { - return 0; - } - fnode1->x3C = 1; - } - - for (scannd = fnode1->first; scannd && scannd != fnode1->last->next; scannd = scannd->next) { - if (!(scannd->flags & IROLF_Reffed)) { - if (StatementContainsUse(scannd, nd)) - return 0; - Bv_Clear(IRO_VarKills); - IRO_WalkInts(scannd, scannd, GetExprUses); - if (Bv_BitsInCommon(bv, IRO_VarKills)) - return 1; - } - } - - if (fnode1 != fnode3) { - for (i = 0; i < fnode1->numsucc; i++) { - if (UsesAKilledVarBeforeUse(IRO_NodeTable[fnode1->succ[i]], fnode2, fnode3, nd, bv, 0)) - return 1; - } - } - - return 0; -} - -static void GetExprUses(IROLinear *linear, Boolean isEntry) { - Object *obj; - VarRecord *var; - - if (isEntry) { - if (linear->type == IROLinearOperand && linear->u.node->type == EOBJREF) { - obj = linear->u.node->data.objref; - if ((linear->flags & IROLF_Ind) && (!(linear->flags & IROLF_Assigned) || (linear->flags & IROLF_Used))) { - if ((var = IRO_FindVar(obj, 0, 1))) - Bv_SetBit(var->index, IRO_VarKills); - } - } - } -} - -static void GetExprKills(IROLinear *linear, Boolean isEntry) { - if (isEntry) - IRO_GetKills(linear); -} - -static void CheckUnorderedRegionForSideEffectsAndUses(IROLinear *nd, BitVector *bv1, BitVector *bv2, Boolean *result) { - if (IRO_HasSideEffect(nd)) { - *result = 1; - } else { - Bv_Clear(bv2); - Bv_Clear(IRO_VarKills); - IRO_WalkTree(nd, GetExprUses); - Bv_Or(IRO_VarKills, bv2); - - if (Bv_BitsInCommon(bv1, bv2)) - *result = 1; - } -} - -static void CheckUnorderedRegionsForSideEffectsAndUses(IROLinear *nd1, IROLinear *nd2, BitVector *bv1, BitVector *bv2, Boolean *result) { - int i; - - switch (nd1->type) { - case IROLinearOp2Arg: - if (nd1->nodetype != ELAND && nd1->nodetype != ELOR && nd1->nodetype != ECOMMA) { - if (nd1->u.diadic.left != nd2) - CheckUnorderedRegionForSideEffectsAndUses(nd1->u.diadic.left, bv1, bv2, result); - if (nd1->u.diadic.right != nd2) - CheckUnorderedRegionForSideEffectsAndUses(nd1->u.diadic.right, bv1, bv2, result); - } - break; - case IROLinearFunccall: - if (nd1->u.funccall.linear8 != nd2) - CheckUnorderedRegionForSideEffectsAndUses(nd1->u.funccall.linear8, bv1, bv2, result); - for (i = 0; !*result && i < nd1->u.funccall.argCount; i++) { - if (nd1->u.funccall.args[i] != nd2) - CheckUnorderedRegionForSideEffectsAndUses(nd1->u.funccall.args[i], bv1, bv2, result); - } - break; - } -} - -static Boolean CheckThenOrElseBranch(IRONode *fnode1, IRONode *fnode2, IROLinear *nd, Boolean flag) { - IRONode *fnode; - IROLinear *scannd; - IRONodes nodes; - Boolean result; - - IROFlowgraph_sub_4C2140(&nodes); - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) - fnode->x3C = 0; - AddNodeAndSuccessorsRecursively(&nodes, fnode1, fnode2); - - while (IROFlowgraph_sub_4C2040(&nodes)) { - fnode = IRO_NodeTable[IROFlowgraph_sub_4C2100(&nodes)]; - if (fnode) { - if (!Bv_IsBitSet(fnode1->index, fnode->dom)) { - result = 0; - goto done; - } - - for (scannd = fnode->first; scannd && scannd != fnode->last->next; scannd = scannd->next) { - if (!nd || scannd != nd) { - if (!flag || (scannd->type != IROLinearReturn)) { - if (fnode->numpred == 2 && scannd->type == IROLinearLabel) - RebuildPossibleCondExpression(fnode); - - if (scannd->type != IROLinearNop && - scannd->type != IROLinearLabel && - scannd->type != IROLinearGoto && - !(scannd->flags & IROLF_Reffed)) { - result = 0; - goto done; - } - } - } - } - } - } - - result = 1; -done: - IROFlowgraph_sub_4C20E0(&nodes); - return result; -} - -static void RebuildPossibleCondExpression(IRONode *fnode) { - IRONode *pred1; - IRONode *pred2; - IRONode *r30; - IROLinear *leftAss; - IROLinear *rightAss; - IROLinear *r27; - IROLinear *r13; - IROLinear *var_58; - IRONode *left; - IRONode *right; - IRONode *r24; - ENode *r23; - IRODef *r22; - IRODef *r21; - IRODef *def; - IROUse *use; - UInt32 r20; - UInt32 r19; - Boolean r18; - Boolean r17; - UInt32 i; - Boolean compareType; - Type *var_60; - IROLinear copy1; - IROLinear copy2; - IROLinear copy3; - - if ( - !fnode || - fnode->numpred != 2 || - !fnode->first || - fnode->first->type != IROLinearLabel - ) - return; - - pred1 = IRO_NodeTable[fnode->pred[0]]; - pred2 = IRO_NodeTable[fnode->pred[1]]; - if ( - !pred1 || !pred2 || - pred1->numsucc != 1 || pred2->numsucc != 1 - ) - return; - - r24 = NULL; - for (i = 0; i < IRO_NumNodes; i++) { - if ( - Bv_IsBitSet(i, fnode->dom) && - (r24 = IRO_NodeTable[i]) && - r24->last && - (r24->last->type == IROLinearIf || r24->last->type == IROLinearIfNot) && - r24->last->u.label.label && - r24->numsucc == 2 - ) { - if (Bv_IsBitSet(r24->succ[0], pred1->dom) && - !Bv_IsBitSet(r24->succ[0], pred2->dom) && - Bv_IsBitSet(r24->succ[1], pred2->dom) && - !Bv_IsBitSet(r24->succ[1], pred1->dom)) - break; - - if (Bv_IsBitSet(r24->succ[0], pred2->dom) && - !Bv_IsBitSet(r24->succ[0], pred1->dom) && - Bv_IsBitSet(r24->succ[1], pred1->dom) && - !Bv_IsBitSet(r24->succ[1], pred2->dom)) - break; - } - } - - if (i >= IRO_NumNodes) - return; - - /*if ( - (r30 = IRO_NodeTable[r24->succ[0]]) && - r30->numpred == 1 && - r30->first && - r30->first->type == IROLinearLabel && - r30->first->u.label.label == r24->last->u.label.label - ) { - goto ok; - } else if ( - (r30 = IRO_NodeTable[r24->succ[1]]) && - r30->numpred == 1 && - r30->first && - r30->first->type == IROLinearLabel && - r30->first->u.label.label == r24->last->u.label.label - ) { - goto ok; - } else { - return; - }*/ - /*if ( - (!(r30 = IRO_NodeTable[r24->succ[0]]) || - r30->numpred != 1 || - !r30->first || - r30->first->type != IROLinearLabel || - r30->first->u.label.label != r24->last->u.label.label) - && - (!(r30 = IRO_NodeTable[r24->succ[1]]) || - r30->numpred != 1 || - !r30->first || - r30->first->type != IROLinearLabel || - r30->first->u.label.label != r24->last->u.label.label) - ) - return;*/ - r30 = IRO_NodeTable[r24->succ[0]]; - if ( - r30 && - r30->numpred == 1 && - r30->first && - r30->first->type == IROLinearLabel && - r30->first->u.label.label == r24->last->u.label.label - ) { - (void)0; - } else { - r30 = IRO_NodeTable[r24->succ[1]]; - if ( - r30 && - r30->numpred == 1 && - r30->first && - r30->first->type == IROLinearLabel && - r30->first->u.label.label == r24->last->u.label.label - ) { - } else { - return; - } - } - -ok: - if (Bv_IsBitSet(r30->index, pred1->dom)) { - left = pred2; - right = pred1; - } else { - left = pred1; - right = pred2; - } - - leftAss = FindLastDiadicTopLevelAssignmentInFlowgraphNode(left); - if ( - !leftAss || - leftAss->type != IROLinearOp2Arg || - !leftAss->u.diadic.left || - leftAss->u.diadic.left->type != IROLinearOp1Arg || - leftAss->u.diadic.left->nodetype != EINDIRECT || - !leftAss->u.diadic.left->u.monadic || - leftAss->u.diadic.left->u.monadic->type != IROLinearOperand || - !(r23 = leftAss->u.diadic.left->u.monadic->u.node) || - !r23->rtype || - !IS_TYPE_POINTER_ONLY(r23->rtype) || - !r23->data.objref || - is_volatile_object(r23->data.objref) || - r23->data.objref->datatype != DLOCAL - ) - r23 = NULL; - - if (r23) { - rightAss = FindLastDiadicTopLevelAssignmentInFlowgraphNode(right); - if ( - !rightAss || - rightAss->type != IROLinearOp2Arg || - !rightAss->u.diadic.left || - rightAss->u.diadic.left->type != IROLinearOp1Arg || - rightAss->u.diadic.left->nodetype != EINDIRECT || - !rightAss->u.diadic.left->u.monadic || - rightAss->u.diadic.left->u.monadic->type != IROLinearOperand || - !rightAss->u.diadic.left->u.monadic->u.node || - !rightAss->u.diadic.left->u.monadic->u.node->rtype || - !IS_TYPE_POINTER_ONLY(rightAss->u.diadic.left->u.monadic->u.node->rtype) || - rightAss->u.diadic.left->u.monadic->u.node->type != EOBJREF || - rightAss->u.diadic.left->u.monadic->u.node->data.objref != r23->data.objref || - rightAss->rtype != leftAss->rtype - ) - r23 = NULL; - } - - if (r23) { - if (!CheckThenOrElseBranch(r24->nextnode, left, leftAss, 0) || !CheckThenOrElseBranch(r30, right, rightAss, 0)) - return; - - r19 = 0; - r20 = 0; - r18 = 0; - r17 = 0; - if (!r23->data.objref->varptr || !r23->data.objref->varptr->uses || !r23->data.objref->varptr->defs) { - r23 = NULL; - } else { - r21 = NULL; - r22 = NULL; - for (def = r23->data.objref->varptr->defs; def && (!r22 || !r21); def = def->varnext) { - if (def->x18 && def->linear == leftAss) - r22 = def; - else if (def->x18 && def->linear == rightAss) - r21 = def; - } - - if (!r22 || !r21) { - r23 = NULL; - } else { - for (use = r23->data.objref->varptr->uses; r23 && use; use = use->varnext) { - if (use->x1C) { - r20++; - if (Bv_IsBitSet(r22->index, use->x18) && Bv_IsBitSet(r21->index, use->x18)) { - for (i = 0; r23 && i < use->x18->size; i++) { - if (i != r22->index && i != r21->index && Bv_IsBitSet(i, use->x18)) - r23 = NULL; - } - - if (r23 && !Bv_IsBitSet(fnode->index, use->node->dom)) - r23 = NULL; - - if (r23) { - if (RewriteUse(use, r23, rightAss, 0)) - r19++; - else - r23 = NULL; - } - - if (r23 && !r17) - r17 = HasSideEffectsBeforeUse(fnode, fnode, use->node, use->linear, 1); - - if (r23 && !r18 && (IRO_HasSideEffect(r24->last->u.label.x4) || IRO_HasSideEffect(leftAss->u.label.x4) || - IRO_HasSideEffect(rightAss->u.label.x4))) - r18 = 1; - } else if (Bv_IsBitSet(r22->index, use->x18) || Bv_IsBitSet(r21->index, use->x18)) { - r23 = NULL; - } - } - } - } - } - } - - if (!r23) - return; - - compareType = r24->last->type == IROLinearIf; - r27 = r24->last->u.label.x4; - r13 = leftAss->u.label.x4; - var_58 = rightAss->u.label.x4; - var_60 = rightAss->rtype; - memcpy(©1, r13, sizeof(IROLinear)); - memcpy(©2, rightAss, sizeof(IROLinear)); - - r24->last->type = IROLinearNop; - r24->last->expr = NULL; - r30->first->type = IROLinearNop; - r30->first->expr = NULL; - fnode->first->type = IROLinearNop; - fnode->first->expr = NULL; - if (left->last->type == IROLinearGoto) { - left->last->type = IROLinearNop; - left->last->expr = NULL; - } - if (right->last->type == IROLinearGoto) { - right->last->type = IROLinearNop; - right->last->expr = NULL; - } - - if (r23) { - IRO_NopOut(leftAss->u.diadic.left); - leftAss->type = IROLinearNop; - leftAss->expr = NULL; - } - - memcpy(rightAss, ©1, sizeof(IROLinear)); - rightAss->type = IROLinearOp3Arg; - rightAss->nodetype = ECOND; - rightAss->index = copy2.index; - rightAss->u.args3.a = r27; - rightAss->rtype = var_60; - rightAss->next = copy2.next; - if (compareType) { - rightAss->u.args3.b = var_58; - rightAss->u.args3.c = r13; - } else { - rightAss->u.args3.b = r13; - rightAss->u.args3.c = var_58; - } - rightAss->flags |= IROLF_Reffed; - - if (r19 == 1 && !r17 && !r18 && !r23->data.objref->varptr->xB) { - for (use = r23->data.objref->varptr->uses; use; use = use->varnext) { - if (use->x1C && Bv_IsBitSet(r22->index, use->x18) && Bv_IsBitSet(r21->index, use->x18)) { - RewriteUse(use, r23, rightAss, 1); - if ((r18 = (use->linear->flags & IROLF_4000) && IRO_HasSideEffect(r27))) { - IROLinear *tmp; - Object *obj; - - tmp = IRO_NewLinear(IROLinearOperand); - memcpy(tmp, copy2.u.diadic.left->u.monadic, sizeof(IROLinear)); - tmp->index = IRO_NumLinear++; - tmp->rtype = r27->rtype; - if (r20 == 1) { - tmp->u.node->data.objref->type = r27->rtype; - tmp->u.node->rtype = CDecl_NewPointerType(r27->rtype); - } else { - obj = create_temp_object(tmp->rtype); - IRO_FindVar(obj, 1, 1); - tmp->u.node = create_objectrefnode(obj); - } - IRO_PasteAfter(tmp, tmp, r27); - - tmp = IRO_NewLinear(IROLinearOp1Arg); - memcpy(tmp, copy2.u.diadic.left, sizeof(IROLinear)); - tmp->index = IRO_NumLinear++; - tmp->u.monadic = r27->next; - tmp->rtype = r27->rtype; - IRO_PasteAfter(tmp, tmp, r27->next); - - tmp = IRO_NewLinear(IROLinearOp2Arg); - memcpy(tmp, ©2, sizeof(IROLinear)); - tmp->index = IRO_NumLinear++; - tmp->u.diadic.right = r27; - tmp->u.diadic.left = r27->next->next; - tmp->rtype = r27->rtype; - IRO_PasteAfter(tmp, tmp, r27->next->next); - - if (r20 != 1) { - tmp = copy2.u.diadic.left->u.monadic; - tmp->u.node = create_objectrefnode(obj); - } - - rightAss->u.args3.a = copy2.u.diadic.left; - rightAss->u.args3.a->rtype = r27->rtype; - - if (r20 == 1) { - r21->linear = r27->next->next; - if (Bv_IsBitSet(r21->index, right->x1A)) { - Bv_ClearBit(r21->index, right->x1A); - Bv_SetBit(r21->index, r24->x1A); - } - if (Bv_IsBitSet(r21->index, right->x1E)) { - Bv_ClearBit(r21->index, right->x1E); - Bv_SetBit(r21->index, r24->x1E); - } - if (Bv_IsBitSet(r21->index, right->x22)) { - Bv_ClearBit(r21->index, right->x22); - Bv_SetBit(r21->index, r24->x22); - } - } - } - } - } - - if (!r18) { - if (r20 == 1 && r23->data.objref->u.var.info) { - r23->data.objref->u.var.info->usage = 0; - r23->data.objref->u.var.info->used = 0; - } - r22->x18 = 0; - IRO_NopOut(copy2.u.diadic.left); - r21->x18 = 0; - } - } else { - memcpy(©3, fnode->first, sizeof(IROLinear)); - memcpy(fnode->first, ©2, sizeof(IROLinear)); - - fnode->first->index = copy3.index; - fnode->first->u.diadic.right = rightAss; - fnode->first->next = copy3.next; - r22->x18 = 0; - r21->linear = fnode->first; - if (Bv_IsBitSet(r21->index, right->x1A)) { - Bv_ClearBit(r21->index, right->x1A); - Bv_SetBit(r21->index, fnode->x1A); - } - if (Bv_IsBitSet(r21->index, right->x1E)) { - Bv_ClearBit(r21->index, right->x1E); - Bv_SetBit(r21->index, fnode->x1E); - } - if (Bv_IsBitSet(r21->index, right->x22)) { - Bv_ClearBit(r21->index, right->x22); - Bv_SetBit(r21->index, fnode->x22); - } - } -} - -static void RebuildPossibleReturnCondExpression(IRONode *fnode) { - IRONode *succ1; - IRONode *succ2; - IROLinear *node1; - IROLinear *node2; - IROLinear *node3; - IRONode *r27; - Boolean isIf; - Type *type; - IROList list; - - if ( - !fnode || - fnode->numsucc != 2 || - !fnode->last || - (fnode->last->type != IROLinearIf && fnode->last->type != IROLinearIfNot) - ) - return; - - succ1 = IRO_NodeTable[fnode->succ[0]]; - succ2 = IRO_NodeTable[fnode->succ[1]]; - if ( - !succ1 || !succ2 || - succ1->numsucc != 0 || succ1->numpred != 1 || - succ2->numsucc != 0 || succ2->numpred != 1 - ) - return; - - if (succ1->first && succ1->first->type == IROLinearLabel && succ1->first->u.label.label == fnode->last->u.label.label) { - r27 = succ1; - } else if (succ2->first && succ2->first->type == IROLinearLabel && succ2->first->u.label.label == fnode->last->u.label.label) { - r27 = succ2; - } else { - return; - } - - if (r27->numpred != 1) - return; - - if (!CheckThenOrElseBranch(fnode->nextnode, fnode->nextnode, NULL, 1) || !CheckThenOrElseBranch(r27, r27, NULL, 1)) - return; - - if ( - !fnode->nextnode->last || - fnode->nextnode->last->type != IROLinearReturn || - !fnode->nextnode->last->u.monadic || - !r27->last || - r27->last->type != IROLinearReturn || - !r27->last->u.monadic || - !IRO_TypesEqual(fnode->nextnode->last->u.monadic->rtype, r27->last->u.monadic->rtype) - ) - return; - - isIf = fnode->last->type == IROLinearIf; - node1 = fnode->last->u.diadic.right; - node2 = fnode->nextnode->last->u.diadic.left; - node3 = r27->last->u.diadic.left; - type = node2->rtype; - - fnode->last->type = IROLinearNop; - fnode->last->expr = NULL; - r27->last->type = IROLinearNop; - r27->last->expr = NULL; - r27->first->type = IROLinearNop; - r27->first->expr = NULL; - - if (IRO_IsIntConstant(node2) && IRO_IsIntConstant(node3) && - ((IRO_IsConstantOne(node2) && IRO_IsConstantZero(node3)) || - (IRO_IsConstantZero(node2) && IRO_IsConstantOne(node3)))) { - if (!(node1->type == IROLinearOp1Arg && node1->nodetype == ELOGNOT && node1->rtype == type)) { - IROLinear *tmp1; - IROLinear *tmp2; - - tmp1 = IRO_NewLinear(IROLinearOp1Arg); - memcpy(tmp1, node2, sizeof(IROLinear)); - tmp1->type = IROLinearOp1Arg; - tmp1->nodetype = ELOGNOT; - tmp1->index = IRO_NumLinear++; - tmp1->u.monadic = node1; - - tmp1->next = tmp2 = IRO_NewLinear(IROLinearOp1Arg); - memcpy(tmp2, node2, sizeof(IROLinear)); - tmp2->type = IROLinearOp1Arg; - tmp2->nodetype = ELOGNOT; - tmp2->index = IRO_NumLinear++; - tmp2->u.monadic = tmp1; - - IRO_PasteAfter(tmp1, tmp2, node1); - node1 = tmp2; - } - - if ((IRO_IsConstantZero(node2) && !isIf) || (IRO_IsConstantOne(node2) && isIf)) { - if (node1->type == IROLinearOp1Arg && node1->nodetype == ELOGNOT && node1->rtype == node1->u.monadic->rtype) { - IROLinear *tmp = node1; - node1 = node1->u.monadic; - tmp->type = IROLinearNop; - tmp->expr = NULL; - } else { - IROLinear *tmp = IRO_NewLinear(IROLinearOp1Arg); - memcpy(tmp, node2, sizeof(IROLinear)); - tmp->type = IROLinearOp1Arg; - tmp->nodetype = ELOGNOT; - tmp->index = IRO_NumLinear++; - tmp->u.monadic = node1; - IRO_PasteAfter(tmp, tmp, node1); - node1 = tmp; - } - } - - node2->type = IROLinearNop; - node2->expr = NULL; - node3->type = IROLinearNop; - node3->expr = NULL; - fnode->nextnode->last->u.monadic = node1; - } else { - IROLinear *tmp1; - IROLinear *tmp2; - - IRO_InitList(&list); - tmp1 = IRO_DuplicateExpr(node3, &list); - IRO_NopOut(node3); - IRO_Paste(list.head, list.tail, fnode->nextnode->last); - - tmp2 = IRO_NewLinear(IROLinearOp3Arg); - memcpy(tmp2, node2, sizeof(IROLinear)); - tmp2->type = IROLinearOp3Arg; - tmp2->nodetype = ECOND; - tmp2->index = IRO_NumLinear++; - tmp2->u.args3.a = node1; - tmp2->rtype = type; - IRO_Paste(tmp2, tmp2, fnode->nextnode->last); - - if (isIf) { - tmp2->u.args3.b = tmp1; - tmp2->u.args3.c = node2; - } else { - tmp2->u.args3.b = node2; - tmp2->u.args3.c = tmp1; - } - - fnode->nextnode->last->u.monadic = tmp2; - } -} - -static void RebuildCondExpressions(void) { - IRONode *fnode; - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - if (fnode->numpred == 2) { - if (fnode->first && fnode->first->type == IROLinearLabel) - RebuildPossibleCondExpression(fnode); - } else if (fnode->numsucc == 2) { - if (fnode->last && (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot)) - RebuildPossibleReturnCondExpression(fnode); - } - } - - IRO_CheckForUserBreak(); -} - -static Boolean IsLogicalExpressionAssign(IROLinear *nd) { - IROLinear *right; - IROLinear *left; - - return ( - nd->type == IROLinearOp2Arg && - nd->nodetype == EASS && - (left = nd->u.diadic.left) && - (right = nd->u.diadic.right) && - right->type == IROLinearOperand && - right->u.node && - right->u.node->type == EINTCONST && - (CInt64_Equal(right->u.node->data.intval, cint64_one) || CInt64_Equal(right->u.node->data.intval, cint64_zero)) && - left->type == IROLinearOp1Arg && - left->nodetype == EINDIRECT && - left->u.monadic && - IS_TYPE_POINTER_ONLY(left->u.monadic->rtype) && - left->u.monadic->type == IROLinearOperand && - left->u.monadic->u.node && - left->u.monadic->u.node->type == EOBJREF && - left->u.monadic->u.node->data.objref && - left->u.monadic->u.node->data.objref->datatype == DLOCAL); -} - -static Boolean IsPossibleLogicalExpressionStart(IRONode *fnode, IROLinear *nd) { - return - fnode->numsucc == 2 && - fnode->last && - (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot) && - IsLogicalExpressionAssign(nd); -} - -static Boolean CheckForTopLevelExpressions(IRONode *fnode1, IRONode *fnode2, IRONode *fnode3, IROLinear *nd1, IROLinear *nd2, Boolean flag) { - IRONode *fnode; - IROLinear *nd; - UInt16 i; - - if (fnode1 != fnode3) { - if (!Bv_IsBitSet(fnode2->index, fnode1->dom)) - return 0; - - if (flag) { - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) - fnode->x3C = 0; - } else if (fnode1->x3C) { - return 1; - } - fnode1->x3C = 1; - - for (i = 0; i < fnode1->numsucc; i++) { - fnode = IRO_NodeTable[fnode1->succ[i]]; - if (!CheckForTopLevelExpressions(fnode, fnode2, fnode3, fnode->first, nd2, 0)) - return 0; - } - } - - for (nd = nd1; nd && nd != fnode1->last->next; nd = nd->next) { - if (nd == nd2) - return 1; - - if (nd->type != IROLinearNop && nd->type != IROLinearLabel && !(nd->flags & IROLF_Reffed)) - return 0; - } - - return 1; -} - -static void AddNodeAndSuccessorsRecursively(IRONodes *nodes, IRONode *fnode1, IRONode *fnode2) { - UInt16 i; - - if (fnode1 && !fnode1->x3C) { - fnode1->x3C = 1; - IROFlowgraph_sub_4C3880(nodes, fnode1->index); - if (fnode1 != fnode2) { - for (i = 0; i < fnode1->numsucc; i++) - AddNodeAndSuccessorsRecursively(nodes, IRO_NodeTable[fnode1->succ[i]], fnode2); - } - } -} - -static Boolean RebuildPossibleLogicalExpression(IRONode *fnode, IROLinear *nd) { - IROUse *use; - IROLinear *nd2; - IROLinear *left; - IROLinear *right; - IRONode *r25; - IRONode *r24; - ENode *objnode; - IRODef *def1; - IRODef *def2; - UInt32 useCount; - UInt32 rewrittenUseCount; - Boolean sideEffectFlag; - IROLinearType compareType; - CLabel *somelab; - IRONode *var_68; - IRONode *var_6C; - CInt64 compareVal; - Boolean killedFlag; - BitVector *bv1; - BitVector *bv2; - - IROLinear *father; - IROLinear *iter; - IRODef *def; - UInt32 i; - IROLinear *newlin; - - objnode = nd->u.diadic.left->u.monadic->u.node; - if (!objnode->data.objref->varptr) - return 0; - - if (CInt64_Equal(nd->u.diadic.right->u.node->data.intval, cint64_zero)) { - compareType = IROLinearIfNot; - compareVal = cint64_one; - } else { - compareType = IROLinearIf; - compareVal = cint64_zero; - } - - var_68 = NULL; - def1 = NULL; - for (def = objnode->data.objref->varptr->defs; def && !def1; def = def->varnext) { - if (def->x18 && def->linear == nd) - def1 = def; - } - - if (def1) { - for (use = objnode->data.objref->varptr->uses; use; use = use->varnext) { - if (use->x1C == 2 && Bv_IsBitSet(def1->index, use->x18)) { - if (!var_68) { - var_68 = use->node; - } else if (Bv_IsBitSet(use->node->index, var_68->dom)) { - var_68 = use->node; - } - } - } - - if (var_68) { - for (use = objnode->data.objref->varptr->uses; use; use = use->varnext) { - if (use->node != var_68 && use->x1C == 2 && Bv_IsBitSet(def1->index, use->x18) && !Bv_IsBitSet(var_68->index, use->node->dom)) { - var_68 = NULL; - break; - } - } - } - } - - if ( - !var_68 || - !var_68->first || - var_68->first->type != IROLinearLabel || - !(somelab = var_68->first->u.label.label) || - var_68->numpred != 3 - ) - return 0; - - r25 = IRO_NodeTable[var_68->pred[0]]; - if (Bv_IsBitSet(IRO_NodeTable[var_68->pred[1]]->index, r25->dom)) { - r25 = IRO_NodeTable[var_68->pred[1]]; - } else if (!Bv_IsBitSet(r25->index, IRO_NodeTable[var_68->pred[1]]->dom)) { - return 0; - } - - if (Bv_IsBitSet(IRO_NodeTable[var_68->pred[2]]->index, r25->dom)) { - r25 = IRO_NodeTable[var_68->pred[2]]; - } else if (!Bv_IsBitSet(r25->index, IRO_NodeTable[var_68->pred[2]]->dom)) { - return 0; - } - - if ( - !r25 || - !(left = r25->last) || - left->type != compareType || - left->u.label.label != somelab - ) - return 0; - - if ( - !FindFlowgraphNodeThatStartsWithLabel(left->u.label.label, &var_68, &var_6C) || - !var_6C || - var_6C->numpred != 1 || - !(r24 = IRO_NodeTable[var_6C->pred[0]]) || - !(right = r24->last) || - right->type != compareType || - right->u.label.label != left->u.label.label || - !(nd2 = FindLastDiadicTopLevelAssignmentInFlowgraphNode(var_6C)) || - !IsLogicalExpressionAssign(nd2) || - nd2->u.diadic.left->u.monadic->u.node->data.objref != objnode->data.objref || - !CInt64_Equal(compareVal, nd2->u.diadic.right->u.node->data.intval) || - nd2->rtype != nd->rtype - ) - return 0; - - if ( - !CheckForTopLevelExpressions(fnode, fnode, r25, nd->next, left, 1) || - !CheckForTopLevelExpressions(r25->nextnode, r25->nextnode, r24, r25->nextnode->first, right, 1) || - !CheckForTopLevelExpressions(r24->nextnode, r24->nextnode, var_6C, right->next, nd2, 1) || - !CheckForTopLevelExpressions(var_6C, var_6C, var_6C, nd2->next, var_68->first, 1) - ) - return 0; - - rewrittenUseCount = 0; - useCount = 0; - killedFlag = 0; - sideEffectFlag = 0; - if (!objnode->data.objref->varptr || !(objnode->data.objref->varptr->uses) || !(objnode->data.objref->varptr->defs)) { - objnode = NULL; - } else { - def1 = def2 = NULL; - for (def = objnode->data.objref->varptr->defs; def && (!def1 || !def2); def = def->varnext) { - if (def->x18 && def->linear == nd) - def1 = def; - else if (def->x18 && def->linear == nd2) - def2 = def; - } - - if (!def1 || !def2) { - objnode = NULL; - } else { - for (use = objnode->data.objref->varptr->uses; objnode && use; use = use->varnext) { - if (use->x1C) { - useCount++; - if (Bv_IsBitSet(def1->index, use->x18) && Bv_IsBitSet(def2->index, use->x18)) { - for (i = 0; objnode && i < use->x18->size; i++) { - if (i != def1->index && i != def2->index && Bv_IsBitSet(i, use->x18)) - objnode = NULL; - } - - if (objnode && !Bv_IsBitSet(var_68->index, use->node->dom)) - objnode = NULL; - - if (objnode) { - if (RewriteUse(use, objnode, nd2, 0)) - rewrittenUseCount++; - else - objnode = NULL; - } - - if (objnode) { - if (!sideEffectFlag) - sideEffectFlag = HasSideEffectsBeforeUse(var_68, var_68, use->node, use->linear, 1); - - if (!killedFlag && (IRO_HasSideEffect(left->u.label.x4) || IRO_HasSideEffect(right->u.label.x4))) { - iter = use->linear; - if ((father = IRO_LocateFather(use->linear))) { - Bv_AllocVector(&bv1, IRO_NumVars + 1); - Bv_AllocVector(&bv2, IRO_NumVars + 1); - Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); - IRO_WalkTree(left->u.label.x4, GetExprKills); - IRO_WalkTree(right->u.label.x4, GetExprKills); - Bv_Or(IRO_VarKills, bv1); - while (father && !killedFlag) { - CheckUnorderedRegionsForSideEffectsAndUses(father, iter, bv1, bv2, &killedFlag); - iter = father; - father = IRO_LocateFather(father); - } - } - - if (!killedFlag) - killedFlag = UsesAKilledVarBeforeUse(var_68, var_68, use->node, use->linear, bv1, 1); - } - } - } else if (Bv_IsBitSet(def1->index, use->x18) || Bv_IsBitSet(def2->index, use->x18)) - objnode = NULL; - } - } - } - } - - if (!objnode) - return 0; - - left->type = right->type = IROLinearNop; - left->expr = right->expr = NULL; - - IRO_NopOut(nd); - - newlin = IRO_NewLinear(IROLinearOp2Arg); - memcpy(newlin, nd2, sizeof(IROLinear)); - newlin->nodetype = (compareType == IROLinearIf) ? ELOR : ELAND; - newlin->index = IRO_NumLinear++; - newlin->u.diadic.left = left->u.label.x4; - newlin->u.diadic.right = right->u.label.x4; - newlin->flags |= IROLF_Reffed; - IRO_Paste(newlin, newlin, nd2); - - if (rewrittenUseCount == 1 && !sideEffectFlag && !killedFlag && !objnode->data.objref->varptr->xB) { - for (use = objnode->data.objref->varptr->uses; use; use = use->varnext) { - if (use->x1C && Bv_IsBitSet(def1->index, use->x18) && Bv_IsBitSet(def2->index, use->x18)) - RewriteUse(use, objnode, newlin, 1); - } - - if (useCount == 1 && objnode->data.objref->u.var.info) { - objnode->data.objref->u.var.info->usage = 0; - objnode->data.objref->u.var.info->used = 0; - } - IRO_NopOut(nd2); - def1->x18 = 0; - def2->x18 = 0; - } else { - IRO_NopOut(nd2->u.label.x4); - nd2->u.label.x4 = newlin; - def1->x18 = 0; - } - - if (r24->numpred == 1 && IRO_NodeTable[r24->pred[0]] == r25 && IRO_MergeFlowGraphNodes(r25, r24)) - r24 = r25; - if (var_6C->numpred == 1 && IRO_NodeTable[var_6C->pred[0]] == r24 && IRO_MergeFlowGraphNodes(r24, var_6C)) - var_6C = r24; - if (var_68->numpred == 1 && r24 == r25 && var_6C == r24) - IRO_MergeFlowGraphNodes(var_6C, var_68); - return 1; -} - -static void RebuildLogicalExpressions(void) { - IRONode *fnode; - IROLinear *nd; - Boolean flag; - - flag = 1; - while (flag) { - flag = 0; - for (fnode = IRO_FirstNode; fnode && fnode->last; fnode = fnode->nextnode) { - for (nd = fnode->first; nd && nd != fnode->last->next; nd = nd->next) { - if (IsPossibleLogicalExpressionStart(fnode, nd) && RebuildPossibleLogicalExpression(fnode, nd)) - flag = 1; - } - } - } - - IRO_CheckForUserBreak(); -} - -static Boolean IsPossibleCondAssStart(IRONode *fnode) { - return (fnode->numsucc == 2) && fnode->last && (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot); -} - -static Type *logicalType(void) { - if (copts.cplusplus && copts.booltruefalse) - return TYPE(&stbool); - else - return TYPE(&stsignedint); -} - -static Boolean GeneratePossibleCondAss(IRONode *fnode) { - IROLinear *r31; - IRONode *node2; - IRONode *r29; - Boolean r28; - IRONode *node1; - IROLinear *r24; - Boolean r23; - IROLinear *r19; - Boolean r18; - IROLinear *r20; - Boolean r19flag; - IROLinear *r18nd; - IROLinear *ass; - IROLinear *cond; - IROLinear *r16; - IROLinear *r15; - BitVector *saveVarKills; - IROList list; - Object *obj; - IROLinear *r14; - - if (!fnode || fnode->numsucc != 2 || !fnode->last || (fnode->last->type != IROLinearIf && fnode->last->type != IROLinearIfNot)) - return 0; - - if (IRO_NodeTable[fnode->succ[0]] && - IRO_NodeTable[fnode->succ[0]]->first && - IRO_NodeTable[fnode->succ[0]]->first->type == IROLinearLabel && - IRO_NodeTable[fnode->succ[0]]->first->u.label.label == fnode->last->u.label.label) { - node1 = IRO_NodeTable[fnode->succ[0]]; - node2 = IRO_NodeTable[fnode->succ[1]]; - } else { - node1 = IRO_NodeTable[fnode->succ[1]]; - if (node1 && node1->first && node1->first->type == IROLinearLabel && node1->first->u.label.label == fnode->last->u.label.label) { - node2 = IRO_NodeTable[fnode->succ[0]]; - } else { - return 0; - } - } - - if (!node2 || node2->numpred != 1 || node2->numsucc != 1 || node2->last->next != node1->first) - return 0; - - if (IRO_NodeTable[node2->succ[0]] == node1 && Bv_IsBitSet(fnode->index, node1->dom)) { - r28 = 0; - } else if ( - node1->numpred == 1 && node1->numsucc == 1 && - node2->succ[0] == node1->succ[0] && - (r29 = IRO_NodeTable[node2->succ[0]]) && - Bv_IsBitSet(fnode->index, r29->dom) && - node1->last->next == r29->first - ) { - r28 = 1; - } else { - return 0; - } - - r24 = NULL; - if (node2->last) { - for (r19 = node2->first; r19 && r19 != node2->last->next; r19 = r19->next) { - if (IRO_IsAssignment(r19) && !(r19->flags & IROLF_Reffed) && !r24) { - r24 = r19; - } else if (r19->type != IROLinearNop && r19->type != IROLinearLabel && r19->type != IROLinearGoto && !(r19->flags & IROLF_Reffed)) { - return 0; - } - } - } - - if ( - !r24 || - (r24->nodetype != EASS && !IRO_TransformSelfAssignmentToAssignment(r24)) || - !r24->u.diadic.left || - r24->u.diadic.left->type != IROLinearOp1Arg || - r24->u.diadic.left->nodetype != EINDIRECT || - !r24->u.diadic.left->u.monadic || - r24->u.diadic.left->u.monadic->type != IROLinearOperand || - !r24->u.diadic.left->u.monadic->u.node || - !r24->u.diadic.left->u.monadic->u.node->rtype || - !IS_TYPE_POINTER_ONLY(r24->u.diadic.left->u.monadic->u.node->rtype) || - !r24->u.diadic.left->u.monadic->u.node->data.monadic - ) - return 0; - - if (r28) { - r31 = NULL; - if (node1->last) { - for (r19 = node1->first; r19 && r19 != node1->last->next; r19 = r19->next) { - if (IRO_IsAssignment(r19) && !(r19->flags & IROLF_Reffed) && !r31) { - r31 = r19; - } else if (r19->type != IROLinearNop && r19->type != IROLinearLabel && r19->type != IROLinearGoto && !(r19->flags & IROLF_Reffed)) { - return 0; - } - } - } - - if ( - !r31 || - (r31->nodetype != EASS && !IRO_TransformSelfAssignmentToAssignment(r31)) || - !r31->u.diadic.left || - r31->u.diadic.left->type != IROLinearOp1Arg || - r31->u.diadic.left->nodetype != EINDIRECT || - !r31->u.diadic.left->u.monadic || - r31->u.diadic.left->u.monadic->type != IROLinearOperand || - !r31->u.diadic.left->u.monadic->u.node || - !r31->u.diadic.left->u.monadic->u.node->rtype || - !IS_TYPE_POINTER_ONLY(r31->u.diadic.left->u.monadic->u.node->rtype) || - !r31->u.diadic.left->u.monadic->u.node->data.monadic - ) - return 0; - - r18 = IRO_ExprsSame(r24->u.diadic.left, r31->u.diadic.left); - } - - r23 = fnode->last->type == IROLinearIf; - r20 = fnode->last->u.diadic.right; - r19flag = 0; - if (r28 && copts.commonsubs && IRO_IsSubableExpression(r20)) - r19flag = 1; - - if (r19flag) { - IRO_FindDepends(r20); - r19flag = !IRO_NotSubable; - } - - if (r28) { - if (r18) { - r19flag = 0; - } else if (IRO_HasSideEffect(r20)) { - r19flag = 1; - } else { - Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); - IRO_WalkTree(r20, GetExprUses); - saveVarKills = IRO_VarKills; - Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); - IRO_WalkTree(r20, GetExprKills); - if (Bv_BitsInCommon(IRO_VarKills, saveVarKills)) - r19flag = 1; - } - - if (r19flag && !copts.commonsubs) - return 0; - } - - if (r19flag) { - IRO_InitList(&list); - obj = create_temp_object(r20->rtype); - IRO_FindVar(obj, 1, 1); - ass = IRO_NewLinear(IROLinearOp2Arg); - ass->u.diadic.left = IRO_TempReference(obj, &list); - ass->rtype = r20->rtype; - ass->nodetype = EASS; - ass->index = ++IRO_NumLinear; - ass->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned; - ass->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned; - ass->u.diadic.right = r20; - IRO_AddToList(ass, &list); - IRO_PasteAfter(list.head, list.tail, r20); - } - - r16 = r24->u.diadic.left; - r15 = r24->u.diadic.right; - fnode->last->type = IROLinearNop; - fnode->last->expr = NULL; - if (node2->last->type == IROLinearGoto) { - node2->last->type = IROLinearNop; - node2->last->expr = NULL; - } - if (r28 || node1->numpred == 2) { - node1->first->type = IROLinearNop; - node1->first->expr = NULL; - } - - if (r28 && r18) { - if (node1->last->type == IROLinearGoto) { - node1->last->type = IROLinearNop; - node1->last->expr = NULL; - } - if (r29->numpred == 2) { - r29->first->type = IROLinearNop; - r29->first->expr = NULL; - } - - cond = IRO_NewLinear(IROLinearOp3Arg); - memcpy(cond, r24, sizeof(IROLinear)); - cond->type = IROLinearOp3Arg; - cond->nodetype = ECOND; - cond->index = ++IRO_NumLinear; - cond->rtype = r16->rtype; - cond->flags |= IROLF_Reffed; - if (r19flag) { - IRO_InitList(&list); - r14 = IRO_TempReference(obj, &list); - IRO_Paste(list.head, list.tail, r31); - } else { - r14 = r20; - } - cond->u.args3.a = r14; - - if (r23) { - cond->u.args3.b = r31->u.diadic.right; - cond->u.args3.c = r15; - } else { - cond->u.args3.b = r15; - cond->u.args3.c = r31->u.diadic.right; - } - - r24->type = IROLinearNop; - r24->expr = NULL; - IRO_NopOut(r24->u.diadic.left); - IRO_Paste(cond, cond, r31); - r31->u.diadic.right = cond; - } else { - r24->type = IROLinearOp3Arg; - r24->nodetype = ECONDASS; - if (r19flag) { - IRO_InitList(&list); - r20 = IRO_TempReference(obj, &list); - IRO_Paste(list.head, list.tail, r24); - } - cond = r20; - if (r23) { - r18nd = IRO_NewLinear(IROLinearOp1Arg); - memcpy(r18nd, r20, sizeof(IROLinear)); - r18nd->type = IROLinearOp1Arg; - r18nd->nodetype = ELOGNOT; - r18nd->index = ++IRO_NumLinear; - r18nd->rtype = logicalType(); - r18nd->u.monadic = r20; - r18nd->flags |= IROLF_Reffed; - IRO_Paste(r18nd, r18nd, r24); - r20 = r18nd; - } - r24->u.args3.a = r20; - r24->u.args3.b = r16; - r24->u.args3.c = r15; - if (r28) { - r15 = r31->u.diadic.left; - r16 = r31->u.diadic.right; - if (node1->last->type == IROLinearGoto) { - node1->last->type = IROLinearNop; - node1->last->expr = NULL; - } - if (r29->numpred == 2) { - r29->first->type = IROLinearNop; - r29->first->expr = NULL; - } - r31->type = IROLinearOp3Arg; - r31->nodetype = ECONDASS; - if (r19flag) { - IRO_InitList(&list); - cond = IRO_TempReference(obj, &list); - IRO_Paste(list.head, list.tail, r31); - } else { - IRO_InitList(&list); - cond = IRO_DuplicateExpr(cond, &list); - IRO_Paste(list.head, list.tail, r31); - } - if (!r23) { - r14 = IRO_NewLinear(IROLinearOp1Arg); - memcpy(r14, cond, sizeof(IROLinear)); - r14->type = IROLinearOp1Arg; - r14->nodetype = ELOGNOT; - r14->index = ++IRO_NumLinear; - r14->rtype = logicalType(); - r14->u.monadic = cond; - r14->flags |= IROLF_Reffed; - IRO_Paste(r14, r14, r31); - cond = r14; - } - r31->u.args3.a = cond; - r31->u.args3.b = r15; - r31->u.args3.c = r16; - } - } - - if (IRO_MergeFlowGraphNodes(fnode, node2)) - node2 = fnode; - if ((r28 || node1->numpred == 1) && IRO_MergeFlowGraphNodes(node2, node1)) - node1 = node2; - if (r28 && r29->numpred == 1) - IRO_MergeFlowGraphNodes(node1, r29); - return 1; -} - -static void GenerateCondAssignments(void) { - IRONode *fnode; - - fnode = IRO_FirstNode; - while (fnode && fnode->last) { - if (IsPossibleCondAssStart(fnode)) { - if (!GeneratePossibleCondAss(fnode)) - fnode = fnode->nextnode; - } else { - fnode = fnode->nextnode; - } - } - - IRO_CheckForUserBreak(); -} - -void IRO_RegenerateExpressions(void) { - IRO_UpdateFlagsOnInts(); - IRO_ComputeSuccPred(); - IRO_ComputeDom(); - IRO_UseDef(0, 0); - - if (copts.optimizationlevel > 0) { - IRO_Dump("Rebuilding ELORs and ELANDs\n"); - RebuildLogicalExpressions(); - IRO_DumpAfterPhase("RebuildLogicalExpressions", 0); - } - - if (copts.optimizationlevel > 0) { - IRO_Dump("Rebuilding ECONDs\n"); - RebuildCondExpressions(); - IRO_DumpAfterPhase("RebuildCondExpressions", 0); - } - - if (copts.optimizationlevel > 0) { - IRO_Dump("Generating ECONDASSes\n"); - GenerateCondAssignments(); - IRO_DumpAfterPhase("GenerateCondAssignments", 0); - } -} diff --git a/compiler_and_linker/unsorted/IroFlowgraph.c b/compiler_and_linker/unsorted/IroFlowgraph.c deleted file mode 100644 index 5c9c840..0000000 --- a/compiler_and_linker/unsorted/IroFlowgraph.c +++ /dev/null @@ -1,439 +0,0 @@ -#include "compiler/IroFlowgraph.h" -#include "compiler/IroCSE.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroPropagate.h" -#include "compiler/IROUseDef.h" -#include "compiler/IroUtil.h" -#include "compiler/CError.h" -#include "compiler/CFunc.h" -#include "compiler/CompilerTools.h" -#include "compiler/Exceptions.h" -#include "compiler/InlineAsmPPC.h" - -UInt16 IRO_NumNodes; -IRONode *IRO_FirstNode; -IRONode *IRO_LastNode; -IRONode *IRO_EndNode; -IRONode **IRO_NodeTable; -BitVector *IRO_VarKills; -BitVector *IRO_Avail; -BitVector *IRO_FuncKills; -BitVector *IRO_ExprKills; - -static IRONode *StartNode(IROLinear *linear) { - IRONode *node = oalloc(sizeof(IRONode)); - - node->index = IRO_NumNodes; - node->numsucc = 0; - node->succ = NULL; - node->numpred = 0; - node->pred = NULL; - node->first = linear; - node->last = linear; - node->x16 = NULL; - node->x1A = NULL; - node->x1E = NULL; - node->x22 = NULL; - node->x26 = 0; - node->x2A = NULL; - node->dom = NULL; - node->nextnode = NULL; - node->x36 = 0; - node->x37 = 0; - node->mustreach = 0; - node->x39 = 0; - node->loopdepth = 0; - node->x3C = 0; - node->addressed = NULL; - - IRO_NumNodes++; - if (!IRO_FirstNode) - IRO_FirstNode = node; - else - IRO_LastNode->nextnode = node; - IRO_LastNode = node; - return node; -} - -static void AddSucc(IRONode *a, IRONode *b) { - a->succ[a->numsucc++] = b->index; - b->numpred++; -} - -static void AddLabelSucc(IRONode *node, CLabel *label) { - IRONode *targetnode = (IRONode *) label->stmt; - if (targetnode) { - AddSucc(node, targetnode); - targetnode->x39 = 1; - } else { - CError_FATAL(126); - } -} - -static void AddSwitchSucc(IRONode *node) { - SwitchInfo *info = node->last->u.swtch.info; - SwitchCase *curcase = info->cases; - SInt32 i = 1; - - while (curcase) { - curcase = curcase->next; - i++; - } - - node->succ = oalloc(sizeof(UInt16) * i); - for (curcase = info->cases; curcase; curcase = curcase->next) - AddLabelSucc(node, curcase->label); - AddLabelSucc(node, info->defaultlabel); -} - -static void AddPred(UInt32 a, UInt16 b) { - IRONode *node = IRO_NodeTable[a]; - node->pred[node->numpred++] = b; -} - -void IRO_ComputeSuccPred(void) { - CLabel *label; - IRONode *node; - SInt32 count; - IROLinear *linear; - ExceptionAction *action; - IAEffects effects; - UInt16 i; - - for (label = Labels; label; label = label->next) - label->stmt = NULL; - - for (node = IRO_FirstNode; node; node = node->nextnode) { - node->x39 = 0; - node->numsucc = 0; - node->numpred = 0; - node->x36 = 0; - node->x37 = 0; - if (node->first && node->first->type == IROLinearLabel) - node->first->u.label.label->stmt = (Statement *) node; - } - - for (node = IRO_FirstNode; node; node = node->nextnode) { - if (!node->first) { - if (node->nextnode) { - node->succ = oalloc(sizeof(UInt16)); - AddSucc(node, node->nextnode); - } - } else { - linear = node->last; - next_linear: - switch (linear->type) { - case IROLinearReturn: - case IROLinearEnd: - break; - case IROLinearGoto: - node->succ = oalloc(sizeof(UInt16)); - AddLabelSucc(node, linear->u.label.label); - break; - case IROLinearIf: - case IROLinearIfNot: - node->succ = oalloc(sizeof(UInt16) * 2); - AddSucc(node, node->nextnode); - AddLabelSucc(node, linear->u.label.label); - break; - case IROLinearSwitch: - AddSwitchSucc(node); - break; - case IROLinearFunccall: - count = 1; - if (IRO_FunctionCallMightThrowException(linear)) { - for (action = linear->stmt->dobjstack; action; action = action->prev) { - if (action->type == EAT_CATCHBLOCK || action->type == EAT_SPECIFICATION) - count++; - } - } - node->succ = oalloc(sizeof(UInt16) * count); - AddSucc(node, node->nextnode); - if (IRO_FunctionCallMightThrowException(linear)) { - for (action = linear->stmt->dobjstack; action; action = action->prev) { - if (action->type == EAT_CATCHBLOCK) - AddLabelSucc(node, action->data.catch_block.catch_label); - else if (action->type == EAT_SPECIFICATION) - AddLabelSucc(node, action->data.specification.unexp_label); - } - } - break; - case IROLinearAsm: - CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); - node->succ = oalloc(sizeof(UInt16) * (!effects.x5 + effects.numlabels)); - if (!effects.x5) - AddSucc(node, node->nextnode); - for (i = 0; i < effects.numlabels; i++) - AddLabelSucc(node, effects.labels[i]); - break; - case IROLinearOp2Arg: - if (linear->nodetype == ECOMMA) { - linear = linear->u.diadic.right; - goto next_linear; - } - default: - if (node->nextnode) { - node->succ = oalloc(sizeof(UInt16)); - AddSucc(node, node->nextnode); - } - } - } - } - - for (node = IRO_FirstNode; node; node = node->nextnode) { - if (node->numpred) - node->pred = oalloc(sizeof(UInt16) * node->numpred); - else - node->pred = NULL; - node->numpred = 0; - } - - for (node = IRO_FirstNode; node; node = node->nextnode) { - for (i = 0; i < node->numsucc; i++) - AddPred(node->succ[i], node->index); - } - - for (node = IRO_FirstNode; node; node = node->nextnode) { - if (node->first && node->first->type == IROLinearLabel) { - IROLinear *linear = node->first; - do { - if (linear->type == IROLinearBeginCatch || linear->type == IROLinearEndCatch || linear->type == IROLinearEndCatchDtor) { - node->x39 = 1; - break; - } - } while (linear != node->last && (linear = linear->next)); - } - } -} - -void IRO_ComputeDom(void) { - IRONode *node; - BitVector *bv; - SInt32 i; - int repeat; - - Bv_AllocVector(&IRO_FirstNode->dom, IRO_NumNodes); - Bv_SetBit(IRO_FirstNode->index, IRO_FirstNode->dom); - for (node = IRO_FirstNode->nextnode; node; node = node->nextnode) { - Bv_AllocVector(&node->dom, IRO_NumNodes); - Bv_Set(node->dom); - } - - Bv_AllocVector(&bv, IRO_NumNodes); - - do { - repeat = 0; - for (node = IRO_FirstNode->nextnode; node; node = node->nextnode) { - if (node->numpred) { - Bv_Set(bv); - for (i = 0; i < node->numpred; i++) { - Bv_And(IRO_NodeTable[node->pred[i]]->dom, bv); - } - Bv_SetBit(node->index, bv); - } else { - Bv_Clear(bv); - Bv_SetBit(node->index, bv); - } - - if (!Bv_Compare(bv, node->dom)) { - Bv_Copy(bv, node->dom); - repeat = 1; - } - } - } while (repeat); -} - -void IRO_BuildFlowgraph(IROLinear *linear) { - IROLinear *scan; - CLabel *label; - ExceptionAction *action; - IAEffects effects; - IRONode *node; - SInt32 i; - int flag; - - for (label = Labels; label; label = label->next) - label->stmt = NULL; - - scan = linear; - IRO_NumNodes = 0; - IRO_FirstNode = IRO_LastNode = IRO_EndNode = NULL; - while (scan) { - StartNode(scan); - if (scan->type == IROLinearLabel) - scan->u.label.label->stmt = (Statement *) IRO_LastNode; - - flag = 0; - while (!flag && scan->next && !(scan->next->flags & IROLF_1)) { - switch (scan->type) { - case IROLinearGoto: - case IROLinearReturn: - case IROLinearEntry: - case IROLinearExit: - case IROLinearEnd: - flag = 1; - break; - case IROLinearIf: - case IROLinearIfNot: - case IROLinearSwitch: - flag = 1; - skip: - if (scan->next->type == IROLinearLabel) { - IROLinear *nw = IRO_NewLinear(IROLinearNop); - nw->index = ++IRO_NumLinear; - nw->next = scan->next; - scan->next = nw; - } - break; - case IROLinearFunccall: - if (IRO_FunctionCallMightThrowException(scan)) { - for (action = scan->stmt->dobjstack; action; action = action->prev) { - if (action->type == EAT_CATCHBLOCK || action->type == EAT_SPECIFICATION) { - flag = 1; - goto skip; - } - } - } - break; - case IROLinearAsm: - CodeGen_GetAsmEffects(scan->u.asm_stmt, &effects); - if (effects.numlabels) - flag = 1; - break; - } - if (!flag) - scan = scan->next; - } - - if (scan->type == IROLinearEnd) - IRO_EndNode = IRO_LastNode; - IRO_LastNode->last = scan; - scan = scan->next; - } - - IRO_NodeTable = oalloc(IRO_NumNodes * sizeof(IRONode *)); - memset(IRO_NodeTable, 0, IRO_NumNodes * sizeof(IRONode *)); - for (node = IRO_FirstNode, i = 0; node; node = node->nextnode) - IRO_NodeTable[i++] = node; - - IRO_ComputeSuccPred(); - IRO_ComputeDom(); - IRO_CheckForUserBreak(); -} - -IRONode *IRO_NewFlowGraphNode(void) { - IRONode *node = oalloc(sizeof(IRONode)); - memset(node, 0, sizeof(IRONode)); - node->index = IRO_NumNodes; - IRO_NumNodes++; - node->nextnode = NULL; - return node; -} - -IRONode *IRO_MergeFlowGraphNodes(IRONode *a, IRONode *b) { - IRONode *succ; - Boolean found; - UInt32 i; - UInt32 j; - UInt32 k; - - if (a->nextnode == b && a->last && b->first && a->last->next == b->first) { - if (b->first->type == IROLinearLabel) - IRO_NopOut(b->first); - - a->nextnode = b->nextnode; - a->last = b->last; - - for (i = 0; i < a->numsucc; i++) { - if (b->index == a->succ[i]) { - for (j = i; j < a->numsucc; j++) { - if ((j + 1) < a->numsucc) - a->succ[j] = a->succ[j + 1]; - else - a->succ[j] = 0; - } - a->numsucc--; - break; - } - } - - for (i = 0; i < b->numsucc; i++) { - succ = IRO_NodeTable[b->succ[i]]; - for (j = 0; j < a->numsucc; j++) { - if (b->succ[i] == a->succ[j]) - break; - } - - if (j == a->numsucc) { - AddSucc(a, IRO_NodeTable[b->succ[i]]); - succ->numpred--; - } - - found = 0; - for (j = 0; j < succ->numpred; j++) { - if (a->index == succ->pred[j]) { - found = 1; - break; - } - } - - for (j = 0; j < succ->numpred; j++) { - if (b->index == succ->pred[j]) { - if (!found) { - succ->pred[j] = a->index; - } else { - for (k = j; k < succ->numpred; k++) { - if ((k + 1) < succ->numpred) - succ->pred[k] = succ->pred[k + 1]; - else - succ->pred[k] = 0; - } - succ->numpred--; - } - break; - } - } - } - - b->numsucc = b->numpred = 0; - b->first = b->last = NULL; - b->nextnode = NULL; - b->x36 = 0; - b->x37 = 0; - b->mustreach = 0; - b->x39 = 0; - b->loopdepth = 0; - - if (IRO_LastNode == b) - IRO_LastNode = a; - - if (IRO_FirstExpr && IRO_LastExpr) { - IROExpr *expr; - for (expr = IRO_FirstExpr; expr && expr != IRO_LastExpr->next; expr = expr->next) { - if (expr->node == b) - expr->node = a; - } - } - - if (IRO_FirstAssign && IRO_LastAssign) { - IROAssign *assign; - for (assign = IRO_FirstAssign; assign && assign != IRO_LastAssign->next; assign = assign->next) { - if (assign->node == b) - assign->node = a; - } - } - - if (IRO_FirstVarUse && IRO_LastVarUse) { - IROUse *use; - for (use = IRO_FirstVarUse; use && use != IRO_LastVarUse->globalnext; use = use->globalnext) { - if (use->node == b) - use->node = a; - } - } - - IRO_NodeTable[b->index] = NULL; - return a; - } - - return NULL; -} diff --git a/compiler_and_linker/unsorted/IroJump.c b/compiler_and_linker/unsorted/IroJump.c deleted file mode 100644 index e39e3f0..0000000 --- a/compiler_and_linker/unsorted/IroJump.c +++ /dev/null @@ -1,267 +0,0 @@ -#include "compiler/IroJump.h" -#include "compiler/IroDump.h" -#include "compiler/IroFlowgraph.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroUtil.h" -#include "compiler/CFunc.h" -#include "compiler/Exceptions.h" - -static Boolean CheckChain(CLabel **labelptr) { - IRONode *node; - - for (node = IRO_FirstNode; node; node = node->nextnode) { - if (node->first && node->first->type == IROLinearLabel && node->first->u.label.label == *labelptr) { - IROLinear *linear; - CLabel *lab; - for (linear = node->first->next, lab = NULL; linear && (linear->type == IROLinearLabel || linear->type == IROLinearNop); linear = linear->next) { - if (linear->type == IROLinearLabel) - lab = linear->u.label.label; - } - - if (linear->type == IROLinearGoto && *labelptr != linear->u.label.label) { - *labelptr = linear->u.label.label; - IRO_Dump("Chaining goto at %d\n", linear->index); - return 1; - } - - if (lab && *labelptr != lab) - *labelptr = lab; - return 0; - } - } - - return 0; -} - -Boolean IRO_DoJumpChaining(void) { - IRONode *node; - IROLinear *linear; - Boolean flag; - SwitchInfo *info; - SwitchCase *curcase; - Boolean result; - - result = 0; - do { - flag = 0; - for (node = IRO_FirstNode; node; node = node->nextnode) { - if (node->first) { - linear = node->last; - switch (linear->type) { - case IROLinearGoto: - if (CheckChain(&linear->u.label.label)) - flag = 1; - break; - case IROLinearIf: - case IROLinearIfNot: - if (CheckChain(&linear->u.label.label)) - flag = 1; - break; - case IROLinearSwitch: - info = linear->u.swtch.info; - for (curcase = info->cases; curcase; curcase = curcase->next) { - if (CheckChain(&curcase->label)) - flag = 1; - } - if (CheckChain(&info->defaultlabel)) - flag = 1; - break; - } - } - } - result |= flag; - IRO_CheckForUserBreak(); - } while (flag); - - return result; -} - -void IRO_MakeReachable(IRONode *node) { - UInt16 i; - Boolean flag; - - node->x36 = 1; - do { - flag = 0; - for (node = IRO_FirstNode; node; node = node->nextnode) { - if (node->x36 && !node->x37) { - for (i = 0; i < node->numsucc; i++) { - if (!IRO_NodeTable[node->succ[i]]->x36) { - flag = 1; - IRO_NodeTable[node->succ[i]]->x36 = 1; - } - } - node->x37 = 1; - } - } - } while (flag); -} - -Boolean IRO_RemoveUnreachable(void) { - IRONode *node2; - IRONode *node1; - IROLinear *scan; - IROLinear *linear; - Boolean result; - ExceptionAction **actptr; - ExceptionAction *act; - - result = 0; - IRO_ComputeSuccPred(); - IRO_MakeReachable(IRO_FirstNode); - node1 = IRO_FirstNode; - for (node2 = IRO_FirstNode->nextnode; node2; node2 = node2->nextnode) { - if (node2->first && !node2->x36) { - IRO_Dump("Removing unreachable code at: %d\n", node2->index); - node1->nextnode = node2->nextnode; - node1->last->next = node2->last->next; - result = 1; - for (linear = node2->first; linear && linear->type == IROLinearLabel && linear != node2->last->next; linear = linear->next) { - for (scan = IRO_FirstLinear; scan; scan = scan->next) { - if (scan->stmt) - scan->stmt->marked = 0; - } - - for (scan = IRO_FirstLinear; scan; scan = scan->next) { - if (scan->stmt && !scan->stmt->marked) { - scan->stmt->marked = 1; - for (actptr = &scan->stmt->dobjstack; (act = *actptr); actptr = &act->prev) { - if ( - (act->type == EAT_CATCHBLOCK && act->data.catch_block.catch_label == linear->u.label.label) || - (act->type == EAT_SPECIFICATION && act->data.specification.unexp_label == linear->u.label.label)) { - *actptr = act->prev; - } - } - } - } - } - if (node2 == IRO_LastNode) - IRO_LastNode = node1; - } else { - node1 = node2; - } - } - - if (result) { - IRO_ComputeSuccPred(); - IRO_ComputeDom(); - } - - IRO_CheckForUserBreak(); - return result; -} - -Boolean IRO_RemoveRedundantJumps(void) { - IRONode *node; - IROLinear *linear; - IROLinear *scan; - IROLinear *scan2; - SwitchInfo *info; - SwitchCase *curcase; - Boolean result; - - result = 0; - for (node = IRO_FirstNode; node; node = node->nextnode) { - if (node->first) { - linear = node->last; - switch (linear->type) { - case IROLinearGoto: - scan = linear->next; - while (scan && ((scan->type == IROLinearNop) || (scan->type == IROLinearLabel && scan->u.label.label != linear->u.label.label))) - scan = scan->next; - while (1) { - if (!scan) break; - if (scan->type != IROLinearLabel) break; - if (scan->u.label.label == linear->u.label.label) { - IRO_Dump("Removing goto next at %d\n", linear->index); - linear->type = IROLinearNop; - result = 1; - break; - } - scan = scan->next; - } - break; - - case IROLinearIf: - case IROLinearIfNot: - scan = linear->next; - while (scan && scan->type == IROLinearNop) - scan = scan->next; - if (scan && scan->type == IROLinearGoto) { - scan2 = scan->next; - while (scan2 && ((scan2->type == IROLinearNop) || (scan2->type == IROLinearLabel && scan2->u.label.label != linear->u.label.label))) - scan2 = scan2->next; - - if (scan2 && scan2->type == IROLinearLabel && scan2->u.label.label == linear->u.label.label) { - if (linear->type == IROLinearIf) - linear->type = IROLinearIfNot; - else - linear->type = IROLinearIf; - - linear->u.label.label = scan->u.label.label; - scan->type = IROLinearNop; - IRO_Dump("Removing branch around goto at %d\n", linear->index); - result = 1; - } - } - - scan2 = linear->next; - while (scan2 && ((scan2->type == IROLinearNop) || (scan2->type == IROLinearLabel && scan2->u.label.label != linear->u.label.label))) - scan2 = scan2->next; - while (1) { - if (!scan2) break; - if (scan2->type != IROLinearLabel) break; - if (scan2->u.label.label == linear->u.label.label) { - IRO_Dump("Removing If/IfNot_Goto next at %d\n", linear->index); - linear->type = IROLinearNop; - IRO_CheckSideEffect(linear->u.label.x4); - result = 1; - break; - } - scan2 = scan2->next; - } - break; - - case IROLinearSwitch: - info = linear->u.swtch.info; - curcase = info->cases; - while (curcase && curcase->label == info->defaultlabel) - curcase = curcase->next; - if (!curcase) { - IRO_Dump("Removing Switch next at %d\n", linear->index); - IRO_CheckSideEffect(linear->u.swtch.x4); - linear->type = IROLinearGoto; - linear->u.label.label = info->defaultlabel; - result = 1; - } - break; - } - } - } - - if (result) { - IRO_ComputeSuccPred(); - IRO_ComputeDom(); - } - - IRO_CheckForUserBreak(); - return result; -} - -Boolean IRO_RemoveLabels(void) { - Boolean result; - IRONode *node; - - result = 0; - IRO_ComputeSuccPred(); - for (node = IRO_FirstNode; node; node = node->nextnode) { - if (node->first && node->first->type == IROLinearLabel && !node->x39) { - node->first->type = IROLinearNop; - node->first->flags &= ~IROLF_1; - result = 1; - } - } - - IRO_CheckForUserBreak(); - return result; -} diff --git a/compiler_and_linker/unsorted/IroLinearForm.c b/compiler_and_linker/unsorted/IroLinearForm.c deleted file mode 100644 index 4941587..0000000 --- a/compiler_and_linker/unsorted/IroLinearForm.c +++ /dev/null @@ -1,1797 +0,0 @@ -#include "compiler/IroLinearForm.h" -#include "compiler/IroDump.h" -#include "compiler/IroFlowgraph.h" -#include "compiler/IroUtil.h" -#include "compiler/IroVars.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInt64.h" -#include "compiler/CParser.h" -#include "compiler/CompilerTools.h" -#include "compiler/InlineAsm.h" -#include "compiler/InlineAsmPPC.h" -#include "compiler/types.h" - -typedef struct NullCheckListNode { - SInt32 precompid; - Object *tempobj; - struct NullCheckListNode *next; -} NullCheckListNode; - -IROLinear *IRO_FirstLinear; -IROLinear *IRO_LastLinear; -UInt32 IRO_NumLinear; -Statement *CurStat; -static NullCheckListNode *NullCheckList; -static Statement *CurrStmt; -static Statement *PrevStmt; - -static void LinkLinear(IROLinear *linear) { - linear->index = IRO_NumLinear++; - if (IRO_FirstLinear) - IRO_LastLinear->next = linear; - else - IRO_FirstLinear = linear; - IRO_LastLinear = linear; -} - -IROLinear *IRO_NewLinear(IROLinearType type) { - IROLinear *linear = oalloc(sizeof(IROLinear)); - memset(linear, 0, sizeof(IROLinear)); - linear->stmt = CurStat; - linear->nodetype = EPOSTINC; - linear->next = NULL; - linear->type = type; - linear->rtype = NULL; - linear->flags = 0; - linear->nodeflags = 0; - linear->expr = NULL; - linear->x16 = 0; - return linear; -} - -static void MarkAssigned(IROLinear *linear, Boolean flag) { - IROLinear *inner; - IROAddrRecord *rec; - - if (IS_LINEAR_MONADIC(linear, EINDIRECT) && IS_LINEAR_MONADIC(linear->u.monadic, EBITFIELD)) { - linear->flags |= IROLF_Assigned; - inner = linear->u.monadic->u.monadic; - if (inner->type == IROLinearOperand) { - inner->flags |= IROLF_Assigned; - if (flag) { - linear->flags |= IROLF_Used; - inner->flags |= IROLF_Used; - } - } - - if (IS_LINEAR_DIADIC(inner, EADD)) { - if (IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) { - if (IS_LINEAR_ENODE(inner->u.diadic.right, EINTCONST)) - inner->u.diadic.left->flags |= IROLF_Assigned; - if (flag) { - linear->flags |= IROLF_Used; - inner->u.diadic.left->flags |= IROLF_Used; - } - } - - rec = IRO_InitAddrRecordPointer(inner); - IRO_DecomposeAddressExpression(inner, rec); - if (rec->numObjRefs == 1 && IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) { - ((IROLinear *) rec->objRefs->element)->flags |= IROLF_Assigned; - if (flag) { - linear->flags |= IROLF_Used; - ((IROLinear *) rec->objRefs->element)->flags |= IROLF_Used; - } - } - } - } - - if (IS_LINEAR_MONADIC(linear, EINDIRECT)) { - linear->flags |= IROLF_Assigned; - if (linear->u.monadic->type == IROLinearOperand) { - linear->u.monadic->flags |= IROLF_Assigned; - if (flag) { - linear->flags |= IROLF_Used; - linear->u.monadic->flags |= IROLF_Used; - } - } - } - - if (IS_LINEAR_MONADIC(linear, EINDIRECT)) { - linear->flags |= IROLF_Assigned; - inner = linear->u.monadic; - - if (IS_LINEAR_DIADIC(inner, EADD)) { - if (IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) { - if (IS_LINEAR_ENODE(inner->u.diadic.right, EINTCONST)) - inner->u.diadic.left->flags |= IROLF_Assigned; - if (flag) { - linear->flags |= IROLF_Used; - inner->u.diadic.left->flags |= IROLF_Used; - } - } - - rec = IRO_InitAddrRecordPointer(inner); - IRO_DecomposeAddressExpression(inner, rec); - if (rec->numObjRefs == 1 && IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) { - ((IROLinear *) rec->objRefs->element)->flags |= IROLF_Assigned; - if (flag) { - linear->flags |= IROLF_Used; - ((IROLinear *) rec->objRefs->element)->flags |= IROLF_Used; - } - } - } - } -} - -static void MarkSubscript(IROLinear *linear) { - linear->flags |= IROLF_Subs; - if (IS_LINEAR_DIADIC(linear, EADD)) { - if (IRO_IsAddressMultiply(linear->u.diadic.left) || IS_LINEAR_MONADIC(linear->u.diadic.left, EINDIRECT)) - linear->u.diadic.left->flags |= IROLF_Subs; - if (IRO_IsAddressMultiply(linear->u.diadic.right) || IS_LINEAR_MONADIC(linear->u.diadic.right, EINDIRECT)) - linear->u.diadic.right->flags |= IROLF_Subs; - - if (IS_LINEAR_DIADIC(linear->u.diadic.left, EADD)) - MarkSubscript(linear->u.diadic.left); - if (IS_LINEAR_DIADIC(linear->u.diadic.right, EADD)) - MarkSubscript(linear->u.diadic.right); - } -} - -static void MarkArgs(IROLinear *linear) { - int i; - linear->flags |= IROLF_4000; - - switch (linear->type) { - case IROLinearEnd: - break; - case IROLinearOp1Arg: - case IROLinearBeginCatch: - case IROLinearEndCatch: - case IROLinearEndCatchDtor: - MarkArgs(linear->u.monadic); - break; - case IROLinearOp2Arg: - MarkArgs(linear->u.diadic.left); - MarkArgs(linear->u.diadic.right); - break; - case IROLinearIf: - case IROLinearIfNot: - MarkArgs(linear->u.label.x4); - break; - case IROLinearReturn: - if (linear->u.monadic) - MarkArgs(linear->u.monadic); - break; - case IROLinearSwitch: - MarkArgs(linear->u.swtch.x4); - break; - case IROLinearOp3Arg: - MarkArgs(linear->u.args3.a); - MarkArgs(linear->u.args3.b); - MarkArgs(linear->u.args3.c); - break; - case IROLinearFunccall: - MarkArgs(linear->u.funccall.linear8); - for (i = 0; i < linear->u.funccall.argCount; i++) - MarkArgs(linear->u.funccall.args[i]); - break; - } -} - -// assumed name, position -CW_INLINE void MarkSubExpr(IROLinear *linear) { - int i; - - switch (linear->type) { - case IROLinearNop: - case IROLinearOperand: - case IROLinearGoto: - case IROLinearLabel: - case IROLinearEntry: - case IROLinearExit: - case IROLinearAsm: - case IROLinearEnd: - break; - case IROLinearOp1Arg: - case IROLinearBeginCatch: - case IROLinearEndCatch: - case IROLinearEndCatchDtor: - linear->u.monadic->flags |= IROLF_Reffed; - break; - case IROLinearOp2Arg: - linear->u.diadic.left->flags |= IROLF_Reffed; - linear->u.diadic.right->flags |= IROLF_Reffed; - break; - case IROLinearIf: - case IROLinearIfNot: - linear->u.label.x4->flags |= IROLF_Reffed; - break; - case IROLinearReturn: - if (linear->u.monadic) - linear->u.monadic->flags |= IROLF_Reffed; - break; - case IROLinearSwitch: - linear->u.swtch.x4->flags |= IROLF_Reffed; - break; - case IROLinearOp3Arg: - linear->u.args3.a->flags |= IROLF_Reffed; - linear->u.args3.b->flags |= IROLF_Reffed; - linear->u.args3.c->flags |= IROLF_Reffed; - break; - case IROLinearFunccall: - linear->u.funccall.linear8->flags |= IROLF_Reffed; - for (i = 0; i < linear->u.funccall.argCount; i++) - linear->u.funccall.args[i]->flags |= IROLF_Reffed; - break; - default: - CError_FATAL(368); - } -} - -static void MarkSubs1(IROLinear *linear) { - IROAddrRecord *rec; - - if (IS_LINEAR_MONADIC(linear, EBITFIELD)) { - linear = linear->u.monadic; - if (IS_LINEAR_ENODE(linear, EOBJREF)) - linear->flags |= IROLF_Ind; - } - - if (IS_LINEAR_DIADIC(linear, EADD)) { - if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF) && IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) - linear->u.diadic.left->flags |= IROLF_Ind; - - rec = IRO_InitAddrRecordPointer(linear); - IRO_DecomposeAddressExpression(linear, rec); - if (rec->numObjRefs == 1 && IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF)) - ((IROLinear *) rec->objRefs->element)->flags |= IROLF_Ind; - } -} - -static void MakeLeftChildAsAssignment(ENode *enode) { - Statement *stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_EXPRESSION; - stmt->expr = enode->data.diadic.left; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; -} - -static void AssignCommaRToTemp(ENode *enode, Boolean flag) { - Statement *stmt; - - if (!IS_TYPE_VOID(enode->rtype) && !flag) { - Object *obj = create_temp_object(enode->rtype); - ENode *indnode = IRO_NewENode(EINDIRECT); - indnode->data.monadic = create_objectrefnode(obj); - - if (!IS_TYPE_VOID(enode->rtype)) - indnode->rtype = enode->rtype; - else - CError_FATAL(548); - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_EXPRESSION; - stmt->expr = IRO_NewENode(EASS); - stmt->expr->data.diadic.left = indnode; - stmt->expr->data.diadic.right = enode->data.diadic.right; - stmt->expr->rtype = enode->rtype; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; - - enode->type = EINDIRECT; - enode->data.monadic = create_objectrefnode(obj); - CError_ASSERT(580, !IS_TYPE_VOID(enode->rtype)); - } else { - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_EXPRESSION; - stmt->expr = enode->data.diadic.right; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; - - enode->type = EINTCONST; - enode->data.intval = cint64_zero; - } -} - -static void AssignDangerousArgumentToTemp(ENode *enode) { - Statement *stmt; - Object *obj; - ENode *indnode; - ENode *rightnode; - - obj = create_temp_object(enode->rtype); - indnode = IRO_NewENode(EINDIRECT); - indnode->data.monadic = create_objectrefnode(obj); - - if (!IS_TYPE_VOID(enode->rtype)) - indnode->rtype = enode->rtype; - else - CError_FATAL(627); - - rightnode = IRO_NewENode(enode->type); - memcpy(rightnode, enode, sizeof(ENode)); - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_EXPRESSION; - stmt->expr = IRO_NewENode(EASS); - stmt->expr->data.diadic.left = indnode; - stmt->expr->data.diadic.right = rightnode; - stmt->expr->rtype = enode->rtype; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; - - enode->type = EINDIRECT; - enode->data.monadic = create_objectrefnode(obj); -} - -static void CreateTempAssignmentToZero(ENode *enode, Object **objptr) { - Statement *stmt; - ENode *indnode; - ENode *rightnode; - - *objptr = create_temp_object(enode->rtype); - indnode = IRO_NewENode(EINDIRECT); - indnode->data.monadic = create_objectrefnode(*objptr); - if (!IS_TYPE_VOID(enode->rtype)) - indnode->rtype = enode->rtype; - else - CError_FATAL(678); - - rightnode = IRO_NewENode(EINTCONST); - rightnode->data.intval = cint64_zero; - rightnode->rtype = enode->rtype; - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_EXPRESSION; - stmt->expr = IRO_NewENode(EASS); - stmt->expr->data.diadic.left = indnode; - stmt->expr->data.diadic.right = rightnode; - stmt->expr->rtype = enode->rtype; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; -} - -static void CreateTempAssignmentToOne(ENode *enode, Object **objptr) { - Statement *stmt; - ENode *indnode; - ENode *rightnode; - - *objptr = create_temp_object(enode->rtype); - indnode = IRO_NewENode(EINDIRECT); - indnode->data.monadic = create_objectrefnode(*objptr); - if (!IS_TYPE_VOID(enode->rtype)) - indnode->rtype = enode->rtype; - else - CError_FATAL(720); - - rightnode = IRO_NewENode(EINTCONST); - rightnode->data.intval = cint64_one; - rightnode->rtype = enode->rtype; - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_EXPRESSION; - stmt->expr = IRO_NewENode(EASS); - stmt->expr->data.diadic.left = indnode; - stmt->expr->data.diadic.right = rightnode; - stmt->expr->rtype = enode->rtype; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; -} - -static void GenerateCondExpression(ENode *enode, CLabel **label) { - Statement *stmt; - - *label = IRO_NewLabel(); - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_IFNGOTO; - stmt->expr = enode->data.cond.cond; - stmt->label = *label; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; -} - -static void GenerateGoToStmt(ENode *enode, CLabel **label) { - Statement *stmt; - - *label = IRO_NewLabel(); - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_GOTO; - stmt->label = *label; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; -} - -static void PutTempOnNullCheckList(ENode *expr, Object *obj) { - NullCheckListNode *n = lalloc(sizeof(NullCheckListNode)); - n->precompid = expr->data.nullcheck.precompid; - n->tempobj = obj; - n->next = NULL; - if (NullCheckList) { - n->next = NullCheckList; - NullCheckList = n; - } else { - NullCheckList = n; - } -} - -static Object *GetTempFromtheList(ENode *expr) { - NullCheckListNode *n; - - for (n = NullCheckList; n; n = n->next) { - if (n->precompid == expr->data.precompid) - break; - } - - CError_ASSERT(839, n); - return n->tempobj; -} - -static void GenerateNullcheckExprTempAssignment(ENode *enode, Object **objptr) { - Statement *stmt; - ENode *indnode; - - if (!IS_TYPE_VOID(enode->rtype)) - *objptr = create_temp_object(enode->rtype); - else - *objptr = create_temp_object(enode->data.nullcheck.nullcheckexpr->rtype); - - PutTempOnNullCheckList(enode, *objptr); - - indnode = IRO_NewENode(EINDIRECT); - indnode->data.monadic = create_objectrefnode(*objptr); - if (!IS_TYPE_VOID(enode->rtype)) - indnode->rtype = enode->rtype; - else - indnode->rtype = enode->data.nullcheck.nullcheckexpr->rtype; - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_EXPRESSION; - stmt->expr = IRO_NewENode(EASS); - stmt->expr->data.diadic.left = indnode; - stmt->expr->data.diadic.right = enode->data.nullcheck.nullcheckexpr; - if (!IS_TYPE_VOID(enode->rtype)) - stmt->expr->rtype = enode->rtype; - else - stmt->expr->rtype = enode->data.nullcheck.nullcheckexpr->rtype; - - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; -} - -static void GenerateExpr1TempAssignment(ENode *enode, Object **objptr) { - Statement *stmt; - ENode *indnode; - - if (!IS_TYPE_VOID(enode->rtype)) { - *objptr = create_temp_object(enode->rtype); - indnode = IRO_NewENode(EINDIRECT); - indnode->data.monadic = create_objectrefnode(*objptr); - indnode->rtype = enode->rtype; - CError_ASSERT(905, !IS_TYPE_VOID(enode->rtype)); - } - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_EXPRESSION; - if (!IS_TYPE_VOID(enode->rtype)) { - stmt->expr = IRO_NewENode(EASS); - stmt->expr->data.diadic.left = indnode; - stmt->expr->data.diadic.right = enode->data.cond.expr1; - stmt->expr->rtype = enode->rtype; - } else { - stmt->expr = enode->data.cond.expr1; - } - - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; -} - -static void GenerateExpr2TempAssignment(ENode *enode, Object **objptr) { - Statement *stmt; - ENode *indnode; - - if (!IS_TYPE_VOID(enode->rtype)) { - indnode = IRO_NewENode(EINDIRECT); - indnode->data.monadic = create_objectrefnode(*objptr); - indnode->rtype = enode->rtype; - CError_ASSERT(953, !IS_TYPE_VOID(enode->rtype)); - } - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_EXPRESSION; - if (!IS_TYPE_VOID(enode->rtype)) { - stmt->expr = IRO_NewENode(EASS); - stmt->expr->data.diadic.left = indnode; - stmt->expr->data.diadic.right = enode->data.cond.expr2; - stmt->expr->rtype = enode->rtype; - } else { - stmt->expr = enode->data.cond.expr2; - } - - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; -} - -static void GenerateForceLoadTempAssignment(ENode *enode, Object **objptr) { - Statement *stmt; - ENode *indnode; - - if (!IS_TYPE_VOID(enode->rtype)) { - *objptr = create_temp_object(enode->rtype); - indnode = IRO_NewENode(EINDIRECT); - indnode->data.monadic = create_objectrefnode(*objptr); - indnode->rtype = enode->rtype; - CError_ASSERT(1003, !IS_TYPE_VOID(enode->rtype)); - } - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_EXPRESSION; - if (!IS_TYPE_VOID(enode->rtype)) { - stmt->expr = IRO_NewENode(EASS); - stmt->expr->data.diadic.left = indnode; - stmt->expr->data.diadic.right = enode->data.monadic; - stmt->expr->rtype = enode->rtype; - } else { - stmt->expr = enode->data.monadic; - } - - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; -} - -static void GenerateLabel(CLabel **labelptr) { - Statement *stmt; - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_LABEL; - stmt->label = *labelptr; - stmt->label->stmt = stmt; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; -} - -static void GenerateIfNotTemp(ENode *enode, Object **objptr, CLabel **labelptr) { - Statement *stmt; - ENode *indnode; - - indnode = IRO_NewENode(EINDIRECT); - indnode->data.monadic = create_objectrefnode(*objptr); - if (!IS_TYPE_VOID(enode->rtype)) - indnode->rtype = enode->rtype; - else - indnode->rtype = enode->data.monadic->rtype; - - *labelptr = IRO_NewLabel(); - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_IFNGOTO; - stmt->expr = indnode; - stmt->label = *labelptr; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; -} - -static void GenerateNullcheckCondExpr(ENode *enode, Object **objptr) { - Statement *stmt; - ENode *indnode; - - indnode = IRO_NewENode(EINDIRECT); - indnode->data.monadic = create_objectrefnode(*objptr); - if (!IS_TYPE_VOID(enode->rtype)) - indnode->rtype = enode->rtype; - else - indnode->rtype = enode->data.nullcheck.nullcheckexpr->rtype; - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_EXPRESSION; - stmt->expr = IRO_NewENode(EASS); - stmt->expr->data.diadic.left = indnode; - stmt->expr->data.diadic.right = enode->data.nullcheck.condexpr; - if (!IS_TYPE_VOID(enode->rtype)) - stmt->expr->rtype = enode->rtype; - else - stmt->expr->rtype = enode->data.nullcheck.nullcheckexpr->rtype; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; -} - -static void TransformLogicalAndLHS(ENode *enode, Object **objptr, CLabel **labelptr) { - Statement *stmt; - - *labelptr = IRO_NewLabel(); - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_IFNGOTO; - stmt->expr = enode->data.diadic.left; - stmt->label = *labelptr; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; -} - -static void TransformLogicalAndRHS(ENode *enode, Object **objptr, CLabel **labelptr) { - Statement *stmt; - ENode *indnode; - ENode *rightnode; - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_IFNGOTO; - stmt->expr = enode->data.diadic.right; - stmt->label = *labelptr; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; - - indnode = IRO_NewENode(EINDIRECT); - indnode->data.monadic = create_objectrefnode(*objptr); - if (!IS_TYPE_VOID(enode->rtype)) - indnode->rtype = enode->rtype; - else - CError_FATAL(1225); - - rightnode = IRO_NewENode(EINTCONST); - rightnode->data.intval = cint64_one; - rightnode->rtype = enode->rtype; - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_EXPRESSION; - stmt->expr = IRO_NewENode(EASS); - stmt->expr->data.diadic.left = indnode; - stmt->expr->data.diadic.right = rightnode; - stmt->expr->rtype = enode->rtype; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_LABEL; - stmt->label = *labelptr; - stmt->label->stmt = stmt; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; - - enode->type = EINDIRECT; - enode->data.monadic = create_objectrefnode(*objptr); - CError_ASSERT(1276, !IS_TYPE_VOID(enode->rtype)); -} - -static void TransformLogicalOrLHS(ENode *enode, Object **objptr, CLabel **labelptr) { - Statement *stmt; - - *labelptr = IRO_NewLabel(); - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_IFGOTO; - stmt->expr = enode->data.diadic.left; - stmt->label = *labelptr; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; -} - -static void TransformLogicalOrRHS(ENode *enode, Object **objptr, CLabel **labelptr) { - Statement *stmt; - ENode *indnode; - ENode *rightnode; - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_IFGOTO; - stmt->expr = enode->data.diadic.right; - stmt->label = *labelptr; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; - - indnode = IRO_NewENode(EINDIRECT); - indnode->data.monadic = create_objectrefnode(*objptr); - if (!IS_TYPE_VOID(enode->rtype)) - indnode->rtype = enode->rtype; - else - CError_FATAL(1354); - - rightnode = IRO_NewENode(EINTCONST); - rightnode->data.intval = cint64_zero; - rightnode->rtype = enode->rtype; - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_EXPRESSION; - stmt->expr = IRO_NewENode(EASS); - stmt->expr->data.diadic.left = indnode; - stmt->expr->data.diadic.right = rightnode; - stmt->expr->rtype = enode->rtype; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; - - stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = ST_LABEL; - stmt->label = *labelptr; - stmt->label->stmt = stmt; - stmt->dobjstack = CurrStmt->dobjstack; - stmt->sourceoffset = CurrStmt->sourceoffset; - stmt->sourcefilepath = CurrStmt->sourcefilepath; - stmt->value = CurrStmt->value; - stmt->flags = CurrStmt->flags; - - if (PrevStmt) { - stmt->next = PrevStmt->next; - PrevStmt->next = stmt; - } else { - stmt->next = NULL; - } - PrevStmt = stmt; - - enode->type = EINDIRECT; - enode->data.monadic = create_objectrefnode(*objptr); - CError_ASSERT(1405, !IS_TYPE_VOID(enode->rtype)); -} - -static void LinearizeExpr1(ENode *a, ENode *b, Boolean flag, Boolean flag2) { - switch (a->type) { - ENODE_CASE_MONADIC: - LinearizeExpr1(a->data.monadic, a, 0, 0); - if (a->type == EFORCELOAD) { - Object *obj; - GenerateForceLoadTempAssignment(a, &obj); - a->type = EINDIRECT; - a->data.monadic = create_objectrefnode(obj); - CError_ASSERT(1428, !IS_TYPE_VOID(a->rtype)); - } - break; - ENODE_CASE_DIADIC_1: - case ECOMMA: - case EPMODULO: - case EROTL: - case EROTR: - case EBTST: - if (a->type == ECOMMA) { - LinearizeExpr1(a->data.diadic.left, a, 1, 0); - MakeLeftChildAsAssignment(a); - LinearizeExpr1(a->data.diadic.right, a, 0, 0); - AssignCommaRToTemp(a, flag); - } else if (a->data.diadic.right->cost >= a->data.diadic.left->cost) { - LinearizeExpr1(a->data.diadic.right, a, 0, 0); - LinearizeExpr1(a->data.diadic.left, a, 0, 0); - } else { - LinearizeExpr1(a->data.diadic.left, a, 0, 0); - LinearizeExpr1(a->data.diadic.right, a, 0, 0); - } - break; - ENODE_CASE_ASSIGN: - LinearizeExpr1(a->data.diadic.right, a, 0, 0); - LinearizeExpr1(a->data.diadic.left, a, 0, 0); - break; - case ELAND: - case ELOR: - if (a->type == ELAND) { - CLabel *label; - Object *obj; - CreateTempAssignmentToZero(a, &obj); - LinearizeExpr1(a->data.diadic.left, a, 0, 0); - TransformLogicalAndLHS(a, &obj, &label); - LinearizeExpr1(a->data.diadic.right, a, 0, 0); - TransformLogicalAndRHS(a, &obj, &label); - } else if (a->type == ELOR) { - CLabel *label; - Object *obj; - CreateTempAssignmentToOne(a, &obj); - LinearizeExpr1(a->data.diadic.left, a, 0, 0); - TransformLogicalOrLHS(a, &obj, &label); - LinearizeExpr1(a->data.diadic.right, a, 0, 0); - TransformLogicalOrRHS(a, &obj, &label); - } - break; - case ECOND: { - CLabel *label1, *label2; - Object *obj; - LinearizeExpr1(a->data.cond.cond, a, 0, 0); - GenerateCondExpression(a, &label1); - LinearizeExpr1(a->data.cond.expr1, a, 0, 0); - GenerateExpr1TempAssignment(a, &obj); - GenerateGoToStmt(a, &label2); - GenerateLabel(&label1); - LinearizeExpr1(a->data.cond.expr2, a, 0, 0); - GenerateExpr2TempAssignment(a, &obj); - GenerateLabel(&label2); - if (!IS_TYPE_VOID(a->rtype)) { - a->type = EINDIRECT; - a->data.monadic = create_objectrefnode(obj); - CError_ASSERT(1596, !IS_TYPE_VOID(a->rtype)); - } else { - a->type = EINTCONST; - a->data.intval = cint64_zero; - } - break; - } - case EPRECOMP: { - Object *temp = GetTempFromtheList(a); - a->type = EINDIRECT; - a->data.monadic = create_objectrefnode(temp); - CError_ASSERT(1614, !IS_TYPE_VOID(a->rtype)); - break; - } - case ENULLCHECK: { - CLabel *label; - Object *obj; - LinearizeExpr1(a->data.nullcheck.nullcheckexpr, a, 0, 0); - GenerateNullcheckExprTempAssignment(a, &obj); - GenerateIfNotTemp(a, &obj, &label); - LinearizeExpr1(a->data.nullcheck.condexpr, a, 0, 0); - GenerateNullcheckCondExpr(a, &obj); - GenerateLabel(&label); - if (!IS_TYPE_VOID(a->rtype)) { - a->type = EINDIRECT; - a->data.monadic = create_objectrefnode(obj); - CError_ASSERT(1639, !IS_TYPE_VOID(a->rtype)); - } else { - a->type = EINTCONST; - a->data.intval = cint64_zero; - } - break; - } - case EFUNCCALL: - case EFUNCCALLP: { - SInt32 count; - SInt32 i; - ENodeList *list; - ENode **arr; - SInt16 *arr2; - - IRO_IsLeafFunction = 0; - - list = a->data.funccall.args; - count = 0; - while (list) { - list = list->next; - count++; - } - - if (count) { - arr = oalloc(sizeof(ENode *) * count); - list = a->data.funccall.args; - count = 0; - while (list) { - arr[count] = list->node; - list = list->next; - count++; - } - - arr2 = oalloc(sizeof(SInt16) * count); - for (i = 0; i < count; i++) - arr2[i] = count - i - 1; - - for (i = 0; i < count; i++) - LinearizeExpr1(arr[arr2[i]], a, 0, 0); - } - - LinearizeExpr1(a->data.funccall.funcref, a, 0, 0); - break; - } - - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case ESETCONST: - case EVECTOR128CONST: - break; - - default: - CError_FATAL(1723); - } -} - -static IROLinear *LinearizeExpr(ENode *enode) { - IROLinear *linear = NULL; - - switch (enode->type) { - ENODE_CASE_MONADIC: - linear = IRO_NewLinear(IROLinearOp1Arg); - linear->u.monadic = LinearizeExpr(enode->data.monadic); - linear->nodetype = enode->type; - linear->rtype = enode->rtype; - linear->nodeflags = enode->flags; - if (IRO_IsAssignOp[linear->nodetype]) - MarkAssigned(linear->u.monadic, 1); - if (linear->nodetype == EINDIRECT) { - MarkSubs1(linear->u.monadic); - linear->u.monadic->flags |= IROLF_Immind | IROLF_Ind; - if (IS_LINEAR_DIADIC(linear->u.monadic, EADD)) - MarkSubscript(linear->u.monadic); - } - break; - ENODE_CASE_DIADIC_1: - case ECOMMA: - case EPMODULO: - case EROTL: - case EROTR: - case EBTST: - linear = IRO_NewLinear(IROLinearOp2Arg); - linear->nodeflags = enode->flags; - if (!ENODE_IS(enode, ECOMMA) && enode->data.diadic.right->cost >= enode->data.diadic.left->cost) { - linear->u.diadic.right = LinearizeExpr(enode->data.diadic.right); - linear->u.diadic.left = LinearizeExpr(enode->data.diadic.left); - linear->flags |= IROLF_8000; - } else { - linear->u.diadic.left = LinearizeExpr(enode->data.diadic.left); - linear->u.diadic.right = LinearizeExpr(enode->data.diadic.right); - } - linear->nodetype = enode->type; - linear->rtype = enode->rtype; - if (IRO_IsAssignOp[linear->nodetype]) - MarkAssigned(linear->u.diadic.left, IRO_IsModifyOp[linear->nodetype]); - break; - ENODE_CASE_ASSIGN: - linear = IRO_NewLinear(IROLinearOp2Arg); - linear->nodeflags = enode->flags; - linear->u.diadic.right = LinearizeExpr(enode->data.diadic.right); - linear->u.diadic.left = LinearizeExpr(enode->data.diadic.left); - linear->flags |= IROLF_8000; - linear->nodetype = enode->type; - linear->rtype = enode->rtype; - MarkAssigned(linear->u.diadic.left, IRO_IsModifyOp[linear->nodetype]); - break; - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case EVECTOR128CONST: - linear = IRO_NewLinear(IROLinearOperand); - linear->nodeflags = enode->flags; - linear->u.node = enode; - linear->rtype = enode->rtype; - break; - case EFUNCCALL: - case EFUNCCALLP: { - SInt32 count; - SInt32 i; - ENodeList *list; - ENode **arr; - SInt16 *arr2; - - linear = IRO_NewLinear(IROLinearFunccall); - linear->nodeflags = enode->flags; - linear->u.funccall.ispascal = enode->type == EFUNCCALLP; - - list = enode->data.funccall.args; - count = 0; - while (list) { - list = list->next; - count++; - } - - arr = NULL; - if (count) { - arr = oalloc(sizeof(ENode *) * count); - list = enode->data.funccall.args; - count = 0; - while (list) { - arr[count] = list->node; - list = list->next; - count++; - } - - arr2 = oalloc(sizeof(SInt16) * count); - for (i = 0; i < count; i++) - arr2[i] = count - i - 1; - - for (i = 0; i < count; i++) { - arr[arr2[i]] = (ENode *) LinearizeExpr(arr[arr2[i]]); - MarkArgs((IROLinear *) arr[arr2[i]]); - } - } - - linear->u.funccall.argCount = count; - linear->u.funccall.args = (IROLinear **) arr; - linear->u.funccall.linear8 = LinearizeExpr(enode->data.funccall.funcref); - linear->u.funccall.functype = enode->data.funccall.functype; - linear->rtype = enode->rtype; - break; - } - default: - CError_FATAL(1943); - } - - if (linear) - LinkLinear(linear); - return linear; -} - -void IRO_PreLinearize(Statement *stmt) { - IRO_FirstLinear = IRO_LastLinear = NULL; - IRO_NumLinear = 0; - CurrStmt = PrevStmt = NULL; - - while (stmt) { - CurStat = stmt; - CurrStmt = stmt; - NullCheckList = NULL; - - switch (stmt->type) { - case ST_NOP: - case ST_LABEL: - case ST_GOTO: - break; - case ST_OVF: - CError_FATAL(1989); - case ST_EXPRESSION: - LinearizeExpr1(stmt->expr, NULL, 0, 0); - break; - case ST_SWITCH: - LinearizeExpr1(stmt->expr, NULL, 0, 0); - break; - case ST_IFGOTO: - LinearizeExpr1(stmt->expr, NULL, 0, 0); - break; - case ST_IFNGOTO: - LinearizeExpr1(stmt->expr, NULL, 0, 0); - break; - case ST_RETURN: - if (stmt->expr) - LinearizeExpr1(stmt->expr, NULL, 0, 0); - break; - case ST_BEGINCATCH: - LinearizeExpr1(stmt->expr, NULL, 0, 0); - break; - case ST_ENDCATCH: - LinearizeExpr1(stmt->expr, NULL, 0, 0); - break; - case ST_ENDCATCHDTOR: - LinearizeExpr1(stmt->expr, NULL, 0, 0); - break; - - case ST_EXIT: - case ST_ENTRY: - case ST_ASM: - break; - - default: - CError_FATAL(2038); - } - - PrevStmt = stmt; - stmt = stmt->next; - } - - IRO_CheckForUserBreak(); -} - -static void MarkAllSubExprs(IROLinear *linear) { - IROLinear *scan; - int i; - - for (scan = linear; scan; scan = scan->next) - scan->flags &= ~IROLF_Reffed; - - for (scan = linear; scan; scan = scan->next) - MarkSubExpr(scan); -} - -void IRO_Linearize(Statement *stmt) { - IROLinear *linear; - - IRO_FirstLinear = IRO_LastLinear = NULL; - IRO_NumLinear = 0; - - while (stmt) { - CurStat = stmt; - linear = NULL; - - switch (stmt->type) { - case ST_NOP: - linear = IRO_NewLinear(IROLinearNop); - break; - case ST_LABEL: - linear = IRO_NewLinear(IROLinearLabel); - linear->u.label.label = stmt->label; - linear->flags |= IROLF_1; - break; - case ST_GOTO: - linear = IRO_NewLinear(IROLinearGoto); - linear->u.label.label = stmt->label; - break; - case ST_EXPRESSION: - LinearizeExpr(stmt->expr); - break; - case ST_SWITCH: - linear = IRO_NewLinear(IROLinearSwitch); - linear->u.swtch.x4 = LinearizeExpr(stmt->expr); - linear->u.swtch.info = (SwitchInfo *) stmt->label; - break; - case ST_IFGOTO: - linear = IRO_NewLinear(IROLinearIf); - linear->u.label.x4 = LinearizeExpr(stmt->expr); - linear->u.label.label = stmt->label; - break; - case ST_IFNGOTO: - linear = IRO_NewLinear(IROLinearIfNot); - linear->u.label.x4 = LinearizeExpr(stmt->expr); - linear->u.label.label = stmt->label; - break; - case ST_RETURN: - IRO_FunctionHasReturn = 1; - linear = IRO_NewLinear(IROLinearReturn); - if (stmt->expr) - linear->u.monadic = LinearizeExpr(stmt->expr); - else - linear->u.monadic = NULL; - break; - case ST_OVF: - CError_FATAL(2143); - break; - case ST_EXIT: - linear = IRO_NewLinear(IROLinearExit); - linear->u.label.label = stmt->label; - break; - case ST_ENTRY: - linear = IRO_NewLinear(IROLinearEntry); - linear->u.label.label = stmt->label; - linear->flags |= IROLF_1; - break; - case ST_BEGINCATCH: - linear = IRO_NewLinear(IROLinearBeginCatch); - linear->u.ctch.linear = LinearizeExpr(stmt->expr); - linear->u.ctch.x4 = 0; - linear->u.ctch.x8 = 0; - break; - case ST_ENDCATCH: - linear = IRO_NewLinear(IROLinearEndCatch); - linear->u.monadic = LinearizeExpr(stmt->expr); - break; - case ST_ENDCATCHDTOR: - linear = IRO_NewLinear(IROLinearEndCatchDtor); - linear->u.monadic = LinearizeExpr(stmt->expr); - break; - case ST_ASM: - linear = IRO_NewLinear(IROLinearAsm); - linear->u.asm_stmt = stmt; - if (copts.optimizewithasm) { - IAEffects effects; - CodeGen_GetAsmEffects(stmt, &effects); - if (effects.x0 || effects.x3) - DisableDueToAsm = 1; - } else { - DisableDueToAsm = 1; - } - break; - default: - CError_FATAL(2194); - } - - if (linear) - LinkLinear(linear); - stmt = stmt->next; - } - - linear = IRO_NewLinear(IROLinearEnd); - linear->flags |= IROLF_1; - LinkLinear(linear); - - MarkAllSubExprs(IRO_FirstLinear); - IRO_CheckForUserBreak(); -} - -static Statement *NewStatement(IROLinear *linear, StatementType sttype) { - Statement *stmt = lalloc(sizeof(Statement)); - memset(stmt, 0, sizeof(Statement)); - stmt->type = sttype; - stmt->value = 1; - if (linear->stmt) { - stmt->dobjstack = linear->stmt->dobjstack; - stmt->sourceoffset = linear->stmt->sourceoffset; - stmt->sourcefilepath = linear->stmt->sourcefilepath; - stmt->value = linear->stmt->value; - stmt->flags = linear->stmt->flags; - } else { - stmt->sourceoffset = -1; - stmt->sourcefilepath = NULL; - } - return stmt; -} - -ENode *IRO_NewENode(ENodeType nodetype) { - ENode *enode = lalloc(sizeof(ENode)); - memset(enode, 0, sizeof(ENode)); - enode->type = nodetype; - return enode; -} - -static ENode *BuildExpr(IROLinear *linear) { - ENode *enode; - - switch (linear->type) { - case IROLinearOperand: - enode = IRO_NewENode(linear->u.node->type); - enode->flags = linear->nodeflags; - *enode = *linear->u.node; - break; - case IROLinearOp1Arg: - enode = IRO_NewENode(linear->nodetype); - enode->flags = linear->nodeflags; - enode->data.monadic = BuildExpr(linear->u.monadic); - enode->rtype = linear->rtype; - enode->cost = enode->data.monadic->cost; - if (!enode->cost) - enode->cost = 1; - break; - case IROLinearOp2Arg: - enode = IRO_NewENode(linear->nodetype); - enode->flags = linear->nodeflags; - enode->data.diadic.left = BuildExpr(linear->u.diadic.left); - enode->data.diadic.right = BuildExpr(linear->u.diadic.right); - - enode->cost = enode->data.diadic.left->cost; - if (enode->data.diadic.right->cost > enode->cost) - enode->cost = enode->data.diadic.right->cost; - else if (enode->data.diadic.right->cost == enode->cost) - enode->cost += 1; - - if (ENODE_IS4(enode, ESHL, ESHR, EDIV, EMODULO)) - enode->cost += 2; - if (enode->cost > 200) - enode->cost = 200; - - enode->rtype = linear->rtype; - break; - case IROLinearOp3Arg: - enode = IRO_NewENode(linear->nodetype); - enode->flags = linear->nodeflags; - enode->data.cond.cond = BuildExpr(linear->u.args3.a); - enode->data.cond.expr1 = BuildExpr(linear->u.args3.b); - enode->data.cond.expr2 = BuildExpr(linear->u.args3.c); - enode->rtype = linear->rtype; - - enode->cost = enode->data.cond.cond->cost; - if (enode->data.cond.expr1->cost > enode->cost) - enode->cost = enode->data.cond.expr1->cost; - if (enode->data.cond.expr2->cost > enode->cost) - enode->cost = enode->data.cond.expr2->cost; - enode->cost += 1; - - if (enode->cost > 200) - enode->cost = 200; - - break; - - case IROLinearFunccall: { - int i; - enode = IRO_NewENode(linear->u.funccall.ispascal ? EFUNCCALLP : EFUNCCALL); - enode->flags = linear->nodeflags; - enode->data.funccall.funcref = BuildExpr(linear->u.funccall.linear8); - enode->data.funccall.functype = linear->u.funccall.functype; - enode->data.funccall.args = NULL; - enode->cost = 200; - for (i = linear->u.funccall.argCount - 1; i >= 0; i--) { - ENodeList *list = lalloc(sizeof(ENodeList)); - list->node = BuildExpr(linear->u.funccall.args[i]); - list->next = enode->data.funccall.args; - enode->data.funccall.args = list; - } - enode->rtype = linear->rtype; - break; - } - - default: - IRO_Dump("Oh, oh, bad expression type in BuildExpr at: %d\n", linear->index); - CError_FATAL(2390); - } - - enode->pointsTo = linear->pointsToFunction; - return enode; -} - -Statement *IRO_Delinearize(IRONode *node, IROLinear *linear) { - IROLinear *scanlin; - Statement *firstStmt; - Statement *lastStmt; - IRONode *scan; - Statement *stmt; - IRONode mynode; - - firstStmt = lastStmt = NULL; - - if (node) { - scan = node; - MarkAllSubExprs(IRO_FirstLinear); - } else { - memset(&mynode, 0, sizeof(IRONode)); - mynode.first = linear; - scan = &mynode; - MarkAllSubExprs(linear); - } - - while (scan) { - for (scanlin = scan->first; scanlin; scanlin = scanlin->next) { - stmt = NULL; - if (!(scanlin->flags & IROLF_Reffed)) { - switch (scanlin->type) { - case IROLinearNop: - if (scan == node) - stmt = NewStatement(scanlin, ST_NOP); - else - stmt = NULL; - break; - case IROLinearOperand: - case IROLinearOp1Arg: - case IROLinearOp2Arg: - case IROLinearOp3Arg: - case IROLinearFunccall: - stmt = NewStatement(scanlin, ST_EXPRESSION); - stmt->expr = BuildExpr(scanlin); - break; - case IROLinearGoto: - stmt = NewStatement(scanlin, ST_GOTO); - stmt->label = scanlin->u.label.label; - break; - case IROLinearExit: - stmt = NewStatement(scanlin, ST_EXIT); - stmt->label = scanlin->u.label.label; - break; - case IROLinearIf: - case IROLinearIfNot: - stmt = NewStatement(scanlin, (scanlin->type == IROLinearIf) ? ST_IFGOTO : ST_IFNGOTO); - stmt->label = scanlin->u.label.label; - stmt->expr = BuildExpr(scanlin->u.label.x4); - break; - case IROLinearReturn: - stmt = NewStatement(scanlin, ST_RETURN); - if (scanlin->u.monadic) - stmt->expr = BuildExpr(scanlin->u.monadic); - break; - case IROLinearLabel: - stmt = NewStatement(scanlin, ST_LABEL); - stmt->label = scanlin->u.label.label; - stmt->label->stmt = stmt; - break; - case IROLinearEntry: - stmt = NewStatement(scanlin, ST_ENTRY); - stmt->label = scanlin->u.label.label; - stmt->label->stmt = stmt; - break; - case IROLinearSwitch: - stmt = NewStatement(scanlin, ST_SWITCH); - stmt->expr = BuildExpr(scanlin->u.swtch.x4); - stmt->label = (CLabel *) scanlin->u.swtch.info; - break; - case IROLinearBeginCatch: - stmt = NewStatement(scanlin, ST_BEGINCATCH); - stmt->expr = BuildExpr(scanlin->u.ctch.linear); - break; - case IROLinearEndCatch: - stmt = NewStatement(scanlin, ST_ENDCATCH); - stmt->expr = BuildExpr(scanlin->u.monadic); - break; - case IROLinearEndCatchDtor: - stmt = NewStatement(scanlin, ST_ENDCATCHDTOR); - stmt->expr = BuildExpr(scanlin->u.monadic); - break; - case IROLinearAsm: - stmt = scanlin->u.asm_stmt; - break; - case IROLinearEnd: - stmt = NULL; - break; - default: - CError_FATAL(2685); - } - - if (stmt) { - if (LoopOptimizerRun) { - SInt32 i; - SInt32 value = 1; - for (i = 0; i < scan->loopdepth; i++) { - value = (value < 4096) ? (value * 8) : (value + 1); - } - stmt->value = value; - } - if (firstStmt) - lastStmt->next = stmt; - else - firstStmt = stmt; - lastStmt = stmt; - } - } - if (scanlin == scan->last) - break; - } - scan = scan->nextnode; - } - - return firstStmt; -} - -void IRO_RenumberInts(void) { - IROLinear *linear = IRO_FirstLinear; - IRO_NumLinear = 0; - while (linear) { - linear->index = IRO_NumLinear++; - linear = linear->next; - } -} - -static void TravExprToUpdateFlags(IROLinear *linear) { - int i; - - linear->flags &= ~(IROLF_Assigned | IROLF_8 | IROLF_Used | IROLF_Ind | IROLF_Subs | IROLF_LoopInvariant | IROLF_Ris | IROLF_Immind | IROLF_CouldError); - switch (linear->type) { - case IROLinearNop: - case IROLinearOperand: - break; - case IROLinearOp1Arg: - TravExprToUpdateFlags(linear->u.monadic); - if (IRO_IsAssignOp[linear->nodetype]) - MarkAssigned(linear->u.monadic, 1); - if (linear->nodetype == EINDIRECT) { - MarkSubs1(linear->u.monadic); - linear->u.monadic->flags |= IROLF_Immind | IROLF_Ind; - if (IS_LINEAR_DIADIC(linear->u.monadic, EADD)) - MarkSubscript(linear->u.monadic); - } - break; - case IROLinearOp2Arg: - TravExprToUpdateFlags(linear->u.diadic.left); - TravExprToUpdateFlags(linear->u.diadic.right); - if (IRO_IsAssignOp[linear->nodetype]) - MarkAssigned(linear->u.diadic.left, IRO_IsModifyOp[linear->nodetype]); - break; - case IROLinearOp3Arg: - TravExprToUpdateFlags(linear->u.args3.a); - TravExprToUpdateFlags(linear->u.args3.b); - TravExprToUpdateFlags(linear->u.args3.c); - break; - case IROLinearFunccall: - TravExprToUpdateFlags(linear->u.funccall.linear8); - for (i = linear->u.funccall.argCount - 1; i >= 0; i--) - TravExprToUpdateFlags(linear->u.funccall.args[i]); - break; - default: - IRO_Dump("Oh, oh, bad expression type in TravExprToUpdateFlags at: %d\n", linear->index); - CError_FATAL(2853); - } -} - -void IRO_UpdateFlagsOnInts(void) { - IROLinear *linear; - IRONode *node; - - MarkAllSubExprs(IRO_FirstLinear); - - for (node = IRO_FirstNode; node; node = node->nextnode) { - for (linear = node->first; linear; linear = linear->next) { - if (!(linear->flags & IROLF_Reffed)) { - switch (linear->type) { - case IROLinearOperand: - case IROLinearOp1Arg: - case IROLinearOp2Arg: - case IROLinearOp3Arg: - case IROLinearFunccall: - TravExprToUpdateFlags(linear); - break; - case IROLinearIf: - case IROLinearIfNot: - TravExprToUpdateFlags(linear->u.label.x4); - break; - case IROLinearReturn: - if (linear->u.monadic) - TravExprToUpdateFlags(linear->u.monadic); - break; - case IROLinearSwitch: - TravExprToUpdateFlags(linear->u.swtch.x4); - break; - case IROLinearBeginCatch: - TravExprToUpdateFlags(linear->u.ctch.linear); - break; - case IROLinearEndCatch: - TravExprToUpdateFlags(linear->u.monadic); - break; - case IROLinearEndCatchDtor: - TravExprToUpdateFlags(linear->u.monadic); - break; - case IROLinearNop: - case IROLinearGoto: - case IROLinearLabel: - case IROLinearEntry: - case IROLinearExit: - case IROLinearAsm: - case IROLinearEnd: - break; - default: - CError_FATAL(2931); - } - } - if (linear == node->last) - break; - } - } -} - -void IRO_SaveLinearIR(IROLinearIRSave *save) { - save->firstLinear = IRO_FirstLinear; - save->lastLinear = IRO_LastLinear; - save->numLinear = IRO_NumLinear; - save->curStat = CurStat; - save->disableDueToAsm = DisableDueToAsm; - save->isLeafFunction = IRO_IsLeafFunction; - save->functionHasReturn = IRO_FunctionHasReturn; - save->nullCheckList = NullCheckList; - save->currStmt = CurrStmt; - save->prevStmt = PrevStmt; -} - -void IRO_RestoreLinearIR(IROLinearIRSave *save) { - IRO_FirstLinear = save->firstLinear; - IRO_LastLinear = save->lastLinear; - IRO_NumLinear = save->numLinear; - CurStat = save->curStat; - DisableDueToAsm = save->disableDueToAsm; - IRO_IsLeafFunction = save->isLeafFunction; - IRO_FunctionHasReturn = save->functionHasReturn; - NullCheckList = save->nullCheckList; - CurrStmt = save->currStmt; - PrevStmt = save->prevStmt; -} - diff --git a/compiler_and_linker/unsorted/IroLoop.c b/compiler_and_linker/unsorted/IroLoop.c deleted file mode 100644 index d6ec5f0..0000000 --- a/compiler_and_linker/unsorted/IroLoop.c +++ /dev/null @@ -1,2324 +0,0 @@ -#include "compiler/IroLoop.h" -#include "compiler/IroCSE.h" -#include "compiler/IroDump.h" -#include "compiler/IroFlowgraph.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroPropagate.h" -#include "compiler/IroSubable.h" -#include "compiler/IroUtil.h" -#include "compiler/IroVars.h" -#include "compiler/CFunc.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -IRONode *LoopNode; -Boolean ConditionalHeaderAtBottom; -IROLoopInd *FirstInd; -BitVector *InLoop; -IROList IRO_InitLList; -BitVector *InLoop_Exits; -BitVector *InLoop_Tails; -UInt32 LoopExitNumber; -UInt32 LoopTailNum; -IRONode *LoopExitSuccessor; -IRONode *LoopTail; -IROLoopMemRef *IRO_LoopMemRefFirst; -IROLoopMemRef *IRO_LoopMemRefCurrent; -static IROExpr *RisList; -static BitVector *AllKills; -static Boolean KnownBounds; -static SInt32 Times; -static IROLinear *PredInt; -static IROElmList *FirstAddendLinear; -static IROElmList *LastAddendLinear; -static int NoSubableSubs; - -// forward decls -static void MyHandleLoop_Vector(IRONode *fnode); -static void MyHandleLoop_Motion(IRONode *fnode); -static void CheckAllLoopAddresses(IRONode *fnode, BitVector *bv, Boolean *resultFlag); -static void MakeLoopEntry(IROLinear *nd, IROAddrRecord *rec, Boolean mustreach1, Boolean flag2); -static void MoveInvarianceInAddressExpr(void); -static IROLinear *RearrangeInvarianceInAddressExpr(IROLinear *nd, IROList *list); -static UInt32 IsAssignmentReductionCandidate(IROLinear *nd); - -void FindMustReach(void) { - IRONode *fnode; - IRONode *fnode2; - IRONode *pred; - int i; - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - fnode->mustreach = 0; - if (Bv_IsBitSet(fnode->index, InLoop)) { - fnode->mustreach = 1; - - for (i = 0; i < LoopNode->numpred; i++) { - pred = IRO_NodeTable[LoopNode->pred[i]]; - if (Bv_IsBitSet(pred->index, InLoop) && !Bv_IsBitSet(fnode->index, pred->dom)) { - fnode->mustreach = 0; - break; - } - } - - for (fnode2 = IRO_FirstNode; fnode2; fnode2 = fnode2->nextnode) { - if (Bv_IsBitSet(fnode2->index, InLoop)) { - for (i = 0; i < fnode2->numsucc; i++) { - if (!Bv_IsBitSet(fnode2->succ[i], InLoop) && !Bv_IsBitSet(fnode->index, fnode2->dom)) { - fnode->mustreach = 0; - break; - } - } - - if (!fnode->mustreach) - break; - } - } - } - } -} - -void FindMustReach1(IRONode *checkfnode) { - IRONode *fnode; - IRONode *fnode2; - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - if (Bv_IsBitSet(fnode->index, InLoop)) { - fnode->mustreach1 = 1; - for (fnode2 = IRO_FirstNode; fnode2; fnode2 = fnode2->nextnode) { - if (Bv_IsBitSet(fnode2->index, InLoop)) { - if (Bv_IsBitSet(fnode2->index, InLoop_Tails) && !Bv_IsBitSet(fnode->index, fnode2->dom)) - fnode->mustreach1 = 0; - - if (Bv_IsBitSet(fnode2->index, InLoop_Exits) && fnode2 != checkfnode && !Bv_IsBitSet(fnode->index, fnode2->dom)) - fnode->mustreach1 = 0; - - if (!fnode->mustreach1) - break; - } - } - } - } -} - -static void IRO_FindLoopTailsAndExits(IRONode *fnode) { - IRONode *scan; - IRONode *succ; - int i; - - for (scan = IRO_FirstNode; scan; scan = scan->nextnode) { - if (Bv_IsBitSet(scan->index, InLoop)) { - for (i = 0; i < scan->numsucc; i++) { - succ = IRO_NodeTable[scan->succ[i]]; - if (succ == fnode) { - Bv_SetBit(scan->index, InLoop_Tails); - LoopTail = scan; - LoopTailNum++; - } - if (!Bv_IsBitSet(succ->index, InLoop)) { - LoopExitNumber++; - LoopExitSuccessor = succ; - Bv_SetBit(scan->index, InLoop_Exits); - } - } - } - } - - IRO_Dump("IRO_FindLoopTailsAndExits:For header %d, Loop exits and loop tails are \n", fnode->index); - IRO_DumpBits("Loop Exits: ", InLoop_Exits); - IRO_DumpBits("Loop Tails: ", InLoop_Tails); - IRO_Dump("LoopExitNum=%d: \n", LoopExitNumber); - if (LoopExitSuccessor) - IRO_Dump("LoopExitSuccessor node =%d: \n", LoopExitSuccessor->index); -} - -static int IsSafeTypcon(IROLinear *nd) { - Type *srcType; - Type *destType; - SInt32 srcSize; - SInt32 destSize; - Boolean srcUnsigned; - Boolean destUnsigned; - - srcType = nd->u.monadic->rtype; - destType = nd->rtype; - if (!IS_TYPE_INT(srcType) || !IS_TYPE_INT(destType)) - return 0; - - srcSize = srcType->size; - destSize = destType->size; - srcUnsigned = IRO_IsUnsignedType(srcType); - destUnsigned = IRO_IsUnsignedType(destType); - - if (srcUnsigned == destUnsigned && destSize >= srcSize) - return 1; - if (srcUnsigned == 1 && destUnsigned == 0 && destSize > srcSize) - return 1; - return 0; -} - -static int Reducable(IROLinear *nd, IROLinear **resultNd1, IROLinear **resultNd2, VarRecord **resultVar) { - IROLinear *indirect; - IROLinear *left; - IROLinear *right; - Boolean leftInvariant; - Boolean rightInvariant; - Boolean leftTypcon; - Boolean rightTypcon; - Object *obj; - ENode *enode; - IROLoopInd *ind; - CInt64 val64; - SInt32 val; - SInt32 div; - - leftInvariant = 0; - rightInvariant = 0; - leftTypcon = 0; - rightTypcon = 0; - - if (nd->type == IROLinearOp2Arg && nd->nodetype == EADD && (IS_TYPE_INT(nd->rtype) || IS_TYPE_POINTER_ONLY(nd->rtype))) { - left = nd->u.diadic.left; - right = nd->u.diadic.right; - if (left->type == IROLinearOp1Arg && left->nodetype == ETYPCON) { - leftTypcon = 1; - leftInvariant = (left->flags & IROLF_LoopInvariant) != 0; - left = left->u.monadic; - } - if (right->type == IROLinearOp1Arg && right->nodetype == ETYPCON) { - rightTypcon = 1; - rightInvariant = (right->flags & IROLF_LoopInvariant) != 0; - right = right->u.monadic; - } - - if (((left->flags & IROLF_LoopInvariant) || leftInvariant) && IRO_IsVariable(right)) { - if (leftInvariant || ((!(obj = IRO_IsVariable(left)) || !IRO_IsRegable(obj)) && !IRO_IsConstant(left))) { - if ( - left->type == IROLinearOp2Arg && - left->nodetype == EADD && - (obj = IRO_IsVariable(left->u.diadic.left)) && - IRO_IsRegable(obj) && - IRO_IsConstant(left->u.diadic.right) - ) - return 0; - - if (rightTypcon) { - if (!IsSafeTypcon(nd->u.diadic.right)) - return 0; - *resultNd2 = nd->u.diadic.right; - } else { - *resultNd2 = right; - } - - indirect = right; - *resultNd1 = IRO_NewLinear(IROLinearOperand); - - enode = IRO_NewENode(EINTCONST); - enode->data.intval = cint64_one; - enode->rtype = nd->u.diadic.right->rtype; - (*resultNd1)->rtype = nd->u.diadic.right->rtype; - (*resultNd1)->u.node = enode; - } else { - return 0; - } - } else if ( - ((left->flags & IROLF_LoopInvariant) || leftInvariant) && - right->type == IROLinearOp2Arg && - !rightTypcon && - (right->nodetype == EMUL || right->nodetype == ESHL) - ) { - if (IRO_IsConstant(right->u.diadic.right)) { - if (right->nodetype == ESHL) { - right->nodetype = EMUL; - right->u.diadic.right->u.node->data.intval = CInt64_Shl(cint64_one, right->u.diadic.right->u.node->data.intval); - } - if (right->u.diadic.left->type == IROLinearOp1Arg) { - if (IRO_IsVariable(right->u.diadic.left)) { - *resultNd2 = right->u.diadic.left; - indirect = right->u.diadic.left; - *resultNd1 = right->u.diadic.right; - } else if (right->u.diadic.left->nodetype == ETYPCON && IRO_IsVariable(right->u.diadic.left->u.monadic)) { - if (!IsSafeTypcon(right->u.diadic.left)) - return 0; - *resultNd2 = right->u.diadic.left; - indirect = right->u.diadic.left->u.monadic; - *resultNd1 = right->u.diadic.right; - } else { - return 0; - } - } else { - return 0; - } - } else { - return 0; - } - } else if ( - ((right->flags & IROLF_LoopInvariant) || rightInvariant) && - left->type == IROLinearOp2Arg && - !leftTypcon && - (left->nodetype == EMUL || left->nodetype == ESHL) - ) { - if (IRO_IsConstant(left->u.diadic.right)) { - if (left->nodetype == ESHL) { - left->nodetype = EMUL; - left->u.diadic.right->u.node->data.intval = CInt64_Shl(cint64_one, left->u.diadic.right->u.node->data.intval); - } - if (left->u.diadic.left->type == IROLinearOp1Arg) { - if (IRO_IsVariable(left->u.diadic.left)) { - *resultNd2 = left->u.diadic.left; - indirect = left->u.diadic.left; - *resultNd1 = left->u.diadic.right; - } else if (left->u.diadic.left->nodetype == ETYPCON && IRO_IsVariable(left->u.diadic.left->u.monadic)) { - if (!IsSafeTypcon(left->u.diadic.left)) - return 0; - *resultNd2 = left->u.diadic.left; - indirect = left->u.diadic.left->u.monadic; - *resultNd1 = left->u.diadic.right; - } else { - return 0; - } - } else { - return 0; - } - } else { - return 0; - } - } else if ( - ((right->flags & IROLF_LoopInvariant) || rightInvariant) && - IRO_IsVariable(left) - ) { - if (rightInvariant || ((!(obj = IRO_IsVariable(right)) || !IRO_IsRegable(obj)) && !IRO_IsConstant(right))) { - if ( - right->type == IROLinearOp2Arg && - right->nodetype == EADD && - (obj = IRO_IsVariable(right->u.diadic.left)) && - IRO_IsRegable(obj) && - IRO_IsConstant(right->u.diadic.right) - ) - return 0; - - if (leftTypcon) { - if (!IsSafeTypcon(nd->u.diadic.left)) - return 0; - *resultNd2 = nd->u.diadic.left; - } else { - *resultNd2 = left; - } - - indirect = left; - *resultNd1 = IRO_NewLinear(IROLinearOperand); - - enode = IRO_NewENode(EINTCONST); - enode->data.intval = cint64_one; - enode->rtype = nd->u.diadic.left->rtype; - (*resultNd1)->rtype = nd->u.diadic.left->rtype; - (*resultNd1)->u.node = enode; - } else { - return 0; - } - } else { - return 0; - } - } else if (nd->type == IROLinearOp2Arg && (nd->nodetype == EMUL || nd->nodetype == ESHL) && nd->rtype->size <= 4 && (IS_TYPE_INT(nd->rtype) || IS_TYPE_POINTER_ONLY(nd->rtype))) { - left = nd->u.diadic.left; - right = nd->u.diadic.right; - - if (IRO_IsConstant(right) && IRO_IsVariable(left)) { - *resultNd2 = left; - indirect = left; - *resultNd1 = right; - } else if (IRO_IsConstant(nd->u.diadic.right) && left->type == IROLinearOp1Arg && left->nodetype == ETYPCON && - IRO_IsVariable(left->u.monadic)) { - if (!IsSafeTypcon(left)) - return 0; - *resultNd2 = left; - indirect = left->u.monadic; - *resultNd1 = right; - } else { - if (nd->type == IROLinearOp2Arg && nd->nodetype == ESHL) - return 0; - - if (nd->u.diadic.right->flags & IROLF_LoopInvariant) { - if (IRO_IsVariable(left)) { - *resultNd2 = left; - indirect = left; - *resultNd1 = right; - } else if (left->type == IROLinearOp1Arg && left->nodetype == ETYPCON && IRO_IsVariable(left->u.monadic)) { - if (!IsSafeTypcon(left)) - return 0; - *resultNd2 = left; - indirect = left->u.monadic; - *resultNd1 = right; - } else { - return 0; - } - } else if (nd->u.diadic.left->flags & IROLF_LoopInvariant) { - if (IRO_IsVariable(right)) { - *resultNd2 = right; - indirect = right; - *resultNd1 = left; - } else if (right->type == IROLinearOp1Arg && right->nodetype == ETYPCON && IRO_IsVariable(right->u.monadic) && nd->type == IROLinearOp2Arg && nd->nodetype == EMUL) { - if (!IsSafeTypcon(right)) - return 0; - *resultNd2 = right; - indirect = right->u.monadic; - *resultNd1 = left; - } else { - return 0; - } - } else { - return 0; - } - } - } else if (nd->type == IROLinearOp2Arg && (nd->nodetype == EDIV || nd->nodetype == ESHR) && nd->rtype->size <= 4 && IS_TYPE_INT(nd->rtype)) { - if (IRO_IsVariable(nd->u.diadic.left) && IRO_IsConstant(nd->u.diadic.right)) { - val64 = nd->u.diadic.right->u.node->data.intval; - if (nd->type == IROLinearOp2Arg && nd->nodetype == ESHR) { - CInt64_GetULong(&val64); - if (CInt64_GetULong(&val64) > 32 || CTool_EndianReadWord32(&val64.hi)) - return 0; - val64 = CInt64_Shl(cint64_one, val64); - } - *resultNd2 = nd->u.diadic.left; - indirect = nd->u.diadic.left; - } else { - return 0; - } - } else { - return 0; - } - - if ( - nd->type == IROLinearOp2Arg && - nd->nodetype == ESHL && - ( - !IRO_IsConstant(*resultNd1) || - (SInt32) CInt64_GetULong(&(*resultNd1)->u.node->data.intval) < 0 || - (SInt32) CInt64_GetULong(&(*resultNd1)->u.node->data.intval) > 32 || - CTool_EndianReadWord32(&(*resultNd1)->u.node->data.intval.hi) - ) - ) - return 0; - - CError_ASSERT(802, indirect->u.monadic->u.node != NULL); - *resultVar = IRO_FindVar(indirect->u.monadic->u.node->data.objref, 0, 1); - if (!*resultVar || (*resultVar)->xA != 2) - return 0; - - if (copts.ANSIstrict || copts.strengthreductionstrict) { - Type *type = (*resultVar)->object->type; - if (IRO_IsUnsignedType(type) && type->size < stunsignedlong.size) - return 0; - } - - if (nd->type == IROLinearOp2Arg && (nd->nodetype == ESHR || nd->nodetype == EDIV)) { - ind = FirstInd; - while (ind && ind->var != *resultVar) - ind = ind->next; - - CError_ASSERT(845, ind != NULL); - - if (ind->addNode == NULL) { - if (ind->addConst < (val = CInt64_GetULong(&val64))) - return 0; - if ((div = ind->addConst / val) <= 0) - return 0; - - *resultNd1 = IRO_NewLinear(IROLinearOperand); - enode = IRO_NewENode(EINTCONST); - CInt64_SetULong(&enode->data.intval, div); - enode->rtype = nd->u.diadic.left->rtype; - (*resultNd1)->rtype = nd->u.diadic.left->rtype; - (*resultNd1)->u.node = enode; - } else { - return 0; - } - } - - return 1; -} - -static void IRO_RemoveExpr_Action(IROLinear *linear, Boolean isFirst) { - if (isFirst && linear->expr) - IRO_RemoveExpr(linear->expr); -} - -static void IRO_ActUnmarkRISCandidate(IROLinear *linear, Boolean isFirst) { - if (isFirst && linear->expr) - linear->flags &= ~IROLF_Ris; -} - -static IROExpr *CreateRIS(IROExpr *expr, IROLinear *nd1, IROLinear *nd2, IROLoopInd *induction, int unk) { - Object *tempObj; - Type *type; - Boolean flag23; - Object *tempObj2; - IROLinear *firstnode; - IROLinear *fourthnode; - IROLinear *fifthnode; - IROLinear *secondnode; - IROLinear *thirdnode; - IROLinear *tmp; - ENode *enode; - IROList list1; - IROList list2; - - flag23 = 0; - type = expr->linear->rtype; - tempObj = create_temp_object(type); - IRO_FindVar(tempObj, 1, 1); - IRO_InitList(&list1); - - if (IS_LINEAR_DIADIC(expr->linear, EADD)) { - firstnode = IRO_DuplicateExpr(expr->linear, &list1); - } else if (IS_LINEAR_DIADIC_2(expr->linear, EDIV, ESHR)) { - firstnode = IRO_DuplicateExpr(expr->linear, &list1); - } else { - firstnode = IRO_NewLinear(IROLinearOp2Arg); - firstnode->index = ++IRO_NumLinear; - firstnode->rtype = type; - firstnode->nodetype = EMUL; - firstnode->u.diadic.left = IRO_DuplicateExpr(nd1, &list1); - if (unk) - firstnode->u.diadic.right = IRO_DuplicateExpr(nd1, &list1); - else - firstnode->u.diadic.right = IRO_DuplicateExpr(nd2, &list1); - IRO_AddToList(firstnode, &list1); - } - - secondnode = IRO_NewLinear(IROLinearOp2Arg); - secondnode->index = ++IRO_NumLinear; - secondnode->rtype = type; - secondnode->nodetype = EASS; - secondnode->u.diadic.left = IRO_TempReference(tempObj, &list1); - secondnode->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned; - secondnode->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned; - secondnode->u.diadic.right = firstnode; - IRO_AddToList(secondnode, &list1); - IRO_Paste(list1.head, list1.tail, PredInt); - if ( - !IS_LINEAR_DIADIC_2(expr->linear, EDIV, ESHR) && - induction->addConst != 1 && - (induction->addNode || !IRO_IsConstant(nd2)) - ) { - flag23 = 1; - IRO_InitList(&list1); - thirdnode = IRO_NewLinear(IROLinearOp2Arg); - thirdnode->index = ++IRO_NumLinear; - thirdnode->rtype = nd2->rtype; - thirdnode->nodetype = EMUL; - - if (!induction->addNode) { - thirdnode->u.diadic.left = IRO_DuplicateExpr(nd2, &list1); - thirdnode->u.diadic.right = IRO_NewLinear(IROLinearOperand); - thirdnode->u.diadic.right->index = ++IRO_NumLinear; - enode = IRO_NewENode(EINTCONST); - enode->rtype = nd2->rtype; - thirdnode->u.diadic.right->rtype = nd2->rtype; - CInt64_SetLong(&enode->data.intval, induction->addConst); - thirdnode->u.diadic.right->u.node = enode; - IRO_AddToList(thirdnode->u.diadic.right, &list1); - } else { - thirdnode->u.diadic.left = IRO_DuplicateExpr(nd2, &list1); - thirdnode->u.diadic.right = IRO_DuplicateExpr(induction->addNode, &list1); - if (nd2->rtype != induction->addNode->rtype) { - tmp = IRO_NewLinear(IROLinearOp1Arg); - tmp->nodetype = ETYPCON; - tmp->index = ++IRO_NumLinear; - tmp->rtype = nd2->rtype; - tmp->u.monadic = thirdnode->u.diadic.right; - IRO_AddToList(tmp, &list1); - thirdnode->u.diadic.right = tmp; - } - } - IRO_AddToList(thirdnode, &list1); - - tempObj2 = create_temp_object(nd2->rtype); - - fourthnode = IRO_NewLinear(IROLinearOp2Arg); - fourthnode->index = ++IRO_NumLinear; - fourthnode->rtype = nd2->rtype; - fourthnode->nodetype = EASS; - fourthnode->u.diadic.left = IRO_TempReference(tempObj2, &list1); - fourthnode->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned; - fourthnode->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned; - fourthnode->u.diadic.right = thirdnode; - IRO_AddToList(fourthnode, &list1); - IRO_Paste(list1.head, list1.tail, PredInt); - } - - IRO_InitList(&list2); - fifthnode = IRO_NewLinear(IROLinearOp2Arg); - fifthnode->index = ++IRO_NumLinear; - fifthnode->rtype = type; - if (induction->nd->type == IROLinearOp2Arg) { - if (induction->nd->nodetype == EASS && IS_LINEAR_DIADIC(induction->nd->u.diadic.right, EADD)) - fifthnode->nodetype = EADDASS; - else if (induction->nd->nodetype == EASS && IS_LINEAR_DIADIC(induction->nd->u.diadic.right, ESUB)) - fifthnode->nodetype = ESUBASS; - else - fifthnode->nodetype = induction->nd->nodetype; - } else { - if (induction->nd->nodetype == EPREINC || induction->nd->nodetype == EPOSTINC) - fifthnode->nodetype = EADDASS; - else - fifthnode->nodetype = ESUBASS; - } - - fifthnode->u.diadic.left = IRO_TempReference(tempObj, &list2); - fifthnode->u.diadic.left->flags |= IROLF_Ind | IROLF_Used | IROLF_Assigned; - fifthnode->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Used | IROLF_Assigned; - if (!unk) { - if (!flag23) { - if (induction->addConst == 1 || IS_LINEAR_DIADIC_2(expr->linear, EDIV, ESHR)) { - fifthnode->u.diadic.right = IRO_DuplicateExpr(nd2, &list2); - } else { - fifthnode->u.diadic.right = IRO_NewLinear(IROLinearOperand); - fifthnode->u.diadic.right->index = ++IRO_NumLinear; - enode = IRO_NewENode(EINTCONST); - enode->rtype = nd2->rtype; - fifthnode->u.diadic.right->rtype = nd2->rtype; - CInt64_SetLong(&enode->data.intval, induction->addConst * CInt64_GetULong(&nd2->u.node->data.intval)); - fifthnode->u.diadic.right->u.node = enode; - IRO_AddToList(fifthnode->u.diadic.right, &list2); - } - } else { - fifthnode->u.diadic.right = IRO_TempReference(tempObj2, &list2); - fifthnode->u.diadic.right->flags |= IROLF_Used; - } - } - - fifthnode->index = ++IRO_NumLinear; - IRO_AddToList(fifthnode, &list2); - IRO_Paste(list2.head, list2.tail, IRO_FindStart(induction->nd)); - IRO_WalkTree(expr->linear, IRO_RemoveExpr_Action); - expr->x8 = tempObj; - expr->next = RisList; - RisList = expr; - return expr; -} - -static IRONode *CreatePreHeader(IRONode *fnode1, IRONode *fnode2) { - IROLinear *labelnode; - IRONode *newfnode; - IRONode *iter; - CLabel *oldlabel; - CLabel *newlabel; - SwitchInfo *swinfo; - SwitchCase *swcase; - - newfnode = oalloc(sizeof(IRONode)); - memset(newfnode, 0, sizeof(IRONode)); - newfnode->index = IRO_NumNodes; - IRO_NumNodes++; - - labelnode = IRO_NewLinear(IROLinearLabel); - labelnode->index = IRO_NumLinear++; - labelnode->next = NULL; - labelnode->u.label.label = IRO_NewLabel(); - labelnode->flags |= IROLF_1; - labelnode->u.label.label->stmt = (Statement *) newfnode; - newfnode->first = labelnode; - newfnode->last = labelnode; - - if (fnode2) { - fnode2->last->next = labelnode; - labelnode->next = IRO_NewLinear(IROLinearNop); - labelnode->next->next = fnode1->first; - fnode2->nextnode = newfnode; - newfnode->nextnode = fnode1; - } else { - CError_ASSERT(1254, fnode1->first->type == IROLinearLabel); - labelnode->next = IRO_NewLinear(IROLinearGoto); - labelnode->next->u.label.label = fnode1->first->u.label.label; - IRO_LastNode->last->next = labelnode; - IRO_LastNode->nextnode = newfnode; - IRO_LastNode = newfnode; - IRO_LastLinear = labelnode->next; - } - - newfnode->last = labelnode->next; - - IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes); - memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes); - for (iter = IRO_FirstNode; iter; iter = iter->nextnode) - IRO_NodeTable[iter->index] = iter; - - if (fnode1->first->type == IROLinearLabel) { - oldlabel = fnode1->first->u.label.label; - newlabel = newfnode->first->u.label.label; - for (iter = IRO_FirstNode; iter; iter = iter->nextnode) { - if (!Bv_IsBitSet(iter->index, InLoop) && iter != newfnode) { - switch (iter->last->type) { - case IROLinearGoto: - if (iter->last->u.label.label == oldlabel) - iter->last->u.label.label = newlabel; - break; - case IROLinearIf: - case IROLinearIfNot: - if (iter->last->u.label.label == oldlabel) - iter->last->u.label.label = newlabel; - break; - case IROLinearSwitch: - swinfo = iter->last->u.swtch.info; - for (swcase = swinfo->cases; swcase; swcase = swcase->next) { - if (swcase->label == oldlabel) - swcase->label = newlabel; - } - if (swinfo->defaultlabel == oldlabel) - swinfo->defaultlabel = newlabel; - break; - } - } - } - } - - IRO_ComputeSuccPred(); - IRO_ComputeDom(); - return newfnode; -} - -static IRONode *CreateNewLoopExitSuccessor(IRONode *fnode1) { - IROLinear *labelnode; - IRONode *fnode2; - IRONode *newfnode; - Boolean flag; - IRONode *iter; - CLabel *oldlabel; - CLabel *newlabel; - SwitchInfo *swinfo; - SwitchCase *swcase; - UInt16 i; - - CError_ASSERT(1355, fnode1 != NULL && LoopExitNumber == 1); - - fnode2 = NULL; - flag = 0; - - for (i = 0; i < fnode1->numpred; i++) { - iter = IRO_NodeTable[fnode1->pred[i]]; - if (Bv_IsBitSet(iter->index, InLoop_Exits)) { - CError_ASSERT(1366, fnode2 == NULL); - fnode2 = iter; - if (!flag) { - if ( - !iter->last || - !fnode1->first || - fnode1->first->type != IROLinearLabel || - ( - (iter->last->type == IROLinearIf || iter->last->type == IROLinearIfNot) && - iter->last->u.label.label != fnode1->first->u.label.label - )) - flag = 1; - } - } - } - - CError_ASSERT(1382, fnode2 != NULL); - - newfnode = oalloc(sizeof(IRONode)); - memset(newfnode, 0, sizeof(IRONode)); - newfnode->index = IRO_NumNodes; - IRO_NumNodes++; - - labelnode = IRO_NewLinear(IROLinearLabel); - labelnode->index = IRO_NumLinear++; - labelnode->next = NULL; - labelnode->u.label.label = IRO_NewLabel(); - labelnode->flags |= IROLF_1; - labelnode->u.label.label->stmt = (Statement *) newfnode; - newfnode->first = labelnode; - newfnode->last = labelnode; - - if (flag) { - fnode2->last->next = labelnode; - labelnode->next = IRO_NewLinear(IROLinearNop); - labelnode->next->next = fnode1->first; - fnode2->nextnode = newfnode; - newfnode->nextnode = fnode1; - } else { - CError_ASSERT(1422, fnode1->first->type == IROLinearLabel); - labelnode->next = IRO_NewLinear(IROLinearGoto); - labelnode->next->u.label.label = fnode1->first->u.label.label; - IRO_LastNode->last->next = labelnode; - IRO_LastNode->nextnode = newfnode; - IRO_LastNode = newfnode; - IRO_LastLinear = labelnode->next; - } - - newfnode->last = labelnode->next; - - IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes); - memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes); - for (iter = IRO_FirstNode; iter; iter = iter->nextnode) - IRO_NodeTable[iter->index] = iter; - - if (fnode1->first->type == IROLinearLabel) { - oldlabel = fnode1->first->u.label.label; - newlabel = newfnode->first->u.label.label; - switch (fnode2->last->type) { - case IROLinearGoto: - if (fnode2->last->u.label.label == oldlabel) - fnode2->last->u.label.label = newlabel; - break; - case IROLinearIf: - case IROLinearIfNot: - if (fnode2->last->u.label.label == oldlabel) - fnode2->last->u.label.label = newlabel; - break; - case IROLinearSwitch: - swinfo = fnode2->last->u.swtch.info; - for (swcase = swinfo->cases; swcase; swcase = swcase->next) { - if (swcase->label == oldlabel) - swcase->label = newlabel; - } - if (swinfo->defaultlabel == oldlabel) - swinfo->defaultlabel = newlabel; - break; - } - } - - IRO_ComputeSuccPred(); - IRO_ComputeDom(); - return newfnode; -} - -void AddPreds(IRONode *fnode) { - IRONode *pred; - int i; - - for (i = 0; i < fnode->numpred; i++) { - pred = IRO_NodeTable[fnode->pred[i]]; - if (!Bv_IsBitSet(pred->index, InLoop)) { - Bv_SetBit(pred->index, InLoop); - AddPreds(pred); - } - } -} - -static void RemoveNoopsFromExprList(void) { - IROExpr *expr; - IROExpr *prev; - - expr = IRO_FirstExpr; - prev = NULL; - while (expr) { - if (expr->linear->type == IROLinearNop) { - if (prev) - prev->next = expr->next; - else - IRO_FirstExpr = expr->next; - expr = expr->next; - } else { - prev = expr; - expr = expr->next; - } - } -} - -void IncLoopDepth(void) { - IRONode *fnode; - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - if (Bv_IsBitSet(fnode->index, InLoop)) - fnode->loopdepth++; - } -} - -void IRO_SetLoopDepth(void) { - IRONode *fnode; - IRONode *pred; - UInt16 i; - UInt16 flag; - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) - fnode->loopdepth = 0; - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - flag = 0; - - for (i = 0; i < fnode->numpred; i++) { - pred = IRO_NodeTable[fnode->pred[i]]; - if (Bv_IsBitSet(fnode->index, pred->dom)) { - if (!flag) { - Bv_AllocVector(&InLoop, IRO_NumNodes + 1); - Bv_Clear(InLoop); - Bv_SetBit(fnode->index, InLoop); - } - flag = 1; - Bv_SetBit(pred->index, InLoop); - if (pred != fnode) - AddPreds(pred); - } - } - - if (flag) - IncLoopDepth(); - } - - IRO_CheckForUserBreak(); -} - -static void InsertBranchAroundLoopPreheaders(void) { - IRONode *fnode; - CLabel *label; - IRONode *iter; - IROLinear *endnode; - IROLinear *labelnode; - - if (IRO_EndNode && IRO_EndNode->last && IRO_EndNode->last->type == IROLinearEnd) { - label = IRO_NewLabel(); - fnode = IRO_NewFlowGraphNode(); - IRO_LastNode->nextnode = fnode; - label->stmt = (Statement *) fnode; - - IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes); - memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes); - for (iter = IRO_FirstNode; iter; iter = iter->nextnode) - IRO_NodeTable[iter->index] = iter; - - labelnode = IRO_NewLinear(IROLinearLabel); - labelnode->index = ++IRO_NumLinear; - labelnode->u.label.label = label; - labelnode->flags |= IROLF_1; - fnode->first = labelnode; - IRO_LastLinear->next = labelnode; - - endnode = IRO_NewLinear(IROLinearEnd); - memcpy(endnode, IRO_EndNode->last, sizeof(IROLinear)); - endnode->index = ++IRO_NumLinear; - endnode->next = NULL; - fnode->last = endnode; - labelnode->next = endnode; - IRO_LastLinear = endnode; - - IRO_EndNode->last->type = IROLinearGoto; - IRO_EndNode->last->u.label.label = label; - IRO_LastNode = fnode; - IRO_EndNode = fnode; - - IRO_ComputeSuccPred(); - IRO_ComputeDom(); - } -} - -void IRO_FindLoops(void) { - IRONode *fnode; - IRONode *pred; - UInt16 i; - UInt16 flag; - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - flag = 0; - - for (i = 0; i < fnode->numpred; i++) { - pred = IRO_NodeTable[fnode->pred[i]]; - if (Bv_IsBitSet(fnode->index, pred->dom)) { - if (!flag) { - Bv_AllocVector(&InLoop, IRO_NumNodes + 1); - Bv_Clear(InLoop); - Bv_SetBit(fnode->index, InLoop); - } - flag = 1; - Bv_SetBit(pred->index, InLoop); - if (pred != fnode) - AddPreds(pred); - } - } - - if (flag) { - IncLoopDepth(); - IRO_Dump("IRO_FindLoops:Found loop with header %d\n", fnode->index); - IRO_DumpBits("Loop includes: ", InLoop); - MyHandleLoop_Motion(fnode); - IRO_UpdateFlagsOnInts(); - MyHandleLoop_Vector(fnode); - RemoveNoopsFromExprList(); - IRO_UpdateFlagsOnInts(); - IRO_UpdateVars(); - } - } - - if (!IRO_FunctionHasReturn && IRO_EndNode != IRO_LastNode) - InsertBranchAroundLoopPreheaders(); -} - -static void CheckSubableSub(IROLinear *linear, Boolean isFirst) { - if (isFirst && IRO_IsSubableExpression(linear)) { - IRO_Dump("Subable Expression is %d\n", linear->index); - NoSubableSubs = 0; - } -} - -static int NoSubableSubExprs(IROLinear *nd) { - NoSubableSubs = 1; - IRO_WalkTree(nd, CheckSubableSub); - return NoSubableSubs; -} - -void ComputeLoopKills(void) { - IRONode *fnode; - IROLinear *nd; - - Bv_AllocVector(&AllKills, IRO_NumVars + 1); - Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) { - Bv_AllocVector(&fnode->x16, IRO_NumVars + 1); - Bv_AllocVector(&fnode->x1E, IRO_NumVars + 1); - while (1) { - Bv_Clear(IRO_VarKills); - IRO_GetKills(nd); - Bv_Or(IRO_VarKills, AllKills); - if (nd == fnode->last) - break; - nd = nd->next; - } - } - } -} - -void ComputeLoopInvariance(void) { - IRONode *fnode; - IROLinear *nd; - - IRO_Depends = IRO_VarKills; - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) { - nd->flags &= ~IROLF_LoopInvariant; - while (1) { - if ((nd->flags & IROLF_Reffed) && nd->type != IROLinearNop) { - IRO_FindDepends_NoAlloc(nd); - if (!IRO_IsVolatile && !Bv_BitsInCommon(IRO_Depends, AllKills)) - nd->flags |= IROLF_LoopInvariant; - - if (IRO_CouldError) - nd->flags |= IROLF_CouldError; - else - nd->flags &= ~IROLF_CouldError; - } - - if (nd == fnode->last) - break; - nd = nd->next; - } - } - } -} - -void ComputeLoopInduction(void) { - IRONode *fnode; - IROLinear *nd; - Boolean flag; - Object *obj; - Object *obj2; - Object *obj3; - VarRecord *var; - IROLinear *tmpnd; - IROLoopInd *ind; - Boolean isUnsigned; - - Bv_AllocVector(&AllKills, IRO_NumVars + 1); - Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) { - while (1) { - Bv_Clear(IRO_VarKills); - IRO_GetKills(nd); - Bv_Or(IRO_VarKills, AllKills); - flag = 0; - if ( - ( - nd->type == IROLinearOp2Arg && - nd->rtype->size <= 4 && - (nd->nodetype == EADDASS || nd->nodetype == ESUBASS) && - (obj = IRO_IsVariable(nd->u.diadic.left)) && - obj->type->size == nd->rtype->size && - IS_TYPE_INT(obj->type) && - ( - (IRO_IsIntConstant(nd->u.diadic.right) && CInt64_GetULong(&nd->u.diadic.right->u.node->data.intval)) - || - (nd->u.diadic.right->flags & IROLF_LoopInvariant) - ) - ) - || - ( - nd->type == IROLinearOp1Arg && - nd->rtype->size <= 4 && - (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC || nd->nodetype == EPREINC || nd->nodetype == EPREDEC) && - (obj = IRO_IsVariable(nd->u.monadic)) && - obj->type->size == nd->rtype->size && - IS_TYPE_INT(obj->type) - ) - ) - { - flag = 1; - } - else if ( - nd->type == IROLinearOp2Arg && - nd->rtype->size <= 4 && - nd->nodetype == EASS && - (obj = IRO_IsVariable(nd->u.diadic.left)) && - obj->type->size == nd->rtype->size && - IS_TYPE_INT(obj->type) && - nd->u.diadic.right->type == IROLinearOp2Arg && - (nd->u.diadic.right->nodetype == EADD || nd->u.diadic.right->nodetype == ESUB) - ) - { - if (nd->u.diadic.right->nodetype == EADD) { - obj2 = IRO_IsVariable(nd->u.diadic.right->u.diadic.left); - obj3 = IRO_IsVariable(nd->u.diadic.right->u.diadic.right); - if (obj2 == obj && obj3 != obj && (nd->u.diadic.right->u.diadic.right->flags & IROLF_LoopInvariant)) - flag = 1; - - if (obj3 == obj && obj2 != obj && (nd->u.diadic.right->u.diadic.left->flags & IROLF_LoopInvariant)) { - flag = 1; - tmpnd = nd->u.diadic.right->u.diadic.left; - nd->u.diadic.right->u.diadic.left = nd->u.diadic.right->u.diadic.right; - nd->u.diadic.right->u.diadic.right = tmpnd; - } - } else { - obj2 = IRO_IsVariable(nd->u.diadic.right->u.diadic.left); - obj3 = IRO_IsVariable(nd->u.diadic.right->u.diadic.right); - if (obj2 == obj && obj3 != obj && (nd->u.diadic.right->u.diadic.right->flags & IROLF_LoopInvariant)) - flag = 1; - } - } - - if (flag) { - if ((var = IRO_FindAssigned(nd))) { - if (var->xA == 2) - var->xA = 0; - else if (var->xA == 1) - var->xA = 2; - } - } else { - for (var = IRO_FirstVar; var; var = var->next) { - if (Bv_IsBitSet(var->index, IRO_VarKills)) - var->xA = 0; - } - } - - if (nd == fnode->last) - break; - nd = nd->next; - } - } - } - - IRO_DumpBits("Killed in loop: ", AllKills); - - for (fnode = IRO_FirstNode, FirstInd = NULL; fnode; fnode = fnode->nextnode) { - if (Bv_IsBitSet(fnode->index, InLoop) && (nd = fnode->first)) { - while (1) { - if ( - ( - nd->type == IROLinearOp2Arg && - (nd->nodetype == EADDASS || nd->nodetype == ESUBASS || nd->nodetype == EASS) - ) - || - ( - nd->type == IROLinearOp1Arg && - (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC || nd->nodetype == EPREINC || nd->nodetype == EPREDEC) - ) - ) { - if ((var = IRO_FindAssigned(nd)) && var->xA == 2 && var->object->type->size <= 4) { - ind = oalloc(sizeof(IROLoopInd)); - ind->fnode = fnode; - ind->var = var; - ind->nd = nd; - ind->next = FirstInd; - ind->addNode = NULL; - ind->addConst = 0; - ind->flags = 0; - - if (nd->type == IROLinearOp2Arg) { - isUnsigned = IRO_IsUnsignedType(nd->rtype); - if (IRO_IsIntConstant(nd->u.diadic.right)) { - CInt64 val = nd->u.diadic.right->u.node->data.intval; - if (IS_LINEAR_DIADIC(nd, EADDASS) && CInt64_Less(val, cint64_zero)) { - nd->nodetype = ESUBASS; - nd->u.diadic.right->u.node->data.intval = CInt64_Neg(val); - } - if (isUnsigned) { - CInt64_ConvertUInt32(&nd->u.diadic.right->u.node->data.intval); - ind->addConst = CInt64_GetULong(&nd->u.diadic.right->u.node->data.intval); - } else { - CInt64_ConvertInt32(&nd->u.diadic.right->u.node->data.intval); - ind->addConst = CInt64_GetULong(&nd->u.diadic.right->u.node->data.intval); - } - ind->addNode = NULL; - } else if (nd->nodetype == EADDASS || nd->nodetype == ESUBASS) { - ind->addNode = nd->u.diadic.right; - } else if (nd->nodetype == EASS) { - ind->addNode = nd->u.diadic.right->u.diadic.right; - } - } else { - if (IS_TYPE_POINTER_ONLY(nd->rtype)) - ind->addConst = TPTR_TARGET(nd->rtype)->size; - else - ind->addConst = 1; - ind->addNode = NULL; - } - - FirstInd = ind; - - if (IS_LINEAR_DIADIC_2(nd, EADDASS, ESUBASS)) { - if (nd->u.diadic.right->flags & IROLF_LoopInvariant) - IRO_Dump("Found induction variable the new way: %s\n", var->object->name->name); - else - IRO_Dump("Found induction variable the old way: %s\n", var->object->name->name); - } else if (nd->type == IROLinearOp2Arg && (nd->u.diadic.right->nodetype == EADD || nd->u.diadic.right->nodetype == ESUB)) { - IRO_Dump("Found induction variable the new way: %s\n", var->object->name->name); - } else { - IRO_Dump("Found induction variable the old way: %s\n", var->object->name->name); - } - } - } - - if (nd == fnode->last) - break; - nd = nd->next; - } - } - } -} - -static void IRO_ActUnmarkLoopInvariance(IROLinear *linear, Boolean isFirst) { - if (isFirst) - linear->flags &= ~IROLF_LoopInvariant; -} - -static void UnmarkSubexpressionsOfInvariantExpressions(void) { - IROExpr *expr; - - for (expr = IRO_FirstExpr; expr; expr = expr->next) { - if ( - Bv_IsBitSet(expr->node->index, InLoop) && - !expr->notSubable && - (!expr->couldError || expr->node->mustreach) && - (expr->linear->flags & IROLF_LoopInvariant) - ) { - IRO_WalkTree(expr->linear, IRO_ActUnmarkLoopInvariance); - expr->linear->flags |= IROLF_LoopInvariant; - } - } -} - -static void MyHandleLoop_Vector(IRONode *fnode) { - IRONode *pred; - UInt16 i; - IROExpr *expr; - IROExpr *removedExprs; - IROExpr *exprnext; - IROLoopInd *induction; - IROExpr *exprinner; - Boolean flag24; - IRONode *v2; - IRONode *node22; - int flag21; - IRONode *iter; - IROExpr *searchris; - IROLinear *reduceNd1; - VarRecord *var; - IROLinear *reduceNd2; - - IRO_FirstExpr = NULL; - LoopNode = fnode; - FindMustReach(); - - for (var = IRO_FirstVar; var; var = var->next) - var->xA = 1; - - ComputeLoopKills(); - ComputeLoopInvariance(); - ComputeLoopInduction(); - LoopNode = fnode; - ConditionalHeaderAtBottom = 0; - - v2 = NULL; - flag21 = 0; - node22 = NULL; - for (i = 0; i < LoopNode->numpred; i++) { - pred = IRO_NodeTable[LoopNode->pred[i]]; - if (!Bv_IsBitSet(pred->index, InLoop)) { - if (flag21) - node22 = NULL; - else - node22 = pred; - flag21 = 1; - if (pred->nextnode == fnode) { - CError_ASSERT(2880, v2 == NULL || pred == v2); - v2 = pred; - } - } - } - - if (!flag21) { - IRO_Dump("No predecessor outside the loop\n"); - return; - } - - if (!node22 || node22->last->type != IROLinearGoto) - node22 = CreatePreHeader(fnode, v2); - PredInt = node22->last; - - if (PredInt->type == IROLinearGoto && PredInt->u.label.label != LoopNode->first->u.label.label) { - if (!KnownBounds || !Times) { - for (iter = IRO_FirstNode; iter; iter = iter->nextnode) - iter->mustreach = 0; - } else { - PredInt->u.label.label = LoopNode->first->u.label.label; - IRO_ComputeSuccPred(); - } - } - - if (copts.loopinvariants || copts.strengthreduction) { - MoveInvarianceInAddressExpr(); - IRO_DumpAfterPhase("MoveInvarianceInAddressExpr", 0); - IRO_FindExpressions(InLoop, 1); - IRO_DumpExprs(); - } - - if (copts.loopinvariants) - UnmarkSubexpressionsOfInvariantExpressions(); - - if (!copts.optimizesize && copts.strengthreduction) { - for (expr = IRO_FirstExpr; expr; expr = expr->next) { - if ( - !(expr->x0 & 4) && - Bv_IsBitSet(expr->node->index, InLoop) && - !expr->notSubable && - (!expr->couldError || expr->node->mustreach) && - Reducable(expr->linear, &reduceNd1, &reduceNd2, &var) - ) { - IRO_WalkTree(expr->linear, IRO_ActUnmarkRISCandidate); - expr->linear->flags |= IROLF_Ris; - expr->x1A = reduceNd1; - expr->x1E = var; - expr->x22 = reduceNd2; - } - } - } - - if (!copts.optimizesize && copts.strengthreduction) { - RisList = NULL; - for (expr = IRO_FirstExpr; expr; expr = exprnext) { - exprnext = expr->next; - if (!(expr->x0 & 4) && (expr->linear->flags & IROLF_Ris)) { - reduceNd1 = expr->x1A; - var = expr->x1E; - reduceNd2 = expr->x22; - - induction = FirstInd; - while (induction && induction->var != var) - induction = induction->next; - CError_ASSERT(3529, induction != NULL); - - IRO_FindDepends(reduceNd1); - if (!Bv_BitsInCommon(IRO_Depends, AllKills)) { - IRO_Dump("Found reduction in strength: %d\n", expr->linear->index); - if (IS_LINEAR_DIADIC(expr->linear, ESHL)) { - expr->linear->nodetype = EMUL; - CInt64_SetULong(&reduceNd1->u.node->data.intval, 1 << CInt64_GetULong(&reduceNd1->u.node->data.intval)); - reduceNd1->u.node->rtype = expr->linear->rtype; - } - - searchris = RisList; - while (1) { - if (!searchris) - break; - if (IRO_ExprsSame(expr->linear, searchris->linear)) - break; - searchris = searchris->next; - } - - if (searchris) { - IRO_Dump("Using existing RIS: %d\n", searchris->linear->index); - IRO_WalkTree(expr->linear, IRO_RemoveExpr_Action); - } else { - searchris = CreateRIS(expr, reduceNd2, reduceNd1, induction, 0); - } - IRO_ReplaceReference(expr->linear, searchris->x8, expr->linear); - IRO_ClipExpr(expr); - } - } - } - } - - RisList = NULL; - - expr = IRO_FirstExpr; - removedExprs = NULL; - if (copts.loopinvariants) { - while (expr) { - exprnext = expr->next; - flag24 = 0; - - if ( - Bv_IsBitSet(expr->node->index, InLoop) && - !expr->notSubable && - (!expr->couldError || expr->node->mustreach) && - (expr->linear->flags & IROLF_LoopInvariant) && - !(expr->x0 & 4) - ) { - IRO_Dump("Found loop invariant: %d\n", expr->linear->index); - - for (exprinner = removedExprs; exprinner; exprinner = exprinner->next) { - if (IRO_ExprsSame(exprinner->linear, expr->linear)) { - IRO_ReplaceReference(expr->linear, exprinner->x8, expr->linear); - IRO_NopOut(expr->linear); - IRO_Dump("Using already removed expr: %d\n", exprinner->linear->index); - IRO_RemoveExpr(expr); - flag24 = 1; - } - } - - if (!flag24 && !expr->x8) { - IRO_GetTemp(expr); - IRO_ReplaceReference(expr->linear, expr->x8, expr->linear); - IRO_MoveExpression(expr, PredInt); - IRO_AssignToTemp(expr); - IRO_RemoveExpr(expr); - expr->next = removedExprs; - removedExprs = expr; - } - } - - expr = exprnext; - } - } -} - -static void MyHandleLoop_Motion(IRONode *fnode) { - IROLoopMemRef *memref; - IRONode *pred; - UInt16 i; - IRONode *v2; - IRONode *node21; - Object *tempobj; - int flag20; - IRONode *iter; - IROLinear *ass; - VarRecord *var; - Boolean checkflag; - IROLoop *loop; - IROList list; - IROElmList *refiter; - - IRO_FirstExpr = NULL; - LoopNode = fnode; - FindMustReach(); - - for (var = IRO_FirstVar; var; var = var->next) - var->xA = 1; - - ComputeLoopKills(); - ComputeLoopInvariance(); - ComputeLoopInduction(); - LoopNode = fnode; - ConditionalHeaderAtBottom = 0; - - v2 = NULL; - flag20 = 0; - node21 = NULL; - for (i = 0; i < LoopNode->numpred; i++) { - pred = IRO_NodeTable[LoopNode->pred[i]]; - if (!Bv_IsBitSet(pred->index, InLoop)) { - if (flag20) - node21 = NULL; - else - node21 = pred; - flag20 = 1; - if (pred->nextnode == fnode) { - CError_ASSERT(3880, v2 == NULL || pred == v2); - v2 = pred; - } - } - } - - if (!flag20) { - IRO_Dump("No predecessor outside the loop\n"); - return; - } - - if (!node21 || node21->last->type != IROLinearGoto) - node21 = CreatePreHeader(fnode, v2); - PredInt = node21->last; - - if (PredInt->type == IROLinearGoto && PredInt->u.label.label != LoopNode->first->u.label.label) { - if (!KnownBounds || !Times) { - for (iter = IRO_FirstNode; iter; iter = iter->nextnode) - iter->mustreach = 0; - } else { - PredInt->u.label.label = LoopNode->first->u.label.label; - IRO_ComputeSuccPred(); - } - } - - if (copts.loopinvariants || copts.strengthreduction) { - MoveInvarianceInAddressExpr(); - IRO_DumpAfterPhase("MoveInvarianceInAddressExpr", 0); - IRO_FindExpressions(InLoop, 0); - IRO_DumpExprs(); - } - - if (copts.loopinvariants) - UnmarkSubexpressionsOfInvariantExpressions(); - - checkflag = 1; - Bv_AllocVector(&InLoop_Exits, IRO_NumNodes + 1); - Bv_AllocVector(&InLoop_Tails, IRO_NumNodes + 1); - LoopExitNumber = 0; - LoopExitSuccessor = NULL; - LoopTailNum = 0; - LoopTail = NULL; - IRO_FindLoopTailsAndExits(fnode); - FindMustReach1(fnode); - - loop = NULL; - if (LoopTailNum == 1) { - if (fnode->last->type == IROLinearIf || fnode->last->type == IROLinearIfNot) - loop = ExtractLoopInfo(fnode); - else if (LoopTail->last->type == IROLinearIf || LoopTail->last->type == IROLinearIfNot) - loop = ExtractLoopInfo(LoopTail); - } - - if (loop && !(loop->flags & LP_IFEXPR_NON_CANONICAL) && LoopExitNumber == 1) { - IRO_LoopMemRefFirst = NULL; - IRO_LoopMemRefCurrent = NULL; - CheckAllLoopAddresses(IRO_FirstNode, InLoop, &checkflag); - CheckAllLoopAddresses(IRO_FirstNode, InLoop, &checkflag); - if (checkflag) { - for (memref = IRO_LoopMemRefFirst; memref; memref = memref->next) { - if (memref->flags & LoopMemRef_10) - memref->flags |= LoopMemRef_8; - } - - for (memref = IRO_LoopMemRefFirst; memref; memref = memref->next) { - IRO_Dump("Loop Motion Candidate:: Int= %d", memref->nd->index); - if (memref->flags & LoopMemRef_8) - IRO_Dump(""); - if (memref->flags & LoopMemRef_1) - IRO_Dump(""); - if (memref->flags & LoopMemRef_2) - IRO_Dump(""); - IRO_Dump("\n"); - - if (!(memref->flags & LoopMemRef_8)) { - tempobj = create_temp_object(memref->nd->rtype); - IRO_FindVar(tempobj, 1, 1); - if (IRO_FindVar(((IROLinear *) memref->rec->objRefs->element)->u.node->data.objref, 0, 1)) { - IRO_InitList(&list); - ass = IRO_NewLinear(IROLinearOp2Arg); - ass->index = ++IRO_NumLinear; - ass->rtype = memref->nd->rtype; - ass->nodetype = EASS; - ass->u.diadic.left = IRO_TempReference(tempobj, &list); - ass->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned; - ass->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned; - ass->u.diadic.right = IRO_DuplicateExpr(memref->nd, &list); - IRO_AddToList(ass, &list); - IRO_Paste(list.head, list.tail, PredInt); - } else { - CError_FATAL(4123); - } - - if (LoopExitSuccessor->numpred != 1) - LoopExitSuccessor = CreateNewLoopExitSuccessor(LoopExitSuccessor); - - IRO_InitList(&list); - ass = IRO_NewLinear(IROLinearOp2Arg); - ass->index = ++IRO_NumLinear; - ass->rtype = memref->nd->rtype; - ass->nodetype = EASS; - ass->u.diadic.left = IRO_DuplicateExpr(memref->nd, &list); - ass->u.diadic.left->flags |= IROLF_Ind | IROLF_Assigned; - ass->u.diadic.left->u.monadic->flags |= IROLF_Ind | IROLF_Assigned; - ass->u.diadic.right = IRO_TempReference(tempobj, &list); - IRO_AddToList(ass, &list); - - if (LoopExitSuccessor->first->type == IROLinearLabel) - IRO_PasteAfter(list.head, list.tail, LoopExitSuccessor->first); - else - IRO_Paste(list.head, list.tail, LoopExitSuccessor->first); - - for (refiter = memref->list; refiter; refiter = refiter->next) { - IRO_Dump("Loop Motion Candidate Reference at Int= %d\n", ((IROLinear *) refiter->element)->index); - IRO_InitList(&list); - IRO_TempReference(tempobj, &list); - IRO_Paste(list.head, list.tail, refiter->element); - IRO_LocateFather_Cut_And_Paste(refiter->element, list.tail); - } - } - } - } - } - - IRO_DumpAfterPhase("After Motion", 0); -} - -static Boolean CheckLoopAddress(IROLinear *nd, Boolean mustreach1) { - IROLoopMemRef *memref; - IROAddrRecord *rec; - IROAddrRecord *otherrec; - IROLinear *inner; - IROElmList *list; - Boolean flag; - - inner = nd->u.monadic; - rec = IRO_InitAddrRecordPointer(inner); - if (IS_LINEAR_ENODE(inner, EOBJREF)) { - rec->numObjRefs++; - IRO_AddElmToList(inner, &rec->objRefs); - } else if (IS_LINEAR_DIADIC(inner, EADD)) { - IRO_DecomposeAddressExpression(inner, rec); - } else { - return 0; - } - - if (rec->numObjRefs != 1) - return 0; - - flag = (nd->flags & IROLF_CouldError) || !(nd->flags & IROLF_Reffed); - if (!IRO_LoopMemRefFirst) { - MakeLoopEntry(nd, rec, mustreach1, flag); - } else { - for (memref = IRO_LoopMemRefFirst; memref; memref = memref->next) { - otherrec = memref->rec; - if (((IROLinear *) rec->objRefs->element)->u.node->data.objref == ((IROLinear *) otherrec->objRefs->element)->u.node->data.objref) { - if (IRO_ExprsSame(inner, otherrec->linear)) { - list = oalloc(sizeof(IROElmList)); - list->element = nd; - list->next = NULL; - if (!memref->list) { - memref->list = list; - } else { - list->next = memref->list; - memref->list = list; - } - } else { - memref->flags |= LoopMemRef_8; - } - - if (!mustreach1 && flag) - memref->flags |= LoopMemRef_8; - if (mustreach1 || flag) - memref->flags &= ~LoopMemRef_10; - break; - } - } - - if (!memref) - MakeLoopEntry(nd, rec, mustreach1, flag); - } - - return 1; -} - -static void CheckAllLoopAddresses(IRONode *fnode, BitVector *bv, Boolean *resultFlag) { - IROLinear *nd; - Boolean flag; - - flag = *resultFlag; - while (fnode) { - if (Bv_IsBitSet(fnode->index, bv) && (nd = fnode->first)) { - while (flag) { - if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT) - flag = CheckLoopAddress(nd, fnode->mustreach1); - else if (nd->type == IROLinearFunccall) - flag = 0; - - if (nd == fnode->last) - break; - nd = nd->next; - } - - if (!flag) - break; - } - fnode = fnode->nextnode; - } - *resultFlag = flag; -} - -static void MakeLoopEntry(IROLinear *nd, IROAddrRecord *rec, Boolean mustreach1, Boolean flag2) { - IROElmList *list; - - if (!IRO_IsRegable(((IROLinear *) rec->objRefs->element)->u.node->data.objref) && - (nd->u.monadic->flags & IROLF_LoopInvariant) && - !IRO_HasSideEffect(nd)) { - if (!IRO_LoopMemRefFirst) { - IRO_LoopMemRefCurrent = IRO_LoopMemRefFirst = oalloc(sizeof(IROLoopMemRef)); - } else { - IRO_LoopMemRefCurrent->next = oalloc(sizeof(IROLoopMemRef)); - IRO_LoopMemRefCurrent = IRO_LoopMemRefCurrent->next; - } - IRO_LoopMemRefCurrent->flags = LoopMemRef_10; - IRO_LoopMemRefCurrent->nd = nd; - IRO_LoopMemRefCurrent->rec = rec; - IRO_LoopMemRefCurrent->next = NULL; - IRO_LoopMemRefCurrent->list = NULL; - - list = oalloc(sizeof(IROElmList)); - list->element = nd; - list->next = NULL; - if (!IRO_LoopMemRefCurrent->list) { - IRO_LoopMemRefCurrent->list = list; - } else { - list->next = IRO_LoopMemRefCurrent->list; - IRO_LoopMemRefCurrent->list = list; - } - - if (((IROLinear *) rec->objRefs->element)->flags & IROLF_Assigned) { - IRO_LoopMemRefCurrent->flags |= LoopMemRef_2; - if (((IROLinear *) rec->objRefs->element)->flags & IROLF_Used) - IRO_LoopMemRefCurrent->flags |= LoopMemRef_1; - } else { - IRO_LoopMemRefCurrent->flags |= LoopMemRef_1; - } - - if (!mustreach1 && flag2) - IRO_LoopMemRefCurrent->flags |= LoopMemRef_8; - - if (mustreach1 || flag2) - IRO_LoopMemRefCurrent->flags &= ~LoopMemRef_10; - } -} - -void FindAssignmenttoInductionVar(IROLoop *loop, IRONode *fnode) { - IROLinear *nd; - UInt32 index; - - if (!loop->induction) { - loop->nd14 = NULL; - } else { - index = loop->induction->var->index; - for (nd = fnode->first; nd; nd = nd->next) { - Bv_Clear(IRO_VarKills); - IRO_GetKills(nd); - if (Bv_IsBitSet(index, IRO_VarKills)) - loop->nd14 = nd; - - if (nd == fnode->last) - break; - } - - if (loop->nd14 && loop->nd14->type != IROLinearOp2Arg) - loop->nd14 = NULL; - } -} - -static void ComputeIntWeight(IROLoop *loop, IROLinear *Int) { - loop->sizeBySomeMeasurement++; -} - -static IROLinear *IsTypconVar(IROLinear *nd) { - if (IS_LINEAR_MONADIC(nd, ETYPCON) && IRO_IsVariable(nd->u.monadic)) - return nd->u.monadic; - else - return NULL; -} - -IROLoop *ExtractLoopInfo(IRONode *fnode) { - Boolean flag30; - Boolean flag29; - Boolean flag28; - UInt32 counter27; - IROLoopInd *ind23; - Object *obj; - IROLinear *nd21; - IRONode *scanfnode; - IROLinear *left19; - IROLinear *right18; - IROLinear *tmp18; - IROLinear *scannd; - IROLinear *tmp; - VarRecord *var; - IROLoopInd *scanind; - IROLinear *left; - IROLinear *right; - UInt32 counter2; - UInt32 i; - IROLoop *loop; - - flag30 = 0; - flag29 = 0; - flag28 = 0; - counter27 = 0; - LoopNode = fnode; - - loop = oalloc(sizeof(IROLoop)); - loop->fnode = fnode; - nd21 = LoopNode->last->u.label.x4; - loop->nd18 = nd21; - loop->flags = 0; - loop->x8 = 0; - loop->nd14 = NULL; - loop->induction = NULL; - loop->index20 = -1; - loop->index24 = -1; - loop->sizeBySomeMeasurement = 0; - - if (nd21->type == IROLinearOp2Arg && IS_TYPE_INT(nd21->rtype)) { - ind23 = NULL; - left19 = nd21->u.diadic.left; - right18 = nd21->u.diadic.right; - if (IRO_IsVariable(left19) || (left19 = IsTypconVar(left19))) { - if ((var = IRO_FindVar(left19->u.monadic->u.node->data.objref, 0, 1))) { - scanind = FirstInd; - while (scanind && scanind->var != var) - scanind = scanind->next; - if (scanind) { - ind23 = scanind; - loop->flags |= LoopFlags_1; - loop->induction = scanind; - } - } - } - - if (IRO_IsVariable(right18) || (right18 = IsTypconVar(right18))) { - if ((var = IRO_FindVar(right18->u.monadic->u.node->data.objref, 0, 1))) { - scanind = FirstInd; - while (scanind && scanind->var != var) - scanind = scanind->next; - if (scanind) { - ind23 = scanind; - loop->flags &= ~LoopFlags_1; - loop->induction = scanind; - } - } - } - - if (ind23 && ind23->addConst > 0) { - if (loop->flags & LoopFlags_1) { - if ( - loop->nd18->type != IROLinearOp2Arg || - !(loop->nd18->nodetype == ELESS || loop->nd18->nodetype == EGREATER || loop->nd18->nodetype == ELESSEQU || loop->nd18->nodetype == EGREATEREQU) || - !loop->nd18->u.diadic.left || - !loop->nd18->u.diadic.left->rtype || - !IS_TYPE_INT(loop->nd18->u.diadic.left->rtype) || - !loop->nd18->u.diadic.right || - !loop->nd18->u.diadic.right->rtype || - !IS_TYPE_INT(loop->nd18->u.diadic.right->rtype) - ) { - loop->flags |= LP_IFEXPR_NON_CANONICAL; - return loop; - } - } else { - if ( - loop->nd18->type == IROLinearOp2Arg && - (loop->nd18->nodetype == EGREATER || loop->nd18->nodetype == EGREATEREQU) && - (left = loop->nd18->u.diadic.left) && - left->rtype && - IS_TYPE_INT(left->rtype) && - (right = loop->nd18->u.diadic.right) && - right->rtype && - IS_TYPE_INT(right->rtype) - ) { - loop->nd18->u.diadic.left = right; - loop->nd18->u.diadic.right = left; - if (loop->nd18->nodetype == EGREATER) - loop->nd18->nodetype = ELESS; - else if (loop->nd18->nodetype == EGREATEREQU) - loop->nd18->nodetype = ELESSEQU; - loop->flags |= LoopFlags_1; - } else if ( - loop->nd18->type == IROLinearOp2Arg && - (loop->nd18->nodetype == ELESS || loop->nd18->nodetype == ELESSEQU) && - (left = loop->nd18->u.diadic.left) && - left->rtype && - IS_TYPE_INT(left->rtype) && - (right = loop->nd18->u.diadic.right) && - right->rtype && - IS_TYPE_INT(right->rtype) - ) { - loop->nd18->u.diadic.left = right; - loop->nd18->u.diadic.right = left; - if (loop->nd18->nodetype == ELESS) - loop->nd18->nodetype = EGREATER; - else if (loop->nd18->nodetype == ELESSEQU) - loop->nd18->nodetype = EGREATEREQU; - loop->flags |= LoopFlags_1; - } else { - loop->flags |= LP_IFEXPR_NON_CANONICAL; - return loop; - } - } - } else { - loop->flags |= LP_INDUCTION_NOT_FOUND; - return loop; - } - } else if (nd21->type == IROLinearOp1Arg && IS_TYPE_INT(nd21->rtype)) { - if (nd21->nodetype == EPREINC || nd21->nodetype == EPOSTINC || nd21->nodetype == EPREDEC || nd21->nodetype == EPOSTDEC) { - if (IRO_IsVariable(nd21->u.monadic)) { - if ((var = IRO_FindVar(nd21->u.monadic->u.monadic->u.node->data.objref, 0, 1))) { - scanind = FirstInd; - while (scanind && scanind->var != var) - scanind = scanind->next; - if (scanind) { - ind23 = scanind; - loop->flags |= LoopFlags_10000; - loop->induction = scanind; - } else { - loop->flags |= LP_INDUCTION_NOT_FOUND; - return loop; - } - } else { - loop->flags |= LP_INDUCTION_NOT_FOUND; - return loop; - } - } else { - loop->flags |= LP_INDUCTION_NOT_FOUND; - return loop; - } - } else { - loop->flags |= LP_INDUCTION_NOT_FOUND; - return loop; - } - } else { - loop->flags |= LP_IFEXPR_NON_CANONICAL; - return loop; - } - - counter2 = 0; - scanind = FirstInd; - while (scanind) { - scanind = scanind->next; - counter2++; - } - - if (counter2 > 1) - loop->flags |= LP_HAS_MULTIPLE_INDUCTIONS; - - if ((scanind = loop->induction)) { - nd21 = scanind->nd; - if (nd21->type == IROLinearOp2Arg) { - if (IS_LINEAR_DIADIC_2(loop->nd18, ELESS, ELESSEQU)) { - if (nd21->nodetype == EADDASS) { - if (scanind->addConst == 1) - loop->flags |= LP_LOOP_STEP_ISADD; - if (scanind->addConst > 0) - loop->flags |= LP_LOOP_STEP_ISPOS; - } else if (nd21->nodetype == EASS && - IS_LINEAR_DIADIC(nd21->u.diadic.right, EADD) && - IRO_IsIntConstant(tmp18 = nd21->u.diadic.right->u.diadic.right) && - CTool_EndianReadWord32(&tmp18->u.node->data.intval.hi) == 0) { - if (CInt64_GetULong(&tmp18->u.node->data.intval) == 1) - loop->flags |= LP_LOOP_STEP_ISADD; - if (CInt64_GetULong(&tmp18->u.node->data.intval) > 0) - loop->flags |= LP_LOOP_STEP_ISPOS; - } - } - } else if (nd21->type == IROLinearOp1Arg) { - if (nd21->nodetype == EPREINC || nd21->nodetype == EPOSTINC) { - if (scanind->addConst == 1) - loop->flags |= LP_LOOP_STEP_ISADD; - if (scanind->addConst > 0) - loop->flags |= LP_LOOP_STEP_ISPOS; - } - if (nd21->nodetype == EPREDEC || nd21->nodetype == EPOSTDEC) { - if (scanind->addConst == 1) - loop->flags |= LoopFlags_2000; - if (scanind->addConst > 0) - loop->flags |= LP_LOOP_STEP_ISNEG; - } - } - loop->index24 = nd21->index; - loop->index20 = IRO_FindStart(nd21)->index; - } - - if (ind23) { - tmp = IRO_FindStart(fnode->last->u.diadic.right); - loop->flags |= LoopFlags_200; - if (loop->flags & LoopFlags_10000) { - for (scannd = loop->fnode->first; scannd && scannd != tmp; scannd = scannd->next) { - if (scannd->type != IROLinearLabel && scannd->type != IROLinearNop) - loop->flags &= ~LoopFlags_200; - } - } else { - for (scannd = ind23->nd->next; scannd && scannd != tmp; scannd = scannd->next){ - if (scannd->type != IROLinearLabel && scannd->type != IROLinearNop) - loop->flags &= ~LoopFlags_200; - } - for (scannd = loop->fnode->first; scannd && scannd != tmp; scannd = scannd->next){ - if ((scannd->index < loop->index20 || scannd->index > loop->index24) && scannd->type != IROLinearLabel && scannd->type != IROLinearNop) - loop->flags &= ~LoopFlags_200; - } - } - } - - for (scanfnode = IRO_FirstNode; scanfnode; scanfnode = scanfnode->nextnode) { - if (Bv_IsBitSet(scanfnode->index, InLoop) && scanfnode != fnode && (scannd = scanfnode->first)) { - while (1) { - if (scannd->type == IROLinearFunccall) - flag30 = 1; - if (scannd->type == IROLinearGoto) - flag28++; - if (flag28 >= 1) - flag29 = 1; - if (scannd->type == IROLinearIf || scannd->type == IROLinearIfNot || scannd->type == IROLinearSwitch || scannd->type == IROLinearReturn) - flag29 = 1; - - if (scannd->type == IROLinearAsm) - loop->flags |= LP_LOOP_HAS_ASM; - - if (!(scannd->flags & IROLF_Reffed) && scannd->type != IROLinearNop && scannd->type != IROLinearLabel) { - if (!IRO_IsAssignOp[scannd->nodetype]) { - loop->flags |= LoopFlags_8; - } else if (scannd->index < loop->index20 || scannd->index > loop->index24) { - counter27++; - if (IsAssignmentReductionCandidate(scannd) && counter27 == 1) - loop->flags |= LoopFlags_40000; - if (counter27 > 1) - loop->flags &= ~LoopFlags_40000; - } - } - - if (scannd->index < loop->index20 || scannd->index > loop->index24) { - if (IS_LINEAR_ENODE(scannd, EOBJREF)) { - obj = scannd->u.node->data.objref; - if ((scannd->flags & IROLF_Ind) && obj && obj == loop->induction->var->object) { - if (!(scannd->flags & IROLF_Assigned) && (scannd->flags & IROLF_Used)) { - IRO_Dump("Induction Used in loop\n"); - loop->flags |= LoopFlags_800; - } - } - } - - if (IS_LINEAR_DIADIC(scannd, ESHR) && - (obj = IRO_IsVariable(scannd->u.diadic.left)) && - IRO_IsIntConstant(scannd->u.diadic.right)) { - for (scanind = FirstInd; scanind; scanind = scanind->next) { - if (scanind->var->object == obj) { - IRO_Dump("Induction has DIV: %s\n", obj->name->name); - scanind->flags |= LoopInd_HasDiv; - } - } - } - - if (IS_LINEAR_DIADIC(scannd, EAND) && - (obj = IRO_IsVariable(scannd->u.diadic.left)) && - IRO_IsIntConstant(scannd->u.diadic.right)) { - for (scanind = FirstInd; scanind && obj; scanind = scanind->next) { - if (scanind->var->object == obj) { - IRO_Dump("Induction has MOD: %s\n", obj->name->name); - scanind->flags |= LoopInd_HasMod; - } - } - } - } - - ComputeIntWeight(loop, scannd); - if (scannd == scanfnode->last) - break; - scannd = scannd->next; - } - } - - if (flag30) - loop->flags |= LP_LOOP_HAS_CALLS; - if (flag29) - loop->flags |= LP_LOOP_HAS_CNTRLFLOW; - - for (i = 0; i < scanfnode->numsucc && scanfnode != fnode; i++) { - if (Bv_IsBitSet(scanfnode->index, InLoop) && !Bv_IsBitSet(scanfnode->succ[i], InLoop)) { - IRO_Dump("Node %d has an out of loop successor %d\n", scanfnode->index, scanfnode->succ[i]); - IRO_DumpBits("Loop includes: ", InLoop); - IRO_Dump("loop has multiple exits\n"); - loop->flags |= LoopFlags_1000; - } - } - } - - return loop; -} - -CLabel *BuildLabel(IROList *list) { - IROLinear *nd; - - nd = IRO_NewLinear(IROLinearLabel); - nd->index = IRO_NumLinear++; - nd->u.label.label = IRO_NewLabel(); - nd->flags |= IROLF_1; - IRO_AddToList(nd, list); - return nd->u.label.label; -} - -static void MoveInvarianceInAddressExpr(void) { - IRONode *fnode; - IROLinear *nd; - IROLinear *start; - IROList list; - - IRO_FirstExpr = IRO_LastExpr = NULL; - IRO_NumExprs = 0; - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - if (Bv_IsBitSet(fnode->index, InLoop)) { - for (nd = fnode->first; nd; nd = nd->next) { - if (nd->type == IROLinearOp1Arg && - (nd->nodetype == EINDIRECT || nd->nodetype == EINDIRECT) && - IS_LINEAR_DIADIC(nd->u.monadic, EADD)) { - RearrangeInvarianceInAddressExpr(nd->u.monadic, &list); - start = IRO_FindStart(nd->u.monadic); - IRO_LocateFather_Cut_And_Paste(nd->u.monadic, list.tail); - IRO_Paste(list.head, list.tail, start); - } - - if (nd == fnode->last) - break; - } - } - } - - IRO_UpdateFlagsOnInts(); -} - -static void AddAddendLinear(IROLinear *nd) { - IROElmList *list; - - if (IS_LINEAR_DIADIC(nd, EADD)) { - AddAddendLinear(nd->u.diadic.left); - AddAddendLinear(nd->u.diadic.right); - } else { - list = oalloc(sizeof(IROElmList)); - list->element = nd; - list->next = NULL; - if (FirstAddendLinear) - LastAddendLinear->next = list; - else - FirstAddendLinear = list; - LastAddendLinear = list; - } -} - -static IROLinear *RearrangeInvarianceInAddressExpr(IROLinear *nd, IROList *list) { - IROLinear *result; - IROElmList *scanlist; - IROElmList *elist; - IROLinear *scannd; - - IRO_InitList(list); - FirstAddendLinear = LastAddendLinear = NULL; - AddAddendLinear(nd->u.diadic.left); - AddAddendLinear(nd->u.diadic.right); - - elist = NULL; - result = NULL; - for (scanlist = FirstAddendLinear; scanlist; scanlist = scanlist->next) { - scannd = scanlist->element; - if (!IRO_IsIntConstant(scannd) && (scannd->flags & IROLF_LoopInvariant)) { - if (result) { - IROLinear *tmp = IRO_NewLinear(IROLinearOp2Arg); - tmp->index = ++IRO_NumLinear; - tmp->nodetype = EADD; - tmp->u.diadic.left = result; - tmp->u.diadic.right = IRO_DuplicateExpr(scannd, list); - IRO_AddToList(tmp, list); - tmp->flags |= IROLF_LoopInvariant; - tmp->flags |= IROLF_Reffed; - tmp->rtype = result->rtype; - result = tmp; - } else { - result = IRO_DuplicateExpr(scannd, list); - } - - if (elist) - elist->next = scanlist->next; - else - FirstAddendLinear = scanlist->next; - } else { - elist = scanlist; - } - } - - for (scanlist = FirstAddendLinear, elist = NULL; scanlist; scanlist = scanlist->next) { - scannd = scanlist->element; - if (!IRO_IsIntConstant(scannd)) { - if (result) { - IROLinear *tmp = IRO_NewLinear(IROLinearOp2Arg); - tmp->index = ++IRO_NumLinear; - tmp->nodetype = EADD; - tmp->u.diadic.left = result; - tmp->u.diadic.right = IRO_DuplicateExpr(scannd, list); - IRO_AddToList(tmp, list); - tmp->flags |= IROLF_Reffed; - tmp->rtype = result->rtype; - result = tmp; - } else { - result = IRO_DuplicateExpr(scannd, list); - } - - if (elist) - elist->next = scanlist->next; - else - FirstAddendLinear = scanlist->next; - } else { - elist = scanlist; - } - } - - for (scanlist = FirstAddendLinear; scanlist; scanlist = scanlist->next) { - scannd = scanlist->element; - if (result) { - IROLinear *tmp = IRO_NewLinear(IROLinearOp2Arg); - tmp->index = ++IRO_NumLinear; - tmp->nodetype = EADD; - tmp->u.diadic.left = result; - tmp->u.diadic.right = scannd; - tmp->u.diadic.right = IRO_DuplicateExpr(scannd, list); - IRO_AddToList(tmp, list); - tmp->flags |= IROLF_Reffed; - tmp->rtype = result->rtype; - result = tmp; - } else { - result = IRO_DuplicateExpr(scannd, list); - } - } - - return result; -} - -static IROLinear *FindAddendForReductionPattern(IROLinear *a, IROLinear *b, Boolean *resultFlag) { - IROLinear *left; - IROLinear *right; - IROLinear *node28; - Boolean subflag; - - left = b->u.diadic.left; - right = b->u.diadic.right; - if (b->nodetype == EADD || b->nodetype == ESUB) { - node28 = left; - while (IS_LINEAR_MONADIC(node28, ETYPCON)) - node28 = node28->u.monadic; - - if (IS_LINEAR_MONADIC(node28, EINDIRECT) && (node28->u.monadic->flags & IROLF_LoopInvariant) && IRO_ExprsSame(a, node28)) { - *resultFlag = 1; - return left; - } - - if (IS_LINEAR_DIADIC_2(node28, EADD, ESUB)) { - if ((node28 = FindAddendForReductionPattern(a, node28, &subflag))) { - *resultFlag = 1; - return node28; - } - } - } - - *resultFlag = 0; - if (b->nodetype == EADD) { - node28 = right; - while (IS_LINEAR_MONADIC(node28, ETYPCON)) - node28 = node28->u.monadic; - - if (IS_LINEAR_MONADIC(node28, EINDIRECT) && (node28->u.monadic->flags & IROLF_LoopInvariant) && IRO_ExprsSame(a, node28)) { - return right; - } - - if (IS_LINEAR_DIADIC_2(node28, EADD, ESUB)) { - if ((node28 = FindAddendForReductionPattern(a, node28, &subflag))) { - return node28; - } - } - } - - return NULL; -} - -static void ReorderOperandsForReductionPattern(IROLinear *a, IROLinear *b) { - IROLinear *left; - IROLinear *right; - IROLinear *addend; - IROLinear *tmp; - Boolean flag; - - left = b->u.diadic.left; - right = b->u.diadic.right; - - if (b->nodetype == EADD && (addend = FindAddendForReductionPattern(a, b, &flag)) && addend != left) { - if (flag && IS_LINEAR_DIADIC_2(left, EADD, ESUB) && addend->rtype == right->rtype) { - tmp = left; - b->u.diadic.left = right; - left = right; - b->u.diadic.right = tmp; - right = tmp; - flag = 0; - } - - if (!flag && IS_LINEAR_DIADIC_2(right, EADD, ESUB) && addend->rtype == left->rtype) { - if (IRO_LocateFather_Cut_And_Paste_Without_Nopping(addend, left)) - b->u.diadic.left = addend; - } - } -} - -static UInt32 IsAssignmentReductionCandidate(IROLinear *nd) { - IROLinear *left; - IROLinear *right; - IROLinear *tmp; - - if (nd->type == IROLinearOp2Arg) { - if (nd->nodetype == EASS) { - left = nd->u.diadic.left; - right = nd->u.diadic.right; - if (IS_LINEAR_MONADIC(left, EINDIRECT) && (left->u.monadic->flags & IROLF_LoopInvariant)) { - if (IS_LINEAR_MONADIC(right, ETYPCON) && - right->rtype->type == right->u.monadic->rtype->type && - IS_TYPE_INT(right->rtype) && - right->rtype->size < right->u.monadic->rtype->size) - right = right->u.monadic; - - if (IS_LINEAR_DIADIC_2(right, EADD, ESUB)) { - ReorderOperandsForReductionPattern(left, right); - tmp = right->u.diadic.left; - if (IS_LINEAR_MONADIC(tmp, ETYPCON)) - tmp = tmp->u.monadic; - if (IS_LINEAR_MONADIC(tmp, EINDIRECT) && - (tmp->u.monadic->flags & IROLF_LoopInvariant) && - IRO_ExprsSame(left, tmp) && - right->u.diadic.right->type == IROLinearOp2Arg) { - if (right->u.diadic.right->nodetype == EADD) - return 1; - if (right->u.diadic.right->nodetype == ESUB) - return 1; - if (right->u.diadic.right->nodetype == EMUL) - return 1; - if (right->u.diadic.right->nodetype == EDIV) - return 1; - } - } - } - } else if (nd->nodetype == EADDASS || nd->nodetype == ESUBASS) { - left = nd->u.diadic.left; - right = nd->u.diadic.right; - - if (IS_LINEAR_MONADIC(right, ETYPCON) && - right->rtype->type == right->u.monadic->rtype->type && - IS_TYPE_INT(right->rtype) && - right->rtype->size < right->u.monadic->rtype->size) - right = right->u.monadic; - - if (IS_LINEAR_MONADIC(left, EINDIRECT) && - (left->u.monadic->flags & IROLF_LoopInvariant) && - right->type == IROLinearOp2Arg) { - if (right->nodetype == EADD) - return 1; - if (right->nodetype == ESUB) - return 1; - if (right->nodetype == EMUL) - return 1; - if (right->nodetype == EDIV) - return 1; - } - } - } - - return 0; -} - diff --git a/compiler_and_linker/unsorted/IroMalloc.c b/compiler_and_linker/unsorted/IroMalloc.c deleted file mode 100644 index 8928ba9..0000000 --- a/compiler_and_linker/unsorted/IroMalloc.c +++ /dev/null @@ -1,564 +0,0 @@ -#include "compiler/IroMalloc.h" -#include "compiler/CompilerTools.h" - -#define FLAGMASK 0xF - -typedef struct Block { - struct Block *prev; - struct Block *next; - void *x8; - void *xC; - size_t remain; - size_t x14; -} Block; - -typedef struct SubBlockBase { - size_t x0; - Block *block; -} SubBlockBase; - -typedef struct SubBlock { - size_t x0; - Block *block; - struct SubBlock *x8; - struct SubBlock *xC; -} SubBlock; - -typedef struct SubBlockTail { - size_t x0copy; -} SubBlockTail; - -typedef struct BlockTail { - size_t x14copy; - SubBlock *unk; -} BlockTail; - -typedef struct FixStart { - struct FixBlock *a; - struct FixSubBlock *b; - long count; -} FixStart; - -typedef struct FixBlock { - struct FixBlock *prev; - struct FixBlock *next; - size_t entrysize; -} FixBlock; - -typedef struct FixSubBlockBase { - FixBlock *fixblock; -} FixSubBlockBase; - -typedef struct FixSubBlock { - FixBlock *fixblock; - struct FixSubBlock *next; -} FixSubBlock; - -static const size_t fix_pool_sizes[] = {0xC, 0x1C, 0x2C, 0x4C}; -static Block *start_; -static FixStart fix_start[4]; -static int initialized; - -// forward decls -static void Block_link(Block *block, SubBlock *subblock); -static void Block_unlink(Block *block, SubBlock *subblock); -static void SubBlock_construct(SubBlock *subblock, size_t size, Block *block, int flag1, int flag2); -static SubBlock *SubBlock_split(SubBlock *subblock, size_t pos); -static SubBlock *SubBlock_merge_prev(SubBlock *subblock, SubBlock **sbptr); -static void SubBlock_merge_next(SubBlock *subblock, SubBlock **sbptr); - -#define BLOCK_TAIL(block) ((BlockTail *) ((long) (block) + ((block)->x14 & ~FLAGMASK) - sizeof(BlockTail))) - -#define BUF_LOCATOR(buf) (*((size_t *) ((long) (buf) - sizeof(size_t)))) -#define SBB_BLOCK(sbb) ((Block *) ((long) ((sbb)->block) & ~1)) - -#define BUF_IS_VAR(buf) (BUF_LOCATOR(buf) & 1) -#define VARBUF_SBB(buf) ((SubBlockBase *) ((long) (buf) - sizeof(SubBlockBase))) -#define VARBUF_SB(buf) ((SubBlock *) ((long) (buf) - sizeof(SubBlockBase))) -#define VARBUF_BLOCKSIZE(buf) (VARBUF_SBB(buf)->x0 & ~FLAGMASK) -#define VARBUF_SIZE(buf) (((VARBUF_SBB(buf)->x0 & ~FLAGMASK) - sizeof(SubBlockBase))) -#define VARBUF_BLOCK(buf) SBB_BLOCK(VARBUF_SBB(buf)) -#define FIXBUF_SIZE(buf) (((FixBlock *) BUF_LOCATOR(buf))->entrysize) - -#define BUF_SIZE(buf) BUF_IS_VAR(buf) ? VARBUF_SIZE(buf) : FIXBUF_SIZE(buf) - -static void Block_construct(Block *block, size_t size) { - SubBlock *subblock; - - block->x14 = size | 3; - ((BlockTail *) ((long) block + size - sizeof(BlockTail)))->x14copy = block->x14; - - subblock = (SubBlock *) (block + 1); - SubBlock_construct(subblock, size - sizeof(Block) - sizeof(BlockTail), block, 0, 0); - - block->remain = size - sizeof(Block) - sizeof(BlockTail); - BLOCK_TAIL(block)->unk = NULL; - - Block_link(block, subblock); -} - -static SubBlock *Block_subBlock(Block *block, size_t size) { - SubBlock *subblock; - size_t check; - size_t best; - - if (!BLOCK_TAIL(block)->unk) - return NULL; - - subblock = BLOCK_TAIL(block)->unk; - best = subblock->x0 & ~FLAGMASK; - check = subblock->x0 & ~FLAGMASK; - while (check < size) { - subblock = subblock->xC; - check = subblock->x0 & ~FLAGMASK; - if (best < check) - best = check; - if (subblock == BLOCK_TAIL(block)->unk) { - block->remain = best; - return NULL; - } - } - - if ((check - size) >= 0x60) - SubBlock_split(subblock, size); - - BLOCK_TAIL(block)->unk = subblock->xC; - Block_unlink(block, subblock); - return subblock; -} - -static void Block_link(Block *block, SubBlock *subblock) { - size_t size; - SubBlock **sbptr; - - size = subblock->x0 & ~FLAGMASK; - subblock->x0 &= ~2; - ((SubBlock *) ((long) subblock + size))->x0 &= ~4; - ((SubBlockTail *) ((long) subblock + size - sizeof(SubBlockTail)))->x0copy = size; - - sbptr = &BLOCK_TAIL(block)->unk; - if (*sbptr) { - subblock->x8 = (*sbptr)->x8; - subblock->x8->xC = subblock; - subblock->xC = *sbptr; - (*sbptr)->x8 = subblock; - *sbptr = subblock; - *sbptr = SubBlock_merge_prev(*sbptr, sbptr); - SubBlock_merge_next(*sbptr, sbptr); - } else { - *sbptr = subblock; - subblock->x8 = subblock; - subblock->xC = subblock; - } - - if (block->remain < ((*sbptr)->x0 & ~FLAGMASK)) - block->remain = (*sbptr)->x0 & ~FLAGMASK; -} - -static void Block_unlink(Block *block, SubBlock *subblock) { - size_t size; - SubBlock **sbptr; - - size = subblock->x0 & ~FLAGMASK; - subblock->x0 |= 2; - ((SubBlock *) ((long) subblock + size))->x0 |= 4; - - sbptr = &BLOCK_TAIL(block)->unk; - if (*sbptr == subblock) - *sbptr = subblock->xC; - - if (*sbptr == subblock) { - *sbptr = NULL; - block->remain = 0; - } else { - subblock->xC->x8 = subblock->x8; - subblock->x8->xC = subblock->xC; - } -} - -static void SubBlock_construct(SubBlock *subblock, size_t size, Block *block, int flag1, int flag2) { - subblock->block = (Block *) ((long) block | 1); - subblock->x0 = size; - if (flag1) - subblock->x0 |= 4; - if (flag2) { - subblock->x0 |= 2; - ((SubBlock *) (((long) subblock) + size))->x0 |= 4; - } else { - ((SubBlockTail *) (((long) subblock) + size - sizeof(SubBlockTail)))->x0copy = size; - } -} - -static SubBlock *SubBlock_split(SubBlock *subblock, size_t pos) { - size_t oldsize; - int flag; - SubBlock *splitright; - Block *block; - - oldsize = subblock->x0 & ~FLAGMASK; - flag = !(subblock->x0 & 2); - splitright = (SubBlock *) ((long) subblock + pos); - block = (Block *) ((long) subblock->block & ~1); - SubBlock_construct(subblock, pos, block, subblock->x0 & 4, !flag); - SubBlock_construct(splitright, oldsize - pos, block, !flag, !flag); - if (flag) { - splitright->xC = subblock->xC; - splitright->xC->x8 = splitright; - splitright->x8 = subblock; - subblock->xC = splitright; - } - - return splitright; -} - -static SubBlock *SubBlock_merge_prev(SubBlock *subblock, SubBlock **sbptr) { - size_t prevsize; - SubBlock *prevblock; - - if (!(subblock->x0 & 4)) { - prevsize = ((SubBlockTail *) ((long) subblock - sizeof(SubBlockTail)))->x0copy; - if (prevsize & 2) - return subblock; - - prevblock = (SubBlock *) ((long) subblock - prevsize); - prevblock->x0 = prevblock->x0 & FLAGMASK; - prevblock->x0 |= (prevsize + (subblock->x0 & ~FLAGMASK)) & ~FLAGMASK; - if (!(prevblock->x0 & 2)) - ((SubBlockTail *) ((long) prevblock + prevsize + (subblock->x0 & ~FLAGMASK) - sizeof(SubBlockTail)))->x0copy = prevsize + (subblock->x0 & ~FLAGMASK); - - if (*sbptr == subblock) - *sbptr = (*sbptr)->xC; - - subblock->xC->x8 = subblock->x8; - subblock->xC->x8->xC = subblock->xC; - return prevblock; - } - - return subblock; -} - -static void SubBlock_merge_next(SubBlock *subblock, SubBlock **sbptr) { - SubBlock *nextblock; - size_t nextsize; - - nextblock = (SubBlock *) ((long) subblock + (subblock->x0 & ~FLAGMASK)); - if (!(nextblock->x0 & 2)) { - nextsize = (subblock->x0 & ~FLAGMASK) + (nextblock->x0 & ~FLAGMASK); - subblock->x0 = subblock->x0 & FLAGMASK; - subblock->x0 |= nextsize & ~FLAGMASK; - - if (!(subblock->x0 & 2)) - ((SubBlockTail *) ((long) subblock + nextsize - sizeof(SubBlockTail)))->x0copy = nextsize; - - if (!(subblock->x0 & 2)) - ((SubBlock *) ((long) subblock + nextsize))->x0 &= ~4; - else - ((SubBlock *) ((long) subblock + nextsize))->x0 |= 4; - - if (*sbptr == nextblock) - *sbptr = (*sbptr)->xC; - if (*sbptr == nextblock) - *sbptr = NULL; - - nextblock->xC->x8 = nextblock->x8; - nextblock->x8->xC = nextblock->xC; - } -} - -static void link_block(Block *block) { - if (start_) { - block->prev = start_->prev; - block->prev->next = block; - block->next = start_; - - start_->prev = block; - start_ = block; - } else { - start_ = block; - block->prev = block; - block->next = block; - } -} - -static Block *unlink_block(Block *block) { - Block *newblock; - - newblock = block->next; - if (newblock == block) - newblock = NULL; - - if (start_ == block) - start_ = newblock; - - if (newblock) { - newblock->prev = block->prev; - newblock->prev->next = newblock; - } - - block->prev = block->next = NULL; - return newblock; -} - -static Block *link_new_block(size_t size) { - Block *block; - - size = (size + 0x1000 + sizeof(Block) + sizeof(BlockTail) - 1) & ~0xFFF; - if (size < 0x10000) - size = 0x10000; - - if (!(block = galloc(size))) - return NULL; - - Block_construct(block, size); - link_block(block); - return block; -} - -static void *allocate_from_var_pools(size_t size) { - Block *block; - SubBlock *subblock; - - size = (size + sizeof(Block) - 1) & ~0xF; - if (size < 0x60) - size = 0x60; - - block = start_ ? start_ : link_new_block(size); - if (!block) - return NULL; - - do { - if (size <= block->remain) { - if ((subblock = Block_subBlock(block, size))) { - start_ = block; - goto allocated; - } - } - } while ((block = block->next) != start_); - - block = link_new_block(size); - if (!block) - return NULL; - subblock = Block_subBlock(block, size); -allocated: - return (SubBlockBase *) subblock + 1; -} - -static void deallocate_from_var_pools(void *buf) { - Block *block; - SubBlock *subblock; - int flag; - - subblock = (SubBlock *) ((long) buf - sizeof(SubBlockBase)); - block = (Block *) ((long) subblock->block & ~1); - Block_link(block, subblock); - - flag = 0; - subblock = (SubBlock *) (block + 1); - if (!(subblock->x0 & 2)) { - if ((subblock->x0 & ~FLAGMASK) == ((block->x14 & ~FLAGMASK) - sizeof(Block) - sizeof(BlockTail))) - flag = 1; - } - - if (flag) - unlink_block(block); -} - -static void FixBlock_construct(FixBlock *fixblock, FixBlock *prev, FixBlock *next, int poolIndex, void *buffer, size_t buffersize) { - size_t entrysize; - size_t entrycount; - size_t i; - FixSubBlock *fsb; - FixSubBlock *fsbnext; - - fixblock->prev = prev; - fixblock->next = next; - fixblock->entrysize = fix_pool_sizes[poolIndex]; - - entrysize = fix_pool_sizes[poolIndex] + sizeof(void *); - entrycount = (buffersize / entrysize); - fsb = buffer; - for (i = 0; i < (entrycount - 1); i++) { - fsbnext = (FixSubBlock *) ((long) fsb + entrysize); - fsb->fixblock = fixblock; - fsb->next = fsbnext; - fsb = fsbnext; - } - - fsb->fixblock = fixblock; - fsb->next = fix_start[poolIndex].b; - fix_start[poolIndex].b = buffer; -} - -static void *allocate_from_fixed_pools(size_t size) { - int poolIndex; - FixSubBlock *fsb; - - poolIndex = 0; - while (size > fix_pool_sizes[poolIndex]) - poolIndex++; - - if (!fix_start[poolIndex].b) { - void *buf; - size_t bufsize; - - buf = allocate_from_var_pools(4000); - if (!buf) - return NULL; - - bufsize = !BUF_IS_VAR(buf) ? FIXBUF_SIZE(buf) : VARBUF_SIZE(buf); - FixBlock_construct( - buf, NULL, fix_start[poolIndex].a, poolIndex, - ((FixBlock *) buf) + 1, - bufsize - sizeof(FixBlock) - ); - fix_start[poolIndex].a = buf; - } - - fsb = fix_start[poolIndex].b; - fix_start[poolIndex].b = fsb->next; - fix_start[poolIndex].count++; - return ((FixSubBlockBase *) fsb) + 1; -} - -static void deallocate_from_fixed_pools(void *buf, size_t size) { - int poolIndex; - FixBlock *fixblock; - FixBlock *nextfb; - FixSubBlock *fsb; - - poolIndex = 0; - while (size > fix_pool_sizes[poolIndex]) - poolIndex++; - - fsb = (FixSubBlock *) ((long) buf - sizeof(FixSubBlockBase)); - fsb->next = fix_start[poolIndex].b; - fix_start[poolIndex].b = fsb; - if (--fix_start[poolIndex].count == 0) { - fixblock = fix_start[poolIndex].a; - while (fixblock) { - nextfb = fixblock->next; - deallocate_from_var_pools(fixblock); - fixblock = nextfb; - } - fix_start[poolIndex].a = NULL; - fix_start[poolIndex].b = NULL; - } -} - -size_t IRO_msize(void *buf) { - return BUF_SIZE(buf); -} - -void *IRO_malloc(size_t size) { - if (!size) - return NULL; - - if (size <= 0x4C) - return allocate_from_fixed_pools(size); - else - return allocate_from_var_pools(size); -} - -void IRO_free(void *buf) { - if (buf) { - size_t size = !BUF_IS_VAR(buf) ? FIXBUF_SIZE(buf) : VARBUF_SIZE(buf); - - if (size <= 0x4C) - deallocate_from_fixed_pools(buf, size); - else - deallocate_from_var_pools(buf); - } -} - -void *IRO_realloc(void *buf, size_t newsize) { - size_t oldsize; - size_t newblocksize; - void *newbuf; - - if (!buf) - return IRO_malloc(newsize); - - if (!newsize) { - IRO_free(buf); - return NULL; - } - - oldsize = !BUF_IS_VAR(buf) ? FIXBUF_SIZE(buf) : VARBUF_SIZE(buf); - if (newsize > oldsize) { - if (BUF_IS_VAR(buf)) { - newblocksize = (newsize + sizeof(Block) - 1) & ~FLAGMASK; - if (newblocksize < 0x60) - newblocksize = 0x60; - SubBlock_merge_next(VARBUF_SB(buf), &BLOCK_TAIL(VARBUF_BLOCK(buf))->unk); - if (VARBUF_BLOCKSIZE(buf) >= newblocksize) { - if ((VARBUF_BLOCKSIZE(buf) - newblocksize) >= 0x60) { - Block_link(VARBUF_BLOCK(buf), SubBlock_split(VARBUF_SB(buf), newblocksize)); - } - return buf; - } - } - - newbuf = IRO_malloc(newsize); - if (!newbuf) - return NULL; - - memcpy(newbuf, buf, oldsize); - IRO_free(buf); - return newbuf; - } - - if (BUF_IS_VAR(buf)) { - newsize = (newsize + sizeof(Block) - 1) & ~FLAGMASK; - if (newsize < 0x60) - newsize = 0x60; - if ((VARBUF_BLOCKSIZE(buf) - newsize) >= 0x60) { - Block_link(VARBUF_BLOCK(buf), SubBlock_split(VARBUF_SB(buf), newsize)); - } - } - - return buf; -} - -void *IRO_calloc(size_t a, size_t b) { - void *buf; - size_t len = b * a; - buf = IRO_malloc(len); - if (buf) - memset(buf, 0, len); - return buf; -} - -void IRO_pool_free_all(void) { - int i; - Block *block; - if ((block = start_)) { - do { - block = block->next; - } while (block != start_); - start_ = NULL; - - for (i = 0; i < 4; i++) { - fix_start[i].a = NULL; - fix_start[i].b = NULL; - fix_start[i].count = 0; - } - } -} - -void IRO_InitializeAllocator(void) { - if (!initialized) { - int i; - for (i = 0; i < 4; i++) { - fix_start[i].a = NULL; - fix_start[i].b = NULL; - fix_start[i].count = 0; - } - start_ = NULL; - initialized = 1; - } -} - -void IRO_TerminateAllocator(void) { - initialized = 0; -} - diff --git a/compiler_and_linker/unsorted/IroPointerAnalysis.c b/compiler_and_linker/unsorted/IroPointerAnalysis.c deleted file mode 100644 index 4fcb8d3..0000000 --- a/compiler_and_linker/unsorted/IroPointerAnalysis.c +++ /dev/null @@ -1,5734 +0,0 @@ -#include "compiler/IroPointerAnalysis.h" -#include "compiler/IroEval.h" -#include "compiler/IroFlowgraph.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroMalloc.h" -#include "compiler/IroUtil.h" -#include "compiler/IroVars.h" -#include "compiler/CDecl.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CScope.h" -#include "compiler/InlineAsmPPC.h" -#include "compiler/CompilerTools.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler_and_linker/unsorted/IroPointerAnalysisADTs.c" - -// forward decls -static Object *GetLocalObject(PALocalVar *local, Object *proc, Boolean flag); -static Boolean GetActualLocsOfExtendedParam(LocationSetSet *set, LocationSet *ls, Object *var, Stack **stackPtr, ParamMappingFunction *map, Boolean flag); -static int ExpandLocationSetSetToActuals(Stack **stackPtr, ParamMappingFunction *map, LocationSetSet *thingsPointedTo); -static Boolean Lookup(LocationSetSet *set, Stack **stackPtr, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf, LocationSet *dst, PointsToFunction *pointsToFunc, Boolean unk, Type *indRtype); -static ExtendedParam *CreateExtendedParam(Stack **stackPtr, ParamMappingFunction *map, Object *var, Boolean *result); -static Boolean Assign(PartialTransferFunction *ptf, LocationSet *dst, LocationSetSet *srcs, Object *proc, IROLinear *nd, IRONode *fnode); -static ObjectList *FunctionArguments(Object *proc); -static IRONode **FunctionNodeTable(Object *proc); -static Boolean ApplySummary(PartialTransferFunction *tgtPTF, ParamMappingFunction *tgtMap, Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf, ParamMappingFunction *map, Boolean flag); -static PartialTransferFunction *GetPTF(ParamMappingFunction *map, Object *proc, IROLinear *nd, PartialTransferFunction *ptf, Boolean *needVisit); -static Boolean ObjectIsAFunctionArgument(Object *proc, Object *obj); -static Boolean ObjectIsARealFunctionArgument(Object *proc, Object *obj); -static void EvalProc(Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf); -static void FindGlobalObjectAction(Object *object, void *refcon); - -static Boolean ObjectIsRestrictQualified(Object *obj) { - return (CParser_GetTypeQualifiers(obj->type, obj->qual) & Q_RESTRICT) != 0; -} - -static Boolean LocationIsVolatile(LocationSet *loc, Object *proc) { - Boolean result; - Type *rtype; - - IRO_ASSERT(932, loc != NULL); - IRO_ASSERT(933, proc != NULL); - - result = 0; - - if ((rtype = LocationSet_rtype(loc))) { - UInt32 qual; - switch (rtype->type) { - case TYPEARRAY: - qual = TYPE_POINTER(rtype)->qual; - break; - case TYPEPOINTER: - qual = TYPE_POINTER(rtype)->qual; - break; - case TYPEMEMBERPOINTER: - qual = TYPE_MEMBER_POINTER(rtype)->qual; - break; - default: - qual = 0; - } - if (qual & Q_VOLATILE) - result = 1; - } - - if (!result && !LocationSet_IsUnknown(loc)) { - Object *obj = NULL; - PAMemoryBlock *block = LocationSet_block(loc); - - switch (PAMemoryBlock_kind(block)) { - case PAMEMORYBLOCKKIND_LOCALVAR: { - PALocalVar *local = PAMemoryBlock_thing(block); - if (local) - obj = GetLocalObject(local, proc, 0); - break; - } - case PAMEMORYBLOCKKIND_EXTENDEDPARAM: { - ExtendedParam *ep = PAMemoryBlock_thing(block); - if (ep) { - ObjectSet *objSet = ExtendedParam_objectSet(ep); - if (objSet) { - if (ObjectSet_Count(objSet) == 1) - obj = ObjectSet_FindFirst(objSet); - else - ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); - } - } - break; - } - } - - if (obj && is_volatile_object(obj)) - result = 1; - } - - return result; -} - -static Object *GetLocalObject(PALocalVar *local, Object *proc, Boolean flag) { - ObjectList *list; - Object *arg; - Object *obj; - char *name; - - IRO_ASSERT(999, local != NULL); - IRO_ASSERT(1000, proc != NULL); - - obj = PALocalVar_Get0_sub_4847E0(local); - name = PALocalVar_Get4_sub_4847D0(local); - - if (proc != &stUnknown && !obj && name && name[0] && flag) { - for (list = FunctionArguments(proc); list && !obj; list = list->next) { - arg = list->object; - if (arg && arg != &stUnknown && arg->name && arg->name->name) { - if (!strcmp(arg->name->name, name)) - obj = arg; - } - } - } - - if (obj) - PALocalVar_SetSth_sub_4847C0(local, obj); - - return obj; -} - -static Boolean ObjectIsAnExtendedParamCandidate(Object *obj) { - IRO_ASSERT(1042, obj != NULL); - - return Inline_IsObjectData(obj) || - obj->datatype == DABSOLUTE || - obj->datatype == DFUNC || - obj->datatype == DVFUNC || - obj->datatype == DINLINEFUNC; -} - -static Boolean ObjectIsAFunction(Object *obj) { - IRO_ASSERT(1054, obj != NULL); - - return obj->datatype == DFUNC || - obj->datatype == DVFUNC || - obj->datatype == DINLINEFUNC; -} - -static Boolean LocationSetRepresentsSingleLocation(LocationSet *ls, Object *proc, PointsToFunction *pointsToFunc) { - Boolean result; - PAMemoryBlock *mb; - PAMemoryBlockKind kind; - ExtendedParam *ep; - ObjectSet *objSet; - - IRO_ASSERT(1073, ls != NULL); - IRO_ASSERT(1074, proc == NULL || proc != NULL); - IRO_ASSERT(1075, pointsToFunc == NULL || pointsToFunc != NULL); - - result = 1; - if (LocationSet_IsUnknown(ls) || LocationSet_stride(ls)) { - result = 0; - } else { - mb = LocationSet_block(ls); - IRO_ASSERT(1084, mb != NULL); - - kind = PAMemoryBlock_kind(mb); - if (kind == PAMEMORYBLOCKKIND_HEAPBLOCK) { - result = 0; - } else if (kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { - ep = PAMemoryBlock_thing(mb); - if (!ep) { - result = 0; - } else { - if ((objSet = ExtendedParam_objectSet(ep)) && ObjectSet_Count(objSet) > 1) { - Object *obj = NULL; - ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); - - if (!obj) { - LocationSetSet *lss; - LocationSet *tmp; - ExtendedParam *ep; - ObjectSet *objSet; - - lss = LocationSetSet_New(); - LocationSetSet_Init(lss); - GetActualLocsOfExtendedParam(lss, ls, NULL, &stCallingContextStack, NULL, 0); - if ( - LocationSetSet_Count(lss) != 1 || - !(tmp = LocationSetSet_FindFirst(lss)) || - LocationSet_IsUnknown(tmp) || - (!((mb = LocationSet_block(tmp)) && (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) && (ep = PAMemoryBlock_thing(mb)) && (objSet = ExtendedParam_objectSet(ep)) && (ObjectSet_Count(objSet) == 1) && - ObjectIsAnExtendedParamCandidate(ObjectSet_FindFirst(objSet))) && - !LocationSetRepresentsSingleLocation(tmp, proc, pointsToFunc)) - ) - result = 0; - - LocationSetSet_Term(lss); - LocationSetSet_Delete(lss); - } - } - } - } - } - - return result; -} - -static void EvalExprAction(LocationSet *ls, void *refcon) { - CInt64 value; - UInt32 stride; - PAMemoryBlock *mb; - - IRO_ASSERT(1151, ls != NULL); - IRO_ASSERT(1152, !LocationSet_IsUnknown(ls)); - IRO_ASSERT(1153, refcon != NULL); - - value = *((CInt64 *) refcon); - stride = LocationSet_stride(ls); - mb = LocationSet_block(ls); - - if (mb && PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT) { - Type *rtype = LocationSet_rtype(ls); - LocationSet_Term(ls); - value = CInt64_Add(value, *((CInt64 *) PAMemoryBlock_thing(mb))); - mb = PAMemoryBlock_New(); - PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value); - LocationSet_InitKnown(ls, mb, cint64_zero, stride, rtype); - } else { - value = CInt64_Add(value, LocationSet_field(ls)); - if (stride) { - CInt64 strideval; - CInt64_SetLong(&strideval, stride); - value = CInt64_Mod(value, strideval); - } - SetsLocationSetField_sub_4851B0(ls, value); - } -} - -static void EvalExprAction2(LocationSet *ls, void *refcon) { - UInt32 value; - - IRO_ASSERT(1188, ls != NULL); - IRO_ASSERT(1189, !LocationSet_IsUnknown(ls)); - IRO_ASSERT(1190, refcon != NULL); - - value = CInt64_GetULong((CInt64 *) refcon); - if (value) { - SetsLocationSetField_sub_4851B0(ls, CInt64_Mod(LocationSet_field(ls), *((CInt64 *) refcon))); - } - SetsLocationSetStride_sub_4852D0(ls, value); -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct EvalExprAction3Params { - LocationSetSet *set; - Stack **stackPtr; - Object *proc; - ParamMappingFunction *map; - PartialTransferFunction *ptf; - PointsToFunction *pointsToFunc; - Type *indRtype; - Boolean x1C; -} EvalExprAction3Params; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void EvalExprAction3(LocationSet *ls, void *refcon) { - EvalExprAction3Params *params; - - IRO_ASSERT(1219, ls != NULL); - IRO_ASSERT(1220, refcon != NULL); - - params = refcon; - - params->x1C |= Lookup( - params->set, - params->stackPtr, - params->proc, - params->map, - params->ptf, - ls, - params->pointsToFunc, - 1, - params->indRtype - ); -} - -static void EvalExprAction4(LocationSet *ls, void *refcon) { - Type *type; - PAMemoryBlock *mb; - - IRO_ASSERT(1235, ls != NULL); - IRO_ASSERT(1236, refcon != NULL); - - type = refcon; - - if (LocationSet_IsUnknown(ls)) { - LocationSet_SetRtype(ls, type); - } else if ((mb = LocationSet_block(ls))) { - if (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT) { - CInt64 value; - CInt64 field; - UInt32 stride; - - value = *((CInt64 *) PAMemoryBlock_thing(mb)); - IRO_TruncateValueToType(&value, type); - field = LocationSet_field(ls); - IRO_TruncateValueToType(&field, type); - stride = LocationSet_stride(ls); - LocationSet_Term(ls); - - mb = PAMemoryBlock_New(); - PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value); - - LocationSet_InitKnown(ls, mb, field, stride, type); - } - LocationSet_SetRtype(ls, type); - } -} - -static Boolean EvalExpr(LocationSetSet *set, Object *proc, IROLinear *Int, Stack **stackPtr, ParamMappingFunction *map, PartialTransferFunction *ptf) { - Boolean result; - LocationSetSet *lss; - LocationSetSet *lss2; - IROLinear *indirect; - EvalExprAction3Params params; - IROLinear *originalInt; - - IRO_ASSERT(1284, set == NULL || set != NULL); - IRO_ASSERT(1285, proc != NULL); - IRO_ASSERT(1286, Int != NULL); - IRO_ASSERT(1287, map == NULL || map != NULL); - IRO_ASSERT(1288, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); - - result = 0; - lss = LocationSetSet_New(); - LocationSetSet_Init(lss); - - originalInt = Int; - while (Int && Int->type == IROLinearOp1Arg && Int->nodetype == ETYPCON) - Int = Int->u.monadic; - - IRO_ASSERT(1302, Int != NULL); - - if (IRO_IsAssignment(Int)) { - if (Int->type == IROLinearOp1Arg) - indirect = Int->u.monadic; - else - indirect = Int->u.diadic.left; - IRO_ASSERT(1310, indirect->type == IROLinearOp1Arg && indirect->nodetype == EINDIRECT); - - lss2 = LocationSetSet_New(); - LocationSetSet_Init(lss2); - result |= EvalExpr(lss2, proc, indirect->u.monadic, stackPtr, map, ptf); - - memset(¶ms, 0, sizeof(params)); - params.set = lss; - params.stackPtr = stackPtr; - params.proc = proc; - params.map = map; - params.ptf = ptf; - if (Int->nodetype == EPOSTINC || Int->nodetype == EPOSTDEC) - params.pointsToFunc = indirect->pointsToFunction; - else - params.pointsToFunc = Int->pointsToFunction; - params.indRtype = indirect->rtype; - params.x1C = 0; - LocationSetSet_ForEach(lss2, EvalExprAction3, ¶ms); - result |= params.x1C; - LocationSetSet_Term(lss2); - LocationSetSet_Delete(lss2); - } else if (Int->type == IROLinearFunccall) { - IRO_ASSERT(1338, Int->u.funccall.returnedLocs != NULL); - LocationSetSet_AddSet(lss, Int->u.funccall.returnedLocs); - } else if (Int->type == IROLinearOp1Arg && Int->nodetype == EINDIRECT) { - lss2 = LocationSetSet_New(); - LocationSetSet_Init(lss2); - result |= EvalExpr(lss2, proc, Int->u.monadic, stackPtr, map, ptf); - - memset(¶ms, 0, sizeof(params)); - params.set = lss; - params.stackPtr = stackPtr; - params.proc = proc; - params.map = map; - params.ptf = ptf; - params.pointsToFunc = Int->pointsToFunction; - params.indRtype = Int->rtype; - params.x1C = 0; - LocationSetSet_ForEach(lss2, EvalExprAction3, ¶ms); - result |= params.x1C; - LocationSetSet_Term(lss2); - LocationSetSet_Delete(lss2); - } else if (Int->type == IROLinearOp2Arg && Int->nodetype == EADD) { - IROAddrRecord *addr = IRO_InitAddrRecordPointer(Int); - IRO_DecomposeAddressExpression(Int, addr); - if (addr->numObjRefs > 1) { - LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); - } else { - CInt64 value; - CInt64 max; - CInt64 work; - Boolean flag1; - Boolean flag2; - - CInt64_SetLong(&value, 0); - flag1 = 0; - flag2 = 0; - if (addr->numObjRefs == 1) { - Object *obj; - IRO_ASSERT(1383, addr->objRefs->element->type == IROLinearOperand); - IRO_ASSERT(1384, addr->objRefs->element->u.node->type == EOBJREF); - obj = ((IROLinear *) addr->objRefs->element)->u.node->data.objref; - IRO_ASSERT(1387, obj != NULL); - result |= EvalExpr(lss, proc, addr->objRefs->element, stackPtr, map, ptf); - flag2 = 1; - } - - if (addr->numMisc != 0) { - IROElmList *list; - IROLinear *nd; - max = cint64_max; - - for (list = addr->misc; list; list = list->next) { - nd = list->element; - while (nd && nd->type == IROLinearOp1Arg && nd->nodetype == ETYPCON) - nd = nd->u.monadic; - - if (nd) { - if (nd->type == IROLinearOp2Arg && nd->nodetype == EMUL) { - if (IRO_IsIntConstant(nd->u.diadic.left) && IRO_IsIntConstant(nd->u.diadic.right)) { - if (IRO_IsUnsignedType(nd->rtype)) - work = CInt64_MulU(nd->u.diadic.left->u.node->data.intval, nd->u.diadic.right->u.node->data.intval); - else - work = CInt64_Mul(nd->u.diadic.left->u.node->data.intval, nd->u.diadic.right->u.node->data.intval); - IRO_TruncateValueToType(&work, ((IROLinear *) list->element)->rtype); - value = CInt64_Add(value, work); - } else if (IRO_IsIntConstant(nd->u.diadic.left)) { - work = nd->u.diadic.left->u.node->data.intval; - if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) - max = work; - } else if (IRO_IsIntConstant(nd->u.diadic.right)) { - work = nd->u.diadic.right->u.node->data.intval; - if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) - max = work; - } else { - max = cint64_one; - } - } else if (nd->type == IROLinearOp2Arg && nd->nodetype == ESHL) { - if (IRO_IsIntConstant(nd->u.diadic.left) && IRO_IsIntConstant(nd->u.diadic.right)) { - work = CInt64_Shl(nd->u.diadic.left->u.node->data.intval, nd->u.diadic.right->u.node->data.intval); - IRO_TruncateValueToType(&work, ((IROLinear *) list->element)->rtype); - value = CInt64_Add(value, work); - } else if (IRO_IsIntConstant(nd->u.diadic.right)) { - work = CInt64_Shl(cint64_one, nd->u.diadic.right->u.node->data.intval); - IRO_TruncateValueToType(&work, ((IROLinear *) list->element)->rtype); - if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) - max = work; - } else { - max = cint64_one; - } - } else { - LocationSet *tmp; - PAMemoryBlock *mb; - - lss2 = LocationSetSet_New(); - LocationSetSet_Init(lss2); - result |= EvalExpr(lss2, proc, nd, stackPtr, map, ptf); - - if (LocationSetSet_FindUnknown(lss2)) { - max = cint64_one; - } else if ( - LocationSetSet_Count(lss2) == 1 && - (tmp = LocationSetSet_FindFirst(lss2)) && - (LocationSet_stride(tmp) == 0) && - (mb = LocationSet_block(tmp)) && - (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT) - ) { - value = CInt64_Add(value, *((CInt64 *) PAMemoryBlock_thing(mb))); - } else if (!flag2 && (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype))) { - if (flag1) { - LocationSetSet_RemoveAll(lss); - max = cint64_one; - } - LocationSetSet_AddSet(lss, lss2); - flag2 = 1; - } else if (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype)) { - LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); - } else if (!flag1) { - LocationSetSet_AddSet(lss, lss2); - flag1 = 1; - } else { - LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); - } - LocationSetSet_Term(lss2); - LocationSetSet_Delete(lss2); - } - } - } - - if (IS_TYPE_POINTER(Int->rtype)) - CInt64_SetLong(&work, TYPE_POINTER(Int->rtype)->target->size); - else if (IS_TYPE_MEMBERPOINTER(Int->rtype)) - CInt64_SetLong(&work, TYPE_MEMBER_POINTER(Int->rtype)->ty1->size); - else - work = cint64_zero; - - if (CInt64_GreaterU(work, max)) - max = work; - } - - if (addr->numInts != 0) { - IROElmList *list; - IROLinear *addend; - - for (list = addr->ints; list; list = list->next) { - addend = list->element; - - if (addend) { - IRO_ASSERT(1536, IRO_IsIntConstant(addend)); - - value = CInt64_Add(value, addend->u.node->data.intval); - } - } - } - - IRO_TruncateValueToType(&value, Int->rtype); - - if (LocationSetSet_Count(lss) == 0) { - if (CInt64_Equal(max, cint64_max)) { - PAMemoryBlock *mb; - LocationSet *ls; - - mb = PAMemoryBlock_New(); - PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value); - - ls = LocationSet_New(); - LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype); - LocationSetSet_Add(lss, ls); - LocationSet_Term(ls); - LocationSet_Delete(ls); - } else { - LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); - } - } else { - if (!LocationSetSet_FindUnknown(lss) && !CInt64_IsZero(&value)) - LocationSetSet_ForEach(lss, EvalExprAction, &value); - } - - if (!LocationSetSet_FindUnknown(lss) && addr->numMisc && !CInt64_Equal(max, cint64_max)) - LocationSetSet_ForEach(lss, EvalExprAction2, &max); - } - } else if (Int->type == IROLinearOperand) { - Object *obj; - void *thing; - PAMemoryBlockKind kind; - - thing = NULL; - if (IRO_IsIntConstant(Int)) { - kind = PAMEMORYBLOCKKIND_INT; - thing = &Int->u.node->data.intval; - } else if (Int->u.node->type == ESTRINGCONST) { - kind = PAMEMORYBLOCKKIND_6; - thing = Int->u.node; - } else if (Int->u.node->type == EOBJREF) { - obj = Int->u.node->data.objref; - IRO_ASSERT(1597, obj != NULL); - if (ObjectIsAnExtendedParamCandidate(obj)) { - kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM; - thing = CreateExtendedParam(stackPtr, map, obj, &result); - } else { - kind = PAMEMORYBLOCKKIND_LOCALVAR; - thing = PALocalVar_New(); - if (obj->name && obj->name->name && ObjectIsARealFunctionArgument(proc, obj)) - PALocalVar_InitByName(thing, obj->name->name); - else - PALocalVar_InitByObject(thing, obj); - } - } - - if (thing) { - PAMemoryBlock *mb; - LocationSet *ls; - - mb = PAMemoryBlock_New(); - PAMemoryBlock_Init(mb, kind, thing); - - ls = LocationSet_New(); - LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype); - LocationSetSet_Add(lss, ls); - LocationSet_Term(ls); - LocationSet_Delete(ls); - } - } else if (Int->type == IROLinearOp1Arg && Int->nodetype == EBITFIELD) { - LocationSet *ls; - - lss2 = LocationSetSet_New(); - LocationSetSet_Init(lss2); - result |= EvalExpr(lss2, proc, Int->u.monadic, stackPtr, map, ptf); - - if (LocationSetSet_Count(lss2) == 1 && (ls = LocationSetSet_FindFirst(lss2))) - LocationSetSet_AddUnknown(lss, NULL, NULL, ls); - else - CError_FATAL(1643); - - LocationSetSet_Term(lss2); - LocationSetSet_Delete(lss2); - } else { - LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); - } - - LocationSetSet_ForEach(lss, EvalExprAction4, originalInt->rtype); - - if (set && lss) - LocationSetSet_AddSet(set, lss); - - LocationSetSet_Term(lss); - LocationSetSet_Delete(lss); - - return result; -} - -static IROAddrRecord *IRO_InitENodeAddrRecordPointer(ENode *enode) { - IROAddrRecord *addr = IRO_malloc(sizeof(IROAddrRecord)); - - addr->numObjRefs = 0; - addr->objRefs = NULL; - addr->numMisc = 0; - addr->misc = NULL; - addr->numInts = 0; - addr->ints = NULL; - addr->x16 = 0; - addr->linear = (IROLinear *) enode; - - return addr; -} - -static void IRO_AddENodeElmToList(ENode *linear, IROElmList **list) { - IROElmList *elmlist = IRO_malloc(sizeof(IROElmList)); - elmlist->element = linear; - elmlist->next = NULL; - if (!*list) { - *list = elmlist; - } else { - elmlist->next = *list; - *list = elmlist; - } -} - -static void IRO_DecomposeENodeAddressExpression(ENode *node, IROAddrRecord *addr) { - if (node->data.diadic.left->type == EADD) { - IRO_DecomposeENodeAddressExpression(node->data.diadic.left, addr); - } else if (node->data.diadic.left->type == EINTCONST) { - addr->numInts++; - IRO_AddENodeElmToList(node->data.diadic.left, &addr->ints); - } else if (node->data.diadic.left->type == EOBJREF) { - addr->numObjRefs++; - IRO_AddENodeElmToList(node->data.diadic.left, &addr->objRefs); - } else { - addr->numMisc++; - IRO_AddENodeElmToList(node->data.diadic.left, &addr->misc); - } - - if (node->data.diadic.right->type == EADD) { - IRO_DecomposeENodeAddressExpression(node->data.diadic.right, addr); - } else if (node->data.diadic.right->type == EINTCONST) { - addr->numInts++; - IRO_AddENodeElmToList(node->data.diadic.right, &addr->ints); - } else if (node->data.diadic.right->type == EOBJREF) { - addr->numObjRefs++; - IRO_AddENodeElmToList(node->data.diadic.right, &addr->objRefs); - } else { - addr->numMisc++; - IRO_AddENodeElmToList(node->data.diadic.right, &addr->misc); - } -} - -static Boolean EvalENodeExpr(LocationSetSet *set, Object *proc, ENode *Int, Stack **stackPtr, ParamMappingFunction *map, PartialTransferFunction *ptf) { - Boolean result; - LocationSetSet *lss; - LocationSetSet *lss2; - ENode *indirect; - EvalExprAction3Params params; - ENode *originalInt; - - IRO_ASSERT(0, set == NULL || set != NULL); - IRO_ASSERT(0, proc != NULL); - IRO_ASSERT(0, Int != NULL); - IRO_ASSERT(0, map == NULL || map != NULL); - IRO_ASSERT(0, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); - - result = 0; - lss = LocationSetSet_New(); - LocationSetSet_Init(lss); - - originalInt = Int; - while (Int && Int->type == ETYPCON) - Int = Int->data.monadic; - - IRO_ASSERT(0, Int != NULL); - - if (IRO_IsAssignOp[Int->type]) { - if (Int->type == EPOSTINC || Int->type == EPOSTDEC || Int->type == EPREINC || Int->type == EPREDEC) - indirect = Int->data.monadic; - else - indirect = Int->data.diadic.left; - IRO_ASSERT(0, indirect->type == EINDIRECT); - - lss2 = LocationSetSet_New(); - LocationSetSet_Init(lss2); - result |= EvalENodeExpr(lss2, proc, indirect->data.monadic, stackPtr, map, ptf); - - memset(¶ms, 0, sizeof(params)); - params.set = lss; - params.stackPtr = stackPtr; - params.proc = proc; - params.map = map; - params.ptf = ptf; - if (Int->type == EPOSTINC || Int->type == EPOSTDEC) - params.pointsToFunc = indirect->pointsTo; - else - params.pointsToFunc = Int->pointsTo; - params.indRtype = indirect->rtype; - params.x1C = 0; - LocationSetSet_ForEach(lss2, EvalExprAction3, ¶ms); - result |= params.x1C; - LocationSetSet_Term(lss2); - LocationSetSet_Delete(lss2); - } else if (Int->type == EINDIRECT) { - lss2 = LocationSetSet_New(); - LocationSetSet_Init(lss2); - result |= EvalENodeExpr(lss2, proc, Int->data.monadic, stackPtr, map, ptf); - - memset(¶ms, 0, sizeof(params)); - params.set = lss; - params.stackPtr = stackPtr; - params.proc = proc; - params.map = map; - params.ptf = ptf; - params.pointsToFunc = Int->pointsTo; - params.indRtype = Int->rtype; - params.x1C = 0; - LocationSetSet_ForEach(lss2, EvalExprAction3, ¶ms); - result |= params.x1C; - LocationSetSet_Term(lss2); - LocationSetSet_Delete(lss2); - } else if (Int->type == EADD) { - IROAddrRecord *addr = IRO_InitENodeAddrRecordPointer(Int); - IRO_DecomposeENodeAddressExpression(Int, addr); - if (addr->numObjRefs > 1) { - LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); - } else { - CInt64 value; - CInt64 max; - CInt64 work; - Boolean flag1; - Boolean flag2; - - CInt64_SetLong(&value, 0); - flag1 = 0; - flag2 = 0; - if (addr->numObjRefs == 1) { - Object *obj; - // IRO_ASSERT(addr->objRefs->element->type == IROLinearOperand); - // IRO_ASSERT(addr->objRefs->element->u.node->type == EOBJREF); - obj = ((ENode *) addr->objRefs->element)->data.objref; - IRO_ASSERT(0, obj != NULL); - result |= EvalENodeExpr(lss, proc, addr->objRefs->element, stackPtr, map, ptf); - flag2 = 1; - } - - if (addr->numMisc != 0) { - IROElmList *list; - ENode *nd; - max = cint64_max; - - for (list = addr->misc; list; list = list->next) { - nd = list->element; - while (nd && nd->type == ETYPCON) - nd = nd->data.monadic; - - if (nd) { - if (nd->type == EMUL) { - if (nd->data.diadic.left->type == EINTCONST && nd->data.diadic.right->type == EINTCONST) { - if (IRO_IsUnsignedType(nd->rtype)) - work = CInt64_MulU(nd->data.diadic.left->data.intval, - nd->data.diadic.right->data.intval); - else - work = CInt64_Mul(nd->data.diadic.left->data.intval, - nd->data.diadic.right->data.intval); - IRO_TruncateValueToType(&work, ((ENode *) list->element)->rtype); - value = CInt64_Add(value, work); - } else if (nd->data.diadic.left->type == EINTCONST) { - work = nd->data.diadic.left->data.intval; - if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) - max = work; - } else if (nd->data.diadic.right->type == EINTCONST) { - work = nd->data.diadic.right->data.intval; - if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) - max = work; - } else { - max = cint64_one; - } - } else if (nd->type == ESHL) { - if (nd->data.diadic.left->type == EINTCONST && nd->data.diadic.right->type == EINTCONST) { - work = CInt64_Shl(nd->data.diadic.left->data.intval, - nd->data.diadic.right->data.intval); - IRO_TruncateValueToType(&work, ((ENode *) list->element)->rtype); - value = CInt64_Add(value, work); - } else if (nd->data.diadic.right->type == EINTCONST) { - work = CInt64_Shl(cint64_one, nd->data.diadic.right->data.intval); - IRO_TruncateValueToType(&work, ((ENode *) list->element)->rtype); - if (!CInt64_IsZero(&work) && CInt64_LessU(work, max)) - max = work; - } else { - max = cint64_one; - } - } else { - LocationSet *tmp; - PAMemoryBlock *mb; - - lss2 = LocationSetSet_New(); - LocationSetSet_Init(lss2); - result |= EvalENodeExpr(lss2, proc, nd, stackPtr, map, ptf); - - if (LocationSetSet_FindUnknown(lss2)) { - max = cint64_one; - } else if ( - LocationSetSet_Count(lss2) == 1 && - (tmp = LocationSetSet_FindFirst(lss2)) && - (LocationSet_stride(tmp) == 0) && - (mb = LocationSet_block(tmp)) && - (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_INT) - ) { - value = CInt64_Add(value, *((CInt64 *) PAMemoryBlock_thing(mb))); - } else if (!flag2 && (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype))) { - if (flag1) { - LocationSetSet_RemoveAll(lss); - max = cint64_one; - } - LocationSetSet_AddSet(lss, lss2); - flag2 = 1; - } else if (IS_TYPE_POINTER(nd->rtype) || IS_TYPE_MEMBERPOINTER(nd->rtype)) { - LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); - } else if (!flag1) { - LocationSetSet_AddSet(lss, lss2); - flag1 = 1; - } else { - LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); - } - LocationSetSet_Term(lss2); - LocationSetSet_Delete(lss2); - } - } - } - - if (IS_TYPE_POINTER(Int->rtype)) - CInt64_SetLong(&work, TYPE_POINTER(Int->rtype)->target->size); - else if (IS_TYPE_MEMBERPOINTER(Int->rtype)) - CInt64_SetLong(&work, TYPE_MEMBER_POINTER(Int->rtype)->ty1->size); - else - work = cint64_zero; - - if (CInt64_GreaterU(work, max)) - max = work; - } - - if (addr->numInts != 0) { - IROElmList *list; - ENode *addend; - - for (list = addr->ints; list; list = list->next) { - addend = list->element; - - if (addend) { - IRO_ASSERT(0, addend->type == EINTCONST); - - value = CInt64_Add(value, addend->data.intval); - } - } - } - - IRO_TruncateValueToType(&value, Int->rtype); - - if (LocationSetSet_Count(lss) == 0) { - if (CInt64_Equal(max, cint64_max)) { - PAMemoryBlock *mb; - LocationSet *ls; - - mb = PAMemoryBlock_New(); - PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_INT, &value); - - ls = LocationSet_New(); - LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype); - LocationSetSet_Add(lss, ls); - LocationSet_Term(ls); - LocationSet_Delete(ls); - } else { - LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); - } - } else { - if (!LocationSetSet_FindUnknown(lss) && !CInt64_IsZero(&value)) - LocationSetSet_ForEach(lss, EvalExprAction, &value); - } - - if (!LocationSetSet_FindUnknown(lss) && addr->numMisc && !CInt64_Equal(max, cint64_max)) - LocationSetSet_ForEach(lss, EvalExprAction2, &max); - } - } else if (Int->type == EOBJREF || Int->type == EINTCONST || Int->type == ESTRINGCONST) { - Object *obj; - void *thing; - PAMemoryBlockKind kind; - - thing = NULL; - if (Int->type == EINTCONST) { - kind = PAMEMORYBLOCKKIND_INT; - thing = &Int->data.intval; - } else if (Int->type == ESTRINGCONST) { - kind = PAMEMORYBLOCKKIND_6; - thing = Int; - } else if (Int->type == EOBJREF) { - obj = Int->data.objref; - IRO_ASSERT(0, obj != NULL); - if (ObjectIsAnExtendedParamCandidate(obj)) { - kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM; - thing = CreateExtendedParam(stackPtr, map, obj, &result); - } else { - kind = PAMEMORYBLOCKKIND_LOCALVAR; - thing = PALocalVar_New(); - if (obj->name && obj->name->name && ObjectIsARealFunctionArgument(proc, obj)) - PALocalVar_InitByName(thing, obj->name->name); - else - PALocalVar_InitByObject(thing, obj); - } - } - - if (thing) { - PAMemoryBlock *mb; - LocationSet *ls; - - mb = PAMemoryBlock_New(); - PAMemoryBlock_Init(mb, kind, thing); - - ls = LocationSet_New(); - LocationSet_InitKnown(ls, mb, cint64_zero, 0, Int->rtype); - LocationSetSet_Add(lss, ls); - LocationSet_Term(ls); - LocationSet_Delete(ls); - } - } else if (Int->type == EBITFIELD) { - LocationSet *ls; - - lss2 = LocationSetSet_New(); - LocationSetSet_Init(lss2); - result |= EvalENodeExpr(lss2, proc, Int->data.monadic, stackPtr, map, ptf); - - if (LocationSetSet_Count(lss2) == 1 && (ls = LocationSetSet_FindFirst(lss2))) - LocationSetSet_AddUnknown(lss, NULL, NULL, ls); - else - CError_FATAL(2146); - - LocationSetSet_Term(lss2); - LocationSetSet_Delete(lss2); - } else { - LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); - } - - LocationSetSet_ForEach(lss, EvalExprAction4, originalInt->rtype); - - if (set && lss) - LocationSetSet_AddSet(set, lss); - - LocationSetSet_Term(lss); - LocationSetSet_Delete(lss); - - return result; -} - -static Boolean EvalVarAddr(LocationSetSet *set, Object *proc, VarRecord *var, Stack **stackPtr, ParamMappingFunction *map) { - Boolean result; - PAMemoryBlockKind kind; - void *thing; - Object *obj; - PAMemoryBlock *block; - LocationSet *loc; - - result = 0; - obj = var->object; - - if (ObjectIsAnExtendedParamCandidate(obj)) { - kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM; - thing = CreateExtendedParam(stackPtr, map, obj, &result); - } else { - kind = PAMEMORYBLOCKKIND_LOCALVAR; - thing = PALocalVar_New(); - if (obj->name && obj->name->name && ObjectIsAFunctionArgument(proc, obj)) - PALocalVar_InitByName(thing, obj->name->name); - else - PALocalVar_InitByObject(thing, obj); - } - - block = PAMemoryBlock_New(); - PAMemoryBlock_Init(block, kind, thing); - - loc = LocationSet_New(); - LocationSet_InitKnown(loc, block, cint64_zero, 0, CDecl_NewPointerType(obj->type)); - LocationSetSet_Add(set, loc); - LocationSet_Term(loc); - LocationSet_Delete(loc); - - return result; -} - -static Boolean EvalVariable(LocationSetSet *set, Object *proc, VarRecord *var, PointsToFunction *pointsToFunc, Stack **stackPtr, ParamMappingFunction *map, PartialTransferFunction *ptf) { - LocationSetSet *locs; - Boolean result; - EvalExprAction3Params params; - - locs = LocationSetSet_New(); - LocationSetSet_Init(locs); - result = EvalVarAddr(locs, proc, var, stackPtr, map); - - memset(¶ms, 0, sizeof(params)); - params.set = set; - params.stackPtr = stackPtr; - params.proc = proc; - params.map = map; - params.ptf = ptf; - params.pointsToFunc = pointsToFunc; - params.indRtype = var->object->type; - params.x1C = 0; - LocationSetSet_ForEach(locs, EvalExprAction3, ¶ms); - - result |= params.x1C; - LocationSetSet_Term(locs); - LocationSetSet_Delete(locs); - - return result; -} - -static void StoreReturnedLocationsAction(LocationSet *loc, void *refcon) { - IRO_ASSERT(2275, loc != NULL); - IRO_ASSERT(2276, refcon != NULL); - - if (!LocationSet_IsUnknown(loc)) { - if (PAMemoryBlock_kind(LocationSet_block(loc)) == PAMEMORYBLOCKKIND_HEAPBLOCK) { - PAHeapBlock *hb; - PAMemoryBlock *mb; - CInt64 field; - UInt32 stride; - Type *rtype; - - hb = CreateUniqueHeapAlloc_sub_486420(); - InitUniqueHeapAlloc_sub_486410(hb, refcon); - - mb = PAMemoryBlock_New(); - PAMemoryBlock_Init(mb, PAMEMORYBLOCKKIND_HEAPBLOCK, hb); - - field = LocationSet_field(loc); - stride = LocationSet_stride(loc); - rtype = LocationSet_rtype(loc); - LocationSet_Term(loc); - LocationSet_InitKnown(loc, mb, field, stride, rtype); - } - } -} - -static void StoreReturnedLocations(IROLinear *nd, PartialTransferFunction *ptf, ParamMappingFunction *map) { - LocationSet *retLoc; - LocationSetSet *retLocs; - - IRO_ASSERT(2307, nd != NULL); - IRO_ASSERT(2308, nd->type == IROLinearFunccall); - IRO_ASSERT(2309, ptf != NULL); - IRO_ASSERT(2310, map != NULL); - - retLoc = PartialTransferFunction_returnLocation(ptf); - retLocs = nd->u.funccall.returnedLocs; - if (!retLocs) { - LocationSetSet_Init(retLocs = nd->u.funccall.returnedLocs = LocationSetSet_New()); - } else { - LocationSetSet_RemoveAll(retLocs); - } - - Lookup(retLocs, NULL, NULL, NULL, NULL, retLoc, PartialTransferFunction_finalPointsToFn(ptf), 0, NULL); - ExpandLocationSetSetToActuals(&stCallingContextStack, map, retLocs); - LocationSetSet_ForEach(retLocs, StoreReturnedLocationsAction, nd); -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct EPParams { - ParamMappingFunction *map; - ExtendedParam *ep; - Object *proc; - Object *var; - unsigned char x10; - unsigned char x11; -} EPParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void FillInAppropriateMappingsWithExtParamAction(Object *obj, void *refcon) { - EPParams *params; - ParamMapping *mapping; - - IRO_ASSERT(2352, obj != NULL); - IRO_ASSERT(2353, refcon != NULL); - - params = refcon; - - IRO_ASSERT(2357, params->map != NULL); - IRO_ASSERT(2358, params->ep != NULL); - IRO_ASSERT(2359, params->proc == NULL || params->proc != NULL); - IRO_ASSERT(2360, params->proc != &stUnknown); - IRO_ASSERT(2361, params->var == NULL || params->var != NULL); - IRO_ASSERT(2362, params->var != &stUnknown); - - mapping = ParamMappingFunction_FindMappingByFormal(params->map, obj); - if (!mapping) { - if (ObjectIsAnExtendedParamCandidate(obj) || !params->proc || ObjectIsAFunctionArgument(params->proc, obj)) { - mapping = ParamMapping_New(); - ParamMapping_Init_PROBABLY(mapping, NULL, obj, params->ep); - Pmf_Add_sub_486610(params->map, mapping); - ParamMapping_Term(mapping); - ParamMapping_Delete(mapping); - params->x11 = 1; - } - } else { - if (ParamMapping_extended(mapping) != params->ep) { - ParamMapping_SetExtended(mapping, params->ep); - params->x11 = 1; - } - } - - if (obj == params->var) - params->x10 = 1; -} - -static Boolean FillInAppropriateMappingsWithExtParam(ParamMappingFunction *map, Object *var, ExtendedParam *ep, Object *proc) { - EPParams params; - ObjectSet *objSet; - - IRO_ASSERT(2398, map != NULL); - IRO_ASSERT(2399, var == NULL || var != NULL); - IRO_ASSERT(2400, var != &stUnknown); - IRO_ASSERT(2401, ep != NULL); - IRO_ASSERT(2402, proc == NULL || proc != NULL); - IRO_ASSERT(2403, proc != &stUnknown); - - memset(¶ms, 0, sizeof(params)); - params.map = map; - params.ep = ep; - params.proc = proc; - params.var = var; - params.x10 = 0; - params.x11 = 0; - - if ((objSet = ExtendedParam_objectSet(ep))) - ObjectSet_ForEach(objSet, FillInAppropriateMappingsWithExtParamAction, ¶ms); - - if (var && !params.x10) { - ExtendedParam_sub_4867B0(ep, var); - FillInAppropriateMappingsWithExtParamAction(var, ¶ms); - } - - return params.x11; -} - -static void MatchPTFHelper(LocationSet *loc, LocationSetSet *locs, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf) { - PointsToFunction *initial; - PAMemoryBlock *block; - PAMemoryBlockKind kind; - Object *obj; - - IRO_ASSERT(2448, loc != NULL); - IRO_ASSERT(2449, !LocationSet_IsUnknown(loc)); - IRO_ASSERT(2450, locs != NULL); - IRO_ASSERT(2451, proc != NULL); - IRO_ASSERT(2452, map != NULL); - IRO_ASSERT(2453, ptf != NULL); - - initial = PartialTransferFunction_initialPointsToFn(ptf); - IRO_ASSERT(2456, initial != NULL); - - IRO_ASSERT(2458, !LocationSet_IsUnknown(loc)); - - block = LocationSet_block(loc); - IRO_ASSERT(2460, block != NULL); - - kind = PAMemoryBlock_kind(block); - - if (kind == PAMEMORYBLOCKKIND_LOCALVAR) { - PALocalVar *local; - - local = PAMemoryBlock_thing(block); - IRO_ASSERT(2466, local != NULL); - - obj = GetLocalObject(local, proc, 1); - if (obj && ObjectIsAFunctionArgument(proc, obj)) { - if (LocationSetSet_Count(locs) == 1) { - LocationSet *ls; - ls = LocationSetSet_FindFirst(locs); - if (ls && !LocationSet_IsUnknown(ls)) { - if ((block = LocationSet_block(ls))) { - if (PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { - ExtendedParam *ep; - if ((ep = PAMemoryBlock_thing(block))) { - ExtendedParam_sub_4867B0(ep, obj); - if (stExtParamSet) - ExtParamSet_sub_487630(stExtParamSet, ep); - FillInAppropriateMappingsWithExtParam(map, obj, ep, proc); - } - } - } - } - } - } - } else if (kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { - void *ep = PAMemoryBlock_thing(block); - IRO_ASSERT(2489, ep != NULL); - - obj = NULL; - ObjectSet_ForEach(ExtendedParam_objectSet(ep), FindGlobalObjectAction, &obj); - if (obj && obj != &stUnknown) - FillInAppropriateMappingsWithExtParam(map, obj, ep, proc); - } else { - CError_FATAL(2500); - } - - if (!PointsToFunction_FindByLookupCompatibleLocationSet(initial, loc)) { - PointsToEntry *pte = PointsToEntry_New(); - PointsToEntry_Init(pte, loc, locs); - PointsToFunction_AddWithoutChecking(initial, pte); - PointsToEntry_Term(pte); - PointsToEntry_Delete(pte); - } -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct MatchPTFActionParams { - Object *proc; - PartialTransferFunction *ptfCopy; - ParamMappingFunction *mapCopy; - Stack **stackPtr; -} MatchPTFActionParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void MatchPTFAction1(PointsToEntry *tgtPTE, void *refcon) { - MatchPTFActionParams *params; - LocationSet *loc; - LocationSetSet *locs; - PAMemoryBlock *block; - PAMemoryBlockKind kind; - - IRO_ASSERT(2525, tgtPTE != NULL); - IRO_ASSERT(2526, refcon != NULL); - - params = refcon; - - IRO_ASSERT(2530, params->proc != NULL); - IRO_ASSERT(2531, params->ptfCopy != NULL); - IRO_ASSERT(2532, params->mapCopy != NULL); - - if ((loc = PointsToEntry_loc(tgtPTE)) && (locs = PointsToEntry_locs(tgtPTE))) { - if ((block = LocationSet_block(loc))) { - kind = PAMemoryBlock_kind(block); - if (kind == PAMEMORYBLOCKKIND_LOCALVAR) { - MatchPTFHelper(loc, locs, params->proc, params->mapCopy, params->ptfCopy); - } else if (kind != PAMEMORYBLOCKKIND_EXTENDEDPARAM) { - CError_FATAL(2547); - } - } - } -} - -static void MatchPTFAction2(PointsToEntry *tgtPTE, void *refcon) { - MatchPTFActionParams *params; - LocationSet *loc; - LocationSetSet *locs; - PAMemoryBlock *block; - PAMemoryBlockKind kind; - - IRO_ASSERT(2561, tgtPTE != NULL); - IRO_ASSERT(2562, refcon != NULL); - - params = refcon; - - IRO_ASSERT(2566, params->proc != NULL); - IRO_ASSERT(2567, params->ptfCopy != NULL); - IRO_ASSERT(2568, params->mapCopy != NULL); - - if ((loc = PointsToEntry_loc(tgtPTE)) && (locs = PointsToEntry_locs(tgtPTE))) { - if ((block = LocationSet_block(loc))) { - kind = PAMemoryBlock_kind(block); - if (kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { - MatchPTFHelper(loc, locs, params->proc, params->mapCopy, params->ptfCopy); - } - } - } -} - -static Boolean MatchPTF(PartialTransferFunction *tgtPTF, Object *proc, ParamMappingFunction *map, IROLinear *nd, PartialTransferFunction *ptf) { - Boolean result; - PartialTransferFunction *ptfCopy; - ParamMappingFunction *mapCopy; - PointsToFunction *initial; - MatchPTFActionParams params; - - IRO_ASSERT(2593, tgtPTF != NULL); - IRO_ASSERT(2594, proc != NULL); - IRO_ASSERT(2595, map != NULL); - IRO_ASSERT(2596, nd != NULL); - IRO_ASSERT(2597, ptf != NULL); - - ptfCopy = PartialTransferFunction_New(); - PartialTransferFunction_Copy(ptfCopy, ptf); - - mapCopy = ParamMappingFunction_New(); - ParamMappingFunction_Copy(mapCopy, map); - - initial = PartialTransferFunction_initialPointsToFn(tgtPTF); - PointsToFunction_SortByExtendedParamNum(initial); - - memset(¶ms, 0, sizeof(params)); - params.proc = proc; - params.ptfCopy = ptfCopy; - params.mapCopy = mapCopy; - params.stackPtr = &stCallingContextStack; - - PointsToFunction_ForEach(initial, MatchPTFAction1, ¶ms); - PointsToFunction_ForEach(initial, MatchPTFAction2, ¶ms); - - result = PointsToFunctions_Match(initial, PartialTransferFunction_initialPointsToFn(ptfCopy)); - if (result) { - PartialTransferFunction_Term(ptf); - PartialTransferFunction_Copy(ptf, ptfCopy); - - ParamMappingFunction_Term(map); - ParamMappingFunction_Copy(map, mapCopy); - } - - PartialTransferFunction_Term(ptfCopy); - PartialTransferFunction_Delete(ptfCopy); - - ParamMappingFunction_Term(mapCopy); - ParamMappingFunction_Delete(mapCopy); - - return result; -} - -static void FindCallTargetsAction2(Object *obj, void *refcon) { - ObjectSet *procList; - - IRO_ASSERT(2650, obj != NULL); - IRO_ASSERT(2651, refcon != NULL); - - procList = refcon; - - if (obj == &stUnknown || ObjectIsAFunction(obj)) - ObjectSet_sub_4867D0(procList, obj); -} - -static void FindCallTargetsAction(LocationSet *ls, void *refcon) { - ObjectSet *procList; - - IRO_ASSERT(2669, ls != NULL); - IRO_ASSERT(2670, refcon != NULL); - - procList = refcon; - - if (!LocationSet_IsUnknown(ls)) { - PAMemoryBlock *mb = LocationSet_block(ls); - if (PAMemoryBlock_kind(mb) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { - ExtendedParam *ep = PAMemoryBlock_thing(mb); - ObjectSet *objSet = ExtendedParam_objectSet(ep); - ObjectSet_ForEach(objSet, FindCallTargetsAction2, procList); - } - } else { - FindCallTargetsAction2(&stUnknown, procList); - } -} - -static int FindCallTargets(ObjectSet *procList, Object *proc, IROLinear *nd, ParamMappingFunction *map, PartialTransferFunction *ptf) { - LocationSetSet *set; - int evalResult; - int result; - - IRO_ASSERT(2696, procList != NULL); - IRO_ASSERT(2697, proc != NULL); - IRO_ASSERT(2698, nd != NULL); - IRO_ASSERT(2699, nd->type == IROLinearFunccall); - IRO_ASSERT(2700, map != NULL); - IRO_ASSERT(2701, ptf != NULL); - - set = LocationSetSet_New(); - LocationSetSet_Init(set); - evalResult = EvalExpr(set, proc, nd->u.funccall.linear8, &stCallingContextStack, map, ptf); - result = evalResult | ExpandLocationSetSetToActuals(&stCallingContextStack, map, set); - LocationSetSet_ForEach(set, FindCallTargetsAction, procList); - LocationSetSet_Term(set); - LocationSetSet_Delete(set); - - return result; -} - -static int LookupParam(LocationSetSet *set, LocationSet *ls, Object *var, Stack **stackPtr, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf, Boolean unkflag) { - Boolean result; - ExtendedParam *ep; - - IRO_ASSERT(2728, set == NULL || set != NULL); - IRO_ASSERT(2729, ls != NULL); - IRO_ASSERT(2730, var != NULL); - IRO_ASSERT(2731, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); - IRO_ASSERT(2732, proc != NULL); - IRO_ASSERT(2733, map == NULL || map != NULL); - IRO_ASSERT(2734, ptf == NULL || ptf != NULL); - - result = 0; - - ep = ExtendedParam_FindByObject(var); - if (!ep) - ep = CreateExtendedParam(stackPtr, map, var, &result); - - IRO_ASSERT(2741, ep != NULL); - - if (ep) { - PAMemoryBlock *block; - LocationSet *newLS; - - block = PAMemoryBlock_New(); - PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, ep); - - newLS = LocationSet_New(); - LocationSet_InitKnown(newLS, block, LocationSet_field(ls), LocationSet_stride(ls), LocationSet_rtype(ls)); - if (set) - LocationSetSet_Add(set, newLS); - - if (unkflag) { - if (map) - result |= FillInAppropriateMappingsWithExtParam(map, var, ep, proc); - - if (ptf) { - PointsToFunction *initial; - - initial = PartialTransferFunction_initialPointsToFn(ptf); - if (initial && !PointsToFunction_FindByLookupCompatibleLocationSet(initial, ls)) { - LocationSet_Term(newLS); - LocationSet_InitKnown(newLS, LocationSet_block(ls), cint64_zero, 0, LocationSet_rtype(ls)); - if (!PointsToFunction_FindByLookupCompatibleLocationSet(initial, newLS)) { - LocationSet *newLS2; - LocationSetSet *newSet; - PointsToEntry *newPTE; - - newLS2 = LocationSet_New(); - LocationSet_InitKnown(newLS2, block, cint64_zero, 0, LocationSet_rtype(ls)); - - newSet = LocationSetSet_New(); - LocationSetSet_Init(newSet); - LocationSetSet_Add(newSet, newLS2); - - newPTE = PointsToEntry_New(); - PointsToEntry_Init(newPTE, newLS, newSet); - result |= PointsToFunction_Add(initial, newPTE); - PointsToEntry_Term(newPTE); - PointsToEntry_Delete(newPTE); - - LocationSetSet_Term(newSet); - LocationSetSet_Delete(newSet); - - LocationSet_Term(newLS2); - LocationSet_Delete(newLS2); - } - } - } - } - - LocationSet_Term(newLS); - LocationSet_Delete(newLS); - } - - return result; -} - -static Boolean GetActualLocsOfExtendedParam(LocationSetSet *set, LocationSet *ls, Object *var, Stack **stackPtr, ParamMappingFunction *map, Boolean flag) { - Boolean result; - PAMemoryBlock *block; - IROLinear *nd; - ExtendedParam *ep; - ParamMapping *mapping; - Type *savedRtype; - CInt64 savedField; - UInt32 savedStride; - LocationSetSet *newSet; - - IRO_ASSERT(2821, set == NULL || set != NULL); - IRO_ASSERT(2822, (ls != NULL && var == NULL) || (ls == NULL && var != NULL)); - IRO_ASSERT(2823, ls == NULL || !LocationSet_IsUnknown(ls)); - IRO_ASSERT(2824, var != &stUnknown); - IRO_ASSERT(2825, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); - IRO_ASSERT(2826, map == NULL || map != NULL); - - result = 0; - block = NULL; - nd = 0; - ep = NULL; - mapping = NULL; - - if (ls) { - block = LocationSet_block(ls); - IRO_ASSERT(2838, block != NULL); - IRO_ASSERT(2839, PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM); - - ep = PAMemoryBlock_thing(block); - IRO_ASSERT(2842, ep != NULL); - - savedField = LocationSet_field(ls); - savedStride = LocationSet_stride(ls); - savedRtype = LocationSet_rtype(ls); - } - - IRO_ASSERT(2848, ep == NULL || ep != NULL); - - if (stackPtr && *stackPtr) { - StackElement *element = Stack_Top(stackPtr); - if (element && !map) - map = StackElement_map(element); - } - - IRO_ASSERT(2859, map == NULL || map != NULL); - - if (ep) { - IRO_ASSERT(2863, var == NULL); - ObjectSet_ForEach(ExtendedParam_objectSet(ep), FindGlobalObjectAction, &var); - if (!var) - var = ObjectSet_FindFirst(ExtendedParam_objectSet(ep)); - if (!var) - var = &stUnknown; - } - - IRO_ASSERT(2870, var != NULL); - - if (map && var != &stUnknown) { - if (flag) - result |= FillInAppropriateMappingsWithExtParam(map, var, ep, NULL); - mapping = ParamMappingFunction_FindMappingByFormal(map, var); - } - - newSet = LocationSetSet_New(); - LocationSetSet_Init(newSet); - - IRO_ASSERT(2884, mapping == NULL || mapping != NULL); - - if (mapping) - nd = ParamMapping_actual(mapping); - - if (!nd) { - if (!ls) { - IRO_ASSERT(2893, var != NULL); - IRO_ASSERT(2894, ep == NULL); - - if (var != &stUnknown) { - ep = CreateExtendedParam(stackPtr, NULL, var, &result); - if (flag && mapping && ParamMapping_extended(mapping) != ep) { - ParamMapping_SetExtended(mapping, ep); - result = 1; - } - - block = PAMemoryBlock_New(); - PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, ep); - savedField = cint64_zero; - savedStride = 0; - savedRtype = CDecl_NewPointerType(var->type); - } else { - block = LocationSet_block(stUnknownLs); - savedRtype = NULL; - } - } else if (var == &stUnknown || !ObjectIsAnExtendedParamCandidate(var)) { - block = LocationSet_block(stUnknownLs); - savedRtype = NULL; - } - - IRO_ASSERT(2925, block != NULL); - - if (block == LocationSet_block(stUnknownLs)) { - LocationSetSet_AddUnknown(newSet, savedRtype, NULL, NULL); - } else { - LocationSet *tmp = LocationSet_New(); - LocationSet_InitKnown(tmp, block, savedField, savedStride, savedRtype); - LocationSetSet_Add(newSet, tmp); - LocationSet_Term(tmp); - LocationSet_Delete(tmp); - } - } else { - Stack *next; - StackElement *element; - if (stackPtr && *stackPtr && (next = Stack_Next(stackPtr)) && (element = Stack_Top(&next))) { - if (ls) { - if (!savedStride && !CInt64_IsZero(&savedField)) { - IROLinear *ic; - IROLinear *d; - ic = IRO_NewIntConst(savedField, TYPE(&stunsignedlong)); - d = IRO_NewLinear(IROLinearOp2Arg); - d->index = ++IRO_NumLinear; - d->rtype = nd->rtype; - d->u.diadic.left = nd; - d->u.diadic.right = ic; - nd = d; - } - if (savedStride) { - IROLinear *call; - IROLinear *d; - call = IRO_NewLinear(IROLinearFunccall); - call->u.funccall.returnedLocs = LocationSetSet_New(); - LocationSetSet_Init(call->u.funccall.returnedLocs); - LocationSetSet_AddUnknown(call->u.funccall.returnedLocs, NULL, NULL, NULL); - d = IRO_NewLinear(IROLinearOp2Arg); - d->index = ++IRO_NumLinear; - d->rtype = nd->rtype; - d->u.diadic.left = nd; - d->u.diadic.right = call; - nd = d; - } - } - EvalExpr(newSet, StackElement_proc(element), nd, &next, StackElement_map(element), StackElement_ptf(element)); - } else { - LocationSetSet_AddUnknown(newSet, NULL, NULL, NULL); - } - } - - if (set) - LocationSetSet_AddSet(set, newSet); - - LocationSetSet_Term(newSet); - LocationSetSet_Delete(newSet); - - return result; -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct ExpandLocationSetSetActionParams { - LocationSetSet *toBeRemoved; - LocationSetSet *toBeAdded; - Stack **stackPtr; - ParamMappingFunction *map; - Boolean x10; -} ExpandLocationSetSetActionParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void ExpandLocationSetSetToActualsAction(LocationSet *ls, void *refcon) { - ExpandLocationSetSetActionParams *params; - - IRO_ASSERT(3021, ls != NULL); - IRO_ASSERT(3022, refcon != NULL); - - params = refcon; - - IRO_ASSERT(3026, params->toBeRemoved != NULL); - IRO_ASSERT(3027, params->toBeAdded != NULL); - IRO_ASSERT(3028, params->stackPtr == NULL || *params->stackPtr == NULL || *params->stackPtr != NULL); - IRO_ASSERT(3029, params->map == NULL || params->map != NULL); - - if (!LocationSet_IsUnknown(ls)) { - PAMemoryBlock *block = LocationSet_block(ls); - if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { - ExtendedParam *ep = PAMemoryBlock_thing(block); - if (ep) { - ObjectSet *objSet = ExtendedParam_objectSet(ep); - Object *obj = NULL; - ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); - if (!obj) { - LocationSetSet_Add(params->toBeRemoved, ls); - params->x10 |= GetActualLocsOfExtendedParam(params->toBeAdded, ls, NULL, params->stackPtr, params->map, 0); - } - } - } - } -} - -static int ExpandLocationSetSetToActuals(Stack **stackPtr, ParamMappingFunction *map, LocationSetSet *thingsPointedTo) { - LocationSetSet *toBeRemoved; - LocationSetSet *toBeAdded; - ExpandLocationSetSetActionParams params; - Boolean result; - - IRO_ASSERT(3063, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); - IRO_ASSERT(3064, map == NULL || map != NULL); - IRO_ASSERT(3065, thingsPointedTo != NULL); - - toBeRemoved = LocationSetSet_New(); - LocationSetSet_Init(toBeRemoved); - - toBeAdded = LocationSetSet_New(); - LocationSetSet_Init(toBeAdded); - - memset(¶ms, 0, sizeof(params)); - params.toBeRemoved = toBeRemoved; - params.toBeAdded = toBeAdded; - params.stackPtr = stackPtr; - params.map = map; - params.x10 = 0; - - LocationSetSet_ForEach(thingsPointedTo, ExpandLocationSetSetToActualsAction, ¶ms); - - result = params.x10; - LocationSetSet_sub_488700(thingsPointedTo, toBeRemoved); - LocationSetSet_AddSet(thingsPointedTo, toBeAdded); - - LocationSetSet_Term(toBeRemoved); - LocationSetSet_Delete(toBeRemoved); - - LocationSetSet_Term(toBeAdded); - LocationSetSet_Delete(toBeAdded); - - return result; -} - -static void EvaluatePartialAbsolute(LocationSetSet *set, LocationSetSet *thingsPointedTo, LocationSet *dst, Type *indRtype) { - LocationSet *absLoc; - Type *absLocRtype; - PAMemoryBlock *block; - - IRO_ASSERT(3108, set != NULL); - IRO_ASSERT(3109, thingsPointedTo != NULL); - IRO_ASSERT(3110, dst != NULL); - IRO_ASSERT(3111, indRtype != NULL); - - absLoc = LocationSetSet_FindFirst(thingsPointedTo); - IRO_ASSERT(3114, absLoc != NULL); - - if (!LocationSet_IsUnknown(absLoc)) - absLocRtype = LocationSet_rtype(absLoc); - - if (!LocationSet_IsUnknown(absLoc) && indRtype->size == absLocRtype->size) { - LocationSetSet_AddSet(set, thingsPointedTo); - } else if ( - !LocationSet_IsUnknown(absLoc) && - !LocationSet_stride(absLoc) && - LocationSetSet_Count(thingsPointedTo) == 1 && - (block = LocationSet_block(absLoc)) && - PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_INT && - absLocRtype->size <= stsignedlonglong.size && - indRtype->size < absLocRtype->size - ) { - CInt64 val2; - CInt64 val8; - CInt64 val4; - CInt64 val5; - CInt64 val1; - CInt64 val3; - CInt64 val7; - CInt64 val6; - LocationSet *ls; - - val1 = LocationSet_field(absLoc); - val2 = *((CInt64 *) PAMemoryBlock_thing(block)); - CInt64_SetLong(&val3, 8); - val4 = cint64_zero; - CInt64_SetLong(&val5, stsignedlonglong.size - absLocRtype->size); - val6 = CInt64_Sub(LocationSet_field(dst), val1); - CInt64_SetLong(&val7, absLocRtype->size - indRtype->size); - val5 = CInt64_Add(val5, val6); - val4 = CInt64_Add(val4, val7); - val4 = CInt64_Sub(val4, val6); - val5 = CInt64_MulU(val5, val3); - val4 = CInt64_MulU(val4, val3); - val8 = cint64_negone; - val8 = CInt64_Shl(val8, val5); - val8 = CInt64_ShrU(val8, val5); - val2 = CInt64_And(val2, val8); - val2 = CInt64_ShrU(val2, val4); - - block = PAMemoryBlock_New(); - PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_INT, &val2); - - ls = LocationSet_New(); - LocationSet_InitKnown(ls, block, cint64_zero, 0, indRtype); - LocationSetSet_Add(set, ls); - LocationSet_Term(ls); - LocationSet_Delete(ls); - } else { - LocationSetSet_AddUnknown(set, indRtype, NULL, NULL); - } -} - -static Boolean AddToInitialPointsToFunc(Boolean flag, PartialTransferFunction *ptf, LocationSet *dst, LocationSetSet *set) { - Boolean result; - LocationSet *ls; - PointsToFunction *initial; - PointsToEntry *pte; - - IRO_ASSERT(3192, ptf == NULL || ptf != NULL); - IRO_ASSERT(3193, dst != NULL); - IRO_ASSERT(3194, set != NULL); - - result = 0; - - if (flag && ptf) { - ls = LocationSetSet_FindUnknown(set); - if (!ls || LocationSet_rtype(ls)) { - initial = PartialTransferFunction_initialPointsToFn(ptf); - if (initial && !PointsToFunction_FindByLookupCompatibleLocationSet(initial, dst)) { - IRO_ASSERT(3208, dst != NULL); - - pte = PointsToEntry_New(); - PointsToEntry_Init(pte, dst, set); - result = PointsToFunction_AddWithoutChecking(initial, pte); - PointsToEntry_Term(pte); - PointsToEntry_Delete(pte); - } - } - } - - return result; -} - -static Boolean Lookup(LocationSetSet *set, Stack **stackPtr, Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf, LocationSet *dst, PointsToFunction *pointsToFunc, Boolean unk, Type *indRtype) { - Boolean result; - LocationSetSet *mySet; - LocationSetSet *set2; - PAMemoryBlock *block; - ExtendedParam *ep; - PALocalVar *local; - ObjectSet *objSet; - Object *obj; - - IRO_ASSERT(3245, set == NULL || set != NULL); - IRO_ASSERT(3246, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); - IRO_ASSERT(3247, proc == NULL || proc != NULL); - IRO_ASSERT(3248, map == NULL || map != NULL); - IRO_ASSERT(3249, ptf == NULL || ptf != NULL); - IRO_ASSERT(3250, dst != NULL); - IRO_ASSERT(3251, pointsToFunc == NULL || pointsToFunc != NULL); - IRO_ASSERT(3252, indRtype == NULL || indRtype != NULL); - - result = 0; - - set2 = NULL; - - mySet = LocationSetSet_New(); - LocationSetSet_Init(mySet); - - if (proc) { - if (LocationIsVolatile(dst, proc)) - LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL); - } - - if (pointsToFunc && !LocationSet_IsUnknown(dst)) { - PointsToEntry *pte = PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, dst); - if (pte) { - set2 = PointsToEntry_locs(pte); - } else if (indRtype) { - pte = PointsToFunction_FindContainingLocationSet(pointsToFunc, dst, indRtype); - if (pte) - set2 = PointsToEntry_locs(pte); - } - } - - if (set2) { - if (indRtype) - EvaluatePartialAbsolute(mySet, set2, dst, indRtype); - else - LocationSetSet_AddSet(mySet, set2); - } else if (!set2) { - block = NULL; - if (!LocationSet_IsUnknown(dst)) - block = LocationSet_block(dst); - - if (!LocationSet_IsUnknown(dst) && LocationSet_stride(dst)) { - LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL); - } else if ( - block && - PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM && - (ep = PAMemoryBlock_thing(block)) && - (objSet = ExtendedParam_objectSet(ep)) - ) { - obj = NULL; - ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); - if (!obj) { - LocationSetSet *lss3; - LocationSet *tmp; - // Boolean result1; - EvalExprAction3Params params; - - lss3 = LocationSetSet_New(); - LocationSetSet_Init(lss3); - result = GetActualLocsOfExtendedParam(lss3, dst, NULL, stackPtr, map, unk); - - memset(¶ms, 0, sizeof(params)); - params.set = mySet; - params.stackPtr = stackPtr; - params.proc = proc; - params.map = map; - params.ptf = ptf; - params.pointsToFunc = pointsToFunc; - params.indRtype = indRtype; - params.x1C = 0; - LocationSetSet_ForEach(lss3, EvalExprAction3, ¶ms); - result |= params.x1C; - - LocationSetSet_Term(lss3); - LocationSetSet_Delete(lss3); - - if ((tmp = LocationSetSet_FindUnknown(mySet))) { - if (!LocationSet_restriction(tmp) && ObjectSet_Count(objSet) == 1) { - if ((obj = ObjectSet_FindFirst(objSet))) { - if (ObjectIsRestrictQualified(obj)) { - LocationSet_Term(tmp); - LocationSet_InitUnknown(tmp, indRtype, block, NULL); - } - } - } - } - - result |= AddToInitialPointsToFunc(unk, ptf, dst, mySet); - } else { - // Boolean result1; - Stack *next; - StackElement *element; - - result = GetActualLocsOfExtendedParam(NULL, dst, NULL, stackPtr, map, unk); - if (stackPtr && *stackPtr && (next = Stack_Next(stackPtr)) && (element = Stack_Top(&next))) { - result |= Lookup(mySet, &next, StackElement_proc(element), StackElement_map(element), - StackElement_ptf(element), dst, StackElement_funcCall(element)->pointsToFunction, unk, indRtype); - } else { - LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL); - } - - result |= AddToInitialPointsToFunc(unk, ptf, dst, mySet); - } - } else if ( - block && - PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR && - (local = PAMemoryBlock_thing(block)) && - proc && - (obj = GetLocalObject(local, proc, 1)) && - ObjectIsAFunctionArgument(proc, obj) - ) { - result = LookupParam(mySet, dst, obj, stackPtr, proc, map, ptf, unk); - } else { - LocationSetSet_AddUnknown(mySet, indRtype, NULL, NULL); - } - } - - if (set) - LocationSetSet_AddSet(set, mySet); - - LocationSetSet_Term(mySet); - LocationSetSet_Delete(mySet); - - return result; -} - -static Boolean InputsHaveNewPointerValues(PartialTransferFunction *tgtPTF, PartialTransferFunction *ptf) { - IRO_ASSERT(3393, tgtPTF != NULL); - IRO_ASSERT(3394, ptf != NULL); - - return 0; -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct CreateEPActionParams { - ParamMapping *last; - ParamMapping *lowest; -} CreateEPActionParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void CreateExtendedParamAction(ParamMapping *mapping, void *refcon) { - CreateEPActionParams *params; - ExtendedParam *ep; - uint32 value; - ExtendedParam *lowestEP; - uint32 lowestValue; - ExtendedParam *lastEP; - uint32 lastValue; - - IRO_ASSERT(3417, mapping != NULL); - IRO_ASSERT(3418, refcon != NULL); - - params = refcon; - - IRO_ASSERT(3422, params->last == NULL || params->last != NULL); - IRO_ASSERT(3423, params->lowest == NULL || params->lowest != NULL); - - if ((ep = ParamMapping_extended(mapping))) { - value = ExtendedParam_sub_489110(ep); - - if (params->lowest) { - lowestEP = ParamMapping_extended(params->lowest); - lowestValue = ExtendedParam_sub_489110(lowestEP); - if (params->last) { - lastEP = ParamMapping_extended(params->last); - lastValue = ExtendedParam_sub_489110(lastEP); - if (value > lastValue && value < lowestValue) - params->lowest = mapping; - } else if (value < lowestValue) { - params->lowest = mapping; - } - } else if (params->last) { - lastEP = ParamMapping_extended(params->last); - lastValue = ExtendedParam_sub_489110(lastEP); - if (value > lastValue) - params->lowest = mapping; - } else { - params->lowest = mapping; - } - } -} - -static ExtendedParam *FindMatchingExtendedParam(Stack **stackPtr, ParamMappingFunction *map, LocationSetSet *lss, ParamMapping *lowest, Boolean *result) { - ExtendedParam *ep; - ExtendedParam *lowestEP; - - IRO_ASSERT(3473, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); - IRO_ASSERT(3474, map == NULL || map != NULL); - IRO_ASSERT(3475, lss != NULL); - IRO_ASSERT(3476, lowest != NULL); - - ep = NULL; - if ((lowestEP = ParamMapping_extended(lowest))) { - PAMemoryBlock *block; - LocationSet *lowestLS; - LocationSetSet *lowestLSS; - - block = PAMemoryBlock_New(); - PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, lowestEP); - - lowestLS = LocationSet_New(); - LocationSet_InitKnown(lowestLS, block, cint64_zero, 0, TYPE(&void_ptr)); - - lowestLSS = LocationSetSet_New(); - LocationSetSet_Init(lowestLSS); - - *result |= GetActualLocsOfExtendedParam(lowestLSS, lowestLS, NULL, stackPtr, map, 0); - if (LocationSetSets_Equal(lowestLSS, lss)) - ep = lowestEP; - - LocationSetSet_Term(lowestLSS); - LocationSetSet_Delete(lowestLSS); - - LocationSet_Term(lowestLS); - LocationSet_Delete(lowestLS); - } - - return ep; -} - -static ExtendedParam *CreateExtendedParam(Stack **stackPtr, ParamMappingFunction *map, Object *var, Boolean *result) { - ExtendedParam *ep; - ParamMapping *mapping; - LocationSetSet *lss; - CreateEPActionParams params; - - IRO_ASSERT(3518, map == NULL || map != NULL); - IRO_ASSERT(3519, stackPtr == NULL || *stackPtr == NULL || *stackPtr != NULL); - IRO_ASSERT(3520, var != NULL); - - mapping = NULL; - if (map) - mapping = ParamMappingFunction_FindMappingByFormal(map, var); - - ep = ExtendedParam_FindByObject(var); - if (ep) { - if (mapping) - IRO_ASSERT(3535, ep == ParamMapping_extended(mapping) || ParamMapping_extended(mapping) == NULL); - } else if (map && !ObjectIsRestrictQualified(var)) { - lss = LocationSetSet_New(); - LocationSetSet_Init(lss); - *result |= GetActualLocsOfExtendedParam(lss, NULL, var, stackPtr, map, 0); - - memset(¶ms, 0, sizeof(params)); - params.last = NULL; - do { - params.lowest = NULL; - pmf_sub_487C70(map, CreateExtendedParamAction, ¶ms); - if (params.lowest && params.lowest != mapping) - ep = FindMatchingExtendedParam(stackPtr, map, lss, params.lowest, result); - params.last = params.lowest; - } while (params.lowest && !ep); - - LocationSetSet_Term(lss); - LocationSetSet_Delete(lss); - } - - if (!ep) - ep = ExtendedParam_FindByObject(var); - - if (!ep) { - ep = ExtendedParam_New(); - ExtendedParam_Init(ep, var); - } else { - ExtendedParam_sub_4867B0(ep, var); - } - - if (stExtParamSet) - ExtParamSet_sub_487630(stExtParamSet, ep); - - IRO_ASSERT(3583, ep != NULL); - - return ep; -} - -#ifdef IRO_DEBUG -void __assertion_failed(char *expr, char *filename, int line) { - CError_ASSERT(3605, filename); - CError_Internal(filename, line); -} -#endif - -static void RecordActuals(IROLinear *nd, Object *proc, ParamMappingFunction *map) { - IRO_ASSERT(3628, nd != NULL); - IRO_ASSERT(3629, nd->type == IROLinearFunccall); - IRO_ASSERT(3630, proc != NULL); - IRO_ASSERT(3631, map != NULL); - - if (proc != &stUnknown) { - int i; - ObjectList *args; - Object *arg; - - args = FunctionArguments(proc); - if (args) - arg = args->object; - else - arg = &stUnknown; - - for (i = 0; i < nd->u.funccall.argCount; i++) { - IRO_ASSERT(3643, arg != NULL); - - if (arg != &stUnknown) { - ParamMapping *mapping = ParamMapping_New(); - ParamMapping_Init_PROBABLY(mapping, nd->u.funccall.args[i], arg, NULL); - Pmf_Add_sub_486610(map, mapping); - ParamMapping_Term(mapping); - ParamMapping_Delete(mapping); - } - - if (args) { - args = args->next; - if (args) - arg = args->object; - else - arg = &stUnknown; - } - } - } -} - -static Boolean IsAddressableLocation(LocationSet *loc, Object *proc, IRONode *fnode, IROLinear *nd) { - IRO_ASSERT(3676, loc != NULL); - IRO_ASSERT(3677, fnode != NULL); - IRO_ASSERT(3678, nd != NULL); - - if (!LocationSet_IsUnknown(loc)) { - PAMemoryBlock *block; - PALocalVar *local; - Object *obj; - ExtendedParam *ep; - ObjectSet *objSet; - - block = LocationSet_block(loc); - if ( - PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR && - (local = PAMemoryBlock_thing(block)) && - (obj = GetLocalObject(local, proc, 0)) && - fnode->addressed && - !ObjectSet_sub_485020(fnode->addressed, obj) - ) { - return 0; - } - - if ( - PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM && - (ep = PAMemoryBlock_thing(block)) && - (objSet = ExtendedParam_objectSet(ep)) && - ObjectSet_Count(objSet) == 1 && - (obj = ObjectSet_FindFirst(objSet)) && - ObjectIsAFunctionArgument(proc, obj) && - ObjectIsRestrictQualified(obj) - ) { - return 0; - } - } - - return 1; -} - -static Boolean LocationSetsAlias(LocationSet *ls1, LocationSet *ls2) { - IRO_ASSERT(3719, ls1 != NULL); - IRO_ASSERT(3720, ls2 != NULL); - - return - (ls1 == ls2) || - LocationSet_IsUnknown(ls1) || - LocationSet_IsUnknown(ls2) || - ( - (LocationSet_stride(ls1) || - LocationSet_stride(ls2) || - CInt64_Equal(LocationSet_field(ls1), LocationSet_field(ls2))) && - MemoryBlocks_Equal(LocationSet_block(ls1), LocationSet_block(ls2)) - ); -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct FindAliasingParams { - LocationSetSet *x0; - LocationSet *x4; - Boolean x8; -} FindAliasingParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void FindAliasingAction2(LocationSet *ls, void *refcon) { - FindAliasingParams *params; - - params = refcon; - - if (!params->x8) { - if (LocationSetsAlias(params->x4, ls)) - params->x8 = 1; - } -} - -static void FindAliasingAction(LocationSet *ls, void *refcon) { - FindAliasingParams *params; - - IRO_ASSERT(3751, ls != NULL); - IRO_ASSERT(3752, refcon != NULL); - - params = refcon; - - if (!params->x8) { - params->x4 = ls; - LocationSetSet_ForEach(params->x0, FindAliasingAction2, params); - } -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct KillLocationParams { - Object *proc; - IRONode *fnode; - IROLinear *nd; - PartialTransferFunction *ptf; - PointsToFunction *toBeKilled; - LocationSet *dst; - Boolean x18; -} KillLocationParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void KillAllAddressableLocationsAction(PointsToEntry *pte, void *refcon) { - KillLocationParams *params; - LocationSet *loc; - - IRO_ASSERT(3779, pte != NULL); - IRO_ASSERT(3780, refcon != NULL); - - params = refcon; - - IRO_ASSERT(3784, params->proc != NULL); - IRO_ASSERT(3785, params->fnode != NULL); - IRO_ASSERT(3786, params->nd != NULL); - IRO_ASSERT(3787, params->ptf != NULL); - IRO_ASSERT(3788, params->toBeKilled != NULL); - IRO_ASSERT(3789, params->dst == NULL); - - loc = PointsToEntry_loc(pte); - IRO_ASSERT(3793, loc != NULL); - IRO_ASSERT(3794, !LocationSet_IsUnknown(loc)); - - if (IsAddressableLocation(loc, params->proc, params->fnode, params->nd)) - PointsToFunction_Add(params->toBeKilled, pte); -} - -static void KillAllAliasingExtParamLocsAction(PointsToEntry *pte, void *refcon) { - KillLocationParams *params; - LocationSet *loc; - - IRO_ASSERT(3813, pte != NULL); - IRO_ASSERT(3814, refcon != NULL); - - params = refcon; - - IRO_ASSERT(3818, params->proc != NULL); - IRO_ASSERT(3819, params->fnode != NULL); - IRO_ASSERT(3820, params->nd != NULL); - IRO_ASSERT(3821, params->ptf != NULL); - IRO_ASSERT(3822, params->toBeKilled != NULL); - IRO_ASSERT(3823, params->dst != NULL); - IRO_ASSERT(3824, LocationSet_block(params->dst) != NULL); - IRO_ASSERT(3825, PAMemoryBlock_kind(LocationSet_block(params->dst)) == PAMEMORYBLOCKKIND_EXTENDEDPARAM); - - loc = PointsToEntry_loc(pte); - IRO_ASSERT(3829, loc != NULL); - IRO_ASSERT(3830, !LocationSet_IsUnknown(loc)); - - if (loc != params->dst) { - if (LocationSetsAlias(loc, params->dst)) { - PointsToFunction_Add(params->toBeKilled, pte); - } else { - ExtendedParam *ep; - ObjectSet *objSet; - Object *obj; - PAMemoryBlock *block; - - if ( - (ep = PAMemoryBlock_thing(LocationSet_block(params->dst))) && - (objSet = ExtendedParam_objectSet(ep)) && - (ObjectSet_Count(objSet) != 1 || !(obj = ObjectSet_FindFirst(objSet)) || !ObjectIsRestrictQualified(obj)) && - (block = LocationSet_block(loc)) && - PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM && - (ep = PAMemoryBlock_thing(block)) && - (objSet = ExtendedParam_objectSet(ep)) && - (ObjectSet_Count(objSet) != 1 || !(obj = ObjectSet_FindFirst(objSet)) || !ObjectIsRestrictQualified(obj)) - ) { - LocationSetSet *lss1; - LocationSetSet *lss2; - Boolean changed; - FindAliasingParams aparams; - - lss1 = LocationSetSet_New(); - LocationSetSet_Init(lss1); - lss2 = LocationSetSet_New(); - LocationSetSet_Init(lss2); - - changed = GetActualLocsOfExtendedParam(lss1, loc, NULL, &stCallingContextStack, NULL, 0); - changed |= GetActualLocsOfExtendedParam(lss2, params->dst, NULL, &stCallingContextStack, NULL, 0); - - memset(&aparams, 0, sizeof(aparams)); - aparams.x8 = 0; - aparams.x0 = lss2; - LocationSetSet_ForEach(lss1, FindAliasingAction, &aparams); - if (aparams.x8) - PointsToFunction_Add(params->toBeKilled, pte); - - LocationSetSet_Term(lss1); - LocationSetSet_Delete(lss1); - LocationSetSet_Term(lss2); - LocationSetSet_Delete(lss2); - } - } - } -} - -static void KillLocationsAction(PointsToEntry *pte, void *refcon) { - KillLocationParams *params; - LocationSet *loc; - LocationSetSet *lss; - - IRO_ASSERT(3886, pte != NULL); - IRO_ASSERT(3887, refcon != NULL); - - params = refcon; - - IRO_ASSERT(3891, params->proc != NULL); - IRO_ASSERT(3892, params->fnode != NULL); - IRO_ASSERT(3893, params->nd != NULL); - IRO_ASSERT(3894, params->ptf != NULL); - IRO_ASSERT(3895, params->toBeKilled != NULL); - IRO_ASSERT(3896, params->dst == NULL); - - loc = PointsToEntry_loc(pte); - IRO_ASSERT(3900, loc != NULL); - IRO_ASSERT(3901, !LocationSet_IsUnknown(loc)); - - lss = LocationSetSet_New(); - LocationSetSet_Init(lss); - LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); - - params->x18 |= Assign(params->ptf, loc, lss, params->proc, params->nd, params->fnode); - - LocationSetSet_Term(lss); - LocationSetSet_Delete(lss); -} - -static Boolean KillAllAddressableLocations(Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf) { - Boolean result; - PointsToFunction *pointsToFunc; - PointsToFunction *pointsToFuncCopy; - PointsToFunction *toBeKilled; - KillLocationParams params; - - IRO_ASSERT(3921, proc != NULL); - IRO_ASSERT(3922, fnode == NULL || fnode != NULL); - IRO_ASSERT(3923, nd == NULL || nd != NULL); - IRO_ASSERT(3924, ptf != NULL); - - if (nd && nd->pointsToFunction) - pointsToFunc = nd->pointsToFunction; - else - pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf); - - pointsToFuncCopy = PointsToFunction_New(); - PointsToFunction_Copy(pointsToFuncCopy, pointsToFunc); - - toBeKilled = PointsToFunction_New(); - PointsToFunction_Init(toBeKilled); - - memset(¶ms, 0, sizeof(params)); - params.proc = proc; - params.fnode = fnode; - params.nd = nd; - params.ptf = ptf; - params.toBeKilled = toBeKilled; - params.dst = NULL; - params.x18 = 0; - - if (pointsToFunc) { - PointsToFunction_ForEach(pointsToFunc, KillAllAddressableLocationsAction, ¶ms); - PointsToFunction_ForEach(params.toBeKilled, KillLocationsAction, ¶ms); - } - - PointsToFunction_Term(toBeKilled); - PointsToFunction_Delete(toBeKilled); - - if (params.x18) - result = !PointsToFunctions_Equal(pointsToFuncCopy, pointsToFunc); - else - result = 0; - - PointsToFunction_Term(pointsToFuncCopy); - PointsToFunction_Delete(pointsToFuncCopy); - - return result; -} - -static void KillAllAliasingExtParamLocs(Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf, LocationSet *dst) { - PointsToFunction *pointsToFunc; - PointsToFunction *toBeKilled; - KillLocationParams params; - - IRO_ASSERT(3974, proc != NULL); - IRO_ASSERT(3975, fnode == NULL || fnode != NULL); - IRO_ASSERT(3976, nd == NULL || nd != NULL); - IRO_ASSERT(3977, ptf != NULL); - IRO_ASSERT(3978, dst != NULL); - - if (!LocationSet_IsUnknown(dst) && LocationSet_block(dst)) { - if (PAMemoryBlock_kind(LocationSet_block(dst)) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { - - if (nd && nd->pointsToFunction) - pointsToFunc = nd->pointsToFunction; - else - pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf); - - toBeKilled = PointsToFunction_New(); - PointsToFunction_Init(toBeKilled); - - memset(¶ms, 0, sizeof(params)); - params.proc = proc; - params.fnode = fnode; - params.nd = nd; - params.ptf = ptf; - params.toBeKilled = toBeKilled; - params.dst = dst; - params.x18 = 0; - - if (pointsToFunc) { - PointsToFunction_ForEach(pointsToFunc, KillAllAliasingExtParamLocsAction, ¶ms); - PointsToFunction_ForEach(params.toBeKilled, KillLocationsAction, ¶ms); - } - - PointsToFunction_Term(toBeKilled); - PointsToFunction_Delete(toBeKilled); - } - } -} - -static Boolean Assign(PartialTransferFunction *ptf, LocationSet *dst, LocationSetSet *srcs, Object *proc, IROLinear *nd, IRONode *fnode) { - PointsToFunction *pointsToFunc; - Boolean result; - PointsToEntry *pte; - LocationSet *loc; - LocationSetSet *locs; - LocationSet *bitfieldOf; - LocationSetSet *lss; - - IRO_ASSERT(4027, ptf != NULL); - IRO_ASSERT(4028, dst != NULL); - IRO_ASSERT(4029, srcs != NULL); - IRO_ASSERT(4030, proc != NULL); - IRO_ASSERT(4031, nd == NULL || nd != NULL); - IRO_ASSERT(4032, fnode == NULL || fnode != NULL); - - if (nd) { - if (!nd->pointsToFunction) { - nd->pointsToFunction = PointsToFunction_New(); - PointsToFunction_Init(nd->pointsToFunction); - } - pointsToFunc = nd->pointsToFunction; - } else { - pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf); - } - - pte = PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, dst); - if (pte) { - loc = PointsToEntry_loc(pte); - locs = PointsToEntry_locs(pte); - IRO_ASSERT(4056, !LocationSet_IsUnknown(dst)); - IRO_ASSERT(4057, LocationSet_stride(dst) == 0 || LocationSet_stride(loc) != 0); - - result = !LocationSetSets_Equal(srcs, locs) || LocationSet_stride(dst) != LocationSet_stride(loc); - - if (result) { - pte = PointsToEntry_New(); - PointsToEntry_Init(pte, dst, srcs); - PointsToFunction_RemoveByLocationSet(pointsToFunc, loc); - PointsToFunction_AddWithoutChecking(pointsToFunc, pte); - PointsToEntry_Term(pte); - PointsToEntry_Delete(pte); - } - } else if (!LocationSet_IsUnknown(dst)) { - KillAllAliasingExtParamLocs(proc, fnode, nd, ptf, dst); - - pte = PointsToEntry_New(); - PointsToEntry_Init(pte, dst, srcs); - result = PointsToFunction_AddWithoutChecking(pointsToFunc, pte); - PointsToEntry_Term(pte); - PointsToEntry_Delete(pte); - } else if ((bitfieldOf = LocationSet_bitfieldOf(dst))) { - lss = LocationSetSet_New(); - LocationSetSet_Init(lss); - LocationSetSet_AddUnknown(lss, NULL, NULL, NULL); - result = Assign(ptf, bitfieldOf, lss, proc, nd, fnode); - LocationSetSet_Term(lss); - LocationSetSet_Delete(lss); - } else if (!LocationSet_restriction(dst)) { - result = KillAllAddressableLocations(proc, fnode, nd, ptf); - } - - return result; -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct EvalMeetActionParams { - Object *proc; - IRONode *fnode; - IRONode *pred; - IROLinear *nd; - PartialTransferFunction *ptf; - Boolean x14; - Boolean x15; -} EvalMeetActionParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void EvalMeetAction(PointsToEntry *pte, void *refcon) { - EvalMeetActionParams *params; - LocationSet *loc; - LocationSetSet *set; - UInt16 i; - - IRO_ASSERT(4123, pte != NULL); - IRO_ASSERT(4124, refcon != NULL); - - params = refcon; - - IRO_ASSERT(4128, params->proc != NULL); - IRO_ASSERT(4129, params->fnode != NULL); - IRO_ASSERT(4130, params->pred != NULL); - IRO_ASSERT(4131, params->nd != NULL); - IRO_ASSERT(4132, params->ptf != NULL); - - loc = PointsToEntry_loc(pte); - - set = LocationSetSet_New(); - LocationSetSet_Init(set); - LocationSetSet_AddSet(set, PointsToEntry_locs(pte)); - - for (i = 0; i < params->fnode->numpred; i++) { - IRONode *pred = FunctionNodeTable(params->proc)[params->fnode->pred[i]]; - if (pred->x3C && pred != params->pred) { - params->x14 |= Lookup(set, &stCallingContextStack, params->proc, NULL, params->ptf, loc, pred->last->pointsToFunction, 0, NULL); - } - } - - params->x15 |= Assign(params->ptf, loc, set, params->proc, params->nd, params->fnode); - LocationSetSet_Term(set); - LocationSetSet_Delete(set); -} - -static Boolean EvalMeet(Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf) { - PointsToFunction *pointsToFunc; - EvalMeetActionParams params; - int i; - - IRO_ASSERT(4163, proc != NULL); - IRO_ASSERT(4164, fnode != NULL); - IRO_ASSERT(4165, nd != NULL); - IRO_ASSERT(4166, ptf != NULL); - - pointsToFunc = PointsToFunction_New(); - if (nd->pointsToFunction) - PointsToFunction_Copy(pointsToFunc, nd->pointsToFunction); - else - PointsToFunction_Init(pointsToFunc); - - memset(¶ms, 0, sizeof(params)); - params.proc = proc; - params.fnode = fnode; - params.nd = nd; - params.ptf = ptf; - params.x14 = 0; - params.x15 = 0; - - for (i = 0; i < fnode->numpred; i++) { - IRONode *pred = FunctionNodeTable(proc)[fnode->pred[i]]; - params.pred = pred; - if (pred->x3C && pred->last->pointsToFunction) { - PointsToFunction_ForEach(pred->last->pointsToFunction, EvalMeetAction, ¶ms); - } - } - - if (!params.x14 && params.x15) { - if (nd->pointsToFunction) - params.x14 = !PointsToFunctions_Equal(pointsToFunc, nd->pointsToFunction); - else - params.x14 = PointsToFunction_FindFirst(pointsToFunc) != NULL; - } - - PointsToFunction_Term(pointsToFunc); - PointsToFunction_Delete(pointsToFunc); - - return params.x14; -} - -static PartialTransferFunction *AllocatePTF(Object *proc, IROLinear *nd, PartialTransferFunction *ptf) { - PartialTransferFunction *newPTF; - - IRO_ASSERT(4210, proc != NULL); - IRO_ASSERT(4211, proc->u.func.ptfList != NULL); - IRO_ASSERT(4212, nd == NULL || nd != NULL); - IRO_ASSERT(4213, ptf == NULL || ptf != NULL); - - newPTF = PartialTransferFunction_New(); - PartialTransferFunction_Init(newPTF, nd, ptf); - PTFList_sub_48A050(proc->u.func.ptfList, newPTF); - return newPTF; -} - -static Object *FindMainEntryPoint(Object *function) { - IRO_ASSERT(4229, function != NULL); - - return function; -} - -static ObjectList *FunctionArguments(Object *proc) { - Object *search; - ObjectList *scan; - ObjectList *list; - ObjectList *prev; - ExtendedParam *ep; - char *name; - VarInfo *vi; - Object *obj; - FuncArg *args; - Boolean notFound; - - IRO_ASSERT(4252, proc != NULL); - - if (proc == stCurrentProc) { - for (list = arguments; list; list = list->next) { - if ((obj = list->object) && obj->name && (name = obj->name->name) && name[0]) { - prev = NULL; - for (scan = proc->u.func.argList; scan; scan = scan->next) { - prev = scan; - if ((search = scan->object) && search->name && search->name->name) { - if (!strcmp(name, search->name->name)) - break; - } - } - - if (!scan) - search = NULL; - - notFound = !search; - - if (!search) { - search = IRO_malloc(sizeof(Object)); - ep = NULL; - search->u.var.info = IRO_malloc(sizeof(VarInfo)); - memset(search->u.var.info, 0, sizeof(VarInfo)); - search->u.var.info->func = proc; - } else { - ep = search->extParam; - } - - vi = search->u.var.info; - memcpy(search, obj, sizeof(Object)); - search->extParam = ep; - search->u.var.info = vi; - search->u.var.realObj = obj; - - if (notFound) { - scan = IRO_malloc(sizeof(ObjectList)); - scan->next = NULL; - scan->object = search; - if (!prev) - proc->u.func.argList = scan; - else - prev->next = scan; - } - } - } - } else if (proc->type) { - for (args = TYPE_FUNC(proc->type)->args; args; args = args->next) { - if (args->name && (name = args->name->name) && name[0]) { - prev = NULL; - for (scan = proc->u.func.argList; scan; scan = scan->next) { - prev = scan; - if ((search = scan->object) && search->name && search->name->name) { - if (!strcmp(name, search->name->name)) - break; - } - } - - if (!scan) - search = NULL; - - if (!search) { - search = IRO_malloc(sizeof(Object)); - memset(search, 0, sizeof(Object)); - search->datatype = DLOCAL; - search->extParam = NULL; - search->name = GetHashNameNodeExport(name); - search->type = args->type; - search->qual = args->qual; - search->u.var.info = IRO_malloc(sizeof(VarInfo)); - memset(search->u.var.info, 0, sizeof(VarInfo)); - search->u.var.info->func = proc; - - scan = IRO_malloc(sizeof(ObjectList)); - scan->next = NULL; - scan->object = search; - if (!prev) - proc->u.func.argList = scan; - else - prev->next = scan; - } - } - } - } - - return proc->u.func.argList; -} - -static IRONode **FunctionNodeTable(Object *proc) { - IRO_ASSERT(4383, proc != NULL); - - IRO_ASSERT(4391, proc == stCurrentProc); - - return IRO_NodeTable; -} - -static IRONode *FunctionFirstNode(Object *proc) { - IRO_ASSERT(4401, proc != NULL); - - IRO_ASSERT(4409, proc == stCurrentProc); - - return IRO_FirstNode; -} - -static void UpdatePTFDomain() { - // no idea what this would've done -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct EvalCallActionParams { - Object *proc; - IRONode *fnode; - IROLinear *nd; - PartialTransferFunction *ptf; - ParamMappingFunction *map; - int x14; - Boolean x18; - Boolean x19; - Boolean x1A; -} EvalCallActionParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void EvalCallAction(Object *proc, void *refcon) { - EvalCallActionParams *params; - ParamMappingFunction *pmf; - PartialTransferFunction *tgtPTF; - Boolean flag; - Boolean flag2; - - IRO_ASSERT(4458, proc != NULL); - IRO_ASSERT(4459, refcon != NULL); - - params = refcon; - - IRO_ASSERT(4463, params->proc != NULL); - IRO_ASSERT(4464, params->fnode != NULL); - IRO_ASSERT(4465, params->nd != NULL); - IRO_ASSERT(4466, params->ptf != NULL); - IRO_ASSERT(4467, params->map == NULL || params->map != NULL); - - if (!params->x18) { - pmf = ParamMappingFunction_New(); - ParamMappingFunction_Init(pmf); - RecordActuals(params->nd, proc, pmf); - - flag = 0; - if (!Stack_sub_48A710(&stCallingContextStack, proc)) { - StackElement *element; - - flag2 = 0; - tgtPTF = GetPTF(pmf, proc, params->nd, params->ptf, &flag2); - - element = StackElement_New(); - StackElement_Init(element, proc, tgtPTF, pmf, params->nd); - Stack_sub_48A660(&stCallingContextStack, element); - StackElement_Term(element); - StackElement_Delete(element); - - IRO_ASSERT(4490, tgtPTF != NULL); - - flag = 1; - - if (stPTFList) - PTFList_sub_48A050(stPTFList, tgtPTF); - PartialTransferFunction_sub_48A610(tgtPTF, 0); - - if (flag2 || params->x1A) { - if (params->x1A) { - params->x1A = 0; - EvalProc(proc, pmf, tgtPTF); - } else { - tgtPTF = stUnknownPTF; - } - } - } else { - tgtPTF = stUnknownPTF; - } - - if (params->map) - params->x19 |= ApplySummary(tgtPTF, pmf, params->proc, params->fnode, params->nd, params->ptf, params->map, params->x14 == 1); - - if (flag) { - StackElement *element = Stack_sub_48A5B0(&stCallingContextStack); - StackElement_Term(element); - StackElement_Delete(element); - } - - ParamMappingFunction_Term(pmf); - ParamMappingFunction_Delete(pmf); - } -} - -static Boolean EvalCall(Object *proc, IRONode *fnode, IROLinear *nd, ParamMappingFunction *map, PartialTransferFunction *ptf) { - EvalCallActionParams params; - ObjectSet *objSet; - - IRO_ASSERT(4548, proc != NULL); - IRO_ASSERT(4549, fnode != NULL); - IRO_ASSERT(4550, nd != NULL); - IRO_ASSERT(4551, map != NULL); - IRO_ASSERT(4552, ptf != NULL); - - memset(¶ms, 0, sizeof(params)); - params.proc = proc; - params.fnode = fnode; - params.nd = nd; - params.ptf = ptf; - params.map = map; - params.x18 = 0; - params.x19 = 0; - params.x1A = 0; - - objSet = ObjectSet_New(); - ObjectSet_Init(objSet); - - params.x19 |= FindCallTargets(objSet, proc, nd, map, ptf); - params.x14 = ObjectSet_Count(objSet); - ObjectSet_ForEach(objSet, EvalCallAction, ¶ms); - - ObjectSet_Term(objSet); - ObjectSet_Delete(objSet); - - return params.x19; -} - -static void AdjustTypesForVolatilityAction(LocationSet *ls, void *refcon) { - Type *type; - Type *newtype; - UInt32 qual; - - type = LocationSet_rtype(ls); - switch (type->type) { - case TYPEARRAY: - qual = TYPE_POINTER(type)->qual; - break; - case TYPEPOINTER: - qual = TYPE_POINTER(type)->qual; - break; - case TYPEMEMBERPOINTER: - qual = TYPE_MEMBER_POINTER(type)->qual; - break; - default: - CError_FATAL(4604); - } - - if (!(qual & Q_VOLATILE)) { - switch (type->type) { - case TYPEARRAY: - newtype = CDecl_NewArrayType(TYPE_POINTER(type)->target, type->size); - TYPE_POINTER(newtype)->qual |= Q_VOLATILE; - break; - case TYPEPOINTER: - newtype = CDecl_NewPointerType(TYPE_POINTER(type)->target); - TYPE_POINTER(newtype)->qual |= Q_VOLATILE; - break; - case TYPEMEMBERPOINTER: - newtype = galloc(sizeof(TypeMemberPointer)); - memcpy(newtype, type, sizeof(TypeMemberPointer)); - TYPE_MEMBER_POINTER(newtype)->qual |= Q_VOLATILE; - break; - } - - LocationSet_SetRtype(ls, newtype); - } -} - -static void AdjustTypesForVolatility(LocationSetSet *set, Object *proc, IROLinear *nd) { - if (nd->rtype && CParser_IsVolatile(nd->rtype, nd->nodeflags & ENODE_FLAG_QUALS)) - LocationSetSet_ForEach(set, AdjustTypesForVolatilityAction, NULL); -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct EvalAssignAction2Params { - CInt64 x0; - IROLinear *nd; - Boolean xC; -} EvalAssignAction2Params; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void EvalAssignAction2(LocationSet *ls, void *refcon) { - EvalAssignAction2Params *params; - CInt64 value; - IROLinear *nd; - ENodeType oper; - UInt32 stride; - Type *rtype; - PAMemoryBlock *block; - - IRO_ASSERT(4657, ls != NULL); - IRO_ASSERT(4658, refcon != NULL); - - params = refcon; - - if (!params->xC && !LocationSet_IsUnknown(ls)) { - value = params->x0; - nd = params->nd; - IRO_ASSERT(4665, nd != NULL); - oper = nd->nodetype; - - stride = LocationSet_stride(ls); - rtype = LocationSet_rtype(ls); - block = LocationSet_block(ls); - - if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_INT) { - LocationSet_Term(ls); - - switch (oper) { - case EPOSTINC: - case EPREINC: - case EADDASS: - value = CInt64_Add(*((CInt64 *) PAMemoryBlock_thing(block)), value); - break; - case EPOSTDEC: - case EPREDEC: - case ESUBASS: - value = CInt64_Sub(*((CInt64 *) PAMemoryBlock_thing(block)), value); - break; - case EMULASS: - if (IRO_IsUnsignedType(nd->rtype)) - value = CInt64_MulU(*((CInt64 *) PAMemoryBlock_thing(block)), value); - else - value = CInt64_Mul(*((CInt64 *) PAMemoryBlock_thing(block)), value); - break; - case EDIVASS: - if (CInt64_IsZero(&value)) { - if (nd->stmt->sourceoffset) { - TStreamElement *e = CPrep_CurStreamElement(); - e->tokenoffset = nd->stmt->sourceoffset; - CError_SetErrorToken(e); - } - CError_Warning(CErrorStr139); - params->xC = 1; - } else { - if (IRO_IsUnsignedType(nd->rtype)) - value = CInt64_DivU(*((CInt64 *) PAMemoryBlock_thing(block)), value); - else - value = CInt64_Div(*((CInt64 *) PAMemoryBlock_thing(block)), value); - } - break; - case EMODASS: - if (CInt64_IsZero(&value)) { - if (nd->stmt->sourceoffset) { - TStreamElement *e = CPrep_CurStreamElement(); - e->tokenoffset = nd->stmt->sourceoffset; - CError_SetErrorToken(e); - } - CError_Warning(CErrorStr139); - params->xC = 1; - } else { - if (IRO_IsUnsignedType(nd->rtype)) - value = CInt64_ModU(*((CInt64 *) PAMemoryBlock_thing(block)), value); - else - value = CInt64_Mod(*((CInt64 *) PAMemoryBlock_thing(block)), value); - } - break; - case ESHLASS: - value = CInt64_Shl(*((CInt64 *) PAMemoryBlock_thing(block)), value); - break; - case ESHRASS: - if (IRO_IsUnsignedType(nd->rtype)) - value = CInt64_ShrU(*((CInt64 *) PAMemoryBlock_thing(block)), value); - else - value = CInt64_Shr(*((CInt64 *) PAMemoryBlock_thing(block)), value); - break; - case EANDASS: - value = CInt64_And(*((CInt64 *) PAMemoryBlock_thing(block)), value); - break; - case EXORASS: - value = CInt64_Xor(*((CInt64 *) PAMemoryBlock_thing(block)), value); - break; - case EORASS: - value = CInt64_Or(*((CInt64 *) PAMemoryBlock_thing(block)), value); - break; - default: - CError_FATAL(4746); - } - - block = PAMemoryBlock_New(); - PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_INT, &value); - LocationSet_InitKnown(ls, block, cint64_zero, stride, rtype); - } else { - if (oper == EPOSTDEC || oper == EPREDEC || oper == ESUBASS) - value = CInt64_Neg(value); - - switch (oper) { - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EADDASS: - case ESUBASS: - value = CInt64_Add(LocationSet_field(ls), value); - if (stride) { - CInt64 tmp; - CInt64_SetLong(&tmp, stride); - value = CInt64_Mod(value, tmp); - } - SetsLocationSetField_sub_4851B0(ls, value); - break; - default: - params->xC = 1; - break; - } - } - } -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct EvalAssignActionParams { - Object *proc; - PartialTransferFunction *ptf; - IROLinear *nd; - IRONode *fnode; - LocationSetSet *srcs; - Boolean x14; - Boolean x15; - Boolean x16; -} EvalAssignActionParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void EvalAssignAction(LocationSet *dst, void *refcon) { - EvalAssignActionParams *params; - LocationSetSet *srcs; - - IRO_ASSERT(4797, dst != NULL); - IRO_ASSERT(4798, refcon != NULL); - - params = refcon; - - IRO_ASSERT(4802, params->proc != NULL); - IRO_ASSERT(4802, params->ptf != NULL); - IRO_ASSERT(4803, params->nd != NULL); - IRO_ASSERT(4804, params->fnode != NULL); - IRO_ASSERT(4805, params->srcs != NULL); - - srcs = params->srcs; - if ( - !params->x14 || - !LocationSetRepresentsSingleLocation(dst, params->proc, params->nd->pointsToFunction) || - LocationIsVolatile(dst, params->proc) || - LocationSet_sub_48AF30(dst) - ) { - LocationSetSet *set = LocationSetSet_New(); - LocationSetSet_Init(set); - params->x15 |= Lookup(set, &stCallingContextStack, params->proc, NULL, params->ptf, dst, params->nd->pointsToFunction, 0, params->nd->rtype); - LocationSetSet_AddSet(srcs, set); - LocationSetSet_Term(set); - LocationSetSet_Delete(set); - } - - params->x16 |= Assign(params->ptf, dst, srcs, params->proc, params->nd, params->fnode); -} - -static Boolean EvalAssign(Object *proc, IROLinear *nd, IRONode *fnode, ParamMappingFunction *map, PartialTransferFunction *ptf) { - EvalAssignActionParams params; - EvalAssignAction2Params params2; - LocationSetSet *set; - LocationSet *tmp; - PAMemoryBlock *block; - Type *type; - - IRO_ASSERT(4840, proc != NULL); - IRO_ASSERT(4841, nd != NULL); - IRO_ASSERT(4842, fnode != NULL); - IRO_ASSERT(4843, map != NULL); - IRO_ASSERT(4844, ptf != NULL); - - memset(¶ms, 0, sizeof(params)); - params.proc = proc; - params.ptf = ptf; - params.nd = nd; - params.fnode = fnode; - params.x15 = 0; - params.x16 = 0; - - set = LocationSetSet_New(); - params.srcs = LocationSetSet_New(); - LocationSetSet_Init(set); - LocationSetSet_Init(params.srcs); - - if (nd->type == IROLinearOp2Arg) { - IRO_ASSERT(4861, nd->u.diadic.left->type == IROLinearOp1Arg && nd->u.diadic.left->nodetype == EINDIRECT); - - params.x15 |= EvalExpr(set, proc, nd->u.diadic.left->u.monadic, &stCallingContextStack, map, ptf); - AdjustTypesForVolatility(set, proc, nd->u.diadic.left); - params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.right, &stCallingContextStack, map, ptf); - - if (nd->nodetype != EASS) { - switch (nd->nodetype) { - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - if ( - LocationSetSet_Count(params.srcs) == 1 && - (tmp = LocationSetSet_FindFirst(params.srcs)) && - !LocationSet_IsUnknown(tmp) && - !LocationSet_stride(tmp) && - (block = LocationSet_block(tmp)) && - PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_INT - ) { - LocationSetSet_Term(params.srcs); - LocationSetSet_Init(params.srcs); - params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.left, &stCallingContextStack, map, ptf); - - memset(¶ms2, 0, sizeof(params2)); - params2.x0 = *((CInt64 *) PAMemoryBlock_thing(block)); - IRO_TruncateValueToType(¶ms2.x0, nd->u.diadic.right->rtype); - params2.nd = nd; - params2.xC = 0; - - if (!CInt64_IsZero(¶ms2.x0)) { - LocationSetSet_ForEach(params.srcs, EvalAssignAction2, ¶ms2); - if (params2.xC) { - LocationSetSet_Term(params.srcs); - LocationSetSet_Init(params.srcs); - params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.left, &stCallingContextStack, map, ptf); - if (!LocationSetSet_FindUnknown(params.srcs)) - LocationSetSet_ForEach(params.srcs, EvalExprAction2, (void *) &cint64_one); - } - } - } else { - LocationSetSet_Term(params.srcs); - LocationSetSet_Init(params.srcs); - params.x15 |= EvalExpr(params.srcs, proc, nd->u.diadic.left, &stCallingContextStack, map, ptf); - if (!LocationSetSet_FindUnknown(params.srcs)) - LocationSetSet_ForEach(params.srcs, EvalExprAction2, (void *) &cint64_one); - } - break; - default: - LocationSetSet_Term(params.srcs); - LocationSetSet_Init(params.srcs); - LocationSetSet_AddUnknown(params.srcs, nd->rtype, NULL, NULL); - break; - } - } - } else if (nd->type == IROLinearOp1Arg) { - IRO_ASSERT(4958, nd->u.monadic.left->type == IROLinearOp1Arg && nd->u.monadic->nodetype == EINDIRECT); - - params.x15 |= EvalExpr(set, proc, nd->u.monadic->u.monadic, &stCallingContextStack, map, ptf); - AdjustTypesForVolatility(set, proc, nd->u.monadic); - params.x15 |= EvalExpr(params.srcs, proc, nd->u.monadic, &stCallingContextStack, map, ptf); - - switch (nd->nodetype) { - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - memset(¶ms2, 0, sizeof(params2)); - params2.x0 = cint64_one; - params2.nd = nd; - params2.xC = 0; - - type = NULL; - if (IS_TYPE_POINTER(nd->rtype)) - type = TPTR_TARGET(nd->rtype); - else if (IS_TYPE_MEMBERPOINTER(nd->rtype)) - type = TYPE_MEMBER_POINTER(nd->rtype)->ty1; - - if (type) - CInt64_SetLong(¶ms2.x0, type->size); - - if (!CInt64_IsZero(¶ms2.x0)) { - LocationSetSet_ForEach(params.srcs, EvalAssignAction2, ¶ms2); - if (params2.xC) { - LocationSetSet_Term(params.srcs); - LocationSetSet_Init(params.srcs); - params.x15 |= EvalExpr(params.srcs, proc, nd->u.monadic, &stCallingContextStack, map, ptf); - if (!LocationSetSet_FindUnknown(params.srcs)) - LocationSetSet_ForEach(params.srcs, EvalExprAction2, (void *) &cint64_one); - } - } - break; - - default: - LocationSetSet_Term(params.srcs); - LocationSetSet_Init(params.srcs); - LocationSetSet_AddUnknown(params.srcs, nd->rtype, NULL, NULL); - break; - } - } else { - CError_FATAL(5006); - } - - if (LocationSetSet_Count(params.srcs) != 0) { - PointsToFunction *pointsToFunc; - - pointsToFunc = PointsToFunction_New(); - if (nd->pointsToFunction) - PointsToFunction_Copy(pointsToFunc, nd->pointsToFunction); - else - PointsToFunction_Init(pointsToFunc); - - params.x14 = LocationSetSet_Count(set) == 1; - LocationSetSet_ForEach(set, EvalAssignAction, ¶ms); - - if (!params.x15 && params.x16) { - if (nd->pointsToFunction) - params.x15 = !PointsToFunctions_Equal(pointsToFunc, nd->pointsToFunction); - else - params.x15 = PointsToFunction_FindFirst(pointsToFunc) != NULL; - } - - PointsToFunction_Term(pointsToFunc); - PointsToFunction_Delete(pointsToFunc); - } - - LocationSetSet_Term(set); - LocationSetSet_Term(params.srcs); - LocationSetSet_Delete(set); - LocationSetSet_Delete(params.srcs); - - return params.x15; -} - -static Boolean EvalReturn(Object *proc, IROLinear *nd, IRONode *fnode, ParamMappingFunction *map, PartialTransferFunction *ptf) { - EvalAssignActionParams params; - LocationSet *loc; - - IRO_ASSERT(5046, proc != NULL); - IRO_ASSERT(5047, nd != NULL); - IRO_ASSERT(5048, nd->type == IROLinearReturn); - IRO_ASSERT(5049, fnode != NULL); - IRO_ASSERT(5050, map != NULL); - IRO_ASSERT(5051, ptf != NULL); - - memset(¶ms, 0, sizeof(params)); - params.proc = proc; - params.ptf = ptf; - params.nd = nd; - params.fnode = fnode; - params.x15 = 0; - params.x16 = 0; - - if (nd->u.monadic) { - params.srcs = LocationSetSet_New(); - LocationSetSet_Init(params.srcs); - - loc = PartialTransferFunction_returnLocation(ptf); - params.x15 |= EvalExpr(params.srcs, proc, nd->u.monadic, &stCallingContextStack, map, ptf); - - if (LocationSetSet_Count(params.srcs) != 0) { - params.x14 = 1; - EvalAssignAction(loc, ¶ms); - params.x15 |= params.x16; - } - - LocationSetSet_Term(params.srcs); - LocationSetSet_Delete(params.srcs); - } - - return params.x15; -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct ApplySummaryActionParams { - ParamMappingFunction *tgtMap; - Object *proc; - IRONode *fnode; - IROLinear *nd; - PartialTransferFunction *ptf; - ParamMappingFunction *map; - LocationSet *loc; - LocationSetSet *locs; - Boolean x20; - Boolean x21; - Boolean x22; -} ApplySummaryActionParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void ApplySummaryAction2(ParamMapping *mapping, void *refcon) { - ApplySummaryActionParams *params; - PAMemoryBlock *block; - ExtendedParam *ep; - IROLinear *nd; - LocationSetSet *set; - EvalAssignActionParams assignParams; - - IRO_ASSERT(5108, mapping != NULL); - IRO_ASSERT(5109, refcon != NULL); - - params = refcon; - - IRO_ASSERT(5113, params->tgtMap != NULL); - IRO_ASSERT(5114, params->proc != NULL); - IRO_ASSERT(5115, params->fnode != NULL); - IRO_ASSERT(5116, params->nd != NULL); - IRO_ASSERT(5117, params->nd->type == IROLinearFunccall); - IRO_ASSERT(5118, params->ptf != NULL); - IRO_ASSERT(5119, params->map != NULL); - IRO_ASSERT(5120, params->loc != NULL); - IRO_ASSERT(5121, params->locs != NULL); - - block = LocationSet_block(params->loc); - - IRO_ASSERT(5124, block != NULL); - IRO_ASSERT(5125, PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM); - - ep = PAMemoryBlock_thing(block); - - IRO_ASSERT(5127, ep != NULL); - - if (ParamMapping_extended(mapping) == ep && (nd = ParamMapping_actual(mapping))) { - set = LocationSetSet_New(); - LocationSetSet_Init(set); - params->x21 |= EvalExpr(set, params->proc, nd, &stCallingContextStack, params->map, params->ptf); - - if (!LocationSetSet_FindUnknown(set)) { - CInt64 stride64; - CInt64 value; - - value = LocationSet_field(params->loc); - LocationSetSet_ForEach(set, EvalExprAction, &value); - - CInt64_SetULong(&stride64, LocationSet_stride(params->loc)); - LocationSetSet_ForEach(set, EvalExprAction2, &stride64); - } - - memset(&assignParams, 0, sizeof(assignParams)); - assignParams.proc = params->proc; - assignParams.ptf = params->ptf; - assignParams.nd = params->nd; - assignParams.fnode = params->fnode; - assignParams.srcs = params->locs; - assignParams.x14 = params->x20 && (LocationSetSet_Count(set) == 1); - assignParams.x15 = 0; - assignParams.x16 = 0; - LocationSetSet_ForEach(set, EvalAssignAction, &assignParams); - - LocationSetSet_Term(set); - LocationSetSet_Delete(set); - - params->x21 |= assignParams.x15; - params->x22 |= assignParams.x16; - } -} - -static void ApplySummaryAction(PointsToEntry *pte, void *refcon) { - ApplySummaryActionParams *params; - LocationSet *loc; - PAMemoryBlock *block; - - IRO_ASSERT(5175, pte != NULL); - IRO_ASSERT(5176, refcon != NULL); - - params = refcon; - - IRO_ASSERT(5180, params->tgtMap != NULL); - IRO_ASSERT(5181, params->proc != NULL); - IRO_ASSERT(5182, params->fnode != NULL); - IRO_ASSERT(5183, params->nd != NULL); - IRO_ASSERT(5184, params->nd->type == IROLinearFunccall); - IRO_ASSERT(5185, params->ptf != NULL); - IRO_ASSERT(5186, params->map != NULL); - - loc = PointsToEntry_loc(pte); - - IRO_ASSERT(5189, loc != NULL); - IRO_ASSERT(5190, !LocationSet_IsUnknown(loc)); - - block = LocationSet_block(loc); - if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { - params->loc = loc; - params->locs = PointsToEntry_locs(pte); - pmf_sub_487C70(params->tgtMap, ApplySummaryAction2, params); - } -} - -static Boolean ApplySummary(PartialTransferFunction *tgtPTF, ParamMappingFunction *tgtMap, Object *proc, IRONode *fnode, IROLinear *nd, PartialTransferFunction *ptf, ParamMappingFunction *map, Boolean flag) { - Boolean result; - ApplySummaryActionParams params; - PointsToFunction *pointsToFunc; - - IRO_ASSERT(5208, tgtPTF != NULL); - IRO_ASSERT(5209, tgtMap != NULL); - IRO_ASSERT(5210, proc != NULL); - IRO_ASSERT(5211, fnode != NULL); - IRO_ASSERT(5212, nd != NULL); - IRO_ASSERT(5213, nd->type == IROLinearFunccall); - IRO_ASSERT(5214, ptf != NULL); - IRO_ASSERT(5215, map != NULL); - - StoreReturnedLocations(nd, tgtPTF, tgtMap); - if (tgtPTF == stUnknownPTF) { - result = KillAllAddressableLocations(proc, fnode, nd, ptf); - } else { - pointsToFunc = PointsToFunction_New(); - if (nd->pointsToFunction) - PointsToFunction_Copy(pointsToFunc, nd->pointsToFunction); - else - PointsToFunction_Init(pointsToFunc); - - memset(¶ms, 0, sizeof(params)); - params.tgtMap = tgtMap; - params.proc = proc; - params.fnode = fnode; - params.nd = nd; - params.ptf = ptf; - params.map = map; - params.loc = NULL; - params.locs = NULL; - params.x20 = flag; - params.x21 = 0; - params.x22 = 0; - - PointsToFunction_ForEach(PartialTransferFunction_finalPointsToFn(tgtPTF), ApplySummaryAction, ¶ms); - - result = params.x21; - if (!params.x21 && params.x22) { - if (nd->pointsToFunction) - result = !PointsToFunctions_Equal(pointsToFunc, nd->pointsToFunction); - else - result = PointsToFunction_FindFirst(pointsToFunc) != NULL; - } - } - - return result; -} - -static void GetPTFAction2(ParamMapping *mapping, void *refcon) { - IRO_ASSERT(5331, mapping != NULL); - - if (ParamMapping_extended(mapping)) - ParamMapping_SetExtended(mapping, NULL); -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct GetPTFActionParams { - ParamMappingFunction *map; - Object *proc; - IROLinear *nd; - PartialTransferFunction *ptf; - Boolean *needVisit; - PartialTransferFunction *x14; - PartialTransferFunction *x18; -} GetPTFActionParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void GetPTFAction(PartialTransferFunction *tgtPTF, void *refcon) { - GetPTFActionParams *params; - - IRO_ASSERT(5359, tgtPTF != NULL); - IRO_ASSERT(5360, refcon != NULL); - - params = refcon; - - IRO_ASSERT(5364, params->map != NULL); - IRO_ASSERT(5365, params->proc != NULL); - IRO_ASSERT(5366, params->proc != &stUnknown); - IRO_ASSERT(5367, params->nd != NULL); - IRO_ASSERT(5368, params->ptf != NULL); - IRO_ASSERT(5369, params->needVisit != NULL); - - if (!params->x18) { - if (MatchPTF(tgtPTF, params->proc, params->map, params->nd, params->ptf)) { - if (InputsHaveNewPointerValues(tgtPTF, params->ptf)) - *params->needVisit = 1; - params->x18 = tgtPTF; - } else { - pmf_sub_487C70(params->map, GetPTFAction2, NULL); - if (PTF_sub_48B980(tgtPTF) == params->nd && PTF_sub_48B970(tgtPTF) == params->ptf) - params->x14 = tgtPTF; - } - } -} - -static PartialTransferFunction *GetPTF(ParamMappingFunction *map, Object *proc, IROLinear *nd, PartialTransferFunction *ptf, Boolean *needVisit) { - PartialTransferFunction *found; - PartialTransferFunction *result; - GetPTFActionParams params; - - IRO_ASSERT(5396, map != NULL); - IRO_ASSERT(5397, proc != NULL); - IRO_ASSERT(5398, nd != NULL); - IRO_ASSERT(5399, ptf != NULL); - IRO_ASSERT(5400, needVisit != NULL); - - if (proc == &stUnknown) { - result = stUnknownPTF; - } else { - memset(¶ms, 0, sizeof(params)); - params.map = map; - params.proc = proc; - params.nd = nd; - params.ptf = PartialTransferFunction_New(); - PartialTransferFunction_Init(params.ptf, nd, ptf); - params.needVisit = needVisit; - params.x14 = NULL; - params.x18 = NULL; - - if (!proc->u.func.ptfList) { - proc->u.func.ptfList = PTFList_New(); - PTFList_Init(proc->u.func.ptfList); - } - - PTFList_ForEach(proc->u.func.ptfList, GetPTFAction, ¶ms); - - found = params.x18; - if (found && !*needVisit) { - PartialTransferFunction_Copy(result = PartialTransferFunction_New(), found); - } else { - result = stUnknownPTF; - } - - PartialTransferFunction_Term(params.ptf); - PartialTransferFunction_Delete(params.ptf); - } - - return result; -} - -static Boolean IsMeetNode(IRONode *fnode, IROLinear *nd) { - return (fnode->numpred > 1) && (fnode->first == nd); -} - -static Boolean IsExitNode(Object *proc, IRONode *fnode) { - IRO_ASSERT(5467, proc != NULL); - IRO_ASSERT(5468, fnode != NULL); - - return (fnode->numsucc == 0) && Bv_IsBitSet(FunctionFirstNode(proc)->index, fnode->dom); -} - -static Boolean SomePredecessorHasBeenVisited(Object *proc, IRONode *fnode) { - UInt16 i; - - IRO_ASSERT(5479, proc != NULL); - IRO_ASSERT(5480, fnode != NULL); - - for (i = 0; i < fnode->numpred; i++) { - if (FunctionNodeTable(proc)[fnode->pred[i]]->x3C) - return 1; - } - - return 0; -} - -static Boolean AllPredecessorsHaveBeenVisited(Object *proc, IRONode *fnode) { - UInt16 i; - - IRO_ASSERT(0, proc != NULL); - IRO_ASSERT(0, fnode != NULL); - - for (i = 0; i < fnode->numpred; i++) { - if (!FunctionNodeTable(proc)[fnode->pred[i]]->x3C) - return 0; - } - - return 1; -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct EvalProcActionParams { - Object *proc; - IRONode *fnode; - PartialTransferFunction *ptf; -} EvalProcActionParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void EvalProcAction2(PointsToEntry *pte, void *refcon) { - EvalProcActionParams *params; - LocationSet *dst; - PAMemoryBlock *block; - LocationSetSet *set; - IRONode *node; - - IRO_ASSERT(5525, pte != NULL); - IRO_ASSERT(5526, refcon != NULL); - - params = refcon; - - IRO_ASSERT(5530, params->proc != NULL); - IRO_ASSERT(5531, params->fnode != NULL); - IRO_ASSERT(5532, params->ptf != NULL); - - dst = PointsToEntry_loc(pte); - - IRO_ASSERT(5535, dst != NULL); - IRO_ASSERT(5536, !LocationSet_IsUnknown(dst)); - - block = LocationSet_block(dst); - - if (block && (LocationSet_sub_48AF30(dst) || PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM)) { - set = LocationSetSet_New(); - LocationSetSet_Init(set); - LocationSetSet_AddSet(set, PointsToEntry_locs(pte)); - - for (node = FunctionFirstNode(params->proc); node; node = node->nextnode) { - if (node->x3C && node != params->fnode && IsExitNode(params->proc, node)) { - if (node->last->pointsToFunction) - Lookup(set, &stCallingContextStack, params->proc, NULL, params->ptf, dst, node->last->pointsToFunction, 0, NULL); - } - } - - Assign(params->ptf, dst, set, params->proc, NULL, NULL); - - LocationSetSet_Term(set); - LocationSetSet_Delete(set); - } -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct AssignEachInPointsToFunctionActionParams { - Object *proc; - IROLinear *nd; - IRONode *fnode; - PartialTransferFunction *ptf; - Boolean x10; -} AssignEachInPointsToFunctionActionParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void AssignEachInPointsToFunctionAction(PointsToEntry *pte, void *refcon) { - AssignEachInPointsToFunctionActionParams *params; - LocationSet *dst; - LocationSetSet *srcs; - - IRO_ASSERT(5577, pte != NULL); - IRO_ASSERT(5578, refcon != NULL); - - params = refcon; - - IRO_ASSERT(5582, params->proc != NULL); - IRO_ASSERT(5583, params->nd != NULL); - IRO_ASSERT(5584, params->fnode != NULL); - IRO_ASSERT(5585, params->ptf != NULL); - - dst = PointsToEntry_loc(pte); - - srcs = LocationSetSet_New(); - LocationSetSet_Init(srcs); - LocationSetSet_AddSet(srcs, PointsToEntry_locs(pte)); - params->x10 |= Assign(params->ptf, dst, srcs, params->proc, params->nd, params->fnode); - LocationSetSet_Term(srcs); - LocationSetSet_Delete(srcs); -} - -static void AssignEachInPointsToFunction(PointsToFunction *pointsTo, void *refcon) { - AssignEachInPointsToFunctionActionParams *params; - PointsToFunction *pointsToFunc; - - IRO_ASSERT(5602, pointsTo != NULL); - IRO_ASSERT(5603, refcon != NULL); - - params = refcon; - - IRO_ASSERT(5607, params->nd != NULL); - - pointsToFunc = PointsToFunction_New(); - if (params->nd->pointsToFunction) - PointsToFunction_Copy(pointsToFunc, params->nd->pointsToFunction); - else - PointsToFunction_Init(pointsToFunc); - - if (PointsToFunction_FindFirst(pointsToFunc)) { - PointsToFunction_ForEach(pointsTo, AssignEachInPointsToFunctionAction, params); - } else { - if (!params->nd->pointsToFunction) - params->nd->pointsToFunction = PointsToFunction_New(); - else - PointsToFunction_Term(params->nd->pointsToFunction); - - PointsToFunction_Copy(params->nd->pointsToFunction, pointsTo); - params->x10 = 1; - } - - if (params->x10) { - if (params->nd->pointsToFunction) - params->x10 = !PointsToFunctions_Equal(pointsToFunc, params->nd->pointsToFunction); - else - params->x10 = PointsToFunction_FindFirst(pointsToFunc) != NULL; - } - - PointsToFunction_Term(pointsToFunc); - PointsToFunction_Delete(pointsToFunc); -} - -static Boolean ObjectIsAFunctionArgument(Object *proc, Object *obj) { - ObjectList *list; - - IRO_ASSERT(5643, proc != NULL); - IRO_ASSERT(5644, proc != &stUnknown); - IRO_ASSERT(5645, obj != NULL); - - if (obj->datatype == DLOCAL) { - for (list = FunctionArguments(proc); list; list = list->next) { - if (obj == list->object) - return 1; - } - } - - return 0; -} - -static Boolean ObjectIsARealFunctionArgument(Object *proc, Object *obj) { - ObjectList *list; - - IRO_ASSERT(5661, proc != NULL); - IRO_ASSERT(5662, proc != &stUnknown); - IRO_ASSERT(5663, obj != NULL); - - if (obj->datatype == DLOCAL && proc == cscope_currentfunc) { - for (list = arguments; list; list = list->next) { - if (obj == list->object) - return 1; - } - } - - return 0; -} - -static void AddLocalVarsAddressedByExceptionUses(Object *var) { - IRO_ASSERT(5699, var != NULL); - IRO_ASSERT(5700, stExceptionFNode != NULL); - IRO_ASSERT(5701, stExceptionFNode->addressed != NULL); - - if (var->datatype == DLOCAL) - ObjectSet_sub_4867D0(stExceptionFNode->addressed, var); -} - -static Boolean LinearNodeIsInFlowgraphNode(IROLinear *nd, IRONode *fnode) { - IROLinear *first; - IROLinear *last; - IROLinear *scan; - - if (fnode && (first = fnode->first) && (last = fnode->last)) { - for (scan = first; scan && scan != last->next; scan = scan->next) { - if (scan == nd) - return 1; - } - } - - return 0; -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -static struct { - Object *proc; - IRONode *fnode; - ParamMappingFunction *map; - PartialTransferFunction *ptf; - PointsToFunction *pointsToFunc; - Boolean *changed; - Boolean x18; - Boolean x19; -} stEvalProcActionParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void EvalProcAction(IROLinear *Int, Boolean flag) { - Boolean *changed; - Boolean result; - Object *proc; - PartialTransferFunction *ptf; - Boolean x18; - Boolean x19; - IRONode *fnode; - PointsToFunction *pointsToFunc; - ParamMappingFunction *map; - Object *obj; - AssignEachInPointsToFunctionActionParams params; - - static int userBreakCounter; - - if (!flag && !Int->x1E) { - IRO_ASSERT(5748, Int != NULL); - IRO_ASSERT(5749, stEvalProcActionParams.changed != NULL); - - proc = stEvalProcActionParams.proc; - fnode = stEvalProcActionParams.fnode; - map = stEvalProcActionParams.map; - ptf = stEvalProcActionParams.ptf; - pointsToFunc = stEvalProcActionParams.pointsToFunc; - changed = stEvalProcActionParams.changed; - x18 = stEvalProcActionParams.x18; - x19 = stEvalProcActionParams.x19; - - IRO_ASSERT(5760, proc != NULL); - IRO_ASSERT(5761, fnode != NULL); - IRO_ASSERT(5762, map != NULL); - IRO_ASSERT(5763, ptf != NULL); - - if (++userBreakCounter > 40) { - IRO_CheckForUserBreak(); - userBreakCounter = 0; - } - - result = 0; - - if (x19 && Int->pointsToFunction) { - PointsToFunction_Term(Int->pointsToFunction); - PointsToFunction_Delete(Int->pointsToFunction); - Int->pointsToFunction = NULL; - } - - memset(¶ms, 0, sizeof(params)); - params.proc = proc; - params.nd = Int; - params.fnode = fnode; - params.ptf = ptf; - params.x10 = 0; - - if (x18) { - PointsToFunction *initial = PartialTransferFunction_initialPointsToFn(ptf); - if (fnode == FunctionFirstNode(proc) && initial) { - AssignEachInPointsToFunction(initial, ¶ms); - result |= params.x10; - } - result |= EvalMeet(proc, fnode, Int, ptf); - pointsToFunc = Int->pointsToFunction; - x18 = 0; - } else if (!Int->pointsToFunction) { - if (pointsToFunc) - AssignEachInPointsToFunction(pointsToFunc, ¶ms); - result |= params.x10; - pointsToFunc = Int->pointsToFunction; - } - - if (IRO_IsAssignment(Int)) { - if (Int->flags & IROLF_4000) - longjmp(stAbortPointerAnalysis, 1); - result |= EvalAssign(proc, Int, fnode, map, ptf); - pointsToFunc = Int->pointsToFunction; - } else if (Int->type == IROLinearReturn) { - result |= EvalReturn(proc, Int, fnode, map, ptf); - pointsToFunc = Int->pointsToFunction; - } else if (Int->type == IROLinearFunccall) { - if (Int->flags & IROLF_4000) - longjmp(stAbortPointerAnalysis, 1); - if (Int->stmt && IRO_FunctionCallMightThrowException(Int)) { - stExceptionFNode = fnode; - IRO_WalkExcActions(Int->stmt->dobjstack, AddLocalVarsAddressedByExceptionUses); - } - result |= EvalCall(proc, fnode, Int, map, ptf); - pointsToFunc = Int->pointsToFunction; - } else if (Int->type == IROLinearOp1Arg && Int->nodetype == EINDIRECT && (!(Int->flags & IROLF_Assigned) || (Int->flags & IROLF_Used))) { - result |= EvalExpr(NULL, proc, Int, &stCallingContextStack, map, ptf); - } else if (Int->type == IROLinearOperand && !(Int->flags & IROLF_Ind) && Int->u.node->type == EOBJREF && (obj = Int->u.node->data.objref) && obj->datatype == DLOCAL) { - ObjectSet_sub_4867D0(fnode->addressed, obj); - } else if (Int->type == IROLinearAsm) { - IAEffects effects; - int i; - CodeGen_GetAsmEffects(Int->u.asm_stmt, &effects); - for (i = 0; i < effects.numoperands; i++) { - obj = effects.operands[i].object; - if (obj && obj->datatype == DLOCAL && effects.operands[i].type == IAEffect_3) { - ObjectSet_sub_4867D0(fnode->addressed, obj); - } - } - } - - if (result && Int != fnode->last && fnode->last->pointsToFunction) { - PointsToFunction_Term(fnode->last->pointsToFunction); - PointsToFunction_Delete(fnode->last->pointsToFunction); - fnode->last->pointsToFunction = NULL; - } - - *changed |= result; - x19 |= result; - - stEvalProcActionParams.pointsToFunc = pointsToFunc; - stEvalProcActionParams.x18 = x18; - stEvalProcActionParams.x19 = x19; - - Int->x1E = 1; - - if (Int->type != IROLinearReturn) { - IROLinear *father = IRO_LocateFather(Int); - if (father && father->type == IROLinearReturn) { - if (LinearNodeIsInFlowgraphNode(father, fnode)) - EvalProcAction(father, 0); - else - longjmp(stAbortPointerAnalysis, 1); - } - } - } -} - -static void EvalProc(Object *proc, ParamMappingFunction *map, PartialTransferFunction *ptf) { - IRONode *fnode; - IRONode *pred; - IROLinear *nd; - UInt32 passCount; - Boolean changed; - UInt16 i; - AssignEachInPointsToFunctionActionParams assignParams; - EvalProcActionParams params; - - IRO_ASSERT(5964, proc != NULL); - IRO_ASSERT(5965, map != NULL); - IRO_ASSERT(5966, ptf != NULL); - - for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) - fnode->x3C = 0; - - passCount = 0; - do { - clock(); - changed = 0; - for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) { - if (fnode->last && ((fnode->numpred == 0) || SomePredecessorHasBeenVisited(proc, fnode))) { - clock(); - if (!fnode->addressed) { - fnode->addressed = ObjectSet_New(); - ObjectSet_Init(fnode->addressed); - } - - for (i = 0; i < fnode->numpred; i++) { - pred = FunctionNodeTable(proc)[fnode->pred[i]]; - if (pred->addressed) - ObjectSet_sub_48C590(fnode->addressed, pred->addressed); - } - - memset(&stEvalProcActionParams, 0, sizeof(stEvalProcActionParams)); - stEvalProcActionParams.proc = proc; - stEvalProcActionParams.fnode = fnode; - stEvalProcActionParams.map = map; - stEvalProcActionParams.ptf = ptf; - stEvalProcActionParams.pointsToFunc = NULL; - stEvalProcActionParams.changed = &changed; - stEvalProcActionParams.x18 = 1; - stEvalProcActionParams.x19 = 0; - - for (nd = fnode->first; nd && nd != fnode->last->next; nd = nd->next) - nd->x1E = 0; - IRO_WalkInts(fnode->first, fnode->last, EvalProcAction); - - if (stEvalProcActionParams.x18 || !fnode->last->pointsToFunction) { - memset(&assignParams, 0, sizeof(assignParams)); - assignParams.proc = proc; - assignParams.nd = fnode->last; - assignParams.fnode = fnode; - assignParams.ptf = ptf; - assignParams.x10 = 0; - if (stEvalProcActionParams.x18) { - PointsToFunction *initial = PartialTransferFunction_initialPointsToFn(ptf); - if (fnode == FunctionFirstNode(proc) && initial) { - AssignEachInPointsToFunction(initial, &assignParams); - changed |= assignParams.x10; - } - changed |= EvalMeet(proc, fnode, fnode->last, ptf); - stEvalProcActionParams.x18 = 0; - } else { - if (stEvalProcActionParams.pointsToFunc) - AssignEachInPointsToFunction(stEvalProcActionParams.pointsToFunc, &assignParams); - changed |= assignParams.x10; - } - } - - fnode->x3C = 1; - clock(); - } - } - - clock(); - if (++passCount > 32) - CError_FATAL(6072); - } while (changed); - - if (passCount > stMaxPassCount) - stMaxPassCount = passCount; - - PartialTransferFunction_sub_48A610(ptf, 1); - - memset(¶ms, 0, sizeof(params)); - params.proc = proc; - params.ptf = ptf; - for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) { - if (fnode->x3C && IsExitNode(proc, fnode) && fnode->last->pointsToFunction) { - params.fnode = fnode; - PointsToFunction_ForEach(fnode->last->pointsToFunction, EvalProcAction2, ¶ms); - } - } -} - -static void PointerAnalysis_Init(void) { - stCallingContextStack = Stack_New(); - Stack_Init(stCallingContextStack); - - stUnknownPTF = PartialTransferFunction_New(); - PartialTransferFunction_Init(stUnknownPTF, NULL, NULL); - - stExtParamSet = AllocsExtParamSet_sub_4876C0(); - InitsExtParamSet_sub_4876A0(stExtParamSet); - - stPTFList = PTFList_New(); - PTFList_Init(stPTFList); -} - -static void CleanseLocationSet(LocationSet *loc, void *refcon) { - PAMemoryBlock *block; - PALocalVar *local; - - IRO_ASSERT(6161, loc != NULL); - IRO_ASSERT(6162, refcon == NULL); - - if ( - !LocationSet_IsUnknown(loc) && - (block = LocationSet_block(loc)) && - PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR && - (local = PAMemoryBlock_thing(block)) - ) { - PALocalVar_SetSth_sub_4847C0(local, NULL); - } -} - -static void CleansePointsToEntry(PointsToEntry *pte, void *refcon) { - IRO_ASSERT(6177, pte != NULL); - IRO_ASSERT(6178, refcon == NULL); - - CleanseLocationSet(PointsToEntry_loc(pte), NULL); - LocationSetSet_ForEach(PointsToEntry_locs(pte), CleanseLocationSet, NULL); -} - -static void PointerAnalysis_TermAction4(PartialTransferFunction *ptf, void *refcon) { - IRO_ASSERT(6187, ptf != NULL); - IRO_ASSERT(6188, refcon == NULL); - - if (ptf != stUnknownPTF) { - PointsToFunction_ForEach(PartialTransferFunction_initialPointsToFn(ptf), CleansePointsToEntry, NULL); - PointsToFunction_ForEach(PartialTransferFunction_finalPointsToFn(ptf), CleansePointsToEntry, NULL); - } -} - -static void PointerAnalysis_TermAction3(ExtendedParam *ep) { - ExtendedParam_Term(ep); - ExtendedParam_Delete(ep); -} - -static void PointerAnalysis_TermAction2(Object *obj, void *refcon) { - ObjectSet *objSet; - Object *proc; - ObjectList *list; - - objSet = refcon; - - if (!ObjectIsAnExtendedParamCandidate(obj)) { - if ( - obj->datatype == DLOCAL && - obj->u.var.info && - (proc = obj->u.var.info->func) && - ObjectIsAFunction(proc) && - proc->u.func.argList - ) { - for (list = proc->u.func.argList; list; list = list->next) { - if (obj == list->object) - break; - } - - if (!list) - ObjectSet_sub_4867D0(objSet, obj); - } else { - ObjectSet_sub_4867D0(objSet, obj); - } - } -} - -static void PointerAnalysis_TermAction1(ExtendedParam *ep, void *refcon) { - ObjectSet *objSet; - ObjectSet *epObjSet; - Object *obj; - - objSet = ObjectSet_New(); - ObjectSet_Init(objSet); - - epObjSet = ExtendedParam_objectSet(ep); - obj = NULL; - ObjectSet_ForEach(epObjSet, FindGlobalObjectAction, &obj); - if (obj) { - ObjectSet_ForEach(epObjSet, PointerAnalysis_TermAction2, objSet); - if (ObjectSet_FindFirst(objSet)) - EP_sub_48C850(ep, objSet); - } - - ObjectSet_Term(objSet); - ObjectSet_Delete(objSet); -} - -static void PointerAnalysis_Term(void) { - if (stExtParamSet) { - MaybeWalkExtParamSet_sub_48CBE0(stExtParamSet, PointerAnalysis_TermAction1, NULL); - TermsExtParamSet_sub_48CB00(stExtParamSet); - FreesExtParamSet_sub_48CAE0(stExtParamSet); - stExtParamSet = NULL; - } - - if (stPTFList) { - PTFList_ForEach(stPTFList, PointerAnalysis_TermAction4, NULL); - PTFList_Term(stPTFList); - PTFList_Delete(stPTFList); - stPTFList = NULL; - } - - PartialTransferFunction_Term(stUnknownPTF); - PartialTransferFunction_Delete(stUnknownPTF); - stUnknownPTF = NULL; - - Stack_Term(&stCallingContextStack); - Stack_Delete(stCallingContextStack); - stCallingContextStack = NULL; -} - -static void InvalidatePointsToFunctions(Object *proc) { - IRONode *fnode; - IROLinear *nd; - - IRO_ASSERT(6302, proc != NULL); - - for (fnode = FunctionFirstNode(proc); fnode; fnode = fnode->nextnode) { - if (fnode->last) { - if (fnode->addressed) { - ObjectSet_Term(fnode->addressed); - ObjectSet_Delete(fnode->addressed); - fnode->addressed = NULL; - } - - for (nd = fnode->first; nd && nd != fnode->last->next; nd = nd->next) { - if (nd->pointsToFunction) { - PointsToFunction_Term(nd->pointsToFunction); - PointsToFunction_Delete(nd->pointsToFunction); - nd->pointsToFunction = NULL; - } - } - } - } -} - -static void InitialSetup(void) { -} - -static void PointerAnalysis_HeapErrorProc(void) { - longjmp(stAbortPointerAnalysis, 2); -} - -void PointerAnalysis_Setup(void) { - IRO_InitializeAllocator(); - stExtendedParamNum = 0; - stParamObjs = NULL; - stMaxPassCount = 0; -} - -void PointerAnalysis_Cleanup(void) { - ObjectList *list; - ObjectList *next; - - for (list = stParamObjs; list; list = next) { - IRO_free(list->object); - next = list->next; - IRO_free(list); - } - stParamObjs = NULL; - IRO_TerminateAllocator(); -} - -void IRO_AnalyzePointers(Object *function) { - EvalCallActionParams params; - IROLinear nd; - IRONode fnode; - int code; - volatile heaperror_t saveheaperror; - - IRO_ASSERT(6393, function != NULL); - - PointerAnalysis_Init(); - - memset(¶ms, 0, sizeof(params)); - memset(&nd, 0, sizeof(nd)); - nd.type = IROLinearFunccall; - memset(&fnode, 0, sizeof(fnode)); - params.proc = &stUnknown; - params.fnode = &fnode; - params.nd = &nd; - params.ptf = stUnknownPTF; - params.map = NULL; - params.x18 = 0; - params.x19 = 0; - params.x1A = 1; - - stCurrentProc = FindMainEntryPoint(function); - - if ((code = setjmp(stAbortPointerAnalysis)) == 0) { - saveheaperror = getheaperror(); - setheaperror(PointerAnalysis_HeapErrorProc); - InitialSetup(); - EvalCallAction(stCurrentProc, ¶ms); - PointerAnalysis_Term(); - stCurrentProc = NULL; - setheaperror(saveheaperror); - } else { - setheaperror(saveheaperror); - InvalidatePointsToFunctions(stCurrentProc); - PointerAnalysis_Term(); - stCurrentProc = NULL; - if (code == 2 && saveheaperror) - saveheaperror(); - } -} - -static void RemoveRestrictedExtendedParamsAction(LocationSet *ls, void *refcon) { - LocationSetSet *locs; - PAMemoryBlock *block; - ExtendedParam *ep; - ObjectSet *objSet; - Object *obj; - - locs = refcon; - - if ( - !LocationSet_IsUnknown(ls) && - (block = LocationSet_block(ls)) && - PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM && - (ep = PAMemoryBlock_thing(block)) - ) { - objSet = ExtendedParam_objectSet(ep); - if ( - ObjectSet_Count(objSet) == 1 && - (obj = ObjectSet_FindFirst(objSet)) && - ObjectIsRestrictQualified(obj) - ) { - LocationSetSet_Add(locs, ls); - } - } -} - -static void RemoveRestrictedExtendedParams(LocationSetSet *locs) { - LocationSetSet *set; - - set = LocationSetSet_New(); - LocationSetSet_Init(set); - LocationSetSet_ForEach(locs, RemoveRestrictedExtendedParamsAction, set); - LocationSetSet_sub_488700(locs, set); - LocationSetSet_Term(set); - LocationSetSet_Delete(set); -} - -Boolean PointerAnalysis_TwoLinearNodePointerExprsMightAlias(Object *proc, IROLinear *nd1, IROLinear *nd2) { - LocationSetSet *lss1; - LocationSetSet *lss2; - PointsToFunction *pointsTo1; - PointsToFunction *pointsTo2; - PointsToFunction *savePointsTo1; - PointsToFunction *savePointsTo2; - FindAliasingParams params; - - pointsTo1 = nd1->pointsToFunction; - pointsTo2 = nd2->pointsToFunction; - if (!pointsTo1) - pointsTo1 = pointsTo2; - if (!pointsTo2) - pointsTo2 = pointsTo1; - - if (copts.opt_pointer_analysis_mode == 2 && !is_typeequal(nd1->rtype, nd2->rtype)) - return 0; - if (!pointsTo1 || !pointsTo2) - return 1; - - lss1 = LocationSetSet_New(); - LocationSetSet_Init(lss1); - lss2 = LocationSetSet_New(); - LocationSetSet_Init(lss2); - - savePointsTo1 = nd1->pointsToFunction; - nd1->pointsToFunction = pointsTo1; - EvalExpr(lss1, proc, nd1, NULL, NULL, NULL); - nd1->pointsToFunction = savePointsTo1; - - savePointsTo2 = nd2->pointsToFunction; - nd2->pointsToFunction = pointsTo2; - EvalExpr(lss2, proc, nd2, NULL, NULL, NULL); - nd2->pointsToFunction = savePointsTo2; - - memset(¶ms, 0, sizeof(params)); - params.x8 = 0; - params.x0 = lss2; - LocationSetSet_ForEach(lss1, FindAliasingAction, ¶ms); - - if (!params.x8) { - params.x0 = lss1; - LocationSetSet_ForEach(lss2, FindAliasingAction, ¶ms); - - if (!params.x8) { - RemoveRestrictedExtendedParams(lss1); - RemoveRestrictedExtendedParams(lss2); - ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss1); - ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss2); - - params.x0 = lss2; - LocationSetSet_ForEach(lss1, FindAliasingAction, ¶ms); - - if (!params.x8) { - params.x0 = lss1; - LocationSetSet_ForEach(lss2, FindAliasingAction, ¶ms); - } - } - } - - LocationSetSet_Term(lss1); - LocationSetSet_Delete(lss1); - LocationSetSet_Term(lss2); - LocationSetSet_Delete(lss2); - - return params.x8; -} - -Boolean PointerAnalysis_TwoENodePointerExprsMightAlias(Object *proc, ENode *nd1, ENode *nd2) { - LocationSetSet *lss1; - LocationSetSet *lss2; - PointsToFunction *pointsTo1; - PointsToFunction *pointsTo2; - PointsToFunction *savePointsTo1; - PointsToFunction *savePointsTo2; - FindAliasingParams params; - - pointsTo1 = nd1->pointsTo; - pointsTo2 = nd2->pointsTo; - if (!pointsTo1) - pointsTo1 = pointsTo2; - if (!pointsTo2) - pointsTo2 = pointsTo1; - - if (copts.opt_pointer_analysis_mode == 2 && !is_typeequal(nd1->rtype, nd2->rtype)) - return 0; - if (!pointsTo1 || !pointsTo2) - return 1; - - lss1 = LocationSetSet_New(); - LocationSetSet_Init(lss1); - lss2 = LocationSetSet_New(); - LocationSetSet_Init(lss2); - - savePointsTo1 = nd1->pointsTo; - nd1->pointsTo = pointsTo1; - EvalENodeExpr(lss1, proc, nd1, NULL, NULL, NULL); - nd1->pointsTo = savePointsTo1; - - savePointsTo2 = nd2->pointsTo; - nd2->pointsTo = pointsTo2; - EvalENodeExpr(lss2, proc, nd2, NULL, NULL, NULL); - nd2->pointsTo = savePointsTo2; - - memset(¶ms, 0, sizeof(params)); - params.x8 = 0; - params.x0 = lss2; - LocationSetSet_ForEach(lss1, FindAliasingAction, ¶ms); - - if (!params.x8) { - params.x0 = lss1; - LocationSetSet_ForEach(lss2, FindAliasingAction, ¶ms); - - if (!params.x8) { - RemoveRestrictedExtendedParams(lss1); - RemoveRestrictedExtendedParams(lss2); - ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss1); - ExpandLocationSetSetToActuals(&stCallingContextStack, NULL, lss2); - - params.x0 = lss2; - LocationSetSet_ForEach(lss1, FindAliasingAction, ¶ms); - - if (!params.x8) { - params.x0 = lss1; - LocationSetSet_ForEach(lss2, FindAliasingAction, ¶ms); - } - } - } - - LocationSetSet_Term(lss1); - LocationSetSet_Delete(lss1); - LocationSetSet_Term(lss2); - LocationSetSet_Delete(lss2); - - return params.x8; -} - -Boolean PointerAnalysis_IsLinearNodePointerExprDefinite(Object *proc, IROLinear *nd) { - LocationSetSet *lss; - LocationSet *loc; - Boolean result; - - if (!nd->pointsToFunction) - return 0; - - lss = LocationSetSet_New(); - LocationSetSet_Init(lss); - EvalExpr(lss, proc, nd, NULL, NULL, NULL); - - result = - (LocationSetSet_Count(lss) == 1) && - (loc = LocationSetSet_FindFirst(lss)) && - LocationSetRepresentsSingleLocation(loc, NULL, NULL); - - LocationSetSet_Term(lss); - LocationSetSet_Delete(lss); - - return result; -} - -Boolean PointerAnalysis_IsENodePointerExprDefinite(Object *proc, ENode *nd) { - LocationSetSet *lss; - LocationSet *loc; - Boolean result; - - if (!nd->pointsTo) - return 0; - - lss = LocationSetSet_New(); - LocationSetSet_Init(lss); - EvalENodeExpr(lss, proc, nd, NULL, NULL, NULL); - - result = - (LocationSetSet_Count(lss) == 1) && - (loc = LocationSetSet_FindFirst(lss)) && - LocationSetRepresentsSingleLocation(loc, NULL, NULL); - - LocationSetSet_Term(lss); - LocationSetSet_Delete(lss); - - return result; -} - -Boolean PointerAnalysis_IsVariableValueDefinite(Object *proc, VarRecord *var, PointsToFunction *pointsTo) { - LocationSetSet *lss; - LocationSet *loc; - Boolean result; - - if (!pointsTo) - return 0; - - lss = LocationSetSet_New(); - LocationSetSet_Init(lss); - EvalVariable(lss, proc, var, pointsTo, NULL, NULL, NULL); - - result = - (LocationSetSet_Count(lss) == 1) && - (loc = LocationSetSet_FindFirst(lss)) && - LocationSetRepresentsSingleLocation(loc, NULL, NULL); - - LocationSetSet_Term(lss); - LocationSetSet_Delete(lss); - - return result; -} - -static void FindGlobalObjectAction(Object *object, void *refcon) { - if (ObjectIsAnExtendedParamCandidate(object)) { - Object **ptr = refcon; - *ptr = object; - } -} - -static void GetDefiniteObjectOfExtendedParamLoc(LocationSet *loc, Object **resultObj, CInt64 *resultField) { - Object *obj; - CInt64 field; - PAMemoryBlock *block; - ExtendedParam *ep; - ObjectSet *objSet; - LocationSetSet *locs; - LocationSet *tmp; - PALocalVar *local; - - IRO_ASSERT(6763, loc != NULL); - IRO_ASSERT(6764, resultObj != NULL); - IRO_ASSERT(6765, resultField != NULL); - - obj = NULL; - field = LocationSet_field(loc); - block = LocationSet_block(loc); - - if (block && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { - if ((ep = PAMemoryBlock_thing(block)) && (objSet = ExtendedParam_objectSet(ep))) { - IRO_ASSERT(6777, obj == NULL); - ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); - } - } - - if (!obj) { - locs = LocationSetSet_New(); - LocationSetSet_Init(locs); - GetActualLocsOfExtendedParam(locs, loc, NULL, &stCallingContextStack, NULL, 0); - - if ( - LocationSetSet_Count(locs) == 1 && - (tmp = LocationSetSet_FindFirst(locs)) && - !LocationSet_IsUnknown(tmp)) - { - field = CInt64_Add(field, LocationSet_field(tmp)); - if ( - (block = LocationSet_block(tmp)) && - PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM && - (ep = PAMemoryBlock_thing(block)) && - (objSet = ExtendedParam_objectSet(ep)) - ) - { - IRO_ASSERT(6801, obj == NULL); - ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); - } else if ( - (block = LocationSet_block(tmp)) && - PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_LOCALVAR && - (local = PAMemoryBlock_thing(block)) - ) - { - obj = GetLocalObject(local, &stUnknown, 0); - } - } - - LocationSetSet_Term(locs); - LocationSetSet_Delete(locs); - } - - *resultObj = obj; - *resultField = field; -} - -static void CreateExpressionForLocationSet(LocationSet *loc, IROList *list, Type *rtype, Object *proc) { - CInt64 field; - PAMemoryBlock *block; - PAMemoryBlockKind kind; - void *thing; - IROLinear *nd; - Object *obj; - - IRO_ASSERT(6833, loc != NULL); - IRO_ASSERT(6834, !LocationSet_IsUnknown(loc)); - IRO_ASSERT(6835, LocationSet_stride(loc) == 0); - IRO_ASSERT(6836, list != NULL); - IRO_ASSERT(6837, rtype != NULL); - IRO_ASSERT(6838, proc != NULL); - - field = LocationSet_field(loc); - block = LocationSet_block(loc); - kind = PAMemoryBlock_kind(block); - thing = PAMemoryBlock_thing(block); - nd = NULL; - - switch (kind) { - case PAMEMORYBLOCKKIND_EXTENDEDPARAM: - GetDefiniteObjectOfExtendedParamLoc(loc, &obj, &field); - if (obj) { - nd = IRO_NewLinear(IROLinearOperand); - nd->u.node = create_objectrefnode(obj); - nd->rtype = rtype; - nd->index = ++IRO_NumLinear; - IRO_AddToList(nd, list); - } - break; - case PAMEMORYBLOCKKIND_LOCALVAR: - obj = GetLocalObject(thing, proc, 0); - if (obj) { - if (ObjectIsAFunctionArgument(proc, obj) && obj->u.var.realObj) - obj = obj->u.var.realObj; - nd = IRO_NewLinear(IROLinearOperand); - nd->u.node = create_objectrefnode(obj); - nd->rtype = rtype; - nd->index = ++IRO_NumLinear; - IRO_AddToList(nd, list); - } - break; - case PAMEMORYBLOCKKIND_INT: - if (IS_TYPE_INT(rtype)) { - nd = IRO_NewIntConst(*((CInt64 *) thing), rtype); - IRO_AddToList(nd, list); - } - break; - case PAMEMORYBLOCKKIND_6: - break; - default: - CError_FATAL(6894); - } - - if (nd && !CInt64_IsZero(&field)) { - IROLinear *nd2; - IROLinear *nd3; - - nd2 = IRO_NewIntConst(field, TYPE(&stunsignedlong)); - IRO_AddToList(nd2, list); - - nd3 = IRO_NewLinear(IROLinearOp2Arg); - nd3->nodetype = EADD; - nd3->index = ++IRO_NumLinear; - nd3->rtype = rtype; - nd3->u.diadic.left = nd; - nd3->u.diadic.right = nd2; - IRO_AddToList(nd3, list); - } -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct LookupLinearExprActionParams { - Object *proc; - Type *indirectType; - IROListNode **list; -} LookupLinearExprActionParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void LookupLinearExprAction(LocationSet *loc, void *refcon) { - LookupLinearExprActionParams *params; - IROListNode *list; - - IRO_ASSERT(6926, loc != NULL); - IRO_ASSERT(6927, refcon != NULL); - - params = refcon; - - IRO_ASSERT(6931, params->proc != NULL); - IRO_ASSERT(6932, params->indirectType != NULL); - IRO_ASSERT(6933, params->list != NULL); - - list = *params->list = IRO_malloc(sizeof(IROListNode)); - IRO_InitList(&list->list); - list->nextList = NULL; - - if (!LocationSet_IsUnknown(loc) && LocationSetRepresentsSingleLocation(loc, NULL, NULL)) - CreateExpressionForLocationSet(loc, &list->list, params->indirectType, params->proc); - - params->list = &list->nextList; -} - -void PointerAnalysis_LookupLinearNodePointerExpr(Object *proc, IROLinear *indirect, IROListNode **list) { - LocationSetSet *set; - LookupLinearExprActionParams params; - - IRO_ASSERT(6957, indirect != NULL); - - if (indirect->pointsToFunction) { - set = LocationSetSet_New(); - LocationSetSet_Init(set); - EvalExpr(set, proc, indirect, NULL, NULL, NULL); - - memset(¶ms, 0, sizeof(params)); - params.proc = proc; - params.indirectType = indirect->rtype; - params.list = list; - - LocationSetSet_ForEach(set, LookupLinearExprAction, ¶ms); - LocationSetSet_Term(set); - LocationSetSet_Delete(set); - } -} - -static void CreateENodeForLocationSet(LocationSet *loc, ENode **resultNode, Type *rtype, Object *proc) { - CInt64 field; - PAMemoryBlock *block; - PAMemoryBlockKind kind; - void *thing; - ENode *nd; - Object *obj; - - IRO_ASSERT(0, loc != NULL); - IRO_ASSERT(0, !LocationSet_IsUnknown(loc)); - IRO_ASSERT(0, LocationSet_stride(loc) == 0); - IRO_ASSERT(0, resultNode != NULL); - IRO_ASSERT(0, rtype != NULL); - IRO_ASSERT(0, proc != NULL); - - field = LocationSet_field(loc); - block = LocationSet_block(loc); - kind = PAMemoryBlock_kind(block); - thing = PAMemoryBlock_thing(block); - nd = NULL; - - switch (kind) { - case PAMEMORYBLOCKKIND_EXTENDEDPARAM: - GetDefiniteObjectOfExtendedParamLoc(loc, &obj, &field); - if (obj) { - nd = create_objectrefnode(obj); - nd->rtype = rtype; - } - break; - case PAMEMORYBLOCKKIND_LOCALVAR: - obj = GetLocalObject(thing, proc, 0); - if (obj) { - if (ObjectIsAFunctionArgument(proc, obj) && obj->u.var.realObj) - obj = obj->u.var.realObj; - nd = create_objectrefnode(obj); - nd->rtype = rtype; - } - break; - case PAMEMORYBLOCKKIND_INT: - if (IS_TYPE_INT(rtype)) { - nd = IRO_NewENode(EINTCONST); - nd->data.intval = *((CInt64 *) thing); - nd->rtype = rtype; - } - break; - case PAMEMORYBLOCKKIND_6: - break; - default: - CError_FATAL(7040); - } - - if (nd && !CInt64_IsZero(&field)) { - ENode *nd2; - ENode *nd3; - - nd2 = IRO_NewENode(EINTCONST); - nd2->data.intval = field; - nd2->rtype = TYPE(&stunsignedlong); - - nd3 = IRO_NewENode(EADD); - nd3->data.diadic.left = nd; - nd3->data.diadic.right = nd2; - nd3->rtype = rtype; - - *resultNode = nd3; - } else { - *resultNode = nd; - } -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct LookupENodeExprActionParams { - Object *proc; - Type *indirectType; - ENodeList **list; -} LookupENodeExprActionParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void LookupENodeExprAction(LocationSet *loc, void *refcon) { - LookupENodeExprActionParams *params; - ENodeList *list; - - IRO_ASSERT(0, loc != NULL); - IRO_ASSERT(0, refcon != NULL); - - params = refcon; - - IRO_ASSERT(0, params->proc != NULL); - IRO_ASSERT(0, params->indirectType != NULL); - IRO_ASSERT(0, params->list != NULL); - - list = *params->list = IRO_malloc(sizeof(ENodeList)); - list->node = NULL; - list->next = NULL; - - if (!LocationSet_IsUnknown(loc) && LocationSetRepresentsSingleLocation(loc, NULL, NULL)) - CreateENodeForLocationSet(loc, &list->node, params->indirectType, params->proc); - - params->list = &list->next; -} - -void PointerAnalysis_LookupENodePointerExpr(Object *proc, ENode *indirect, ENodeList **list) { - LocationSetSet *set; - LookupENodeExprActionParams params; - - IRO_ASSERT(0, indirect != NULL); - - if (indirect->pointsTo) { - set = LocationSetSet_New(); - LocationSetSet_Init(set); - EvalENodeExpr(set, proc, indirect, NULL, NULL, NULL); - - memset(¶ms, 0, sizeof(params)); - params.proc = proc; - params.indirectType = indirect->rtype; - params.list = list; - - LocationSetSet_ForEach(set, LookupENodeExprAction, ¶ms); - LocationSetSet_Term(set); - LocationSetSet_Delete(set); - } -} - -void PointerAnalysis_LookupVariableIntoLinearNodeExprs(Object *proc, VarRecord *var, PointsToFunction *pointsTo, IROListNode **list) { - LocationSetSet *set; - LookupLinearExprActionParams params; - - if (pointsTo) { - set = LocationSetSet_New(); - LocationSetSet_Init(set); - EvalVariable(set, proc, var, pointsTo, NULL, NULL, NULL); - - memset(¶ms, 0, sizeof(params)); - params.proc = proc; - params.indirectType = var->object->type; - params.list = list; - - LocationSetSet_ForEach(set, LookupLinearExprAction, ¶ms); - LocationSetSet_Term(set); - LocationSetSet_Delete(set); - } -} - -void PointerAnalysis_LookupVariableIntoENodeExprs(Object *proc, VarRecord *var, PointsToFunction *pointsTo, ENodeList **list) { - LocationSetSet *set; - LookupENodeExprActionParams params; - - if (pointsTo) { - set = LocationSetSet_New(); - LocationSetSet_Init(set); - EvalVariable(set, proc, var, pointsTo, NULL, NULL, NULL); - - memset(¶ms, 0, sizeof(params)); - params.proc = proc; - params.indirectType = var->object->type; - params.list = list; - - LocationSetSet_ForEach(set, LookupENodeExprAction, ¶ms); - LocationSetSet_Term(set); - LocationSetSet_Delete(set); - } -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct GetFunctionDepsOrKillsActionParams { - Object *proc; - PartialTransferFunction *ptf; - IROLinear *funccall; - ParamMappingFunction *map; - ObjectList **list; -} GetFunctionDepsOrKillsActionParams; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void GetFunctionDepsOrKillsAction(LocationSet *ls, void *refcon) { - GetFunctionDepsOrKillsActionParams *params; - ObjectList *list; - PAMemoryBlock *block; - ExtendedParam *ep; - ObjectSet *objSet; - PALocalVar *local; - Object *obj; - - IRO_ASSERT(7204, ls != NULL); - IRO_ASSERT(7205, refcon != NULL); - - params = refcon; - - IRO_ASSERT(7209, params->proc != NULL); - IRO_ASSERT(7210, params->ptf != NULL); - IRO_ASSERT(7211, params->funccall != NULL); - IRO_ASSERT(7212, params->map == NULL || params->map != NULL); - IRO_ASSERT(7213, params->list != NULL); - - list = *params->list = IRO_malloc(sizeof(ObjectList)); - list->object = NULL; - list->next = NULL; - - if (!LocationSet_IsUnknown(ls) && (block = LocationSet_block(ls))) { - obj = NULL; - switch (PAMemoryBlock_kind(block)) { - case PAMEMORYBLOCKKIND_EXTENDEDPARAM: - if ((ep = PAMemoryBlock_thing(block)) && (objSet = ExtendedParam_objectSet(ep))) { - IRO_ASSERT(7232, obj == NULL); - ObjectSet_ForEach(objSet, FindGlobalObjectAction, &obj); - } - break; - case PAMEMORYBLOCKKIND_LOCALVAR: - if ((local = PAMemoryBlock_thing(block))) { - obj = GetLocalObject(local, &stUnknown, 0); - if (ObjectIsAFunctionArgument(FunctionName, obj) && obj->u.var.realObj) - obj = obj->u.var.realObj; - } - break; - } - - list->object = obj; - } - - params->list = &list->next; -} - -static void GetFunctionDepsOrKillsAction2(PointsToEntry *pte, void *refcon) { - GetFunctionDepsOrKillsActionParams *params; - LocationSet *loc; - PAMemoryBlock *block; - LocationSetSet *set; - - IRO_ASSERT(7264, pte != NULL); - IRO_ASSERT(7265, refcon != NULL); - - params = refcon; - - IRO_ASSERT(7269, params->proc != NULL); - IRO_ASSERT(7270, params->ptf != NULL); - IRO_ASSERT(7271, params->funccall != NULL); - IRO_ASSERT(7272, params->map != NULL); - IRO_ASSERT(7273, params->list != NULL); - - loc = PointsToEntry_loc(pte); - - IRO_ASSERT(7277, !LocationSet_IsUnknown(loc)); - - if ((block = LocationSet_block(loc)) && PAMemoryBlock_kind(block) == PAMEMORYBLOCKKIND_EXTENDEDPARAM) { - set = LocationSetSet_New(); - LocationSetSet_Init(set); - GetActualLocsOfExtendedParam(set, loc, NULL, &stCallingContextStack, params->map, 0); - LocationSetSet_ForEach(set, GetFunctionDepsOrKillsAction, params); - LocationSetSet_Term(set); - LocationSetSet_Delete(set); - } -} - -static void CreateFalseContext(Object *proc, IROLinear *funccall, PartialTransferFunction **resultPTF, ParamMappingFunction **resultMap) { - IROLinear myFunccall; - Boolean needVisit; - ParamMappingFunction *map; - PartialTransferFunction *ptf; - StackElement *stackElement; - ParamMappingFunction *map2; - PartialTransferFunction *ptf2; - StackElement *stackElement2; - - PointerAnalysis_Init(); - memset(&myFunccall, 0, sizeof(myFunccall)); - myFunccall.type = IROLinearFunccall; - - map = ParamMappingFunction_New(); - ParamMappingFunction_Init(map); - RecordActuals(&myFunccall, FunctionName, map); - - needVisit = 0; - ptf = GetPTF(map, FunctionName, &myFunccall, stUnknownPTF, &needVisit); - - stackElement = StackElement_New(); - StackElement_Init(stackElement, FunctionName, ptf, map, &myFunccall); - Stack_sub_48A660(&stCallingContextStack, stackElement); - StackElement_Term(stackElement); - StackElement_Delete(stackElement); - - map2 = ParamMappingFunction_New(); - ParamMappingFunction_Init(map2); - RecordActuals(funccall, proc, map2); - - if (FunctionName != proc) { - needVisit = 0; - ptf2 = GetPTF(map2, proc, funccall, ptf, &needVisit); - - stackElement2 = StackElement_New(); - StackElement_Init(stackElement2, proc, ptf2, map2, funccall); - Stack_sub_48A660(&stCallingContextStack, stackElement2); - StackElement_Term(stackElement2); - StackElement_Delete(stackElement2); - } else { - ptf2 = stUnknownPTF; - } - - *resultPTF = ptf2; - *resultMap = map2; -} - -static void DestroyFalseContext(Object *proc, PartialTransferFunction *ptf, ParamMappingFunction *map) { - StackElement *element; - - if (FunctionName != proc) { - element = Stack_sub_48A5B0(&stCallingContextStack); - StackElement_Term(element); - StackElement_Delete(element); - } - - ParamMappingFunction_Term(map); - ParamMappingFunction_Delete(map); - - element = Stack_sub_48A5B0(&stCallingContextStack); - map = StackElement_map(element); - ParamMappingFunction_Term(map); - ParamMappingFunction_Delete(map); - StackElement_Term(element); - StackElement_Delete(element); - - PointerAnalysis_Term(); -} - -void PointerAnalysis_GetFunctionKills(Object *proc, IROLinear *funccall, ObjectList **list) { - Boolean fail; - PartialTransferFunction *ptf; - LocationSetSet *set; - GetFunctionDepsOrKillsActionParams params; - - IRO_ASSERT(7398, proc != NULL); - IRO_ASSERT(7399, funccall != NULL); - IRO_ASSERT(7400, funccall->type == IROLinearFunccall); - - if (!ObjectIsAFunction(proc)) - return; - - fail = !proc->u.func.ptfList || !(ptf = PTFList_FindFirst(proc->u.func.ptfList)); - if (!fail) { - fail = !(set = PTF_sub_48D750(ptf)); - if (!fail) { - memset(¶ms, 0, sizeof(params)); - params.proc = proc; - params.ptf = ptf; - params.funccall = funccall; - params.map = NULL; - params.list = list; - LocationSetSet_ForEach(set, GetFunctionDepsOrKillsAction, ¶ms); - } - } - - if (fail) { - *list = IRO_malloc(sizeof(ObjectList)); - (*list)->object = NULL; - (*list)->next = NULL; - } -} - -void PointerAnalysis_GetFunctionDependencies(Object *proc, IROLinear *funccall, ObjectList **list) { - Boolean fail; - PartialTransferFunction *ptf; - ParamMappingFunction *map; - PointsToFunction *finalPointsTo; - GetFunctionDepsOrKillsActionParams params; - - IRO_ASSERT(7446, proc != NULL); - IRO_ASSERT(7447, funccall != NULL); - IRO_ASSERT(7448, funccall->type == IROLinearFunccall); - - if (!ObjectIsAFunction(proc)) - return; - - fail = !proc->u.func.ptfList || !PTFList_FindFirst(proc->u.func.ptfList); - if (!fail) { - CreateFalseContext(proc, funccall, &ptf, &map); - fail = !ptf || !map || !(finalPointsTo = PartialTransferFunction_finalPointsToFn(ptf)); - if (!fail) { - memset(¶ms, 0, sizeof(params)); - params.proc = proc; - params.ptf = ptf; - params.funccall = funccall; - params.map = map; - params.list = list; - PointsToFunction_ForEach(finalPointsTo, GetFunctionDepsOrKillsAction2, ¶ms); - } - DestroyFalseContext(proc, ptf, map); - } - - if (fail) { - *list = IRO_malloc(sizeof(ObjectList)); - (*list)->object = NULL; - (*list)->next = NULL; - } -} - -void PointerAnalysis_PragmaMode(void) { - if (cparamblkptr->preprocess) { - skipendofline(); - return; - } - - if (notendofline()) { - if (plex() == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "addr")) { - copts.opt_pointer_analysis_mode = 0; - return; - } - if (!strcmp(tkidentifier->name, "ansi")) { - copts.opt_pointer_analysis_mode = 1; - return; - } - if (!strcmp(tkidentifier->name, "type")) { - copts.opt_pointer_analysis_mode = 2; - return; - } - } - - CPrep_Warning(CErrorStr105); - skipendofline(); - return; - } - - if (copts.warn_illpragma) - CPrep_Warning(CErrorStr186); - skipendofline(); -} - -typedef enum CreateNewParamObjects { - CREATE_NEW_PARAM_OBJECTS_FALSE, - CREATE_NEW_PARAM_OBJECTS_TRUE -} CreateNewParamObjects; - -static void ParseLocationSet(LocationSet *loc, Type *rtype, Object *proc, CreateNewParamObjects createNewParamObjects, Boolean arg5, int arg6, Boolean *arg7, Boolean *resultFailed) { - CInt64 field; - UInt32 stride; - PAMemoryBlock *block; - PAMemoryBlock *restriction; - Boolean failed; - Boolean flag37; - Boolean epFlag; - Boolean anotherFlag; - Boolean isUnknown; - - IRO_ASSERT(7552, loc != NULL); - IRO_ASSERT(7553, rtype == NULL || rtype != NULL); - IRO_ASSERT(7554, proc != NULL); - IRO_ASSERT(7555, createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_FALSE || createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_TRUE); - IRO_ASSERT(7556, resultFailed != NULL); - IRO_ASSERT(7557, *resultFailed == false); - IRO_ASSERT(7558, proc != NULL); - IRO_ASSERT(7559, proc == NULL || ObjectIsAFunction(proc)); - - failed = 0; - isUnknown = 0; - anotherFlag = 0; - field = cint64_zero; - stride = 0; - - tk = lex(); - if (tk == TK_IDENTIFIER) { - if (!strcmp(tkidentifier->name, "__unknown")) { - flag37 = 0; - isUnknown = 1; - tk = lookahead(); - if (tk == '(') { - lex(); - tk = lex(); - if (tk != TK_IDENTIFIER) { - CError_Error(CErrorStr107); - failed = 1; - } - if (!failed) { - PALocalVar *local; - local = PALocalVar_New(); - PALocalVar_InitByName(local, tkidentifier->name); - - block = PAMemoryBlock_New(); - PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_LOCALVAR, local); - - tk = lex(); - if (tk != ')') { - CError_Error(CErrorStr115); - failed = 1; - } - if (!failed) { - rtype = NULL; - restriction = block; - } - } - } else { - rtype = NULL; - restriction = NULL; - } - } else if (arg5 && !strcmp(tkidentifier->name, "__return_value")) { - flag37 = 0; - anotherFlag = 1; - } else if (!strcmp(tkidentifier->name, "__unique_heap_allocation")) { - PAHeapBlock *hb; - - flag37 = 0; - hb = CreateUniqueHeapAlloc_sub_486420(); - InitUniqueHeapAlloc_sub_486410(hb, NULL); - - block = PAMemoryBlock_New(); - PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_HEAPBLOCK, hb); - } else if (!strcmp(tkidentifier->name, "__parameter_representative")) { - flag37 = 1; - tk = lex(); - - if (tk == '(') { - tk = lex(); - if (tk != TK_INTCONST) { - CError_Error(CErrorStr121); - failed = 1; - } - if (!failed) { - Object *obj; - ObjectList *list; - ExtendedParam *ep; - obj = NULL; - for (list = stParamObjs; list; list = list->next) { - if ((obj = list->object) && (obj->u.var.uid == CInt64_GetULong(&tkintconst))) - break; - } - if (!list) - obj = NULL; - - if (!obj) { - if (createNewParamObjects) { - obj = IRO_malloc(sizeof(Object)); - memset(obj, 0, sizeof(Object)); - obj->datatype = DLOCAL; - obj->extParam = NULL; - obj->name = CParser_GetUniqueName(); - obj->type = TYPE(&stunsignedlong); - obj->qual = 0; - obj->u.var.info = NULL; - obj->u.var.uid = CInt64_GetULong(&tkintconst); - - list = IRO_malloc(sizeof(ObjectList)); - list->next = stParamObjs; - list->object = obj; - stParamObjs = list; - - ep = CreateExtendedParam(NULL, NULL, obj, &epFlag); - } else { - char buf[64]; - sprintf(buf, "__parameter_representative(%" PRId32 ")", obj->u.var.uid); - CError_Error(CErrorStr140, buf); - failed = 1; - } - } else { - ep = obj->extParam; - IRO_ASSERT(7687, ep != NULL); - } - - if (!failed) { - tk = lex(); - if (tk != ')') { - CError_Error(CErrorStr115); - failed = 1; - } - } - if (!failed) { - block = PAMemoryBlock_New(); - PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_EXTENDEDPARAM, ep); - } - } - } - } else { - Object *obj; - NameSpace *nspace; - - obj = NULL; - for (nspace = cscope_current; nspace; nspace = nspace->parent) { - NameSpaceObjectList *chk; - if ((chk = CScope_GetLocalObject(nspace, tkidentifier)) && chk->object->otype == OT_OBJECT) { - if (notendofline()) { - obj = OBJECT(chk->object); - break; - } - } - } - - if (!obj) { - ObjectList *chk; - for (chk = FunctionArguments(proc); chk; chk = chk->next) { - if (chk->object && chk->object->name && chk->object->name->name && !strcmp(tkidentifier->name, chk->object->name->name)) { - obj = chk->object; - } - } - } - - if (obj) { - PAMemoryBlockKind kind; - void *thing; - - if (ObjectIsAnExtendedParamCandidate(obj)) { - kind = PAMEMORYBLOCKKIND_EXTENDEDPARAM; - thing = CreateExtendedParam(NULL, NULL, obj, &epFlag); - } else { - kind = PAMEMORYBLOCKKIND_LOCALVAR; - thing = PALocalVar_New(); - if (obj->name && obj->name->name && ObjectIsAFunctionArgument(proc, obj)) - PALocalVar_InitByName(thing, obj->name->name); - else - PALocalVar_InitByObject(thing, obj); - } - - block = PAMemoryBlock_New(); - PAMemoryBlock_Init(block, kind, thing); - rtype = CDecl_NewPointerType(obj->type); - } else { - CError_Error(CErrorStr140, tkidentifier->name); - failed = 1; - } - } - } else if (tk == TK_INTCONST) { - flag37 = 0; - block = PAMemoryBlock_New(); - PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_INT, &tkintconst); - } else if (tk == '(') { - ParseLocationSet(loc, rtype, proc, createNewParamObjects, arg5, 1, &anotherFlag, &failed); - if (!failed) { - tk = plex(); - if (tk != ')') - CError_Error(CErrorStr115); - failed = 1; - } - } else { - CError_Error(CErrorStr121); - failed = 1; - } - - if (!failed && flag37) { - tk = lookahead(); - if (tk == '[') { - lex(); - if (rtype && IS_TYPE_POINTER(rtype) && IS_TYPE_POINTER(TPTR_TARGET(rtype))) { - tk = lex(); - if (tk == ']') { - if ((stride = rtype->size)) { - CInt64 tmp; - CInt64_SetLong(&tmp, stride); - field = CInt64_Mod(field, tmp); - } - rtype = TPTR_TARGET(rtype); - } else { - CError_Error(CErrorStr125); - } - } else { - CError_Error(CErrorStr148); - } - } else if (tk == '.') { - lex(); - if (rtype && IS_TYPE_POINTER(rtype) && IS_TYPE_STRUCT(TPTR_TARGET(rtype))) { - if (TPTR_TARGET(rtype)->size) { - tk = lex(); - if (tk == TK_IDENTIFIER) { - StructMember *member; - if ((member = ismember(TYPE_STRUCT(TPTR_TARGET(rtype)), tkidentifier))) { - CInt64_SetLong(&field, member->offset); - rtype = CDecl_NewPointerType(member->type); - } else { - CError_Error(CErrorStr150, tkidentifier); - } - } else { - CError_Error(CErrorStr107); - } - } else { - CError_Error(CErrorStr136, TPTR_TARGET(rtype), 0); - } - } else { - CError_Error(CErrorStr149); - } - } - } - - if (!failed && !anotherFlag) { - LocationSet_Term(loc); - if (!isUnknown) - LocationSet_InitKnown(loc, block, field, stride, rtype); - else - LocationSet_InitUnknown(loc, rtype, restriction, NULL); - } - - *arg7 = anotherFlag; - *resultFailed = failed; -} - -static void ParseLocationSetSet(LocationSetSet *locs, Type *rtype, Object *proc, CreateNewParamObjects createNewParamObjects, Boolean *resultFailed) { - Boolean failed; - - IRO_ASSERT(7892, locs != NULL); - IRO_ASSERT(7893, rtype == NULL || rtype != NULL); - IRO_ASSERT(7894, proc != NULL); - IRO_ASSERT(7895, createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_FALSE || createNewParamObjects == CREATE_NEW_PARAM_OBJECTS_TRUE); - IRO_ASSERT(7896, resultFailed != NULL); - IRO_ASSERT(7897, *resultFailed == false); - IRO_ASSERT(7898, proc != NULL); - IRO_ASSERT(7899, proc == NULL || ObjectIsAFunction(proc)); - - failed = 0; - - tk = lex(); - if (tk != '(') { - CError_Error(CErrorStr114); - failed = 1; - } - - if (!failed) { - Boolean anotherFlag; - - LocationSet *ls; - ls = LocationSet_New(); - LocationSet_InitUnknown(ls, NULL, NULL, NULL); - - tk = lookahead(); - while (!failed && tk != ')') { - ParseLocationSet(ls, rtype, proc, createNewParamObjects, 0, 0, &anotherFlag, &failed); - if (!failed) - LocationSetSet_Add(locs, ls); - - if (!failed) { - tk = lookahead(); - if (tk == ',') { - lex(); - tk = lookahead(); - } else if (tk != ')') { - lex(); - CError_Error(CErrorStr121); - failed = 1; - } - } - } - - if (!failed) - lex(); - - LocationSet_Term(ls); - LocationSet_Delete(ls); - } - - *resultFailed = failed; -} - -static Object *GetFunctionObjectFromDeclInfo(DeclInfo *di) { - Object *proc; - - IRO_ASSERT(7953, di != NULL); - - if (di->storageclass != TK_TYPEDEF && IS_TYPE_FUNC(di->thetype)) { - Boolean flag; - proc = CDecl_GetFunctionObject(di, NULL, &flag, 1); - if (flag) - di->x64 = 1; - } else { - proc = NULL; - } - - return proc; -} - -void PointerAnalysis_ParseEntryPointsToSpecifier(DeclInfo *di) { - Object *proc; - Boolean failed; - Boolean anotherFlag; - - IRO_ASSERT(7982, di != NULL); - - proc = GetFunctionObjectFromDeclInfo(di); - if (proc) { - IRO_ASSERT(7987, proc == NULL || ObjectIsAFunction(proc)); - - tk = lex(); - IRO_ASSERT(7996, tk == TK_IDENTIFIER && strcmp(tkidentifier->name,"entry_points_to") == 0); - - failed = 0; - - tk = lex(); - if (tk != '(') { - CError_Error(CErrorStr114); - failed = 1; - } - - if (!failed) { - LocationSet *ls; - ls = LocationSet_New(); - LocationSet_InitUnknown(ls, NULL, NULL, NULL); - ParseLocationSet(ls, NULL, proc, CREATE_NEW_PARAM_OBJECTS_FALSE, 0, 0, &anotherFlag, &failed); - if (!failed) { - if ((tk = lex()) != ',') { - CError_Error(CErrorStr116); - failed = 1; - } - } - if (!failed) { - Type *type; - Type *innerType; - LocationSetSet *lss; - - type = LocationSet_rtype(ls); - if (type && IS_TYPE_POINTER(type)) - innerType = TPTR_TARGET(type); - else - innerType = NULL; - - lss = LocationSetSet_New(); - LocationSetSet_Init(lss); - ParseLocationSetSet(lss, innerType, proc, CREATE_NEW_PARAM_OBJECTS_TRUE, &failed); - if (!failed) { - if ((tk = lex()) != ')') { - CError_Error(CErrorStr115); - failed = 1; - } - } - if (!failed) { - PartialTransferFunction *ptf; - PointsToFunction *pointsToFunc; - PointsToEntry *pte; - - if (!proc->u.func.ptfList) { - proc->u.func.ptfList = PTFList_New(); - PTFList_Init(proc->u.func.ptfList); - } - ptf = PTFList_FindFirst(proc->u.func.ptfList); - if (!ptf) - ptf = AllocatePTF(proc, NULL, NULL); - - pointsToFunc = PartialTransferFunction_initialPointsToFn(ptf); - pte = PointsToEntry_New(); - PointsToEntry_Init(pte, ls, lss); - PointsToFunction_Add(pointsToFunc, pte); - PointsToEntry_Term(pte); - PointsToEntry_Delete(pte); - } - LocationSetSet_Term(lss); - LocationSetSet_Delete(lss); - } - LocationSet_Term(ls); - LocationSet_Delete(ls); - } - } -} - -void PointerAnalysis_ParseExitPointsToSpecifier(DeclInfo *di) { - Object *proc; - Boolean failed; - Boolean anotherFlag; - - IRO_ASSERT(8097, di != NULL); - - proc = GetFunctionObjectFromDeclInfo(di); - if (proc) { - IRO_ASSERT(8102, proc == NULL || ObjectIsAFunction(proc)); - - tk = lex(); - IRO_ASSERT(8111, tk == TK_IDENTIFIER && strcmp(tkidentifier->name,"exit_points_to") == 0); - - failed = 0; - - tk = lex(); - if (tk != '(') { - CError_Error(CErrorStr114); - failed = 1; - } - - if (!failed) { - LocationSet *ls; - ls = LocationSet_New(); - LocationSet_InitUnknown(ls, NULL, NULL, NULL); - ParseLocationSet(ls, NULL, proc, CREATE_NEW_PARAM_OBJECTS_FALSE, 1, 0, &anotherFlag, &failed); - if (!failed) { - if ((tk = lex()) != ',') { - CError_Error(CErrorStr116); - failed = 1; - } - } - if (!failed) { - Type *type; - Type *innerType; - LocationSetSet *lss; - - type = LocationSet_rtype(ls); - if (type && IS_TYPE_POINTER(type)) - innerType = TPTR_TARGET(type); - else - innerType = NULL; - - lss = LocationSetSet_New(); - LocationSetSet_Init(lss); - ParseLocationSetSet(lss, innerType, proc, CREATE_NEW_PARAM_OBJECTS_FALSE, &failed); - if (!failed) { - if ((tk = lex()) != ')') { - CError_Error(CErrorStr115); - failed = 1; - } - } - if (!failed) { - PartialTransferFunction *ptf; - PointsToFunction *pointsToFunc; - PointsToEntry *pte; - - if (!proc->u.func.ptfList) { - proc->u.func.ptfList = PTFList_New(); - PTFList_Init(proc->u.func.ptfList); - } - ptf = PTFList_FindFirst(proc->u.func.ptfList); - if (!ptf) - ptf = AllocatePTF(proc, NULL, NULL); - - pointsToFunc = PartialTransferFunction_finalPointsToFn(ptf); - pte = PointsToEntry_New(); - if (anotherFlag) - PointsToEntry_Init(pte, PartialTransferFunction_returnLocation(ptf), lss); - else - PointsToEntry_Init(pte, ls, lss); - PointsToFunction_Add(pointsToFunc, pte); - PointsToEntry_Term(pte); - PointsToEntry_Delete(pte); - } - LocationSetSet_Term(lss); - LocationSetSet_Delete(lss); - } - LocationSet_Term(ls); - LocationSet_Delete(ls); - } - } -} - -void PointerAnalysis_ParseFunctionModifiesSpecifier(DeclInfo *di) { - Object *proc; - Boolean failed; - LocationSetSet *lss; - PartialTransferFunction *ptf; - LocationSetSet *ptfLSS; - - IRO_ASSERT(8211, di != NULL); - - proc = GetFunctionObjectFromDeclInfo(di); - if (proc) { - IRO_ASSERT(8216, proc == NULL || ObjectIsAFunction(proc)); - - tk = lex(); - IRO_ASSERT(8225, tk == TK_IDENTIFIER && strcmp(tkidentifier->name,"function_modifies") == 0); - - failed = 0; - lss = LocationSetSet_New(); - LocationSetSet_Init(lss); - ParseLocationSetSet(lss, NULL, proc, CREATE_NEW_PARAM_OBJECTS_FALSE, &failed); - if (!failed) { - if (!proc->u.func.ptfList) { - proc->u.func.ptfList = PTFList_New(); - PTFList_Init(proc->u.func.ptfList); - } - ptf = PTFList_FindFirst(proc->u.func.ptfList); - if (!ptf) - ptf = AllocatePTF(proc, NULL, NULL); - ptfLSS = PTF_sub_48D750(ptf); - LocationSetSet_RemoveAll(ptfLSS); - LocationSetSet_AddSet(ptfLSS, lss); - } - LocationSetSet_Term(lss); - LocationSetSet_Delete(lss); - } -} - diff --git a/compiler_and_linker/unsorted/IroPointerAnalysisADTs.c b/compiler_and_linker/unsorted/IroPointerAnalysisADTs.c deleted file mode 100644 index 6e24e6f..0000000 --- a/compiler_and_linker/unsorted/IroPointerAnalysisADTs.c +++ /dev/null @@ -1,2736 +0,0 @@ -#include "compiler/IroPointerAnalysis.h" -#include "compiler/IroMalloc.h" -#include "compiler/CError.h" -#include "compiler/CInt64.h" -#include "compiler/CParser.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -// TODO: this should really be elsewhere (but where?) -CW_INLINE UInt32 gcd(UInt32 a, UInt32 b) { - UInt32 chk; - - if (!a) - return b; - if (!b) - return a; - - while (1) { - chk = a % b; - if (!chk) - return b; - a = b; - b = chk; - } -} - -// #define IRO_DEBUG - -typedef struct ExtendedParamSet ExtendedParamSet; -typedef struct LocationSet LocationSet; -typedef struct LocationSetSet LocationSetSet; -typedef struct ObjectSet ObjectSet; -typedef struct PAHeapBlock PAHeapBlock; -typedef struct PALocalVar PALocalVar; -typedef struct PAMemoryBlock PAMemoryBlock; -typedef struct ParamMapping ParamMapping; -typedef struct ParamMappingFunction ParamMappingFunction; -typedef struct PartialTransferFunction PartialTransferFunction; -typedef struct PointsToEntry PointsToEntry; -// typedef struct PointsToFunction PointsToFunction; -typedef struct Stack Stack; -typedef struct StackElement StackElement; - -typedef UInt32 uint32; - -void __assertion_failed(char *expr, char *filename, int line); - -#ifdef IRO_DEBUG -#define IRO_ASSERT(line, expr) \ - do { \ - if (!(expr)) { \ - __assertion_failed(#expr, __FILE__, line); \ - } \ - } while (0); - -#define IRO_DEBUG_CLEAR(obj, type) \ - memset((obj), 0xFF, sizeof(type)) -#else -#define IRO_ASSERT(line, expr) ((void) 0) -#define IRO_DEBUG_CLEAR(obj, type) ((void) 0) -#endif - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -struct StackElement { - Object *proc; - PartialTransferFunction *ptf; - ParamMappingFunction *map; - IROLinear *funcCall; -}; - -struct Stack { - StackElement *top; - Stack *next; -}; - -struct ObjectSet { - Object *proc; - ObjectSet *otherProcs; -}; - -struct ExtendedParam { - ObjectSet *objectSet; - uint32 x4; -}; - -struct ExtendedParamSet { - ExtendedParam *ep; - ExtendedParamSet *otherEps; -}; - -struct PAHeapBlock { - IROLinear *x0; -}; - -struct PALocalVar { - Object *x0; - char *x4; -}; - -typedef enum { - PAMEMORYBLOCKKIND_INVALID, - PAMEMORYBLOCKKIND_1, - PAMEMORYBLOCKKIND_EXTENDEDPARAM, - PAMEMORYBLOCKKIND_LOCALVAR, - PAMEMORYBLOCKKIND_HEAPBLOCK, - PAMEMORYBLOCKKIND_INT, - PAMEMORYBLOCKKIND_6 -} PAMemoryBlockKind; - -struct PAMemoryBlock { - PAMemoryBlockKind kind; - union { - ExtendedParam *ep; - PALocalVar *localvar; - PAHeapBlock *heapblock; - CInt64 intval; - void *x6; - } u; -}; - -struct LocationSet { - PAMemoryBlock *block; - Type *rtype; - union { - struct { - CInt64 field; - UInt32 stride; - } known; - struct { - PAMemoryBlock *restriction; - LocationSet *bitfieldOf; - } unknown; - } u; -}; - -struct LocationSetSet { - LocationSet *loc; - LocationSetSet *otherLocs; - UInt8 count; -}; - -struct ParamMapping { - IROLinear *actual; - Object *formal; - ExtendedParam *extended; -}; - -struct ParamMappingFunction { - ParamMapping *mapping; - ParamMappingFunction *otherMappings; -}; - -struct PointsToEntry { - LocationSet *loc; - LocationSetSet *locs; -}; - -struct PointsToFunction { - PointsToEntry *pte; - PointsToFunction *otherPtes; -}; - -struct PartialTransferFunction { - PointsToFunction *initialPointsToFn; - PointsToFunction *finalPointsToFn; - LocationSetSet *funcModifies; - LocationSet *returnLocation; - Boolean x10; - struct { - IROLinear *nd; - PartialTransferFunction *ptf; - } context; -}; - -struct PTFList { - PartialTransferFunction *ptf; - PTFList *otherPTFs; -}; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -// TODO: how many of these are actually in IroPointerAnalysis.c? -static uint32 stExtendedParamNum; -static PartialTransferFunction *stUnknownPTF; -static uint32 stIndentationLevel; -static UInt8 stTabs[0x2C]; // unused mystery object -static Stack *stCallingContextStack; -static ObjectList *stParamObjs; -static jmp_buf stAbortPointerAnalysis; -static Object stUnknown; -static Object *stCurrentProc; -static ExtendedParamSet *stExtParamSet; -static PTFList *stPTFList; -static uint32 stMaxPassCount; -// TODO: stEvalProcActionParams -static IRONode *stExceptionFNode; - -static PAMemoryBlock stDummyMemoryBlock = { - PAMEMORYBLOCKKIND_1 -}; -static PAMemoryBlock *stUnknownMb = &stDummyMemoryBlock; - -static LocationSet stDummyLocationSet = { - &stDummyMemoryBlock -}; - -static LocationSet *stUnknownLs = &stDummyLocationSet; - -// forward decls -CW_INLINE StackElement *Stack_sub_48A5B0(Stack **stackPtr); -CW_INLINE void ObjectSet_RemoveAll(ObjectSet *procList); -CW_INLINE void ExtendedParamSet_RemoveAll(ExtendedParamSet *epList); -CW_INLINE void LocationSet_Copy(LocationSet *dest, LocationSet *src); -CW_INLINE Boolean LocationSet_IsUnknown(LocationSet *ls); -CW_INLINE void LocationSetSet_RemoveAll(LocationSetSet *lss); -CW_INLINE void LocationSetSet_AddSet(LocationSetSet *dest, LocationSetSet *src); -CW_INLINE void ParamMappingFunction_RemoveAll(ParamMappingFunction *pmf); -CW_INLINE void ParamMappingFunction_AddAllMaybe_sub_487C50(ParamMappingFunction *dest, ParamMappingFunction *src); -CW_INLINE void PointsToFunction_RemoveAll(PointsToFunction *pointsToFunc); -CW_INLINE void PointsToFunction_AddAllIGuess_sub_487D80(PointsToFunction *dest, PointsToFunction *src); -CW_INLINE void PTFList_RemoveAll(PTFList *ptfList); - -CW_INLINE StackElement *StackElement_New(void) { - StackElement *stackElement = IRO_malloc(sizeof(StackElement)); - IRO_ASSERT(103, stackElement != NULL); -#ifdef IRO_DEBUG - stackElement->proc = NULL; - stackElement->ptf = NULL; - stackElement->map = NULL; - stackElement->funcCall = NULL; -#endif - return stackElement; -} - -CW_INLINE void StackElement_Delete(StackElement *stackElement) { - IRO_ASSERT(117, stackElement != NULL); - IRO_ASSERT(118, stackElement->proc == NULL); - IRO_ASSERT(119, stackElement->ptf == NULL); - IRO_ASSERT(120, stackElement->map == NULL); - IRO_ASSERT(121, stackElement->funcCall == NULL); - IRO_DEBUG_CLEAR(stackElement, sizeof(StackElement)); - IRO_free(stackElement); -} - -CW_INLINE void StackElement_Init(StackElement *stackElement, Object *proc, PartialTransferFunction *ptf, ParamMappingFunction *map, IROLinear *funcCall) { - IRO_ASSERT(131, stackElement != NULL); - IRO_ASSERT(132, proc != NULL); - IRO_ASSERT(133, ptf != NULL); - IRO_ASSERT(134, map != NULL); - IRO_ASSERT(135, funcCall != NULL); - stackElement->proc = proc; - stackElement->ptf = ptf; - stackElement->map = map; - stackElement->funcCall = funcCall; -} - -CW_INLINE void StackElement_Copy(StackElement *dest, StackElement *src) { - IRO_ASSERT(145, dest != NULL); - IRO_ASSERT(146, src != NULL); - StackElement_Init(dest, src->proc, src->ptf, src->map, src->funcCall); -} - -CW_INLINE void StackElement_Term(StackElement *stackElement) { - IRO_ASSERT(156, stackElement != NULL); -#ifdef IRO_DEBUG - stackElement->proc = NULL; - stackElement->ptf = NULL; - stackElement->map = NULL; - stackElement->funcCall = NULL; -#endif -} - -CW_INLINE void *StackElement_sub_48A780(StackElement *stackElement) { - IRO_ASSERT(213, stackElement != NULL); - return stackElement->proc; -} - -CW_INLINE Boolean StackRelated_sub_48A760(void *key1, void *key2) { - IRO_ASSERT(220, key1 != NULL); - IRO_ASSERT(221, key2 != NULL); - return key1 == key2; -} - -CW_INLINE Object *StackElement_proc(StackElement *stackElement) { - IRO_ASSERT(228, stackElement != NULL); - return stackElement->proc; -} - -CW_INLINE PartialTransferFunction *StackElement_ptf(StackElement *stackElement) { - IRO_ASSERT(235, stackElement != NULL); - return stackElement->ptf; -} - -CW_INLINE ParamMappingFunction *StackElement_map(StackElement *stackElement) { - IRO_ASSERT(242, stackElement != NULL); - return stackElement->map; -} - -CW_INLINE IROLinear *StackElement_funcCall(StackElement *stackElement) { - IRO_ASSERT(249, stackElement != NULL); - return stackElement->funcCall; -} - -CW_INLINE Stack *Stack_New(void) { - Stack *stack = IRO_malloc(sizeof(Stack)); - IRO_ASSERT(265, stack != NULL); -#ifdef IRO_DEBUG - stack->top = NULL; - stack->next = NULL; -#endif - return stack; -} - -CW_INLINE void Stack_Delete(Stack *stack) { - IRO_ASSERT(277, stack != NULL); - IRO_ASSERT(278, stack->top == NULL); - IRO_ASSERT(279, stack->next == NULL); - IRO_DEBUG_CLEAR(stack, sizeof(Stack)); - IRO_free(stack); -} - -CW_INLINE void Stack_Init(Stack *stack) { - IRO_ASSERT(289, stack != NULL); - stack->top = NULL; - stack->next = NULL; -} - -CW_INLINE void Stack_Term(Stack **stackPtr) { - StackElement *stackElement; - - IRO_ASSERT(299, stackPtr != NULL); - IRO_ASSERT(300, *stackPtr != NULL); - - while ((*stackPtr)->top) { - stackElement = Stack_sub_48A5B0(stackPtr); - StackElement_Term(stackElement); - StackElement_Delete(stackElement); - } -} - -CW_INLINE void Stack_sub_48A660(Stack **stackPtr, StackElement *stackElement) { - StackElement *newElement; - Stack *newStack; - - IRO_ASSERT(315, stackPtr != NULL); - IRO_ASSERT(316, *stackPtr != NULL); - - newElement = StackElement_New(); - StackElement_Copy(newElement, stackElement); - - newStack = Stack_New(); - newStack->top = newElement; - newStack->next = *stackPtr; - *stackPtr = newStack; -} - -CW_INLINE StackElement *Stack_Top(Stack **stackPtr) { - IRO_ASSERT(331, stackPtr != NULL); - IRO_ASSERT(332, *stackPtr != NULL); - - return (*stackPtr)->top; -} - -CW_INLINE Stack *Stack_Next(Stack **stackPtr) { - IRO_ASSERT(343, stackPtr != NULL); - IRO_ASSERT(344, *stackPtr != NULL); - - return (*stackPtr)->next; -} - -CW_INLINE StackElement *Stack_sub_48A5B0(Stack **stackPtr) { - StackElement *stackElement; - - IRO_ASSERT(357, stackPtr != NULL); - IRO_ASSERT(358, *stackPtr != NULL); - - stackElement = (*stackPtr)->top; - if (stackElement) { - Stack *next = (*stackPtr)->next; - (*stackPtr)->top = NULL; - (*stackPtr)->next = NULL; - Stack_Delete(*stackPtr); - *stackPtr = next; - } - - return stackElement; -} - -CW_INLINE StackElement *Stack_sub_48A710(Stack **stackPtr, void *key) { - Stack *stack; - - IRO_ASSERT(379, stackPtr != NULL); - IRO_ASSERT(380, key != NULL); - - for (stack = *stackPtr; stack; stack = stack->next) { - if (stack->top) { - if (StackRelated_sub_48A760(StackElement_sub_48A780(stack->top), key)) - return stack->top; - } - } - - return NULL; -} - -CW_INLINE ObjectSet *ObjectSet_New(void) { - ObjectSet *procList; - - procList = IRO_malloc(sizeof(ObjectSet)); - IRO_ASSERT(439, procList != NULL); -#ifdef IRO_DEBUG - procList->proc = NULL; - procList->otherProcs = NULL; -#endif - return procList; -} - -CW_INLINE void ObjectSet_Delete(ObjectSet *procList) { - IRO_ASSERT(451, procList != NULL); - IRO_ASSERT(452, procList->proc == NULL); - IRO_ASSERT(453, procList->otherProcs == NULL); - IRO_DEBUG_CLEAR(procList, sizeof(ObjectSet)); - IRO_free(procList); -} - -CW_INLINE void ObjectSet_Init(ObjectSet *procList) { - IRO_ASSERT(463, procList != NULL); - procList->proc = NULL; - procList->otherProcs = NULL; -} - -CW_INLINE void ObjectSet_Term(ObjectSet *procList) { - IRO_ASSERT(481, procList != NULL); - ObjectSet_RemoveAll(procList); -#ifdef IRO_DEBUG - procList->proc = NULL; - procList->otherProcs = NULL; -#endif -} - -CW_INLINE void ObjectSet_ForEach(ObjectSet *procList, void (*action)(Object *, void *), void *refcon) { - IRO_ASSERT(528, procList != NULL); - IRO_ASSERT(529, action != NULL); - IRO_ASSERT(530, refcon == NULL || refcon != NULL); - - while (procList && procList->proc) { - action(procList->proc, refcon); - procList = procList->otherProcs; - } -} - -CW_INLINE Object *ObjectSet_sub_485020(ObjectSet *procList, Object *proc) { - IRO_ASSERT(540, procList != NULL); - IRO_ASSERT(541, proc != NULL); - while (procList && procList->proc) { - if (procList->proc == proc) - return procList->proc; - procList = procList->otherProcs; - } - return NULL; -} - -CW_INLINE Object *ObjectSet_FindFirst(ObjectSet *procList) { - IRO_ASSERT(552, procList != NULL); - return procList->proc; -} - -CW_INLINE int ObjectSet_Count(ObjectSet *procList) { - int count; - - IRO_ASSERT(561, procList != NULL); - - count = 0; - while (procList && procList->proc) { - count++; - procList = procList->otherProcs; - } - - return count; -} - -CW_INLINE void ObjectSet_sub_486800(ObjectSet *procList, Object *proc) { - ObjectSet *newProcList; - - IRO_ASSERT(574, procList != NULL); - IRO_ASSERT(575, proc != NULL); - - if (procList->proc) { - newProcList = ObjectSet_New(); - ObjectSet_Init(newProcList); - newProcList->proc = procList->proc; - newProcList->otherProcs = procList->otherProcs; - procList->otherProcs = newProcList; - } - - procList->proc = proc; -} - -CW_INLINE void ObjectSet_sub_4867D0(ObjectSet *procList, Object *proc) { - IRO_ASSERT(592, procList != NULL); - IRO_ASSERT(593, proc != NULL); - - if (!ObjectSet_sub_485020(procList, proc)) - ObjectSet_sub_486800(procList, proc); -} - -CW_INLINE void ObjectSet_Remove(ObjectSet *procList, Object *proc) { - ObjectSet *prev; - ObjectSet *tmp; - - IRO_ASSERT(605, procList != NULL); - IRO_ASSERT(606, proc != NULL); - - prev = NULL; - while (procList && procList->proc) { - if (procList->proc == proc) { - if (!prev) { - if (procList->otherProcs == NULL) { - procList->proc = NULL; - } else { - tmp = procList->otherProcs; - procList->proc = procList->otherProcs->proc; - procList->otherProcs = procList->otherProcs->otherProcs; - tmp->proc = NULL; - tmp->otherProcs = NULL; - ObjectSet_Term(tmp); - ObjectSet_Delete(tmp); - } - } else { - prev->otherProcs = procList->otherProcs; - procList->proc = NULL; - procList->otherProcs = NULL; - ObjectSet_Term(procList); - ObjectSet_Delete(procList); - } - return; - } - prev = procList; - procList = procList->otherProcs; - } -} - -CW_INLINE void ObjectSet_RemoveAll(ObjectSet *procList) { - IRO_ASSERT(645, procList != NULL); - - while (procList && procList->proc) - ObjectSet_Remove(procList, procList->proc); -} - -CW_INLINE void ObjectSet_AddSetAction(Object *proc, void *refcon) { - IRO_ASSERT(655, proc != NULL); - IRO_ASSERT(656, refcon != NULL); - - ObjectSet_sub_4867D0(refcon, proc); -} - -CW_INLINE void ObjectSet_SimpleAddSetAction(Object *proc, void *refcon) { - IRO_ASSERT(663, proc != NULL); - IRO_ASSERT(664, refcon != NULL); - - ObjectSet_sub_486800(refcon, proc); -} - -CW_INLINE void ObjectSet_sub_48C590(ObjectSet *dest, ObjectSet *src) { - IRO_ASSERT(671, dest != NULL); - IRO_ASSERT(672, src != NULL); - - if (dest->proc) - ObjectSet_ForEach(src, ObjectSet_AddSetAction, dest); - else - ObjectSet_ForEach(src, ObjectSet_SimpleAddSetAction, dest); -} - -CW_INLINE void ObjectSet_RemoveSetAction(Object *proc, void *refcon) { - IRO_ASSERT(682, proc != NULL); - IRO_ASSERT(683, refcon != NULL); - - ObjectSet_Remove(refcon, proc); -} - -CW_INLINE void ObjectSet_removeiter_sub_48C890(ObjectSet *dest, ObjectSet *src) { - IRO_ASSERT(690, dest != NULL); - IRO_ASSERT(691, src != NULL); - - ObjectSet_ForEach(src, ObjectSet_RemoveSetAction, dest); -} - -CW_INLINE Boolean ObjectSet_sub_484FA0(ObjectSet *os1, ObjectSet *os2) { - ObjectSet *scan; - - IRO_ASSERT(700, os1 != NULL); - IRO_ASSERT(701, os2 != NULL); - - if (os1 == os2) - return 1; - - for (scan = os1; scan && scan->proc; scan = scan->otherProcs) { - if (!ObjectSet_sub_485020(os2, scan->proc)) - return 0; - } - - for (scan = os2; scan && scan->proc; scan = scan->otherProcs) { - if (!ObjectSet_sub_485020(os1, scan->proc)) - return 0; - } - - return 1; -} - -CW_INLINE ExtendedParam *ExtendedParam_New(void) { - ExtendedParam *ep = IRO_malloc(sizeof(ExtendedParam)); - - IRO_ASSERT(755, ep != NULL); -#ifdef IRO_DEBUG - ep->objectSet = NULL; -#endif - return ep; -} - -CW_INLINE void ExtendedParam_Delete(ExtendedParam *ep) { - IRO_ASSERT(762, ep != NULL); - IRO_ASSERT(763, ep->objectSet == NULL); - IRO_DEBUG_CLEAR(ep, sizeof(ExtendedParam)); - IRO_free(ep); -} - -CW_INLINE void ExtendedParam_Init(ExtendedParam *ep, Object *obj) { - IRO_ASSERT(777, ep != NULL); - IRO_ASSERT(778, obj != NULL); - IRO_ASSERT(779, obj->extParam == NULL); - IRO_ASSERT(780, stExtendedParamNum < ((uint32) -1) / 2 - 1); - - ep->objectSet = ObjectSet_New(); - ObjectSet_Init(ep->objectSet); - ObjectSet_sub_4867D0(ep->objectSet, obj); - obj->extParam = ep; - - ep->x4 = stExtendedParamNum++; -} - -CW_INLINE void ExtendedParam_TermAction(Object *obj, void *refcon) { - obj->extParam = NULL; -} - -CW_INLINE void ExtendedParam_Term(ExtendedParam *ep) { - IRO_ASSERT(800, ep != NULL); - - ObjectSet_ForEach(ep->objectSet, ExtendedParam_TermAction, NULL); - ObjectSet_Term(ep->objectSet); - ObjectSet_Delete(ep->objectSet); -#ifdef IRO_DEBUG - ep->objectSet = NULL; -#endif -} - -CW_INLINE Boolean ExtendedParams_Equal(ExtendedParam *ep1, ExtendedParam *ep2) { - IRO_ASSERT(841, ep1 != NULL); - IRO_ASSERT(842, ep2 != NULL); - IRO_ASSERT(843, ep1->objectSet != NULL); - IRO_ASSERT(844, ep2->objectSet != NULL); - - if (ep1 == ep2) - return 1; - - return ep1->x4 == ep2->x4 && ObjectSet_sub_484FA0(ep1->objectSet, ep2->objectSet); -} - -CW_INLINE ExtendedParam *ExtendedParam_FindByObject(Object *obj) { - IRO_ASSERT(856, obj != NULL); - - return obj->extParam; -} - -CW_INLINE void ExtendedParam_sub_4867B0(ExtendedParam *ep, Object *obj) { - IRO_ASSERT(863, ep != NULL); - IRO_ASSERT(864, ep->objectSet != NULL); - IRO_ASSERT(865, obj != NULL); - - ObjectSet_sub_4867D0(ep->objectSet, obj); - obj->extParam = ep; -} - -CW_INLINE void ExtendedParam_RemoveObjectSetAction(Object *object, void *refcon) { - object->extParam = NULL; -} - -CW_INLINE void EP_sub_48C850(ExtendedParam *ep, ObjectSet *objSet) { - IRO_ASSERT(888, ep != NULL); - IRO_ASSERT(889, ep->objectSet != NULL); - IRO_ASSERT(890, objSet != NULL); - - ObjectSet_removeiter_sub_48C890(ep->objectSet, objSet); - ObjectSet_ForEach(objSet, ExtendedParam_RemoveObjectSetAction, NULL); -} - -CW_INLINE ObjectSet *ExtendedParam_objectSet(ExtendedParam *ep) { - IRO_ASSERT(898, ep != NULL); - - return ep->objectSet; -} - -CW_INLINE uint32 ExtendedParam_sub_489110(ExtendedParam *ep) { - IRO_ASSERT(905, ep != NULL); - - return ep->x4; -} - -CW_INLINE ExtendedParamSet *AllocsExtParamSet_sub_4876C0(void) { - ExtendedParamSet *epList = IRO_malloc(sizeof(ExtendedParamSet)); - - IRO_ASSERT(924, epList != NULL); -#ifdef IRO_DEBUG - epList->ep = NULL; - epList->otherEps = NULL; -#endif - return epList; -} - -CW_INLINE void FreesExtParamSet_sub_48CAE0(ExtendedParamSet *epList) { - IRO_ASSERT(936, epList != NULL); - IRO_ASSERT(937, epList->ep == NULL); - IRO_ASSERT(938, epList->otherEps == NULL); - IRO_DEBUG_CLEAR(epList, sizeof(ExtendedParamSet)); - IRO_free(epList); -} - -CW_INLINE void InitsExtParamSet_sub_4876A0(ExtendedParamSet *epList) { - IRO_ASSERT(948, epList != NULL); - epList->ep = NULL; - epList->otherEps = NULL; -} - -CW_INLINE void TermsExtParamSet_sub_48CB00(ExtendedParamSet *epList) { - IRO_ASSERT(966, epList != NULL); - ExtendedParamSet_RemoveAll(epList); -#ifdef IRO_DEBUG - epList->ep = NULL; - epList->otherEps = NULL; -#endif -} - -CW_INLINE void MaybeWalkExtParamSet_sub_48CBE0(ExtendedParamSet *epList, void (*action)(ExtendedParam *, void *), void *refcon) { - IRO_ASSERT(1010, epList != NULL); - IRO_ASSERT(1011, action != NULL); - - while (epList && epList->ep) { - action(epList->ep, refcon); - epList = epList->otherEps; - } -} - -CW_INLINE ExtendedParam *ExtParamSet_sub_4876D0(ExtendedParamSet *epList, ExtendedParam *ep) { - IRO_ASSERT(1022, epList != NULL); - IRO_ASSERT(1023, ep != NULL); - - while (epList && epList->ep) { - if (epList->ep == ep) - return epList->ep; - epList = epList->otherEps; - } - - return NULL; -} - -CW_INLINE void ExtParamSet_sub_487660(ExtendedParamSet *epList, ExtendedParam *ep) { - IRO_ASSERT(1056, epList != NULL); - IRO_ASSERT(1057, ep != NULL); - - if (epList->ep) { - ExtendedParamSet *newSet = AllocsExtParamSet_sub_4876C0(); - InitsExtParamSet_sub_4876A0(newSet); - newSet->ep = epList->ep; - newSet->otherEps = epList->otherEps; - epList->otherEps = newSet; - } - - epList->ep = ep; -} - -CW_INLINE void ExtParamSet_sub_487630(ExtendedParamSet *epList, ExtendedParam *ep) { - IRO_ASSERT(1076, epList != NULL); - IRO_ASSERT(1077, ep != NULL); - - if (!ExtParamSet_sub_4876D0(epList, ep)) - ExtParamSet_sub_487660(epList, ep); -} - -CW_INLINE void ExtendedParamSet_Remove(ExtendedParamSet *epList, ExtendedParam *ep) { - ExtendedParamSet *prev; - ExtendedParamSet *tmp; - - IRO_ASSERT(1089, epList != NULL); - IRO_ASSERT(1090, ep != NULL); - - prev = NULL; - while (epList && epList->ep) { - if (epList->ep == ep) { - if (!prev) { - if (epList->otherEps == NULL) { - epList->ep = NULL; - } else { - tmp = epList->otherEps; - epList->ep = epList->otherEps->ep; - epList->otherEps = epList->otherEps->otherEps; - tmp->ep = NULL; - tmp->otherEps = NULL; - TermsExtParamSet_sub_48CB00(tmp); - FreesExtParamSet_sub_48CAE0(tmp); - } - } else { - prev->otherEps = epList->otherEps; - epList->ep = NULL; - epList->otherEps = NULL; - TermsExtParamSet_sub_48CB00(epList); - FreesExtParamSet_sub_48CAE0(epList); - } - return; - } - prev = epList; - epList = epList->otherEps; - } -} - -CW_INLINE void ExtendedParamSet_RemoveAll(ExtendedParamSet *epList) { - IRO_ASSERT(1129, epList != NULL); - - while (epList && epList->ep) - ExtendedParamSet_Remove(epList, epList->ep); -} - -CW_INLINE PAHeapBlock *CreateUniqueHeapAlloc_sub_486420(void) { - PAHeapBlock *hb = IRO_malloc(sizeof(PAHeapBlock)); - - IRO_ASSERT(1225, hb != NULL); -#ifdef IRO_DEBUG - hb->parent = NULL; -#endif - return hb; -} - -CW_INLINE void InitUniqueHeapAlloc_sub_486410(PAHeapBlock *hb, IROLinear *nd) { - IRO_ASSERT(1247, hb != NULL); - - hb->x0 = nd; -} - -CW_INLINE Boolean PAHeapBlocks_Equal(PAHeapBlock *hb1, PAHeapBlock *hb2) { - IRO_ASSERT(1296, hb1 != NULL); - IRO_ASSERT(1297, hb2 != NULL); - - return (hb1 == hb2) || (hb1->x0 == hb2->x0); -} - -CW_INLINE PALocalVar *PALocalVar_New(void) { - PALocalVar *local = IRO_malloc(sizeof(PALocalVar)); - - IRO_ASSERT(1333, local != NULL); -#ifdef IRO_DEBUG - local->parent = NULL; - local->nextSibling = NULL; -#endif - return local; -} - -CW_INLINE void PALocalVar_InitByObject(PALocalVar *local, Object *obj) { - IRO_ASSERT(1357, local != NULL); - IRO_ASSERT(1358, obj != NULL); - - local->x0 = obj; - if (obj->name && obj->name->name) { - local->x4 = IRO_malloc(strlen(obj->name->name) + 1); - strcpy(local->x4, obj->name->name); - } else { - local->x4 = NULL; - } -} - -CW_INLINE void PALocalVar_InitByName(PALocalVar *local, char *name) { - IRO_ASSERT(1372, local != NULL); - IRO_ASSERT(1373, name != NULL); - - local->x0 = NULL; - local->x4 = IRO_malloc(strlen(name) + 1); - strcpy(local->x4, name); -} - -CW_INLINE Boolean PALocalVars_Equal(PALocalVar *local1, PALocalVar *local2) { - IRO_ASSERT(1419, local1 == NULL || local1 != NULL); - IRO_ASSERT(1420, local2 == NULL || local2 != NULL); - - if (local1 == local2) - return 1; - if (!local1 || !local2) - return 0; - - if (!local1->x0 || !local2->x0) { - if (local1->x4) - return local2->x4 && !strcmp(local1->x4, local2->x4); - } - - return local1->x0 == local2->x0; -} - -CW_INLINE void PALocalVar_SetSth_sub_4847C0(PALocalVar *local, Object *obj) { - IRO_ASSERT(1436, local != NULL); - IRO_ASSERT(1437, obj == NULL || obj != NULL); - - local->x0 = obj; -} - -CW_INLINE Object *PALocalVar_Get0_sub_4847E0(PALocalVar *local) { - IRO_ASSERT(1444, local != NULL); - return local->x0; -} - -CW_INLINE char *PALocalVar_Get4_sub_4847D0(PALocalVar *local) { - IRO_ASSERT(1451, local != NULL); - return local->x4; -} - -CW_INLINE PAMemoryBlock *PAMemoryBlock_New(void) { - PAMemoryBlock *mb = IRO_malloc(sizeof(PAMemoryBlock)); - - IRO_ASSERT(1491, mb != NULL); -#ifdef IRO_DEBUG - mb->kind = PAMEMORYBLOCKKIND_INVALID; -#endif - return mb; -} - -CW_INLINE void PAMemoryBlock_Delete(PAMemoryBlock *mb) { - IRO_ASSERT(1502, mb != NULL); - IRO_ASSERT(1503, mb->kind == PAMEMORYBLOCKKIND_INVALID); - IRO_free(mb); -} - -CW_INLINE void PAMemoryBlock_Init(PAMemoryBlock *mb, PAMemoryBlockKind kind, void *thing) { - IRO_ASSERT(1513, mb != NULL); - IRO_ASSERT(1514, thing == NULL || thing != NULL); - - mb->kind = kind; - switch (mb->kind) { - case PAMEMORYBLOCKKIND_EXTENDEDPARAM: - mb->u.ep = (ExtendedParam *) thing; - break; - case PAMEMORYBLOCKKIND_LOCALVAR: - mb->u.localvar = (PALocalVar *) thing; - break; - case PAMEMORYBLOCKKIND_HEAPBLOCK: - mb->u.heapblock = (PAHeapBlock *) thing; - break; - case PAMEMORYBLOCKKIND_INT: - mb->u.intval = *((CInt64 *) thing); - break; - case PAMEMORYBLOCKKIND_6: - mb->u.x6 = (void *) thing; - break; - default: - CError_FATAL(1535); - } -} - -CW_INLINE void PAMemoryBlock_Term(PAMemoryBlock *mb) { - IRO_ASSERT(1552, mb != NULL); - -#ifdef IRO_DEBUG - mb->kind = PAMEMORYBLOCKKIND_INVALID; -#endif -} - -CW_INLINE Boolean MemoryBlocks_Equal(PAMemoryBlock *mb1, PAMemoryBlock *mb2) { - IRO_ASSERT(1657, mb1 == NULL || mb1 != NULL); - IRO_ASSERT(1658, mb2 == NULL || mb2 != NULL); - - if (mb1 == mb2) - return 1; - - if (!mb1 || !mb2 || mb1->kind != mb2->kind) - return 0; - - switch (mb1->kind) { - case PAMEMORYBLOCKKIND_EXTENDEDPARAM: - return ExtendedParams_Equal(mb1->u.ep, mb2->u.ep); - case PAMEMORYBLOCKKIND_LOCALVAR: - return PALocalVars_Equal(mb1->u.localvar, mb2->u.localvar); - case PAMEMORYBLOCKKIND_HEAPBLOCK: - return PAHeapBlocks_Equal(mb1->u.heapblock, mb2->u.heapblock); - case PAMEMORYBLOCKKIND_INT: - return CInt64_Equal(mb1->u.intval, mb2->u.intval); - case PAMEMORYBLOCKKIND_6: - return mb1->u.x6 == mb2->u.x6; - default: - CError_FATAL(1684); - return 0; - } -} - -CW_INLINE PAMemoryBlockKind PAMemoryBlock_kind(PAMemoryBlock *mb) { - IRO_ASSERT(1692, mb != NULL); - - return mb->kind; -} - -CW_INLINE void *PAMemoryBlock_thing(PAMemoryBlock *mb) { - IRO_ASSERT(1699, mb != NULL); - - switch (mb->kind) { - case PAMEMORYBLOCKKIND_EXTENDEDPARAM: - return mb->u.ep; - case PAMEMORYBLOCKKIND_LOCALVAR: - return mb->u.localvar; - case PAMEMORYBLOCKKIND_HEAPBLOCK: - return mb->u.heapblock; - case PAMEMORYBLOCKKIND_INT: - return &mb->u.intval; - case PAMEMORYBLOCKKIND_6: - return mb->u.x6; - default: - CError_FATAL(1719); - return NULL; - } -} - -CW_INLINE LocationSet *LocationSet_New(void) { - LocationSet *ls = IRO_malloc(sizeof(LocationSet)); - - IRO_ASSERT(1767, ls != NULL); -#ifdef IRO_DEBUG - ls->block = NULL; - ls->rtype = NULL; - ls->u.known.field = cint64_zero; - ls->u.known.stride = 0; -#endif - return ls; -} - -CW_INLINE void LocationSet_Delete(LocationSet *ls) { - IRO_ASSERT(1781, ls != NULL); - IRO_ASSERT(1782, ls != stUnknownLs); - IRO_ASSERT(1783, ls->block == NULL); - IRO_ASSERT(1784, CInt64_IsZero(&ls->u.known.field)); - IRO_ASSERT(1785, ls->u.known.stride == 0); - IRO_ASSERT(1786, ls->rtype == NULL); - IRO_DEBUG_CLEAR(ls, sizeof(LocationSet)); - IRO_free(ls); -} - -CW_INLINE void LocationSet_InitKnown(LocationSet *ls, PAMemoryBlock *block, CInt64 field, UInt32 stride, Type *rtype) { - IRO_ASSERT(1796, ls != NULL); - IRO_ASSERT(1797, ls != stUnknownLs); - IRO_ASSERT(1798, block != NULL); - IRO_ASSERT(1799, rtype == NULL || rtype != NULL); - ls->block = block; - ls->rtype = rtype; - ls->u.known.field = field; - ls->u.known.stride = stride; -} - -CW_INLINE void LocationSet_InitUnknown(LocationSet *ls, Type *rtype, PAMemoryBlock *restriction, LocationSet *bitfieldOf) { - IRO_ASSERT(1809, ls != NULL); - IRO_ASSERT(1810, ls != stUnknownLs); - IRO_ASSERT(1811, rtype == NULL || rtype != NULL); - IRO_ASSERT(1812, restriction == NULL || restriction != NULL); - IRO_ASSERT(1813, bitfieldOf == NULL || bitfieldOf != NULL); - - LocationSet_Copy(ls, stUnknownLs); - ls->rtype = rtype; - ls->u.unknown.restriction = restriction; - if (bitfieldOf) { - ls->u.unknown.bitfieldOf = LocationSet_New(); - LocationSet_Copy(ls->u.unknown.bitfieldOf, bitfieldOf); - } else { - ls->u.unknown.bitfieldOf = NULL; - } -} - -CW_INLINE void LocationSet_Copy(LocationSet *dest, LocationSet *src) { - IRO_ASSERT(1829, src != NULL); - IRO_ASSERT(1830, dest != NULL); - - dest->block = src->block; - dest->rtype = src->rtype; - - if (!LocationSet_IsUnknown(src)) { - dest->u.known.field = src->u.known.field; - dest->u.known.stride = src->u.known.stride; - } else { - dest->u.unknown.restriction = src->u.unknown.restriction; - if (src->u.unknown.bitfieldOf != NULL) { - dest->u.unknown.bitfieldOf = LocationSet_New(); - LocationSet_Copy(dest->u.unknown.bitfieldOf, src->u.unknown.bitfieldOf); - } else { - dest->u.unknown.bitfieldOf = NULL; - } - } -} - -CW_INLINE void LocationSet_Term(LocationSet *ls) { - IRO_ASSERT(1857, ls != NULL); - IRO_ASSERT(1858, ls != stUnknownLs); - -#ifdef IRO_DEBUG - if (LocationSet_IsUnknown(ls) && ls->u.unknown.bitfieldOf) { - LocationSet_Term(ls->u.unknown.bitfieldOf); - LocationSet_Delete(ls->u.unknown.bitfieldOf); - } - ls->block = NULL; - ls->rtype = NULL; - ls->u.known.field = cint64_zero; - ls->u.known.stride = 0; -#endif -} - -CW_INLINE Boolean LocationSets_Overlap(LocationSet *ls1, Type *rtype1, LocationSet *ls2, Type *rtype2) { - Boolean isUnknown1, isUnknown2; - PAMemoryBlock *restriction1, *restriction2; - - IRO_ASSERT(1974, ls1 != NULL); - IRO_ASSERT(1975, rtype1 == NULL || rtype1 != NULL); - IRO_ASSERT(1976, ls2 != NULL); - IRO_ASSERT(1977, rtype2 == NULL || rtype2 != NULL); - - if (ls1 == ls2) - return 1; - - isUnknown1 = LocationSet_IsUnknown(ls1); - if (isUnknown1) - restriction1 = ls1->u.unknown.restriction; - else - restriction1 = NULL; - - isUnknown2 = LocationSet_IsUnknown(ls2); - if (isUnknown2) - restriction2 = ls2->u.unknown.restriction; - else - restriction2 = NULL; - - if ( - (isUnknown1 && !restriction1) || - (isUnknown2 && !restriction2) || - (isUnknown1 && isUnknown2 && MemoryBlocks_Equal(restriction1, restriction2)) - ) - return 1; - - if (isUnknown1 || isUnknown2) - return 0; - - if (MemoryBlocks_Equal(ls1->block, ls2->block)) { - UInt32 size1; - UInt32 size2; - UInt32 i; - CInt64 work; - CInt64 longgcd; - - if (rtype1) - size1 = rtype1->size; - else - size1 = -1; - - if (rtype2) - size2 = rtype2->size; - else - size2 = -1; - - if (ls1->u.known.stride == ls2->u.known.stride) { - CInt64 longsize1; - CInt64 longsize2; - CInt64_SetULong(&longsize1, size1); - CInt64_SetULong(&longsize2, size2); - - return CInt64_Equal(ls1->u.known.field, ls2->u.known.field) || - (CInt64_Less(ls1->u.known.field, ls2->u.known.field) && CInt64_Greater(CInt64_Add(ls1->u.known.field, longsize1), ls2->u.known.field)) || - (CInt64_Less(ls2->u.known.field, ls1->u.known.field) && CInt64_Greater(CInt64_Add(ls2->u.known.field, longsize2), ls1->u.known.field)); - } else { - work = CInt64_Sub(ls1->u.known.field, ls2->u.known.field); - if (CInt64_IsNegative(&work)) - work = CInt64_Neg(work); - - CInt64_SetULong(&longgcd, gcd(ls1->u.known.stride, ls2->u.known.stride)); - if (CInt64_Equal(CInt64_ModU(work, longgcd), cint64_zero)) - return 1; - - if (size1 == -1) - return 1; - - for (i = 1; i < size1; i++) { - CInt64_SetLong(&work, i); - work = CInt64_Add(work, ls1->u.known.field); - work = CInt64_Sub(work, ls2->u.known.field); - if (CInt64_IsNegative(&work)) - work = CInt64_Neg(work); - if (CInt64_Equal(CInt64_ModU(work, longgcd), cint64_zero)) - return 1; - } - - if (size2 == -1) - return 1; - - for (i = 1; i < size2; i++) { - CInt64_SetLong(&work, i); - work = CInt64_Add(work, ls2->u.known.field); - work = CInt64_Sub(work, ls1->u.known.field); - if (CInt64_IsNegative(&work)) - work = CInt64_Neg(work); - if (CInt64_Equal(CInt64_ModU(work, longgcd), cint64_zero)) - return 1; - } - - return 0; - } - } - - return 0; -} - -CW_INLINE Boolean LocationSets_Equal(LocationSet *ls1, LocationSet *ls2) { - IRO_ASSERT(2080, ls1 != NULL); - IRO_ASSERT(2081, ls2 != NULL); - - return - (ls1 == ls2) || - ( - (LocationSet_IsUnknown(ls1) && LocationSet_IsUnknown(ls2)) && - (MemoryBlocks_Equal(ls1->u.unknown.restriction, ls2->u.unknown.restriction)) && - ((ls1->u.unknown.bitfieldOf == ls2->u.unknown.bitfieldOf) || - (ls1->u.unknown.bitfieldOf && ls2->u.unknown.bitfieldOf && LocationSets_Equal(ls1->u.unknown.bitfieldOf, ls2->u.unknown.bitfieldOf))) && - ((ls1->rtype == ls2->rtype) || (ls1->rtype && ls2->rtype && ls1->rtype->size == ls2->rtype->size)) - ) || - ( - (!LocationSet_IsUnknown(ls1) && !LocationSet_IsUnknown(ls2)) && - (ls1->u.known.stride == ls2->u.known.stride) && - ((ls1->rtype == ls2->rtype) || (ls1->rtype && ls2->rtype && ls1->rtype->size == ls2->rtype->size)) && - CInt64_Equal(ls1->u.known.field, ls2->u.known.field) && - MemoryBlocks_Equal(ls1->block, ls2->block) - ); -} - -CW_INLINE Boolean LocationSets_LookupCompatible(LocationSet *ls1, LocationSet *ls2) { - IRO_ASSERT(2119, ls1 != NULL); - IRO_ASSERT(2120, ls2 != NULL); - - if ( - (ls1 == ls2) || - ( - LocationSet_IsUnknown(ls1) && - LocationSet_IsUnknown(ls2) && - MemoryBlocks_Equal(ls1->u.unknown.restriction, ls2->u.unknown.restriction) && - (ls1->rtype == ls2->rtype || (ls1->rtype && ls2->rtype && ls1->rtype->size == ls2->rtype->size)) - )) - return 1; - - if ( - (!LocationSet_IsUnknown(ls1) && !LocationSet_IsUnknown(ls2)) && - (ls1->rtype == ls2->rtype || (ls1->rtype && ls2->rtype && ls1->rtype->size == ls2->rtype->size)) && - MemoryBlocks_Equal(ls1->block, ls2->block) - ) { - CInt64 work; - CInt64 longgcd; - - if (ls1->u.known.stride == ls2->u.known.stride) - return CInt64_Equal(ls1->u.known.field, ls2->u.known.field); - - work = CInt64_Sub(ls1->u.known.field, ls2->u.known.field); - if (CInt64_IsNegative(&work)) - work = CInt64_Neg(work); - - CInt64_SetULong(&longgcd, gcd(ls1->u.known.stride, ls2->u.known.stride)); - return CInt64_Equal(CInt64_ModU(work, longgcd), cint64_zero); - } - - return 0; -} - -CW_INLINE Boolean LocationSet_Contains(LocationSet *ls1, Type *rtype1, LocationSet *ls2, Type *rtype2) { - Boolean unknown1; - Boolean unknown2; - PAMemoryBlock *restriction2; - PAMemoryBlock *restriction1; - CInt64 longsize1; - CInt64 longsize2; - - IRO_ASSERT(2168, ls1 != NULL); - IRO_ASSERT(2169, ls2 != NULL); - IRO_ASSERT(2170, rtype1 != NULL); - IRO_ASSERT(2171, rtype2 != NULL); - - if (ls1 == ls2) - return 1; - - unknown1 = LocationSet_IsUnknown(ls1); - if (unknown1) - restriction1 = ls1->u.unknown.restriction; - else - restriction1 = NULL; - - unknown2 = LocationSet_IsUnknown(ls2); - if (unknown2) - restriction2 = ls2->u.unknown.restriction; - else - restriction2 = NULL; - - if (unknown1) - return !restriction1 || (unknown2 && MemoryBlocks_Equal(restriction2, restriction1)); - - CInt64_SetULong(&longsize1, rtype1->size); - CInt64_SetULong(&longsize2, rtype2->size); - - return - !LocationSet_IsUnknown(ls2) && - (ls1->u.known.stride == 0) && - (ls2->u.known.stride == 0) && - rtype1->size >= rtype2->size && - CInt64_LessEqual(ls1->u.known.field, ls2->u.known.field) && - CInt64_GreaterEqual(CInt64_Add(ls1->u.known.field, longsize1), CInt64_Add(ls2->u.known.field, longsize2)) && - MemoryBlocks_Equal(ls1->block, ls2->block); -} - -CW_INLINE Boolean LocationSet_IsUnknown(LocationSet *ls) { - IRO_ASSERT(2233, ls != NULL); - - return (ls == stUnknownLs) || (ls->block == stUnknownMb); -} - -CW_INLINE Boolean LocationSet_sub_48AF30(LocationSet *ls) { - return - !LocationSet_IsUnknown(ls) && - (ls->u.known.stride == 0) && - CInt64_IsZero(&ls->u.known.field) && - PAMemoryBlock_kind(ls->block) == PAMEMORYBLOCKKIND_LOCALVAR && - !PAMemoryBlock_thing(ls->block); -} - -CW_INLINE void LocationSet_SetRtype(LocationSet *ls, Type *rtype) { - IRO_ASSERT(2263, ls != NULL); - IRO_ASSERT(2264, ls != stUnknownLs); - IRO_ASSERT(2265, rtype != NULL); - - ls->rtype = rtype; -} - -CW_INLINE void SetsLocationSetField_sub_4851B0(LocationSet *ls, CInt64 field) { - IRO_ASSERT(2272, ls != NULL); - IRO_ASSERT(2273, !LocationSet_IsUnknown(ls)); - - ls->u.known.field = field; -} - -CW_INLINE void SetsLocationSetStride_sub_4852D0(LocationSet *ls, SInt32 stride) { - IRO_ASSERT(2280, ls != NULL); - IRO_ASSERT(2281, !LocationSet_IsUnknown(ls)); - - ls->u.known.stride = stride; -} - -CW_INLINE PAMemoryBlock *LocationSet_block(LocationSet *ls) { - IRO_ASSERT(2298, ls != NULL); - - return ls->block; -} - -CW_INLINE Type *LocationSet_rtype(LocationSet *ls) { - IRO_ASSERT(2306, ls != NULL); - IRO_ASSERT(2307, ls != stUnknownLs); - - return ls->rtype; -} - -CW_INLINE CInt64 LocationSet_field(LocationSet *ls) { - IRO_ASSERT(2314, ls != NULL); - IRO_ASSERT(2315, !LocationSet_IsUnknown(ls)); - - return ls->u.known.field; -} - -CW_INLINE UInt32 LocationSet_stride(LocationSet *ls) { - IRO_ASSERT(2322, ls != NULL); - IRO_ASSERT(2323, !LocationSet_IsUnknown(ls)); - - return ls->u.known.stride; -} - -CW_INLINE PAMemoryBlock *LocationSet_restriction(LocationSet *ls) { - IRO_ASSERT(2330, ls != NULL); - IRO_ASSERT(2331, LocationSet_IsUnknown(ls)); - - return ls->u.unknown.restriction; -} - -CW_INLINE LocationSet *LocationSet_bitfieldOf(LocationSet *ls) { - IRO_ASSERT(2338, ls != NULL); - IRO_ASSERT(2339, LocationSet_IsUnknown(ls)); - - return ls->u.unknown.bitfieldOf; -} - -CW_INLINE LocationSetSet *LocationSetSet_New(void) { - LocationSetSet *lss = IRO_malloc(sizeof(LocationSetSet)); - - IRO_ASSERT(2356, lss != NULL); -#ifdef IRO_DEBUG - lss->loc = NULL; - lss->otherLocs = NULL; - lss->count = 0; -#endif - return lss; -} - -CW_INLINE void LocationSetSet_Delete(LocationSetSet *lss) { - IRO_ASSERT(2369, lss != NULL); - IRO_ASSERT(2370, lss->loc == NULL); - IRO_ASSERT(2371, lss->otherLocs == NULL); - IRO_ASSERT(2372, lss->count == 0); - IRO_DEBUG_CLEAR(lss, sizeof(LocationSetSet)); - IRO_free(lss); -} - -CW_INLINE void LocationSetSet_Init(LocationSetSet *lss) { - IRO_ASSERT(2382, lss != NULL); - - lss->loc = NULL; - lss->otherLocs = NULL; - lss->count = 0; -} - -CW_INLINE void LocationSetSet_Copy(LocationSetSet *dest, LocationSetSet *src) { - IRO_ASSERT(2391, dest != NULL); - IRO_ASSERT(2392, src != NULL); - - dest->loc = NULL; - dest->otherLocs = NULL; - dest->count = 0; - LocationSetSet_AddSet(dest, src); -} - -CW_INLINE void LocationSetSet_Term(LocationSetSet *lss) { - IRO_ASSERT(2402, lss != NULL); - - LocationSetSet_RemoveAll(lss); - -#ifdef IRO_DEBUG - lss->loc = NULL; - lss->otherLocs = NULL; - lss->count = 0; -#endif -} - -CW_INLINE void LocationSetSet_ForEach(LocationSetSet *lss, void (*action)(LocationSet *, void *), void *refcon) { - IRO_ASSERT(2446, lss != NULL); - IRO_ASSERT(2447, action != NULL); - IRO_ASSERT(2448, refcon == NULL || refcon != NULL); - - while (lss && lss->loc) { - action(lss->loc, refcon); - lss = lss->otherLocs; - } -} - -CW_INLINE LocationSet *LocationSetSet_Find(LocationSetSet *lss, LocationSet *ls) { - IRO_ASSERT(2458, lss != NULL); - IRO_ASSERT(2459, ls != NULL); - - while (lss && lss->loc) { - if (LocationSets_Equal(lss->loc, ls)) - return lss->loc; - lss = lss->otherLocs; - } - - return NULL; -} - -CW_INLINE LocationSet *LocationSetSet_FindUnknown(LocationSetSet *lss) { - IRO_ASSERT(2470, lss != NULL); - - if (!lss->loc) - return stUnknownLs; - - while (lss && lss->loc) { - if (LocationSet_IsUnknown(lss->loc)) - return lss->loc; - lss = lss->otherLocs; - } - - return NULL; -} - -CW_INLINE LocationSet *LocationSetSet_FindFirst(LocationSetSet *lss) { - IRO_ASSERT(2498, lss != NULL); - - return lss->loc; -} - -CW_INLINE int LocationSetSet_Count(LocationSetSet *lss) { - IRO_ASSERT(2505, lss != NULL); - - return lss->count; -} - -CW_INLINE void LocationSetSet_RemoveAllWithMemoryBlock(LocationSetSet *lss, PAMemoryBlock *block) { - LocationSetSet *first; - LocationSetSet *prev; - LocationSetSet *next; - LocationSetSet *tmp; - - IRO_ASSERT(2514, lss != NULL); - IRO_ASSERT(2515, block != NULL); - - first = lss; - prev = NULL; - while (lss && lss->loc) { - next = lss->otherLocs; - if (MemoryBlocks_Equal(block, lss->loc->block)) { - if (lss->loc != stUnknownLs) { - LocationSet_Term(lss->loc); - LocationSet_Delete(lss->loc); - } - if (!prev) { - if (lss->otherLocs == NULL) { - lss->loc = NULL; - prev = lss; - } else { - tmp = lss->otherLocs; - lss->loc = lss->otherLocs->loc; - lss->otherLocs = lss->otherLocs->otherLocs; - tmp->loc = NULL; - tmp->otherLocs = NULL; - LocationSetSet_Term(tmp); - LocationSetSet_Delete(tmp); - prev = NULL; - next = lss; - } - } else { - prev->otherLocs = lss->otherLocs; - lss->loc = NULL; - lss->otherLocs = NULL; - LocationSetSet_Term(lss); - LocationSetSet_Delete(lss); - prev = lss; - } - first->count--; - } - lss = next; - } -} - -CW_INLINE void LocationSetSet_SimpleAdd(LocationSetSet *lss, LocationSet *ls) { - IRO_ASSERT(2572, lss != NULL); - IRO_ASSERT(2573, ls != NULL); - - if (!LocationSet_IsUnknown(ls) && lss->count < 4) { - LocationSet *ls2; - - if (ls == stUnknownLs) { - ls2 = stUnknownLs; - } else { - ls2 = LocationSet_New(); - LocationSet_Copy(ls2, ls); - } - - if (lss->loc) { - LocationSetSet *lss2 = LocationSetSet_New(); - LocationSetSet_Init(lss2); - lss2->loc = lss->loc; - lss2->otherLocs = lss->otherLocs; - lss->otherLocs = lss2; - } - - lss->loc = ls2; - lss->count++; - } else { - LocationSet *ls2; - - LocationSetSet_RemoveAll(lss); - ls2 = LocationSet_New(); - if (LocationSet_IsUnknown(ls)) { - LocationSet_Copy(ls2, ls); - } else { - LocationSet_Copy(ls2, stUnknownLs); - if (ls->rtype) - LocationSet_SetRtype(ls2, ls->rtype); - } - - lss->loc = ls2; - lss->count = 1; - } -} - -CW_INLINE void LocationSetSet_Add(LocationSetSet *lss, LocationSet *ls) { - IRO_ASSERT(2622, lss != NULL); - IRO_ASSERT(2623, ls != NULL); - - if (!lss->loc || (!LocationSet_IsUnknown(lss->loc) && !LocationSetSet_Find(lss, ls))) { - if (!LocationSet_IsUnknown(ls) && ls->u.known.stride) - LocationSetSet_RemoveAllWithMemoryBlock(lss, ls->block); - LocationSetSet_SimpleAdd(lss, ls); - } -} - -CW_INLINE void LocationSetSet_AddUnknown(LocationSetSet *lss, Type *rtype, PAMemoryBlock *restriction, LocationSet *bitfieldOf) { - LocationSet *ls; - - IRO_ASSERT(2643, lss != NULL); - IRO_ASSERT(2644, rtype == NULL || rtype != NULL); - IRO_ASSERT(2645, restriction == NULL || restriction != NULL); - IRO_ASSERT(2646, bitfieldOf == NULL || bitfieldOf != NULL); - - ls = LocationSet_New(); - LocationSet_InitUnknown(ls, rtype, restriction, bitfieldOf); - LocationSetSet_Add(lss, ls); - LocationSet_Term(ls); - LocationSet_Delete(ls); -} - -CW_INLINE void LocationSetSet_Remove(LocationSetSet *lss, LocationSet *ls) { - LocationSetSet *prev; - LocationSetSet *first; - LocationSetSet *tmp; - - IRO_ASSERT(2659, lss != NULL); - IRO_ASSERT(2660, ls != NULL); - - first = lss; - prev = NULL; - while (lss && lss->loc) { - if (LocationSets_Equal(lss->loc, ls)) { - if (lss->loc != stUnknownLs) { - LocationSet_Term(lss->loc); - LocationSet_Delete(lss->loc); - } - if (!prev) { - if (lss->otherLocs == NULL) { - lss->loc = NULL; - } else { - tmp = lss->otherLocs; - lss->loc = lss->otherLocs->loc; - lss->otherLocs = lss->otherLocs->otherLocs; - tmp->loc = NULL; - tmp->otherLocs = NULL; - LocationSetSet_Term(tmp); - LocationSetSet_Delete(tmp); - } - } else { - prev->otherLocs = lss->otherLocs; - lss->loc = NULL; - lss->otherLocs = NULL; - LocationSetSet_Term(lss); - LocationSetSet_Delete(lss); - } - first->count--; - return; - } - - prev = lss; - lss = lss->otherLocs; - } -} - -CW_INLINE void LocationSetSet_RemoveAll(LocationSetSet *lss) { - IRO_ASSERT(2707, lss != NULL); - - while (lss && lss->loc) - LocationSetSet_Remove(lss, lss->loc); -} - -CW_INLINE void LocationSetSet_AddSetAction(LocationSet *ls, void *refcon) { - IRO_ASSERT(2717, ls != NULL); - IRO_ASSERT(2718, refcon != NULL); - - LocationSetSet_Add((LocationSetSet *) refcon, ls); -} - -CW_INLINE void LocationSetSet_SimpleAddSetAction(LocationSet *ls, void *refcon) { - IRO_ASSERT(2725, ls != NULL); - IRO_ASSERT(2726, refcon != NULL); - - LocationSetSet_SimpleAdd((LocationSetSet *) refcon, ls); -} - -CW_INLINE void LocationSetSet_AddSet(LocationSetSet *dest, LocationSetSet *src) { - IRO_ASSERT(2733, dest != NULL); - IRO_ASSERT(2734, src != NULL); - - if (dest->count) - LocationSetSet_ForEach(src, LocationSetSet_AddSetAction, dest); - else - LocationSetSet_ForEach(src, LocationSetSet_SimpleAddSetAction, dest); -} - -CW_INLINE void LocationSetSet_RemoveSetAction(LocationSet *ls, void *refcon) { - IRO_ASSERT(2744, ls != NULL); - IRO_ASSERT(2745, refcon != NULL); - - LocationSetSet_Remove((LocationSetSet *) refcon, ls); -} - -CW_INLINE void LocationSetSet_sub_488700(LocationSetSet *dest, LocationSetSet *src) { - IRO_ASSERT(2752, dest != NULL); - IRO_ASSERT(2753, src != NULL); - - LocationSetSet_ForEach(src, LocationSetSet_RemoveSetAction, dest); -} - -CW_INLINE Boolean LocationSetSets_Equal(LocationSetSet *lss1, LocationSetSet *lss2) { - IRO_ASSERT(2826, lss1 != NULL); - IRO_ASSERT(2827, lss2 != NULL); - - if (lss1 == lss2) - return 1; - if (LocationSetSet_Count(lss1) != LocationSetSet_Count(lss2)) - return 0; - - while (lss1 && lss1->loc) { - if (!LocationSetSet_Find(lss2, lss1->loc)) - return 0; - lss1 = lss1->otherLocs; - } - - return 1; -} - -CW_INLINE ParamMapping *ParamMapping_New(void) { - ParamMapping *pm = IRO_malloc(sizeof(ParamMapping)); - - IRO_ASSERT(2885, pm != NULL); -#ifdef IRO_DEBUG - pm->actual = NULL; - pm->formal = NULL; - pm->extended = NULL; -#endif - return pm; -} - -CW_INLINE void ParamMapping_Delete(ParamMapping *pm) { - IRO_ASSERT(2898, pm != NULL); - IRO_ASSERT(2899, pm->actual == NULL); - IRO_ASSERT(2900, pm->formal == NULL); - IRO_ASSERT(2901, pm->extended == NULL); - IRO_DEBUG_CLEAR(pm, sizeof(ParamMapping)); - IRO_free(pm); -} - -CW_INLINE void ParamMapping_Init_PROBABLY(ParamMapping *pm, IROLinear *actual, Object *formal, ExtendedParam *extended) { - IRO_ASSERT(2911, pm != NULL); - - pm->actual = actual; - pm->formal = formal; - pm->extended = extended; -} - -CW_INLINE void ParamMapping_Copy(ParamMapping *dest, ParamMapping *src) { - IRO_ASSERT(2920, src != NULL); - IRO_ASSERT(2921, dest != NULL); - - dest->actual = src->actual; - dest->formal = src->formal; - dest->extended = src->extended; -} - -CW_INLINE void ParamMapping_Term(ParamMapping *pm) { - IRO_ASSERT(2933, pm != NULL); - -#ifdef IRO_DEBUG - pm->actual = NULL; - pm->formal = NULL; - pm->extended = NULL; -#endif -} - -CW_INLINE void ParamMapping_SetExtended(ParamMapping *pm, ExtendedParam *ep) { - IRO_ASSERT(2992, pm != NULL); - - pm->extended = ep; -} - -CW_INLINE IROLinear *ParamMapping_actual(ParamMapping *pm) { - IRO_ASSERT(2999, pm != NULL); - - return pm->actual; -} - -CW_INLINE ExtendedParam *ParamMapping_extended(ParamMapping *pm) { - IRO_ASSERT(3011, pm != NULL); - - return pm->extended; -} - -CW_INLINE ParamMappingFunction *ParamMappingFunction_New(void) { - ParamMappingFunction *pmf = IRO_malloc(sizeof(ParamMappingFunction)); - - IRO_ASSERT(3026, pmf != NULL); -#ifdef IRO_DEBUG - pmf->mapping = NULL; - pmf->otherMappings = NULL; -#endif - return pmf; -} - -CW_INLINE void ParamMappingFunction_Delete(ParamMappingFunction *pmf) { - IRO_ASSERT(3039, pmf != NULL); - IRO_ASSERT(3040, pmf->mapping == NULL); - IRO_ASSERT(3041, pmf->otherMappings == NULL); - IRO_DEBUG_CLEAR(pmf, sizeof(ParamMappingFunction)); - IRO_free(pmf); -} - -CW_INLINE void ParamMappingFunction_Init(ParamMappingFunction *pmf) { - IRO_ASSERT(3050, pmf != NULL); - - pmf->mapping = NULL; - pmf->otherMappings = NULL; -} - -CW_INLINE void ParamMappingFunction_Copy(ParamMappingFunction *dest, ParamMappingFunction *src) { - IRO_ASSERT(3058, src != NULL); - IRO_ASSERT(3059, dest != NULL); - - dest->mapping = NULL; - dest->otherMappings = NULL; - ParamMappingFunction_AddAllMaybe_sub_487C50(dest, src); -} - -CW_INLINE void ParamMappingFunction_Term(ParamMappingFunction *pmf) { - IRO_ASSERT(3068, pmf != NULL); - - ParamMappingFunction_RemoveAll(pmf); - -#ifdef IRO_DEBUG - pmf->mapping = NULL; - pmf->otherMappings = NULL; -#endif -} - -CW_INLINE void pmf_sub_487C70(ParamMappingFunction *pmf, void (*action)(ParamMapping *, void *), void *refcon) { - IRO_ASSERT(3111, pmf != NULL); - IRO_ASSERT(3112, action != NULL); - IRO_ASSERT(3113, refcon == NULL || refcon != NULL); - - while (pmf && pmf->mapping) { - action(pmf->mapping, refcon); - pmf = pmf->otherMappings; - } -} - -CW_INLINE ParamMapping *ParamMappingFunction_FindMappingByFormal(ParamMappingFunction *pmf, Object *formal) { - IRO_ASSERT(3123, pmf != NULL); - IRO_ASSERT(3124, formal != NULL); - - while (pmf && pmf->mapping) { - if (pmf->mapping->formal == formal) - return pmf->mapping; - pmf = pmf->otherMappings; - } - - return NULL; -} - -CW_INLINE void Pmf_Add_sub_486610(ParamMappingFunction *pmf, ParamMapping *mapping) { - ParamMapping *existing; - - IRO_ASSERT(3138, pmf != NULL); - IRO_ASSERT(3139, mapping != NULL); - - existing = ParamMappingFunction_FindMappingByFormal(pmf, mapping->formal); - if (!existing) { - existing = ParamMapping_New(); - ParamMapping_Copy(existing, mapping); - if (pmf->mapping) { - ParamMappingFunction *newPMF = ParamMappingFunction_New(); - ParamMappingFunction_Init(newPMF); - newPMF->mapping = pmf->mapping; - newPMF->otherMappings = pmf->otherMappings; - pmf->otherMappings = newPMF; - } - pmf->mapping = existing; - } else { - existing->actual = mapping->actual; - existing->extended = mapping->extended; - } -} - -CW_INLINE void ParamMappingFunction_Remove(ParamMappingFunction *pmf, ParamMapping *mapping) { - ParamMappingFunction *prev; - ParamMappingFunction *tmp; - - IRO_ASSERT(3170, pmf != NULL); - IRO_ASSERT(3171, mapping != NULL); - - prev = NULL; - while (pmf && pmf->mapping) { - if (pmf->mapping->formal == mapping->formal) { - ParamMapping_Term(pmf->mapping); - ParamMapping_Delete(pmf->mapping); - if (!prev) { - if (pmf->otherMappings == NULL) { - pmf->mapping = NULL; - } else { - tmp = pmf->otherMappings; - pmf->mapping = pmf->otherMappings->mapping; - pmf->otherMappings = pmf->otherMappings->otherMappings; - tmp->mapping = NULL; - tmp->otherMappings = NULL; - ParamMappingFunction_Term(tmp); - ParamMappingFunction_Delete(tmp); - } - } else { - prev->otherMappings = pmf->otherMappings; - pmf->mapping = NULL; - pmf->otherMappings = NULL; - ParamMappingFunction_Term(pmf); - ParamMappingFunction_Delete(pmf); - } - return; - } - - prev = pmf; - pmf = pmf->otherMappings; - } -} - -CW_INLINE void ParamMappingFunction_RemoveAll(ParamMappingFunction *pmf) { - IRO_ASSERT(3213, pmf != NULL); - - while (pmf && pmf->mapping) - ParamMappingFunction_Remove(pmf, pmf->mapping); -} - -CW_INLINE void ParamMappingFunction_AddFunctionAction(ParamMapping *mapping, void *refcon) { - IRO_ASSERT(3223, mapping != NULL); - IRO_ASSERT(3224, refcon != NULL); - - Pmf_Add_sub_486610((ParamMappingFunction *) refcon, mapping); -} - -CW_INLINE void ParamMappingFunction_AddAllMaybe_sub_487C50(ParamMappingFunction *dest, ParamMappingFunction *src) { - IRO_ASSERT(3231, dest != NULL); - IRO_ASSERT(3232, src != NULL); - - pmf_sub_487C70(src, ParamMappingFunction_AddFunctionAction, dest); -} - -CW_INLINE PointsToEntry *PointsToEntry_New(void) { - PointsToEntry *pte = IRO_malloc(sizeof(PointsToEntry)); - - IRO_ASSERT(3288, pte != NULL); -#ifdef IRO_DEBUG - pte->loc = NULL; - pte->locs = NULL; -#endif - return pte; -} - -CW_INLINE void PointsToEntry_Delete(PointsToEntry *pte) { - IRO_ASSERT(3300, pte != NULL); - IRO_ASSERT(3301, pte->loc == NULL); - IRO_ASSERT(3302, pte->locs == NULL); - IRO_DEBUG_CLEAR(pte, sizeof(PointsToEntry)); - IRO_free(pte); -} - -CW_INLINE void PointsToEntry_Init(PointsToEntry *pte, LocationSet *loc, LocationSetSet *locs) { - IRO_ASSERT(3312, pte != NULL); - IRO_ASSERT(3313, loc != NULL); - IRO_ASSERT(3314, !LocationSet_IsUnknown(loc)); - IRO_ASSERT(3315, locs != NULL); - - pte->loc = LocationSet_New(); - LocationSet_Copy(pte->loc, loc); - - pte->locs = LocationSetSet_New(); - LocationSetSet_Copy(pte->locs, locs); -} - -CW_INLINE void PointsToEntry_Copy(PointsToEntry *dest, PointsToEntry *src) { - IRO_ASSERT(3325, src != NULL); - IRO_ASSERT(3326, dest != NULL); - - PointsToEntry_Init(dest, src->loc, src->locs); -} - -CW_INLINE void PointsToEntry_Term(PointsToEntry *pte) { - IRO_ASSERT(3333, pte != NULL); - - LocationSet_Term(pte->loc); - LocationSet_Delete(pte->loc); - LocationSetSet_Term(pte->locs); - LocationSetSet_Delete(pte->locs); - -#ifdef IRO_DEBUG - pte->loc = NULL; - pte->locs = NULL; -#endif -} - -CW_INLINE Boolean PointsToEntries_Equal(PointsToEntry *pte1, PointsToEntry *pte2) { - IRO_ASSERT(3381, pte1 != NULL); - IRO_ASSERT(3382, pte2 != NULL); - - if (pte1 == pte2) - return 1; - - return LocationSets_Equal(pte1->loc, pte2->loc) && LocationSetSets_Equal(pte1->locs, pte2->locs); -} - -CW_INLINE LocationSet *PointsToEntry_loc(PointsToEntry *pte) { - IRO_ASSERT(3407, pte != NULL); - - return pte->loc; -} - -CW_INLINE LocationSetSet *PointsToEntry_locs(PointsToEntry *pte) { - IRO_ASSERT(3414, pte != NULL); - - return pte->locs; -} - -CW_INLINE PointsToFunction *PointsToFunction_New(void) { - PointsToFunction *pointsToFunc = IRO_malloc(sizeof(PointsToFunction)); - - IRO_ASSERT(3430, pointsToFunc != NULL); -#ifdef IRO_DEBUG - pointsToFunc->pte = NULL; - pointsToFunc->otherPtes = NULL; -#endif - return pointsToFunc; -} - -CW_INLINE void PointsToFunction_Delete(PointsToFunction *pointsToFunc) { - IRO_ASSERT(3442, pointsToFunc != NULL); - IRO_ASSERT(3443, pointsToFunc->pte == NULL); - IRO_ASSERT(3444, pointsToFunc->otherPtes == NULL); - IRO_DEBUG_CLEAR(pointsToFunc, sizeof(PointsToFunction)); - IRO_free(pointsToFunc); -} - -CW_INLINE void PointsToFunction_Init(PointsToFunction *pointsToFunc) { - IRO_ASSERT(3454, pointsToFunc != NULL); - - pointsToFunc->pte = NULL; - pointsToFunc->otherPtes = NULL; -} - -CW_INLINE void PointsToFunction_Copy(PointsToFunction *dest, PointsToFunction *src) { - IRO_ASSERT(3462, src != NULL); - IRO_ASSERT(3463, dest != NULL); - - dest->pte = NULL; - dest->otherPtes = NULL; - PointsToFunction_AddAllIGuess_sub_487D80(dest, src); -} - -CW_INLINE void PointsToFunction_Term(PointsToFunction *pointsToFunc) { - IRO_ASSERT(3472, pointsToFunc != NULL); - - PointsToFunction_RemoveAll(pointsToFunc); - -#ifdef IRO_DEBUG - pointsToFunc->pte = NULL; - pointsToFunc->otherPtes = NULL; -#endif -} - -CW_INLINE void PointsToFunction_ForEach(PointsToFunction *pointsToFunc, void (*action)(PointsToEntry *, void *), void *refcon) { - IRO_ASSERT(3515, pointsToFunc != NULL); - IRO_ASSERT(3516, action != NULL); - IRO_ASSERT(3517, refcon == NULL || refcon != NULL); - - while (pointsToFunc && pointsToFunc->pte) { - action(pointsToFunc->pte, refcon); - pointsToFunc = pointsToFunc->otherPtes; - } -} - -CW_INLINE PointsToEntry *PointsToFunction_FindByLocationSet(PointsToFunction *pointsToFunc, LocationSet *ls) { - IRO_ASSERT(3527, pointsToFunc != NULL); - IRO_ASSERT(3528, ls != NULL); - - while (pointsToFunc && pointsToFunc->pte) { - if (LocationSets_Equal(pointsToFunc->pte->loc, ls)) - return pointsToFunc->pte; - pointsToFunc = pointsToFunc->otherPtes; - } - - return NULL; -} - -CW_INLINE PointsToEntry *PointsToFunction_FindFirst(PointsToFunction *pointsToFunc) { - IRO_ASSERT(3539, pointsToFunc != NULL); - - return pointsToFunc->pte; -} - -CW_INLINE PointsToEntry *PointsToFunction_FindByLookupCompatibleLocationSet(PointsToFunction *pointsToFunc, LocationSet *ls) { - IRO_ASSERT(3546, pointsToFunc != NULL); - IRO_ASSERT(3547, ls != NULL); - - while (pointsToFunc && pointsToFunc->pte) { - if (ls->u.known.stride) { - if (LocationSets_Equal(pointsToFunc->pte->loc, ls)) - return pointsToFunc->pte; - } else if (LocationSets_LookupCompatible(pointsToFunc->pte->loc, ls)) { - return pointsToFunc->pte; - } - pointsToFunc = pointsToFunc->otherPtes; - } - - return NULL; -} - -CW_INLINE PointsToEntry *PointsToFunction_FindContainingLocationSet(PointsToFunction *pointsToFunc, LocationSet *ls, Type *rtype) { - IRO_ASSERT(3565, pointsToFunc != NULL); - IRO_ASSERT(3566, ls != NULL); - IRO_ASSERT(3567, rtype != NULL); - - while (pointsToFunc && pointsToFunc->pte) { - if (pointsToFunc->pte->locs->loc && !LocationSet_IsUnknown(pointsToFunc->pte->locs->loc)) { - if (!pointsToFunc->pte->locs->otherLocs && LocationSet_Contains(pointsToFunc->pte->loc, pointsToFunc->pte->locs->loc->rtype, ls, rtype)) - return pointsToFunc->pte; - } - pointsToFunc = pointsToFunc->otherPtes; - } - - return NULL; -} - -CW_INLINE void PointsToFunction_RemoveOverlappingLocations(PointsToFunction *pointsToFunc, PointsToEntry *pte) { - Type *rtype1; - Type *rtype2; - LocationSet *ls; - PointsToFunction *prev; - PointsToFunction *next; - PointsToFunction *tmp; - - IRO_ASSERT(3601, pointsToFunc != NULL); - IRO_ASSERT(3602, pte != NULL); - IRO_ASSERT(3603, pte->locs != NULL); - - if (pte->locs->loc && pte->locs->loc != stUnknownLs) - rtype1 = pte->locs->loc->rtype; - else - rtype1 = NULL; - ls = pte->loc; - IRO_ASSERT(3614, ls != NULL); - - prev = NULL; - while (pointsToFunc && pointsToFunc->pte) { - next = pointsToFunc->otherPtes; - if (pointsToFunc->pte->locs->loc && pointsToFunc->pte->locs->loc != stUnknownLs) - rtype2 = pointsToFunc->pte->locs->loc->rtype; - else - rtype2 = NULL; - - if (LocationSets_Overlap(ls, rtype1, pointsToFunc->pte->loc, rtype2)) { - PointsToEntry_Term(pointsToFunc->pte); - PointsToEntry_Delete(pointsToFunc->pte); - if (!prev) { - if (pointsToFunc->otherPtes == NULL) { - pointsToFunc->pte = NULL; - prev = pointsToFunc; - } else { - tmp = pointsToFunc->otherPtes; - pointsToFunc->pte = pointsToFunc->otherPtes->pte; - pointsToFunc->otherPtes = pointsToFunc->otherPtes->otherPtes; - tmp->pte = NULL; - tmp->otherPtes = NULL; - PointsToFunction_Term(tmp); - PointsToFunction_Delete(tmp); - prev = NULL; - next = pointsToFunc; - } - } else { - prev->otherPtes = pointsToFunc->otherPtes; - pointsToFunc->pte = NULL; - pointsToFunc->otherPtes = NULL; - PointsToFunction_Term(pointsToFunc); - PointsToFunction_Delete(pointsToFunc); - prev = pointsToFunc; - } - } - - pointsToFunc = next; - } -} - -CW_INLINE Boolean ShouldAddNewPointsToEntryToFunction(PointsToFunction *pointsToFunc, PointsToEntry *pte) { - Boolean flag; - Boolean isKnown; - SInt32 stride; - PointsToFunction *next; - LocationSet *loc; - LocationSet *loc2; - Type *rtype1; - Type *rtype2; - LocationSetSet *locs2; - LocationSet *tmp; - LocationSet *unknown; - Boolean flag2; - Boolean flag3; - - IRO_ASSERT(3675, pointsToFunc != NULL); - IRO_ASSERT(3676, pte != NULL); - IRO_ASSERT(3677, pte->locs != NULL); - IRO_ASSERT(3678, PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, pte->loc) == NULL); - IRO_ASSERT(3679, (unknown = LocationSetSet_FindFirst(pte->locs)) != NULL); - IRO_ASSERT(3680, LocationSet_IsUnknown(unknown)); - IRO_ASSERT(3681, LocationSet_bitfieldOf(unknown) == NULL); - IRO_ASSERT(3682, LocationSet_restriction(unknown) == NULL); - - if (pte->locs->loc && pte->locs->loc != stUnknownLs) - rtype1 = pte->locs->loc->rtype; - else - rtype1 = NULL; - - loc = pte->loc; - IRO_ASSERT(3693, loc != NULL); - - isKnown = !LocationSet_IsUnknown(loc); - if (isKnown) - stride = LocationSet_stride(loc); - - flag = 0; - while (pointsToFunc && pointsToFunc->pte) { - next = pointsToFunc->otherPtes; - - locs2 = pointsToFunc->pte->locs; - - if (locs2->loc && locs2->loc != stUnknownLs) - rtype2 = locs2->loc->rtype; - else - rtype2 = NULL; - - loc2 = pointsToFunc->pte->loc; - - flag2 = !(tmp = LocationSetSet_FindFirst(locs2)) || - !LocationSet_IsUnknown(tmp) || - LocationSet_bitfieldOf(tmp) || - LocationSet_restriction(tmp); - - flag3 = LocationSets_Overlap(loc, rtype1, loc2, rtype2); - - if (!flag && flag3) - flag = 1; - - if (flag3 && (flag2 || (isKnown && stride && LocationSet_stride(loc2) == 0))) - return 1; - - pointsToFunc = next; - } - - return !flag; -} - -CW_INLINE Boolean PointsToFunction_SimpleAdd(PointsToFunction *pointsToFunc, PointsToEntry *pte) { - PointsToEntry *newPTE; - - IRO_ASSERT(3741, pointsToFunc != NULL); - IRO_ASSERT(3742, pte != NULL); - - newPTE = PointsToEntry_New(); - PointsToEntry_Copy(newPTE, pte); - if (pointsToFunc->pte) { - PointsToFunction *newPointsToFunc = PointsToFunction_New(); - PointsToFunction_Init(newPointsToFunc); - newPointsToFunc->pte = pointsToFunc->pte; - newPointsToFunc->otherPtes = pointsToFunc->otherPtes; - pointsToFunc->otherPtes = newPointsToFunc; - } - pointsToFunc->pte = newPTE; - return 1; -} - -CW_INLINE Boolean PointsToFunction_Add(PointsToFunction *pointsToFunc, PointsToEntry *pte) { - IRO_ASSERT(3766, pointsToFunc != NULL); - IRO_ASSERT(3767, pte != NULL); - - if (!PointsToFunction_FindByLookupCompatibleLocationSet(pointsToFunc, pte->loc)) { - LocationSet *ls; - if (!(ls = LocationSetSet_FindFirst(pte->locs)) || !LocationSet_IsUnknown(ls) || LocationSet_bitfieldOf(ls) || - LocationSet_restriction(ls) || ShouldAddNewPointsToEntryToFunction(pointsToFunc, pte)) { - PointsToFunction_RemoveOverlappingLocations(pointsToFunc, pte); - if (!LocationSet_IsUnknown(pte->loc) || pte->loc->rtype) - PointsToFunction_SimpleAdd(pointsToFunc, pte); - return 1; - } - } - - return 0; -} - -CW_INLINE Boolean PointsToFunction_AddWithoutChecking(PointsToFunction *pointsToFunc, PointsToEntry *pte) { - LocationSet *ls; - - IRO_ASSERT(3793, pointsToFunc != NULL); - IRO_ASSERT(3794, pte != NULL); - - if (!(ls = LocationSetSet_FindFirst(pte->locs)) || !LocationSet_IsUnknown(ls) || LocationSet_bitfieldOf(ls) || - LocationSet_restriction(ls) || ShouldAddNewPointsToEntryToFunction(pointsToFunc, pte)) { - PointsToFunction_RemoveOverlappingLocations(pointsToFunc, pte); - if (!LocationSet_IsUnknown(pte->loc) || pte->loc->rtype) - PointsToFunction_SimpleAdd(pointsToFunc, pte); - return 1; - } - - return 0; -} - -CW_INLINE void PointsToFunction_RemoveByLocationSet(PointsToFunction *pointsToFunc, LocationSet *ls) { - PointsToFunction *prev; - PointsToFunction *tmp; - - IRO_ASSERT(3818, pointsToFunc != NULL); - IRO_ASSERT(3819, ls != NULL); - IRO_ASSERT(3820, !LocationSet_IsUnknown(ls)); - - prev = NULL; - while (pointsToFunc && pointsToFunc->pte) { - if (LocationSets_Equal(pointsToFunc->pte->loc, ls)) { - PointsToEntry_Term(pointsToFunc->pte); - PointsToEntry_Delete(pointsToFunc->pte); - if (!prev) { - if (pointsToFunc->otherPtes == NULL) { - pointsToFunc->pte = NULL; - } else { - tmp = pointsToFunc->otherPtes; - pointsToFunc->pte = pointsToFunc->otherPtes->pte; - pointsToFunc->otherPtes = pointsToFunc->otherPtes->otherPtes; - tmp->pte = NULL; - tmp->otherPtes = NULL; - PointsToFunction_Term(tmp); - PointsToFunction_Delete(tmp); - } - } else { - prev->otherPtes = pointsToFunc->otherPtes; - pointsToFunc->pte = NULL; - pointsToFunc->otherPtes = NULL; - PointsToFunction_Term(pointsToFunc); - PointsToFunction_Delete(pointsToFunc); - } - return; - } - - prev = pointsToFunc; - pointsToFunc = pointsToFunc->otherPtes; - } -} - -CW_INLINE void PointsToFunction_RemoveAll(PointsToFunction *pointsToFunc) { - IRO_ASSERT(3862, pointsToFunc != NULL); - - while (pointsToFunc && pointsToFunc->pte) - PointsToFunction_RemoveByLocationSet(pointsToFunc, pointsToFunc->pte->loc); -} - -CW_INLINE void PointsToFunction_AddFunctionAction(PointsToEntry *pte, void *refcon) { - IRO_ASSERT(3872, pte != NULL); - IRO_ASSERT(3873, refcon != NULL); - - PointsToFunction_Add((PointsToFunction *) refcon, pte); -} - -CW_INLINE void PointsToFunction_SimpleAddFunctionAction(PointsToEntry *pte, void *refcon) { - IRO_ASSERT(3880, pte != NULL); - IRO_ASSERT(3881, refcon != NULL); - - PointsToFunction_SimpleAdd((PointsToFunction *) refcon, pte); -} - -CW_INLINE void PointsToFunction_AddAllIGuess_sub_487D80(PointsToFunction *dest, PointsToFunction *src) { - IRO_ASSERT(3888, dest != NULL); - IRO_ASSERT(3889, src != NULL); - - if (dest->pte) - PointsToFunction_ForEach(src, PointsToFunction_AddFunctionAction, dest); - else - PointsToFunction_ForEach(src, PointsToFunction_SimpleAddFunctionAction, dest); -} - -CW_INLINE void PointsToFunction_SortByExtendedParamNum(PointsToFunction *pointsToFunc) { - UInt32 value1; - UInt32 value2; - PointsToFunction *scan; - - while (pointsToFunc && pointsToFunc->pte) { - value1 = 0; - if (pointsToFunc->pte->loc && pointsToFunc->pte->loc->block) { - PAMemoryBlock *block = pointsToFunc->pte->loc->block; - if (block->kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM && block->u.ep) { - value1 = 2 * (block->u.ep->x4) + 1; - } else if (block->kind == PAMEMORYBLOCKKIND_LOCALVAR && block->u.localvar) { - if (block->u.localvar->x0 && block->u.localvar->x0->extParam) - value1 = 2 * block->u.localvar->x0->extParam->x4; - } - } - - for (scan = pointsToFunc->otherPtes; scan && scan->pte; scan = scan->otherPtes) { - value2 = 0; - if (scan->pte->loc && scan->pte->loc->block) { - PAMemoryBlock *block = scan->pte->loc->block; - if (block->kind == PAMEMORYBLOCKKIND_EXTENDEDPARAM && block->u.ep) { - value2 = 2 * (block->u.ep->x4) + 1; - } else if (block->kind == PAMEMORYBLOCKKIND_LOCALVAR && block->u.localvar) { - if (block->u.localvar->x0 && block->u.localvar->x0->extParam) - value2 = 2 * block->u.localvar->x0->extParam->x4; - } - } - - if (value2 < value1) { - LocationSet *saveloc; - LocationSetSet *savelocs; - saveloc = pointsToFunc->pte->loc; - savelocs = pointsToFunc->pte->locs; - pointsToFunc->pte->loc = scan->pte->loc; - pointsToFunc->pte->locs = scan->pte->locs; - scan->pte->loc = saveloc; - scan->pte->locs = savelocs; - } - } - - pointsToFunc = pointsToFunc->otherPtes; - } -} - -CW_INLINE Boolean PointsToFunctions_Equal(PointsToFunction *pointsToFunc1, PointsToFunction *pointsToFunc2) { - PointsToFunction *scan; - PointsToEntry *pte; - - IRO_ASSERT(3968, pointsToFunc1 != NULL); - IRO_ASSERT(3969, pointsToFunc2 != NULL); - - if (pointsToFunc1 == pointsToFunc2) - return 1; - - for (scan = pointsToFunc1; scan && scan->pte; scan = scan->otherPtes) { - pte = PointsToFunction_FindByLocationSet(pointsToFunc2, scan->pte->loc); - if (!pte || !PointsToEntries_Equal(pte, scan->pte)) - return 0; - } - - for (scan = pointsToFunc2; scan && scan->pte; scan = scan->otherPtes) { - pte = PointsToFunction_FindByLocationSet(pointsToFunc1, scan->pte->loc); - if (!pte || !PointsToEntries_Equal(pte, scan->pte)) - return 0; - } - - return 1; -} - -CW_INLINE Boolean PointsToFunctions_Match(PointsToFunction *pointsToFunc1, PointsToFunction *pointsToFunc2) { - return 1; -} - -CW_INLINE PartialTransferFunction *PartialTransferFunction_New(void) { - PartialTransferFunction *ptf = IRO_malloc(sizeof(PartialTransferFunction)); - - IRO_ASSERT(4110, ptf != NULL); -#ifdef IRO_DEBUG - ptf->initialPointsToFn = NULL; - ptf->finalPointsToFn = NULL; - ptf->funcModifies = NULL; - ptf->context.nd = NULL; - ptf->context.ptf = NULL; - ptf->returnLocation = NULL; -#endif - return ptf; -} - -CW_INLINE void PartialTransferFunction_Delete(PartialTransferFunction *ptf) { - IRO_ASSERT(4126, ptf != NULL); - IRO_ASSERT(4127, ptf->initialPointsToFn == NULL); - IRO_ASSERT(4128, ptf->finalPointsToFn == NULL); - IRO_ASSERT(4129, ptf->funcModifies == NULL); - IRO_ASSERT(4130, ptf->context.nd == NULL); - IRO_ASSERT(4131, ptf->context.ptf == NULL); - IRO_ASSERT(4132, ptf->returnLocation == NULL); - IRO_DEBUG_CLEAR(ptf, sizeof(PartialTransferFunction)); - IRO_free(ptf); -} - -CW_INLINE void PartialTransferFunction_Init(PartialTransferFunction *ptf, IROLinear *contextNd, PartialTransferFunction *contextPTF) { - IRO_ASSERT(4142, ptf != NULL); - IRO_ASSERT(4143, contextNd != NULL); - IRO_ASSERT(4144, contextPTF != NULL); - - ptf->initialPointsToFn = PointsToFunction_New(); - PointsToFunction_Init(ptf->initialPointsToFn); - ptf->finalPointsToFn = PointsToFunction_New(); - PointsToFunction_Init(ptf->finalPointsToFn); - - ptf->funcModifies = LocationSetSet_New(); - LocationSetSet_Init(ptf->funcModifies); - LocationSetSet_AddUnknown(ptf->funcModifies, NULL, NULL, NULL); - - ptf->returnLocation = NULL; - ptf->x10 = 0; - - ptf->context.nd = contextNd; - ptf->context.ptf = contextPTF; -} - -CW_INLINE void PartialTransferFunction_Copy(PartialTransferFunction *dest, PartialTransferFunction *src) { - IRO_ASSERT(4164, src != NULL); - IRO_ASSERT(4165, dest != NULL); - - dest->initialPointsToFn = PointsToFunction_New(); - PointsToFunction_Copy(dest->initialPointsToFn, src->initialPointsToFn); - dest->finalPointsToFn = PointsToFunction_New(); - PointsToFunction_Copy(dest->finalPointsToFn, src->finalPointsToFn); - - dest->funcModifies = LocationSetSet_New(); - LocationSetSet_Copy(dest->funcModifies, src->funcModifies); - - if (src->returnLocation) { - dest->returnLocation = LocationSet_New(); - LocationSet_Copy(dest->returnLocation, src->returnLocation); - } else { - dest->returnLocation = NULL; - } - - dest->x10 = src->x10; - dest->context = src->context; -} - -CW_INLINE void PartialTransferFunction_Term(PartialTransferFunction *ptf) { - IRO_ASSERT(4190, ptf != NULL); - - PointsToFunction_Term(ptf->initialPointsToFn); - PointsToFunction_Delete(ptf->initialPointsToFn); - PointsToFunction_Term(ptf->finalPointsToFn); - PointsToFunction_Delete(ptf->finalPointsToFn); - LocationSetSet_Term(ptf->funcModifies); - LocationSetSet_Delete(ptf->funcModifies); - - if (ptf->returnLocation) { - PAMemoryBlock_Term(ptf->returnLocation->block); - PAMemoryBlock_Delete(ptf->returnLocation->block); - LocationSet_Term(ptf->returnLocation); - LocationSet_Delete(ptf->returnLocation); - ptf->returnLocation = NULL; - } - -#ifdef IRO_DEBUG - ptf->initialPointsToFn = NULL; - ptf->finalPointsToFn = NULL; - ptf->funcModifies = NULL; - ptf->context.nd = NULL; - ptf->context.ptf = NULL; -#endif -} - -CW_INLINE PointsToFunction *PartialTransferFunction_initialPointsToFn(PartialTransferFunction *ptf) { - IRO_ASSERT(4221, ptf != NULL); - - return ptf->initialPointsToFn; -} - -CW_INLINE PointsToFunction *PartialTransferFunction_finalPointsToFn(PartialTransferFunction *ptf) { - IRO_ASSERT(4227, ptf != NULL); - - return ptf->finalPointsToFn; -} - -CW_INLINE LocationSetSet *PTF_sub_48D750(PartialTransferFunction *ptf) { - IRO_ASSERT(4233, ptf != NULL); - - return ptf->funcModifies; -} - -CW_INLINE LocationSet *PartialTransferFunction_returnLocation(PartialTransferFunction *ptf) { - IRO_ASSERT(4249, ptf != NULL); - - if (!ptf->returnLocation) { - PAMemoryBlock *block; - LocationSet *ls; - - block = PAMemoryBlock_New(); - PAMemoryBlock_Init(block, PAMEMORYBLOCKKIND_LOCALVAR, NULL); - ls = LocationSet_New(); - LocationSet_InitKnown(ls, block, cint64_zero, 0, TYPE(&void_ptr)); - ptf->returnLocation = ls; - } - - return ptf->returnLocation; -} - -CW_INLINE IROLinear *PTF_sub_48B980(PartialTransferFunction *ptf) { - IRO_ASSERT(4265, ptf != NULL); - - return ptf->context.nd; -} - -CW_INLINE PartialTransferFunction *PTF_sub_48B970(PartialTransferFunction *ptf) { - IRO_ASSERT(4271, ptf != NULL); - - return ptf->context.ptf; -} - -CW_INLINE void PartialTransferFunction_sub_48A610(PartialTransferFunction *ptf, Boolean value) { - IRO_ASSERT(4298, ptf != NULL); - - ptf->x10 = (value != 0) ? 1 : 0; -} - -CW_INLINE PTFList *PTFList_New(void) { - PTFList *ptfList = IRO_malloc(sizeof(PTFList)); - - IRO_ASSERT(4393, ptfList != NULL); -#ifdef IRO_DEBUG - ptfList->ptf = NULL; - ptfList->otherPTFs = NULL; -#endif - return ptfList; -} - -CW_INLINE void PTFList_Delete(PTFList *ptfList) { - IRO_ASSERT(4405, ptfList != NULL); - IRO_ASSERT(4406, ptfList->ptf == NULL); - IRO_ASSERT(4407, ptfList->otherPTFs == NULL); - IRO_DEBUG_CLEAR(ptfList, sizeof(PTFList)); - IRO_free(ptfList); -} - -CW_INLINE void PTFList_Init(PTFList *ptfList) { - IRO_ASSERT(4417, ptfList != NULL); - - ptfList->ptf = NULL; - ptfList->otherPTFs = NULL; -} - -CW_INLINE void PTFList_Term(PTFList *ptfList) { - IRO_ASSERT(4435, ptfList != NULL); - - PTFList_RemoveAll(ptfList); - -#ifdef IRO_DEBUG - ptfList->ptf = NULL; - ptfList->otherPTFs = NULL; -#endif -} - -CW_INLINE void PTFList_ForEach(PTFList *ptfList, void (*action)(PartialTransferFunction *, void *), void *refcon) { - IRO_ASSERT(4478, ptfList != NULL); - IRO_ASSERT(4479, action != NULL); - IRO_ASSERT(4480, refcon == NULL || refcon != NULL); - - while (ptfList && ptfList->ptf) { - action(ptfList->ptf, refcon); - ptfList = ptfList->otherPTFs; - } -} - -CW_INLINE PartialTransferFunction *PTFList_sub_48A0F0(PTFList *ptfList, PartialTransferFunction *ptf) { - IRO_ASSERT(4490, ptfList != NULL); - IRO_ASSERT(4491, ptf != NULL); - - while (ptfList && ptfList->ptf) { - if (ptfList->ptf == ptf) - return ptfList->ptf; - - ptfList = ptfList->otherPTFs; - } - - return NULL; -} - -CW_INLINE PartialTransferFunction *PTFList_FindFirst(PTFList *ptfList) { - IRO_ASSERT(4502, ptfList != NULL); - - return ptfList->ptf; -} - -CW_INLINE void PTFList_sub_48A080(PTFList *ptfList, PartialTransferFunction *ptf) { - IRO_ASSERT(4511, ptfList != NULL); - IRO_ASSERT(4512, ptf != NULL); - - if (ptfList->ptf) { - PTFList *newList = PTFList_New(); - PTFList_Init(newList); - newList->ptf = ptfList->ptf; - newList->otherPTFs = ptfList->otherPTFs; - ptfList->otherPTFs = newList; - } - - ptfList->ptf = ptf; -} - -CW_INLINE void PTFList_sub_48A050(PTFList *ptfList, PartialTransferFunction *ptf) { - IRO_ASSERT(4529, ptfList != NULL); - IRO_ASSERT(4530, ptf != NULL); - - if (!PTFList_sub_48A0F0(ptfList, ptf)) - PTFList_sub_48A080(ptfList, ptf); -} - -CW_INLINE void PTFList_Remove(PTFList *ptfList, PartialTransferFunction *ptf) { - PTFList *prev; - PTFList *tmp; - - IRO_ASSERT(4542, ptfList != NULL); - IRO_ASSERT(4543, ptf != NULL); - - prev = NULL; - while (ptfList && ptfList->ptf) { - if (ptfList->ptf == ptf) { - if (!prev) { - if (ptfList->otherPTFs == NULL) { - ptfList->ptf = NULL; - } else { - tmp = ptfList->otherPTFs; - ptfList->ptf = ptfList->otherPTFs->ptf; - ptfList->otherPTFs = ptfList->otherPTFs->otherPTFs; - tmp->ptf = NULL; - tmp->otherPTFs = NULL; - PTFList_Term(tmp); - PTFList_Delete(tmp); - } - } else { - prev->otherPTFs = ptfList->otherPTFs; - ptfList->ptf = NULL; - ptfList->otherPTFs = NULL; - PTFList_Term(ptfList); - PTFList_Delete(ptfList); - } - return; - } - - prev = ptfList; - ptfList = ptfList->otherPTFs; - } -} - -CW_INLINE void PTFList_RemoveAll(PTFList *ptfList) { - IRO_ASSERT(4582, ptfList != NULL); - - while (ptfList && ptfList->ptf) - PTFList_Remove(ptfList, ptfList->ptf); -} diff --git a/compiler_and_linker/unsorted/IroPropagate.c b/compiler_and_linker/unsorted/IroPropagate.c deleted file mode 100644 index 401250c..0000000 --- a/compiler_and_linker/unsorted/IroPropagate.c +++ /dev/null @@ -1,593 +0,0 @@ -#include "compiler/IroPropagate.h" -#include "compiler/IroCSE.h" -#include "compiler/IroDump.h" -#include "compiler/IroEval.h" -#include "compiler/IroFlowgraph.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IROUseDef.h" -#include "compiler/IroUtil.h" -#include "compiler/IroVars.h" -#include "compiler/objects.h" -#include "compiler/CExpr.h" -#include "compiler/CompilerTools.h" -#include "compiler/CParser.h" -#include "compiler/InlineAsm.h" -#include "compiler/InlineAsmPPC.h" - -IROAssign *IRO_FirstAssign; -IROAssign *IRO_LastAssign; -SInt32 IRO_NumAssign; - -static Boolean VarIsUsedInOtherFNodes(VarRecord *var, IRONode *node) { - if (var->defs && var->uses) { - IROUse *use; - IRODef *def = NULL; - for (use = var->uses; use; use = use->varnext) { - if (!def && use->node == node && use->linear && !(use->linear->flags & IROLF_Assigned)) { - for (def = var->defs; def; def = def->varnext) { - if (Bv_IsBitSet(def->index, use->x18)) - break; - } - } - } - - if (def) { - for (use = var->uses; use; use = use->varnext) { - if (use->node != node && use->linear && !(use->linear->flags & IROLF_Assigned)) { - if (Bv_IsBitSet(def->index, use->x18)) - return 1; - } - } - } - } else { - IROLinear *linear; - IRONode *scan; - for (scan = IRO_FirstNode; scan; scan = scan->nextnode) { - if (scan != node) { - linear = scan->first; - while (1) { - if (!linear) - break; - - if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) { - if (IRO_FindVar(linear->u.diadic.left->u.node->data.objref, 0, 1) == var) - return 1; - } - - if (linear == scan->last) - break; - linear = linear->next; - } - } - } - IRO_CheckForUserBreak(); - } - - return 0; -} - -static void GetExprUses(IROLinear *linear, Boolean isFirst) { - if (isFirst && IS_LINEAR_ENODE(linear, EOBJREF)) { - Object *obj = linear->u.node->data.objref; - if ((linear->flags & IROLF_Ind) && (!(linear->flags & IROLF_Assigned) || (linear->flags & IROLF_Used))) { - VarRecord *var = IRO_FindVar(obj, 0, 1); - if (var) - Bv_SetBit(var->index, IRO_VarKills); - } - } -} - -static void GetExprKills(IROLinear *linear, Boolean isFirst) { - if (isFirst) - IRO_GetKills(linear); -} - -static void CheckUnorderedRegionForDefs(IROLinear *linear, BitVector *a, BitVector *b, Boolean *flag) { - Bv_Clear(a); - Bv_Clear(IRO_VarKills); - IRO_WalkTree(linear, GetExprKills); - Bv_Or(IRO_VarKills, a); - if (Bv_BitsInCommon(a, b)) - *flag = 1; -} - -static void CheckUnorderedRegionsForDefs(IROLinear *linear1, IROLinear *linear2, BitVector *a, BitVector *b, Boolean *flag) { - int i; - - switch (linear1->type) { - case IROLinearOp2Arg: - if (linear1->nodetype == ELAND) break; - if (linear1->nodetype == ELOR) break; - if (linear1->nodetype == ECOMMA) break; - if (linear1->u.diadic.left != linear2) - CheckUnorderedRegionForDefs(linear1->u.diadic.left, a, b, flag); - if (linear1->u.diadic.right != linear2) - CheckUnorderedRegionForDefs(linear1->u.diadic.right, a, b, flag); - break; - case IROLinearFunccall: - if (linear1->u.funccall.linear8 != linear2) - CheckUnorderedRegionForDefs(linear1->u.funccall.linear8, a, b, flag); - for (i = 0; !*flag && i < linear1->u.funccall.argCount; i++) { - if (linear1->u.funccall.args[i] != linear2) - CheckUnorderedRegionForDefs(linear1->u.funccall.args[i], a, b, flag); - } - break; - } -} - -static Boolean PropagationHasDefsInUnorderedRegions(IROLinear *a, IROLinear *b) { - Boolean flag; - IROLinear *father; - BitVector *bv1; - BitVector *bv2; - VarRecord *var; - - flag = 0; - if ((father = IRO_LocateFather(a))) { - Bv_AllocVector(&bv1, IRO_NumVars + 1); - Bv_AllocVector(&bv2, IRO_NumVars + 1); - Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); - IRO_WalkTree(b, GetExprUses); - Bv_Or(IRO_VarKills, bv2); - var = IRO_FindVar(a->u.diadic.left->u.node->data.objref, 0, 1); - Bv_SetBit(var->index, bv2); - while (father && !flag) { - CheckUnorderedRegionsForDefs(father, a, bv1, bv2, &flag); - a = father; - father = IRO_LocateFather(father); - } - } - - return flag; -} - -int IRO_IsRegable(Object *obj) { - if (obj->datatype == DLOCAL && obj->u.var.info) - return obj->u.var.info->noregister == 0; - return 0; -} - -static Boolean IsPropagatable(IROLinear *linear) { - Object *obj; - Object *obj2; - - if (IS_LINEAR_DIADIC(linear, EASS) && (obj = IRO_IsVariable(linear->u.diadic.left)) && obj->type == linear->rtype && !is_volatile_object(obj)) { - if (linear->u.diadic.left->flags & IROLF_BitfieldIndirect) { - if (!IRO_IsConstant(linear->u.diadic.right)) - return 0; - else - return 1; - } - - if (IRO_IsConstant(linear->u.diadic.right)) - return 1; - - if ((obj2 = IRO_IsVariable(linear->u.diadic.right)) && !is_volatile_object(obj2) && IRO_TypesEqual(obj->type, linear->rtype)) { - if (!Inline_IsObjectData(linear->u.diadic.right->u.monadic->u.node->data.objref)) { - if (IRO_IsRegable(obj) && !IRO_IsRegable(obj2)) - return 0; - return 1; - } - } - } - - return 0; -} - -static Boolean IsIntGenKillCandidate(IROLinear *linear) { - if (linear->type == IROLinearFunccall) - return 1; - - if (IRO_IsAssignOp[linear->nodetype] && (linear->type == IROLinearOp1Arg || linear->type == IROLinearOp2Arg)) - return 1; - - if (linear->type == IROLinearAsm) - return 1; - - return 0; -} - -static Boolean IsPropagatableExpr(IROLinear *linear, IROList *list) { - Object *obj; - if (IS_LINEAR_DIADIC(linear, EASS) && !(linear->flags & IROLF_Reffed)) { - if ((obj = IRO_IsVariable(linear->u.diadic.left)) && !is_volatile_object(obj) && !(linear->u.diadic.left->flags & IROLF_BitfieldIndirect)) { - if (!IRO_IsRegable(obj)) - return 0; - if (IS_LINEAR_ENODE(linear->u.diadic.right, ESTRINGCONST)) - return 0; - - IRO_FindDepends(linear->u.diadic.right); - if (!IRO_NotSubable) - return 1; - } - } - - return 0; -} - -static void ClearAvailibilityOnNode(IRONode *node, UInt32 bit) { - IRONode *scan; - - for (scan = node->nextnode; scan; scan = scan->nextnode) - Bv_ClearBit(bit, scan->x16); -} - -Boolean IRO_CopyAndConstantPropagation(void) { - IROAssign *ass2; - IROAssign *ass; - IROLinear *linear; - IRONode *node; - VarRecord *var; - BitVector *bv; - Boolean flag; - Boolean result; - - IRO_FirstAssign = NULL; - IRO_NumAssign = 0; - result = 0; - - for (node = IRO_FirstNode; node; node = node->nextnode) { - linear = node->first; - while (1) { - if (!linear) - break; - - if (IsPropagatable(linear) && (var = IRO_FindAssigned(linear))) { - IROAssign *newass; - IRO_Dump("Found propagatable assignment at: %d\n", linear->index); - newass = oalloc(sizeof(IROAssign)); - newass->linear = linear; - newass->next = NULL; - newass->index = ++IRO_NumAssign; - newass->varIndex = var->index; - newass->linear2 = linear->u.diadic.right; - newass->var = NULL; - newass->varObj = IRO_IsVariable(linear->u.diadic.right); - newass->node = node; - if (newass->varObj) - newass->var = IRO_FindVar(newass->varObj, 0, 1); - if (!IRO_FirstAssign) - IRO_FirstAssign = newass; - else - IRO_LastAssign->next = newass; - IRO_LastAssign = newass; - } - - if (linear == node->last) - break; - linear = linear->next; - } - } - - IRO_CheckForUserBreak(); - - node = IRO_FirstNode; - ass = IRO_FirstAssign; - Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); - while (node) { - Bv_AllocVector(&node->x16, IRO_NumAssign); - if (node != IRO_FirstNode) - Bv_Set(node->x16); - Bv_AllocVector(&node->x22, IRO_NumAssign); - Bv_AllocVector(&node->x1E, IRO_NumAssign); - Bv_AllocVector(&node->x2A, IRO_NumAssign); - node->x1A = NULL; - - linear = node->first; - while (1) { - if (!linear) - break; - - if (IsIntGenKillCandidate(linear)) { - //IROAssign *ass2; - Bv_Clear(IRO_VarKills); - IRO_GetKills(linear); - - for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) { - if (Bv_IsBitSet(ass2->varIndex, IRO_VarKills)) { - Bv_SetBit(ass2->index, node->x22); - Bv_ClearBit(ass2->index, node->x1E); - } - if (ass2->var && Bv_IsBitSet(ass2->var->index, IRO_VarKills)) { - Bv_SetBit(ass2->index, node->x22); - Bv_ClearBit(ass2->index, node->x1E); - } - } - } - - while (ass && ass->linear == linear) { - Bv_SetBit(ass->index, node->x1E); - ass = ass->next; - } - - if (linear == node->last) - break; - linear = linear->next; - } - - Bv_Copy(node->x16, node->x2A); - Bv_Minus(node->x22, node->x2A); - Bv_Or(node->x1E, node->x2A); - node = node->nextnode; - } - - IRO_CheckForUserBreak(); - - Bv_AllocVector(&bv, IRO_NumAssign); - do { - flag = 0; - for (node = IRO_FirstNode; node; node = node->nextnode) { - if (node == IRO_FirstNode) { - Bv_Clear(bv); - } else { - UInt16 i; - Bv_Set(bv); - for (i = 0; i < node->numpred; i++) - Bv_And(IRO_NodeTable[node->pred[i]]->x2A, bv); - } - - if (!Bv_Compare(bv, node->x16)) { - flag = 1; - Bv_Copy(bv, node->x16); - } - - Bv_Copy(node->x16, node->x2A); - Bv_Minus(node->x22, node->x2A); - Bv_Or(node->x1E, node->x2A); - } - } while (flag); - - IRO_CheckForUserBreak(); - - node = IRO_FirstNode; - ass = IRO_FirstAssign; - while (node) { - IRO_Avail = node->x16; - linear = node->first; - while (1) { - if (!linear) - break; - - if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) { - if ((var = IRO_FindVar(linear->u.diadic.left->u.node->data.objref, 0, 1))) { - //IROAssign *ass2; - for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) { - if ( - ass2->varIndex == var->index && - Bv_IsBitSet(ass2->index, IRO_Avail) && - (IRO_IsConstant(ass2->linear2) || node->loopdepth <= ass2->node->loopdepth) && - !PropagationHasDefsInUnorderedRegions(linear, ass2->linear2) - ) { - if (ass2->linear2->type == IROLinearOperand && IRO_is_CPtypeequal(linear->rtype, ass2->linear->u.diadic.left->rtype)) { - ENode *enode = IRO_NewENode(ass2->linear2->u.node->type); - *enode = *ass2->linear2->u.node; - if (enode->type == EINTCONST) { - if (linear->flags & IROLF_BitfieldIndirect) { - IRO_TruncateBitfieldValueToType(&enode->data.intval, linear->rtype, var->x1A); - enode->rtype = linear->rtype; - result = 1; - } else { - IRO_TruncateValueToType(&enode->data.intval, linear->rtype); - enode->rtype = linear->rtype; - } - } - linear->u.monadic->type = IROLinearNop; - linear->type = IROLinearOperand; - linear->u.node = enode; - } else if (ass2->varObj && IRO_is_CPtypeequal(linear->rtype, ass2->linear->rtype)) { - linear->u.diadic.left->u.node = create_objectrefnode(ass2->varObj); - if (ass2->linear2->flags & IROLF_BitfieldIndirect) - linear->flags |= IROLF_BitfieldIndirect; - } - IRO_Dump("Found propagation at %d from %d\n", linear->index, ass2->linear->index); - break; - } - } - } - } else if (linear->type == IROLinearAsm) { - IAEffects effects; - int i; - CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); - - for (i = 0; i < effects.numoperands; i++) { - if (effects.operands[i].type == IAEffect_0 && effects.operands[i].offset == 0 && effects.operands[i].object->type->size == effects.operands[i].size) { - if ((var = IRO_FindVar(effects.operands[i].object, 0, 1))) { - //IROAssign *ass2; - for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) { - if (ass2->varIndex == var->index && Bv_IsBitSet(ass2->index, IRO_Avail) && ass2->linear->rtype->size == effects.operands[i].size) { - ENode *enode; - if (ass2->varObj) - enode = create_objectrefnode(ass2->varObj); - else if (ass2->linear2->type == IROLinearOperand) - enode = ass2->linear2->u.node; - else - CError_FATAL(768); - CodeGen_PropagateIntoAsm(linear->u.asm_stmt, effects.operands[i].object, enode); - break; - } - } - } - } - } - } - - if (IsIntGenKillCandidate(linear)) { - //IROAssign *ass2; - Bv_Clear(IRO_VarKills); - IRO_GetKills(linear); - - for (ass2 = IRO_FirstAssign; ass2; ass2 = ass2->next) { - if (Bv_IsBitSet(ass2->varIndex, IRO_VarKills)) { - Bv_ClearBit(ass2->index, IRO_Avail); - } - if (ass2->var && Bv_IsBitSet(ass2->var->index, IRO_VarKills)) { - Bv_ClearBit(ass2->index, IRO_Avail); - } - } - - while (ass && ass->linear == linear) { - Bv_SetBit(ass->index, IRO_Avail); - ass = ass->next; - } - } - - if (linear == node->last) - break; - linear = linear->next; - } - node = node->nextnode; - } - - IRO_CheckForUserBreak(); - - return result; -} - -void IRO_ExpressionPropagation(void) { - IRONode *node; - IROLinear *linear; - Object *obj; - VarRecord *var; - IROAssign *ass; - - for (node = IRO_FirstNode; node; node = node->nextnode) { - IRO_FirstAssign = NULL; - IRO_LastAssign = NULL; - IRO_NumAssign = 0; - - linear = node->first; - while (1) { - IROList list; - if (!linear) - break; - - IRO_InitList(&list); - if (IsPropagatableExpr(linear, &list)) { - if ((var = IRO_FindAssigned(linear))) { - IRO_Dump("Found propagatable expression assignment at: %d\n", linear->index); - ass = oalloc(sizeof(IROAssign)); - ass->linear = linear; - ass->next = NULL; - ass->index = ++IRO_NumAssign; - ass->varIndex = var->index; - ass->linear2 = linear->u.diadic.right; - ass->x20 = 0; - ass->node = node; - IRO_FindDepends(linear->u.diadic.right); - ass->depends = IRO_Depends; - if (!IRO_FirstAssign) { - IRO_FirstAssign = ass; - ass->prev = NULL; - } else { - IRO_LastAssign->next = ass; - ass->prev = IRO_LastAssign; - } - IRO_LastAssign = ass; - } - } - - if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) { - if ((var = IRO_FindVar(linear->u.monadic->u.node->data.objref, 0, 1))) { - for (ass = IRO_LastAssign; ass; ass = ass->prev) { - if (ass->varIndex == var->index) - ass->x20++; - } - } - } - - if (linear == node->last) - break; - linear = linear->next; - } - - Bv_AllocVector(&IRO_Avail, IRO_NumAssign); - - linear = node->first; - while (1) { - if (!linear) - break; - - if (IRO_IsVariable(linear) && !(linear->flags & IROLF_Assigned)) { - if ((var = IRO_FindVar(linear->u.monadic->u.node->data.objref, 0, 1))) { - for (ass = IRO_FirstAssign; ass; ass = ass->next) { - if (ass->varIndex == var->index && Bv_IsBitSet(ass->index, IRO_Avail) && !PropagationHasDefsInUnorderedRegions(linear, ass->linear2)) { - if (ass->linear2->type == IROLinearOperand && IRO_is_CPtypeequal(linear->rtype, ass->linear->u.diadic.left->rtype)) { - ENode *enode = IRO_NewENode(ass->linear2->u.node->type); - *enode = *ass->linear2->u.node; - if (enode->type == EINTCONST) { - IRO_TruncateValueToType(&enode->data.intval, linear->rtype); - enode->rtype = linear->rtype; - } else if (enode->type == EOBJREF) { - IROLinear *tmp = IRO_LocateFather(linear); - if (tmp && (tmp->flags & IROLF_Assigned)) - linear->flags |= IROLF_Assigned; - } - linear->u.monadic->type = IROLinearNop; - linear->type = IROLinearOperand; - linear->u.node = enode; - } else if (IRO_IsVariable(ass->linear2) && IRO_is_CPtypeequal(linear->rtype, ass->linear->rtype)) { - linear->u.monadic->u.node = create_objectrefnode(ass->linear2->u.monadic->u.node->data.objref); - if (ass->linear2->flags & IROLF_BitfieldIndirect) - linear->flags |= IROLF_BitfieldIndirect; - } else if (IRO_is_CPtypeequal(linear->rtype, ass->linear->rtype) && ass->x20 == 1 && !VarIsUsedInOtherFNodes(var, node)) { - IROList list; - IRO_InitList(&list); - IRO_DuplicateExpr(ass->linear->u.diadic.right, &list); - if (IS_TYPE_FLOAT(ass->linear->rtype)) { - IROLinear *tmp = IRO_NewLinear(IROLinearOp1Arg); - tmp->index = ++IRO_NumLinear; - tmp->rtype = ass->linear->rtype; - tmp->nodetype = ETYPCON; - tmp->nodeflags = ENODE_FLAG_80; - tmp->u.monadic = list.tail; - IRO_AddToList(tmp, &list); - } - IRO_PasteAfter(list.head, list.tail, linear); - IRO_LocateFather_Cut_And_Paste(linear, list.tail); - linear = list.tail; - } - IRO_Dump("Found expression propagation at %d from %d\n", linear->index, ass->linear->index); - break; - } - } - } - } - - if (linear->type != IROLinearNop && IsIntGenKillCandidate(linear)) { - Bv_Clear(IRO_VarKills); - IRO_GetKills(linear); - for (ass = IRO_FirstAssign; ass; ass = ass->next) { - if (Bv_IsBitSet(ass->varIndex, IRO_VarKills)) - Bv_ClearBit(ass->index, IRO_Avail); - if ((obj = IRO_IsVariable(ass->linear->u.diadic.right))) { - if ((var = IRO_FindVar(obj, 0, 1))) { - if (Bv_IsBitSet(var->index, IRO_VarKills)) - Bv_ClearBit(ass->index, IRO_Avail); - } - } else { - IROList list; - IRO_InitList(&list); - IRO_Depends = ass->depends; - IRO_FindDepends_NoAlloc(ass->linear->u.diadic.right); - if (Bv_BitsInCommon(IRO_VarKills, ass->depends)) - Bv_ClearBit(ass->index, IRO_Avail); - } - } - - for (ass = IRO_FirstAssign; ass; ass = ass->next) { - IRO_Depends = ass->depends; - IRO_FindDepends_NoAlloc(ass->linear->u.diadic.right); - if (ass->linear == linear && !Bv_IsBitSet(ass->varIndex, ass->depends)) - Bv_SetBit(ass->index, IRO_Avail); - } - } - - if (linear == node->last) - break; - linear = linear->next; - } - } - - IRO_CheckForUserBreak(); -} - diff --git a/compiler_and_linker/unsorted/IroRangePropagation.c b/compiler_and_linker/unsorted/IroRangePropagation.c deleted file mode 100644 index d15ef86..0000000 --- a/compiler_and_linker/unsorted/IroRangePropagation.c +++ /dev/null @@ -1,774 +0,0 @@ -#include "compiler/IroRangePropagation.h" -#include "compiler/IroDump.h" -#include "compiler/IroFlowgraph.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroMalloc.h" -#include "compiler/IroPointerAnalysis.h" -#include "compiler/IroUtil.h" -#include "compiler/IroVars.h" -#include "compiler/CInt64.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef enum ERangeType { - ERangeType0, - ERangeType1, - ERangeType2, - ERangeType3 -} ERangeType; - -typedef struct ERange { - ERangeType type; - CInt64 upper; - CInt64 lower; -} ERange; - -typedef struct ERecord { - Object *object; - ERange *range; - struct ERecord *next; -} ERecord; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static ERecord *ERangeFirst; -static ERecord *ERangeLast; - -static ERange *ERnewERange(ERangeType type) { - ERange *range; - - range = oalloc(sizeof(ERange)); - range->type = type; - return range; -} - -static ERecord *ERnewRecord(Object *object, ERange *range) { - ERecord *record; - - record = oalloc(sizeof(ERecord)); - record->object = object; - record->range = range; - record->next = ERangeFirst; - ERangeFirst = record; - if (!ERangeLast) - ERangeLast = record; - return record; -} - -static ERecord *ERecordFound(Object *obj) { - ERecord *scan; - - scan = ERangeFirst; - while (scan && obj != scan->object) - scan = scan->next; - - return scan; -} - -static Boolean EREandHasNoUse(ERange *range, CInt64 val) { - UInt16 i; - CInt64 v11; - CInt64 work; - - i = 0; - work = range->upper; - while (CInt64_NotEqual(work = CInt64_ShrU(work, cint64_one), cint64_zero)) - i++; - - if (CInt64_NotEqual(range->upper, cint64_zero)) - i++; - - CInt64_SetULong(&work, i); - v11 = CInt64_Sub(CInt64_Shl(cint64_one, work), cint64_one); - if (CInt64_NotEqual(cint64_zero, CInt64_And(CInt64_Inv(val), v11))) - return 0; - else - return 1; -} - -static void ERcheckOverflow(ERange *range, Type *type) { - CInt64 typeSize; - CInt64 work; - CInt64 work2; - CInt64 value3; - - if (!range) - return; - - if (!IS_TYPE_INT(type)) { - range->type = ERangeType3; - return; - } - - CInt64_SetLong(&typeSize, type->size); - CInt64_SetLong(&value3, 3); - - if (IRO_IsUnsignedType(type)) { - if (type->size < 8) { - work = CInt64_Sub(CInt64_Shl(cint64_one, CInt64_Shl(typeSize, value3)), cint64_one); - if (CInt64_GreaterU(range->upper, work)) - range->type = ERangeType3; - } else { - range->type = ERangeType3; - } - } else { - if (type->size < 8) { - work = CInt64_Sub(CInt64_Shl(cint64_one, CInt64_Sub(CInt64_Shl(typeSize, value3), cint64_one)), cint64_one); - work2 = CInt64_Shl(cint64_negone, CInt64_Sub(CInt64_Shl(typeSize, value3), cint64_one)); - if (CInt64_Greater(range->upper, work) || CInt64_Less(range->lower, work2)) - range->type = ERangeType3; - } else { - range->type = ERangeType3; - } - } -} - -static void ERinvalidAll(void) { - ERecord *record; - - for (record = ERangeFirst; record; record = record->next) - record->range->type = ERangeType3; -} - -static void SetRangesForKillsByIndirectAssignment(IROLinear *nd) { - IROListNode *list; - IROListNode *scan; - IROLinear *inner; - Boolean failed; - IROListNode *resultList; - IROLinear *scannd; - Boolean foundObjRef; - ERecord *record; - ERange *range; - IROListNode *next; - Object *obj; - IROLinear *analysend; - Object *proc; - - failed = 0; - if (nd->type == IROLinearOp2Arg) - inner = nd->u.diadic.left; - else - inner = nd->u.monadic; - - if ( - inner && - inner->type == IROLinearOp1Arg && - inner->nodetype == EINDIRECT && - (analysend = inner->u.monadic) && - copts.opt_pointer_analysis && - analysend->pointsToFunction && - (proc = FunctionName) - ) { - resultList = NULL; - PointerAnalysis_LookupLinearNodePointerExpr(proc, analysend, &resultList); - - if ((list = resultList)) { - for (scan = list; scan; scan = scan->nextList) { - if (!scan->list.head || !scan->list.tail) { - failed = 1; - break; - } - - foundObjRef = 0; - for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { - if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { - foundObjRef = 1; - break; - } - } - - if (!foundObjRef) { - failed = 1; - break; - } - } - - if (!failed) { - for (; list; list = list->nextList) { - for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { - if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { - obj = scannd->u.node->data.objref; - CError_ASSERT(302, obj != NULL); - - range = nd->x16; - if (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC) - range = inner->x16; - - record = ERecordFound(obj); - if (!record) - ERnewRecord(obj, range); - else - record->range = range; - } - } - } - } - - while (resultList) { - next = resultList->nextList; - IRO_free(resultList); - resultList = next; - } - } else { - failed = 1; - } - } else { - failed = 1; - } - - if (failed) { - ERinvalidAll(); - nd->x16 = ERnewERange(ERangeType3); - } -} - -static void InvalidateRangesForKillsByFunctionCall(IROLinear *nd) { - IROListNode *scan; - IROLinear *scannd; - Boolean failed; - Boolean foundObjRef; - IROListNode *list; - IROListNode *resultList; - ERecord *record; - IROListNode *next; - Object *obj; - IROLinear *analysend; - Object *proc; - ObjectList *olist; - ObjectList *killList; - - failed = 0; - - if ( - (analysend = nd->u.funccall.linear8) && - copts.opt_pointer_analysis && - analysend->pointsToFunction && - (proc = FunctionName) - ) { - resultList = NULL; - PointerAnalysis_LookupLinearNodePointerExpr(proc, analysend, &resultList); - - if (resultList) { - for (scan = resultList; scan; scan = scan->nextList) { - if (!scan->list.head || !scan->list.tail) { - failed = 1; - break; - } - - foundObjRef = 0; - for (scannd = scan->list.head; scannd != scan->list.tail->next; scannd = scannd->next) { - if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { - foundObjRef = 1; - obj = scannd->u.node->data.objref; - CError_ASSERT(385, obj != NULL); - - killList = NULL; - PointerAnalysis_GetFunctionKills(obj, nd, &killList); - - for (olist = killList; olist; olist = olist->next) { - if (!olist->object) { - failed = 1; - break; - } - } - - while (killList) { - olist = killList->next; - IRO_free(killList); - killList = olist; - } - - if (failed) - break; - } - } - - if (!foundObjRef) - failed = 1; - if (failed) - break; - } - - if (!failed) { - for (list = resultList; list; list = list->nextList) { - for (scannd = list->list.head; scannd != list->list.tail->next; scannd = scannd->next) { - if (scannd->type == IROLinearOperand && scannd->u.node->type == EOBJREF) { - obj = scannd->u.node->data.objref; - killList = NULL; - PointerAnalysis_GetFunctionKills(obj, nd, &killList); - - for (olist = killList; olist; olist = olist->next) { - if ((record = ERecordFound(olist->object))) - record->range->type = ERangeType3; - } - - while (killList) { - olist = killList->next; - IRO_free(killList); - killList = olist; - } - } - } - } - } - - while (resultList) { - next = resultList->nextList; - IRO_free(resultList); - resultList = next; - } - } else { - failed = 1; - } - } else { - failed = 1; - } - - if (failed) - ERinvalidAll(); -} - -static void ERfoldOperand(IROLinear *nd) { - switch (nd->u.node->type) { - case EOBJREF: - nd->x16 = NULL; - break; - case EINTCONST: - nd->x16 = ERnewERange(ERangeType0); - nd->x16->upper = nd->x16->lower = nd->u.node->data.intval; - break; - case EFLOATCONST: - case ESTRINGCONST: - nd->x16 = ERnewERange(ERangeType0); - break; - } -} - -static Boolean ERfoldExpr(IROLinear *nd) { - ERecord *record; - ERange *range; - IROLinear *tmp; - IROLinear *inner; - Object *obj; - - switch (nd->nodetype) { - case EINDIRECT: - inner = nd->u.monadic; - if (IS_TYPE_INT(nd->rtype)) { - if (inner->type == IROLinearOperand && inner->u.node->type == EOBJREF) { - if (!inner->x16 && (obj = inner->u.node->data.objref)) { - if ((record = ERecordFound(obj))) { - inner->x16 = ERnewERange(ERangeType3); - *inner->x16 = *record->range; - } else { - inner->x16 = ERnewERange(ERangeType3); - inner->x16->upper = cint64_max; - inner->x16->lower = cint64_min; - ERnewRecord(obj, inner->x16); - } - } - nd->x16 = inner->x16; - } else { - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - } - } else { - if (inner->type == IROLinearOperand && inner->u.node->type == EOBJREF && !inner->x16) - inner->x16 = ERnewERange(ERangeType3); - nd->x16 = ERnewERange(ERangeType3); - } - break; - case EAND: - case EANDASS: - if (IRO_IsIntConstant(nd->u.diadic.right)) { - CInt64 val = nd->u.diadic.right->u.node->data.intval; - nd->x16 = ERnewERange(ERangeType1); - nd->x16->upper = val; - nd->x16->lower = cint64_zero; - if ( - (range = nd->u.diadic.left->x16) && - range->type != ERangeType3 && - CInt64_LessEqualU(range->upper, val) && - CInt64_LessEqualU(range->lower, val) && - EREandHasNoUse(range, val) && - !IRO_HasSideEffect(nd->u.diadic.left) - ) { - IRO_Dump("eliminating redundant EAND %" PRId32 "; upperBound==0x%x, lowerBound==0x%x, Constant==0x%x\n", - nd->index, - CInt64_GetULong(&range->upper), - CInt64_GetULong(&range->upper), - CInt64_GetULong(&val) - ); - IRO_NopOut(nd->u.diadic.right); - nd->type = IROLinearNop; - nd->expr = NULL; - tmp = nd->u.diadic.left; - nd->u.diadic.left = nd->u.diadic.right; - if (!IRO_LocateFather_Cut_And_Paste(nd, tmp)) { - tmp->flags &= ~IROLF_Reffed; - if (IRO_IsVariable(tmp)) - IRO_NopOut(tmp); - } - } - } else { - if (nd->u.diadic.right->x16) { - nd->x16 = ERnewERange(ERangeType3); - *nd->x16 = *nd->u.diadic.right->x16; - } - } - ERcheckOverflow(nd->x16, nd->rtype); - break; - case ELOGNOT: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case ELAND: - case ELOR: - nd->x16 = ERnewERange(ERangeType1); - nd->x16->upper = cint64_one; - nd->x16->lower = cint64_zero; - ERcheckOverflow(nd->x16, nd->rtype); - break; - case EBINNOT: - case EFORCELOAD: - case EXOR: - case EOR: - case EXORASS: - case EORASS: - case ECOMMA: - case ETYPCON: - case EBITFIELD: - case ECOND: - case ENULLCHECK: - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - break; - case EASS: - if (IS_TYPE_INT(nd->rtype)) - nd->x16 = nd->u.diadic.right->x16; - break; - case EMUL: - case EMULV: - case EMULASS: - if (IS_TYPE_INT(nd->rtype)) { - if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && - nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { - nd->x16 = ERnewERange(ERangeType2); - if (IRO_IsUnsignedType(nd->rtype)) { - nd->x16->upper = CInt64_MulU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper); - nd->x16->lower = CInt64_MulU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower); - } else { - nd->x16->upper = CInt64_Mul(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper); - nd->x16->lower = CInt64_Mul(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower); - } - } else { - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - } - } - ERcheckOverflow(nd->x16, nd->rtype); - break; - case EDIV: - case EDIVASS: - if (IS_TYPE_INT(nd->rtype)) { - if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && - nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { - nd->x16 = ERnewERange(ERangeType2); - if (!CInt64_IsZero(&nd->u.diadic.right->x16->lower) && !CInt64_IsZero(&nd->u.diadic.right->x16->upper)) { - if (IRO_IsUnsignedType(nd->rtype)) { - nd->x16->upper = CInt64_DivU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); - nd->x16->lower = CInt64_DivU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); - } else { - nd->x16->upper = CInt64_Div(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); - nd->x16->lower = CInt64_Div(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); - } - } else { - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - } - } else { - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - } - } - ERcheckOverflow(nd->x16, nd->rtype); - break; - case EMODULO: - case EMODASS: - if (IS_TYPE_INT(nd->rtype)) { - if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && - nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { - nd->x16 = ERnewERange(ERangeType2); - if (!CInt64_IsZero(&nd->u.diadic.right->x16->lower) && !CInt64_IsZero(&nd->u.diadic.right->x16->upper)) { - if (IRO_IsUnsignedType(nd->rtype)) { - nd->x16->upper = CInt64_ModU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); - nd->x16->lower = CInt64_ModU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); - } else { - nd->x16->upper = CInt64_Mod(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); - nd->x16->lower = CInt64_Mod(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); - } - } else { - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - } - } else { - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - } - } - ERcheckOverflow(nd->x16, nd->rtype); - break; - case EADDV: - case EADD: - case EADDASS: - if (IS_TYPE_INT(nd->rtype)) { - if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && - nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { - nd->x16 = ERnewERange(ERangeType2); - nd->x16->upper = CInt64_Add(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper); - nd->x16->lower = CInt64_Add(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower); - } else { - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - } - } - ERcheckOverflow(nd->x16, nd->rtype); - break; - case ESUBV: - case ESUB: - case ESUBASS: - if (IS_TYPE_INT(nd->rtype)) { - if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && - nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { - nd->x16 = ERnewERange(ERangeType2); - nd->x16->upper = CInt64_Sub(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); - nd->x16->lower = CInt64_Sub(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); - } else { - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - } - } - ERcheckOverflow(nd->x16, nd->rtype); - break; - case ESHL: - case ESHLASS: - if (IS_TYPE_INT(nd->rtype)) { - if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && - nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { - nd->x16 = ERnewERange(ERangeType2); - nd->x16->upper = CInt64_Shl(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->upper); - nd->x16->lower = CInt64_Shl(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->lower); - } else { - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - } - } - ERcheckOverflow(nd->x16, nd->rtype); - break; - case ESHR: - case ESHRASS: - if (IS_TYPE_INT(nd->rtype)) { - if (nd->u.diadic.left->x16 && nd->u.diadic.left->x16->type != ERangeType3 && - nd->u.diadic.right->x16 && nd->u.diadic.right->x16->type != ERangeType3) { - nd->x16 = ERnewERange(ERangeType2); - if (IRO_IsUnsignedType(nd->rtype)) { - nd->x16->upper = CInt64_ShrU(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); - nd->x16->lower = CInt64_ShrU(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); - } else { - nd->x16->upper = CInt64_Shr(nd->u.diadic.left->x16->upper, nd->u.diadic.right->x16->lower); - nd->x16->lower = CInt64_Shr(nd->u.diadic.left->x16->lower, nd->u.diadic.right->x16->upper); - } - } else { - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - } - } - ERcheckOverflow(nd->x16, nd->rtype); - break; - case EPOSTINC: - if (IS_TYPE_INT(nd->rtype)) { - if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) { - nd->x16 = ERnewERange(ERangeType2); - range = nd->u.monadic->x16; - *nd->x16 = *range; - range->upper = CInt64_Add(range->upper, cint64_one); - range->lower = CInt64_Add(range->lower, cint64_one); - } else { - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - } - } - ERcheckOverflow(nd->x16, nd->rtype); - break; - case EPOSTDEC: - if (IS_TYPE_INT(nd->rtype)) { - if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) { - nd->x16 = ERnewERange(ERangeType2); - range = nd->u.monadic->x16; - *nd->x16 = *range; - range->upper = CInt64_Sub(range->upper, cint64_one); - range->lower = CInt64_Sub(range->lower, cint64_one); - } else { - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - } - } - ERcheckOverflow(nd->x16, nd->rtype); - break; - case EPREINC: - if (IS_TYPE_INT(nd->rtype)) { - if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) { - nd->x16 = ERnewERange(ERangeType2); - range = nd->u.monadic->x16; - nd->x16->upper = CInt64_Add(range->upper, cint64_one); - nd->x16->lower = CInt64_Add(range->lower, cint64_one); - } else { - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - } - } - ERcheckOverflow(nd->x16, nd->rtype); - break; - case EPREDEC: - if (IS_TYPE_INT(nd->rtype)) { - if (nd->u.monadic->x16 && nd->u.monadic->x16->type != ERangeType3) { - nd->x16 = ERnewERange(ERangeType2); - range = nd->u.monadic->x16; - nd->x16->upper = CInt64_Sub(range->upper, cint64_one); - nd->x16->lower = CInt64_Sub(range->lower, cint64_one); - } else { - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - } - } - ERcheckOverflow(nd->x16, nd->rtype); - break; - case EMONMIN: - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - break; - case EPMODULO: - case EROTL: - case EROTR: - case EBCLR: - case EBTST: - case EBSET: - nd->x16 = ERnewERange(ERangeType3); - nd->x16->upper = cint64_max; - nd->x16->lower = cint64_min; - break; - default: - ERcheckOverflow(nd->x16, nd->rtype); - break; - } - - if ( - (nd->type == IROLinearOp1Arg || nd->type == IROLinearOp2Arg) && - IRO_IsAssignOp[nd->nodetype] && - nd->x16 && - IS_TYPE_INT(nd->rtype) - ) { - IROLinear *x = NULL; - if (nd->type == IROLinearOp2Arg) - x = nd->u.diadic.left; - else if (nd->type == IROLinearOp1Arg) - x = nd->u.monadic; - - if (x->type == IROLinearOp1Arg && - x->nodetype == EINDIRECT && - (x->u.monadic->nodetype == EINDIRECT || x->u.monadic->nodetype == EADD)) { - SetRangesForKillsByIndirectAssignment(nd); - } else { - obj = NULL; - if (x) - obj = IRO_IsVariable(x); - if (!obj) - return 0; - - range = nd->x16; - if (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC) - range = x->x16; - - record = ERecordFound(obj); - if (!record) - ERnewRecord(obj, range); - else - record->range = range; - } - } - - return nd->x16 != NULL; -} - -static Boolean ERfoldLinear(IROLinear *nd) { - nd->x16 = 0; - - switch (nd->type) { - case IROLinearNop: - case IROLinearEnd: - break; - case IROLinearOperand: - ERfoldOperand(nd); - break; - case IROLinearOp1Arg: - case IROLinearOp2Arg: - ERfoldExpr(nd); - break; - case IROLinearFunccall: - InvalidateRangesForKillsByFunctionCall(nd); - break; - case IROLinearAsm: - ERinvalidAll(); - break; - } - - return 0; -} - -Boolean IRO_RangePropagateInFNode(void) { - IRONode *fnode; - IROLinear *nd; - Boolean result; - - result = 0; - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - ERangeFirst = ERangeLast = NULL; - for (nd = fnode->first; nd != fnode->last; nd = nd->next) - ERfoldLinear(nd); - if (ERfoldLinear(nd)) - result = 1; - } - - if (result) { - IRO_ComputeSuccPred(); - IRO_ComputeDom(); - } - - IRO_CheckForUserBreak(); - return result; -} diff --git a/compiler_and_linker/unsorted/IroSubable.c b/compiler_and_linker/unsorted/IroSubable.c deleted file mode 100644 index 6b8daf0..0000000 --- a/compiler_and_linker/unsorted/IroSubable.c +++ /dev/null @@ -1,160 +0,0 @@ -#include "compiler/IroSubable.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroPropagate.h" -#include "compiler/IroUtil.h" -#include "compiler/enode.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -static Boolean IsSubableOp[MAXEXPR]; - -void IRO_InitializeIsSubableOpArray(void) { - int i; - - for (i = 0; i < MAXEXPR; i++) - IsSubableOp[i] = 0; - - IsSubableOp[EPOSTINC] = 0; - IsSubableOp[EPOSTDEC] = 0; - IsSubableOp[EPREINC] = 0; - IsSubableOp[EPREDEC] = 0; - IsSubableOp[EINDIRECT] = 0; - IsSubableOp[EMONMIN] = 1; - IsSubableOp[EBINNOT] = 1; - IsSubableOp[ELOGNOT] = 1; - IsSubableOp[EFORCELOAD] = 0; - IsSubableOp[EMUL] = 1; - IsSubableOp[EMULV] = 1; - IsSubableOp[EDIV] = 1; - IsSubableOp[EMODULO] = 1; - IsSubableOp[EADDV] = 1; - IsSubableOp[ESUBV] = 1; - IsSubableOp[EADD] = 1; - IsSubableOp[ESUB] = 1; - IsSubableOp[ESHL] = 1; - IsSubableOp[ESHR] = 1; - IsSubableOp[ELESS] = 0; - IsSubableOp[EGREATER] = 0; - IsSubableOp[ELESSEQU] = 0; - IsSubableOp[EGREATEREQU] = 0; - IsSubableOp[EEQU] = 0; - IsSubableOp[ENOTEQU] = 0; - IsSubableOp[EAND] = 1; - IsSubableOp[EXOR] = 1; - IsSubableOp[EOR] = 1; - IsSubableOp[ELAND] = 0; - IsSubableOp[ELOR] = 0; - IsSubableOp[EASS] = 0; - IsSubableOp[EMULASS] = 0; - IsSubableOp[EDIVASS] = 0; - IsSubableOp[EMODASS] = 0; - IsSubableOp[EADDASS] = 0; - IsSubableOp[ESUBASS] = 0; - IsSubableOp[ESHLASS] = 0; - IsSubableOp[ESHRASS] = 0; - IsSubableOp[EANDASS] = 0; - IsSubableOp[EXORASS] = 0; - IsSubableOp[EORASS] = 0; - IsSubableOp[ECOMMA] = 0; - IsSubableOp[EPMODULO] = 0; - IsSubableOp[EROTL] = 0; - IsSubableOp[EROTR] = 0; - IsSubableOp[EBCLR] = 0; - IsSubableOp[EBTST] = 0; - IsSubableOp[EBSET] = 0; - IsSubableOp[ETYPCON] = 0; - IsSubableOp[EBITFIELD] = 0; - IsSubableOp[EINTCONST] = 0; - IsSubableOp[EFLOATCONST] = 0; - IsSubableOp[ESTRINGCONST] = 0; - IsSubableOp[ECOND] = 0; - IsSubableOp[EFUNCCALL] = 0; - IsSubableOp[EFUNCCALLP] = 0; - IsSubableOp[EOBJREF] = 0; - IsSubableOp[EMFPOINTER] = 0; - IsSubableOp[ENULLCHECK] = 0; - IsSubableOp[EPRECOMP] = 0; - IsSubableOp[ETEMP] = 0; - IsSubableOp[EARGOBJ] = 0; - IsSubableOp[ELOCOBJ] = 0; - IsSubableOp[ELABEL] = 0; - IsSubableOp[ESETCONST] = 0; - IsSubableOp[ENEWEXCEPTION] = 0; - IsSubableOp[ENEWEXCEPTIONARRAY] = 0; - IsSubableOp[EOBJLIST] = 0; - IsSubableOp[EMEMBER] = 0; - IsSubableOp[ETEMPLDEP] = 0; - IsSubableOp[EINSTRUCTION] = 0; - IsSubableOp[EDEFINE] = 0; - IsSubableOp[EREUSE] = 0; - IsSubableOp[EASSBLK] = 0; - IsSubableOp[EVECTOR128CONST] = 0; - IsSubableOp[ECONDASS] = 0; -} - -static int IsSubscript(IROLinear *nd) { - return 0; -} - -Boolean IRO_IsSubableExpression(IROLinear *nd) { - Object *varobj; - Boolean result; - - switch (nd->type) { - case IROLinearOp2Arg: - if (nd->nodetype == EADD || nd->nodetype == ESUB) { - if ( - IRO_IsConstant(nd->u.diadic.right) && - (varobj = IRO_IsVariable(nd->u.diadic.left)) && - varobj->datatype == DLOCAL && - varobj->u.var.info && - !varobj->u.var.info->noregister) - return 0; - - } - result = IsSubableOp[nd->nodetype] && !IsSubscript(nd); - return result; - case IROLinearOp1Arg: - if (IsSubableOp[nd->nodetype] && !IsSubscript(nd)) - return 1; - - if (nd->nodetype == EINDIRECT && !(nd->flags & IROLF_Assigned)) { - if (nd->flags & IROLF_Ind) { - nd = nd->u.monadic; - if (nd->type == IROLinearOperand && - nd->u.node->type == EOBJREF && - nd->u.node->data.objref->datatype == DLOCAL && - nd->u.node->data.objref->u.var.info && - !nd->u.node->data.objref->u.var.info->noregister - ) - return 0; - return 1; - } - - if (IRO_IsVariable(nd) && IRO_IsRegable(nd->u.monadic->u.node->data.objref)) - return 0; - return 1; - } else if (nd->nodetype == ETYPCON && IS_TYPE_INT(nd->rtype) && nd->rtype->size >= nd->u.monadic->rtype->size) { - return 1; - } else { - return 0; - } - case IROLinearOperand: - default: - return 0; - } -} - -Boolean IRO_IsVectorTempCandidate(IROLinear *nd) { - return - ( - nd->type == IROLinearOp1Arg || - nd->type == IROLinearOp2Arg || - nd->type == IROLinearOp3Arg || - nd->type == IROLinearOperand || - nd->type == IROLinearFunccall - ) && ( - (nd->flags & IROLF_LoopInvariant) && - !(nd->flags & IROLF_Ind) - ); -} diff --git a/compiler_and_linker/unsorted/IroTransform.c b/compiler_and_linker/unsorted/IroTransform.c deleted file mode 100644 index 54f3302..0000000 --- a/compiler_and_linker/unsorted/IroTransform.c +++ /dev/null @@ -1,2794 +0,0 @@ -#include "compiler/IroTransform.h" -#include "compiler/CError.h" -#include "compiler/CFunc.h" -#include "compiler/CInt64.h" -#include "compiler/CIRTransform.h" -#include "compiler/CMachine.h" -#include "compiler/CPrep.h" -#include "compiler/CompilerTools.h" -#include "compiler/IroDump.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroMalloc.h" -#include "compiler/IroPointerAnalysis.h" -#include "compiler/IROUseDef.h" -#include "compiler/IroUtil.h" -#include "compiler/IroVars.h" -#include "compiler/enode.h" -#include "compiler/types.h" - -ENodeType ExprType; -ENode *IndirectRef; -Boolean FirstTime; -CInt64 OperandConst; -Object *OperandObject; -ENodeList *FirstAddend; -ENodeList *LastAddend; -static ENodeType AssignmentOp[MAXEXPR]; -static ENodeType ComplementaryOpLogical[MAXEXPR]; -static ENodeType ComplementaryOp[MAXEXPR]; - -// forward decls -static void DoDiadic(IROLinear *nd); - -static int GetTypeSize(Type *type) { - if (type->size == 1) - return 0; - if (type->size == 2) - return 1; - if (type->size == 4) - return 2; - if (type->size == 8) - return 3; - return -1; -} - -void IRO_InitializeAssignmentOpArray(void) { - int i; - - for (i = 0; i < MAXEXPR; i++) - AssignmentOp[i] = MAXEXPR; - - AssignmentOp[EPOSTINC] = MAXEXPR; - AssignmentOp[EPOSTDEC] = MAXEXPR; - AssignmentOp[EPREINC] = MAXEXPR; - AssignmentOp[EPREDEC] = MAXEXPR; - AssignmentOp[EINDIRECT] = MAXEXPR; - AssignmentOp[EMONMIN] = MAXEXPR; - AssignmentOp[EBINNOT] = MAXEXPR; - AssignmentOp[ELOGNOT] = MAXEXPR; - AssignmentOp[EFORCELOAD] = MAXEXPR; - AssignmentOp[EMUL] = EMULASS; - AssignmentOp[EMULV] = MAXEXPR; - AssignmentOp[EDIV] = EDIVASS; - AssignmentOp[EMODULO] = EMODASS; - AssignmentOp[EADDV] = MAXEXPR; - AssignmentOp[ESUBV] = MAXEXPR; - AssignmentOp[EADD] = EADDASS; - AssignmentOp[ESUB] = ESUBASS; - AssignmentOp[ESHL] = ESHLASS; - AssignmentOp[ESHR] = ESHRASS; - AssignmentOp[ELESS] = MAXEXPR; - AssignmentOp[EGREATER] = MAXEXPR; - AssignmentOp[ELESSEQU] = MAXEXPR; - AssignmentOp[EGREATEREQU] = MAXEXPR; - AssignmentOp[EEQU] = MAXEXPR; - AssignmentOp[ENOTEQU] = MAXEXPR; - AssignmentOp[EAND] = EANDASS; - AssignmentOp[EXOR] = EXORASS; - AssignmentOp[EOR] = EORASS; - AssignmentOp[ELAND] = MAXEXPR; - AssignmentOp[ELOR] = MAXEXPR; - AssignmentOp[EASS] = MAXEXPR; - AssignmentOp[EMULASS] = MAXEXPR; - AssignmentOp[EDIVASS] = MAXEXPR; - AssignmentOp[EMODASS] = MAXEXPR; - AssignmentOp[EADDASS] = MAXEXPR; - AssignmentOp[ESUBASS] = MAXEXPR; - AssignmentOp[ESHLASS] = MAXEXPR; - AssignmentOp[ESHRASS] = MAXEXPR; - AssignmentOp[EANDASS] = MAXEXPR; - AssignmentOp[EXORASS] = MAXEXPR; - AssignmentOp[EORASS] = MAXEXPR; - AssignmentOp[ECOMMA] = MAXEXPR; - AssignmentOp[EPMODULO] = MAXEXPR; - AssignmentOp[EROTL] = MAXEXPR; - AssignmentOp[EROTR] = MAXEXPR; - AssignmentOp[EBCLR] = MAXEXPR; - AssignmentOp[EBTST] = MAXEXPR; - AssignmentOp[EBSET] = MAXEXPR; - AssignmentOp[ETYPCON] = MAXEXPR; - AssignmentOp[EBITFIELD] = MAXEXPR; - AssignmentOp[EINTCONST] = MAXEXPR; - AssignmentOp[EFLOATCONST] = MAXEXPR; - AssignmentOp[ESTRINGCONST] = MAXEXPR; - AssignmentOp[ECOND] = MAXEXPR; - AssignmentOp[EFUNCCALL] = MAXEXPR; - AssignmentOp[EFUNCCALLP] = MAXEXPR; - AssignmentOp[EOBJREF] = MAXEXPR; - AssignmentOp[EMFPOINTER] = MAXEXPR; - AssignmentOp[ENULLCHECK] = MAXEXPR; - AssignmentOp[EPRECOMP] = MAXEXPR; - AssignmentOp[ETEMP] = MAXEXPR; - AssignmentOp[EARGOBJ] = MAXEXPR; - AssignmentOp[ELOCOBJ] = MAXEXPR; - AssignmentOp[ELABEL] = MAXEXPR; - AssignmentOp[ESETCONST] = MAXEXPR; - AssignmentOp[ENEWEXCEPTION] = MAXEXPR; - AssignmentOp[ENEWEXCEPTIONARRAY] = MAXEXPR; - AssignmentOp[EOBJLIST] = MAXEXPR; - AssignmentOp[EMEMBER] = MAXEXPR; - AssignmentOp[ETEMPLDEP] = MAXEXPR; - AssignmentOp[EINSTRUCTION] = MAXEXPR; - AssignmentOp[EDEFINE] = MAXEXPR; - AssignmentOp[EREUSE] = MAXEXPR; - AssignmentOp[EASSBLK] = MAXEXPR; - AssignmentOp[EVECTOR128CONST] = MAXEXPR; - AssignmentOp[ECONDASS] = MAXEXPR; -} - -void IRO_InitializeComplementaryOpArray(void) { - int i; - - for (i = 0; i < MAXEXPR; i++) - ComplementaryOp[i] = MAXEXPR; - - ComplementaryOp[EPOSTINC] = EPOSTDEC; - ComplementaryOp[EPOSTDEC] = EPOSTINC; - ComplementaryOp[EPREINC] = EPREDEC; - ComplementaryOp[EPREDEC] = EPREINC; - ComplementaryOp[EINDIRECT] = MAXEXPR; - ComplementaryOp[EMONMIN] = EMONMIN; - ComplementaryOp[EBINNOT] = EBINNOT; - ComplementaryOp[ELOGNOT] = ELOGNOT; - ComplementaryOp[EFORCELOAD] = MAXEXPR; - ComplementaryOp[EMUL] = EDIV; - ComplementaryOp[EMULV] = MAXEXPR; - ComplementaryOp[EDIV] = EMUL; - ComplementaryOp[EMODULO] = MAXEXPR; - ComplementaryOp[EADDV] = ESUBV; - ComplementaryOp[ESUBV] = EADDV; - ComplementaryOp[EADD] = ESUB; - ComplementaryOp[ESUB] = EADD; - ComplementaryOp[ESHL] = ESHR; - ComplementaryOp[ESHR] = ESHL; - ComplementaryOp[ELESS] = EGREATER; - ComplementaryOp[EGREATER] = ELESS; - ComplementaryOp[ELESSEQU] = EGREATEREQU; - ComplementaryOp[EGREATEREQU] = ELESSEQU; - ComplementaryOp[EEQU] = ENOTEQU; - ComplementaryOp[ENOTEQU] = EEQU; - ComplementaryOp[EAND] = EOR; - ComplementaryOp[EXOR] = MAXEXPR; - ComplementaryOp[EOR] = EAND; - ComplementaryOp[ELAND] = ELOR; - ComplementaryOp[ELOR] = ELAND; - ComplementaryOp[EASS] = MAXEXPR; - ComplementaryOp[EMULASS] = EDIVASS; - ComplementaryOp[EDIVASS] = EMULASS; - ComplementaryOp[EMODASS] = MAXEXPR; - ComplementaryOp[EADDASS] = ESUBASS; - ComplementaryOp[ESUBASS] = EADDASS; - ComplementaryOp[ESHLASS] = ESHRASS; - ComplementaryOp[ESHRASS] = ESHLASS; - ComplementaryOp[EANDASS] = EORASS; - ComplementaryOp[EXORASS] = MAXEXPR; - ComplementaryOp[EORASS] = EANDASS; - ComplementaryOp[ECOMMA] = MAXEXPR; - ComplementaryOp[EPMODULO] = MAXEXPR; - ComplementaryOp[EROTL] = EROTR; - ComplementaryOp[EROTR] = EROTL; - ComplementaryOp[EBCLR] = MAXEXPR; - ComplementaryOp[EBTST] = MAXEXPR; - ComplementaryOp[EBSET] = MAXEXPR; - ComplementaryOp[ETYPCON] = MAXEXPR; - ComplementaryOp[EBITFIELD] = MAXEXPR; - ComplementaryOp[EINTCONST] = MAXEXPR; - ComplementaryOp[EFLOATCONST] = MAXEXPR; - ComplementaryOp[ESTRINGCONST] = MAXEXPR; - ComplementaryOp[ECOND] = MAXEXPR; - ComplementaryOp[EFUNCCALL] = MAXEXPR; - ComplementaryOp[EFUNCCALLP] = MAXEXPR; - ComplementaryOp[EOBJREF] = MAXEXPR; - ComplementaryOp[EMFPOINTER] = MAXEXPR; - ComplementaryOp[ENULLCHECK] = MAXEXPR; - ComplementaryOp[EPRECOMP] = MAXEXPR; - ComplementaryOp[ETEMP] = MAXEXPR; - ComplementaryOp[EARGOBJ] = MAXEXPR; - ComplementaryOp[ELOCOBJ] = MAXEXPR; - ComplementaryOp[ELABEL] = MAXEXPR; - ComplementaryOp[ESETCONST] = MAXEXPR; - ComplementaryOp[ENEWEXCEPTION] = MAXEXPR; - ComplementaryOp[ENEWEXCEPTIONARRAY] = MAXEXPR; - ComplementaryOp[EOBJLIST] = MAXEXPR; - ComplementaryOp[EMEMBER] = MAXEXPR; - ComplementaryOp[ETEMPLDEP] = MAXEXPR; - ComplementaryOp[EINSTRUCTION] = MAXEXPR; - ComplementaryOp[EDEFINE] = MAXEXPR; - ComplementaryOp[EREUSE] = MAXEXPR; - ComplementaryOp[EASSBLK] = MAXEXPR; - ComplementaryOp[EVECTOR128CONST] = MAXEXPR; - ComplementaryOp[ECONDASS] = MAXEXPR; -} - -void IRO_InitializeComplementaryOpLogicalArray(void) { - int i; - - for (i = 0; i < MAXEXPR; i++) - ComplementaryOpLogical[i] = MAXEXPR; - - ComplementaryOpLogical[EPOSTINC] = MAXEXPR; - ComplementaryOpLogical[EPOSTDEC] = MAXEXPR; - ComplementaryOpLogical[EPREINC] = MAXEXPR; - ComplementaryOpLogical[EPREDEC] = MAXEXPR; - ComplementaryOpLogical[EINDIRECT] = MAXEXPR; - ComplementaryOpLogical[EMONMIN] = MAXEXPR; - ComplementaryOpLogical[EBINNOT] = MAXEXPR; - ComplementaryOpLogical[ELOGNOT] = ELOGNOT; - ComplementaryOpLogical[EFORCELOAD] = MAXEXPR; - ComplementaryOpLogical[EMUL] = MAXEXPR; - ComplementaryOpLogical[EMULV] = MAXEXPR; - ComplementaryOpLogical[EDIV] = MAXEXPR; - ComplementaryOpLogical[EMODULO] = MAXEXPR; - ComplementaryOpLogical[EADDV] = MAXEXPR; - ComplementaryOpLogical[ESUBV] = MAXEXPR; - ComplementaryOpLogical[EADD] = MAXEXPR; - ComplementaryOpLogical[ESUB] = MAXEXPR; - ComplementaryOpLogical[ESHL] = MAXEXPR; - ComplementaryOpLogical[ESHR] = MAXEXPR; - ComplementaryOpLogical[ELESS] = EGREATEREQU; - ComplementaryOpLogical[EGREATER] = ELESSEQU; - ComplementaryOpLogical[ELESSEQU] = EGREATER; - ComplementaryOpLogical[EGREATEREQU] = ELESS; - ComplementaryOpLogical[EEQU] = ENOTEQU; - ComplementaryOpLogical[ENOTEQU] = EEQU; - ComplementaryOpLogical[EAND] = MAXEXPR; - ComplementaryOpLogical[EXOR] = MAXEXPR; - ComplementaryOpLogical[EOR] = MAXEXPR; - ComplementaryOpLogical[ELAND] = ELOR; - ComplementaryOpLogical[ELOR] = ELAND; - ComplementaryOpLogical[EASS] = MAXEXPR; - ComplementaryOpLogical[EMULASS] = MAXEXPR; - ComplementaryOpLogical[EDIVASS] = MAXEXPR; - ComplementaryOpLogical[EMODASS] = MAXEXPR; - ComplementaryOpLogical[EADDASS] = MAXEXPR; - ComplementaryOpLogical[ESUBASS] = MAXEXPR; - ComplementaryOpLogical[ESHLASS] = MAXEXPR; - ComplementaryOpLogical[ESHRASS] = MAXEXPR; - ComplementaryOpLogical[EANDASS] = MAXEXPR; - ComplementaryOpLogical[EXORASS] = MAXEXPR; - ComplementaryOpLogical[EORASS] = MAXEXPR; - ComplementaryOpLogical[ECOMMA] = MAXEXPR; - ComplementaryOpLogical[EPMODULO] = MAXEXPR; - ComplementaryOpLogical[EROTL] = MAXEXPR; - ComplementaryOpLogical[EROTR] = MAXEXPR; - ComplementaryOpLogical[EBCLR] = MAXEXPR; - ComplementaryOpLogical[EBTST] = MAXEXPR; - ComplementaryOpLogical[EBSET] = MAXEXPR; - ComplementaryOpLogical[ETYPCON] = MAXEXPR; - ComplementaryOpLogical[EBITFIELD] = MAXEXPR; - ComplementaryOpLogical[EINTCONST] = MAXEXPR; - ComplementaryOpLogical[EFLOATCONST] = MAXEXPR; - ComplementaryOpLogical[ESTRINGCONST] = MAXEXPR; - ComplementaryOpLogical[ECOND] = MAXEXPR; - ComplementaryOpLogical[EFUNCCALL] = MAXEXPR; - ComplementaryOpLogical[EFUNCCALLP] = MAXEXPR; - ComplementaryOpLogical[EOBJREF] = MAXEXPR; - ComplementaryOpLogical[EMFPOINTER] = MAXEXPR; - ComplementaryOpLogical[ENULLCHECK] = MAXEXPR; - ComplementaryOpLogical[EPRECOMP] = MAXEXPR; - ComplementaryOpLogical[ETEMP] = MAXEXPR; - ComplementaryOpLogical[EARGOBJ] = MAXEXPR; - ComplementaryOpLogical[ELOCOBJ] = MAXEXPR; - ComplementaryOpLogical[ELABEL] = MAXEXPR; - ComplementaryOpLogical[ESETCONST] = MAXEXPR; - ComplementaryOpLogical[ENEWEXCEPTION] = MAXEXPR; - ComplementaryOpLogical[ENEWEXCEPTIONARRAY] = MAXEXPR; - ComplementaryOpLogical[EOBJLIST] = MAXEXPR; - ComplementaryOpLogical[EMEMBER] = MAXEXPR; - ComplementaryOpLogical[ETEMPLDEP] = MAXEXPR; - ComplementaryOpLogical[EINSTRUCTION] = MAXEXPR; - ComplementaryOpLogical[EDEFINE] = MAXEXPR; - ComplementaryOpLogical[EREUSE] = MAXEXPR; - ComplementaryOpLogical[EASSBLK] = MAXEXPR; - ComplementaryOpLogical[EVECTOR128CONST] = MAXEXPR; - ComplementaryOpLogical[ECONDASS] = MAXEXPR; -} - -static void DoTransformations(IROLinear *nd) { - IROLinear *nd2; - IROLinear *nd3; - IROLinear *nd4; - IROLinear *nd5; - Type *newtype; - SInt32 value; - - if (nd->type == IROLinearOp2Arg) { - switch (nd->nodetype) { - case EASS: - nd2 = nd->u.diadic.right; - if ( - nd2->type == IROLinearOp2Arg && - AssignmentOp[nd2->nodetype] < MAXEXPR && - IRO_TypesEqual(nd->rtype, nd2->rtype) && - IRO_IsVariable(nd3 = nd->u.diadic.left) && - !(nd3->flags & IROLF_BitfieldIndirect) && - IRO_ExprsSame(nd3, nd2->u.diadic.left) - ) - { - nd->nodetype = AssignmentOp[nd2->nodetype]; - nd->u.diadic.right = nd2->u.diadic.right; - IRO_NopOut(nd2->u.diadic.left); - nd2->type = IROLinearNop; - - nd3->flags |= IROLF_Used; - nd3->u.diadic.left->flags |= IROLF_Used; - } - break; - - case EMUL: - if ( - IS_TYPE_INT(nd->rtype) && - IRO_IsPow2(nd->u.diadic.right, &value) - ) - { - nd->nodetype = ESHL; - CInt64_SetLong(&nd->u.diadic.right->u.node->data.intval, value); - } - break; - - case EDIV: - if ( - IS_TYPE_INT(nd->rtype) && - IRO_IsPow2(nd->u.diadic.right, &value) - ) - { - if (IRO_IsUnsignedType(nd->rtype)) { - nd->nodetype = ESHR; - CInt64_SetLong(&nd->u.diadic.right->u.node->data.intval, value); - } else if ( - !IRO_IsUnsignedType(nd->rtype) && - TYPE_INTEGRAL(nd->rtype)->integral != IT_BOOL && - nd->u.diadic.left->nodetype == ETYPCON && - IS_TYPE_INT(nd->u.diadic.left->u.monadic->rtype) && - IRO_IsUnsignedType(nd->u.diadic.left->u.monadic->rtype) && - nd->u.diadic.left->u.monadic->rtype->size < nd->u.diadic.left->rtype->size - ) - { - nd->nodetype = ESHR; - CInt64_SetLong(&nd->u.diadic.right->u.node->data.intval, value); - if (nd->flags & IROLF_Reffed) { - IROLinear *copy = IRO_NewLinear(IROLinearOp1Arg); - memcpy(copy, nd, sizeof(IROLinear)); - copy->type = IROLinearOp1Arg; - copy->nodetype = ETYPCON; - copy->index = IRO_NumLinear++; - copy->rtype = nd->rtype; - IRO_PasteAfter(copy, copy, nd); - IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, copy); - copy->u.monadic = nd; - nd->flags |= IROLF_Reffed; - } - nd->rtype = IRO_UnsignedType(nd->rtype); - newtype = IRO_UnsignedType(nd->u.diadic.right->rtype); - nd->u.diadic.right->u.node->rtype = newtype; - nd->u.diadic.right->rtype = newtype; - nd->u.diadic.left->rtype = IRO_UnsignedType(nd->u.diadic.left->rtype); - } - } - break; - - case EMODULO: - if ( - IS_TYPE_INT(nd->rtype) && - IRO_IsUnsignedType(nd->rtype) && - IRO_IsPow2(nd->u.diadic.right, &value) - ) - { - nd->nodetype = EAND; - nd->u.diadic.right->u.node->data.intval = CInt64_Sub(nd->u.diadic.right->u.node->data.intval, cint64_one); - } - break; - - case EEQU: - if ( - (nd2 = IRO_LocateFather(nd)) && - nd2->nodetype == ETYPCON && - IS_TYPE_INT(nd2->rtype) && - (nd3 = IRO_LocateFather(nd2)) && - nd3->nodetype == ELOGNOT && - (nd4 = IRO_LocateFather(nd3)) && - nd4->nodetype == ETYPCON && - IS_TYPE_INT(nd4->rtype) && - ( - ((nd5 = IRO_LocateFather(nd4)) && nd5->type == IROLinearIf) || - nd5->type == IROLinearIfNot - ) - ) - { - IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd4, nd); - nd->nodetype = ENOTEQU; - nd2->type = IROLinearNop; - nd3->type = IROLinearNop; - nd4->type = IROLinearNop; - } - break; - } - } -} - -static void IRO_SwitchChildren(IROLinear *nd) { - IROLinear *tmp = nd->u.diadic.left; - nd->u.diadic.left = nd->u.diadic.right; - nd->u.diadic.right = tmp; -} - -static void ReplaceExprWithConst(IROLinear *nd, CInt64 val) { - IRO_NopOut(nd); - nd->type = IROLinearOperand; - nd->nodetype = EINTCONST; - nd->u.node = IRO_NewENode(EINTCONST); - nd->u.node->data.intval = val; - nd->u.node->flags = nd->nodeflags; - nd->u.node->rtype = nd->rtype; - - if (IS_TYPE_FLOAT(nd->rtype)) { - nd->u.node->type = EFLOATCONST; - nd->nodetype = EFLOATCONST; - nd->u.node->data.floatval = CMach_CalcFloatConvertFromInt(TYPE(&stsignedlong), val); - } -} - -static void ReplaceExprWithLeftChild(IROLinear *nd) { - IROLinear *left = nd->u.diadic.left; - IROLinear *right = nd->u.diadic.right; - - if (left->rtype == nd->rtype) { - IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, left); - left->flags = nd->flags; - left->nodeflags = nd->nodeflags; - nd->type = IROLinearNop; - IRO_NopOut(right); - } else { - nd->type = IROLinearOp1Arg; - nd->nodetype = ETYPCON; - nd->u.monadic = left; - IRO_NopOut(right); - } -} - -static void ReplaceExprWithRightChild(IROLinear *nd) { - IROLinear *left = nd->u.diadic.left; - IROLinear *right = nd->u.diadic.right; - - if (right->rtype == nd->rtype) { - IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, right); - right->flags = nd->flags; - right->nodeflags = nd->nodeflags; - nd->type = IROLinearNop; - IRO_NopOut(left); - } else { - nd->type = IROLinearOp1Arg; - nd->nodetype = ETYPCON; - nd->u.monadic = right; - IRO_NopOut(left); - } -} - -static void ReplaceExprWithMonaminRight(IROLinear *nd) { - IROLinear *left = nd->u.diadic.left; - IROLinear *right = nd->u.diadic.right; - - if (right->rtype == nd->rtype) { - nd->type = IROLinearOp1Arg; - nd->nodetype = EMONMIN; - nd->u.monadic = right; - IRO_NopOut(left); - } else { - IRO_NopOut(left); - left->type = IROLinearOp1Arg; - left->nodetype = ETYPCON; - left->expr = right->expr; - left->rtype = nd->rtype; - left->u.monadic = right; - nd->type = IROLinearOp1Arg; - nd->nodetype = EMONMIN; - nd->u.monadic = left; - } -} - -static void ReplaceExprWithMonaminLeft(IROLinear *nd) { - IROLinear *left = nd->u.diadic.left; - IROLinear *right = nd->u.diadic.right; - - if (left->rtype == nd->rtype) { - nd->type = IROLinearOp1Arg; - nd->nodetype = EMONMIN; - nd->u.monadic = left; - IRO_NopOut(right); - } else { - IRO_NopOut(right); - right->type = IROLinearOp1Arg; - right->nodetype = ETYPCON; - right->expr = left->expr; - right->rtype = nd->rtype; - right->u.monadic = left; - nd->type = IROLinearOp1Arg; - nd->nodetype = EMONMIN; - nd->u.monadic = right; - } -} - -static void switchFatherLeftMonadic(IROLinear *nd) { - IROLinear *inner = nd->u.monadic; - IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, inner); - nd->u.monadic = inner->u.monadic; - inner->u.monadic = nd; - inner->rtype = nd->rtype; - inner->flags = nd->flags; - inner->nodeflags = nd->nodeflags; - IRO_CutAndPasteAfter(inner, inner, nd); -} - -static void switchFatherLeft(IROLinear *nd, int isRight) { - IROLinear *a; - IROLinear *b; - - a = nd->u.diadic.left; - IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, a); - - if (isRight) { - nd->u.diadic.left = a->u.diadic.left; - a->u.diadic.left = nd; - b = a->u.diadic.right; - } else { - nd->u.diadic.left = a->u.diadic.right; - a->u.diadic.right = nd; - b = a->u.diadic.left; - } - - a->rtype = nd->rtype; - a->flags = nd->flags; - a->nodeflags = nd->nodeflags; - IRO_CutAndPasteAfter(a, a, nd); - IRO_CutAndPasteAfter(IRO_FindFirst(b), b, nd); -} - -static void PickCommonsubAtLeftLeft(IROLinear *nd) { - switchFatherLeft(nd, 0); - ReplaceExprWithRightChild(nd->u.diadic.right); -} - -static void PickCommonsubAtRightLeft(IROLinear *nd) { - switchFatherLeft(nd, 1); - ReplaceExprWithRightChild(nd->u.diadic.right); -} - -static void PickCommonsubAtLeftRight(IROLinear *nd) { - switchFatherLeft(nd, 0); - ReplaceExprWithLeftChild(nd->u.diadic.right); -} - -static void PickCommonsubAtRightRight(IROLinear *nd) { - switchFatherLeft(nd, 1); - ReplaceExprWithLeftChild(nd->u.diadic.right); -} - -static void DoTransformations11(IROLinear *nd) { - IROLinear *left; - IROLinear *right; - int changed; - int compare; - Type *type; - SInt32 tmp1; - SInt32 tmp2; - CInt64 val; - - if (nd->type == IROLinearOp2Arg) { - left = nd->u.diadic.left; - right = nd->u.diadic.right; - if (IS_TYPE_FLOAT(nd->rtype) || IS_TYPE_FLOAT(left->rtype) || IS_TYPE_FLOAT(right->rtype)) - return; - - changed = 0; - if (!IRO_HasSideEffect(left) && !IRO_HasSideEffect(right)) { - if (IRO_IsIntConstant(right) || IRO_IsFloatConstant(right)) { - if (IRO_IsConstantZero(right)) { - switch (nd->nodetype) { - case EADDV: - case ESUBV: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case EXOR: - case EOR: - case ELOR: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EXORASS: - case EORASS: - ReplaceExprWithLeftChild(nd); - changed = 1; - break; - case EMUL: - case EAND: - case ELAND: - ReplaceExprWithConst(nd, cint64_zero); - changed = 1; - break; - case EMULASS: - case EANDASS: - nd->nodetype = EASS; - nd->u.diadic.right->rtype = nd->rtype; - nd->u.diadic.right->u.node->rtype = nd->rtype; - changed = 1; - break; - case EDIV: - case EMODULO: - case EDIVASS: - case EMODASS: - if (nd->stmt->sourceoffset) { - TStreamElement *token = CPrep_CurStreamElement(); - token->tokenoffset = nd->stmt->sourceoffset; - CError_SetErrorToken(token); - } - CError_Warning(CErrorStr139); - break; - } - } else if (nd->nodetype == ELAND) { - ReplaceExprWithLeftChild(nd); - changed = 1; - } else if (nd->nodetype == ELOR) { - ReplaceExprWithConst(nd, cint64_one); - changed = 1; - } else if (nd->nodetype == ESHL || nd->nodetype == ESHR || nd->nodetype == ESHLASS || nd->nodetype == ESHRASS) { - type = nd->rtype; - tmp1 = type->size * 8; - if (left->type == IROLinearOp1Arg && left->nodetype == ETYPCON) { - type = left->u.monadic->rtype; - if ( - left->u.monadic->type == IROLinearOp1Arg && - left->u.monadic->nodetype == EINDIRECT && - left->u.monadic->u.monadic->type == IROLinearOp1Arg && - left->u.monadic->u.monadic->nodetype == EBITFIELD && - IS_TYPE_BITFIELD(left->u.monadic->u.monadic->rtype) - ) - tmp2 = TYPE_BITFIELD(left->u.monadic->u.monadic->rtype)->bitlength; - else - tmp2 = type->size * 8; - } else { - tmp2 = tmp1; - } - - switch (nd->nodetype) { - case ESHL: - case ESHLASS: - CInt64_SetLong(&val, tmp1); - if (IRO_IsUnsignedType(type)) - compare = CInt64_GreaterEqualU(right->u.node->data.intval, val); - else - compare = CInt64_GreaterEqual(right->u.node->data.intval, val); - break; - case ESHR: - case ESHRASS: - CInt64_SetLong(&val, tmp2); - compare = IRO_IsUnsignedType(type) && CInt64_GreaterEqualU(right->u.node->data.intval, val); - break; - } - - if (compare) { - switch (nd->nodetype) { - case ESHL: - case ESHR: - ReplaceExprWithConst(nd, cint64_zero); - break; - case ESHLASS: - case ESHRASS: - nd->nodetype = EASS; - ReplaceExprWithConst(right, cint64_zero); - break; - } - changed = 1; - } - } else if (IRO_IsConstantOne(right)) { - switch (nd->nodetype) { - case EMUL: - case EMULV: - case EDIV: - case EMULASS: - case EDIVASS: - ReplaceExprWithLeftChild(nd); - changed = 1; - break; - case EMODULO: - ReplaceExprWithConst(nd, cint64_zero); - changed = 1; - break; - case EMODASS: - nd->nodetype = EASS; - ReplaceExprWithConst(right, cint64_zero); - nd->u.diadic.right->rtype = nd->rtype; - nd->u.diadic.right->u.node->rtype = nd->rtype; - changed = 1; - break; - } - } else if (IRO_IsConstantNegativeOne(right)) { - switch (nd->nodetype) { - case EMUL: - case EMULV: - case EDIV: - ReplaceExprWithMonaminLeft(nd); - changed = 1; - break; - case EMODULO: - ReplaceExprWithConst(nd, cint64_zero); - changed = 1; - break; - case EMODASS: - nd->nodetype = EASS; - ReplaceExprWithConst(right, cint64_zero); - nd->u.diadic.right->rtype = nd->rtype; - nd->u.diadic.right->u.node->rtype = nd->rtype; - changed = 1; - break; - } - } - } - - if (!changed && (IRO_IsIntConstant(left) || IRO_IsFloatConstant(left))) { - if (IRO_IsConstantZero(left)) { - switch (nd->nodetype) { - case EADDV: - case EADD: - case EXOR: - case EOR: - case ELOR: - ReplaceExprWithRightChild(nd); - break; - case EMUL: - case ESHL: - case ESHR: - case EAND: - case ELAND: - ReplaceExprWithConst(nd, cint64_zero); - break; - case ESUBV: - case ESUB: - ReplaceExprWithMonaminRight(nd); - break; - } - } else if (nd->nodetype == ELAND) { - ReplaceExprWithRightChild(nd); - } else if (nd->nodetype == ELOR) { - ReplaceExprWithConst(nd, cint64_one); - } else if (IRO_IsConstantOne(left)) { - switch (nd->nodetype) { - case EMUL: - case EMULV: - ReplaceExprWithRightChild(nd); - break; - } - } else if (IRO_IsConstantNegativeOne(left)) { - switch (nd->nodetype) { - case EMUL: - case EMULV: - ReplaceExprWithMonaminRight(nd); - break; - } - } - } - } - } -} - -static void DoTransformations12(IROLinear *nd) { - IROLinear *left; - IROLinear *right; - - if (nd->type == IROLinearOp2Arg) { - left = nd->u.diadic.left; - right = nd->u.diadic.right; - if (IS_TYPE_FLOAT(nd->rtype) || IS_TYPE_FLOAT(left->rtype) || IS_TYPE_FLOAT(right->rtype)) - return; - - if (IRO_ExprsSameSemantically(left, right) && !IRO_HasSideEffect(left)) { - switch (nd->nodetype) { - case ESUBV: - case ESUB: - case ELESS: - case EGREATER: - case ENOTEQU: - case EXOR: - ReplaceExprWithConst(nd, cint64_zero); - break; - case ELESSEQU: - case EGREATEREQU: - case EEQU: - ReplaceExprWithConst(nd, cint64_one); - break; - case EAND: - case EOR: - case ELAND: - case ELOR: - case EASS: - case EANDASS: - case EORASS: - ReplaceExprWithLeftChild(nd); - break; - case ESUBASS: - case EXORASS: - nd->nodetype = EASS; - ReplaceExprWithConst(right, cint64_zero); - break; - } - } - } -} - -static void DoTransformations13(IROLinear *nd) { - IROLinear *left; - IROLinear *right; - IROLinear *left2; - IROLinear *right2; - IROListNode *tmp; - IROListNode *leftlist; - IROListNode *rightlist; - - if (nd->type == IROLinearOp2Arg) { - left = nd->u.diadic.left; - right = nd->u.diadic.right; - - if ( - !IRO_HasSideEffect(left) && - !IRO_HasSideEffect(right) && - (nd->nodetype == EEQU || nd->nodetype == ENOTEQU) && - PointerAnalysis_IsLinearNodePointerExprDefinite(FunctionName, left) && - PointerAnalysis_IsLinearNodePointerExprDefinite(FunctionName, right) - ) - { - leftlist = NULL; - PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, left, &leftlist); - if (leftlist) { - if (leftlist->list.head && leftlist->list.tail && !leftlist->nextList) { - rightlist = NULL; - PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, right, &rightlist); - if (rightlist) { - if (rightlist->list.head && rightlist->list.tail && !rightlist->nextList) { - left2 = leftlist->list.tail; - right2 = rightlist->list.tail; - if (IRO_ExprsSameSemantically(left2, right2)) { - ReplaceExprWithConst(nd, (nd->nodetype == EEQU) ? cint64_one : cint64_zero); - } else if (left2->type == right2->type && IRO_TypesEqual(left2->rtype, right2->rtype)) { - ReplaceExprWithConst(nd, (nd->nodetype == EEQU) ? cint64_zero : cint64_one); - } - } - - while (rightlist) { - tmp = rightlist->nextList; - IRO_free(rightlist); - rightlist = tmp; - } - } - } - - while (leftlist) { - tmp = leftlist->nextList; - IRO_free(leftlist); - leftlist = tmp; - } - } - } - } -} - -static void DoTransformations21(IROLinear *nd) { - IROLinear *left; - IROLinear *right; - Boolean changed; - - if (nd->type == IROLinearOp2Arg) { - left = nd->u.diadic.left; - right = nd->u.diadic.right; - - if (left->type == IROLinearOp1Arg && right->type == IROLinearOp1Arg && left->nodetype == right->nodetype) { - switch (left->nodetype) { - case EMONMIN: - case EBINNOT: - case ELOGNOT: - changed = 0; - switch (nd->nodetype) { - case EXOR: - if (left->nodetype == EBINNOT) - goto collapse; - break; - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - if (left->nodetype == EMONMIN) { - nd->nodetype = ComplementaryOp[nd->nodetype]; - goto collapse; - } - break; - case EMUL: - case EDIV: - if (left->nodetype == EMONMIN) - goto collapse; - break; - case EEQU: - case ENOTEQU: - if (left->nodetype != ELOGNOT) { - collapse: - nd->u.diadic.left = left->u.monadic; - nd->u.diadic.right = right->u.monadic; - left->type = right->type = IROLinearNop; - changed = 1; - } - break; - case ELAND: - case ELOR: - if (left->nodetype == ELOGNOT) { - nd->nodetype = ComplementaryOp[nd->nodetype]; - goto switchfather; - } - break; - case EAND: - case EOR: - if ( - !IS_TYPE_FLOAT(nd->rtype) && - !IS_TYPE_FLOAT(left->rtype) && - !IS_TYPE_FLOAT(right->rtype) && - left->nodetype != EMONMIN - ) - { - nd->nodetype = ComplementaryOp[nd->nodetype]; - goto switchfather; - } - break; - case EADD: - case ESUB: - if ( - !IS_TYPE_FLOAT(nd->rtype) && - !IS_TYPE_FLOAT(left->rtype) && - !IS_TYPE_FLOAT(right->rtype) && - left->nodetype == EMONMIN - ) - { - switchfather: - switchFatherLeftMonadic(nd); - nd->u.diadic.right = right->u.monadic; - right->type = IROLinearNop; - changed = 1; - } - break; - } - - if (changed) { - DoTransformations(nd); - DoTransformations11(nd); - DoTransformations12(nd); - DoTransformations13(nd); - } - break; - } - } - } -} - -static void DoTransformations22(IROLinear *nd) { - IROLinear *left; - IROLinear *right; - IROLinear *ndtmp; - - if (nd->type == IROLinearOp2Arg) { - left = nd->u.diadic.left; - right = nd->u.diadic.right; - if (IS_TYPE_FLOAT(nd->rtype) || IS_TYPE_FLOAT(left->rtype) || IS_TYPE_FLOAT(right->rtype)) - return; - - if (!IRO_HasSideEffect(left) && !IRO_HasSideEffect(right)) { - if (left->type == IROLinearOp1Arg && left->nodetype == EMONMIN) { - switch (nd->nodetype) { - case ESUB: - case ESUBV: - nd->nodetype = ComplementaryOp[nd->nodetype]; - switchFatherLeftMonadic(nd); - break; - - case EADD: - case EADDV: - nd->nodetype = ComplementaryOp[nd->nodetype]; - nd->u.diadic.left = right; - nd->u.diadic.right = left->u.monadic; - left->type = IROLinearNop; - DoTransformations(nd); - DoTransformations12(nd); - DoTransformations21(nd); - break; - - case EDIV: - if (IRO_ExprsSameSemantically(left->u.monadic, right)) - ReplaceExprWithConst(nd, cint64_negone); - break; - } - } else { - ndtmp = NULL; - if (left->type == IROLinearOp1Arg && IRO_ExprsSameSemantically(left->u.monadic, right)) - ndtmp = left; - else if (right->type == IROLinearOp1Arg && IRO_ExprsSameSemantically(left, right->u.monadic)) - ndtmp = right; - - if (ndtmp) { - switch (nd->nodetype) { - case EAND: - if (ndtmp->nodetype == EBINNOT || ndtmp->nodetype == ELOGNOT) - ReplaceExprWithConst(nd, cint64_zero); - break; - - case EANDASS: - if (ndtmp->nodetype == EBINNOT || ndtmp->nodetype == ELOGNOT) { - nd->nodetype = EASS; - ReplaceExprWithConst(right, cint64_zero); - nd->u.diadic.right->rtype = nd->rtype; - nd->u.diadic.right->u.node->rtype = nd->rtype; - } - break; - - case EXOR: - case EOR: - if (ndtmp->nodetype == EBINNOT) { - ReplaceExprWithConst(nd, cint64_zero); - nd->u.node->data.intval = CInt64_Inv(nd->u.node->data.intval); - } - break; - - case EXORASS: - case EORASS: - if (ndtmp->nodetype == EBINNOT) { - nd->nodetype = EASS; - ReplaceExprWithConst(right, cint64_zero); - right->u.node->data.intval = CInt64_Inv(right->u.node->data.intval); - nd->u.diadic.right->rtype = nd->rtype; - nd->u.diadic.right->u.node->rtype = nd->rtype; - } - break; - - case ELOR: - if (ndtmp->nodetype == EBINNOT || ndtmp->nodetype == ELOGNOT) - ReplaceExprWithConst(nd, cint64_one); - break; - - case ELAND: - if (ndtmp->nodetype == ELOGNOT) - ReplaceExprWithConst(nd, cint64_zero); - break; - - case EDIV: - if (ndtmp->nodetype == EMONMIN) - ReplaceExprWithConst(nd, cint64_negone); - break; - - case EDIVASS: - if (ndtmp->nodetype == EMONMIN) { - nd->nodetype = EASS; - ReplaceExprWithConst(right, cint64_negone); - nd->u.diadic.right->rtype = nd->rtype; - nd->u.diadic.right->u.node->rtype = nd->rtype; - } - break; - } - } - } - } - } -} - -static void DoTransformations23(IROLinear *nd) { - Boolean changed; - Boolean isCompare; - UInt8 which; - IROLinear *left; - IROLinear *right; - CInt64 size; - CInt64 val; - - if (nd->type == IROLinearOp2Arg && !IRO_HasSideEffect(nd)) { - left = nd->u.diadic.left; - right = nd->u.diadic.right; - if (IS_TYPE_FLOAT(nd->rtype) || IS_TYPE_FLOAT(left->rtype) || IS_TYPE_FLOAT(right->rtype)) - return; - - isCompare = 0; - changed = 0; - which = 0; - - switch (nd->nodetype) { - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - isCompare = 1; - case EADDV: - case EADD: - case EEQU: - case ENOTEQU: - case EAND: - case EOR: - if (left->type == IROLinearOp2Arg) { - if (IRO_ExprsSameSemantically(right, left->u.diadic.left)) - which = 1; - else if (IRO_ExprsSameSemantically(right, left->u.diadic.right)) - which = 2; - - if (which) { - if (isCompare) - nd->nodetype = ComplementaryOp[nd->nodetype]; - IRO_SwitchChildren(nd); - left = nd->u.diadic.left; - right = nd->u.diadic.right; - break; - } - } - case ESUBV: - case ESUB: - case EADDASS: - case ESUBASS: - case EANDASS: - case EORASS: - if (right->type == IROLinearOp2Arg) { - if (IRO_ExprsSameSemantically(left, right->u.diadic.left)) - which = 1; - else if (IRO_ExprsSameSemantically(left, right->u.diadic.right)) - which = 2; - } - break; - - default: - goto done; - } - - if (which) { - switch (right->nodetype) { - case EAND: - case EOR: - if (which == 2) - IRO_SwitchChildren(right); - - if ( - nd->nodetype == right->nodetype || - (nd->nodetype == EANDASS && right->nodetype == EAND) || - (nd->nodetype == EORASS && right->nodetype == EOR) - ) - { - ReplaceExprWithRightChild(right); - changed = 1; - } - else if ( - nd->nodetype == ComplementaryOp[right->nodetype] || - (nd->nodetype == EANDASS && right->nodetype == EOR) || - (nd->nodetype == EORASS && right->nodetype == EAND) - ) - { - ReplaceExprWithLeftChild(nd); - } - break; - - case EADD: - if (which == 2) - IRO_SwitchChildren(right); - - switch (nd->nodetype) { - case EEQU: - case ENOTEQU: - ReplaceExprWithConst(left, cint64_zero); - ReplaceExprWithRightChild(right); - IRO_SwitchChildren(nd); - if (isCompare) - nd->nodetype = ComplementaryOp[nd->nodetype]; - changed = 1; - break; - - case ESUB: - case ESUBV: - ReplaceExprWithRightChild(right); - ReplaceExprWithMonaminRight(nd); - changed = 1; - break; - - case ESUBASS: - ReplaceExprWithRightChild(right); - changed = 1; - break; - } - break; - - case ESUB: - switch (nd->nodetype) { - case EEQU: - case ENOTEQU: - if (which == 1) { - ReplaceExprWithConst(left, cint64_zero); - ReplaceExprWithRightChild(right); - IRO_SwitchChildren(nd); - } - break; - case EADD: - case EADDV: - if (which == 2) { - ReplaceExprWithLeftChild(right); - ReplaceExprWithRightChild(nd); - } - break; - case ESUB: - case ESUBV: - if (which == 1) { - ReplaceExprWithRightChild(right); - ReplaceExprWithRightChild(nd); - } - break; - case EADDASS: - if (which == 2) { - nd->nodetype = EASS; - ReplaceExprWithLeftChild(right); - changed = 1; - } - break; - case ESUBASS: - if (which == 1) { - nd->nodetype = EASS; - ReplaceExprWithRightChild(right); - changed = 1; - } - break; - } - break; - } - } - - done: - if (!changed) { - switch (nd->nodetype) { - case ESUB: - case ESUBV: - which = 0; - if (left->type == IROLinearOp2Arg) { - if (IRO_ExprsSameSemantically(right, left->u.diadic.left)) - which = 1; - else if (IRO_ExprsSameSemantically(right, left->u.diadic.right)) - which = 2; - } - - if (which == 1) { - if (left->nodetype == ESUB) { - ReplaceExprWithMonaminRight(left); - ReplaceExprWithLeftChild(nd); - } else if (left->nodetype == EADD) { - ReplaceExprWithRightChild(left); - ReplaceExprWithLeftChild(nd); - } - } else if (which == 2) { - if (left->nodetype == EADD) { - ReplaceExprWithLeftChild(left); - ReplaceExprWithLeftChild(nd); - } - } - break; - } - - switch (nd->nodetype) { - case ESHL: - case ESHR: - case ESHLASS: - case ESHRASS: - which = 0; - if (left->type == IROLinearOp2Arg) { - if (left->nodetype == ComplementaryOp[nd->nodetype] || left->nodetype == AssignmentOp[ComplementaryOp[nd->nodetype]]) { - if (IRO_IsIntConstant(right) && IRO_ExprsSameSemantically(right, left->u.diadic.right)) - which = 2; - } - } - - if (which == 2) { - val = right->u.node->data.intval; - if (left->nodetype == ESHR || left->nodetype == ESHRASS) { - ReplaceExprWithLeftChild(left); - nd->nodetype = (nd->nodetype == ESHL) ? EAND : EANDASS; - right->u.node->data.intval = CInt64_Shl(cint64_negone, val); - changed = 1; - } else if (IRO_IsUnsignedType(nd->rtype)) { - ReplaceExprWithLeftChild(left); - nd->nodetype = (nd->nodetype == ESHR) ? EAND : EANDASS; - if (nd->rtype->size < 8) { - CInt64_SetLong(&size, 64 - 8 * nd->rtype->size); - val = CInt64_Add(val, size); - } - right->u.node->data.intval = CInt64_ShrU(cint64_negone, val); - changed = 1; - } - } - break; - } - } - - if (changed) { - DoTransformations(nd); - DoTransformations11(nd); - DoTransformations12(nd); - DoTransformations13(nd); - DoTransformations21(nd); - DoTransformations22(nd); - DoTransformations23(nd); - } - } -} - -static void DoTransformations24(IROLinear *nd) { - IROLinear *left; - IROLinear *right; - UInt8 changed; - - if (nd->type == IROLinearOp2Arg) { - left = nd->u.diadic.left; - right = nd->u.diadic.right; - if (IS_TYPE_FLOAT(nd->rtype) || IS_TYPE_FLOAT(left->rtype) || IS_TYPE_FLOAT(right->rtype)) - return; - - if (left->type == IROLinearOp2Arg && right->type == IROLinearOp2Arg && !IRO_HasSideEffect(nd)) { - changed = 0; - - if (IRO_ExprsSameSemantically(left->u.diadic.left, right->u.diadic.left)) { - if (left->nodetype == right->nodetype) { - switch (left->nodetype) { - case EADD: - if (nd->nodetype == ComplementaryOp[left->nodetype]) { - ReplaceExprWithRightChild(left); - ReplaceExprWithRightChild(right); - changed = 1; - } - break; - case ESUB: - if (nd->nodetype == ESUB || nd->nodetype == ESUBV) { - ReplaceExprWithRightChild(left); - ReplaceExprWithRightChild(right); - IRO_SwitchChildren(nd); - changed = 1; - } - break; - case EMUL: - switch (nd->nodetype) { - case EADD: - case ESUB: - PickCommonsubAtLeftLeft(nd); - changed = 3; - break; - } - break; - case EAND: - if (nd->nodetype == EXOR) { - PickCommonsubAtLeftLeft(nd); - changed = 3; - break; - } - case EOR: - if (nd->nodetype == left->nodetype) { - ReplaceExprWithRightChild(left); - changed = 1; - } else if (nd->nodetype == ComplementaryOp[left->nodetype]) { - PickCommonsubAtLeftLeft(nd); - changed = 3; - } - break; - } - } else if (left->nodetype == ComplementaryOp[right->nodetype]) { - switch (nd->nodetype) { - case ESUB: - case ESUBV: - switch (left->nodetype) { - case EADD: - nd->nodetype = ComplementaryOp[nd->nodetype]; - ReplaceExprWithRightChild(left); - ReplaceExprWithRightChild(right); - changed = 1; - break; - case ESUB: - ReplaceExprWithMonaminRight(left); - ReplaceExprWithRightChild(right); - changed = 1; - break; - } - break; - - case EAND: - case EOR: - if (left->nodetype == nd->nodetype) - ReplaceExprWithLeftChild(nd); - else if (right->nodetype == nd->nodetype) - ReplaceExprWithRightChild(nd); - break; - } - } - } else if (IRO_ExprsSameSemantically(left->u.diadic.right, right->u.diadic.left)) { - if (left->nodetype == right->nodetype) { - switch (left->nodetype) { - case EADD: - if (nd->nodetype == ComplementaryOp[left->nodetype]) { - ReplaceExprWithLeftChild(left); - ReplaceExprWithRightChild(right); - changed = 1; - } - break; - case EMUL: - switch (nd->nodetype) { - case EADD: - case ESUB: - PickCommonsubAtRightLeft(nd); - changed = 3; - break; - } - break; - case EAND: - if (nd->nodetype == EXOR) { - PickCommonsubAtRightLeft(nd); - changed = 3; - break; - } - case EOR: - if (nd->nodetype == left->nodetype) { - ReplaceExprWithLeftChild(left); - changed = 1; - } else if (nd->nodetype == ComplementaryOp[left->nodetype]) { - PickCommonsubAtRightLeft(nd); - changed = 3; - } - break; - } - } else if (left->nodetype == ComplementaryOp[right->nodetype]) { - switch (nd->nodetype) { - case ESUB: - case ESUBV: - if (left->nodetype == EADD) { - nd->nodetype = ComplementaryOp[nd->nodetype]; - ReplaceExprWithLeftChild(left); - ReplaceExprWithRightChild(right); - changed = 1; - } - break; - - case EADD: - case EADDV: - if (left->nodetype == ESUB) { - ReplaceExprWithLeftChild(left); - ReplaceExprWithRightChild(right); - changed = 1; - } - break; - - case EAND: - case EOR: - if (left->nodetype == nd->nodetype) - ReplaceExprWithLeftChild(nd); - else if (right->nodetype == nd->nodetype) - ReplaceExprWithRightChild(nd); - break; - } - } - } else if (IRO_ExprsSameSemantically(left->u.diadic.left, right->u.diadic.right)) { - if (left->nodetype == right->nodetype) { - switch (left->nodetype) { - case EADD: - if (nd->nodetype == ComplementaryOp[left->nodetype]) { - ReplaceExprWithRightChild(left); - ReplaceExprWithLeftChild(right); - changed = 1; - } - break; - case ESUB: - switch (nd->nodetype) { - case EADDV: - case EADD: - nd->nodetype = ComplementaryOp[nd->nodetype]; - ReplaceExprWithRightChild(left); - ReplaceExprWithLeftChild(right); - IRO_SwitchChildren(nd); - changed = 1; - break; - } - break; - case EMUL: - switch (nd->nodetype) { - case EADD: - case ESUB: - PickCommonsubAtLeftRight(nd); - changed = 2; - break; - } - break; - case EAND: - if (nd->nodetype == EXOR) { - PickCommonsubAtLeftRight(nd); - changed = 2; - break; - } - case EOR: - if (nd->nodetype == left->nodetype) { - ReplaceExprWithRightChild(left); - changed = 1; - } else if (nd->nodetype == ComplementaryOp[left->nodetype]) { - PickCommonsubAtLeftRight(nd); - changed = 2; - } - break; - } - } else if (left->nodetype == ComplementaryOp[right->nodetype]) { - switch (nd->nodetype) { - case EADD: - case EADDV: - if (left->nodetype == EADD) { - ReplaceExprWithRightChild(left); - ReplaceExprWithLeftChild(right); - changed = 1; - } - break; - - case ESUB: - case ESUBV: - if (left->nodetype == ESUB) { - ReplaceExprWithMonaminRight(left); - ReplaceExprWithRightChild(right); - changed = 1; - } - break; - - case EAND: - case EOR: - if (left->nodetype == nd->nodetype) - ReplaceExprWithLeftChild(nd); - else if (right->nodetype == nd->nodetype) - ReplaceExprWithRightChild(nd); - break; - } - } - } else if (IRO_ExprsSameSemantically(left->u.diadic.right, right->u.diadic.right)) { - if (left->nodetype == right->nodetype) { - switch (nd->nodetype) { - case ESUB: - switch (left->nodetype) { - case EADD: - case ESUB: - ReplaceExprWithLeftChild(left); - ReplaceExprWithLeftChild(right); - changed = 1; - } - case EADD: - switch (left->nodetype) { - case EMUL: - case ESHL: - PickCommonsubAtRightRight(nd); - changed = 2; - break; - } - break; - case EXOR: - switch (left->nodetype) { - case ESHL: - case ESHR: - case EAND: - PickCommonsubAtRightRight(nd); - changed = 2; - break; - } - break; - case EAND: - case EOR: - if (left->nodetype == nd->nodetype) { - ReplaceExprWithLeftChild(right); - changed = 1; - } else if ( - left->nodetype == ComplementaryOp[nd->nodetype] || - left->nodetype == ESHR || - left->nodetype == ESHL - ) - { - PickCommonsubAtRightRight(nd); - changed = 2; - } - break; - } - } else if (left->nodetype == ComplementaryOp[right->nodetype]) { - switch (nd->nodetype) { - case EADD: - case EADDV: - switch (left->nodetype) { - case EADD: - case ESUB: - ReplaceExprWithLeftChild(left); - ReplaceExprWithLeftChild(right); - changed = 1; - break; - } - break; - - case EAND: - case EOR: - if (left->nodetype == nd->nodetype) - ReplaceExprWithLeftChild(nd); - else if (right->nodetype == nd->nodetype) - ReplaceExprWithRightChild(nd); - break; - } - } - } - - if (changed) { - DoDiadic(nd); - if (changed == 2) - DoDiadic(nd->u.diadic.left); - else if (changed == 3) - DoDiadic(nd->u.diadic.right); - IRO_Dump("remove common op at: %d\n", nd->index); - } - } - } -} - -static void DoTransformations25(IROLinear *nd) { - int changed = 0; - IROLinear *left; - IROLinear *right; - - if (nd->type == IROLinearOp2Arg) { - left = nd->u.diadic.left; - right = nd->u.diadic.right; - - if ( - (left->type == IROLinearOp2Arg && (IS_TYPE_FLOAT(left->u.diadic.left->rtype) || IS_TYPE_FLOAT(left->u.diadic.right->rtype))) || - (right->type == IROLinearOp2Arg && (IS_TYPE_FLOAT(right->u.diadic.left->rtype) || IS_TYPE_FLOAT(right->u.diadic.right->rtype))) - ) - return; - - switch (left->nodetype) { - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - switch (nd->nodetype) { - case EEQU: - if (IRO_IsConstantOne(right)) { - ReplaceExprWithLeftChild(nd); - changed = 1; - } else if (IRO_IsConstantZero(right)) { - left->nodetype = ComplementaryOpLogical[left->nodetype]; - ReplaceExprWithLeftChild(nd); - changed = 1; - } - break; - case ENOTEQU: - if (IRO_IsConstantOne(right)) { - left->nodetype = ComplementaryOpLogical[left->nodetype]; - ReplaceExprWithLeftChild(nd); - changed = 1; - } else if (IRO_IsConstantZero(right)) { - ReplaceExprWithLeftChild(nd); - changed = 1; - } - break; - } - break; - case ELAND: - case ELOR: - switch (nd->nodetype) { - case EEQU: - if (IRO_IsConstantOne(right)) { - ReplaceExprWithLeftChild(nd); - changed = 1; - } - break; - case ENOTEQU: - if (IRO_IsConstantZero(right)) { - ReplaceExprWithLeftChild(nd); - changed = 1; - } - break; - } - break; - } - - if (!changed) { - switch (right->nodetype) { - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - switch (nd->nodetype) { - case EEQU: - if (IRO_IsConstantOne(left)) { - ReplaceExprWithRightChild(nd); - } else if (IRO_IsConstantZero(left)) { - right->nodetype = ComplementaryOpLogical[right->nodetype]; - ReplaceExprWithRightChild(nd); - } - break; - case ENOTEQU: - if (IRO_IsConstantOne(left)) { - right->nodetype = ComplementaryOpLogical[right->nodetype]; - ReplaceExprWithRightChild(nd); - } else if (IRO_IsConstantZero(left)) { - ReplaceExprWithRightChild(nd); - } - break; - } - break; - case ELAND: - case ELOR: - switch (nd->nodetype) { - case EEQU: - if (IRO_IsConstantOne(left)) { - ReplaceExprWithRightChild(nd); - } - break; - case ENOTEQU: - if (IRO_IsConstantZero(left)) { - ReplaceExprWithRightChild(nd); - } - break; - } - break; - } - } - } -} - -static Boolean isOrderingOperator(ENodeType op) { - switch (op) { - case ELAND: - case ELOR: - case ECOMMA: - case ECOND: - case ECONDASS: - return 1; - default: - return 0; - } -} - -static void RemoveUnreffed(IROLinear *nd) { - if (!(nd->flags & IROLF_Reffed)) { - switch (nd->type) { - case IROLinearOperand: - IRO_NopNonSideEffects(nd, 0); - break; - case IROLinearOp1Arg: - case IROLinearOp2Arg: - case IROLinearOp3Arg: - case IROLinearFunccall: - if (!isOrderingOperator(nd->nodetype)) - IRO_NopNonSideEffects(nd, 0); - break; - } - } -} - -static void RemoveRedundantMonadicOp(IROLinear *nd) { - IROLinear *nd2; - IROLinear *nd3; - - if (nd->type == IROLinearOp1Arg && (nd2 = IRO_LocateFather(nd)) && nd2->nodetype == nd->nodetype) { - switch (nd->nodetype) { - case ELOGNOT: - if ((nd3 = IRO_LocateFather(nd2))) { - if ( - nd3->rtype && - TYPE_INTEGRAL(nd3->rtype)->integral == IT_BOOL && - nd->u.monadic->rtype && - TYPE_INTEGRAL(nd->u.monadic->rtype)->integral == IT_BOOL - ) - goto remove; - - if (nd3->type == IROLinearIf) - goto remove; - if (nd3->type == IROLinearIfNot) - goto remove; - if (nd3->type == IROLinearOp3Arg && nd == nd3->u.args3.a) - goto remove; - - switch (nd3->nodetype) { - case ELOGNOT: - case ELAND: - case ELOR: - goto remove; - } - } - - if (nd->u.monadic->type == IROLinearOp1Arg || nd->u.monadic->type == IROLinearOp2Arg) { - switch (nd->u.monadic->nodetype) { - case ELOGNOT: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case ELAND: - case ELOR: - goto remove; - } - } - break; - - case EMONMIN: - case EBINNOT: - remove: - IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd2, nd->u.monadic); - nd2->type = IROLinearNop; - nd->type = IROLinearNop; - break; - - case ETYPCON: - if (TYPE_INTEGRAL(nd->rtype)->integral == IT_FLOAT) { - switch (TYPE_INTEGRAL(nd2->rtype)->integral) { - case IT_DOUBLE: - case IT_LONGDOUBLE: - switch (TYPE_INTEGRAL(nd->u.monadic->rtype)->integral) { - case IT_BOOL: - case IT_CHAR: - case IT_SCHAR: - case IT_UCHAR: - case IT_SHORT: - case IT_USHORT: - nd->type = IROLinearNop; - nd2->u.monadic = nd->u.monadic; - break; - } - break; - } - } - break; - } - } -} - -static void ReverseOpForMonmin(IROLinear *nd) { - IROLinear *father; - - if ( - nd->type == IROLinearOp1Arg && - nd->nodetype == EMONMIN && - (father = IRO_LocateFather(nd)) && - father->type == IROLinearOp2Arg && - father->u.diadic.right == nd - ) - { - switch (father->nodetype) { - case EADDV: - case ESUBV: - case EADD: - case ESUB: - case EADDASS: - case ESUBASS: - father->nodetype = ComplementaryOp[father->nodetype]; - nd->type = IROLinearNop; - father->u.diadic.right = nd->u.monadic; - break; - } - } -} - -static void DoDiadic(IROLinear *nd) { - RemoveUnreffed(nd); - DoTransformations(nd); - DoTransformations11(nd); - DoTransformations12(nd); - DoTransformations13(nd); - DoTransformations21(nd); - DoTransformations22(nd); - DoTransformations23(nd); - DoTransformations24(nd); - DoTransformations25(nd); -} - -void IRO_DoTransformations(void) { - IROLinear *nd; - - for (nd = IRO_FirstLinear; nd; nd = nd->next) { - switch (nd->type) { - case IROLinearOp2Arg: - DoDiadic(nd); - break; - case IROLinearOp1Arg: - RemoveUnreffed(nd); - RemoveRedundantMonadicOp(nd); - ReverseOpForMonmin(nd); - break; - case IROLinearOperand: - RemoveUnreffed(nd); - break; - } - } - - IRO_CheckForUserBreak(); -} - -static Boolean ReconcileAssignments(IROLinear *nd1, IROLinear *nd2, IROList *list) { - IROLinear *copy; - Boolean result = 0; - int argCount; - int i; - IROLinear *tmp; - - if ( - (nd2->type == IROLinearOp1Arg && nd2->nodetype == ETYPCON) && - !(nd1->type == IROLinearOp1Arg && nd1->nodetype == ETYPCON) && - ReconcileAssignments(nd1, nd2->u.monadic, list) - ) - { - result = 1; - } - - if ( - (nd1->type == IROLinearOp1Arg && nd1->nodetype == ETYPCON) && - !(nd2->type == IROLinearOp1Arg && nd2->nodetype == ETYPCON) && - ReconcileAssignments(nd1->u.monadic, nd2, list) - ) - { - copy = IRO_NewLinear(IROLinearOp1Arg); - *copy = *nd2; - copy->index = IRO_NumLinear++; - copy->type = IROLinearOp1Arg; - copy->nodetype = ETYPCON; - copy->rtype = nd1->rtype; - copy->next = NULL; - copy->u.monadic = list->tail; - IRO_AddToList(copy, list); - result = 1; - } - - if (nd1->type == nd2->type && nd1->nodetype == nd2->nodetype) { - copy = IRO_NewLinear(IROLinearNop); - *copy = *nd2; - copy->index = IRO_NumLinear++; - copy->rtype = nd1->rtype; - copy->next = NULL; - switch (nd1->type) { - case IROLinearOperand: - if (nd1->u.node->type == nd2->u.node->type) { - if (!(nd1->u.node->type == EOBJREF && nd1->u.node->data.objref != nd2->u.node->data.objref)) - result = 1; - } - break; - - case IROLinearOp1Arg: - if (ReconcileAssignments(nd1->u.monadic, nd2->u.monadic, list)) { - copy->u.monadic = list->tail; - result = 1; - } - break; - - case IROLinearOp2Arg: - tmp = list->tail; - if (ReconcileAssignments(nd1->u.diadic.left, nd2->u.diadic.left, list)) { - copy->u.diadic.left = list->tail; - if (ReconcileAssignments(nd1->u.diadic.right, nd2->u.diadic.right, list)) { - copy->u.diadic.right = list->tail; - result = 1; - } - } - - if (!result && !IRO_HasSideEffect(nd1) && !IRO_HasSideEffect(nd2)) { - if (nd1->nodetype == EMUL || nd1->nodetype == EADD || nd1->nodetype == EAND || nd1->nodetype == EXOR || nd1->nodetype == EOR) { - list->tail = tmp; - if (ReconcileAssignments(nd1->u.diadic.left, nd2->u.diadic.right, list)) { - copy->u.diadic.right = list->tail; - if (ReconcileAssignments(nd1->u.diadic.right, nd2->u.diadic.left, list)) { - copy->u.diadic.left = list->tail; - result = 1; - } - } - } - } - break; - - case IROLinearOp3Arg: - if (ReconcileAssignments(nd1->u.args3.c, nd2->u.args3.c, list)) { - copy->u.args3.c = list->tail; - if (ReconcileAssignments(nd1->u.args3.b, nd2->u.args3.b, list)) { - copy->u.args3.b = list->tail; - if (ReconcileAssignments(nd1->u.args3.a, nd2->u.args3.a, list)) { - copy->u.args3.a = list->tail; - result = 1; - } - } - } - break; - - case IROLinearFunccall: - argCount = nd1->u.funccall.argCount; - if (argCount == nd2->u.funccall.argCount) { - result = 1; - copy->u.funccall.args = oalloc(sizeof(IROLinear *) * argCount); - for (i = argCount - 1; i >= 0; i--) { - if (!ReconcileAssignments(nd1->u.funccall.args[i], nd2->u.funccall.args[i], list)) { - result = 0; - break; - } - copy->u.funccall.args[i] = list->tail; - } - - if (result) { - if (!ReconcileAssignments(nd1->u.funccall.linear8, nd2->u.funccall.linear8, list)) { - result = 0; - break; - } - copy->u.funccall.linear8 = list->tail; - } - } - break; - } - - if (result) - IRO_AddToList(copy, list); - } - - return result; -} - -static IROLinear *FrontendTransformSelfAssignmentToAssignment(IROLinear *nd) { - Statement *stmt; - IROList list; - IROLinearIRSave save; - - IRO_SaveLinearIR(&save); - - IRO_InitList(&list); - IRO_DuplicateExpr(nd, &list); - - stmt = IRO_Delinearize(NULL, list.head); - CError_ASSERT(3550, stmt); - CError_ASSERT(3552, stmt->expr); - stmt->expr = CIRTrans_TransformOpAss(stmt->expr); - CError_ASSERT(3557, stmt->expr); - - if (DoLinearize) - IRO_PreLinearize(stmt); - IRO_Linearize(stmt); - - IRO_InitList(&list); - list.head = IRO_FirstLinear; - list.tail = IRO_LastLinear; - - IRO_RestoreLinearIR(&save); - - for (nd = list.head; nd; nd = nd->next) { - if (!(nd->flags & IROLF_Reffed) && IRO_IsAssignment(nd)) - break; - } - - return nd; -} - -static Type *PromotedIntegralType(Type *type) { - CError_ASSERT(3586, IS_TYPE_ENUM(type) || IS_TYPE_INT(type)); - - if (IS_TYPE_ENUM(type)) - type = TYPE_ENUM(type)->enumtype; - - if (TYPE_INTEGRAL(type)->integral < IT_INT) { - if (IRO_IsUnsignedType(type)) - return TYPE(&stunsignedint); - else - return TYPE(&stsignedint); - } else { - return type; - } -} - -static Boolean TransformMonadicSelfAssignmentToDiadicSelfAssignment(IROLinear *nd) { - ENodeType t; - ENodeType newtype; - IROLinear *incExpr; - IROLinear *varExpr; - - t = nd->nodetype; - - if (IRO_IsAssignment(nd) && IRO_IsModifyOp[t]) { - incExpr = NULL; - varExpr = NULL; - newtype = MAXEXPR; - - if ( - nd->type == IROLinearOp1Arg && - (t == EPOSTINC || t == EPOSTDEC || t == EPREINC || t == EPREDEC) && - (!(nd->flags & IROLF_Reffed) || t == EPREINC || t == EPREDEC) - ) - { - Type *type = nd->rtype; - TypeType typetype = type->type; - varExpr = nd->u.monadic; - if (typetype == TYPEINT || typetype == TYPEENUM) { - incExpr = IRO_NewIntConst(cint64_one, PromotedIntegralType(type)); - } else if (typetype == TYPEPOINTER || typetype == TYPEARRAY || typetype == TYPEMEMBERPOINTER) { - Type *inner = NULL; - CInt64 val = cint64_zero; - - if (typetype == TYPEPOINTER || typetype == TYPEARRAY) - inner = TPTR_TARGET(type); - else if (typetype == TYPEMEMBERPOINTER) - inner = TYPE_MEMBER_POINTER(type)->ty1; - - if (inner) - CInt64_SetLong(&val, inner->size); - - if (!CInt64_IsZero(&val)) { - incExpr = IRO_NewIntConst(val, TYPE(&stsignedlong)); - } else { - return 0; - } - } else if (typetype == TYPEFLOAT) { - Float fval; - fval = CMach_CalcFloatConvertFromInt(type, cint64_one); - incExpr = IRO_NewFloatConst(fval, nd->rtype); - } else { - return 0; - } - - if (t == EPOSTINC || t == EPREINC) - newtype = EADDASS; - else - newtype = ESUBASS; - } - - if ( - varExpr && - incExpr && - newtype != MAXEXPR && - varExpr->u.diadic.left && - varExpr->u.diadic.left->type == IROLinearOperand && - varExpr->u.diadic.left->u.node && - varExpr->u.diadic.left->u.node->type == EOBJREF && - !IRO_HasSideEffect(varExpr) - ) - { - incExpr->flags |= IROLF_Reffed; - nd->nodetype = newtype; - nd->u.diadic.right = incExpr; - nd->type = IROLinearOp2Arg; - IRO_Paste(incExpr, incExpr, nd); - return 1; - } - } - - return 0; -} - -Boolean IRO_TransformSelfAssignmentToAssignment(IROLinear *nd) { - ENodeType nonAssOp; - IROLinear *left; - IROLinear *right; - ENodeType nodetype; - IROLinear *nonAss; - IROLinear *dupLeft; - IROLinear *last; - IROList list1; - IROList list2; - - nodetype = nd->nodetype; - if ( - IRO_IsAssignment(nd) && - IRO_IsModifyOp[nodetype] && - nd->type == IROLinearOp1Arg && - TransformMonadicSelfAssignmentToDiadicSelfAssignment(nd) - ) - nodetype = nd->nodetype; - - if ( - IRO_IsAssignment(nd) && - IRO_IsModifyOp[nodetype] && - nd->type == IROLinearOp2Arg && - IRO_NonAssignmentOp[nodetype] != MAXEXPR - ) - { - left = nd->u.diadic.left; - right = nd->u.diadic.right; - nonAssOp = IRO_NonAssignmentOp[nodetype]; - if ( - left && - right && - nonAssOp != MAXEXPR && - left->u.monadic && - left->u.monadic->type == IROLinearOperand && - left->u.monadic->u.node && - left->u.monadic->u.node->type == EOBJREF && - !IRO_HasSideEffect(left) - ) - { - IRO_InitList(&list1); - dupLeft = IRO_DuplicateExpr(left, &list1); - - if (left->rtype != right->rtype) { - IROLinear *tmp = IRO_NewLinear(IROLinearOp1Arg); - tmp->nodetype = ETYPCON; - tmp->flags |= IROLF_Reffed; - tmp->rtype = right->rtype; - tmp->index = ++IRO_NumLinear; - tmp->u.monadic = dupLeft; - IRO_AddToList(tmp, &list1); - dupLeft = tmp; - } - - nonAss = IRO_NewLinear(IROLinearOp2Arg); - nonAss->nodetype = nonAssOp; - nonAss->flags |= IROLF_Reffed; - nonAss->rtype = dupLeft->rtype; - nonAss->index = ++IRO_NumLinear; - nonAss->u.diadic.left = dupLeft; - nonAss->u.diadic.right = right; - IRO_AddToList(nonAss, &list1); - - if (left->rtype != right->rtype) { - IROLinear *tmp = IRO_NewLinear(IROLinearOp1Arg); - tmp->nodetype = ETYPCON; - tmp->flags |= IROLF_Reffed; - tmp->rtype = left->rtype; - tmp->index = ++IRO_NumLinear; - tmp->u.monadic = nonAss; - IRO_AddToList(tmp, &list1); - nonAss = tmp; - } - - IRO_InitList(&list2); - last = FrontendTransformSelfAssignmentToAssignment(nd); - if ( - last && - last->type == IROLinearOp2Arg && - ReconcileAssignments(last->u.diadic.right, nonAss, &list2) - ) - { - IRO_NopOut(nd->u.diadic.right); - nd->nodetype = EASS; - nd->u.diadic.right = list2.tail; - nd->type = IROLinearOp2Arg; - IRO_Paste(list2.head, list2.tail, nd); - return 1; - } - } - } - - return 0; -} - -static void AddAddend(ENode *expr) { - if (expr->type == EADD) { - AddAddend(expr->data.diadic.left); - AddAddend(expr->data.diadic.right); - } else { - ENodeList *list = oalloc(sizeof(ENodeList)); - list->node = expr; - list->next = NULL; - - if (FirstAddend) - LastAddend->next = list; - else - FirstAddend = list; - LastAddend = list; - } -} - -static ENode *CombineConstants(ENode *expr) { - ENode *addend; - ENodeList *el; - ENode *result; - ENode *var; - Type *type; - ENode *tmp; - ENodeList *prev; - CInt64 val; - - FirstAddend = LastAddend = NULL; - AddAddend(expr->data.diadic.left); - AddAddend(expr->data.diadic.right); - - // these variable names are courtesy of the resource fork in abort_exit.c - el = FirstAddend; - prev = NULL; - var = NULL; - while (el) { - addend = el->node; - if (addend->type == EOBJREF) { - var = addend; - if (prev) - prev->next = el->next; - else - FirstAddend = el->next; - break; - } - prev = el; - el = el->next; - } - - if (!var) { - el = FirstAddend; - prev = NULL; - while (el) { - addend = el->node; - if (addend->type == EINDIRECT) { - var = addend; - if (prev) - prev->next = el->next; - else - FirstAddend = el->next; - break; - } - prev = el; - el = el->next; - } - } - - prev = NULL; - CInt64_SetLong(&val, 0); - type = NULL; - - for (el = FirstAddend; el; el = el->next) { - addend = el->node; - if (addend->type == EINTCONST && addend->rtype) { - if (!type || type->size < addend->rtype->size) - type = addend->rtype; - val = CInt64_Add(val, addend->data.intval); - if (prev) - prev->next = el->next; - else - FirstAddend = el->next; - } else if (addend->type == EMUL && addend->data.diadic.right->type == EINTCONST && addend->rtype) { - if (!type || type->size < addend->rtype->size) - type = addend->rtype; - - tmp = addend->data.diadic.left; - if (tmp->type == EADD && tmp->data.diadic.right->type == EINTCONST) { - val = CInt64_Add(val, CInt64_MulU(tmp->data.diadic.right->data.intval, addend->data.diadic.right->data.intval)); - addend->data.diadic.left = tmp->data.diadic.left; - } - prev = el; - } else { - prev = el; - } - } - - result = NULL; - if (var) { - result = var; - if (!CInt64_IsZero(&val)) { - result = IRO_NewENode(EADD); - result->data.diadic.left = var; - result->data.diadic.right = IRO_NewENode(EINTCONST); - result->data.diadic.right->data.intval = val; - result->data.diadic.right->rtype = type; - result->rtype = var->rtype; - result->cost = 1; - CInt64_SetLong(&val, 0); - } - } - - for (el = FirstAddend; el; el = el->next) { - addend = el->node; - if (result) { - tmp = IRO_NewENode(EADD); - tmp->data.diadic.left = result; - tmp->data.diadic.right = addend; - tmp->cost = result->cost + 1; - tmp->rtype = result->rtype; - result = tmp; - } else { - result = addend; - } - } - - if (!CInt64_IsZero(&val)) { - tmp = IRO_NewENode(EADD); - tmp->data.diadic.left = result; - tmp->data.diadic.right = IRO_NewENode(EINTCONST); - tmp->data.diadic.right->data.intval = val; - tmp->data.diadic.right->rtype = type; - tmp->cost = result->cost + 1; - tmp->rtype = result->rtype; - result = tmp; - } - - return result; -} - -static ENode *TransformExprNode(ENode *expr) { - ENode *left; - ENode *right; - - switch (expr->type) { - case EINDIRECT: - if (ENODE_IS(expr->data.monadic, EADD)) - expr->data.monadic = CombineConstants(expr->data.monadic); - break; - - case EMUL: - case EADD: - case EAND: - case EXOR: - case EOR: - if ( - IS_TYPE_INT(expr->rtype) && - !ENODE_IS(right = expr->data.diadic.right, EINTCONST) && - ENODE_IS(left = expr->data.diadic.left, EINTCONST) - ) - { - expr->data.diadic.left = right; - expr->data.diadic.right = left; - } - break; - - case EEQU: - case ENOTEQU: - if ( - IS_TYPE_INT(expr->rtype) && - !ENODE_IS(left = expr->data.diadic.right, EINTCONST) && - ENODE_IS(right = expr->data.diadic.left, EINTCONST) - ) - { - expr->data.diadic.left = left; - expr->data.diadic.right = right; - } - - if ( - ENODE_IS(expr->data.diadic.right, EINTCONST) && - ENODE_IS(left = expr->data.diadic.left, EBINNOT) - ) - { - expr->data.diadic.left = left->data.monadic; - left->data.monadic = expr->data.diadic.right; - expr->data.diadic.right = left; - } - - break; - } - - return expr; -} - -static ENode *TransformExprTree(ENode *expr) { - ENodeList *list; - - switch (expr->type) { - ENODE_CASE_MONADIC: - expr->data.monadic = TransformExprTree(expr->data.monadic); - break; - - ENODE_CASE_DIADIC_ALL: - expr->data.diadic.left = TransformExprTree(expr->data.diadic.left); - expr->data.diadic.right = TransformExprTree(expr->data.diadic.right); - break; - - case EFUNCCALL: - case EFUNCCALLP: - TransformExprTree(expr->data.funccall.funcref); - for (list = expr->data.funccall.args; list; list = list->next) - TransformExprTree(list->node); - break; - - case ECOND: - TransformExprTree(expr->data.cond.cond); - TransformExprTree(expr->data.cond.expr1); - TransformExprTree(expr->data.cond.expr2); - break; - - case ENULLCHECK: - TransformExprTree(expr->data.nullcheck.nullcheckexpr); - TransformExprTree(expr->data.nullcheck.condexpr); - break; - } - - return TransformExprNode(expr); -} - -static void FoldConstantsinAssociativeExprs(ENode *expr) { - short nodetype1; - short nodetype2; - short nodetype3; - Boolean changed; - short op; - CInt64 val1; - CInt64 val2; - CInt64 tmpval; - - if ( - ( - expr->type == EADD || - expr->type == EMUL || - expr->type == EAND || - expr->type == EXOR || - expr->type == EOR || - expr->type == ESHL || - expr->type == ESHR - ) && - IS_TYPE_INT(expr->rtype) && - expr->data.diadic.right->type == EINTCONST - ) - { - do { - changed = 0; - - if ( - expr->data.diadic.left->type == expr->type && - expr->data.diadic.left->data.diadic.right->type == EINTCONST - ) - { - val1 = expr->data.diadic.right->data.intval; - val2 = expr->data.diadic.left->data.diadic.right->data.intval; - switch (expr->type) { - case EADD: - case ESHL: - op = '+'; - break; - case ESHR: - op = '+'; - if (!IRO_IsUnsignedType(expr->rtype)) { - CInt64_SetLong(&tmpval, expr->rtype->size * 8); - if (CInt64_GreaterEqualU(val1, tmpval) || CInt64_GreaterEqualU(val2, tmpval)) - return; - - if (CInt64_GreaterEqualU(CMach_CalcIntDiadic(expr->rtype, val1, '+', val2), tmpval)) { - val1 = CInt64_Sub(tmpval, cint64_one); - val2 = cint64_zero; - } - } - break; - case EMUL: - op = '*'; - break; - case EAND: - op = '&'; - break; - case EOR: - op = '|'; - break; - case EXOR: - op = '^'; - break; - default: - return; - } - - expr->data.diadic.right->data.intval = CMach_CalcIntDiadic(expr->rtype, val1, op, val2); - expr->data.diadic.left = expr->data.diadic.left->data.diadic.left; - changed = 1; - } else if ( - ((nodetype1 = expr->type) == EAND || nodetype1 == EOR) && - ((nodetype2 = expr->data.diadic.left->type) == EAND || nodetype2 == EOR) && - ((nodetype3 = expr->data.diadic.left->data.diadic.left->type) == EAND || nodetype3 == EOR) && - expr->data.diadic.left->data.diadic.left->data.diadic.right->type == EINTCONST - ) - { - val1 = expr->data.diadic.right->data.intval; - if (CInt64_Equal(val1, expr->data.diadic.left->data.diadic.left->data.diadic.right->data.intval)) { - if (nodetype1 == nodetype3) { - expr->data.diadic.left->data.diadic.left = expr->data.diadic.left->data.diadic.left->data.diadic.left; - changed = 1; - } else if (nodetype2 == nodetype3) { - *expr = *expr->data.diadic.right; - changed = 1; - } else { - expr->data.diadic.left = expr->data.diadic.left->data.diadic.right; - changed = 1; - } - } - } - } while (changed); - } -} - -static void TransformExprTree1(ENode *expr) { - ENodeList *list; - - switch (expr->type) { - ENODE_CASE_MONADIC: - TransformExprTree1(expr->data.monadic); - break; - - ENODE_CASE_DIADIC_ALL: - TransformExprTree1(expr->data.diadic.left); - TransformExprTree1(expr->data.diadic.right); - break; - - case EFUNCCALL: - case EFUNCCALLP: - TransformExprTree1(expr->data.funccall.funcref); - for (list = expr->data.funccall.args; list; list = list->next) - TransformExprTree1(list->node); - break; - - case ECOND: - TransformExprTree1(expr->data.cond.cond); - TransformExprTree1(expr->data.cond.expr1); - TransformExprTree1(expr->data.cond.expr2); - break; - - case ENULLCHECK: - TransformExprTree1(expr->data.nullcheck.nullcheckexpr); - TransformExprTree1(expr->data.nullcheck.condexpr); - break; - } - - FoldConstantsinAssociativeExprs(expr); -} - -static int RemoveRedundantBitOperations(ENode *expr) { - Boolean a; - Boolean b; - - if (expr->type == ExprType) { - a = RemoveRedundantBitOperations(expr->data.diadic.left); - b = RemoveRedundantBitOperations(expr->data.diadic.right); - return a & b; - } - - if (expr->type == EINDIRECT) { - if (expr->data.monadic->type == EOBJREF) { - if (!OperandObject) { - OperandObject = expr->data.monadic->data.objref; - IndirectRef = expr; - return 1; - } else { - return expr->data.monadic->data.objref == OperandObject; - } - } else { - return 0; - } - } - - if (expr->type == EINTCONST) { - if (FirstTime) { - OperandConst = expr->data.intval; - FirstTime = 0; - } else if (ExprType == EAND) { - OperandConst = CInt64_And(expr->data.intval, OperandConst); - } else if (ExprType == EOR) { - OperandConst = CInt64_Or(expr->data.intval, OperandConst); - } else if (ExprType == EXOR) { - OperandConst = CInt64_Xor(expr->data.intval, OperandConst); - } - return 1; - } - - return 0; -} - -static void TransformExprTree2(ENode *expr) { - ENodeList *list; - - switch (expr->type) { - ENODE_CASE_MONADIC: - TransformExprTree2(expr->data.monadic); - break; - - ENODE_CASE_DIADIC_ALL: - TransformExprTree2(expr->data.diadic.left); - TransformExprTree2(expr->data.diadic.right); - break; - - case EFUNCCALL: - case EFUNCCALLP: - TransformExprTree2(expr->data.funccall.funcref); - for (list = expr->data.funccall.args; list; list = list->next) - TransformExprTree2(list->node); - break; - - case ECOND: - TransformExprTree2(expr->data.cond.cond); - TransformExprTree2(expr->data.cond.expr1); - TransformExprTree2(expr->data.cond.expr2); - break; - - case ENULLCHECK: - TransformExprTree2(expr->data.nullcheck.nullcheckexpr); - TransformExprTree2(expr->data.nullcheck.condexpr); - break; - } - - if ( - ENODE_IS3(expr, EAND, EOR, EXOR) && - (expr->type == expr->data.diadic.left->type || expr->type == expr->data.diadic.right->type) - ) - { - OperandObject = NULL; - ExprType = expr->type; - FirstTime = 1; - IndirectRef = NULL; - - if (RemoveRedundantBitOperations(expr)) { - expr->data.diadic.left = IndirectRef; - expr->data.diadic.right->type = EINTCONST; - expr->data.diadic.right->data.intval = OperandConst; - } - } -} - -static void PullOutPostOps(Statement *stmt, ENode **pExpr) { - ENode *ind; - ENode *inner; - Statement *newStmt; - - switch ((*pExpr)->type) { - ENODE_CASE_MONADIC: - if ((*pExpr)->type != EFORCELOAD) - PullOutPostOps(stmt, &(*pExpr)->data.monadic); - - if (ENODE_IS2(*pExpr, EPOSTINC, EPOSTDEC)) { - inner = (*pExpr)->data.monadic; - if ( - ENODE_IS(inner, EINDIRECT) && - inner->rtype && - !CParser_IsVolatile(inner->rtype, ENODE_QUALS(inner)) && - ENODE_IS(inner->data.monadic, EOBJREF) && - !is_volatile_object(inner->data.monadic->data.objref) - ) - { - newStmt = lalloc(sizeof(Statement)); - memset(newStmt, 0, sizeof(Statement)); - newStmt->type = ST_EXPRESSION; - newStmt->expr = *pExpr; - newStmt->dobjstack = stmt->dobjstack; - newStmt->sourceoffset = stmt->sourceoffset; - newStmt->sourcefilepath = stmt->sourcefilepath; - newStmt->value = stmt->value; - newStmt->flags = stmt->flags; - newStmt->next = stmt->next; - stmt->next = newStmt; - - ind = IRO_NewENode(EINDIRECT); - *ind = *inner; - ind->data.monadic = IRO_NewENode(EOBJREF); - *ind->data.monadic = *inner->data.monadic; - *pExpr = ind; - } - } - break; - - ENODE_CASE_DIADIC_ALL: - if (ENODE_IS(*pExpr, ECOND)) - break; - if (ENODE_IS(*pExpr, ECOMMA)) - break; - if (ENODE_IS(*pExpr, ELOR)) - break; - if (ENODE_IS(*pExpr, ELAND)) - break; - if (ENODE_IS(*pExpr, ENULLCHECK)) - break; - PullOutPostOps(stmt, &(*pExpr)->data.diadic.left); - PullOutPostOps(stmt, &(*pExpr)->data.diadic.right); - break; - } -} - -void IRO_TransformTree(Statement *statements) { - Statement *stmt; - Statement *next; - - for (stmt = statements; stmt; stmt = next) { - next = stmt->next; - switch (stmt->type) { - case ST_EXPRESSION: - case ST_SWITCH: - case ST_IFGOTO: - case ST_IFNGOTO: - case ST_RETURN: - if (stmt->expr) { - stmt->expr = TransformExprTree(stmt->expr); - TransformExprTree2(stmt->expr); - TransformExprTree1(stmt->expr); - } - break; - } - } - - IRO_CheckForUserBreak(); -} diff --git a/compiler_and_linker/unsorted/IroUnrollLoop.c b/compiler_and_linker/unsorted/IroUnrollLoop.c deleted file mode 100644 index 45b774e..0000000 --- a/compiler_and_linker/unsorted/IroUnrollLoop.c +++ /dev/null @@ -1,2305 +0,0 @@ -#include "compiler/IroUnrollLoop.h" -#include "compiler/CError.h" -#include "compiler/IroFlowgraph.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroUtil.h" -#include "compiler/LoopDetection.h" -#include "compiler/IroLoop.h" -#include "compiler/IroDump.h" -#include "compiler/IroVars.h" -#include "compiler/CFunc.h" -#include "compiler/CMachine.h" - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct LoopList { - UInt8 flags; - BitVector *bv; - struct LoopList *next; - IRONode *fnode; - int xE; -} LoopList; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -// forward decls -static void IRO_FindLoops_Unroll(void); -static void LoopUnroll(int count, IRONode *fnode); -static int IsLoopUnrollable(IROLoop *loop); -static int IsDifferenceOfTermsConstant(IROAddrRecord *lowerRec, IROAddrRecord *upperRec, int isUnsigned, CInt64 *pval); -static IROLinear *BuildOrigIterationCount_DoWhile(IROList *list, IROLoop *loop); -static IROLinear *BuildPreAlignTemp(IROLoopInd *ind, UInt32 unrollFactor, IROList *list); -static IROLinear *BuildNewFinalvalue_DoWhile(IROLinear *iterCount, UInt32 unrollFactor, IROList *list, IROLoop *loop); -static IROLinear *BuildUnrolledFinalvalue_DoWhile(IROLinear *iterCount, UInt32 unrollFactor, IROList *list, IROLoop *loop); - -void IRO_LoopUnroller(void) { - VectorPhaseCalledFromUnroll = 1; - IRO_FindLoops_Unroll(); - IRO_CheckForUserBreak(); -} - -static void IRO_FindLoops_Unroll(void) { - IRONode *fnode; - IRONode *pred; - UInt16 i; - UInt16 flag; - LoopList *list; - LoopList *list2; - - fnode = IRO_FirstNode; - LoopList_First = NULL; - - while (fnode) { - flag = 0; - for (i = 0; i < fnode->numpred; i++) { - pred = IRO_NodeTable[fnode->pred[i]]; - if (Bv_IsBitSet(fnode->index, pred->dom)) { - if (!flag) { - Bv_AllocVector(&InLoop, IRO_NumNodes + 1); - Bv_Clear(InLoop); - Bv_SetBit(fnode->index, InLoop); - } - flag = 1; - Bv_SetBit(pred->index, InLoop); - if (pred != fnode) - AddPreds(pred); - } - } - - if (flag) { - if (!LoopList_First) { - list = oalloc(sizeof(LoopList)); - list->next = NULL; - } else { - list = oalloc(sizeof(LoopList)); - list->next = LoopList_First; - } - LoopList_First = list; - - Bv_AllocVector(&list->bv, IRO_NumNodes + 1); - list->flags |= 1; - Bv_Copy(InLoop, list->bv); - list->fnode = fnode; - list->xE = 0; - } - - fnode = fnode->nextnode; - } - - list = LoopList_First; - Bv_AllocVector(&LoopTemp, IRO_NumNodes + 1); - while (list) { - for (list2 = LoopList_First; list2; list2 = list2->next) { - if (list2 != list) { - IRO_Dump(" header = %d \n", list2->fnode->index); - IRO_Dump(" l1 bit vector=\n"); - IRO_DumpBits("", list2->bv); - IRO_Dump(" l bit vector=\n"); - IRO_DumpBits("", list->bv); - if (Bv_IsSubset(list->bv, list2->bv)) - list2->flags &= ~1; - } - } - list = list->next; - } - - for (list = LoopList_First; list; list = list->next) { - if (list->flags & 1) { - IRONode *listfnode; - Bv_Copy(list->bv, InLoop); - listfnode = list->fnode; - IRO_Dump("IRO_FindLoops_Unroll:Found loop with header %d\n", listfnode->index); - IRO_DumpBits("Loop includes: ", InLoop); - LoopUnroll(copts.unrollfactor, listfnode); - IRO_UpdateFlagsOnInts(); - } - } -} - -static int CheckConstant(CInt64 a, CInt64 b, CInt64 *result) { - CInt64 shl = cint64_zero; - CInt64 work = cint64_zero; - CInt64 and = cint64_zero; - CInt64 i; - - for (i = cint64_zero; CInt64_Less(i, a); i = CInt64_Add(i, cint64_one)) { - shl = CInt64_Shl(b, i); - and = CInt64_And(shl, work); - if (CInt64_NotEqual(and, cint64_zero)) - return 0; - work = CInt64_Or(shl, work); - } - - *result = work; - return 1; -} - -typedef struct LoopPattern { - IROLinear *nd0; - IROLinear *nd4; - Type *type; - IROLinear *ndC; - IROLinear *nd10; - CInt64 val14; - CInt64 val1C; -} LoopPattern; - -static void UnrollWhileLoopBody(IRONode *header, IRONode *fnode2, IRONode *fnode3, IROLoop *loop, LoopPattern *pattern, UInt32 unrollFactor) { - IRONode *scan; - int pass; - IROLinear *firstnode; - IROLinear *lastnd; - IROLinear *nd; - IROLinear *nd1; - IROLinear *nd2; - IROLinear *nd3; - IROLinear *nd4; - IROLinear *nd5; - IROLinear *nd6; - IROLinear *nd8; - IROLinear *nd7; - ENode *expr; - IROList list; - CInt64 zero; - CInt64 shiftval; - - CInt64_SetLong(&zero, 0); - - pass = 0; - - do { - firstnode = NULL; - for (scan = fnode3; scan && scan != header; scan = scan->nextnode) { - IRO_InitList(&list); - lastnd = scan->last; - nd = scan->first; - while (1) { - if (nd->stmt) - nd->stmt->flags |= StmtFlag_10; - - if ( - (nd->index < loop->index20 || nd->index > loop->index24) && - nd->type != IROLinearLabel && - nd->type != IROLinearNop && - !(nd->flags & IROLF_Reffed) - ) - { - CError_ASSERT(345, nd->nodetype == EORASS || nd->nodetype == EANDASS || nd->nodetype == EXORASS); - - IRO_DuplicateExpr(pattern->nd0, &list); - nd1 = list.tail; - - shiftval = cint64_one; - shiftval = CInt64_Shl(shiftval, pattern->val1C); - - nd2 = IRO_NewLinear(IROLinearOperand); - nd2->index = ++IRO_NumLinear; - nd2->rtype = pattern->nd0->rtype; - expr = IRO_NewENode(EINTCONST); - expr->rtype = pattern->nd0->rtype; - CInt64_SetLong(&expr->data.intval, pass * CInt64_GetULong(&shiftval)); - nd2->u.node = expr; - IRO_AddToList(nd2, &list); - - IRO_DuplicateExpr(pattern->nd4, &list); - - nd3 = IRO_NewLinear(IROLinearOp2Arg); - nd3->index = ++IRO_NumLinear; - nd3->nodetype = EADD; - nd3->rtype = pattern->type; - nd3->u.diadic.left = list.tail; - nd3->u.diadic.right = nd2; - IRO_AddToList(nd3, &list); - - nd4 = IRO_NewLinear(IROLinearOp2Arg); - nd4->index = ++IRO_NumLinear; - nd4->nodetype = EADD; - nd4->rtype = pattern->type; - nd4->u.diadic.left = nd3; - nd4->u.diadic.right = nd1; - IRO_AddToList(nd4, &list); - - nd5 = IRO_NewLinear(IROLinearOp1Arg); - nd5->index = ++IRO_NumLinear; - nd5->nodetype = EINDIRECT; - nd5->rtype = nd->rtype; - nd5->u.monadic = nd4; - IRO_AddToList(nd5, &list); - - nd6 = IRO_NewLinear(IROLinearOp2Arg); - *nd6 = *nd; - nd6->index = ++IRO_NumLinear; - nd6->u.diadic.left = list.tail; - nd6->next = NULL; - - nd7 = IRO_NewLinear(IROLinearOperand); - nd7->index = ++IRO_NumLinear; - nd7->rtype = pattern->ndC->rtype; - expr = IRO_NewENode(EINTCONST); - expr->rtype = pattern->ndC->rtype; - nd7->u.node = expr; - nd7->next = NULL; - expr->data.intval = pattern->val14; - - if ( - IS_LINEAR_DIADIC(nd, EANDASS) && - CInt64_Equal(pattern->val14, cint64_zero) - ) - { - nd6->nodetype = EASS; - } else if ( - IS_LINEAR_DIADIC(nd, EORASS) && - !CTool_EndianReadWord32(&pattern->val14.hi) - ) - { - UInt32 tmp = CInt64_GetULong(&pattern->val14); - if ( - (nd->rtype->size == 1 && tmp == 0xFF) || - (nd->rtype->size == 2 && tmp == 0xFFFF) || - (nd->rtype->size == 4 && tmp == 0xFFFFFFFF) - ) - { - nd6->nodetype = EASS; - } - } - - IRO_AddToList(nd7, &list); - - if (IS_LINEAR_MONADIC(pattern->nd10, ETYPCON)) { - nd8 = IRO_NewLinear(IROLinearOp1Arg); - *nd8 = *pattern->nd10; - nd8->index = ++IRO_NumLinear; - nd8->u.monadic = nd7; - nd8->next = NULL; - IRO_AddToList(nd8, &list); - } else { - nd8 = nd7; - } - nd6->u.diadic.right = nd8; - IRO_AddToList(nd6, &list); - - if (!firstnode) - firstnode = list.head; - } - - if (nd == lastnd) - break; - nd = nd->next; - } - - if (list.head && list.tail) - IRO_Paste(list.head, list.tail, fnode2->last); - } - } while (++pass < 8); -} - -static int PatternMatchLoop(IRONode *fnode, IROLoop *loop, IROLoopInd *ind, UInt32 *unrollFactor, SInt32 *result1, SInt32 *result2, LoopPattern *pattern) { - IROLinear *scan; - IROLinear *varnode; - IROLinear *nd1; - IROLinear *nd2; - IROLinear *left1; - IROLinear *left2; - IROLinear *right1; - IROLinear *right2; - Object *obj1; - Object *obj2; - CInt64 shl; - CInt64 val; - - *result1 = 0; - *result2 = 0; - - if ((scan = fnode->first)) { - while (1) { - if ( - (scan->index < loop->index20 || scan->index > loop->index24) && - !(scan->flags & IROLF_Reffed) && - scan->type != IROLinearNop && - scan->type != IROLinearLabel - ) - { - if (IS_LINEAR_DIADIC_3(scan, EORASS, EXORASS, EANDASS)) { - (*result2)++; - if (IS_LINEAR_MONADIC(scan->u.diadic.left, EINDIRECT)) { - varnode = scan->u.diadic.left->u.monadic; - if (IS_LINEAR_DIADIC(varnode, EADD)) { - pattern->nd4 = varnode->u.diadic.left; - pattern->type = varnode->rtype; - if (IRO_IsVariable(varnode->u.diadic.left)) { - pattern->nd0 = varnode->u.diadic.right; - if ( - IS_LINEAR_DIADIC(pattern->nd0, ESHL) && - IRO_IsConstant(pattern->nd0->u.diadic.right) - ) - { - pattern->val1C = pattern->nd0->u.diadic.right->u.node->data.intval; - nd1 = pattern->nd0->u.diadic.left; - } else { - return 0; - } - } else { - return 0; - } - } else { - return 0; - } - } else { - return 0; - } - - pattern->nd10 = scan->u.diadic.right; - - if (IS_LINEAR_MONADIC(pattern->nd10, ETYPCON)) { - if (IS_LINEAR_DIADIC(scan, EANDASS)) { - if (IS_LINEAR_MONADIC(pattern->nd10->u.monadic, EBINNOT)) { - pattern->ndC = pattern->nd10->u.monadic->u.monadic; - } else { - return 0; - } - } else { - pattern->ndC = pattern->nd10->u.monadic; - } - - if (IS_LINEAR_DIADIC(pattern->ndC, ESHL) && IRO_IsConstant(pattern->ndC->u.diadic.left)) { - val = pattern->ndC->u.diadic.left->u.node->data.intval; - nd2 = pattern->ndC->u.diadic.right; - } else { - return 0; - } - } else if (IS_LINEAR_DIADIC(pattern->nd10, ESHL) && IS_LINEAR_DIADIC_2(scan, EORASS, EXORASS)) { - pattern->ndC = pattern->nd10; - if (IRO_IsConstant(pattern->ndC->u.diadic.left)) { - val = pattern->ndC->u.diadic.left->u.node->data.intval; - nd2 = pattern->ndC->u.diadic.right; - } else { - return 0; - } - } else if (IS_LINEAR_MONADIC(pattern->nd10, EBINNOT) && IS_LINEAR_DIADIC(scan, EANDASS)) { - pattern->ndC = pattern->nd10->u.monadic; - if (IS_LINEAR_DIADIC(pattern->ndC, ESHL) && IRO_IsConstant(pattern->ndC->u.diadic.left)) { - val = pattern->ndC->u.diadic.left->u.node->data.intval; - nd2 = pattern->ndC->u.diadic.right; - } else { - return 0; - } - } else { - return 0; - } - - if (IS_LINEAR_DIADIC(nd2, EAND) && IS_LINEAR_DIADIC(nd1, ESHR)) { - left1 = nd1->u.diadic.left; - left2 = nd2->u.diadic.left; - obj1 = IRO_IsVariable(left1); - obj2 = IRO_IsVariable(left2); - if (obj1 == obj2 && obj1 == ind->var->object) { - right1 = nd1->u.diadic.right; - right2 = nd2->u.diadic.right; - if (IRO_IsConstant(right1) && IRO_IsConstant(right2)) { - shl = cint64_one; - shl = CInt64_Shl(shl, right1->u.node->data.intval); - shl = CInt64_Sub(shl, cint64_one); - if (CInt64_Equal(shl, right2->u.node->data.intval)) { - if (CTool_EndianReadWord32(&shl.hi) == 0) { - *unrollFactor = CInt64_GetULong(&shl) + 1; - if (CheckConstant(CInt64_Add(shl, cint64_one), val, &pattern->val14)) { - (*result1)++; - if (IS_LINEAR_DIADIC(scan, EANDASS)) - pattern->val14 = CInt64_Not(pattern->val14); - } - } else { - return 0; - } - } else { - return 0; - } - } else { - return 0; - } - } else { - return 0; - } - } else { - return 0; - } - } else { - return 0; - } - } - - if (scan == fnode->last) - break; - scan = scan->next; - } - } - - return 1; -} - -static UInt32 UnrollWhileLoop(IRONode *header, IRONode *fnode2, IRONode *fnode3, IROLoop *loop, UInt32 unrollFactor) { - IROLoopInd *ind; - IRONode *scan; - CLabel *lastlabel; - IROLinear *lastlabelnode; - IROLinear *earlyLoopExitTest; - CLabel *earlyLoopExitTestLabel; - IROLinear *origIterationCount; - IROLinear *unrolledFinalValue; - IROLinear *preAlignTemp; - IROLinear *newFinalValue; - IROLinear *savedHead60; - IROLinear *unrolledBodyEntryTest; - CLabel *label; - IROLinear *savedHead2; - IROLinear *loophead25; - IROLinear *loopend; - IROLinear *loopscan; - IROLinear *indvar; - IROLinear *less; - IROLinear *loopExitTest; - IROLinear *saveTail; - CLabel *label2; - IROLinear *gotond; - CLabel *label3; - IROLinear *savedHead3; - IROLinear *updIndInc; - IROLinear *label2nd; - IROLinear *less2; - IROLinear *saveTail2; - IROLinear *less3; - IROLinear *wtf; - IROLinear *constnd; - IROLinear *ass; - IROLinear *nd18; - IRONode *fn19; - IRONode *newfnode1; - IRONode *newfnode2; - IRONode *newfnode3; - IRONode *newfnode4; - IRONode *newfnode5; - IRONode *newfnode6; - IRONode *newfnode7; - IRONode *newfnode8; - IROLinear *lastnd; - ENode *expr; - SInt32 result1; - SInt32 result2; - LoopPattern pattern; - IROList list; - - IRO_Dump("while(n--) loop \n"); - - if (loop->flags & LoopFlags_800) { - IRO_Dump("loop not unrolled because induction used in loop \n"); - return 0; - } - if (loop->flags & LoopFlags_1000) { - IRO_Dump("loop not unrolled because loop has multiple exits \n"); - return 0; - } - - if (!(loop->flags & LP_HAS_MULTIPLE_INDUCTIONS)) - return 0; - - for (ind = FirstInd; ind; ind = ind->next) { - if ((ind->flags & LoopInd_HasMod) && (ind->flags & LoopInd_HasDiv)) - break; - } - - if (!ind) { - IRO_Dump("Could not find loop with and induction with MOD and DIV operation\n"); - return 0; - } - - if (!IRO_IsUnsignedType(ind->nd->rtype)) - return 0; - - if (ind->nd->type == IROLinearOp2Arg) { - if (ind->nd->nodetype == EADDASS && IRO_IsConstant(ind->nd->u.diadic.right)) { - if (ind->addConst != 1) - return 0; - } else if (ind->nd->nodetype == EASS) { - if ( - ind->nd->u.diadic.right->type != IROLinearOp2Arg || - ind->nd->u.diadic.right->nodetype != EADD || - !IRO_IsConstant(ind->nd->u.diadic.right->u.diadic.right) - ) - return 0; - - if (ind->addConst != 1) - return 0; - } else { - return 0; - } - } else if (ind->nd->type == IROLinearOp1Arg && ind->nd->nodetype != EPREINC && ind->nd->nodetype != EPOSTINC) { - return 0; - } - - loop->induction = ind; - loop->index24 = ind->nd->index; - loop->index20 = IRO_FindStart(ind->nd)->index; - - scan = IRO_FirstNode; - memset(&pattern, 0, sizeof(pattern)); - while (scan) { - if (Bv_IsBitSet(scan->index, InLoop) && scan != header) { - if (!PatternMatchLoop(scan, loop, ind, &unrollFactor, &result1, &result2, &pattern)) - return 0; - } - scan = scan->nextnode; - } - - if (result1 > 1 || result2 > 1) - return 0; - - lastlabel = fnode2->last->u.label.label; - lastlabelnode = IRO_FindLabelNode(fnode2->last->u.label.label, fnode2->last); - - IRO_InitList(&list); - IRO_DuplicateExprRange(lastlabelnode->next, LoopNode->last->u.label.x4->u.diadic.left, &list); - IRO_DuplicateExpr(LoopNode->last->u.label.x4, &list); - IRO_Paste(list.head, list.tail, fnode2->last); - lastlabelnode = list.tail; - - IRO_InitList(&list); - earlyLoopExitTest = BuildEarlyLoopExitTest(LoopNode->last->type, &list); - earlyLoopExitTestLabel = IRO_NewLabel(); - earlyLoopExitTest->u.label.label = earlyLoopExitTestLabel; - earlyLoopExitTest->u.label.x4 = lastlabelnode; - earlyLoopExitTest->u.label.x4->flags |= IROLF_Reffed; - earlyLoopExitTest->rtype = LoopNode->last->rtype; - IRO_Paste(list.head, list.tail, fnode2->last); - - IRO_InitList(&list); - origIterationCount = BuildOrigIterationCount_DoWhile(&list, loop); - IRO_Paste(list.head, list.tail, fnode2->last); - savedHead60 = list.head; - - IRO_InitList(&list); - preAlignTemp = BuildPreAlignTemp(ind, unrollFactor, &list); - IRO_Paste(list.head, list.tail, fnode2->last); - - IRO_InitList(&list); - unrolledFinalValue = BuildUnrolledFinalvalue_DoWhile(origIterationCount, unrollFactor, &list, loop); - IRO_Paste(list.head, list.tail, fnode2->last); - - IRO_InitList(&list); - newFinalValue = BuildNewFinalvalue_DoWhile(origIterationCount, unrollFactor, &list, loop); - IRO_Paste(list.head, list.tail, fnode2->last); - - IRO_InitList(&list); - BuildUnrolledBodyEntryTest(&list, origIterationCount, unrollFactor, lastlabel); - IRO_Paste(list.head, list.tail, fnode2->last); - unrolledBodyEntryTest = list.tail; - - IRO_InitList(&list); - label = BuildLabel(&list); - IRO_Paste(list.head, list.tail, fnode2->last); - - savedHead2 = list.head; - loophead25 = NULL; - for (scan = fnode3; scan && scan != header; scan = scan->nextnode) { - IRO_InitList(&list); - loopend = scan->last; - loopscan = scan->first; - while (1) { - if (loopscan->stmt) - loopscan->stmt->flags |= StmtFlag_10; - if (loopscan->type != IROLinearLabel && !(loopscan->flags & IROLF_Reffed)) { - IRO_DuplicateExpr(loopscan, &list); - if (!loophead25) - loophead25 = list.head; - } - if (loopscan == loopend) - break; - loopscan = loopscan->next; - } - - if (list.head && list.tail) - IRO_Paste(list.head, list.tail, fnode2->last); - } - - IRO_InitList(&list); - - if (ind->nd->type == IROLinearOp1Arg) - IRO_DuplicateExpr(ind->nd->u.monadic, &list); - else - IRO_DuplicateExpr(ind->nd->u.diadic.left, &list); - list.tail->flags &= ~IROLF_Assigned; - indvar = list.tail; - - IRO_DuplicateExpr(preAlignTemp, &list); - list.tail->flags &= ~IROLF_Assigned; - - less = IRO_NewLinear(IROLinearOp2Arg); - less->nodetype = ELESS; - less->rtype = TYPE(&stbool); - less->index = ++IRO_NumLinear; - less->next = NULL; - less->u.diadic.left = indvar; - less->u.diadic.right = list.tail; - IRO_AddToList(less, &list); - less->flags |= IROLF_Reffed; - - loopExitTest = BuildLoopExitTest(LoopNode->last->type, &list); - loopExitTest->u.label.label = label; - loopExitTest->u.label.x4 = less; - loopExitTest->u.label.x4->flags |= IROLF_Reffed; - loopExitTest->rtype = LoopNode->last->rtype; - IRO_Paste(list.head, list.tail, fnode2->last); - saveTail = list.tail; - - IRO_InitList(&list); - label2 = IRO_NewLabel(); - gotond = IRO_NewLinear(IROLinearOp1Arg); - gotond->index = ++IRO_NumLinear; - gotond->type = IROLinearGoto; - gotond->u.label.label = label2; - IRO_AddToList(gotond, &list); - IRO_Paste(list.head, list.tail, fnode2->last); - - IRO_InitList(&list); - label3 = BuildLabel(&list); - IRO_Paste(list.head, list.tail, fnode2->last); - savedHead3 = list.head; - - UnrollWhileLoopBody(header, fnode2, fnode3, loop, &pattern, unrollFactor); - updIndInc = UpdateInductionIncrement(loop, 8 * unrollFactor, fnode2->last); - - IRO_InitList(&list); - label2nd = IRO_NewLinear(IROLinearLabel); - label2nd->index = IRO_NumLinear++; - label2nd->u.label.label = label2; - label2nd->flags |= IROLF_1; - IRO_AddToList(label2nd, &list); - IRO_Paste(list.head, list.tail, fnode2->last); - - IRO_InitList(&list); - - if (ind->nd->type == IROLinearOp1Arg) - IRO_DuplicateExpr(ind->nd->u.monadic, &list); - else - IRO_DuplicateExpr(ind->nd->u.diadic.left, &list); - list.tail->flags &= ~IROLF_Assigned; - indvar = list.tail; - - IRO_DuplicateExpr(unrolledFinalValue, &list); - list.tail->flags &= ~IROLF_Assigned; - - less2 = IRO_NewLinear(IROLinearOp2Arg); - less2->nodetype = ELESS; - less2->rtype = TYPE(&stbool); - less2->index = ++IRO_NumLinear; - less2->next = NULL; - less2->u.diadic.left = indvar; - less2->u.diadic.right = list.tail; - IRO_AddToList(less2, &list); - less2->flags |= IROLF_Reffed; - - loopExitTest = BuildLoopExitTest(LoopNode->last->type, &list); - loopExitTest->u.label.label = label3; - loopExitTest->u.label.x4 = less2; - loopExitTest->u.label.x4->flags |= IROLF_Reffed; - loopExitTest->rtype = LoopNode->last->rtype; - IRO_Paste(list.head, list.tail, fnode2->last); - saveTail2 = list.tail; - - IRO_InitList(&list); - - if (ind->nd->type == IROLinearOp1Arg) - IRO_DuplicateExpr(ind->nd->u.monadic, &list); - else - IRO_DuplicateExpr(ind->nd->u.diadic.left, &list); - list.tail->flags &= ~IROLF_Assigned; - indvar = list.tail; - - IRO_DuplicateExpr(newFinalValue, &list); - list.tail->flags &= ~IROLF_Assigned; - - less3 = IRO_NewLinear(IROLinearOp2Arg); - less3->nodetype = ELESS; - less3->rtype = TYPE(&stbool); - less3->index = ++IRO_NumLinear; - less3->next = NULL; - less3->u.diadic.left = indvar; - less3->u.diadic.right = list.tail; - IRO_AddToList(less3, &list); - less3->flags |= IROLF_Reffed; - - wtf = LoopNode->last->u.label.x4; - IRO_Paste(list.head, list.tail, LoopNode->last); - LoopNode->last->u.label.x4 = list.tail; - - IRO_InitList(&list); - - constnd = IRO_NewLinear(IROLinearOperand); - constnd->index = ++IRO_NumLinear; - expr = IRO_NewENode(EINTCONST); - expr->rtype = wtf->u.diadic.left->rtype; - expr->data.intval = cint64_zero; - constnd->u.node = expr; - constnd->rtype = expr->rtype; - IRO_AddToList(constnd, &list); - constnd->flags |= IROLF_Reffed; - - IRO_DuplicateExpr(wtf->u.diadic.left, &list); - - ass = IRO_NewLinear(IROLinearOp2Arg); - ass->nodetype = EASS; - ass->rtype = list.tail->rtype; - ass->index = ++IRO_NumLinear; - ass->next = NULL; - ass->u.diadic.left = list.tail; - ass->u.diadic.right = constnd; - IRO_AddToList(ass, &list); - ass->flags |= IROLF_Assigned; - - IRO_NopOut(wtf); - - fn19 = fnode2->nextnode; - nd18 = fnode2->last; - fnode2->last = earlyLoopExitTest; - - newfnode1 = IRO_NewFlowGraphNode(); - newfnode1->first = savedHead60; - newfnode1->last = unrolledBodyEntryTest; - fnode2->nextnode = newfnode1; - - newfnode2 = IRO_NewFlowGraphNode(); - newfnode2->first = savedHead2; - newfnode2->last = saveTail; - savedHead2->u.label.label->stmt = (Statement *) newfnode2; - newfnode1->nextnode = newfnode2; - - newfnode3 = IRO_NewFlowGraphNode(); - newfnode3->first = gotond; - newfnode3->last = gotond; - newfnode2->nextnode = newfnode3; - - newfnode4 = IRO_NewFlowGraphNode(); - newfnode4->first = savedHead3; - newfnode4->last = updIndInc; - savedHead3->u.label.label->stmt = (Statement *) newfnode4; - newfnode3->nextnode = newfnode4; - - newfnode5 = IRO_NewFlowGraphNode(); - newfnode5->first = label2nd; - newfnode5->last = saveTail2; - label2nd->u.label.label->stmt = (Statement *) newfnode5; - newfnode4->nextnode = newfnode5; - - newfnode6 = IRO_NewFlowGraphNode(); - newfnode6->first = nd18; - newfnode6->last = nd18; - newfnode5->nextnode = newfnode6; - newfnode6->nextnode = fn19; - - newfnode7 = oalloc(sizeof(IRONode)); - memset(newfnode7, 0, sizeof(IRONode)); - newfnode7->index = IRO_NumNodes; - IRO_NumNodes++; - - newfnode7->first = list.head; - newfnode7->last = list.tail; - - list.tail->next = LoopNode->last->next; - LoopNode->last->next = list.head; - - newfnode7->nextnode = LoopNode->nextnode; - LoopNode->nextnode = newfnode7; - - newfnode8 = oalloc(sizeof(IRONode)); - memset(newfnode8, 0, sizeof(IRONode)); - newfnode8->index = IRO_NumNodes; - IRO_NumNodes++; - - lastnd = IRO_NewLinear(IROLinearLabel); - lastnd->index = IRO_NumLinear++; - lastnd->next = NULL; - lastnd->u.label.label = earlyLoopExitTestLabel; - lastnd->flags |= IROLF_1; - earlyLoopExitTestLabel->stmt = (Statement *) newfnode8; - - newfnode8->first = lastnd; - newfnode8->last = lastnd; - - lastnd->next = newfnode7->last->next; - newfnode7->last->next = lastnd; - - newfnode8->nextnode = newfnode7->nextnode; - newfnode7->nextnode = newfnode8; - - return 1; -} - -void IRO_IterateForLoopBody(IRONode *start, IRONode *end, IROLoop *loop, IROLinear *destnode, SInt32 addConst, CInt64 *val, Boolean funkyFlag) { - IROLinear *first = NULL; - IROLinear *last = NULL; - IRONode *fnode; - IROLinear *lastnd; - IROLinear *nd; - IROList list; - - for (fnode = start; fnode && fnode != end; fnode = fnode->nextnode) { - IRO_InitList(&list); - - lastnd = fnode->last; - nd = fnode->first; - while (1) { - if (nd->stmt) - nd->stmt->flags |= StmtFlag_10; - - if ( - (nd->index < loop->index20 || nd->index > loop->index24) && - nd->type != IROLinearLabel && - !(nd->flags & IROLF_Reffed) - ) - { - IRO_DuplicateExpr(nd, &list); - if (!first) - first = list.head; - last = list.tail; - } - - if (nd == lastnd) - break; - nd = nd->next; - } - - if (list.head && list.tail) - IRO_Paste(list.head, list.tail, destnode); - } - - if (funkyFlag) { - *val = CInt64_Add(*val, IRO_MakeLong(loop->induction->addConst)); - ChangeInductionReference(first, last, *val, loop); - } -} - -void IRO_LinearizeForLoopPostLoop(IRONode *fnode1, IRONode *fnode2, IROLoop *loop, IRONode *fnode3, UInt32 unrollFactor) { - IRONode *newfnode; - IROLinear *newnd; - SInt32 i; - CInt64 val; - - newfnode = oalloc(sizeof(IRONode)); - memset(newfnode, 0, sizeof(IRONode)); - newfnode->index = IRO_NumNodes; - IRO_NumNodes++; - - newnd = IRO_NewLinear(IROLinearNop); - newnd->index = IRO_NumLinear++; - newnd->next = NULL; - newnd->flags |= IROLF_1; - - newfnode->first = newfnode->last = newnd; - - newfnode->nextnode = fnode3->nextnode; - fnode3->nextnode = newfnode; - - newnd->next = fnode3->last->next; - fnode3->last->next = newnd; - - val = cint64_zero; - for (i = 0; i < unrollFactor; i++) - IRO_IterateForLoopBody(fnode2, fnode1, loop, newfnode->last, loop->induction->addConst, &val, i > 0); - UpdateInductionIncrement(loop, unrollFactor, newfnode->last); -} - -static UInt32 UnrollForLoop(IRONode *header, IRONode *fnode2, IRONode *fnode3, IROLoop *loop, UInt32 unrollFactor) { - IROLinear *lastlabelnode; - IROLinear *earlyLoopExitTest; - IROLinear *origIterationCount; - IROLinear *saveHead1; - IROLinear *newFinalValue; - IROLinear *unrolledBodyEntryTest; - IROLinear *gotoNd; - IROLinear *saveHead2; - IROLinear *updIndInc; - IROLinear *labelNd; - IROLinear *saveTail2; - IROLinear *ndCopy; - IROLinear *saveTail3; - IROLinear *loopExitTest; - IROLinear *lastnd; - IROLinear *labelNd2; - IROLinear *saveTail4; - IROLinear *labelNd3; - IROLinear *scan; - IRONode *nd18; - IRONode *newfnode1; - IRONode *newfnode2; - IRONode *newfnode3; - IRONode *newfnode4; - IRONode *newfnode5; - IRONode *newfnode6; - CLabel *lastlabel; - CLabel *earlyLoopExitTestLabel; - CLabel *label; - CLabel *label2; - SInt32 i; - - IROList list; - CInt64 iterCount; - int isConstant; - UInt32 needOrigLoop = 0; - UInt32 needUnrollBodyTest = 0; - UInt32 resetUnrolledFinalValue = 0; - SInt32 leftOver; - CInt64 val; - - lastlabelnode = IRO_FindLabelNode(fnode2->last->u.label.label, fnode2->last); - lastlabel = IRO_NewLabel(); - - IRO_InitList(&list); - IRO_DuplicateExprRange(lastlabelnode->next, LoopNode->last->u.label.x4, &list); - IRO_DuplicateExpr(LoopNode->last->u.label.x4, &list); - IRO_Paste(list.head, list.tail, fnode2->last); - lastlabelnode = list.tail; - - IRO_InitList(&list); - earlyLoopExitTest = BuildEarlyLoopExitTest(LoopNode->last->type, &list); - earlyLoopExitTestLabel = IRO_NewLabel(); - earlyLoopExitTest->u.label.label = earlyLoopExitTestLabel; - earlyLoopExitTest->u.label.x4 = lastlabelnode; - earlyLoopExitTest->u.label.x4->flags |= IROLF_Reffed; - earlyLoopExitTest->rtype = LoopNode->last->rtype; - IRO_Paste(list.head, list.tail, fnode2->last); - - isConstant = IsIterationCountConstant(loop, &iterCount); - needOrigLoop = 1; - needUnrollBodyTest = 1; - resetUnrolledFinalValue = 0; - if (isConstant) - IRO_TestConstantIterationCount(loop, &iterCount, 1, &unrollFactor, &leftOver, &needOrigLoop, &needUnrollBodyTest, &resetUnrolledFinalValue); - - IRO_InitList(&list); - origIterationCount = BuildOrigIterationCount(&list, loop); - IRO_Paste(list.head, list.tail, fnode2->last); - saveHead1 = list.head; - - IRO_InitList(&list); - newFinalValue = BuildNewFinalvalue(origIterationCount, unrollFactor, &list, loop); - IRO_Paste(list.head, list.tail, fnode2->last); - - IRO_InitList(&list); - BuildUnrolledBodyEntryTest(&list, origIterationCount, unrollFactor, lastlabel); - IRO_Paste(list.head, list.tail, fnode2->last); - unrolledBodyEntryTest = list.tail; - - label = IRO_NewLabel(); - IRO_InitList(&list); - gotoNd = IRO_NewLinear(IROLinearOp1Arg); - gotoNd->index = ++IRO_NumLinear; - gotoNd->type = IROLinearGoto; - gotoNd->u.label.label = label; - IRO_AddToList(gotoNd, &list); - IRO_Paste(list.head, list.tail, fnode2->last); - - IRO_InitList(&list); - label2 = BuildLabel(&list); - IRO_Paste(list.head, list.tail, fnode2->last); - saveHead2 = list.head; - - val = cint64_zero; - for (i = 0; i < unrollFactor; i++) - IRO_IterateForLoopBody(fnode3, header, loop, fnode2->last, loop->induction->addConst, &val, i > 0); - updIndInc = UpdateInductionIncrement(loop, unrollFactor, fnode2->last); - - IRO_InitList(&list); - labelNd = IRO_NewLinear(IROLinearLabel); - labelNd->index = IRO_NumLinear++; - labelNd->u.label.label = label; - labelNd->flags |= IROLF_1; - IRO_AddToList(labelNd, &list); - IRO_Paste(list.head, list.tail, fnode2->last); - - IRO_InitList(&list); - - IRO_DuplicateExpr(LoopNode->last->u.label.x4->u.diadic.left, &list); - saveTail2 = list.tail; - - if (resetUnrolledFinalValue) - IRO_DuplicateExpr(loop->nd18->u.diadic.right, &list); - else - IRO_DuplicateExpr(newFinalValue, &list); - - ndCopy = IRO_NewLinear(LoopNode->last->u.label.x4->type); - *ndCopy = *LoopNode->last->u.label.x4; - ndCopy->index = ++IRO_NumLinear; - ndCopy->next = NULL; - ndCopy->expr = NULL; - ndCopy->u.diadic.left = saveTail2; - ndCopy->u.diadic.right = list.tail; - IRO_AddToList(ndCopy, &list); - - IRO_Paste(list.head, list.tail, fnode2->last); - saveTail3 = list.tail; - - IRO_InitList(&list); - loopExitTest = BuildLoopExitTest(LoopNode->last->type, &list); - loopExitTest->u.label.label = label2; - loopExitTest->u.label.x4 = saveTail3; - loopExitTest->u.label.x4->flags |= IROLF_Reffed; - loopExitTest->rtype = LoopNode->last->rtype; - IRO_Paste(list.head, list.tail, fnode2->last); - saveTail4 = list.tail; - - IRO_InitList(&list); - labelNd2 = IRO_NewLinear(IROLinearLabel); - labelNd2->index = IRO_NumLinear++; - labelNd2->u.label.label = lastlabel; - labelNd2->flags |= IROLF_1; - IRO_AddToList(labelNd2, &list); - IRO_Paste(list.head, list.tail, fnode2->last); - - lastnd = fnode2->last; - nd18 = fnode2->nextnode; - fnode2->last = earlyLoopExitTest; - - newfnode1 = IRO_NewFlowGraphNode(); - newfnode1->first = saveHead1; - newfnode1->last = unrolledBodyEntryTest; - fnode2->nextnode = newfnode1; - - newfnode2 = IRO_NewFlowGraphNode(); - newfnode2->first = gotoNd; - newfnode2->last = gotoNd; - newfnode1->nextnode = newfnode2; - - newfnode3 = IRO_NewFlowGraphNode(); - newfnode3->first = saveHead2; - newfnode3->last = updIndInc; - - saveHead2->u.label.label->stmt = (Statement *) newfnode3; - if (newfnode2) - newfnode2->nextnode = newfnode3; - else - newfnode1->nextnode = newfnode3; - - newfnode4 = IRO_NewFlowGraphNode(); - newfnode4->first = labelNd; - newfnode4->last = saveTail4; - labelNd->u.label.label->stmt = (Statement *) newfnode4; - newfnode3->nextnode = newfnode4; - - newfnode5 = IRO_NewFlowGraphNode(); - newfnode5->first = labelNd2; - newfnode5->last = lastnd; - newfnode4->nextnode = newfnode5; - newfnode5->nextnode = nd18; - - newfnode6 = oalloc(sizeof(IRONode)); - memset(newfnode6, 0, sizeof(IRONode)); - newfnode6->index = IRO_NumNodes; - IRO_NumNodes++; - - labelNd3 = IRO_NewLinear(IROLinearLabel); - labelNd3->index = IRO_NumLinear++; - labelNd3->next = NULL; - labelNd3->u.label.label = earlyLoopExitTestLabel; - labelNd3->flags |= IROLF_1; - earlyLoopExitTestLabel->stmt = (Statement *) newfnode6; - - newfnode6->first = labelNd3; - newfnode6->last = labelNd3; - - labelNd3->next = LoopNode->last->next; - LoopNode->last->next = labelNd3; - - newfnode6->nextnode = LoopNode->nextnode; - LoopNode->nextnode = newfnode6; - - if (!needOrigLoop) { - NoOpBlock(newfnode5); - NoOpBlock(header); - NoOpBlock(fnode3); - NoOpBlock(loop->induction->fnode); - IRO_NopOut(newfnode1->last->u.label.x4); - newfnode1->last->type = IROLinearNop; - } - - if (!needUnrollBodyTest) { - IRO_NopOut(earlyLoopExitTest->u.label.x4); - earlyLoopExitTest->type = IROLinearNop; - - IRO_NopOut(newfnode4->last->u.label.x4); - newfnode4->last->type = IROLinearNop; - - if (newfnode2) - newfnode2->last->type = IROLinearNop; - - for (scan = newfnode1->first; scan; scan = scan->next) { - if (!(scan->flags & IROLF_Reffed)) - IRO_NopOut(scan); - if (scan == newfnode1->last) - break; - } - } - - return 1; -} - -static UInt32 UnrollStandardLoop(IRONode *header, IRONode *fnode2, IRONode *fnode3, int count) { - IROLoop *loop; - - ConditionalHeaderAtBottom = 1; - loop = ExtractLoopInfo(header); - loop->xC = fnode2; - loop->x10 = fnode3; - FindAssignmenttoInductionVar(loop, fnode2); - - if (!IsLoopUnrollable(loop)) { - IRO_Dump("LoopUnroll:loop with header %d not unrolled because IsLoopUnrollable failed\n", header->index); - return 0; - } - - if (loop->flags & LoopFlags_10000) - return UnrollWhileLoop(header, fnode2, fnode3, loop, count); - else - return UnrollForLoop(header, fnode2, fnode3, loop, count); -} - -static void LoopUnroll(int count, IRONode *header) { - VarRecord *var; - IRONode *tmp; - UInt16 i; - UInt16 j; - IRONode *prevpred; - IRONode *prevsucc; - int foundpred; - UInt32 predcount; - UInt32 success = 0; - - LoopNode = header; - FindMustReach(); - - for (var = IRO_FirstVar; var; var = var->next) - var->xA = 1; - - ComputeLoopKills(); - ComputeLoopInvariance(); - ComputeLoopInduction(); - - LoopNode = header; - ConditionalHeaderAtBottom = 0; - - prevpred = NULL; - foundpred = 0; - for (i = 0; i < LoopNode->numpred; i++) { - tmp = IRO_NodeTable[LoopNode->pred[i]]; - if (!Bv_IsBitSet(tmp->index, InLoop)) { - foundpred = 1; - if (tmp->nextnode == header) { - CError_ASSERT(2101, !prevpred || tmp == prevpred); - prevpred = tmp; - } - } - } - - if (!foundpred) { - IRO_Dump("No predecessor outside the loop\n"); - return; - } - - if (LoopNode->last->type == IROLinearIf || LoopNode->last->type == IROLinearIfNot) { - if (LoopNode->nextnode && !Bv_IsBitSet(LoopNode->nextnode->index, InLoop)) { - prevsucc = NULL; - for (i = 0; i < LoopNode->numsucc; i++) { - tmp = IRO_NodeTable[LoopNode->succ[i]]; - if (Bv_IsBitSet(tmp->index, InLoop)) { - CError_ASSERT(2159, !prevsucc); - prevsucc = tmp; - } - } - - prevpred = NULL; - predcount = 0; - for (j = 0; j < LoopNode->numpred; j++) { - tmp = IRO_NodeTable[LoopNode->pred[j]]; - if (!Bv_IsBitSet(tmp->index, InLoop)) { - prevpred = tmp; - predcount++; - } - } - - if ( - predcount == 1 && - prevpred->last->type == IROLinearGoto && - prevpred->nextnode == prevsucc && - prevsucc != LoopNode - ) - { - success = UnrollStandardLoop(header, prevpred, prevsucc, count); - } - } - } else { - IRO_Dump(" LoopUnroll:Loop with header = %d is not a conditional loop\n", header->index); - } - - if (!success) - return; - - IRO_NodeTable = oalloc(sizeof(IRONode *) * IRO_NumNodes); - memset(IRO_NodeTable, 0, sizeof(IRONode *) * IRO_NumNodes); - for (tmp = IRO_FirstNode; tmp; tmp = tmp->nextnode) - IRO_NodeTable[tmp->index] = tmp; - IRO_ComputeSuccPred(); - IRO_ComputeDom(); - if (success) - IRO_Dump(" LoopUnroll:Loop with header = %d Unrolled\n", header->index); -} - -static int IsLoopUnrollable(IROLoop *loop) { - CInt64 tmp; - - if (loop->flags & LP_LOOP_HAS_ASM) { - IRO_Dump("IsLoopUnrollable:No due to LP_LOOP_HAS_ASM \n"); - return 0; - } - if (loop->flags & LP_IFEXPR_NON_CANONICAL) { - IRO_Dump("IsLoopUnrollable:No due to LP_IFEXPR_NON_CANONICAL \n"); - return 0; - } - if (loop->flags & LP_LOOP_HAS_CALLS) { - IRO_Dump("IsLoopUnrollable:No due to LP_LOOP_HAS_CALLS \n"); - return 0; - } - if (loop->flags & LP_LOOP_HAS_CNTRLFLOW) { - IRO_Dump("IsLoopUnrollable:No due to LP_LOOP_HAS_CNTRLFLOW \n"); - return 0; - } - if (loop->flags & LP_INDUCTION_NOT_FOUND) { - IRO_Dump("IsLoopUnrollable:No due to LP_INDUCTION_NOT_FOUND \n"); - return 0; - } - if (loop->flags & LP_LOOP_HDR_HAS_SIDEEFFECTS) { - IRO_Dump("IsLoopUnrollable:No due to LP_LOOP_HDR_HAS_SIDEEFFECTS \n"); - return 0; - } - if (!(loop->flags & LoopFlags_200)) { - IRO_Dump("IsLoopUnrollable:No because header does not follow induction update \n"); - return 0; - } - - if (!(loop->flags & LoopFlags_10000)) { - IROLinear *upperBound = loop->nd18->u.diadic.right; - if (!IRO_IsIntConstant(upperBound) && !(upperBound->flags & IROLF_LoopInvariant)) { - IRO_Dump("IsLoopUnrollable:No because Loop Upper Bound is Variant in the loop\n"); - return 0; - } - if (!loop->nd14) { - IRO_Dump("IsLoopUnrollable:No because there is no initialization of loop index in PreHeader\n"); - return 0; - } - if (!IRO_IsVariable(loop->nd14->u.diadic.left)) { - IRO_Dump("IsLoopUnrollable:No because initial value of induction stored thru pointer\n"); - return 0; - } - - if (!IRO_IsUnsignedType(loop->nd14->rtype)) { - if (IRO_IsIntConstant(loop->nd14->u.diadic.right)) { - if (!CInt64_GreaterEqual(loop->nd14->u.diadic.right->u.node->data.intval, cint64_zero)) { - IRO_Dump("IsLoopUnrollable:No because initial value of induction is signed but init < 0\n"); - return 0; - } - } else if (IsIterationCountConstant(loop, &tmp)) { - IRO_Dump("IsLoopUnrollable:Yes, the limits substract out to be constants\n"); - } else { - IRO_Dump("IsLoopUnrollable:No because initial value of induction is signed and not constant\n"); - return 0; - } - } - - if (!(loop->flags & LP_LOOP_STEP_ISADD)) { - IRO_Dump("IsLoopUnrollable:No because LP_LOOP_STEP_ISADD is not set i.e induciton is not updated by 1\n"); - return 0; - } - - } else { - if (!IRO_IsUnsignedType(loop->nd18->u.diadic.left->rtype)) { - IRO_Dump("IsLoopUnrollable:No because the while loop induction is signed\n"); - return 0; - } - if (!(loop->flags & LoopFlags_2000)) { - IRO_Dump("IsLoopUnrollable:No because the while loop operator is not of decrement form\n"); - return 0; - } - } - - if (loop->sizeBySomeMeasurement > copts.unrollinstrfactor) { - IRO_Dump("IsLoopUnrollable:No because loop size greater than threshold\n"); - return 0; - } - - return 1; -} - -IROLinear *BuildEarlyLoopExitTest(IROLinearType type, IROList *list) { - IROLinear *nd = IRO_NewLinear(IROLinearOp1Arg); - nd->index = ++IRO_NumLinear; - if (type == IROLinearIf) - nd->type = IROLinearIfNot; - else - nd->type = IROLinearIf; - IRO_AddToList(nd, list); - return nd; -} - -IROLinear *BuildLoopExitTest(IROLinearType type, IROList *list) { - IROLinear *nd = IRO_NewLinear(IROLinearOp1Arg); - nd->index = ++IRO_NumLinear; - nd->type = type; - IRO_AddToList(nd, list); - return nd; -} - -int IsIterationCountConstant(IROLoop *loop, CInt64 *pval) { - IROLinear *lowerBound; - IROLinear *upperBound; - Type *type; - int isUnsigned; - IROAddrRecord *lowerRec; - IROAddrRecord *upperRec; - CInt64 lowerval; - CInt64 upperval; - CInt64 incval; - CInt64 negOne; - - lowerBound = loop->nd14->u.diadic.right; - if (loop->flags & LoopFlags_1) { - upperBound = loop->nd18->u.diadic.right; - type = loop->nd18->u.diadic.right->rtype; - } else { - upperBound = loop->nd18->u.diadic.left; - type = loop->nd18->u.diadic.left->rtype; - } - - isUnsigned = IRO_IsUnsignedType(type); - - if (IRO_IsIntConstant(lowerBound) && IRO_IsIntConstant(upperBound)) { - lowerval = lowerBound->u.node->data.intval; - upperval = upperBound->u.node->data.intval; - if (isUnsigned) { - if (CInt64_LessEqualU(upperval, lowerval)) - return 0; - } else { - if (CInt64_LessEqual(upperval, lowerval)) - return 0; - } - - CInt64_SetLong(&incval, loop->induction->addConst); - CInt64_SetLong(&negOne, -1); - *pval = CInt64_Sub(upperval, lowerval); - *pval = CInt64_Add(*pval, incval); - - if (IS_LINEAR_DIADIC(loop->nd18, ELESS)) - *pval = CInt64_Add(*pval, negOne); - - CError_ASSERT(2486, !CInt64_IsZero(&incval)); - - if (isUnsigned) - *pval = CInt64_DivU(*pval, incval); - else - *pval = CInt64_Div(*pval, incval); - - if (CInt64_Equal(*pval, cint64_zero)) - return 0; - - if (isUnsigned) { - CError_ASSERT(2508, !CInt64_LessEqualU(*pval, cint64_zero)); - } else { - CError_ASSERT(2517, !CInt64_LessEqual(*pval, cint64_zero)); - } - - return 1; - } - - lowerRec = IRO_InitAddrRecordPointer(lowerBound); - upperRec = IRO_InitAddrRecordPointer(upperBound); - - if (IS_LINEAR_DIADIC(lowerBound, EADD)) { - IRO_DecomposeAddressExpression(lowerBound, lowerRec); - } else if (IRO_IsIntConstant(lowerBound)) { - lowerRec->numInts++; - IRO_AddElmToList(lowerBound, &lowerRec->ints); - lowerRec->numObjRefs = 0; - lowerRec->numMisc = 0; - } else { - lowerRec->numMisc++; - IRO_AddElmToList(lowerBound, &lowerRec->misc); - lowerRec->numObjRefs = 0; - lowerRec->numInts = 0; - } - - if (IS_LINEAR_DIADIC(upperBound, EADD)) { - IRO_DecomposeAddressExpression(upperBound, upperRec); - } else if (IRO_IsIntConstant(upperBound)) { - upperRec->numInts++; - IRO_AddElmToList(upperBound, &upperRec->ints); - upperRec->numObjRefs = 0; - upperRec->numMisc = 0; - } else { - upperRec->numMisc++; - IRO_AddElmToList(upperBound, &upperRec->misc); - upperRec->numObjRefs = 0; - upperRec->numInts = 0; - } - - if (IsDifferenceOfTermsConstant(lowerRec, upperRec, isUnsigned, pval)) { - if (IS_LINEAR_DIADIC(loop->nd18, ELESSEQU)) - *pval = CInt64_Add(*pval, cint64_one); - return 1; - } - - return 0; -} - -static int IsDifferenceOfTermsConstant(IROAddrRecord *lowerRec, IROAddrRecord *upperRec, int isUnsigned, CInt64 *pval) { - UInt32 i; - CInt64 upperval; - CInt64 lowerval; - IROElmList *el; - IROLinear *nd; - - if (upperRec->numObjRefs == lowerRec->numObjRefs && upperRec->numObjRefs != 0) - return 0; - else if (upperRec->numObjRefs != lowerRec->numObjRefs) - return 0; - - if (upperRec->numMisc == lowerRec->numMisc && upperRec->numMisc != 0) { - for (i = 0; i < upperRec->numMisc; i++) { - // bug? surely this should index on i...? - if (!IRO_ExprsSame(lowerRec->misc->element, upperRec->misc->element)) - return 0; - } - } else if (upperRec->numMisc != lowerRec->numMisc) { - return 0; - } - - upperval = cint64_zero; - for (el = upperRec->ints; el; el = el->next) { - nd = el->element; - upperval = CMach_CalcIntDiadic(nd->rtype, upperval, '+', nd->u.node->data.intval); - } - - lowerval = cint64_zero; - for (el = lowerRec->ints; el; el = el->next) { - nd = el->element; - lowerval = CMach_CalcIntDiadic(nd->rtype, lowerval, '+', nd->u.node->data.intval); - } - - if (CInt64_Equal(upperval, lowerval)) - return 0; - - if (CInt64_Greater(upperval, lowerval)) { - *pval = CInt64_Sub(upperval, lowerval); - return 1; - } else { - return 0; - } -} - -void NoOpBlock(IRONode *fnode) { - IROLinear *last, *scan; - - for (scan = fnode->first, last = fnode->last; scan; scan = scan->next) { - scan->type = IROLinearNop; - if (scan == last) - break; - } -} - -void IRO_TestConstantIterationCount(IROLoop *loop, CInt64 *iterCount, SInt32 vectorStride, UInt32 *unrollFactor, SInt32 *leftOver, UInt32 *needOrigLoop, UInt32 *needUnrollBodyTest, UInt32 *resetUnrolledFinalValue) { - UInt32 isUnsigned; - CInt64 val; - CInt64 val3; - CInt64 mod; - CInt64 val2; - CInt64 loopvar3; - CInt64 loopvar1; - CInt64 loopvar2; - CInt64 strideVal; - - CError_ASSERT(2737, *unrollFactor); - - isUnsigned = IRO_IsUnsignedType( - (loop->flags & LoopFlags_1) ? loop->nd18->u.diadic.right->rtype :loop->nd18->u.diadic.left->rtype); - - CError_ASSERT(2756, vectorStride); - - strideVal = IRO_MakeLong(vectorStride); - if (isUnsigned ? CInt64_LessU(*iterCount, strideVal) : CInt64_Less(*iterCount, strideVal)) { - *needOrigLoop = 1; - *needUnrollBodyTest = 0; - *unrollFactor = 0; - *leftOver = CInt64_GetULong(iterCount); - } else { - switch (vectorStride) { - case 1: - val = *iterCount; - break; - case 2: - val = CInt64_ShrU(*iterCount, cint64_one); - break; - case 4: - val = CInt64_ShrU(*iterCount, IRO_MakeLong(2)); - break; - case 8: - val = CInt64_ShrU(*iterCount, IRO_MakeLong(3)); - break; - case 16: - val = CInt64_ShrU(*iterCount, IRO_MakeLong(4)); - break; - default: - val = CInt64_Div(*iterCount, strideVal); - } - - if (CInt64_LessU(val, IRO_MakeLong(*unrollFactor))) - *unrollFactor = CInt64_GetULong(&val); - - CInt64_SetLong(&val2, *unrollFactor); - switch (vectorStride) { - case 1: - val3 = cint64_zero; - break; - case 2: - val3 = CInt64_And(*iterCount, cint64_one); - break; - case 4: - val3 = CInt64_And(*iterCount, IRO_MakeLong(3)); - break; - case 8: - val3 = CInt64_And(*iterCount, IRO_MakeLong(7)); - break; - case 16: - val3 = CInt64_And(*iterCount, IRO_MakeLong(15)); - break; - default: - val3 = CInt64_Mod(*iterCount, strideVal); - } - - if (CInt64_LessEqualU(val, IRO_MakeLong(8))) { - *needUnrollBodyTest = vectorStride > 1; - *unrollFactor = CInt64_GetULong(&val); - *leftOver = CInt64_GetULong(&val3); - *needOrigLoop = *leftOver != 0; - *resetUnrolledFinalValue = !(*needOrigLoop && *needUnrollBodyTest); - } else { - loopvar1 = IRO_MakeLong(0x7FFFFFFF); - loopvar2 = IRO_MakeLong(0x7FFFFFFF); - do { - mod = CInt64_Mod(val, val2); - loopvar3 = CInt64_Add(CInt64_Mul(mod, strideVal), val3); - if (CInt64_Less(loopvar3, loopvar2)) { - loopvar2 = loopvar3; - loopvar1 = val2; - } - if (vectorStride > 1) - break; - val2 = CInt64_Add(val2, cint64_negone); - } while (CInt64_GreaterEqualU(CInt64_Mul(val2, val2), val)); - - *unrollFactor = CInt64_GetULong(&loopvar1); - *leftOver = CInt64_GetULong(&loopvar2); - *needOrigLoop = *leftOver != 0; - *needUnrollBodyTest = CInt64_Less(loopvar1, val) || vectorStride > 1; - *resetUnrolledFinalValue = !(*needOrigLoop && *needUnrollBodyTest); - } - } - - IRO_Dump( - "---- IterCount = %d, VectorStride = %d, UnrollFactor = %d, LeftOver = %d,\n" - "\tNeedOrigLoop = %d, NeedUnrollBodyTest = %d, ResetUnrolledFinalValue = %d\n", - CInt64_GetULong(iterCount), vectorStride, *unrollFactor, *leftOver, - *needOrigLoop, *needUnrollBodyTest, *resetUnrolledFinalValue - ); -} - -IROLinear *BuildOrigIterationCount(IROList *list, IROLoop *loop) { - IROLinear *upperBound; - IROLinear *nd29b; - IROLinear *lowerBound; - IROLinear *finalCount; - IROLinear *divisor; - Type *type; - IROLinear *nd25; - IROLinear *tmp; - Boolean isZeroBase; - Object *tempobj; - IROLinear *iterCount; - IROLinear *negone; - IROLinear *ass; - ENode *expr; - SInt32 powval; - - isZeroBase = 0; - lowerBound = loop->nd14->u.diadic.right; - if (IRO_IsIntConstant(lowerBound) && CInt64_Equal(lowerBound->u.node->data.intval, cint64_zero)) - isZeroBase = 1; - - if (!isZeroBase) - lowerBound = IRO_DuplicateExpr(lowerBound, list); - - if (loop->flags & LoopFlags_1) { - upperBound = IRO_DuplicateExpr(loop->nd18->u.diadic.right, list); - type = loop->nd18->u.diadic.right->rtype; - } else { - upperBound = IRO_DuplicateExpr(loop->nd18->u.diadic.left, list); - type = loop->nd18->u.diadic.left->rtype; - } - - CError_ASSERT(2924, loop->induction); - CError_ASSERT(2929, loop->induction->addConst); - - divisor = IRO_NewLinear(IROLinearOperand); - divisor->index = ++IRO_NumLinear; - divisor->rtype = type; - expr = IRO_NewENode(EINTCONST); - expr->rtype = type; - CInt64_SetLong(&expr->data.intval, loop->induction->addConst); - divisor->u.node = expr; - - if (isZeroBase) { - iterCount = upperBound; - } else { - iterCount = IRO_NewLinear(IROLinearOp2Arg); - iterCount->index = ++IRO_NumLinear; - iterCount->nodetype = ESUB; - iterCount->u.diadic.left = upperBound; - iterCount->u.diadic.right = lowerBound; - iterCount->rtype = type; - IRO_AddToList(iterCount, list); - } - - nd25 = IRO_DuplicateExpr(divisor, list); - - nd29b = IRO_NewLinear(IROLinearOp2Arg); - nd29b->index = ++IRO_NumLinear; - nd29b->nodetype = EADD; - nd29b->u.diadic.left = iterCount; - nd29b->u.diadic.right = nd25; - nd29b->rtype = type; - IRO_AddToList(nd29b, list); - - if (loop->nd18->type == IROLinearOp2Arg && loop->nd18->nodetype == ELESS) { - tmp = nd29b; - - negone = IRO_NewLinear(IROLinearOperand); - negone->index = ++IRO_NumLinear; - negone->rtype = type; - expr = IRO_NewENode(EINTCONST); - expr->rtype = type; - CInt64_SetLong(&expr->data.intval, -1); - negone->u.node = expr; - IRO_AddToList(negone, list); - - nd29b = IRO_NewLinear(IROLinearOp2Arg); - nd29b->index = ++IRO_NumLinear; - nd29b->nodetype = EADD; - nd29b->u.diadic.left = tmp; - nd29b->u.diadic.right = negone; - nd29b->rtype = type; - IRO_AddToList(nd29b, list); - } - - if (CInt64_Equal(divisor->u.node->data.intval, cint64_one)) { - finalCount = nd29b; - } else { - if (divisor->rtype->size <= 4 && IS_TYPE_INT(divisor->rtype) && IRO_IsPow2(divisor, &powval)) { - finalCount = IRO_NewLinear(IROLinearOp2Arg); - finalCount->index = ++IRO_NumLinear; - finalCount->nodetype = ESHL; - finalCount->u.diadic.left = nd29b; - finalCount->u.diadic.right = divisor; - CInt64_SetLong(&divisor->u.node->data.intval, powval); - finalCount->rtype = type; - IRO_AddToList(divisor, list); - IRO_AddToList(finalCount, list); - } else { - finalCount = IRO_NewLinear(IROLinearOp2Arg); - finalCount->index = ++IRO_NumLinear; - finalCount->nodetype = EDIV; - finalCount->u.diadic.left = nd29b; - finalCount->u.diadic.right = divisor; - finalCount->rtype = type; - IRO_AddToList(divisor, list); - IRO_AddToList(finalCount, list); - } - } - - tempobj = create_temp_object(type); - IRO_FindVar(tempobj, 1, 1); - - ass = IRO_NewLinear(IROLinearOp2Arg); - ass->index = ++IRO_NumLinear; - ass->nodetype = EASS; - ass->u.diadic.left = IRO_TempReference(tempobj, list); - ass->u.diadic.left->flags |= IROLF_Assigned | IROLF_Ind; - ass->u.diadic.left->u.monadic->flags |= IROLF_Assigned | IROLF_Ind; - ass->u.diadic.right = finalCount; - ass->u.diadic.right->flags |= IROLF_Reffed; - ass->rtype = type; - IRO_AddToList(ass, list); - - return ass->u.diadic.left; -} - -static IROLinear *BuildOrigIterationCount_DoWhile(IROList *list, IROLoop *loop) { - IROLinear *finalCount; - IROLinear *count; - IROLinear *ass; - Type *type; - Object *tempobj; - ENode *expr; - - type = loop->nd18->u.diadic.left->rtype; - - count = IRO_NewLinear(IROLinearOperand); - count->index = ++IRO_NumLinear; - expr = IRO_NewENode(EINTCONST); - expr->rtype = type; - expr->data.intval = cint64_one; - count->u.node = expr; - count->rtype = type; - IRO_AddToList(count, list); - count->flags |= IROLF_Reffed; - - finalCount = IRO_NewLinear(IROLinearOp2Arg); - finalCount->index = ++IRO_NumLinear; - finalCount->nodetype = EADD; - finalCount->rtype = type; - finalCount->u.diadic.left = IRO_DuplicateExpr(loop->nd18->u.diadic.left, list); - finalCount->u.diadic.left->flags |= IROLF_Reffed; - finalCount->u.diadic.left->flags &= ~IROLF_Assigned; - finalCount->u.diadic.left->u.monadic->flags &= ~IROLF_Assigned; - finalCount->u.diadic.right = count; - IRO_AddToList(finalCount, list); - - tempobj = create_temp_object(type); - IRO_FindVar(tempobj, 1, 1); - - ass = IRO_NewLinear(IROLinearOp2Arg); - ass->index = ++IRO_NumLinear; - ass->nodetype = EASS; - ass->u.diadic.left = IRO_TempReference(tempobj, list); - ass->u.diadic.left->flags |= IROLF_Assigned | IROLF_Ind; - ass->u.diadic.left->u.monadic->flags |= IROLF_Assigned | IROLF_Ind; - ass->u.diadic.right = finalCount; - ass->rtype = type; - IRO_AddToList(ass, list); - - return ass->u.diadic.left; -} - -IROLinear *BuildNewFinalvalue(IROLinear *iterCount, UInt32 unrollFactor, IROList *list, IROLoop *loop) { - IROLinear *sub; - IROLinear *addvalue; - Type *type; - IROLinear *ass; - IROLinear *dupbound; - Object *tempobj; - ENode *expr; - - type = iterCount->rtype; - - addvalue = IRO_NewLinear(IROLinearOperand); - addvalue->index = ++IRO_NumLinear; - addvalue->rtype = type; - expr = IRO_NewENode(EINTCONST); - expr->rtype = type; - CInt64_SetLong(&expr->data.intval, loop->induction->addConst * unrollFactor); - addvalue->u.node = expr; - IRO_AddToList(addvalue, list); - - if (loop->flags & LoopFlags_1) - dupbound = IRO_DuplicateExpr(loop->nd18->u.diadic.right, list); - else - dupbound = IRO_DuplicateExpr(loop->nd18->u.diadic.left, list); - - sub = IRO_NewLinear(IROLinearOp2Arg); - sub->index = ++IRO_NumLinear; - sub->nodetype = ESUB; - sub->u.diadic.left = dupbound; - sub->u.diadic.right = addvalue; - sub->rtype = type; - IRO_AddToList(sub, list); - - tempobj = create_temp_object(type); - IRO_FindVar(tempobj, 1, 1); - - ass = IRO_NewLinear(IROLinearOp2Arg); - ass->index = ++IRO_NumLinear; - ass->nodetype = EASS; - ass->u.diadic.left = IRO_TempReference(tempobj, list); - ass->u.diadic.left->flags |= IROLF_Assigned | IROLF_Ind; - ass->u.diadic.left->u.monadic->flags |= IROLF_Assigned | IROLF_Ind; - ass->u.diadic.right = sub; - ass->u.diadic.right->flags |= IROLF_Reffed; - ass->rtype = type; - IRO_AddToList(ass, list); - - return ass->u.diadic.left; -} - -static IROLinear *BuildPreAlignTemp(IROLoopInd *ind, UInt32 unrollFactor, IROList *list) { - Type *type; - IROLinear *indnd; - IROLinear *factornd; - IROLinear *div; - IROLinear *constnd; - IROLinear *add; - IROLinear *mul; - IROLinear *ass; - Object *tempobj; - ENode *expr; - - indnd = ind->nd; - type = indnd->rtype; - - factornd = IRO_NewLinear(IROLinearOperand); - factornd->index = ++IRO_NumLinear; - factornd->rtype = type; - expr = IRO_NewENode(EINTCONST); - expr->rtype = type; - CInt64_SetLong(&expr->data.intval, unrollFactor); - factornd->u.node = expr; - IRO_AddToList(factornd, list); - - if (indnd->type == IROLinearOp1Arg) - IRO_DuplicateExpr(indnd->u.monadic, list); - else - IRO_DuplicateExpr(indnd->u.diadic.left, list); - - list->tail->flags &= ~IROLF_Assigned; - list->tail->u.monadic->flags &= ~IROLF_Assigned; - - div = IRO_NewLinear(IROLinearOp2Arg); - div->index = ++IRO_NumLinear; - div->nodetype = EDIV; - div->u.diadic.left = list->tail; - div->u.diadic.right = factornd; - div->rtype = type; - IRO_AddToList(div, list); - div->flags |= IROLF_Reffed; - - constnd = IRO_NewLinear(IROLinearOperand); - constnd->index = ++IRO_NumLinear; - expr = IRO_NewENode(EINTCONST); - expr->rtype = type; - expr->data.intval = cint64_one; - constnd->u.node = expr; - constnd->rtype = type; - IRO_AddToList(constnd, list); - constnd->flags |= IROLF_Reffed; - - add = IRO_NewLinear(IROLinearOp2Arg); - add->index = ++IRO_NumLinear; - add->nodetype = EADD; - add->u.diadic.left = div; - add->u.diadic.right = constnd; - add->rtype = type; - IRO_AddToList(add, list); - add->flags |= IROLF_Reffed; - - IRO_DuplicateExpr(factornd, list); - - mul = IRO_NewLinear(IROLinearOp2Arg); - mul->index = ++IRO_NumLinear; - mul->nodetype = EMUL; - mul->u.diadic.left = add; - mul->u.diadic.right = list->tail; - mul->rtype = type; - IRO_AddToList(mul, list); - mul->flags |= IROLF_Reffed; - - tempobj = create_temp_object(type); - IRO_FindVar(tempobj, 1, 1); - - ass = IRO_NewLinear(IROLinearOp2Arg); - ass->index = ++IRO_NumLinear; - ass->nodetype = EASS; - ass->u.diadic.left = IRO_TempReference(tempobj, list); - ass->u.diadic.left->flags |= IROLF_Assigned | IROLF_Ind; - ass->u.diadic.left->u.monadic->flags |= IROLF_Assigned | IROLF_Ind; - ass->u.diadic.right = mul; - ass->u.diadic.right->flags |= IROLF_Reffed; - ass->rtype = type; - IRO_AddToList(ass, list); - - return ass->u.diadic.left; -} - -static IROLinear *BuildNewFinalvalue_DoWhile(IROLinear *iterCount, UInt32 unrollFactor, IROList *list, IROLoop *loop) { - IROLinear *addvalue; - IROLinear *add; - IROLinear *mul; - IROLinear *ass; - Type *type; - Object *tempobj; - ENode *expr; - - type = iterCount->rtype; - - addvalue = IRO_NewLinear(IROLinearOperand); - addvalue->index = ++IRO_NumLinear; - addvalue->rtype = type; - expr = IRO_NewENode(EINTCONST); - expr->rtype = type; - CInt64_SetLong(&expr->data.intval, loop->induction->addConst); - addvalue->u.node = expr; - IRO_AddToList(addvalue, list); - addvalue->flags |= IROLF_Reffed; - - mul = IRO_NewLinear(IROLinearOp2Arg); - mul->index = ++IRO_NumLinear; - mul->nodetype = EMUL; - mul->u.diadic.left = IRO_DuplicateExpr(iterCount, list); - mul->u.diadic.right = addvalue; - mul->rtype = type; - IRO_AddToList(mul, list); - mul->flags |= IROLF_Reffed; - mul->u.diadic.left->flags &= ~IROLF_Assigned; - mul->u.diadic.left->u.diadic.left->flags &= ~IROLF_Assigned; - - if (loop->induction->nd->type == IROLinearOp1Arg) - IRO_DuplicateExpr(loop->induction->nd->u.monadic, list); - else - IRO_DuplicateExpr(loop->induction->nd->u.diadic.left, list); - list->tail->flags &= ~IROLF_Assigned; - list->tail->u.diadic.left->flags &= ~IROLF_Assigned; - - add = IRO_NewLinear(IROLinearOp2Arg); - add->index = ++IRO_NumLinear; - add->nodetype = EADD; - add->u.diadic.left = mul; - add->u.diadic.right = list->tail; - add->rtype = type; - IRO_AddToList(add, list); - add->flags |= IROLF_Reffed; - - tempobj = create_temp_object(type); - IRO_FindVar(tempobj, 1, 1); - - ass = IRO_NewLinear(IROLinearOp2Arg); - ass->index = ++IRO_NumLinear; - ass->nodetype = EASS; - ass->u.diadic.left = IRO_TempReference(tempobj, list); - ass->u.diadic.left->flags |= IROLF_Assigned | IROLF_Ind; - ass->u.diadic.left->u.monadic->flags |= IROLF_Assigned | IROLF_Ind; - ass->u.diadic.right = add; - ass->u.diadic.right->flags |= IROLF_Reffed; - ass->rtype = type; - IRO_AddToList(ass, list); - - return ass->u.diadic.left; -} - -static IROLinear *BuildUnrolledFinalvalue_DoWhile(IROLinear *iterCount, UInt32 unrollFactor, IROList *list, IROLoop *loop) { - IROLinear *addvalue_mult; - IROLinear *addvalue; - IROLinear *mul; - IROLinear *sub; - IROLinear *add; - IROLinear *ass; - Type *type; - Object *tempobj; - ENode *expr; - - type = iterCount->rtype; - - addvalue_mult = IRO_NewLinear(IROLinearOperand); - addvalue_mult->index = ++IRO_NumLinear; - addvalue_mult->rtype = type; - expr = IRO_NewENode(EINTCONST); - expr->rtype = type; - CInt64_SetLong(&expr->data.intval, loop->induction->addConst * unrollFactor); - addvalue_mult->u.node = expr; - IRO_AddToList(addvalue_mult, list); - addvalue_mult->flags |= IROLF_Reffed; - - addvalue = IRO_NewLinear(IROLinearOperand); - addvalue->index = ++IRO_NumLinear; - addvalue->rtype = type; - expr = IRO_NewENode(EINTCONST); - expr->rtype = type; - CInt64_SetLong(&expr->data.intval, loop->induction->addConst); - addvalue->u.node = expr; - IRO_AddToList(addvalue, list); - addvalue->flags |= IROLF_Reffed; - - mul = IRO_NewLinear(IROLinearOp2Arg); - mul->index = ++IRO_NumLinear; - mul->nodetype = EMUL; - mul->u.diadic.left = IRO_DuplicateExpr(iterCount, list); - mul->u.diadic.right = addvalue; - mul->rtype = type; - IRO_AddToList(mul, list); - mul->flags |= IROLF_Reffed; - mul->u.diadic.left->flags &= ~IROLF_Assigned; - mul->u.diadic.left->u.diadic.left->flags &= ~IROLF_Assigned; - - sub = IRO_NewLinear(IROLinearOp2Arg); - sub->index = ++IRO_NumLinear; - sub->nodetype = ESUB; - sub->u.diadic.left = mul; - sub->u.diadic.right = addvalue_mult; - sub->rtype = type; - IRO_AddToList(sub, list); - sub->flags |= IROLF_Reffed; - - if (loop->induction->nd->type == IROLinearOp1Arg) - IRO_DuplicateExpr(loop->induction->nd->u.monadic, list); - else - IRO_DuplicateExpr(loop->induction->nd->u.diadic.left, list); - list->tail->flags &= ~IROLF_Assigned; - list->tail->u.diadic.left->flags &= ~IROLF_Assigned; - - add = IRO_NewLinear(IROLinearOp2Arg); - add->index = ++IRO_NumLinear; - add->nodetype = EADD; - add->u.diadic.left = sub; - add->u.diadic.right = list->tail; - add->rtype = type; - IRO_AddToList(add, list); - add->flags |= IROLF_Reffed; - - tempobj = create_temp_object(type); - IRO_FindVar(tempobj, 1, 1); - - ass = IRO_NewLinear(IROLinearOp2Arg); - ass->index = ++IRO_NumLinear; - ass->nodetype = EASS; - ass->u.diadic.left = IRO_TempReference(tempobj, list); - ass->u.diadic.left->flags |= IROLF_Assigned | IROLF_Ind; - ass->u.diadic.left->u.monadic->flags |= IROLF_Assigned | IROLF_Ind; - ass->u.diadic.right = add; - ass->u.diadic.right->flags |= IROLF_Reffed; - ass->rtype = type; - IRO_AddToList(ass, list); - - return ass->u.diadic.left; -} - -void BuildUnrolledBodyEntryTest(IROList *list, IROLinear *iterCount, UInt32 unrollFactor, CLabel *label) { - Type *type; - IROLinear *ifnot; - IROLinear *comp; - IROLinear *var; - IROLinear *value; - ENode *expr; - - type = iterCount->rtype; - - value = IRO_NewLinear(IROLinearOperand); - value->index = ++IRO_NumLinear; - value->rtype = type; - expr = IRO_NewENode(EINTCONST); - expr->rtype = type; - CInt64_SetLong(&expr->data.intval, unrollFactor); - value->u.node = expr; - IRO_AddToList(value, list); - - var = IRO_DuplicateExpr(iterCount, list); - - comp = IRO_NewLinear(IROLinearOp2Arg); - comp->index = ++IRO_NumLinear; - comp->nodetype = EGREATER; - comp->u.diadic.left = var; - comp->u.diadic.right = value; - comp->u.diadic.right->flags |= IROLF_Reffed; - comp->rtype = type; - IRO_AddToList(comp, list); - - ifnot = IRO_NewLinear(IROLinearOp1Arg); - ifnot->index = ++IRO_NumLinear; - ifnot->type = IROLinearIfNot; - ifnot->u.label.x4 = comp; - ifnot->u.label.x4->flags |= IROLF_Reffed; - ifnot->rtype = type; - ifnot->u.label.label = label; - IRO_AddToList(ifnot, list); -} - -void ChangeInductionReference(IROLinear *first, IROLinear *last, CInt64 val, IROLoop *loop) { - IROLinear *nd; - IROLinear *value; - IROLinear *add; - UInt32 isUnsigned; - IROLinear *father; - Boolean flag; - IROLinear *father2; - IROLinear *father3; - Type *tmp; - UInt32 flag2; - Object *varobj; - IROLinear *next; - ENode *expr; - Type *type; - - CInt64 val2; - CInt64 val1; - IROList list; - - type = loop->induction->nd->rtype; - isUnsigned = IRO_IsUnsignedType(type); - - for (nd = first; nd; nd = next) { - next = nd->next; - - varobj = IRO_IsVariable(nd); - if (varobj && loop->induction->var->object == varobj) { - value = IRO_NewLinear(IROLinearOperand); - value->index = ++IRO_NumLinear; - value->rtype = type; - expr = IRO_NewENode(EINTCONST); - expr->rtype = type; - expr->data.intval = val; - value->u.node = expr; - - add = IRO_NewLinear(IROLinearOp2Arg); - add->index = ++IRO_NumLinear; - add->nodetype = EADD; - add->rtype = type; - - father = IRO_LocateFather(nd); - flag = 1; - if (father && IS_LINEAR_MONADIC(father, ETYPCON)) { - tmp = father->rtype; - father = IRO_LocateFather(father); - if (tmp->type != nd->rtype->type || tmp->size < nd->rtype->size) - flag = 0; - } - - flag2 = 0; - if ( - flag && - father && - IS_LINEAR_DIADIC_2(father, ESHL, EMUL) && - IRO_IsIntConstant(father->u.diadic.right) && - (father2 = IRO_LocateFather(father)) && - IS_LINEAR_DIADIC(father2, EADD) && - father2->u.diadic.right == father && - (father3 = IRO_LocateFather(father2)) - ) - { - IRO_InitList(&list); - val2 = father->u.diadic.right->u.node->data.intval; - if (father->nodetype == ESHL) - val2 = CInt64_Shl(cint64_one, val2); - - val1 = value->u.node->data.intval; - if (isUnsigned) - val1 = CInt64_MulU(val2, val1); - else - val1 = CInt64_Mul(val2, val1); - value->u.node->data.intval = val1; - - IRO_AddToList(value, &list); - IRO_AddToList(add, &list); - add->u.diadic.right = value; - IRO_Paste(list.head, list.tail, father3); - IRO_LocateFather_Cut_And_Paste_Without_Nopping(father2, add); - add->u.diadic.left = father2; - add->rtype = father2->rtype; - flag2 = 1; - } - - if (!flag2) { - add->u.diadic.right = value; - add->u.diadic.right->flags |= IROLF_Reffed; - value->next = add; - - add->u.diadic.left = nd; - IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, add); - add->flags |= IROLF_Reffed; - - nd->next = value; - add->next = next; - } - } - - if (nd == last) - break; - } -} - -IROLinear *UpdateInductionIncrement(IROLoop *loop, SInt32 value, IROLinear *before) { - IROLinear *ind_nd; - IROLinear *addvalue; - IROLinear *ass; - Type *type; - ENode *expr; - IROList list; - - IRO_InitList(&list); - ind_nd = loop->induction->nd; - type = ind_nd->rtype; - - addvalue = IRO_NewLinear(IROLinearOperand); - addvalue->index = ++IRO_NumLinear; - addvalue->rtype = type; - expr = IRO_NewENode(EINTCONST); - expr->rtype = type; - CInt64_SetLong(&expr->data.intval, value * loop->induction->addConst); - addvalue->u.node = expr; - IRO_AddToList(addvalue, &list); - - if (IS_LINEAR_MONADIC_2(ind_nd, EPREINC, EPOSTINC)) { - ind_nd = IRO_DuplicateExpr(ind_nd->u.monadic, &list); - - ass = IRO_NewLinear(IROLinearOp2Arg); - ass->index = ++IRO_NumLinear; - ass->nodetype = EADDASS; - ass->u.diadic.left = ind_nd; - ass->u.diadic.right = addvalue; - ass->rtype = type; - IRO_AddToList(ass, &list); - } else if (IS_LINEAR_MONADIC_2(ind_nd, EPREDEC, EPOSTDEC)) { - ind_nd = IRO_DuplicateExpr(ind_nd->u.monadic, &list); - - ass = IRO_NewLinear(IROLinearOp2Arg); - ass->index = ++IRO_NumLinear; - ass->nodetype = ESUBASS; - ass->u.diadic.left = ind_nd; - ass->u.diadic.right = addvalue; - ass->rtype = type; - IRO_AddToList(ass, &list); - } else if (IS_LINEAR_DIADIC(ind_nd, EADDASS)) { - ind_nd = IRO_DuplicateExpr(ind_nd->u.monadic, &list); - - ass = IRO_NewLinear(IROLinearOp2Arg); - ass->index = ++IRO_NumLinear; - ass->nodetype = EADDASS; - ass->u.diadic.left = ind_nd; - ass->u.diadic.right = addvalue; - ass->rtype = type; - IRO_AddToList(ass, &list); - } - - IRO_Paste(list.head, list.tail, before); - return list.tail; -} - -void GenInitialAssignment(IROLoop *loop, Object *var, IROList *list) { - Type *type; - IROLinear *nd; - - CError_ASSERT(3924, loop->nd14 && loop->nd14->type == IROLinearOp2Arg); - - type = loop->induction->nd->rtype; - - nd = IRO_NewLinear(IROLinearOp2Arg); - nd->index = ++IRO_NumLinear; - nd->nodetype = EASS; - nd->u.diadic.left = IRO_TempReference(var, list); - nd->u.diadic.right = IRO_DuplicateExpr(loop->nd14->u.diadic.right, list); - nd->rtype = type; - IRO_AddToList(nd, list); -} - -void GenNewInduction(void) { - CError_FATAL(3941); -} diff --git a/compiler_and_linker/unsorted/IroUtil.c b/compiler_and_linker/unsorted/IroUtil.c deleted file mode 100644 index 4ade9b1..0000000 --- a/compiler_and_linker/unsorted/IroUtil.c +++ /dev/null @@ -1,1262 +0,0 @@ -#include "compiler/IroUtil.h" -#include "compiler/IroCSE.h" -#include "compiler/IroDump.h" -#include "compiler/IroFlowgraph.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroLoop.h" -#include "compiler/IroVars.h" -#include "compiler/InlineAsmPPC.h" -#include "compiler/CompilerTools.h" -#include "compiler/CCompiler.h" -#include "compiler/CError.h" -#include "compiler/CException.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/Exceptions.h" -#include "compiler/objects.h" -#include "compiler/types.h" -#include "cos.h" - -static UInt32 IRO_LastUserBreakTick; -static IROLinear *ExprStart; -static IROLinear *ExprEnd; -static IRONode *IRO_Node; -static SInt32 FuncLevel; -Object *FunctionName; -Boolean IRO_IsLeafFunction; -Boolean IRO_FunctionHasReturn; -Boolean DisableDueToAsm; -Boolean LoopOptimizerRun; - -Object *IRO_IsVariable(IROLinear *linear) { - if (linear->type == IROLinearOp1Arg && - linear->nodetype == EINDIRECT && - linear->u.monadic->type == IROLinearOperand && - linear->u.monadic->u.node->type == EOBJREF) - return linear->u.monadic->u.node->data.objref; - - return NULL; -} - -Boolean IRO_IsConstant(IROLinear *linear) { - if (linear->type == IROLinearOperand && ENODE_IS3(linear->u.node, EINTCONST, EVECTOR128CONST, EFLOATCONST)) - return 1; - return 0; -} - -Boolean IRO_IsPow2(IROLinear *linear, SInt32 *powvalue) { - UInt32 desired; - UInt32 value; - SInt32 i; - - *powvalue = -1; - if (linear->type == IROLinearOperand && linear->u.node->type == EINTCONST) { - if (CTool_EndianReadWord32(&linear->u.node->data.intval.hi)) - return 0; - - desired = CInt64_GetULong(&linear->u.node->data.intval); - value = 1; - for (i = 0; i < 31; i++) { - if (value == desired) { - *powvalue = i; - return 1; - } - value += value; - } - } - - return 0; -} - -Boolean IRO_IsIntConstant(IROLinear *linear) { - if (linear->type == IROLinearOperand && ENODE_IS(linear->u.node, EINTCONST)) - return 1; - return 0; -} - -Boolean IRO_IsFloatConstant(IROLinear *linear) { - if (linear->type == IROLinearOperand && ENODE_IS(linear->u.node, EFLOATCONST)) - return 1; - return 0; -} - -Boolean IRO_IsVector128Constant(IROLinear *linear) { - if (linear->type == IROLinearOperand && ENODE_IS(linear->u.node, EVECTOR128CONST)) - return 1; - return 0; -} - -Boolean IRO_IsAssignment(IROLinear *linear) { - if (linear->type == IROLinearOp1Arg || linear->type == IROLinearOp2Arg) { - if (IRO_IsAssignOp[linear->nodetype]) - return 1; - } - return 0; -} - -static Boolean IRO_OperandsSame(ENode *a, ENode *b) { - if (a->type == b->type) { - switch (a->type) { - case EINTCONST: - return CInt64_Equal(a->data.intval, b->data.intval); - case ESTRINGCONST: - return 0; - case EFLOATCONST: - return a->data.floatval.value == b->data.floatval.value; - case EVECTOR128CONST: - return (a->data.vector128val.ul[0] == b->data.vector128val.ul[0]) && - (a->data.vector128val.ul[1] == b->data.vector128val.ul[1]) && - (a->data.vector128val.ul[2] == b->data.vector128val.ul[2]) && - (a->data.vector128val.ul[3] == b->data.vector128val.ul[3]); - case EOBJREF: - return a->data.objref == b->data.objref; - } - } - - return 0; -} - -Boolean IRO_TypesEqual(Type *a, Type *b) { - if (IS_TYPE_BITFIELD(a)) { - if (IS_TYPE_BITFIELD(b)) { - if ( - (TYPE_BITFIELD(a)->bitfieldtype == TYPE_BITFIELD(b)->bitfieldtype) && - (TYPE_BITFIELD(a)->offset == TYPE_BITFIELD(b)->offset) && - (TYPE_BITFIELD(a)->bitlength == TYPE_BITFIELD(b)->bitlength)) - return 1; - } - return 0; - } - - if (IS_TYPE_POINTER_ONLY(a) && IS_TYPE_POINTER_ONLY(b)) - return 1; - - return is_typeequal(a, b) != 0; -} - -Type *IRO_UnsignedType(Type *type) { - if (IS_TYPE_ENUM(type) || IS_TYPE_POINTER_ONLY(type)) { - if (type->size == stunsignedchar.size) - return TYPE(&stunsignedchar); - if (type->size == stunsignedint.size) - return TYPE(&stunsignedint); - if (type->size == stunsignedshort.size) - return TYPE(&stunsignedshort); - if (type->size == stunsignedlong.size) - return TYPE(&stunsignedlong); - if (type->size == stunsignedlonglong.size) - return TYPE(&stunsignedlonglong); - CError_FATAL(281); - return NULL; - } - - if (!IS_TYPE_INT(type)) { - CError_FATAL(287); - return NULL; - } - - if (type == TYPE(&stbool) || type == TYPE(&stwchar)) - return type; - - if (type == TYPE(&stchar) || type == TYPE(&stsignedchar) || type == TYPE(&stunsignedchar)) - return TYPE(&stunsignedchar); - if (type == TYPE(&stsignedshort) || type == TYPE(&stunsignedshort)) - return TYPE(&stunsignedshort); - if (type == TYPE(&stsignedint) || type == TYPE(&stunsignedint)) - return TYPE(&stunsignedint); - if (type == TYPE(&stsignedlong) || type == TYPE(&stunsignedlong)) - return TYPE(&stunsignedlong); - if (type == TYPE(&stsignedlonglong) || type == TYPE(&stunsignedlonglong)) - return TYPE(&stunsignedlonglong); - - CError_FATAL(319); - return NULL; -} - -Type *IRO_SignedType(Type *type) { - if (IS_TYPE_ENUM(type) || IS_TYPE_POINTER_ONLY(type)) { - if (type->size == stsignedchar.size) - return TYPE(&stsignedchar); - if (type->size == stsignedint.size) - return TYPE(&stsignedint); - if (type->size == stsignedshort.size) - return TYPE(&stsignedshort); - if (type->size == stsignedlong.size) - return TYPE(&stsignedlong); - if (type->size == stsignedlonglong.size) - return TYPE(&stsignedlonglong); - CError_FATAL(357); - return NULL; - } - - if (!IS_TYPE_INT(type)) { - CError_FATAL(363); - return NULL; - } - - if (type == TYPE(&stbool) && type->size == stsignedchar.size) - return TYPE(&stsignedchar); - - if (type == TYPE(&stwchar) && type->size == stsignedshort.size) - return TYPE(&stsignedshort); - - if (type == TYPE(&stchar) || type == TYPE(&stsignedchar) || type == TYPE(&stunsignedchar)) - return TYPE(&stsignedchar); - if (type == TYPE(&stsignedshort) || type == TYPE(&stunsignedshort)) - return TYPE(&stsignedshort); - if (type == TYPE(&stsignedint) || type == TYPE(&stunsignedint)) - return TYPE(&stsignedint); - if (type == TYPE(&stsignedlong) || type == TYPE(&stunsignedlong)) - return TYPE(&stsignedlong); - if (type == TYPE(&stsignedlonglong) || type == TYPE(&stunsignedlonglong)) - return TYPE(&stsignedlonglong); - - CError_FATAL(399); - return NULL; -} - -Boolean IRO_is_CPtypeequal(Type *a, Type *b) { - if (IS_TYPE_POINTER_ONLY(a) && IS_TYPE_POINTER_ONLY(b)) - return 1; - - return is_typeequal(a, b) != 0; -} - -Boolean IRO_ExprsSame(IROLinear *a, IROLinear *b) { - if (a->type == b->type && IRO_TypesEqual(a->rtype, b->rtype)) { - switch (a->type) { - case IROLinearOperand: - return IRO_OperandsSame(a->u.node, b->u.node); - case IROLinearOp1Arg: - if (a->nodetype == b->nodetype) - return IRO_ExprsSame(a->u.monadic, b->u.monadic); - return 0; - case IROLinearOp2Arg: - if (a->nodetype == b->nodetype) - return IRO_ExprsSame(a->u.diadic.left, b->u.diadic.left) && - IRO_ExprsSame(a->u.diadic.right, b->u.diadic.right); - return 0; - case IROLinearOp3Arg: - if (a->nodetype == b->nodetype) - return IRO_ExprsSame(a->u.args3.a, b->u.args3.a) && - IRO_ExprsSame(a->u.args3.b, b->u.args3.b) && - IRO_ExprsSame(a->u.args3.c, b->u.args3.c); - return 0; - case IROLinearFunccall: - return 0; - default: - return 0; - } - } - - return 0; -} - -CLabel *IRO_NewLabel(void) { - CLabel *label = newlabel(); - label->next = Labels; - Labels = label; - return label; -} - -Boolean IRO_ExprsSameSemantically(IROLinear *a, IROLinear *b) { - if (a->type == b->type && IRO_TypesEqual(a->rtype, b->rtype)) { - Boolean flag = 0; - - switch (a->type) { - case IROLinearOperand: - return IRO_OperandsSame(a->u.node, b->u.node); - case IROLinearOp1Arg: - if (a->nodetype == b->nodetype) - return IRO_ExprsSameSemantically(a->u.monadic, b->u.monadic); - return 0; - case IROLinearOp2Arg: - if (a->nodetype == b->nodetype) { - switch (a->nodetype) { - case EMUL: - case EADD: - case EAND: - case EXOR: - case EOR: - case ELAND: - case ELOR: - if (!IRO_HasSideEffect(a)) { - flag = IRO_ExprsSameSemantically(a->u.diadic.left, b->u.diadic.right) && - IRO_ExprsSameSemantically(a->u.diadic.right, b->u.diadic.left); - } - } - - return flag || (IRO_ExprsSameSemantically(a->u.diadic.left, b->u.diadic.left) && - IRO_ExprsSameSemantically(a->u.diadic.right, b->u.diadic.right)); - } - return 0; - case IROLinearOp3Arg: - if (a->nodetype == b->nodetype) - return IRO_ExprsSameSemantically(a->u.args3.a, b->u.args3.a) && - IRO_ExprsSameSemantically(a->u.args3.b, b->u.args3.b) && - IRO_ExprsSameSemantically(a->u.args3.c, b->u.args3.c); - return 0; - case IROLinearFunccall: - return 0; - default: - return 0; - } - } - - return 0; -} - -IROLinear *IRO_FindPrecedAfter(IROLinear *a, IROLinear *iter) { - IROLinear *prev = iter; - while (iter && iter != a) { - prev = iter; - iter = iter->next; - } - - if (iter) - return prev; - return iter; -} - -IROLinear *IRO_FindPreced(IROLinear *a) { - IROLinear *iter; - IROLinear *prev; - - prev = iter = IRO_FirstLinear; - while (iter && iter != a) { - prev = iter; - iter = iter->next; - } - - if (iter) - return prev; - return iter; -} - -IROLinear *IRO_FindFirst(IROLinear *linear) { - short i; - - switch (linear->type) { - case IROLinearOperand: - return linear; - case IROLinearOp1Arg: - return IRO_FindFirst(linear->u.monadic); - case IROLinearOp2Arg: - if (linear->u.diadic.right->index < linear->u.diadic.left->index) - return IRO_FindFirst(linear->u.diadic.right); - else - return IRO_FindFirst(linear->u.diadic.left); - case IROLinearOp3Arg: - if (linear->u.args3.a->index < linear->u.args3.b->index) { - if (linear->u.args3.b->index < linear->u.args3.c->index) - return IRO_FindFirst(linear->u.args3.a); - else - return IRO_FindFirst(linear->u.args3.c); - } else { - if (linear->u.args3.b->index < linear->u.args3.c->index) - return IRO_FindFirst(linear->u.args3.b); - else - return IRO_FindFirst(linear->u.args3.c); - } - case IROLinearFunccall: - i = linear->u.funccall.argCount - 1; - return IRO_FindFirst(linear->u.funccall.args[i]); - default: - CError_FATAL(641); - return NULL; - } -} - -void IRO_CutAndPasteAfter(IROLinear *a, IROLinear *b, IROLinear *c) { - IROLinear *preced = IRO_FindPreced(a); - preced->next = b->next; - b->next = c->next; - c->next = a; -} - -Boolean IRO_IsConstantZero(IROLinear *linear) { - return (IRO_IsIntConstant(linear) && CInt64_IsZero(&linear->u.node->data.intval)) || - (IRO_IsFloatConstant(linear) && CMach_FloatIsZero(linear->u.node->data.floatval)); -} - -Boolean IRO_IsConstantOne(IROLinear *linear) { - return (IRO_IsIntConstant(linear) && CInt64_IsOne(&linear->u.node->data.intval)) || - (IRO_IsFloatConstant(linear) && CMach_FloatIsOne(linear->u.node->data.floatval)); -} - -Boolean IRO_IsConstantNegativeOne(IROLinear *linear) { - CInt64 neg = CInt64_Neg(linear->u.node->data.intval); - return (IRO_IsIntConstant(linear) && CInt64_IsOne(&neg)) || - (IRO_IsFloatConstant(linear) && CMach_FloatIsNegOne(linear->u.node->data.floatval)); -} - -static void ActNop(IROLinear *linear, Boolean isEntry) { - if (!isEntry) { - linear->type = IROLinearNop; - linear->expr = NULL; - } -} - -void IRO_NopOut(IROLinear *linear) { - IRO_WalkTree(linear, ActNop); -} - -static Boolean NotNoppable(IROLinear *linear) { - return ( - (linear->type == IROLinearFunccall) || - IRO_IsAssignment(linear) || - ((linear->type == IROLinearOperand) && ENODE_IS(linear->u.node, EINSTRUCTION)) || - (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) || - ((linear->type == IROLinearOperand) && ENODE_IS(linear->u.node, EOBJREF) && is_volatile_object(linear->u.node->data.objref)) - ); -} - -static void ActNopNonSideEffects(IROLinear *linear, Boolean isEntry) { - if (isEntry) { - if (NotNoppable(linear)) { - if (!FuncLevel) - linear->flags &= ~IROLF_Reffed; - FuncLevel++; - } - } else { - if (NotNoppable(linear)) { - FuncLevel--; - } else if (!FuncLevel) { - linear->type = IROLinearNop; - } - } -} - -void IRO_NopNonSideEffects(IROLinear *linear, SInt32 level) { - FuncLevel = level; - IRO_WalkTree(linear, ActNopNonSideEffects); -} - -void IRO_BuildList(IROLinear *linear, Boolean isEntry) { - if (!isEntry) { - linear->next = NULL; - IRO_AddToList(linear, &IRO_InitLList); - } -} - -void IRO_WalkTree(IROLinear *linear, IROWalkTreeFunc func) { - int i; - - func(linear, 1); - switch (linear->type) { - case IROLinearOperand: - break; - case IROLinearOp1Arg: - IRO_WalkTree(linear->u.monadic, func); - break; - case IROLinearOp2Arg: - IRO_WalkTree(linear->u.diadic.left, func); - IRO_WalkTree(linear->u.diadic.right, func); - break; - case IROLinearOp3Arg: - IRO_WalkTree(linear->u.args3.a, func); - IRO_WalkTree(linear->u.args3.b, func); - IRO_WalkTree(linear->u.args3.c, func); - break; - case IROLinearFunccall: - IRO_WalkTree(linear->u.funccall.linear8, func); - for (i = 0; i < linear->u.funccall.argCount; i++) - IRO_WalkTree(linear->u.funccall.args[i], func); - break; - } - func(linear, 0); -} - -void IRO_WalkTreeToPropagateFlags(IROLinear *linear, IROWalkTreeFunc func) { - int i; - - switch (linear->type) { - case IROLinearOperand: - break; - case IROLinearOp1Arg: - IRO_WalkTreeToPropagateFlags(linear->u.monadic, func); - break; - case IROLinearOp2Arg: - IRO_WalkTreeToPropagateFlags(linear->u.diadic.left, func); - IRO_WalkTreeToPropagateFlags(linear->u.diadic.right, func); - break; - case IROLinearOp3Arg: - IRO_WalkTreeToPropagateFlags(linear->u.args3.a, func); - IRO_WalkTreeToPropagateFlags(linear->u.args3.b, func); - IRO_WalkTreeToPropagateFlags(linear->u.args3.c, func); - break; - case IROLinearFunccall: - IRO_WalkTreeToPropagateFlags(linear->u.funccall.linear8, func); - for (i = 0; i < linear->u.funccall.argCount; i++) - IRO_WalkTreeToPropagateFlags(linear->u.funccall.args[i], func); - break; - } - func(linear, 0); -} - -void IRO_WalkInts(IROLinear *a, IROLinear *b, IROWalkTreeFunc func) { - IROLinear *scan; - - for (scan = a; scan; scan = scan->next) { - switch (scan->type) { - case IROLinearBeginCatch: - case IROLinearEndCatch: - case IROLinearEndCatchDtor: - IRO_WalkTree(scan->u.ctch.linear, func); - break; - case IROLinearOperand: - case IROLinearOp1Arg: - case IROLinearOp2Arg: - case IROLinearOp3Arg: - case IROLinearFunccall: - IRO_WalkTree(scan, func); - break; - case IROLinearIf: - case IROLinearIfNot: - IRO_WalkTree(scan->u.label.x4, func); - break; - case IROLinearReturn: - if (scan->u.monadic) - IRO_WalkTree(scan->u.monadic, func); - break; - case IROLinearSwitch: - IRO_WalkTree(scan->u.swtch.x4, func); - break; - case IROLinearAsm: - func(scan, 1); - func(scan, 0); - break; - case IROLinearEnd: - break; - } - - if (scan == b) - break; - } -} - -void IRO_Cut(IROLinear *a, IROLinear *b) { - IROLinear *scan; - IROLinear *prev; - IRONode *node; - - scan = a; - while (1) { - scan->stmt = NULL; - if (scan == b) - break; - scan = scan->next; - } - - prev = NULL; - for (scan = IRO_FirstLinear; scan && scan != a; scan = scan->next) - prev = scan; - - CError_ASSERT(951, scan); - - for (node = IRO_FirstNode; node; node = node->nextnode) { - if (node->first == a) { - if (node->last == b) { - node->first = node->last = NULL; - break; - } else { - node->first = b->next; - break; - } - } else if (node->last == b) { - node->last = prev; - break; - } - } - - if (prev) - prev->next = b->next; - else - IRO_FirstLinear = b->next; -} - -void IRO_Paste(IROLinear *a, IROLinear *b, IROLinear *c) { - IROLinear *prev; - IROLinear *scan; - IRONode *node; - - CError_ASSERT(1002, c && c->type != IROLinearLabel); - - prev = NULL; - for (scan = IRO_FirstLinear; scan && scan != c; scan = scan->next) - prev = scan; - - CError_ASSERT(1016, scan); - - for (node = IRO_FirstNode; node; node = node->nextnode) { - if (node->first == c) { - node->first = a; - break; - } - } - - b->next = c; - if (prev) - prev->next = a; - else - IRO_FirstLinear = a; -} - -void IRO_PasteAfter(IROLinear *a, IROLinear *b, IROLinear *c) { - IRONode *node; - - switch (c->type) { - case IROLinearGoto: - case IROLinearIf: - case IROLinearIfNot: - case IROLinearSwitch: - CError_FATAL(1060); - } - - for (node = IRO_FirstNode; node; node = node->nextnode) { - if (node->last == c) { - node->last = b; - break; - } - } - - b->next = c->next; - c->next = a; -} - -static void FindStart(IROLinear *linear, Boolean isEntry) { - IROLinear *scan; - if (isEntry) { - scan = linear; - do { - if (scan == ExprStart) { - ExprStart = linear; - return; - } - if (scan == ExprEnd) - return; - } while ((scan = scan->next)); - } -} - -void IRO_ClipExpr(IROExpr *expr) { - ExprStart = ExprEnd = expr->linear; - IRO_WalkTree(expr->linear, FindStart); - IRO_Cut(ExprStart, ExprEnd); -} - -void IRO_ClipExprTree(IROLinear *linear) { - ExprStart = ExprEnd = linear; - IRO_WalkTree(linear, FindStart); - IRO_Cut(ExprStart, ExprEnd); -} - -static void SetNodeNumInExprList(IROLinear *linear, Boolean isEntry) { - if (isEntry && linear->expr) - linear->expr->node = IRO_Node; -} - -void IRO_MoveExpression(IROExpr *expr, IROLinear *linear) { - IRONode *node; - IROLinear *scan; - - ExprStart = ExprEnd = expr->linear; - IRO_WalkTree(expr->linear, FindStart); - - if (ExprStart != linear) { - IRO_Cut(ExprStart, ExprEnd); - IRO_Paste(ExprStart, ExprEnd, linear); - for (node = IRO_FirstNode; node; node = node->nextnode) { - for (scan = node->first; scan; scan = scan->next) { - if (scan == expr->linear) { - expr->node = node; - break; - } - if (scan == node->last) - break; - } - } - - IRO_Node = expr->node; - IRO_WalkTree(expr->linear, SetNodeNumInExprList); - } -} - -void IRO_InitList(IROList *list) { - list->head = list->tail = NULL; -} - -void IRO_AddToList(IROLinear *linear, IROList *list) { - if (list->head) - list->tail->next = linear; - else - list->head = linear; - - list->tail = linear; - while (list->tail->next) - list->tail = list->tail->next; -} - -IROLinear *IRO_FindLabelNode(CLabel *label, IROLinear *linear) { - IROLinear *scan; - - for (scan = linear; scan; scan = scan->next) { - if (scan->type == IROLinearLabel && scan->u.label.label == label) - break; - } - - CError_ASSERT(1244, scan); - return scan; -} - -void IRO_DuplicateExprRange(IROLinear *start, IROLinear *end, IROList *list) { - IROLinear *scan; - - for (scan = start; scan; scan = scan->next) { - if (scan->type != IROLinearNop && !(scan->flags & IROLF_Reffed)) - IRO_DuplicateExpr(scan, list); - if (scan == end) - break; - } -} - -IROLinear *IRO_DuplicateExpr(IROLinear *linear, IROList *list) { - IROLinear *copy; - ENode *copynode; - int i; - - copy = IRO_NewLinear(linear->type); - *copy = *linear; - - copy->index = ++IRO_NumLinear; - copy->next = NULL; - copy->expr = NULL; - - switch (copy->type) { - case IROLinearOperand: - copynode = lalloc(sizeof(ENode)); - *copynode = *linear->u.node; - copy->u.node = copynode; - break; - case IROLinearOp1Arg: - copy->u.monadic = IRO_DuplicateExpr(copy->u.monadic, list); - break; - case IROLinearOp2Arg: - if (linear->flags & IROLF_8000) { - copy->u.diadic.right = IRO_DuplicateExpr(copy->u.diadic.right, list); - copy->u.diadic.left = IRO_DuplicateExpr(copy->u.diadic.left, list); - } else { - copy->u.diadic.left = IRO_DuplicateExpr(copy->u.diadic.left, list); - copy->u.diadic.right = IRO_DuplicateExpr(copy->u.diadic.right, list); - } - break; - case IROLinearOp3Arg: - copy->u.args3.a = IRO_DuplicateExpr(copy->u.args3.a, list); - copy->u.args3.b = IRO_DuplicateExpr(copy->u.args3.b, list); - copy->u.args3.c = IRO_DuplicateExpr(copy->u.args3.c, list); - break; - case IROLinearFunccall: - copy->u.funccall.linear8 = IRO_DuplicateExpr(copy->u.funccall.linear8, list); - copy->u.funccall.args = oalloc(sizeof(IROLinear *) * copy->u.funccall.argCount); - for (i = 0; i < copy->u.funccall.argCount; i++) { - copy->u.funccall.args[i] = IRO_DuplicateExpr(linear->u.funccall.args[i], list); - } - break; - case IROLinearAsm: - copy->u.asm_stmt = CodeGen_CopyAsmStat(linear->u.asm_stmt); - break; - } - - IRO_AddToList(copy, list); - return copy; -} - -IROLinear *IRO_TempReference(Object *obj, IROList *list) { - IROLinear *op; - IROLinear *ind; - - op = IRO_NewLinear(IROLinearOperand); - op->u.node = create_objectrefnode(obj); - op->rtype = op->u.node->data.objref->type; - op->index = ++IRO_NumLinear; - op->flags |= IROLF_Reffed | IROLF_Ind; - IRO_AddToList(op, list); - - ind = IRO_NewLinear(IROLinearOp1Arg); - ind->nodetype = EINDIRECT; - ind->rtype = obj->type; - ind->u.monadic = op; - ind->index = ++IRO_NumLinear; - ind->next = NULL; - IRO_AddToList(ind, list); - - return ind; -} - -CW_INLINE IROLinear *LocateFatherHelper(IROLinear *linear, Boolean a, IROLinear ***b) { - IROLinear *scan; - SInt32 index; - int i; - - for (scan = linear->next, index = 0; index < (a ? 2 : 1); index++) { - while (scan) { - switch (scan->type) { - case IROLinearIf: - case IROLinearIfNot: - if (scan->u.label.x4 == linear) { - if (b) - *b = &scan->u.label.x4; - return scan; - } - break; - case IROLinearReturn: - if (scan->u.monadic == linear) { - if (b) - *b = &scan->u.monadic; - return scan; - } - break; - case IROLinearOp1Arg: - if (scan->u.monadic == linear) { - if (b) - *b = &scan->u.monadic; - return scan; - } - break; - case IROLinearSwitch: - if (scan->u.swtch.x4 == linear) { - if (b) - *b = &scan->u.swtch.x4; - return scan; - } - break; - case IROLinearOp2Arg: - if (scan->u.diadic.left == linear) { - if (b) - *b = &scan->u.diadic.left; - return scan; - } - if (scan->u.diadic.right == linear) { - if (b) - *b = &scan->u.diadic.right; - return scan; - } - break; - case IROLinearOp3Arg: - if (scan->u.args3.a == linear) { - if (b) - *b = &scan->u.args3.a; - return scan; - } - if (scan->u.args3.b == linear) { - if (b) - *b = &scan->u.args3.b; - return scan; - } - if (scan->u.args3.c == linear) { - if (b) - *b = &scan->u.args3.c; - return scan; - } - break; - case IROLinearFunccall: - if (scan->u.funccall.linear8 == linear) { - if (b) - *b = &scan->u.funccall.linear8; - return scan; - } - for (i = 0; i < scan->u.funccall.argCount; i++) { - if (scan->u.funccall.args[i] == linear) { - if (b) - *b = &scan->u.funccall.args[i]; - return scan; - } - } - break; - case IROLinearNop: - case IROLinearOperand: - case IROLinearGoto: - case IROLinearLabel: - case IROLinearEntry: - case IROLinearExit: - case IROLinearBeginCatch: - case IROLinearEndCatch: - case IROLinearEndCatchDtor: - case IROLinearAsm: - case IROLinearEnd: - break; - default: - CError_FATAL(1536); - } - scan = scan->next; - } - - scan = IRO_FirstLinear; - } - - if (b) - *b = NULL; - return NULL; -} - -IROLinear *IRO_LocateFather(IROLinear *linear) { - return LocateFatherHelper(linear, 0, NULL); -} - -IROLinear *IRO_LocateFather_Cut_And_Paste(IROLinear *a, IROLinear *b) { - IROLinear **p; - IROLinear *l = LocateFatherHelper(a, 0, &p); - if (l) { - CError_ASSERT(1568, p && *p); - IRO_NopOut(a); - *p = b; - } - return l; -} - -IROLinear *IRO_LocateFather_Cut_And_Paste_Without_Nopping(IROLinear *a, IROLinear *b) { - IROLinear **p; - IROLinear *l = LocateFatherHelper(a, 0, &p); - if (l) { - CError_ASSERT(1585, p && *p); - *p = b; - } - return l; -} - -void IRO_ReplaceReference(IROLinear *a, Object *obj, IROLinear *b) { - IROLinear **ptr; - IROList list; - - if (LocateFatherHelper(a, 1, &ptr)) { - CError_ASSERT(1605, ptr && *ptr); - IRO_InitList(&list); - *ptr = IRO_TempReference(obj, &list); - IRO_PasteAfter(list.head, list.tail, b); - if (a->flags & IROLF_LoopInvariant) - list.tail->flags |= IROLF_LoopInvariant; - } else { - IRO_Dump("Oh, oh, did not find reference to replace\n"); - } -} - -void IRO_ReplaceReferenceWithNode(IROLinear *a, IROLinear *b) { - IROLinear **ptr; - IROList list; - - if (LocateFatherHelper(a, 1, &ptr)) { - CError_ASSERT(1664, ptr && *ptr); - *ptr = b; - b->flags |= IROLF_Reffed; - } else { - IRO_Dump("Oh, oh, did not find reference to replace\n"); - } -} - -VarRecord *IRO_GetTemp(IROExpr *expr) { - expr->x8 = create_temp_object(expr->linear->rtype); - return IRO_FindVar(expr->x8, 1, 1); -} - -IROLinear *IRO_AssignToTemp(IROExpr *expr) { - IROLinear *objref; - IROLinear *ind; - IROLinear *ass; - - objref = IRO_NewLinear(IROLinearOperand); - objref->u.node = create_objectrefnode(expr->x8); - objref->rtype = objref->u.node->data.objref->type; - objref->index = ++IRO_NumLinear; - objref->flags |= IROLF_Reffed | IROLF_Assigned | IROLF_Ind; - - ind = IRO_NewLinear(IROLinearOp1Arg); - ind->nodetype = EINDIRECT; - ind->rtype = expr->linear->rtype; - ind->u.monadic = objref; - ind->index = ++IRO_NumLinear; - ind->flags |= IROLF_Reffed | IROLF_Assigned; - - ass = IRO_NewLinear(IROLinearOp2Arg); - ass->nodetype = EASS; - ass->u.diadic.left = ind; - ass->u.diadic.right = expr->linear; - ass->rtype = expr->linear->rtype; - ass->index = ++IRO_NumLinear; - - objref->next = ind; - ind->next = ass; - IRO_PasteAfter(objref, ass, expr->linear); - return ass; -} - -IROLinear *IRO_FindStart(IROLinear *linear) { - ExprStart = ExprEnd = linear; - IRO_WalkTree(linear, FindStart); - return ExprStart; -} - -void IRO_DeleteCommaNode(IROLinear *linear, IROExpr *expr) { - IROLinear *scan; - for (scan = linear; scan; scan = scan->next) { - if (scan->nodetype == ECOMMA) { - if (scan != expr->linear) { - IRO_NopOut(scan->u.diadic.left); - IRO_LocateFather_Cut_And_Paste(scan, scan->u.diadic.right); - } else { - IRO_NopOut(scan->u.diadic.left); - expr->linear = scan->u.diadic.right; - } - } - } -} - -void IRO_RemoveCommaNodeFromIR(void) { - IRONode *node; - IROLinear *linear; - - for (node = IRO_FirstNode; node; node = node->nextnode) { - linear = node->first; - do { - if (!linear) - break; - if (linear->nodetype == ECOMMA) { - linear->u.diadic.left->flags = linear->u.diadic.left->flags & ~IROLF_Reffed; - IRO_LocateFather_Cut_And_Paste_Without_Nopping(linear, linear->u.diadic.right); - linear->type = IROLinearNop; - } - linear = linear->next; - } while (linear != node->last); - } -} - -IROAddrRecord *IRO_InitAddrRecordPointer(IROLinear *linear) { - IROAddrRecord *rec = oalloc(sizeof(IROAddrRecord)); - rec->numObjRefs = 0; - rec->objRefs = NULL; - rec->numMisc = 0; - rec->misc = NULL; - rec->numInts = 0; - rec->ints = NULL; - rec->x16 = 0; - rec->linear = linear; - return rec; -} - -IROLinear *IRO_HasSideEffect(IROLinear *linear) { - IROLinear *tmp; - - if (!linear) - return linear; - - if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) - return linear; - - switch (linear->type) { - case IROLinearAsm: - return linear; - case IROLinearOperand: - if (ENODE_IS(linear->u.node, EOBJREF) && is_volatile_object(linear->u.node->data.objref)) - return linear; - return NULL; - case IROLinearOp1Arg: - if (IRO_IsAssignOp[linear->nodetype]) - return linear; - else - return IRO_HasSideEffect(linear->u.monadic); - case IROLinearOp2Arg: - if (IRO_IsAssignOp[linear->nodetype]) - return linear; - else if ((tmp = IRO_HasSideEffect(linear->u.diadic.left))) - return tmp; - else - return IRO_HasSideEffect(linear->u.diadic.right); - case IROLinearOp3Arg: - if ((tmp = IRO_HasSideEffect(linear->u.args3.a))) - return tmp; - else if ((tmp = IRO_HasSideEffect(linear->u.args3.b))) - return tmp; - else - return IRO_HasSideEffect(linear->u.args3.c); - case IROLinearFunccall: - return linear; - default: - return linear; - } -} - -IROLinear *IRO_CheckSideEffect(IROLinear *linear) { - IROLinear *result; - IROLinear *tmp; - IROLinear *tmp2; - IROLinear *tmp3; - - if (!linear) - return linear; - - if (linear->rtype && CParser_IsVolatile(linear->rtype, linear->nodeflags & ENODE_FLAG_QUALS)) { - linear->flags &= ~IROLF_Reffed; - return linear; - } - - result = NULL; - switch (linear->type) { - case IROLinearAsm: - linear->flags &= ~IROLF_Reffed; - return linear; - case IROLinearOperand: - if (ENODE_IS(linear->u.node, EOBJREF) && is_volatile_object(linear->u.node->data.objref)) { - linear->flags &= ~IROLF_Reffed; - return linear; - } - break; - case IROLinearOp1Arg: - if (IRO_IsAssignOp[linear->nodetype]) { - linear->flags &= ~IROLF_Reffed; - return linear; - } - if ((result = IRO_CheckSideEffect(linear->u.monadic))) { - if (linear->nodetype == EINDIRECT && linear->u.monadic->type == IROLinearOperand) { - linear->flags &= ~IROLF_Reffed; - return linear; - } - } - break; - case IROLinearOp2Arg: - if (IRO_IsAssignOp[linear->nodetype]) { - linear->flags &= ~IROLF_Reffed; - return linear; - } - tmp = IRO_CheckSideEffect(linear->u.diadic.left); - tmp2 = IRO_CheckSideEffect(linear->u.diadic.right); - if (tmp) - result = tmp; - else - result = tmp2; - break; - case IROLinearOp3Arg: - tmp = IRO_CheckSideEffect(linear->u.args3.a); - tmp2 = IRO_CheckSideEffect(linear->u.args3.b); - tmp3 = IRO_CheckSideEffect(linear->u.args3.c); - result = tmp ? tmp : tmp2 ? tmp2 : tmp3; - break; - case IROLinearFunccall: - linear->flags &= ~IROLF_Reffed; - return linear; - default: - return linear; - } - - linear->type = IROLinearNop; - IRO_Dump("Nop out with side-effects checking at: %d\n", linear->index); - return result; -} - -void IRO_WalkExcActions(ExceptionAction *action, WalkObjFunc func) { - while (action) { - switch (action->type) { - case EAT_DESTROYLOCAL: - func(action->data.destroy_local.local); - break; - case EAT_DESTROYLOCALCOND: - func(action->data.destroy_local_cond.local); - func(action->data.destroy_local_cond.cond); - break; - case EAT_DESTROYLOCALOFFSET: - func(action->data.destroy_local_offset.local); - break; - case EAT_DESTROYLOCALPOINTER: - func(action->data.destroy_local_pointer.pointer); - break; - case EAT_DESTROYLOCALARRAY: - func(action->data.destroy_local_array.localarray); - break; - case EAT_DESTROYPARTIALARRAY: - func(action->data.destroy_partial_array.arraypointer); - func(action->data.destroy_partial_array.arraycounter); - func(action->data.destroy_partial_array.element_size); - break; - case EAT_DESTROYBASE: - func(action->data.destroy_member.objectptr); // wrong union? - break; - case EAT_DESTROYMEMBER: - func(action->data.destroy_member.objectptr); - break; - case EAT_DESTROYMEMBERCOND: - func(action->data.destroy_member_cond.objectptr); - func(action->data.destroy_member_cond.cond); - break; - case EAT_DESTROYMEMBERARRAY: - func(action->data.destroy_member_array.objectptr); - break; - case EAT_DELETEPOINTER: - func(action->data.delete_pointer.pointerobject); - break; - case EAT_DELETEPOINTERCOND: - func(action->data.delete_pointer_cond.pointerobject); - func(action->data.delete_pointer_cond.cond); - break; - } - action = action->prev; - } -} - -Boolean IRO_FunctionCallMightThrowException(IROLinear *linear) { - Object *obj; - if (linear->type == IROLinearFunccall) { - obj = NULL; - if (linear->u.funccall.linear8->type == IROLinearOperand && ENODE_IS(linear->u.funccall.linear8->u.node, EOBJREF)) - obj = linear->u.funccall.linear8->u.node->data.objref; - if (!obj || CExcept_CanThrowException(obj, obj->datatype == DVFUNC && !(linear->nodeflags & ENODE_FLAG_80))) - return 1; - } - return 0; -} - -IROLinear *IRO_NewIntConst(CInt64 val, Type *type) { - ENode *node; - IROLinear *linear; - - node = IRO_NewENode(EINTCONST); - node->data.intval = val; - node->rtype = type; - - linear = IRO_NewLinear(IROLinearOperand); - linear->index = ++IRO_NumLinear; - linear->rtype = type; - linear->u.node = node; - return linear; -} - -IROLinear *IRO_NewFloatConst(const Float val, Type *type) { - ENode *node; - IROLinear *linear; - - node = IRO_NewENode(EFLOATCONST); - node->data.floatval = val; - node->rtype = type; - - linear = IRO_NewLinear(IROLinearOperand); - linear->index = ++IRO_NumLinear; - linear->rtype = type; - linear->u.node = node; - return linear; -} - -Boolean IRO_IsAddressMultiply(IROLinear *linear) { - return 0; -} - -void IRO_SetupForUserBreakChecking(void) { - IRO_LastUserBreakTick = 0; -} - -void IRO_CheckForUserBreak(void) { - if (IRO_LastUserBreakTick + 8 < COS_GetTicks()) { - if (CWUserBreak(cparams.context)) - CError_UserBreak(); - IRO_LastUserBreakTick = COS_GetTicks(); - } -} diff --git a/compiler_and_linker/unsorted/IroVars.c b/compiler_and_linker/unsorted/IroVars.c deleted file mode 100644 index 6bb3d02..0000000 --- a/compiler_and_linker/unsorted/IroVars.c +++ /dev/null @@ -1,1430 +0,0 @@ -#include "compiler/IroVars.h" -#include "compiler/IroDump.h" -#include "compiler/IroFlowgraph.h" -#include "compiler/IroJump.h" -#include "compiler/IroLinearForm.h" -#include "compiler/IroMalloc.h" -#include "compiler/IroPointerAnalysis.h" -#include "compiler/IroUtil.h" -#include "compiler/IROUseDef.h" -#include "compiler/CClass.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CParser.h" -#include "compiler/CompilerTools.h" -#include "compiler/Exceptions.h" -#include "compiler/objects.h" -#include "compiler/InlineAsm.h" -#include "compiler/InlineAsmPPC.h" -#include "compiler/BitVector.h" - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct IndirectRecordMatch { - IROLinear *nd; - struct IndirectRecordMatch *otherMatches; -} IndirectRecordMatch; - -typedef struct IndirectRecord { - IROLinear *linear; - unsigned char flags; - VarRecord *var; - SInt32 addend; - SInt32 size; - int startbit; - int endbit; - Type *type; - struct IndirectRecord *next; - IndirectRecordMatch *matches; - IROLinear *x26; -} IndirectRecord; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static IndirectRecord *IRO_FirstIndirectRecord; -static IndirectRecord *IRO_LastIndirectRecord; -static IROLinear *TheBaseTerm; -VarRecord *IRO_FirstVar; -VarRecord *IRO_LastVar; -SInt32 IRO_NumVars; -Boolean IRO_IsBitField; -SInt32 IRO_BaseTerms; -SInt32 IRO_VarTerms; -Boolean IRO_IsModifyOp[MAXEXPR]; -Boolean IRO_IsAssignOp[MAXEXPR]; - -// forward decls -static Boolean CheckAddress(IROLinear *nd, Boolean *resultFlag); -static Boolean CheckAddressConsistency(IROLinear *nd, VarRecord *var, SInt32 addend, Type *type); -static void DisableEntries(IndirectRecord *irec); -static void DisableAddressedEntries(void); -static UInt32 ObjectIsArg(Object *obj); - -void IRO_InitializeIRO_IsModifyOpArray(void) { - int i; - - for (i = 0; i < MAXEXPR; i++) - IRO_IsModifyOp[i] = 0; - - IRO_IsModifyOp[EPOSTINC] = 1; - IRO_IsModifyOp[EPOSTDEC] = 1; - IRO_IsModifyOp[EPREINC] = 1; - IRO_IsModifyOp[EPREDEC] = 1; - IRO_IsModifyOp[EINDIRECT] = 0; - IRO_IsModifyOp[EMONMIN] = 0; - IRO_IsModifyOp[EBINNOT] = 0; - IRO_IsModifyOp[ELOGNOT] = 0; - IRO_IsModifyOp[EFORCELOAD] = 0; - IRO_IsModifyOp[EMUL] = 0; - IRO_IsModifyOp[EMULV] = 0; - IRO_IsModifyOp[EDIV] = 0; - IRO_IsModifyOp[EMODULO] = 0; - IRO_IsModifyOp[EADDV] = 0; - IRO_IsModifyOp[ESUBV] = 0; - IRO_IsModifyOp[EADD] = 0; - IRO_IsModifyOp[ESUB] = 0; - IRO_IsModifyOp[ESHL] = 0; - IRO_IsModifyOp[ESHR] = 0; - IRO_IsModifyOp[ELESS] = 0; - IRO_IsModifyOp[EGREATER] = 0; - IRO_IsModifyOp[ELESSEQU] = 0; - IRO_IsModifyOp[EGREATEREQU] = 0; - IRO_IsModifyOp[EEQU] = 0; - IRO_IsModifyOp[ENOTEQU] = 0; - IRO_IsModifyOp[EAND] = 0; - IRO_IsModifyOp[EXOR] = 0; - IRO_IsModifyOp[EOR] = 0; - IRO_IsModifyOp[ELAND] = 0; - IRO_IsModifyOp[ELOR] = 0; - IRO_IsModifyOp[EASS] = 0; - IRO_IsModifyOp[EMULASS] = 1; - IRO_IsModifyOp[EDIVASS] = 1; - IRO_IsModifyOp[EMODASS] = 1; - IRO_IsModifyOp[EADDASS] = 1; - IRO_IsModifyOp[ESUBASS] = 1; - IRO_IsModifyOp[ESHLASS] = 1; - IRO_IsModifyOp[ESHRASS] = 1; - IRO_IsModifyOp[EANDASS] = 1; - IRO_IsModifyOp[EXORASS] = 1; - IRO_IsModifyOp[EORASS] = 1; - IRO_IsModifyOp[ECOMMA] = 0; - IRO_IsModifyOp[EPMODULO] = 1; - IRO_IsModifyOp[EROTL] = 1; - IRO_IsModifyOp[EROTR] = 1; - IRO_IsModifyOp[EBCLR] = 1; - IRO_IsModifyOp[EBTST] = 1; - IRO_IsModifyOp[EBSET] = 1; - IRO_IsModifyOp[ETYPCON] = 0; - IRO_IsModifyOp[EBITFIELD] = 0; - IRO_IsModifyOp[EINTCONST] = 0; - IRO_IsModifyOp[EFLOATCONST] = 0; - IRO_IsModifyOp[ESTRINGCONST] = 0; - IRO_IsModifyOp[ECOND] = 0; - IRO_IsModifyOp[EFUNCCALL] = 0; - IRO_IsModifyOp[EFUNCCALLP] = 0; - IRO_IsModifyOp[EOBJREF] = 0; - IRO_IsModifyOp[EMFPOINTER] = 0; - IRO_IsModifyOp[ENULLCHECK] = 0; - IRO_IsModifyOp[EPRECOMP] = 0; - IRO_IsModifyOp[ETEMP] = 0; - IRO_IsModifyOp[EARGOBJ] = 0; - IRO_IsModifyOp[ELOCOBJ] = 0; - IRO_IsModifyOp[ELABEL] = 0; - IRO_IsModifyOp[ESETCONST] = 0; - IRO_IsModifyOp[ENEWEXCEPTION] = 0; - IRO_IsModifyOp[ENEWEXCEPTIONARRAY] = 0; - IRO_IsModifyOp[EOBJLIST] = 0; - IRO_IsModifyOp[EMEMBER] = 0; - IRO_IsModifyOp[ETEMPLDEP] = 0; - IRO_IsModifyOp[EINSTRUCTION] = 0; - IRO_IsModifyOp[EDEFINE] = 0; - IRO_IsModifyOp[EREUSE] = 0; - IRO_IsModifyOp[EASSBLK] = 0; - IRO_IsModifyOp[EVECTOR128CONST] = 0; - IRO_IsModifyOp[ECONDASS] = 1; -} - -void IRO_InitializeIRO_IsAssignOpArray(void) { - int i; - - for (i = 0; i < MAXEXPR; i++) - IRO_IsAssignOp[i] = 0; - - IRO_IsAssignOp[EPOSTINC] = 1; - IRO_IsAssignOp[EPOSTDEC] = 1; - IRO_IsAssignOp[EPREINC] = 1; - IRO_IsAssignOp[EPREDEC] = 1; - IRO_IsAssignOp[EINDIRECT] = 0; - IRO_IsAssignOp[EMONMIN] = 0; - IRO_IsAssignOp[EBINNOT] = 0; - IRO_IsAssignOp[ELOGNOT] = 0; - IRO_IsAssignOp[EFORCELOAD] = 0; - IRO_IsAssignOp[EMUL] = 0; - IRO_IsAssignOp[EMULV] = 0; - IRO_IsAssignOp[EDIV] = 0; - IRO_IsAssignOp[EMODULO] = 0; - IRO_IsAssignOp[EADDV] = 0; - IRO_IsAssignOp[ESUBV] = 0; - IRO_IsAssignOp[EADD] = 0; - IRO_IsAssignOp[ESUB] = 0; - IRO_IsAssignOp[ESHL] = 0; - IRO_IsAssignOp[ESHR] = 0; - IRO_IsAssignOp[ELESS] = 0; - IRO_IsAssignOp[EGREATER] = 0; - IRO_IsAssignOp[ELESSEQU] = 0; - IRO_IsAssignOp[EGREATEREQU] = 0; - IRO_IsAssignOp[EEQU] = 0; - IRO_IsAssignOp[ENOTEQU] = 0; - IRO_IsAssignOp[EAND] = 0; - IRO_IsAssignOp[EXOR] = 0; - IRO_IsAssignOp[EOR] = 0; - IRO_IsAssignOp[ELAND] = 0; - IRO_IsAssignOp[ELOR] = 0; - IRO_IsAssignOp[EASS] = 1; - IRO_IsAssignOp[EMULASS] = 1; - IRO_IsAssignOp[EDIVASS] = 1; - IRO_IsAssignOp[EMODASS] = 1; - IRO_IsAssignOp[EADDASS] = 1; - IRO_IsAssignOp[ESUBASS] = 1; - IRO_IsAssignOp[ESHLASS] = 1; - IRO_IsAssignOp[ESHRASS] = 1; - IRO_IsAssignOp[EANDASS] = 1; - IRO_IsAssignOp[EXORASS] = 1; - IRO_IsAssignOp[EORASS] = 1; - IRO_IsAssignOp[ECOMMA] = 0; - IRO_IsAssignOp[EPMODULO] = 1; - IRO_IsAssignOp[EROTL] = 1; - IRO_IsAssignOp[EROTR] = 1; - IRO_IsAssignOp[EBCLR] = 1; - IRO_IsAssignOp[EBTST] = 1; - IRO_IsAssignOp[EBSET] = 1; - IRO_IsAssignOp[ETYPCON] = 0; - IRO_IsAssignOp[EBITFIELD] = 0; - IRO_IsAssignOp[EINTCONST] = 0; - IRO_IsAssignOp[EFLOATCONST] = 0; - IRO_IsAssignOp[ESTRINGCONST] = 0; - IRO_IsAssignOp[ECOND] = 0; - IRO_IsAssignOp[EFUNCCALL] = 0; - IRO_IsAssignOp[EFUNCCALLP] = 0; - IRO_IsAssignOp[EOBJREF] = 0; - IRO_IsAssignOp[EMFPOINTER] = 0; - IRO_IsAssignOp[ENULLCHECK] = 0; - IRO_IsAssignOp[EPRECOMP] = 0; - IRO_IsAssignOp[ETEMP] = 0; - IRO_IsAssignOp[EARGOBJ] = 0; - IRO_IsAssignOp[ELOCOBJ] = 0; - IRO_IsAssignOp[ELABEL] = 0; - IRO_IsAssignOp[ESETCONST] = 0; - IRO_IsAssignOp[ENEWEXCEPTION] = 0; - IRO_IsAssignOp[ENEWEXCEPTIONARRAY] = 0; - IRO_IsAssignOp[EOBJLIST] = 0; - IRO_IsAssignOp[EMEMBER] = 0; - IRO_IsAssignOp[ETEMPLDEP] = 0; - IRO_IsAssignOp[EINSTRUCTION] = 0; - IRO_IsAssignOp[EDEFINE] = 0; - IRO_IsAssignOp[EREUSE] = 0; - IRO_IsAssignOp[EASSBLK] = 0; - IRO_IsAssignOp[EVECTOR128CONST] = 0; - IRO_IsAssignOp[ECONDASS] = 1; -} - -VarRecord *IRO_FindVar(Object *object, Boolean flag1, Boolean flag2) { - VarRecord *var; - VarInfo *vi; - - var = object->varptr; - if (!var && flag1) { - vi = NULL; - if (object->datatype == DLOCAL) - vi = object->u.var.info; - if (vi) - vi->usage = 0; - var = oalloc(sizeof(VarRecord)); - var->object = object; - var->index = ++IRO_NumVars; - var->x6 = 0; - var->xA = 0; - var->next = NULL; - var->defs = NULL; - var->uses = NULL; - var->x1A = NULL; - var->x1E = NULL; - var->xB = 0; - if (IRO_FirstVar) - IRO_LastVar->next = var; - else - IRO_FirstVar = var; - IRO_LastVar = var; - object->varptr = var; - } - - if (var && !flag2) { - var->xB = 1; - if (object->datatype == DLOCAL && object->u.var.info && object->u.var.info->noregister == 0) - object->u.var.info->noregister = 2; - } - - return var; -} - -static void ResetVars(void) { - VarRecord *var; - - for (var = IRO_FirstVar; var; var = var->next) { - var->xB = 0; - if (var->object && var->object->datatype == DLOCAL && var->object->u.var.info) { - if (var->object->u.var.info->noregister == 2) - var->object->u.var.info->noregister = 0; - } - } -} - -static void IRO_HandleExceptionActions(IROLinear *linear) { - ExceptionAction *action; - - for (action = linear->stmt->dobjstack; action; action = action->prev) { - switch (action->type) { - case EAT_DESTROYLOCAL: - IRO_FindVar(action->data.destroy_local.local, 1, 0); - break; - case EAT_DESTROYLOCALCOND: - IRO_FindVar(action->data.destroy_local_cond.local, 1, 0); - break; - case EAT_DESTROYLOCALOFFSET: - IRO_FindVar(action->data.destroy_local_offset.local, 1, 0); - break; - case EAT_DESTROYLOCALARRAY: - IRO_FindVar(action->data.destroy_local_array.localarray, 1, 0); - break; - case EAT_DESTROYMEMBER: - case EAT_DESTROYBASE: - IRO_FindVar(action->data.destroy_member.objectptr, 1, 0); - break; - case EAT_DESTROYMEMBERCOND: - IRO_FindVar(action->data.destroy_member_cond.objectptr, 1, 0); - break; - case EAT_DESTROYMEMBERARRAY: - IRO_FindVar(action->data.destroy_member_array.objectptr, 1, 0); - break; - case EAT_CATCHBLOCK: - if (action->data.catch_block.catch_object) - IRO_FindVar(action->data.catch_block.catch_object, 1, 0); - IRO_FindVar(action->data.catch_block.catch_info_object, 1, 0); - break; - case EAT_ACTIVECATCHBLOCK: - IRO_FindVar(action->data.active_catch_block.catch_info_object, 1, 0); - break; - } - } -} - -void IRO_FindAllVars(void) { - IROLinear *linear; - VarRecord *var; - - linear = IRO_FirstLinear; - IRO_NumVars = 0; - IRO_FirstVar = IRO_LastVar = NULL; - - while (linear) { - if (IS_LINEAR_ENODE(linear, EOBJREF)) { - if (Inline_IsObjectData(linear->u.node->data.objref) || linear->u.node->data.objref->datatype == DLOCAL) - IRO_FindVar(linear->u.node->data.objref, 1, (linear->flags & IROLF_Ind) != 0); - else - linear->u.node->data.objref->varptr = NULL; - } else if (linear->type == IROLinearFunccall) { - if (linear->stmt && IRO_FunctionCallMightThrowException(linear)) - IRO_HandleExceptionActions(linear); - } else if (linear->type == IROLinearAsm) { - IAEffects effects; - int i; - CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); - for (i = 0; i < effects.numoperands; i++) - IRO_FindVar(effects.operands[i].object, 1, effects.operands[i].type != IAEffect_3); - } - linear = linear->next; - } - - var = IRO_FirstVar; - Bv_AllocVector(&IRO_FuncKills, IRO_NumVars + 1); - Bv_SetBit(0, IRO_FuncKills); - while (var) { - if (Inline_IsObjectData(var->object) || var->xB) - Bv_SetBit(var->index, IRO_FuncKills); - var = var->next; - } - - IRO_CheckForUserBreak(); -} - -void IRO_ZapVarPtrs(void) { - VarRecord *var; - - for (var = IRO_FirstVar; var; var = var->next) - var->object->varptr = NULL; -} - -void IRO_UpdateVars(void) { - IROLinear *linear; - VarRecord *var; - - ResetVars(); - - for (linear = IRO_FirstLinear; linear; linear = linear->next) { - if (IS_LINEAR_ENODE(linear, EOBJREF)) { - if (Inline_IsObjectData(linear->u.node->data.objref) || linear->u.node->data.objref->datatype == DLOCAL) - IRO_FindVar(linear->u.node->data.objref, 0, (linear->flags & IROLF_Ind) || !(linear->flags & IROLF_Reffed)); - } else if (linear->type == IROLinearFunccall) { - if (linear->stmt && IRO_FunctionCallMightThrowException(linear)) - IRO_HandleExceptionActions(linear); - } else if (linear->type == IROLinearAsm) { - IAEffects effects; - int i; - CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); - for (i = 0; i < effects.numoperands; i++) - IRO_FindVar(effects.operands[i].object, 0, effects.operands[i].type != IAEffect_3); - } - } - - var = IRO_FirstVar; - Bv_AllocVector(&IRO_FuncKills, IRO_NumVars + 1); - Bv_SetBit(0, IRO_FuncKills); - while (var) { - if (Inline_IsObjectData(var->object) || var->xB) - Bv_SetBit(var->index, IRO_FuncKills); - var = var->next; - } -} - -void IRO_AddElmToList(IROLinear *linear, IROElmList **list) { - IROElmList *l = oalloc(sizeof(IROElmList)); - l->element = linear; - l->next = NULL; - if (!*list) { - *list = l; - } else { - l->next = *list; - *list = l; - } -} - -void IRO_DecomposeAddressExpression(IROLinear *linear, IROAddrRecord *rec) { - if (IS_LINEAR_DIADIC(linear->u.diadic.left, EADD)) { - IRO_DecomposeAddressExpression(linear->u.diadic.left, rec); - } else if (IS_LINEAR_ENODE(linear->u.diadic.left, EINTCONST)) { - rec->numInts++; - IRO_AddElmToList(linear->u.diadic.left, &rec->ints); - } else if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF)) { - rec->numObjRefs++; - IRO_AddElmToList(linear->u.diadic.left, &rec->objRefs); - } else { - rec->numMisc++; - IRO_AddElmToList(linear->u.diadic.left, &rec->misc); - } - - if (IS_LINEAR_DIADIC(linear->u.diadic.right, EADD)) { - IRO_DecomposeAddressExpression(linear->u.diadic.right, rec); - } else if (IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) { - rec->numInts++; - IRO_AddElmToList(linear->u.diadic.right, &rec->ints); - } else if (IS_LINEAR_ENODE(linear->u.diadic.right, EOBJREF)) { - rec->numObjRefs++; - IRO_AddElmToList(linear->u.diadic.right, &rec->objRefs); - } else { - rec->numMisc++; - IRO_AddElmToList(linear->u.diadic.right, &rec->misc); - } -} - -void IRO_DecomposeAddressExpression_Cheap(IROLinear *linear) { - if (IS_LINEAR_DIADIC(linear->u.diadic.left, EADD)) { - IRO_DecomposeAddressExpression_Cheap(linear->u.diadic.left); - } else if (!IS_LINEAR_ENODE(linear->u.diadic.left, EINTCONST)) { - if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF)) { - IRO_BaseTerms++; - TheBaseTerm = linear->u.diadic.left; - } else { - IRO_VarTerms++; - } - } - - if (IS_LINEAR_DIADIC(linear->u.diadic.right, EADD)) { - IRO_DecomposeAddressExpression_Cheap(linear->u.diadic.right); - } else if (!IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) { - if (IS_LINEAR_ENODE(linear->u.diadic.right, EOBJREF)) { - IRO_BaseTerms++; - TheBaseTerm = linear->u.diadic.right; - } else { - IRO_VarTerms++; - } - } -} - -VarRecord *IRO_FindAssigned(IROLinear *linear) { - VarRecord *rec; - - IRO_IsBitField = 0; - if (linear->type == IROLinearOp2Arg) - linear = linear->u.diadic.left; - else if (linear->type == IROLinearOp1Arg) - linear = linear->u.monadic; - else - CError_FATAL(818); - - if (IS_LINEAR_MONADIC(linear, EINDIRECT)) - linear = linear->u.monadic; - - if (IS_LINEAR_MONADIC(linear, EBITFIELD)) { - IRO_IsBitField = 1; - linear = linear->u.monadic; - } - - if (IS_LINEAR_DIADIC(linear, EADD)) { - if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF) && IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) { - linear = linear->u.diadic.left; - } else { - IRO_BaseTerms = 0; - IRO_DecomposeAddressExpression_Cheap(linear); - if (IRO_BaseTerms == 1) - linear = TheBaseTerm; - } - } - - if (!IS_LINEAR_ENODE(linear, EOBJREF)) - return NULL; - - if ((rec = IRO_FindVar(linear->u.node->data.objref, 0, 1))) - return rec; - else - return NULL; -} - -static void GetKillsByIndirectAssignment(IROLinear *linear) { - IROListNode *resultList; - IROLinear *nd; - IROListNode *list; - IROListNode *scan; - IROLinear *inner; - Boolean result; - Boolean foundLinear; - - result = 0; - - if (linear->type == IROLinearOp2Arg) - linear = linear->u.diadic.left; - else - linear = linear->u.monadic; - - if ( - linear && - linear->type == IROLinearOp1Arg && - linear->nodetype == EINDIRECT && - (inner = linear->u.monadic) && - copts.opt_pointer_analysis && - inner->pointsToFunction && - FunctionName - ) - { - resultList = NULL; - PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList); - if ((list = resultList)) { - for (scan = list; scan; scan = scan->nextList) { - if (!scan->list.head || !scan->list.tail) { - result = 1; - break; - } - - foundLinear = 0; - for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { - if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { - foundLinear = 1; - break; - } - } - if (!foundLinear) { - result = 1; - break; - } - } - - if (!result) { - while (list) { - for (nd = list->list.head; nd != list->list.tail->next; nd = nd->next) { - if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { - Object *obj; - VarRecord *var; - int index; - - obj = nd->u.node->data.objref; - CError_ASSERT(952, obj != NULL); - - var = IRO_FindVar(obj, 1, 1); - CError_ASSERT(954, var != NULL); - - index = var->index; - CError_ASSERT(956, index != 0); - - Bv_SetBit(index, IRO_VarKills); - } - } - - list = list->nextList; - } - } - - while (resultList) { - IROListNode *next = resultList->nextList; - IRO_free(resultList); - resultList = next; - } - } else { - result = 1; - } - } else { - result = 1; - } - - if (result) - Bv_Or(IRO_FuncKills, IRO_VarKills); -} - -static void GetKillsByFunctionCall(IROLinear *linear) { - IROListNode *resultList; - IROLinear *nd; - IROListNode *list; - IROListNode *scan; - IROLinear *inner; - Boolean result; - Boolean foundLinear; - Object *obj; - ObjectList *killList; - ObjectList *olist; - - result = 0; - - if ( - (inner = linear->u.funccall.linear8) && - copts.opt_pointer_analysis && - inner->pointsToFunction && - FunctionName - ) - { - resultList = NULL; - PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList); - if (resultList) { - for (scan = resultList; scan; scan = scan->nextList) { - if (!scan->list.head || !scan->list.tail) { - result = 1; - break; - } - - foundLinear = 0; - for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { - if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { - foundLinear = 1; - obj = nd->u.node->data.objref; - CError_ASSERT(1028, obj != NULL); - - killList = NULL; - PointerAnalysis_GetFunctionKills(obj, linear, &killList); - - for (olist = killList; olist; olist = olist->next) { - if (!olist->object) { - result = 1; - break; - } - } - - while (killList) { - ObjectList *next = killList->next; - IRO_free(killList); - killList = next; - } - - if (result) - break; - } - } - - if (!foundLinear) - result = 1; - if (result) - break; - } - - if (!result) { - for (scan = resultList; scan; scan = scan->nextList) { - for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { - if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { - obj = nd->u.node->data.objref; - killList = NULL; - PointerAnalysis_GetFunctionKills(obj, linear, &killList); - - for (olist = killList; olist; olist = olist->next) { - VarRecord *var; - int index; - - var = IRO_FindVar(olist->object, 1, 1); - CError_ASSERT(1079, var != NULL); - - index = var->index; - CError_ASSERT(1081, index != 0); - - Bv_SetBit(index, IRO_VarKills); - } - - while (killList) { - ObjectList *next = killList->next; - IRO_free(killList); - killList = next; - } - } - } - } - } - - while (resultList) { - IROListNode *next = resultList->nextList; - IRO_free(resultList); - resultList = next; - } - } else { - result = 1; - } - } else { - result = 1; - } - - if (result) - Bv_Or(IRO_FuncKills, IRO_VarKills); -} - -void IRO_GetKills(IROLinear *linear) { - VarRecord *var; - - switch (linear->type) { - case IROLinearOp1Arg: - case IROLinearOp2Arg: - if (IRO_IsAssignOp[linear->nodetype]) { - IROLinear *assigned; - int index; - - var = IRO_FindAssigned(linear); - index = 0; - if (var) index = var->index; - Bv_SetBit(index, IRO_VarKills); - - if (!index) - GetKillsByIndirectAssignment(linear); - } - break; - case IROLinearFunccall: - GetKillsByFunctionCall(linear); - break; - case IROLinearAsm: { - IAEffects effects; - int i; - - CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects); - for (i = 0; i < effects.numoperands; i++) { - switch (effects.operands[i].type) { - case IAEffect_1: - case IAEffect_2: - case IAEffect_4: - if ((var = IRO_FindVar(effects.operands[i].object, 0, 1))) - Bv_SetBit(var->index, IRO_VarKills); - break; - } - } - - if (effects.x1 || effects.x4) - Bv_Or(IRO_FuncKills, IRO_VarKills); - break; - } - } -} - -void IRO_CheckInit(void) { - IRONode *fnode; - IROLinear *nd; - VarRecord *var; - ObjectList *olist; - int flag; - int i; - BitVector *bv; - - IRO_MakeReachable(IRO_FirstNode); - fnode = IRO_FirstNode; - Bv_AllocVector(&IRO_VarKills, IRO_NumVars + 1); - - while (fnode) { - Bv_AllocVector(&fnode->x16, IRO_NumVars + 1); - Bv_AllocVector(&fnode->x1E, IRO_NumVars + 1); - - for (nd = fnode->first; nd; nd = nd->next) { - if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { - if (nd->flags & IROLF_Ind) { - if (!(nd->flags & IROLF_Assigned) || (nd->flags & IROLF_Used)) { - if ((var = IRO_FindVar(nd->u.node->data.objref, 0, 1))) { - if (!Bv_IsBitSet(var->index, fnode->x1E)) - Bv_SetBit(var->index, fnode->x16); - } - } - } else { - if ((var = IRO_FindVar(nd->u.node->data.objref, 0, 0))) { - Bv_SetBit(var->index, fnode->x1E); - } - } - } else if (nd->type == IROLinearOp2Arg && nd->nodetype == EASS) { - if ((var = IRO_FindAssigned(nd))) - Bv_SetBit(var->index, fnode->x1E); - } else if (nd->type == IROLinearAsm) { - IAEffects effects; - - CodeGen_GetAsmEffects(nd->u.asm_stmt, &effects); - for (i = 0; i < effects.numoperands; i++) { - var = IRO_FindVar(effects.operands[i].object, 0, 1); - switch (effects.operands[i].type) { - case IAEffect_1: - case IAEffect_2: - case IAEffect_4: - Bv_SetBit(var->index, fnode->x1E); - break; - } - } - } - - if (nd == fnode->last) - break; - } - - fnode = fnode->nextnode; - } - - Bv_AllocVector(&bv, IRO_NumVars + 1); - - do { - flag = 0; - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - Bv_Copy(fnode->x1E, bv); - for (i = 0; i < fnode->numpred; i++) - Bv_Or(IRO_NodeTable[fnode->pred[i]]->x1E, bv); - if (!Bv_Compare(bv, fnode->x1E)) { - Bv_Copy(bv, fnode->x1E); - flag = 1; - } - } - } while (flag); - - Bv_Clear(IRO_VarKills); - - for (fnode = IRO_FirstNode; fnode; fnode = fnode->nextnode) { - if (fnode->x36) { - Bv_Copy(fnode->x16, bv); - for (i = 0; i < fnode->numpred; i++) - Bv_Minus(IRO_NodeTable[fnode->pred[i]]->x1E, bv); - Bv_Or(bv, IRO_VarKills); - } - } - - for (olist = locals; olist; olist = olist->next) { - if ((var = IRO_FindVar(olist->object, 0, 1)) && Bv_IsBitSet(var->index, IRO_VarKills)) { - VarInfo *vi = olist->object->u.var.info; - if (!IsTempName(olist->object->name) && !is_volatile_object(olist->object)) { - if (!IS_TYPE_CLASS(olist->object->type) || !CClass_IsEmpty(TYPE_CLASS(olist->object->type))) { - CError_SetErrorToken(&vi->deftoken); - CError_Warning(CErrorStr185, olist->object->name->name); - } - } - } - } - - IRO_CheckForUserBreak(); -} - -static void RewriteIndDec(void) { - IROLinear *add; - IROLinear *indirect; - IROLinear *Int; - IROLinear *nd; - CInt64 value; - IROList list; - - for (nd = IRO_FirstLinear; nd; nd = nd->next) { - if ( - nd->type == IROLinearOp1Arg && - (nd->nodetype == EPOSTINC || nd->nodetype == EPOSTDEC) && - !(nd->flags & IROLF_Reffed) - ) { - indirect = nd->u.monadic; - if ( - indirect->type == IROLinearOp1Arg && - indirect->nodetype == EINDIRECT && - indirect->u.monadic->type == IROLinearOp1Arg && - indirect->u.monadic->nodetype == EBITFIELD - ) { - value = IRO_GetSelfAssignmentVal(nd); - IRO_InitList(&list); - - nd->type = IROLinearOp2Arg; - nd->nodetype = EASS; - nd->u.diadic.left = indirect; - IRO_DuplicateExpr(indirect, &list); - - Int = IRO_NewIntConst(value, indirect->rtype); - Int->flags |= IROLF_Used | IROLF_Reffed; - - add = IRO_NewLinear(IROLinearOp2Arg); - add->nodetype = EADD; - add->u.diadic.left = list.tail; - add->u.diadic.left->flags = 0; - add->u.diadic.left->flags |= IROLF_Used | IROLF_Reffed; - add->u.diadic.right = Int; - add->rtype = indirect->rtype; - add->flags = 0; - add->flags |= IROLF_Used | IROLF_Reffed; - - nd->u.diadic.right = add; - - IRO_AddToList(Int, &list); - IRO_AddToList(add, &list); - IRO_PasteAfter(list.head, list.tail, indirect); - } - } - } -} - -void IRO_RewriteBitFieldTemps(void) { - IROLinear *nd; - IROLinear *expr2; - Object *obj; - VarRecord *var; - IROList list; - - for (nd = IRO_FirstLinear; nd; nd = nd->next) { - if ((obj = IRO_IsVariable(nd)) && (nd->flags & IROLF_BitfieldIndirect)) { - var = IRO_FindVar(obj, 0, 1); - CError_ASSERT(1526, var != NULL); - - expr2 = var->x1E; - CError_ASSERT(1532, expr2 != NULL); - - IRO_InitList(&list); - IRO_DuplicateExpr(expr2, &list); - IRO_NopOut(nd->u.monadic); - nd->u.monadic = list.tail; - IRO_Paste(list.head, list.tail, nd); - } - } -} - -static Boolean FunctionCallMightUseOrKillAnyAddressedVar(IROLinear *funccall) { - IROLinear *funcnd; - IROLinear *nd; - IROListNode *scan; - IROListNode *resultList; - ObjectList *olist; - ObjectList *killList; - VarRecord *var; - Boolean result; - Boolean foundObjRef; - Object *obj; - - result = 0; - - funcnd = funccall->u.funccall.linear8; - if (funcnd && copts.opt_pointer_analysis && funcnd->pointsToFunction && FunctionName) { - resultList = NULL; - PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, funcnd, &resultList); - - if (resultList) { - for (scan = resultList; scan; scan = scan->nextList) { - if (!scan->list.head || !scan->list.tail) { - result = 1; - break; - } - - foundObjRef = 0; - for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { - if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { - foundObjRef = 1; - obj = nd->u.node->data.objref; - CError_ASSERT(1592, obj != NULL); - - killList = NULL; - PointerAnalysis_GetFunctionKills(obj, funccall, &killList); - for (olist = killList; olist; olist = olist->next) { - if (!olist->object) { - result = 1; - } else { - var = IRO_FindVar(olist->object, 1, 1); - CError_ASSERT(1604, var != NULL); - if (var->xB) - result = 1; - } - - if (result) - break; - } - - while (killList) { - ObjectList *next = killList->next; - IRO_free(killList); - killList = next; - } - - if (!result) { - killList = NULL; - PointerAnalysis_GetFunctionDependencies(obj, funccall, &killList); - for (olist = killList; olist; olist = olist->next) { - if (!olist->object) { - result = 1; - } else { - var = IRO_FindVar(olist->object, 1, 1); - CError_ASSERT(1632, var != NULL); - if (var->xB) - result = 1; - } - - if (result) - break; - } - - while (killList) { - ObjectList *next = killList->next; - IRO_free(killList); - killList = next; - } - } - - if (result) - break; - } - } - - if (!foundObjRef) - result = 1; - if (result) - break; - } - - while (resultList) { - IROListNode *next = resultList->nextList; - IRO_free(resultList); - resultList = next; - } - } else { - result = 1; - } - } else { - result = 1; - } - - return result; -} - -static Boolean IndirectMightUseOrKillAnyAddressedVar(IROLinear *indirect) { - Boolean result; - IROLinear *inner; - IROLinear *nd; - IROListNode *scan; - IROListNode *resultList; - Boolean foundObjRef; - Object *obj; - VarRecord *var; - - result = 0; - - if ( - indirect && - indirect->type == IROLinearOp1Arg && - indirect->nodetype == EINDIRECT && - (inner = indirect->u.monadic) && - copts.opt_pointer_analysis && - inner->pointsToFunction && - FunctionName - ) { - resultList = NULL; - PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, inner, &resultList); - if (resultList) { - for (scan = resultList; scan; scan = scan->nextList) { - if (!scan->list.head || !scan->list.tail) { - result = 1; - break; - } - - foundObjRef = 0; - for (nd = scan->list.head; nd != scan->list.tail->next; nd = nd->next) { - if (nd->type == IROLinearOperand && nd->u.node->type == EOBJREF) { - foundObjRef = 1; - obj = nd->u.node->data.objref; - CError_ASSERT(1723, obj != NULL); - var = IRO_FindVar(obj, 1, 1); - CError_ASSERT(1725, var != NULL); - - if (var->xB) - result = 1; - } - } - - if (!foundObjRef) - result = 1; - if (result) - break; - } - - while (resultList) { - IROListNode *next = resultList->nextList; - IRO_free(resultList); - resultList = next; - } - } else { - result = 1; - } - } else { - result = 1; - } - - return result; -} - -void IRO_ScalarizeClassDataMembers(void) { - IROLinear *nd; - VarRecord *var; - Boolean flag; - Object *obj; - IndirectRecord *irec; - IndirectRecordMatch *match; - IROLinear *tmp; - - nd = IRO_FirstLinear; - IRO_FirstIndirectRecord = NULL; - IRO_LastIndirectRecord = NULL; - RewriteIndDec(); - IRO_DumpAfterPhase("RewriteIndDec", 0); - flag = 0; - - while (nd) { - if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT) { - CheckAddress(nd, &flag); - } - if (nd->type == IROLinearAsm) { - IAEffects effects; - SInt32 i; - CodeGen_GetAsmEffects(nd->u.asm_stmt, &effects); - for (i = 0; i < effects.numoperands; i++) { - if ((var = IRO_FindVar(effects.operands[i].object, 0, 1))) - CheckAddressConsistency(nd, var, -1, &stvoid); - else - CError_FATAL(1823); - } - } - if (nd->type == IROLinearFunccall && !flag) - flag = FunctionCallMightUseOrKillAnyAddressedVar(nd); - - nd = nd->next; - } - - if (flag) - DisableAddressedEntries(); - - for (irec = IRO_FirstIndirectRecord; irec; irec = irec->next) { - if (!(irec->flags & 1)) { - IROList list1; - IROList list2; - - obj = create_temp_object(irec->type); - var = IRO_FindVar(obj, 1, 1); - for (match = irec->matches; match; match = match->otherMatches) { - IRO_InitList(&list1); - IRO_InitList(&list2); - IRO_DuplicateExpr(match->nd, &list1); - IRO_DuplicateExpr(match->nd, &list2); - if (match->nd->type == IROLinearOperand && match->nd->u.node->type == EOBJREF) { - tmp = IRO_LocateFather(match->nd); - if (irec->flags & 2) { - tmp->flags |= IROLF_BitfieldIndirect; - var->x1A = match->nd->rtype; - var->x1E = list2.tail; - } - match->nd->u.node = create_objectrefnode(obj); - irec->x26 = list2.tail; - } else { - tmp = IRO_LocateFather(match->nd); - if (irec->flags & 2) { - tmp->flags |= IROLF_BitfieldIndirect; - var->x1A = match->nd->rtype; - var->x1E = list2.tail; - } - irec->x26 = list2.tail; - - IRO_NopOut(tmp->u.monadic); - tmp->u.monadic = IRO_NewLinear(IROLinearOperand); - tmp->u.monadic->u.node = create_objectrefnode(obj); - tmp->u.monadic->rtype = match->nd->rtype; - tmp->u.monadic->index = ++IRO_NumLinear; - tmp->u.monadic->flags |= IROLF_Ind | IROLF_Reffed; - IRO_NopOut(match->nd); - IRO_PasteAfter(tmp->u.monadic, tmp->u.monadic, match->nd); - } - } - - if (ObjectIsArg(irec->var->object)) { - IROLinear *op1; - IROLinear *op2; - IROLinear *op3; - IROLinear *op4; - IROLinear *op5; - - op1 = IRO_NewLinear(IROLinearOperand); - op1->u.node = create_objectrefnode(obj); - op1->rtype = op1->u.node->data.objref->type; - op1->index = ++IRO_NumLinear; - op1->flags |= IROLF_Ind | IROLF_Assigned; - - op2 = list1.tail; - - op3 = IRO_NewLinear(IROLinearOp1Arg); - op3->nodetype = EINDIRECT; - op3->rtype = irec->type; - op3->u.monadic = op1; - op3->index = ++IRO_NumLinear; - op3->flags |= IROLF_Assigned; - - op4 = IRO_NewLinear(IROLinearOp1Arg); - op4->nodetype = EINDIRECT; - op4->rtype = irec->type; - op4->u.monadic = op2; - op4->index = ++IRO_NumLinear; - op4->flags |= IROLF_Reffed; - - op5 = IRO_NewLinear(IROLinearOp2Arg); - op5->nodetype = EASS; - op5->u.diadic.left = op3; - op5->u.diadic.right = op4; - op5->rtype = irec->type; - op5->index = ++IRO_NumLinear; - - op2->next = op4; - op4->next = op1; - op1->next = op3; - op3->next = op5; - - IRO_PasteAfter(list1.head, op5, IRO_FirstLinear); - } - } - } - - IRO_CheckForUserBreak(); -} - -static Boolean CheckAddress(IROLinear *nd, Boolean *resultFlag) { - IROLinear *inner; - VarRecord *var; - Boolean result; - - inner = nd->u.monadic; - if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD) - inner = inner->u.monadic; - - result = 0; - - if (inner->type == IROLinearOperand && inner->u.node->type == EOBJREF) { - if (IS_TYPE_CLASS(inner->u.node->data.objref->type) || IS_TYPE_STRUCT(inner->u.node->data.objref->type) || - IS_TYPE_ARRAY(inner->u.node->data.objref->type)) { - if (inner->u.node->data.objref->datatype == DLOCAL) { - var = IRO_FindVar(inner->u.node->data.objref, 0, 1); - CError_ASSERT(2240, var != NULL); - CheckAddressConsistency(nd, var, 0, nd->rtype); - result = 1; - } - } - } else if ( - inner->type == IROLinearOp2Arg && - inner->nodetype == EADD && - inner->u.diadic.left->type == IROLinearOperand && - inner->u.diadic.left->u.node->type == EOBJREF) { - if ( - inner->u.diadic.right->type == IROLinearOperand && - inner->u.diadic.right->u.node->type == EINTCONST && - inner->u.diadic.right->u.node->data.intval.hi == 0) { - if ( - IS_TYPE_CLASS(inner->u.diadic.left->u.node->data.objref->type) || - IS_TYPE_STRUCT(inner->u.diadic.left->u.node->data.objref->type) || - IS_TYPE_ARRAY(inner->u.diadic.left->u.node->data.objref->type) - ) { - if (inner->u.diadic.left->u.node->data.objref->datatype == DLOCAL) { - var = IRO_FindVar(inner->u.diadic.left->u.node->data.objref, 0, 1); - CError_ASSERT(2267, var != NULL); - CheckAddressConsistency(nd, var, inner->u.diadic.right->u.node->data.intval.lo, nd->rtype); - result = 1; - } - } - } else { - if ( - IS_TYPE_CLASS(inner->u.diadic.left->u.node->data.objref->type) || - IS_TYPE_STRUCT(inner->u.diadic.left->u.node->data.objref->type) || - IS_TYPE_ARRAY(inner->u.diadic.left->u.node->data.objref->type) - ) { - if (inner->u.diadic.left->u.node->data.objref->datatype == DLOCAL) { - var = IRO_FindVar(inner->u.diadic.left->u.node->data.objref, 0, 1); - CheckAddressConsistency(nd, var, -1, nd->rtype); - result = 1; - } - } - } - } - - if (!result && !*resultFlag) { - *resultFlag = IndirectMightUseOrKillAnyAddressedVar(nd); - } - - return 0; -} - -static Boolean CheckAddressConsistency(IROLinear *nd, VarRecord *var, SInt32 addend, Type *type) { - IndirectRecord *rp; - IndirectRecordMatch *match; - UInt32 flag; - IROLinear *inner; - UInt32 start_bit; - UInt32 end_bit; - - flag = 0; - inner = nd->u.monadic; - if (inner->type == IROLinearOp1Arg && inner->nodetype == EBITFIELD) { - start_bit = TYPE_BITFIELD(inner->rtype)->offset + 8 * addend; - end_bit = start_bit + TYPE_BITFIELD(inner->rtype)->bitlength - 1; - } else { - start_bit = 8 * addend; - end_bit = start_bit + 8 * type->size - 1; - } - - if (var->xB && !copts.opt_pointer_analysis) - return 0; - - if (nd->rtype && CParser_IsVolatile(nd->rtype, nd->nodeflags & ENODE_FLAG_QUALS)) - addend = -1; - if (is_volatile_object(var->object)) - addend = -1; - - for (rp = IRO_FirstIndirectRecord; rp; rp = rp->next) { - if (rp->var->index == var->index) { - if (rp->flags & 1) - return 0; - - if (addend == -1) { - flag = 1; - break; - } - - if (IRO_TypesEqual(rp->type, type) && rp->startbit == start_bit && rp->endbit == end_bit) { - match = oalloc(sizeof(IndirectRecordMatch)); - match->nd = inner; - match->otherMatches = NULL; - if (!rp->matches) { - rp->matches = match; - } else { - match->otherMatches = rp->matches; - rp->matches = match; - } - - IRO_Dump("Exact Match of Type and bits at %d and %d\n", rp->linear->index, nd->index); - IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit); - return 1; - } - - if (rp->startbit == start_bit && rp->endbit == end_bit && !IRO_TypesEqual(rp->type, type)) { - IRO_Dump("match on bits but mismatch on type %d and %d\n", rp->linear->index, nd->index); - IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit); - flag = 1; - break; - } - - if (rp->startbit >= start_bit && end_bit >= rp->startbit) { - IRO_Dump("Overlap detected --1 %d and %d\n", rp->linear->index, nd->index); - IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit); - flag = 1; - break; - } - - if (rp->startbit < start_bit && rp->endbit >= start_bit) { - IRO_Dump("Overlap detected --2 %d and %d\n", rp->linear->index, nd->index); - IRO_Dump("Rp->startbit=%d,Rp->endbit=%d,start_bit=%d,end_bit=%d\n", rp->startbit, rp->endbit, start_bit, end_bit); - flag = 1; - break; - } - } - } - - if (flag) { - DisableEntries(rp); - if (addend >= 0) - return 0; - } - - IRO_Dump("Create Entry at %d\n", nd->index); - IRO_Dump("start_bit=%d,end_bit=%d\n", start_bit, end_bit); - - rp = oalloc(sizeof(IndirectRecord)); - rp->linear = nd; - rp->flags = 0; - rp->var = var; - rp->addend = addend; - rp->size = type->size; - rp->type = type; - rp->next = NULL; - rp->matches = oalloc(sizeof(IndirectRecordMatch)); - rp->matches->nd = inner; - rp->matches->otherMatches = NULL; - rp->startbit = start_bit; - rp->endbit = end_bit; - - if (nd->type == IROLinearOp1Arg && nd->nodetype == EINDIRECT && - nd->u.monadic->type == IROLinearOp1Arg && nd->u.monadic->nodetype == EBITFIELD) - rp->flags |= 2; - - if (!(IS_TYPE_FLOAT(type) || IS_TYPE_INT(type) || IS_TYPE_POINTER_ONLY(type)) || - addend == -1 || ((inner->flags & IROLF_4000) && ObjectIsArg(var->object))) - rp->flags |= 1; - - if (IRO_FirstIndirectRecord) - IRO_LastIndirectRecord->next = rp; - else - IRO_FirstIndirectRecord = rp; - IRO_LastIndirectRecord = rp; - return 1; -} - -static void DisableEntries(IndirectRecord *irec) { - IndirectRecord *scan; - - for (scan = IRO_FirstIndirectRecord; scan; scan = scan->next) { - if (irec->var->index == scan->var->index) - scan->flags |= 1; - } -} - -static void DisableAddressedEntries(void) { - IndirectRecord *scan; - - for (scan = IRO_FirstIndirectRecord; scan; scan = scan->next) { - if (scan->var->xB) - scan->flags |= 1; - } -} - -static UInt32 ObjectIsArg(Object *obj) { - ObjectList *scan; - - for (scan = arguments; scan; scan = scan->next) { - if (scan->object == obj) - return 1; - } - - return 0; -} - diff --git a/compiler_and_linker/unsorted/LoopDetection.c b/compiler_and_linker/unsorted/LoopDetection.c deleted file mode 100644 index 6bb2d51..0000000 --- a/compiler_and_linker/unsorted/LoopDetection.c +++ /dev/null @@ -1,885 +0,0 @@ -#include "compiler/LoopDetection.h" -#include "compiler/CFunc.h" -#include "compiler/PCode.h" -#include "compiler/TOC.h" -#include "compiler/UseDefChains.h" -#include "compiler/CompilerTools.h" -#include "compiler/BitVectors.h" -#include "compiler/enode.h" -#include "compiler/objects.h" - -Loop *loopsinflowgraph; -int loopdetection_nblocks; -static UInt32 **dominators; -static BlockList *loopheaders; -static int nloopheaders; -static PCodeBlock **loopstack; -BitVector *LoopTemp; -struct LoopList *LoopList_First; - -static void computedominators(void) { - int i; - PCodeBlock *block; - int blockCount; - int flag; - UInt32 *myvec; - PCLink *link; - - blockCount = pcblockcount; - flag = 1; - - dominators = oalloc(sizeof(UInt32 *) * pcblockcount); - for (i = 0; i < pcblockcount; i++) - dominators[i] = oalloc(4 * ((blockCount + 31) >> 5)); - - myvec = oalloc(4 * ((blockCount + 31) >> 5)); - - bitvectorinitialize(dominators[pcbasicblocks->blockIndex], blockCount, 0); - //dominators[pcbasicblocks->blockIndex][0] |= 1; - bitvectorsetbit(0, dominators[pcbasicblocks->blockIndex]); - - for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) - bitvectorinitialize(dominators[block->blockIndex], blockCount, 0xFFFFFFFF); - - computedepthfirstordering(); - - while (flag) { - flag = 0; - for (i = 0; i < pcblockcount; i++) { - block = depthfirstordering[i]; - if (block && block->blockIndex != pcbasicblocks->blockIndex) { - bitvectorcopy(myvec, dominators[block->predecessors->block->blockIndex], blockCount); - for (link = block->predecessors->nextLink; link; link = link->nextLink) - bitvectorintersect(myvec, dominators[link->block->blockIndex], blockCount); - //myvec[block->blockIndex >> 5] |= 1 << (block->blockIndex & 31); - bitvectorsetbit(block->blockIndex, myvec); - - if (bitvectorchanged(dominators[block->blockIndex], myvec, blockCount)) - flag = 1; - } - } - } -} - -static BlockList *findloopheaders(void) { - PCodeBlock *block; - PCLink *link; - BlockList *list; - - loopheaders = NULL; - nloopheaders = 0; - - for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) { - for (link = block->predecessors; link; link = link->nextLink) { - //if ((1 << (block->blockIndex & 31)) & dominators[link->block->blockIndex][block->blockIndex >> 5]) - if (bitvectorgetbit(block->blockIndex, dominators[link->block->blockIndex])) - break; - } - - if (link) { - list = oalloc(sizeof(BlockList)); - list->block = block; - list->next = loopheaders; - loopheaders = list; - nloopheaders++; - } - } - - return loopheaders; -} - -void addblocktoloop(Loop *loop, PCodeBlock *block) { - BlockList *list = lalloc(sizeof(BlockList)); - - //loop->memberblocks[block->blockIndex >> 5] |= 1 << (block->blockIndex & 31); - bitvectorsetbit(block->blockIndex, loop->memberblocks); - - list->block = block; - list->next = loop->blocks; - loop->blocks = list; -} - -static void findnaturalloop(Loop *loop) { - BlockList *list; - BlockList *list2; - PCLink *link; - PCodeBlock *block; - int i; - - i = 0; - addblocktoloop(loop, loop->body); - for (link = loop->body->predecessors; link; link = link->nextLink) { - if (bitvectorgetbit(loop->body->blockIndex, dominators[link->block->blockIndex]) && link->block != loop->body) { - addblocktoloop(loop, link->block); - loopstack[i++] = link->block; - } - } - - while (i) { - link = loopstack[--i]->predecessors; - while (link) { - if (!bitvectorgetbit(link->block->blockIndex, loop->memberblocks)) { - addblocktoloop(loop, link->block); - loopstack[i++] = link->block; - } - link = link->nextLink; - } - } - - for (list = loop->blocks; list; list = list->next) { - block = list->block; - for (link = block->successors; link; link = link->nextLink) { - if (!bitvectorgetbit(link->block->blockIndex, loop->memberblocks)) { - bitvectorsetbit(block->blockIndex, loop->vec24); - break; - } - } - } - - for (list = loop->blocks; list; list = list->next) { - for (list2 = loop->blocks; list2; list2 = list2->next) { - if (bitvectorgetbit(list2->block->blockIndex, loop->vec24) && - !bitvectorgetbit(list->block->blockIndex, dominators[list2->block->blockIndex])) - break; - } - - if (!list2) - bitvectorsetbit(list->block->blockIndex, loop->vec28); - } - - for (list = loop->blocks; list; list = list->next) { - for (link = loop->body->predecessors; link; link = link->nextLink) { - if (bitvectorgetbit(link->block->blockIndex, loop->memberblocks) && - !bitvectorgetbit(list->block->blockIndex, dominators[link->block->blockIndex])) - break; - } - - if (!link) - bitvectorsetbit(list->block->blockIndex, loop->vec2C); - } -} - -static void addlooptolist(Loop *loop, Loop **list) { - Loop **scan; - Loop *scanloop; - - scan = list; - while ((scanloop = *scan)) { - if (bitvectorgetbit(loop->body->blockIndex, scanloop->memberblocks)) { - loop->parent = scanloop; - addlooptolist(loop, &scanloop->children); - return; - } - - if (bitvectorgetbit(scanloop->body->blockIndex, loop->memberblocks)) { - *scan = scanloop->nextSibling; - scanloop->parent = loop; - scanloop->nextSibling = loop->children; - loop->children = scanloop; - } else { - scan = &scanloop->nextSibling; - } - } - - loop->nextSibling = *list; - *list = loop; -} - -static void findnaturalloops(void) { - Loop *loop; - int size; - - loopdetection_nblocks = pcblockcount + 5 * nloopheaders; - loopstack = oalloc(sizeof(PCodeBlock *) * pcblockcount); - while (loopheaders) { - loop = lalloc(sizeof(Loop)); - loop->parent = loop->nextSibling = loop->children = NULL; - loop->body = loopheaders->block; - loop->preheader = NULL; - loop->blocks = NULL; - loop->basicInductionVars = NULL; - loop->footer = NULL; - loop->pc18 = NULL; - loop->loopWeight = loop->body->loopWeight; - - bitvectorinitialize(loop->memberblocks = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); - bitvectorinitialize(loop->vec24 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); - bitvectorinitialize(loop->vec28 = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); - bitvectorinitialize(loop->vec2C = lalloc(4 * ((loopdetection_nblocks + 31) >> 5)), loopdetection_nblocks, 0); - - findnaturalloop(loop); - addlooptolist(loop, &loopsinflowgraph); - - loopheaders = loopheaders->next; - } -} - -static PCodeBlock *makepreheaderblock(void) { - PCodeLabel *label; - PCodeBlock *block; - - label = makepclabel(); - block = lalloc(sizeof(PCodeBlock)); - block->nextBlock = NULL; - block->prevBlock = NULL; - block->labels = NULL; - block->successors = NULL; - block->predecessors = NULL; - block->firstPCode = block->lastPCode = NULL; - block->pcodeCount = 0; - block->flags = 0; - block->blockIndex = pcblockcount++; - pclabel(block, label); - return block; -} - -static void insertpreheaderbefore(PCodeBlock *a, PCodeBlock *b) { - a->nextBlock = b; - a->prevBlock = b->prevBlock; - b->prevBlock->nextBlock = a; - b->prevBlock = a; -} - -void insertpreheaderblock(Loop *loop) { - PCodeBlock *preheader; - PCodeBlock *block29; - PCodeBlock *block28; - PCode *pcode27; - PCLink *link; // r26 - PCLink **linkptr; // r25 - PCodeLabel *newlabel; // r23 - PCLink *innerlink; - PCodeBlock *block; - PCodeArg *arg; - int i; - - preheader = loop->preheader = makepreheaderblock(); - block29 = NULL; - block28 = loop->body; - - if (!block28->labels) - pclabel(block28, makepclabel()); - - appendpcode(preheader, makepcode(PC_B, block28->labels)); - preheader->loopWeight = loop->parent ? loop->parent->loopWeight : 1; - - linkptr = &block28->predecessors; - while ((link = *linkptr)) { - if (bitvectorgetbit(link->block->blockIndex, loop->memberblocks)) { - linkptr = &link->nextLink; - } else { - if (link->block->pcodeCount) { - pcode27 = link->block->lastPCode; - if (pcode27->op == PC_B) { - CError_ASSERT(462, pcode27->args[0].kind == PCOp_LABEL); - if (pcode27->args[0].data.label.label->block == block28) - pcode27->args[0].data.label.label = preheader->labels; - } else if (pcode27->op == PC_BT || pcode27->op == PC_BF) { - CError_ASSERT(474, pcode27->args[2].kind == PCOp_LABEL); - if (pcode27->args[2].data.label.label->block == block28) - pcode27->args[2].data.label.label = preheader->labels; - } else if (pcode27->op == PC_BCTR) { - if (pcode27->argCount > 1 && pcode27->args[1].kind == PCOp_MEMORY) { - Object *obj = pcode27->args[1].data.mem.obj; - UInt32 *array = (UInt32 *) obj->u.data.u.switchtable.data; - int i; - for (i = 0; i < obj->u.data.u.switchtable.size; i++) { - if (((PCodeLabel *) CTool_ResolveIndexToPointer(array[i]))->block == block28) - array[i] = CTool_CreateIndexFromPointer(preheader->labels); - } - } else { - CodeLabelList *cll; - for (cll = codelabellist; cll; cll = cll->next) { - if (cll->label->pclabel->block == block28) - cll->label->pclabel = preheader->labels; - } - } - } else { - CError_ASSERT(505, link->block->nextBlock == block28); - } - } - - for (innerlink = link->block->successors; innerlink; innerlink = innerlink->nextLink) { - if (innerlink->block == block28) - innerlink->block = preheader; - } - - *linkptr = link->nextLink;; - link->nextLink = preheader->predecessors; - preheader->predecessors = link; - } - } - - if (!bitvectorgetbit(block28->prevBlock->blockIndex, loop->memberblocks)) { - insertpreheaderbefore(preheader, block28); - - if ( - (!block28->nextBlock || !bitvectorgetbit(block28->nextBlock->blockIndex, loop->memberblocks)) && - block28->lastPCode && - (block28->lastPCode->flags & fIsBranch) && - block28->lastPCode->op != PC_BDNZ - ) { - i = block28->lastPCode->argCount; - arg = block28->lastPCode->args; - while (i && arg->kind != PCOp_LABEL) { - arg++; - i--; - } - - if (i && arg->kind == PCOp_LABEL && arg->data.label.label->block == block28) { - block29 = makepreheaderblock(); - insertpreheaderbefore(block29, block28); - newlabel = makepclabel(); - pclabel(block29, newlabel); - arg->data.label.label = newlabel; - - link = lalloc(sizeof(PCLink)); - link->block = block28; - link->nextLink = block29->predecessors; - block29->predecessors = link; - - link = lalloc(sizeof(PCLink)); - link->block = block28; - link->nextLink = block29->successors; - block29->successors = link; - - for (link = block28->successors; link; link = link->nextLink) { - if (link->block == block28) - link->block = block29; - } - for (link = block28->predecessors; link; link = link->nextLink) { - if (link->block == block28) - link->block = block29; - } - - bitvectorsetbit(block29->blockIndex, loop->vec2C); - addblocktoloop(loop, block29); - } - } - } else { - for (block = pcbasicblocks; block; block = block->nextBlock) { - if (bitvectorgetbit(block->blockIndex, loop->memberblocks)) - break; - } - insertpreheaderbefore(preheader, block); - } - - link = lalloc(sizeof(PCLink)); - link->block = preheader; - link->nextLink = block28->predecessors; - block28->predecessors = link; - - link = lalloc(sizeof(PCLink)); - link->block = block28; - link->nextLink = preheader->successors; - preheader->successors = link; - - for (loop = loop->parent; loop; loop = loop->parent) { - addblocktoloop(loop, preheader); - if (bitvectorgetbit(block28->blockIndex, loop->vec28)) { - bitvectorsetbit(preheader->blockIndex, loop->vec28); - if (block29) - bitvectorsetbit(block29->blockIndex, loop->vec28); - } - if (bitvectorgetbit(block28->blockIndex, loop->vec2C)) { - bitvectorsetbit(preheader->blockIndex, loop->vec2C); - if (block29) - bitvectorsetbit(block29->blockIndex, loop->vec2C); - } - } -} - -static void insertpreheaderblocks(Loop *loop) { - while (loop) { - if (loop->children) - insertpreheaderblocks(loop->children); - insertpreheaderblock(loop); - loop = loop->nextSibling; - } -} - -void findloopsinflowgraph(void) { - loopsinflowgraph = NULL; - computedominators(); - if (findloopheaders()) { - findnaturalloops(); - insertpreheaderblocks(loopsinflowgraph); - } - freeoheap(); -} - -static int checklooplimits(SInt32 opcode, SInt32 condition, SInt32 c, SInt32 d, SInt32 addend, SInt32 *result) { - if (opcode == PC_BT) { - if (condition == 0) { - if (addend <= 0) - return 0; - if (c < d) - *result = (d - c + addend - 1) / addend; - else - *result = 0; - } else if (condition == 1) { - if (addend >= 0) - return 0; - if (c > d) - *result = (c - d - addend - 1) / -addend; - else - *result = 0; - } else { - return 0; - } - } else { - if (condition == 0) { - if (addend >= 0) - return 0; - if (c >= d) - *result = (c - d - addend) / -addend; - else - *result = 0; - } else if (condition == 1) { - if (addend <= 0) - return 0; - if (c <= d) - *result = (d - c + addend) / addend; - else - *result = 0; - } else if (c < d) { - if (addend <= 0) - return 0; - if ((d - c) % addend) - return 0; - *result = (d - c) / addend; - } else if (c > d) { - if (addend >= 0) - return 0; - if ((c - d) % -addend) - return 0; - *result = (c - d) / -addend; - } else { - *result = 0; - } - } - - return 1; -} - -static int checkunsignedlooplimits(SInt32 opcode, SInt32 condition, UInt32 c, UInt32 d, SInt32 addend, UInt32 *result) { - if (opcode == PC_BT) { - if (condition == 0) { - if (addend <= 0) - return 0; - if (c < d) - *result = (d - c + addend - 1) / addend; - else - *result = 0; - } else if (condition == 1) { - if (addend >= 0) - return 0; - if (c > d) - *result = (c - d - addend - 1) / -addend; - else - *result = 0; - } else { - return 0; - } - } else { - if (condition == 0) { - if (addend >= 0) - return 0; - if (c >= d) - *result = (c - d - addend) / -addend; - else - *result = 0; - } else if (condition == 1) { - if (addend <= 0) - return 0; - if (c <= d) - *result = (d - c + addend) / addend; - else - *result = 0; - } else if (c < d) { - if (addend <= 0) - return 0; - if ((d - c) % addend) - return 0; - *result = (d - c) / addend; - } else if (c > d) { - if (addend >= 0) - return 0; - if ((c - d) % -addend) - return 0; - *result = (c - d) / -addend; - } else { - *result = 0; - } - } - - return (*result & 0x80000000) == 0; -} - -static int checkunknownloop(int a, int b, int c, unsigned char *op) { - if (a == PC_BT) { - if (b == 0) { - if (c <= 0) - return 0; - *op = ELESS; - } else if (b == 1) { - if (c >= 0) - return 0; - *op = EGREATER; - } else { - return 0; - } - } else { - if (b == 0) { - if (c >= 0) - return 0; - *op = EGREATEREQU; - } else if (b == 1) { - if (c <= 0) - return 0; - *op = ELESSEQU; - } else if (c == 1) { - *op = ENOTEQU; - } else if (c == -1) { - *op = ENOTEQU; - } else { - return 0; - } - } - - return 1; -} - -static void checkcountingloop(Loop *loop) { - RegUseOrDef *list; - PCode *lastpcode; - PCode *prevpcode; - PCode *pc8; - PCode *check; - short op12; - short reg11; - SInt16 reg4; - short reg11b; - Loop *child; - - if (!(lastpcode = loop->body->lastPCode)) - return; - if (lastpcode->op != PC_BT && lastpcode->op != PC_BF) - return; - if (lastpcode->args[2].kind != PCOp_LABEL) - return; - - if (!bitvectorgetbit(lastpcode->args[2].data.label.label->block->blockIndex, loop->memberblocks)) - return; - if (bitvectorgetbit(loop->body->nextBlock->blockIndex, loop->memberblocks)) - return; - - reg11 = lastpcode->args[0].data.reg.reg; - reg4 = lastpcode->args[1].data.imm.value; - prevpcode = lastpcode->prevPCode; - if (!prevpcode) - return; - - op12 = prevpcode->op; - if (op12 == PC_ADDI && prevpcode->args[2].kind == PCOp_IMMEDIATE) { - pc8 = prevpcode; - prevpcode = prevpcode->prevPCode; - if (!prevpcode) - return; - - op12 = prevpcode->op; - if (pc8->args[0].data.reg.reg != pc8->args[1].data.reg.reg) - return; - if (op12 != PC_CMP && op12 != PC_CMPL && op12 != PC_CMPI && op12 != PC_CMPLI) - return; - if (prevpcode->args[1].data.reg.reg != pc8->args[0].data.reg.reg) - return; - if ((loop->step = pc8->args[2].data.imm.value) == 0) - return; - } - - if (op12 != PC_CMP && op12 != PC_CMPL && op12 != PC_CMPI && op12 != PC_CMPLI) - return; - - if (prevpcode->args[0].data.reg.reg != reg11) - return; - - reg11b = prevpcode->args[1].data.reg.reg; - if (reg11b < 32) - return; - - if (loop->preheader->nextBlock != lastpcode->args[2].data.label.label->block) - return; - - if (op12 == PC_CMPI) { - if (prevpcode->prevPCode) - return; - loop->upper = prevpcode->args[2].data.imm.value; - loop->upperType = LOOP_BOUND_CONSTANT; - } else if (op12 == PC_CMPLI) { - if (prevpcode->prevPCode) - return; - loop->upper = prevpcode->args[2].data.imm.value & 0xFFFF; - loop->upperType = LOOP_BOUND_CONSTANT; - } else if (op12 == PC_CMP || op12 == PC_CMPL) { - if (prevpcode->prevPCode) { - if ( - prevpcode->prevPCode->op == PC_LI && - prevpcode->prevPCode->args[1].kind == PCOp_IMMEDIATE && - prevpcode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg && - !prevpcode->prevPCode->prevPCode - ) { - loop->upper = prevpcode->prevPCode->args[1].data.imm.value; - loop->upperType = LOOP_BOUND_CONSTANT; - } else if ( - prevpcode->prevPCode->op == PC_LIS && - prevpcode->prevPCode->args[1].kind == PCOp_IMMEDIATE && - prevpcode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg && - !prevpcode->prevPCode->prevPCode - ) { - loop->upper = prevpcode->prevPCode->args[1].data.imm.value << 16; - loop->upperType = LOOP_BOUND_CONSTANT; - } else if ( - prevpcode->prevPCode->op == PC_ADDI && - prevpcode->prevPCode->args[2].kind == PCOp_IMMEDIATE && - prevpcode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg && - prevpcode->prevPCode->args[1].data.reg.reg == prevpcode->args[2].data.reg.reg && - prevpcode->prevPCode->prevPCode && - prevpcode->prevPCode->prevPCode->op == PC_LIS && - prevpcode->prevPCode->prevPCode->args[1].kind == PCOp_IMMEDIATE && - prevpcode->prevPCode->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg && - !prevpcode->prevPCode->prevPCode->prevPCode - ) { - loop->upper = prevpcode->prevPCode->args[2].data.imm.value + - (prevpcode->prevPCode->prevPCode->args[1].data.imm.value << 16); - loop->upperType = LOOP_BOUND_CONSTANT; - } else { - return; - } - } else { - pc8 = NULL; - for (list = reg_Defs[RegClass_GPR][prevpcode->args[2].data.reg.reg]; list; list = list->next) { - if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks)) - return; - } - for (list = reg_Defs[RegClass_GPR][prevpcode->args[2].data.reg.reg]; list; list = list->next) { - if (bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].defvec8)) { - if (!pc8) { - pc8 = Defs[list->id].pcode; - if ( - pc8->op == PC_LI && - pc8->args[1].kind == PCOp_IMMEDIATE - ) { - loop->upper = pc8->args[1].data.imm.value; - loop->upperType = LOOP_BOUND_CONSTANT; - } else if ( - pc8->op == PC_LIS && - pc8->args[1].kind == PCOp_IMMEDIATE - ) { - loop->upper = pc8->args[1].data.imm.value << 16; - loop->upperType = LOOP_BOUND_CONSTANT; - } else if ( - pc8->op == PC_ADDI && - pc8->args[2].kind == PCOp_IMMEDIATE && - pc8->args[1].data.reg.reg == prevpcode->args[2].data.reg.reg && - pc8->prevPCode && - pc8->prevPCode->op == PC_LIS && - pc8->prevPCode->args[1].kind == PCOp_IMMEDIATE && - pc8->prevPCode->args[0].data.reg.reg == prevpcode->args[2].data.reg.reg - ) { - loop->upper = pc8->args[2].data.imm.value + - (pc8->prevPCode->args[1].data.imm.value << 16); - loop->upperType = LOOP_BOUND_CONSTANT; - } else { - loop->upperType = LOOP_BOUND_VARIABLE; - break; - } - } else { - loop->upperType = LOOP_BOUND_VARIABLE; - break; - } - } - } - - if (loop->upperType == LOOP_BOUND_INDETERMINATE) - loop->upperType = LOOP_BOUND_VARIABLE; - } - } - - pc8 = NULL; - - for (list = reg_Defs[RegClass_GPR][reg11b]; list; list = list->next) { - check = Defs[list->id].pcode; - if (bitvectorgetbit(check->block->blockIndex, loop->memberblocks)) { - if (!pc8) { - pc8 = check; - if (check->op != PC_ADDI) - return; - if (check->args[1].data.reg.reg != reg11b) - return; - if (check->args[2].kind != PCOp_IMMEDIATE) - return; - if ((loop->step = check->args[2].data.imm.value) == 0) - return; - } else { - return; - } - } - } - - if (!pc8) - return; - - if (pc8->block != prevpcode->block && !bitvectorgetbit(prevpcode->block->blockIndex, loop->vec2C)) - return; - - if (loop->children) { - for (child = loop->children; child; child = child->nextSibling) { - if (bitvectorgetbit(pc8->block->blockIndex, child->memberblocks)) - return; - } - } - - loop->pc18 = pc8; - - pc8 = NULL; - - for (list = reg_Defs[RegClass_GPR][reg11b]; list; list = list->next) { - if (bitvectorgetbit(list->id, usedefinfo[loop->preheader->blockIndex].defvec8)) { - if (!pc8) { - pc8 = Defs[list->id].pcode; - if ( - pc8->op == PC_LI && - pc8->args[1].kind == PCOp_IMMEDIATE - ) { - loop->lower = pc8->args[1].data.imm.value; - loop->lowerType = LOOP_BOUND_CONSTANT; - } else if ( - pc8->op == PC_LIS && - pc8->args[1].kind == PCOp_IMMEDIATE - ) { - loop->lower = pc8->args[1].data.imm.value << 16; - loop->lowerType = LOOP_BOUND_CONSTANT; - } else if ( - pc8->op == PC_ADDI && - pc8->args[2].kind == PCOp_IMMEDIATE && - pc8->args[1].data.reg.reg == reg11b && - pc8->prevPCode && - pc8->prevPCode->op == PC_LIS && - pc8->prevPCode->args[1].kind == PCOp_IMMEDIATE && - pc8->prevPCode->args[0].data.reg.reg == reg11b - ) { - loop->lower = pc8->args[2].data.imm.value + - (pc8->prevPCode->args[1].data.imm.value << 16); - loop->lowerType = LOOP_BOUND_CONSTANT; - } else { - loop->lowerType = LOOP_BOUND_VARIABLE; - break; - } - } else { - loop->lowerType = LOOP_BOUND_INDETERMINATE; - break; - } - } - } - - if (loop->lowerType == LOOP_BOUND_INDETERMINATE) - loop->lowerType = LOOP_BOUND_VARIABLE; - - if (loop->lowerType == LOOP_BOUND_CONSTANT && loop->upperType == LOOP_BOUND_CONSTANT) { - if (op12 == PC_CMP || op12 == PC_CMPI) { - if (!checklooplimits(lastpcode->op, reg4, loop->lower, loop->upper, loop->step, &loop->iterationCount)) - return; - } else { - if (!checkunsignedlooplimits(lastpcode->op, reg4, loop->lower, loop->upper, loop->step, (UInt32 *) &loop->iterationCount)) - return; - } - loop->isKnownCountingLoop = 1; - } else if (loop->lowerType != LOOP_BOUND_INDETERMINATE || loop->upperType != LOOP_BOUND_INDETERMINATE) { - if (!checkunknownloop(lastpcode->op, reg4, loop->step, &loop->unknownCondition)) - return; - loop->isUnknownCountingLoop = 1; - } -} - -void analyzeForCountableLoops(Loop *loop) { - if (!loop) - return; - - while (loop) { - if (loop->children) - analyzeForCountableLoops(loop->children); - checkcountingloop(loop); - loop = loop->nextSibling; - } -} - -void analyzeloop(Loop *loop) { - BlockList *list; - PCodeBlock *block; - PCode *pcode; - - loop->bodySize = 0; - loop->x4D = 0; - loop->x4E = 0; - loop->x4F = 1; - loop->isKnownCountingLoop = 0; - loop->isUnknownCountingLoop = 0; - loop->lowerType = LOOP_BOUND_INDETERMINATE; - loop->upperType = LOOP_BOUND_INDETERMINATE; - loop->iterationCount = -1; - loop->x57 = 0; - loop->x52 = 0; - - for (list = loop->blocks; list; list = list->next) { - block = list->block; - if (!loop->children) - block->flags |= fPCBlockFlag2000; - loop->bodySize += block->pcodeCount; - - if (block != loop->body) { - if (!block->successors || !block->predecessors || block->successors->nextLink || block->predecessors->nextLink) - loop->x4F = 0; - } - - if ((block->flags & fPCBlockFlag4000) == fPCBlockFlag4000) - loop->x52 = 1; - - for (pcode = block->firstPCode; pcode; pcode = pcode->nextPCode) { - if (PCODE_FLAG_SET_T(pcode) & fLink) - loop->x4D = 1; - - if (pcode->op == PC_BCTRL || pcode->op == PC_BCTR || pcode->op == PC_BCCTR || pcode->op == PC_MTCTR || pcode->op == PC_MFCTR) { - loop->x4E = 1; - } else if (pcode->flags & fIsRead) { - if (pcode->op == PC_LBZX || pcode->op == PC_LHZX || pcode->op == PC_LHAX || pcode->op == PC_LWZX || pcode->op == PC_LFSX || pcode->op == PC_LFDX) - loop->x53 = 1; - } else if (pcode->flags & fIsWrite) { - if (pcode->op == PC_STBX || pcode->op == PC_STHX || pcode->op == PC_STWX || pcode->op == PC_STFSX || pcode->op == PC_STFDX) - loop->x54 = 1; - } else { - if (pcode->op == PC_EIEIO || pcode->op == PC_SYNC || pcode->op == PC_ISYNC) - loop->x57 = 1; - } - } - } - - if (!loop->children && !loop->x4D && loop->bodySize < 32) { - for (list = loop->blocks; list; list = list->next) - list->block->flags |= fPCBlockFlag2000; - } -} - -static void analyzeloops(Loop *loop) { - while (loop) { - if (loop->children) - analyzeloops(loop->children); - analyzeloop(loop); - loop = loop->nextSibling; - } -} - -void analyzeloopsinflowgraph(void) { - if (loopsinflowgraph) - analyzeloops(loopsinflowgraph); -} diff --git a/compiler_and_linker/unsorted/LoopOptimization.c b/compiler_and_linker/unsorted/LoopOptimization.c deleted file mode 100644 index b2aef1e..0000000 --- a/compiler_and_linker/unsorted/LoopOptimization.c +++ /dev/null @@ -1,1553 +0,0 @@ -#include "compiler/LoopOptimization.h" -#include "compiler/CFunc.h" -#include "compiler/CParser.h" -#include "compiler/BitVectors.h" -#include "compiler/CompilerTools.h" -#include "compiler/LoopDetection.h" -#include "compiler/PCode.h" -#include "compiler/Registers.h" -#include "compiler/UseDefChains.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -int optimizedloops; -int optimizedloop_full_unroll; -int optimizedloop_trans_regs; -static UInt32 *liveonexit; -static UInt32 *inductionvariables; -static int last_virtual_GPR; - -static int ispowerof2(SInt32 value) { - int bit = getbit(value); - return (bit > 0 && bit < 31) ? bit : 0; -} - -static void insertupdateinstructions(Loop *loop) { - // nothing -} - -static void computeliveonexit(Loop *loop) { - UInt32 *usevec; - UInt32 *defvec; - BlockList *blocklist; - RegUseOrDef *list; - int gpr; - - bitvectorinitialize(usevec = oalloc(4 * ((number_of_Uses + 31) >> 5)), number_of_Uses, 0); - for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { - if (bitvectorgetbit(blocklist->block->blockIndex, loop->vec24)) - bitvectorunion(usevec, usedefinfo[blocklist->block->blockIndex].usevec1C, number_of_Uses); - } - - bitvectorinitialize(defvec = oalloc(4 * ((number_of_Defs + 31) >> 5)), number_of_Defs, 0); - if (loop->preheader) - bitvectorunion(defvec, usedefinfo[loop->preheader->blockIndex].defvec8, number_of_Defs); - - bitvectorinitialize(liveonexit, last_virtual_GPR, 0); - - for (gpr = 32; gpr < last_virtual_GPR; gpr++) { - for (list = reg_Defs[RegClass_GPR][gpr]; list; list = list->next) { - if (bitvectorgetbit(list->id, defvec)) { - if (!Defs[list->id].pcode->block || bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks)) { - bitvectorsetbit(gpr, liveonexit); - break; - } - } - } - - for (list = reg_Uses[RegClass_GPR][gpr]; list; list = list->next) { - if (bitvectorgetbit(list->id, usevec)) { - if (!Uses[list->id].pcode->block || !bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks)) { - bitvectorsetbit(gpr, liveonexit); - break; - } - } - } - } -} - -static void eliminateinductionvariables(Loop *loop) { - BlockList *blocklist; - PCode *instr; - PCode *nextInstr; - PCodeArg *op; - int i; - - bitvectorinitialize(inductionvariables, last_virtual_GPR, 0xFFFFFFFF); - - for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { - for (instr = blocklist->block->firstPCode; instr; instr = instr->nextPCode) { - if ( - instr->op != PC_ADDI || - instr->args[0].data.reg.reg < 32 || - instr->args[0].data.reg.reg >= last_virtual_GPR || - instr->args[1].data.reg.reg != instr->args[0].data.reg.reg - ) { - op = instr->args; - i = instr->argCount; - while (i--) { - if ( - op->kind == PCOp_REGISTER && - op->arg == RegClass_GPR && - op->data.reg.reg >= n_real_registers[RegClass_GPR] && - op->data.reg.reg < last_virtual_GPR - ) - bitvectorclearbit(op->data.reg.reg, inductionvariables); - op++; - } - } - } - } - - if (loop->parent) { - for (instr = loop->preheader->firstPCode; instr; instr = nextInstr) { - nextInstr = instr->nextPCode; - op = instr->args; - i = instr->argCount; - while (i--) { - if ( - op->kind == PCOp_REGISTER && - op->arg == RegClass_GPR && - op->data.reg.reg >= n_real_registers[RegClass_GPR] && - op->data.reg.reg < last_virtual_GPR - ) - bitvectorsetbit(op->data.reg.reg, liveonexit); - op++; - } - } - } - - for (blocklist = loop->blocks; blocklist; blocklist = blocklist->next) { - for (instr = blocklist->block->firstPCode; instr; instr = nextInstr) { - nextInstr = instr->nextPCode; - if ( - instr->op == PC_ADDI && - instr->args[0].data.reg.reg >= 32 && - instr->args[0].data.reg.reg < last_virtual_GPR && - instr->args[1].data.reg.reg == instr->args[0].data.reg.reg && - bitvectorgetbit(instr->args[0].data.reg.reg, inductionvariables) && - !bitvectorgetbit(instr->args[0].data.reg.reg, liveonexit) - ) { - deletepcode(instr); - optimizedloops = 1; - } - } - } -} - -static void skiplooptest(Loop *loop) { - PCodeBlock *preheader; - PCodeLabel *label; - PCLink **ptr; - PCLink *link; - PCode *lastInstr; - PCode *instr; - - preheader = loop->preheader; - lastInstr = loop->body->lastPCode; - CError_ASSERT(340, lastInstr->args[2].kind == PCOp_LABEL); - - label = lastInstr->args[2].data.label.label; - preheader->lastPCode->args[0].data.label.label = label; - preheader->successors->block = label->block; - - ptr = &loop->body->predecessors; - while ((link = *ptr)) { - if (link->block == preheader) { - *ptr = link->nextLink; - break; - } - ptr = &link->nextLink; - } - - link->nextLink = label->block->predecessors; - label->block->predecessors = link; - - while (1) { - instr = loop->body->firstPCode; - CError_ASSERT(369, instr); - - if (instr->op == PC_CMP || instr->op == PC_CMPI || instr->op == PC_CMPLI || instr->op == PC_CMPL) - break; - - deletepcode(instr); - insertpcodebefore(loop->preheader->lastPCode, instr); - loop->bodySize--; - } - - for (instr = instr->nextPCode; instr && !(instr->flags & fIsBranch); instr = instr->nextPCode) - insertpcodebefore(loop->preheader->lastPCode, copypcode(instr)); -} - -static void unrollloop(Loop *loop) { - PCodeBlock *newBlock; - int i; - int factor; - PCode *instr; - PCodeBlock *block; - PCode *firstInstr; - PCode *nextInstr; - - for (factor = copts.unroll_factor_limit; factor > 1; factor--) { - if ((loop->iterationCount % factor) == 0 && (loop->bodySize - 2) * factor <= copts.unroll_instr_limit) - break; - } - - if (factor == 1) - return; - if ((loop->iterationCount / factor) != 1 && loop->bodySize < 4) - return; - - newBlock = oalloc(sizeof(PCodeBlock)); - newBlock->firstPCode = newBlock->lastPCode = NULL; - for (i = 0; i < factor - 1; i++) { - firstInstr = loop->body->firstPCode; - CError_ASSERT(448, firstInstr); - if (firstInstr->op != PC_CMP && firstInstr->op != PC_CMPL && firstInstr->op != PC_CMPI && firstInstr->op != PC_CMPLI) - CError_FATAL(450); - - for (instr = firstInstr->nextPCode; instr && !(instr->flags & fIsBranch); instr = instr->nextPCode) - appendpcode(newBlock, copypcode(instr)); - - for (block = loop->preheader->successors->block; block != loop->body; block = block->successors->block) { - for (instr = block->firstPCode; instr; instr = instr->nextPCode) { - if (instr->op != PC_B) - appendpcode(newBlock, copypcode(instr)); - } - } - } - - block = loop->body->predecessors->block; - for (instr = newBlock->firstPCode; instr; instr = nextInstr) { - nextInstr = instr->nextPCode; - appendpcode(block, instr); - } - loop->iterationCount /= factor; -} - -void pccomputepredecessors1(PCodeBlock *block) { - PCLink *succ; - PCLink *pred; - - for (succ = block->successors; succ; succ = succ->nextLink) { - if (!succ->block) { - CError_FATAL(496); - } else { - for (pred = succ->block->predecessors; pred; pred = pred->nextLink) { - if (pred->block == block) - break; - } - - if (!pred) { - pred = lalloc(sizeof(PCLink)); - pred->block = block; - pred->nextLink = succ->block->predecessors; - succ->block->predecessors = pred; - } - } - } -} - -static PCodeBlock *insertnewpcblock(PCodeBlock *block, int loopWeight) { - PCodeBlock *newBlock; - PCodeBlock *nextBlock; - PCodeLabel *label; - PCLink *prev; - PCLink *link; - - label = makepclabel(); - newBlock = lalloc(sizeof(PCodeBlock)); - - nextBlock = block->nextBlock; - newBlock->nextBlock = nextBlock; - block->nextBlock = newBlock; - - newBlock->prevBlock = block; - nextBlock->prevBlock = newBlock; - - newBlock->labels = NULL; - newBlock->predecessors = newBlock->successors = NULL; - newBlock->firstPCode = newBlock->lastPCode = NULL; - newBlock->pcodeCount = 0; - newBlock->loopWeight = loopWeight; - newBlock->flags = 0; - newBlock->blockIndex = pcblockcount++; - pclabel(newBlock, label); - - prev = NULL; - for (link = block->successors; link; link = link->nextLink) { - if (link->block == nextBlock) { - if (!prev) - block->successors = link->nextLink; - else - prev->nextLink = link->nextLink; - link->nextLink = NULL; - newBlock->successors = link; - break; - } - prev = link; - } - - prev = NULL; - for (link = nextBlock->predecessors; link; link = link->nextLink) { - if (link->block == block) { - if (!prev) - nextBlock->predecessors = link->nextLink; - else - prev->nextLink = link->nextLink; - link->nextLink = NULL; - newBlock->predecessors = link; - break; - } - prev = link; - } - - link = lalloc(sizeof(PCLink)); - link->block = newBlock; - link->nextLink = block->successors; - block->successors = link; - - link = lalloc(sizeof(PCLink)); - link->block = newBlock; - link->nextLink = nextBlock->predecessors; - nextBlock->predecessors = link; - - return newBlock; -} - -static void unrollloopconditional(Loop *loop) { - PCodeBlock *lastBlock; - PCodeLabel *label24; - PCode *instr; - PCode *instrCopy; - int outputBlockCount; - int inputBlockCount; - PCodeBlock **blocks; - PCodeBlock **blocks2; - PCodeBlock **blocks3; - PCode *firstInstr; - int factor; - PCodeBlock *block; - PCLink *link; - PCLink *prev; - int i; - int j; - int k; - int instructionCount; - - label24 = NULL; - outputBlockCount = 0; - instructionCount = 0; - - for (factor = copts.unroll_factor_limit; factor > 1; factor--) { - if ((loop->iterationCount % factor) == 0 && (loop->bodySize - 2) * factor <= copts.unroll_instr_limit) - break; - } - - if (factor == 1) - return; - - inputBlockCount = 0; - for (block = loop->preheader->successors->block; block != loop->body; block = block->nextBlock) { - inputBlockCount++; - if (!bitvectorgetbit(block->blockIndex, loop->memberblocks)) - instructionCount += block->pcodeCount; - } - - if ((loop->bodySize - instructionCount - 2) < instructionCount || instructionCount > 8) - return; - - blocks = oalloc(inputBlockCount * sizeof(PCodeBlock *)); - blocks2 = oalloc(inputBlockCount * sizeof(PCodeBlock *)); - blocks3 = oalloc(factor * (inputBlockCount * sizeof(PCodeBlock *))); - memclrw(blocks, inputBlockCount * sizeof(PCodeBlock *)); - memclrw(blocks2, inputBlockCount * sizeof(PCodeBlock *)); - memclrw(blocks3, factor * (inputBlockCount * sizeof(PCodeBlock *))); - - block = loop->preheader->nextBlock; - for (i = 0; i < inputBlockCount; i++) { - blocks[i] = block; - block = block->nextBlock; - } - - lastBlock = blocks[inputBlockCount - 1]; - for (i = 0; i < factor - 1; i++) { - for (j = 0; j < inputBlockCount; j++) { - blocks2[j] = insertnewpcblock(lastBlock, loop->loopWeight); - blocks3[outputBlockCount++] = blocks2[j]; - lastBlock = blocks2[j]; - } - if (label24) { - pclabel(blocks2[0], label24); - label24 = NULL; - } - - for (j = 0; j < inputBlockCount; j++) { - for (instr = blocks[j]->firstPCode; instr; instr = instr->nextPCode) { - if (instr->flags & fIsBranch) { - PCodeArg *op; - int opID; - instrCopy = copypcode(instr); - op = NULL; - for (opID = 0; opID < instr->argCount; opID++) { - if (instr->args[opID].kind == PCOp_LABEL) { - op = &instr->args[opID]; - break; - } - } - - if (op) { - if (op->data.label.label->block == loop->body) { - if (!label24) - label24 = makepclabel(); - instrCopy->args[opID].data.label.label = label24; - } else { - for (k = 0; k < inputBlockCount; k++) { - if (op->data.label.label->block == blocks[k]) { - instrCopy->args[opID].data.label.label = blocks2[k]->labels; - break; - } - } - } - } - - appendpcode(blocks2[j], instrCopy); - if (op) - pcbranch(blocks2[j], instrCopy->args[opID].data.label.label); - } else { - appendpcode(blocks2[j], copypcode(instr)); - } - } - } - - firstInstr = loop->body->firstPCode; - CError_ASSERT(762, firstInstr != NULL); - if (firstInstr->op != PC_CMP && firstInstr->op != PC_CMPL && firstInstr->op != PC_CMPI && firstInstr->op != PC_CMPLI) - CError_FATAL(764); - - for (instr = firstInstr->nextPCode; instr && !(instr->flags & fIsBranch); instr = instr->nextPCode) - appendpcode(blocks2[inputBlockCount - 1], copypcode(instr)); - - for (j = 0; j < inputBlockCount; j++) { - for (link = blocks[j]->successors; link; link = link->nextLink) { - if (link->block == blocks[j]->nextBlock) - break; - } - - if (!link) { - for (link = blocks2[j]->successors, prev = NULL; link; link = link->nextLink) { - if (link->block == blocks2[j]->nextBlock) { - if (prev) - prev->nextLink = link->nextLink; - else - blocks2[j]->successors = link->nextLink; - } else { - prev = link; - } - } - - for (link = blocks2[j]->nextBlock->predecessors, prev = NULL; link; link = link->nextLink) { - if (link->block == blocks2[j]) { - if (prev) - prev->nextLink = link->nextLink; - else - blocks2[j]->nextBlock->predecessors = link->nextLink; - } else { - prev = link; - } - } - } - } - } - - if (label24) - pclabel(loop->body, label24); - - for (i = 0; i < inputBlockCount; i++) { - for (instr = blocks[i]->firstPCode; instr; instr = instr->nextPCode) { - if (instr->flags & fIsBranch) { - PCodeArg *op; - int opID; - op = NULL; - for (opID = 0; opID < instr->argCount; opID++) { - if (instr->args[opID].kind == PCOp_LABEL) { - op = &instr->args[opID]; - break; - } - } - - if (op && op->data.label.label->block == loop->body) { - instr->args[opID].data.label.label = blocks3[0]->labels; - - for (link = blocks[i]->successors, prev = NULL; link; link = link->nextLink) { - if (link->block == loop->body) { - if (prev) - prev->nextLink = link->nextLink; - else - blocks[i]->successors = link->nextLink; - } else { - prev = link; - } - } - - for (link = loop->body->predecessors, prev = NULL; link; link = link->nextLink) { - if (link->block == blocks[i]) { - if (prev) - prev->nextLink = link->nextLink; - else - loop->body->predecessors = link->nextLink; - } else { - prev = link; - } - } - - link = blocks[i]->successors; - while (link && link->block != blocks3[0]) - link = link->nextLink; - - if (!link) { - pcbranch(blocks[i], op->data.label.label); - pccomputepredecessors1(blocks[i]); - } - } - } - } - } - - for (i = 0; i < outputBlockCount; i++) - pccomputepredecessors1(blocks3[i]); - - loop->iterationCount /= factor; -} - -static void unrollunknownBDNZ(Loop *loop) { - int factor; // r29 - PCodeBlock *preheader; // r17 - PCodeBlock *blockA; // r23 - PCodeBlock *postheader; // r22 - PCodeBlock *newblock1; // r26 - PCodeBlock *newblock2; // r31 - PCodeBlock *newblock3; // r19 - PCodeBlock *newblock4; // r20 - PCodeBlock *newblock5; // r24 - PCode *mtctr; // r21 - int mtctr_reg; // r27 - PCode *instr28; // r28 - PCode *instr6; // r6 - PCodeBlock *block; - PCode *instr; - PCodeArg *op; - int i; - int val; - short mtctr_shifted_reg; // r16 - short reg25; // r25 - PCLink *link; - - if (loop->bodySize < 4) - return; - - factor = 128; - while (factor > copts.unroll_factor_limit) - factor >>= 1; - while (factor > 1 && (loop->bodySize - 2) * factor > copts.unroll_instr_limit) - factor >>= 1; - - if (factor < 2) - return; - - preheader = loop->preheader; - blockA = loop->body->nextBlock; - postheader = preheader->nextBlock; - - newblock1 = insertnewpcblock(preheader, loop->loopWeight); - newblock2 = insertnewpcblock(newblock1, loop->loopWeight); - newblock3 = insertnewpcblock(newblock2, loop->loopWeight); - newblock4 = insertnewpcblock(newblock3, loop->loopWeight); - newblock5 = insertnewpcblock(newblock4, loop->loopWeight); - addblocktoloop(loop, newblock1); - addblocktoloop(loop, newblock2); - addblocktoloop(loop, newblock3); - addblocktoloop(loop, newblock4); - addblocktoloop(loop, newblock5); - - for (instr = preheader->lastPCode; instr; instr = instr->prevPCode) { - if (instr->op == PC_MTCTR) { - mtctr = instr; - mtctr_reg = instr->args[0].data.reg.reg; - } - } - - if (!mtctr) - return; - - instr28 = NULL; - for (block = postheader; block != loop->body; block = block->successors->block) { - for (instr = block->firstPCode; instr; instr = instr->nextPCode) { - if (instr->op != PC_B) { - appendpcode(newblock2, copypcode(instr)); - if (instr == loop->pc18) - instr28 = newblock2->lastPCode; - } - } - } - - if (!instr28) { - appendpcode(newblock2, copypcode(loop->pc18)); - instr28 = newblock2->lastPCode; - } - - instr6 = NULL; - for (instr = newblock2->firstPCode; instr; instr = instr->nextPCode) { - if (instr != instr28) { - op = instr->args; - i = instr->argCount; - while (i--) { - if ( - op->kind == PCOp_REGISTER && - op->arg == RegClass_GPR && - op->data.reg.reg == loop->pc18->args[0].data.reg.reg && - (op->data.reg.effect & (EffectRead | EffectWrite)) - ) { - instr6 = instr; - break; - } - op++; - } - } - if (instr6) - break; - } - - if (!instr6) { - deletepcode(instr28); - deletepcode(loop->pc18); - if (loop->footer) - blockA = loop->footer; - else - blockA = insertnewpcblock(loop->body, loop->loopWeight); - } else { - instr28 = NULL; - } - - for (i = 1; i < factor; i++) { - for (block = postheader; block != loop->body; block = block->successors->block) { - for (instr = block->firstPCode; instr; instr = instr->nextPCode) { - if (instr->op != PC_B) - appendpcode(newblock2, copypcode(instr)); - } - } - } - - mtctr_shifted_reg = used_virtual_registers[RegClass_GPR]++; - appendpcode(newblock1, makepcode( - PC_RLWINM, - mtctr_shifted_reg, - mtctr_reg, - 32 - ispowerof2(factor), - ispowerof2(factor), - 31)); - - appendpcode(newblock1, makepcode(PC_CMPLI, 0, mtctr_shifted_reg, 0)); - - if (instr28) { - reg25 = used_virtual_registers[RegClass_GPR]++; - if (loop->step == 1) { - instr = makepcode(PC_MR, reg25, mtctr_reg); - } else if (loop->step == -1) { - instr = makepcode(PC_NEG, reg25, mtctr_reg); - } else { - val = ispowerof2(abs(loop->step)); - if (val > 0) { - instr = makepcode(PC_RLWINM, reg25, mtctr_reg, val, 0, 31 - val); - if (loop->step < 0) { - appendpcode(newblock1, instr); - instr = makepcode(PC_NEG, reg25, reg25); - } - } else { - instr = makepcode(PC_MULLI, reg25, mtctr_reg, loop->step); - } - } - appendpcode(newblock1, instr); - } - - appendpcode(newblock1, makepcode(PC_MTCTR, mtctr_shifted_reg)); - appendpcode(newblock1, makepcode(PC_BT, 0, 2, newblock5->labels)); - pcbranch(newblock1, newblock5->labels); - - link = lalloc(sizeof(PCLink)); - link->block = newblock1; - link->nextLink = newblock5->predecessors; - newblock5->predecessors = link; - - appendpcode(newblock3, makepcode(PC_BDNZ, newblock2->labels)); - pcbranch(newblock3, newblock2->labels); - - link = lalloc(sizeof(PCLink)); - link->block = newblock3; - link->nextLink = newblock2->predecessors; - newblock2->predecessors = link; - - appendpcode(newblock4, makepcode(PC_ANDI, mtctr_reg, mtctr_reg, factor - 1)); - appendpcode(newblock4, makepcode(PC_BT, 0, 2, blockA->labels)); - pcbranch(newblock4, blockA->labels); - - link = lalloc(sizeof(PCLink)); - link->block = newblock4; - link->nextLink = blockA->predecessors; - blockA->predecessors = link; - - deletepcode(mtctr); - appendpcode(newblock5, mtctr); - - if (instr28 && bitvectorgetbit(instr28->args[0].data.reg.reg, liveonexit)) { - instr = makepcode(PC_ADD, instr28->args[0].data.reg.reg, instr28->args[0].data.reg.reg, reg25); - if (blockA->firstPCode) - insertpcodebefore(blockA->firstPCode, instr); - else - appendpcode(blockA, instr); - } -} - -static void deleteloop(Loop *loop) { - PCodeBlock *body; - PCodeBlock *preheader; - PCodeBlock *nextblock; - PCodeLabel *label; - PCode *instr; - PCLink **ptr; - PCLink *link; - PCodeBlock *block; - - body = loop->body; - preheader = loop->preheader; - nextblock = body->nextBlock; - label = makepclabel(); - - while (1) { - instr = body->firstPCode; - CError_ASSERT(1294, instr != NULL); - - if (instr->op == PC_CMP || instr->op == PC_CMPI || instr->op == PC_CMPLI || instr->op == PC_CMPL) - break; - - deletepcode(instr); - insertpcodebefore(loop->preheader->lastPCode, instr); - loop->bodySize--; - } - - pclabel(nextblock, label); - preheader->lastPCode->args[0].data.label.label = label; - preheader->successors->block = nextblock; - - ptr = &nextblock->predecessors; - while ((link = *ptr)) { - if (link->block == body) { - link->block = preheader; - break; - } - ptr = &link->nextLink; - } - - block = pcbasicblocks; - while ((nextblock = block->nextBlock)) { - if (bitvectorgetbit(nextblock->blockIndex, loop->memberblocks)) - block->nextBlock = nextblock->nextBlock; - else - block = nextblock; - } -} - -static void deleteloopheader(Loop *loop) { - PCLink *link; - PCLink **ptr; - - ptr = &loop->body->successors; - while ((link = *ptr)) { - if (link->block == loop->body->lastPCode->args[2].data.label.label->block) { - *ptr = link->nextLink; - break; - } - ptr = &link->nextLink; - } - - ptr = &loop->body->lastPCode->args[2].data.label.label->block->predecessors; - while ((link = *ptr)) { - if (link->block == loop->body) { - *ptr = link->nextLink; - break; - } - ptr = &link->nextLink; - } - - deletepcode(loop->body->firstPCode); - deletepcode(loop->body->lastPCode); - optimizedloop_full_unroll = 1; -} - -static void rewriteloopwithBDNZ(Loop *loop) { - PCode *instr; - - if (!FITS_IN_SHORT(loop->iterationCount)) { - instr = makepcode(PC_LIS, used_virtual_registers[RegClass_GPR]++, 0, HIGH_PART(loop->iterationCount)); - insertpcodebefore(loop->preheader->lastPCode, instr); - - if (loop->iterationCount != 0) - insertpcodeafter(instr, makepcode(PC_ADDI, instr->args[0].data.reg.reg, instr->args[0].data.reg.reg, 0, LOW_PART(loop->iterationCount))); - } else { - instr = makepcode(PC_LI, used_virtual_registers[RegClass_GPR]++, loop->iterationCount); - insertpcodebefore(loop->preheader->lastPCode, instr); - } - - insertpcodebefore(loop->preheader->lastPCode, makepcode(PC_MTCTR, instr->args[0].data.reg.reg)); - - instr = makepcode(PC_BDNZ, loop->body->lastPCode->args[2].data.label.label); - deletepcode(loop->body->firstPCode); - deletepcode(loop->body->lastPCode); - appendpcode(loop->body, instr); - - for (loop = loop->parent; loop; loop = loop->parent) - loop->x4E = 1; -} - -static void rewriteunknownloopwithBDNZ(Loop *loop) { - SInt32 value1; // r24 - SInt32 value2; // r30 - Opcode branchOpcode; // r19 - SInt32 absStep; // r28 - int branchCondition; // r20 - int counterReg; // r27 - int reg1; // r26 - int reg2; // r22 - unsigned char mode; // r23 - PCodeBlock *afterLoop; // r25 - PCode *addiInstr; - PCode *instr; - PCLink *link; - PCLink **ptr; - - absStep = abs(loop->step); - afterLoop = NULL; - - for (addiInstr = loop->body->lastPCode->prevPCode; addiInstr->op == PC_ADDI; addiInstr = loop->body->lastPCode->prevPCode) { - deletepcode(addiInstr); - if (loop->body->lastPCode->args[2].data.label.label->block->firstPCode) - insertpcodebefore(loop->body->lastPCode->args[2].data.label.label->block->firstPCode, addiInstr); - else - appendpcode(loop->body->lastPCode->args[2].data.label.label->block, addiInstr); - - afterLoop = insertnewpcblock(loop->body, loop->loopWeight); - appendpcode(afterLoop, copypcode(addiInstr)); - loop->footer = afterLoop; - } - - if (loop->unknownCondition == ELESS) { - branchOpcode = PC_BF; - if (loop->lowerType == LOOP_BOUND_CONSTANT) { - branchCondition = 1; // GT - value1 = loop->lower; - reg1 = addiInstr->args[2].data.reg.reg; - value2 = absStep - 1 - loop->lower; - mode = 0; - } else if (loop->upperType == LOOP_BOUND_CONSTANT) { - branchCondition = 0; // LT - value1 = loop->upper; - reg1 = addiInstr->args[1].data.reg.reg; - value2 = absStep - 1 + loop->upper; - mode = 1; - } else { - branchCondition = 0; // LT - reg1 = addiInstr->args[1].data.reg.reg; - reg2 = addiInstr->args[2].data.reg.reg; - value2 = absStep - 1; - mode = 2; - } - } else if (loop->unknownCondition == ELESSEQU) { - branchOpcode = PC_BT; - if (loop->lowerType == LOOP_BOUND_CONSTANT) { - branchCondition = 0; // LT - value1 = loop->lower; - reg1 = addiInstr->args[2].data.reg.reg; - value2 = absStep - loop->lower; - mode = 0; - } else if (loop->upperType == LOOP_BOUND_CONSTANT) { - branchCondition = 1; // GT - value1 = loop->upper; - reg1 = addiInstr->args[1].data.reg.reg; - value2 = absStep + loop->upper; - mode = 1; - } else { - branchCondition = 1; // GT - value1 = 0; - reg1 = addiInstr->args[1].data.reg.reg; - reg2 = addiInstr->args[2].data.reg.reg; - value2 = absStep; - mode = 2; - } - } else if (loop->unknownCondition == EGREATER) { - branchOpcode = PC_BF; - if (loop->lowerType == LOOP_BOUND_CONSTANT) { - branchCondition = 0; // LT - value1 = loop->lower; - reg1 = addiInstr->args[2].data.reg.reg; - value2 = absStep - 1 + loop->lower; - mode = 1; - } else if (loop->upperType == LOOP_BOUND_CONSTANT) { - branchCondition = 1; // GT - value1 = loop->upper; - reg1 = addiInstr->args[1].data.reg.reg; - value2 = absStep - 1 - loop->upper; - mode = 0; - } else { - branchCondition = 1; // GT - value1 = 0; - reg1 = addiInstr->args[1].data.reg.reg; - reg2 = addiInstr->args[2].data.reg.reg; - value2 = absStep - 1; - mode = 3; - } - } else if (loop->unknownCondition == EGREATEREQU) { - branchOpcode = PC_BT; - if (loop->lowerType == LOOP_BOUND_CONSTANT) { - branchCondition = 1; // GT - value1 = loop->lower; - reg1 = addiInstr->args[2].data.reg.reg; - value2 = absStep + loop->lower; - mode = 1; - } else if (loop->upperType == LOOP_BOUND_CONSTANT) { - branchCondition = 0; // LT - value1 = loop->upper; - reg1 = addiInstr->args[1].data.reg.reg; - value2 = absStep - loop->upper; - mode = 0; - } else { - branchCondition = 0; // LT - reg1 = addiInstr->args[1].data.reg.reg; - reg2 = addiInstr->args[2].data.reg.reg; - value2 = absStep; - mode = 3; - } - } else if (loop->unknownCondition == ENOTEQU) { - branchOpcode = PC_BT; - branchCondition = 2; // EQ - if (loop->step > 0) { - if (loop->lowerType == LOOP_BOUND_CONSTANT) { - value1 = loop->lower; - reg1 = addiInstr->args[2].data.reg.reg; - value2 = absStep - 1 - loop->lower; - mode = 0; - } else if (loop->upperType == LOOP_BOUND_CONSTANT) { - value1 = loop->upper; - reg1 = addiInstr->args[1].data.reg.reg; - value2 = absStep - 1 + loop->upper; - mode = 1; - } else { - reg1 = addiInstr->args[1].data.reg.reg; - reg2 = addiInstr->args[2].data.reg.reg; - value2 = absStep - 1; - mode = 2; - } - } else { - if (loop->lowerType == LOOP_BOUND_CONSTANT) { - value1 = loop->lower; - reg1 = addiInstr->args[2].data.reg.reg; - value2 = absStep - 1 + loop->lower; - mode = 1; - } else if (loop->upperType == LOOP_BOUND_CONSTANT) { - value1 = loop->upper; - reg1 = addiInstr->args[1].data.reg.reg; - value2 = absStep - 1 - loop->upper; - mode = 0; - } else { - reg1 = addiInstr->args[1].data.reg.reg; - reg2 = addiInstr->args[2].data.reg.reg; - value2 = absStep - 1; - mode = 3; - } - } - } - - while (1) { - instr = loop->body->firstPCode; - CError_ASSERT(1857, instr); - - if (instr->op == PC_CMP || instr->op == PC_CMPI || instr->op == PC_CMPLI || instr->op == PC_CMPL) - break; - - deletepcode(instr); - insertpcodebefore(loop->preheader->lastPCode, instr); - loop->bodySize--; - } - - // build a value for mtctr - counterReg = used_virtual_registers[RegClass_GPR]++; - - if (mode == 1) { - if (value2 == 0) { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_NEG, counterReg, reg1)); - } else if (FITS_IN_SHORT(value2)) { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_SUBFIC, counterReg, reg1, value2)); - } else { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_LIS, counterReg, 0, HIGH_PART(value2))); - if (value2 != 0) { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_ADDI, counterReg, counterReg, 0, LOW_PART(value2))); - } - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_SUBF, counterReg, reg1, counterReg)); - } - } else if (mode == 0) { - if (value2 == 0) { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_MR, counterReg, reg1)); - } else if (FITS_IN_SHORT(value2)) { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_ADDI, counterReg, reg1, 0, value2)); - } else { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_ADDIS, counterReg, reg1, 0, HIGH_PART(value2))); - if (value2 != 0) { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_ADDI, counterReg, counterReg, 0, LOW_PART(value2))); - } - } - } else if (mode == 2) { - if (value2 == 0) { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_SUBF, counterReg, reg1, reg2)); - } else if (FITS_IN_SHORT(value2)) { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_ADDI, counterReg, reg2, 0, value2)); - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_SUBF, counterReg, reg1, counterReg)); - } else { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_ADDIS, counterReg, reg2, 0, HIGH_PART(value2))); - if (value2 != 0) { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_ADDI, counterReg, counterReg, 0, LOW_PART(value2))); - } - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_SUBF, counterReg, reg1, counterReg)); - } - } else { - if (value2 == 0) { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_SUBF, counterReg, reg2, reg1)); - } else { - if (FITS_IN_SHORT(value2)) { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_ADDI, counterReg, reg1, 0, value2)); - } else { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_ADDIS, counterReg, reg1, 0, HIGH_PART(value2))); - if (value2 != 0) { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_ADDI, counterReg, counterReg, 0, LOW_PART(value2))); - } - } - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_SUBF, counterReg, reg2, counterReg)); - } - } - - if (absStep > 1) { - unsigned char bits; - if ((bits = ispowerof2(absStep))) { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_RLWINM, counterReg, counterReg, 32 - bits, bits, 31)); - } else { - int reg = used_virtual_registers[RegClass_GPR]++; - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_LI, reg, absStep)); - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_DIVWU, counterReg, counterReg, reg)); - } - } - - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_MTCTR, counterReg)); - - if (mode < 2) { - if (addiInstr->op == PC_CMPL || addiInstr->op == PC_CMPLI) { - if (FITS_IN_USHORT(value1)) { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_CMPLI, 0, reg1, value1)); - } else { - PCode *tmp; - tmp = makepcode(PC_LIS, used_virtual_registers[RegClass_GPR]++, 0, HIGH_PART(value1)); - insertpcodebefore(loop->preheader->lastPCode, tmp); - - if (loop->iterationCount != 0) - insertpcodeafter(tmp, - makepcode(PC_ADDI, - tmp->args[0].data.reg.reg, - tmp->args[0].data.reg.reg, - 0, LOW_PART(value1))); - - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_CMPL, 0, reg1, tmp->args[0].data.reg.reg)); - } - } else { - if (FITS_IN_SHORT(value1)) { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_CMPI, 0, reg1, value1)); - } else { - PCode *tmp; - tmp = makepcode(PC_LIS, used_virtual_registers[RegClass_GPR]++, 0, HIGH_PART(value1)); - insertpcodebefore(loop->preheader->lastPCode, tmp); - - if (loop->iterationCount != 0) - insertpcodeafter(tmp, - makepcode(PC_ADDI, - tmp->args[0].data.reg.reg, - tmp->args[0].data.reg.reg, - 0, LOW_PART(value1))); - - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_CMP, 0, reg1, tmp->args[0].data.reg.reg)); - } - } - } else { - if (addiInstr->op == PC_CMPL || addiInstr->op == PC_CMPLI) { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_CMPL, 0, reg1, reg2)); - } else { - insertpcodebefore(loop->preheader->lastPCode, - makepcode(PC_CMP, 0, reg1, reg2)); - } - } - - if (!afterLoop) - afterLoop = loop->body->nextBlock; - - instr = makepcode(branchOpcode, 0, branchCondition, afterLoop->labels); - deletepcode(loop->preheader->lastPCode); - appendpcode(loop->preheader, instr); - - instr = makepcode(PC_BDNZ, loop->body->lastPCode->args[2].data.label.label); - deletepcode(loop->body->firstPCode); - deletepcode(loop->body->lastPCode); - appendpcode(loop->body, instr); - - loop->preheader->successors = NULL; - ptr = &loop->body->predecessors; - while ((link = *ptr)) { - if (link->block == loop->preheader) { - *ptr = link->nextLink; - break; - } - ptr = &link->nextLink; - } - - link = lalloc(sizeof(PCLink)); - link->block = loop->preheader->nextBlock; - link->nextLink = loop->preheader->successors; - loop->preheader->successors = link; - - link = lalloc(sizeof(PCLink)); - link->block = loop->preheader; - link->nextLink = loop->preheader->nextBlock->predecessors; - loop->preheader->nextBlock->predecessors = link; - - link = lalloc(sizeof(PCLink)); - link->block = afterLoop; - link->nextLink = loop->preheader->successors; - loop->preheader->successors = link; - - link = lalloc(sizeof(PCLink)); - link->block = loop->preheader; - link->nextLink = afterLoop->predecessors; - afterLoop->predecessors = link; - - for (loop = loop->parent; loop; loop = loop->parent) - loop->x4E = 1; -} - -static void optimizeloop(Loop *loop) { - computeliveonexit(loop); - - if (loop->x53 || loop->x54) - insertupdateinstructions(loop); - - if (loop->isKnownCountingLoop) { - if (loop->iterationCount > 0) { - skiplooptest(loop); - if (!copts.optimizesize && !loop->x4D && !loop->x57) { - if (loop->x4F) - unrollloop(loop); - else if (!loop->x4E) - unrollloopconditional(loop); - } - } - - if (loop->iterationCount != 0) { - if (loop->iterationCount == 1) - deleteloopheader(loop); - else if (!loop->x4E && !loop->x4D) - rewriteloopwithBDNZ(loop); - } - - optimizedloops = 1; - } else if (loop->isUnknownCountingLoop && !loop->x4E && !loop->x4D) { - rewriteunknownloopwithBDNZ(loop); - if (copts.unroll_speculative && !copts.optimizesize) { - if (loop->x4F && !loop->x57 && !loop->x52) - unrollunknownBDNZ(loop); - } - optimizedloops = 1; - } - - eliminateinductionvariables(loop); -} - -typedef struct LocalArray { - struct LocalArray *next; - Object *object; - unsigned int invalid:1; - unsigned int isFloat:1; - unsigned int isSigned:1; - SInt32 elementSize; - SInt32 arraySize; - SInt32 elementCount; - int totalUses; - int elements[1]; -} LocalArray; - -static LocalArray *scanforlocalarrays(void) { - SInt32 elementCount; - LocalArray *head; - LocalArray *array; - ObjectList *list; - int i; - SInt32 arraySize; - SInt32 elementSize; - - head = NULL; - - for (list = locals; list; list = list->next) { - if ( - list->object && - !(IS_TYPE_POINTER(list->object->type) ? (TPTR_QUAL(list->object->type) & Q_VOLATILE) : (list->object->qual & Q_VOLATILE)) && - list->object->type && - IS_TYPE_ARRAY(list->object->type) && - TPTR_TARGET(list->object->type) && - TPTR_TARGET(list->object->type)->type < TYPESTRUCT - ) { - arraySize = list->object->type->size; - elementSize = TPTR_TARGET(list->object->type)->size; - elementCount = arraySize / elementSize; - if (elementCount > 0 && elementCount <= 8) { - array = oalloc(sizeof(int) * (elementCount - 1) + sizeof(LocalArray)); - array->next = head; - head = array; - - array->object = list->object; - array->elementSize = elementSize; - array->arraySize = arraySize; - array->elementCount = elementCount; - array->totalUses = 0; - array->isSigned = 1; - array->isFloat = IS_TYPE_FLOAT(TPTR_TARGET(list->object->type)); - array->invalid = 0; - array->isSigned = 1; - if (!array->isFloat && is_unsigned(TPTR_TARGET(list->object->type))) - array->isSigned = 0; - - for (i = 0; i < elementCount; i++) { - array->elements[i] = 0; - } - } - } - } - - return head; -} - -static LocalArray *lookup_array_object(LocalArray *arrays, Object *object) { - while (arrays) { - if (arrays->object == object) - return arrays; - arrays = arrays->next; - } - return NULL; -} - -void changearraytoregisters(void) { - LocalArray *arrays; - PCodeBlock *block; - PCode *instr; - int i; - PCodeArg *op; - LocalArray **ptr; - LocalArray *array; - int intCounter; - int floatCounter; - int reg; - int reg2; - PCode *newInstr; - - arrays = NULL; - if ((arrays = scanforlocalarrays())) { - for (block = pcbasicblocks; block; block = block->nextBlock) { - for (instr = block->firstPCode; instr; instr = instr->nextPCode) { - if (!(instr->flags & fIsBranch) && instr->argCount) { - op = instr->args; - i = instr->argCount; - while (i--) { - if ( - op->kind == PCOp_MEMORY && - (PCOpMemoryArg) op->arg == PCOpMemory1 && - (array = lookup_array_object(arrays, op->data.mem.obj)) && - !array->invalid - ) { - if ( - (instr->flags & (fIsRead | fIsWrite)) && - (op->data.mem.offset % array->elementSize) == 0 && - op->data.mem.offset < array->arraySize - ) { - switch (instr->op) { - case PC_LBZ: - case PC_STB: - if (array->elementSize != 1) - array->invalid = 1; - break; - case PC_LHZ: - case PC_LHA: - case PC_STH: - if (array->elementSize != 2) - array->invalid = 1; - break; - case PC_LWZ: - case PC_STW: - if (array->elementSize != 4) - array->invalid = 1; - break; - case PC_LFD: - case PC_STFD: - if (array->elementSize != 8) - array->invalid = 1; - break; - default: - array->invalid = 1; - break; - } - - if (!array->invalid) - array->elements[op->data.mem.offset / array->elementSize]++; - } else { - array->invalid = 1; - } - } - op++; - } - } - } - } - - intCounter = 0; - floatCounter = 0; - ptr = &arrays; - array = *ptr; - while (array) { - if (array->invalid) { - *ptr = array = array->next; - continue; - } - - if (array->isFloat) - floatCounter += array->elementCount; - if (!array->isFloat) - intCounter += array->elementCount; - - for (i = 0; i < array->elementCount; i++) - array->totalUses += array->elements[i]; - - array = array->next; - } - - if (arrays) { - while (intCounter > 8) { - LocalArray *best; - int score; - score = 0; - best = NULL; - for (array = arrays; array; array = array->next) { - if (!array->isFloat) { - if (best) { - if (array->totalUses < score) { - score = array->totalUses; - best = array; - } - } else { - best = array; - score = array->totalUses; - } - } - } - - if (!best) - break; - - if (best == arrays) { - arrays = best->next; - } else { - for (array = arrays; array; array = array->next) { - if (array->next == best) { - array->next = best->next; - break; - } - } - } - - intCounter -= best->elementCount; - } - - while (floatCounter > 8) { - LocalArray *best; - int score; - score = 0; - best = NULL; - for (array = arrays; array; array = array->next) { - if (array->isFloat) { - if (best) { - if (array->totalUses < score) { - score = array->totalUses; - best = array; - } - } else { - best = array; - score = array->totalUses; - } - } - } - - if (!best) - break; - - if (best == arrays) { - arrays = best->next; - } else { - for (array = arrays; array; array = array->next) { - if (array->next == best) { - array->next = best->next; - break; - } - } - } - - floatCounter -= best->elementCount; - } - - CError_ASSERT(2394, intCounter <= 8 && floatCounter <= 8); - - if (!arrays) - return; - - optimizedloop_trans_regs = 1; - - for (array = arrays; array; array = array->next) { - for (i = 0; i < array->elementCount; i++) { - if (array->isFloat) - array->elements[i] = used_virtual_registers[RegClass_FPR]++; - else - array->elements[i] = used_virtual_registers[RegClass_GPR]++; - } - } - - for (block = pcbasicblocks; block; block = block->nextBlock) { - for (instr = block->firstPCode; instr; instr = instr->nextPCode) { - if ( - !(instr->flags & fIsBranch) && - instr->argCount && - (instr->flags & (fIsRead | fIsWrite)) && - instr->args[2].kind == PCOp_MEMORY && - (PCOpMemoryArg) instr->args[2].arg == PCOpMemory1 && - (array = lookup_array_object(arrays, instr->args[2].data.mem.obj)) && - !(array->invalid) - ) - { - reg2 = instr->args[0].data.reg.reg; - reg = array->elements[instr->args[2].data.mem.offset / array->elementSize]; - newInstr = NULL; - switch (instr->op) { - case PC_LBZ: - if (array->isSigned) - newInstr = makepcode(PC_MR, reg2, reg); - else - newInstr = makepcode(PC_RLWINM, reg2, reg, 0, 24, 31); - break; - case PC_STB: - if (array->isSigned) - newInstr = makepcode(PC_EXTSB, reg, reg2); - else - newInstr = makepcode(PC_RLWINM, reg, reg2, 0, 24, 31); - break; - case PC_LHZ: - newInstr = makepcode(PC_RLWINM, reg2, reg, 0, 16, 31); - break; - case PC_LHA: - newInstr = makepcode(PC_EXTSH, reg2, reg); - break; - case PC_STH: - if (array->isSigned) - newInstr = makepcode(PC_EXTSH, reg, reg2); - else - newInstr = makepcode(PC_RLWINM, reg, reg2, 0, 16, 31); - break; - case PC_LWZ: - newInstr = makepcode(PC_MR, reg2, reg); - break; - case PC_STW: - newInstr = makepcode(PC_MR, reg, reg2); - break; - case PC_LFD: - newInstr = makepcode(PC_FMR, reg2, reg); - break; - case PC_STFD: - newInstr = makepcode(PC_FMR, reg, reg2); - break; - default: - CError_FATAL(2494); - break; - } - - if (newInstr) { - insertpcodebefore(instr, newInstr); - deletepcode(instr); - instr = newInstr; - } - } - } - } - } - } - - freeoheap(); -} - -static void optimizenestedloops(Loop *loop) { - while (loop) { - if (loop->children) - optimizenestedloops(loop->children); - optimizeloop(loop); - loop = loop->nextSibling; - } -} - -void optimizeloops(void) { - optimizedloops = 0; - optimizedloop_full_unroll = 0; - optimizedloop_trans_regs = 0; - if (loopsinflowgraph) { - computeusedefchains(0); - last_virtual_GPR = used_virtual_registers[RegClass_GPR]; - liveonexit = oalloc(4 * ((used_virtual_registers[RegClass_GPR] + 31) >> 5)); - inductionvariables = oalloc(4 * ((last_virtual_GPR + 31) >> 5)); - optimizenestedloops(loopsinflowgraph); - freeoheap(); - } -} - diff --git a/compiler_and_linker/unsorted/MachineSimulation601.c b/compiler_and_linker/unsorted/MachineSimulation601.c deleted file mode 100644 index 2d54678..0000000 --- a/compiler_and_linker/unsorted/MachineSimulation601.c +++ /dev/null @@ -1,552 +0,0 @@ -#include "compiler/Scheduler.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" - -// https://stuff.mit.edu/afs/sipb/contrib/doc/specs/ic/cpu/powerpc/mpc601.pdf -// https://www.nxp.com/docs/en/user-guide/MPC601UMAD.pdf - -typedef enum Stage { - IU, // Integer Unit - FD, // FP Decode - FPM, // FP Multiply - FPA, // FP Add - FWA, // FP Arithmetic Writeback - BPU, // Branch Processing Unit - NumStages, - Serialize, // special form for instructions that use IU but are serialised - Unsupported // instructions not supported by this processor -} Stage; - -static struct { - // the instruction currently in this pipeline stage - PCode *instr; - - // how many cycles are left for this instruction to finish - int remaining; -} pipeline[NumStages]; - -static struct { - // the initial stage for this instruction - Stage stage; - - // the total amount of cycles required by this instruction - char latency; - - // how long it takes to finish each stage - char cycles[4]; -} instruction_timing[OPCODE_MAX] = { - BPU, 0, 0, 0, 0, 1, // PC_B - BPU, 0, 0, 0, 0, 1, // PC_BL - BPU, 0, 0, 0, 0, 1, // PC_BC - BPU, 0, 0, 0, 0, 1, // PC_BCLR - BPU, 0, 0, 0, 0, 1, // PC_BCCTR - BPU, 0, 0, 0, 0, 1, // PC_BT - BPU, 0, 0, 0, 0, 1, // PC_BTLR - BPU, 0, 0, 0, 0, 1, // PC_BTCTR - BPU, 0, 0, 0, 0, 1, // PC_BF - BPU, 0, 0, 0, 0, 1, // PC_BFLR - BPU, 0, 0, 0, 0, 1, // PC_BFCTR - BPU, 0, 0, 0, 0, 1, // PC_BDNZ - BPU, 0, 0, 0, 0, 1, // PC_BDNZT - BPU, 0, 0, 0, 0, 1, // PC_BDNZF - BPU, 0, 0, 0, 0, 1, // PC_BDZ - BPU, 0, 0, 0, 0, 1, // PC_BDZT - BPU, 0, 0, 0, 0, 1, // PC_BDZF - BPU, 0, 0, 0, 0, 1, // PC_BLR - BPU, 0, 0, 0, 0, 1, // PC_BCTR - BPU, 0, 0, 0, 0, 1, // PC_BCTRL - BPU, 0, 0, 0, 0, 1, // PC_BLRL - IU, 2, 1, 0, 0, 0, // PC_LBZ - IU, 2, 1, 0, 0, 0, // PC_LBZU - IU, 2, 1, 0, 0, 0, // PC_LBZX - IU, 2, 1, 0, 0, 0, // PC_LBZUX - IU, 2, 1, 0, 0, 0, // PC_LHZ - IU, 2, 1, 0, 0, 0, // PC_LHZU - IU, 2, 1, 0, 0, 0, // PC_LHZX - IU, 2, 1, 0, 0, 0, // PC_LHZUX - IU, 2, 1, 0, 0, 0, // PC_LHA - IU, 2, 1, 0, 0, 0, // PC_LHAU - IU, 2, 1, 0, 0, 0, // PC_LHAX - IU, 2, 1, 0, 0, 0, // PC_LHAUX - IU, 2, 1, 0, 0, 0, // PC_LHBRX - IU, 2, 1, 0, 0, 0, // PC_LWZ - IU, 2, 1, 0, 0, 0, // PC_LWZU - IU, 2, 1, 0, 0, 0, // PC_LWZX - IU, 2, 1, 0, 0, 0, // PC_LWZUX - IU, 2, 1, 0, 0, 0, // PC_LWBRX - IU, 1, 1, 0, 0, 0, // PC_LMW - IU, 1, 1, 0, 0, 0, // PC_STB - IU, 1, 1, 0, 0, 0, // PC_STBU - IU, 1, 1, 0, 0, 0, // PC_STBX - IU, 1, 1, 0, 0, 0, // PC_STBUX - IU, 1, 1, 0, 0, 0, // PC_STH - IU, 1, 1, 0, 0, 0, // PC_STHU - IU, 1, 1, 0, 0, 0, // PC_STHX - IU, 1, 1, 0, 0, 0, // PC_STHUX - IU, 1, 1, 0, 0, 0, // PC_STHBRX - IU, 1, 1, 0, 0, 0, // PC_STW - IU, 1, 1, 0, 0, 0, // PC_STWU - IU, 1, 1, 0, 0, 0, // PC_STWX - IU, 1, 1, 0, 0, 0, // PC_STWUX - IU, 1, 1, 0, 0, 0, // PC_STWBRX - IU, 1, 1, 0, 0, 0, // PC_STMW - IU, 2, 1, 0, 0, 0, // PC_DCBF - IU, 2, 1, 0, 0, 0, // PC_DCBST - IU, 2, 1, 0, 0, 0, // PC_DCBT - IU, 2, 1, 0, 0, 0, // PC_DCBTST - IU, 2, 1, 0, 0, 0, // PC_DCBZ - IU, 1, 1, 0, 0, 0, // PC_ADD - IU, 1, 1, 0, 0, 0, // PC_ADDC - IU, 1, 1, 0, 0, 0, // PC_ADDE - IU, 1, 1, 0, 0, 0, // PC_ADDI - IU, 1, 1, 0, 0, 0, // PC_ADDIC - IU, 1, 1, 0, 0, 0, // PC_ADDICR - IU, 1, 1, 0, 0, 0, // PC_ADDIS - IU, 1, 1, 0, 0, 0, // PC_ADDME - IU, 1, 1, 0, 0, 0, // PC_ADDZE - IU, 36, 36, 0, 0, 0, // PC_DIVW - IU, 36, 36, 0, 0, 0, // PC_DIVWU - IU, 5, 5, 0, 0, 0, // PC_MULHW - IU, 5, 5, 0, 0, 0, // PC_MULHWU - IU, 5, 5, 0, 0, 0, // PC_MULLI - IU, 5, 5, 0, 0, 0, // PC_MULLW - IU, 1, 1, 0, 0, 0, // PC_NEG - IU, 1, 1, 0, 0, 0, // PC_SUBF - IU, 1, 1, 0, 0, 0, // PC_SUBFC - IU, 1, 1, 0, 0, 0, // PC_SUBFE - IU, 1, 1, 0, 0, 0, // PC_SUBFIC - IU, 1, 1, 0, 0, 0, // PC_SUBFME - IU, 1, 1, 0, 0, 0, // PC_SUBFZE - IU, 3, 1, 0, 0, 0, // PC_CMPI - IU, 3, 1, 0, 0, 0, // PC_CMP - IU, 3, 1, 0, 0, 0, // PC_CMPLI - IU, 3, 1, 0, 0, 0, // PC_CMPL - IU, 1, 1, 0, 0, 0, // PC_ANDI - IU, 1, 1, 0, 0, 0, // PC_ANDIS - IU, 1, 1, 0, 0, 0, // PC_ORI - IU, 1, 1, 0, 0, 0, // PC_ORIS - IU, 1, 1, 0, 0, 0, // PC_XORI - IU, 1, 1, 0, 0, 0, // PC_XORIS - IU, 1, 1, 0, 0, 0, // PC_AND - IU, 1, 1, 0, 0, 0, // PC_OR - IU, 1, 1, 0, 0, 0, // PC_XOR - IU, 1, 1, 0, 0, 0, // PC_NAND - IU, 1, 1, 0, 0, 0, // PC_NOR - IU, 1, 1, 0, 0, 0, // PC_EQV - IU, 1, 1, 0, 0, 0, // PC_ANDC - IU, 1, 1, 0, 0, 0, // PC_ORC - IU, 1, 1, 0, 0, 0, // PC_EXTSB - IU, 1, 1, 0, 0, 0, // PC_EXTSH - IU, 1, 1, 0, 0, 0, // PC_CNTLZW - IU, 1, 1, 0, 0, 0, // PC_RLWINM - IU, 1, 1, 0, 0, 0, // PC_RLWNM - IU, 1, 1, 0, 0, 0, // PC_RLWIMI - IU, 1, 1, 0, 0, 0, // PC_SLW - IU, 1, 1, 0, 0, 0, // PC_SRW - IU, 1, 1, 0, 0, 0, // PC_SRAWI - IU, 1, 1, 0, 0, 0, // PC_SRAW - IU, 1, 1, 0, 0, 0, // PC_CRAND - IU, 1, 1, 0, 0, 0, // PC_CRANDC - IU, 1, 1, 0, 0, 0, // PC_CREQV - IU, 1, 1, 0, 0, 0, // PC_CRNAND - IU, 1, 1, 0, 0, 0, // PC_CRNOR - IU, 1, 1, 0, 0, 0, // PC_CROR - IU, 1, 1, 0, 0, 0, // PC_CRORC - IU, 1, 1, 0, 0, 0, // PC_CRXOR - IU, 1, 1, 0, 0, 0, // PC_MCRF - IU, 4, 1, 0, 0, 0, // PC_MTXER - IU, 4, 1, 0, 0, 0, // PC_MTCTR - IU, 4, 1, 0, 0, 0, // PC_MTLR - IU, 2, 1, 0, 0, 0, // PC_MTCRF - IU, 1, 0, 0, 0, 0, // PC_MTMSR - IU, 1, 0, 0, 0, 0, // PC_MTSPR - IU, 1, 0, 0, 0, 0, // PC_MFMSR - IU, 1, 0, 0, 0, 0, // PC_MFSPR - IU, 1, 1, 0, 0, 0, // PC_MFXER - IU, 1, 1, 0, 0, 0, // PC_MFCTR - IU, 1, 1, 0, 0, 0, // PC_MFLR - IU, 1, 1, 0, 0, 0, // PC_MFCR - FD, 4, 1, 1, 1, 1, // PC_MFFS - FD, 4, 1, 1, 1, 1, // PC_MTFSF - Serialize, 1, 1, 0, 0, 1, // PC_EIEIO - Serialize, 1, 1, 0, 0, 1, // PC_ISYNC - Serialize, 1, 1, 0, 0, 1, // PC_SYNC - Serialize, 0, 0, 0, 0, 1, // PC_RFI - IU, 1, 1, 0, 0, 0, // PC_LI - IU, 1, 1, 0, 0, 0, // PC_LIS - IU, 1, 1, 0, 0, 0, // PC_MR - IU, 1, 1, 0, 0, 0, // PC_NOP - IU, 1, 1, 0, 0, 0, // PC_NOT - IU, 3, 1, 0, 0, 0, // PC_LFS - IU, 3, 1, 0, 0, 0, // PC_LFSU - IU, 3, 1, 0, 0, 0, // PC_LFSX - IU, 3, 1, 0, 0, 0, // PC_LFSUX - IU, 3, 1, 0, 0, 0, // PC_LFD - IU, 3, 1, 0, 0, 0, // PC_LFDU - IU, 3, 1, 0, 0, 0, // PC_LFDX - IU, 3, 1, 0, 0, 0, // PC_LFDUX - IU, 1, 1, 0, 0, 0, // PC_STFS - IU, 1, 1, 0, 0, 0, // PC_STFSU - IU, 1, 1, 0, 0, 0, // PC_STFSX - IU, 1, 1, 0, 0, 0, // PC_STFSUX - IU, 1, 1, 0, 0, 0, // PC_STFD - IU, 1, 1, 0, 0, 0, // PC_STFDU - IU, 1, 1, 0, 0, 0, // PC_STFDX - IU, 1, 1, 0, 0, 0, // PC_STFDUX - FD, 4, 1, 1, 1, 1, // PC_FMR - FD, 4, 1, 1, 1, 1, // PC_FABS - FD, 4, 1, 1, 1, 1, // PC_FNEG - FD, 4, 1, 1, 1, 1, // PC_FNABS - FD, 4, 1, 1, 1, 1, // PC_FADD - FD, 4, 1, 1, 1, 1, // PC_FADDS - FD, 4, 1, 1, 1, 1, // PC_FSUB - FD, 4, 1, 1, 1, 1, // PC_FSUBS - FD, 5, 1, 1, 2, 1, // PC_FMUL - FD, 4, 1, 1, 1, 1, // PC_FMULS - FD, 31, 1, 1, 28, 1, // PC_FDIV - FD, 17, 1, 1, 14, 1, // PC_FDIVS - FD, 5, 1, 1, 2, 1, // PC_FMADD - FD, 4, 1, 1, 1, 1, // PC_FMADDS - FD, 5, 1, 1, 2, 1, // PC_FMSUB - FD, 4, 1, 1, 1, 1, // PC_FMSUBS - FD, 5, 1, 1, 2, 1, // PC_FNMADD - FD, 4, 1, 1, 1, 1, // PC_FNMADDS - FD, 5, 1, 1, 2, 1, // PC_FNMSUB - FD, 4, 1, 1, 1, 1, // PC_FNMSUBS - FD, 4, 1, 1, 1, 1, // PC_FRES - FD, 4, 1, 1, 1, 1, // PC_FRSQRTE - FD, 4, 1, 1, 1, 1, // PC_FSEL - FD, 4, 1, 1, 1, 1, // PC_FRSP - FD, 4, 1, 1, 1, 1, // PC_FCTIW - FD, 4, 1, 1, 1, 1, // PC_FCTIWZ - FD, 6, 1, 1, 1, 1, // PC_FCMPU - FD, 6, 1, 1, 1, 1, // PC_FCMPO - IU, 0, 0, 0, 0, 0, // PC_LWARX - IU, 0, 0, 0, 0, 0, // PC_LSWI - IU, 0, 0, 0, 0, 0, // PC_LSWX - IU, 0, 0, 0, 0, 0, // PC_STFIWX - IU, 0, 0, 0, 0, 0, // PC_STSWI - IU, 0, 0, 0, 0, 0, // PC_STSWX - IU, 0, 0, 0, 0, 0, // PC_STWCX - IU, 0, 0, 0, 0, 0, // PC_ECIWX - IU, 0, 0, 0, 0, 0, // PC_ECOWX - IU, 0, 0, 0, 0, 0, // PC_DCBI - IU, 0, 0, 0, 0, 0, // PC_ICBI - IU, 0, 0, 0, 0, 0, // PC_MCRFS - IU, 0, 0, 0, 0, 0, // PC_MCRXR - IU, 0, 0, 0, 0, 0, // PC_MFTB - IU, 0, 0, 0, 0, 0, // PC_MFSR - IU, 0, 0, 0, 0, 0, // PC_MTSR - IU, 0, 0, 0, 0, 0, // PC_MFSRIN - IU, 0, 0, 0, 0, 0, // PC_MTSRIN - IU, 0, 0, 0, 0, 0, // PC_MTFSB0 - IU, 0, 0, 0, 0, 0, // PC_MTFSB1 - IU, 0, 0, 0, 0, 0, // PC_MTFSFI - Serialize, 0, 0, 0, 0, 0, // PC_SC - IU, 0, 0, 0, 0, 0, // PC_FSQRT - IU, 0, 0, 0, 0, 0, // PC_FSQRTS - IU, 0, 0, 0, 0, 0, // PC_TLBIA - IU, 0, 0, 0, 0, 0, // PC_TLBIE - IU, 0, 0, 0, 0, 0, // PC_TLBLD - IU, 0, 0, 0, 0, 0, // PC_TLBLI - IU, 0, 0, 0, 0, 0, // PC_TLBSYNC - Serialize, 0, 0, 0, 0, 0, // PC_TW - Serialize, 0, 0, 0, 0, 0, // PC_TRAP - Serialize, 0, 0, 0, 0, 0, // PC_TWI - Serialize, 0, 0, 0, 0, 0, // PC_OPWORD - IU, 0, 0, 0, 0, 0, // PC_MFROM - IU, 0, 0, 0, 0, 0, // PC_DSA - IU, 0, 0, 0, 0, 0, // PC_ESA - IU, 0, 0, 0, 0, 0, // PC_DCCCI - IU, 0, 0, 0, 0, 0, // PC_DCREAD - IU, 0, 0, 0, 0, 0, // PC_ICBT - IU, 0, 0, 0, 0, 0, // PC_ICCCI - IU, 0, 0, 0, 0, 0, // PC_ICREAD - IU, 0, 0, 0, 0, 0, // PC_RFCI - IU, 0, 0, 0, 0, 0, // PC_TLBRE - IU, 0, 0, 0, 0, 0, // PC_TLBSX - IU, 0, 0, 0, 0, 0, // PC_TLBWE - IU, 0, 0, 0, 0, 0, // PC_WRTEE - IU, 0, 0, 0, 0, 0, // PC_WRTEEI - IU, 0, 0, 0, 0, 0, // PC_MFDCR - IU, 0, 0, 0, 0, 0, // PC_MTDCR - Unsupported, 0, 0, 0, 0, 0, // PC_DCBA - Unsupported, 0, 0, 0, 0, 0, // PC_DSS - Unsupported, 0, 0, 0, 0, 0, // PC_DSSALL - Unsupported, 0, 0, 0, 0, 0, // PC_DST - Unsupported, 0, 0, 0, 0, 0, // PC_DSTT - Unsupported, 0, 0, 0, 0, 0, // PC_DSTST - Unsupported, 0, 0, 0, 0, 0, // PC_DSTSTT - Unsupported, 0, 0, 0, 0, 0, // PC_LVEBX - Unsupported, 0, 0, 0, 0, 0, // PC_LVEHX - Unsupported, 0, 0, 0, 0, 0, // PC_LVEWX - Unsupported, 0, 0, 0, 0, 0, // PC_LVSL - Unsupported, 0, 0, 0, 0, 0, // PC_LVSR - Unsupported, 0, 0, 0, 0, 0, // PC_LVX - Unsupported, 0, 0, 0, 0, 0, // PC_LVXL - Unsupported, 0, 0, 0, 0, 0, // PC_STVEBX - Unsupported, 0, 0, 0, 0, 0, // PC_STVEHX - Unsupported, 0, 0, 0, 0, 0, // PC_STVEWX - Unsupported, 0, 0, 0, 0, 0, // PC_STVX - Unsupported, 0, 0, 0, 0, 0, // PC_STVXL - Unsupported, 0, 0, 0, 0, 0, // PC_MFVSCR - Unsupported, 0, 0, 0, 0, 0, // PC_MTVSCR - Unsupported, 0, 0, 0, 0, 0, // PC_VADDCUW - Unsupported, 0, 0, 0, 0, 0, // PC_VADDFP - Unsupported, 0, 0, 0, 0, 0, // PC_VADDSBS - Unsupported, 0, 0, 0, 0, 0, // PC_VADDSHS - Unsupported, 0, 0, 0, 0, 0, // PC_VADDSWS - Unsupported, 0, 0, 0, 0, 0, // PC_VADDUBM - Unsupported, 0, 0, 0, 0, 0, // PC_VADDUBS - Unsupported, 0, 0, 0, 0, 0, // PC_VADDUHM - Unsupported, 0, 0, 0, 0, 0, // PC_VADDUHS - Unsupported, 0, 0, 0, 0, 0, // PC_VADDUWM - Unsupported, 0, 0, 0, 0, 0, // PC_VADDUWS - Unsupported, 0, 0, 0, 0, 0, // PC_VAND - Unsupported, 0, 0, 0, 0, 0, // PC_VANDC - Unsupported, 0, 0, 0, 0, 0, // PC_VAVGSB - Unsupported, 0, 0, 0, 0, 0, // PC_VAVGSH - Unsupported, 0, 0, 0, 0, 0, // PC_VAVGSW - Unsupported, 0, 0, 0, 0, 0, // PC_VAVGUB - Unsupported, 0, 0, 0, 0, 0, // PC_VAVGUH - Unsupported, 0, 0, 0, 0, 0, // PC_VAVGUW - Unsupported, 0, 0, 0, 0, 0, // PC_VCFSX - Unsupported, 0, 0, 0, 0, 0, // PC_VCFUX - Unsupported, 0, 0, 0, 0, 0, // PC_VCMPBFP - Unsupported, 0, 0, 0, 0, 0, // PC_VCMPEQFP - Unsupported, 0, 0, 0, 0, 0, // PC_VCMPEQUB - Unsupported, 0, 0, 0, 0, 0, // PC_VCMPEQUH - Unsupported, 0, 0, 0, 0, 0, // PC_VCMPEQUW - Unsupported, 0, 0, 0, 0, 0, // PC_VCMPGEFP - Unsupported, 0, 0, 0, 0, 0, // PC_VCMPGTFP - Unsupported, 0, 0, 0, 0, 0, // PC_VCMPGTSB - Unsupported, 0, 0, 0, 0, 0, // PC_VCMPGTSH - Unsupported, 0, 0, 0, 0, 0, // PC_VCMPGTSW - Unsupported, 0, 0, 0, 0, 0, // PC_VCMPGTUB - Unsupported, 0, 0, 0, 0, 0, // PC_VCMPGTUH - Unsupported, 0, 0, 0, 0, 0, // PC_VCMPGTUW - Unsupported, 0, 0, 0, 0, 0, // PC_VCTSXS - Unsupported, 0, 0, 0, 0, 0, // PC_VCTUXS - Unsupported, 0, 0, 0, 0, 0, // PC_VEXPTEFP - Unsupported, 0, 0, 0, 0, 0, // PC_VLOGEFP - Unsupported, 0, 0, 0, 0, 0, // PC_VMAXFP - Unsupported, 0, 0, 0, 0, 0, // PC_VMAXSB - Unsupported, 0, 0, 0, 0, 0, // PC_VMAXSH - Unsupported, 0, 0, 0, 0, 0, // PC_VMAXSW - Unsupported, 0, 0, 0, 0, 0, // PC_VMAXUB - Unsupported, 0, 0, 0, 0, 0, // PC_VMAXUH - Unsupported, 0, 0, 0, 0, 0, // PC_VMAXUW - Unsupported, 0, 0, 0, 0, 0, // PC_VMINFP - Unsupported, 0, 0, 0, 0, 0, // PC_VMINSB - Unsupported, 0, 0, 0, 0, 0, // PC_VMINSH - Unsupported, 0, 0, 0, 0, 0, // PC_VMINSW - Unsupported, 0, 0, 0, 0, 0, // PC_VMINUB - Unsupported, 0, 0, 0, 0, 0, // PC_VMINUH - Unsupported, 0, 0, 0, 0, 0, // PC_VMINUW - Unsupported, 0, 0, 0, 0, 0, // PC_VMRGHB - Unsupported, 0, 0, 0, 0, 0, // PC_VMRGHH - Unsupported, 0, 0, 0, 0, 0, // PC_VMRGHW - Unsupported, 0, 0, 0, 0, 0, // PC_VMRGLB - Unsupported, 0, 0, 0, 0, 0, // PC_VMRGLH - Unsupported, 0, 0, 0, 0, 0, // PC_VMRGLW - Unsupported, 0, 0, 0, 0, 0, // PC_VMULESB - Unsupported, 0, 0, 0, 0, 0, // PC_VMULESH - Unsupported, 0, 0, 0, 0, 0, // PC_VMULEUB - Unsupported, 0, 0, 0, 0, 0, // PC_VMULEUH - Unsupported, 0, 0, 0, 0, 0, // PC_VMULOSB - Unsupported, 0, 0, 0, 0, 0, // PC_VMULOSH - Unsupported, 0, 0, 0, 0, 0, // PC_VMULOUB - Unsupported, 0, 0, 0, 0, 0, // PC_VMULOUH - Unsupported, 0, 0, 0, 0, 0, // PC_VNOR - Unsupported, 0, 0, 0, 0, 0, // PC_VOR - Unsupported, 0, 0, 0, 0, 0, // PC_VPKPX - Unsupported, 0, 0, 0, 0, 0, // PC_VPKSHSS - Unsupported, 0, 0, 0, 0, 0, // PC_VPKSHUS - Unsupported, 0, 0, 0, 0, 0, // PC_VPKSWSS - Unsupported, 0, 0, 0, 0, 0, // PC_VPKSWUS - Unsupported, 0, 0, 0, 0, 0, // PC_VPKUHUM - Unsupported, 0, 0, 0, 0, 0, // PC_VPKUHUS - Unsupported, 0, 0, 0, 0, 0, // PC_VPKUWUM - Unsupported, 0, 0, 0, 0, 0, // PC_VPKUWUS - Unsupported, 0, 0, 0, 0, 0, // PC_VREFP - Unsupported, 0, 0, 0, 0, 0, // PC_VRFIM - Unsupported, 0, 0, 0, 0, 0, // PC_VRFIN - Unsupported, 0, 0, 0, 0, 0, // PC_VRFIP - Unsupported, 0, 0, 0, 0, 0, // PC_VRFIZ - Unsupported, 0, 0, 0, 0, 0, // PC_VRLB - Unsupported, 0, 0, 0, 0, 0, // PC_VRLH - Unsupported, 0, 0, 0, 0, 0, // PC_VRLW - Unsupported, 0, 0, 0, 0, 0, // PC_VRSQRTEFP - Unsupported, 0, 0, 0, 0, 0, // PC_VSL - Unsupported, 0, 0, 0, 0, 0, // PC_VSLB - Unsupported, 0, 0, 0, 0, 0, // PC_VSLH - Unsupported, 0, 0, 0, 0, 0, // PC_VSLO - Unsupported, 0, 0, 0, 0, 0, // PC_VSLW - Unsupported, 0, 0, 0, 0, 0, // PC_VSPLTB - Unsupported, 0, 0, 0, 0, 0, // PC_VSPLTH - Unsupported, 0, 0, 0, 0, 0, // PC_VSPLTW - Unsupported, 0, 0, 0, 0, 0, // PC_VSPLTISB - Unsupported, 0, 0, 0, 0, 0, // PC_VSPLTISH - Unsupported, 0, 0, 0, 0, 0, // PC_VSPLTISW - Unsupported, 0, 0, 0, 0, 0, // PC_VSR - Unsupported, 0, 0, 0, 0, 0, // PC_VSRAB - Unsupported, 0, 0, 0, 0, 0, // PC_VSRAH - Unsupported, 0, 0, 0, 0, 0, // PC_VSRAW - Unsupported, 0, 0, 0, 0, 0, // PC_VSRB - Unsupported, 0, 0, 0, 0, 0, // PC_VSRH - Unsupported, 0, 0, 0, 0, 0, // PC_VSRO - Unsupported, 0, 0, 0, 0, 0, // PC_VSRW - Unsupported, 0, 0, 0, 0, 0, // PC_VSUBCUW - Unsupported, 0, 0, 0, 0, 0, // PC_VSUBFP - Unsupported, 0, 0, 0, 0, 0, // PC_VSUBSBS - Unsupported, 0, 0, 0, 0, 0, // PC_VSUBSHS - Unsupported, 0, 0, 0, 0, 0, // PC_VSUBSWS - Unsupported, 0, 0, 0, 0, 0, // PC_VSUBUBM - Unsupported, 0, 0, 0, 0, 0, // PC_VSUBUBS - Unsupported, 0, 0, 0, 0, 0, // PC_VSUBUHM - Unsupported, 0, 0, 0, 0, 0, // PC_VSUBUHS - Unsupported, 0, 0, 0, 0, 0, // PC_VSUBUWM - Unsupported, 0, 0, 0, 0, 0, // PC_VSUBUWS - Unsupported, 0, 0, 0, 0, 0, // PC_VSUMSWS - Unsupported, 0, 0, 0, 0, 0, // PC_VSUFPMSWS - Unsupported, 0, 0, 0, 0, 0, // PC_VSUFWASBS - Unsupported, 0, 0, 0, 0, 0, // PC_VSUFWASHS - Unsupported, 0, 0, 0, 0, 0, // PC_VSUFWAUBS - Unsupported, 0, 0, 0, 0, 0, // PC_VUPKHPX - Unsupported, 0, 0, 0, 0, 0, // PC_VUPKHSB - Unsupported, 0, 0, 0, 0, 0, // PC_VUPKHSH - Unsupported, 0, 0, 0, 0, 0, // PC_VUPKLPX - Unsupported, 0, 0, 0, 0, 0, // PC_VUPKLSB - Unsupported, 0, 0, 0, 0, 0, // PC_VUPKLSH - Unsupported, 0, 0, 0, 0, 0, // PC_VXOR - Unsupported, 0, 0, 0, 0, 0, // PC_VMADDFP - Unsupported, 0, 0, 0, 0, 0, // PC_VMHADDSHS - Unsupported, 0, 0, 0, 0, 0, // PC_VMHRADDSHS - Unsupported, 0, 0, 0, 0, 0, // PC_VMLADDUHM - Unsupported, 0, 0, 0, 0, 0, // PC_VMSUMMBM - Unsupported, 0, 0, 0, 0, 0, // PC_VMSUMSHM - Unsupported, 0, 0, 0, 0, 0, // PC_VMSUMSHS - Unsupported, 0, 0, 0, 0, 0, // PC_VMSUMUBM - Unsupported, 0, 0, 0, 0, 0, // PC_VMSUMUHM - Unsupported, 0, 0, 0, 0, 0, // PC_VMSUMUHS - Unsupported, 0, 0, 0, 0, 0, // PC_VNMSUBFP - Unsupported, 0, 0, 0, 0, 0, // PC_VPERM - Unsupported, 0, 0, 0, 0, 0, // PC_VSEL - Unsupported, 0, 0, 0, 0, 0, // PC_VSLDOI - Unsupported, 0, 0, 0, 0, 0, // PC_VMR - Unsupported, 0, 0, 0, 0, 0, // PC_VMRP - IU, 0, 0, 0, 0, 0, // PC_SLE - IU, 0, 0, 0, 0, 0, // PC_SLEQ - IU, 0, 0, 0, 0, 0, // PC_SLIQ - IU, 0, 0, 0, 0, 0, // PC_SLLIQ - IU, 0, 0, 0, 0, 0, // PC_SLLQ - IU, 0, 0, 0, 0, 0, // PC_SLQ - IU, 0, 0, 0, 0, 0, // PC_SRAIQ - IU, 0, 0, 0, 0, 0, // PC_SRAQ - IU, 0, 0, 0, 0, 0, // PC_SRE - IU, 0, 0, 0, 0, 0, // PC_SREA - IU, 0, 0, 0, 0, 0, // PC_SREQ - IU, 0, 0, 0, 0, 0, // PC_SRIQ - IU, 0, 0, 0, 0, 0, // PC_SRLIQ - IU, 0, 0, 0, 0, 0, // PC_SRLQ - IU, 0, 0, 0, 0, 0, // PC_SRQ - IU, 0, 0, 0, 0, 0, // PC_MASKG - IU, 0, 0, 0, 0, 0, // PC_MASKIR - IU, 0, 0, 0, 0, 0, // PC_LSCBX - IU, 0, 0, 0, 0, 0, // PC_DIV - IU, 0, 0, 0, 0, 0, // PC_DIVS - IU, 0, 0, 0, 0, 0, // PC_DOZ - IU, 0, 0, 0, 0, 0, // PC_MUL - IU, 0, 0, 0, 0, 0, // PC_NABS - IU, 0, 0, 0, 0, 0, // PC_ABS - IU, 0, 0, 0, 0, 0, // PC_CLCS - IU, 0, 0, 0, 0, 0, // PC_DOZI - IU, 0, 0, 0, 0, 0, // PC_RLMI - IU, 0, 0, 0, 0, 0, // PC_RRIB -}; - -static void advance(int stageCount, int oldStage, int newStage) { - PCode *instr = pipeline[oldStage].instr; - int cycles = instruction_timing[instr->op].cycles[newStage - stageCount]; - pipeline[newStage].instr = instr; - pipeline[newStage].remaining = cycles; - pipeline[oldStage].instr = NULL; -} - -static void complete_instruction(int stage) { - pipeline[stage].instr = NULL; -} - -static int latency(PCode *instr) { - int cycles = instruction_timing[instr->op].latency; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - cycles += 2; - if (instr->op == PC_LMW || instr->op == PC_STMW) - cycles += instr->argCount - 2; - return cycles; -} - -static void initialize(void) { - int stage; - - for (stage = 0; stage < NumStages; stage++) - pipeline[stage].instr = NULL; -} - -static int can_issue(PCode *instr) { - int stage = instruction_timing[instr->op].stage; - if (stage == Serialize) - stage = IU; - if (pipeline[stage].instr) - return 0; - return 1; -} - -static void issue(PCode *instr) { - int stage = instruction_timing[instr->op].stage; - int cycles = instruction_timing[instr->op].cycles[IU]; - if (stage == Serialize) - stage = IU; - pipeline[stage].instr = instr; - pipeline[stage].remaining = cycles; -} - -static void advance_clock(void) { - int stage; - - for (stage = 0; stage < NumStages; stage++) { - if (pipeline[stage].instr && pipeline[stage].remaining) - --pipeline[stage].remaining; - } - - if (pipeline[IU].instr && pipeline[IU].remaining == 0) - complete_instruction(IU); - if (pipeline[FWA].instr && pipeline[FWA].remaining == 0) - complete_instruction(FWA); - if (pipeline[BPU].instr && pipeline[BPU].remaining == 0) - complete_instruction(BPU); - - if (pipeline[FPA].instr && pipeline[FPA].remaining == 0 && !pipeline[FWA].instr) - advance(1, FPA, FWA); - if (pipeline[FPM].instr && pipeline[FPM].remaining == 0 && !pipeline[FPA].instr) - advance(1, FPM, FPA); - if (pipeline[FD].instr && pipeline[FD].remaining == 0 && !pipeline[FPM].instr) - advance(1, FD, FPM); -} - -static int serializes(PCode *instr) { - return instruction_timing[instr->op].stage == Serialize; -} - -MachineInfo machine601 = { - 2, - 0, - 0, - &latency, - &initialize, - &can_issue, - &issue, - &advance_clock, - &serializes, - &default_uses_vpermute_unit -}; diff --git a/compiler_and_linker/unsorted/MachineSimulation603.c b/compiler_and_linker/unsorted/MachineSimulation603.c deleted file mode 100644 index 49d1ea0..0000000 --- a/compiler_and_linker/unsorted/MachineSimulation603.c +++ /dev/null @@ -1,626 +0,0 @@ -#include "compiler/Scheduler.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" - -// this is actually for 603e, but i couldn't find the 603 doc -// https://www.nxp.com/docs/en/reference-manual/MPC603EUM.pdf - -typedef enum Stage { - BPU, // Branch Prediction Unit - IU, // Integer Unit - LSU1, // Load/Store Unit - LSU2, - FPU1, // Floating Point Unit - FPU2, - FPU3, - SRU, // System Register Unit - NumStages -} Stage; - -static struct { - // the instruction currently in this pipeline stage - PCode *instr; - - // how many cycles are left for this instruction to finish - int remaining; -} pipeline[NumStages]; - -enum { - MaxEntries = 5 -}; - -static struct { - // how many entries remain unused in the queue - unsigned int free; - - // how many entries are currently used in the queue - unsigned int used; - - // the index of the next instruction that will be retired - unsigned int nextToRetire; - - // the index of the next free slot that will be used when an instruction is dispatched - unsigned int nextFreeSlot; - - // circular array of entries in the completion queue - struct { - PCode *instr; - int completed; - } entries[MaxEntries]; -} completionbuffers; - -static struct { - // the initial stage for this instruction - Stage stage; - - // the total amount of cycles required by this instruction - char latency; - - // how long it takes to finish each stage - char cycles[3]; - - // does this instruction serialise? - char serializes; -} instruction_timing[OPCODE_MAX] = { - BPU, 0, 0, 0, 0, 1, // PC_B - BPU, 0, 0, 0, 0, 1, // PC_BL - BPU, 0, 0, 0, 0, 1, // PC_BC - BPU, 0, 0, 0, 0, 1, // PC_BCLR - BPU, 0, 0, 0, 0, 1, // PC_BCCTR - BPU, 0, 0, 0, 0, 1, // PC_BT - BPU, 0, 0, 0, 0, 1, // PC_BTLR - BPU, 0, 0, 0, 0, 1, // PC_BTCTR - BPU, 0, 0, 0, 0, 1, // PC_BF - BPU, 0, 0, 0, 0, 1, // PC_BFLR - BPU, 0, 0, 0, 0, 1, // PC_BFCTR - BPU, 0, 0, 0, 0, 1, // PC_BDNZ - BPU, 0, 0, 0, 0, 1, // PC_BDNZT - BPU, 0, 0, 0, 0, 1, // PC_BDNZF - BPU, 0, 0, 0, 0, 1, // PC_BDZ - BPU, 0, 0, 0, 0, 1, // PC_BDZT - BPU, 0, 0, 0, 0, 1, // PC_BDZF - BPU, 0, 0, 0, 0, 1, // PC_BLR - BPU, 0, 0, 0, 0, 1, // PC_BCTR - BPU, 0, 0, 0, 0, 1, // PC_BCTRL - BPU, 0, 0, 0, 0, 1, // PC_BLRL - LSU1, 2, 1, 1, 0, 0, // PC_LBZ - LSU1, 2, 1, 1, 0, 0, // PC_LBZU - LSU1, 2, 1, 1, 0, 0, // PC_LBZX - LSU1, 2, 1, 1, 0, 0, // PC_LBZUX - LSU1, 2, 1, 1, 0, 0, // PC_LHZ - LSU1, 2, 1, 1, 0, 0, // PC_LHZU - LSU1, 2, 1, 1, 0, 0, // PC_LHZX - LSU1, 2, 1, 1, 0, 0, // PC_LHZUX - LSU1, 2, 1, 1, 0, 0, // PC_LHA - LSU1, 2, 1, 1, 0, 0, // PC_LHAU - LSU1, 2, 1, 1, 0, 0, // PC_LHAX - LSU1, 2, 1, 1, 0, 0, // PC_LHAUX - LSU1, 2, 1, 1, 0, 0, // PC_LHBRX - LSU1, 2, 1, 1, 0, 0, // PC_LWZ - LSU1, 2, 1, 1, 0, 0, // PC_LWZU - LSU1, 2, 1, 1, 0, 0, // PC_LWZX - LSU1, 2, 1, 1, 0, 0, // PC_LWZUX - LSU1, 2, 1, 1, 0, 0, // PC_LWBRX - LSU1, 2, 1, 1, 0, 0, // PC_LMW - LSU1, 2, 1, 1, 0, 0, // PC_STB - LSU1, 2, 1, 1, 0, 0, // PC_STBU - LSU1, 2, 1, 1, 0, 0, // PC_STBX - LSU1, 2, 1, 1, 0, 0, // PC_STBUX - LSU1, 2, 1, 1, 0, 0, // PC_STH - LSU1, 2, 1, 1, 0, 0, // PC_STHU - LSU1, 2, 1, 1, 0, 0, // PC_STHX - LSU1, 2, 1, 1, 0, 0, // PC_STHUX - LSU1, 2, 1, 1, 0, 0, // PC_STHBRX - LSU1, 2, 1, 1, 0, 0, // PC_STW - LSU1, 2, 1, 1, 0, 0, // PC_STWU - LSU1, 2, 1, 1, 0, 0, // PC_STWX - LSU1, 2, 1, 1, 0, 0, // PC_STWUX - LSU1, 2, 1, 1, 0, 0, // PC_STWBRX - LSU1, 2, 1, 1, 0, 0, // PC_STMW - LSU1, 2, 1, 1, 0, 0, // PC_DCBF - LSU1, 2, 1, 1, 0, 0, // PC_DCBST - LSU1, 2, 1, 1, 0, 0, // PC_DCBT - LSU1, 2, 1, 1, 0, 0, // PC_DCBTST - LSU1, 2, 1, 1, 0, 0, // PC_DCBZ - IU, 1, 1, 0, 0, 0, // PC_ADD - IU, 1, 1, 0, 0, 0, // PC_ADDC - IU, 1, 1, 0, 0, 0, // PC_ADDE - IU, 1, 1, 0, 0, 0, // PC_ADDI - IU, 1, 1, 0, 0, 0, // PC_ADDIC - IU, 1, 1, 0, 0, 0, // PC_ADDICR - IU, 1, 1, 0, 0, 0, // PC_ADDIS - IU, 1, 1, 0, 0, 0, // PC_ADDME - IU, 1, 1, 0, 0, 0, // PC_ADDZE - IU, 37, 37, 0, 0, 0, // PC_DIVW - IU, 37, 37, 0, 0, 0, // PC_DIVWU - IU, 5, 5, 0, 0, 0, // PC_MULHW - IU, 5, 5, 0, 0, 0, // PC_MULHWU - IU, 3, 3, 0, 0, 0, // PC_MULLI - IU, 5, 5, 0, 0, 0, // PC_MULLW - IU, 1, 1, 0, 0, 0, // PC_NEG - IU, 1, 1, 0, 0, 0, // PC_SUBF - IU, 1, 1, 0, 0, 0, // PC_SUBFC - IU, 1, 1, 0, 0, 0, // PC_SUBFE - IU, 1, 1, 0, 0, 0, // PC_SUBFIC - IU, 1, 1, 0, 0, 0, // PC_SUBFME - IU, 1, 1, 0, 0, 0, // PC_SUBFZE - IU, 3, 1, 0, 0, 0, // PC_CMPI - IU, 3, 1, 0, 0, 0, // PC_CMP - IU, 3, 1, 0, 0, 0, // PC_CMPLI - IU, 3, 1, 0, 0, 0, // PC_CMPL - IU, 1, 1, 0, 0, 0, // PC_ANDI - IU, 1, 1, 0, 0, 0, // PC_ANDIS - IU, 1, 1, 0, 0, 0, // PC_ORI - IU, 1, 1, 0, 0, 0, // PC_ORIS - IU, 1, 1, 0, 0, 0, // PC_XORI - IU, 1, 1, 0, 0, 0, // PC_XORIS - IU, 1, 1, 0, 0, 0, // PC_AND - IU, 1, 1, 0, 0, 0, // PC_OR - IU, 1, 1, 0, 0, 0, // PC_XOR - IU, 1, 1, 0, 0, 0, // PC_NAND - IU, 1, 1, 0, 0, 0, // PC_NOR - IU, 1, 1, 0, 0, 0, // PC_EQV - IU, 1, 1, 0, 0, 0, // PC_ANDC - IU, 1, 1, 0, 0, 0, // PC_ORC - IU, 1, 1, 0, 0, 0, // PC_EXTSB - IU, 1, 1, 0, 0, 0, // PC_EXTSH - IU, 1, 1, 0, 0, 0, // PC_CNTLZW - IU, 1, 1, 0, 0, 0, // PC_RLWINM - IU, 1, 1, 0, 0, 0, // PC_RLWNM - IU, 1, 1, 0, 0, 0, // PC_RLWIMI - IU, 1, 1, 0, 0, 0, // PC_SLW - IU, 1, 1, 0, 0, 0, // PC_SRW - IU, 1, 1, 0, 0, 0, // PC_SRAWI - IU, 1, 1, 0, 0, 0, // PC_SRAW - SRU, 1, 1, 0, 0, 0, // PC_CRAND - SRU, 1, 1, 0, 0, 0, // PC_CRANDC - SRU, 1, 1, 0, 0, 0, // PC_CREQV - SRU, 1, 1, 0, 0, 0, // PC_CRNAND - SRU, 1, 1, 0, 0, 0, // PC_CRNOR - SRU, 1, 1, 0, 0, 0, // PC_CROR - SRU, 1, 1, 0, 0, 0, // PC_CRORC - SRU, 1, 1, 0, 0, 0, // PC_CRXOR - SRU, 1, 1, 0, 0, 0, // PC_MCRF - SRU, 2, 2, 0, 0, 0, // PC_MTXER - SRU, 2, 2, 0, 0, 0, // PC_MTCTR - SRU, 2, 2, 0, 0, 0, // PC_MTLR - SRU, 1, 1, 0, 0, 0, // PC_MTCRF - SRU, 1, 1, 0, 0, 1, // PC_MTMSR - SRU, 1, 1, 0, 0, 1, // PC_MTSPR - SRU, 1, 1, 0, 0, 1, // PC_MFMSR - SRU, 1, 1, 0, 0, 1, // PC_MFSPR - SRU, 1, 1, 0, 0, 0, // PC_MFXER - SRU, 1, 1, 0, 0, 0, // PC_MFCTR - SRU, 1, 1, 0, 0, 0, // PC_MFLR - SRU, 1, 1, 0, 0, 0, // PC_MFCR - FPU1, 3, 1, 1, 1, 0, // PC_MFFS - FPU1, 3, 1, 1, 1, 0, // PC_MTFSF - SRU, 1, 1, 0, 0, 1, // PC_EIEIO - SRU, 1, 1, 0, 0, 1, // PC_ISYNC - SRU, 1, 1, 0, 0, 1, // PC_SYNC - SRU, 1, 1, 0, 0, 1, // PC_RFI - IU, 1, 1, 0, 0, 0, // PC_LI - IU, 1, 1, 0, 0, 0, // PC_LIS - IU, 1, 1, 0, 0, 0, // PC_MR - IU, 1, 1, 0, 0, 0, // PC_NOP - IU, 1, 1, 0, 0, 0, // PC_NOT - LSU1, 2, 1, 1, 0, 0, // PC_LFS - LSU1, 2, 1, 1, 0, 0, // PC_LFSU - LSU1, 2, 1, 1, 0, 0, // PC_LFSX - LSU1, 2, 1, 1, 0, 0, // PC_LFSUX - LSU1, 2, 1, 1, 0, 0, // PC_LFD - LSU1, 2, 1, 1, 0, 0, // PC_LFDU - LSU1, 2, 1, 1, 0, 0, // PC_LFDX - LSU1, 2, 1, 1, 0, 0, // PC_LFDUX - LSU1, 2, 1, 1, 0, 0, // PC_STFS - LSU1, 2, 1, 1, 0, 0, // PC_STFSU - LSU1, 2, 1, 1, 0, 0, // PC_STFSX - LSU1, 2, 1, 1, 0, 0, // PC_STFSUX - LSU1, 2, 1, 1, 0, 0, // PC_STFD - LSU1, 2, 1, 1, 0, 0, // PC_STFDU - LSU1, 2, 1, 1, 0, 0, // PC_STFDX - LSU1, 2, 1, 1, 0, 0, // PC_STFDUX - FPU1, 3, 1, 1, 1, 0, // PC_FMR - FPU1, 3, 1, 1, 1, 0, // PC_FABS - FPU1, 3, 1, 1, 1, 0, // PC_FNEG - FPU1, 3, 1, 1, 1, 0, // PC_FNABS - FPU1, 3, 1, 1, 1, 0, // PC_FADD - FPU1, 3, 1, 1, 1, 0, // PC_FADDS - FPU1, 3, 1, 1, 1, 0, // PC_FSUB - FPU1, 3, 1, 1, 1, 0, // PC_FSUBS - FPU1, 4, 2, 1, 1, 0, // PC_FMUL - FPU1, 3, 1, 1, 1, 0, // PC_FMULS - FPU1, 33, 33, 0, 0, 0, // PC_FDIV - FPU1, 18, 18, 0, 0, 0, // PC_FDIVS - FPU1, 4, 2, 1, 1, 0, // PC_FMADD - FPU1, 3, 1, 1, 1, 0, // PC_FMADDS - FPU1, 4, 2, 1, 1, 0, // PC_FMSUB - FPU1, 3, 1, 1, 1, 0, // PC_FMSUBS - FPU1, 4, 2, 1, 1, 0, // PC_FNMADD - FPU1, 3, 1, 1, 1, 0, // PC_FNMADDS - FPU1, 4, 2, 1, 1, 0, // PC_FNMSUB - FPU1, 3, 1, 1, 1, 0, // PC_FNMSUBS - FPU1, 18, 18, 0, 0, 0, // PC_FRES - FPU1, 3, 1, 1, 1, 0, // PC_FRSQRTE - FPU1, 3, 1, 1, 1, 0, // PC_FSEL - FPU1, 3, 1, 1, 1, 0, // PC_FRSP - FPU1, 3, 1, 1, 1, 0, // PC_FCTIW - FPU1, 3, 1, 1, 1, 0, // PC_FCTIWZ - FPU1, 5, 1, 1, 1, 0, // PC_FCMPU - FPU1, 5, 1, 1, 1, 0, // PC_FCMPO - LSU1, 1, 1, 0, 0, 0, // PC_LWARX - LSU1, 1, 1, 0, 0, 0, // PC_LSWI - LSU1, 1, 1, 0, 0, 0, // PC_LSWX - LSU1, 1, 1, 0, 0, 0, // PC_STFIWX - LSU1, 1, 1, 0, 0, 0, // PC_STSWI - LSU1, 1, 1, 0, 0, 0, // PC_STSWX - LSU1, 1, 1, 0, 0, 0, // PC_STWCX - IU, 1, 1, 0, 0, 1, // PC_ECIWX - IU, 1, 1, 0, 0, 1, // PC_ECOWX - IU, 1, 1, 0, 0, 0, // PC_DCBI - IU, 1, 1, 0, 0, 0, // PC_ICBI - IU, 1, 1, 0, 0, 0, // PC_MCRFS - IU, 1, 1, 0, 0, 0, // PC_MCRXR - IU, 1, 1, 0, 0, 0, // PC_MFTB - IU, 1, 1, 0, 0, 0, // PC_MFSR - IU, 1, 1, 0, 0, 0, // PC_MTSR - IU, 1, 1, 0, 0, 0, // PC_MFSRIN - IU, 1, 1, 0, 0, 0, // PC_MTSRIN - IU, 1, 1, 0, 0, 0, // PC_MTFSB0 - IU, 1, 1, 0, 0, 0, // PC_MTFSB1 - IU, 1, 1, 0, 0, 0, // PC_MTFSFI - IU, 1, 1, 0, 0, 1, // PC_SC - FPU1, 1, 1, 0, 0, 0, // PC_FSQRT - FPU1, 1, 1, 0, 0, 0, // PC_FSQRTS - IU, 1, 1, 0, 0, 0, // PC_TLBIA - IU, 1, 1, 0, 0, 0, // PC_TLBIE - IU, 1, 1, 0, 0, 0, // PC_TLBLD - IU, 1, 1, 0, 0, 0, // PC_TLBLI - IU, 1, 1, 0, 0, 0, // PC_TLBSYNC - IU, 1, 1, 0, 0, 1, // PC_TW - IU, 1, 1, 0, 0, 1, // PC_TRAP - IU, 1, 1, 0, 0, 1, // PC_TWI - IU, 1, 1, 0, 0, 1, // PC_OPWORD - IU, 1, 1, 0, 0, 0, // PC_MFROM - IU, 1, 1, 0, 0, 1, // PC_DSA - IU, 1, 1, 0, 0, 1, // PC_ESA - IU, 0, 0, 0, 0, 0, // PC_DCCCI - IU, 0, 0, 0, 0, 0, // PC_DCREAD - IU, 0, 0, 0, 0, 0, // PC_ICBT - IU, 0, 0, 0, 0, 0, // PC_ICCCI - IU, 0, 0, 0, 0, 0, // PC_ICREAD - IU, 0, 0, 0, 0, 0, // PC_RFCI - IU, 0, 0, 0, 0, 0, // PC_TLBRE - IU, 0, 0, 0, 0, 0, // PC_TLBSX - IU, 0, 0, 0, 0, 0, // PC_TLBWE - IU, 0, 0, 0, 0, 0, // PC_WRTEE - IU, 0, 0, 0, 0, 0, // PC_WRTEEI - IU, 0, 0, 0, 0, 0, // PC_MFDCR - IU, 0, 0, 0, 0, 0, // PC_MTDCR - IU, 0, 0, 0, 0, 0, // PC_DCBA - BPU, 0, 0, 0, 0, 0, // PC_DSS - BPU, 0, 0, 0, 0, 0, // PC_DSSALL - BPU, 0, 0, 0, 0, 0, // PC_DST - BPU, 0, 0, 0, 0, 0, // PC_DSTT - BPU, 0, 0, 0, 0, 0, // PC_DSTST - BPU, 0, 0, 0, 0, 0, // PC_DSTSTT - BPU, 0, 0, 0, 0, 0, // PC_LVEBX - BPU, 0, 0, 0, 0, 0, // PC_LVEHX - BPU, 0, 0, 0, 0, 0, // PC_LVEWX - BPU, 0, 0, 0, 0, 0, // PC_LVSL - BPU, 0, 0, 0, 0, 0, // PC_LVSR - BPU, 0, 0, 0, 0, 0, // PC_LVX - BPU, 0, 0, 0, 0, 0, // PC_LVXL - BPU, 0, 0, 0, 0, 0, // PC_STVEBX - BPU, 0, 0, 0, 0, 0, // PC_STVEHX - BPU, 0, 0, 0, 0, 0, // PC_STVEWX - BPU, 0, 0, 0, 0, 0, // PC_STVX - BPU, 0, 0, 0, 0, 0, // PC_STVXL - BPU, 0, 0, 0, 0, 0, // PC_MFVSCR - BPU, 0, 0, 0, 0, 0, // PC_MTVSCR - BPU, 0, 0, 0, 0, 0, // PC_VADDCUW - BPU, 0, 0, 0, 0, 0, // PC_VADDFP - BPU, 0, 0, 0, 0, 0, // PC_VADDSBS - BPU, 0, 0, 0, 0, 0, // PC_VADDSHS - BPU, 0, 0, 0, 0, 0, // PC_VADDSWS - BPU, 0, 0, 0, 0, 0, // PC_VADDUBM - BPU, 0, 0, 0, 0, 0, // PC_VADDUBS - BPU, 0, 0, 0, 0, 0, // PC_VADDUHM - BPU, 0, 0, 0, 0, 0, // PC_VADDUHS - BPU, 0, 0, 0, 0, 0, // PC_VADDUWM - BPU, 0, 0, 0, 0, 0, // PC_VADDUWS - BPU, 0, 0, 0, 0, 0, // PC_VAND - BPU, 0, 0, 0, 0, 0, // PC_VANDC - BPU, 0, 0, 0, 0, 0, // PC_VAVGSB - BPU, 0, 0, 0, 0, 0, // PC_VAVGSH - BPU, 0, 0, 0, 0, 0, // PC_VAVGSW - BPU, 0, 0, 0, 0, 0, // PC_VAVGUB - BPU, 0, 0, 0, 0, 0, // PC_VAVGUH - BPU, 0, 0, 0, 0, 0, // PC_VAVGUW - BPU, 0, 0, 0, 0, 0, // PC_VCFSX - BPU, 0, 0, 0, 0, 0, // PC_VCFUX - BPU, 0, 0, 0, 0, 0, // PC_VCMPBFP - BPU, 0, 0, 0, 0, 0, // PC_VCMPEQFP - BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUB - BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUH - BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUW - BPU, 0, 0, 0, 0, 0, // PC_VCMPGEFP - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTFP - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSB - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSH - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSW - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUB - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUH - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUW - BPU, 0, 0, 0, 0, 0, // PC_VCTSXS - BPU, 0, 0, 0, 0, 0, // PC_VCTUXS - BPU, 0, 0, 0, 0, 0, // PC_VEXPTEFP - BPU, 0, 0, 0, 0, 0, // PC_VLOGEFP - BPU, 0, 0, 0, 0, 0, // PC_VMAXFP - BPU, 0, 0, 0, 0, 0, // PC_VMAXSB - BPU, 0, 0, 0, 0, 0, // PC_VMAXSH - BPU, 0, 0, 0, 0, 0, // PC_VMAXSW - BPU, 0, 0, 0, 0, 0, // PC_VMAXUB - BPU, 0, 0, 0, 0, 0, // PC_VMAXUH - BPU, 0, 0, 0, 0, 0, // PC_VMAXUW - BPU, 0, 0, 0, 0, 0, // PC_VMINFP - BPU, 0, 0, 0, 0, 0, // PC_VMINSB - BPU, 0, 0, 0, 0, 0, // PC_VMINSH - BPU, 0, 0, 0, 0, 0, // PC_VMINSW - BPU, 0, 0, 0, 0, 0, // PC_VMINUB - BPU, 0, 0, 0, 0, 0, // PC_VMINUH - BPU, 0, 0, 0, 0, 0, // PC_VMINUW - BPU, 0, 0, 0, 0, 0, // PC_VMRGHB - BPU, 0, 0, 0, 0, 0, // PC_VMRGHH - BPU, 0, 0, 0, 0, 0, // PC_VMRGHW - BPU, 0, 0, 0, 0, 0, // PC_VMRGLB - BPU, 0, 0, 0, 0, 0, // PC_VMRGLH - BPU, 0, 0, 0, 0, 0, // PC_VMRGLW - BPU, 0, 0, 0, 0, 0, // PC_VMULESB - BPU, 0, 0, 0, 0, 0, // PC_VMULESH - BPU, 0, 0, 0, 0, 0, // PC_VMULEUB - BPU, 0, 0, 0, 0, 0, // PC_VMULEUH - BPU, 0, 0, 0, 0, 0, // PC_VMULOSB - BPU, 0, 0, 0, 0, 0, // PC_VMULOSH - BPU, 0, 0, 0, 0, 0, // PC_VMULOUB - BPU, 0, 0, 0, 0, 0, // PC_VMULOUH - BPU, 0, 0, 0, 0, 0, // PC_VNOR - BPU, 0, 0, 0, 0, 0, // PC_VOR - BPU, 0, 0, 0, 0, 0, // PC_VPKPX - BPU, 0, 0, 0, 0, 0, // PC_VPKSHSS - BPU, 0, 0, 0, 0, 0, // PC_VPKSHUS - BPU, 0, 0, 0, 0, 0, // PC_VPKSWSS - BPU, 0, 0, 0, 0, 0, // PC_VPKSWUS - BPU, 0, 0, 0, 0, 0, // PC_VPKUHUM - BPU, 0, 0, 0, 0, 0, // PC_VPKUHUS - BPU, 0, 0, 0, 0, 0, // PC_VPKUWUM - BPU, 0, 0, 0, 0, 0, // PC_VPKUWUS - BPU, 0, 0, 0, 0, 0, // PC_VREFP - BPU, 0, 0, 0, 0, 0, // PC_VRFIM - BPU, 0, 0, 0, 0, 0, // PC_VRFIN - BPU, 0, 0, 0, 0, 0, // PC_VRFIP - BPU, 0, 0, 0, 0, 0, // PC_VRFIZ - BPU, 0, 0, 0, 0, 0, // PC_VRLB - BPU, 0, 0, 0, 0, 0, // PC_VRLH - BPU, 0, 0, 0, 0, 0, // PC_VRLW - BPU, 0, 0, 0, 0, 0, // PC_VRSQRTEFP - BPU, 0, 0, 0, 0, 0, // PC_VSL - BPU, 0, 0, 0, 0, 0, // PC_VSLB - BPU, 0, 0, 0, 0, 0, // PC_VSLH - BPU, 0, 0, 0, 0, 0, // PC_VSLO - BPU, 0, 0, 0, 0, 0, // PC_VSLW - BPU, 0, 0, 0, 0, 0, // PC_VSPLTB - BPU, 0, 0, 0, 0, 0, // PC_VSPLTH - BPU, 0, 0, 0, 0, 0, // PC_VSPLTW - BPU, 0, 0, 0, 0, 0, // PC_VSPLTISB - BPU, 0, 0, 0, 0, 0, // PC_VSPLTISH - BPU, 0, 0, 0, 0, 0, // PC_VSPLTISW - BPU, 0, 0, 0, 0, 0, // PC_VSR - BPU, 0, 0, 0, 0, 0, // PC_VSRAB - BPU, 0, 0, 0, 0, 0, // PC_VSRAH - BPU, 0, 0, 0, 0, 0, // PC_VSRAW - BPU, 0, 0, 0, 0, 0, // PC_VSRB - BPU, 0, 0, 0, 0, 0, // PC_VSRH - BPU, 0, 0, 0, 0, 0, // PC_VSRO - BPU, 0, 0, 0, 0, 0, // PC_VSRW - BPU, 0, 0, 0, 0, 0, // PC_VSUBCUW - BPU, 0, 0, 0, 0, 0, // PC_VSUBFP - BPU, 0, 0, 0, 0, 0, // PC_VSUBSBS - BPU, 0, 0, 0, 0, 0, // PC_VSUBSHS - BPU, 0, 0, 0, 0, 0, // PC_VSUBSWS - BPU, 0, 0, 0, 0, 0, // PC_VSUBUBM - BPU, 0, 0, 0, 0, 0, // PC_VSUBUBS - BPU, 0, 0, 0, 0, 0, // PC_VSUBUHM - BPU, 0, 0, 0, 0, 0, // PC_VSUBUHS - BPU, 0, 0, 0, 0, 0, // PC_VSUBUWM - BPU, 0, 0, 0, 0, 0, // PC_VSUBUWS - BPU, 0, 0, 0, 0, 0, // PC_VSUMSWS - BPU, 0, 0, 0, 0, 0, // PC_VSUM2SWS - BPU, 0, 0, 0, 0, 0, // PC_VSUM4SBS - BPU, 0, 0, 0, 0, 0, // PC_VSUM4SHS - BPU, 0, 0, 0, 0, 0, // PC_VSUM4UBS - BPU, 0, 0, 0, 0, 0, // PC_VUPKHPX - BPU, 0, 0, 0, 0, 0, // PC_VUPKHSB - BPU, 0, 0, 0, 0, 0, // PC_VUPKHSH - BPU, 0, 0, 0, 0, 0, // PC_VUPKLPX - BPU, 0, 0, 0, 0, 0, // PC_VUPKLSB - BPU, 0, 0, 0, 0, 0, // PC_VUPKLSH - BPU, 0, 0, 0, 0, 0, // PC_VXOR - BPU, 0, 0, 0, 0, 0, // PC_VMADDFP - BPU, 0, 0, 0, 0, 0, // PC_VMHADDSHS - BPU, 0, 0, 0, 0, 0, // PC_VMHRADDSHS - BPU, 0, 0, 0, 0, 0, // PC_VMLADDUHM - BPU, 0, 0, 0, 0, 0, // PC_VMSUMMBM - BPU, 0, 0, 0, 0, 0, // PC_VMSUMSHM - BPU, 0, 0, 0, 0, 0, // PC_VMSUMSHS - BPU, 0, 0, 0, 0, 0, // PC_VMSUMUBM - BPU, 0, 0, 0, 0, 0, // PC_VMSUMUHM - BPU, 0, 0, 0, 0, 0, // PC_VMSUMUHS - BPU, 0, 0, 0, 0, 0, // PC_VNMSUBFP - BPU, 0, 0, 0, 0, 0, // PC_VPERM - BPU, 0, 0, 0, 0, 0, // PC_VSEL - BPU, 0, 0, 0, 0, 0, // PC_VSLDOI - BPU, 0, 0, 0, 0, 0, // PC_VMR - BPU, 0, 0, 0, 0, 0, // PC_VMRP - BPU, 0, 0, 0, 0, 0, // PC_SLE - BPU, 0, 0, 0, 0, 0, // PC_SLEQ - BPU, 0, 0, 0, 0, 0, // PC_SLIQ - BPU, 0, 0, 0, 0, 0, // PC_SLLIQ - BPU, 0, 0, 0, 0, 0, // PC_SLLQ - BPU, 0, 0, 0, 0, 0, // PC_SLQ - BPU, 0, 0, 0, 0, 0, // PC_SRAIQ - BPU, 0, 0, 0, 0, 0, // PC_SRAQ - BPU, 0, 0, 0, 0, 0, // PC_SRE - BPU, 0, 0, 0, 0, 0, // PC_SREA - BPU, 0, 0, 0, 0, 0, // PC_SREQ - BPU, 0, 0, 0, 0, 0, // PC_SRIQ - BPU, 0, 0, 0, 0, 0, // PC_SRLIQ - BPU, 0, 0, 0, 0, 0, // PC_SRLQ - BPU, 0, 0, 0, 0, 0, // PC_SRQ - BPU, 0, 0, 0, 0, 0, // PC_MASKG - BPU, 0, 0, 0, 0, 0, // PC_MASKIR - BPU, 0, 0, 0, 0, 0, // PC_LSCBX - BPU, 0, 0, 0, 0, 0, // PC_DIV - BPU, 0, 0, 0, 0, 0, // PC_DIVS - BPU, 0, 0, 0, 0, 0, // PC_DOZ - BPU, 0, 0, 0, 0, 0, // PC_MUL - BPU, 0, 0, 0, 0, 0, // PC_NABS - BPU, 0, 0, 0, 0, 0, // PC_ABS - BPU, 0, 0, 0, 0, 0, // PC_CLCS - BPU, 0, 0, 0, 0, 0, // PC_DOZI - BPU, 0, 0, 0, 0, 0, // PC_RLMI - BPU, 0, 0, 0, 0, 0, // PC_RRIB -}; - -static void advance(int firstStage, int oldStage, int newStage) { - PCode *instr = pipeline[oldStage].instr; - int cycles = instruction_timing[instr->op].cycles[newStage - firstStage]; - pipeline[newStage].instr = instr; - pipeline[newStage].remaining = cycles; - pipeline[oldStage].instr = NULL; -} - -static void assign_completion_buffer(PCode *instr) { - completionbuffers.used++; - completionbuffers.free--; - completionbuffers.entries[completionbuffers.nextFreeSlot].instr = instr; - completionbuffers.entries[completionbuffers.nextFreeSlot].completed = 0; - completionbuffers.nextFreeSlot = (completionbuffers.nextFreeSlot + 1) % MaxEntries; -} - -static void complete_instruction(int stage) { - PCode *instr = pipeline[stage].instr; - int buf = 0; - while (buf < MaxEntries && completionbuffers.entries[buf].instr != instr) - buf++; - - completionbuffers.entries[buf].completed = 1; - pipeline[stage].instr = NULL; -} - -static void retire_instruction(void) { - completionbuffers.entries[completionbuffers.nextToRetire].instr = NULL; - completionbuffers.used--; - completionbuffers.free++; - completionbuffers.nextToRetire = (completionbuffers.nextToRetire + 1) % MaxEntries; -} - -static int latency(PCode *instr) { - int cycles = instruction_timing[instr->op].latency; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - cycles += 2; - if (instr->op == PC_LMW || instr->op == PC_STMW) - cycles += instr->argCount - 2; - return cycles; -} - -static void initialize(void) { - int stage; - int i; - - for (stage = 0; stage < NumStages; stage++) - pipeline[stage].instr = NULL; - - completionbuffers.free = 5; - completionbuffers.used = 0; - completionbuffers.nextToRetire = 0; - completionbuffers.nextFreeSlot = 0; - for (i = 0; i < MaxEntries; i++) - completionbuffers.entries[i].instr = NULL; -} - -static int can_issue(PCode *instr) { - if (completionbuffers.free == 0) - return 0; - if (pipeline[instruction_timing[instr->op].stage].instr) - return 0; - if ((instr->flags & fIsWrite) && pipeline[LSU2].instr && (pipeline[LSU2].instr->flags & fIsWrite)) - return 0; - return 1; -} - -static void issue(PCode *instr) { - int stage = instruction_timing[instr->op].stage; - int cycles = instruction_timing[instr->op].cycles[0]; - assign_completion_buffer(instr); - pipeline[stage].instr = instr; - pipeline[stage].remaining = cycles; -} - -static void advance_clock(void) { - int stage; - - for (stage = 0; stage < NumStages; stage++) { - if (pipeline[stage].instr && pipeline[stage].remaining) - --pipeline[stage].remaining; - } - - if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { - retire_instruction(); - if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { - retire_instruction(); - } - } - - if (pipeline[IU].instr && pipeline[IU].remaining == 0) - complete_instruction(IU); - if (pipeline[LSU2].instr && pipeline[LSU2].remaining == 0) - complete_instruction(LSU2); - if (pipeline[FPU3].instr && pipeline[FPU3].remaining == 0) - complete_instruction(FPU3); - if (pipeline[SRU].instr && pipeline[SRU].remaining == 0) - complete_instruction(SRU); - if (pipeline[BPU].instr && pipeline[BPU].remaining == 0) - complete_instruction(BPU); - - if ( - pipeline[FPU1].instr && - pipeline[FPU1].remaining == 0 && - (pipeline[FPU1].instr->op == PC_FDIV || pipeline[FPU1].instr->op == PC_FDIVS) - ) - complete_instruction(FPU1); - - if (pipeline[FPU2].instr && pipeline[FPU2].remaining == 0 && !pipeline[FPU3].instr) - advance(FPU1, FPU2, FPU3); - if (pipeline[FPU1].instr && pipeline[FPU1].remaining == 0 && !pipeline[FPU2].instr) - advance(FPU1, FPU1, FPU2); - if (pipeline[LSU1].instr && pipeline[LSU1].remaining == 0 && !pipeline[LSU2].instr) - advance(LSU1, LSU1, LSU2); -} - -static int serializes(PCode *instr) { - return instruction_timing[instr->op].serializes; -} - -MachineInfo machine603 = { - 2, - 1, - 0, - &latency, - &initialize, - &can_issue, - &issue, - &advance_clock, - &serializes, - &default_uses_vpermute_unit -}; diff --git a/compiler_and_linker/unsorted/MachineSimulation603e.c b/compiler_and_linker/unsorted/MachineSimulation603e.c deleted file mode 100644 index d3e1e47..0000000 --- a/compiler_and_linker/unsorted/MachineSimulation603e.c +++ /dev/null @@ -1,650 +0,0 @@ -#include "compiler/Scheduler.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" - -// https://www.nxp.com/docs/en/reference-manual/MPC603EUM.pdf - -typedef enum Stage { - BPU, // Branch Prediction Unit - IU, // Integer Unit - LSU1, // Load/Store Unit - LSU2, - FPU1, // Floating Point Unit - FPU2, - FPU3, - SRU, // System Register Unit - NumStages -} Stage; - -static struct { - // the instruction currently in this pipeline stage - PCode *instr; - - // how many cycles are left for this instruction to finish - int remaining; -} pipeline[NumStages]; - -enum { - MaxEntries = 5 -}; - -static struct { - // how many entries remain unused in the queue - unsigned int free; - - // how many entries are currently used in the queue - unsigned int used; - - // the index of the next instruction that will be retired - unsigned int nextToRetire; - - // the index of the next free slot that will be used when an instruction is dispatched - unsigned int nextFreeSlot; - - // circular array of entries in the completion queue - struct { - PCode *instr; - int completed; - } entries[MaxEntries]; -} completionbuffers; - -static struct { - // the initial stage for this instruction - Stage stage; - - // the total amount of cycles required by this instruction - char latency; - - // how long it takes to finish each stage - char cycles[3]; - - // does this instruction serialise? - char serializes; -} instruction_timing[OPCODE_MAX] = { - BPU, 0, 0, 0, 0, 1, // PC_B - BPU, 0, 0, 0, 0, 1, // PC_BL - BPU, 0, 0, 0, 0, 1, // PC_BC - BPU, 0, 0, 0, 0, 1, // PC_BCLR - BPU, 0, 0, 0, 0, 1, // PC_BCCTR - BPU, 0, 0, 0, 0, 1, // PC_BT - BPU, 0, 0, 0, 0, 1, // PC_BTLR - BPU, 0, 0, 0, 0, 1, // PC_BTCTR - BPU, 0, 0, 0, 0, 1, // PC_BF - BPU, 0, 0, 0, 0, 1, // PC_BFLR - BPU, 0, 0, 0, 0, 1, // PC_BFCTR - BPU, 0, 0, 0, 0, 1, // PC_BDNZ - BPU, 0, 0, 0, 0, 1, // PC_BDNZT - BPU, 0, 0, 0, 0, 1, // PC_BDNZF - BPU, 0, 0, 0, 0, 1, // PC_BDZ - BPU, 0, 0, 0, 0, 1, // PC_BDZT - BPU, 0, 0, 0, 0, 1, // PC_BDZF - BPU, 0, 0, 0, 0, 1, // PC_BLR - BPU, 0, 0, 0, 0, 1, // PC_BCTR - BPU, 0, 0, 0, 0, 1, // PC_BCTRL - BPU, 0, 0, 0, 0, 1, // PC_BLRL - LSU1, 2, 1, 1, 0, 0, // PC_LBZ - LSU1, 2, 1, 1, 0, 0, // PC_LBZU - LSU1, 2, 1, 1, 0, 0, // PC_LBZX - LSU1, 2, 1, 1, 0, 0, // PC_LBZUX - LSU1, 2, 1, 1, 0, 0, // PC_LHZ - LSU1, 2, 1, 1, 0, 0, // PC_LHZU - LSU1, 2, 1, 1, 0, 0, // PC_LHZX - LSU1, 2, 1, 1, 0, 0, // PC_LHZUX - LSU1, 2, 1, 1, 0, 0, // PC_LHA - LSU1, 2, 1, 1, 0, 0, // PC_LHAU - LSU1, 2, 1, 1, 0, 0, // PC_LHAX - LSU1, 2, 1, 1, 0, 0, // PC_LHAUX - LSU1, 2, 1, 1, 0, 0, // PC_LHBRX - LSU1, 2, 1, 1, 0, 0, // PC_LWZ - LSU1, 2, 1, 1, 0, 0, // PC_LWZU - LSU1, 2, 1, 1, 0, 0, // PC_LWZX - LSU1, 2, 1, 1, 0, 0, // PC_LWZUX - LSU1, 2, 1, 1, 0, 0, // PC_LWBRX - LSU1, 2, 1, 1, 0, 0, // PC_LMW - LSU1, 2, 1, 1, 0, 0, // PC_STB - LSU1, 2, 1, 1, 0, 0, // PC_STBU - LSU1, 2, 1, 1, 0, 0, // PC_STBX - LSU1, 2, 1, 1, 0, 0, // PC_STBUX - LSU1, 2, 1, 1, 0, 0, // PC_STH - LSU1, 2, 1, 1, 0, 0, // PC_STHU - LSU1, 2, 1, 1, 0, 0, // PC_STHX - LSU1, 2, 1, 1, 0, 0, // PC_STHUX - LSU1, 2, 1, 1, 0, 0, // PC_STHBRX - LSU1, 2, 1, 1, 0, 0, // PC_STW - LSU1, 2, 1, 1, 0, 0, // PC_STWU - LSU1, 2, 1, 1, 0, 0, // PC_STWX - LSU1, 2, 1, 1, 0, 0, // PC_STWUX - LSU1, 2, 1, 1, 0, 0, // PC_STWBRX - LSU1, 2, 1, 1, 0, 0, // PC_STMW - LSU1, 2, 1, 1, 0, 0, // PC_DCBF - LSU1, 2, 1, 1, 0, 0, // PC_DCBST - LSU1, 2, 1, 1, 0, 0, // PC_DCBT - LSU1, 2, 1, 1, 0, 0, // PC_DCBTST - LSU1, 2, 1, 1, 0, 0, // PC_DCBZ - IU, 1, 1, 0, 0, 0, // PC_ADD - IU, 1, 1, 0, 0, 0, // PC_ADDC - IU, 1, 1, 0, 0, 0, // PC_ADDE - IU, 1, 1, 0, 0, 0, // PC_ADDI - IU, 1, 1, 0, 0, 0, // PC_ADDIC - IU, 1, 1, 0, 0, 0, // PC_ADDICR - IU, 1, 1, 0, 0, 0, // PC_ADDIS - IU, 1, 1, 0, 0, 0, // PC_ADDME - IU, 1, 1, 0, 0, 0, // PC_ADDZE - IU, 37, 37, 0, 0, 0, // PC_DIVW - IU, 37, 37, 0, 0, 0, // PC_DIVWU - IU, 5, 5, 0, 0, 0, // PC_MULHW - IU, 5, 5, 0, 0, 0, // PC_MULHWU - IU, 3, 3, 0, 0, 0, // PC_MULLI - IU, 5, 5, 0, 0, 0, // PC_MULLW - IU, 1, 1, 0, 0, 0, // PC_NEG - IU, 1, 1, 0, 0, 0, // PC_SUBF - IU, 1, 1, 0, 0, 0, // PC_SUBFC - IU, 1, 1, 0, 0, 0, // PC_SUBFE - IU, 1, 1, 0, 0, 0, // PC_SUBFIC - IU, 1, 1, 0, 0, 0, // PC_SUBFME - IU, 1, 1, 0, 0, 0, // PC_SUBFZE - IU, 3, 1, 0, 0, 0, // PC_CMPI - IU, 3, 1, 0, 0, 0, // PC_CMP - IU, 3, 1, 0, 0, 0, // PC_CMPLI - IU, 3, 1, 0, 0, 0, // PC_CMPL - IU, 1, 1, 0, 0, 0, // PC_ANDI - IU, 1, 1, 0, 0, 0, // PC_ANDIS - IU, 1, 1, 0, 0, 0, // PC_ORI - IU, 1, 1, 0, 0, 0, // PC_ORIS - IU, 1, 1, 0, 0, 0, // PC_XORI - IU, 1, 1, 0, 0, 0, // PC_XORIS - IU, 1, 1, 0, 0, 0, // PC_AND - IU, 1, 1, 0, 0, 0, // PC_OR - IU, 1, 1, 0, 0, 0, // PC_XOR - IU, 1, 1, 0, 0, 0, // PC_NAND - IU, 1, 1, 0, 0, 0, // PC_NOR - IU, 1, 1, 0, 0, 0, // PC_EQV - IU, 1, 1, 0, 0, 0, // PC_ANDC - IU, 1, 1, 0, 0, 0, // PC_ORC - IU, 1, 1, 0, 0, 0, // PC_EXTSB - IU, 1, 1, 0, 0, 0, // PC_EXTSH - IU, 1, 1, 0, 0, 0, // PC_CNTLZW - IU, 1, 1, 0, 0, 0, // PC_RLWINM - IU, 1, 1, 0, 0, 0, // PC_RLWNM - IU, 1, 1, 0, 0, 0, // PC_RLWIMI - IU, 1, 1, 0, 0, 0, // PC_SLW - IU, 1, 1, 0, 0, 0, // PC_SRW - IU, 1, 1, 0, 0, 0, // PC_SRAWI - IU, 1, 1, 0, 0, 0, // PC_SRAW - SRU, 1, 1, 0, 0, 0, // PC_CRAND - SRU, 1, 1, 0, 0, 0, // PC_CRANDC - SRU, 1, 1, 0, 0, 0, // PC_CREQV - SRU, 1, 1, 0, 0, 0, // PC_CRNAND - SRU, 1, 1, 0, 0, 0, // PC_CRNOR - SRU, 1, 1, 0, 0, 0, // PC_CROR - SRU, 1, 1, 0, 0, 0, // PC_CRORC - SRU, 1, 1, 0, 0, 0, // PC_CRXOR - SRU, 1, 1, 0, 0, 0, // PC_MCRF - SRU, 2, 2, 0, 0, 0, // PC_MTXER - SRU, 2, 2, 0, 0, 0, // PC_MTCTR - SRU, 2, 2, 0, 0, 0, // PC_MTLR - SRU, 1, 1, 0, 0, 0, // PC_MTCRF - SRU, 1, 1, 0, 0, 1, // PC_MTMSR - SRU, 1, 1, 0, 0, 1, // PC_MTSPR - SRU, 1, 1, 0, 0, 1, // PC_MFMSR - SRU, 1, 1, 0, 0, 1, // PC_MFSPR - SRU, 1, 1, 0, 0, 0, // PC_MFXER - SRU, 1, 1, 0, 0, 0, // PC_MFCTR - SRU, 1, 1, 0, 0, 0, // PC_MFLR - SRU, 1, 1, 0, 0, 0, // PC_MFCR - FPU1, 3, 1, 1, 1, 0, // PC_MFFS - FPU1, 3, 1, 1, 1, 0, // PC_MTFSF - SRU, 1, 1, 0, 0, 1, // PC_EIEIO - SRU, 1, 1, 0, 0, 1, // PC_ISYNC - SRU, 1, 1, 0, 0, 1, // PC_SYNC - SRU, 1, 1, 0, 0, 1, // PC_RFI - IU, 1, 1, 0, 0, 0, // PC_LI - IU, 1, 1, 0, 0, 0, // PC_LIS - IU, 1, 1, 0, 0, 0, // PC_MR - IU, 1, 1, 0, 0, 0, // PC_NOP - IU, 1, 1, 0, 0, 0, // PC_NOT - LSU1, 2, 1, 1, 0, 0, // PC_LFS - LSU1, 2, 1, 1, 0, 0, // PC_LFSU - LSU1, 2, 1, 1, 0, 0, // PC_LFSX - LSU1, 2, 1, 1, 0, 0, // PC_LFSUX - LSU1, 2, 1, 1, 0, 0, // PC_LFD - LSU1, 2, 1, 1, 0, 0, // PC_LFDU - LSU1, 2, 1, 1, 0, 0, // PC_LFDX - LSU1, 2, 1, 1, 0, 0, // PC_LFDUX - LSU1, 2, 1, 1, 0, 0, // PC_STFS - LSU1, 2, 1, 1, 0, 0, // PC_STFSU - LSU1, 2, 1, 1, 0, 0, // PC_STFSX - LSU1, 2, 1, 1, 0, 0, // PC_STFSUX - LSU1, 2, 1, 1, 0, 0, // PC_STFD - LSU1, 2, 1, 1, 0, 0, // PC_STFDU - LSU1, 2, 1, 1, 0, 0, // PC_STFDX - LSU1, 2, 1, 1, 0, 0, // PC_STFDUX - FPU1, 3, 1, 1, 1, 0, // PC_FMR - FPU1, 3, 1, 1, 1, 0, // PC_FABS - FPU1, 3, 1, 1, 1, 0, // PC_FNEG - FPU1, 3, 1, 1, 1, 0, // PC_FNABS - FPU1, 3, 1, 1, 1, 0, // PC_FADD - FPU1, 3, 1, 1, 1, 0, // PC_FADDS - FPU1, 3, 1, 1, 1, 0, // PC_FSUB - FPU1, 3, 1, 1, 1, 0, // PC_FSUBS - FPU1, 4, 2, 1, 1, 0, // PC_FMUL - FPU1, 3, 1, 1, 1, 0, // PC_FMULS - FPU1, 33, 33, 0, 0, 0, // PC_FDIV - FPU1, 18, 18, 0, 0, 0, // PC_FDIVS - FPU1, 4, 2, 1, 1, 0, // PC_FMADD - FPU1, 3, 1, 1, 1, 0, // PC_FMADDS - FPU1, 4, 2, 1, 1, 0, // PC_FMSUB - FPU1, 3, 1, 1, 1, 0, // PC_FMSUBS - FPU1, 4, 2, 1, 1, 0, // PC_FNMADD - FPU1, 3, 1, 1, 1, 0, // PC_FNMADDS - FPU1, 4, 2, 1, 1, 0, // PC_FNMSUB - FPU1, 3, 1, 1, 1, 0, // PC_FNMSUBS - FPU1, 18, 18, 0, 0, 0, // PC_FRES - FPU1, 3, 1, 1, 1, 0, // PC_FRSQRTE - FPU1, 3, 1, 1, 1, 0, // PC_FSEL - FPU1, 3, 1, 1, 1, 0, // PC_FRSP - FPU1, 3, 1, 1, 1, 0, // PC_FCTIW - FPU1, 3, 1, 1, 1, 0, // PC_FCTIWZ - FPU1, 5, 1, 1, 1, 0, // PC_FCMPU - FPU1, 5, 1, 1, 1, 0, // PC_FCMPO - LSU1, 1, 1, 0, 0, 0, // PC_LWARX - LSU1, 1, 1, 0, 0, 0, // PC_LSWI - LSU1, 1, 1, 0, 0, 0, // PC_LSWX - LSU1, 1, 1, 0, 0, 0, // PC_STFIWX - LSU1, 1, 1, 0, 0, 0, // PC_STSWI - LSU1, 1, 1, 0, 0, 0, // PC_STSWX - LSU1, 1, 1, 0, 0, 0, // PC_STWCX - IU, 1, 1, 0, 0, 1, // PC_ECIWX - IU, 1, 1, 0, 0, 1, // PC_ECOWX - IU, 1, 1, 0, 0, 0, // PC_DCBI - IU, 1, 1, 0, 0, 0, // PC_ICBI - IU, 1, 1, 0, 0, 0, // PC_MCRFS - IU, 1, 1, 0, 0, 0, // PC_MCRXR - IU, 1, 1, 0, 0, 0, // PC_MFTB - IU, 1, 1, 0, 0, 0, // PC_MFSR - IU, 1, 1, 0, 0, 0, // PC_MTSR - IU, 1, 1, 0, 0, 0, // PC_MFSRIN - IU, 1, 1, 0, 0, 0, // PC_MTSRIN - IU, 1, 1, 0, 0, 0, // PC_MTFSB0 - IU, 1, 1, 0, 0, 0, // PC_MTFSB1 - IU, 1, 1, 0, 0, 0, // PC_MTFSFI - IU, 1, 1, 0, 0, 1, // PC_SC - FPU1, 1, 1, 0, 0, 0, // PC_FSQRT - FPU1, 1, 1, 0, 0, 0, // PC_FSQRTS - IU, 1, 1, 0, 0, 0, // PC_TLBIA - IU, 1, 1, 0, 0, 0, // PC_TLBIE - IU, 1, 1, 0, 0, 0, // PC_TLBLD - IU, 1, 1, 0, 0, 0, // PC_TLBLI - IU, 1, 1, 0, 0, 0, // PC_TLBSYNC - IU, 1, 1, 0, 0, 1, // PC_TW - IU, 1, 1, 0, 0, 1, // PC_TRAP - IU, 1, 1, 0, 0, 1, // PC_TWI - IU, 1, 1, 0, 0, 1, // PC_OPWORD - IU, 1, 1, 0, 0, 0, // PC_MFROM - IU, 1, 1, 0, 0, 1, // PC_DSA - IU, 1, 1, 0, 0, 1, // PC_ESA - IU, 0, 0, 0, 0, 0, // PC_DCCCI - IU, 0, 0, 0, 0, 0, // PC_DCREAD - IU, 0, 0, 0, 0, 0, // PC_ICBT - IU, 0, 0, 0, 0, 0, // PC_ICCCI - IU, 0, 0, 0, 0, 0, // PC_ICREAD - IU, 0, 0, 0, 0, 0, // PC_RFCI - IU, 0, 0, 0, 0, 0, // PC_TLBRE - IU, 0, 0, 0, 0, 0, // PC_TLBSX - IU, 0, 0, 0, 0, 0, // PC_TLBWE - IU, 0, 0, 0, 0, 0, // PC_WRTEE - IU, 0, 0, 0, 0, 0, // PC_WRTEEI - IU, 0, 0, 0, 0, 0, // PC_MFDCR - IU, 0, 0, 0, 0, 0, // PC_MTDCR - IU, 0, 0, 0, 0, 0, // PC_DCBA - BPU, 0, 0, 0, 0, 0, // PC_DSS - BPU, 0, 0, 0, 0, 0, // PC_DSSALL - BPU, 0, 0, 0, 0, 0, // PC_DST - BPU, 0, 0, 0, 0, 0, // PC_DSTT - BPU, 0, 0, 0, 0, 0, // PC_DSTST - BPU, 0, 0, 0, 0, 0, // PC_DSTSTT - BPU, 0, 0, 0, 0, 0, // PC_LVEBX - BPU, 0, 0, 0, 0, 0, // PC_LVEHX - BPU, 0, 0, 0, 0, 0, // PC_LVEWX - BPU, 0, 0, 0, 0, 0, // PC_LVSL - BPU, 0, 0, 0, 0, 0, // PC_LVSR - BPU, 0, 0, 0, 0, 0, // PC_LVX - BPU, 0, 0, 0, 0, 0, // PC_LVXL - BPU, 0, 0, 0, 0, 0, // PC_STVEBX - BPU, 0, 0, 0, 0, 0, // PC_STVEHX - BPU, 0, 0, 0, 0, 0, // PC_STVEWX - BPU, 0, 0, 0, 0, 0, // PC_STVX - BPU, 0, 0, 0, 0, 0, // PC_STVXL - BPU, 0, 0, 0, 0, 0, // PC_MFVSCR - BPU, 0, 0, 0, 0, 0, // PC_MTVSCR - BPU, 0, 0, 0, 0, 0, // PC_VADDCUW - BPU, 0, 0, 0, 0, 0, // PC_VADDFP - BPU, 0, 0, 0, 0, 0, // PC_VADDSBS - BPU, 0, 0, 0, 0, 0, // PC_VADDSHS - BPU, 0, 0, 0, 0, 0, // PC_VADDSWS - BPU, 0, 0, 0, 0, 0, // PC_VADDUBM - BPU, 0, 0, 0, 0, 0, // PC_VADDUBS - BPU, 0, 0, 0, 0, 0, // PC_VADDUHM - BPU, 0, 0, 0, 0, 0, // PC_VADDUHS - BPU, 0, 0, 0, 0, 0, // PC_VADDUWM - BPU, 0, 0, 0, 0, 0, // PC_VADDUWS - BPU, 0, 0, 0, 0, 0, // PC_VAND - BPU, 0, 0, 0, 0, 0, // PC_VANDC - BPU, 0, 0, 0, 0, 0, // PC_VAVGSB - BPU, 0, 0, 0, 0, 0, // PC_VAVGSH - BPU, 0, 0, 0, 0, 0, // PC_VAVGSW - BPU, 0, 0, 0, 0, 0, // PC_VAVGUB - BPU, 0, 0, 0, 0, 0, // PC_VAVGUH - BPU, 0, 0, 0, 0, 0, // PC_VAVGUW - BPU, 0, 0, 0, 0, 0, // PC_VCFSX - BPU, 0, 0, 0, 0, 0, // PC_VCFUX - BPU, 0, 0, 0, 0, 0, // PC_VCMPBFP - BPU, 0, 0, 0, 0, 0, // PC_VCMPEQFP - BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUB - BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUH - BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUW - BPU, 0, 0, 0, 0, 0, // PC_VCMPGEFP - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTFP - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSB - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSH - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSW - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUB - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUH - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUW - BPU, 0, 0, 0, 0, 0, // PC_VCTSXS - BPU, 0, 0, 0, 0, 0, // PC_VCTUXS - BPU, 0, 0, 0, 0, 0, // PC_VEXPTEFP - BPU, 0, 0, 0, 0, 0, // PC_VLOGEFP - BPU, 0, 0, 0, 0, 0, // PC_VMAXFP - BPU, 0, 0, 0, 0, 0, // PC_VMAXSB - BPU, 0, 0, 0, 0, 0, // PC_VMAXSH - BPU, 0, 0, 0, 0, 0, // PC_VMAXSW - BPU, 0, 0, 0, 0, 0, // PC_VMAXUB - BPU, 0, 0, 0, 0, 0, // PC_VMAXUH - BPU, 0, 0, 0, 0, 0, // PC_VMAXUW - BPU, 0, 0, 0, 0, 0, // PC_VMINFP - BPU, 0, 0, 0, 0, 0, // PC_VMINSB - BPU, 0, 0, 0, 0, 0, // PC_VMINSH - BPU, 0, 0, 0, 0, 0, // PC_VMINSW - BPU, 0, 0, 0, 0, 0, // PC_VMINUB - BPU, 0, 0, 0, 0, 0, // PC_VMINUH - BPU, 0, 0, 0, 0, 0, // PC_VMINUW - BPU, 0, 0, 0, 0, 0, // PC_VMRGHB - BPU, 0, 0, 0, 0, 0, // PC_VMRGHH - BPU, 0, 0, 0, 0, 0, // PC_VMRGHW - BPU, 0, 0, 0, 0, 0, // PC_VMRGLB - BPU, 0, 0, 0, 0, 0, // PC_VMRGLH - BPU, 0, 0, 0, 0, 0, // PC_VMRGLW - BPU, 0, 0, 0, 0, 0, // PC_VMULESB - BPU, 0, 0, 0, 0, 0, // PC_VMULESH - BPU, 0, 0, 0, 0, 0, // PC_VMULEUB - BPU, 0, 0, 0, 0, 0, // PC_VMULEUH - BPU, 0, 0, 0, 0, 0, // PC_VMULOSB - BPU, 0, 0, 0, 0, 0, // PC_VMULOSH - BPU, 0, 0, 0, 0, 0, // PC_VMULOUB - BPU, 0, 0, 0, 0, 0, // PC_VMULOUH - BPU, 0, 0, 0, 0, 0, // PC_VNOR - BPU, 0, 0, 0, 0, 0, // PC_VOR - BPU, 0, 0, 0, 0, 0, // PC_VPKPX - BPU, 0, 0, 0, 0, 0, // PC_VPKSHSS - BPU, 0, 0, 0, 0, 0, // PC_VPKSHUS - BPU, 0, 0, 0, 0, 0, // PC_VPKSWSS - BPU, 0, 0, 0, 0, 0, // PC_VPKSWUS - BPU, 0, 0, 0, 0, 0, // PC_VPKUHUM - BPU, 0, 0, 0, 0, 0, // PC_VPKUHUS - BPU, 0, 0, 0, 0, 0, // PC_VPKUWUM - BPU, 0, 0, 0, 0, 0, // PC_VPKUWUS - BPU, 0, 0, 0, 0, 0, // PC_VREFP - BPU, 0, 0, 0, 0, 0, // PC_VRFIM - BPU, 0, 0, 0, 0, 0, // PC_VRFIN - BPU, 0, 0, 0, 0, 0, // PC_VRFIP - BPU, 0, 0, 0, 0, 0, // PC_VRFIZ - BPU, 0, 0, 0, 0, 0, // PC_VRLB - BPU, 0, 0, 0, 0, 0, // PC_VRLH - BPU, 0, 0, 0, 0, 0, // PC_VRLW - BPU, 0, 0, 0, 0, 0, // PC_VRSQRTEFP - BPU, 0, 0, 0, 0, 0, // PC_VSL - BPU, 0, 0, 0, 0, 0, // PC_VSLB - BPU, 0, 0, 0, 0, 0, // PC_VSLH - BPU, 0, 0, 0, 0, 0, // PC_VSLO - BPU, 0, 0, 0, 0, 0, // PC_VSLW - BPU, 0, 0, 0, 0, 0, // PC_VSPLTB - BPU, 0, 0, 0, 0, 0, // PC_VSPLTH - BPU, 0, 0, 0, 0, 0, // PC_VSPLTW - BPU, 0, 0, 0, 0, 0, // PC_VSPLTISB - BPU, 0, 0, 0, 0, 0, // PC_VSPLTISH - BPU, 0, 0, 0, 0, 0, // PC_VSPLTISW - BPU, 0, 0, 0, 0, 0, // PC_VSR - BPU, 0, 0, 0, 0, 0, // PC_VSRAB - BPU, 0, 0, 0, 0, 0, // PC_VSRAH - BPU, 0, 0, 0, 0, 0, // PC_VSRAW - BPU, 0, 0, 0, 0, 0, // PC_VSRB - BPU, 0, 0, 0, 0, 0, // PC_VSRH - BPU, 0, 0, 0, 0, 0, // PC_VSRO - BPU, 0, 0, 0, 0, 0, // PC_VSRW - BPU, 0, 0, 0, 0, 0, // PC_VSUBCUW - BPU, 0, 0, 0, 0, 0, // PC_VSUBFP - BPU, 0, 0, 0, 0, 0, // PC_VSUBSBS - BPU, 0, 0, 0, 0, 0, // PC_VSUBSHS - BPU, 0, 0, 0, 0, 0, // PC_VSUBSWS - BPU, 0, 0, 0, 0, 0, // PC_VSUBUBM - BPU, 0, 0, 0, 0, 0, // PC_VSUBUBS - BPU, 0, 0, 0, 0, 0, // PC_VSUBUHM - BPU, 0, 0, 0, 0, 0, // PC_VSUBUHS - BPU, 0, 0, 0, 0, 0, // PC_VSUBUWM - BPU, 0, 0, 0, 0, 0, // PC_VSUBUWS - BPU, 0, 0, 0, 0, 0, // PC_VSUMSWS - BPU, 0, 0, 0, 0, 0, // PC_VSUM2SWS - BPU, 0, 0, 0, 0, 0, // PC_VSUM4SBS - BPU, 0, 0, 0, 0, 0, // PC_VSUM4SHS - BPU, 0, 0, 0, 0, 0, // PC_VSUM4UBS - BPU, 0, 0, 0, 0, 0, // PC_VUPKHPX - BPU, 0, 0, 0, 0, 0, // PC_VUPKHSB - BPU, 0, 0, 0, 0, 0, // PC_VUPKHSH - BPU, 0, 0, 0, 0, 0, // PC_VUPKLPX - BPU, 0, 0, 0, 0, 0, // PC_VUPKLSB - BPU, 0, 0, 0, 0, 0, // PC_VUPKLSH - BPU, 0, 0, 0, 0, 0, // PC_VXOR - BPU, 0, 0, 0, 0, 0, // PC_VMADDFP - BPU, 0, 0, 0, 0, 0, // PC_VMHADDSHS - BPU, 0, 0, 0, 0, 0, // PC_VMHRADDSHS - BPU, 0, 0, 0, 0, 0, // PC_VMLADDUHM - BPU, 0, 0, 0, 0, 0, // PC_VMSUMMBM - BPU, 0, 0, 0, 0, 0, // PC_VMSUMSHM - BPU, 0, 0, 0, 0, 0, // PC_VMSUMSHS - BPU, 0, 0, 0, 0, 0, // PC_VMSUMUBM - BPU, 0, 0, 0, 0, 0, // PC_VMSUMUHM - BPU, 0, 0, 0, 0, 0, // PC_VMSUMUHS - BPU, 0, 0, 0, 0, 0, // PC_VNMSUBFP - BPU, 0, 0, 0, 0, 0, // PC_VPERM - BPU, 0, 0, 0, 0, 0, // PC_VSEL - BPU, 0, 0, 0, 0, 0, // PC_VSLDOI - BPU, 0, 0, 0, 0, 0, // PC_VMR - BPU, 0, 0, 0, 0, 0, // PC_VMRP - BPU, 0, 0, 0, 0, 0, // PC_SLE - BPU, 0, 0, 0, 0, 0, // PC_SLEQ - BPU, 0, 0, 0, 0, 0, // PC_SLIQ - BPU, 0, 0, 0, 0, 0, // PC_SLLIQ - BPU, 0, 0, 0, 0, 0, // PC_SLLQ - BPU, 0, 0, 0, 0, 0, // PC_SLQ - BPU, 0, 0, 0, 0, 0, // PC_SRAIQ - BPU, 0, 0, 0, 0, 0, // PC_SRAQ - BPU, 0, 0, 0, 0, 0, // PC_SRE - BPU, 0, 0, 0, 0, 0, // PC_SREA - BPU, 0, 0, 0, 0, 0, // PC_SREQ - BPU, 0, 0, 0, 0, 0, // PC_SRIQ - BPU, 0, 0, 0, 0, 0, // PC_SRLIQ - BPU, 0, 0, 0, 0, 0, // PC_SRLQ - BPU, 0, 0, 0, 0, 0, // PC_SRQ - BPU, 0, 0, 0, 0, 0, // PC_MASKG - BPU, 0, 0, 0, 0, 0, // PC_MASKIR - BPU, 0, 0, 0, 0, 0, // PC_LSCBX - BPU, 0, 0, 0, 0, 0, // PC_DIV - BPU, 0, 0, 0, 0, 0, // PC_DIVS - BPU, 0, 0, 0, 0, 0, // PC_DOZ - BPU, 0, 0, 0, 0, 0, // PC_MUL - BPU, 0, 0, 0, 0, 0, // PC_NABS - BPU, 0, 0, 0, 0, 0, // PC_ABS - BPU, 0, 0, 0, 0, 0, // PC_CLCS - BPU, 0, 0, 0, 0, 0, // PC_DOZI - BPU, 0, 0, 0, 0, 0, // PC_RLMI - BPU, 0, 0, 0, 0, 0, // PC_RRIB -}; - -static void advance(int firstStage, int oldStage, int newStage) { - PCode *instr = pipeline[oldStage].instr; - int cycles = instruction_timing[instr->op].cycles[newStage - firstStage]; - pipeline[newStage].instr = instr; - pipeline[newStage].remaining = cycles; - pipeline[oldStage].instr = NULL; -} - -static void assign_completion_buffer(PCode *instr) { - completionbuffers.used++; - completionbuffers.free--; - completionbuffers.entries[completionbuffers.nextFreeSlot].instr = instr; - completionbuffers.entries[completionbuffers.nextFreeSlot].completed = 0; - completionbuffers.nextFreeSlot = (completionbuffers.nextFreeSlot + 1) % MaxEntries; -} - -static void complete_instruction(int stage) { - PCode *instr = pipeline[stage].instr; - int buf = 0; - while (buf < MaxEntries && completionbuffers.entries[buf].instr != instr) - buf++; - - completionbuffers.entries[buf].completed = 1; - pipeline[stage].instr = NULL; -} - -static void retire_instruction(void) { - completionbuffers.entries[completionbuffers.nextToRetire].instr = NULL; - completionbuffers.used--; - completionbuffers.free++; - completionbuffers.nextToRetire = (completionbuffers.nextToRetire + 1) % MaxEntries; -} - -static int latency(PCode *instr) { - int cycles = instruction_timing[instr->op].latency; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - cycles += 2; - if (instr->op == PC_LMW || instr->op == PC_STMW) - cycles += instr->argCount - 2; - return cycles; -} - -static void initialize(void) { - int stage; - int i; - - for (stage = 0; stage < NumStages; stage++) - pipeline[stage].instr = NULL; - - completionbuffers.free = MaxEntries; - completionbuffers.used = 0; - completionbuffers.nextToRetire = 0; - completionbuffers.nextFreeSlot = 0; - for (i = 0; i < MaxEntries; i++) - completionbuffers.entries[i].instr = NULL; -} - -static int can_issue(PCode *instr) { - int stage; - - if (completionbuffers.free == 0) - return 0; - - stage = instruction_timing[instr->op].stage; - if (pipeline[stage].instr) { - if (stage == IU) { - switch (instr->op) { - case PC_ADD: - case PC_ADDC: - case PC_ADDI: - case PC_ADDIS: - case PC_CMPI: - case PC_CMP: - case PC_CMPLI: - case PC_CMPL: - if (is_dependent(instr, pipeline[IU].instr, RegClass_GPR)) - return 0; - if (!pipeline[SRU].instr) - return 1; - } - } - return 0; - } - - if ((instr->flags & fIsWrite) && pipeline[LSU2].instr && (pipeline[LSU2].instr->flags & fIsWrite)) - return 0; - - return 1; -} - -static void issue(PCode *instr) { - int stage = instruction_timing[instr->op].stage; - int cycles = instruction_timing[instr->op].cycles[0]; - if (stage == IU && pipeline[IU].instr) - stage = SRU; - assign_completion_buffer(instr); - pipeline[stage].instr = instr; - pipeline[stage].remaining = cycles; -} - -static void advance_clock(void) { - int stage; - - for (stage = 0; stage < NumStages; stage++) { - if (pipeline[stage].instr && pipeline[stage].remaining) - --pipeline[stage].remaining; - } - - if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { - retire_instruction(); - if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { - retire_instruction(); - } - } - - if (pipeline[IU].instr && pipeline[IU].remaining == 0) - complete_instruction(IU); - if (pipeline[LSU2].instr && pipeline[LSU2].remaining == 0) - complete_instruction(LSU2); - if (pipeline[FPU3].instr && pipeline[FPU3].remaining == 0) - complete_instruction(FPU3); - if (pipeline[SRU].instr && pipeline[SRU].remaining == 0) - complete_instruction(SRU); - if (pipeline[BPU].instr && pipeline[BPU].remaining == 0) - complete_instruction(BPU); - - if ( - pipeline[FPU1].instr && - pipeline[FPU1].remaining == 0 && - (pipeline[FPU1].instr->op == PC_FDIV || pipeline[FPU1].instr->op == PC_FDIVS) - ) - complete_instruction(FPU1); - - if (pipeline[FPU2].instr && pipeline[FPU2].remaining == 0 && !pipeline[FPU3].instr) - advance(FPU1, FPU2, FPU3); - if (pipeline[FPU1].instr && pipeline[FPU1].remaining == 0 && !pipeline[FPU2].instr) - advance(FPU1, FPU1, FPU2); - if (pipeline[LSU1].instr && pipeline[LSU1].remaining == 0 && !pipeline[LSU2].instr) - advance(LSU1, LSU1, LSU2); -} - -static int serializes(PCode *instr) { - return instruction_timing[instr->op].serializes; -} - -MachineInfo machine603e = { - 2, - 1, - 0, - &latency, - &initialize, - &can_issue, - &issue, - &advance_clock, - &serializes, - &default_uses_vpermute_unit -}; diff --git a/compiler_and_linker/unsorted/MachineSimulation604.c b/compiler_and_linker/unsorted/MachineSimulation604.c deleted file mode 100644 index 9775c9e..0000000 --- a/compiler_and_linker/unsorted/MachineSimulation604.c +++ /dev/null @@ -1,670 +0,0 @@ -#include "compiler/Scheduler.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" - -// https://archive.org/details/bitsavers_motorolaPosManualNov94_22719504 - -typedef enum Stage { - SCIU, // Single-Cycle Integer Unit 1 - SCIU2, // Single-Cycle Integer Unit 2 - MCIU, // Multiple-Cycle Integer Unit - FPU1, // Floating Point Unit - FPU2, - FPU3, - LSU1, // Load/Store Unit - LSU2, - BPU, // Branch Prediction Unit - NumStages -} Stage; - -static struct { - // the instruction currently in this pipeline stage - PCode *instr; - - // how many cycles are left for this instruction to finish - int remaining; -} pipeline[NumStages]; - -enum { - MaxEntries = 16 -}; - -static struct { - // how many entries remain unused in the queue - unsigned int free; - - // how many entries are currently used in the queue - unsigned int used; - - // the index of the next instruction that will be retired - unsigned int nextToRetire; - - // the index of the next free slot that will be used when an instruction is dispatched - unsigned int nextFreeSlot; - - // circular array of entries in the completion queue - struct { - PCode *instr; - int completed; - } entries[MaxEntries]; -} completionbuffers; - -static PCode *sciu_completed_instruction; -static PCode *sciu2_completed_instruction; - -static struct { - // the initial stage for this instruction - Stage stage; - - // the total amount of cycles required by this instruction - char latency; - - // how long it takes to finish each stage - char cycles[3]; - - // does this instruction serialise? - char serializes; -} instruction_timing[OPCODE_MAX] = { - BPU, 0, 0, 0, 0, 1, // PC_B - BPU, 0, 0, 0, 0, 1, // PC_BL - BPU, 0, 0, 0, 0, 1, // PC_BC - BPU, 0, 0, 0, 0, 1, // PC_BCLR - BPU, 0, 0, 0, 0, 1, // PC_BCCTR - BPU, 0, 0, 0, 0, 1, // PC_BT - BPU, 0, 0, 0, 0, 1, // PC_BTLR - BPU, 0, 0, 0, 0, 1, // PC_BTCTR - BPU, 0, 0, 0, 0, 1, // PC_BF - BPU, 0, 0, 0, 0, 1, // PC_BFLR - BPU, 0, 0, 0, 0, 1, // PC_BFCTR - BPU, 0, 0, 0, 0, 1, // PC_BDNZ - BPU, 0, 0, 0, 0, 1, // PC_BDNZT - BPU, 0, 0, 0, 0, 1, // PC_BDNZF - BPU, 0, 0, 0, 0, 1, // PC_BDZ - BPU, 0, 0, 0, 0, 1, // PC_BDZT - BPU, 0, 0, 0, 0, 1, // PC_BDZF - BPU, 0, 0, 0, 0, 1, // PC_BLR - BPU, 0, 0, 0, 0, 1, // PC_BCTR - BPU, 0, 0, 0, 0, 1, // PC_BCTRL - BPU, 0, 0, 0, 0, 1, // PC_BLRL - LSU1, 2, 1, 1, 0, 0, // PC_LBZ - LSU1, 2, 1, 1, 0, 0, // PC_LBZU - LSU1, 2, 1, 1, 0, 0, // PC_LBZX - LSU1, 2, 1, 1, 0, 0, // PC_LBZUX - LSU1, 2, 1, 1, 0, 0, // PC_LHZ - LSU1, 2, 1, 1, 0, 0, // PC_LHZU - LSU1, 2, 1, 1, 0, 0, // PC_LHZX - LSU1, 2, 1, 1, 0, 0, // PC_LHZUX - LSU1, 2, 1, 1, 0, 0, // PC_LHA - LSU1, 2, 1, 1, 0, 0, // PC_LHAU - LSU1, 2, 1, 1, 0, 0, // PC_LHAX - LSU1, 2, 1, 1, 0, 0, // PC_LHAUX - LSU1, 2, 1, 1, 0, 0, // PC_LHBRX - LSU1, 2, 1, 1, 0, 0, // PC_LWZ - LSU1, 2, 1, 1, 0, 0, // PC_LWZU - LSU1, 2, 1, 1, 0, 0, // PC_LWZX - LSU1, 2, 1, 1, 0, 0, // PC_LWZUX - LSU1, 2, 1, 1, 0, 0, // PC_LWBRX - LSU1, 2, 1, 1, 0, 0, // PC_LMW - LSU1, 3, 1, 1, 0, 0, // PC_STB - LSU1, 3, 1, 1, 0, 0, // PC_STBU - LSU1, 3, 1, 1, 0, 0, // PC_STBX - LSU1, 3, 1, 1, 0, 0, // PC_STBUX - LSU1, 3, 1, 1, 0, 0, // PC_STH - LSU1, 3, 1, 1, 0, 0, // PC_STHU - LSU1, 3, 1, 1, 0, 0, // PC_STHX - LSU1, 3, 1, 1, 0, 0, // PC_STHUX - LSU1, 3, 1, 1, 0, 0, // PC_STHBRX - LSU1, 3, 1, 1, 0, 0, // PC_STW - LSU1, 3, 1, 1, 0, 0, // PC_STWU - LSU1, 3, 1, 1, 0, 0, // PC_STWX - LSU1, 3, 1, 1, 0, 0, // PC_STWUX - LSU1, 3, 1, 1, 0, 0, // PC_STWBRX - LSU1, 2, 1, 1, 0, 0, // PC_STMW - LSU1, 2, 1, 1, 0, 0, // PC_DCBF - LSU1, 2, 1, 1, 0, 0, // PC_DCBST - LSU1, 2, 1, 1, 0, 0, // PC_DCBT - LSU1, 2, 1, 1, 0, 0, // PC_DCBTST - LSU1, 2, 1, 1, 0, 0, // PC_DCBZ - SCIU, 1, 1, 0, 0, 0, // PC_ADD - SCIU, 1, 1, 0, 0, 0, // PC_ADDC - SCIU, 1, 1, 0, 0, 0, // PC_ADDE - SCIU, 1, 1, 0, 0, 0, // PC_ADDI - SCIU, 1, 1, 0, 0, 0, // PC_ADDIC - SCIU, 1, 1, 0, 0, 0, // PC_ADDICR - SCIU, 1, 1, 0, 0, 0, // PC_ADDIS - SCIU, 1, 1, 0, 0, 0, // PC_ADDME - SCIU, 1, 1, 0, 0, 0, // PC_ADDZE - MCIU, 20, 20, 0, 0, 0, // PC_DIVW - MCIU, 20, 20, 0, 0, 0, // PC_DIVWU - MCIU, 4, 4, 0, 0, 0, // PC_MULHW - MCIU, 4, 4, 0, 0, 0, // PC_MULHWU - MCIU, 3, 3, 0, 0, 0, // PC_MULLI - MCIU, 4, 4, 0, 0, 0, // PC_MULLW - SCIU, 1, 1, 0, 0, 0, // PC_NEG - SCIU, 1, 1, 0, 0, 0, // PC_SUBF - SCIU, 1, 1, 0, 0, 0, // PC_SUBFC - SCIU, 1, 1, 0, 0, 0, // PC_SUBFE - SCIU, 1, 1, 0, 0, 0, // PC_SUBFIC - SCIU, 1, 1, 0, 0, 0, // PC_SUBFME - SCIU, 1, 1, 0, 0, 0, // PC_SUBFZE - SCIU, 3, 1, 0, 0, 0, // PC_CMPI - SCIU, 3, 1, 0, 0, 0, // PC_CMP - SCIU, 3, 1, 0, 0, 0, // PC_CMPLI - SCIU, 3, 1, 0, 0, 0, // PC_CMPL - SCIU, 1, 1, 0, 0, 0, // PC_ANDI - SCIU, 1, 1, 0, 0, 0, // PC_ANDIS - SCIU, 1, 1, 0, 0, 0, // PC_ORI - SCIU, 1, 1, 0, 0, 0, // PC_ORIS - SCIU, 1, 1, 0, 0, 0, // PC_XORI - SCIU, 1, 1, 0, 0, 0, // PC_XORIS - SCIU, 1, 1, 0, 0, 0, // PC_AND - SCIU, 1, 1, 0, 0, 0, // PC_OR - SCIU, 1, 1, 0, 0, 0, // PC_XOR - SCIU, 1, 1, 0, 0, 0, // PC_NAND - SCIU, 1, 1, 0, 0, 0, // PC_NOR - SCIU, 1, 1, 0, 0, 0, // PC_EQV - SCIU, 1, 1, 0, 0, 0, // PC_ANDC - SCIU, 1, 1, 0, 0, 0, // PC_ORC - SCIU, 1, 1, 0, 0, 0, // PC_EXTSB - SCIU, 1, 1, 0, 0, 0, // PC_EXTSH - SCIU, 1, 1, 0, 0, 0, // PC_CNTLZW - SCIU, 1, 1, 0, 0, 0, // PC_RLWINM - SCIU, 1, 1, 0, 0, 0, // PC_RLWNM - SCIU, 1, 1, 0, 0, 0, // PC_RLWIMI - SCIU, 1, 1, 0, 0, 0, // PC_SLW - SCIU, 1, 1, 0, 0, 0, // PC_SRW - SCIU, 1, 1, 0, 0, 0, // PC_SRAWI - SCIU, 1, 1, 0, 0, 0, // PC_SRAW - BPU, 1, 1, 0, 0, 0, // PC_CRAND - BPU, 1, 1, 0, 0, 0, // PC_CRANDC - BPU, 1, 1, 0, 0, 0, // PC_CREQV - BPU, 1, 1, 0, 0, 0, // PC_CRNAND - BPU, 1, 1, 0, 0, 0, // PC_CRNOR - BPU, 1, 1, 0, 0, 0, // PC_CROR - BPU, 1, 1, 0, 0, 0, // PC_CRORC - BPU, 1, 1, 0, 0, 0, // PC_CRXOR - BPU, 1, 1, 0, 0, 0, // PC_MCRF - MCIU, 1, 1, 0, 0, 0, // PC_MTXER - MCIU, 1, 1, 0, 0, 0, // PC_MTCTR - MCIU, 1, 1, 0, 0, 0, // PC_MTLR - MCIU, 1, 1, 0, 0, 0, // PC_MTCRF - MCIU, 1, 1, 0, 0, 0, // PC_MTMSR - MCIU, 1, 1, 0, 0, 0, // PC_MTSPR - MCIU, 1, 1, 0, 0, 0, // PC_MFMSR - MCIU, 1, 1, 0, 0, 0, // PC_MFSPR - MCIU, 3, 3, 0, 0, 0, // PC_MFXER - MCIU, 3, 3, 0, 0, 0, // PC_MFCTR - MCIU, 3, 3, 0, 0, 0, // PC_MFLR - MCIU, 3, 3, 0, 0, 0, // PC_MFCR - FPU1, 3, 1, 1, 1, 0, // PC_MFFS - FPU1, 3, 1, 1, 1, 0, // PC_MTFSF - LSU1, 1, 0, 0, 0, 1, // PC_EIEIO - LSU1, 1, 0, 0, 0, 1, // PC_ISYNC - LSU1, 1, 0, 0, 0, 1, // PC_SYNC - LSU1, 1, 1, 0, 0, 1, // PC_RFI - SCIU, 1, 1, 0, 0, 0, // PC_LI - SCIU, 1, 1, 0, 0, 0, // PC_LIS - SCIU, 1, 1, 0, 0, 0, // PC_MR - SCIU, 1, 1, 0, 0, 0, // PC_NOP - SCIU, 1, 1, 0, 0, 0, // PC_NOT - LSU1, 3, 1, 1, 0, 0, // PC_LFS - LSU1, 3, 1, 1, 0, 0, // PC_LFSU - LSU1, 3, 1, 1, 0, 0, // PC_LFSX - LSU1, 3, 1, 1, 0, 0, // PC_LFSUX - LSU1, 3, 1, 1, 0, 0, // PC_LFD - LSU1, 3, 1, 1, 0, 0, // PC_LFDU - LSU1, 3, 1, 1, 0, 0, // PC_LFDX - LSU1, 3, 1, 1, 0, 0, // PC_LFDUX - LSU1, 3, 1, 1, 0, 0, // PC_STFS - LSU1, 3, 1, 1, 0, 0, // PC_STFSU - LSU1, 3, 1, 1, 0, 0, // PC_STFSX - LSU1, 3, 1, 1, 0, 0, // PC_STFSUX - LSU1, 3, 1, 1, 0, 0, // PC_STFD - LSU1, 3, 1, 1, 0, 0, // PC_STFDU - LSU1, 3, 1, 1, 0, 0, // PC_STFDX - LSU1, 3, 1, 1, 0, 0, // PC_STFDUX - FPU1, 3, 1, 1, 1, 0, // PC_FMR - FPU1, 3, 1, 1, 1, 0, // PC_FABS - FPU1, 3, 1, 1, 1, 0, // PC_FNEG - FPU1, 3, 1, 1, 1, 0, // PC_FNABS - FPU1, 3, 1, 1, 1, 0, // PC_FADD - FPU1, 3, 1, 1, 1, 0, // PC_FADDS - FPU1, 3, 1, 1, 1, 0, // PC_FSUB - FPU1, 3, 1, 1, 1, 0, // PC_FSUBS - FPU1, 3, 1, 1, 1, 0, // PC_FMUL - FPU1, 3, 1, 1, 1, 0, // PC_FMULS - FPU1, 32, 32, 0, 0, 0, // PC_FDIV - FPU1, 18, 18, 0, 0, 0, // PC_FDIVS - FPU1, 3, 1, 1, 1, 0, // PC_FMADD - FPU1, 3, 1, 1, 1, 0, // PC_FMADDS - FPU1, 3, 1, 1, 1, 0, // PC_FMSUB - FPU1, 3, 1, 1, 1, 0, // PC_FMSUBS - FPU1, 3, 1, 1, 1, 0, // PC_FNMADD - FPU1, 3, 1, 1, 1, 0, // PC_FNMADDS - FPU1, 3, 1, 1, 1, 0, // PC_FNMSUB - FPU1, 3, 1, 1, 1, 0, // PC_FNMSUBS - FPU1, 18, 18, 0, 0, 0, // PC_FRES - FPU1, 3, 1, 1, 1, 0, // PC_FRSQRTE - FPU1, 3, 1, 1, 1, 0, // PC_FSEL - FPU1, 3, 1, 1, 1, 0, // PC_FRSP - FPU1, 3, 1, 1, 1, 0, // PC_FCTIW - FPU1, 3, 1, 1, 1, 0, // PC_FCTIWZ - FPU1, 5, 1, 1, 1, 0, // PC_FCMPU - FPU1, 5, 1, 1, 1, 0, // PC_FCMPO - LSU1, 1, 1, 0, 0, 0, // PC_LWARX - LSU1, 1, 1, 0, 0, 0, // PC_LSWI - LSU1, 1, 1, 0, 0, 0, // PC_LSWX - LSU1, 1, 1, 0, 0, 0, // PC_STFIWX - LSU1, 1, 1, 0, 0, 0, // PC_STSWI - LSU1, 1, 1, 0, 0, 0, // PC_STSWX - LSU1, 1, 1, 0, 0, 0, // PC_STWCX - MCIU, 1, 1, 0, 0, 1, // PC_ECIWX - MCIU, 1, 1, 0, 0, 1, // PC_ECOWX - MCIU, 1, 1, 0, 0, 0, // PC_DCBI - MCIU, 1, 1, 0, 0, 0, // PC_ICBI - MCIU, 1, 1, 0, 0, 0, // PC_MCRFS - MCIU, 1, 1, 0, 0, 0, // PC_MCRXR - MCIU, 1, 1, 0, 0, 0, // PC_MFTB - MCIU, 1, 1, 0, 0, 0, // PC_MFSR - MCIU, 1, 1, 0, 0, 0, // PC_MTSR - MCIU, 1, 1, 0, 0, 0, // PC_MFSRIN - MCIU, 1, 1, 0, 0, 0, // PC_MTSRIN - MCIU, 1, 1, 0, 0, 0, // PC_MTFSB0 - MCIU, 1, 1, 0, 0, 0, // PC_MTFSB1 - MCIU, 1, 1, 0, 0, 0, // PC_MTFSFI - MCIU, 1, 1, 0, 0, 1, // PC_SC - FPU1, 1, 1, 0, 0, 0, // PC_FSQRT - FPU1, 1, 1, 0, 0, 0, // PC_FSQRTS - MCIU, 1, 1, 0, 0, 0, // PC_TLBIA - MCIU, 1, 1, 0, 0, 0, // PC_TLBIE - MCIU, 1, 1, 0, 0, 0, // PC_TLBLD - MCIU, 1, 1, 0, 0, 0, // PC_TLBLI - MCIU, 1, 1, 0, 0, 0, // PC_TLBSYNC - MCIU, 1, 1, 0, 0, 1, // PC_TW - MCIU, 1, 1, 0, 0, 1, // PC_TRAP - MCIU, 1, 1, 0, 0, 1, // PC_TWI - MCIU, 1, 1, 0, 0, 1, // PC_OPWORD - MCIU, 1, 1, 0, 0, 0, // PC_MFROM - MCIU, 1, 1, 0, 0, 1, // PC_DSA - MCIU, 1, 1, 0, 0, 1, // PC_ESA - MCIU, 0, 0, 0, 0, 0, // PC_DCCCI - MCIU, 0, 0, 0, 0, 0, // PC_DCREAD - MCIU, 0, 0, 0, 0, 0, // PC_ICBT - MCIU, 0, 0, 0, 0, 0, // PC_ICCCI - MCIU, 0, 0, 0, 0, 0, // PC_ICREAD - MCIU, 0, 0, 0, 0, 0, // PC_RFCI - MCIU, 0, 0, 0, 0, 0, // PC_TLBRE - MCIU, 0, 0, 0, 0, 0, // PC_TLBSX - MCIU, 0, 0, 0, 0, 0, // PC_TLBWE - MCIU, 0, 0, 0, 0, 0, // PC_WRTEE - MCIU, 0, 0, 0, 0, 0, // PC_WRTEEI - MCIU, 0, 0, 0, 0, 0, // PC_MFDCR - MCIU, 0, 0, 0, 0, 0, // PC_MTDCR - MCIU, 0, 0, 0, 0, 0, // PC_DCBA - SCIU, 0, 0, 0, 0, 0, // PC_DSS - SCIU, 0, 0, 0, 0, 0, // PC_DSSALL - SCIU, 0, 0, 0, 0, 0, // PC_DST - SCIU, 0, 0, 0, 0, 0, // PC_DSTT - SCIU, 0, 0, 0, 0, 0, // PC_DSTST - SCIU, 0, 0, 0, 0, 0, // PC_DSTSTT - SCIU, 0, 0, 0, 0, 0, // PC_LVEBX - SCIU, 0, 0, 0, 0, 0, // PC_LVEHX - SCIU, 0, 0, 0, 0, 0, // PC_LVEWX - SCIU, 0, 0, 0, 0, 0, // PC_LVSL - SCIU, 0, 0, 0, 0, 0, // PC_LVSR - SCIU, 0, 0, 0, 0, 0, // PC_LVX - SCIU, 0, 0, 0, 0, 0, // PC_LVXL - SCIU, 0, 0, 0, 0, 0, // PC_STVEBX - SCIU, 0, 0, 0, 0, 0, // PC_STVEHX - SCIU, 0, 0, 0, 0, 0, // PC_STVEWX - SCIU, 0, 0, 0, 0, 0, // PC_STVX - SCIU, 0, 0, 0, 0, 0, // PC_STVXL - SCIU, 0, 0, 0, 0, 0, // PC_MFVSCR - SCIU, 0, 0, 0, 0, 0, // PC_MTVSCR - SCIU, 0, 0, 0, 0, 0, // PC_VADDCUW - SCIU, 0, 0, 0, 0, 0, // PC_VADDFP - SCIU, 0, 0, 0, 0, 0, // PC_VADDSBS - SCIU, 0, 0, 0, 0, 0, // PC_VADDSHS - SCIU, 0, 0, 0, 0, 0, // PC_VADDSWS - SCIU, 0, 0, 0, 0, 0, // PC_VADDUBM - SCIU, 0, 0, 0, 0, 0, // PC_VADDUBS - SCIU, 0, 0, 0, 0, 0, // PC_VADDUHM - SCIU, 0, 0, 0, 0, 0, // PC_VADDUHS - SCIU, 0, 0, 0, 0, 0, // PC_VADDUWM - SCIU, 0, 0, 0, 0, 0, // PC_VADDUWS - SCIU, 0, 0, 0, 0, 0, // PC_VAND - SCIU, 0, 0, 0, 0, 0, // PC_VANDC - SCIU, 0, 0, 0, 0, 0, // PC_VAVGSB - SCIU, 0, 0, 0, 0, 0, // PC_VAVGSH - SCIU, 0, 0, 0, 0, 0, // PC_VAVGSW - SCIU, 0, 0, 0, 0, 0, // PC_VAVGUB - SCIU, 0, 0, 0, 0, 0, // PC_VAVGUH - SCIU, 0, 0, 0, 0, 0, // PC_VAVGUW - SCIU, 0, 0, 0, 0, 0, // PC_VCFSX - SCIU, 0, 0, 0, 0, 0, // PC_VCFUX - SCIU, 0, 0, 0, 0, 0, // PC_VCMPBFP - SCIU, 0, 0, 0, 0, 0, // PC_VCMPEQFP - SCIU, 0, 0, 0, 0, 0, // PC_VCMPEQUB - SCIU, 0, 0, 0, 0, 0, // PC_VCMPEQUH - SCIU, 0, 0, 0, 0, 0, // PC_VCMPEQUW - SCIU, 0, 0, 0, 0, 0, // PC_VCMPGEFP - SCIU, 0, 0, 0, 0, 0, // PC_VCMPGTFP - SCIU, 0, 0, 0, 0, 0, // PC_VCMPGTSB - SCIU, 0, 0, 0, 0, 0, // PC_VCMPGTSH - SCIU, 0, 0, 0, 0, 0, // PC_VCMPGTSW - SCIU, 0, 0, 0, 0, 0, // PC_VCMPGTUB - SCIU, 0, 0, 0, 0, 0, // PC_VCMPGTUH - SCIU, 0, 0, 0, 0, 0, // PC_VCMPGTUW - SCIU, 0, 0, 0, 0, 0, // PC_VCTSXS - SCIU, 0, 0, 0, 0, 0, // PC_VCTUXS - SCIU, 0, 0, 0, 0, 0, // PC_VEXPTEFP - SCIU, 0, 0, 0, 0, 0, // PC_VLOGEFP - SCIU, 0, 0, 0, 0, 0, // PC_VMAXFP - SCIU, 0, 0, 0, 0, 0, // PC_VMAXSB - SCIU, 0, 0, 0, 0, 0, // PC_VMAXSH - SCIU, 0, 0, 0, 0, 0, // PC_VMAXSW - SCIU, 0, 0, 0, 0, 0, // PC_VMAXUB - SCIU, 0, 0, 0, 0, 0, // PC_VMAXUH - SCIU, 0, 0, 0, 0, 0, // PC_VMAXUW - SCIU, 0, 0, 0, 0, 0, // PC_VMINFP - SCIU, 0, 0, 0, 0, 0, // PC_VMINSB - SCIU, 0, 0, 0, 0, 0, // PC_VMINSH - SCIU, 0, 0, 0, 0, 0, // PC_VMINSW - SCIU, 0, 0, 0, 0, 0, // PC_VMINUB - SCIU, 0, 0, 0, 0, 0, // PC_VMINUH - SCIU, 0, 0, 0, 0, 0, // PC_VMINUW - SCIU, 0, 0, 0, 0, 0, // PC_VMRGHB - SCIU, 0, 0, 0, 0, 0, // PC_VMRGHH - SCIU, 0, 0, 0, 0, 0, // PC_VMRGHW - SCIU, 0, 0, 0, 0, 0, // PC_VMRGLB - SCIU, 0, 0, 0, 0, 0, // PC_VMRGLH - SCIU, 0, 0, 0, 0, 0, // PC_VMRGLW - SCIU, 0, 0, 0, 0, 0, // PC_VMULESB - SCIU, 0, 0, 0, 0, 0, // PC_VMULESH - SCIU, 0, 0, 0, 0, 0, // PC_VMULEUB - SCIU, 0, 0, 0, 0, 0, // PC_VMULEUH - SCIU, 0, 0, 0, 0, 0, // PC_VMULOSB - SCIU, 0, 0, 0, 0, 0, // PC_VMULOSH - SCIU, 0, 0, 0, 0, 0, // PC_VMULOUB - SCIU, 0, 0, 0, 0, 0, // PC_VMULOUH - SCIU, 0, 0, 0, 0, 0, // PC_VNOR - SCIU, 0, 0, 0, 0, 0, // PC_VOR - SCIU, 0, 0, 0, 0, 0, // PC_VPKPX - SCIU, 0, 0, 0, 0, 0, // PC_VPKSHSS - SCIU, 0, 0, 0, 0, 0, // PC_VPKSHUS - SCIU, 0, 0, 0, 0, 0, // PC_VPKSWSS - SCIU, 0, 0, 0, 0, 0, // PC_VPKSWUS - SCIU, 0, 0, 0, 0, 0, // PC_VPKUHUM - SCIU, 0, 0, 0, 0, 0, // PC_VPKUHUS - SCIU, 0, 0, 0, 0, 0, // PC_VPKUWUM - SCIU, 0, 0, 0, 0, 0, // PC_VPKUWUS - SCIU, 0, 0, 0, 0, 0, // PC_VREFP - SCIU, 0, 0, 0, 0, 0, // PC_VRFIM - SCIU, 0, 0, 0, 0, 0, // PC_VRFIN - SCIU, 0, 0, 0, 0, 0, // PC_VRFIP - SCIU, 0, 0, 0, 0, 0, // PC_VRFIZ - SCIU, 0, 0, 0, 0, 0, // PC_VRLB - SCIU, 0, 0, 0, 0, 0, // PC_VRLH - SCIU, 0, 0, 0, 0, 0, // PC_VRLW - SCIU, 0, 0, 0, 0, 0, // PC_VRSQRTEFP - SCIU, 0, 0, 0, 0, 0, // PC_VSL - SCIU, 0, 0, 0, 0, 0, // PC_VSLB - SCIU, 0, 0, 0, 0, 0, // PC_VSLH - SCIU, 0, 0, 0, 0, 0, // PC_VSLO - SCIU, 0, 0, 0, 0, 0, // PC_VSLW - SCIU, 0, 0, 0, 0, 0, // PC_VSPLTB - SCIU, 0, 0, 0, 0, 0, // PC_VSPLTH - SCIU, 0, 0, 0, 0, 0, // PC_VSPLTW - SCIU, 0, 0, 0, 0, 0, // PC_VSPLTISB - SCIU, 0, 0, 0, 0, 0, // PC_VSPLTISH - SCIU, 0, 0, 0, 0, 0, // PC_VSPLTISW - SCIU, 0, 0, 0, 0, 0, // PC_VSR - SCIU, 0, 0, 0, 0, 0, // PC_VSRAB - SCIU, 0, 0, 0, 0, 0, // PC_VSRAH - SCIU, 0, 0, 0, 0, 0, // PC_VSRAW - SCIU, 0, 0, 0, 0, 0, // PC_VSRB - SCIU, 0, 0, 0, 0, 0, // PC_VSRH - SCIU, 0, 0, 0, 0, 0, // PC_VSRO - SCIU, 0, 0, 0, 0, 0, // PC_VSRW - SCIU, 0, 0, 0, 0, 0, // PC_VSUBCUW - SCIU, 0, 0, 0, 0, 0, // PC_VSUBFP - SCIU, 0, 0, 0, 0, 0, // PC_VSUBSBS - SCIU, 0, 0, 0, 0, 0, // PC_VSUBSHS - SCIU, 0, 0, 0, 0, 0, // PC_VSUBSWS - SCIU, 0, 0, 0, 0, 0, // PC_VSUBUBM - SCIU, 0, 0, 0, 0, 0, // PC_VSUBUBS - SCIU, 0, 0, 0, 0, 0, // PC_VSUBUHM - SCIU, 0, 0, 0, 0, 0, // PC_VSUBUHS - SCIU, 0, 0, 0, 0, 0, // PC_VSUBUWM - SCIU, 0, 0, 0, 0, 0, // PC_VSUBUWS - SCIU, 0, 0, 0, 0, 0, // PC_VSUMSWS - SCIU, 0, 0, 0, 0, 0, // PC_VSUM2SWS - SCIU, 0, 0, 0, 0, 0, // PC_VSUM4SBS - SCIU, 0, 0, 0, 0, 0, // PC_VSUM4SHS - SCIU, 0, 0, 0, 0, 0, // PC_VSUM4UBS - SCIU, 0, 0, 0, 0, 0, // PC_VUPKHPX - SCIU, 0, 0, 0, 0, 0, // PC_VUPKHSB - SCIU, 0, 0, 0, 0, 0, // PC_VUPKHSH - SCIU, 0, 0, 0, 0, 0, // PC_VUPKLPX - SCIU, 0, 0, 0, 0, 0, // PC_VUPKLSB - SCIU, 0, 0, 0, 0, 0, // PC_VUPKLSH - SCIU, 0, 0, 0, 0, 0, // PC_VXOR - SCIU, 0, 0, 0, 0, 0, // PC_VMADDFP - SCIU, 0, 0, 0, 0, 0, // PC_VMHADDSHS - SCIU, 0, 0, 0, 0, 0, // PC_VMHRADDSHS - SCIU, 0, 0, 0, 0, 0, // PC_VMLADDUHM - SCIU, 0, 0, 0, 0, 0, // PC_VMSUMMBM - SCIU, 0, 0, 0, 0, 0, // PC_VMSUMSHM - SCIU, 0, 0, 0, 0, 0, // PC_VMSUMSHS - SCIU, 0, 0, 0, 0, 0, // PC_VMSUMUBM - SCIU, 0, 0, 0, 0, 0, // PC_VMSUMUHM - SCIU, 0, 0, 0, 0, 0, // PC_VMSUMUHS - SCIU, 0, 0, 0, 0, 0, // PC_VNMSUBFP - SCIU, 0, 0, 0, 0, 0, // PC_VPERM - SCIU, 0, 0, 0, 0, 0, // PC_VSEL - SCIU, 0, 0, 0, 0, 0, // PC_VSLDOI - SCIU, 0, 0, 0, 0, 0, // PC_VMR - SCIU, 0, 0, 0, 0, 0, // PC_VMRP - SCIU, 0, 0, 0, 0, 0, // PC_SLE - SCIU, 0, 0, 0, 0, 0, // PC_SLEQ - SCIU, 0, 0, 0, 0, 0, // PC_SLIQ - SCIU, 0, 0, 0, 0, 0, // PC_SLLIQ - SCIU, 0, 0, 0, 0, 0, // PC_SLLQ - SCIU, 0, 0, 0, 0, 0, // PC_SLQ - SCIU, 0, 0, 0, 0, 0, // PC_SRAIQ - SCIU, 0, 0, 0, 0, 0, // PC_SRAQ - SCIU, 0, 0, 0, 0, 0, // PC_SRE - SCIU, 0, 0, 0, 0, 0, // PC_SREA - SCIU, 0, 0, 0, 0, 0, // PC_SREQ - SCIU, 0, 0, 0, 0, 0, // PC_SRIQ - SCIU, 0, 0, 0, 0, 0, // PC_SRLIQ - SCIU, 0, 0, 0, 0, 0, // PC_SRLQ - SCIU, 0, 0, 0, 0, 0, // PC_SRQ - SCIU, 0, 0, 0, 0, 0, // PC_MASKG - SCIU, 0, 0, 0, 0, 0, // PC_MASKIR - SCIU, 0, 0, 0, 0, 0, // PC_LSCBX - SCIU, 0, 0, 0, 0, 0, // PC_DIV - SCIU, 0, 0, 0, 0, 0, // PC_DIVS - SCIU, 0, 0, 0, 0, 0, // PC_DOZ - SCIU, 0, 0, 0, 0, 0, // PC_MUL - SCIU, 0, 0, 0, 0, 0, // PC_NABS - SCIU, 0, 0, 0, 0, 0, // PC_ABS - SCIU, 0, 0, 0, 0, 0, // PC_CLCS - SCIU, 0, 0, 0, 0, 0, // PC_DOZI - SCIU, 0, 0, 0, 0, 0, // PC_RLMI - SCIU, 0, 0, 0, 0, 0, // PC_RRIB -}; - -static void advance(int firstStage, int oldStage, int newStage) { - PCode *instr = pipeline[oldStage].instr; - int cycles = instruction_timing[instr->op].cycles[newStage - firstStage]; - pipeline[newStage].instr = instr; - pipeline[newStage].remaining = cycles; - pipeline[oldStage].instr = NULL; -} - -static void assign_completion_buffer(PCode *instr) { - completionbuffers.used++; - completionbuffers.free--; - completionbuffers.entries[completionbuffers.nextFreeSlot].instr = instr; - completionbuffers.entries[completionbuffers.nextFreeSlot].completed = 0; - completionbuffers.nextFreeSlot = (completionbuffers.nextFreeSlot + 1) % MaxEntries; -} - -static void complete_instruction(int stage) { - PCode *instr = pipeline[stage].instr; - int buf = 0; - while (buf < MaxEntries && completionbuffers.entries[buf].instr != instr) - buf++; - - completionbuffers.entries[buf].completed = 1; - pipeline[stage].instr = NULL; - - if (stage == SCIU) - sciu_completed_instruction = instr; - else if (stage == SCIU2) - sciu2_completed_instruction = instr; -} - -static void retire_instruction(void) { - completionbuffers.entries[completionbuffers.nextToRetire].instr = NULL; - completionbuffers.used--; - completionbuffers.free++; - completionbuffers.nextToRetire = (completionbuffers.nextToRetire + 1) % MaxEntries; -} - -static int latency(PCode *instr) { - int cycles = instruction_timing[instr->op].latency; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - cycles += 2; - if (instr->op == PC_LMW || instr->op == PC_STMW) - cycles += instr->argCount - 2; - return cycles; -} - -static void initialize(void) { - int stage; - int i; - - for (stage = 0; stage < NumStages; stage++) - pipeline[stage].instr = NULL; - - completionbuffers.free = MaxEntries; - completionbuffers.used = 0; - completionbuffers.nextToRetire = 0; - completionbuffers.nextFreeSlot = 0; - for (i = 0; i < MaxEntries; i++) - completionbuffers.entries[i].instr = NULL; - - sciu_completed_instruction = NULL; - sciu2_completed_instruction = NULL; -} - -static int can_issue(PCode *instr) { - PCode *check; - int stage = instruction_timing[instr->op].stage; - - if (completionbuffers.free == 0) - return 0; - - if (stage == SCIU) { - int isClear1 = !pipeline[SCIU].instr; - int isClear2 = !pipeline[SCIU2].instr; - if (!isClear1 && !isClear2) - return 0; - if (isClear1 && isClear2) - return 1; - - if (isClear1) - check = pipeline[SCIU2].instr; - else - check = pipeline[SCIU].instr; - - if (is_dependent(instr, check, RegClass_GPR)) - return 0; - if (is_dependent(instr, sciu_completed_instruction, RegClass_GPR)) - return 0; - if (is_dependent(instr, sciu2_completed_instruction, RegClass_GPR)) - return 0; - } else { - if (pipeline[stage].instr) - return 0; - } - - return 1; -} - -static void issue(PCode *instr) { - int stage = instruction_timing[instr->op].stage; - int cycles = instruction_timing[instr->op].cycles[0]; - if (stage == SCIU && pipeline[SCIU].instr) - stage = SCIU2; - assign_completion_buffer(instr); - pipeline[stage].instr = instr; - pipeline[stage].remaining = cycles; -} - -static void advance_clock(void) { - int stage; - int i; - - sciu_completed_instruction = NULL; - sciu2_completed_instruction = NULL; - - for (stage = 0; stage < NumStages; stage++) { - if (pipeline[stage].instr && pipeline[stage].remaining) - --pipeline[stage].remaining; - } - - for (i = 0; i < 5; i++) { - if (completionbuffers.used == 0) - break; - if (completionbuffers.entries[completionbuffers.nextToRetire].completed == 0) - break; - retire_instruction(); - } - - if (pipeline[SCIU].instr && pipeline[SCIU].remaining == 0) - complete_instruction(SCIU); - if (pipeline[SCIU2].instr && pipeline[SCIU2].remaining == 0) - complete_instruction(SCIU2); - if (pipeline[MCIU].instr && pipeline[MCIU].remaining == 0) - complete_instruction(MCIU); - if (pipeline[LSU2].instr && pipeline[LSU2].remaining == 0) - complete_instruction(LSU2); - if (pipeline[FPU3].instr && pipeline[FPU3].remaining == 0) - complete_instruction(FPU3); - if (pipeline[BPU].instr && pipeline[BPU].remaining == 0) - complete_instruction(BPU); - - if ( - pipeline[FPU1].instr && - pipeline[FPU1].remaining == 0 && - (pipeline[FPU1].instr->op == PC_FDIV || pipeline[FPU1].instr->op == PC_FDIVS) - ) - complete_instruction(FPU1); - - if (pipeline[FPU2].instr && pipeline[FPU2].remaining == 0 && !pipeline[FPU3].instr) - advance(FPU1, FPU2, FPU3); - if (pipeline[FPU1].instr && pipeline[FPU1].remaining == 0 && !pipeline[FPU2].instr) - advance(FPU1, FPU1, FPU2); - if (pipeline[LSU1].instr && pipeline[LSU1].remaining == 0 && !pipeline[LSU2].instr) - advance(LSU1, LSU1, LSU2); -} - -static int serializes(PCode *instr) { - return instruction_timing[instr->op].serializes; -} - -MachineInfo machine604 = { - 4, - 1, - 0, - &latency, - &initialize, - &can_issue, - &issue, - &advance_clock, - &serializes, - &default_uses_vpermute_unit -}; diff --git a/compiler_and_linker/unsorted/MachineSimulation7400.c b/compiler_and_linker/unsorted/MachineSimulation7400.c deleted file mode 100644 index 56b375c..0000000 --- a/compiler_and_linker/unsorted/MachineSimulation7400.c +++ /dev/null @@ -1,744 +0,0 @@ -#include "compiler/Scheduler.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" - -// https://www.nxp.com/docs/en/reference-manual/MPC7410UM.pdf - -typedef enum Stage { - BPU, // Branch Prediction Unit - IU1, // Integer Unit 1 - IU2, // Integer Unit 2 - - LSU1, // Load/Store Unit - LSU2, - - FPU1, // Floating Point Unit - FPU2, - FPU3, - - SRU, // System Register Unit - VSIU, // Vector Simple Integer Unit - VPU, // AltiVec Permute Unit - - VCIU1, // Vector Complex Integer Unit - VCIU2, - VCIU3, - - VFPU1, // Vector Floating-Point Unit - VFPU2, - VFPU3, - VFPU4, - - NumStages -} Stage; - -static struct { - // the instruction currently in this pipeline stage - PCode *instr; - - // how many cycles are left for this instruction to finish - int remaining; -} pipeline[NumStages]; - -static PCode *iu1_completed_instruction; -static PCode *iu2_completed_instruction; - -enum { - MaxEntries = 8 -}; - -static struct { - // how many entries remain unused in the queue - unsigned int free; - - // how many entries are currently used in the queue - unsigned int used; - - // the index of the next instruction that will be retired - unsigned int nextToRetire; - - // the index of the next free slot that will be used when an instruction is dispatched - unsigned int nextFreeSlot; - - // circular array of entries in the completion queue - struct { - PCode *instr; - int completed; - } entries[MaxEntries]; -} completionbuffers; - -static struct { - // the initial stage for this instruction - Stage stage; - - // the total amount of cycles required by this instruction - char latency; - - // how long it takes to finish each stage - char cycles[4]; - - // does this instruction serialise? - char serializes; - - char unused; -} instruction_timing[OPCODE_MAX] = { - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_B - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BL - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BC - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BCLR - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BCCTR - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BT - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BTLR - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BTCTR - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BF - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BFLR - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BFCTR - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDNZ - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDNZT - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDNZF - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDZ - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDZT - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDZF - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BLR - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BCTR - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BCTRL - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BLRL - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LBZ - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LBZU - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LBZX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LBZUX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHZ - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHZU - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHZX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHZUX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHA - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHAU - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHAX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHAUX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LHBRX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LWZ - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LWZU - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LWZX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LWZUX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LWBRX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LMW - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STB - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STBU - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STBX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STBUX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STH - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STHU - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STHX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STHUX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STHBRX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STW - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STWU - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STWX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STWUX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STWBRX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STMW - LSU1, 3, 1, 2, 0, 0, 0, 0, // PC_DCBF - LSU1, 3, 1, 2, 0, 0, 0, 0, // PC_DCBST - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_DCBT - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_DCBTST - LSU1, 3, 1, 2, 0, 0, 0, 0, // PC_DCBZ - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADD - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADDC - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADDE - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADDI - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADDIC - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADDICR - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADDIS - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADDME - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ADDZE - IU1, 19, 19, 0, 0, 0, 0, 0, // PC_DIVW - IU1, 19, 19, 0, 0, 0, 0, 0, // PC_DIVWU - IU1, 5, 5, 0, 0, 0, 0, 0, // PC_MULHW - IU1, 6, 5, 0, 0, 0, 0, 0, // PC_MULHWU - IU1, 3, 3, 0, 0, 0, 0, 0, // PC_MULLI - IU1, 5, 5, 0, 0, 0, 0, 0, // PC_MULLW - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_NEG - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SUBF - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFC - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFE - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFIC - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFME - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFZE - IU2, 3, 1, 0, 0, 0, 0, 0, // PC_CMPI - IU2, 3, 1, 0, 0, 0, 0, 0, // PC_CMP - IU2, 3, 1, 0, 0, 0, 0, 0, // PC_CMPLI - IU2, 3, 1, 0, 0, 0, 0, 0, // PC_CMPL - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ANDI - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ANDIS - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ORI - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ORIS - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_XORI - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_XORIS - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_AND - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_OR - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_XOR - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_NAND - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_NOR - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_EQV - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ANDC - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ORC - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_EXTSB - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_EXTSH - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_CNTLZW - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_RLWINM - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_RLWNM - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_RLWIMI - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SLW - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SRW - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SRAWI - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_SRAW - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_CRAND - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_CRANDC - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_CREQV - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_CRNAND - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_CRNOR - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_CROR - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_CRORC - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_CRXOR - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MCRF - SRU, 2, 2, 0, 0, 0, 1, 0, // PC_MTXER - SRU, 2, 2, 0, 0, 0, 1, 0, // PC_MTCTR - SRU, 2, 2, 0, 0, 0, 1, 0, // PC_MTLR - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MTCRF - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MTMSR - SRU, 2, 2, 0, 0, 0, 1, 0, // PC_MTSPR - SRU, 1, 1, 0, 0, 0, 0, 0, // PC_MFMSR - SRU, 3, 3, 0, 0, 0, 1, 0, // PC_MFSPR - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MFXER - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MFCTR - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MFLR - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MFCR - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_MFFS - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_MTFSF - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_EIEIO - SRU, 2, 2, 0, 0, 0, 1, 0, // PC_ISYNC - SRU, 3, 3, 0, 0, 0, 1, 0, // PC_SYNC - SRU, 2, 2, 0, 0, 0, 1, 0, // PC_RFI - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_LI - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_LIS - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_MR - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_NOP - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_NOT - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LFS - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LFSU - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LFSX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LFSUX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LFD - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LFDU - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LFDX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LFDUX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFS - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFSU - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFSX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFSUX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFD - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFDU - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFDX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFDUX - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FMR - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FABS - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FNEG - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FNABS - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FADD - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FADDS - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FSUB - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FSUBS - FPU1, 4, 2, 1, 1, 0, 0, 0, // PC_FMUL - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FMULS - FPU1, 31, 31, 0, 0, 0, 0, 0, // PC_FDIV - FPU1, 17, 17, 0, 0, 0, 0, 0, // PC_FDIVS - FPU1, 4, 2, 1, 1, 0, 0, 0, // PC_FMADD - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FMADDS - FPU1, 4, 2, 1, 1, 0, 0, 0, // PC_FMSUB - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FMSUBS - FPU1, 4, 2, 1, 1, 0, 0, 0, // PC_FNMADD - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FNMADDS - FPU1, 4, 2, 1, 1, 0, 0, 0, // PC_FNMSUB - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FNMSUBS - FPU1, 10, 10, 0, 0, 0, 0, 0, // PC_FRES - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FRSQRTE - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FSEL - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FRSP - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FCTIW - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FCTIWZ - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FCMPU - FPU1, 3, 1, 1, 1, 0, 0, 0, // PC_FCMPO - LSU1, 2, 1, 1, 0, 0, 1, 0, // PC_LWARX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LSWI - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LSWX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STFIWX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STSWI - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STSWX - LSU1, 2, 1, 1, 0, 0, 1, 0, // PC_STWCX - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ECIWX - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ECOWX - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_DCBI - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ICBI - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MCRFS - SRU, 1, 1, 0, 0, 0, 1, 0, // PC_MCRXR - SRU, 1, 1, 0, 0, 0, 0, 0, // PC_MFTB - SRU, 3, 3, 0, 0, 0, 0, 0, // PC_MFSR - SRU, 2, 2, 0, 0, 0, 1, 0, // PC_MTSR - SRU, 3, 3, 0, 0, 0, 0, 0, // PC_MFSRIN - SRU, 2, 2, 0, 0, 0, 1, 0, // PC_MTSRIN - FPU1, 1, 1, 0, 0, 0, 0, 0, // PC_MTFSB0 - FPU1, 1, 1, 0, 0, 0, 0, 0, // PC_MTFSB1 - FPU1, 1, 1, 0, 0, 0, 0, 0, // PC_MTFSFI - SRU, 2, 2, 0, 0, 0, 1, 0, // PC_SC - FPU1, 1, 1, 0, 0, 0, 0, 0, // PC_FSQRT - FPU1, 1, 1, 0, 0, 0, 0, 0, // PC_FSQRTS - LSU1, 1, 1, 0, 0, 0, 0, 0, // PC_TLBIA - LSU1, 1, 1, 0, 0, 0, 0, 0, // PC_TLBIE - LSU1, 1, 1, 0, 0, 0, 0, 0, // PC_TLBLD - LSU1, 1, 1, 0, 0, 0, 0, 0, // PC_TLBLI - LSU1, 1, 1, 0, 0, 0, 1, 0, // PC_TLBSYNC - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_TW - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_TRAP - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_TWI - IU2, 1, 1, 0, 0, 0, 1, 0, // PC_OPWORD - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_MFROM - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_DSA - IU2, 1, 1, 0, 0, 0, 0, 0, // PC_ESA - IU2, 1, 0, 0, 0, 0, 0, 0, // PC_DCCCI - IU2, 1, 0, 0, 0, 0, 0, 0, // PC_DCREAD - IU2, 1, 0, 0, 0, 0, 0, 0, // PC_ICBT - IU2, 1, 0, 0, 0, 0, 0, 0, // PC_ICCCI - IU2, 1, 0, 0, 0, 0, 0, 0, // PC_ICREAD - IU2, 1, 0, 0, 0, 0, 0, 0, // PC_RFCI - IU2, 1, 0, 0, 0, 0, 0, 0, // PC_TLBRE - IU2, 1, 0, 0, 0, 0, 0, 0, // PC_TLBSX - IU2, 1, 0, 0, 0, 0, 0, 0, // PC_TLBWE - IU2, 1, 0, 0, 0, 0, 0, 0, // PC_WRTEE - IU2, 1, 0, 0, 0, 0, 0, 0, // PC_WRTEEI - IU2, 1, 0, 0, 0, 0, 0, 0, // PC_MFDCR - IU2, 1, 0, 0, 0, 0, 0, 0, // PC_MTDCR - LSU1, 3, 1, 2, 0, 0, 0, 0, // PC_DCBA - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_DSS - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_DSSALL - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_DST - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_DSTT - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_DSTST - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_DSTSTT - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LVEBX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LVEHX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LVEWX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LVSL - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LVSR - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LVX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_LVXL - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STVEBX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STVEHX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STVEWX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STVX - LSU1, 2, 1, 1, 0, 0, 0, 0, // PC_STVXL - VSIU, 1, 1, 0, 0, 0, 1, 0, // PC_MFVSCR - VSIU, 1, 1, 0, 0, 0, 1, 0, // PC_MTVSCR - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDCUW - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VADDFP - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDSBS - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDSHS - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDSWS - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUBM - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUBS - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUHM - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUHS - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUWM - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUWS - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VAND - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VANDC - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGSB - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGSH - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGSW - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGUB - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGUH - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGUW - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VCFSX - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VCFUX - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VCMPBFP - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VCMPEQFP - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPEQUB - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPEQUH - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPEQUW - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VCMPGEFP - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VCMPGTFP - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTSB - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTSH - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTSW - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTUB - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTUH - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTUW - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VCTSXS - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VCTUXS - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VEXPTEFP - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VLOGEFP - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VMAXFP - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXSB - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXSH - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXSW - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXUB - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXUH - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXUW - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VMINFP - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMINSB - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMINSH - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMINSW - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMINUB - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMINUH - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMINUW - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VMRGHB - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VMRGHH - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VMRGHW - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VMRGLB - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VMRGLH - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VMRGLW - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMULESB - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMULESH - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMULEUB - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMULEUH - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMULOSB - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMULOSH - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMULOUB - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMULOUH - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VNOR - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VOR - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKPX - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKSHSS - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKSHUS - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKSWSS - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKSWUS - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKUHUM - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKUHUS - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKUWUM - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPKUWUS - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VREFP - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VRFIM - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VRFIN - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VRFIP - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VRFIZ - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VRLB - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VRLH - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VRLW - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VRSQRTEFP - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSL - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSLB - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSLH - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSLO - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSLW - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSPLTB - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSPLTH - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSPLTW - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSPLTISB - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSPLTISH - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSPLTISW - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSR - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSRAB - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSRAH - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSRAW - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSRB - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSRH - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSRO - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSRW - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBCUW - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VSUBFP - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBSBS - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBSHS - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBSWS - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUBM - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUBS - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUHM - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUHS - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUWM - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUWS - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VSUMSWS - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VSUM2SWS - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VSUM4SBS - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VSUM4SHS - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VSUM4UBS - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VUPKHPX - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VUPKHSB - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VUPKHSH - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VUPKLPX - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VUPKLSB - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VUPKLSH - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VXOR - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VMADDFP - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMHADDSHS - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMHRADDSHS - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMLADDUHM - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMSUMMBM - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMSUMSHM - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMSUMSHS - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMSUMUBM - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMSUMUHM - VCIU1, 3, 1, 1, 1, 0, 0, 0, // PC_VMSUMUHS - VFPU1, 4, 1, 1, 1, 1, 0, 0, // PC_VNMSUBFP - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VPERM - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VSEL - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VSLDOI - VSIU, 1, 1, 0, 0, 0, 0, 0, // PC_VMR - VPU, 1, 1, 0, 0, 0, 0, 0, // PC_VMRP - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SLE - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SLEQ - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SLIQ - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SLLIQ - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SLLQ - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SLQ - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SRAIQ - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SRAQ - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SRE - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SREA - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SREQ - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SRIQ - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SRLIQ - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SRLQ - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_SRQ - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_MASKG - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_MASKIR - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_LSCBX - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_DIV - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_DIVS - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_DOZ - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_MUL - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_NABS - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_ABS - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_CLCS - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_DOZI - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_RLMI - BPU, 0, 0, 0, 0, 0, 0, 0, // PC_RRIB -}; - -static void advance(int firstStage, int oldStage, int newStage) { - PCode *instr = pipeline[oldStage].instr; - int cycles = instruction_timing[instr->op].cycles[newStage - firstStage]; - pipeline[newStage].instr = instr; - pipeline[newStage].remaining = cycles; - pipeline[oldStage].instr = NULL; -} - -static void assign_completion_buffer(PCode *instr) { - completionbuffers.used++; - completionbuffers.free--; - completionbuffers.entries[completionbuffers.nextFreeSlot].instr = instr; - completionbuffers.entries[completionbuffers.nextFreeSlot].completed = 0; - completionbuffers.nextFreeSlot = (completionbuffers.nextFreeSlot + 1) % MaxEntries; -} - -static void complete_instruction(int stage) { - PCode *instr = pipeline[stage].instr; - int buf = 0; - while (buf < MaxEntries && completionbuffers.entries[buf].instr != instr) - buf++; - - completionbuffers.entries[buf].completed = 1; - pipeline[stage].instr = NULL; - - if (stage == IU1) - iu1_completed_instruction = instr; - else if (stage == IU2) - iu2_completed_instruction = instr; -} - -static void retire_instruction(void) { - completionbuffers.entries[completionbuffers.nextToRetire].instr = NULL; - completionbuffers.used--; - completionbuffers.free++; - completionbuffers.nextToRetire = (completionbuffers.nextToRetire + 1) % MaxEntries; -} - -static int latency(PCode *instr) { - int cycles = instruction_timing[instr->op].latency; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - cycles += 2; - if (instr->op == PC_LMW || instr->op == PC_STMW) - cycles += instr->argCount - 2; - return cycles; -} - -static void initialize(void) { - int stage; - int i; - - for (stage = 0; stage < NumStages; stage++) - pipeline[stage].instr = NULL; - - completionbuffers.free = MaxEntries; - completionbuffers.used = 0; - completionbuffers.nextToRetire = 0; - completionbuffers.nextFreeSlot = 0; - for (i = 0; i < MaxEntries; i++) - completionbuffers.entries[i].instr = NULL; - - iu1_completed_instruction = NULL; - iu2_completed_instruction = NULL; -} - -static int can_issue(PCode *instr) { - int stage; - - if (completionbuffers.free == 0) - return 0; - - stage = instruction_timing[instr->op].stage; - - if (stage == IU2) { - PCode *check; - int isClear1 = !pipeline[IU1].instr; - int isClear2 = !pipeline[IU2].instr; - if (!isClear1 && !isClear2) - return 0; - if (isClear1 && isClear2) - return 1; - - if (isClear1) - check = pipeline[IU2].instr; - else - check = pipeline[IU1].instr; - - if (is_dependent(instr, check, RegClass_GPR)) - return 0; - if (is_dependent(instr, iu1_completed_instruction, RegClass_GPR)) - return 0; - if (is_dependent(instr, iu2_completed_instruction, RegClass_GPR)) - return 0; - } else if (stage == VFPU1 || stage == VCIU1 || stage == VSIU || stage == VPU) { - PCode *check; - int isVpuClear = !pipeline[VPU].instr; - int isVFpuClear = !pipeline[VFPU1].instr; - int isVCiuClear = !pipeline[VCIU1].instr; - int isVSiuClear = !pipeline[VSIU].instr; - - if (stage == VPU) { - if (!isVpuClear) - return 0; - - if (!isVFpuClear) - check = pipeline[VFPU1].instr; - else if (!isVCiuClear) - check = pipeline[VCIU1].instr; - else if (!isVSiuClear) - check = pipeline[VSIU].instr; - else - check = NULL; - - if (is_dependent(instr, check, RegClass_VR)) - return 0; - } else { - if (!isVFpuClear || !isVCiuClear || !isVSiuClear) - return 0; - - if (!isVpuClear && is_dependent(instr, pipeline[VPU].instr, RegClass_VR)) - return 0; - } - } else { - if (pipeline[stage].instr) - return 0; - } - - if ((instr->flags & fIsWrite) && pipeline[LSU2].instr && (pipeline[LSU2].instr->flags & fIsWrite)) - return 0; - - return 1; -} - -static void issue(PCode *instr) { - int stage = instruction_timing[instr->op].stage; - int cycles = instruction_timing[instr->op].cycles[0]; - assign_completion_buffer(instr); - if (stage == IU2 && !pipeline[IU1].instr) - stage = IU1; - pipeline[stage].instr = instr; - pipeline[stage].remaining = cycles; -} - -static void advance_clock(void) { - int stage; - - iu1_completed_instruction = NULL; - iu2_completed_instruction = NULL; - - for (stage = 0; stage < NumStages; stage++) { - if (pipeline[stage].instr && pipeline[stage].remaining) - --pipeline[stage].remaining; - } - - if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { - retire_instruction(); - if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { - retire_instruction(); - } - } - - if (pipeline[IU1].instr && pipeline[IU1].remaining == 0) - complete_instruction(IU1); - if (pipeline[VPU].instr && pipeline[VPU].remaining == 0) - complete_instruction(VPU); - if (pipeline[LSU2].instr && pipeline[LSU2].remaining == 0) - complete_instruction(LSU2); - if (pipeline[FPU3].instr && pipeline[FPU3].remaining == 0) - complete_instruction(FPU3); - if (pipeline[SRU].instr && pipeline[SRU].remaining == 0) - complete_instruction(SRU); - if (pipeline[BPU].instr && pipeline[BPU].remaining == 0) - complete_instruction(BPU); - if (pipeline[VSIU].instr && pipeline[VSIU].remaining == 0) - complete_instruction(VSIU); - if (pipeline[VCIU3].instr && pipeline[VCIU3].remaining == 0) - complete_instruction(VCIU3); - if (pipeline[VFPU4].instr && pipeline[VFPU4].remaining == 0) - complete_instruction(VFPU4); - if (pipeline[IU2].instr && pipeline[IU2].remaining == 0) - complete_instruction(IU2); - - if ( - pipeline[FPU1].instr && - pipeline[FPU1].remaining == 0 && - (pipeline[FPU1].instr->op == PC_FDIV || pipeline[FPU1].instr->op == PC_FDIVS) - ) - complete_instruction(FPU1); - - if (pipeline[FPU2].instr && pipeline[FPU2].remaining == 0 && !pipeline[FPU3].instr) - advance(FPU1, FPU2, FPU3); - if (pipeline[FPU1].instr && pipeline[FPU1].remaining == 0 && !pipeline[FPU2].instr) - advance(FPU1, FPU1, FPU2); - - if (pipeline[LSU1].instr && pipeline[LSU1].remaining == 0 && !pipeline[LSU2].instr) - advance(LSU1, LSU1, LSU2); - - if (pipeline[VCIU2].instr && pipeline[VCIU2].remaining == 0 && !pipeline[VCIU3].instr) - advance(VCIU1, VCIU2, VCIU3); - if (pipeline[VCIU1].instr && pipeline[VCIU1].remaining == 0 && !pipeline[VCIU2].instr) - advance(VCIU1, VCIU1, VCIU2); - - if (pipeline[VFPU3].instr && pipeline[VFPU3].remaining == 0 && !pipeline[VFPU4].instr) - advance(VFPU1, VFPU3, VFPU4); - if (pipeline[VFPU2].instr && pipeline[VFPU2].remaining == 0 && !pipeline[VFPU3].instr) - advance(VFPU1, VFPU2, VFPU3); - if (pipeline[VFPU1].instr && pipeline[VFPU1].remaining == 0 && !pipeline[VFPU2].instr) - advance(VFPU1, VFPU1, VFPU2); -} - -static int serializes(PCode *instr) { - return instruction_timing[instr->op].serializes; -} - -static int uses_vpermute_unit_7400(PCode *instr) { - return instruction_timing[instr->op].stage == VPU; -} - -MachineInfo machine7400 = { - 2, - 1, - 0, - &latency, - &initialize, - &can_issue, - &issue, - &advance_clock, - &serializes, - &uses_vpermute_unit_7400 -}; diff --git a/compiler_and_linker/unsorted/MachineSimulation750.c b/compiler_and_linker/unsorted/MachineSimulation750.c deleted file mode 100644 index d412df3..0000000 --- a/compiler_and_linker/unsorted/MachineSimulation750.c +++ /dev/null @@ -1,678 +0,0 @@ -#include "compiler/Scheduler.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" - -// https://www.nxp.com/docs/en/reference-manual/MPC750UM.pdf - -typedef enum Stage { - BPU, // Branch Prediction Unit - IU1, // Integer Unit 1 - IU2, // Integer Unit 2 - - LSU1, // Load/Store Unit - LSU2, - - FPU1, // Floating Point Unit - FPU2, - FPU3, - - SRU, // System Register Unit - - NumStages -} Stage; - -static struct { - // the instruction currently in this pipeline stage - PCode *instr; - - // how many cycles are left for this instruction to finish - int remaining; -} pipeline[NumStages]; - -static PCode *iu1_completed_instruction; -static PCode *iu2_completed_instruction; - -enum { - MaxEntries = 6 -}; - -static struct { - // how many entries remain unused in the queue - unsigned int free; - - // how many entries are currently used in the queue - unsigned int used; - - // the index of the next instruction that will be retired - unsigned int nextToRetire; - - // the index of the next free slot that will be used when an instruction is dispatched - unsigned int nextFreeSlot; - - // circular array of entries in the completion queue - struct { - PCode *instr; - int completed; - } entries[MaxEntries]; -} completionbuffers; - -static struct { - // the initial stage for this instruction - Stage stage; - - // the total amount of cycles required by this instruction - char latency; - - // how long it takes to finish each stage - char cycles[3]; - - // does this instruction serialise? - char serializes; -} instruction_timing[OPCODE_MAX] = { - BPU, 0, 0, 0, 0, 1, // PC_B - BPU, 0, 0, 0, 0, 1, // PC_BL - BPU, 0, 0, 0, 0, 1, // PC_BC - BPU, 0, 0, 0, 0, 1, // PC_BCLR - BPU, 0, 0, 0, 0, 1, // PC_BCCTR - BPU, 0, 0, 0, 0, 1, // PC_BT - BPU, 0, 0, 0, 0, 1, // PC_BTLR - BPU, 0, 0, 0, 0, 1, // PC_BTCTR - BPU, 0, 0, 0, 0, 1, // PC_BF - BPU, 0, 0, 0, 0, 1, // PC_BFLR - BPU, 0, 0, 0, 0, 1, // PC_BFCTR - BPU, 0, 0, 0, 0, 1, // PC_BDNZ - BPU, 0, 0, 0, 0, 1, // PC_BDNZT - BPU, 0, 0, 0, 0, 1, // PC_BDNZF - BPU, 0, 0, 0, 0, 1, // PC_BDZ - BPU, 0, 0, 0, 0, 1, // PC_BDZT - BPU, 0, 0, 0, 0, 1, // PC_BDZF - BPU, 0, 0, 0, 0, 1, // PC_BLR - BPU, 0, 0, 0, 0, 1, // PC_BCTR - BPU, 0, 0, 0, 0, 1, // PC_BCTRL - BPU, 0, 0, 0, 0, 1, // PC_BLRL - LSU1, 2, 1, 1, 0, 0, // PC_LBZ - LSU1, 2, 1, 1, 0, 0, // PC_LBZU - LSU1, 2, 1, 1, 0, 0, // PC_LBZX - LSU1, 2, 1, 1, 0, 0, // PC_LBZUX - LSU1, 2, 1, 1, 0, 0, // PC_LHZ - LSU1, 2, 1, 1, 0, 0, // PC_LHZU - LSU1, 2, 1, 1, 0, 0, // PC_LHZX - LSU1, 2, 1, 1, 0, 0, // PC_LHZUX - LSU1, 2, 1, 1, 0, 0, // PC_LHA - LSU1, 2, 1, 1, 0, 0, // PC_LHAU - LSU1, 2, 1, 1, 0, 0, // PC_LHAX - LSU1, 2, 1, 1, 0, 0, // PC_LHAUX - LSU1, 2, 1, 1, 0, 0, // PC_LHBRX - LSU1, 2, 1, 1, 0, 0, // PC_LWZ - LSU1, 2, 1, 1, 0, 0, // PC_LWZU - LSU1, 2, 1, 1, 0, 0, // PC_LWZX - LSU1, 2, 1, 1, 0, 0, // PC_LWZUX - LSU1, 2, 1, 1, 0, 0, // PC_LWBRX - LSU1, 2, 1, 1, 0, 0, // PC_LMW - LSU1, 2, 1, 1, 0, 0, // PC_STB - LSU1, 2, 1, 1, 0, 0, // PC_STBU - LSU1, 2, 1, 1, 0, 0, // PC_STBX - LSU1, 2, 1, 1, 0, 0, // PC_STBUX - LSU1, 2, 1, 1, 0, 0, // PC_STH - LSU1, 2, 1, 1, 0, 0, // PC_STHU - LSU1, 2, 1, 1, 0, 0, // PC_STHX - LSU1, 2, 1, 1, 0, 0, // PC_STHUX - LSU1, 2, 1, 1, 0, 0, // PC_STHBRX - LSU1, 2, 1, 1, 0, 0, // PC_STW - LSU1, 2, 1, 1, 0, 0, // PC_STWU - LSU1, 2, 1, 1, 0, 0, // PC_STWX - LSU1, 2, 1, 1, 0, 0, // PC_STWUX - LSU1, 2, 1, 1, 0, 0, // PC_STWBRX - LSU1, 2, 1, 1, 0, 0, // PC_STMW - LSU1, 3, 1, 2, 0, 0, // PC_DCBF - LSU1, 3, 1, 2, 0, 0, // PC_DCBST - LSU1, 2, 1, 1, 0, 0, // PC_DCBT - LSU1, 2, 1, 1, 0, 0, // PC_DCBTST - LSU1, 3, 1, 2, 0, 0, // PC_DCBZ - IU2, 1, 1, 0, 0, 0, // PC_ADD - IU2, 1, 1, 0, 0, 0, // PC_ADDC - IU2, 1, 1, 0, 0, 0, // PC_ADDE - IU2, 1, 1, 0, 0, 0, // PC_ADDI - IU2, 1, 1, 0, 0, 0, // PC_ADDIC - IU2, 1, 1, 0, 0, 0, // PC_ADDICR - IU2, 1, 1, 0, 0, 0, // PC_ADDIS - IU2, 1, 1, 0, 0, 0, // PC_ADDME - IU2, 1, 1, 0, 0, 0, // PC_ADDZE - IU1, 19, 19, 0, 0, 0, // PC_DIVW - IU1, 19, 19, 0, 0, 0, // PC_DIVWU - IU1, 5, 5, 0, 0, 0, // PC_MULHW - IU1, 6, 5, 0, 0, 0, // PC_MULHWU - IU1, 3, 3, 0, 0, 0, // PC_MULLI - IU1, 5, 5, 0, 0, 0, // PC_MULLW - IU2, 1, 1, 0, 0, 0, // PC_NEG - IU2, 1, 1, 0, 0, 0, // PC_SUBF - IU2, 1, 1, 0, 0, 0, // PC_SUBFC - IU2, 1, 1, 0, 0, 0, // PC_SUBFE - IU2, 1, 1, 0, 0, 0, // PC_SUBFIC - IU2, 1, 1, 0, 0, 0, // PC_SUBFME - IU2, 1, 1, 0, 0, 0, // PC_SUBFZE - IU2, 3, 1, 0, 0, 0, // PC_CMPI - IU2, 3, 1, 0, 0, 0, // PC_CMP - IU2, 3, 1, 0, 0, 0, // PC_CMPLI - IU2, 3, 1, 0, 0, 0, // PC_CMPL - IU2, 1, 1, 0, 0, 0, // PC_ANDI - IU2, 1, 1, 0, 0, 0, // PC_ANDIS - IU2, 1, 1, 0, 0, 0, // PC_ORI - IU2, 1, 1, 0, 0, 0, // PC_ORIS - IU2, 1, 1, 0, 0, 0, // PC_XORI - IU2, 1, 1, 0, 0, 0, // PC_XORIS - IU2, 1, 1, 0, 0, 0, // PC_AND - IU2, 1, 1, 0, 0, 0, // PC_OR - IU2, 1, 1, 0, 0, 0, // PC_XOR - IU2, 1, 1, 0, 0, 0, // PC_NAND - IU2, 1, 1, 0, 0, 0, // PC_NOR - IU2, 1, 1, 0, 0, 0, // PC_EQV - IU2, 1, 1, 0, 0, 0, // PC_ANDC - IU2, 1, 1, 0, 0, 0, // PC_ORC - IU2, 1, 1, 0, 0, 0, // PC_EXTSB - IU2, 1, 1, 0, 0, 0, // PC_EXTSH - IU2, 1, 1, 0, 0, 0, // PC_CNTLZW - IU2, 1, 1, 0, 0, 0, // PC_RLWINM - IU2, 1, 1, 0, 0, 0, // PC_RLWNM - IU2, 1, 1, 0, 0, 0, // PC_RLWIMI - IU2, 1, 1, 0, 0, 0, // PC_SLW - IU2, 1, 1, 0, 0, 0, // PC_SRW - IU2, 1, 1, 0, 0, 0, // PC_SRAWI - IU2, 1, 1, 0, 0, 0, // PC_SRAW - SRU, 1, 1, 0, 0, 1, // PC_CRAND - SRU, 1, 1, 0, 0, 1, // PC_CRANDC - SRU, 1, 1, 0, 0, 1, // PC_CREQV - SRU, 1, 1, 0, 0, 1, // PC_CRNAND - SRU, 1, 1, 0, 0, 1, // PC_CRNOR - SRU, 1, 1, 0, 0, 1, // PC_CROR - SRU, 1, 1, 0, 0, 1, // PC_CRORC - SRU, 1, 1, 0, 0, 1, // PC_CRXOR - SRU, 1, 1, 0, 0, 1, // PC_MCRF - SRU, 2, 2, 0, 0, 1, // PC_MTXER - SRU, 2, 2, 0, 0, 1, // PC_MTCTR - SRU, 2, 2, 0, 0, 1, // PC_MTLR - SRU, 1, 1, 0, 0, 1, // PC_MTCRF - SRU, 1, 1, 0, 0, 0, // PC_MTMSR - SRU, 1, 1, 0, 0, 1, // PC_MTSPR - SRU, 1, 1, 0, 0, 1, // PC_MFMSR - SRU, 1, 1, 0, 0, 1, // PC_MFSPR - SRU, 1, 1, 0, 0, 1, // PC_MFXER - SRU, 1, 1, 0, 0, 1, // PC_MFCTR - SRU, 1, 1, 0, 0, 1, // PC_MFLR - SRU, 1, 1, 0, 0, 1, // PC_MFCR - FPU1, 3, 1, 1, 1, 0, // PC_MFFS - FPU1, 3, 1, 1, 1, 0, // PC_MTFSF - SRU, 1, 1, 0, 0, 1, // PC_EIEIO - SRU, 2, 2, 0, 0, 1, // PC_ISYNC - SRU, 3, 3, 0, 0, 1, // PC_SYNC - SRU, 1, 1, 0, 0, 1, // PC_RFI - IU2, 1, 1, 0, 0, 0, // PC_LI - IU2, 1, 1, 0, 0, 0, // PC_LIS - IU2, 1, 1, 0, 0, 0, // PC_MR - IU2, 1, 1, 0, 0, 0, // PC_NOP - IU2, 1, 1, 0, 0, 0, // PC_NOT - LSU1, 2, 1, 1, 0, 0, // PC_LFS - LSU1, 2, 1, 1, 0, 0, // PC_LFSU - LSU1, 2, 1, 1, 0, 0, // PC_LFSX - LSU1, 2, 1, 1, 0, 0, // PC_LFSUX - LSU1, 2, 1, 1, 0, 0, // PC_LFD - LSU1, 2, 1, 1, 0, 0, // PC_LFDU - LSU1, 2, 1, 1, 0, 0, // PC_LFDX - LSU1, 2, 1, 1, 0, 0, // PC_LFDUX - LSU1, 2, 1, 1, 0, 0, // PC_STFS - LSU1, 2, 1, 1, 0, 0, // PC_STFSU - LSU1, 2, 1, 1, 0, 0, // PC_STFSX - LSU1, 2, 1, 1, 0, 0, // PC_STFSUX - LSU1, 2, 1, 1, 0, 0, // PC_STFD - LSU1, 2, 1, 1, 0, 0, // PC_STFDU - LSU1, 2, 1, 1, 0, 0, // PC_STFDX - LSU1, 2, 1, 1, 0, 0, // PC_STFDUX - FPU1, 3, 1, 1, 1, 0, // PC_FMR - FPU1, 3, 1, 1, 1, 0, // PC_FABS - FPU1, 3, 1, 1, 1, 0, // PC_FNEG - FPU1, 3, 1, 1, 1, 0, // PC_FNABS - FPU1, 3, 1, 1, 1, 0, // PC_FADD - FPU1, 3, 1, 1, 1, 0, // PC_FADDS - FPU1, 3, 1, 1, 1, 0, // PC_FSUB - FPU1, 3, 1, 1, 1, 0, // PC_FSUBS - FPU1, 4, 2, 1, 1, 0, // PC_FMUL - FPU1, 3, 1, 1, 1, 0, // PC_FMULS - FPU1, 31, 31, 0, 0, 0, // PC_FDIV - FPU1, 17, 17, 0, 0, 0, // PC_FDIVS - FPU1, 4, 2, 1, 1, 0, // PC_FMADD - FPU1, 3, 1, 1, 1, 0, // PC_FMADDS - FPU1, 4, 2, 1, 1, 0, // PC_FMSUB - FPU1, 3, 1, 1, 1, 0, // PC_FMSUBS - FPU1, 4, 2, 1, 1, 0, // PC_FNMADD - FPU1, 3, 1, 1, 1, 0, // PC_FNMADDS - FPU1, 4, 2, 1, 1, 0, // PC_FNMSUB - FPU1, 3, 1, 1, 1, 0, // PC_FNMSUBS - FPU1, 10, 10, 0, 0, 0, // PC_FRES - FPU1, 3, 1, 1, 1, 0, // PC_FRSQRTE - FPU1, 3, 1, 1, 1, 0, // PC_FSEL - FPU1, 3, 1, 1, 1, 0, // PC_FRSP - FPU1, 3, 1, 1, 1, 0, // PC_FCTIW - FPU1, 3, 1, 1, 1, 0, // PC_FCTIWZ - FPU1, 3, 1, 1, 1, 0, // PC_FCMPU - FPU1, 3, 1, 1, 1, 0, // PC_FCMPO - LSU1, 1, 1, 0, 0, 0, // PC_LWARX - LSU1, 1, 1, 0, 0, 0, // PC_LSWI - LSU1, 1, 1, 0, 0, 0, // PC_LSWX - LSU1, 1, 1, 0, 0, 0, // PC_STFIWX - LSU1, 1, 1, 0, 0, 0, // PC_STSWI - LSU1, 1, 1, 0, 0, 0, // PC_STSWX - LSU1, 1, 1, 0, 0, 0, // PC_STWCX - IU1, 1, 1, 0, 0, 1, // PC_ECIWX - IU1, 1, 1, 0, 0, 1, // PC_ECOWX - IU1, 1, 1, 0, 0, 0, // PC_DCBI - IU1, 1, 1, 0, 0, 0, // PC_ICBI - IU1, 1, 1, 0, 0, 0, // PC_MCRFS - IU1, 1, 1, 0, 0, 0, // PC_MCRXR - IU1, 1, 1, 0, 0, 0, // PC_MFTB - IU1, 1, 1, 0, 0, 0, // PC_MFSR - IU1, 1, 1, 0, 0, 0, // PC_MTSR - IU1, 1, 1, 0, 0, 0, // PC_MFSRIN - IU1, 1, 1, 0, 0, 0, // PC_MTSRIN - IU1, 1, 1, 0, 0, 0, // PC_MTFSB0 - IU1, 1, 1, 0, 0, 0, // PC_MTFSB1 - IU1, 1, 1, 0, 0, 0, // PC_MTFSFI - IU1, 1, 1, 0, 0, 1, // PC_SC - FPU1, 1, 1, 0, 0, 0, // PC_FSQRT - FPU1, 1, 1, 0, 0, 0, // PC_FSQRTS - IU1, 1, 1, 0, 0, 0, // PC_TLBIA - IU1, 1, 1, 0, 0, 0, // PC_TLBIE - IU1, 1, 1, 0, 0, 0, // PC_TLBLD - IU1, 1, 1, 0, 0, 0, // PC_TLBLI - IU1, 1, 1, 0, 0, 0, // PC_TLBSYNC - IU1, 1, 1, 0, 0, 1, // PC_TW - IU1, 1, 1, 0, 0, 1, // PC_TRAP - IU1, 1, 1, 0, 0, 1, // PC_TWI - IU1, 1, 1, 0, 0, 1, // PC_OPWORD - IU1, 1, 1, 0, 0, 0, // PC_MFROM - IU1, 1, 1, 0, 0, 1, // PC_DSA - IU1, 1, 1, 0, 0, 1, // PC_ESA - IU1, 0, 0, 0, 0, 0, // PC_DCCCI - IU1, 0, 0, 0, 0, 0, // PC_DCREAD - IU1, 0, 0, 0, 0, 0, // PC_ICBT - IU1, 0, 0, 0, 0, 0, // PC_ICCCI - IU1, 0, 0, 0, 0, 0, // PC_ICREAD - IU1, 0, 0, 0, 0, 0, // PC_RFCI - IU1, 0, 0, 0, 0, 0, // PC_TLBRE - IU1, 0, 0, 0, 0, 0, // PC_TLBSX - IU1, 0, 0, 0, 0, 0, // PC_TLBWE - IU1, 0, 0, 0, 0, 0, // PC_WRTEE - IU1, 0, 0, 0, 0, 0, // PC_WRTEEI - IU1, 0, 0, 0, 0, 0, // PC_MFDCR - IU1, 0, 0, 0, 0, 0, // PC_MTDCR - IU1, 0, 0, 0, 0, 0, // PC_DCBA - BPU, 0, 0, 0, 0, 0, // PC_DSS - BPU, 0, 0, 0, 0, 0, // PC_DSSALL - BPU, 0, 0, 0, 0, 0, // PC_DST - BPU, 0, 0, 0, 0, 0, // PC_DSTT - BPU, 0, 0, 0, 0, 0, // PC_DSTST - BPU, 0, 0, 0, 0, 0, // PC_DSTSTT - BPU, 0, 0, 0, 0, 0, // PC_LVEBX - BPU, 0, 0, 0, 0, 0, // PC_LVEHX - BPU, 0, 0, 0, 0, 0, // PC_LVEWX - BPU, 0, 0, 0, 0, 0, // PC_LVSL - BPU, 0, 0, 0, 0, 0, // PC_LVSR - BPU, 0, 0, 0, 0, 0, // PC_LVX - BPU, 0, 0, 0, 0, 0, // PC_LVXL - BPU, 0, 0, 0, 0, 0, // PC_STVEBX - BPU, 0, 0, 0, 0, 0, // PC_STVEHX - BPU, 0, 0, 0, 0, 0, // PC_STVEWX - BPU, 0, 0, 0, 0, 0, // PC_STVX - BPU, 0, 0, 0, 0, 0, // PC_STVXL - BPU, 0, 0, 0, 0, 0, // PC_MFVSCR - BPU, 0, 0, 0, 0, 0, // PC_MTVSCR - BPU, 0, 0, 0, 0, 0, // PC_VADDCUW - BPU, 0, 0, 0, 0, 0, // PC_VADDFP - BPU, 0, 0, 0, 0, 0, // PC_VADDSBS - BPU, 0, 0, 0, 0, 0, // PC_VADDSHS - BPU, 0, 0, 0, 0, 0, // PC_VADDSWS - BPU, 0, 0, 0, 0, 0, // PC_VADDUBM - BPU, 0, 0, 0, 0, 0, // PC_VADDUBS - BPU, 0, 0, 0, 0, 0, // PC_VADDUHM - BPU, 0, 0, 0, 0, 0, // PC_VADDUHS - BPU, 0, 0, 0, 0, 0, // PC_VADDUWM - BPU, 0, 0, 0, 0, 0, // PC_VADDUWS - BPU, 0, 0, 0, 0, 0, // PC_VAND - BPU, 0, 0, 0, 0, 0, // PC_VANDC - BPU, 0, 0, 0, 0, 0, // PC_VAVGSB - BPU, 0, 0, 0, 0, 0, // PC_VAVGSH - BPU, 0, 0, 0, 0, 0, // PC_VAVGSW - BPU, 0, 0, 0, 0, 0, // PC_VAVGUB - BPU, 0, 0, 0, 0, 0, // PC_VAVGUH - BPU, 0, 0, 0, 0, 0, // PC_VAVGUW - BPU, 0, 0, 0, 0, 0, // PC_VCFSX - BPU, 0, 0, 0, 0, 0, // PC_VCFUX - BPU, 0, 0, 0, 0, 0, // PC_VCMPBFP - BPU, 0, 0, 0, 0, 0, // PC_VCMPEQFP - BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUB - BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUH - BPU, 0, 0, 0, 0, 0, // PC_VCMPEQUW - BPU, 0, 0, 0, 0, 0, // PC_VCMPGEFP - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTFP - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSB - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSH - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTSW - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUB - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUH - BPU, 0, 0, 0, 0, 0, // PC_VCMPGTUW - BPU, 0, 0, 0, 0, 0, // PC_VCTSXS - BPU, 0, 0, 0, 0, 0, // PC_VCTUXS - BPU, 0, 0, 0, 0, 0, // PC_VEXPTEFP - BPU, 0, 0, 0, 0, 0, // PC_VLOGEFP - BPU, 0, 0, 0, 0, 0, // PC_VMAXFP - BPU, 0, 0, 0, 0, 0, // PC_VMAXSB - BPU, 0, 0, 0, 0, 0, // PC_VMAXSH - BPU, 0, 0, 0, 0, 0, // PC_VMAXSW - BPU, 0, 0, 0, 0, 0, // PC_VMAXUB - BPU, 0, 0, 0, 0, 0, // PC_VMAXUH - BPU, 0, 0, 0, 0, 0, // PC_VMAXUW - BPU, 0, 0, 0, 0, 0, // PC_VMINFP - BPU, 0, 0, 0, 0, 0, // PC_VMINSB - BPU, 0, 0, 0, 0, 0, // PC_VMINSH - BPU, 0, 0, 0, 0, 0, // PC_VMINSW - BPU, 0, 0, 0, 0, 0, // PC_VMINUB - BPU, 0, 0, 0, 0, 0, // PC_VMINUH - BPU, 0, 0, 0, 0, 0, // PC_VMINUW - BPU, 0, 0, 0, 0, 0, // PC_VMRGHB - BPU, 0, 0, 0, 0, 0, // PC_VMRGHH - BPU, 0, 0, 0, 0, 0, // PC_VMRGHW - BPU, 0, 0, 0, 0, 0, // PC_VMRGLB - BPU, 0, 0, 0, 0, 0, // PC_VMRGLH - BPU, 0, 0, 0, 0, 0, // PC_VMRGLW - BPU, 0, 0, 0, 0, 0, // PC_VMULESB - BPU, 0, 0, 0, 0, 0, // PC_VMULESH - BPU, 0, 0, 0, 0, 0, // PC_VMULEUB - BPU, 0, 0, 0, 0, 0, // PC_VMULEUH - BPU, 0, 0, 0, 0, 0, // PC_VMULOSB - BPU, 0, 0, 0, 0, 0, // PC_VMULOSH - BPU, 0, 0, 0, 0, 0, // PC_VMULOUB - BPU, 0, 0, 0, 0, 0, // PC_VMULOUH - BPU, 0, 0, 0, 0, 0, // PC_VNOR - BPU, 0, 0, 0, 0, 0, // PC_VOR - BPU, 0, 0, 0, 0, 0, // PC_VPKPX - BPU, 0, 0, 0, 0, 0, // PC_VPKSHSS - BPU, 0, 0, 0, 0, 0, // PC_VPKSHUS - BPU, 0, 0, 0, 0, 0, // PC_VPKSWSS - BPU, 0, 0, 0, 0, 0, // PC_VPKSWUS - BPU, 0, 0, 0, 0, 0, // PC_VPKUHUM - BPU, 0, 0, 0, 0, 0, // PC_VPKUHUS - BPU, 0, 0, 0, 0, 0, // PC_VPKUWUM - BPU, 0, 0, 0, 0, 0, // PC_VPKUWUS - BPU, 0, 0, 0, 0, 0, // PC_VREFP - BPU, 0, 0, 0, 0, 0, // PC_VRFIM - BPU, 0, 0, 0, 0, 0, // PC_VRFIN - BPU, 0, 0, 0, 0, 0, // PC_VRFIP - BPU, 0, 0, 0, 0, 0, // PC_VRFIZ - BPU, 0, 0, 0, 0, 0, // PC_VRLB - BPU, 0, 0, 0, 0, 0, // PC_VRLH - BPU, 0, 0, 0, 0, 0, // PC_VRLW - BPU, 0, 0, 0, 0, 0, // PC_VRSQRTEFP - BPU, 0, 0, 0, 0, 0, // PC_VSL - BPU, 0, 0, 0, 0, 0, // PC_VSLB - BPU, 0, 0, 0, 0, 0, // PC_VSLH - BPU, 0, 0, 0, 0, 0, // PC_VSLO - BPU, 0, 0, 0, 0, 0, // PC_VSLW - BPU, 0, 0, 0, 0, 0, // PC_VSPLTB - BPU, 0, 0, 0, 0, 0, // PC_VSPLTH - BPU, 0, 0, 0, 0, 0, // PC_VSPLTW - BPU, 0, 0, 0, 0, 0, // PC_VSPLTISB - BPU, 0, 0, 0, 0, 0, // PC_VSPLTISH - BPU, 0, 0, 0, 0, 0, // PC_VSPLTISW - BPU, 0, 0, 0, 0, 0, // PC_VSR - BPU, 0, 0, 0, 0, 0, // PC_VSRAB - BPU, 0, 0, 0, 0, 0, // PC_VSRAH - BPU, 0, 0, 0, 0, 0, // PC_VSRAW - BPU, 0, 0, 0, 0, 0, // PC_VSRB - BPU, 0, 0, 0, 0, 0, // PC_VSRH - BPU, 0, 0, 0, 0, 0, // PC_VSRO - BPU, 0, 0, 0, 0, 0, // PC_VSRW - BPU, 0, 0, 0, 0, 0, // PC_VSUBCUW - BPU, 0, 0, 0, 0, 0, // PC_VSUBFP - BPU, 0, 0, 0, 0, 0, // PC_VSUBSBS - BPU, 0, 0, 0, 0, 0, // PC_VSUBSHS - BPU, 0, 0, 0, 0, 0, // PC_VSUBSWS - BPU, 0, 0, 0, 0, 0, // PC_VSUBUBM - BPU, 0, 0, 0, 0, 0, // PC_VSUBUBS - BPU, 0, 0, 0, 0, 0, // PC_VSUBUHM - BPU, 0, 0, 0, 0, 0, // PC_VSUBUHS - BPU, 0, 0, 0, 0, 0, // PC_VSUBUWM - BPU, 0, 0, 0, 0, 0, // PC_VSUBUWS - BPU, 0, 0, 0, 0, 0, // PC_VSUMSWS - BPU, 0, 0, 0, 0, 0, // PC_VSUM2SWS - BPU, 0, 0, 0, 0, 0, // PC_VSUM4SBS - BPU, 0, 0, 0, 0, 0, // PC_VSUM4SHS - BPU, 0, 0, 0, 0, 0, // PC_VSUM4UBS - BPU, 0, 0, 0, 0, 0, // PC_VUPKHPX - BPU, 0, 0, 0, 0, 0, // PC_VUPKHSB - BPU, 0, 0, 0, 0, 0, // PC_VUPKHSH - BPU, 0, 0, 0, 0, 0, // PC_VUPKLPX - BPU, 0, 0, 0, 0, 0, // PC_VUPKLSB - BPU, 0, 0, 0, 0, 0, // PC_VUPKLSH - BPU, 0, 0, 0, 0, 0, // PC_VXOR - BPU, 0, 0, 0, 0, 0, // PC_VMADDFP - BPU, 0, 0, 0, 0, 0, // PC_VMHADDSHS - BPU, 0, 0, 0, 0, 0, // PC_VMHRADDSHS - BPU, 0, 0, 0, 0, 0, // PC_VMLADDUHM - BPU, 0, 0, 0, 0, 0, // PC_VMSUMMBM - BPU, 0, 0, 0, 0, 0, // PC_VMSUMSHM - BPU, 0, 0, 0, 0, 0, // PC_VMSUMSHS - BPU, 0, 0, 0, 0, 0, // PC_VMSUMUBM - BPU, 0, 0, 0, 0, 0, // PC_VMSUMUHM - BPU, 0, 0, 0, 0, 0, // PC_VMSUMUHS - BPU, 0, 0, 0, 0, 0, // PC_VNMSUBFP - BPU, 0, 0, 0, 0, 0, // PC_VPERM - BPU, 0, 0, 0, 0, 0, // PC_VSEL - BPU, 0, 0, 0, 0, 0, // PC_VSLDOI - BPU, 0, 0, 0, 0, 0, // PC_VMR - BPU, 0, 0, 0, 0, 0, // PC_VMRP - BPU, 0, 0, 0, 0, 0, // PC_SLE - BPU, 0, 0, 0, 0, 0, // PC_SLEQ - BPU, 0, 0, 0, 0, 0, // PC_SLIQ - BPU, 0, 0, 0, 0, 0, // PC_SLLIQ - BPU, 0, 0, 0, 0, 0, // PC_SLLQ - BPU, 0, 0, 0, 0, 0, // PC_SLQ - BPU, 0, 0, 0, 0, 0, // PC_SRAIQ - BPU, 0, 0, 0, 0, 0, // PC_SRAQ - BPU, 0, 0, 0, 0, 0, // PC_SRE - BPU, 0, 0, 0, 0, 0, // PC_SREA - BPU, 0, 0, 0, 0, 0, // PC_SREQ - BPU, 0, 0, 0, 0, 0, // PC_SRIQ - BPU, 0, 0, 0, 0, 0, // PC_SRLIQ - BPU, 0, 0, 0, 0, 0, // PC_SRLQ - BPU, 0, 0, 0, 0, 0, // PC_SRQ - BPU, 0, 0, 0, 0, 0, // PC_MASKG - BPU, 0, 0, 0, 0, 0, // PC_MASKIR - BPU, 0, 0, 0, 0, 0, // PC_LSCBX - BPU, 0, 0, 0, 0, 0, // PC_DIV - BPU, 0, 0, 0, 0, 0, // PC_DIVS - BPU, 0, 0, 0, 0, 0, // PC_DOZ - BPU, 0, 0, 0, 0, 0, // PC_MUL - BPU, 0, 0, 0, 0, 0, // PC_NABS - BPU, 0, 0, 0, 0, 0, // PC_ABS - BPU, 0, 0, 0, 0, 0, // PC_CLCS - BPU, 0, 0, 0, 0, 0, // PC_DOZI - BPU, 0, 0, 0, 0, 0, // PC_RLMI - BPU, 0, 0, 0, 0, 0, // PC_RRIB -}; - -static void advance(int firstStage, int oldStage, int newStage) { - PCode *instr = pipeline[oldStage].instr; - int cycles = instruction_timing[instr->op].cycles[newStage - firstStage]; - pipeline[newStage].instr = instr; - pipeline[newStage].remaining = cycles; - pipeline[oldStage].instr = NULL; -} - -static void assign_completion_buffer(PCode *instr) { - completionbuffers.used++; - completionbuffers.free--; - completionbuffers.entries[completionbuffers.nextFreeSlot].instr = instr; - completionbuffers.entries[completionbuffers.nextFreeSlot].completed = 0; - completionbuffers.nextFreeSlot = (completionbuffers.nextFreeSlot + 1) % MaxEntries; -} - -static void complete_instruction(int stage) { - PCode *instr = pipeline[stage].instr; - int buf = 0; - while (buf < MaxEntries && completionbuffers.entries[buf].instr != instr) - buf++; - - completionbuffers.entries[buf].completed = 1; - pipeline[stage].instr = NULL; - - if (stage == IU1) - iu1_completed_instruction = instr; - else if (stage == IU2) - iu2_completed_instruction = instr; -} - -static void retire_instruction(void) { - completionbuffers.entries[completionbuffers.nextToRetire].instr = NULL; - completionbuffers.used--; - completionbuffers.free++; - completionbuffers.nextToRetire = (completionbuffers.nextToRetire + 1) % MaxEntries; -} - -static int latency(PCode *instr) { - int cycles = instruction_timing[instr->op].latency; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - cycles += 2; - if (instr->op == PC_LMW || instr->op == PC_STMW) - cycles += instr->argCount - 2; - return cycles; -} - -static void initialize(void) { - int stage; - int i; - - for (stage = 0; stage < NumStages; stage++) - pipeline[stage].instr = NULL; - - completionbuffers.free = MaxEntries; - completionbuffers.used = 0; - completionbuffers.nextToRetire = 0; - completionbuffers.nextFreeSlot = 0; - for (i = 0; i < MaxEntries; i++) - completionbuffers.entries[i].instr = NULL; - - iu1_completed_instruction = NULL; - iu2_completed_instruction = NULL; -} - -static int can_issue(PCode *instr) { - int stage; - - if (completionbuffers.free == 0) - return 0; - - stage = instruction_timing[instr->op].stage; - - if (stage == IU2) { - PCode *check; - int isClear1 = !pipeline[IU1].instr; - int isClear2 = !pipeline[IU2].instr; - if (!isClear1 && !isClear2) - return 0; - if (isClear1 && isClear2) - return 1; - - if (isClear1) - check = pipeline[IU2].instr; - else - check = pipeline[IU1].instr; - - if (is_dependent(instr, check, RegClass_GPR)) - return 0; - if (is_dependent(instr, iu1_completed_instruction, RegClass_GPR)) - return 0; - if (is_dependent(instr, iu2_completed_instruction, RegClass_GPR)) - return 0; - } else { - if (pipeline[stage].instr) - return 0; - } - - if ((instr->flags & fIsWrite) && pipeline[LSU2].instr && (pipeline[LSU2].instr->flags & fIsWrite)) - return 0; - - return 1; -} - -static void issue(PCode *instr) { - int stage = instruction_timing[instr->op].stage; - int cycles = instruction_timing[instr->op].cycles[0]; - assign_completion_buffer(instr); - if (stage == IU2 && !pipeline[IU1].instr) - stage = IU1; - pipeline[stage].instr = instr; - pipeline[stage].remaining = cycles; -} - -static void advance_clock(void) { - int stage; - - iu1_completed_instruction = NULL; - iu2_completed_instruction = NULL; - - for (stage = 0; stage < NumStages; stage++) { - if (pipeline[stage].instr && pipeline[stage].remaining) - --pipeline[stage].remaining; - } - - if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { - retire_instruction(); - if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { - retire_instruction(); - } - } - - if (pipeline[IU1].instr && pipeline[IU1].remaining == 0) - complete_instruction(IU1); - if (pipeline[LSU2].instr && pipeline[LSU2].remaining == 0) - complete_instruction(LSU2); - if (pipeline[FPU3].instr && pipeline[FPU3].remaining == 0) - complete_instruction(FPU3); - if (pipeline[SRU].instr && pipeline[SRU].remaining == 0) - complete_instruction(SRU); - if (pipeline[BPU].instr && pipeline[BPU].remaining == 0) - complete_instruction(BPU); - if (pipeline[IU2].instr && pipeline[IU2].remaining == 0) - complete_instruction(IU2); - - if ( - pipeline[FPU1].instr && - pipeline[FPU1].remaining == 0 && - (pipeline[FPU1].instr->op == PC_FDIV || pipeline[FPU1].instr->op == PC_FDIVS) - ) - complete_instruction(FPU1); - - if (pipeline[FPU2].instr && pipeline[FPU2].remaining == 0 && !pipeline[FPU3].instr) - advance(FPU1, FPU2, FPU3); - if (pipeline[FPU1].instr && pipeline[FPU1].remaining == 0 && !pipeline[FPU2].instr) - advance(FPU1, FPU1, FPU2); - - if (pipeline[LSU1].instr && pipeline[LSU1].remaining == 0 && !pipeline[LSU2].instr) - advance(LSU1, LSU1, LSU2); -} - -static int serializes(PCode *instr) { - return instruction_timing[instr->op].serializes; -} - -MachineInfo machine750 = { - 2, - 1, - 0, - &latency, - &initialize, - &can_issue, - &issue, - &advance_clock, - &serializes, - &default_uses_vpermute_unit -}; diff --git a/compiler_and_linker/unsorted/MachineSimulation821.c b/compiler_and_linker/unsorted/MachineSimulation821.c deleted file mode 100644 index bbf0509..0000000 --- a/compiler_and_linker/unsorted/MachineSimulation821.c +++ /dev/null @@ -1,615 +0,0 @@ -#include "compiler/Scheduler.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" - -// https://www.nxp.com/docs/en/user-guide/MPC821UM.pdf - -typedef enum Stage { - BranchUnit, - Stage1, - Stage2, - LSU1, - LSU2, - CRUnit, - NumStages, - Stage7 -} Stage; - -static struct { - // the instruction currently in this pipeline stage - PCode *instr; - - // how many cycles are left for this instruction to finish - int remaining; -} pipeline[NumStages]; - -enum { - MaxEntries = 6 -}; - -static struct { - // how many entries remain unused in the queue - unsigned int free; - - // how many entries are currently used in the queue - unsigned int used; - - // the index of the next instruction that will be retired - unsigned int nextToRetire; - - // the index of the next free slot that will be used when an instruction is dispatched - unsigned int nextFreeSlot; - - // circular array of entries in the completion queue - struct { - PCode *instr; - int completed; - } entries[MaxEntries]; -} completionbuffers; - -static struct { - // the initial stage for this instruction - Stage stage; - - // the total amount of cycles required by this instruction - char latency; - - // how long it takes to finish each stage - char cycles[3]; - - // does this instruction serialise? - char serializes; -} instruction_timing[OPCODE_MAX] = { - BranchUnit, 0, 0, 0, 0, 0, // PC_B - BranchUnit, 0, 0, 0, 0, 0, // PC_BL - BranchUnit, 0, 0, 0, 0, 0, // PC_BC - BranchUnit, 0, 0, 0, 0, 0, // PC_BCLR - BranchUnit, 0, 0, 0, 0, 0, // PC_BCCTR - BranchUnit, 0, 0, 0, 0, 0, // PC_BT - BranchUnit, 0, 0, 0, 0, 0, // PC_BTLR - BranchUnit, 0, 0, 0, 0, 0, // PC_BTCTR - BranchUnit, 0, 0, 0, 0, 0, // PC_BF - BranchUnit, 0, 0, 0, 0, 0, // PC_BFLR - BranchUnit, 0, 0, 0, 0, 0, // PC_BFCTR - BranchUnit, 0, 0, 0, 0, 0, // PC_BDNZ - BranchUnit, 0, 0, 0, 0, 0, // PC_BDNZT - BranchUnit, 0, 0, 0, 0, 0, // PC_BDNZF - BranchUnit, 0, 0, 0, 0, 0, // PC_BDZ - BranchUnit, 0, 0, 0, 0, 0, // PC_BDZT - BranchUnit, 0, 0, 0, 0, 0, // PC_BDZF - BranchUnit, 0, 0, 0, 0, 0, // PC_BLR - BranchUnit, 0, 0, 0, 0, 0, // PC_BCTR - BranchUnit, 0, 0, 0, 0, 0, // PC_BCTRL - BranchUnit, 0, 0, 0, 0, 0, // PC_BLRL - BranchUnit, 0, 0, 0, 0, 0, // PC_LBZ - LSU1, 2, 1, 1, 0, 0, // PC_LBZU - LSU1, 2, 1, 1, 0, 0, // PC_LBZX - LSU1, 2, 1, 1, 0, 0, // PC_LBZUX - LSU1, 2, 1, 1, 0, 0, // PC_LHZ - LSU1, 2, 1, 1, 0, 0, // PC_LHZU - LSU1, 2, 1, 1, 0, 0, // PC_LHZX - LSU1, 2, 1, 1, 0, 0, // PC_LHZUX - LSU1, 2, 1, 1, 0, 0, // PC_LHA - LSU1, 2, 1, 1, 0, 0, // PC_LHAU - LSU1, 2, 1, 1, 0, 0, // PC_LHAX - LSU1, 2, 1, 1, 0, 0, // PC_LHAUX - LSU1, 2, 1, 1, 0, 0, // PC_LHBRX - LSU1, 2, 1, 1, 0, 0, // PC_LWZ - LSU1, 2, 1, 1, 0, 0, // PC_LWZU - LSU1, 2, 1, 1, 0, 0, // PC_LWZX - LSU1, 2, 1, 1, 0, 0, // PC_LWZUX - LSU1, 2, 1, 1, 0, 0, // PC_LWBRX - LSU1, 2, 1, 1, 0, 0, // PC_LMW - LSU1, 2, 1, 1, 0, 0, // PC_STB - LSU1, 2, 1, 1, 0, 0, // PC_STBU - LSU1, 2, 1, 1, 0, 0, // PC_STBX - LSU1, 2, 1, 1, 0, 0, // PC_STBUX - LSU1, 2, 1, 1, 0, 0, // PC_STH - LSU1, 2, 1, 1, 0, 0, // PC_STHU - LSU1, 2, 1, 1, 0, 0, // PC_STHX - LSU1, 2, 1, 1, 0, 0, // PC_STHUX - LSU1, 2, 1, 1, 0, 0, // PC_STHBRX - LSU1, 2, 1, 1, 0, 0, // PC_STW - LSU1, 2, 1, 1, 0, 0, // PC_STWU - LSU1, 2, 1, 1, 0, 0, // PC_STWX - LSU1, 2, 1, 1, 0, 0, // PC_STWUX - LSU1, 2, 1, 1, 0, 0, // PC_STWBRX - LSU1, 2, 1, 1, 0, 0, // PC_STMW - LSU1, 2, 1, 1, 0, 0, // PC_DCBF - LSU1, 2, 1, 1, 0, 0, // PC_DCBST - LSU1, 2, 1, 1, 0, 0, // PC_DCBT - LSU1, 2, 1, 1, 0, 0, // PC_DCBTST - LSU1, 2, 1, 1, 0, 0, // PC_DCBZ - LSU1, 2, 1, 1, 0, 0, // PC_ADD - Stage1, 1, 1, 0, 0, 0, // PC_ADDC - Stage1, 1, 1, 0, 0, 0, // PC_ADDE - Stage1, 1, 1, 0, 0, 0, // PC_ADDI - Stage1, 1, 1, 0, 0, 0, // PC_ADDIC - Stage1, 1, 1, 0, 0, 0, // PC_ADDICR - Stage1, 1, 1, 0, 0, 0, // PC_ADDIS - Stage1, 1, 1, 0, 0, 0, // PC_ADDME - Stage1, 1, 1, 0, 0, 0, // PC_ADDZE - Stage1, 1, 1, 0, 0, 0, // PC_DIVW - Stage1, 37, 37, 0, 0, 0, // PC_DIVWU - Stage1, 37, 37, 0, 0, 0, // PC_MULHW - Stage1, 5, 5, 0, 0, 0, // PC_MULHWU - Stage1, 5, 5, 0, 0, 0, // PC_MULLI - Stage1, 3, 3, 0, 0, 0, // PC_MULLW - Stage1, 5, 5, 0, 0, 0, // PC_NEG - Stage1, 1, 1, 0, 0, 0, // PC_SUBF - Stage1, 1, 1, 0, 0, 0, // PC_SUBFC - Stage1, 1, 1, 0, 0, 0, // PC_SUBFE - Stage1, 1, 1, 0, 0, 0, // PC_SUBFIC - Stage1, 1, 1, 0, 0, 0, // PC_SUBFME - Stage1, 1, 1, 0, 0, 0, // PC_SUBFZE - Stage1, 1, 1, 0, 0, 0, // PC_CMPI - Stage1, 3, 1, 0, 0, 0, // PC_CMP - Stage1, 3, 1, 0, 0, 0, // PC_CMPLI - Stage1, 3, 1, 0, 0, 0, // PC_CMPL - Stage1, 3, 1, 0, 0, 0, // PC_ANDI - Stage1, 1, 1, 0, 0, 0, // PC_ANDIS - Stage1, 1, 1, 0, 0, 0, // PC_ORI - Stage1, 1, 1, 0, 0, 0, // PC_ORIS - Stage1, 1, 1, 0, 0, 0, // PC_XORI - Stage1, 1, 1, 0, 0, 0, // PC_XORIS - Stage1, 1, 1, 0, 0, 0, // PC_AND - Stage1, 1, 1, 0, 0, 0, // PC_OR - Stage1, 1, 1, 0, 0, 0, // PC_XOR - Stage1, 1, 1, 0, 0, 0, // PC_NAND - Stage1, 1, 1, 0, 0, 0, // PC_NOR - Stage1, 1, 1, 0, 0, 0, // PC_EQV - Stage1, 1, 1, 0, 0, 0, // PC_ANDC - Stage1, 1, 1, 0, 0, 0, // PC_ORC - Stage1, 1, 1, 0, 0, 0, // PC_EXTSB - Stage1, 1, 1, 0, 0, 0, // PC_EXTSH - Stage1, 1, 1, 0, 0, 0, // PC_CNTLZW - Stage1, 1, 1, 0, 0, 0, // PC_RLWINM - Stage1, 1, 1, 0, 0, 0, // PC_RLWNM - Stage1, 1, 1, 0, 0, 0, // PC_RLWIMI - Stage1, 1, 1, 0, 0, 0, // PC_SLW - Stage1, 1, 1, 0, 0, 0, // PC_SRW - Stage1, 1, 1, 0, 0, 0, // PC_SRAWI - Stage1, 1, 1, 0, 0, 0, // PC_SRAW - Stage1, 1, 1, 0, 0, 0, // PC_CRAND - CRUnit, 1, 1, 0, 0, 0, // PC_CRANDC - CRUnit, 1, 1, 0, 0, 0, // PC_CREQV - CRUnit, 1, 1, 0, 0, 0, // PC_CRNAND - CRUnit, 1, 1, 0, 0, 0, // PC_CRNOR - CRUnit, 1, 1, 0, 0, 0, // PC_CROR - CRUnit, 1, 1, 0, 0, 0, // PC_CRORC - CRUnit, 1, 1, 0, 0, 0, // PC_CRXOR - CRUnit, 1, 1, 0, 0, 0, // PC_MCRF - CRUnit, 1, 1, 0, 0, 0, // PC_MTXER - Stage1, 1, 1, 0, 0, 0, // PC_MTCTR - BranchUnit, 2, 2, 0, 0, 0, // PC_MTLR - BranchUnit, 2, 2, 0, 0, 0, // PC_MTCRF - Stage1, 1, 1, 0, 0, 0, // PC_MTMSR - Stage1, 1, 1, 0, 0, 0, // PC_MTSPR - Stage1, 1, 1, 0, 0, 0, // PC_MFMSR - Stage1, 1, 1, 0, 0, 0, // PC_MFSPR - Stage1, 1, 1, 0, 0, 0, // PC_MFXER - Stage7, 3, 1, 1, 1, 0, // PC_MFCTR - Stage7, 3, 1, 1, 1, 0, // PC_MFLR - Stage1, 1, 1, 0, 0, 0, // PC_MFCR - Stage1, 1, 1, 0, 0, 0, // PC_MFFS - Stage1, 1, 1, 0, 0, 0, // PC_MTFSF - Stage1, 1, 1, 0, 0, 0, // PC_EIEIO - Stage1, 1, 1, 0, 0, 0, // PC_ISYNC - Stage1, 1, 1, 0, 0, 0, // PC_SYNC - Stage1, 1, 1, 0, 0, 0, // PC_RFI - Stage1, 1, 1, 0, 0, 0, // PC_LI - LSU1, 2, 1, 1, 0, 0, // PC_LIS - LSU1, 2, 1, 1, 0, 0, // PC_MR - LSU1, 2, 1, 1, 0, 0, // PC_NOP - LSU1, 2, 1, 1, 0, 0, // PC_NOT - LSU1, 2, 1, 1, 0, 0, // PC_LFS - LSU1, 2, 1, 1, 0, 0, // PC_LFSU - LSU1, 2, 1, 1, 0, 0, // PC_LFSX - LSU1, 2, 1, 1, 0, 0, // PC_LFSUX - LSU1, 2, 1, 1, 0, 0, // PC_LFD - LSU1, 2, 1, 1, 0, 0, // PC_LFDU - LSU1, 2, 1, 1, 0, 0, // PC_LFDX - LSU1, 2, 1, 1, 0, 0, // PC_LFDUX - LSU1, 2, 1, 1, 0, 0, // PC_STFS - LSU1, 2, 1, 1, 0, 0, // PC_STFSU - LSU1, 2, 1, 1, 0, 0, // PC_STFSX - LSU1, 2, 1, 1, 0, 0, // PC_STFSUX - Stage7, 3, 1, 1, 1, 0, // PC_STFD - Stage7, 3, 1, 1, 1, 0, // PC_STFDU - Stage7, 3, 1, 1, 1, 0, // PC_STFDX - Stage7, 3, 1, 1, 1, 0, // PC_STFDUX - Stage7, 3, 1, 1, 1, 0, // PC_FMR - Stage7, 3, 1, 1, 1, 0, // PC_FABS - Stage7, 3, 1, 1, 1, 0, // PC_FNEG - Stage7, 3, 1, 1, 1, 0, // PC_FNABS - Stage7, 4, 2, 1, 1, 0, // PC_FADD - Stage7, 3, 1, 1, 1, 0, // PC_FADDS - Stage7, 33, 33, 0, 0, 0, // PC_FSUB - Stage7, 18, 18, 0, 0, 0, // PC_FSUBS - Stage7, 4, 2, 1, 1, 0, // PC_FMUL - Stage7, 3, 1, 1, 1, 0, // PC_FMULS - Stage7, 4, 2, 1, 1, 0, // PC_FDIV - Stage7, 3, 1, 1, 1, 0, // PC_FDIVS - Stage7, 4, 2, 1, 1, 0, // PC_FMADD - Stage7, 3, 1, 1, 1, 0, // PC_FMADDS - Stage7, 4, 2, 1, 1, 0, // PC_FMSUB - Stage7, 3, 1, 1, 1, 0, // PC_FMSUBS - Stage7, 18, 18, 0, 0, 0, // PC_FNMADD - Stage7, 3, 1, 1, 1, 0, // PC_FNMADDS - Stage7, 3, 1, 1, 1, 0, // PC_FNMSUB - Stage7, 3, 1, 1, 1, 0, // PC_FNMSUBS - Stage7, 3, 1, 1, 1, 0, // PC_FRES - Stage7, 3, 1, 1, 1, 0, // PC_FRSQRTE - Stage7, 5, 1, 1, 1, 0, // PC_FSEL - Stage7, 5, 1, 1, 1, 0, // PC_FRSP - LSU1, 1, 0, 0, 0, 0, // PC_FCTIW - LSU1, 1, 0, 0, 0, 0, // PC_FCTIWZ - LSU1, 1, 0, 0, 0, 0, // PC_FCMPU - LSU1, 1, 0, 0, 0, 0, // PC_FCMPO - LSU1, 1, 0, 0, 0, 0, // PC_LWARX - LSU1, 1, 0, 0, 0, 0, // PC_LSWI - LSU1, 1, 0, 0, 0, 0, // PC_LSWX - Stage1, 1, 0, 0, 0, 0, // PC_STFIWX - Stage1, 1, 0, 0, 0, 0, // PC_STSWI - Stage1, 1, 0, 0, 0, 0, // PC_STSWX - Stage1, 1, 0, 0, 0, 0, // PC_STWCX - Stage1, 1, 0, 0, 0, 0, // PC_ECIWX - Stage1, 1, 0, 0, 0, 0, // PC_ECOWX - Stage1, 1, 0, 0, 0, 0, // PC_DCBI - Stage1, 1, 0, 0, 0, 0, // PC_ICBI - Stage1, 1, 0, 0, 0, 0, // PC_MCRFS - Stage1, 1, 0, 0, 0, 0, // PC_MCRXR - Stage1, 1, 0, 0, 0, 0, // PC_MFTB - Stage1, 1, 0, 0, 0, 0, // PC_MFSR - Stage1, 1, 0, 0, 0, 0, // PC_MTSR - Stage1, 1, 0, 0, 0, 0, // PC_MFSRIN - Stage1, 1, 0, 0, 0, 0, // PC_MTSRIN - Stage1, 1, 0, 0, 0, 0, // PC_MTFSB0 - Stage1, 1, 0, 0, 0, 0, // PC_MTFSB1 - Stage1, 1, 0, 0, 0, 0, // PC_MTFSFI - Stage1, 1, 0, 0, 0, 1, // PC_SC - Stage1, 1, 0, 0, 0, 1, // PC_FSQRT - Stage1, 1, 0, 0, 0, 0, // PC_FSQRTS - Stage1, 1, 0, 0, 0, 0, // PC_TLBIA - Stage1, 1, 0, 0, 0, 0, // PC_TLBIE - Stage1, 1, 0, 0, 0, 0, // PC_TLBLD - Stage1, 1, 0, 0, 0, 0, // PC_TLBLI - Stage1, 1, 0, 0, 0, 0, // PC_TLBSYNC - Stage1, 1, 0, 0, 0, 0, // PC_TW - Stage1, 1, 0, 0, 0, 1, // PC_TRAP - Stage1, 1, 0, 0, 0, 1, // PC_TWI - Stage1, 1, 0, 0, 0, 1, // PC_OPWORD - Stage1, 1, 0, 0, 0, 1, // PC_MFROM - Stage1, 1, 0, 0, 0, 0, // PC_DSA - Stage1, 1, 0, 0, 0, 0, // PC_ESA - Stage1, 1, 0, 0, 0, 0, // PC_DCCCI - Stage1, 0, 0, 0, 0, 0, // PC_DCREAD - Stage1, 0, 0, 0, 0, 0, // PC_ICBT - Stage1, 0, 0, 0, 0, 0, // PC_ICCCI - Stage1, 0, 0, 0, 0, 0, // PC_ICREAD - Stage1, 0, 0, 0, 0, 0, // PC_RFCI - Stage1, 0, 0, 0, 0, 0, // PC_TLBRE - Stage1, 0, 0, 0, 0, 0, // PC_TLBSX - Stage1, 0, 0, 0, 0, 0, // PC_TLBWE - Stage1, 0, 0, 0, 0, 0, // PC_WRTEE - Stage1, 0, 0, 0, 0, 0, // PC_WRTEEI - Stage1, 0, 0, 0, 0, 0, // PC_MFDCR - Stage1, 0, 0, 0, 0, 0, // PC_MTDCR - Stage1, 0, 0, 0, 0, 0, // PC_DCBA - Stage1, 0, 0, 0, 0, 0, // PC_DSS - BranchUnit, 0, 0, 0, 0, 0, // PC_DSSALL - BranchUnit, 0, 0, 0, 0, 0, // PC_DST - BranchUnit, 0, 0, 0, 0, 0, // PC_DSTT - BranchUnit, 0, 0, 0, 0, 0, // PC_DSTST - BranchUnit, 0, 0, 0, 0, 0, // PC_DSTSTT - BranchUnit, 0, 0, 0, 0, 0, // PC_LVEBX - BranchUnit, 0, 0, 0, 0, 0, // PC_LVEHX - BranchUnit, 0, 0, 0, 0, 0, // PC_LVEWX - BranchUnit, 0, 0, 0, 0, 0, // PC_LVSL - BranchUnit, 0, 0, 0, 0, 0, // PC_LVSR - BranchUnit, 0, 0, 0, 0, 0, // PC_LVX - BranchUnit, 0, 0, 0, 0, 0, // PC_LVXL - BranchUnit, 0, 0, 0, 0, 0, // PC_STVEBX - BranchUnit, 0, 0, 0, 0, 0, // PC_STVEHX - BranchUnit, 0, 0, 0, 0, 0, // PC_STVEWX - BranchUnit, 0, 0, 0, 0, 0, // PC_STVX - BranchUnit, 0, 0, 0, 0, 0, // PC_STVXL - BranchUnit, 0, 0, 0, 0, 0, // PC_MFVSCR - BranchUnit, 0, 0, 0, 0, 0, // PC_MTVSCR - BranchUnit, 0, 0, 0, 0, 0, // PC_VADDCUW - BranchUnit, 0, 0, 0, 0, 0, // PC_VADDFP - BranchUnit, 0, 0, 0, 0, 0, // PC_VADDSBS - BranchUnit, 0, 0, 0, 0, 0, // PC_VADDSHS - BranchUnit, 0, 0, 0, 0, 0, // PC_VADDSWS - BranchUnit, 0, 0, 0, 0, 0, // PC_VADDUBM - BranchUnit, 0, 0, 0, 0, 0, // PC_VADDUBS - BranchUnit, 0, 0, 0, 0, 0, // PC_VADDUHM - BranchUnit, 0, 0, 0, 0, 0, // PC_VADDUHS - BranchUnit, 0, 0, 0, 0, 0, // PC_VADDUWM - BranchUnit, 0, 0, 0, 0, 0, // PC_VADDUWS - BranchUnit, 0, 0, 0, 0, 0, // PC_VAND - BranchUnit, 0, 0, 0, 0, 0, // PC_VANDC - BranchUnit, 0, 0, 0, 0, 0, // PC_VAVGSB - BranchUnit, 0, 0, 0, 0, 0, // PC_VAVGSH - BranchUnit, 0, 0, 0, 0, 0, // PC_VAVGSW - BranchUnit, 0, 0, 0, 0, 0, // PC_VAVGUB - BranchUnit, 0, 0, 0, 0, 0, // PC_VAVGUH - BranchUnit, 0, 0, 0, 0, 0, // PC_VAVGUW - BranchUnit, 0, 0, 0, 0, 0, // PC_VCFSX - BranchUnit, 0, 0, 0, 0, 0, // PC_VCFUX - BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPBFP - BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPEQFP - BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPEQUB - BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPEQUH - BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPEQUW - BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPGEFP - BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPGTFP - BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPGTSB - BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPGTSH - BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPGTSW - BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPGTUB - BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPGTUH - BranchUnit, 0, 0, 0, 0, 0, // PC_VCMPGTUW - BranchUnit, 0, 0, 0, 0, 0, // PC_VCTSXS - BranchUnit, 0, 0, 0, 0, 0, // PC_VCTUXS - BranchUnit, 0, 0, 0, 0, 0, // PC_VEXPTEFP - BranchUnit, 0, 0, 0, 0, 0, // PC_VLOGEFP - BranchUnit, 0, 0, 0, 0, 0, // PC_VMAXFP - BranchUnit, 0, 0, 0, 0, 0, // PC_VMAXSB - BranchUnit, 0, 0, 0, 0, 0, // PC_VMAXSH - BranchUnit, 0, 0, 0, 0, 0, // PC_VMAXSW - BranchUnit, 0, 0, 0, 0, 0, // PC_VMAXUB - BranchUnit, 0, 0, 0, 0, 0, // PC_VMAXUH - BranchUnit, 0, 0, 0, 0, 0, // PC_VMAXUW - BranchUnit, 0, 0, 0, 0, 0, // PC_VMINFP - BranchUnit, 0, 0, 0, 0, 0, // PC_VMINSB - BranchUnit, 0, 0, 0, 0, 0, // PC_VMINSH - BranchUnit, 0, 0, 0, 0, 0, // PC_VMINSW - BranchUnit, 0, 0, 0, 0, 0, // PC_VMINUB - BranchUnit, 0, 0, 0, 0, 0, // PC_VMINUH - BranchUnit, 0, 0, 0, 0, 0, // PC_VMINUW - BranchUnit, 0, 0, 0, 0, 0, // PC_VMRGHB - BranchUnit, 0, 0, 0, 0, 0, // PC_VMRGHH - BranchUnit, 0, 0, 0, 0, 0, // PC_VMRGHW - BranchUnit, 0, 0, 0, 0, 0, // PC_VMRGLB - BranchUnit, 0, 0, 0, 0, 0, // PC_VMRGLH - BranchUnit, 0, 0, 0, 0, 0, // PC_VMRGLW - BranchUnit, 0, 0, 0, 0, 0, // PC_VMULESB - BranchUnit, 0, 0, 0, 0, 0, // PC_VMULESH - BranchUnit, 0, 0, 0, 0, 0, // PC_VMULEUB - BranchUnit, 0, 0, 0, 0, 0, // PC_VMULEUH - BranchUnit, 0, 0, 0, 0, 0, // PC_VMULOSB - BranchUnit, 0, 0, 0, 0, 0, // PC_VMULOSH - BranchUnit, 0, 0, 0, 0, 0, // PC_VMULOUB - BranchUnit, 0, 0, 0, 0, 0, // PC_VMULOUH - BranchUnit, 0, 0, 0, 0, 0, // PC_VNOR - BranchUnit, 0, 0, 0, 0, 0, // PC_VOR - BranchUnit, 0, 0, 0, 0, 0, // PC_VPKPX - BranchUnit, 0, 0, 0, 0, 0, // PC_VPKSHSS - BranchUnit, 0, 0, 0, 0, 0, // PC_VPKSHUS - BranchUnit, 0, 0, 0, 0, 0, // PC_VPKSWSS - BranchUnit, 0, 0, 0, 0, 0, // PC_VPKSWUS - BranchUnit, 0, 0, 0, 0, 0, // PC_VPKUHUM - BranchUnit, 0, 0, 0, 0, 0, // PC_VPKUHUS - BranchUnit, 0, 0, 0, 0, 0, // PC_VPKUWUM - BranchUnit, 0, 0, 0, 0, 0, // PC_VPKUWUS - BranchUnit, 0, 0, 0, 0, 0, // PC_VREFP - BranchUnit, 0, 0, 0, 0, 0, // PC_VRFIM - BranchUnit, 0, 0, 0, 0, 0, // PC_VRFIN - BranchUnit, 0, 0, 0, 0, 0, // PC_VRFIP - BranchUnit, 0, 0, 0, 0, 0, // PC_VRFIZ - BranchUnit, 0, 0, 0, 0, 0, // PC_VRLB - BranchUnit, 0, 0, 0, 0, 0, // PC_VRLH - BranchUnit, 0, 0, 0, 0, 0, // PC_VRLW - BranchUnit, 0, 0, 0, 0, 0, // PC_VRSQRTEFP - BranchUnit, 0, 0, 0, 0, 0, // PC_VSL - BranchUnit, 0, 0, 0, 0, 0, // PC_VSLB - BranchUnit, 0, 0, 0, 0, 0, // PC_VSLH - BranchUnit, 0, 0, 0, 0, 0, // PC_VSLO - BranchUnit, 0, 0, 0, 0, 0, // PC_VSLW - BranchUnit, 0, 0, 0, 0, 0, // PC_VSPLTB - BranchUnit, 0, 0, 0, 0, 0, // PC_VSPLTH - BranchUnit, 0, 0, 0, 0, 0, // PC_VSPLTW - BranchUnit, 0, 0, 0, 0, 0, // PC_VSPLTISB - BranchUnit, 0, 0, 0, 0, 0, // PC_VSPLTISH - BranchUnit, 0, 0, 0, 0, 0, // PC_VSPLTISW - BranchUnit, 0, 0, 0, 0, 0, // PC_VSR - BranchUnit, 0, 0, 0, 0, 0, // PC_VSRAB - BranchUnit, 0, 0, 0, 0, 0, // PC_VSRAH - BranchUnit, 0, 0, 0, 0, 0, // PC_VSRAW - BranchUnit, 0, 0, 0, 0, 0, // PC_VSRB - BranchUnit, 0, 0, 0, 0, 0, // PC_VSRH - BranchUnit, 0, 0, 0, 0, 0, // PC_VSRO - BranchUnit, 0, 0, 0, 0, 0, // PC_VSRW - BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBCUW - BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBFP - BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBSBS - BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBSHS - BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBSWS - BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBUBM - BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBUBS - BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBUHM - BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBUHS - BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBUWM - BranchUnit, 0, 0, 0, 0, 0, // PC_VSUBUWS - BranchUnit, 0, 0, 0, 0, 0, // PC_VSUMSWS - BranchUnit, 0, 0, 0, 0, 0, // PC_VSUM2SWS - BranchUnit, 0, 0, 0, 0, 0, // PC_VSUM4SBS - BranchUnit, 0, 0, 0, 0, 0, // PC_VSUM4SHS - BranchUnit, 0, 0, 0, 0, 0, // PC_VSUM4UBS - BranchUnit, 0, 0, 0, 0, 0, // PC_VUPKHPX - BranchUnit, 0, 0, 0, 0, 0, // PC_VUPKHSB - BranchUnit, 0, 0, 0, 0, 0, // PC_VUPKHSH - BranchUnit, 0, 0, 0, 0, 0, // PC_VUPKLPX - BranchUnit, 0, 0, 0, 0, 0, // PC_VUPKLSB - BranchUnit, 0, 0, 0, 0, 0, // PC_VUPKLSH - BranchUnit, 0, 0, 0, 0, 0, // PC_VXOR - BranchUnit, 0, 0, 0, 0, 0, // PC_VMADDFP - BranchUnit, 0, 0, 0, 0, 0, // PC_VMHADDSHS - BranchUnit, 0, 0, 0, 0, 0, // PC_VMHRADDSHS - BranchUnit, 0, 0, 0, 0, 0, // PC_VMLADDUHM - BranchUnit, 0, 0, 0, 0, 0, // PC_VMSUMMBM - BranchUnit, 0, 0, 0, 0, 0, // PC_VMSUMSHM - BranchUnit, 0, 0, 0, 0, 0, // PC_VMSUMSHS - BranchUnit, 0, 0, 0, 0, 0, // PC_VMSUMUBM - BranchUnit, 0, 0, 0, 0, 0, // PC_VMSUMUHM - BranchUnit, 0, 0, 0, 0, 0, // PC_VMSUMUHS - BranchUnit, 0, 0, 0, 0, 0, // PC_VNMSUBFP - BranchUnit, 0, 0, 0, 0, 0, // PC_VPERM - BranchUnit, 0, 0, 0, 0, 0, // PC_VSEL - BranchUnit, 0, 0, 0, 0, 0, // PC_VSLDOI - BranchUnit, 0, 0, 0, 0, 0, // PC_VMR - BranchUnit, 0, 0, 0, 0, 0, // PC_VMRP - BranchUnit, 0, 0, 0, 0, 0, // PC_SLE - BranchUnit, 0, 0, 0, 0, 0, // PC_SLEQ - BranchUnit, 0, 0, 0, 0, 0, // PC_SLIQ - BranchUnit, 0, 0, 0, 0, 0, // PC_SLLIQ - BranchUnit, 0, 0, 0, 0, 0, // PC_SLLQ - BranchUnit, 0, 0, 0, 0, 0, // PC_SLQ - BranchUnit, 0, 0, 0, 0, 0, // PC_SRAIQ - BranchUnit, 0, 0, 0, 0, 0, // PC_SRAQ - BranchUnit, 0, 0, 0, 0, 0, // PC_SRE - BranchUnit, 0, 0, 0, 0, 0, // PC_SREA - BranchUnit, 0, 0, 0, 0, 0, // PC_SREQ - BranchUnit, 0, 0, 0, 0, 0, // PC_SRIQ - BranchUnit, 0, 0, 0, 0, 0, // PC_SRLIQ - BranchUnit, 0, 0, 0, 0, 0, // PC_SRLQ - BranchUnit, 0, 0, 0, 0, 0, // PC_SRQ - BranchUnit, 0, 0, 0, 0, 0, // PC_MASKG - BranchUnit, 0, 0, 0, 0, 0, // PC_MASKIR - BranchUnit, 0, 0, 0, 0, 0, // PC_LSCBX - BranchUnit, 0, 0, 0, 0, 0, // PC_DIV - BranchUnit, 0, 0, 0, 0, 0, // PC_DIVS - BranchUnit, 0, 0, 0, 0, 0, // PC_DOZ - BranchUnit, 0, 0, 0, 0, 0, // PC_MUL - BranchUnit, 0, 0, 0, 0, 0, // PC_NABS - BranchUnit, 0, 0, 0, 0, 0, // PC_ABS - BranchUnit, 0, 0, 0, 0, 0, // PC_CLCS - BranchUnit, 0, 0, 0, 0, 0, // PC_DOZI - BranchUnit, 0, 0, 0, 0, 0, // PC_RLMI - BranchUnit, 0, 0, 0, 0, 0, // PC_RRIB -}; - -static void advance(int firstStage, int oldStage, int newStage) { - PCode *instr = pipeline[oldStage].instr; - int cycles = instruction_timing[instr->op].cycles[newStage - firstStage]; - pipeline[newStage].instr = instr; - pipeline[newStage].remaining = cycles; - pipeline[oldStage].instr = NULL; -} - -static void assign_completion_buffer(PCode *instr) { - completionbuffers.used++; - completionbuffers.free--; - completionbuffers.entries[completionbuffers.nextFreeSlot].instr = instr; - completionbuffers.entries[completionbuffers.nextFreeSlot].completed = 0; - completionbuffers.nextFreeSlot = (completionbuffers.nextFreeSlot + 1) % MaxEntries; -} - -static void complete_instruction(int stage) { - PCode *instr = pipeline[stage].instr; - int buf = 0; - while (buf < MaxEntries && completionbuffers.entries[buf].instr != instr) - buf++; - - completionbuffers.entries[buf].completed = 1; - pipeline[stage].instr = NULL; -} - -static void retire_instruction(void) { - completionbuffers.entries[completionbuffers.nextToRetire].instr = NULL; - completionbuffers.used--; - completionbuffers.free++; - completionbuffers.nextToRetire = (completionbuffers.nextToRetire + 1) % MaxEntries; -} - -static int latency(PCode *instr) { - int cycles = instruction_timing[instr->op].latency; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - cycles += 2; - if (instr->op == PC_LMW || instr->op == PC_STMW) - cycles += instr->argCount - 2; - return cycles; -} - -static void initialize(void) { - int stage; - int i; - - for (stage = 0; stage < NumStages; stage++) - pipeline[stage].instr = NULL; - - completionbuffers.free = MaxEntries; - completionbuffers.used = 0; - completionbuffers.nextToRetire = 0; - completionbuffers.nextFreeSlot = 0; - for (i = 0; i < MaxEntries; i++) - completionbuffers.entries[i].instr = NULL; -} - -static int can_issue(PCode *instr) { - int stage; - - if (completionbuffers.free == 0) - return 0; - - stage = instruction_timing[instr->op].stage; - if (pipeline[stage].instr) - return 0; - - if ((instr->flags & fIsWrite) && pipeline[LSU2].instr && (pipeline[LSU2].instr->flags & fIsWrite)) - return 0; - - return 1; -} - -static void issue(PCode *instr) { - int stage = instruction_timing[instr->op].stage; - int cycles = instruction_timing[instr->op].cycles[0]; - assign_completion_buffer(instr); - pipeline[stage].instr = instr; - pipeline[stage].remaining = cycles; -} - -static void advance_clock(void) { - int stage; - - for (stage = 0; stage < NumStages; stage++) { - if (pipeline[stage].instr && pipeline[stage].remaining) - --pipeline[stage].remaining; - } - - if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { - retire_instruction(); - if (completionbuffers.used && completionbuffers.entries[completionbuffers.nextToRetire].completed) { - retire_instruction(); - } - } - - if (pipeline[Stage1].instr && pipeline[Stage1].remaining == 0) - complete_instruction(Stage1); - if (pipeline[LSU2].instr && pipeline[LSU2].remaining == 0) - complete_instruction(LSU2); - if (pipeline[BranchUnit].instr && pipeline[BranchUnit].remaining == 0) - complete_instruction(BranchUnit); - - if (pipeline[LSU1].instr && pipeline[LSU1].remaining == 0 && !pipeline[LSU2].instr) - advance(LSU1, LSU1, LSU2); -} - -static int serializes(PCode *instr) { - return instruction_timing[instr->op].serializes; -} - -MachineInfo machine821 = { - 1, - 0, - 0, - &latency, - &initialize, - &can_issue, - &issue, - &advance_clock, - &serializes, - &default_uses_vpermute_unit -}; diff --git a/compiler_and_linker/unsorted/MachineSimulationAltiVec.c b/compiler_and_linker/unsorted/MachineSimulationAltiVec.c deleted file mode 100644 index d261ee9..0000000 --- a/compiler_and_linker/unsorted/MachineSimulationAltiVec.c +++ /dev/null @@ -1,752 +0,0 @@ -#include "compiler/Scheduler.h" -#include "compiler/CError.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" - -// https://www.nxp.com/docs/en/reference-manual/MPC7450UM.pdf - -typedef enum Stage { - BPU, // Branch Prediction Unit - - IU2_1, // Multiple-Cycle Integer Unit - IU2_2, - IU2_3, - - IU1a, // Single-Cycle Integer Unit - IU1b, // Single-Cycle Integer Unit - IU1c, // Single-Cycle Integer Unit - - LSU_1, // Load/Store Unit - LSU_2, - LSU_3, - LSU_4, - - FPU_1, // Floating-Point Unit - FPU_2, - FPU_3, - FPU_4, - - VIU1, // Vector Simple Integer Unit - - VPU_1, // Vector Permute Unit - VPU_2, - - VIU2_1, // Vector Complex Integer Unit - VIU2_2, - VIU2_3, - VIU2_4, - - VFPU_1, // Vector Floating-Point Unit - VFPU_2, - VFPU_3, - VFPU_4, - - NumStages -} Stage; - -static struct { - // the instruction currently in this pipeline stage - PCode *instr; - - // how many cycles are left for this instruction to finish - int remaining; -} pipeline_altivec[NumStages]; - -enum { - Queue0, - Queue1, - Queue2, - Queue3, - Queue4, - Queue5, - Queue6, - Queue7, - NumQueues -}; - -static int fetchqueues[NumQueues]; - -enum { - MaxEntries = 16 -}; - -static struct { - // how many entries remain unused in the queue - unsigned int free; - - // how many entries are currently used in the queue - unsigned int used; - - // the index of the next instruction that will be retired - unsigned int nextToRetire; - - // the index of the next free slot that will be used when an instruction is dispatched - unsigned int nextFreeSlot; - - // circular array of entries in the completion queue - struct { - PCode *instr; - int completed; - } entries[MaxEntries]; -} completionbuffers; - -static struct { - short index; - - // the initial stage for this instruction - Stage stage; - - // the total amount of cycles required by this instruction - char latency; - - // how long it takes to finish each stage - char cycles[4]; - - // does this instruction serialise? - char serializes; - - char unused; -} instruction_timing[] = { - 0, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_B - 1, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BL - 2, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BC - 3, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BCLR - 4, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BCCTR - 5, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BT - 6, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BTLR - 7, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BTCTR - 8, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BF - 9, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BFLR - 10, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BFCTR - 11, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDNZ - 12, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDNZT - 13, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDNZF - 14, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDZ - 15, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDZT - 16, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BDZF - 17, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BLR - 18, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BCTR - 19, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BCTRL - 20, BPU, 0, 0, 0, 0, 0, 0, 0, // PC_BLRL - 21, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LBZ - 22, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LBZU - 23, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LBZX - 24, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LBZUX - 25, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHZ - 26, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHZU - 27, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHZX - 28, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHZUX - 29, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHA - 30, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHAU - 31, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHAX - 32, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHAUX - 33, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LHBRX - 34, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LWZ - 35, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LWZU - 36, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LWZX - 37, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LWZUX - 38, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LWBRX - 39, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_LMW - 40, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STB - 41, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STBU - 42, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STBX - 43, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STBUX - 44, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STH - 45, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STHU - 46, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STHX - 47, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STHUX - 48, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STHBRX - 49, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STW - 50, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STWU - 51, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STWX - 52, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STWUX - 53, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STWBRX - 54, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STMW - 55, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_DCBF - 56, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_DCBST - 57, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DCBT - 58, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DCBTST - 59, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DCBZ - 60, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADD - 61, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADDC - 62, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADDE - 63, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADDI - 64, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADDIC - 65, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADDICR - 66, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADDIS - 67, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADDME - 68, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ADDZE - 69, IU2_1, 23, 23, 0, 0, 0, 0, 0, // PC_DIVW - 70, IU2_1, 23, 23, 0, 0, 0, 0, 0, // PC_DIVWU - 71, IU2_1, 4, 2, 2, 0, 0, 0, 0, // PC_MULHW - 72, IU2_1, 4, 2, 2, 0, 0, 0, 0, // PC_MULHWU - 73, IU2_1, 3, 1, 1, 1, 0, 0, 0, // PC_MULLI - 74, IU2_1, 4, 2, 2, 0, 0, 0, 0, // PC_MULLW - 75, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_NEG - 76, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_SUBF - 77, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFC - 78, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFE - 79, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFIC - 80, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFME - 81, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_SUBFZE - 82, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_CMPI - 83, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_CMP - 84, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_CMPLI - 85, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_CMPL - 86, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ANDI - 87, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ANDIS - 88, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ORI - 89, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ORIS - 90, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_XORI - 91, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_XORIS - 92, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_AND - 93, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_OR - 94, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_XOR - 95, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_NAND - 96, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_NOR - 97, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_EQV - 98, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ANDC - 99, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ORC - 100, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_EXTSB - 101, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_EXTSH - 102, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_CNTLZW - 103, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_RLWINM - 104, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_RLWNM - 105, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_RLWIMI - 106, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_SLW - 107, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_SRW - 108, IU1a, 2, 2, 0, 0, 0, 0, 0, // PC_SRAWI - 109, IU1a, 2, 2, 0, 0, 0, 0, 0, // PC_SRAW - 110, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_CRAND - 111, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_CRANDC - 112, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_CREQV - 113, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_CRNAND - 114, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_CRNOR - 115, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_CROR - 116, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_CRORC - 117, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_CRXOR - 118, IU2_1, 1, 1, 0, 0, 0, 1, 0, // PC_MCRF - 119, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_MTXER - 120, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_MTCTR - 121, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_MTLR - 122, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_MTCRF - 123, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_MTMSR - 124, IU2_1, 3, 3, 0, 0, 0, 1, 0, // PC_MTSPR - 125, IU2_1, 3, 2, 1, 0, 0, 0, 0, // PC_MFMSR - 126, IU2_1, 3, 3, 0, 0, 0, 1, 0, // PC_MFSPR - 127, IU2_1, 1, 1, 0, 0, 0, 1, 0, // PC_MFXER - 128, IU2_1, 1, 1, 0, 0, 0, 1, 0, // PC_MFCTR - 129, IU2_1, 1, 1, 0, 0, 0, 1, 0, // PC_MFLR - 130, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_MFCR - 131, FPU_1, 5, 5, 0, 0, 0, 1, 0, // PC_MFFS - 132, FPU_1, 5, 5, 0, 0, 0, 1, 0, // PC_MTFSF - 133, LSU_1, 3, 3, 0, 0, 0, 1, 0, // PC_EIEIO - 134, IU2_1, 1, 1, 0, 0, 0, 1, 0, // PC_ISYNC - 135, LSU_1, 35, 35, 0, 0, 0, 1, 0, // PC_SYNC - 136, IU2_1, 1, 1, 0, 0, 0, 1, 0, // PC_RFI - 137, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_LI - 138, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_LIS - 139, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_MR - 140, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_NOP - 141, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_NOT - 142, LSU_1, 4, 1, 1, 1, 1, 0, 0, // PC_LFS - 143, LSU_1, 4, 1, 1, 1, 1, 0, 0, // PC_LFSU - 144, LSU_1, 4, 1, 1, 1, 1, 0, 0, // PC_LFSX - 145, LSU_1, 4, 1, 1, 1, 1, 0, 0, // PC_LFSUX - 146, LSU_1, 4, 1, 1, 1, 1, 0, 0, // PC_LFD - 147, LSU_1, 4, 1, 1, 1, 1, 0, 0, // PC_LFDU - 148, LSU_1, 4, 1, 1, 1, 1, 0, 0, // PC_LFDX - 149, LSU_1, 4, 1, 1, 1, 1, 0, 0, // PC_LFDUX - 150, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STFS - 151, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STFSU - 152, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STFSX - 153, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STFSUX - 154, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STFD - 155, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STFDU - 156, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STFDX - 157, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STFDUX - 158, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FMR - 159, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FABS - 160, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FNEG - 161, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FNABS - 162, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FADD - 163, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FADDS - 164, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FSUB - 165, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FSUBS - 166, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FMUL - 167, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FMULS - 168, FPU_1, 35, 35, 0, 0, 0, 0, 0, // PC_FDIV - 169, FPU_1, 21, 21, 0, 0, 0, 0, 0, // PC_FDIVS - 170, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FMADD - 171, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FMADDS - 172, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FMSUB - 173, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FMSUBS - 174, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FNMADD - 175, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FNMADDS - 176, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FNMSUB - 177, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FNMSUBS - 178, FPU_1, 14, 14, 0, 0, 0, 0, 0, // PC_FRES - 179, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FRSQRTE - 180, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FSEL - 181, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FRSP - 182, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FCTIW - 183, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FCTIWZ - 184, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FCMPU - 185, FPU_1, 5, 1, 1, 1, 2, 0, 0, // PC_FCMPO - 186, LSU_1, 3, 3, 0, 0, 0, 1, 0, // PC_LWARX - 187, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LSWI - 188, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_LSWX - 189, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STFIWX - 190, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STSWI - 191, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_STSWX - 192, LSU_1, 3, 1, 1, 1, 0, 1, 0, // PC_STWCX - 193, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_ECIWX - 194, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_ECOWX - 195, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_DCBI - 196, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_ICBI - 197, IU2_1, 5, 5, 0, 0, 0, 1, 0, // PC_MCRFS - 198, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_MCRXR - 199, IU2_1, 5, 5, 0, 0, 0, 0, 0, // PC_MFTB - 200, IU2_1, 4, 1, 3, 0, 0, 0, 0, // PC_MFSR - 201, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_MTSR - 202, IU2_1, 4, 1, 3, 0, 0, 0, 0, // PC_MFSRIN - 203, IU2_1, 2, 2, 0, 0, 0, 1, 0, // PC_MTSRIN - 204, FPU_1, 5, 5, 0, 0, 0, 1, 0, // PC_MTFSB0 - 205, FPU_1, 5, 5, 0, 0, 0, 1, 0, // PC_MTFSB1 - 206, FPU_1, 5, 5, 0, 0, 0, 0, 0, // PC_MTFSFI - 207, IU2_1, 1, 1, 0, 0, 0, 1, 0, // PC_SC - 208, FPU_1, 1, 1, 0, 0, 0, 0, 0, // PC_FSQRT - 209, FPU_1, 1, 1, 0, 0, 0, 0, 0, // PC_FSQRTS - 210, LSU_1, 1, 1, 0, 0, 0, 0, 0, // PC_TLBIA - 211, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_TLBIE - 212, LSU_1, 3, 3, 0, 0, 0, 0, 0, // PC_TLBLD - 213, LSU_1, 3, 3, 0, 0, 0, 1, 0, // PC_TLBLI - 214, LSU_1, 3, 3, 0, 0, 0, 1, 0, // PC_TLBSYNC - 215, IU1a, 2, 2, 0, 0, 0, 0, 0, // PC_TW - 216, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_TRAP - 217, IU1a, 2, 2, 0, 0, 0, 0, 0, // PC_TWI - 218, IU1a, 1, 1, 0, 0, 0, 1, 0, // PC_OPWORD - 219, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_MFROM - 220, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_DSA - 221, IU1a, 1, 1, 0, 0, 0, 0, 0, // PC_ESA - 222, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_DCCCI - 223, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_DCREAD - 224, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_ICBT - 225, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_ICCCI - 226, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_ICREAD - 227, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_RFCI - 228, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_TLBRE - 229, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_TLBSX - 230, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_TLBWE - 231, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_WRTEE - 232, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_WRTEEI - 233, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_MFDCR - 234, IU1a, 1, 0, 0, 0, 0, 0, 0, // PC_MTDCR - 235, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DCBA - 236, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DSS - 237, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DSSALL - 238, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DST - 239, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DSTT - 240, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DSTST - 241, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_DSTSTT - 242, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LVEBX - 243, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LVEHX - 244, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LVEWX - 245, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LVSL - 246, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LVSR - 247, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LVX - 248, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_LVXL - 249, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STVEBX - 250, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STVEHX - 251, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STVEWX - 252, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STVX - 253, LSU_1, 3, 1, 1, 1, 0, 0, 0, // PC_STVXL - 254, VFPU_1, 2, 2, 0, 0, 0, 1, 0, // PC_MFVSCR - 255, VFPU_1, 2, 2, 0, 0, 0, 1, 0, // PC_MTVSCR - 256, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDCUW - 257, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VADDFP - 258, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDSBS - 259, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDSHS - 260, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDSWS - 261, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUBM - 262, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUBS - 263, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUHM - 264, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUHS - 265, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUWM - 266, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VADDUWS - 267, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VAND - 268, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VANDC - 269, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGSB - 270, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGSH - 271, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGSW - 272, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGUB - 273, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGUH - 274, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VAVGUW - 275, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VCFSX - 276, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VCFUX - 277, VFPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VCMPBFP - 278, VFPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VCMPEQFP - 279, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPEQUB - 280, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPEQUH - 281, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPEQUW - 282, VFPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VCMPGEFP - 283, VFPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VCMPGTFP - 284, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTSB - 285, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTSH - 286, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTSW - 287, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTUB - 288, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTUH - 289, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VCMPGTUW - 290, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VCTSXS - 291, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VCTUXS - 292, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VEXPTEFP - 293, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VLOGEFP - 294, VFPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMAXFP - 295, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXSB - 296, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXSH - 297, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXSW - 298, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXUB - 299, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXUH - 300, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMAXUW - 301, VFPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMINFP - 302, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMINSB - 303, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMINSH - 304, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMINSW - 305, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMINUB - 306, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMINUH - 307, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMINUW - 308, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMRGHB - 309, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMRGHH - 310, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMRGHW - 311, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMRGLB - 312, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMRGLH - 313, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMRGLW - 314, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMULESB - 315, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMULESH - 316, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMULEUB - 317, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMULEUH - 318, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMULOSB - 319, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMULOSH - 320, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMULOUB - 321, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMULOUH - 322, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VNOR - 323, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VOR - 324, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKPX - 325, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKSHSS - 326, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKSHUS - 327, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKSWSS - 328, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKSWUS - 329, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKUHUM - 330, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKUHUS - 331, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKUWUM - 332, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPKUWUS - 333, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VREFP - 334, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VRFIM - 335, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VRFIN - 336, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VRFIP - 337, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VRFIZ - 338, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VRLB - 339, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VRLH - 340, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VRLW - 341, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VRSQRTEFP - 342, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSL - 343, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSLB - 344, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSLH - 345, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSLO - 346, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSLW - 347, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSPLTB - 348, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSPLTH - 349, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSPLTW - 350, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSPLTISB - 351, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSPLTISH - 352, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSPLTISW - 353, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSR - 354, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSRAB - 355, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSRAH - 356, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSRAW - 357, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSRB - 358, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSRH - 359, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSRO - 360, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSRW - 361, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBCUW - 362, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VSUBFP - 363, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBSBS - 364, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBSHS - 365, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBSWS - 366, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUBM - 367, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUBS - 368, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUHM - 369, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUHS - 370, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUWM - 371, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSUBUWS - 372, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VSUMSWS - 373, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VSUM2SWS - 374, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VSUM4SBS - 375, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VSUM4SHS - 376, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VSUM4UBS - 377, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VUPKHPX - 378, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VUPKHSB - 379, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VUPKHSH - 380, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VUPKLPX - 381, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VUPKLSB - 382, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VUPKLSH - 383, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VXOR - 384, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMADDFP - 385, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMHADDSHS - 386, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMHRADDSHS - 387, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMLADDUHM - 388, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMSUMMBM - 389, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMSUMSHM - 390, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMSUMSHS - 391, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMSUMUBM - 392, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMSUMUHM - 393, VIU2_1, 4, 1, 1, 1, 1, 0, 0, // PC_VMSUMUHS - 394, VFPU_1, 4, 1, 1, 1, 1, 0, 0, // PC_VNMSUBFP - 395, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VPERM - 396, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VSEL - 397, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VSLDOI - 398, VIU1, 1, 1, 0, 0, 0, 0, 0, // PC_VMR - 399, VPU_1, 2, 1, 1, 0, 0, 0, 0, // PC_VMRP - -1, IU2_1, 1, 1, 0, 0, 0, 1, 0 -}; - -enum { NumPipelineUnits = 6 }; -static struct { - Stage start, end; -} pipeline_units[8] = { - IU2_1, IU2_3, - LSU_1, LSU_4, - FPU_1, FPU_4, - VPU_1, VPU_2, - VIU2_1, VIU2_4, - VFPU_1, VFPU_4 -}; - -enum { NumFinalStages = 11 }; -static Stage finalstages[16] = { - BPU, IU2_3, IU1a, IU1b, - IU1c, LSU_4, FPU_4, VIU1, - VPU_2, VIU2_4, VFPU_4 -}; - -// forward decl -static void complete_instruction(int stage); - -static void advance(int firstStage, int oldStage, int newStage) { - PCode *instr = pipeline_altivec[oldStage].instr; - int cycles = instruction_timing[instr->op].cycles[newStage - firstStage]; - pipeline_altivec[newStage].instr = instr; - pipeline_altivec[newStage].remaining = cycles; - pipeline_altivec[oldStage].instr = NULL; - pipeline_altivec[oldStage].remaining = 0; - if (cycles == 0) - complete_instruction(newStage); -} - -static void assign_completion_buffer(PCode *instr) { - completionbuffers.used++; - completionbuffers.free--; - completionbuffers.entries[completionbuffers.nextFreeSlot].instr = instr; - completionbuffers.entries[completionbuffers.nextFreeSlot].completed = 0; - completionbuffers.nextFreeSlot = (completionbuffers.nextFreeSlot + 1) % MaxEntries; -} - -static void complete_instruction(int stage) { - PCode *instr = pipeline_altivec[stage].instr; - int buf = 0; - while (buf < MaxEntries && completionbuffers.entries[buf].instr != instr) - buf++; - - completionbuffers.entries[buf].completed = 1; - pipeline_altivec[stage].instr = NULL; -} - -static void retire_instruction(void) { - completionbuffers.entries[completionbuffers.nextToRetire].instr = NULL; - completionbuffers.entries[completionbuffers.nextToRetire].completed = 0; - completionbuffers.used--; - completionbuffers.free++; - completionbuffers.nextToRetire = (completionbuffers.nextToRetire + 1) % MaxEntries; -} - -static int latency(PCode *instr) { - int cycles = instruction_timing[instr->op].latency; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - cycles += 1; - if (instr->op == PC_LMW || instr->op == PC_STMW) - cycles += instr->argCount - 2; - return cycles; -} - -static void initialize(void) { - int stage; - int i; - - fetchqueues[Queue0] = 1; - for (i = 1; i < NumQueues; i++) - fetchqueues[i] = 0; - - for (stage = 0; stage < NumStages; stage++) - pipeline_altivec[stage].instr = NULL; - - completionbuffers.free = MaxEntries; - completionbuffers.used = 0; - completionbuffers.nextToRetire = 0; - completionbuffers.nextFreeSlot = 0; - for (i = 0; i < MaxEntries; i++) { - completionbuffers.entries[i].instr = NULL; - completionbuffers.entries[i].completed = 0; - } -} - -static int can_issue(PCode *instr) { - int stage; - - if (completionbuffers.free == 0) - return 0; - - stage = instruction_timing[instr->op].stage; - - if (stage == IU1a) { - int isClear1 = !pipeline_altivec[IU1a].instr; - int isClear2 = !pipeline_altivec[IU1b].instr; - if (!isClear1 && !isClear2) - return 0; - } else { - if (pipeline_altivec[stage].instr) - return 0; - } - - if (fetchqueues[Queue1] <= 0) - return 0; - - if (stage == FPU_1) { - if (fetchqueues[Queue2] < 1 || fetchqueues[Queue5] >= 1) - return 0; - } else if (stage >= VIU1 && stage <= VFPU_1) { - if (fetchqueues[Queue4] < 1 || fetchqueues[Queue7] >= 2) - return 0; - } else if (stage != BPU) { - if (fetchqueues[Queue3] < 1 || fetchqueues[Queue6] >= 3) - return 0; - } - - return 1; -} - -static void issue(PCode *instr) { - int stage = instruction_timing[instr->op].stage; - int cycles = instruction_timing[instr->op].cycles[0]; - assign_completion_buffer(instr); - - CError_ASSERT(879, --fetchqueues[Queue1] >= 0); - - if (stage == FPU_1) { - fetchqueues[Queue2]--; - fetchqueues[Queue5]++; - } else if (stage >= VIU1 && stage <= VFPU_1) { - fetchqueues[Queue4]--; - fetchqueues[Queue7]++; - } else if (stage != BPU) { - fetchqueues[Queue3]--; - fetchqueues[Queue6]++; - } - - fetchqueues[Queue2] = (fetchqueues[Queue1] < fetchqueues[Queue2]) ? fetchqueues[Queue1] : fetchqueues[Queue2]; - fetchqueues[Queue3] = (fetchqueues[Queue1] < fetchqueues[Queue3]) ? fetchqueues[Queue1] : fetchqueues[Queue3]; - fetchqueues[Queue4] = (fetchqueues[Queue1] < fetchqueues[Queue4]) ? fetchqueues[Queue1] : fetchqueues[Queue4]; - - if (stage == IU1a) { - if (!pipeline_altivec[IU1a].instr) - stage = IU1a; - else if (!pipeline_altivec[IU1b].instr) - stage = IU1b; - else if (!pipeline_altivec[IU1c].instr) - stage = IU1c; - } - - pipeline_altivec[stage].instr = instr; - pipeline_altivec[stage].remaining = cycles; -} - -static void advance_clock(void) { - int num; - int i; - unsigned int unit; - - for (i = 0; i < NumStages; i++) { - if (pipeline_altivec[i].instr && pipeline_altivec[i].remaining) - --pipeline_altivec[i].remaining; - } - - for (i = 0; i < 3; i++) { - if (completionbuffers.used == 0) - break; - if (completionbuffers.entries[completionbuffers.nextToRetire].completed == 0) - break; - retire_instruction(); - } - - unit = 0; - do { - if (pipeline_altivec[finalstages[unit]].instr && pipeline_altivec[finalstages[unit]].remaining == 0) - complete_instruction(finalstages[unit]); - } while (++unit < NumFinalStages); - - unit = 0; - do { - Stage first; - Stage current; - first = pipeline_units[unit].start; - for (current = first; current < pipeline_units[unit].end; current++) { - if (pipeline_altivec[current].instr && pipeline_altivec[current].remaining == 0 && !pipeline_altivec[current + 1].instr) - advance(first, current, current + 1); - } - } while (++unit < NumPipelineUnits); - - fetchqueues[Queue5] = 0; - fetchqueues[Queue6] = 0; - fetchqueues[Queue7] = 0; - -#define CHEAP_MIN(a, b) ( ((a) < (b)) ? (a) : (b) ) - num = 2 - fetchqueues[Queue2]; - num += 6 - fetchqueues[Queue3]; - num += 4 - fetchqueues[Queue4]; - num = (num > 3) ? 3 : num; - num = (completionbuffers.free < num) ? completionbuffers.free : num; - if (fetchqueues[Queue0] < num) - num = fetchqueues[Queue0]; - - fetchqueues[Queue1] += num; - fetchqueues[Queue0] -= num; - - fetchqueues[Queue2] = CHEAP_MIN(fetchqueues[Queue1], CHEAP_MIN(2, fetchqueues[Queue2] + num)); - fetchqueues[Queue3] = CHEAP_MIN(fetchqueues[Queue1], CHEAP_MIN(6, fetchqueues[Queue3] + num)); - fetchqueues[Queue4] = CHEAP_MIN(fetchqueues[Queue1], CHEAP_MIN(4, fetchqueues[Queue4] + num)); - - CError_ASSERT(991, fetchqueues[Queue1] <= (fetchqueues[Queue2] + fetchqueues[Queue3] + fetchqueues[Queue4])); - - if (fetchqueues[Queue0] <= 8) - fetchqueues[Queue0] += 4; -} - -static int serializes(PCode *instr) { - return instruction_timing[instr->op].serializes; -} - -static int uses_vpermute_unit_altivec(PCode *instr) { - return instruction_timing[instr->op].stage == VPU_1; -} - -MachineInfo machine7450 = { - 6, - 1, - 4, - &latency, - &initialize, - &can_issue, - &issue, - &advance_clock, - &serializes, - &uses_vpermute_unit_altivec -}; diff --git a/compiler_and_linker/unsorted/ObjGenMachO.c b/compiler_and_linker/unsorted/ObjGenMachO.c index 072824a..f6f6216 100644 --- a/compiler_and_linker/unsorted/ObjGenMachO.c +++ b/compiler_and_linker/unsorted/ObjGenMachO.c @@ -7,9 +7,9 @@ #include "compiler/CParser.h" #include "compiler/CodeGen.h" #include "compiler/CompilerTools.h" -#include "compiler/uDump.h" +#include "compiler/DumpIR.h" #include "compiler/GenStabs.h" -#include "compiler/IrOptimizer.h" +#include "../FrontEnd/Optimizer/IrOptimizer.h" #include "compiler/MachO.h" #include "compiler/PCodeListing.h" #include "compiler/TOC.h" diff --git a/compiler_and_linker/unsorted/Operands.c b/compiler_and_linker/unsorted/Operands.c deleted file mode 100644 index c5da285..0000000 --- a/compiler_and_linker/unsorted/Operands.c +++ /dev/null @@ -1,1040 +0,0 @@ -#include "compiler/Operands.h" -#include "compiler/CError.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/CodeGen.h" -#include "compiler/CompilerTools.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" -#include "compiler/PCodeUtilities.h" -#include "compiler/RegisterInfo.h" -#include "compiler/Registers.h" -#include "compiler/StackFrame.h" -#include "compiler/TOC.h" -#include "compiler/enode.h" -#include "compiler/objects.h" - -unsigned long long uns_to_float_cc = 0x4330000000000000; -unsigned long long int_to_float_cc = 0x4330000080000000; -Float one_point_zero = {1.0}; - -void load_immediate(short reg, SInt32 value) { - short tmpreg = reg; - short tmpreg2; - - if (!FITS_IN_SHORT(value)) { - if (copts.optimizationlevel > 1 && LOW_PART_BUGGY(value)) - tmpreg = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_LIS, tmpreg2 = tmpreg, 0, (short) HIGH_PART(value)); - if (LOW_PART_BUGGY(value)) - emitpcode(PC_ADDI, reg, tmpreg2, 0, LOW_PART(value)); - } else { - emitpcode(PC_LI, reg, value); - } -} - -static void set_op_flags(Operand *op, ENode *expr) { - CError_ASSERT(118, op); - - if (expr) { - if (expr->type == EINTCONST) { - op->flags = 0; - if (expr->flags & ENODE_FLAG_VOLATILE) - op->flags |= OpndFlags_Volatile; - if (expr->flags & ENODE_FLAG_CONST) - op->flags |= OpndFlags_Const; - } else { - op->flags = CParserIsVolatileExpr(expr) ? OpndFlags_Volatile : 0; - op->flags |= CParserIsConstExpr(expr) ? OpndFlags_Const : 0; - } - } else { - op->flags = 0; - } -} - -void symbol_operand(Operand *op, Object *obj) { - memclrw(op, sizeof(Operand)); - op->optype = OpndType_Symbol; - op->object = obj; -} - -void indirect(Operand *op, ENode *expr) { - switch (op->optype) { - case OpndType_GPRPair: - CError_FATAL(163); - case OpndType_CRField: - case OpndType_IndirectGPR_ImmOffset: - case OpndType_IndirectGPR_Indexed: - case OpndType_IndirectSymbol: - if (op->optype) - Coerce_to_register(op, TYPE(&void_ptr), 0); - case OpndType_GPR: - op->immOffset = 0; - op->object = NULL; - case OpndType_GPR_ImmOffset: - op->optype = OpndType_IndirectGPR_ImmOffset; - set_op_flags(op, expr); - break; - case OpndType_GPR_Indexed: - op->optype = OpndType_IndirectGPR_Indexed; - set_op_flags(op, expr); - break; - case OpndType_Absolute: - if (FITS_IN_SHORT(op->immediate)) { - op->reg = 0; - op->immOffset = op->immediate; - } else { - emitpcode(PC_LIS, op->reg = used_virtual_registers[RegClass_GPR]++, 0, (short) HIGH_PART(op->immediate)); - op->immOffset = LOW_PART(op->immediate); - } - op->object = NULL; - op->optype = OpndType_IndirectGPR_ImmOffset; - set_op_flags(op, expr); - break; - case OpndType_Symbol: - op->optype = OpndType_IndirectSymbol; - set_op_flags(op, expr); - break; - default: - CError_FATAL(215); - } -} - -#define COMBO_OP(a, b) (b + (a * 11)) - -void combine(Operand *opA, Operand *opB, short output_reg, Operand *opOut) { - Operand *tmp_op; - int tmp; - - if (opA->optype == OpndType_Symbol || opA->optype == OpndType_IndirectSymbol) - coerce_to_addressable(opA); - if (opB->optype == OpndType_Symbol || opB->optype == OpndType_IndirectSymbol) - coerce_to_addressable(opB); - - switch (COMBO_OP(opA->optype, opB->optype)) { - case COMBO_OP(OpndType_GPR, OpndType_GPR): - opOut->optype = OpndType_GPR_Indexed; - opOut->reg = opA->reg; - opOut->regOffset = opB->reg; - break; - case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR_ImmOffset): - if (FITS_IN_SHORT(opA->immOffset + opB->immOffset) && (!opA->object || !opB->object)) { - opB->immOffset += opA->immOffset; - if (!opB->object) - opB->object = opA->object; - } else { - tmp = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; - add_immediate(tmp, opA->reg, opA->object, opA->immOffset); - opA->reg = tmp; - } - case COMBO_OP(OpndType_GPR, OpndType_GPR_ImmOffset): - tmp_op = opA; - opA = opB; - opB = tmp_op; - case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR): - if (opA->reg == _FP_ || opA->reg == _CALLER_SP_) { - opOut->optype = OpndType_GPR_Indexed; - opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; - opOut->regOffset = opB->reg; - add_immediate(opOut->reg, opA->reg, opA->object, LOW_PART(opA->immOffset)); - } else if (opB->reg == _FP_ || opB->reg == _CALLER_SP_) { - opOut->optype = OpndType_GPR_Indexed; - opOut->reg = (output_reg && (output_reg != opA->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; - opOut->regOffset = opA->reg; - add_immediate(opOut->reg, opB->reg, opA->object, LOW_PART(opA->immOffset)); - } else if (opA->object) { - opOut->optype = OpndType_GPR_Indexed; - opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; - opOut->regOffset = opB->reg; - add_immediate(opOut->reg, opA->reg, opA->object, LOW_PART(opA->immOffset)); - } else { - opOut->optype = OpndType_GPR_ImmOffset; - opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - opOut->immOffset = opA->immOffset; - opOut->object = opA->object; - emitpcode(PC_ADD, opOut->reg, opA->reg, opB->reg); - } - break; - case COMBO_OP(OpndType_GPR, OpndType_GPR_Indexed): - tmp_op = opA; - opA = opB; - opB = tmp_op; - case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR): - opOut->optype = OpndType_GPR_Indexed; - opOut->reg = opA->reg; - opOut->regOffset = (output_reg && (output_reg != opA->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_ADD, opOut->regOffset, opA->regOffset, opB->reg); - break; - case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR_Indexed): - tmp_op = opA; - opA = opB; - opB = tmp_op; - case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR_ImmOffset): - if (opB->object) { - opOut->optype = OpndType_GPR_Indexed; - opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg - : used_virtual_registers[RegClass_GPR]++; - opOut->regOffset = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_ADD, opOut->reg, opA->reg, opA->regOffset); - add_immediate(opOut->regOffset, opB->reg, opB->object, opB->immOffset); - } else { - opOut->optype = OpndType_GPR_ImmOffset; - opOut->immOffset = opB->immOffset; - opOut->object = opB->object; - opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg - : used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_ADD, opOut->reg, opA->reg, opA->regOffset); - emitpcode(PC_ADD, opOut->reg, opOut->reg, opB->reg); - } - break; - case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR_Indexed): - opOut->optype = OpndType_GPR_Indexed; - opOut->reg = opA->reg; - opOut->regOffset = (output_reg && (output_reg != opA->regOffset)) ? output_reg - : used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_ADD, opOut->regOffset, opB->reg, opB->regOffset); - emitpcode(PC_ADD, opOut->regOffset, opOut->regOffset, opA->regOffset); - break; - case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_Absolute): - tmp_op = opA; - opA = opB; - opB = tmp_op; - case COMBO_OP(OpndType_Absolute, OpndType_GPR_ImmOffset): - if (!opB->object) { - opOut->optype = OpndType_GPR_ImmOffset; - opOut->reg = opB->reg; - opOut->immOffset = opB->immOffset; - opOut->object = opB->object; - if (FITS_IN_SHORT(opOut->immOffset + opA->immediate)) { - opOut->immOffset += opA->immediate; - } else { - opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - if (!HIGH_PART(opA->immediate)) { - emitpcode(PC_ADDI, opOut->reg, opB->reg, 0, LOW_PART(opA->immediate)); - } else { - emitpcode(PC_ADDIS, opOut->reg, opB->reg, 0, (short) HIGH_PART(opA->immediate)); - if (FITS_IN_SHORT(opOut->immOffset + LOW_PART(opA->immediate))) { - opOut->immOffset += LOW_PART(opA->immediate); - } else { - emitpcode(PC_ADDI, opOut->reg, opOut->reg, 0, LOW_PART(opA->immediate)); - } - } - } - break; - } else if (opB->object->datatype == DLOCAL && can_add_displ_to_local(opB->object, opB->immOffset + opA->immediate)) { - opOut->optype = OpndType_GPR_ImmOffset; - opOut->object = opB->object; - opOut->reg = opB->reg; - opOut->immOffset = LOW_PART(opB->immOffset + opA->immediate); - break; - } else { - opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - add_immediate(opOut->reg, opB->reg, opB->object, opB->immOffset); - opB->optype = OpndType_GPR; - opB->reg = opOut->reg; - tmp_op = opA; - opA = opB; - opB = tmp_op; - } - case COMBO_OP(OpndType_GPR, OpndType_Absolute): - tmp_op = opA; - opA = opB; - opB = tmp_op; - case COMBO_OP(OpndType_Absolute, OpndType_GPR): - opOut->optype = (opA->immediate != 0) ? OpndType_GPR_ImmOffset : OpndType_GPR; - opOut->immOffset = LOW_PART(opA->immediate); - opOut->object = NULL; - if (FITS_IN_SHORT(opA->immediate)) { - opOut->reg = opB->reg; - } else { - opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_ADDIS, opOut->reg, opB->reg, 0, (short) HIGH_PART(opA->immediate)); - } - break; - case COMBO_OP(OpndType_GPR_Indexed, OpndType_Absolute): - tmp_op = opA; - opA = opB; - opB = tmp_op; - case COMBO_OP(OpndType_Absolute, OpndType_GPR_Indexed): - opOut->optype = OpndType_GPR_Indexed; - opOut->reg = opB->reg; - opOut->regOffset = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++; - if (!HIGH_PART(opA->immediate)) { - emitpcode(PC_ADDI, opOut->regOffset, opB->regOffset, 0, LOW_PART(opA->immediate)); - } else { - emitpcode(PC_ADDIS, opOut->regOffset, opB->regOffset, 0, (short) HIGH_PART(opA->immediate)); - if (LOW_PART_BUGGY(opA->immediate)) - emitpcode(PC_ADDI, opOut->regOffset, opOut->regOffset, 0, LOW_PART(opA->immediate)); - } - break; - case COMBO_OP(OpndType_Absolute, OpndType_Absolute): - opOut->optype = OpndType_Absolute; - opOut->immediate = opA->immediate + opB->immediate; - break; - default: - CError_FATAL(415); - } -} - -void coerce_to_addressable(Operand *op) { - UInt32 offset; - short reg; - short flag; - short tmp; - Object *obj; - - flag = 0; - obj = op->object; - tmp = 0; - - switch (op->optype) { - case OpndType_GPR: - case OpndType_GPR_ImmOffset: - case OpndType_GPR_Indexed: - case OpndType_GPRPair: - case OpndType_Absolute: - case OpndType_VR: - case OpndType_CRField: - case OpndType_IndirectGPR_ImmOffset: - case OpndType_IndirectGPR_Indexed: - break; - case OpndType_IndirectSymbol: - flag = 1; - case OpndType_Symbol: - if (obj->datatype == DLOCAL) { - if (!local_is_16bit_offset(obj)) { - reg = used_virtual_registers[RegClass_GPR]++; - op_absolute_ha(reg, local_base_register(obj), obj, 0, 1); - op->optype = OpndType_GPR_ImmOffset; - op->reg = reg; - op->object = obj; - } else { - op->optype = OpndType_GPR_ImmOffset; - op->reg = local_base_register(obj); - op->object = obj; - } - } else if (obj->datatype == DABSOLUTE) { - offset = obj->u.address; - if (FITS_IN_SHORT(offset)) { - op->reg = 0; - op->immOffset = obj->u.address; - } else { - emitpcode(PC_LIS, op->reg = used_virtual_registers[RegClass_GPR]++, 0, (short) HIGH_PART(offset)); - op->immOffset = LOW_PART(obj->u.address); - } - op->object = obj; - op->optype = OpndType_GPR_ImmOffset; - } else { - if (copts.codegen_pic) - tmp = pic_base_reg; - reg = used_virtual_registers[RegClass_GPR]++; - op_absolute_ha(reg, tmp, obj, 0, 1); - op->optype = OpndType_GPR_ImmOffset; - op->reg = reg; - } - if (flag) { - if (op->optype == OpndType_GPR_ImmOffset) { - op->optype = OpndType_IndirectGPR_ImmOffset; - } else { - CError_FATAL(563); - } - } - break; - default: - CError_FATAL(581); - } -} - -void Coerce_to_register(Operand *op, Type *type, short output_reg) { - SInt32 offset; - Opcode opcode; - short reg; - short tmp; - short cond_neg; - short cond; - short bit_offset; - short bit_size; - - if (TYPE_IS_8BYTES(type)) { - coerce_to_register_pair(op, type, output_reg, 0); - return; - } - - coerce_to_addressable(op); - switch (op->optype) { - case OpndType_GPRPair: - return; - case OpndType_GPR: - return; - case OpndType_GPR_ImmOffset: - reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - add_immediate(reg, op->reg, op->object, op->immOffset); - break; - case OpndType_GPR_Indexed: - reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_ADD, reg, op->reg, op->regOffset); - break; - case OpndType_Absolute: - reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - offset = op->immediate; - if (FITS_IN_SHORT(offset)) { - emitpcode(PC_LI, reg, offset); - } else { - tmp = reg; - if (copts.optimizationlevel > 1 && LOW_PART_BUGGY(offset)) - tmp = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_LIS, tmp, 0, (short) HIGH_PART(offset)); - if (LOW_PART_BUGGY(offset)) - emitpcode(PC_ADDI, reg, tmp, 0, LOW_PART(offset)); - } - break; - case OpndType_IndirectGPR_ImmOffset: - reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - opcode = PC_LWZ; - if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) { - switch (type->size) { - case 1: - opcode = PC_LBZ; - break; - case 2: - if (is_unsigned(type)) - opcode = PC_LHZ; - else - opcode = PC_LHA; - break; - } - } else { - CError_ASSERT(680, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); - } - load_store_register(opcode, reg, op->reg, op->object, op->immOffset); - setpcodeflags(op->flags); - break; - case OpndType_IndirectGPR_Indexed: - reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - opcode = PC_LWZX; - if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) { - switch (type->size) { - case 1: - opcode = PC_LBZX; - break; - case 2: - if (is_unsigned(type)) - opcode = PC_LHZX; - else - opcode = PC_LHAX; - break; - } - } else { - CError_ASSERT(724, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); - } - emitpcode(opcode, reg, op->reg, op->regOffset); - setpcodeflags(op->flags); - break; - case OpndType_CRField: - cond_neg = 0; - cond = 0; - reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_MFCR, tmp = reg); - switch (op->regOffset) { - case ENOTEQU: - cond_neg = 1; - case EEQU: - cond = 2; - break; - case EGREATEREQU: - cond_neg = 1; - case ELESS: - cond = 0; - break; - case ELESSEQU: - cond_neg = 1; - case EGREATER: - cond = 1; - break; - default: - CError_FATAL(758); - } - bit_offset = cond + (op->reg << 2); - bit_size = 1; - emitpcode(PC_RLWINM, tmp, tmp, (bit_size + bit_offset) & 31, 32 - bit_size, 31); - if (cond_neg) - emitpcode(PC_XORI, tmp, tmp, 1); - break; - default: - CError_FATAL(769); - } - - op->optype = OpndType_GPR; - op->reg = reg; -} - -void coerce_to_register_pair(Operand *op, Type *type, short output_reg, short output_regHi) { - SInt32 offset; - short reg; - short regHi; - short tmp1; - short tmp2; - - regHi = -1; - - CError_ASSERT(794, TYPE_IS_8BYTES(type) || (IS_TYPE_STRUCT(type) && type->size == 8)); - - coerce_to_addressable(op); - switch (op->optype) { - case OpndType_GPRPair: - if (output_reg && !output_regHi) - output_regHi = used_virtual_registers[RegClass_GPR]++; - if (output_regHi && !output_reg) - output_reg = used_virtual_registers[RegClass_GPR]++; - if (op->reg != output_reg || op->regHi != output_regHi) { - tmp1 = output_reg ? output_reg : op->reg; - tmp2 = output_regHi ? output_regHi : op->regHi; - if (tmp1 != op->reg) { - if (tmp1 == op->regHi) { - CError_ASSERT(818, tmp1 != tmp2); - emitpcode(PC_MR, tmp2, op->regHi); - emitpcode(PC_MR, tmp1, op->reg); - } else { - emitpcode(PC_MR, tmp1, op->reg); - if (op->regHi != tmp2) - emitpcode(PC_MR, tmp2, op->regHi); - } - } else if (tmp2 != op->regHi) { - if (tmp2 == op->reg) { - CError_ASSERT(832, tmp1 != tmp2); - emitpcode(PC_MR, tmp1, op->reg); - emitpcode(PC_MR, tmp2, op->regHi); - } else { - emitpcode(PC_MR, tmp2, op->regHi); - if (op->reg != tmp1) - emitpcode(PC_MR, tmp1, op->reg); - } - } - } - reg = op->reg; - regHi = op->regHi; - break; - case OpndType_GPR: - CError_FATAL(849); - break; - case OpndType_GPR_ImmOffset: - CError_FATAL(852); - break; - case OpndType_GPR_Indexed: - CError_FATAL(855); - break; - case OpndType_Absolute: - reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - offset = op->immediate; - if (FITS_IN_SHORT(offset)) { - emitpcode(PC_LI, reg, offset); - } else { - tmp1 = reg; - if (copts.optimizationlevel > 1 && LOW_PART_BUGGY(offset)) - tmp1 = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_LIS, tmp1, 0, (short) HIGH_PART(offset)); - if (LOW_PART_BUGGY(offset)) - emitpcode(PC_ADDI, reg, tmp1, 0, LOW_PART(offset)); - } - regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++; - if (is_unsigned(type) || offset >= 0) - load_immediate(regHi, 0); - else - load_immediate(regHi, -1); - break; - case OpndType_IndirectGPR_ImmOffset: - reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++; - if (op->reg == regHi) { - if (op->reg == reg) { - CError_FATAL(887); - } else { - load_store_register(PC_LWZ, reg, op->reg, op->object, op->immOffset + low_offset); - setpcodeflags(op->flags); - load_store_register(PC_LWZ, regHi, op->reg, op->object, op->immOffset + high_offset); - setpcodeflags(op->flags); - } - } else { - load_store_register(PC_LWZ, regHi, op->reg, op->object, op->immOffset + high_offset); - setpcodeflags(op->flags); - load_store_register(PC_LWZ, reg, op->reg, op->object, op->immOffset + low_offset); - setpcodeflags(op->flags); - } - break; - case OpndType_IndirectGPR_Indexed: - reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_ADD, reg, op->reg, op->regOffset); - load_store_register(PC_LWZ, regHi, reg, NULL, high_offset); - setpcodeflags(op->flags); - load_store_register(PC_LWZ, reg, reg, NULL, low_offset); - setpcodeflags(op->flags); - break; - default: - CError_FATAL(912); - } - - if (regHi == -1) { - CError_FATAL(916); - } else { - op->optype = OpndType_GPRPair; - op->reg = reg; - op->regHi = regHi; - } -} - -void Coerce_to_fp_register(Operand *op, Type *type, short output_reg) { - short reg; - - coerce_to_addressable(op); - - switch (op->optype) { - case OpndType_FPR: - reg = op->reg; - break; - case OpndType_IndirectGPR_ImmOffset: - reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++; - load_store_register((type->size == 4) ? PC_LFS : PC_LFD, reg, op->reg, op->object, op->immOffset); - setpcodeflags(op->flags); - break; - case OpndType_IndirectGPR_Indexed: - reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++; - emitpcode((type->size == 4) ? PC_LFSX : PC_LFDX, reg, op->reg, op->regOffset, 0, 0x390); - setpcodeflags(op->flags); - break; - default: - CError_FATAL(986); - } - - op->optype = OpndType_FPR; - op->reg = reg; -} - -void Coerce_to_v_register(Operand *op, Type *type, short output_reg) { - short reg; - - coerce_to_addressable(op); - - switch (op->optype) { - case OpndType_VR: - reg = op->reg; - break; - case OpndType_IndirectGPR_ImmOffset: - reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++; - load_store_register(PC_LVX, reg, op->reg, op->object, op->immOffset); - setpcodeflags(op->flags); - break; - case OpndType_IndirectGPR_Indexed: - reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++; - emitpcode(PC_LVX, reg, op->reg, op->regOffset); - setpcodeflags(op->flags); - break; - case OpndType_Absolute: - reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++; - switch (TYPE_STRUCT(type)->stype) { - case STRUCT_VECTOR_UCHAR: - case STRUCT_VECTOR_SCHAR: - case STRUCT_VECTOR_BCHAR: - emitpcode(PC_VSPLTISB, reg, op->immediate); - break; - case STRUCT_VECTOR_USHORT: - case STRUCT_VECTOR_SSHORT: - case STRUCT_VECTOR_BSHORT: - case STRUCT_VECTOR_PIXEL: - emitpcode(PC_VSPLTISH, reg, op->immediate); - break; - case STRUCT_VECTOR_UINT: - case STRUCT_VECTOR_SINT: - case STRUCT_VECTOR_BINT: - case STRUCT_VECTOR_FLOAT: - emitpcode(PC_VSPLTISW, reg, op->immediate); - break; - default: - CError_FATAL(1049); - } - op->optype = OpndType_VR; - op->reg = reg; - setpcodeflags(op->flags); - break; - default: - CError_FATAL(1059); - } - - op->optype = OpndType_VR; - op->reg = reg; -} - -void store(short reg, Operand *op, Type *type) { - Opcode opcode; - - coerce_to_addressable(op); - switch (op->optype) { - case OpndType_IndirectGPR_ImmOffset: - opcode = PC_STW; - if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) { - switch (type->size) { - case 1: - opcode = PC_STB; - break; - case 2: - opcode = PC_STH; - break; - } - } else { - CError_ASSERT(1171, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); - } - load_store_register(opcode, reg, op->reg, op->object, op->immOffset); - setpcodeflags(op->flags); - break; - case OpndType_IndirectGPR_Indexed: - opcode = PC_STWX; - if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) { - switch (type->size) { - case 1: - opcode = PC_STBX; - break; - case 2: - opcode = PC_STHX; - break; - } - } else { - CError_ASSERT(1188, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)); - } - emitpcode(opcode, reg, op->reg, op->regOffset); - setpcodeflags(op->flags); - break; - default: - CError_FATAL(1193); - } -} - -void store_pair(short reg, short regHi, Operand *op, Type *type) { - short tmp; - - CError_ASSERT(1208, TYPE_IS_8BYTES(type)); - - coerce_to_addressable(op); - switch (op->optype) { - case OpndType_IndirectGPR_ImmOffset: - load_store_register(PC_STW, reg, op->reg, op->object, op->immOffset + low_offset); - setpcodeflags(op->flags); - load_store_register(PC_STW, regHi, op->reg, op->object, op->immOffset + high_offset); - setpcodeflags(op->flags); - break; - case OpndType_IndirectGPR_Indexed: - tmp = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_ADD, tmp, op->reg, op->regOffset); - load_store_register(PC_STW, reg, tmp, NULL, low_offset); - setpcodeflags(op->flags); - load_store_register(PC_STW, regHi, tmp, NULL, high_offset); - setpcodeflags(op->flags); - break; - default: - CError_FATAL(1228); - } -} - -void store_fp(short reg, Operand *op, Type *type) { - coerce_to_addressable(op); - switch (op->optype) { - case OpndType_IndirectGPR_ImmOffset: - load_store_register((type->size == 4) ? PC_STFS : PC_STFD, reg, op->reg, op->object, op->immOffset); - setpcodeflags(op->flags); - break; - case OpndType_IndirectGPR_Indexed: - emitpcode((type->size == 4) ? PC_STFSX : PC_STFDX, reg, op->reg, op->regOffset); - setpcodeflags(op->flags); - break; - default: - CError_FATAL(1259); - } -} - -void store_v(short reg, Operand *op, Type *tstruct) { - coerce_to_addressable(op); - switch (op->optype) { - case OpndType_IndirectGPR_ImmOffset: - load_store_register(PC_STVX, reg, op->reg, op->object, op->immOffset); - setpcodeflags(op->flags); - break; - case OpndType_IndirectGPR_Indexed: - emitpcode(PC_STVX, reg, op->reg, op->regOffset); - setpcodeflags(op->flags); - break; - default: - CError_FATAL(1283); - } -} - -static Boolean last_matches_rlwinm_or_exts(Operand *op, short opcode, short b, short c) { - PCode *pc; - - if (pclastblock->pcodeCount <= 0) - return 0; - - pc = pclastblock->lastPCode; - if (pc->args[0].kind != PCOp_REGISTER || pc->args[0].arg != RegClass_GPR || pc->args[0].data.reg.reg != op->reg) - return 0; - - if (pc->op != opcode && (opcode != PC_EXTSH || pc->op != PC_EXTSB)) - return 0; - - if (opcode == PC_RLWINM) { - if (pc->args[2].data.imm.value != 0 || pc->args[3].data.imm.value != b || pc->args[4].data.imm.value != c) - return 0; - } - - return 1; -} - -void extend32(Operand *op, Type *type, short output_reg) { - int r28; - int reg; - - r28 = op->optype >= OpndType_IndirectGPR_ImmOffset; - if (op->optype != OpndType_GPR) - Coerce_to_register(op, type, output_reg); - - switch (type->size) { - case 1: - if (is_unsigned(type)) { - if (r28) - return; - if (last_matches_rlwinm_or_exts(op, PC_RLWINM, 24, 31)) - return; - reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_RLWINM, reg, op->reg, 0, 24, 31); - } else { - reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - if (last_matches_rlwinm_or_exts(op, PC_EXTSB, 0, 0)) - return; - emitpcode(PC_EXTSB, reg, op->reg); - } - break; - case 2: - if (r28) - return; - if (is_unsigned(type)) { - if (last_matches_rlwinm_or_exts(op, PC_RLWINM, 16, 31)) - return; - reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_RLWINM, reg, op->reg, 0, 16, 31); - } else { - if (last_matches_rlwinm_or_exts(op, PC_EXTSH, 0, 0)) - return; - reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_EXTSH, reg, op->reg); - } - break; - default: - CError_FATAL(1389); - } - - op->optype = OpndType_GPR; - op->reg = reg; -} - -void extend64(Operand *op, Type *type, short output_reg, short output_regHi) { - short tmp; - short regHi; - - if (op->optype != OpndType_GPR) - Coerce_to_register(op, type, output_reg); - - regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++; - if (regHi == op->reg) { - tmp = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_MR, tmp, op->reg); - op->reg = tmp; - } - - if (is_unsigned(type)) - load_immediate(regHi, 0); - else - emitpcode(PC_SRAWI, regHi, op->reg, 31); - - op->optype = OpndType_GPRPair; - op->regHi = regHi; -} - -void load_floating_constant(short reg, Type *type, Float *data) { - Object *object; - Object *indObject; - Operand op1; - Operand op2; - Operand op3; - SInt32 offset = 0; - - memclrw(&op1, sizeof(Operand)); - - object = CreateFloatConst(type, data, &offset); - indObject = createIndirect(object, 0, 1); - - if (indObject) { - symbol_operand(&op1, indObject); - indirect(&op1, NULL); - } else { - symbol_operand(&op1, object); - } - - if (offset) { - op2 = op1; - memclrw(&op3, sizeof(Operand)); - op3.optype = OpndType_Absolute; - op3.immediate = offset; - if (op2.optype != OpndType_GPR) - Coerce_to_register(&op2, TYPE(&void_ptr), 0); - combine(&op2, &op3, 0, &op1); - } - - indirect(&op1, NULL); - if (op1.optype != OpndType_FPR) - Coerce_to_fp_register(&op1, type, reg); -} - -void convert_integer_to_floating(Operand *op, Boolean is_single, short output_reg) { - Operand temp_op; - Float d; - int const_reg; - int tmp_reg; - int work_reg; - int result_reg; - Opcode opcode; - - symbol_operand(&temp_op, maketemporary(TYPE(&stdouble))); - coerce_to_addressable(&temp_op); - d.value = *((double *) &int_to_float_cc); - - const_reg = used_virtual_registers[RegClass_FPR]++; - load_floating_constant(const_reg, TYPE(&stdouble), &d); - - tmp_reg = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_XORIS, tmp_reg, op->reg, 0x8000); - load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, low_offset); - - emitpcode(PC_LIS, tmp_reg = used_virtual_registers[RegClass_GPR]++, 0, 0x4330); - load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, high_offset); - - load_store_register(PC_LFD, work_reg = used_virtual_registers[RegClass_FPR]++, temp_op.reg, temp_op.object, 0); - - result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++; - if (is_single != 0) - opcode = PC_FSUBS; - else - opcode = PC_FSUB; - emitpcode(opcode, result_reg, work_reg, const_reg); - - op->optype = OpndType_FPR; - op->reg = result_reg; -} - -void convert_unsigned_to_floating(Operand *op, Boolean is_single, short output_reg) { - Operand temp_op; - Float d; - int const_reg; - int tmp_reg; - int work_reg; - int result_reg; - Opcode opcode; - - symbol_operand(&temp_op, maketemporary(TYPE(&stdouble))); - coerce_to_addressable(&temp_op); - d.value = *((double *) &uns_to_float_cc); - - const_reg = used_virtual_registers[RegClass_FPR]++; - load_floating_constant(const_reg, TYPE(&stdouble), &d); - - load_store_register(PC_STW, op->reg, temp_op.reg, temp_op.object, low_offset); - - emitpcode(PC_LIS, tmp_reg = used_virtual_registers[RegClass_GPR]++, 0, 0x4330); - load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, high_offset); - - load_store_register(PC_LFD, work_reg = used_virtual_registers[RegClass_FPR]++, temp_op.reg, temp_op.object, 0); - - result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++; - if (is_single != 0) - opcode = PC_FSUBS; - else - opcode = PC_FSUB; - emitpcode(opcode, result_reg, work_reg, const_reg); - - op->optype = OpndType_FPR; - op->reg = result_reg; -} - -void convert_floating_to_integer(Operand *op, short output_reg) { - Operand temp_op; - int tmp_reg; - int result_reg; - - symbol_operand(&temp_op, maketemporary(TYPE(&stdouble))); - coerce_to_addressable(&temp_op); - - tmp_reg = used_virtual_registers[RegClass_FPR]++; - emitpcode(PC_FCTIWZ, tmp_reg, op->reg); - load_store_register(PC_STFD, tmp_reg, temp_op.reg, temp_op.object, 0); - - result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - load_store_register(PC_LWZ, result_reg, temp_op.reg, temp_op.object, low_offset); - - op->optype = OpndType_GPR; - op->reg = result_reg; -} - -void convert_floating_to_unsigned(Operand *op, short output_reg) { - static UInt32 used_regs[RegClassMax] = {0, 0, 0, 2, 0}; - - if (op->reg != 1) - emitpcode(PC_FMR, 1, op->reg); - - branch_subroutine(rt_cvt_fp2unsigned, 0, used_regs); - - op->optype = OpndType_GPR; - op->reg = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_MR, op->reg, 3); -} - -void extract_bitfield(Operand *input_op, TypeBitfield *tbitfield, short output_reg, Operand *output_op) { - int r27; - int offset; - int tmp_reg; - int output; - - offset = tbitfield->bitlength; - output = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++; - r27 = tbitfield->offset + (32 - (tbitfield->bitfieldtype->size * 8)); - if (is_unsigned(tbitfield->bitfieldtype)) { - emitpcode(PC_RLWINM, output, input_op->reg, (r27 + offset) & 31, 32 - offset, 31); - } else if (r27 == 0) { - emitpcode(PC_SRAWI, output, input_op->reg, 32 - offset); - } else { - tmp_reg = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_RLWINM, tmp_reg, input_op->reg, r27 & 31, 0, offset); - emitpcode(PC_SRAWI, output, tmp_reg, 32 - offset); - } - - output_op->optype = OpndType_GPR; - output_op->reg = output; -} - -void insert_bitfield(short reg, Operand *op, TypeBitfield *tbitfield) { - int offset = tbitfield->bitlength; - int r7 = tbitfield->offset + (32 - (tbitfield->bitfieldtype->size * 8)); - emitpcode(PC_RLWIMI, op->reg, reg, 32 - (r7 + offset), r7, r7 + offset - 1); -} - -void load_address(short dest_reg, Operand *op) { - coerce_to_addressable(op); - if (op->optype == OpndType_IndirectGPR_ImmOffset) { - if (!op->immOffset && !op->object) { - if (op->reg != dest_reg) - emitpcode(PC_MR, dest_reg, op->reg); - } else { - add_immediate(dest_reg, op->reg, op->object, (SInt16) op->immOffset); - } - } else if (op->optype == OpndType_IndirectGPR_Indexed) { - emitpcode(PC_ADD, dest_reg, op->reg, op->regOffset); - } else { - CError_FATAL(1849); - } -} diff --git a/compiler_and_linker/unsorted/PCodeAssembly.c b/compiler_and_linker/unsorted/PCodeAssembly.c deleted file mode 100644 index 368f8c5..0000000 --- a/compiler_and_linker/unsorted/PCodeAssembly.c +++ /dev/null @@ -1,1613 +0,0 @@ -#include "compiler/PCodeAssembly.h" -#include "compiler/CError.h" -#include "compiler/CFunc.h" -#include "compiler/CMangler.h" -#include "compiler/CParser.h" -#include "compiler/CodeGen.h" -#include "compiler/ObjGenMachO.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" -#include "compiler/PCodeListing.h" -#include "compiler/PPCError.h" -#include "compiler/RegisterInfo.h" -#include "compiler/StackFrame.h" -#include "compiler/TOC.h" -#include "compiler/objects.h" - -static UInt32 codebase; - -static SInt32 pcode_update_mem_labeldiff_imm(PCode *instr, const PCodeArg *op, WeirdOperand *wop) { - SInt32 offset; - Object *object; - UInt8 arg; - - if (op->kind == PCOp_MEMORY) { - object = op->data.mem.obj; - offset = op->data.mem.offset; - switch (object->datatype) { - case DLOCAL: - switch ((UInt8) op->arg) { - case RefType_1: - offset += local_offset_16(object); - break; - case RefType_D: - offset = local_offset_lo(object, offset); - break; - case RefType_C: - offset = local_offset_ha(object, offset); - break; - default: - CError_FATAL(83); - } - break; - case DDATA: - case DFUNC: - case DVFUNC: - case DNONLAZYPTR: - switch ((UInt8) op->arg) { - case RefType_6: - wop->type = MW_RELOC_5_LO16; - break; - case RefType_2: - wop->type = MW_RELOC_3; - break; - case RefType_3: - wop->type = MW_RELOC_4; - break; - case RefType_8: - wop->type = MW_RELOC_7_HA16; - break; - case RefType_7: - wop->type = MW_RELOC_6_HI16; - break; - default: - CError_FATAL(135); - } - - wop->x2 = object; - CError_ASSERT(144, offset == 0); - break; - default: - CError_FATAL(164); - } - } else if (op->kind == PCOp_LABELDIFF) { - arg = op->arg; - - offset = op->data.labeldiff.labelA->block->codeOffset - op->data.labeldiff.labelB->block->codeOffset; - offset += op->data.labeldiff.offset; - if (arg == 1) - offset = -offset; - - if (offset > 0x7FFF) - PPCError_Error(PPCErrorStr109); - else if (offset < -0x8000) - PPCError_Error(PPCErrorStr109); - } else if (op->kind == PCOp_IMMEDIATE) { - offset = op->data.imm.value; - } else { - CError_FATAL(193); - } - - return offset; -} - -UInt32 assemblepcode(PCode *instr, UInt32 offset, WeirdOperand *wop) { - UInt32 bits; - - bits = opcodeinfo[instr->op].insn; - wop->type = -1; - wop->x6 = 0; - - switch (instr->op) { - case PC_BL: { - int flag = PCODE_FLAG_SET_T(instr) & fAbsolute; - if (instr->args[0].kind == PCOp_MEMORY) { - bits |= instr->args[0].data.mem.offset & 0x3FFFFFC; - wop->type = MW_RELOC_2_BR24; - wop->x2 = instr->args[0].data.mem.obj; - if (flag == 0) - wop->type = MW_RELOC_2_BR24; - else - CError_FATAL(246); - } else if (instr->args[0].kind == PCOp_IMMEDIATE) { - bits |= instr->args[0].data.imm.value & 0x3FFFFFC; - if (flag) - bits |= 2; - } else { - bits |= (instr->args[0].data.label.label->block->codeOffset - offset) & 0x3FFFFFC; - if (flag) - CError_FATAL(261); - } - break; - } - - case PC_B: { - int flag = PCODE_FLAG_SET_T(instr) & fAbsolute; - if (instr->args[0].kind == PCOp_MEMORY) { - bits |= instr->args[0].data.mem.offset & 0x3FFFFFC; - wop->x2 = instr->args[0].data.mem.obj; - if (flag == 0) - wop->type = MW_RELOC_2_BR24; - else - CError_FATAL(288); - } else if (instr->args[0].kind == PCOp_IMMEDIATE) { - bits |= instr->args[0].data.imm.value & 0x3FFFFFC; - if (flag) - bits |= 2; - } else { - bits |= (instr->args[0].data.label.label->block->codeOffset - offset) & 0x3FFFFFC; - if (flag) - CError_FATAL(302); - } - if (PCODE_FLAG_SET_T(instr) & fLink) - bits |= 1; - break; - } - - case PC_BDNZ: - case PC_BDZ: { - int flag = PCODE_FLAG_SET_T(instr) & fAbsolute; - if (instr->args[0].kind == PCOp_MEMORY) { - bits |= instr->args[0].data.mem.offset & 0xFFFC; - wop->x2 = instr->args[0].data.mem.obj; - if (flag == 0) - wop->type = MW_RELOC_8; - else - CError_FATAL(333); - } else { - SInt32 value; - if (instr->args[0].kind == PCOp_IMMEDIATE) - value = instr->args[0].data.imm.value; - else - value = instr->args[0].data.label.label->block->codeOffset - offset; - - bits |= value & 0xFFFF; - if (value < 0) { - if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken) - bits |= 0x200000u; - } else { - if (PCODE_FLAG_SET_T(instr) & fBranchTaken) - bits |= 0x200000u; - } - } - if (PCODE_FLAG_SET_T(instr) & fLink) - bits |= 1; - break; - } - - case PC_BC: { - int flag = PCODE_FLAG_SET_T(instr) & fAbsolute; - bits |= (instr->args[0].data.imm.value & 31) << 21; - bits |= ((instr->args[1].data.reg.reg * 4 + instr->args[2].data.imm.value) & 31) << 16; - - if (instr->args[3].kind == PCOp_MEMORY) { - bits |= instr->args[3].data.mem.offset & 0xFFFC; - wop->x2 = instr->args[3].data.mem.obj; - if (flag == 0) - wop->type = MW_RELOC_8; - else - CError_FATAL(387); - } else { - SInt32 value; - if (instr->args[3].kind == PCOp_IMMEDIATE) - value = instr->args[3].data.imm.value; - else - value = instr->args[3].data.label.label->block->codeOffset - offset; - - bits |= value & 0xFFFF; - if (value < 0) { - if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken) - bits |= 0x200000u; - } else { - if (PCODE_FLAG_SET_T(instr) & fBranchTaken) - bits |= 0x200000u; - } - } - if (PCODE_FLAG_SET_T(instr) & fLink) - bits |= 1; - break; - } - - case PC_BT: - case PC_BF: - case PC_BDNZT: - case PC_BDNZF: - case PC_BDZT: - case PC_BDZF: { - int flag = PCODE_FLAG_SET_T(instr) & fAbsolute; - bits |= ((instr->args[0].data.reg.reg * 4 + instr->args[1].data.imm.value) & 31) << 16; - - if (instr->args[2].kind == PCOp_MEMORY) { - bits |= instr->args[2].data.mem.offset & 0xFFFC; - wop->x2 = instr->args[2].data.mem.obj; - if (flag == 0) - wop->type = MW_RELOC_8; - else - CError_FATAL(446); - } else { - SInt32 value; - if (instr->args[2].kind == PCOp_IMMEDIATE) { - value = instr->args[2].data.imm.value; - if (flag) - bits |= 2; - } else { - value = instr->args[2].data.label.label->block->codeOffset - offset; - CError_ASSERT(458, !flag); - } - - bits |= value & 0xFFFF; - - if (value < 0) { - if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken) - bits |= 0x200000u; - } else { - if (PCODE_FLAG_SET_T(instr) & fBranchTaken) - bits |= 0x200000u; - } - } - - if (PCODE_FLAG_SET_T(instr) & fLink) - bits |= 1; - break; - } - - case PC_BTLR: - case PC_BTCTR: - case PC_BFLR: - case PC_BFCTR: - bits |= ((instr->args[0].data.reg.reg * 4 + instr->args[1].data.imm.value) & 31) << 16; - if (PCODE_FLAG_SET_T(instr) & fLink) - bits |= 1; - if (PCODE_FLAG_SET_T(instr) & fBranchTaken) - bits |= 0x200000u; - break; - - case PC_BCLR: - case PC_BCCTR: - bits |= instr->args[0].data.imm.value << 21; - bits |= ((instr->args[1].data.reg.reg * 4 + instr->args[2].data.imm.value) & 31) << 16; - case PC_BLR: - case PC_BCTR: - case PC_BCTRL: - case PC_BLRL: - if (PCODE_FLAG_SET_T(instr) & fLink) - bits |= 1; - if (PCODE_FLAG_SET_T(instr) & fBranchTaken) - bits |= 0x200000u; - break; - - case PC_CRAND: - case PC_CRANDC: - case PC_CREQV: - case PC_CRNAND: - case PC_CRNOR: - case PC_CROR: - case PC_CRORC: - case PC_CRXOR: - bits |= ((instr->args[0].data.reg.reg * 4 + instr->args[1].data.imm.value) & 31) << 21; - bits |= ((instr->args[2].data.reg.reg * 4 + instr->args[3].data.imm.value) & 31) << 16; - bits |= ((instr->args[4].data.reg.reg * 4 + instr->args[5].data.imm.value) & 31) << 11; - break; - - case PC_MCRF: - bits |= instr->args[0].data.reg.reg << 23; - bits |= instr->args[1].data.reg.reg << 18; - break; - - case PC_LBZ: - case PC_LBZU: - case PC_LHZ: - case PC_LHZU: - case PC_LHA: - case PC_LHAU: - case PC_LWZ: - case PC_LWZU: - case PC_LMW: - case PC_STB: - case PC_STBU: - case PC_STH: - case PC_STHU: - case PC_STW: - case PC_STWU: - case PC_STMW: - case PC_LFS: - case PC_LFSU: - case PC_LFD: - case PC_LFDU: - case PC_STFS: - case PC_STFSU: - case PC_STFD: - case PC_STFDU: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF; - break; - - case PC_LBZX: - case PC_LBZUX: - case PC_LHZX: - case PC_LHZUX: - case PC_LHAX: - case PC_LHAUX: - case PC_LHBRX: - case PC_LWZX: - case PC_LWZUX: - case PC_LWBRX: - case PC_STBX: - case PC_STBUX: - case PC_STHX: - case PC_STHUX: - case PC_STHBRX: - case PC_STWX: - case PC_STWUX: - case PC_STWBRX: - case PC_LFSX: - case PC_LFSUX: - case PC_LFDX: - case PC_LFDUX: - case PC_STFSX: - case PC_STFSUX: - case PC_STFDX: - case PC_STFDUX: - case PC_LWARX: - case PC_LSWX: - case PC_STFIWX: - case PC_STSWX: - case PC_STWCX: - case PC_ECIWX: - case PC_ECOWX: - case PC_DCREAD: - case PC_TLBSX: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[2].data.reg.reg << 11; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_DCBF: - case PC_DCBST: - case PC_DCBT: - case PC_DCBTST: - case PC_DCBZ: - case PC_DCBI: - case PC_ICBI: - case PC_DCCCI: - case PC_ICBT: - case PC_ICCCI: - case PC_ICREAD: - case PC_DCBA: - bits |= instr->args[0].data.reg.reg << 16; - bits |= instr->args[1].data.reg.reg << 11; - break; - - case PC_ADD: - case PC_ADDC: - case PC_ADDE: - case PC_DIVW: - case PC_DIVWU: - case PC_MULHW: - case PC_MULHWU: - case PC_MULLW: - case PC_SUBF: - case PC_SUBFC: - case PC_SUBFE: - bits |= instr->args[2].data.reg.reg << 11; - case PC_ADDME: - case PC_ADDZE: - case PC_NEG: - case PC_SUBFME: - case PC_SUBFZE: - case PC_MFROM: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - if (PCODE_FLAG_SET_F(instr) & fOverflow) - bits |= 0x400; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_ADDI: - case PC_ADDIC: - case PC_ADDICR: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF; - break; - - case PC_ADDIS: - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[0].data.reg.reg << 21; - bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF; - break; - - case PC_MULLI: - case PC_SUBFIC: - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[2].data.imm.value & 0xFFFF; - break; - - case PC_LI: - case PC_LIS: - bits |= instr->args[0].data.reg.reg << 21; - bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[1], wop) & 0xFFFF; - break; - - case PC_ANDI: - case PC_ANDIS: - case PC_ORI: - case PC_ORIS: - case PC_XORI: - case PC_XORIS: - bits |= instr->args[0].data.reg.reg << 16; - bits |= instr->args[1].data.reg.reg << 21; - bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF; - break; - - case PC_AND: - case PC_OR: - case PC_XOR: - case PC_NAND: - case PC_NOR: - case PC_EQV: - case PC_ANDC: - case PC_ORC: - case PC_SLW: - case PC_SRW: - case PC_SRAW: - bits |= instr->args[0].data.reg.reg << 16; - bits |= instr->args[1].data.reg.reg << 21; - bits |= instr->args[2].data.reg.reg << 11; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_EXTSH: - case PC_EXTSB: - case PC_CNTLZW: - bits |= instr->args[0].data.reg.reg << 16; - bits |= instr->args[1].data.reg.reg << 21; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_MR: - bits |= instr->args[0].data.reg.reg << 16; - bits |= instr->args[1].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 11; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_NOT: - bits |= instr->args[0].data.reg.reg << 16; - bits |= instr->args[1].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 11; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_SRAWI: - bits |= instr->args[0].data.reg.reg << 16; - bits |= instr->args[1].data.reg.reg << 21; - bits |= (instr->args[2].data.imm.value & 31) << 11; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_RLWINM: - case PC_RLWIMI: - bits |= instr->args[0].data.reg.reg << 16; - bits |= instr->args[1].data.reg.reg << 21; - bits |= (instr->args[2].data.imm.value & 31) << 11; - bits |= (instr->args[3].data.imm.value & 31) << 6; - bits |= (instr->args[4].data.imm.value & 31) << 1; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_RLWNM: - bits |= instr->args[0].data.reg.reg << 16; - bits |= instr->args[1].data.reg.reg << 21; - bits |= instr->args[2].data.reg.reg << 11; - bits |= (instr->args[3].data.imm.value & 31) << 6; - bits |= (instr->args[4].data.imm.value & 31) << 1; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_CMP: - case PC_CMPL: - bits |= instr->args[0].data.reg.reg << 23; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[2].data.reg.reg << 11; - break; - - case PC_CMPI: - case PC_CMPLI: - bits |= instr->args[0].data.reg.reg << 23; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[2].data.imm.value & 0xFFFF; - break; - - case PC_MTXER: - case PC_MTCTR: - case PC_MTLR: - case PC_MTMSR: - case PC_MFMSR: - case PC_MFXER: - case PC_MFCTR: - case PC_MFLR: - case PC_MFCR: - bits |= instr->args[0].data.reg.reg << 21; - break; - - case PC_MFFS: - bits |= instr->args[0].data.reg.reg << 21; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_MTCRF: - bits |= instr->args[0].data.imm.value << 12; - bits |= instr->args[1].data.reg.reg << 21; - break; - - case PC_MTFSF: - bits |= (instr->args[0].data.imm.value & 0xFF) << 17; - bits |= instr->args[1].data.reg.reg << 11; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_FMR: - case PC_FABS: - case PC_FNEG: - case PC_FNABS: - case PC_FRES: - case PC_FRSQRTE: - case PC_FRSP: - case PC_FCTIW: - case PC_FCTIWZ: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 11; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_FADD: - case PC_FADDS: - case PC_FSUB: - case PC_FSUBS: - case PC_FDIV: - case PC_FDIVS: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[2].data.reg.reg << 11; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_FMADD: - case PC_FMADDS: - case PC_FMSUB: - case PC_FMSUBS: - case PC_FNMADD: - case PC_FNMADDS: - case PC_FNMSUB: - case PC_FNMSUBS: - case PC_FSEL: - bits |= instr->args[3].data.reg.reg << 11; - case PC_FMUL: - case PC_FMULS: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[2].data.reg.reg << 6; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_FCMPU: - case PC_FCMPO: - bits |= instr->args[0].data.reg.reg << 23; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[2].data.reg.reg << 11; - break; - - case PC_MTSPR: - if (instr->args[0].kind == PCOp_REGISTER) { - CError_ASSERT(1027, instr->args[0].arg == RegClass_SPR); - CError_ASSERT(1028, instr->args[0].data.reg.reg < 4); - bits |= ((spr_to_sysreg[instr->args[0].data.reg.reg] & 0x1F) << 16) + - ((spr_to_sysreg[instr->args[0].data.reg.reg] & 0x3E0) << 6); - } else if (instr->args[0].kind == PCOp_SYSREG && instr->args[0].arg == 0) { - bits |= ((instr->args[0].data.reg.reg & 0x1F) << 16) + - ((instr->args[0].data.reg.reg & 0x3E0) << 6); - } else { - CError_FATAL(1033); - } - - bits |= instr->args[1].data.reg.reg << 21; - break; - - case PC_MTDCR: - if (instr->args[0].kind == PCOp_IMMEDIATE) { - bits |= ((instr->args[0].data.imm.value & 0x1F) << 16) + - ((instr->args[0].data.imm.value & 0x3E0) << 6); - } else { - CError_FATAL(1042); - } - - bits |= instr->args[1].data.reg.reg << 21; - break; - - case PC_MFSPR: - bits |= instr->args[0].data.reg.reg << 21; - - if (instr->args[1].kind == PCOp_REGISTER && instr->args[1].arg == RegClass_SPR) { - CError_ASSERT(1055, instr->args[1].data.reg.reg < 4); - bits |= ((spr_to_sysreg[instr->args[1].data.reg.reg] & 0x1F) << 16) + - ((spr_to_sysreg[instr->args[1].data.reg.reg] & 0x3E0) << 6); - } else if (instr->args[1].kind == PCOp_SYSREG && instr->args[1].arg == 0) { - bits |= ((instr->args[1].data.reg.reg & 0x1F) << 16) + - ((instr->args[1].data.reg.reg & 0x3E0) << 6); - } else { - CError_FATAL(1060); - } - break; - - case PC_MFDCR: - bits |= instr->args[0].data.reg.reg << 21; - - if (instr->args[1].kind == PCOp_IMMEDIATE) { - bits |= ((instr->args[1].data.imm.value & 0x1F) << 16) + - ((instr->args[1].data.imm.value & 0x3E0) << 6); - } else { - CError_FATAL(1069); - } - break; - - case PC_LSWI: - case PC_STSWI: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= (instr->args[2].data.imm.value & 31) << 11; - break; - - case PC_MCRFS: - bits |= (instr->args[1].data.imm.value & 7) << 18; - case PC_MCRXR: - bits |= instr->args[0].data.reg.reg << 23; - break; - - case PC_MFTB: - bits |= instr->args[0].data.reg.reg << 21; - if (instr->args[1].kind == PCOp_SYSREG && instr->args[1].arg == 0) { - if (instr->args[1].data.reg.reg == 284) - bits |= 0xC4000u; - else if (instr->args[1].data.reg.reg == 285) - bits |= 0xD4000u; - else - CError_FATAL(1100); - } else { - CError_FATAL(1103); - } - break; - - case PC_MTSR: - bits |= instr->args[1].data.reg.reg << 21; - bits |= (instr->args[0].data.imm.value & 15) << 16; - break; - - case PC_MFSR: - bits |= instr->args[0].data.reg.reg << 21; - bits |= (instr->args[1].data.imm.value & 15) << 16; - break; - - case PC_MFSRIN: - case PC_MTSRIN: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 11; - break; - - case PC_MTFSB0: - case PC_MTFSB1: - bits |= (instr->args[0].data.imm.value & 31) << 21; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_MTFSFI: - bits |= instr->args[0].data.reg.reg << 23; - bits |= (instr->args[1].data.imm.value & 15) << 12; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_FSQRT: - case PC_FSQRTS: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 11; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_TLBIE: - case PC_TLBLD: - case PC_TLBLI: - bits |= instr->args[0].data.reg.reg << 11; - break; - - case PC_TW: - bits |= (instr->args[0].data.imm.value & 31) << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[2].data.reg.reg << 11; - break; - - case PC_TWI: - bits |= (instr->args[0].data.imm.value & 31) << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[2].data.imm.value & 0xFFFF; - break; - - case PC_OPWORD: - CError_ASSERT(1176, instr->args[0].kind != PCOp_MEMORY); - bits = pcode_update_mem_labeldiff_imm(instr, &instr->args[0], wop); - break; - - case PC_MASKG: - case PC_MASKIR: - bits |= instr->args[1].data.reg.reg << 21; - bits |= instr->args[0].data.reg.reg << 16; - bits |= instr->args[2].data.reg.reg << 11; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_LSCBX: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[2].data.reg.reg << 11; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_DIV: - case PC_DIVS: - case PC_DOZ: - case PC_MUL: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[2].data.reg.reg << 11; - if (PCODE_FLAG_SET_F(instr) & fOverflow) - bits |= 0x400; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_NABS: - case PC_ABS: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - if (PCODE_FLAG_SET_F(instr) & fOverflow) - bits |= 0x400; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_CLCS: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_DOZI: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[2].data.imm.value & 0xFFFF; - break; - - case PC_RLMI: - bits |= instr->args[1].data.reg.reg << 21; - bits |= instr->args[0].data.reg.reg << 16; - bits |= instr->args[2].data.reg.reg << 11; - bits |= (instr->args[3].data.imm.value & 31) << 6; - bits |= (instr->args[4].data.imm.value & 31) << 1; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_SLE: - case PC_SLEQ: - case PC_SLLQ: - case PC_SLQ: - case PC_SRAQ: - case PC_SRE: - case PC_SREA: - case PC_SREQ: - case PC_SRLQ: - case PC_SRQ: - case PC_RRIB: - bits |= instr->args[1].data.reg.reg << 21; - bits |= instr->args[0].data.reg.reg << 16; - bits |= instr->args[2].data.reg.reg << 11; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_SLIQ: - case PC_SLLIQ: - case PC_SRAIQ: - case PC_SRIQ: - case PC_SRLIQ: - bits |= instr->args[1].data.reg.reg << 21; - bits |= instr->args[0].data.reg.reg << 16; - bits |= (instr->args[2].data.imm.value & 31) << 11; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 1; - break; - - case PC_TLBRE: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= (instr->args[2].data.imm.value & 1) << 11; - break; - - case PC_TLBWE: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= (instr->args[2].data.imm.value & 1) << 11; - break; - - case PC_WRTEE: - bits |= instr->args[0].data.reg.reg << 21; - break; - - case PC_WRTEEI: - bits |= instr->args[0].data.imm.value << 15; - break; - - case PC_DSTT: - case PC_DSTSTT: - bits |= 0x2000000u; - bits |= instr->args[0].data.reg.reg << 16; - bits |= instr->args[1].data.reg.reg << 11; - bits |= (instr->args[2].data.imm.value & 3) << 21; - break; - - case PC_DST: - case PC_DSTST: - bits |= (instr->args[3].data.imm.value & 1) << 25; - bits |= instr->args[0].data.reg.reg << 16; - bits |= instr->args[1].data.reg.reg << 11; - bits |= (instr->args[2].data.imm.value & 3) << 21; - break; - - case PC_DSSALL: - bits |= 0x2000000u; - break; - - case PC_DSS: - bits |= (instr->args[1].data.imm.value & 1) << 25; - bits |= (instr->args[0].data.imm.value & 3) << 21; - break; - - case PC_LVEBX: - case PC_LVEHX: - case PC_LVEWX: - case PC_LVSL: - case PC_LVSR: - case PC_LVX: - case PC_LVXL: - case PC_STVEBX: - case PC_STVEHX: - case PC_STVEWX: - case PC_STVX: - case PC_STVXL: - case PC_VADDCUW: - case PC_VADDFP: - case PC_VADDSBS: - case PC_VADDSHS: - case PC_VADDSWS: - case PC_VADDUBM: - case PC_VADDUBS: - case PC_VADDUHM: - case PC_VADDUHS: - case PC_VADDUWM: - case PC_VADDUWS: - case PC_VAND: - case PC_VANDC: - case PC_VAVGSB: - case PC_VAVGSH: - case PC_VAVGSW: - case PC_VAVGUB: - case PC_VAVGUH: - case PC_VAVGUW: - case PC_VMAXFP: - case PC_VMAXSB: - case PC_VMAXSH: - case PC_VMAXSW: - case PC_VMAXUB: - case PC_VMAXUH: - case PC_VMAXUW: - case PC_VMINFP: - case PC_VMINSB: - case PC_VMINSH: - case PC_VMINSW: - case PC_VMINUB: - case PC_VMINUH: - case PC_VMINUW: - case PC_VMRGHB: - case PC_VMRGHH: - case PC_VMRGHW: - case PC_VMRGLB: - case PC_VMRGLH: - case PC_VMRGLW: - case PC_VMULESB: - case PC_VMULESH: - case PC_VMULEUB: - case PC_VMULEUH: - case PC_VMULOSB: - case PC_VMULOSH: - case PC_VMULOUB: - case PC_VMULOUH: - case PC_VNOR: - case PC_VOR: - case PC_VPKPX: - case PC_VPKSHSS: - case PC_VPKSHUS: - case PC_VPKSWSS: - case PC_VPKSWUS: - case PC_VPKUHUM: - case PC_VPKUHUS: - case PC_VPKUWUM: - case PC_VPKUWUS: - case PC_VRLB: - case PC_VRLH: - case PC_VRLW: - case PC_VSL: - case PC_VSLB: - case PC_VSLH: - case PC_VSLO: - case PC_VSLW: - case PC_VSR: - case PC_VSRAB: - case PC_VSRAH: - case PC_VSRAW: - case PC_VSRB: - case PC_VSRH: - case PC_VSRO: - case PC_VSRW: - case PC_VSUBCUW: - case PC_VSUBFP: - case PC_VSUBSBS: - case PC_VSUBSHS: - case PC_VSUBSWS: - case PC_VSUBUBM: - case PC_VSUBUBS: - case PC_VSUBUHM: - case PC_VSUBUHS: - case PC_VSUBUWM: - case PC_VSUBUWS: - case PC_VSUMSWS: - case PC_VSUM2SWS: - case PC_VSUM4SBS: - case PC_VSUM4SHS: - case PC_VSUM4UBS: - case PC_VXOR: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[2].data.reg.reg << 11; - break; - - case PC_VCFSX: - case PC_VCFUX: - case PC_VCTSXS: - case PC_VCTUXS: - case PC_VSPLTB: - case PC_VSPLTH: - case PC_VSPLTW: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 11; - bits |= (instr->args[2].data.imm.value & 31) << 16; - break; - - case PC_VEXPTEFP: - case PC_VLOGEFP: - case PC_VREFP: - case PC_VRFIM: - case PC_VRFIN: - case PC_VRFIP: - case PC_VRFIZ: - case PC_VRSQRTEFP: - case PC_VUPKHPX: - case PC_VUPKHSB: - case PC_VUPKHSH: - case PC_VUPKLPX: - case PC_VUPKLSB: - case PC_VUPKLSH: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 11; - break; - - case PC_VCMPBFP: - case PC_VCMPEQFP: - case PC_VCMPEQUB: - case PC_VCMPEQUH: - case PC_VCMPEQUW: - case PC_VCMPGEFP: - case PC_VCMPGTFP: - case PC_VCMPGTSB: - case PC_VCMPGTSH: - case PC_VCMPGTSW: - case PC_VCMPGTUB: - case PC_VCMPGTUH: - case PC_VCMPGTUW: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[2].data.reg.reg << 11; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - bits |= 0x400; - break; - - case PC_VSPLTISB: - case PC_VSPLTISH: - case PC_VSPLTISW: - bits |= instr->args[0].data.reg.reg << 21; - bits |= (instr->args[1].data.imm.value & 31) << 16; - break; - - case PC_VMHADDSHS: - case PC_VMHRADDSHS: - case PC_VMLADDUHM: - case PC_VMSUMMBM: - case PC_VMSUMSHM: - case PC_VMSUMSHS: - case PC_VMSUMUBM: - case PC_VMSUMUHM: - case PC_VMSUMUHS: - case PC_VPERM: - case PC_VSEL: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[2].data.reg.reg << 11; - bits |= instr->args[3].data.reg.reg << 6; - break; - - case PC_VMADDFP: - case PC_VNMSUBFP: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[2].data.reg.reg << 6; - bits |= instr->args[3].data.reg.reg << 11; - break; - - case PC_VSLDOI: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[2].data.reg.reg << 11; - bits |= (instr->args[3].data.imm.value & 15) << 6; - break; - - case PC_VMR: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[1].data.reg.reg << 11; - break; - - case PC_VMRP: - bits |= instr->args[0].data.reg.reg << 21; - bits |= instr->args[1].data.reg.reg << 16; - bits |= instr->args[1].data.reg.reg << 11; - break; - - case PC_MFVSCR: - bits |= instr->args[0].data.reg.reg << 21; - break; - - case PC_MTVSCR: - bits |= instr->args[0].data.reg.reg << 11; - break; - - case PC_EIEIO: - case PC_ISYNC: - case PC_SYNC: - case PC_RFI: - case PC_NOP: - case PC_SC: - case PC_TLBIA: - case PC_TLBSYNC: - case PC_TRAP: - case PC_DSA: - case PC_ESA: - case PC_RFCI: - break; - - default: - CError_FATAL(2203); - } - - return CTool_EndianConvertWord32(bits); -} - -static PCode *targetinstruction(PCodeLabel *label) { - PCodeBlock *block = label->block; - while (block->pcodeCount == 0) - block = block->nextBlock; - return block->firstPCode; -} - -static void invertybit(PCode *instr, SInt32 value) { - if (instr->op == PC_BC) { - if (instr->args[0].data.imm.value & 1) { - if (value < 0) - instr->flags |= fBranchNotTaken; - else - instr->flags |= fBranchTaken; - } - } else if (instr->op == PC_BCCTR || instr->op == PC_BCLR) { - if (instr->args[0].data.imm.value & 1) - instr->flags |= fBranchTaken; - } - - if (PCODE_FLAG_SET_T(instr) & fBranchTaken) - instr->flags = (instr->flags & ~fBranchTaken) | fBranchNotTaken; - else if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken) - instr->flags = (instr->flags & ~fBranchNotTaken) | fBranchTaken; - else if (value < 0) - instr->flags = (instr->flags & ~fBranchTaken) | fBranchNotTaken; - else - instr->flags = (instr->flags & ~fBranchNotTaken) | fBranchTaken; -} - -static void insertlongbranches(SInt32 mask) { - PCodeBlock *block; - PCodeLabel *label; - SInt32 i; - - i = 0; - for (block = pcbasicblocks; block; block = block->nextBlock) { - block->codeOffset = i; - if (block->pcodeCount) { - i += block->pcodeCount * 4; - if (block->pcodeCount && (block->lastPCode->flags & fIsBranch)) - i += 4; - } - } - - for (block = pcbasicblocks; block; block = block->nextBlock) { - if (block->pcodeCount && (block->lastPCode->flags & fIsBranch)) { - switch (block->lastPCode->op) { - case PC_BT: - case PC_BF: - i = block->codeOffset + ((block->pcodeCount - 1) * 4); - if (block->lastPCode->args[2].kind == PCOp_LABEL) { - label = block->lastPCode->args[2].data.label.label; - i = label->block->codeOffset - i; - if (i != ((SInt16) (i & mask))) { - block->lastPCode->op = (block->lastPCode->op == PC_BT) ? PC_BF : PC_BT; - block->lastPCode->args[2].data.label.label = block->nextBlock->labels; - invertybit(block->lastPCode, i); - appendpcode(block, makepcode(PC_B, label)); - } - } - break; - - case PC_BC: - i = block->codeOffset + ((block->pcodeCount - 1) * 4); - if (block->lastPCode->args[3].kind == PCOp_LABEL) { - label = block->lastPCode->args[3].data.label.label; - i = label->block->codeOffset - i; - invertybit(block->lastPCode, i); - if (i != ((SInt16) (i & mask))) { - switch (block->lastPCode->args[0].data.imm.value & 30) { - case 0: - case 2: - case 8: - case 10: - block->lastPCode->args[0].data.imm.value ^= 11; - block->lastPCode->args[3].data.label.label = block->nextBlock->labels; - break; - case 16: - case 18: - block->lastPCode->args[0].data.imm.value ^= 3; - block->lastPCode->args[3].data.label.label = block->nextBlock->labels; - break; - case 4: - case 12: - block->lastPCode->args[0].data.imm.value ^= 9; - block->lastPCode->args[3].data.label.label = block->nextBlock->labels; - break; - case 20: - deletepcode(block->lastPCode); - break; - default: - CError_FATAL(2368); - } - - appendpcode(block, makepcode(PC_B, label)); - } - } - break; - - case PC_BDNZ: - case PC_BDZ: - i = block->codeOffset + ((block->pcodeCount - 1) * 4); - if (block->lastPCode->args[0].kind == PCOp_LABEL) { - label = block->lastPCode->args[0].data.label.label; - i = label->block->codeOffset - i; - if (i != ((SInt16) (i & mask))) { - switch (block->lastPCode->op) { - case PC_BDZ: - block->lastPCode->op = PC_BDNZ; - break; - case PC_BDNZ: - block->lastPCode->op = PC_BDZ; - break; - default: - CError_FATAL(2389); - } - - block->lastPCode->args[0].data.label.label = block->nextBlock->labels; - invertybit(block->lastPCode, i); - appendpcode(block, makepcode(PC_B, label)); - } - } - break; - - case PC_BDNZT: - case PC_BDNZF: - case PC_BDZT: - case PC_BDZF: - i = block->codeOffset + ((block->pcodeCount - 1) * 4); - if (block->lastPCode->args[2].kind == PCOp_LABEL) { - label = block->lastPCode->args[2].data.label.label; - i = label->block->codeOffset - i; - if (i != ((SInt16) (i & mask))) { - switch (block->lastPCode->op) { - case PC_BDNZT: - block->lastPCode->op = PC_BDZF; - break; - case PC_BDNZF: - block->lastPCode->op = PC_BDZT; - break; - case PC_BDZT: - block->lastPCode->op = PC_BDNZF; - break; - case PC_BDZF: - block->lastPCode->op = PC_BDNZT; - break; - default: - CError_FATAL(2420); - } - - block->lastPCode->args[2].data.label.label = block->nextBlock->labels; - invertybit(block->lastPCode, i); - appendpcode(block, makepcode(PC_B, label)); - } - } - break; - - } - } - } -} - -SInt32 optimizefinalbranches(SInt32 codesize) { - PCodeBlock *block; - PCode *instr; - SInt32 offset; - int changed; - int deleted; - PCodeLabel *label; - PCode *target; - - do { - changed = deleted = 0; - - for (block = pcbasicblocks; block; block = block->nextBlock) { - if (block->pcodeCount == 0) - continue; - - instr = block->lastPCode; - if (!(instr->flags & fIsBranch)) - continue; - - offset = block->codeOffset + (block->pcodeCount - 1) * 4; - - if (instr->op == PC_B && instr->args[0].kind == PCOp_LABEL) { - label = instr->args[0].data.label.label; - target = targetinstruction(label); - - if (label->block->codeOffset == (offset + 4)) { - deletepcode(instr); - changed = deleted = 1; - } else if (target->op == PC_B) { - if (target->args[0].kind == PCOp_LABEL && target->args[0].data.label.label != instr->args[0].data.label.label) { - instr->args[0].data.label.label = target->args[0].data.label.label; - changed = 1; - } - } else if (target->op == PC_BLR) { - instr->op = PC_BLR; - changed = 1; - } - continue; - } - - if ((instr->op == PC_BT || instr->op == PC_BF) && instr->args[2].kind == PCOp_LABEL) { - PCodeBlock *block2 = instr->block; - label = instr->args[2].data.label.label; - target = targetinstruction(label); - - if (label->block->codeOffset == (offset + 4)) { - deletepcode(instr); - changed = deleted = 1; - } else if (target->op == PC_B) { - if (target->args[0].kind == PCOp_LABEL && target->args[0].data.label.label != instr->args[2].data.label.label) { - instr->args[2].data.label.label = target->args[0].data.label.label; - changed = 1; - } - } else if (copts.opt_bcc_lr_ctr) { - if (target->op == PC_BLR) { - if (instr->op == PC_BT) - instr->op = PC_BTLR; - else - instr->op = PC_BFLR; - instr->argCount = 2; - changed = 1; - } else if (target->op == PC_BCTR) { - if (instr->op == PC_BT) - instr->op = PC_BTCTR; - else - instr->op = PC_BFCTR; - instr->argCount = 2; - changed = 1; - } else if ( - block2->nextBlock && - block2->nextBlock->firstPCode && - block2->nextBlock->firstPCode->op == PC_BLR && - label->block->codeOffset == (offset + 8) - ) { - if ( - block2->nextBlock->predecessors && - block2->nextBlock->predecessors->block == block2 && - !block2->nextBlock->predecessors->nextLink - ) { - if (instr->op == PC_BT) - instr->op = PC_BFLR; - else - instr->op = PC_BTLR; - change_num_operands(instr, 2); - deletepcode(block2->nextBlock->firstPCode); - changed = deleted = 1; - } - } else if ( - block2->nextBlock && - block2->nextBlock->firstPCode && - block2->nextBlock->firstPCode->op == PC_BCTR && - label->block->codeOffset == (offset + 8) - ) { - if ( - block2->nextBlock->predecessors && - block2->nextBlock->predecessors->block == block2 && - !block2->nextBlock->predecessors->nextLink - ) { - if (instr->op == PC_BT) - instr->op = PC_BFCTR; - else - instr->op = PC_BTCTR; - change_num_operands(instr, 2); - deletepcode(block2->nextBlock->firstPCode); - changed = deleted = 1; - } - } - } - continue; - } - - if ( - instr->op == PC_BC && - instr->args[3].kind == PCOp_LABEL && - !(PCODE_FLAG_SET_T(instr) & (fSideEffects | fLink)) - ) - { - PCodeBlock *block2 = instr->block; - label = instr->args[3].data.label.label; - target = targetinstruction(label); - - if (label->block->codeOffset == (offset + 4)) { - deletepcode(instr); - changed = deleted = 1; - } else if (target->op == PC_B) { - if (target->args[0].kind == PCOp_LABEL && target->args[0].data.label.label != instr->args[3].data.label.label) { - instr->args[3].data.label.label = target->args[0].data.label.label; - changed = 1; - } - } else if (copts.opt_bcc_lr_ctr) { - if (target->op == PC_BLR) { - instr->op = PC_BCLR; - instr->argCount = 3; - changed = 1; - } else if (target->op == PC_BCTR) { - instr->op = PC_BCCTR; - instr->argCount = 3; - changed = 1; - } else if ( - block2->nextBlock && - block2->nextBlock->firstPCode && - block2->nextBlock->firstPCode->op == PC_BLR && - label->block->codeOffset == (offset + 8) - ) { - SInt32 val = instr->args[0].data.imm.value & 30; - if ( - block2->nextBlock->predecessors && - block2->nextBlock->predecessors->block == block2 && - !block2->nextBlock->predecessors->nextLink - ) { - if ((val & 30) == 4) - instr->args[0].data.imm.value = val | 12; - else if ((val & 30) == 12) - instr->args[0].data.imm.value = val & 23; - instr->op = PC_BCLR; - instr->argCount = 3; - deletepcode(block2->nextBlock->firstPCode); - changed = deleted = 1; - } - } else if ( - block2->nextBlock && - block2->nextBlock->firstPCode && - block2->nextBlock->firstPCode->op == PC_BCTR && - label->block->codeOffset == (offset + 8) - ) { - SInt32 val = instr->args[0].data.imm.value & 30; - if ( - block2->nextBlock->predecessors && - block2->nextBlock->predecessors->block == block2 && - !block2->nextBlock->predecessors->nextLink - ) { - if ((val & 30) == 4) - instr->args[0].data.imm.value = val | 12; - else if ((val & 30) == 12) - instr->args[0].data.imm.value = val & 23; - instr->op = PC_BCCTR; - instr->argCount = 3; - deletepcode(block2->nextBlock->firstPCode); - changed = deleted = 1; - } - } - } - } - } - - if (deleted) - codesize = pccomputeoffsets(); - } while (changed); - - return codesize; -} - -static SInt32 insert_align_nops(Object *func, SInt32 codesize) { - PCodeBlock *block; - int changed; - PCodeBlock *prev; - - do { - changed = 0; - - for (block = pcbasicblocks; block; block = block->nextBlock) { - if ( - (block->flags & fPCBlockFlag6000) == fPCBlockFlag2000 && - (block->codeOffset & 7) && - block->pcodeCount < 8 && - (prev = block->prevBlock) && - !(prev->flags & fPCBlockFlag2000) - ) - { - if (prev->lastPCode && prev->lastPCode->op == PC_NOP && !(prev->lastPCode->flags & fSideEffects)) { - deletepcode(prev->lastPCode); - } else { - PCode *nop = makepcode(PC_NOP); - nop->flags &= ~fSideEffects; - appendpcode(prev, nop); - } - - codesize = pccomputeoffsets(); - changed = 1; - } - } - - if (changed) { - pclistblocks(CMangler_GetLinkName(func)->name, "AFTER INSERT ALIGN NOPs"); - if (codesize > 32766) { - insertlongbranches(32766); - codesize = pccomputeoffsets(); - } - } - - } while (changed); - - return codesize; -} - -SInt32 assemblefunction(Object *func, EntryPoint *entrypoints) { - void *tbdata; - GList *gl; - PCodeBlock *block; - PCode *instr; - SInt32 offset2; - SInt32 codesize; - SInt32 tbsize; - SInt32 offset; - SectionHandle section; - EntryPoint *ep; - WeirdOperand wop; - - codesize = pccomputeoffsets(); - if (codesize <= 0) - PPCError_Error(PPCErrorStr190, func->name->name); - - if (copts.peephole || copts.optimizationlevel >= 3) - codesize = optimizefinalbranches(codesize); - - if (codesize > 32766) { - insertlongbranches(32766); - codesize = pccomputeoffsets(); - } - - if (copts.function_align > 4) - codesize = insert_align_nops(func, codesize); - - tbsize = 0; - if (copts.traceback) - tbdata = generate_traceback(codesize, CMangler_GetLinkName(func)->name, &tbsize, func); - - if (func->section == SECT_DEFAULT) - func->section = SECT_TEXT; - - offset = tbsize; - section = ObjGen_DeclareCode(func, codesize + tbsize); - gl = ObjGen_GetSectionGList(section); - - codebase = gl->size; - AppendGListNoData(gl, codesize + tbsize); - - if (copts.filesyminfo) { - ObjGen_SymFunc(func); - ObjGen_Line(functionbodyoffset, 0); - ObjGen_DeclareSymInfo(); - } - - if (uses_globals && pic_base_reg) - ObjGen_DeclarePICBase(func, pic_base_pcodelabel->block->codeOffset); - - if (entrypoints) { - for (ep = entrypoints; ep; ep = ep->next) { - ObjGen_DeclareEntry(ep->object, ep->block->codeOffset); - } - } - - for (block = pcbasicblocks; block; block = block->nextBlock) { - for (offset2 = block->codeOffset, instr = block->firstPCode; instr; instr = instr->nextPCode, offset2 += 4) { - if (copts.filesyminfo && instr->sourceoffset != -1) - ObjGen_Line(instr->sourceoffset, offset2); - - *((UInt32 *) (*gl->data + codebase + offset2)) = assemblepcode(instr, offset2, &wop); - - if (wop.type != -1) - ObjGen_RelocateObj(section, offset2, wop.x2, wop.type); - } - } - - if (copts.filesyminfo) - ObjGenMach_SymFuncEnd(func, codesize); - - if (copts.traceback) - memcpy(*gl->data + codebase + codesize, tbdata, offset); - - if (copts.traceback) - return codesize + tbsize; - else - return codesize; -} diff --git a/compiler_and_linker/unsorted/PCodeInfo.c b/compiler_and_linker/unsorted/PCodeInfo.c deleted file mode 100644 index b2e2385..0000000 --- a/compiler_and_linker/unsorted/PCodeInfo.c +++ /dev/null @@ -1,1354 +0,0 @@ -#include "compiler/PCodeInfo.h" -#include "compiler/CError.h" -#include "compiler/CMangler.h" -#include "compiler/CParser.h" -#include "compiler/Alias.h" -#include "compiler/CodeGen.h" -#include "compiler/CompilerTools.h" -#include "compiler/PCode.h" -#include "compiler/PCodeListing.h" -#include "compiler/PCodeUtilities.h" -#include "compiler/RegisterInfo.h" -#include "compiler/StackFrame.h" -#include "compiler/TOC.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -#pragma pool_strings on - -int pcode_bad_operand; -char *orig_buf; -static int do_show_basic_blocks; - -void pcode_get_hi_lo(int bits, char typechar, SInt32 *hi, SInt32 *lo) { - if (bits == 0) { - *hi = 0; - *lo = 0; - return; - } - if (bits == 32) { - *hi = 0x7FFFFFFF; - *lo = -0x80000000; - return; - } - - if (bits < 32 && bits > 0) { - switch (typechar) { - case 'u': - *hi = (1 << bits) - 1; - *lo = 0; - break; - case 'i': - case 'x': - *hi = (1 << bits) - 1; - *lo = -(1 << (bits - 1)); - break; - default: - *hi = (1 << (bits - 1)) - 1; - *lo = -(1 << (bits - 1)); - } - } else { - CError_FATAL(65); - } -} - -int pcode_check_imm_bits(SInt32 value, int bits, char typechar) { - char buf[2]; - int forcedBits; - SInt32 r6; - SInt32 r0; - - forcedBits = 0; - if (bits >= 0 && bits < 32) { - if (bits == 0) { - r6 = 0; - r0 = 0; - } else { - switch (typechar) { - case 'u': - r6 = (1 << bits) - 1; - r0 = 0; - break; - case 'i': - case 'x': - r6 = (1 << bits) - 1; - r0 = -(1 << (bits - 1)); - break; - case '1': - case '2': - case '3': - case '4': - buf[0] = typechar; - buf[1] = 0; - forcedBits = atoi(buf); - default: - r6 = (1 << (bits - 1)) - 1; - r0 = -(1 << (bits - 1)); - } - } - - if ((value < r0) || (value > r6)) - return 1; - if (forcedBits > 0 && value != ((value >> forcedBits) << forcedBits)) - return 1; - } else if (bits > 32) { - CError_FATAL(110); - } - - return 0; -} - -int pcode_const_from_format(const char *format, SInt32 *pResult) { - char buf[32]; - int len = 0; - - for (len = 0; len < 30 && isdigit(format[len]); len++) { - buf[len] = format[len]; - } - buf[len] = 0; - - *pResult = atoi(buf); - return len; -} - -PCode *vformatpcode(short opcode, va_list argList) { - // has many wrong registers but probably ok otherwise - int argcount; // r29 - OpcodeInfo *info; // r27 for a short time - int effect; // r27 - const char *format; // r26 - PCode *pcode; // r25 - PCodeArg *arg; // r24 - int unkreg_r23; // r23 - int unkreg_r22; // r22 - PCodeArg *lastArg; // r21 - int pcode_size; // r20 for a short time - int tmp; - int tmp2; // r19 - int i; - SInt32 thing; - SInt32 thing2; - SInt32 thing3; - SInt32 thing4; - Object *obj; - PCodeLabel *label; - char c; - - info = &opcodeinfo[opcode]; - format = info->format; - argcount = info->x8; - unkreg_r23 = 0; - unkreg_r22 = 0; - - if (format[0] == '#') { - unkreg_r23 = va_arg(argList, int); - argcount += unkreg_r23; - format++; - } - - if (info->flags & fCanSetRecordBit) - unkreg_r22 = 1; - - if ((argcount + unkreg_r22) < 5) - unkreg_r22 += 5 - (argcount + unkreg_r22); - - pcode_size = (argcount + unkreg_r22) * sizeof(PCodeArg) + sizeof(PCode); - pcode = lalloc(pcode_size); - memclrw(pcode, pcode_size); - - pcode->op = opcode; - pcode->argCount = argcount; - pcode->flags = info->flags; - lastArg = pcode->args + pcode->argCount; - arg = pcode->args; - while (*format) { - if (arg >= lastArg) - CError_FATAL(189); - - if (*format == ',' || *format == ';') - format++; - if (*format == '[' || *format == '(') - format++; - - effect = EffectRead; - if (*format == '=') { - effect = EffectWrite; - format++; - } else if (*format == '+') { - effect = EffectRead | EffectWrite; - format++; - } - - if (*format == '-') - format++; - if (*format == '?') - format++; - if (*format == '!') - format++; - - switch ((c = *format)) { - case 'b': - tmp = va_arg(argList, int); - if (!tmp) - effect = 0; - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_GPR; - arg->data.reg.reg = tmp; - arg->data.reg.effect = effect; - break; - case 'r': - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_GPR; - arg->data.reg.reg = va_arg(argList, int); - arg->data.reg.effect = effect; - break; - case 'f': - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_FPR; - arg->data.reg.reg = va_arg(argList, int); - arg->data.reg.effect = effect; - break; - case 'v': - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_VR; - arg->data.reg.reg = va_arg(argList, int); - arg->data.reg.effect = effect; - break; - case 'c': - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_CRFIELD; - arg->data.reg.reg = va_arg(argList, int); - arg->data.reg.effect = effect; - break; - case 'C': - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_SPR; - arg->data.reg.reg = 2; - arg->data.reg.effect = effect; - break; - case 'L': - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_SPR; - arg->data.reg.reg = 1; - arg->data.reg.effect = effect; - break; - case 'V': - i = unkreg_r23; - while (i > 0) { - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_GPR; - arg->data.reg.reg = 31 - --i; - arg->data.reg.effect = effect; - arg++; - } - arg--; - break; - case 'X': - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_SPR; - arg->data.reg.reg = 0; - arg->data.reg.effect = effect; - break; - case 'Y': - if (pcode->op == PC_MTCRF) { - tmp = pcode->args[0].data.imm.value; - for (i = 0; i < 8; i++) { - if (tmp & (0x80 >> i)) { - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_CRFIELD; - arg->data.reg.reg = i; - arg->data.reg.effect = EffectWrite; - arg++; - } - } - } else { - i = 0; - while (i < 8) { - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_CRFIELD; - arg->data.reg.reg = i++; - arg->data.reg.effect = EffectRead; - arg++; - } - } - arg--; - break; - case 'Z': - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_CRFIELD; - arg->data.reg.reg = 0; - arg->data.reg.effect = effect; - break; - case 'P': - if (isdigit(format[1])) - format += pcode_const_from_format(format + 1, &thing); - else - CError_FATAL(319); - case 's': - tmp = va_arg(argList, int); - tmp2 = -1; - for (i = 0; i < 4; i++) { - if (tmp == spr_to_sysreg[i]) { - tmp2 = i; - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_SPR; - arg->data.reg.reg = i; - arg->data.reg.effect = effect; - if ((effect & EffectWrite) && (tmp == 0x100)) - pcsetsideeffects(pcode); - break; - } - } - - if (tmp2 < 0) { - pcsetsideeffects(pcode); - arg->kind = PCOp_SYSREG; - arg->arg = RegClass_SPR; - arg->data.reg.reg = tmp; - arg->data.reg.effect = effect; - } - - break; - - case 'T': - tmp = va_arg(argList, int); - if (tmp == 0x10C) { - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_SPR; - arg->data.reg.reg = 0x11C; - arg->data.reg.effect = effect; - } else if (tmp == 0x10D) { - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_SPR; - arg->data.reg.reg = 0x11D; - arg->data.reg.effect = effect; - } else { - CError_FATAL(353); - } - pcsetsideeffects(pcode); - arg->kind = PCOp_SYSREG; - arg->arg = RegClass_SPR; - arg->data.reg.reg = va_arg(argList, int); - arg->data.reg.effect = effect; - break; - - case 'S': - tmp2 = -1; - if (isdigit(format[1])) - format += pcode_const_from_format(format + 1, &thing2); - else - CError_FATAL(371); - - for (i = 0; i < 4; i++) { - if (thing2 == spr_to_sysreg[i]) { - tmp2 = i; - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_SPR; - arg->data.reg.reg = i; - arg->data.reg.effect = effect; - if ((effect & EffectWrite) && (thing2 == 0x100)) - pcsetsideeffects(pcode); - break; - } - } - - if (tmp2 < 0) { - pcsetsideeffects(pcode); - arg->kind = PCOp_SYSREG; - arg->arg = RegClass_SPR; - arg->data.reg.reg = va_arg(argList, int); - arg->data.reg.effect = effect; - } - break; - - case 'a': - case 'i': - case 'n': - case 'u': - case 'w': - case 'x': - tmp2 = (unsigned char) c; - thing3 = 16; - if (*format == 'a') { - if (isdigit(format[1])) - tmp2 = (unsigned char) *(++format); - else - CError_FATAL(408); - } - if (isdigit(format[1])) { - format += pcode_const_from_format(format + 1, &thing3); - } - arg->kind = PCOp_IMMEDIATE; - arg->data.imm.value = va_arg(argList, int); - arg->data.imm.obj = NULL; - if (pcode_check_imm_bits(arg->data.imm.value, thing3, tmp2)) - CError_FATAL(419); - break; - - case 'N': - arg->kind = PCOp_IMMEDIATE; - arg->data.imm.value = va_arg(argList, int); - arg->data.imm.obj = NULL; - if (pcode_check_imm_bits(arg->data.imm.value, 6, 'u')) - CError_FATAL(429); - break; - - case 'D': - arg->kind = PCOp_IMMEDIATE; - arg->data.imm.value = va_arg(argList, int); - arg->data.imm.obj = NULL; - if (pcode_check_imm_bits(arg->data.imm.value, 10, 'u')) - CError_FATAL(438); - break; - - case 'B': - case 't': - arg->kind = PCOp_IMMEDIATE; - arg->data.imm.value = va_arg(argList, int); - arg->data.imm.obj = NULL; - if (pcode_check_imm_bits(arg->data.imm.value, 5, 'u')) - CError_FATAL(448); - break; - - case 'Q': - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_CRFIELD; - arg->data.reg.reg = va_arg(argList, int); - arg->data.reg.effect = effect; - arg++; - case 'q': - arg->kind = PCOp_IMMEDIATE; - arg->data.imm.value = va_arg(argList, int); - arg->data.imm.obj = NULL; - if (pcode_check_imm_bits(arg->data.imm.value, 4, 'u')) - CError_FATAL(463); - break; - - case 'l': - if ((label = va_arg(argList, PCodeLabel *))) { - arg->kind = PCOp_LABEL; - arg->data.label.label = label; - } else { - arg->kind = PCOp_MEMORY; - obj = va_arg(argList, Object *); - CError_ASSERT(476, obj->otype == OT_OBJECT); - arg->data.mem.obj = obj; - arg->data.mem.offset = 0; - arg->arg = RefType_4; - } - break; - - case 'd': - CError_ASSERT(490, format[1] == '('); - effect = EffectRead; - format += 2; - if (*format == '=') { - effect = EffectWrite; - format++; - } else if (*format == '+') { - effect = EffectRead | EffectWrite; - format++; - } - - CError_ASSERT(502, format[0] == 'b'); - - tmp = va_arg(argList, int); - if (tmp == 0) - effect = 0; - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_GPR; - arg->data.reg.reg = tmp; - arg->data.reg.effect = effect; - arg++; - - case 'm': - obj = va_arg(argList, Object *); - if (obj) { - CError_ASSERT(515, obj->otype == OT_OBJECT); - - if (obj->datatype == DABSOLUTE) { - arg->kind = PCOp_IMMEDIATE; - arg->data.imm.obj = obj; - arg->data.imm.value = va_arg(argList, SInt32); - } else { - arg->kind = PCOp_MEMORY; - arg->data.mem.obj = obj; - arg->data.mem.offset = va_arg(argList, SInt32); - - if (pcode->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) { - pcode->alias = make_alias(obj, arg->data.mem.offset, nbytes_loaded_or_stored_by(pcode)); - if (is_volatile_object(obj)) - pcode->flags |= fIsVolatile; - //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_CONST) : (obj->qual & Q_CONST)) - if (OBJ_GET_TARGET_CONST(obj)) - pcode->flags |= fIsConst; - } else { - if (pcode->op == PC_ADDI) - pcode->alias = make_alias(obj, arg->data.mem.offset, 1); - } - CError_ASSERT(536, obj->datatype == DLOCAL || arg->data.mem.offset == 0); - if (pcode->flags & (fIsRead | fIsWrite)) { - //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_VOLATILE) : (obj->qual & Q_VOLATILE)) - if (OBJ_GET_TARGET_VOLATILE(obj)) - pcode->flags |= fIsVolatile; - //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_CONST) : (obj->qual & Q_CONST)) - if (OBJ_GET_TARGET_CONST(obj)) - pcode->flags |= fIsConst; - } - - if (pcode->flags & (fIsBranch | fIsCall)) { - arg->arg = RefType_4; - } else if (obj->datatype == DLOCAL) { - if (!local_is_16bit_offset(obj)) - arg->arg = RefType_D; - else - arg->arg = RefType_1; - } else { - arg->arg = RefType_6; - } - } - } else { - arg->kind = PCOp_IMMEDIATE; - arg->data.imm.value = va_arg(argList, SInt32); - arg->data.imm.obj = NULL; - if (pcode->flags & (fIsRead | fIsWrite)) - pcode->flags |= fIsPtrOp; - } - break; - - case 'M': - obj = va_arg(argList, Object *); - if (obj) { - CError_ASSERT(578, obj->otype == OT_OBJECT); - - if (obj->datatype == DABSOLUTE) { - arg->kind = PCOp_IMMEDIATE; - arg->data.imm.obj = obj; - arg->data.imm.value = va_arg(argList, SInt32); - } else { - arg->kind = PCOp_MEMORY; - arg->data.mem.obj = obj; - arg->data.mem.offset = va_arg(argList, SInt32); - - CError_ASSERT(590, obj->datatype == DLOCAL || arg->data.mem.offset == 0); - if (pcode->flags & (fIsRead | fIsWrite)) { - //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_VOLATILE) : (obj->qual & Q_VOLATILE)) - if (OBJ_GET_TARGET_VOLATILE(obj)) - pcode->flags |= fIsVolatile; - //if ((obj->type->type == TYPEPOINTER || obj->type->type == TYPEARRAY) ? (TYPE_POINTER(obj->type)->qual & Q_CONST) : (obj->qual & Q_CONST)) - if (OBJ_GET_TARGET_CONST(obj)) - pcode->flags |= fIsConst; - } - - if (obj->datatype == DLOCAL) { - arg->arg = RefType_C; - } else { - arg->arg = RefType_8; - } - } - } else { - arg->kind = PCOp_IMMEDIATE; - arg->data.imm.value = va_arg(argList, SInt32); - arg->data.imm.obj = NULL; - if (pcode->flags & (fIsRead | fIsWrite)) - pcode->flags |= fIsPtrOp; - } - break; - - case 'p': - arg->kind = PCOp_PLACEHOLDEROPERAND; - break; - - case 'O': - arg--; - break; - - default: - CError_FATAL(629); - } - - while (format[1] && strchr("/<>|*", format[1])) { - switch (*(++format)) { - case '/': - if (format[1] == '2') - format++; - break; - case '<': - case '*': - case '|': - case '>': - if (format[1] == 'p') - format++; - else if (isdigit(format[1])) - format += pcode_const_from_format(format + 1, &thing4); - else - CError_FATAL(659); - break; - } - } - - if ((c = *(++format)) == ']' || c == ')') - format++; - arg++; - } - - while (arg < lastArg) { - arg->kind = PCOp_PLACEHOLDEROPERAND; - arg++; - } - while (unkreg_r22) { - arg->kind = PCOp_PLACEHOLDEROPERAND; - arg++; - unkreg_r22--; - } - return pcode; -} - -int expectandformatoperand(PCodeArg *operand, PCOpKind expectedKind, char a3, int bitCount, char *buf) { - int errorlen; - char *name; - int tmp; - int regclass; - int refis1; - int b_null; - - errorlen = 0; - - if (operand->kind != expectedKind) { - char *kindstr; - switch (expectedKind) { - case PCOp_REGISTER: kindstr = "REGISTER"; break; - case PCOp_SYSREG: kindstr = "SYSREG"; break; - case PCOp_IMMEDIATE: kindstr = "IMMEDIATE"; break; - case PCOp_MEMORY: kindstr = "MEMORY"; break; - case PCOp_LABEL: kindstr = "LABEL"; break; - case PCOp_LABELDIFF: kindstr = "LABELDIFF"; break; - case PCOp_PLACEHOLDEROPERAND: kindstr = "PLACEHOLDEROPERAND"; break; - default: kindstr = "unknown kind"; - } - tmp = sprintf(buf, "{EXPECTED %s}", kindstr); - errorlen += tmp; - buf += tmp; - pclist_bad_operand = 1; - } - - switch (operand->kind) { - case PCOp_REGISTER: - if (operand->arg != (regclass = a3)) { - tmp = sprintf(buf, "{EXPECTED %s}", register_class_name[regclass]); - errorlen += tmp; - buf += tmp; - } - if (operand->data.reg.reg < n_real_registers[regclass] && (name = special_register_names[operand->arg][operand->data.reg.reg])) - tmp = sprintf(buf, "%s", name); - else - tmp = sprintf(buf, register_class_format[operand->arg], operand->data.reg.reg); - errorlen += tmp; - break; - case PCOp_SYSREG: - if (operand->arg != RegClass_SPR) { - tmp = sprintf(buf, "{EXPECTED %s}", register_class_name[RegClass_SPR]); - errorlen += tmp; - buf += tmp; - } - tmp = sprintf(buf, register_class_format[RegClass_SPR], operand->data.reg.reg); - errorlen += tmp; - break; - case PCOp_IMMEDIATE: - switch (a3) { - case 'x': - tmp = sprintf(buf, "0x%x", operand->data.imm.value); - break; - case 'u': - tmp = sprintf(buf, "%u", operand->data.imm.value); - break; - default: - tmp = sprintf(buf, "%" PRId32, operand->data.imm.value); - break; - } - errorlen += tmp; - buf += tmp; - if (operand->data.imm.obj) { - name = CMangler_GetLinkName(operand->data.imm.obj)->name; - if (strlen(name) > 50) - tmp = sprintf(buf, "{%45.45s...}", name); - else - tmp = sprintf(buf, "{%s}", name); - errorlen += tmp; - buf += tmp; - } - if (pcode_check_imm_bits(operand->data.imm.value, bitCount, (char) a3)) { - errorlen += sprintf(buf, "{IMM too large %i bits}", bitCount); - pclist_bad_operand = 1; - } - break; - case PCOp_MEMORY: - switch ((unsigned char) operand->arg) { - case RefType_0: - case RefType_1: - case RefType_2: - case RefType_3: - case RefType_4: - case RefType_5: - case RefType_9: - break; - case RefType_8: - case RefType_B: - case RefType_C: - tmp = sprintf(buf, "HA("); - errorlen += tmp; - buf += tmp; - break; - case RefType_7: - tmp = sprintf(buf, "HI("); - errorlen += tmp; - buf += tmp; - break; - case RefType_6: - case RefType_A: - case RefType_D: - tmp = sprintf(buf, "LO("); - errorlen += tmp; - buf += tmp; - break; - default: - tmp = sprintf(buf, "{UNEXPECTED reftype = %d}", (unsigned char) operand->arg); - errorlen += tmp; - buf += tmp; - } - name = CMangler_GetLinkName(operand->data.mem.obj)->name; - if (strlen(name) == 0 || strlen(name) > 3200 || name[0] < 0) - CError_FATAL(849); - if (strlen(name) > 50) - tmp = sprintf(buf, "%45.45s...", name); - else - tmp = sprintf(buf, "%s", name); - errorlen += tmp; - buf += tmp; - if (operand->data.mem.offset > 0) - tmp = sprintf(buf, "+%d", operand->data.mem.offset); - else if (operand->data.mem.offset != 0) - tmp = sprintf(buf, "-%d", -operand->data.mem.offset); - else - tmp = 0; - errorlen += tmp; - buf += tmp; - if (copts.codegen_pic && uses_globals && pic_base_reg) { - tmp = sprintf(buf, "-B%d", pic_base_pcodelabel->block->blockIndex); - errorlen += tmp; - buf += tmp; - } - switch ((unsigned char) operand->arg) { - case RefType_6: - case RefType_7: - case RefType_8: - case RefType_A: - case RefType_B: - case RefType_C: - case RefType_D: - errorlen += sprintf(buf, ")"); - } - break; - case PCOp_LABEL: - if (do_show_basic_blocks) { - if (!operand->data.label.label->block) - tmp = sprintf(buf, "B"); - else - tmp = sprintf(buf, "B%" PRId32, operand->data.label.label->block->blockIndex); - } else { - tmp = sprintf(buf, "%.8" PRIX32, operand->data.label.label->block->codeOffset); - } - errorlen += tmp; - break; - case PCOp_LABELDIFF: - refis1 = ((unsigned char) operand->arg == 1); - b_null = !operand->data.labeldiff.labelB->block; - if (operand->data.labeldiff.labelA->block == NULL) { - if (b_null) - tmp = sprintf(buf, "%sB-B+%" PRId32, refis1 ? "-" : "", operand->data.labeldiff.offset); - else - tmp = sprintf(buf, "%sB-B%" PRId32 "+%" PRId32, refis1 ? "-" : "", operand->data.labeldiff.labelB->block->blockIndex, operand->data.labeldiff.offset); - } else { - if (b_null) - tmp = sprintf(buf, "%sB%" PRId32 "-B+%" PRId32, refis1 ? "-" : "", operand->data.labeldiff.labelA->block->blockIndex, operand->data.labeldiff.offset); - else - tmp = sprintf(buf, "%sB%" PRId32 "-B%" PRId32 "+%" PRId32, refis1 ? "-" : "", operand->data.labeldiff.labelA->block->blockIndex, operand->data.labeldiff.labelB->block->blockIndex, operand->data.labeldiff.offset); - } - errorlen += tmp; - break; - case PCOp_PLACEHOLDEROPERAND: - errorlen += sprintf(buf, "{placeholder}"); - break; - default: - errorlen += sprintf(buf, "{UNEXPECTED kind = %d}", operand->kind); - } - - return errorlen; -} - -int formatoperand(PCodeArg *operand, char *buf) { - return expectandformatoperand( - operand, - operand->kind, - (operand->kind == PCOp_REGISTER) ? operand->arg : 'x', - -1, - buf); -} - -void formatoperands(PCode *pcode, char *buf, int showBasicBlocks) { - const char *format; // r29 - // there might be a PCodeArg *arg in r28 - // not sure lol - PCodeArg *pa; - int arg_index; // r27 - - char *name; - int i; - int tmp; - int tmp2; - SInt32 thing; - SInt32 thing2; - SInt32 thing4; - char c; - int flagSetT; - int flagSetF; - - static char *cc[] = { - "lt", "gt", "eq", "un" - }; - static char *to[] = { - "", "lgt", "llt", "", - "eq", "lge", "lle", "", - "gt", "", "", "", - "ge", "", "", "", - "lt", "", "", "", - "le", "", "", "", - "ne", "", "", "", - "", "", "" - }; - - format = opcodeinfo[pcode->op].format; - orig_buf = buf; - do_show_basic_blocks = showBasicBlocks; - - if (format[0] == '#') { - format++; - if (format[0] == ',') - format++; - } - - arg_index = 0; - pa = pcode->args; - while (*format) { - if (*format == ';') - break; - if (arg_index == pcode->argCount) { - pclist_bad_operand = 1; - buf += sprintf(buf, "{EXCEDED noperands, remaning format = %s}", format); - break; - } - - if (*format == ',') { - *(buf++) = ','; - format++; - } - - if (*format == '[' || *format == '(') { - *(buf++) = *format; - format++; - } - - if (*format == '=' || *format == '+') - format++; - if (*format == '-') - format++; - - if (*format == '?') { - format++; - if (*format != 'c') - *(buf++) = ','; - } - - if (*format == '!') - format++; - - switch (*format) { - case 'b': - if (pa->kind == PCOp_REGISTER && pa->arg == RegClass_GPR && pa->data.reg.reg == 0) { - if (pa->data.reg.effect & EffectWrite) { - pclist_bad_operand = 1; - buf += sprintf(buf, "!!!r"); - } - buf += sprintf(buf, "0"); - break; - } - case 'r': - buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_GPR, -1, buf); - break; - case 'f': - buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_FPR, -1, buf); - break; - case 'v': - buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_VR, -1, buf); - break; - case 'c': - buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_CRFIELD, -1, buf); - break; - case 'X': - CError_ASSERT(1124, pa->data.reg.reg == 0); - buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); - break; - case 'C': - CError_ASSERT(1129, pa->data.reg.reg == 2); - buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); - break; - case 'L': - CError_ASSERT(1134, pa->data.reg.reg == 1); - buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); - break; - case 'Z': - CError_ASSERT(1139, pa->data.reg.reg == 0); - buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); - break; - case 'P': - if (isdigit(format[1])) - format += pcode_const_from_format(format + 1, &thing); - else - CError_FATAL(1149); - case 'S': - case 'T': - case 's': - if (pa->kind == PCOp_REGISTER && pa->arg == RegClass_SPR) { - buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_SPR, -1, buf); - } else { - for (i = 0; i < 4; i++) { - if (pa->data.reg.reg == spr_to_sysreg[i]) { - CError_FATAL(1161); - break; - } - } - - buf += expectandformatoperand(pa, PCOp_SYSREG, RegClass_SPR, -1, buf); - } - break; - - case 'V': - do { - buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_GPR, -1, buf); - *(buf++) = ','; - pa++; - arg_index++; - } while (arg_index < pcode->argCount && pa->kind == PCOp_REGISTER && pa->arg == RegClass_GPR); - buf--; - pa--; - arg_index--; - break; - - case 'Y': - do { - buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_CRFIELD, -1, buf); - *(buf++) = ','; - pa++; - arg_index++; - } while (arg_index < pcode->argCount && pa->kind == PCOp_REGISTER && pa->arg == RegClass_CRFIELD); - buf--; - pa--; - arg_index--; - break; - - case 'Q': - buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_CRFIELD, -1, buf); - *(buf++) = ','; - pa++; - arg_index++; - case 'q': - if (pa->kind == PCOp_IMMEDIATE && pa->data.imm.value >= 0 && pa->data.imm.value < 4 && (name = cc[pa->data.imm.value])[0]) { - buf += sprintf(buf, "%s", name); - } else { - buf += sprintf(buf, "{OUT OF RANGE}"); - buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 0, -1, buf); - } - break; - case 'a': - case 'i': - case 'u': - case 'x': - tmp = *format; - if (tmp == 'a') { - if (isdigit(format[1])) { - format++; - tmp = *format; - } else { - CError_FATAL(1227); - } - } - if ((tmp2 = isdigit(format[1]))) - format += pcode_const_from_format(format + 1, &thing2); - if (!tmp2) - thing2 = -1; - buf += expectandformatoperand(pa, PCOp_IMMEDIATE, tmp, thing2, buf); - break; - - case 'N': - buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 'u', 6, buf); - break; - - case 'D': - buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 'u', 10, buf); - break; - - case 't': - if (pa->kind == PCOp_IMMEDIATE && pa->data.imm.value > 0 && pa->data.imm.value < 31 && (name = to[pa->data.imm.value])[0]) { - buf += sprintf(buf, "%s", name); - break; - } - - case 'B': - buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 'x', 5, buf); - break; - - case 'l': - if (pa->kind == PCOp_IMMEDIATE) { - buf += sprintf(buf, "*%s%" PRId32, (pa->data.imm.value >= 0) ? "+" : "", pa->data.imm.value); - } else if (pa->kind == PCOp_LABELDIFF) { - buf += expectandformatoperand(pa, PCOp_LABELDIFF, 0, -1, buf); - } else if (pa->kind == PCOp_LABEL) { - buf += expectandformatoperand(pa, PCOp_LABEL, 0, -1, buf); - } else { - buf += expectandformatoperand(pa, PCOp_MEMORY, 0, -1, buf); - } - break; - - case 'd': - if (pa[1].kind == PCOp_MEMORY) - buf += expectandformatoperand(pa + 1, PCOp_MEMORY, 0, -1, buf); - else - buf += expectandformatoperand(pa + 1, PCOp_IMMEDIATE, 0, -1, buf); - CError_ASSERT(1283, format[1] == '('); - format++; - *(buf++) = *(format++); - if (*format == '+') - format++; - CError_ASSERT(1291, format[0] == 'b'); - if (pa->kind == PCOp_REGISTER && pa->arg == RegClass_GPR && pa->data.reg.reg == 0) { - if (pa->data.reg.effect & (EffectRead | EffectWrite)) { - pclist_bad_operand = 1; - buf += sprintf(buf, "!!!r"); - } - buf += sprintf(buf, "0"); - } else { - buf += expectandformatoperand(pa, PCOp_REGISTER, RegClass_GPR, -1, buf); - } - pa++; - i++; - break; - - case 'w': - if (pa->kind == PCOp_LABELDIFF) - buf += expectandformatoperand(pa, PCOp_LABELDIFF, 0, -1, buf); - else - buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 0, -1, buf); - break; - - case 'm': - case 'n': - if (pa->kind == PCOp_MEMORY) - buf += expectandformatoperand(pa, PCOp_MEMORY, 0, -1, buf); - else if (pa->kind == PCOp_LABELDIFF) - buf += expectandformatoperand(pa, PCOp_LABELDIFF, 0, -1, buf); - else if ((pcode->flags & (fIsBranch | fIsCall)) && (pa->kind == PCOp_LABEL)) - buf += expectandformatoperand(pa, PCOp_LABEL, 0, -1, buf); - else - buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 0, -1, buf); - break; - - case 'M': - if (pa->kind == PCOp_MEMORY) { - CError_ASSERT(1335, pa->arg == RefType_8 || pa->arg == RefType_B || pa->arg == RefType_C); - buf += expectandformatoperand(pa, PCOp_MEMORY, 0, -1, buf); - } else if (pa->kind == PCOp_LABELDIFF) - buf += expectandformatoperand(pa, PCOp_LABELDIFF, 0, -1, buf); - else - buf += expectandformatoperand(pa, PCOp_IMMEDIATE, 0, -1, buf); - break; - - case 'O': - pa--; - arg_index--; - break; - - case 'p': - buf += expectandformatoperand(pa, PCOp_PLACEHOLDEROPERAND, 0, -1, buf); - break; - - default: - CError_FATAL(1465); - } - - while (format[1] && strchr("/<>|*", format[1])) { - switch (*(++format)) { - case '/': - if (format[1] == '2') - format++; - break; - case '<': - case '*': - case '|': - case '>': - if (format[1] == 'p') - format++; - else if (isdigit(format[1])) - format += pcode_const_from_format(format + 1, &thing4); - else - CError_FATAL(1495); - break; - } - } - - if ((c = *(++format)) == ']' || c == ')') { - *(buf++) = c; - format++; - } - - pa++; - arg_index++; - } - - if (buf[-1] == ',') - buf--; - - flagSetT = PCODE_FLAG_SET_T(pcode); - flagSetF = PCODE_FLAG_SET_F(pcode); - if (pcode->flags & fIsConst) - buf += sprintf(buf, "; fIsConst"); - if (pcode->flags & fIsVolatile) - buf += sprintf(buf, "; fIsVolatile"); - if (pcode->flags & fSideEffects) - buf += sprintf(buf, "; fSideEffects"); - if (pcode->flags & fIsCSE) - buf += sprintf(buf, "; fIsCSE"); - if (pcode->flags & fCommutative) - buf += sprintf(buf, "; fCommutative"); - - if (flagSetF & fIsPtrOp) - buf += sprintf(buf, "; fIsPtrOp"); - - if (flagSetT) { - if (flagSetT & fLink) - buf += sprintf(buf, "; fLink"); - if (flagSetT & fAbsolute) - buf += sprintf(buf, "; fAbsolute"); - if (flagSetT & fBranchTaken) - buf += sprintf(buf, "; fBranchTaken"); - if (flagSetT & fBranchNotTaken) - buf += sprintf(buf, "; fBranchNotTaken"); - } else if (flagSetF) { - if (flagSetF & fSetsCarry) - buf += sprintf(buf, "; fSetsCarry"); - if (flagSetF & fOverflow) - buf += sprintf(buf, "; fOverflow"); - } - - *buf = 0; -} - -PCode *makecopyinstruction(PCodeArg *a, PCodeArg *b) { - if (b->kind == PCOp_REGISTER) { - switch (b->arg) { - case RegClass_GPR: - return makepcode(PC_MR, b->data.reg.reg, a->data.reg.reg); - case RegClass_FPR: - return makepcode(PC_FMR, b->data.reg.reg, a->data.reg.reg); - case RegClass_VR: - return makepcode(PC_VMR, b->data.reg.reg, a->data.reg.reg); - case RegClass_CRFIELD: - return makepcode(PC_MCRF, b->data.reg.reg, a->data.reg.reg); - } - } - - CError_FATAL(1622); - return NULL; -} - -int is_location_independent(PCode *pcode) { - switch (pcode->op) { - case PC_LI: - case PC_LIS: - case PC_VSPLTISB: - case PC_VSPLTISH: - case PC_VSPLTISW: - return 1; - case PC_ADDI: - case PC_ADDIS: - case PC_ORI: - case PC_ORIS: - return pcode->args[1].data.reg.reg == _FP_; - case PC_LWZ: - if ( - pcode->args[1].data.reg.reg == 1 && - pcode->args[2].kind == PCOp_IMMEDIATE && - pcode->args[2].data.imm.value == 0 - ) - return 1; - } - - return 0; -} - -int can_reuse_stored_value(PCode *a, PCode *b) { - switch (b->op) { - case PC_LWZ: - case PC_LWZU: - case PC_LWZX: - case PC_LWZUX: - switch (a->op) { - case PC_STW: - case PC_STWU: - case PC_STWX: - case PC_STWUX: - return 1; - } - break; - - case PC_LFD: - case PC_LFDU: - case PC_LFDX: - case PC_LFDUX: - switch (a->op) { - case PC_STFD: - case PC_STFDU: - case PC_STFDX: - case PC_STFDUX: - return 1; - } - break; - - case PC_LVX: - if (a->op == PC_STVX) - return 1; - break; - } - - return 0; -} - -int nbytes_loaded_or_stored_by(PCode *pcode) { - OpcodeInfo *oinfo = opcodeinfo + pcode->op; - if (oinfo->flags & (fIsRead | fIsWrite)) { - switch (pcode->op) { - case PC_LBZ: - case PC_LBZU: - case PC_LBZX: - case PC_LBZUX: - case PC_STB: - case PC_STBU: - case PC_STBX: - case PC_STBUX: - return 1; - case PC_LHZ: - case PC_LHZU: - case PC_LHZX: - case PC_LHZUX: - case PC_LHA: - case PC_LHAU: - case PC_LHAX: - case PC_LHAUX: - case PC_LHBRX: - case PC_STH: - case PC_STHU: - case PC_STHX: - case PC_STHUX: - case PC_STHBRX: - return 2; - case PC_LWZ: - case PC_LWZU: - case PC_LWZX: - case PC_LWZUX: - case PC_LWBRX: - case PC_STW: - case PC_STWU: - case PC_STWX: - case PC_STWUX: - case PC_STWBRX: - case PC_LFS: - case PC_LFSU: - case PC_LFSX: - case PC_LFSUX: - case PC_STFS: - case PC_STFSU: - case PC_STFSX: - case PC_STFSUX: - case PC_LWARX: - case PC_STFIWX: - case PC_STWCX: - case PC_ECIWX: - case PC_ECOWX: - case PC_MFROM: - case PC_LSCBX: - return 4; - case PC_LMW: - case PC_STMW: - if (pcode->args[0].kind == PCOp_REGISTER && pcode->args[0].arg == RegClass_GPR) - return (32 - pcode->args[0].data.reg.reg) * 4; - else - return 128; - case PC_LFD: - case PC_LFDU: - case PC_LFDX: - case PC_LFDUX: - case PC_STFD: - case PC_STFDU: - case PC_STFDX: - case PC_STFDUX: - return 8; - case PC_LSWI: - case PC_STSWI: - return pcode->args[2].data.imm.value; // not sure if imm is the right union type here - case PC_LSWX: - case PC_STSWX: - return 128; - - // there's probably an ifdef here lmao - case PC_LVEBX: - case PC_STVEBX: - return 1; - case PC_LVEHX: - case PC_STVEHX: - return 2; - case PC_LVEWX: - case PC_STVEWX: - return 4; - case PC_LVSL: - case PC_LVSR: - case PC_LVX: - case PC_LVXL: - case PC_STVX: - case PC_STVXL: - return 16; - - default: - CError_FATAL(2011); - } - } - - CError_FATAL(2014); - return 0; -} - -void change_num_operands(PCode *pcode, int newNum) { - int i; - - CError_ASSERT(2026, ((pcode->argCount > 5) ? pcode->argCount : 5) >= newNum); - - for (i = pcode->argCount - 1; i >= newNum; i--) - pcode->args[i].kind = PCOp_PLACEHOLDEROPERAND; - - pcode->argCount = newNum; -} - -void change_opcode(PCode *pcode, short opcode) { - pcode->flags = (pcode->flags & ~(opcodeinfo[pcode->op].flags & ~fIsPtrOp)) | opcodeinfo[opcode].flags; - if ((pcode->flags & fIsMove) && (PCODE_FLAG_SET_F(pcode) & fRecordBit)) - pcode->flags &= ~fIsMove; - pcode->op = opcode; -} diff --git a/compiler_and_linker/unsorted/PCodeListing.c b/compiler_and_linker/unsorted/PCodeListing.c deleted file mode 100644 index 7a9fa13..0000000 --- a/compiler_and_linker/unsorted/PCodeListing.c +++ /dev/null @@ -1,536 +0,0 @@ -#include "compiler/PCodeListing.h" -#include "compiler/CError.h" -#include "compiler/CMangler.h" -#include "compiler/CParser.h" -#include "compiler/Alias.h" -#include "compiler/BitVectors.h" -#include "compiler/CompilerTools.h" -#include "compiler/InterferenceGraph.h" -#include "compiler/LiveInfo.h" -#include "compiler/PCode.h" -#include "compiler/PCodeAssembly.h" -#include "compiler/Registers.h" -#include "compiler/Scheduler.h" -#include "compiler/objects.h" - -static FILE *pcfile; -static int ptime; -static int sourcetext; -static int sourcetext_is_main; -static int sourcelength; -int pclist_bad_operand; - -static void formatdataflowset(char *name, UInt32 *vec, UInt32 size, char *format) { - UInt32 i; - UInt32 counter; - char *separator; - - separator = ""; - fprintf(pcfile, "%s = {", name); - - for (i = 0, counter = 0; i < size; i++) { - if (bitvectorgetbit(i, vec)) { - if (i) - fprintf(pcfile, separator); - if (counter++ == 10) { - fprintf(pcfile, "\n\t\t"); - counter = 0; - } - fprintf(pcfile, format, i); - separator = ","; - } - } - - fprintf(pcfile, "}\n"); -} - -static void pclistblock(PCodeBlock *block, char *format, UInt32 vecSize) { - PCLink *link; - PCodeLabel *label; - int cpu; - int chr; - PCode *instr; - int offset; - int latency; - UInt32 opcode; - MachineInfo *mi; - char buf[500]; - WeirdOperand dummyArg; - - fprintf(pcfile, ":{%4.4x}::::::::::::::::::::::::::::::::::::::::LOOPWEIGHT=%" PRId32 "\n", block->flags, block->loopWeight); - fprintf(pcfile, "B%" PRId32 ": ", block->blockIndex); - - fprintf(pcfile, "Successors = { "); - for (link = block->successors; link; link = link->nextLink) { - if (link->block) - fprintf(pcfile, "B%" PRId32 " ", link->block->blockIndex); - } - fprintf(pcfile, "} "); - - fprintf(pcfile, "Predecessors = { "); - for (link = block->predecessors; link; link = link->nextLink) { - if (link->block) - fprintf(pcfile, "B%" PRId32 " ", link->block->blockIndex); - } - - if (block->labels) { - fprintf(pcfile, "} Labels = { "); - for (label = block->labels; label; label = label->nextLabel) - fprintf(pcfile, "L%" PRId32 " ", label->index); - } - - fprintf(pcfile, "}\n\n"); - - cpu = copts.scheduling; - if (cpu == 10) { - mi = &machine7450; - } else if (copts.altivec_model != 0 || cpu == 7) { - mi = &machine7400; - } else if (cpu == 2) { - mi = &machine603; - } else if (cpu == 5) { - mi = &machine603e; - } else if (cpu == 3) { - mi = &machine604; - } else if (cpu == 6) { - mi = &machine604; - } else if (cpu == 4) { - mi = &machine750; - } else if (cpu == 1) { - mi = &machine601; - } else if (cpu == 9) { - mi = &machine821; - } else { - mi = &machine603; - } - - for (offset = block->codeOffset, instr = block->firstPCode; instr; instr = instr->nextPCode, offset += 4) { - latency = mi->latency(instr); - formatoperands(instr, buf, 1); - chr = (PCODE_FLAG_SET_F(instr) & fRecordBit) ? '.' : ' '; - if (coloring) - opcode = 0; - else - opcode = assemblepcode(instr, offset, &dummyArg); - - fprintf( - pcfile, - " %.8" PRIX32 " %.8" PRIX32 " %4" PRId32 " %-7s%c %s\n", - offset, CTool_EndianConvertWord32(opcode), latency, - opcodeinfo[instr->op].name, chr, buf - ); - - if (instr->alias) - dumpalias(instr->alias, 0, 1, 0); - } - - if (vecSize) { - fprintf(pcfile, "............................................................\n"); - formatdataflowset("use", liveinfo[block->blockIndex].use, vecSize, format); - formatdataflowset("def", liveinfo[block->blockIndex].def, vecSize, format); - formatdataflowset("in ", liveinfo[block->blockIndex].in, vecSize, format); - formatdataflowset("out", liveinfo[block->blockIndex].out, vecSize, format); - } - - fflush(pcfile); - - if (pclist_bad_operand) - CError_FATAL(252); -} - -static void pclistonoff(int flag) { - if (flag) - fprintf(pcfile, "On\n"); - else - fprintf(pcfile, "Off\n"); -} - -void pcinitlisting() { - // unknown args, etc -} - -void pccleanuplisting(void) { -#ifdef CW_ENABLE_PCODE_DEBUG - // this code is not based on the original as we don't have it - if (pcfile) { - fclose(pcfile); - pcfile = NULL; - } -#endif -} - -void pclistblocks(char *name1, char *name2) { -#ifdef CW_ENABLE_PCODE_DEBUG - // this code is not based on the original as we don't have it - PCodeBlock *block; - if (copts.debuglisting) { - if (!pcfile) - pcfile = fopen("pcdump.txt", "a"); - - fprintf(pcfile, "\n%s\n%s\n", name1, name2); - for (block = pcbasicblocks; block; block = block->nextBlock) - pclistblock(block, NULL, 0); - } -#endif -} - -void pclistdataflow() { - // unknown args -} - -void pclistinterferences(char *class_format, int regcount) { -} - -void pclistspill() { - // unknown args -} - -void pclistcopypropitem() { - // unknown args -} - -void pclistcoalesce() { - // unknown args -} - -void pclistusedefs() { - // unknown args -} - -void pclistpropinfo() { - // unknown args -} - -static void listloop() { - // unknown args -} - -static void listloops() { - // unknown args -} - -void pclistloops() { - // unknown args -} - -static void listswitchtables() { - // unknown args -} - -void pclistswitchtables() { - // unknown args -} - -void pclistdominators() { - // unknown args -} - -void pclistbackedge() { - // unknown args -} - -static char *GetInterferenceFlags(IGNode *node) { - char *buf; - Boolean first; - - first = 1; - buf = oalloc(512); - buf[0] = 0; - - if (node->flags & fSpilled) { - strcat(buf, "fSpilled"); - first = 0; - } - - if (node->flags & fPushed) { - if (!first) - strcat(buf, "|"); - strcat(buf, "fPushed"); - first = 0; - } - - if (node->flags & fCoalesced) { - if (!first) - strcat(buf, "|"); - strcat(buf, "fCoalesced"); - first = 0; - } - - if (node->flags & fCoalescedInto) { - if (!first) - strcat(buf, "|"); - strcat(buf, "fCoalescedInto"); - first = 0; - } - - if (node->flags & fPairHigh) { - if (!first) - strcat(buf, "|"); - strcat(buf, "fPairHigh"); - first = 0; - } - - if (node->flags & fPairLow) { - if (!first) - strcat(buf, "|"); - strcat(buf, "fPairLow"); - first = 0; - } - - if (!*buf) - strcat(buf, "no_flags"); - - return buf; -} - -void pclistinterferencegraphnode() { - // unknown args -} - -void pclistinterferencegraph() { - // unknown args -} - -void pclistblock_scheduler() { - // unknown args -} - -void pclistblocks_start_scheduler(char *str1, char *str2) { -} - -void pclistblocks_end_scheduler(void) { - if (pclist_bad_operand) - CError_FATAL(1318); -} - -static void printheapsize() { - // unknown args -} - -void pctotalheap() { - // unknown args -} - -void pctotalmemory() { - // unknown args -} - -void pcmessage(char *probably_a_string, ...) { -} - -int formatalias(Alias *alias, char *buf, int bufSize) { - char *name; - char *typestr; - int len; - int len2; - - if (bufSize < 16) - return sprintf(buf, "..."); - - switch (alias->type) { - case AliasType0: - case AliasType1: - name = CMangler_GetLinkName(alias->object)->name; - if (!strlen(name) || name[0] < 0) - CError_FATAL(1458); - - if (strlen(name) + 16 > bufSize) - return sprintf(buf, "..."); - - switch (alias->object->datatype) { - case DNONLAZYPTR: - typestr = "{NL}"; - break; - case DDATA: - typestr = "{RW}"; - break; - case DLOCAL: - typestr = "{SP}"; - break; - default: - typestr = ""; - } - - len = sprintf(buf, "%0.*s%s", bufSize - 20, name, typestr, alias->size); - buf += len; - if (alias->type == AliasType0) - return len; - - if (alias->offset == 0) - len2 = sprintf(buf, ":%d", alias->size); - else if (alias->offset > 0) - len2 = sprintf(buf, "+%d:%d", alias->offset, alias->size); - else - len2 = sprintf(buf, "-%d:%d", -alias->offset, alias->size); - - return len + len2; - - case AliasType2: - len = 0; - - len2 = sprintf(buf, "{"); - buf += len2; - len += len2; - - len2 = sprintf(buf, "*"); - buf += len2; - len += len2; - - len2 = sprintf(buf, "}"); - buf += len2; - len += len2; - return len; - - default: - CError_FATAL(1543); - return 0; - } -} - -int dumpalias(Alias *alias, int len, Boolean flag1, Boolean flag2) { - char *name; - char *typestr; - AliasMember *member; - Boolean notFirst; - - if (!flag2 && alias == worst_case) { - fprintf(pcfile, " ALIAS = {worst_case}"); - if (flag1) - fprintf(pcfile, "\n"); - return 0; - } - - if (flag1) { - if (alias == worst_case) - fprintf(pcfile, "ALIAS worst_case = "); - else - fprintf(pcfile, " ALIAS = "); - } - - switch (alias->type) { - case AliasType0: - case AliasType1: - name = CMangler_GetLinkName(alias->object)->name; - if (!strlen(name) || name[0] < 0) - CError_FATAL(1581); - - switch (alias->object->datatype) { - case DNONLAZYPTR: - typestr = "{NL}"; - break; - case DDATA: - typestr = "{RW}"; - break; - case DLOCAL: - typestr = "{SP}"; - break; - default: - typestr = ""; - } - - len += fprintf(pcfile, "%0.80s%s", name, typestr); - - if (alias->type == AliasType0) { - if (flag1) - fprintf(pcfile, "\n"); - return len; - } - - if (alias->offset == 0) - len += fprintf(pcfile, ":%d", alias->size); - else if (alias->offset > 0) - len += fprintf(pcfile, "+%d:%d", alias->offset, alias->size); - else - len += fprintf(pcfile, "-%d:%d", -alias->offset, alias->size); - - if (flag1) - fprintf(pcfile, "\n"); - - return len; - - case AliasType2: - len += fprintf(pcfile, "{"); - notFirst = 0; - for (member = alias->parents; member; member = member->nextParent) { - if (member->child->type == AliasType0) { - if (notFirst) - len += fprintf(pcfile, ","); - if (len > 60) { - fprintf(pcfile, "\n "); - len = 0; - } - len = dumpalias(member->child, len, 0, 0); - notFirst = 1; - } - } - for (member = alias->parents; member; member = member->nextParent) { - if (member->child->type != AliasType0) { - if (notFirst) - len += fprintf(pcfile, ","); - if (len > 60) { - fprintf(pcfile, "\n "); - len = 0; - } - len = dumpalias(member->child, len, 0, 0); - notFirst = 1; - } - } - - len += fprintf(pcfile, "}"); - if (flag1) - fprintf(pcfile, "\n"); - return len; - - default: - CError_FATAL(1661); - return 0; - } -} - -void pcformatset() { - // unknown args -} - -int GetLineEndOffset(char *str, int lineNum, int len) { - int offset; - char *work; - - offset = GetLineOffset(str, lineNum, len); - if (offset < 0) - return offset; - - work = str + offset; - while (*work) { - if (*work == '\n') - return work - str - 1; - work++; - } - return -1; -} - -int GetLineOffset(char *str, int lineNum, int len) { - char *work = str; - char *end; - - if (lineNum < 0) - return -1; - - end = str + len; - while (work < end) { - if (*work == '\n' && --lineNum <= 0) - return work - str; - work++; - } - - return 0; -} - -void DumpSourceCode() { - // unknown args -} - -int DumpIR_SrcBreak() { - // unknown args - return 0; -} - diff --git a/compiler_and_linker/unsorted/PCodeUtilities.c b/compiler_and_linker/unsorted/PCodeUtilities.c deleted file mode 100644 index b1f8ffb..0000000 --- a/compiler_and_linker/unsorted/PCodeUtilities.c +++ /dev/null @@ -1,345 +0,0 @@ -#include "compiler/PCodeUtilities.h" -#include "compiler/CError.h" -#include "compiler/CFunc.h" -#include "compiler/CParser.h" -#include "compiler/CodeGen.h" -#include "compiler/Exceptions.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" -#include "compiler/Registers.h" -#include "compiler/enode.h" -#include "compiler/objects.h" - -void pcsetrecordbit(PCode *pc) { - int reg; - PCodeArg *arg; - short argCount; - int argIdx; - - pc->flags &= ~(fIsMove | fCommutative | fIsCSE); - if ((pc->flags & fOpTypeMask) == fOpTypeFPR) { - reg = 1; - } else if ((pc->flags & fOpTypeMask) == fOpTypeVR) { - reg = 6; - } else { - reg = 0; - } - - if (pc->op == PC_ANDI || pc->op == PC_ANDIS) { - pc->flags |= fRecordBit; - } else if (pc->op == PC_ADDI || pc->op == PC_ADDIC) { - pc->flags |= fSetsCarry; - pc->flags |= fRecordBit; - change_num_operands(pc, 5); - pc->op = PC_ADDICR; - - CError_ASSERT(76, pc->args[3].kind == PCOp_PLACEHOLDEROPERAND); - pc->args[3].kind = PCOp_REGISTER; - pc->args[3].arg = RegClass_SPR; - pc->args[3].data.reg.reg = 0; - pc->args[3].data.reg.effect = EffectWrite; - CError_ASSERT(80, pc->args[4].kind == PCOp_PLACEHOLDEROPERAND); - pc->args[4].kind = PCOp_REGISTER; - pc->args[4].arg = RegClass_CRFIELD; - pc->args[4].data.reg.reg = reg; - pc->args[4].data.reg.effect = EffectWrite; - } else { - arg = pc->args; - argIdx = argCount = pc->argCount; - while (arg->kind != PCOp_PLACEHOLDEROPERAND && argIdx) { - if (arg->kind == PCOp_REGISTER && arg->arg == RegClass_CRFIELD && arg->data.reg.reg == reg) { - arg->data.reg.effect |= EffectWrite; - pc->flags |= fRecordBit; - return; - } - arg++; - argIdx--; - } - - if (argIdx <= 0) { - arg = &pc->args[argCount]; - pc->argCount++; - } - - CError_ASSERT(105, arg->kind == PCOp_PLACEHOLDEROPERAND); - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_CRFIELD; - arg->data.reg.reg = reg; - arg->data.reg.effect = EffectWrite; - if (pc->op != PC_ADDICR) - pc->flags |= fRecordBit; - } -} - -void pcsetsideeffects(PCode *pc) { - pc->flags &= ~(fIsMove | fCommutative | fIsCSE); - pc->flags |= fSideEffects; -} - -void pcsetlinkbit(PCode *pc) { - PCodeArg *arg; - int argIdx; - - switch (pc->op) { - case PC_B: - pc->op = PC_BL; - break; - case PC_BCTR: - pc->op = PC_BCTRL; - break; - case PC_BLR: - pc->op = PC_BLRL; - break; - } - - arg = pc->args; - argIdx = pc->argCount; - while (arg->kind != PCOp_PLACEHOLDEROPERAND && argIdx) { - if (arg->kind == PCOp_REGISTER && arg->arg == RegClass_SPR && arg->data.reg.reg == 1) { - arg->data.reg.effect |= EffectWrite; - pc->flags |= fLink; - return; - } - arg++; - argIdx--; - } - - CError_ASSERT(169, arg->kind == PCOp_PLACEHOLDEROPERAND); - arg->kind = PCOp_REGISTER; - arg->arg = RegClass_SPR; - arg->data.reg.reg = 1; - arg->data.reg.effect = EffectWrite; - - if (opcodeinfo[pc->op].flags & fIsCall) { - pc->flags &= ~fIsBranch; - pc->flags |= fIsCall; - } - pc->flags |= fLink; -} - -void branch_label(PCodeLabel *label) { - if (pclastblock->pcodeCount) { - pcbranch(pclastblock, label); - makepcblock(); - } - pclabel(pclastblock, label); -} - -void branch_conditional(short a, short compareop, short c, PCodeLabel *label) { - PCodeBlock *tmpblock; - PCodeLabel *tmplabel; - int r28; - - tmpblock = pclastblock; - tmplabel = makepclabel(); - - switch (compareop) { - case ENOTEQU: - c = !c; - case EEQU: - r28 = 2; - break; - case EGREATEREQU: - c = !c; - case ELESS: - r28 = 0; - break; - case ELESSEQU: - c = !c; - case EGREATER: - r28 = 1; - break; - } - - emitpcode(c ? PC_BT : PC_BF, a, r28, label); - pcbranch(pclastblock, label); - pcbranch(pclastblock, tmplabel); - makepcblock(); - pclabel(pclastblock, tmplabel); -} - -void branch_always(PCodeLabel *label) { - emitpcode(PC_B, label); - pcbranch(pclastblock, label); - makepcblock(); -} - -void branch_decrement_always(Opcode opcode, PCodeLabel *label) { - PCodeLabel *tmplabel = makepclabel(); - emitpcode(opcode, label); - pcbranch(pclastblock, label); - pcbranch(pclastblock, tmplabel); - makepcblock(); - pclabel(pclastblock, tmplabel); -} - -void branch_indirect(Object *obj) { - emitpcode(PC_BCTR, obj, 0); - makepcblock(); -} - -int branch_count_volatiles(void) { - int count = 0; - int i; - RegClass rclass; - - for (rclass = 0; rclass < RegClassMax; rclass++) { - for (i = 0; i < n_scratch_registers[rclass]; i++) { - count++; - } - } - - return count; -} - -PCodeArg *branch_record_volatiles(PCodeArg *arglist, UInt32 *masks) { - int i; - RegClass rclass; - - for (rclass = RegClassMax - 1; rclass >= 0; rclass--) { - for (i = 0; i < n_scratch_registers[rclass]; i++) { - arglist->kind = PCOp_REGISTER; - arglist->arg = rclass; - arglist->data.reg.reg = scratch_registers[rclass][i]; - arglist->data.reg.effect = EffectWrite; - if (masks[rclass] & (1 << scratch_registers[rclass][i])) - arglist->data.reg.effect |= EffectRead; - arglist++; - } - } - - return arglist; -} - -void branch_subroutine(Object *obj, short add_nop, UInt32 *masks) { - int count; - PCode *pc; - PCodeArg *arg; - - count = branch_count_volatiles(); - if (copts.exceptions && current_statement) - count += countexceptionactionregisters(current_statement->dobjstack); - - pc = makepcode(PC_BL, count, obj, 0); - arg = branch_record_volatiles(pc->args + 1, masks); - if (copts.exceptions && current_statement) - noteexceptionactionregisters(current_statement->dobjstack, arg); - appendpcode(pclastblock, pc); - - if (add_nop) - emitpcode(PC_NOP); - - branch_label(makepclabel()); - if (copts.exceptions && current_statement) - recordexceptionactions(pc, current_statement->dobjstack); -} - -void branch_subroutine_ctr(UInt32 *masks) { - int count; - PCode *pc; - PCodeArg *arg; - - count = branch_count_volatiles(); - if (copts.exceptions && current_statement) - count += countexceptionactionregisters(current_statement->dobjstack); - - pc = makepcode(PC_BCTRL, count); - arg = branch_record_volatiles(pc->args + 1, masks); - if (copts.exceptions && current_statement) - noteexceptionactionregisters(current_statement->dobjstack, arg); - appendpcode(pclastblock, pc); - - branch_label(makepclabel()); - if (copts.exceptions && current_statement) - recordexceptionactions(pc, current_statement->dobjstack); -} - -void add_immediate(short dest_reg, short base_reg, Object *obj, SInt16 offset) { - short tmp_reg = base_reg; - - if (obj && offset && obj->datatype != DLOCAL) { - tmp_reg = used_virtual_registers[RegClass_GPR]++; - add_immediate_lo(tmp_reg, base_reg, obj, 0, 1); - obj = NULL; - } - - if (!obj && !offset) - emitpcode(PC_MR, dest_reg, tmp_reg); - else - emitpcode(PC_ADDI, dest_reg, tmp_reg, obj, offset); -} - -PCode *add_immediate_lo(short dest_reg, short base_reg, Object *obj, SInt16 offset, char add_to_block) { - PCode *pc; - - CError_ASSERT(577, obj); - - pc = makepcode(PC_ADDI, dest_reg, base_reg, obj, offset); - if (add_to_block) - appendpcode(pclastblock, pc); - return pc; -} - -PCode *op_absolute_ha(short dest_reg, short base_reg, Object *obj, short offset, char add_to_block) { - PCode *pc; - int tmp_reg; - - if (obj->datatype == DLOCAL) { - pc = makepcode(PC_ADDIS, dest_reg, base_reg, obj, offset); - } else if (copts.codegen_pic) { - tmp_reg = base_reg; - CError_ASSERT(601, tmp_reg); - pc = makepcode(PC_ADDIS, dest_reg, tmp_reg, obj, offset); - } else { - CError_ASSERT(606, base_reg == 0); - pc = makepcode(PC_LIS, dest_reg, obj, offset); - } - - if (add_to_block) - appendpcode(pclastblock, pc); - return pc; -} - -void load_store_register(Opcode opcode, short dest_reg, short base_reg, Object *obj, SInt32 offset) { - short addi_tmp; - short offset_reg1; - short offset_reg2; - - offset_reg1 = base_reg; - if (obj && offset && obj->datatype != DLOCAL) { - offset_reg1 = used_virtual_registers[RegClass_GPR]++; - add_immediate_lo(offset_reg1, base_reg, obj, 0, 1); - obj = NULL; - } - - if (offset != (short)offset) { - if (opcode == PC_LWZ && dest_reg == 12) - offset_reg2 = 12; - else if (opcode == PC_LWZ && dest_reg == 11) - offset_reg2 = 11; - else - offset_reg2 = used_virtual_registers[RegClass_GPR]++; - - emitpcode(PC_ADDIS, offset_reg2, offset_reg1, 0, (short) ((offset >> 16) + ((offset & 0x8000) >> 15))); - offset = (short) offset; - offset_reg1 = offset_reg2; - } - - if (opcode == PC_STVX || opcode == PC_LVX) { - offset_reg2 = 0; - if (obj) { - addi_tmp = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_ADDI, addi_tmp, offset_reg1, obj, offset); - offset_reg1 = addi_tmp; - } else if (offset) { - offset_reg2 = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_LI, offset_reg2, offset); - } - if (!offset_reg2) - emitpcode(opcode, dest_reg, 0, offset_reg1); - else - emitpcode(opcode, dest_reg, offset_reg1, offset_reg2); - } else { - emitpcode(opcode, dest_reg, offset_reg1, obj, offset); - } -} diff --git a/compiler_and_linker/unsorted/PPCError.c b/compiler_and_linker/unsorted/PPCError.c deleted file mode 100644 index 2d4c469..0000000 --- a/compiler_and_linker/unsorted/PPCError.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "compiler/PPCError.h" -#include "compiler/CError.h" -#include "compiler/CParser.h" -#include "compiler/InlineAsm.h" -#include "cos.h" - -static void PPCError_GetErrorString(char *str, short code) { - short scode; - - scode = (short) code; - CError_ASSERT(40, scode >= 100 && scode < PPCErrorStrMAX); - - COS_GetString(str, 10001, scode - 99); -} - -static void PPCError_VAErrorMessage(int code, va_list list, Boolean flag1, Boolean flag2) { - char format[256]; - PPCError_GetErrorString(format, code); - CError_ErrorMessageVA(code + 10001, format, list, flag1, flag2); -} - -void PPCError_Error(int code, ...) { - va_list list; - - if (trychain) - longjmp(trychain->jmpbuf, 1); - - va_start(list, code); - PPCError_VAErrorMessage(code, list, 0, 0); - va_end(list); - - if (in_assembler) - AssemblerError(); -} - -void PPCError_Warning(int code, ...) { - va_list list; - - if (!trychain) { - va_start(list, code); - PPCError_VAErrorMessage(code, list, 0, 1); - va_end(list); - } -} - -void PPCError_Message(char *format, ...) { - va_list list; - - if (!trychain) { - va_start(list, format); - CError_ErrorMessageVA(10213, format, list, 0, 1); - va_end(list); - } -} - -void PPCError_ErrorTerm(short code, ...) { - va_list list; - - if (trychain) - longjmp(trychain->jmpbuf, 1); - - va_start(list, code); - PPCError_VAErrorMessage(code, list, 1, 0); - va_end(list); - - if (in_assembler) - AssemblerError(); - - longjmp(errorreturn, 1); -} diff --git a/compiler_and_linker/unsorted/Peephole.c b/compiler_and_linker/unsorted/Peephole.c deleted file mode 100644 index 151e448..0000000 --- a/compiler_and_linker/unsorted/Peephole.c +++ /dev/null @@ -1,2753 +0,0 @@ -#include "compiler/Peephole.h" -#include "compiler/CompilerTools.h" -#include "compiler/InstrSelection.h" -#include "compiler/PCode.h" -#include "compiler/objects.h" -#include "compiler/types.h" -#include "compiler/Scheduler.h" -#include "compiler/PCodeUtilities.h" -#include "compiler/Alias.h" -#include "compiler/CParser.h" - -typedef int (*PeepholeFunc)(PCode *instr, UInt32 *masks); - -typedef struct Pattern { - struct Pattern *next; - PeepholeFunc func; -} Pattern; - -typedef struct LiveRegs { - UInt32 x0; - UInt32 x4; - UInt32 x8; - UInt32 xC; -} LiveRegs; - -static LiveRegs *liveregs[RegClassMax]; -static Pattern *peepholepatterns[OPCODE_MAX]; -static PCode **defininginstruction; - -static void computeregisterusedefs(void) { - PCodeBlock *block; - PCode *instr; - PCodeArg *op; - int i; - RegClass rclass; - LiveRegs *lr; - UInt32 array1[RegClassMax]; - UInt32 array2[RegClassMax]; - - for (block = pcbasicblocks; block; block = block->nextBlock) { - for (rclass = 0; rclass < RegClassMax; rclass++) { - array1[rclass] = 0; - array2[rclass] = 0; - } - - for (instr = block->firstPCode; instr; instr = instr->nextPCode) { - for (op = instr->args, i = instr->argCount; i--; op++) { - if ( - op->kind == PCOp_REGISTER && - (op->data.reg.effect & EffectRead) && - !((1 << op->data.reg.reg) & array2[op->arg]) - ) - array1[op->arg] |= 1 << op->data.reg.reg; - } - - for (op = instr->args, i = instr->argCount; i--; op++) { - if ( - op->kind == PCOp_REGISTER && - (op->data.reg.effect & EffectWrite) && - !((1 << op->data.reg.reg) & array1[op->arg]) - ) - array2[op->arg] |= 1 << op->data.reg.reg; - } - } - - for (rclass = 0; rclass < RegClassMax; rclass++) { - lr = liveregs[rclass] + block->blockIndex; - lr->x0 = array1[rclass]; - lr->x4 = array2[rclass]; - if (rclass == RegClass_GPR) { - lr->x8 = 1 << 1; - lr->xC = 1 << 1; - } else { - lr->x8 = 0; - lr->xC = 0; - } - } - } -} - -static void computeliveness(LiveRegs *lrarray, UInt32 x) { - PCodeBlock *block; - LiveRegs *lr; - PCLink *link; - UInt32 newC; - UInt32 new8; - int i; - int flag; - - flag = 1; - while (flag) { - flag = 0; - i = pcblockcount; - while (i) { - if ((block = depthfirstordering[--i])) { - lr = lrarray + block->blockIndex; - newC = x; - for (link = block->successors; link; link = link->nextLink) - newC |= lrarray[link->block->blockIndex].x8; - lr->xC = newC; - - new8 = lr->x0 | (lr->xC & ~lr->x4); - if (new8 != lr->x8) { - lr->x8 = new8; - flag = 1; - } - } - } - } -} - -static void computeliveregisters(Object *func) { - Type *returntype; - RegClass rclass; - - returntype = TYPE_FUNC(func->type)->functype; - - for (rclass = 0; rclass < RegClassMax; rclass++) - liveregs[rclass] = lalloc(sizeof(LiveRegs) * pcblockcount); - - computedepthfirstordering(); - computeregisterusedefs(); - - if (TYPE_FITS_IN_REGISTER(returntype)) { - liveregs[RegClass_GPR][epilogue->blockIndex].x0 |= 1 << 3; - if (TYPE_IS_8BYTES(returntype)) - liveregs[RegClass_GPR][epilogue->blockIndex].x0 |= 1 << 4; - } else if (IS_TYPE_FLOAT(returntype)) { - liveregs[RegClass_FPR][epilogue->blockIndex].x0 |= 1 << 1; - } else if (IS_TYPE_VECTOR(returntype)) { - liveregs[RegClass_VR][epilogue->blockIndex].x0 |= 1 << 2; - } - - for (rclass = 0; rclass < RegClassMax; rclass++) { - if (rclass == RegClass_GPR) - computeliveness(liveregs[rclass], 2); - else - computeliveness(liveregs[rclass], 0); - } -} - -static void computeinstructionpredecessors(PCodeBlock *block) { - PCode *nop; - RegClass rclass; - SInt32 i; - SInt32 defID; - SInt32 totalOps; - PCode *instr; - PCodeArg *op; - PCode *array[RegClassMax][32]; - - nop = makepcode(PC_NOP); - for (rclass = 0; rclass < RegClassMax; rclass++) { - for (i = 0; i < 32; i++) { - array[rclass][i] = nop; - } - } - - totalOps = 0; - for (instr = block->firstPCode; instr; instr = instr->nextPCode) - totalOps += instr->argCount; - - if (totalOps) { - defininginstruction = oalloc(sizeof(PCode *) * totalOps); - for (i = 0; i < totalOps; i++) - defininginstruction[i] = nop; - - defID = 0; - for (instr = block->firstPCode; instr; instr = instr->nextPCode) { - instr->defID = defID; - - for (i = 0, op = instr->args; i < instr->argCount; i++, op++) { - if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectRead)) - defininginstruction[defID + i] = array[op->arg][op->data.reg.reg]; - } - - for (i = 0, op = instr->args; i < instr->argCount; i++, op++) { - if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite)) - array[op->arg][op->data.reg.reg] = instr; - } - - defID += instr->argCount; - } - } -} - -static int dead(PCode *instr, UInt32 *masks) { - int i; - PCodeArg *op; - - if (instr->block->flags & (fIsProlog | fIsEpilogue)) - return 0; - if (instr->flags & (fIsBranch | fIsWrite | fIsCall | fIsVolatile | fSideEffects)) - return 0; - if (!instr->block->predecessors) - return 1; - - for (op = instr->args, i = instr->argCount; i--; op++) { - if ( - op->kind == PCOp_REGISTER && - (op->data.reg.effect & EffectWrite) && - ((1 << op->data.reg.reg) & masks[op->arg]) - ) - return 0; - } - - return 1; -} - -static int definedbetween(PCode *start, PCode *end, PCodeArg *checkOp) { - PCode *instr; - PCodeArg *op; - int i; - - for (instr = start->prevPCode; instr != end; instr = instr->prevPCode) { - for (op = instr->args, i = instr->argCount; i--; op++) { - if (PC_OP_IS_WRITE_REGISTER(op, checkOp->arg, checkOp->data.reg.reg)) - return 1; - } - } - - return 0; -} - -static int usedbetween(PCode *start, PCode *end, PCodeArg *checkOp) { - PCode *instr; - PCodeArg *op; - int i; - - for (instr = start->prevPCode; instr != end; instr = instr->prevPCode) { - for (op = instr->args, i = instr->argCount; i--; op++) { - if (PC_OP_IS_READ_REGISTER(op, checkOp->arg, checkOp->data.reg.reg)) - return 1; - } - } - - return 0; -} - -static int isSPRlive(PCode *instr, int reg) { - PCode *scan; - PCodeArg *op; - int i; - - for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { - for (op = scan->args, i = scan->argCount; i--; op++) { - if (PC_OP_IS_READ_REGISTER(op, RegClass_SPR, reg)) - return 1; - - if (PC_OP_IS_WRITE_REGISTER(op, RegClass_SPR, reg)) - return 0; - } - } - - return 0; -} - -static SInt32 extractedbits(PCode *instr) { - SInt32 a = instr->args[2].data.imm.value; - SInt32 b = instr->args[3].data.imm.value; - SInt32 c = instr->args[4].data.imm.value; - SInt32 val; - - if (b <= c) - val = ((b > 31) ? 0 : (0xFFFFFFFFu >> b)) & ~(((c + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c + 1))); - else - val = ((b > 31) ? 0 : (0xFFFFFFFFu >> b)) | ~(((c + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c + 1))); - - return ((UInt32) val >> a) | (val << (32 - a)); -} - -static int canmergemasks(SInt32 b1, SInt32 c1, SInt32 a, SInt32 b2, SInt32 c2, short *first, short *last) { - SInt32 val1; - SInt32 val2; - - if (b1 <= c1) - val1 = ((b1 > 31) ? 0 : (0xFFFFFFFFu >> b1)) & ~(((c1 + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c1 + 1))); - else - val1 = ((b1 > 31) ? 0 : (0xFFFFFFFFu >> b1)) | ~(((c1 + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c1 + 1))); - - if (b2 <= c2) - val2 = ((b2 > 31) ? 0 : (0xFFFFFFFFu >> b2)) & ~(((c2 + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c2 + 1))); - else - val2 = ((b2 > 31) ? 0 : (0xFFFFFFFFu >> b2)) | ~(((c2 + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c2 + 1))); - - return ismaskconstant(val2 & ((val1 << a) | ((UInt32) val1 >> (32 - a))), first, last); -} - -static int canuseupdatetest(PCodeBlock *block, PCode *instr, int count1, int count2, int count3, int count4, int count5) { - int i; - PCLink *link; - - while (instr) { - if (++count1 > 17) - return 1; - - switch (instr->op) { - case PC_DIVW: - case PC_DIVWU: - case PC_MULHW: - case PC_MULHWU: - case PC_MULLI: - case PC_MULLW: - return count3 == 0; - case PC_MTXER: - case PC_MTCTR: - case PC_MTLR: - case PC_MTCRF: - case PC_MTMSR: - case PC_MTSPR: - case PC_MFMSR: - case PC_MFSPR: - case PC_MFXER: - case PC_MFCTR: - case PC_MFLR: - case PC_MFCR: - case PC_ECIWX: - case PC_ECOWX: - case PC_DCBI: - case PC_ICBI: - case PC_MCRFS: - case PC_MCRXR: - case PC_MFTB: - case PC_MFSR: - case PC_MTSR: - case PC_MFSRIN: - case PC_MTSRIN: - case PC_MTFSB0: - case PC_MTFSB1: - case PC_MTFSFI: - case PC_SC: - case PC_TLBIA: - case PC_TLBIE: - case PC_TLBLD: - case PC_TLBLI: - case PC_TLBSYNC: - case PC_TW: - case PC_TRAP: - case PC_TWI: - case PC_MFROM: - case PC_DSA: - case PC_ESA: - return 1; - case PC_CRAND: - case PC_CRANDC: - case PC_CREQV: - case PC_CRNAND: - case PC_CRNOR: - case PC_CROR: - case PC_CRORC: - case PC_CRXOR: - case PC_MCRF: - if (++count5 > 1) - return 1; - } - - if (instr->flags & (fIsRead | fIsWrite)) { - if (++count4 > 1) - return 1; - } else if (instr->flags & fIsBranch) { - if (++count2 > 2) - return 1; - - for (i = 0; i < instr->argCount; i++) { - if (PC_OP_IS_ANY_REGISTER(&instr->args[i], RegClass_CRFIELD)) { - ++count3; - break; - } - } - } - - instr = instr->nextPCode; - } - - if (block && block->successors) { - for (link = block->successors; link; link = link->nextLink) { - if (link->block && !canuseupdatetest(link->block, link->block->firstPCode, count1, count2, count3, count4, count5)) - return 0; - } - } - - return 1; -} - -static int canuseupdate(PCode *instr) { - return canuseupdatetest(instr->block, instr->nextPCode, 0, 0, 0, 0, 0); -} - -static int MR_Rx_Rx(PCode *instr, UInt32 *masks) { - if ( - instr->args[0].data.reg.reg == instr->args[1].data.reg.reg && - !(PCODE_FLAG_SET_F(instr) & fRecordBit) - ) - { - deletepcode(instr); - return 1; - } - - return 0; -} - -static int FMR_Fx_Fx(PCode *instr, UInt32 *masks) { - if ( - instr->args[0].data.reg.reg == instr->args[1].data.reg.reg && - !(PCODE_FLAG_SET_F(instr) & fRecordBit) - ) - { - deletepcode(instr); - return 1; - } - - return 0; -} - -static int VMR_Vx_Vx(PCode *instr, UInt32 *masks) { - if ( - instr->args[0].data.reg.reg == instr->args[1].data.reg.reg && - !(PCODE_FLAG_SET_F(instr) & fRecordBit) - ) - { - deletepcode(instr); - return 1; - } - - return 0; -} - -static int MR_MR(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - - if ( - defInstr->op == PC_MR && - instr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && - !definedbetween(instr, defInstr, &instr->args[0]) && - !(PCODE_FLAG_SET_F(instr) & fRecordBit) - ) - { - deletepcode(instr); - return 1; - } - - return 0; -} - -static int FMR_FMR(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - - if ( - defInstr->op == PC_FMR && - instr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && - !(PCODE_FLAG_SET_F(instr) & fRecordBit) && - !definedbetween(instr, defInstr, &instr->args[0]) - ) - { - deletepcode(instr); - return 1; - } - - return 0; -} - -static int VMR_VMR(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - - if ( - defInstr->op == PC_VMR && - instr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && - !(PCODE_FLAG_SET_F(instr) & fRecordBit) && - !definedbetween(instr, defInstr, &instr->args[0]) - ) - { - deletepcode(instr); - return 1; - } - - return 0; -} - -static int VMR_VMRP(PCode *instr, UInt32 *masks) { - PCode *prev = instr->prevPCode; - PCode *next = instr->nextPCode; - int prevFlag = 0; - int prevPermute = 0; - int nextFlag = 0; - int nextPermute = 0; - - if (prev) { - prevFlag = (prev->flags & fOpTypeMask) == fOpTypeVR; - prevPermute = uses_vpermute_unit(prev); - } - if (next) { - nextFlag = (next->flags & fOpTypeMask) == fOpTypeVR; - nextPermute = uses_vpermute_unit(next); - } - - if (prev) { - if (next) { - if (prevFlag && !prevPermute) { - if (nextFlag) { - if (!nextPermute) { - change_opcode(instr, PC_VMRP); - return 1; - } - } else { - change_opcode(instr, PC_VMRP); - return 1; - } - } - } else { - if (prevFlag && !prevPermute) { - change_opcode(instr, PC_VMRP); - return 1; - } - } - } else { - if (next && nextFlag && !nextPermute) { - change_opcode(instr, PC_VMRP); - return 1; - } - } - - return 0; -} - -static int MR_CMPI(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - PCodeArg op; - - if ( - instr->args[0].data.reg.reg == 0 && - instr->args[2].data.imm.value == 0 && - (PCODE_FLAG_SET_F(defInstr) & (fSideEffects | fCanSetRecordBit | fOpTypeGPR)) == (fCanSetRecordBit | fOpTypeGPR) && - !usedbetween(instr, defInstr, &instr->args[0]) && - !definedbetween(instr, defInstr, &instr->args[0]) - ) - { - if (defInstr->op == PC_ADDI) { - op.kind = PCOp_REGISTER; - op.arg = RegClass_SPR; - op.data.reg.reg = 0; - op.data.reg.effect = EffectRead | EffectWrite; - if (usedbetween(instr, defInstr, &op)) - return 0; - } - - pcsetrecordbit(defInstr); - deletepcode(instr); - return 1; - } - - return 0; -} - -static int EXTSB_RLWINM(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - - if ( - defInstr->op == PC_EXTSB && - (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && - !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && - !definedbetween(instr, defInstr, &defInstr->args[1]) && - !usedbetween(instr, defInstr, &defInstr->args[0]) && - (extractedbits(instr) & 0xFFFFFF00) == 0 - ) - { - instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; - defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; - deletepcode(defInstr); - return 1; - } - - return 0; -} - -static int EXTSH_RLWINM(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - - if ( - defInstr->op == PC_EXTSH && - (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && - !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && - !definedbetween(instr, defInstr, &defInstr->args[1]) && - !usedbetween(instr, defInstr, &defInstr->args[0]) && - (extractedbits(instr) & 0xFFFF0000) == 0 - ) - { - instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; - defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; - deletepcode(defInstr); - return 1; - } - - return 0; -} - -static int LBZ_RLWINM(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - - if ( - (defInstr->op == PC_LBZ || defInstr->op == PC_LBZX) && - instr->args[2].data.imm.value == 0 && - instr->args[3].data.imm.value <= 24 && - instr->args[4].data.imm.value == 31 && - !(PCODE_FLAG_SET_F(instr) & fRecordBit) && - (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && - !usedbetween(instr, defInstr, &defInstr->args[0]) && - !definedbetween(instr, defInstr, &instr->args[0]) && - !usedbetween(instr, defInstr, &instr->args[0]) - ) - { - defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg; - deletepcode(instr); - return 1; - } - - return 0; -} - -static int LHZ_RLWINM(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - - if ( - (defInstr->op == PC_LHZ || defInstr->op == PC_LHZX) && - instr->args[2].data.imm.value == 0 && - instr->args[3].data.imm.value <= 16 && - instr->args[4].data.imm.value == 31 && - !(PCODE_FLAG_SET_F(instr) & fRecordBit) && - (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && - !usedbetween(instr, defInstr, &defInstr->args[0]) && - !definedbetween(instr, defInstr, &instr->args[0]) && - !usedbetween(instr, defInstr, &instr->args[0]) - ) - { - defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg; - deletepcode(instr); - return 1; - } - - return 0; -} - -static int LHA_EXTSH(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - - if ( - defInstr->op == PC_LHA && - !(PCODE_FLAG_SET_F(instr) & fRecordBit) && - (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && - !usedbetween(instr, defInstr, &defInstr->args[0]) && - !definedbetween(instr, defInstr, &instr->args[0]) && - !usedbetween(instr, defInstr, &instr->args[0]) - ) - { - defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg; - deletepcode(instr); - return 1; - } - - if ( - defInstr->op == PC_EXTSB && - !(PCODE_FLAG_SET_F(instr) & fRecordBit) - ) - { - if (defInstr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg) { - if ( - !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg)) && - !usedbetween(instr, defInstr, &defInstr->args[0]) - ) - { - change_opcode(instr, PC_EXTSB); - deletepcode(defInstr); - return 1; - } - } else { - if (!definedbetween(instr, defInstr, &defInstr->args[1])) { - change_opcode(instr, PC_EXTSB); - instr->args[1] = defInstr->args[1]; - } else { - change_opcode(instr, PC_MR); - } - return 1; - } - } - - return 0; -} - -static int ADDI_L_S(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - SInt32 addleft; - SInt32 addright; - - if (defInstr->op == PC_ADDI && instr->args[2].kind == PCOp_IMMEDIATE) { - if (!PC_OP_IS_REGISTER(&instr->args[0], RegClass_GPR, instr->args[1].data.reg.reg)) { - if ( - instr->args[2].data.imm.value == 0 && - defInstr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && - !usedbetween(instr, defInstr, &defInstr->args[0]) && - (!(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg)) || canuseupdate(instr)) - ) - { - if (!(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) { - instr->args[2] = defInstr->args[2]; - } else { - instr->op++; - instr->args[1].data.reg.effect |= EffectWrite; - instr->args[2] = defInstr->args[2]; - } - defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; - deletepcode(defInstr); - return 1; - } - - addleft = 0x1FFFF; - addright = instr->args[2].data.imm.value; - if (defInstr->args[2].kind == PCOp_IMMEDIATE) { - addleft = defInstr->args[2].data.imm.value; - } else if (defInstr->args[2].kind == PCOp_MEMORY) { - if (defInstr->args[2].data.mem.obj->datatype == DLOCAL) - addleft = defInstr->args[2].data.mem.offset + defInstr->args[2].data.mem.obj->u.var.uid; - else if (addright == 0) - addleft = 0; - else - return 0; - } - - if (!FITS_IN_SHORT(addleft + addright)) - return 0; - - if ( - !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg)) && - !usedbetween(instr, defInstr, &defInstr->args[0]) && - !definedbetween(instr, defInstr, &defInstr->args[1]) - ) - { - instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; - defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; - - if (defInstr->args[2].kind == PCOp_MEMORY) { - instr->args[2] = defInstr->args[2]; - instr->args[2].data.mem.offset += addright; - if (instr->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) { - instr->alias = make_alias( - instr->args[2].data.mem.obj, - instr->args[2].data.mem.offset, - nbytes_loaded_or_stored_by(instr) - ); - } - } else { - instr->args[2].data.imm.value = addleft + addright; - } - - deletepcode(defInstr); - return 1; - } - - if ( - instr->args[1].data.reg.reg != defInstr->args[1].data.reg.reg && - !definedbetween(instr, defInstr, &defInstr->args[1]) - ) - { - if (defInstr->args[2].kind == PCOp_MEMORY && defInstr->args[2].data.mem.obj->datatype != DLOCAL) - return 0; - - instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; - defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; - - if (defInstr->args[2].kind == PCOp_MEMORY) { - instr->args[2] = defInstr->args[2]; - instr->args[2].data.mem.offset += addright; - if (instr->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) { - instr->alias = make_alias( - instr->args[2].data.mem.obj, - instr->args[2].data.mem.offset, - nbytes_loaded_or_stored_by(instr) - ); - } - } else { - instr->args[2].data.imm.value = addleft + addright; - } - - return 1; - } - } - } else { - if ( - defInstr->op == PC_MR && - PC_OP_IS_ANY_REGISTER(&defInstr->args[1], RegClass_GPR) && - defInstr->args[1].data.reg.reg != 0 && - !definedbetween(instr, defInstr, &defInstr->args[1]) - ) - { - instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; - defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; - } - } - - return 0; -} - -static int ADDI_LU_SU(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - - if ( - instr->args[2].kind == PCOp_IMMEDIATE && - defInstr->args[2].kind == PCOp_IMMEDIATE && - defInstr->op == PC_ADDI && - defInstr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && - !(instr->args[0].arg == instr->args[1].arg && instr->args[0].data.reg.reg == instr->args[1].data.reg.reg) && - !usedbetween(instr, defInstr, &defInstr->args[0]) && - FITS_IN_SHORT(instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) - ) - { - if ((instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) == 0) { - instr->op--; - instr->args[1].data.reg.effect &= ~EffectWrite; - instr->args[2].data.imm.value = 0; - } else { - instr->args[2].data.imm.value += defInstr->args[2].data.imm.value; - } - - defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; - deletepcode(defInstr); - return 1; - } - - return 0; -} - -static int L_S_ADDI(PCode *instr, UInt32 *masks) { - PCode *scan; - PCodeArg *op; - int i; - short reg; - - if (instr->args[2].kind != PCOp_IMMEDIATE) - return 0; - - reg = instr->args[1].data.reg.reg; - if (!canuseupdate(instr)) - return 0; - - for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { - for (op = scan->args, i = scan->argCount; i--; op++) { - if (PC_OP_IS_READ_REGISTER(op, RegClass_GPR, reg)) - return 0; - - if (PC_OP_IS_WRITE_REGISTER(op, RegClass_GPR, reg)) { - if (scan->op != PC_ADDI) - return 0; - if (scan->args[2].kind != PCOp_IMMEDIATE) - return 0; - - if ( - instr->args[2].data.imm.value == scan->args[2].data.imm.value && - scan->args[0].data.reg.reg == scan->args[1].data.reg.reg && - !(instr->args[0].arg == instr->args[1].arg && instr->args[0].data.reg.reg == instr->args[1].data.reg.reg) - ) - { - if (!(masks[RegClass_GPR] & (1 << scan->args[0].data.reg.reg))) { - instr->args[2] = scan->args[2]; - } else { - instr->op++; - instr->args[1].data.reg.effect |= EffectWrite; - instr->args[2] = scan->args[2]; - } - - change_opcode(scan, PC_NOP); - change_num_operands(scan, 0); - deletepcode(scan); - return 1; - } - - return 0; - } - } - } - - return 0; -} - -static int LI_CMP_BC(PCode *instr, UInt32 *masks) { - PCode *defInstr; - PCode *defInstr2; - PCLink *link; - PCLink **ptr; - - if (instr->args[1].data.imm.value == 2) { - defInstr = defininginstruction[instr->defID]; - if ((defInstr->op == PC_CMPLI || defInstr->op == PC_CMPI) && defInstr->args[0].data.reg.reg == 0) { - defInstr2 = defininginstruction[defInstr->defID + 1]; - if ( - defInstr2->op == PC_LI && - defInstr2->args[1].kind == PCOp_IMMEDIATE && - (instr->op == PC_BT) == (defInstr2->args[1].data.imm.value == defInstr->args[2].data.imm.value) - ) - { - change_opcode(instr, PC_B); - instr->args[0] = instr->args[2]; - change_num_operands(instr, 1); - - defininginstruction[instr->defID] = defininginstruction[instr->defID + 1]; - - for (ptr = &instr->block->successors; (link = *ptr); ptr = &link->nextLink) { - if (link->block == instr->block->nextBlock) { - *ptr = link->nextLink; - break; - } - } - - for (ptr = &instr->block->nextBlock->predecessors; (link = *ptr); ptr = &link->nextLink) { - if (link->block == instr->block) { - *ptr = link->nextLink; - break; - } - } - } - } - } - - return 0; -} - -static int RLWINM_CMPLI_BC(PCode *instr, UInt32 *masks) { - PCode *defInstr; - PCode *defInstr2; - - if (instr->args[1].data.imm.value == 2) { - defInstr = defininginstruction[instr->defID]; - if (defInstr->op == PC_CMPLI && defInstr->args[0].data.reg.reg == 0 && defInstr->args[2].data.imm.value == 0) { - defInstr2 = defininginstruction[defInstr->defID + 1]; - if ( - (PCODE_FLAG_SET_F(defInstr2) & (fSideEffects | fCanSetRecordBit | fOpTypeGPR)) == (fCanSetRecordBit | fOpTypeGPR) && - !usedbetween(defInstr, defInstr2, &defInstr->args[0]) && - !definedbetween(defInstr, defInstr2, &defInstr->args[0]) - ) - { - pcsetrecordbit(defInstr2); - defininginstruction[instr->defID] = defininginstruction[defInstr->defID + 1]; - deletepcode(defInstr); - return 1; - } - } - } - - return 0; -} - -static int LBZ_EXTSB_CMPI_BC(PCode *instr, UInt32 *masks) { - PCode *defInstr; - PCode *defInstr2; - - if (instr->args[1].data.imm.value == 2) { - defInstr = defininginstruction[instr->defID]; - if ( - ( - (defInstr->op == PC_CMPI || defInstr->op == PC_CMPLI) && - defInstr->args[2].data.imm.value >= 0 && - defInstr->args[2].data.imm.value <= 127 - ) - || - ( - (defInstr->op == PC_EXTSB || defInstr->op == PC_EXTSH) && - (PCODE_FLAG_SET_F(defInstr) & fRecordBit) - ) - ) - { - defInstr2 = defininginstruction[defInstr->defID + 1]; - if ( - defInstr2->op == PC_EXTSB && - defininginstruction[defInstr2->defID + 1]->op == PC_LBZ && - !(masks[RegClass_GPR] & (1 << defInstr2->args[0].data.reg.reg)) && - !usedbetween(instr, defInstr, &defInstr2->args[0]) && - !usedbetween(defInstr, defInstr2, &defInstr2->args[0]) && - !definedbetween(defInstr, defInstr2, &defInstr2->args[1]) - ) - { - defInstr->args[1].data.reg.reg = defInstr2->args[1].data.reg.reg; - defininginstruction[defInstr->defID + 1] = defininginstruction[defInstr2->defID + 1]; - deletepcode(defInstr2); - return 1; - } - } - } - - return 0; -} - -static int FRSP_STFS(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID]; - - if ( - defInstr->op == PC_FRSP && - !(masks[RegClass_FPR] & (1 << defInstr->args[0].data.reg.reg)) && - !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && - !definedbetween(instr, defInstr, &defInstr->args[1]) && - !usedbetween(instr, defInstr, &defInstr->args[0]) - ) - { - instr->args[0].data.reg.reg = defInstr->args[1].data.reg.reg; - defininginstruction[instr->defID] = defininginstruction[defInstr->defID + 1]; - deletepcode(defInstr); - return 1; - } - - return 0; -} - -static int NOT_AND(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 2]; - - if ( - defInstr->op == PC_NOT && - (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && - !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && - !definedbetween(instr, defInstr, &defInstr->args[1]) && - !usedbetween(instr, defInstr, &defInstr->args[0]) - ) - { - instr->args[2].data.reg.reg = defInstr->args[1].data.reg.reg; - defininginstruction[instr->defID + 2] = defininginstruction[defInstr->defID + 1]; - change_opcode(instr, PC_ANDC); - deletepcode(defInstr); - return 1; - } - - return 0; -} - -static int LI_MR(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - - if ( - defInstr->op == PC_LI && - (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && - !(PCODE_FLAG_SET_F(instr) & fRecordBit) && - !usedbetween(instr, defInstr, &defInstr->args[0]) - ) - { - change_opcode(instr, PC_LI); - instr->args[1] = defInstr->args[1]; - defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; - deletepcode(defInstr); - return 1; - } - - return 0; -} - -static int VSPLTIS_VMR(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - short opcode = defInstr->op; - - if ( - (opcode == PC_VSPLTISB || opcode == PC_VSPLTISH || opcode == PC_VSPLTISW) && - (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_VR] & (1 << defInstr->args[0].data.reg.reg))) && - !(PCODE_FLAG_SET_F(instr) & fRecordBit) && - !usedbetween(instr, defInstr, &defInstr->args[0]) - ) - { - change_opcode(instr, opcode); - instr->args[1] = defInstr->args[1]; - defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; - deletepcode(defInstr); - return 1; - } - - return 0; -} - -static int L_MR(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - - if ( - (defInstr->flags & fIsRead) && - !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg)) && - !(PCODE_FLAG_SET_F(instr) & fRecordBit) && - !usedbetween(instr, defInstr, &defInstr->args[0]) && - !usedbetween(instr, defInstr, &instr->args[0]) && - !definedbetween(instr, defInstr, &instr->args[0]) - ) - { - defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg; - deletepcode(instr); - return 1; - } - - return 0; -} - -static int L_FMR(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - - if ( - (defInstr->flags & fIsRead) && - !(masks[RegClass_FPR] & (1 << defInstr->args[0].data.reg.reg)) && - !(PCODE_FLAG_SET_F(instr) & fRecordBit) && - !usedbetween(instr, defInstr, &defInstr->args[0]) && - !usedbetween(instr, defInstr, &instr->args[0]) && - !definedbetween(instr, defInstr, &instr->args[0]) - ) - { - defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg; - deletepcode(instr); - return 1; - } - - return 0; -} - -static int L_S(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID]; - SInt32 isIndexed; - SInt32 isFloat; - SInt32 isVector; - PCode *scan; - SInt32 loadSize; - SInt32 defInstrOffset; - SInt32 scanOffset; - SInt32 storeSize; - - if (PCODE_FLAG_SET_F(instr) & (fIsVolatile | fSideEffects | fUpdatesPtr)) - return 0; - if (PCODE_FLAG_SET_F(defInstr) & (fIsVolatile | fSideEffects | fUpdatesPtr)) - return 0; - - if ( - (defInstr->flags & fIsRead) && - PC_OP_IS_REGISTER(&defInstr->args[1], RegClass_GPR, instr->args[1].data.reg.reg) && - defInstr->args[2].kind == instr->args[2].kind && - !definedbetween(instr, defInstr, &instr->args[1]) - ) - { - if (instr->args[2].kind == PCOp_IMMEDIATE) { - if (instr->args[2].data.imm.value != defInstr->args[2].data.imm.value) - return 0; - } else if (instr->args[2].kind == PCOp_MEMORY) { - if (instr->args[2].data.mem.offset != defInstr->args[2].data.mem.offset || - instr->args[2].data.mem.obj != defInstr->args[2].data.mem.obj) - return 0; - } else if (instr->args[2].kind == PCOp_REGISTER && instr->args[2].arg == RegClass_GPR) { - if (instr->args[2].data.reg.reg != defInstr->args[2].data.reg.reg || - definedbetween(instr, defInstr, &instr->args[2])) - return 0; - } else { - return 0; - } - - isIndexed = 0; - isFloat = 0; - isVector = 0; - switch (defInstr->op) { - case PC_LBZX: - isIndexed = 1; - case PC_LBZ: - loadSize = 1; - break; - case PC_LHZX: - case PC_LHAX: - isIndexed = 1; - case PC_LHZ: - case PC_LHA: - loadSize = 2; - break; - case PC_LWZX: - isIndexed = 1; - case PC_LWZ: - loadSize = 4; - break; - case PC_LFSX: - isIndexed = 1; - case PC_LFS: - isFloat = 1; - loadSize = 4; - break; - case PC_LFDX: - isIndexed = 1; - case PC_LFD: - isFloat = 1; - loadSize = 8; - break; - case PC_LVX: - case PC_LVXL: - isIndexed = 1; - isVector = 1; - loadSize = 16; - break; - default: - return 0; - } - - switch (instr->op) { - case PC_STBX: - if (!isIndexed) return 0; - case PC_STB: - if (isFloat) return 0; - if (loadSize != 1) return 0; - break; - case PC_STHX: - if (!isIndexed) return 0; - case PC_STH: - if (isFloat) return 0; - if (loadSize != 2) return 0; - break; - case PC_STWX: - if (!isIndexed) return 0; - case PC_STW: - if (isFloat) return 0; - if (loadSize != 4) return 0; - break; - case PC_STFSX: - if (!isIndexed) return 0; - case PC_STFS: - if (!isFloat) return 0; - if (loadSize != 4) return 0; - break; - case PC_STFDX: - if (!isIndexed) return 0; - case PC_STFD: - if (!isFloat) return 0; - if (loadSize != 8) return 0; - break; - case PC_STVX: - case PC_STVXL: - if (!isIndexed) return 0; - if (!isVector) return 0; - if (loadSize != 16) return 0; - break; - default: - return 0; - } - - for (scan = instr->prevPCode; scan && scan != defInstr; scan = scan->prevPCode) { - if (scan->flags & fIsWrite) { - if (scan->args[1].data.reg.reg != instr->args[1].data.reg.reg) - return 0; - if (scan->args[2].kind != defInstr->args[2].kind) - return 0; - - if (scan->args[2].kind == PCOp_MEMORY) { - if (instr->args[2].data.mem.obj == scan->args[2].data.mem.obj) { - if (instr->args[2].data.mem.offset == defInstr->args[2].data.mem.offset) - return 0; - defInstrOffset = defInstr->args[2].data.mem.offset; - scanOffset = scan->args[2].data.mem.offset; - } - } else if (scan->args[2].kind == PCOp_IMMEDIATE) { - if (instr->args[1].data.reg.reg != scan->args[1].data.reg.reg) - return 0; - if (instr->args[2].data.imm.value == scan->args[2].data.imm.value) - return 0; - defInstrOffset = defInstr->args[2].data.imm.value; - scanOffset = scan->args[2].data.imm.value; - } else { - return 0; - } - - switch (scan->op) { - case PC_STB: - case PC_STBX: - storeSize = 1; - break; - case PC_STH: - case PC_STHX: - storeSize = 2; - break; - case PC_STW: - case PC_STWX: - case PC_STFS: - case PC_STFSX: - storeSize = 4; - break; - case PC_STFD: - case PC_STFDX: - storeSize = 8; - break; - case PC_STVX: - case PC_STVXL: - storeSize = 16; - break; - default: - return 0; - } - - if (defInstrOffset > scanOffset) { - if ((scanOffset + storeSize) > defInstrOffset) - return 0; - } else { - if ((defInstrOffset + loadSize) > scanOffset) - return 0; - } - } - } - - deletepcode(instr); - return 1; - } - - return 0; -} - -static int RLWINM_RLWINM(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - short start; - short end; - - if ( - defInstr->op == PC_RLWINM && - !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && - !definedbetween(instr, defInstr, &defInstr->args[1]) && - !( - defInstr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg && - ( - (defInstr->args[0].data.reg.reg != instr->args[0].data.reg.reg && (masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) || - usedbetween(instr, defInstr, &defInstr->args[0]) - ) - ) && - canmergemasks( - defInstr->args[3].data.imm.value, - defInstr->args[4].data.imm.value, - instr->args[2].data.imm.value, - instr->args[3].data.imm.value, - instr->args[4].data.imm.value, - &start, &end) - ) - { - if (instr->op == PC_RLWIMI) { - if (instr->args[0].data.reg.reg == defInstr->args[0].data.reg.reg) - return 0; - if (start != instr->args[3].data.imm.value || end != instr->args[4].data.imm.value) - return 0; - } - - instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; - defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; - - instr->args[2].data.imm.value = (instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) & 31; - instr->args[3].data.imm.value = start; - instr->args[4].data.imm.value = end; - - if ( - (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && - !usedbetween(instr, defInstr, &defInstr->args[0]) - ) - deletepcode(defInstr); - - return 1; - } - - if ( - defInstr->op == PC_MR && - instr->op == PC_RLWINM && - !definedbetween(instr, defInstr, &defInstr->args[1]) - ) - { - instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; - defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; - - if ( - (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && - !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && - !usedbetween(instr, defInstr, &defInstr->args[0]) - ) - deletepcode(defInstr); - - return 1; - } - - return 0; -} - -static int MULLI_MULLI(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - - if ( - defInstr->op == PC_MULLI && - (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && - !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && - !definedbetween(instr, defInstr, &defInstr->args[1]) && - !usedbetween(instr, defInstr, &defInstr->args[0]) && - FITS_IN_SHORT(instr->args[2].data.imm.value * defInstr->args[2].data.imm.value) - ) - { - instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; - defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; - - instr->args[2].data.imm.value *= defInstr->args[2].data.imm.value; - deletepcode(defInstr); - return 1; - } - - return 0; -} - -static int ADDI_ADDI(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - - if ( - defInstr->op == PC_ADDI && - (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && - !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && - !definedbetween(instr, defInstr, &defInstr->args[1]) && - !usedbetween(instr, defInstr, &defInstr->args[0]) && - instr->args[2].kind == PCOp_IMMEDIATE && - defInstr->args[2].kind == PCOp_IMMEDIATE && - FITS_IN_SHORT(instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) - ) - { - instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; - defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; - - instr->args[2].data.imm.value += defInstr->args[2].data.imm.value; - deletepcode(defInstr); - return 1; - } - - return 0; -} - -static int SRAWI_SRAWI(PCode *instr, UInt32 *masks) { - PCode *defInstr = defininginstruction[instr->defID + 1]; - - if ( - defInstr->op == PC_SRAWI && - (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) && - !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) && - !definedbetween(instr, defInstr, &defInstr->args[1]) && - !usedbetween(instr, defInstr, &defInstr->args[0]) && - instr->args[2].kind == PCOp_IMMEDIATE && - defInstr->args[2].kind == PCOp_IMMEDIATE && - (instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) < 32 && - (instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) > 0 - ) - { - instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg; - defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1]; - - instr->args[2].data.imm.value += defInstr->args[2].data.imm.value; - deletepcode(defInstr); - return 1; - } - - return 0; -} - -static int MR_ADDI(PCode *instr, UInt32 *masks) { - PCode *prev = instr->prevPCode; - PCode *next = instr->nextPCode; - int prevFlag = 0; - int nextFlag = 0; - - if (copts.processor == CPU_PPC603e) { - if (prev) - prevFlag = (prev->flags & fOpTypeMask) == fOpTypeGPR; - if (next) - nextFlag = (next->flags & fOpTypeMask) == fOpTypeGPR; - - if ( - !(PCODE_FLAG_SET_F(instr) & fRecordBit) && - instr->argCount >= 2 && - instr->args[1].data.reg.reg != 0 && - (prevFlag || nextFlag) - ) - { - change_opcode(instr, PC_ADDI); - instr->args[2].kind = PCOp_IMMEDIATE; - instr->args[2].data.imm.value = 0; - instr->args[2].data.imm.obj = NULL; - change_num_operands(instr, 3); - } - } - - return 0; -} - -static int rotatedefinedusedtest(UInt32 *masks, PCode *instr, PCode *a, PCode *b, PCode *subfic) { - PCode *scan; - PCodeArg *op; - int i; - int reg1; - int reg2; - - if ( - (masks[RegClass_GPR] & (1 << subfic->args[0].data.reg.reg)) && - subfic->args[0].data.reg.reg != instr->args[0].data.reg.reg && - subfic->args[0].data.reg.reg != a->args[2].data.reg.reg - ) - return 1; - - for (scan = instr->block->firstPCode; scan != instr->block->lastPCode; scan = scan->nextPCode) { - if (scan == a) break; - if (scan == b) break; - if (scan == subfic) break; - } - - reg1 = a->args[1].data.reg.reg; - reg2 = subfic->args[1].data.reg.reg; - while (scan != instr) { - for (op = instr->args, i = instr->argCount; i--; op++) { - if ( - op->kind == PCOp_REGISTER && - op->arg == RegClass_GPR && - ( - ( - (op->data.reg.reg == reg1 || op->data.reg.reg == reg2) && - (op->data.reg.effect & EffectWrite) - ) - || - ( - op->data.reg.reg == subfic->args[0].data.reg.reg && (op->data.reg.effect & EffectRead) - ) - ) && - scan != a && - scan != b && - scan != subfic - ) - return 1; - } - - scan = scan->nextPCode; - } - - return 0; -} - -static int SRW_SUBFIC_RLW_OR(PCode *instr, UInt32 *masks) { - PCode *subfic; - PCode *defInstr1 = defininginstruction[instr->defID + 1]; - PCode *defInstr2 = defininginstruction[instr->defID + 2]; - - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - return 0; - - if ( - (masks[RegClass_GPR] & (1 << instr->args[1].data.reg.reg)) && - instr->args[1].data.reg.reg != instr->args[0].data.reg.reg - ) - return 0; - - if ( - (masks[RegClass_GPR] & (1 << instr->args[2].data.reg.reg)) && - instr->args[1].data.reg.reg != instr->args[0].data.reg.reg - ) - return 0; - - if (defInstr1->op != PC_SRW && defInstr1->op != PC_SLW) - return 0; - if (defInstr2->op != PC_SRW && defInstr2->op != PC_SLW) - return 0; - - if (usedbetween(instr, defInstr1, &defInstr1->args[0])) - return 0; - if (usedbetween(instr, defInstr2, &defInstr2->args[0])) - return 0; - - if ( - defInstr1->op == PC_SRW && defInstr2->op == PC_SLW && - defInstr1->args[1].data.reg.reg == defInstr2->args[1].data.reg.reg - ) - { - subfic = defininginstruction[defInstr1->defID + 2]; - if ( - subfic->op == PC_SUBFIC && - subfic->args[1].data.reg.reg == defInstr2->args[2].data.reg.reg && - subfic->args[2].data.imm.value == 32 - ) - { - if (rotatedefinedusedtest(masks, instr, defInstr2, defInstr1, subfic)) - return 0; - - change_opcode(instr, PC_RLWNM); - - instr->args[1] = defInstr1->args[1]; - defininginstruction[instr->defID + 1] = defininginstruction[defInstr1->defID + 1]; - - instr->args[2] = defInstr2->args[2]; - defininginstruction[instr->defID + 2] = defininginstruction[defInstr2->defID + 2]; - - instr->args[3].kind = PCOp_IMMEDIATE; - instr->args[3].data.imm.value = 0; - instr->args[3].data.imm.obj = NULL; - - instr->args[4].kind = PCOp_IMMEDIATE; - instr->args[4].data.imm.value = 31; - instr->args[4].data.imm.obj = NULL; - - deletepcode(defInstr1); - deletepcode(defInstr2); - deletepcode(subfic); - return 1; - } - - subfic = defininginstruction[defInstr2->defID + 2]; - if ( - subfic->op == PC_SUBFIC && - subfic->args[1].data.reg.reg == defInstr1->args[2].data.reg.reg && - subfic->args[2].data.imm.value == 32 - ) - { - if (rotatedefinedusedtest(masks, instr, defInstr2, defInstr1, subfic)) - return 0; - - change_opcode(instr, PC_RLWNM); - - instr->args[1] = defInstr1->args[1]; - defininginstruction[instr->defID + 1] = defininginstruction[defInstr1->defID + 1]; - - instr->args[2] = defInstr2->args[2]; - defininginstruction[instr->defID + 2] = defininginstruction[defInstr2->defID + 2]; - - instr->args[3].kind = PCOp_IMMEDIATE; - instr->args[3].data.imm.value = 0; - instr->args[3].data.imm.obj = NULL; - - instr->args[4].kind = PCOp_IMMEDIATE; - instr->args[4].data.imm.value = 31; - instr->args[4].data.imm.obj = NULL; - - deletepcode(defInstr1); - deletepcode(defInstr2); - return 1; - } - } else if ( - defInstr1->op == PC_SLW && defInstr2->op == PC_SRW && - defInstr1->args[1].data.reg.reg == defInstr2->args[1].data.reg.reg - ) - { - subfic = defininginstruction[defInstr1->defID + 2]; - if ( - subfic->op == PC_SUBFIC && - subfic->args[1].data.reg.reg == defInstr2->args[2].data.reg.reg && - subfic->args[2].data.imm.value == 32 - ) - { - if (rotatedefinedusedtest(masks, instr, defInstr1, defInstr2, subfic)) - return 0; - - change_opcode(instr, PC_RLWNM); - - instr->args[1] = defInstr1->args[1]; - defininginstruction[instr->defID + 1] = defininginstruction[defInstr1->defID + 1]; - - instr->args[2] = defInstr1->args[2]; - defininginstruction[instr->defID + 2] = defininginstruction[defInstr1->defID + 2]; - - instr->args[3].kind = PCOp_IMMEDIATE; - instr->args[3].data.imm.value = 0; - instr->args[3].data.imm.obj = NULL; - - instr->args[4].kind = PCOp_IMMEDIATE; - instr->args[4].data.imm.value = 31; - instr->args[4].data.imm.obj = NULL; - - deletepcode(defInstr1); - deletepcode(defInstr2); - return 1; - } - - subfic = defininginstruction[defInstr2->defID + 2]; - if ( - subfic->op == PC_SUBFIC && - subfic->args[1].data.reg.reg == defInstr1->args[2].data.reg.reg && - subfic->args[2].data.imm.value == 32 - ) - { - if (rotatedefinedusedtest(masks, instr, defInstr1, defInstr2, subfic)) - return 0; - - change_opcode(instr, PC_RLWNM); - - instr->args[1] = defInstr1->args[1]; - defininginstruction[instr->defID + 1] = defininginstruction[defInstr1->defID + 1]; - - instr->args[2] = defInstr1->args[2]; - defininginstruction[instr->defID + 2] = defininginstruction[defInstr1->defID + 2]; - - instr->args[3].kind = PCOp_IMMEDIATE; - instr->args[3].data.imm.value = 0; - instr->args[3].data.imm.obj = NULL; - - instr->args[4].kind = PCOp_IMMEDIATE; - instr->args[4].data.imm.value = 31; - instr->args[4].data.imm.obj = NULL; - - deletepcode(defInstr1); - deletepcode(defInstr2); - deletepcode(subfic); - return 1; - } - } - - return 0; -} - -static int RLWINM_RLWIMI_STW(PCode *instr, UInt32 *masks) { - PCode *newInstr; - Boolean isZeroOffset; - int flags; - PCode *scan; - int i; - PCode *array[4]; - - flags = 0; - isZeroOffset = 0; - if (instr->op == PC_STW && instr->args[2].kind == PCOp_IMMEDIATE && instr->args[2].data.imm.value == 0) - isZeroOffset = 1; - - scan = instr; - for (i = 0; i < 4; i++) { - if (scan->op == PC_RLWINM) - array[i] = defininginstruction[scan->defID + 1]; - else - array[i] = defininginstruction[scan->defID]; - - scan = array[i]; - if (array[0]->args[1].data.reg.reg != scan->args[1].data.reg.reg) - return 0; - - if (i < 3) { - if (scan->op != PC_RLWIMI) - return 0; - } else { - if (scan->op != PC_RLWINM) - return 0; - } - - if (scan->args[2].data.imm.value == 8) { - if (scan->args[3].data.imm.value == 24 && scan->args[4].data.imm.value == 31) { - if (flags & 1) - return 0; - flags |= 1; - } else if (scan->args[3].data.imm.value == 8 && scan->args[4].data.imm.value == 15) { - if (flags & 4) - return 0; - flags |= 4; - } else { - return 0; - } - } else if (scan->args[2].data.imm.value == 24) { - if (scan->args[3].data.imm.value == 0 && scan->args[4].data.imm.value == 7) { - if (flags & 8) - return 0; - flags |= 8; - } else if (scan->args[3].data.imm.value == 16 && scan->args[4].data.imm.value == 23) { - if (flags & 2) - return 0; - flags |= 2; - } else { - return 0; - } - } else { - return 0; - } - } - - if (definedbetween(instr, array[3], &array[0]->args[1])) - return 0; - - if (instr->op == PC_STWX) { - change_opcode(instr, PC_STWBRX); - instr->args[0] = array[0]->args[1]; - defininginstruction[instr->defID] = defininginstruction[array[3]->defID + 1]; - return 1; - } - - if (instr->op == PC_STW) { - if (!isZeroOffset) { - if (masks[RegClass_GPR] & (1 << array[0]->args[0].data.reg.reg)) - return 0; - - if (usedbetween(array[2], array[3], &array[0]->args[0])) - return 0; - if (usedbetween(array[1], array[2], &array[0]->args[0])) - return 0; - if (usedbetween(array[0], array[1], &array[0]->args[0])) - return 0; - if (usedbetween(instr, array[0], &array[0]->args[0])) - return 0; - } - - defininginstruction[instr->defID] = defininginstruction[array[3]->defID + 1]; - - if (!isZeroOffset) { - newInstr = makepcode(PC_STWBRX, array[3]->args[1].data.reg.reg, 0, instr->args[0].data.reg.reg); - newInstr->alias = instr->alias; - change_opcode(instr, PC_ADDI); - insertpcodeafter(instr, newInstr); - - masks[RegClass_GPR] |= 1 << newInstr->args[0].data.reg.reg; - masks[RegClass_GPR] |= 1 << newInstr->args[2].data.reg.reg; - instr->args[0].data.reg.effect &= ~EffectRead; - instr->args[0].data.reg.effect |= EffectWrite; - defininginstruction[instr->defID] = instr; - - deletepcode(array[0]); - deletepcode(array[1]); - deletepcode(array[2]); - deletepcode(array[3]); - } else { - change_opcode(instr, PC_STWBRX); - instr->args[0] = array[0]->args[1]; - instr->args[2] = instr->args[1]; - defininginstruction[instr->defID + 2] = defininginstruction[instr->defID + 1]; - - instr->args[1].kind = PCOp_REGISTER; - instr->args[1].arg = RegClass_GPR; - instr->args[1].data.reg.reg = 0; - instr->args[1].data.reg.effect = 0; - } - - return 1; - } - - return 0; -} - -static int RLWINM_RLWIMI_STH(PCode *instr, UInt32 *masks) { - PCode *newInstr; - Boolean isZeroOffset; - int flags; - PCode *scan; - int i; - PCode *array[2]; - - flags = 0; - isZeroOffset = 0; - if (instr->op == PC_STH && instr->args[2].kind == PCOp_IMMEDIATE && instr->args[2].data.imm.value == 0) - isZeroOffset = 1; - - scan = instr; - for (i = 0; i < 2; i++) { - if (scan->op == PC_RLWINM) - array[i] = defininginstruction[scan->defID + 1]; - else - array[i] = defininginstruction[scan->defID]; - - scan = array[i]; - if (array[0]->args[1].data.reg.reg != scan->args[1].data.reg.reg) - return 0; - - if (i < 1) { - if (scan->op != PC_RLWIMI) - return 0; - } else { - if (scan->op != PC_RLWINM) - return 0; - } - - if (scan->args[2].data.imm.value == 8) { - if (scan->args[3].data.imm.value == 16 && scan->args[4].data.imm.value == 23) { - if (flags & 2) - return 0; - flags |= 2; - } else { - return 0; - } - } else if (scan->args[2].data.imm.value == 24) { - if (scan->args[3].data.imm.value == 24 && scan->args[4].data.imm.value == 31) { - if (flags & 1) - return 0; - flags |= 1; - } else { - return 0; - } - } else { - return 0; - } - } - - if (definedbetween(instr, array[1], &array[0]->args[1])) - return 0; - - if (instr->op == PC_STHX) { - change_opcode(instr, PC_STHBRX); - instr->args[0] = array[0]->args[1]; - defininginstruction[instr->defID] = defininginstruction[array[1]->defID + 1]; - return 1; - } - - if (instr->op == PC_STH) { - if (!isZeroOffset) { - if (masks[RegClass_GPR] & (1 << array[0]->args[0].data.reg.reg)) - return 0; - - if (usedbetween(array[0], array[1], &array[0]->args[0])) - return 0; - if (usedbetween(instr, array[0], &array[0]->args[0])) - return 0; - } - - defininginstruction[instr->defID] = defininginstruction[array[1]->defID + 1]; - - if (!isZeroOffset) { - newInstr = makepcode(PC_STHBRX, array[1]->args[1].data.reg.reg, 0, instr->args[0].data.reg.reg); - newInstr->alias = instr->alias; - change_opcode(instr, PC_ADDI); - - instr->args[0].data.reg.effect &= ~EffectRead; - instr->args[0].data.reg.effect |= EffectWrite; - defininginstruction[instr->defID] = instr; - - insertpcodeafter(instr, newInstr); - - masks[RegClass_GPR] |= 1 << newInstr->args[0].data.reg.reg; - masks[RegClass_GPR] |= 1 << newInstr->args[2].data.reg.reg; - - deletepcode(array[0]); - deletepcode(array[1]); - } else { - change_opcode(instr, PC_STHBRX); - instr->args[0] = array[0]->args[1]; - instr->args[2] = instr->args[1]; - defininginstruction[instr->defID + 2] = defininginstruction[instr->defID + 1]; - - instr->args[1].kind = PCOp_REGISTER; - instr->args[1].arg = RegClass_GPR; - instr->args[1].data.reg.reg = 0; - instr->args[1].data.reg.effect = 0; - } - - return 1; - } - - return 0; -} - -static void peepholeoptimizeblock(PCodeBlock *block) { - RegClass rclass; - PCode *instr; - PCodeArg *op; - int i; - Pattern *pattern; - UInt32 masks[RegClassMax]; - - for (rclass = 0; rclass < RegClassMax; rclass++) - masks[rclass] = liveregs[rclass][block->blockIndex].xC; - - for (instr = block->lastPCode; instr; instr = instr->prevPCode) { - if (dead(instr, masks)) { - deletepcode(instr); - } else { - pattern = peepholepatterns[instr->op]; - - while (pattern) { - if (pattern->func(instr, masks)) { - if (!instr->block) - break; - pattern = peepholepatterns[instr->op]; - } else { - pattern = pattern->next; - } - } - - if (instr->block) { - for (op = instr->args, i = instr->argCount; i--; op++) { - if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite)) - masks[op->arg] &= ~(1 << op->data.reg.reg); - } - - for (op = instr->args, i = instr->argCount; i--; op++) { - if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectRead)) - masks[op->arg] |= 1 << op->data.reg.reg; - } - } - } - } -} - -static SInt32 computepossiblemask(PCode *instr, short reg) { - SInt32 mask; - SInt32 val; - PCodeArg *op; - int i; - - mask = 0xFFFFFFFF; - while (instr) { - for (op = instr->args, i = instr->argCount; i--; op++) { - if (PC_OP_IS_WRITE_REGISTER(op, RegClass_GPR, reg)) { - switch (instr->op) { - case PC_LBZ: - case PC_LBZU: - case PC_LBZX: - case PC_LBZUX: - mask = 0xFF; - break; - - case PC_LHZ: - case PC_LHZU: - case PC_LHZX: - case PC_LHZUX: - mask = 0xFFFF; - break; - - case PC_LI: - mask = instr->args[1].data.imm.value; - break; - - case PC_SRAWI: - mask = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg) >> instr->args[2].data.imm.value; - break; - - case PC_RLWINM: - val = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg); - mask = (val << instr->args[2].data.imm.value) | ((UInt32) val >> (32 - instr->args[2].data.imm.value)); - - if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) - val = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) & ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); - else - val = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) | ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); - - mask &= val; - break; - - case PC_RLWIMI: - val = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg); - mask = (val << instr->args[2].data.imm.value) | ((UInt32) val >> (32 - instr->args[2].data.imm.value)); - - if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) - val = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) & ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); - else - val = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) | ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); - - mask &= val; - mask |= computepossiblemask(instr->prevPCode, instr->args[0].data.reg.reg); - break; - - case PC_OR: - mask = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg) | - computepossiblemask(instr->prevPCode, instr->args[2].data.reg.reg); - break; - - case PC_ORI: - mask = instr->args[2].data.imm.value | - computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg); - break; - - case PC_AND: - mask = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg) & - computepossiblemask(instr->prevPCode, instr->args[2].data.reg.reg); - break; - - case PC_ANDI: - mask = instr->args[2].data.imm.value & - computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg); - break; - - case PC_MR: - mask = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg); - break; - } - - return mask; - } - } - instr = instr->prevPCode; - } - - return mask; -} - -static UInt32 fillmaskholes(UInt32 mask) { - UInt32 oneBit; - UInt32 allBits; - UInt32 result; - - oneBit = 1; - allBits = 0xFFFFFFFF; - result = 0; - - if ((mask & 1) && (mask & 0x80000000)) { - result = 0xFFFFFFFF; - while ((mask & oneBit) == 1) { - oneBit <<= 1; - } - - while ((mask & oneBit) == 0) { - result &= ~oneBit; - oneBit <<= 1; - } - - return result; - } else { - while ((mask & oneBit) == 0 && (mask & allBits) != 0) { - oneBit <<= 1; - allBits <<= 1; - } - while ((mask & allBits) != 0) { - result |= oneBit; - oneBit <<= 1; - allBits <<= 1; - } - return result; - } -} - -static int canuseinsert(PCode *instr1, PCode *instr2, short reg) { - if (computepossiblemask(instr2, reg) & fillmaskholes(computepossiblemask(instr1, instr1->args[0].data.reg.reg))) - return 0; - return 1; -} - -static PCode *find_def_backwords(PCode *instr, short reg) { - int i; - - while (instr) { - for (i = 0; i < instr->argCount; i++) { - if (PC_OP_IS_WRITE_REGISTER(&instr->args[i], RegClass_GPR, reg)) - return instr; - } - instr = instr->prevPCode; - } - - return NULL; -} - -static void adjustforward(PCodeBlock *block) { - PCode *instr; - PCode *scan; - PCode *tmp; - PCodeArg *op; - int i; - short opcode; - short reg0; - short reg1; - SInt32 valA; - SInt32 valB; - - instr = block->firstPCode; - while (instr) { - if (instr->op == PC_RLWINM) { - SInt32 val2; - SInt32 val3; - SInt32 val4; - short start; - short end; - - short flag1 = 0; - short flag2 = 0; - reg0 = instr->args[0].data.reg.reg; - reg1 = instr->args[1].data.reg.reg; - val2 = instr->args[2].data.imm.value; - val3 = instr->args[3].data.imm.value; - val4 = instr->args[4].data.imm.value; - - for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { - opcode = scan->op; - if (opcode == PC_RLWINM && scan->args[1].data.reg.reg == reg0) { - if ( - scan->args[3].data.imm.value == val3 && - scan->args[4].data.imm.value == val4 && - scan->args[2].data.imm.value == 0 - ) - { - if (PCODE_FLAG_SET_F(scan) & fRecordBit) { - if (!flag1) { - pcsetrecordbit(instr); - change_opcode(scan, PC_MR); - scan->flags &= ~fRecordBit; - scan->flags |= fIsMove; - change_num_operands(scan, 2); - } else { - change_opcode(scan, PC_MR); - scan->args[2] = scan->args[5]; - change_num_operands(scan, 3); - } - } else { - change_opcode(scan, PC_MR); - change_num_operands(scan, 2); - } - } - else if ( - reg0 != reg1 && - !flag2 && - canmergemasks( - val3, - val4, - scan->args[2].data.imm.value, - scan->args[3].data.imm.value, - scan->args[4].data.imm.value, - &start, &end) - ) - { - scan->args[1].data.reg.reg = reg1; - scan->args[2].data.imm.value = (scan->args[2].data.imm.value + instr->args[2].data.imm.value) & 31; - scan->args[3].data.imm.value = start; - scan->args[4].data.imm.value = end; - } - } - else if ( - opcode == PC_SRAWI && - scan->args[1].data.reg.reg == reg0 && - reg0 != reg1 && - instr->args[2].data.imm.value == 0 && - !(computepossiblemask(instr, reg0) & 0x80000000) && - !flag2 && - canmergemasks(val3, val4, 32 - scan->args[2].data.imm.value, scan->args[2].data.imm.value, 31, &start, &end) && - !isSPRlive(scan, 0) - ) - { - insertpcodeafter(scan, makepcode( - PC_RLWINM, scan->args[0].data.reg.reg, reg1, - 32 - scan->args[2].data.imm.value, start, end - )); - if (PCODE_FLAG_SET_F(scan) & fRecordBit) - pcsetrecordbit(scan->nextPCode); - deletepcode(scan); - } - else if ( - opcode == PC_OR && - !flag2 && - reg0 != reg1 && - !(PCODE_FLAG_SET_F(scan) & fRecordBit) && - !(PCODE_FLAG_SET_F(instr) & fRecordBit) && - scan->args[0].data.reg.reg != instr->args[1].data.reg.reg - ) - { - if (scan->args[1].data.reg.reg == reg0 && canuseinsert(instr, scan, scan->args[2].data.reg.reg)) { - op = &scan->args[2]; - tmp = find_def_backwords(scan->prevPCode, scan->args[2].data.reg.reg); - if (tmp->op == PC_RLWINM && tmp->args[2].data.imm.value == 0) { - if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) - valA = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) & ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); - else - valA = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) | ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); - - if (tmp->args[3].data.imm.value <= tmp->args[4].data.imm.value) - valB = ((tmp->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> tmp->args[3].data.imm.value)) & ~(((tmp->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (tmp->args[4].data.imm.value + 1))); - else - valB = ((tmp->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> tmp->args[3].data.imm.value)) | ~(((tmp->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (tmp->args[4].data.imm.value + 1))); - - if (valA == ~valB) - op = &tmp->args[1]; - } - - change_opcode(scan, PC_MR); - scan->args[1] = *op; - change_num_operands(scan, 2); - - tmp = copypcode(instr); - change_opcode(tmp, PC_RLWIMI); - tmp->args[0] = scan->args[0]; - tmp->args[0].data.reg.effect |= EffectRead; - - if (ismaskconstant(fillmaskholes(computepossiblemask(instr, instr->args[0].data.reg.reg)), &start, &end)) { - tmp->args[3].data.imm.value = start; - tmp->args[4].data.imm.value = end; - } - - insertpcodeafter(scan, tmp); - break; - } - - if ( - scan->args[2].data.reg.reg == reg0 && - canuseinsert(instr, scan, scan->args[1].data.reg.reg) - ) - { - op = &scan->args[1]; - tmp = find_def_backwords(scan->prevPCode, scan->args[1].data.reg.reg); - if (tmp->op == PC_RLWINM && tmp->args[2].data.imm.value == 0) { - if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value) - valA = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) & ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); - else - valA = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) | ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1))); - - if (tmp->args[3].data.imm.value <= tmp->args[4].data.imm.value) - valB = ((tmp->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> tmp->args[3].data.imm.value)) & ~(((tmp->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (tmp->args[4].data.imm.value + 1))); - else - valB = ((tmp->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> tmp->args[3].data.imm.value)) | ~(((tmp->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (tmp->args[4].data.imm.value + 1))); - - if (valA == ~valB) - op = &tmp->args[1]; - } - - change_opcode(scan, PC_MR); - scan->args[1] = *op; - change_num_operands(scan, 2); - - tmp = copypcode(instr); - change_opcode(tmp, PC_RLWIMI); - tmp->args[0] = scan->args[0]; - tmp->args[0].data.reg.effect |= EffectRead; - - if (ismaskconstant(fillmaskholes(computepossiblemask(instr, instr->args[0].data.reg.reg)), &start, &end)) { - tmp->args[3].data.imm.value = start; - tmp->args[4].data.imm.value = end; - } - - insertpcodeafter(scan, tmp); - break; - } - } - else if ( - !flag2 && - reg0 != reg1 && - val4 == 31 && - instr->args[2].data.imm.value == 0 && - ( - ((opcode == PC_STB || opcode == PC_STBX) && val3 <= 24) || - ((opcode == PC_STH || opcode == PC_STHX) && val3 <= 16) - ) && - scan->args[0].data.reg.reg == reg0 - ) - { - scan->args[0].data.reg.reg = reg1; - } - else if ( - opcode == PC_EXTSH && - scan->args[1].data.reg.reg == reg0 && - val2 == 0 && - val3 > 16 && - val3 < val4 - ) - { - change_opcode(scan, PC_MR); - if ((PCODE_FLAG_SET_F(scan) & fRecordBit) && !flag1) { - pcsetrecordbit(instr); - scan->flags &= ~fRecordBit; - scan->flags |= fIsMove; - change_num_operands(scan, 2); - } - } - else if ( - opcode == PC_EXTSB && - scan->args[1].data.reg.reg == reg0 && - val2 == 0 && - val3 > 24 && - val3 < val4 - ) - { - change_opcode(scan, PC_MR); - if ((PCODE_FLAG_SET_F(scan) & fRecordBit) && !flag1) { - pcsetrecordbit(instr); - scan->flags &= ~fRecordBit; - scan->flags |= fIsMove; - change_num_operands(scan, 2); - } - } - - for (op = scan->args, i = scan->argCount; i--; op++) { - if (PC_OP_IS_WRITE_REGISTER(op, RegClass_GPR, reg0)) { - scan = block->lastPCode; - break; - } - - if (PC_OP_IS_WRITE_REGISTER(op, RegClass_GPR, reg1)) - flag2 = 1; - - if (PC_OP_IS_REGISTER(op, RegClass_CRFIELD, 0)) - flag1 = 1; - } - } - - } else if ( - instr->op == PC_EXTSB && - (reg0 = instr->args[0].data.reg.reg) != (reg1 = instr->args[1].data.reg.reg) - ) - { - short flag = 0; - for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { - if ( - (scan->op >= PC_STB && scan->op <= PC_STBUX) && - scan->args[0].data.reg.reg == reg0 - ) - { - scan->args[0].data.reg.reg = reg1; - } - else if ( - (scan->op == PC_EXTSH || scan->op == PC_EXTSB) && - scan->args[1].data.reg.reg == reg0 - ) - { - change_opcode(scan, PC_MR); - if ((PCODE_FLAG_SET_F(scan) & fRecordBit) && !flag) { - pcsetrecordbit(instr); - scan->flags &= ~fRecordBit; - scan->flags |= fIsMove; - change_num_operands(scan, 2); - } - } - - for (op = scan->args, i = scan->argCount; i--; op++) { - if ( - PC_OP_IS_WRITE_ANY_REGISTER(op, RegClass_GPR) && - (op->data.reg.reg == reg0 || op->data.reg.reg == reg1) - ) - { - scan = block->lastPCode; - break; - } - - if (PC_OP_IS_REGISTER(op, RegClass_CRFIELD, 0)) - flag = 1; - } - } - } else if ( - instr->op == PC_EXTSH && - (reg0 = instr->args[0].data.reg.reg) != (reg1 = instr->args[1].data.reg.reg) - ) - { - short flag = 0; - for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { - if ( - ((scan->op >= PC_STB && scan->op <= PC_STBUX) || (scan->op >= PC_STH && scan->op <= PC_STHUX)) && - scan->args[0].data.reg.reg == reg0 - ) - { - scan->args[0].data.reg.reg = reg1; - } - else if (scan->op == PC_EXTSH && scan->args[1].data.reg.reg == reg0) - { - change_opcode(scan, PC_MR); - if ((PCODE_FLAG_SET_F(scan) & fRecordBit) && !flag) { - pcsetrecordbit(instr); - scan->flags &= ~fRecordBit; - scan->flags |= fIsMove; - change_num_operands(scan, 2); - } - } - - for (op = scan->args, i = scan->argCount; i--; op++) { - if ( - PC_OP_IS_WRITE_ANY_REGISTER(op, RegClass_GPR) && - (op->data.reg.reg == reg0 || op->data.reg.reg == reg1) - ) - { - scan = block->lastPCode; - break; - } - - if (PC_OP_IS_REGISTER(op, RegClass_CRFIELD, 0)) - flag = 1; - } - } - } else if ( - instr->op == PC_ADDI && - (reg0 = instr->args[0].data.reg.reg) == (reg1 = instr->args[1].data.reg.reg) && - instr->args[2].kind == PCOp_IMMEDIATE - ) - { - Boolean flag1 = 0; - Boolean flag2 = 0; - SInt32 val2 = instr->args[2].data.imm.value; - - for (scan = instr->nextPCode; scan; scan = scan->nextPCode) { - if ((scan->flags & fIsWrite) && scan->args[0].data.reg.reg == reg0) - break; - - if ( - (scan->flags & (fIsRead | fIsWrite)) && - scan->args[1].data.reg.reg == reg0 && - scan->args[2].kind == PCOp_IMMEDIATE && - FITS_IN_SHORT(val2 + scan->args[2].data.imm.value) - ) - { - scan->args[2].data.imm.value += val2; - tmp = instr->prevPCode; - if ( - (scan->flags & fIsRead) && - scan->args[0].data.reg.reg == reg0 && - scan->args[0].kind == PCOp_REGISTER && - scan->args[0].arg == RegClass_GPR - ) - { - deletepcode(instr); - } else { - deletepcode(instr); - insertpcodeafter(scan, instr); - } - instr = tmp; - break; - } - - if ( - scan->op == PC_ADDI && - scan->args[1].data.reg.reg == reg0 && - scan->args[2].kind == PCOp_IMMEDIATE && - FITS_IN_SHORT(val2 + scan->args[2].data.imm.value) - ) - { - scan->args[2].data.imm.value += val2; - tmp = instr->prevPCode; - if (scan->args[0].data.reg.reg == reg0) { - deletepcode(instr); - } else { - deletepcode(instr); - insertpcodeafter(scan, instr); - } - instr = tmp; - break; - } - - if (scan->flags & (fIsBranch | fIsCall)) { - if (flag1 && scan->prevPCode != instr) { - tmp = instr->prevPCode; - deletepcode(instr); - insertpcodebefore(scan, instr); - instr = tmp; - } - break; - } - - for (op = scan->args, i = scan->argCount; i--; op++) { - if (PC_OP_IS_R_OR_W_REGISTER(op, RegClass_GPR, reg0)) { - if (flag1 && scan->prevPCode != instr) { - tmp = instr->prevPCode; - deletepcode(instr); - insertpcodebefore(scan, instr); - instr = tmp; - } - flag2 = 1; - break; - } - } - - if (flag2) - break; - - if (scan->op != PC_ADDI) - flag1 = 1; - - if (flag1 && !scan->nextPCode) { - tmp = instr->prevPCode; - deletepcode(instr); - appendpcode(block, instr); - instr = tmp; - break; - } - } - } - - if (instr) - instr = instr->nextPCode; - else - instr = block->firstPCode; - } -} - -static void installpattern(Opcode opcode, PeepholeFunc func) { - Pattern *pattern = lalloc(sizeof(Pattern)); - pattern->func = func; - pattern->next = peepholepatterns[opcode]; - peepholepatterns[opcode] = pattern; -} - -static void installpeepholepatterns(void) { - int i; - - for (i = 0; i < OPCODE_MAX; i++) - peepholepatterns[i] = NULL; - - installpattern(PC_AND, NOT_AND); - installpattern(PC_MR, LI_MR); - installpattern(PC_MR, L_MR); - installpattern(PC_FMR, L_FMR); - installpattern(PC_MR, MR_MR); - installpattern(PC_MR, MR_Rx_Rx); - installpattern(PC_FMR, FMR_FMR); - installpattern(PC_FMR, FMR_Fx_Fx); - installpattern(PC_VMR, VMR_VMRP); - installpattern(PC_VMR, VMR_VMR); - installpattern(PC_VMR, VMR_Vx_Vx); - installpattern(PC_VMR, VSPLTIS_VMR); - installpattern(PC_CMPI, MR_CMPI); - installpattern(PC_RLWIMI, RLWINM_RLWINM); - installpattern(PC_RLWINM, RLWINM_RLWINM); - installpattern(PC_RLWINM, EXTSB_RLWINM); - installpattern(PC_RLWINM, EXTSH_RLWINM); - installpattern(PC_RLWINM, LBZ_RLWINM); - installpattern(PC_RLWINM, LHZ_RLWINM); - installpattern(PC_EXTSH, LHA_EXTSH); - installpattern(PC_STW, RLWINM_RLWIMI_STW); - installpattern(PC_STWX, RLWINM_RLWIMI_STW); - installpattern(PC_STH, RLWINM_RLWIMI_STH); - installpattern(PC_STHX, RLWINM_RLWIMI_STH); - installpattern(PC_LBZ, ADDI_L_S); - installpattern(PC_LHZ, ADDI_L_S); - installpattern(PC_LHA, ADDI_L_S); - installpattern(PC_LWZ, ADDI_L_S); - installpattern(PC_STB, ADDI_L_S); - installpattern(PC_STH, ADDI_L_S); - installpattern(PC_STW, ADDI_L_S); - installpattern(PC_LFS, ADDI_L_S); - installpattern(PC_LFD, ADDI_L_S); - installpattern(PC_STFS, ADDI_L_S); - installpattern(PC_STFD, ADDI_L_S); - installpattern(PC_LBZU, ADDI_LU_SU); - installpattern(PC_LHZU, ADDI_LU_SU); - installpattern(PC_LHAU, ADDI_LU_SU); - installpattern(PC_LWZU, ADDI_LU_SU); - installpattern(PC_STBU, ADDI_LU_SU); - installpattern(PC_STHU, ADDI_LU_SU); - installpattern(PC_STWU, ADDI_LU_SU); - installpattern(PC_LFSU, ADDI_LU_SU); - installpattern(PC_LFDU, ADDI_LU_SU); - installpattern(PC_STFSU, ADDI_LU_SU); - installpattern(PC_STFDU, ADDI_LU_SU); - installpattern(PC_LBZ, L_S_ADDI); - installpattern(PC_LHZ, L_S_ADDI); - installpattern(PC_LHA, L_S_ADDI); - installpattern(PC_LWZ, L_S_ADDI); - installpattern(PC_STB, L_S_ADDI); - installpattern(PC_STH, L_S_ADDI); - installpattern(PC_STW, L_S_ADDI); - installpattern(PC_LFS, L_S_ADDI); - installpattern(PC_LFD, L_S_ADDI); - installpattern(PC_STFS, L_S_ADDI); - installpattern(PC_STFD, L_S_ADDI); - installpattern(PC_STB, L_S); - installpattern(PC_STH, L_S); - installpattern(PC_STW, L_S); - installpattern(PC_STFS, L_S); - installpattern(PC_STFD, L_S); - installpattern(PC_STBX, L_S); - installpattern(PC_STHX, L_S); - installpattern(PC_STWX, L_S); - installpattern(PC_STFSX, L_S); - installpattern(PC_STFDX, L_S); - installpattern(PC_BT, LBZ_EXTSB_CMPI_BC); - installpattern(PC_BF, LBZ_EXTSB_CMPI_BC); - installpattern(PC_BT, RLWINM_CMPLI_BC); - installpattern(PC_BF, RLWINM_CMPLI_BC); - installpattern(PC_BT, LI_CMP_BC); - installpattern(PC_BF, LI_CMP_BC); - installpattern(PC_RLWINM, RLWINM_RLWINM); - installpattern(PC_MULLI, MULLI_MULLI); - installpattern(PC_ADDI, ADDI_ADDI); - installpattern(PC_SRAWI, SRAWI_SRAWI); - installpattern(PC_MR, MR_ADDI); - installpattern(PC_OR, SRW_SUBFIC_RLW_OR); -} - -void peepholeoptimizeforward(Object *func) { - PCodeBlock *block; - - for (block = pcbasicblocks; block; block = block->nextBlock) { - if (block->pcodeCount >= 2) - adjustforward(block); - } -} - -void peepholemergeblocks(Object *func, Boolean flag) { - PCodeBlock *block; - PCodeBlock *next; - Boolean flag2; - PCode *instr; - PCode *nextinstr; - PCLink *link; - PCLink *link2; - - for (block = pcbasicblocks; block; block = block->nextBlock) { - flag2 = 0; - next = block->nextBlock; - - if (!flag) { - flag2 = next && (next->flags & fIsEpilogue); - if (block->flags & fIsProlog) - continue; - } - - if (block->pcodeCount > 0) { - for (instr = block->firstPCode; instr; instr = instr->nextPCode) { - if (instr->flags & (fIsCall | fSideEffects)) - break; - } - - if (instr) - continue; - - instr = block->lastPCode; - if (instr && instr->op == PC_B) { - if (instr->args[0].kind == PCOp_LABEL && instr->args[0].data.label.label->block == next) - deletepcode(instr); - else - continue; - } - - instr = block->lastPCode; - if (instr && (instr->flags & fIsBranch) && instr->op != PC_B) - continue; - - while ( - block->successors->block == next && - block->successors->nextLink == NULL && - next->predecessors->block == block && - next->predecessors->nextLink == NULL && - !flag2 && - !(next->flags & fPCBlockFlag8000) && - (block->pcodeCount + next->pcodeCount) <= 100 - ) - { - if (next->pcodeCount > 0) { - for (instr = next->firstPCode; instr; instr = nextinstr) { - nextinstr = instr->nextPCode; - if (instr->flags & (fIsCall | fSideEffects)) - break; - - deletepcode(instr); - if (instr->op != PC_B) { - appendpcode(block, instr); - } else if (instr->args[0].kind == PCOp_LABEL) { - if (instr->args[0].data.label.label->block != next->nextBlock) - appendpcode(block, instr); - } else { - appendpcode(block, instr); - } - } - } - - if (next->pcodeCount != 0) - break; - if (next == epilogue) - break; - - block->successors = next->successors; - - for (link = block->successors; link; link = link->nextLink) { - for (link2 = link->block->predecessors; link2; link2 = link2->nextLink) { - if (link2->block == next) { - link2->block = block; - break; - } - } - } - - block->nextBlock = next->nextBlock; - if (block->nextBlock) - block->nextBlock->prevBlock = block; - - next->flags |= fDeleted; - next = block->nextBlock; - - if (!flag) - flag2 = next && (next->flags & fIsEpilogue); - } - } - } -} - -void peepholeoptimizepcode(Object *func) { - PCodeBlock *block; - - installpeepholepatterns(); - computeliveregisters(func); - - for (block = pcbasicblocks; block; block = block->nextBlock) { - if (block->pcodeCount >= 1) { - computeinstructionpredecessors(block); - peepholeoptimizeblock(block); - freeoheap(); - } - } -} diff --git a/compiler_and_linker/unsorted/RegisterInfo.c b/compiler_and_linker/unsorted/RegisterInfo.c deleted file mode 100644 index 177c2e0..0000000 --- a/compiler_and_linker/unsorted/RegisterInfo.c +++ /dev/null @@ -1,381 +0,0 @@ -#include "compiler/RegisterInfo.h" -#include "compiler/CodeGen.h" -#include "compiler/CError.h" -#include "compiler/CParser.h" -#include "compiler/PCode.h" -#include "compiler/CompilerTools.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -short last_exception_register[RegClassMax]; -short first_fe_temporary_register[RegClassMax]; -short last_argument_register[RegClassMax]; -short _FP_; -short _CALLER_SP_; -char *special_register_names[RegClassMax][RegisterMax]; -static short used_regs_before_coloring; -static UInt8 save_state[RegisterMax]; - -short spr_to_sysreg[4] = {1, 8, 9, 0x100}; - -void asm_used_register(RegClass rclass, short reg) { - int i; - - if ((reg < n_real_registers[rclass]) && (reg_state[rclass][reg] == RegState0)) { - if (reg == nonvolatile_registers[rclass][used_nonvolatile_registers[rclass]]) { - if (assignable_registers[rclass] > 0) - assignable_registers[rclass]--; - reg_state[rclass][reg] = RegState1; - used_nonvolatile_registers[rclass]++; - } else { - for (i = used_nonvolatile_registers[rclass]; i < n_nonvolatile_registers[rclass]; i++) { - if (reg == nonvolatile_registers[rclass][i]) { - reg_state[rclass][reg] = RegState1; - if (assignable_registers[rclass] > 0) - assignable_registers[rclass]--; - } - } - } - } -} - -void retain_register(Object *obj, RegClass rclass, short reg) { - VarInfo *vi; - - CError_ASSERT(95, (short) reg < RegisterMax); - - if (reg_state[rclass][reg] == RegState0) { - assignable_registers[rclass]--; - reg_state[rclass][reg] = RegState1; - if (reg == nonvolatile_registers[rclass][used_nonvolatile_registers[rclass]]) - used_nonvolatile_registers[rclass]++; - } - - if (obj) { - vi = Registers_GetVarInfo(obj); - vi->rclass = rclass; - vi->flags |= VarInfoFlag2; - vi->reg = reg; - } -} - -void retain_GPR_pair(Object *obj, short reg, short regHi) { - VarInfo *vi; - - retain_register(NULL, RegClass_GPR, reg); - retain_register(NULL, RegClass_GPR, regHi); - - if (obj) { - vi = Registers_GetVarInfo(obj); - vi->rclass = RegClass_GPR; - vi->flags |= VarInfoFlag2 | VarInfoFlag4; - vi->reg = reg; - vi->regHi = regHi; - } -} - -int is_register_object(Object *obj) { - return obj->sclass == TK_REGISTER; -} - -int GetABIFirstNonVolatile(RegClass rclass) { - switch (rclass) { - case RegClass_SPR: return 3; - case RegClass_CRFIELD: return 2; - case RegClass_VR: return 20; - case RegClass_GPR: return 13; - case RegClass_FPR: return 14; - default: return -1; - } -} - -char GetRegisterClassName(RegClass rclass) { - switch (rclass) { - case RegClass_VR: return 'v'; - case RegClass_GPR: return 'r'; - case RegClass_FPR: return 'f'; - default: - CError_FATAL(242); - return '?'; - } -} - -static int first_nonvolatile_reg(RegClass rclass) { - return GetABIFirstNonVolatile(rclass); -} - -void setup_diagnostic_reg_strings(void) { - register_class_name[RegClass_SPR] = "SPR"; - register_class_format[RegClass_SPR] = "spr%" PRId32; - register_class_name[RegClass_CRFIELD] = "CRFIELD"; - register_class_format[RegClass_CRFIELD] = "cr%" PRId32; - register_class_name[RegClass_VR] = "VR"; - register_class_format[RegClass_VR] = "vr%" PRId32; - register_class_name[RegClass_FPR] = "FPR"; - register_class_format[RegClass_FPR] = "f%" PRId32; - register_class_name[RegClass_GPR] = "GPR"; - register_class_format[RegClass_GPR] = "r%" PRId32; -} - -void init_target_registers(void) { - int reg; - int end; - RegClass rclass; - - static int last_nonvolatile_reg[] = {3, 5, 31, 31, 31}; - static int nonvol_reserve[] = {0, 0, 0, 4, 3}; - - for (rclass = 0; rclass < RegClassMax; rclass++) { - for (reg = 0; reg < RegisterMax; reg++) - special_register_names[rclass][reg] = NULL; - } - - special_register_names[RegClass_SPR][0] = "XER"; - special_register_names[RegClass_SPR][1] = "LR"; - special_register_names[RegClass_SPR][2] = "CTR"; - special_register_names[RegClass_SPR][3] = "VRSAVE"; - special_register_names[RegClass_GPR][1] = "SP"; - - setup_diagnostic_reg_strings(); - n_real_registers[RegClass_SPR] = 4; - n_real_registers[RegClass_CRFIELD] = 8; - n_real_registers[RegClass_VR] = 32; - n_real_registers[RegClass_FPR] = 32; - n_real_registers[RegClass_GPR] = 32; - reg_state[RegClass_GPR][1] = RegState2; - reg_state[RegClass_GPR][2] = RegState2; - reg_state[RegClass_CRFIELD][5] = RegState2; - - for (rclass = 0; rclass < RegClassMax; rclass++) { - n_nonvolatile_registers[rclass] = 0; - if (last_nonvolatile_reg[rclass] >= 0) { - end = first_nonvolatile_reg(rclass); - for (reg = last_nonvolatile_reg[rclass]; reg >= end; reg--) { - if (reg_state[rclass][reg] == RegState0) { - nonvolatile_registers[rclass][n_nonvolatile_registers[rclass]++] = reg; - } - } - } - - assignable_registers[rclass] = n_nonvolatile_registers[rclass] - nonvol_reserve[rclass]; - if (assignable_registers[rclass] < 0) - assignable_registers[rclass] = 0; - - n_scratch_registers[rclass] = 0; - for (reg = 0; reg < n_real_registers[rclass]; reg++) { - if (reg < GetABIFirstNonVolatile(rclass) || reg > last_nonvolatile_reg[rclass]) { - if (reg_state[rclass][reg] == RegState0) { - scratch_registers[rclass][n_scratch_registers[rclass]++] = reg; - } - } - } - } - - _FP_ = -1; - _CALLER_SP_ = -1; - optimizing = (copts.optimizationlevel > 0) && !disable_optimizer; -} - -void assign_register_by_type(Object *obj) { - VarInfo *vi; - Type *ty; - Boolean flag; - - ty = obj->type; - vi = Registers_GetVarInfo(obj); - flag = 0; - vi->rclass = RegClassMax; - vi->reg = 0; - vi->regHi = 0; - - if ((ty->type == TYPEINT) || (ty->type == TYPEENUM) || ((ty->type == TYPEPOINTER || ty->type == TYPEARRAY) && (ty->type != TYPEARRAY)) || ((ty->type == TYPEMEMBERPOINTER) && (ty->size == 4U))) { - if (((ty->type == TYPEINT) || (ty->type == TYPEENUM)) && (ty->size == 8)) - flag = 1; - vi->rclass = RegClass_GPR; - } else if (ty->type == TYPEFLOAT) { - vi->rclass = RegClass_FPR; - } else if ((ty->type == TYPESTRUCT) && (TYPE_STRUCT(ty)->stype >= STRUCT_VECTOR_UCHAR) && (TYPE_STRUCT(ty)->stype <= STRUCT_VECTOR_PIXEL)) { - vi->rclass = RegClass_VR; - } else { - return; - } - - if (vi->rclass < RegClassMax) { - if (flag) { - CError_ASSERT(520, vi->rclass == RegClass_GPR); - if (assignable_registers[vi->rclass] > 1) - assign_GPR_pair(obj); - } else { - if (assignable_registers[vi->rclass] > 0) - assign_register_to_variable(obj, vi->rclass); - } - } -} - -void assign_GPR_pair(Object *obj) { - VarInfo *vi; - short reg; - short regHi; - - vi = Registers_GetVarInfo(obj); - if (optimizing) { - reg = used_virtual_registers[RegClass_GPR]++; - regHi = used_virtual_registers[RegClass_GPR]++; - } else { - CError_ASSERT(554, assignable_registers[RegClass_GPR] >= 2); - reg = obtain_nonvolatile_register(RegClass_GPR); - regHi = obtain_nonvolatile_register(RegClass_GPR); - retain_GPR_pair(obj, reg, regHi); - } - - vi->rclass = RegClass_GPR; - if (reg > 0 && regHi > 0) { - vi->flags |= VarInfoFlag2 | VarInfoFlag4; - vi->reg = reg; - vi->regHi = regHi; - } else { - CError_FATAL(567); - } -} - -void open_fe_temp_registers(void) { - int r; - - r = used_virtual_registers[RegClass_GPR]; - first_fe_temporary_register[RegClass_GPR] = last_temporary_register[RegClass_GPR] = r; - r = used_virtual_registers[RegClass_FPR]; - first_fe_temporary_register[RegClass_FPR] = last_temporary_register[RegClass_FPR] = r; - r = used_virtual_registers[RegClass_VR]; - first_fe_temporary_register[RegClass_VR] = last_temporary_register[RegClass_VR] = r; -} - -void set_last_exception_registers(void) { - last_exception_register[RegClass_GPR] = used_virtual_registers[RegClass_GPR] - 1; - last_exception_register[RegClass_FPR] = used_virtual_registers[RegClass_FPR] - 1; - last_exception_register[RegClass_VR] = used_virtual_registers[RegClass_VR] - 1; -} - -static VarInfo *Registers_GetNewVarInfo(void) { - VarInfo *vi = galloc(sizeof(VarInfo)); - memclrw(vi, sizeof(VarInfo)); - return vi; -} - -VarInfo *Registers_GetVarInfo(Object *obj) { - switch (obj->datatype) { - case DDATA: - if (!obj->u.data.info) - obj->u.data.info = Registers_GetNewVarInfo(); - return obj->u.data.info; - case DNONLAZYPTR: - if (!obj->u.toc.info) { - CError_FATAL(639); - obj->u.toc.info = CodeGen_GetNewVarInfo(); - } - return obj->u.toc.info; - case DLOCAL: - if (!obj->u.var.info) - CError_FATAL(647); - return obj->u.var.info; - case DABSOLUTE: - // not sure if this is the right union - if (!obj->u.data.info) - obj->u.data.info = Registers_GetNewVarInfo(); - return obj->u.data.info; - default: - CError_FATAL(660); - return NULL; - } -} - -int used_vrstate_VRs(void) { - int count = 0; - int i; - for (i = 0; i < RegisterMax; i++) { - if (reg_state[RegClass_VR][i]) - count++; - } - return count; -} - -UInt32 colored_vrs_as_vrsave(PCodeBlock *block) { - PCode *pc; - UInt32 mask; - int i; - - mask = 0; - if (copts.altivec_vrsave == 2) - return 0xFFFFFFFF; - if (copts.altivec_vrsave == 0) - return 0; - - while (block) { - for (pc = block->firstPCode; pc; pc = pc->nextPCode) { - if (pc->flags & fOpTypeVR) { - for (i = 0; i < pc->argCount; i++) { - if (pc->args[i].kind == PCOp_REGISTER && pc->args[i].arg == RegClass_VR) - mask |= 1 << (31 - pc->args[i].data.reg.reg); - } - } - } - block = block->nextBlock; - } - - return mask; -} - -void save_before_coloring_nonvolatile_registers(RegClass rclass) { - used_regs_before_coloring = used_nonvolatile_registers[rclass]; - memcpy(save_state, reg_state[rclass], sizeof(save_state)); -} - -void reset_nonvolatile_registers(RegClass rclass) { - used_nonvolatile_registers[rclass] = used_regs_before_coloring; - memcpy(reg_state[rclass], save_state, sizeof(save_state)); -} - -int is_nonvolatile_register(RegClass rclass, int reg) { - int i; - - for (i = 0; i < n_nonvolatile_registers[rclass]; i++) { - if (reg == nonvolatile_registers[rclass][i]) - return 1; - } - - return 0; -} - -void init_endian(void) { - if (copts.littleendian) { - high_offset = 4; - low_offset = 0; - high_reg = 4; - low_reg = 3; - high_reg2 = 6; - low_reg2 = 5; - } else { - high_offset = 0; - low_offset = 4; - high_reg = 3; - low_reg = 4; - high_reg2 = 5; - low_reg2 = 6; - } -} - -void update_asm_nonvolatile_registers(void) { - RegClass rclass; - int i; - int reg; - - for (rclass = 0; rclass < RegClassMax; rclass++) { - reg = n_nonvolatile_registers[rclass]; - for (i = n_nonvolatile_registers[rclass] - 1; i >= 0; i--) { - if (reg_state[rclass][nonvolatile_registers[rclass][i]] == RegState1) - break; - reg--; - } - if (reg > used_nonvolatile_registers[rclass]) - used_nonvolatile_registers[rclass] = reg; - } -} diff --git a/compiler_and_linker/unsorted/Scheduler.c b/compiler_and_linker/unsorted/Scheduler.c deleted file mode 100644 index 23b580f..0000000 --- a/compiler_and_linker/unsorted/Scheduler.c +++ /dev/null @@ -1,547 +0,0 @@ -#include "compiler/Scheduler.h" -#include "compiler/CError.h" -#include "compiler/CParser.h" -#include "compiler/Alias.h" -#include "compiler/CompilerTools.h" -#include "compiler/PCode.h" -#include "compiler/Registers.h" - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct DGNode { - struct DGNode *x0; - struct DGNode *x4; - struct DGSuccessor *successors; - PCode *instr; - UInt16 x10; - UInt16 x12; - UInt16 x14; - UInt16 x16; - short predCount; -} DGNode; - -typedef struct DGSuccessor { - struct DGSuccessor *next; - DGNode *node; - UInt16 x8; -} DGSuccessor; - -typedef struct DGNodeList { - struct DGNodeList *next; - DGNode *node; -} DGNodeList; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static DGNodeList **register_uses[RegClassMax]; -static DGNodeList **register_defs[RegClassMax]; -static DGNodeList *memory_uses; -static DGNodeList *memory_defs; -static DGNodeList *side_effects; -static DGNodeList *volatile_refs; -static DGNode *defaultsuccessor; -static UInt16 criticalpath; -static MachineInfo *MI; - -static void initresources(void) { - int rclass; - int i; - - for (rclass = 0; (char) rclass < RegClassMax; rclass++) { - register_uses[(char) rclass] = oalloc(sizeof(DGNodeList *) * used_virtual_registers[(char) rclass]); - register_defs[(char) rclass] = oalloc(sizeof(DGNodeList *) * used_virtual_registers[(char) rclass]); - for (i = 0; i < used_virtual_registers[(char) rclass]; i++) { - register_uses[(char) rclass][i] = register_defs[(char) rclass][i] = NULL; - } - } - - memory_uses = memory_defs = NULL; - side_effects = NULL; - volatile_refs = NULL; - criticalpath = 0; -} - -static DGNode *makedgnode(PCode *instr) { - DGNode *node; - - node = oalloc(sizeof(DGNode)); - node->x0 = NULL; - node->x4 = NULL; - node->successors = NULL; - node->instr = instr; - node->x10 = node->x16 = MI->latency(instr); - node->x12 = 0; - node->x14 = 0; - node->predCount = 0; - return node; -} - -static DGNode *adddgnode(DGNode *head, DGNode *node) { - if (head) - head->x4 = node; - node->x0 = head; - return node; -} - -static DGNode *removedgnode(DGNode *head, DGNode *node) { - if (node->x4) - node->x4->x0 = node->x0; - else - head = node->x0; - - if (node->x0) - node->x0->x4 = node->x4; - - return head; -} - -static void addtolist(DGNodeList **list, DGNode *node) { - DGNodeList *entry = oalloc(sizeof(DGNodeList)); - entry->node = node; - entry->next = *list; - *list = entry; -} - -static DGNodeList *makedglistnode(DGNode *node) { - DGNodeList *list = oalloc(sizeof(DGNodeList)); - list->next = NULL; - list->node = node; - return list; -} - -int is_same_operand(PCodeArg *a, PCodeArg *b) { - if (a->kind != b->kind) - return 0; - - switch (a->kind) { - case PCOp_IMMEDIATE: - if (a->data.imm.value != b->data.imm.value) - return 0; - break; - case PCOp_REGISTER: - if ((char) a->arg != (char) b->arg) - return 0; - if (a->data.reg.reg != b->data.reg.reg) - return 0; - break; - case PCOp_MEMORY: - if (a->data.mem.offset != b->data.mem.offset) - return 0; - if (a->data.mem.obj != b->data.mem.obj) - return 0; - break; - case PCOp_LABEL: - if (a->data.label.label != b->data.label.label) - return 0; - break; - } - - return 1; -} - -static void addsuccessor(DGNode *a, DGNode *b, Boolean flag) { - int v6; - int r29; - DGSuccessor *succ; - - if (flag) - v6 = a->x10; - else - v6 = 0; - - if (a != b) { - r29 = (v6 > 0) ? v6 : 0; - for (succ = a->successors; succ; succ = succ->next) { - if (succ->node == b) { - if (succ->x8 < r29) { - succ->x8 = r29; - if (b->x16 + succ->x8 > a->x16) - a->x16 = b->x16 + succ->x8; - } - return; - } - } - - succ = oalloc(sizeof(DGSuccessor)); - succ->node = b; - succ->next = a->successors; - a->successors = succ; - succ->x8 = r29; - - if (flag && (succ->node->instr->flags & fIsBranch)) - succ->x8 += MI->x8; - - b->predCount++; - - if (b->x16 + succ->x8 > a->x16) - a->x16 = b->x16 + succ->x8; - } -} - -static void serializeall(DGNode *nodes, DGNode *node) { - DGNode *scan; - - for (scan = nodes; scan; scan = scan->x0) - addsuccessor(node, scan, 0); -} - -static void serializelist(DGNode *node, DGNodeList *list) { - while (list) { - if (list->node != node) - addsuccessor(node, list->node, 0); - list = list->next; - } -} - -static void serializeregister(int rclass, DGNode *node, DGNodeList **defs, DGNodeList **uses, int isWrite) { - DGNodeList *list; - - if (isWrite) { - for (list = *uses; list; list = list->next) { - if (list->node != node) - addsuccessor(node, list->node, 1); - } - for (list = *defs; list; list = list->next) { - if (list->node != node) - addsuccessor(node, list->node, ((char) rclass == RegClass_SPR) || (MI->x4 == 0)); - } - - list = makedglistnode(node); - list->next = *defs; - *defs = list; - } else { - for (list = *defs; list; list = list->next) { - if (list->node != node) - addsuccessor(node, list->node, ((char) rclass == RegClass_SPR) || (MI->x4 == 0)); - } - - list = makedglistnode(node); - list->next = *uses; - *uses = list; - } -} - -static void serialize_load(DGNode *node) { - DGNodeList *list; - - for (list = memory_defs; list; list = list->next) { - if (may_alias(node->instr, list->node->instr)) - addsuccessor(node, list->node, 1); - } - - addtolist(&memory_uses, node); -} - -static void serialize_store(DGNode *node) { - DGNodeList *list; - - for (list = memory_uses; list; list = list->next) { - if (may_alias(node->instr, list->node->instr)) - addsuccessor(node, list->node, 1); - } - for (list = memory_defs; list; list = list->next) { - if (may_alias(node->instr, list->node->instr)) - addsuccessor(node, list->node, 1); - } - - addtolist(&memory_defs, node); - if (node->instr->flags & fPCodeFlag40000) - addtolist(&memory_uses, node); -} - -static void findsuccessors(DGNode *nodes, DGNode *node) { - PCode *instr; - PCodeArg *op; - int i; - - instr = node->instr; - for (i = 0, op = instr->args; i < instr->argCount; i++, op++) { - switch (op->kind) { - case PCOp_IMMEDIATE: - case PCOp_MEMORY: - break; - case PCOp_REGISTER: - if ( - op->data.reg.reg < 0 || - op->data.reg.reg > used_virtual_registers[(char) op->arg] - ) - { - CError_FATAL(491); - } - - if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR) { - if (op->data.reg.reg == Register2) - break; - if (op->data.reg.reg == Register0 && !(op->data.reg.effect & (EffectRead | EffectWrite))) - break; - } - - serializeregister( - op->arg, - node, - ®ister_defs[(char) op->arg][op->data.reg.reg], - ®ister_uses[(char) op->arg][op->data.reg.reg], - op->data.reg.effect & EffectWrite - ); - - break; - } - } - - if (instr->flags & (fIsRead | fPCodeFlag20000)) - serialize_load(node); - else if (instr->flags & (fIsWrite | fPCodeFlag40000)) - serialize_store(node); - - if (instr->flags & fIsVolatile) { - serializelist(node, volatile_refs); - addtolist(&volatile_refs, node); - } - - if ( - ((instr->flags & fIsCall | fIsBranch) && (instr->flags & fLink)) || - (instr->flags & fSideEffects) || - MI->serializes(instr) - ) - { - serializeall(nodes, node); - addtolist(&side_effects, node); - } - - if (side_effects) - serializelist(node, side_effects); - - if (!node->successors && defaultsuccessor) - addsuccessor(node, defaultsuccessor, 0); - - if (node->x16 > criticalpath) - criticalpath = node->x16; -} - -static void computedeadlines(DGNode *nodes) { - while (nodes) { - nodes->x14 = criticalpath - nodes->x16; - nodes = nodes->x0; - } -} - -static int uncovering(DGNode *node) { - int counter; - DGSuccessor *succ; - - counter = 0; - for (succ = node->successors; succ; succ = succ->next) { - if (succ->node->predCount == 1) - counter++; - } - - return counter; -} - -static DGNode *selectinstruction(DGNode *nodes, UInt16 counter) { - DGNode *node; - DGNode *node2; - int a; - int b; - - node = nodes; - while (node) { - if (node->predCount == 0 && node->x12 <= counter && MI->can_issue(node->instr)) - break; - node = node->x0; - } - - if (!node) - return NULL; - - for (node2 = node->x0; node2; node2 = node2->x0) { - if ( - node2->predCount == 0 && - node2->x12 <= counter && - MI->can_issue(node2->instr) && - (node->x14 > counter || node2->x14 <= counter) - ) - { - if (node->x14 > counter && node2->x14 <= counter) { - node = node2; - continue; - } - - if ((a = uncovering(node)) > (b = uncovering(node2))) - continue; - - if (a < b) { - node = node2; - continue; - } - - if (node->x16 > node2->x16) - continue; - - if (node->x16 < node2->x16) { - node = node2; - continue; - } - - if (coloring) { - if (opcodeinfo[node->instr->op].x9 < opcodeinfo[node2->instr->op].x9) - continue; - - if (opcodeinfo[node->instr->op].x9 > opcodeinfo[node2->instr->op].x9) - node = node2; - } - } - } - - return node; -} - -static void holdoffsuccessors(DGNode *node, UInt16 counter) { - DGSuccessor *succ; - DGNode *n; - - for (succ = node->successors; succ; succ = succ->next) { - n = succ->node; - n->predCount--; - if (n->x12 < counter + succ->x8) - n->x12 = counter + succ->x8; - } -} - -static void scheduleblock(PCodeBlock *block) { - DGNode *node; - UInt16 counter; - PCode *instr; - UInt16 i; - DGNode *head; - - initresources(); - defaultsuccessor = NULL; - head = NULL; - - for (instr = block->lastPCode; instr; instr = instr->prevPCode) { - DGNode *n = makedgnode(instr); - findsuccessors(head, n); - if (instr->flags & fIsBranch) - defaultsuccessor = n; - head = adddgnode(head, n); - } - - computedeadlines(head); - block->firstPCode = block->lastPCode = NULL; - block->pcodeCount = 0; - - MI->initialize(); - counter = 0; - while (head != NULL) { - for (i = 0; i < MI->x0; i++) { - if (head == NULL) - break; - - node = selectinstruction(head, counter); - if (!node) - break; - - instr = node->instr; - if (node->successors) - holdoffsuccessors(node, counter); - - appendpcode(block, instr); - MI->issue(instr); - head = removedgnode(head, node); - } - - MI->advance_clock(); - counter++; - } - - freeoheap(); -} - -void scheduleinstructions(Boolean flag) { - PCodeBlock *block; - int cpu; - - cpu = copts.scheduling; - if (cpu == 10) { - MI = &machine7450; - } else if (copts.altivec_model != 0 || cpu == 7) { - MI = &machine7400; - } else if (cpu == 2) { - MI = &machine603; - } else if (cpu == 5) { - MI = &machine603e; - } else if (cpu == 3) { - MI = &machine604; - } else if (cpu == 6) { - MI = &machine604; - } else if (cpu == 4) { - MI = &machine750; - } else if (cpu == 1) { - MI = &machine601; - } else if (cpu == 9) { - MI = &machine821; - } else { - MI = &machine603; - } - - gather_alias_info(); - - for (block = pcbasicblocks; block; block = block->nextBlock) { - if ( - block->pcodeCount > 2 && - (flag || !(block->flags & (fIsProlog | fIsEpilogue))) && - !(block->flags & fScheduled) - ) - { - scheduleblock(block); - block->flags |= fScheduled; - } - } -} - -int is_dependent(PCode *a, PCode *b, char rclass) { - int i; - int reg; - PCodeArg *op; - - if ( - b && - b->argCount >= 1 && - b->args[0].kind == PCOp_REGISTER && - (char) b->args[0].arg == rclass && - (b->args[0].data.reg.effect & EffectWrite) - ) - { - reg = b->args[0].data.reg.reg; - for (i = 0; i < a->argCount; i++) { - op = &a->args[i]; - if ( - op->kind == PCOp_REGISTER && - (char) op->arg == rclass && - (op->data.reg.effect & (EffectRead | EffectWrite)) && - op->data.reg.reg == reg - ) - return 1; - } - } - - return 0; -} - -int uses_vpermute_unit(PCode *instr) { - int cpu; - - cpu = copts.scheduling; - if (cpu == 10) - return machine7450.uses_vpermute_unit(instr); - if (copts.altivec_model != 0 || cpu == 7) - return machine7400.uses_vpermute_unit(instr); - return 0; -} - -int default_uses_vpermute_unit(PCode *instr) { - return 0; -} diff --git a/compiler_and_linker/unsorted/SpillCode.c b/compiler_and_linker/unsorted/SpillCode.c deleted file mode 100644 index 69e7e43..0000000 --- a/compiler_and_linker/unsorted/SpillCode.c +++ /dev/null @@ -1,452 +0,0 @@ -#include "compiler/SpillCode.h" -#include "compiler/CError.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/CodeGen.h" -#include "compiler/CompilerTools.h" -#include "compiler/Coloring.h" -#include "compiler/InterferenceGraph.h" -#include "compiler/Operands.h" -#include "compiler/PCode.h" -#include "compiler/PCodeUtilities.h" -#include "compiler/Registers.h" -#include "compiler/RegisterInfo.h" -#include "compiler/StackFrame.h" -#include "compiler/objects.h" - -static int last_unused_vreg_before_spilling; -static short rTEMP_for_VR_spill; - -void estimatespillcosts(void) { - PCodeBlock *block; - PCode *instr; - IGNode *node; - PCodeArg *op; - int i; - int weight; - - for (block = pcbasicblocks; block; block = block->nextBlock) { - if (copts.optimizesize) - weight = 1; - else - weight = block->loopWeight; - - for (instr = block->firstPCode; instr; instr = instr->nextPCode) { - op = instr->args; - i = instr->argCount; - while (i--) { - if (PC_OP_IS_READ_ANY_REGISTER(op, coloring_class)) { - node = interferencegraph[op->data.reg.reg]; - if (node->instr8 || copts.optimizesize) - node->spillCost += weight; - else - node->spillCost += weight * 2; - } - op++; - } - - op = instr->args; - i = instr->argCount; - while (i--) { - if (PC_OP_IS_WRITE_ANY_REGISTER(op, coloring_class)) { - node = interferencegraph[op->data.reg.reg]; - if (node->instr8 || (instr->flags & fIsArgInit)) - node->spillCost -= weight; - else - node->spillCost += weight; - } - op++; - } - } - } -} - -static Object *makespilltemporary(Type *type) { - Object *obj = lalloc(sizeof(Object)); - memclrw(obj, sizeof(Object)); - - obj->otype = OT_OBJECT; - obj->access = ACCESSPUBLIC; - obj->datatype = DLOCAL; - obj->type = type; - obj->name = CParser_GetUniqueName(); - obj->u.var.info = CodeGen_GetNewVarInfo(); - obj->u.var.uid = 0; - - return obj; -} - -static PCode *rematerialize_spilled_register(short reg, IGNode *node) { - PCode *instr = copypcode(node->instr8); - - CError_ASSERT(128, instr->args[0].kind == PCOp_REGISTER); - - instr->args[0].data.reg.reg = reg; - return instr; -} - -static void insert_load_spilled_register(PCode *instr, short reg, IGNode *node) { - Type *type; - Opcode opcode; - Object *object; - PCode *newInstr; - PCode *newInstr2; - SInt32 offset; - Operand operand; - - type = node->spillTemporary->type; - switch (coloring_class) { - case RegClass_CRFIELD: - case RegClass_GPR: - switch (type->size) { - case 1: - opcode = PC_LBZ; - break; - case 2: - opcode = is_unsigned(type) ? PC_LHZ : PC_LHA; - break; - case 4: - opcode = PC_LWZ; - break; - case 8: - opcode = PC_LWZ; - break; - default: - CError_FATAL(187); - } - - memclrw(&operand, sizeof(Operand)); - operand.optype = OpndType_Symbol; - operand.object = node->spillTemporary; - CError_ASSERT(222, node->spillTemporary->datatype == DLOCAL); - - coerce_to_addressable(&operand); - - CError_ASSERT(233, operand.optype == OpndType_GPR_ImmOffset); - - CError_ASSERT(237, node->spillTemporary->datatype == DLOCAL); - - if (node->flags & fPairLow) - offset = low_offset; - else if (node->flags & fPairHigh) - offset = high_offset; - else - offset = 0; - insertpcodebefore(instr, makepcode(opcode, reg, operand.reg, operand.object, operand.immOffset + offset)); - break; - - case RegClass_FPR: - CError_ASSERT(253, node->spillTemporary->datatype == DLOCAL); - - if (node->flags & fPairLow) - offset = low_offset; - else if (node->flags & fPairHigh) - offset = high_offset; - else - offset = 0; - - object = node->spillTemporary; - insertpcodebefore( - instr, - makepcode( - (type->size == 8) ? PC_LFD : PC_LFS, - reg, - local_base_register(object), - object, - offset - ) - ); - break; - - case RegClass_VR: - CError_ASSERT(320, node->spillTemporary->datatype == DLOCAL); - - object = node->spillTemporary; - newInstr = makepcode(PC_ADDI, rTEMP_for_VR_spill, local_base_register(object), object, 0); - newInstr2 = makepcode(PC_LVX, reg, 0, rTEMP_for_VR_spill); - insertpcodebefore(instr, newInstr); - insertpcodeafter(newInstr, newInstr2); - break; - - default: - CError_FATAL(333); - } -} - -static void insert_store_spilled_register(PCode *instr, Boolean flag, short reg, IGNode *node) { - Object *object; // r31 - Opcode opcode; // r30 - SInt32 offset; // r26 - PCode *newInstr2; // r26 - PCode *newInstr; // r25 - Type *type; // r25 - - object = node->spillTemporary; - type = object->type; - - switch (coloring_class) { - case RegClass_CRFIELD: - case RegClass_GPR: - switch (type->size) { - case 1: - opcode = PC_STB; - break; - case 2: - opcode = PC_STH; - break; - case 4: - opcode = PC_STW; - break; - case 8: - opcode = PC_STW; - break; - default: - CError_FATAL(391); - } - - if (node->flags & fPairLow) - offset = low_offset; - else if (node->flags & fPairHigh) - offset = high_offset; - else - offset = 0; - - newInstr = makepcode(opcode, reg, local_base_register(object), object, offset); - if (flag) - insertpcodebefore(instr, newInstr); - else - insertpcodeafter(instr, newInstr); - - break; - - case RegClass_FPR: - newInstr = makepcode((type->size == 8) ? PC_STFD : PC_STFS, reg, local_base_register(object), object, 0); - if (flag) - insertpcodebefore(instr, newInstr); - else - insertpcodeafter(instr, newInstr); - - break; - - case RegClass_VR: - newInstr = makepcode(PC_ADDI, rTEMP_for_VR_spill, local_base_register(object), object, 0); - newInstr2 = makepcode(PC_STVX, reg, 0, rTEMP_for_VR_spill); - if (flag) - insertpcodebefore(instr, newInstr); - else - insertpcodeafter(instr, newInstr); - insertpcodeafter(newInstr, newInstr2); - - break; - - default: - CError_FATAL(527); - } -} - -static void spillinstruction(PCodeBlock *block, PCode *instr) { - int reg; - int reg2; - int regs; - IGNode *node; - PCodeArg *op; - int i; - PCodeArg *op2; - int j; - int readCounter; - int writeCounter; - Boolean flag; - - regs = used_virtual_registers[coloring_class]; - flag = 0; - for (i = 0, op = instr->args; i < instr->argCount; i++, op++) { - CError_ASSERT(563, instr->block != NULL); - - if ( - PC_OP_IS_ANY_REGISTER(op, coloring_class) && - (reg = op->data.reg.reg) < regs && - ((node = interferencegraph[op->data.reg.reg])->flags & fSpilled) - ) - { - reg2 = used_virtual_registers[coloring_class]++; - readCounter = 0; - writeCounter = 0; - - for (j = i, op2 = op; j < instr->argCount; j++, op2++) { - if (PC_OP_IS_REGISTER(op2, coloring_class, reg)) { - if (op2->data.reg.effect & EffectRead) - readCounter++; - if (op2->data.reg.effect & EffectWrite) - writeCounter++; - op2->data.reg.reg = reg2; - op2->data.reg.effect |= Effect40; - } - } - - if (readCounter) { - if (node->instr8) - insertpcodebefore(instr, rematerialize_spilled_register(reg2, node)); - else - insert_load_spilled_register(instr, reg2, node); - } - - if (writeCounter) { - if (node->instr8 || (instr->flags & fIsArgInit)) - flag = 1; - else - insert_store_spilled_register(instr, 0, reg2, node); - } - } - } - - if (flag) - deletepcode(instr); -} - -static void spillcopy(PCodeBlock *block, PCode *instr) { - IGNode *node1; - IGNode *node2; - int reg; - - node1 = interferencegraph[instr->args[1].data.reg.reg]; - node2 = interferencegraph[instr->args[0].data.reg.reg]; - - if (node1->flags & fSpilled) { - if (node2->flags & fSpilled) { - reg = used_virtual_registers[coloring_class]++; - if (node1->instr8) - insertpcodebefore(instr, rematerialize_spilled_register(reg, node1)); - else - insert_load_spilled_register(instr, reg, node1); - insert_store_spilled_register(instr, 1, reg, node2); - } else { - if (node1->instr8) - insertpcodebefore(instr, rematerialize_spilled_register(instr->args[0].data.reg.reg, node1)); - else - insert_load_spilled_register(instr, instr->args[0].data.reg.reg, node1); - } - } else { - insert_store_spilled_register(instr, 1, instr->args[1].data.reg.reg, node2); - } - - deletepcode(instr); -} - -static void spillcall(PCodeBlock *block, PCode *instr) { - PCodeArg *opSrc; - PCodeArg *opDst; - int opCount; - int volatileCount; - int i; - - opCount = instr->argCount; - volatileCount = branch_count_volatiles(); - - opDst = instr->args + volatileCount; - opSrc = instr->args + volatileCount; - for (i = volatileCount; i < opCount; i++) { - if ( - PC_OP_IS_ANY_REGISTER(opSrc, coloring_class) && - opSrc->data.reg.reg >= n_real_registers[coloring_class] && - (interferencegraph[opSrc->data.reg.reg]->flags & fSpilled) - ) - { - instr->argCount--; - } else { - *opDst = *opSrc; - opDst++; - } - opSrc++; - } - - spillinstruction(block, instr); -} - -static void assign_spill_locations(void) { - UInt32 i; - IGNode *node; - Type *type; - - last_unused_vreg_before_spilling = used_virtual_registers[coloring_class]; - for (i = n_real_registers[coloring_class]; i < last_unused_vreg_before_spilling; i++) { - node = interferencegraph[i]; - if (node->flags & fCoalesced) - continue; - if (!(node->flags & fSpilled)) - continue; - - if (!node->spillTemporary) { - switch (coloring_class) { - case RegClass_GPR: - type = TYPE(&stunsignedlong); - break; - case RegClass_CRFIELD: - type = TYPE(&stunsignedlong); - break; - case RegClass_FPR: - type = TYPE(&stunsignedlong); - break; - case RegClass_VR: - type = TYPE(&stvectorunsignedchar); - break; - default: - CError_FATAL(771); - } - - node->spillTemporary = makespilltemporary(type); - } - - if (node->spillTemporary->datatype == DLOCAL && !(node->spillTemporary->u.var.info->flags & VarInfoFlag1)) - assign_local_memory(node->spillTemporary); - - if (node->flags & fPairHigh) - Registers_GetVarInfo(node->spillTemporary)->regHi = Register0; - else - Registers_GetVarInfo(node->spillTemporary)->reg = Register0; - } -} - -void insertspillcode(void) { - PCodeBlock *block; - PCode *instr; - PCode *nextInstr; - PCodeArg *op; - UInt32 i; - int flag; - - rTEMP_for_VR_spill = 0; - assign_spill_locations(); - - for (block = pcbasicblocks; block; block = block->nextBlock) { - for (instr = block->firstPCode; instr; instr = nextInstr) { - nextInstr = instr->nextPCode; - flag = 0; - op = instr->args; - i = instr->argCount; - while (i--) { - if ( - PC_OP_IS_ANY_REGISTER(op, coloring_class) && - op->data.reg.reg < last_unused_vreg_before_spilling && - (interferencegraph[op->data.reg.reg]->flags & fSpilled) - ) - { - flag = 1; - break; - } - op++; - } - - if (flag) { - if (coloring_class == RegClass_VR && rTEMP_for_VR_spill == 0) - rTEMP_for_VR_spill = used_virtual_registers[RegClass_GPR]++; - - if (instr->flags & fIsMove) - spillcopy(block, instr); - else if (instr->flags & fIsCall) - spillcall(block, instr); - else - spillinstruction(block, instr); - } - } - } -} diff --git a/compiler_and_linker/unsorted/StackFrame.c b/compiler_and_linker/unsorted/StackFrame.c deleted file mode 100644 index 6fa4524..0000000 --- a/compiler_and_linker/unsorted/StackFrame.c +++ /dev/null @@ -1,1252 +0,0 @@ -#include "compiler/StackFrame.h" -#include "compiler/CError.h" -#include "compiler/CFunc.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/CodeGen.h" -#include "compiler/CompilerTools.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" -#include "compiler/PCodeUtilities.h" -#include "compiler/RegisterInfo.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -#define ALIGN(thing, alignment) ( ~((alignment) - 1) & ((thing) + (alignment) - 1) ) -#define ALIGN_REMAINDER(thing, alignment) ( ALIGN(thing, alignment) - (thing) ) - -Boolean requires_frame; -Boolean makes_call; -Boolean uses_globals; -Boolean dynamic_stack; -Boolean large_stack; -static SInt32 out_param_alignment; -static SInt32 in_parameter_size; -static SInt32 in_param_alignment; -static SInt32 frame_alignment; -static SInt32 alloca_alignment; -static SInt32 linkage_area_size; -static SInt32 parameter_area_size; -static SInt32 parameter_area_size_estimate; -static SInt32 local_data_size; -static SInt32 local_data_limit; -static SInt32 large_data_near_size; -static SInt32 large_data_far_size; -static ObjectList *local_objects[ObjClassMax]; -static ObjectList *local_objects_tail[ObjClassMax]; -static SInt32 non_volatile_save_offset[RegClassMax]; -static SInt32 VRSAVE_save_offset; -static SInt32 LR_save_offset; -static SInt32 nonvolatile_save_size; -static UInt32 vrsave_mask; -static SInt32 frame_size; -static SInt32 frame_size_estimate; -static SInt32 genuine_frame_size; -static Object *dummylocal; -static Boolean dynamic_align_stack; -static Boolean has_varargs; -static Boolean compressing_data_area; -static PCode *setup_caller_sp; -static PCode *align_instr1; -static PCode *align_instr2; -static short vrsave_register; -static PCode *loadvrsave; -static PCode *storevrsave; -Object *dummyvaparam; -void *dummyprofiler; - -// forward declarations -static void insert_local_object(UInt8 oclass, Object *obj); -static void compress_data_area(void); -static UInt32 align_bits(UInt32 value, UInt8 bitcount); -static Boolean use_helper_function(char rclass); -static Boolean need_link_register(void); -static void call_helper_function(char *name, char rclass, short effect); -static void save_nonvolatile_FPRs(int reg, SInt32 offset); -static void save_nonvolatile_VRs(int reg, SInt32 offset); -static void restore_nonvolatile_FPRs(int reg, SInt32 offset); -static void restore_nonvolatile_VRs(int reg, SInt32 offset); -static void save_nonvolatile_GPRs(int reg, SInt32 offset); -static void restore_nonvolatile_GPRs(int reg, SInt32 offset); -static void do_allocate_dynamic_stack_space(Boolean isConstantSize, int reg1, int reg2, SInt32 size); - -void init_stack_globals(Object *funcobj) { - RegClass rclass; - ObjClass oclass; - - requires_frame = 0; - makes_call = 0; - uses_globals = 0; - dynamic_stack = 0; - large_stack = 0; - vrsave_register = -1; - dynamic_align_stack = 0; - compressing_data_area = 0; - align_instr1 = NULL; - align_instr2 = NULL; - setup_caller_sp = NULL; - dummyvaparam = NULL; - loadvrsave = NULL; - storevrsave = NULL; - local_data_size = 0; - local_data_limit = 0x2000; - large_data_near_size = 0; - large_data_far_size = 0; - frame_size_estimate = 0; - in_parameter_size = 0; - parameter_area_size = 0; - parameter_area_size_estimate = 0; - frame_alignment = 8; - out_param_alignment = 8; - in_param_alignment = 8; - alloca_alignment = 0; - has_varargs = 0; - linkage_area_size = 0; - frame_size = 0; - genuine_frame_size = 0; - nonvolatile_save_size = -1; - VRSAVE_save_offset = -1; - LR_save_offset = -1; - - for (rclass = 0; rclass < RegClassMax; rclass++) - non_volatile_save_offset[rclass] = -1; - - dummyprofiler = NULL; - dummyvaparam = NULL; - dummylocal = NULL; - - for (oclass = 0; oclass < ObjClassMax; oclass++) { - local_objects[oclass] = NULL; - local_objects_tail[oclass] = NULL; - } -} - -void init_frame_sizes(Boolean has_varargs) { - ObjectList *scan; - Object *obj; - SInt32 r30; - SInt32 align; - SInt32 mask; - - r30 = in_parameter_size + parameter_area_size_estimate; - frame_size_estimate = r30 + 2484; - for (scan = locals; scan; scan = scan->next) { - obj = scan->object; - { - align = CMach_AllocationAlignment(obj->type, obj->qual) - 1; - mask = ~align; - } - frame_size_estimate = (frame_size_estimate + align) & mask; - frame_size_estimate += obj->type->size; - } - - if (frame_size_estimate > 0x8000) { - dynamic_stack = 1; - large_stack = 1; - requires_frame = 1; - } - - local_data_limit = 0x8000 - (r30 + 2484); - - if (dynamic_stack) { - requires_frame = 1; - dummylocal = galloc(sizeof(Object)); - memclrw(dummylocal, sizeof(Object)); - dummylocal->type = (Type *) &stvoid; - dummylocal->otype = OT_OBJECT; - dummylocal->name = GetHashNameNode(""); - dummylocal->datatype = DLOCAL; - dummylocal->u.var.info = CodeGen_GetNewVarInfo(); - dummylocal->u.var.info->flags |= VarInfoFlag80; - dummylocal->u.var.info->noregister = 1; - } - - if (dynamic_stack) { - retain_register(NULL, RegClass_GPR, 31); - _FP_ = 31; - } else { - _FP_ = 1; - } -} - -void assign_local_memory(Object *obj) { - // some misassigned registers x.x - short align; - VarInfo *vi; - - align = CMach_AllocationAlignment(obj->type, obj->qual); - if (!compressing_data_area && (obj->u.var.info->flags & VarInfoFlag80)) - return; - - update_frame_align(align); - if (local_data_size + (ALIGN_REMAINDER(local_data_size, align) + ALIGN(obj->type->size, align)) < local_data_limit) { - local_data_size = ALIGN(local_data_size, align); - vi = Registers_GetVarInfo(obj); - vi->flags &= ~VarInfoFlag2; - vi->flags |= VarInfoFlag80; - obj->u.var.uid = local_data_size; - local_data_size += ALIGN(obj->type->size, align); - insert_local_object(ObjClass0, obj); - return; - } - if (compressing_data_area || obj->type->size <= 32) { - large_data_near_size = ALIGN(large_data_near_size, align); - vi = Registers_GetVarInfo(obj); - vi->flags &= ~VarInfoFlag2; - vi->flags |= VarInfoFlag80; - obj->u.var.uid = 0x8000 + large_data_near_size; - large_data_near_size += ALIGN(obj->type->size, align); - insert_local_object(ObjClass1, obj); - } else { - large_data_far_size = ALIGN(large_data_far_size, align); - vi = Registers_GetVarInfo(obj); - vi->flags &= ~VarInfoFlag2; - vi->flags |= VarInfoFlag80; - obj->u.var.uid = 0x10000 + large_data_far_size; - large_data_far_size += ALIGN(obj->type->size, align); - insert_local_object(ObjClass2, obj); - } -} - -void assign_locals_to_memory(ObjectList *first) { - ObjectList *list; - Object *obj; - SInt32 i; - - for (i = 1; i < 1024; i <<= 1) { - for (list = first; list; list = list->next) { - obj = list->object; - if (Registers_GetVarInfo(obj)->used) { - if ((Registers_GetVarInfo(obj) ? Registers_GetVarInfo(obj)->reg : 0) == 0) { - if (obj->type->size <= i) - assign_local_memory(obj); - } - } - } - } - - for (list = first; list; list = list->next) { - obj = list->object; - if (Registers_GetVarInfo(obj)->used) { - if ((Registers_GetVarInfo(obj) ? Registers_GetVarInfo(obj)->reg : 0) == 0) { - assign_local_memory(list->object); - } - } - - if (obj->type && IS_TYPE_ARRAY(obj->type) && IS_TYPE_VECTOR(TYPE_POINTER(obj->type)->target)) - has_altivec_arrays = 1; - } -} - -void compute_frame_sizes(void) { - SInt32 altivec_size; - SInt32 altivec_offset; - - CError_ASSERT(897, alloca_alignment == 0 || alloca_alignment == frame_alignment); - - update_asm_nonvolatile_registers(); - LR_save_offset = 8; - non_volatile_save_offset[RegClass_FPR] = -(used_nonvolatile_registers[RegClass_FPR] * 8); - non_volatile_save_offset[RegClass_GPR] = -(((15 - non_volatile_save_offset[RegClass_FPR]) & ~15) + used_nonvolatile_registers[RegClass_GPR] * 4); - nonvolatile_save_size = -non_volatile_save_offset[RegClass_GPR]; - non_volatile_save_offset[RegClass_CRFIELD] = 4; - VRSAVE_save_offset = -1; - non_volatile_save_offset[RegClass_VR] = -1; - - if (copts.altivec_model) { - if (vrsave_mask) { - VRSAVE_save_offset = non_volatile_save_offset[RegClass_GPR] - 4; - nonvolatile_save_size = nonvolatile_save_size + 4; - } - altivec_size = used_nonvolatile_registers[RegClass_VR] * 16; - if (altivec_size > 0) - nonvolatile_save_size = ALIGN(nonvolatile_save_size + altivec_size, frame_alignment); - } - - if (parameter_area_size) - requires_frame = 1; - - compress_data_area(); - local_data_size = ALIGN(local_data_size, frame_alignment); - nonvolatile_save_size = ALIGN(nonvolatile_save_size, frame_alignment); - if (!requires_frame && (local_data_size + nonvolatile_save_size) <= 224) { - CError_ASSERT(1005, !dynamic_align_stack); - linkage_area_size = 0; - frame_size = 0; - genuine_frame_size = local_data_size + nonvolatile_save_size; - } else { - requires_frame = 1; - if (parameter_area_size < 32) - parameter_area_size = 32; - parameter_area_size = ALIGN(parameter_area_size + 24, frame_alignment) - 24; - if (large_stack) { - CError_ASSERT(1019, !large_data_far_size); - large_data_near_size += parameter_area_size; - parameter_area_size = 0; - } - linkage_area_size = 24; - frame_size = nonvolatile_save_size + (altivec_offset = parameter_area_size + 24 + local_data_size); - if (copts.altivec_model && used_nonvolatile_registers[RegClass_VR]) - non_volatile_save_offset[RegClass_VR] = altivec_offset; - frame_size += ALIGN_REMAINDER(frame_size, 16); - frame_size = ALIGN(frame_size, frame_alignment); - genuine_frame_size = frame_size; - } - if (!large_stack && frame_size > 0x7FFF) - CError_ErrorTerm(CErrorStr210); -} - -static void allocate_new_frame(int reg1, int reg2) { - if (dynamic_align_stack) { - CError_ASSERT(1116, reg1 != _CALLER_SP_); - emitpcode(PC_RLWINM, reg1, 1, 0, align_bits(frame_alignment, 1), 31); - if (frame_size > 0x7FFF) { - CError_FATAL(1122); - return; - } - - if (frame_size) - emitpcode(PC_SUBFIC, reg1, reg1, -frame_size); - else - emitpcode(PC_SUBFIC, reg1, reg1, -genuine_frame_size); - - if (reg2) - emitpcode(PC_MR, reg2, 1); - - emitpcode(PC_STWUX, 1, 1, reg1); - } else { - if (frame_size > 0x7FFF) - CError_FATAL(1153); - else - emitpcode(PC_STWU, 1, 1, 0, -frame_size); - - if (reg2) - emitpcode(PC_MR, reg2, 1); - } -} - -void generate_prologue(PCodeBlock *block, Boolean has_varargs) { - PCodeBlock *save_block; - Boolean needs_lr; - Statement *save_statement; - Statement stmt; - UInt32 vrsave_low; - UInt32 vrsave_high; - - save_block = pclastblock; - needs_lr = need_link_register(); - save_statement = current_statement; - stmt.sourceoffset = functionbodyoffset; - current_statement = &stmt; - pclastblock = block; - - if (setup_caller_sp && setup_caller_sp->block) { - if ( - setup_caller_sp->op == PC_MR && - setup_caller_sp->args[1].kind == PCOp_REGISTER && - setup_caller_sp->args[1].arg == RegClass_GPR && - setup_caller_sp->args[1].data.reg.reg == _FP_ - ) - CError_FATAL(1197); - - _CALLER_SP_ = setup_caller_sp->args[0].data.reg.reg; - deletepcode(setup_caller_sp); - setup_caller_sp = NULL; - } else if (_CALLER_SP_ != _FP_) { - _CALLER_SP_ = -1; - } - - if (align_instr1 && align_instr1->block) { - deletepcode(align_instr1); - align_instr1 = NULL; - } - - if (align_instr2 && align_instr2->block) { - deletepcode(align_instr2); - align_instr2 = NULL; - } - - if (loadvrsave && loadvrsave->block) { - deletepcode(loadvrsave); - loadvrsave = NULL; - } - - if (storevrsave && storevrsave->block) { - deletepcode(storevrsave); - storevrsave = NULL; - } - - if (needs_lr) - emitpcode(PC_MFLR, 0); - - if (used_nonvolatile_registers[RegClass_CRFIELD]) { - emitpcode(PC_MFCR, 12); - emitpcode(PC_STW, 12, 1, 0, non_volatile_save_offset[RegClass_CRFIELD]); - } - - if (used_nonvolatile_registers[RegClass_FPR]) - save_nonvolatile_FPRs(1, 0); - if (used_nonvolatile_registers[RegClass_GPR]) - save_nonvolatile_GPRs(1, 0); - if (needs_lr) - emitpcode(PC_STW, 0, 1, 0, 8); - - if (frame_size) { - if (vrsave_mask) { - emitpcode(PC_MFSPR, 0, 256); - emitpcode(PC_STW, 0, 1, 0, VRSAVE_save_offset); - vrsave_register = 0; - } - allocate_new_frame(12, (_CALLER_SP_ > 0 && _CALLER_SP_ != _FP_) ? _CALLER_SP_ : 0); - } else { - CError_ASSERT(1326, !dynamic_align_stack); - if (vrsave_mask) - emitpcode(PC_MFSPR, vrsave_register, 256); - } - - if (vrsave_mask) { - vrsave_high = vrsave_mask >> 16; - vrsave_low = vrsave_mask & 0xFFFF; - if (vrsave_mask == 0xFFFFFFFF) { - emitpcode(PC_LI, 0, -1); - } else { - if (vrsave_high) - emitpcode(PC_ORIS, 0, vrsave_register, vrsave_high); - if (vrsave_low) - emitpcode(PC_ORI, 0, 0, vrsave_low); - } - emitpcode(PC_MTSPR, 256, 0); - } - - if (used_nonvolatile_registers[RegClass_VR]) - save_nonvolatile_VRs(1, 0); - - if (dynamic_stack) - emitpcode(PC_MR, 31, 1); - - if (large_stack) - do_allocate_dynamic_stack_space(1, 11, 0, large_data_near_size); - - block->flags |= fIsProlog; - pclastblock = save_block; - current_statement = save_statement; -} - -void generate_epilogue(PCodeBlock *block, Boolean add_blr) { - PCodeBlock *save_block; - Boolean needs_lr; - Statement *save_statement; - Statement stmt; - - save_block = pclastblock; - needs_lr = need_link_register(); - save_statement = current_statement; - if (!save_statement) { - stmt.sourceoffset = current_linenumber; - current_statement = &stmt; - } - pclastblock = block; - - if (used_nonvolatile_registers[RegClass_VR]) - restore_nonvolatile_VRs(_FP_, 0); - - if (dynamic_align_stack) { - load_store_register(PC_LWZ, 1, 1, NULL, 0); - setpcodeflags(fSideEffects); - if (needs_lr) - load_store_register(PC_LWZ, 0, 1, 0, 8); - } else { - if (needs_lr) - load_store_register(PC_LWZ, 0, _FP_, 0, frame_size + 8); - if (frame_size > 0) { - if (dynamic_stack) { - load_store_register(PC_LWZ, 1, 1, 0, 0); - setpcodeflags(fSideEffects); - } else { - emitpcode(PC_ADDI, 1, 1, 0, frame_size); - setpcodeflags(fSideEffects); - } - } - } - - if (used_nonvolatile_registers[RegClass_CRFIELD]) { - load_store_register(PC_LWZ, 12, 1, NULL, non_volatile_save_offset[RegClass_CRFIELD]); - emitpcode(PC_MTCRF, 255, 12); - } - - if (vrsave_mask) { - if (!requires_frame) { - emitpcode(PC_MTSPR, 256, vrsave_register); - } else { - emitpcode(PC_LWZ, 11, 1, 0, VRSAVE_save_offset); - emitpcode(PC_MTSPR, 256, 11); - } - } - - if (used_nonvolatile_registers[RegClass_FPR]) - restore_nonvolatile_FPRs(1, 0); - if (needs_lr && !use_helper_function(RegClass_GPR)) - emitpcode(PC_MTLR, 0); - - if (used_nonvolatile_registers[RegClass_GPR]) - restore_nonvolatile_GPRs(1, 0); - if (needs_lr && use_helper_function(RegClass_GPR)) - emitpcode(PC_MTLR, 0); - - if (add_blr) { - emitpcode(PC_BLR); - setpcodeflags(fIsVolatile); - } - - block->flags |= fIsEpilogue; - pclastblock = save_block; - current_statement = save_statement; -} - -static void load_base_offset(int dest_reg, int base_reg, SInt32 offset) { - if (offset) - emitpcode(PC_ADDI, dest_reg, base_reg, 0, offset); - else - emitpcode(PC_MR, dest_reg, base_reg); -} - -static void save_nonvolatile_FPRs(int reg, SInt32 offset) { - short i; - SInt32 o; - - o = offset + non_volatile_save_offset[RegClass_FPR]; - - if (!use_helper_function(RegClass_FPR)) { - for (i = 1; i <= used_nonvolatile_registers[RegClass_FPR]; i++) { - emitpcode(PC_STFD, 32 - i, reg, NULL, o + (used_nonvolatile_registers[RegClass_FPR] - i) * 8); - setpcodeflags(fIsVolatile); - } - } else { - load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_FPR] * 8); - call_helper_function("__save_fpr_%d", RegClass_FPR, EffectRead); - } -} - -static void save_nonvolatile_VRs(int reg, SInt32 offset) { - short i; - SInt32 o; - - o = offset + non_volatile_save_offset[RegClass_VR]; - - if (!use_helper_function(RegClass_VR)) { - for (i = 1; i <= used_nonvolatile_registers[RegClass_VR]; i++) { - emitpcode(PC_LI, 0, o + (used_nonvolatile_registers[RegClass_VR] - i) * 16); - emitpcode(PC_STVX, 32 - i, reg, 0); - setpcodeflags(fIsVolatile); - } - } else { - load_base_offset(0, reg, o + used_nonvolatile_registers[RegClass_VR] * 16); - call_helper_function("__savev%d", RegClass_VR, EffectRead); - } -} - -static void restore_nonvolatile_FPRs(int reg, SInt32 offset) { - short i; - SInt32 o; - - o = offset + non_volatile_save_offset[RegClass_FPR]; - - if (!use_helper_function(RegClass_FPR)) { - for (i = 1; i <= used_nonvolatile_registers[RegClass_FPR]; i++) { - load_store_register(PC_LFD, 32 - i, reg, NULL, o + (used_nonvolatile_registers[RegClass_FPR] - i) * 8); - setpcodeflags(fIsVolatile); - } - } else { - load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_FPR] * 8); - call_helper_function("__restore_fpr_%d", RegClass_FPR, EffectWrite); - } -} - -static void restore_nonvolatile_VRs(int reg, SInt32 offset) { - short i; - SInt32 o; - - o = offset + non_volatile_save_offset[RegClass_VR]; - - if (!use_helper_function(RegClass_VR)) { - for (i = 1; i <= used_nonvolatile_registers[RegClass_VR]; i++) { - emitpcode(PC_LI, 0, o + (used_nonvolatile_registers[RegClass_VR] - i) * 16); - setpcodeflags(fIsVolatile); - emitpcode(PC_LVX, 32 - i, reg, 0); - setpcodeflags(fIsVolatile); - } - } else { - load_base_offset(0, reg, o + used_nonvolatile_registers[RegClass_VR] * 16); - call_helper_function("__restv%d", RegClass_VR, EffectWrite); - } -} - -static void save_nonvolatile_GPRs(int reg, SInt32 offset) { - int i; - SInt32 o; - - o = offset + non_volatile_save_offset[RegClass_GPR]; - - if (!use_helper_function(RegClass_GPR)) { - if (copts.use_lmw_stmw && ((used_nonvolatile_registers[RegClass_GPR] > 4) || (copts.optimizesize && (used_nonvolatile_registers[RegClass_GPR] > 1)))) { - emitpcode(PC_STMW, used_nonvolatile_registers[RegClass_GPR] - 1, 32 - used_nonvolatile_registers[RegClass_GPR], reg, 0, o); - } else { - for (i = 1; i <= used_nonvolatile_registers[RegClass_GPR]; i++) { - emitpcode(PC_STW, 32 - i, reg, 0, o + (used_nonvolatile_registers[RegClass_GPR] - i) * 4); - } - } - } else { - load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_GPR] * 4); - call_helper_function("__savegpr_%d", RegClass_GPR, EffectRead); - } -} - -static void restore_nonvolatile_GPRs(int reg, SInt32 offset) { - int i; - SInt32 o; - - o = offset + non_volatile_save_offset[RegClass_GPR]; - - if (!use_helper_function(RegClass_GPR)) { - if (copts.use_lmw_stmw && ((used_nonvolatile_registers[RegClass_GPR] > 4) || (copts.optimizesize && (used_nonvolatile_registers[RegClass_GPR] > 1)))) { - emitpcode(PC_LMW, used_nonvolatile_registers[RegClass_GPR] - 1, 32 - used_nonvolatile_registers[RegClass_GPR], reg, 0, o); - setpcodeflags(fIsVolatile); - } else { - for (i = 1; i <= used_nonvolatile_registers[RegClass_GPR]; i++) { - emitpcode(PC_LWZ, 32 - i, reg, 0, o + (used_nonvolatile_registers[RegClass_GPR] - i) * 4); - setpcodeflags(fIsVolatile); - } - } - } else { - load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_GPR] * 4); - call_helper_function("__restgpr_%d", RegClass_GPR, EffectWrite); - } -} - -static void do_allocate_dynamic_stack_space(Boolean isConstantSize, int reg1, int reg2, SInt32 size) { - load_store_register(PC_LWZ, reg2, 1, NULL, 0); - if (isConstantSize) { - size = ALIGN(size, frame_alignment); - if (size < 0x8000) { - emitpcode(PC_STWU, reg2, 1, 0, -size); - } else { - emitpcode(PC_LIS, reg1, 0, (short) HIGH_PART(-size)); - if (-size) - emitpcode(PC_ADDI, reg1, reg1, 0, LOW_PART(-size)); - emitpcode(PC_STWUX, reg2, 1, reg1); - setpcodeflags(fIsVolatile | fSideEffects); - } - } else { - emitpcode(PC_STWUX, reg2, 1, reg1); - setpcodeflags(fIsVolatile | fSideEffects); - } -} - -void allocate_dynamic_stack_space(Boolean isConstantSize, int reg1, int reg2, SInt32 size) { - if (copts.altivec_model) - update_frame_align(16); - do_allocate_dynamic_stack_space(isConstantSize, reg1, reg2, size); - add_immediate(reg1, 1, dummylocal, 0); -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct Traceback { - UInt8 x0; - UInt8 x1; - UInt8 x2; - UInt8 x3; - UInt8 x4; - UInt8 x5; - - UInt8 x6_0 : 2; - UInt8 x6_1 : 1; // set to 1 - UInt8 x6_2 : 5; - - UInt8 x7_0 : 1; - UInt8 x7_1 : 1; // set to 1 - UInt8 has_dynamic_stack : 1; // set to 1 if dynamic_stack - UInt8 x7_3 : 3; - UInt8 uses_CRs : 1; // set to 1 if CRs used - UInt8 needs_link_register : 1; // set to 1 if link register used - - UInt8 has_frame_size : 1; // set to 1 if frame_size is nonzero - UInt8 x8_1 : 1; // set to 0 - UInt8 used_FPRs : 6; // stores non-volatile FPRs used - - UInt8 x9_0 : 1; // set to 0 - UInt8 x9_1 : 1; // set to 1 if VRs or vrsave used - UInt8 used_GPRs : 6; // stores non-volatile GPRs used - - UInt8 xA; - UInt8 xB; - - SInt32 funcsize; - SInt16 namelen; - char name[0]; -} Traceback; - -typedef struct TracebackExtra { - UInt8 used_VRs : 6; - UInt8 has_vrsave_mask : 1; - UInt8 is_varargs : 1; - UInt8 vec_arg_count : 7; - UInt8 has_vrsave_mask_or_used_VRs : 1; -} TracebackExtra; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -char *generate_traceback(SInt32 funcsize, char *funcname, SInt32 *tbsize, Object *func) { - char *work; - short namelen; - Traceback *buf; - SInt32 bufsize; - - namelen = strlen(funcname); - bufsize = ALIGN(sizeof(Traceback) + namelen + (dynamic_stack ? 1 : 0) + ((used_nonvolatile_registers[RegClass_VR] || vrsave_mask) ? sizeof(TracebackExtra) : 0), 4); - buf = lalloc(bufsize); - memclrw(buf, bufsize); - - buf->x4 = 0; - buf->x5 = copts.cplusplus ? 9 : 0; - buf->x6_1 = 1; - buf->x7_1 = 1; - if (dynamic_stack) - buf->has_dynamic_stack = 1; - if (used_nonvolatile_registers[RegClass_CRFIELD]) - buf->uses_CRs = 1; - if (need_link_register()) - buf->needs_link_register = 1; - if (frame_size) - buf->has_frame_size = 1; - buf->used_FPRs = used_nonvolatile_registers[RegClass_FPR]; - buf->used_GPRs = used_nonvolatile_registers[RegClass_GPR]; - buf->x8_1 = 0; - buf->x9_0 = 0; - buf->x9_1 = (used_nonvolatile_registers[RegClass_VR] || vrsave_mask) != 0; - buf->funcsize = funcsize; - buf->namelen = namelen; - - work = buf->name; - strcpy(work, funcname); - work += namelen; - if (dynamic_stack) { - *(work++) = 31; - } - - if (vrsave_mask || used_nonvolatile_registers[RegClass_VR]) { - TracebackExtra *extra; - Boolean is_varargs; - int vec_count; - FuncArg *args, *scan; - Type *type; - - extra = (TracebackExtra *) work; - vec_count = 0; - args = TYPE_FUNC(func->type)->args; - scan = args; - while (scan && scan != &elipsis) - scan = scan->next; - is_varargs = scan == &elipsis; - while (args) { - if ((type = args->type) && IS_TYPE_VECTOR(type)) - vec_count++; - args = args->next; - } - extra->used_VRs = used_nonvolatile_registers[RegClass_VR]; - extra->has_vrsave_mask = vrsave_mask != 0; - extra->is_varargs = is_varargs; - extra->vec_arg_count = vec_count; - extra->has_vrsave_mask_or_used_VRs = vrsave_mask || used_nonvolatile_registers[RegClass_VR]; - } - - *tbsize = bufsize; - return (char *) buf; -} - -static SInt32 localsbase(void) { - SInt32 size = parameter_area_size; - if (frame_size || dynamic_align_stack) - size += linkage_area_size; - else - size -= genuine_frame_size; - return size; -} - -static SInt32 parametersbase(int flag) { - if (flag) - return 24; - - return frame_size ? (genuine_frame_size + 24) : 24; -} - -void check_dynamic_aligned_frame(void) { - PCode *pc; - - if (used_nonvolatile_registers[RegClass_VR]) { - update_frame_align(16); - requires_frame = 1; - } - - if (frame_alignment > in_param_alignment) { - dynamic_align_stack = 1; - requires_frame = 1; - CError_ASSERT(2091, !has_varargs || _CALLER_SP_ != -1); - CError_ASSERT(2096, _CALLER_SP_ != _FP_); - if (setup_caller_sp && setup_caller_sp->block) { - align_instr1 = makepcode(PC_RLWINM, 12, 1, 0, 5, 31); - insertpcodebefore(setup_caller_sp, align_instr1); - align_instr2 = makepcode(PC_STWUX, 1, 1, 12); - insertpcodeafter(setup_caller_sp, align_instr2); - } - } else { - dynamic_align_stack = 0; - if (setup_caller_sp && setup_caller_sp->block) { - pc = makepcode(PC_MR, _CALLER_SP_, _FP_); - insertpcodebefore(setup_caller_sp, pc); - deletepcode(setup_caller_sp); - setup_caller_sp = pc; - } - _CALLER_SP_ = _FP_; - } - - vrsave_mask = 0; - if (copts.altivec_model) { - vrsave_mask = colored_vrs_as_vrsave(pcbasicblocks); - if (!requires_frame && vrsave_mask) { - vrsave_register = 11; - loadvrsave = makepcode(PC_LWZ, 11, 1, 0, -4); - appendpcode(prologue, loadvrsave); - storevrsave = makepcode(PC_STW, 11, 1, 0, -4); - appendpcode(epilogue, storevrsave); - } - } -} - -void move_varargs_to_memory(void) { - short reg; - - has_varargs = 1; - dummyvaparam = galloc(sizeof(Object)); - memclrw(dummyvaparam, sizeof(Object)); - - dummyvaparam->type = TYPE(&stvoid); - dummyvaparam->otype = OT_OBJECT; - dummyvaparam->name = GetHashNameNode(""); - dummyvaparam->datatype = DLOCAL; - dummyvaparam->u.var.info = CodeGen_GetNewVarInfo(); - dummyvaparam->u.var.uid = 0; - dummyvaparam->u.var.info->noregister = 1; - Registers_GetVarInfo(dummyvaparam)->flags = (Registers_GetVarInfo(dummyvaparam)->flags & ~VarInfoFlag1) | VarInfoFlag1; - - for (reg = last_argument_register[RegClass_GPR] + 1; (int)reg <= 10; reg++) { - emitpcode(PC_STW, reg, local_base_register(dummyvaparam), dummyvaparam, (reg - 3) * 4); - setpcodeflags(fIsPtrOp | fIsArgInit); - } -} - -void assign_arguments_to_memory(Object *func, UInt8 mysteryFlag, Boolean hasVarargs) { - // almost matches except for the not/andc issue - SInt32 pos; - ObjectList *list; - Object *obj; - Type *type; - short reg; - SInt32 chk; - Boolean flag; - - pos = 0; - reg = 2; - - for (list = arguments; list; list = list->next) { - obj = list->object; - type = obj->type; - if (!IS_TYPE_VECTOR(type)) { - obj->datatype = DLOCAL; - obj->u.var.info = CodeGen_GetNewVarInfo(); - if (IS_TYPE_ARRAY(type) || IS_TYPE_NONVECTOR_STRUCT(type) || IS_TYPE_CLASS(type) || - IS_TYPE_12BYTES_MEMBERPOINTER(type)) { - chk = CMach_ArgumentAlignment(type); - if (chk > 4) { - pos = ALIGN(pos, chk); - update_in_param_align(chk); - } - } - obj->u.var.uid = pos; - Registers_GetVarInfo(obj)->flags = (Registers_GetVarInfo(obj)->flags & ~VarInfoFlag1) | VarInfoFlag1; - if (!copts.littleendian && (IS_TYPE_INT(obj->type) || IS_TYPE_ENUM(obj->type)) && obj->type->size < 4) - obj->u.var.uid += 4 - obj->type->size; - pos += type->size; - pos = ALIGN(pos, 4); - } else { - obj->u.var.info = CodeGen_GetNewVarInfo(); - obj->u.var.uid = 0; - obj->datatype = DLOCAL; - flag = 1; - if (reg <= 13) - flag = hasVarargs; - if (flag) { - pos = ALIGN(pos + 24, 16) - 24; - obj->u.var.uid = pos; - pos += 16; - update_in_param_align(16); - Registers_GetVarInfo(obj)->flags = (Registers_GetVarInfo(obj)->flags & ~VarInfoFlag1) | VarInfoFlag1; - } else { - assign_local_memory(obj); - Registers_GetVarInfo(obj)->flags = Registers_GetVarInfo(obj)->flags & ~VarInfoFlag1; - } - reg++; - } - } - - in_parameter_size = (in_parameter_size < pos) ? pos : in_parameter_size; - CError_ASSERT(2408, !dummyvaparam); -} - -SInt32 set_out_param_displ(SInt32 a, Type *type, Boolean flag, SInt32 *outvar, SInt32 b) { - // does not match due to errant andc - SInt32 argAlign; - - if (!flag && !b) { - *outvar = 0; - return a; - } - - if (IS_TYPE_VECTOR(type)) { - update_out_param_align(16); - a = ALIGN(a + 16 + 24, 16) - 24; - } else if (IS_TYPE_ARRAY(type) || IS_TYPE_NONVECTOR_STRUCT(type) || IS_TYPE_CLASS(type) || IS_TYPE_12BYTES_MEMBERPOINTER(type)) { - argAlign = CMach_ArgumentAlignment(type); - if (argAlign > 4) { - a = ALIGN(a + 24, argAlign) - 24; - update_in_param_align(argAlign); - } - } - - *outvar = a; - a = ALIGN(a + b, 4); - return a; -} - -SInt32 out_param_displ_to_offset(SInt32 displ) { - return displ + 24; -} - -Boolean needs_frame(void) { - return (frame_size > 224) || requires_frame; -} - -void update_out_param_size(SInt32 size) { - if (size < 32) - size = 32; - if (parameter_area_size < size) - parameter_area_size = size; -} - -void estimate_out_param_size(SInt32 size) { - if (parameter_area_size_estimate < size) - parameter_area_size_estimate = size; -} - -void update_out_param_align(SInt32 align) { - if (out_param_alignment < align) - out_param_alignment = align; - update_frame_align(align); -} - -void update_in_param_align(SInt32 align) { - if (in_param_alignment < align) - in_param_alignment = align; -} - -void update_frame_align(SInt32 align) { - if (frame_alignment < align) - frame_alignment = align; -} - -SInt32 local_offset_32(Object *obj) { - short align; - SInt32 offset; - - if (obj->u.var.info->flags & VarInfoFlag1) - align = CMach_ArgumentAlignment(obj->type); - else - align = CMach_AllocationAlignment(obj->type, obj->qual); - - offset = obj->u.var.uid; - if (offset > 0x7FFF) - offset = 0x8000 - offset - ALIGN(obj->type->size, align); - - if (obj->u.var.info->flags & VarInfoFlag1) - return offset + parametersbase(local_base_register(obj) != _FP_); - else - return offset + localsbase(); -} - -SInt32 local_offset_lo(Object *obj, SInt32 offset) { - SInt32 combo = offset + local_offset_32(obj); - return LOW_PART(combo); - //return (SInt16) (offset + local_offset_32(obj)); -} - -SInt32 local_offset_ha(Object *obj, SInt32 offset) { - SInt32 combo = offset + local_offset_32(obj); - return HIGH_PART(combo); - //return (SInt16) ((combo >> 16) + ((combo & 0x8000) >> 15)); -} - -SInt32 local_offset_16(Object *obj) { - SInt32 offset32 = local_offset_32(obj); - SInt16 offset16 = (SInt16) offset32; - CError_ASSERT(2662, offset32 == offset16); - return offset16; -} - -Boolean local_is_16bit_offset(Object *obj) { - SInt32 offset32 = local_offset_32(obj); - SInt16 offset16 = (SInt16) offset32; - return offset32 == offset16; -} - -int local_base_register(Object *obj) { - PCode *pc; - - if (obj->u.var.info->flags & VarInfoFlag1) { - if (coloring && _CALLER_SP_ == -1) { - _CALLER_SP_ = used_virtual_registers[RegClass_GPR]++; - pc = makepcode(PC_LWZ, _CALLER_SP_, 1, 0, 0); - setup_caller_sp = pc; - appendpcode(prologue, pc); - } - return _CALLER_SP_; - } else { - return _FP_; - } -} - -static UInt32 align_bits(UInt32 value, UInt8 bitcount) { - UInt32 base = bitcount != 0; - switch (value) { - case 0x0002: return base + 30; - case 0x0004: return base + 29; - case 0x0008: return base + 28; - case 0x0010: return base + 27; - case 0x0020: return base + 26; - case 0x0040: return base + 25; - case 0x0080: return base + 24; - case 0x0100: return base + 23; - case 0x0200: return base + 22; - case 0x0400: return base + 21; - case 0x0800: return base + 20; - case 0x1000: return base + 19; - case 0x2000: return base + 18; - default: - CError_FATAL(2754); - return base + 27; - } -} - -Boolean is_large_frame(void) { - CError_ASSERT(2769, frame_size != -1); - return large_stack; -} - -void no_frame_for_asm(void) { - frame_size = 0; -} - -Boolean can_add_displ_to_local(Object *obj, SInt32 displ) { - if (obj->datatype != DLOCAL) - return 0; - - if (local_offset_32(obj) == (short) local_offset_32(obj)) - if ((displ + local_offset_32(obj)) == (short) (displ + local_offset_32(obj))) - return 1; - - return 0; -} - -SInt32 get_alloca_alignment(void) { - SInt32 align = frame_alignment; - if (copts.altivec_model) - align = ALIGN(align, 16); - - if (!alloca_alignment) - alloca_alignment = align; - else - CError_ASSERT(2825, alloca_alignment == align); - - return align_bits(align, 0); -} - -static Boolean use_helper_function(char rclass) { - if (copts.no_register_save_helpers) - return 0; - - switch (rclass) { - case RegClass_GPR: - if (copts.use_lmw_stmw) - return 0; - return (used_nonvolatile_registers[RegClass_GPR] > 4) || (copts.optimizesize && used_nonvolatile_registers[RegClass_GPR] > 2); - case RegClass_FPR: - return (used_nonvolatile_registers[RegClass_FPR] > 3) || (copts.optimizesize && used_nonvolatile_registers[RegClass_FPR] > 2); - case RegClass_VR: - return (used_nonvolatile_registers[RegClass_VR] > 3) || (copts.optimizesize && used_nonvolatile_registers[RegClass_VR] > 2); - default: - CError_FATAL(2862); - return 0; - } -} - -static Boolean need_link_register(void) { - if (copts.codegen_pic && uses_globals) - return 1; - - if (makes_call) - return 1; - - return use_helper_function(RegClass_FPR) || use_helper_function(RegClass_GPR) || use_helper_function(RegClass_VR); -} - -static void call_helper_function(char *name, char rclass, short effect) { - char str[32]; - Object *func; - NameSpace *save_scope; - PCode *pc; - int extra_args; - PCodeArg *arg; - short i; - - extra_args = 1; - if (rclass == RegClass_VR) - extra_args = 2; - - sprintf(str, name, 32 - used_nonvolatile_registers[rclass]); - - save_scope = cscope_current; - cscope_current = cscope_root; - func = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - cscope_current = save_scope; - - func->name = GetHashNameNodeExport(str); - - pc = makepcode(PC_BL, extra_args + used_nonvolatile_registers[rclass], func, 0); - for (i = 1, arg = &pc->args[1]; i <= used_nonvolatile_registers[rclass]; i++, arg++) { - arg->kind = PCOp_REGISTER; - arg->arg = rclass; - arg->data.reg.reg = n_real_registers[rclass] - i; - arg->data.reg.effect = effect; - } - - if (rclass == RegClass_VR) { - arg[1].kind = PCOp_REGISTER; - arg[1].arg = RegClass_GPR; - arg[1].data.reg.reg = 12; - arg[1].data.reg.effect = EffectWrite; - arg[2].kind = PCOp_REGISTER; - arg[2].arg = RegClass_GPR; - arg[2].data.reg.reg = 0; - arg[2].data.reg.effect = EffectRead; - } else { - arg[1].kind = PCOp_REGISTER; - arg[1].arg = RegClass_GPR; - arg[1].data.reg.reg = 11; - arg[1].data.reg.effect = EffectRead; - } - - appendpcode(pclastblock, pc); - setpcodeflags(fSideEffects); -} - -static SInt32 nearest_power_of_two(SInt32 n) { - SInt32 power = 1; - do { - power <<= 1; - } while (power && power < n); - - CError_ASSERT(2933, power != 0); - return power; -} - -static void compress_data_area(void) { - // doesn't quite match - SInt32 r0; - SInt32 r7; - ObjectList *list; - Object *obj; - PCodeBlock *block; - PCode *pc; - int i; - - compressing_data_area = 1; - - if (large_stack) { - r0 = 0; - } else { - r0 = parameter_area_size; - if (r0 < 32) - r0 = 32; - } - r7 = ALIGN(r0 + 24, frame_alignment) - 24; - local_data_limit = 0x8000 - ALIGN(24 + in_parameter_size + nonvolatile_save_size + r7, frame_alignment); - - if (local_objects_tail[ObjClass0]) { - if (local_objects[ObjClass1]) { - local_objects_tail[ObjClass0]->next = local_objects[ObjClass1]; - local_objects_tail[ObjClass0] = local_objects_tail[ObjClass1]; - } - if (local_objects[ObjClass2]) { - local_objects_tail[ObjClass0]->next = local_objects[ObjClass2]; - local_objects_tail[ObjClass0] = local_objects_tail[ObjClass2]; - } - } else if (local_objects_tail[ObjClass1]) { - local_objects[ObjClass0] = local_objects[ObjClass1]; - local_objects_tail[ObjClass0] = local_objects_tail[ObjClass1]; - if (local_objects[ObjClass2]) { - local_objects_tail[ObjClass0]->next = local_objects[ObjClass2]; - local_objects_tail[ObjClass0] = local_objects_tail[ObjClass2]; - } - } else { - local_objects[ObjClass0] = local_objects[ObjClass2]; - local_objects_tail[ObjClass0] = local_objects_tail[ObjClass2]; - } - - for (list = local_objects[ObjClass0]; list; list = list->next) - Registers_GetVarInfo(list->object)->used = 0; - - for (block = pcbasicblocks; block; block = block->nextBlock) { - for (pc = block->firstPCode; pc; pc = pc->nextPCode) { - for (i = 0; i < pc->argCount; i++) { - if (pc->args[i].kind == PCOp_MEMORY && pc->args[i].data.mem.obj && pc->args[i].data.mem.obj->datatype == DLOCAL) - Registers_GetVarInfo(pc->args[i].data.mem.obj)->used = 1; - } - } - } - - local_data_size = 0; - large_data_near_size = 0; - large_data_far_size = 0; - - for (list = local_objects[ObjClass0]; list; list = list->next) { - obj = list->object; - if (Registers_GetVarInfo(obj)->used) - assign_local_memory(obj); - } -} - -static void insert_local_object(UInt8 oclass, Object *obj) { - ObjectList *list; - - if (!compressing_data_area) { - list = lalloc(sizeof(ObjectList)); - memclrw(list, sizeof(ObjectList)); - list->object = obj; - if (!local_objects[oclass]) - local_objects[oclass] = list; - if (local_objects_tail[oclass]) - local_objects_tail[oclass]->next = list; - local_objects_tail[oclass] = list; - } -} diff --git a/compiler_and_linker/unsorted/StrengthReduction.c b/compiler_and_linker/unsorted/StrengthReduction.c deleted file mode 100644 index 2b68dca..0000000 --- a/compiler_and_linker/unsorted/StrengthReduction.c +++ /dev/null @@ -1,751 +0,0 @@ -#include "compiler/StrengthReduction.h" -#include "compiler/BitVectors.h" -#include "compiler/CompilerTools.h" -#include "compiler/LoopDetection.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" -#include "compiler/Registers.h" -#include "compiler/UseDefChains.h" - -int strengthreducedloops; - -static PCode *findinitializer(Loop *loop, short reg) { - UInt32 *vec; - PCode *best; - RegUseOrDef *list; - - vec = usedefinfo[loop->body->blockIndex].defvec8; - best = NULL; - - for (list = reg_Defs[RegClass_GPR][reg]; list; list = list->next) { - if ( - !(bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, loop->memberblocks)) && - bitvectorgetbit(list->id, vec) - ) - { - if (best) - return NULL; - best = Defs[list->id].pcode; - } - } - - if (best) { - if (best->op == PC_LI || best->op == PC_ADDI || best->op == PC_ADD) - return best; - } - - return NULL; -} - -static int isbasicinductionvariable(Loop *loop, short reg, SInt32 step) { - RegUseOrDef *list; - PCode *instr; - - for (list = reg_Defs[RegClass_GPR][reg]; list; list = list->next) { - instr = Defs[list->id].pcode; - if (bitvectorgetbit(instr->block->blockIndex, loop->memberblocks)) { - if (instr->op != PC_ADDI) - return 0; - if (instr->args[1].data.reg.reg != reg) - return 0; - if (instr->args[2].data.imm.value != step) - return 0; - } - } - - return 1; -} - -static void addbasicinductionvariable(Loop *loop, short reg, SInt32 step) { - BasicInductionVar *biv; - RegUseOrDef *list; - PCode *instr; - InstrList *instrList; - - for (biv = loop->basicInductionVars; biv; biv = biv->next) { - if (biv->reg == reg) - return; - } - - biv = oalloc(sizeof(BasicInductionVar)); - biv->next = loop->basicInductionVars; - loop->basicInductionVars = biv; - - biv->loop = loop; - biv->inductionVars = NULL; - biv->instrsC = NULL; - biv->step = step; - biv->reg = reg; - - for (list = reg_Defs[RegClass_GPR][reg]; list; list = list->next) { - instr = Defs[list->id].pcode; - if (bitvectorgetbit(instr->block->blockIndex, loop->memberblocks)) { - instrList = oalloc(sizeof(InstrList)); - instrList->next = biv->instrsC; - biv->instrsC = instrList; - instrList->instr = instr; - } - } - - biv->initializer = findinitializer(loop, reg); -} - -static void findbasicinductionvariables(Loop *loop) { - SInt16 step; - BlockList *block; - PCode *instr; - short reg; - - for (block = loop->blocks; block; block = block->next) { - for (instr = block->block->firstPCode; instr; instr = instr->nextPCode) { - if (instr->op == PC_ADDI) { - if ( - (reg = instr->args[0].data.reg.reg) >= 32 && - instr->args[1].data.reg.reg == reg && - isbasicinductionvariable(loop, reg, step = instr->args[2].data.imm.value) - ) - addbasicinductionvariable(loop, reg, step); - } - } - } -} - -static void findallbasicinductionvariables(Loop *loop) { - while (loop) { - if (loop->children) - findallbasicinductionvariables(loop->children); - findbasicinductionvariables(loop); - loop = loop->nextSibling; - } -} - -static int isinductionvariable(BasicInductionVar *biv, int useID, SInt32 *result1, short *result2, short *result3, Loop **result4) { - RegUseOrDef *list; - int counter; - Loop *loop; - Loop *scanloop; - PCode *instr; - - instr = Uses[useID].pcode; - *result2 = 0; - *result3 = 0; - *result4 = NULL; - - switch (instr->op) { - case PC_MULLI: - *result1 = instr->args[2].data.imm.value; - break; - - case PC_RLWINM: - if (instr->args[3].data.imm.value) - return 0; - if (instr->args[2].data.imm.value > 15) - return 0; - if (instr->args[4].data.imm.value != (31 - instr->args[2].data.imm.value)) - return 0; - if (PCODE_FLAG_SET_F(instr) & fRecordBit) - return 0; - *result1 = 1 << instr->args[2].data.imm.value; - break; - - case PC_LBZX: - case PC_LHZX: - case PC_LHAX: - case PC_LWZX: - case PC_STBX: - case PC_STHX: - case PC_STWX: - case PC_LFSX: - case PC_LFDX: - case PC_STFSX: - case PC_STFDX: - *result2 = 0; - *result3 = 0; - if (instr->args[1].data.reg.reg == biv->reg) { - *result2 = 1; - *result3 = 2; - } else if (instr->args[2].data.reg.reg == biv->reg) { - *result2 = 2; - *result3 = 1; - } - - counter = 0; - for (list = reg_Defs[RegClass_GPR][instr->args[*result3].data.reg.reg]; list; list = list->next) { - if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, biv->loop->memberblocks)) - counter++; - } - if (counter) - return 0; - - loop = biv->loop; - for (scanloop = loop->parent; scanloop; scanloop = scanloop->parent) { - counter = 0; - for (list = reg_Defs[RegClass_GPR][instr->args[*result3].data.reg.reg]; list; list = list->next) { - if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, scanloop->memberblocks)) - counter++; - } - if (!biv->initializer || bitvectorgetbit(biv->initializer->block->blockIndex, scanloop->memberblocks)) - counter++; - if (counter) - break; - loop = scanloop; - } - - *result4 = loop; - *result1 = 1; - return 1; - - default: - return 0; - } - - counter = 0; - for (list = reg_Defs[RegClass_GPR][instr->args[0].data.reg.reg]; list; list = list->next) { - if (bitvectorgetbit(Defs[list->id].pcode->block->blockIndex, biv->loop->memberblocks)) - counter++; - } - - return counter == 1; -} - -static void addinductionvariable(BasicInductionVar *biv, PCode *instr, SInt32 val1, short val2, short val3, Loop *val4) { - InductionVar *iv; - - iv = oalloc(sizeof(InductionVar)); - iv->next = biv->inductionVars; - biv->inductionVars = iv; - - iv->basicVar = biv; - iv->instr = instr; - iv->instrC = NULL; - iv->step = val1; - iv->x18 = val2; - iv->x1A = val3; - iv->someloop = val4; - if (instr->flags & (fIsRead | fIsWrite)) - iv->x1C = -1; - else - iv->x1C = instr->args[0].data.reg.reg; - iv->x1E = -1; -} - -static void findnonbasicinductionvariables(Loop *loop) { - BasicInductionVar *biv; - RegUseOrDef *list; - SInt32 result1; - short result2; - short result3; - Loop *result4; - - for (biv = loop->basicInductionVars; biv; biv = biv->next) { - for (list = reg_Uses[RegClass_GPR][biv->reg]; list; list = list->next) { - if (bitvectorgetbit(Uses[list->id].pcode->block->blockIndex, loop->memberblocks)) { - if (isinductionvariable(biv, list->id, &result1, &result2, &result3, &result4)) - addinductionvariable(biv, Uses[list->id].pcode, result1, result2, result3, result4); - } - } - } -} - -static void findallnonbasicinductionvariables(Loop *loop) { - while (loop) { - if (loop->children) - findallnonbasicinductionvariables(loop->children); - if (loop->basicInductionVars) - findnonbasicinductionvariables(loop); - loop = loop->nextSibling; - } -} - -static void initializeinductionvariable(InductionVar *iv) { - BasicInductionVar *biv; // r31 - PCode *instr; // r27 - PCodeBlock *preheader; // r30 - SInt32 value30; // r30 - short reg29; // r29 - short reg26; // r26 - - biv = iv->basicVar; - preheader = biv->loop->preheader; - - if (iv->x1A) { - reg29 = iv->instr->args[iv->x1A].data.reg.reg; - reg26 = iv->instr->args[iv->x18].data.reg.reg; - instr = NULL; - - if ( - biv->initializer && - biv->initializer->op == PC_LI && - biv->initializer->block == preheader - ) - { - if (biv->initializer->args[1].data.imm.value == 0) - instr = makepcode(PC_MR, iv->x1E, reg29); - else if (FITS_IN_SHORT(biv->initializer->args[1].data.imm.value)) - instr = makepcode(PC_ADDI, iv->x1E, reg29, 0, biv->initializer->args[1].data.imm.value); - } - - if (!instr) - instr = makepcode(PC_ADD, iv->x1E, reg29, reg26); - - if (biv->initializer && instr->op != PC_ADD) - insertpcodeafter(biv->initializer, instr); - else if (iv->someloop && iv->someloop->preheader->lastPCode) - insertpcodebefore(iv->someloop->preheader->lastPCode, instr); - else - insertpcodebefore(preheader->lastPCode, instr); - - iv->instrC = instr; - iv->x1C = reg29; - return; - } - - if (!biv->initializer || biv->initializer->op != PC_LI) { - instr = copypcode(iv->instr); - instr->args[0].data.reg.reg = iv->x1E; - insertpcodebefore(preheader->lastPCode, instr); - } else { - value30 = biv->initializer->args[1].data.imm.value * iv->step; - if (!FITS_IN_SHORT(value30)) { - instr = makepcode(PC_LIS, iv->x1E, 0, HIGH_PART(value30)); - insertpcodeafter(biv->initializer, instr); - if (value30 != 0) - insertpcodeafter(instr, makepcode(PC_ADDI, iv->x1E, iv->x1E, 0, LOW_PART(value30))); - } else { - instr = makepcode(PC_LI, iv->x1E, value30); - insertpcodeafter(biv->initializer, instr); - } - } -} - -static void incrementinductionvariable(InductionVar *iv) { - SInt32 value; - BasicInductionVar *biv; - PCode *instr; - InstrList *list; - - biv = iv->basicVar; - value = iv->step * biv->step; - for (list = biv->instrsC; list; list = list->next) { - if (!FITS_IN_SHORT(value)) { - instr = makepcode(PC_ADDIS, iv->x1E, iv->x1E, 0, HIGH_PART(value)); - insertpcodeafter(list->instr, instr); - - if (value != 0) { - instr = makepcode(PC_ADDI, iv->x1E, iv->x1E, 0, LOW_PART(value)); - insertpcodeafter(list->instr->nextPCode, instr); - } - } else { - instr = makepcode(PC_ADDI, iv->x1E, iv->x1E, 0, value); - insertpcodeafter(list->instr, instr); - } - } -} - -static void copyinductionvariable(InductionVar *iv) { - if (iv->instr->flags & (fIsRead | fIsWrite)) { - iv->instr->op -= 2; - iv->instr->args[1].data.reg.reg = iv->x1E; - iv->instr->args[2].kind = PCOp_IMMEDIATE; - iv->instr->args[2].data.imm.value = 0; - iv->instr->args[2].data.imm.obj = NULL; - } else { - insertpcodeafter(iv->instr, makepcode(PC_MR, iv->x1C, iv->x1E)); - deletepcode(iv->instr); - } -} - -static int testnestediv(InductionVar *iv, SInt32 step1, int reg, SInt32 step2, Loop *loop1, Loop *loop2) { - SInt32 addend; - BlockList *list; - PCode *instr; - PCodeArg *op; - int i; - - if (iv->instrC && iv->x1C == reg) { - if (iv->instrC->op == PC_MR) - addend = 0; - else if (iv->instrC->op == PC_ADDI) - addend = iv->instrC->args[2].data.imm.value; - else - return 0; - - if (step2 == (addend + (step1 * iv->step * loop2->iterationCount))) { - for (list = loop1->blocks; list && list->block != loop2->blocks->block; list = list->next) { - for (instr = list->block->firstPCode; instr; instr = instr->nextPCode) { - op = instr->args; - i = instr->argCount; - while (i--) { - if ( - op->kind == PCOp_REGISTER && - op->arg == RegClass_GPR && - op->data.reg.reg == reg - ) - return 0; - op++; - } - } - } - return 1; - } - } - - return 0; -} - -static void strengthreducenestediv(short reg, SInt32 step, PCode *initializer, Loop *loop) { - Loop *scanloop; - BasicInductionVar *biv; - InductionVar *iv; - PCode *instr; - PCodeArg *op; - int i; - - for (scanloop = loop->children; scanloop; scanloop = scanloop->nextSibling) { - if ( - scanloop->isKnownCountingLoop && - scanloop->x4F && - bitvectorgetbit(scanloop->body->blockIndex, loop->vec2C) - ) - { - for (biv = scanloop->basicInductionVars; biv; biv = biv->next) { - for (iv = biv->inductionVars; iv; iv = iv->next) { - if (testnestediv(iv, biv->step, reg, step, loop, scanloop)) { - deletepcode(iv->instrC); - if (initializer) { - insertpcodeafter(initializer, iv->instrC); - } else if (loop->body->lastPCode) { - for (instr = loop->body->lastPCode; instr; instr = instr->prevPCode) { - op = instr->args; - i = instr->argCount; - while (i--) { - if ( - op->kind == PCOp_REGISTER && - op->arg == RegClass_GPR && - (op->data.reg.effect & EffectWrite) && - op->data.reg.reg == reg - ) - break; - op++; - } - } - - if (instr) - insertpcodeafter(instr, iv->instrC); - else - insertpcodebefore(loop->body->firstPCode, iv->instrC); - } else { - appendpcode(loop->body, iv->instrC); - } - } - } - } - } - } -} - -static void strengthreducenestedbiv(BasicInductionVar *biv) { - Loop *loop; - InductionVar *iv; - - loop = biv->loop; - for (iv = biv->inductionVars; iv; iv = iv->next) - strengthreducenestediv(iv->x1E, iv->step * biv->step, iv->instrC, loop); - - strengthreducenestediv(biv->reg, biv->step, biv->initializer, loop); -} - -static void strengthreduceinductionvariable(BasicInductionVar *biv) { - int counter; - InductionVar *iv; - InductionVar *otherIv; - short reg; - - counter = 0; - for (iv = biv->inductionVars; iv; iv = iv->next) { - if (iv->step == 1) - counter++; - } - - for (iv = biv->inductionVars; iv; iv = iv->next) { - if ( - (counter <= 4 || iv->step != 1) && - iv->instr->block && - (iv->x1A == 0 || iv->instr->args[2].kind != PCOp_IMMEDIATE) - ) - { - if (iv->x1E == -1) { - iv->x1E = used_virtual_registers[RegClass_GPR]++; - initializeinductionvariable(iv); - incrementinductionvariable(iv); - if (iv->step == 1) { - reg = iv->instr->args[iv->x1A].data.reg.reg; - for (otherIv = iv->next; otherIv; otherIv = otherIv->next) { - if (otherIv->x1A != 0 && otherIv->instr->args[otherIv->x1A].data.reg.reg == reg) - otherIv->x1E = iv->x1E; - } - } else { - for (otherIv = iv->next; otherIv; otherIv = otherIv->next) { - if (otherIv->step == iv->step) - otherIv->x1E = iv->x1E; - } - } - } - - copyinductionvariable(iv); - strengthreducedloops = 1; - } - } -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct BivInit { - SInt32 x0; - short x4; - short x6; - short x8; - Object *xA; -} BivInit; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -static void calc_biv_init(BasicInductionVar *biv, BivInit *init) { - PCode *instr; - PCode *scan; - PCodeArg *op; - int i; - - instr = biv->initializer; - init->x0 = 0; - init->x4 = -1; - init->x6 = -1; - init->x8 = 0; - init->xA = NULL; - - if (!biv->initializer || (biv->initializer->op != PC_ADDI && biv->initializer->op != PC_ADD)) - return; - - if (instr->op == PC_ADDI) { - if (instr->args[1].data.reg.reg == biv->reg) { - init->x0 = instr->args[2].data.imm.value; - for (scan = instr->prevPCode; scan; scan = scan->prevPCode) { - op = scan->args; - i = scan->argCount; - while (i--) { - if ( - op->kind == PCOp_REGISTER && - op->arg == RegClass_GPR && - op->data.reg.reg == biv->reg && - (op->data.reg.effect & EffectWrite) - ) - { - if (scan->op == PC_ADD) { - init->x4 = scan->args[1].data.reg.reg; - init->x6 = scan->args[2].data.reg.reg; - } else if (scan->op == PC_ADDI) { - if (scan->args[2].kind == PCOp_IMMEDIATE) { - init->x4 = scan->args[1].data.reg.reg; - init->x8 = scan->args[2].data.imm.value; - } else if (scan->args[2].kind == PCOp_MEMORY) { - init->x4 = scan->args[1].data.reg.reg; - init->x8 = scan->args[2].data.mem.offset; - init->xA = scan->args[2].data.mem.obj; - } - } - return; - } - op++; - } - } - } else { - if (instr->args[2].kind == PCOp_IMMEDIATE) { - init->x4 = instr->args[1].data.reg.reg; - init->x8 = instr->args[2].data.imm.value; - } else if (instr->args[2].kind == PCOp_MEMORY) { - init->x4 = instr->args[1].data.reg.reg; - init->x8 = instr->args[2].data.mem.offset; - init->xA = instr->args[2].data.mem.obj; - } - } - } else if (instr->op == PC_ADD) { - if (instr->args[1].data.reg.reg == biv->reg) { - init->x6 = instr->args[2].data.reg.reg; - for (scan = instr->prevPCode; scan; scan = scan->prevPCode) { - op = scan->args; - i = scan->argCount; - while (i--) { - if ( - op->kind == PCOp_REGISTER && - op->arg == RegClass_GPR && - op->data.reg.reg == biv->reg && - (op->data.reg.effect & EffectWrite) && - scan->op == PC_ADDI - ) - { - if (scan->args[2].kind == PCOp_IMMEDIATE) { - init->x4 = scan->args[1].data.reg.reg; - init->x8 = scan->args[2].data.imm.value; - } else if (scan->args[2].kind == PCOp_MEMORY) { - init->x4 = scan->args[1].data.reg.reg; - init->x8 = scan->args[2].data.mem.offset; - init->xA = scan->args[2].data.mem.obj; - } - return; - } - op++; - } - } - } else { - init->x4 = instr->args[1].data.reg.reg; - init->x6 = instr->args[2].data.reg.reg; - } - } -} - -static void combineinductionvariables(Loop *loop, BasicInductionVar *biv1, BasicInductionVar *biv2, SInt32 difference) { - PCode *instr1; // r31 - int reg1; // r30 - int reg2; // r29 - PCode *instr2; // r24 - PCodeBlock *nextBlock; // r24 - BlockList *list; - PCodeArg *op; - int i; - PCode *instr; - - instr1 = NULL; - instr2 = NULL; - - reg1 = biv1->reg; - CError_ASSERT(930, reg1 >= 0); - - reg2 = biv2->reg; - CError_ASSERT(934, reg2 >= 0); - - if (!FITS_IN_SHORT(difference)) - return; - - for (list = loop->blocks; list; list = list->next) { - for (instr = list->block->firstPCode; instr; instr = instr->nextPCode) { - if (instr1) { - op = instr->args; - i = instr->argCount; - while (i--) { - if ( - op->kind == PCOp_REGISTER && - op->arg == RegClass_GPR && - op->data.reg.reg == reg1 - ) - return; - op++; - } - } - - if (instr->op == PC_ADDI) { - if (instr->args[0].data.reg.reg == reg1) { - if (instr1) - return; - instr1 = instr; - } else if (instr->args[0].data.reg.reg == reg2) { - if (instr2) - return; - instr2 = instr; - } - } - } - } - - if (loop->body->lastPCode->flags & fIsBranch) { - nextBlock = NULL; - - for (i = 0; i < loop->body->lastPCode->argCount; i++) { - if (loop->body->lastPCode->args[i].kind == PCOp_LABEL) { - nextBlock = loop->body->lastPCode->args[i].data.label.label->block; - break; - } - } - - if (!nextBlock) - return; - } else { - nextBlock = loop->body->nextBlock; - } - - deletepcode(instr1); - instr1->args[1].data.reg.reg = reg2; - instr1->args[2].data.imm.value = difference; - - if (nextBlock->firstPCode) - insertpcodebefore(nextBlock->firstPCode, instr1); - else - appendpcode(nextBlock, instr1); - - biv1->reg = -1; - strengthreducedloops = 1; -} - -static void strengthreduceinductionvariables(Loop *loop) { - BasicInductionVar *biv1; - BasicInductionVar *biv2; - BivInit init1; - BivInit init2; - - for (biv1 = loop->basicInductionVars; biv1; biv1 = biv1->next) { - if (biv1->inductionVars) - strengthreduceinductionvariable(biv1); - strengthreducenestedbiv(biv1); - } - - for (biv1 = loop->basicInductionVars; biv1; biv1 = biv1->next) { - if (biv1->reg != -1) { - calc_biv_init(biv1, &init1); - if (init1.x4 != -1) { - for (biv2 = loop->basicInductionVars; biv2; biv2 = biv2->next) { - if (biv2->reg != -1 && biv2 != biv1) { - calc_biv_init(biv2, &init2); - if ( - init2.x4 != -1 && - init1.x4 == init2.x4 && - init1.x6 == init2.x6 && - init1.x8 == init2.x8 && - init1.xA == init2.xA && - biv1->step == biv2->step - ) - { - if (init1.x0 < init2.x0) { - combineinductionvariables(loop, biv2, biv1, init2.x0 - init1.x0); - } else { - combineinductionvariables(loop, biv1, biv2, init1.x0 - init2.x0); - break; - } - } - } - } - } - } - } -} - -static void strengthreduceallinductionvariables(Loop *loop) { - while (loop) { - if (loop->children) - strengthreduceallinductionvariables(loop->children); - if (loop->basicInductionVars) - strengthreduceinductionvariables(loop); - loop = loop->nextSibling; - } -} - -void strengthreduceloops(void) { - strengthreducedloops = 0; - if (loopsinflowgraph) { - computeusedefchains(0); - findallbasicinductionvariables(loopsinflowgraph); - findallnonbasicinductionvariables(loopsinflowgraph); - strengthreduceallinductionvariables(loopsinflowgraph); - freeoheap(); - } -} diff --git a/compiler_and_linker/unsorted/StructMoves.c b/compiler_and_linker/unsorted/StructMoves.c deleted file mode 100644 index 7c28b88..0000000 --- a/compiler_and_linker/unsorted/StructMoves.c +++ /dev/null @@ -1,792 +0,0 @@ -#include "compiler/StructMoves.h" -#include "compiler/CError.h" -#include "compiler/CParser.h" -#include "compiler/CodeGen.h" -#include "compiler/Operands.h" -#include "compiler/PCode.h" -#include "compiler/PCodeUtilities.h" -#include "compiler/Registers.h" - -void make_addressable(Operand *opnd, SInt32 offset, int unusedArg) { - int reg; - - if (opnd->optype == OpndType_IndirectSymbol) - coerce_to_addressable(opnd); - - if (opnd->optype != OpndType_IndirectGPR_ImmOffset || (opnd->immOffset + offset) > 0x7FFF) { - reg = used_virtual_registers[RegClass_GPR]++; - load_address(reg, opnd); - opnd->optype = OpndType_IndirectGPR_ImmOffset; - opnd->reg = reg; - opnd->object = NULL; - opnd->immOffset = 0; - } -} - -static void load_displaced_address(Operand *opnd, SInt32 offset) { - int reg; - - reg = used_virtual_registers[RegClass_GPR]++; - if (opnd->optype == OpndType_IndirectSymbol) - coerce_to_addressable(opnd); - - if (opnd->optype == OpndType_IndirectGPR_ImmOffset) { - offset += opnd->immOffset; - if (!FITS_IN_SHORT(offset)) { - add_immediate(reg, opnd->reg, opnd->object, opnd->immOffset); - emitpcode(PC_ADDI, reg, reg, 0, offset - opnd->immOffset); - } else { - add_immediate(reg, opnd->reg, opnd->object, offset); - } - } else if (opnd->optype == OpndType_IndirectGPR_Indexed) { - emitpcode(PC_ADD, reg, opnd->reg, opnd->regOffset); - emitpcode(PC_ADDI, reg, reg, 0, offset); - } else { - CError_FATAL(80); - } - - opnd->optype = OpndType_IndirectGPR_ImmOffset; - opnd->reg = reg; - opnd->object = NULL; - opnd->immOffset = 0; -} - -static void move_block_via_load_store(Operand *dst, Operand *src, SInt32 len, SInt32 align) { - SInt32 step; - SInt32 pos; - int floatReg; - int reg; - - if (src->optype == OpndType_IndirectSymbol) - coerce_to_addressable(src); - if (dst->optype == OpndType_IndirectSymbol) - coerce_to_addressable(dst); - - if (len == 8) { - floatReg = used_virtual_registers[RegClass_FPR]++; - if (src->optype == OpndType_IndirectGPR_ImmOffset) { - load_store_register(PC_LFD, floatReg, src->reg, src->object, src->immOffset); - setpcodeflags(src->flags); - } else if (src->optype == OpndType_IndirectGPR_Indexed) { - emitpcode(PC_LFDX, floatReg, src->reg, src->regOffset); - setpcodeflags(src->flags); - } else { - CError_FATAL(145); - } - - if (dst->optype == OpndType_IndirectGPR_ImmOffset) { - load_store_register(PC_STFD, floatReg, dst->reg, dst->object, dst->immOffset); - setpcodeflags(dst->flags); - } else if (dst->optype == OpndType_IndirectGPR_Indexed) { - emitpcode(PC_STFDX, floatReg, dst->reg, dst->regOffset); - setpcodeflags(dst->flags); - } else { - CError_FATAL(157); - } - - return; - } - - if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { - SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align; - step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2; - } else { - step = ((UInt32) len > 4) ? 4 : ((UInt32) len <= 2) ? len : 2; - } - - if (step != len) { - if (dst->optype == OpndType_IndirectGPR_Indexed) - make_addressable(dst, len, 0); - if (src->optype == OpndType_IndirectGPR_Indexed) - make_addressable(src, len, 0); - } - - for (pos = 0; len != 0; len -= step, pos += step) { - reg = used_virtual_registers[RegClass_GPR]++; - if (src->optype == OpndType_IndirectGPR_ImmOffset) { - load_store_register( - (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, - reg, - src->reg, - src->object, - src->immOffset + pos - ); - setpcodeflags(src->flags); - } else if (src->optype == OpndType_IndirectGPR_Indexed) { - emitpcode( - (step == 1) ? PC_LBZX : (step == 2) ? PC_LHZX : PC_LWZX, - reg, - src->reg, - src->regOffset - ); - setpcodeflags(src->flags); - } else { - CError_FATAL(183); - } - - if (dst->optype == OpndType_IndirectGPR_ImmOffset) { - load_store_register( - (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, - reg, - dst->reg, - dst->object, - dst->immOffset + pos - ); - setpcodeflags(dst->flags); - } else if (dst->optype == OpndType_IndirectGPR_Indexed) { - emitpcode( - (step == 1) ? PC_STBX : (step == 2) ? PC_STHX : PC_STWX, - reg, - dst->reg, - dst->regOffset - ); - setpcodeflags(dst->flags); - } else { - CError_FATAL(195); - } - } -} - -static void move_block_via_load_store_sequence(Operand *dst, Operand *src, SInt32 len, SInt32 align) { - SInt32 pos; - int i; - SInt32 step; - - pos = 0; - make_addressable(dst, len, 0); - make_addressable(src, len, 0); - - if ((align % 8) == 0) { - while (len >= 16) { - int reg1 = used_virtual_registers[RegClass_FPR]++; - int reg2 = used_virtual_registers[RegClass_FPR]++; - load_store_register(PC_LFD, reg1, src->reg, src->object, src->immOffset + pos); - setpcodeflags(src->flags); - load_store_register(PC_LFD, reg2, src->reg, src->object, src->immOffset + pos + 8); - setpcodeflags(src->flags); - - load_store_register(PC_STFD, reg1, dst->reg, dst->object, dst->immOffset + pos); - setpcodeflags(dst->flags); - load_store_register(PC_STFD, reg2, dst->reg, dst->object, dst->immOffset + pos + 8); - setpcodeflags(dst->flags); - - pos += 16; - len -= 16; - } - } - - while (len >= 8) { - if ((align % 8) == 0) { - int reg = used_virtual_registers[RegClass_FPR]++; - - load_store_register(PC_LFD, reg, src->reg, src->object, src->immOffset + pos); - setpcodeflags(src->flags); - - load_store_register(PC_STFD, reg, dst->reg, dst->object, dst->immOffset + pos); - setpcodeflags(dst->flags); - - pos += 8; - len -= 8; - } else { - if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { - SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align; - step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp > 2) ? 2 : 1; - } else { - step = 4; - } - - for (i = 0; i < 8; i += (step * 2)) { - int reg1 = used_virtual_registers[RegClass_GPR]++; - int reg2 = used_virtual_registers[RegClass_GPR]++; - - load_store_register( - (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, - reg1, - src->reg, - src->object, - src->immOffset + pos - ); - setpcodeflags(src->flags); - - load_store_register( - (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, - reg2, - src->reg, - src->object, - src->immOffset + pos + step - ); - setpcodeflags(src->flags); - - load_store_register( - (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, - reg1, - dst->reg, - dst->object, - dst->immOffset + pos - ); - setpcodeflags(dst->flags); - - load_store_register( - (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, - reg2, - dst->reg, - dst->object, - dst->immOffset + pos + step - ); - setpcodeflags(dst->flags); - - pos += (step * 2); - len -= (step * 2); - } - } - } - - while (len) { - int reg; - - if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { - SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align; - step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2; - } else { - step = ((UInt32) len > 4) ? 4 : ((UInt32) len <= 2) ? len : 2; - } - - reg = used_virtual_registers[RegClass_GPR]++; - - load_store_register( - (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, - reg, - src->reg, - src->object, - src->immOffset + pos - ); - setpcodeflags(src->flags); - - load_store_register( - (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, - reg, - dst->reg, - dst->object, - dst->immOffset + pos - ); - setpcodeflags(dst->flags); - - len -= step; - pos += step; - } -} - -static void move_block_via_inline_loop(Operand *dst, Operand *src, SInt32 len, SInt32 align) { - PCodeLabel *label; // r25 - SInt32 pos; // r25 - SInt32 step; // r24 - int reg1; // r22 - int reg2; // r23 - SInt32 remainder; // r23 - - label = makepclabel(); - - if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { - SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align; - step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2; - } else { - step = 4; - } - - load_displaced_address(dst, -step); - load_displaced_address(src, -step); - - CError_ASSERT(377, (len / step) != 0); - - reg1 = used_virtual_registers[RegClass_GPR]++; - load_immediate(reg1, len / (step * 2)); - emitpcode(PC_MTCTR, reg1); - branch_label(label); - - reg1 = used_virtual_registers[RegClass_GPR]++; - reg2 = used_virtual_registers[RegClass_GPR]++; - - load_store_register( - (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, - reg1, - src->reg, - NULL, - step - ); - setpcodeflags(src->flags); - - load_store_register( - (step == 1) ? PC_LBZU : (step == 2) ? PC_LHZU : PC_LWZU, - reg2, - src->reg, - NULL, - step * 2 - ); - setpcodeflags(src->flags); - - load_store_register( - (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, - reg1, - dst->reg, - NULL, - step - ); - setpcodeflags(dst->flags); - - load_store_register( - (step == 1) ? PC_STBU : (step == 2) ? PC_STHU : PC_STWU, - reg2, - dst->reg, - NULL, - step * 2 - ); - setpcodeflags(dst->flags); - - branch_decrement_always(PC_BDNZ, label); - - for (remainder = len & 7, pos = step; remainder != 0; remainder -= step, pos += step) { - int reg; - - if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) { - SInt32 tmp = (align == 0) ? 1 : (align > remainder) ? remainder : align; - step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2; - } else { - step = ((UInt32) remainder > 4) ? 4 : ((UInt32) remainder <= 2) ? remainder : 2; - } - - reg = used_virtual_registers[RegClass_GPR]++; - - load_store_register( - (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ, - reg, - src->reg, - NULL, - pos - ); - setpcodeflags(src->flags); - - load_store_register( - (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW, - reg, - dst->reg, - NULL, - pos - ); - setpcodeflags(dst->flags); - } -} - -void move_block(Operand *dst, Operand *src, SInt32 len, SInt32 align) { - Operand myDst; - - myDst = *dst; - - CError_ASSERT(447, myDst.optype >= OpndType_IndirectGPR_ImmOffset); - CError_ASSERT(449, src->optype >= OpndType_IndirectGPR_ImmOffset); - - if (len == 1 || len == 2 || len == 4) - move_block_via_load_store(&myDst, src, len, align); - else if (len == 8 && align == 8) - move_block_via_load_store(&myDst, src, len, align); - else if (len <= 16 || (copts.optimizesize == 0 && len <= 64)) - move_block_via_load_store_sequence(&myDst, src, len, align); - else - move_block_via_inline_loop(&myDst, src, len, align); -} - -static void load_word_of_small_struct(short dstReg, short srcReg, Operand *opnd, SInt32 offset, SInt32 len, SInt32 align) { - short tmpReg; - short extra = 0; - - switch (len) { - case 1: - tmpReg = used_virtual_registers[RegClass_GPR]++; - load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset); - setpcodeflags(opnd->flags); - emitpcode(PC_RLWINM, dstReg, tmpReg, 24, 0, 7); - setpcodeflags(opnd->flags); - break; - case 2: - case 3: - if (align > 1) { - tmpReg = used_virtual_registers[RegClass_GPR]++; - load_store_register(PC_LHZ, tmpReg, srcReg, opnd->object, offset); - extra += 2; - setpcodeflags(opnd->flags); - emitpcode(PC_RLWINM, dstReg, tmpReg, 16, 0, 15); - setpcodeflags(opnd->flags); - } else { - tmpReg = used_virtual_registers[RegClass_GPR]++; - load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset); - setpcodeflags(opnd->flags); - emitpcode(PC_RLWINM, dstReg, tmpReg, 24, 0, 7); - setpcodeflags(opnd->flags); - - load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 1); - extra += 2; - setpcodeflags(opnd->flags); - emitpcode(PC_RLWIMI, dstReg, tmpReg, 16, 8, 15); - setpcodeflags(opnd->flags); - } - if (len == 3) { - load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + extra); - setpcodeflags(opnd->flags); - emitpcode(PC_RLWIMI, dstReg, tmpReg, 8, 16, 23); - setpcodeflags(opnd->flags); - } - break; - case 4: - if (align > 2) { - load_store_register(PC_LWZ, dstReg, srcReg, opnd->object, offset); - setpcodeflags(opnd->flags); - } else if (align > 1) { - tmpReg = used_virtual_registers[RegClass_GPR]++; - load_store_register(PC_LHZ, tmpReg, srcReg, opnd->object, offset); - setpcodeflags(opnd->flags); - emitpcode(PC_RLWINM, dstReg, tmpReg, 16, 0, 15); - setpcodeflags(opnd->flags); - - load_store_register(PC_LHZ, tmpReg, srcReg, opnd->object, offset + 2); - setpcodeflags(opnd->flags); - emitpcode(PC_RLWIMI, dstReg, tmpReg, 0, 16, 31); - setpcodeflags(opnd->flags); - } else { - tmpReg = used_virtual_registers[RegClass_GPR]++; - load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset); - setpcodeflags(opnd->flags); - emitpcode(PC_RLWINM, dstReg, tmpReg, 24, 0, 7); - setpcodeflags(opnd->flags); - - load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 1); - setpcodeflags(opnd->flags); - emitpcode(PC_RLWIMI, dstReg, tmpReg, 16, 8, 15); - setpcodeflags(opnd->flags); - - load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 2); - setpcodeflags(opnd->flags); - emitpcode(PC_RLWIMI, dstReg, tmpReg, 8, 16, 23); - setpcodeflags(opnd->flags); - - load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 3); - setpcodeflags(opnd->flags); - emitpcode(PC_RLWIMI, dstReg, tmpReg, 0, 24, 31); - setpcodeflags(opnd->flags); - } - break; - } -} - -void load_small_block_into_reg(short dstReg, Operand *srcOpnd, Type *type, SInt32 align) { - short finalReg; - short tmpReg; - SInt32 absAddress; - - coerce_to_addressable(srcOpnd); - - if (srcOpnd->optype == OpndType_IndirectGPR_Indexed) { - CError_FATAL(557); - - tmpReg = used_virtual_registers[RegClass_GPR]++; - load_address(tmpReg, srcOpnd); - srcOpnd->optype = OpndType_IndirectGPR_ImmOffset; - srcOpnd->reg = tmpReg; - srcOpnd->object = NULL; - srcOpnd->immOffset = 0; - } - - if (copts.misaligned_mem_access) - align = 4; - - switch (srcOpnd->optype) { - case OpndType_GPRPair: - return; - case OpndType_GPR: - return; - case OpndType_GPR_ImmOffset: - finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++; - add_immediate(finalReg, srcOpnd->reg, srcOpnd->object, srcOpnd->immOffset); - break; - case OpndType_GPR_Indexed: - finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_ADD, finalReg, srcOpnd->reg, srcOpnd->regOffset); - break; - case OpndType_Absolute: - finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++; - absAddress = srcOpnd->immediate; - if (FITS_IN_SHORT(absAddress)) { - emitpcode(PC_LI, finalReg, absAddress); - } else { - tmpReg = finalReg; - if (copts.optimizationlevel > 1 && absAddress) - tmpReg = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_LIS, tmpReg, 0, HIGH_PART(absAddress)); - if (absAddress) - emitpcode(PC_ADDI, finalReg, tmpReg, 0, LOW_PART(absAddress)); - } - break; - case OpndType_IndirectGPR_ImmOffset: - finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++; - load_word_of_small_struct(finalReg, srcOpnd->reg, srcOpnd, srcOpnd->immOffset, type->size, align); - break; - default: - CError_FATAL(606); - } - - srcOpnd->optype = OpndType_GPR; - srcOpnd->reg = finalReg; -} - -void load_small_block_into_reg_pair(short dstRegLo, short dstRegHi, Operand *srcOpnd, Type *type, SInt32 align) { - short finalRegLo; - short finalRegHi; - short tmpRegLo; - short tmpRegHi; - short tmpReg; - SInt32 absAddress; - - finalRegHi = -1; - coerce_to_addressable(srcOpnd); - - if (srcOpnd->optype == OpndType_IndirectGPR_Indexed) { - CError_FATAL(624); - - tmpReg = used_virtual_registers[RegClass_GPR]++; - load_address(tmpReg, srcOpnd); - srcOpnd->optype = OpndType_IndirectGPR_ImmOffset; - srcOpnd->reg = tmpReg; - srcOpnd->object = NULL; - srcOpnd->immOffset = 0; - } - - if (copts.misaligned_mem_access) - align = 4; - - switch (srcOpnd->optype) { - case OpndType_GPRPair: - if (dstRegLo != 0 && dstRegHi == 0) - dstRegHi = used_virtual_registers[RegClass_GPR]++; - if (dstRegHi != 0 && dstRegLo == 0) - dstRegLo = used_virtual_registers[RegClass_GPR]++; - - if (srcOpnd->reg != dstRegLo || srcOpnd->regHi != dstRegHi) { - tmpRegLo = dstRegLo ? dstRegLo : srcOpnd->reg; - tmpRegHi = dstRegHi ? dstRegHi : srcOpnd->regHi; - - if (tmpRegLo != srcOpnd->reg) { - if (tmpRegLo == srcOpnd->regHi) { - CError_ASSERT(657, tmpRegLo != tmpRegHi); - emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi); - emitpcode(PC_MR, tmpRegLo, srcOpnd->reg); - } else { - emitpcode(PC_MR, tmpRegLo, srcOpnd->reg); - if (srcOpnd->regHi != tmpRegHi) - emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi); - } - } else if (tmpRegHi != srcOpnd->regHi) { - if (tmpRegHi == srcOpnd->reg) { - CError_ASSERT(671, tmpRegLo != tmpRegHi); - emitpcode(PC_MR, tmpRegLo, srcOpnd->reg); - emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi); - } else { - emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi); - if (srcOpnd->reg != tmpRegLo) - emitpcode(PC_MR, tmpRegLo, srcOpnd->reg); - } - } - } - - finalRegLo = srcOpnd->reg; - finalRegHi = srcOpnd->regHi; - break; - case OpndType_GPR: - CError_FATAL(688); - break; - case OpndType_GPR_ImmOffset: - CError_FATAL(691); - break; - case OpndType_GPR_Indexed: - CError_FATAL(694); - break; - case OpndType_Absolute: - finalRegLo = dstRegLo ? dstRegLo : used_virtual_registers[RegClass_GPR]++; - absAddress = srcOpnd->immediate; - if (FITS_IN_SHORT(absAddress)) { - emitpcode(PC_LI, finalRegLo, absAddress); - } else { - tmpReg = finalRegLo; - if (copts.optimizationlevel > 1 && absAddress) - tmpReg = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_LIS, tmpReg, 0, HIGH_PART(absAddress)); - if (absAddress) - emitpcode(PC_ADDI, finalRegLo, tmpReg, 0, LOW_PART(absAddress)); - } - - finalRegHi = dstRegHi ? dstRegHi : used_virtual_registers[RegClass_GPR]++; - if (is_unsigned(type) || absAddress >= 0) - load_immediate(finalRegHi, 0); - else - load_immediate(finalRegHi, -1); - - break; - case OpndType_IndirectGPR_ImmOffset: - finalRegLo = dstRegLo ? dstRegLo : used_virtual_registers[RegClass_GPR]++; - finalRegHi = dstRegHi ? dstRegHi : used_virtual_registers[RegClass_GPR]++; - if (srcOpnd->reg == finalRegHi) { - if (srcOpnd->reg == finalRegLo) { - CError_FATAL(726); - } else { - load_word_of_small_struct( - finalRegLo, srcOpnd->reg, srcOpnd, - srcOpnd->immOffset + low_offset, type->size - 4, align); - load_word_of_small_struct( - finalRegHi, srcOpnd->reg, srcOpnd, - srcOpnd->immOffset + high_offset, 4, align); - } - } else { - load_word_of_small_struct( - finalRegHi, srcOpnd->reg, srcOpnd, - srcOpnd->immOffset + high_offset, 4, align); - load_word_of_small_struct( - finalRegLo, srcOpnd->reg, srcOpnd, - srcOpnd->immOffset + low_offset, type->size - 4, align); - } - break; - default: - CError_FATAL(737); - } - - if (finalRegHi == -1) { - CError_FATAL(741); - } else { - srcOpnd->optype = OpndType_GPRPair; - srcOpnd->reg = finalRegLo; - srcOpnd->regHi = finalRegHi; - } -} - -static void store_word_of_small_struct(short srcReg, short dstReg, Operand *opnd, SInt32 offset, SInt32 len, SInt32 align) { - short tmpReg; - short extra = 0; - - switch (len) { - case 1: - tmpReg = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_RLWINM, tmpReg, srcReg, 8, 24, 31); - setpcodeflags(opnd->flags); - load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset); - setpcodeflags(opnd->flags); - break; - case 2: - case 3: - if (align > 1) { - tmpReg = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 16, 31); - setpcodeflags(opnd->flags); - load_store_register(PC_STH, tmpReg, dstReg, opnd->object, offset); - extra += 2; - setpcodeflags(opnd->flags); - } else { - tmpReg = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_RLWINM, tmpReg, srcReg, 8, 24, 31); - setpcodeflags(opnd->flags); - load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset); - setpcodeflags(opnd->flags); - - emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 24, 31); - setpcodeflags(opnd->flags); - load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + 1); - extra += 2; - setpcodeflags(opnd->flags); - } - if (len == 3) { - emitpcode(PC_RLWINM, tmpReg, srcReg, 24, 24, 31); - setpcodeflags(opnd->flags); - load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + extra); - setpcodeflags(opnd->flags); - } - break; - case 4: - if (align > 2) { - load_store_register(PC_STW, srcReg, dstReg, opnd->object, offset); - setpcodeflags(opnd->flags); - } else if (align > 1) { - tmpReg = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 16, 31); - setpcodeflags(opnd->flags); - load_store_register(PC_STH, tmpReg, dstReg, opnd->object, offset); - setpcodeflags(opnd->flags); - - load_store_register(PC_STH, srcReg, dstReg, opnd->object, offset + 2); - setpcodeflags(opnd->flags); - } else { - tmpReg = used_virtual_registers[RegClass_GPR]++; - emitpcode(PC_RLWINM, tmpReg, srcReg, 8, 24, 31); - setpcodeflags(opnd->flags); - load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset); - setpcodeflags(opnd->flags); - - emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 24, 31); - setpcodeflags(opnd->flags); - load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + 1); - setpcodeflags(opnd->flags); - - emitpcode(PC_RLWINM, tmpReg, srcReg, 24, 24, 31); - setpcodeflags(opnd->flags); - load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + 2); - setpcodeflags(opnd->flags); - - load_store_register(PC_STB, srcReg, dstReg, opnd->object, offset + 3); - setpcodeflags(opnd->flags); - } - break; - } -} - -void store_small_block_from_reg(short srcReg, Operand *dstOpnd, Type *type, SInt32 align) { - short tmpReg; - - coerce_to_addressable(dstOpnd); - - if (dstOpnd->optype == OpndType_IndirectGPR_Indexed) { - CError_FATAL(839); - - tmpReg = used_virtual_registers[RegClass_GPR]++; - load_address(tmpReg, dstOpnd); - dstOpnd->optype = OpndType_IndirectGPR_ImmOffset; - dstOpnd->reg = tmpReg; - dstOpnd->object = NULL; - dstOpnd->immOffset = 0; - } - - if (copts.misaligned_mem_access) - align = 4; - - store_word_of_small_struct(srcReg, dstOpnd->reg, dstOpnd, dstOpnd->immOffset, type->size, align); -} - -void store_small_block_from_reg_pair(short srcRegLo, short srcRegHi, Operand *dstOpnd, Type *type, SInt32 align) { - short tmpReg; - - coerce_to_addressable(dstOpnd); - - if (dstOpnd->optype == OpndType_IndirectGPR_Indexed) { - CError_FATAL(860); - - tmpReg = used_virtual_registers[RegClass_GPR]++; - load_address(tmpReg, dstOpnd); - dstOpnd->optype = OpndType_IndirectGPR_ImmOffset; - dstOpnd->reg = tmpReg; - dstOpnd->object = NULL; - dstOpnd->immOffset = 0; - } - - if (copts.misaligned_mem_access) - align = 4; - - store_word_of_small_struct( - srcRegLo, dstOpnd->reg, dstOpnd, - dstOpnd->immOffset + low_offset, type->size - 4, align); - store_word_of_small_struct( - srcRegHi, dstOpnd->reg, dstOpnd, - dstOpnd->immOffset + high_offset, 4, align); -} diff --git a/compiler_and_linker/unsorted/Switch.c b/compiler_and_linker/unsorted/Switch.c deleted file mode 100644 index 4bbd82e..0000000 --- a/compiler_and_linker/unsorted/Switch.c +++ /dev/null @@ -1,518 +0,0 @@ -#include "compiler/Switch.h" -#include "compiler/CError.h" -#include "compiler/CFunc.h" -#include "compiler/CInt64.h" -#include "compiler/CParser.h" -#include "compiler/InstrSelection.h" -#include "compiler/ObjGenMachO.h" -#include "compiler/Operands.h" -#include "compiler/PCode.h" -#include "compiler/PCodeUtilities.h" -#include "compiler/RegisterInfo.h" -#include "compiler/TOC.h" -#include "compiler/CompilerTools.h" -#include "compiler/objects.h" - -ObjectList *switchtables; -static SwitchCase **caselabels; -static CaseRange *caseranges; -static SInt32 ncases; -static SInt32 nranges_minus1; -static CInt64 min; -static CInt64 max; -static CInt64 first; -static short selector_gpr; -static short selector_gprHi; -static Type *selector_type; -static PCodeLabel *defaultlabel; -static CInt64 range; - -static int compare_cases(const void *a, const void *b) { - const SwitchCase **casea = (const SwitchCase **) a; - const SwitchCase **caseb = (const SwitchCase **) b; - - if (CInt64_Less((*casea)->min, (*caseb)->min)) - return -1; - if (CInt64_Greater((*casea)->min, (*caseb)->min)) - return 1; - return 0; -} - -static void build_case_ranges(Type *type, SwitchCase *cases, CLabel *label) { - SwitchCase **caseptr; - SInt32 i; - SwitchCase *curcase; - CaseRange *currange; - - if (type->size == 8) { - min.lo = 0; - min.hi = 0x80000000; - max.lo = 0xFFFFFFFF; - max.hi = 0x7FFFFFFF; - } else if (type->size == 4) { - CInt64_SetLong(&min, 0x80000000); - CInt64_SetLong(&max, 0x7FFFFFFF); - } else if (is_unsigned(type)) { - min.hi = 0; - min.lo = 0; - max.hi = 0; - max.lo = 0xFFFF; - } else { - CInt64_SetLong(&min, -0x8000); - CInt64_SetLong(&max, 0x7FFF); - } - - caselabels = lalloc(sizeof(SwitchCase *) * ncases); - caseptr = caselabels; - while (cases) { - *caseptr = cases; - cases = cases->next; - ++caseptr; - } - - caseranges = lalloc(((ncases * 2) + 2) * sizeof(CaseRange)); - if (type->size < 8) { - for (i = 0; i < ncases; i++) - CInt64_SetLong(&caselabels[i]->min, caselabels[i]->min.lo); - } - - qsort(caselabels, ncases, sizeof(SwitchCase *), &compare_cases); - - currange = caseranges; - currange->min = min; - currange->range = CInt64_Sub(max, min); - currange->label = label->pclabel; - - for (i = 0; i < ncases; i++) { - curcase = caselabels[i]; - if (CInt64_GreaterEqual(curcase->min, min) && CInt64_LessEqual(curcase->min, max)) { - if (CInt64_Equal(currange->min, min)) - first = curcase->min; - range = CInt64_Sub(curcase->min, first); - - if (CInt64_Greater(curcase->min, currange->min)) { - currange->range = CInt64_Sub(CInt64_Sub(curcase->min, currange->min), cint64_one); - (++currange)->min = curcase->min; - } else if (CInt64_Greater(currange->min, min) && curcase->label->pclabel == currange[-1].label) { - currange[-1].range = CInt64_Add(currange[-1].range, cint64_one); - if (CInt64_Equal(currange->range, cint64_zero)) { - currange--; - } else { - currange->min = CInt64_Add(currange->min, cint64_one); - currange->range = CInt64_Sub(currange->range, cint64_one); - } - continue; - } - - currange->range = cint64_zero; - currange->label = curcase->label->pclabel; - - if (CInt64_Less(curcase->min, max)) { - currange++; - currange->min = CInt64_Add(curcase->min, cint64_one); - currange->range = CInt64_Sub(max, currange->min); - currange->label = label->pclabel; - } - } - } - - nranges_minus1 = currange - caseranges; -} - -static void treecompare(SInt32 start, SInt32 end) { - SInt32 r30; - SInt32 r29; - CaseRange *currange; - int count; - - count = end - start; - CError_ASSERT(175, selector_type->size <= 4); - - r29 = start + (count >> 1) + 1; - currange = caseranges + r29; - - if (CInt64_Equal(currange[-1].range, cint64_zero) && (!(count & 1) || (CInt64_NotEqual(currange->range, cint64_zero) && count > 1))) { - currange--; - r29--; - } - - r30 = r29 - 1; - - if (selector_type->size < 4 && is_unsigned(selector_type)) { - emitpcode(PC_CMPLI, 0, selector_gpr, CInt64_GetULong(&currange->min)); - } else if (FITS_IN_SHORT((SInt32) CInt64_GetULong(&currange->min))) { - emitpcode(PC_CMPI, 0, selector_gpr, CInt64_GetULong(&currange->min)); - } else { - SInt32 value = CInt64_GetULong(&currange->min); - int reg = ALLOC_GPR(); - load_immediate(reg, value); - emitpcode(PC_CMP, 0, selector_gpr, reg); - } - - if (CInt64_Equal(currange->range, cint64_zero) && r29 < end) { - branch_conditional(0, EEQU, 1, currange->label); - r29++; - } - - if (r29 == end) { - if (start == r30) { - if (caseranges[start].label == caseranges[end].label) { - branch_always(caseranges[start].label); - } else { - branch_conditional(0, EGREATEREQU, 1, caseranges[end].label); - branch_always(caseranges[start].label); - } - } else { - branch_conditional(0, EGREATEREQU, 1, caseranges[end].label); - treecompare(start, r30); - } - } else { - if (start == r30) { - branch_conditional(0, ELESS, 1, caseranges[start].label); - treecompare(r29, end); - } else { - PCodeLabel *label = makepclabel(); - branch_conditional(0, EGREATEREQU, 1, label); - treecompare(start, r30); - branch_label(label); - treecompare(r29, end); - } - } -} - -static void I8_treecompare(SInt32 start, SInt32 end) { - SInt32 r30; - SInt32 r29; - CaseRange *currange; - int count; - - count = end - start; - - r29 = start + (count >> 1) + 1; - currange = caseranges + r29; - - if (CInt64_Equal(currange[-1].range, cint64_zero) && (!(count & 1) || (CInt64_NotEqual(currange->range, cint64_zero) && count > 1))) { - currange--; - r29--; - } - - r30 = r29 - 1; - - if (CInt64_Equal(currange->range, cint64_zero) && r29 < end) { - short a = ALLOC_GPR(); - short b = ALLOC_GPR(); - load_immediate(a, currange->min.lo); - load_immediate(b, currange->min.hi); - emitpcode(PC_XOR, a, selector_gpr, a); - emitpcode(PC_XOR, b, selector_gprHi, b); - emitpcode(PC_OR, b, a, b); - emitpcode(PC_CMPI, 0, b, 0); - branch_conditional(0, EEQU, 1, currange->label); - r29++; - } - - if (r29 == end) { - if (start == r30) { - if (caseranges[start].label == caseranges[end].label) { - branch_always(caseranges[start].label); - } else { - short a = ALLOC_GPR(); - short b = ALLOC_GPR(); - short c = ALLOC_GPR(); - short d = ALLOC_GPR(); - load_immediate(a, currange->min.lo); - load_immediate(b, currange->min.hi); - if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) { - emitpcode(PC_XORIS, c, selector_gprHi, 0x8000); - emitpcode(PC_XORIS, d, b, 0x8000); - } else { - c = selector_gprHi; - d = b; - } - emitpcode(PC_SUBFC, a, a, selector_gpr); - emitpcode(PC_SUBFE, b, d, c); - emitpcode(PC_SUBFE, b, a, a); - emitpcode(PC_NEG, b, b); - emitpcode(PC_CMPI, 0, b, 0); - branch_conditional(0, EEQU, 1, caseranges[end].label); - branch_always(caseranges[start].label); - } - } else { - short a = ALLOC_GPR(); - short b = ALLOC_GPR(); - short c = ALLOC_GPR(); - short d = ALLOC_GPR(); - load_immediate(a, currange->min.lo); - load_immediate(b, currange->min.hi); - if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) { - emitpcode(PC_XORIS, c, selector_gprHi, 0x8000); - emitpcode(PC_XORIS, d, b, 0x8000); - } else { - c = selector_gprHi; - d = b; - } - emitpcode(PC_SUBFC, a, a, selector_gpr); - emitpcode(PC_SUBFE, b, d, c); - emitpcode(PC_SUBFE, b, a, a); - emitpcode(PC_NEG, b, b); - emitpcode(PC_CMPI, 0, b, 0); - branch_conditional(0, EEQU, 1, caseranges[end].label); - I8_treecompare(start, r30); - } - } else { - if (start == r30) { - short a = ALLOC_GPR(); - short b = ALLOC_GPR(); - short c = ALLOC_GPR(); - short d = ALLOC_GPR(); - load_immediate(a, currange->min.lo); - load_immediate(b, currange->min.hi); - if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) { - emitpcode(PC_XORIS, c, selector_gprHi, 0x8000); - emitpcode(PC_XORIS, d, b, 0x8000); - } else { - c = selector_gprHi; - d = b; - } - emitpcode(PC_SUBFC, a, selector_gpr, a); - emitpcode(PC_SUBFE, b, c, d); - emitpcode(PC_SUBFE, b, a, a); - emitpcode(PC_NEG, b, b); - emitpcode(PC_CMPI, 0, b, 0); - branch_conditional(0, ENOTEQU, 1, caseranges[end].label); - I8_treecompare(r29, end); - } else { - PCodeLabel *label; - short a = ALLOC_GPR(); - short b = ALLOC_GPR(); - short c = ALLOC_GPR(); - short d = ALLOC_GPR(); - load_immediate(a, currange->min.lo); - load_immediate(b, currange->min.hi); - if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) { - emitpcode(PC_XORIS, c, selector_gprHi, 0x8000); - emitpcode(PC_XORIS, d, b, 0x8000); - } else { - c = selector_gprHi; - d = b; - } - emitpcode(PC_SUBFC, a, a, selector_gpr); - emitpcode(PC_SUBFE, b, d, c); - emitpcode(PC_SUBFE, b, a, a); - emitpcode(PC_NEG, b, b); - emitpcode(PC_CMPI, 0, b, 0); - label = makepclabel(); - branch_conditional(0, EEQU, 1, label); - I8_treecompare(start, r30); - branch_label(label); - I8_treecompare(r29, end); - } - } -} - -static void generate_tree(ENode *expr) { - Operand op; - - memclrw(&op, sizeof(Operand)); - if (TYPE_IS_8BYTES(expr->rtype)) { - GEN_NODE(expr, &op); - coerce_to_register_pair(&op, expr->rtype, 0, 0); - selector_type = expr->rtype; - selector_gpr = op.reg; - selector_gprHi = op.regHi; - I8_treecompare(0, nranges_minus1); - } else { - GEN_NODE(expr, &op); - if (expr->rtype->size < 4) - extend32(&op, expr->rtype, 0); - ENSURE_GPR(&op, expr->rtype, 0); - selector_type = expr->rtype; - selector_gpr = op.reg; - treecompare(0, nranges_minus1); - } -} - -static Object *create_switch_table(void) { - Object *obj; - ObjectList *list; - UInt32 *outptr; - CaseRange *currange; - SInt32 size; - CInt64 value; - - obj = galloc(sizeof(Object)); - list = galloc(sizeof(ObjectList)); - memclrw(obj, sizeof(Object)); - memclrw(list, sizeof(ObjectList)); - - obj->otype = OT_OBJECT; - obj->access = ACCESSPUBLIC; - obj->datatype = DDATA; - obj->name = CParser_GetUniqueName(); - obj->toc = NULL; - obj->sclass = TK_STATIC; - obj->qual = Q_CONST; - obj->flags |= OBJECT_FLAGS_2 | OBJECT_DEFINED; - obj->u.data.linkname = obj->name; - obj->type = NULL; - createIndirect(obj, 0, 0); - obj->type = TYPE(&void_ptr); - - size = CInt64_GetULong(&range) + 1; - obj->u.data.u.switchtable.size = size; - obj->u.data.u.switchtable.data = lalloc(4 * size); - - currange = caseranges; - outptr = (UInt32 *) obj->u.data.u.switchtable.data; - value = cint64_zero; - while (CInt64_LessEqual(value, range)) { - while (CInt64_Greater(CInt64_Add(first, value), CInt64_Add(currange->min, currange->range))) - currange++; - *outptr = CTool_CreateIndexFromPointer(currange->label); - value = CInt64_Add(value, cint64_one); - outptr++; - } - - list->object = obj; - list->next = switchtables; - switchtables = list; - return list->object; -} - -static void generate_table(ENode *expr, SwitchInfo *info) { - Object *table; - SwitchCase *curcase; - short reg; - short reg2; - short reg3; - Operand op1; - Operand op2; - - CInt64 val3 = {0, 3}; - memclrw(&op1, sizeof(Operand)); - memclrw(&op2, sizeof(Operand)); - - if (CInt64_Greater(first, cint64_zero) && CInt64_Less(first, val3)) { - range = CInt64_Add(range, first); - first = cint64_zero; - } - - table = create_switch_table(); - CError_ASSERT(553, !TYPE_IS_8BYTES(expr->rtype)); - - GEN_NODE(expr, &op1); - if (expr->rtype->size < 4) - extend32(&op1, expr->rtype, 0); - ENSURE_GPR(&op1, expr->rtype, 0); - - reg = op1.reg; - if (CInt64_NotEqual(first, cint64_zero)) { - SInt32 value; - reg = ALLOC_GPR(); - value = -CInt64_GetULong(&first); - if (!FITS_IN_SHORT(value)) { - emitpcode(PC_ADDIS, reg, op1.reg, 0, HIGH_PART(value)); - if (value) - emitpcode(PC_ADDI, reg, reg, 0, LOW_PART(value)); - } else { - emitpcode(PC_ADDI, reg, op1.reg, 0, value); - } - } - - if (!FITS_IN_SHORT(CInt64_GetULong(&range))) { - short tmp = ALLOC_GPR(); - load_immediate(tmp, CInt64_GetULong(&range)); - emitpcode(PC_CMPL, 0, reg, tmp); - } else { - emitpcode(PC_CMPLI, 0, reg, CInt64_GetULong(&range)); - } - - branch_conditional(0, EGREATER, 1, defaultlabel); - if (table->toc) { - op2.optype = OpndType_Symbol; - op2.object = table->toc; - indirect(&op2, NULL); - } else { - op2.optype = OpndType_Symbol; - op2.object = table; - } - - if (op2.optype != OpndType_GPR) { - Coerce_to_register(&op2, TYPE(&void_ptr), reg2 = ALLOC_GPR()); - } - - if (op2.optype != OpndType_GPR) { - CError_FATAL(599); - } else { - if (op2.reg != reg2) - emitpcode(PC_MR, reg2, op2.reg); - } - - if (CInt64_Equal(first, cint64_zero)) { - reg = ALLOC_GPR(); - emitpcode(PC_RLWINM, reg, op1.reg, 2, 0, 29); - } else { - emitpcode(PC_RLWINM, reg, reg, 2, 0, 29); - } - - reg3 = reg2; - emitpcode(PC_LWZX, reg3, reg3, reg); - for (curcase = info->cases; curcase; curcase = curcase->next) - pcbranch(pclastblock, curcase->label->pclabel); - pcbranch(pclastblock, info->defaultlabel->pclabel); - emitpcode(PC_MTCTR, reg3); - branch_indirect(table); -} - -void switchstatement(ENode *expr, SwitchInfo *info) { - Boolean use_table; - SwitchCase *swcase; - - use_table = copts.switch_tables; - - ncases = 0; - for (swcase = info->cases; swcase; swcase = swcase->next) { - if (!swcase->label->pclabel) - swcase->label->pclabel = makepclabel(); - ncases++; - } - - CError_ASSERT(656, ncases >= 0 && ncases <= 0x3333332U); - - if (!info->defaultlabel->pclabel) - info->defaultlabel->pclabel = makepclabel(); - defaultlabel = info->defaultlabel->pclabel; - - build_case_ranges(expr->rtype, info->cases, info->defaultlabel); - - if (TYPE_IS_8BYTES(expr->rtype)) { - generate_tree(expr); - return; - } - - if (!use_table || nranges_minus1 < 8 || (nranges_minus1 * 2) < ((range.lo / 2) + 4)) - generate_tree(expr); - else - generate_table(expr, info); -} - -void dumpswitchtables(Object *funcobj) { - Object *table; - ObjectList *list; - SInt32 size; - UInt32 *array; - - for (list = switchtables; list; list = list->next) { - table = list->object; - CError_ASSERT(694, table->otype == OT_OBJECT && table->access == ACCESSPUBLIC && table->datatype == DDATA); - - size = table->u.data.u.switchtable.size; - array = (UInt32 *) table->u.data.u.switchtable.data; - while (size--) { - *array = CTool_EndianConvertWord32(((PCodeLabel *) CTool_ResolveIndexToPointer(*array))->block->codeOffset); - array++; - } - - ObjGen_DeclareSwitchTable(table, funcobj); - } -} diff --git a/compiler_and_linker/unsorted/TOC.c b/compiler_and_linker/unsorted/TOC.c deleted file mode 100644 index 7af09e3..0000000 --- a/compiler_and_linker/unsorted/TOC.c +++ /dev/null @@ -1,2272 +0,0 @@ -#include "cos.h" -#include "compiler/TOC.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CInit.h" -#include "compiler/CInt64.h" -#include "compiler/CFunc.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CParser.h" -#include "compiler/CodeGen.h" -#include "compiler/CompilerTools.h" -#include "compiler/Exceptions.h" -#include "compiler/InlineAsm.h" -#include "compiler/InlineAsmPPC.h" -#include "compiler/InstrSelection.h" -#include "compiler/Intrinsics.h" -#include "compiler/ObjGenMachO.h" -#include "compiler/Operands.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" -#include "compiler/PPCError.h" -#include "compiler/RegisterInfo.h" -#include "compiler/StackFrame.h" -#include "compiler/enode.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -ObjectList *toclist; -ObjectList *exceptionlist; -void *descriptorlist; -PoolEntry *floatconstpool; -PoolEntry *doubleconstpool; -ObjectList *floatconstlist; -PoolEntry *vectorconstpool; -ObjectList *vectorconstlist; -Object toc0; -Boolean no_descriptors; -Object pic_base; -VarInfo pic_base_varinfo; -short pic_base_reg; -CodeLabelList *codelabellist; - -UInt8 lvslBytes[16][16] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, - 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, - 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, - 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, - 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, - 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, - 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, - 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, - 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, - 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E -}; - -UInt8 lvsrBytes[16][16] = { - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, - 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, - 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, - 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, - 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, - 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, - 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, - 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, - 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, - 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 -}; - -// forward decls -static void estimate_func_param_size(ENode *node); - -static int disables_optimizer(ENode *node) { - ENode *funcref = node->data.funccall.funcref; - if (ENODE_IS(funcref, EOBJREF)) { - if (!strcmp(CMangler_GetLinkName(funcref->data.objref)->name, "___setjmp")) - return 1; - if (!strcmp(CMangler_GetLinkName(funcref->data.objref)->name, "___vec_setjmp")) - return 1; - } - return 0; -} - -void setupaddressing(void) { - floatconstlist = NULL; - descriptorlist = NULL; - toclist = NULL; - exceptionlist = NULL; - vectorconstlist = NULL; - vectorconstpool = NULL; - floatconstpool = NULL; - doubleconstpool = NULL; - - no_descriptors = 1; - memclrw(&toc0, sizeof(toc0)); - - pic_base_reg = 0; - memclrw(&pic_base, sizeof(pic_base)); - memclrw(&pic_base_varinfo, sizeof(pic_base_varinfo)); - pic_base.otype = OT_OBJECT; - pic_base.type = (Type *) &void_ptr; - pic_base.datatype = DNONLAZYPTR; - pic_base.u.toc.info = &pic_base_varinfo; -} - -void createNonLazyPointer(Object *obj) { - Object *toc; - ObjectList *list; - - toc = galloc(sizeof(Object)); - obj->toc = toc; - memclrw(toc, sizeof(Object)); - - toc->otype = OT_OBJECT; - toc->name = CParser_GetUniqueName(); - toc->toc = NULL; - toc->section = SECT_NONLAZY_PTRS; - toc->u.toc.info = CodeGen_GetNewVarInfo(); - toc->sclass = TK_STATIC; - toc->qual = Q_CONST; - toc->datatype = DNONLAZYPTR; - toc->flags |= OBJECT_FLAGS_2; - toc->type = CDecl_NewPointerType(obj->type); - toc->u.toc.over_load = obj; - toc->u.toc.linkname = CMangler_GetLinkName(obj); - - list = galloc(sizeof(ObjectList)); - memclrw(list, sizeof(ObjectList)); - list->object = toc; - list->next = toclist; - toclist = list; -} - -void referenceIndirectPointer(Object *obj) { - VarInfo *vi = obj->toc->u.toc.info; - vi->used = 1; - vi->usage += copts.optimizesize ? 1 : curstmtvalue; -} - -Object *createIndirect(Object *obj, Boolean flag1, Boolean flag2) { - CError_ASSERT(622, !copts.no_common || (obj->section != SECT_COMMON_VARS) || (obj->qual & Q_20000)); - - if (CParser_HasInternalLinkage(obj)) - return NULL; - if (ObjGen_IsExported(obj)) - return NULL; - - if (!copts.no_common && obj->datatype == DDATA && obj->section == SECT_DEFAULT && (obj->qual & Q_1000000)) - obj->section = SECT_COMMON_VARS; - - if (copts.codegen_dynamic && (!copts.no_common || !(obj->qual & Q_1000000))) { - if (!obj->toc) - createNonLazyPointer(obj); - else if (flag1) - obj->toc->u.toc.info = CodeGen_GetNewVarInfo(); - - if (flag2) - referenceIndirectPointer(obj); - - return obj->toc; - } else { - return NULL; - } -} - -Object *createfloatconstant(Type *type, Float *data) { - ObjectList *list; - Object *obj; - UInt32 *check; - - for (list = floatconstlist; list; list = list->next) { - obj = list->object; - check = (UInt32 *) obj->u.data.u.floatconst; - if (obj->type == type && check[0] == ((UInt32 *) data)[0] && check[1] == ((UInt32 *) data)[1]) - return obj; - } - - obj = galloc(sizeof(Object)); - memclrw(obj, sizeof(Object)); - obj->otype = OT_OBJECT; - obj->type = type; - obj->name = CParser_GetUniqueName(); - obj->toc = NULL; - obj->u.data.info = NULL; - obj->u.data.linkname = obj->name; - obj->sclass = TK_STATIC; - obj->qual = Q_CONST | Q_INLINE_DATA; - obj->datatype = DDATA; - if (type->size == 8) - obj->section = SECT_8BYTE_LITERALS; - else if (type->size == 4) - obj->section = SECT_4BYTE_LITERALS; - else - CError_FATAL(807); - - obj->flags |= OBJECT_FLAGS_2; - - obj->u.data.u.floatconst = galloc(sizeof(Float)); - *obj->u.data.u.floatconst = *data; - - list = galloc(sizeof(ObjectList)); - memclrw(list, sizeof(ObjectList)); - list->object = obj; - list->next = floatconstlist; - floatconstlist = list; - - ObjGen_DeclareFloatConst(obj); - return obj; -} - -Object *createvectorconstant(Type *type, MWVector128 *data) { - ObjectList *list; - Object *obj; - MWVector128 *check; - - for (list = vectorconstlist; list; list = list->next) { - obj = list->object; - check = obj->u.data.u.vector128const; - if (check->ul[0] == data->ul[0] && check->ul[1] == data->ul[1] && check->ul[2] == data->ul[2] && check->ul[3] == data->ul[3]) - return obj; - } - - obj = galloc(sizeof(Object)); - memclrw(obj, sizeof(Object)); - obj->otype = OT_OBJECT; - obj->type = type; - obj->name = CParser_GetUniqueName(); - obj->toc = NULL; - obj->u.data.info = NULL; - obj->u.data.linkname = obj->name; - obj->sclass = TK_STATIC; - obj->qual = Q_CONST | Q_INLINE_DATA; - obj->datatype = DDATA; - if (type->size == 16) - obj->section = SECT_16BYTE_LITERALS; - else - CError_FATAL(900); - - obj->flags |= OBJECT_FLAGS_2; - - obj->u.data.u.vector128const = galloc(sizeof(MWVector128)); - *obj->u.data.u.vector128const = *data; - - list = galloc(sizeof(ObjectList)); - memclrw(list, sizeof(ObjectList)); - list->object = obj; - list->next = vectorconstlist; - vectorconstlist = list; - - ObjGen_DeclareVectorConst(obj); - return obj; -} - -void DeclarePooledConstants(void) { - PoolEntry *entry; - char *buffer; - SInt32 fsize; - SInt32 dsize; - SInt32 vsize; - - fsize = 0; - for (entry = floatconstpool; entry; entry = entry->next) - fsize += 4; - - if (fsize) { - floatconstpool->object->type = CDecl_NewArrayType(TYPE(&stfloat), fsize); - buffer = galloc(fsize); - for (entry = floatconstpool; entry; entry = entry->next) - memcpy(buffer + entry->offset, entry->buffer, 4); - CInit_DeclareReadOnlyData(floatconstpool->object, buffer, NULL, fsize); - } - - dsize = 0; - for (entry = doubleconstpool; entry; entry = entry->next) - dsize += 8; - - if (dsize) { - doubleconstpool->object->type = CDecl_NewArrayType(TYPE(&stdouble), dsize); - buffer = galloc(dsize); - for (entry = doubleconstpool; entry; entry = entry->next) - memcpy(buffer + entry->offset, entry->buffer, 8); - CInit_DeclareReadOnlyData(doubleconstpool->object, buffer, NULL, dsize); - } - - vsize = 0; - for (entry = vectorconstpool; entry; entry = entry->next) - vsize += 16; - - if (vsize) { - vectorconstpool->object->type = CDecl_NewArrayType(TYPE(&stvectorsignedlong), vsize); - buffer = galloc(vsize); - for (entry = vectorconstpool; entry; entry = entry->next) - memcpy(buffer + entry->offset, entry->buffer, 16); - CInit_DeclareReadOnlyData(vectorconstpool->object, buffer, NULL, vsize); - } -} - -static Object *CreatePooledFloatConst(Type *type, Float *data, SInt32 *pOffset) { - if (type->size == 8u) { - PoolEntry *entry; - void *buffer; - Object *object; - SInt32 offset; - - buffer = galloc(8u); - CMach_InitFloatMem(type, *data, buffer); - if (cparamblkptr->precompile == 1) - CError_Error(CErrorStr180); - - for (entry = doubleconstpool; entry; entry = entry->next) { - if (!memcmp(entry->buffer, buffer, 8u)) - break; - } - - if (!entry) { - if (doubleconstpool) { - object = doubleconstpool->object; - offset = doubleconstpool->offset + 8u; - doubleconstpool->object->type->size += 8u; - } else { - DeclInfo di; - memclrw(&di, sizeof(di)); - di.thetype = CDecl_NewArrayType(TYPE(&stdouble), 8u); - di.name = GetHashNameNodeExport("@doubleBase0"); - di.qual = Q_CONST; - di.storageclass = TK_STATIC; - di.is_extern_c = 1; - di.section = SECT_CONST; - object = CParser_NewGlobalDataObject(&di); - object->nspace = cscope_root; - offset = 0; - } - - entry = galloc(sizeof(PoolEntry)); - entry->next = doubleconstpool; - doubleconstpool = entry; - entry->object = object; - entry->offset = offset; - entry->buffer = galloc(8u); - memcpy(entry->buffer, buffer, 8u); - } - - *pOffset = entry->offset; - return entry->object; - } - - if (type->size == 4u) { - PoolEntry *entry; - void *buffer; - Object *object; - SInt32 offset; - - buffer = galloc(4u); - CMach_InitFloatMem(type, *data, buffer); - if (cparamblkptr->precompile == 1) - CError_Error(CErrorStr180); - - for (entry = floatconstpool; entry; entry = entry->next) { - if (!memcmp(entry->buffer, buffer, 4u)) - break; - } - - if (!entry) { - if (floatconstpool) { - object = floatconstpool->object; - offset = floatconstpool->offset + 4u; - object->type->size += 4u; - } else { - DeclInfo di; - memclrw(&di, sizeof(di)); - di.thetype = CDecl_NewArrayType(TYPE(&stfloat), 4u); - di.name = GetHashNameNodeExport("@floatBase0"); - di.qual = Q_CONST; - di.storageclass = TK_STATIC; - di.is_extern_c = 1; - di.section = SECT_CONST; - object = CParser_NewGlobalDataObject(&di); - object->nspace = cscope_root; - offset = 0; - } - - entry = galloc(sizeof(PoolEntry)); - entry->next = floatconstpool; - floatconstpool = entry; - entry->object = object; - entry->offset = offset; - entry->buffer = galloc(4u); - memcpy(entry->buffer, buffer, 4u); - } - - *pOffset = entry->offset; - return entry->object; - } - - CError_FATAL(1183); - return NULL; -} - -Object *CreateFloatConst(Type *type, Float *data, SInt32 *pOffset) { - *pOffset = 0; - return createfloatconstant(type, data); -} - -static void RewriteFloatConst(ENode *expr) { - Object *obj; - SInt32 n; - ENode *subexpr; - - obj = CreateFloatConst(expr->rtype, &expr->data.floatval, &n); - if (n) { - subexpr = makediadicnode(create_objectrefnode(obj), intconstnode(TYPE(&stunsignedlong), n), EADD); - } else { - subexpr = create_objectrefnode(obj); - } - - expr->type = EINDIRECT; - expr->cost = 1; - expr->flags |= Q_CONST; - expr->data.monadic = subexpr; -} - -static void RewriteVectorConst(ENode *expr) { - PoolEntry *entry; - Object *object; - SInt32 offset; - ENode *inner; - UInt8 data[16]; - - CMach_InitVectorMem(expr->rtype, expr->data.vector128val, data, 1); - - if (cparamblkptr->precompile == 1) - CError_Error(CErrorStr180); - - for (entry = vectorconstpool; entry; entry = entry->next) { - if (!memcmp(entry->buffer, data, 16)) - break; - } - - if (!entry) { - if (vectorconstpool) { - object = vectorconstpool->object; - offset = vectorconstpool->offset + 16; - vectorconstpool->object->type->size += 16; - } else { - DeclInfo di; - memclrw(&di, sizeof(di)); - di.thetype = CDecl_NewArrayType(TYPE(&stvectorsignedlong), 16); - di.name = GetHashNameNodeExport("@vectorBase0"); - di.qual = Q_CONST; - di.storageclass = TK_STATIC; - di.is_extern_c = 1; - di.section = SECT_CONST; - object = CParser_NewGlobalDataObject(&di); - object->nspace = cscope_root; - offset = 0; - } - - entry = galloc(sizeof(PoolEntry)); - entry->next = vectorconstpool; - vectorconstpool = entry; - entry->object = object; - entry->offset = offset; - entry->buffer = galloc(16); - memcpy(entry->buffer, data, 16); - } - - if (entry->offset) { - inner = makediadicnode( - create_objectrefnode(entry->object), - intconstnode(TYPE(&stunsignedlong), entry->offset), - EADD); - } else { - inner = create_objectrefnode(entry->object); - } - - expr->type = EINDIRECT; - expr->cost = 1; - expr->flags |= ENODE_FLAG_CONST; - expr->data.monadic = inner; -} - -static Object *createcodelabel(CLabel *label) { - CodeLabelList *list; - Object *obj; - - for (list = codelabellist; list; list = list->next) { - if (list->label == label) - return list->object; - } - - obj = galloc(sizeof(Object)); - memclrw(obj, sizeof(Object)); - obj->otype = OT_OBJECT; - obj->type = (Type *) &void_ptr; - obj->name = label->uniquename; - obj->toc = NULL; - obj->u.data.info = NULL; // not sure if this is the right union! - obj->sclass = TK_STATIC; - obj->qual = Q_CONST; - obj->datatype = DDATA; - obj->flags |= OBJECT_FLAGS_2 | OBJECT_DEFINED; - - list = galloc(sizeof(CodeLabelList)); - memclrw(list, sizeof(CodeLabelList)); - list->object = obj; - list->label = label; - list->next = codelabellist; - codelabellist = list; - - return obj; -} - -void dumpcodelabels(Object *func) { - CodeLabelList *list; - - for (list = codelabellist; list; list = list->next) - ObjGen_DeclareCodeLabel(list->object, list->label->pclabel->block->codeOffset, func); -} - -static void referenceexception(Object *obj) { - ObjectList *list; - - if (obj && obj->otype == OT_OBJECT && obj->datatype == DLOCAL) { - for (list = exceptionlist; list; list = list->next) { - if (list->object == obj) - return; - } - - list = lalloc(sizeof(ObjectList)); - memclrw(list, sizeof(ObjectList)); - list->object = obj; - list->next = exceptionlist; - exceptionlist = list; - } -} - -static ENodeType invert_relop(ENodeType nodetype) { - switch (nodetype) { - case ELESS: return EGREATEREQU; - case EGREATER: return ELESSEQU; - case ELESSEQU: return EGREATER; - case EGREATEREQU: return ELESS; - case EEQU: return ENOTEQU; - case ENOTEQU: return EEQU; - default: return nodetype; - } -} - -static ENode *COND_to_COMPARE(ENode *cond, ENode *expr1, ENode *expr2) { - SInt32 val1; - SInt32 val2; - SInt32 condval; - ENodeType invop; - - while (expr1->type == ETYPCON && TYPE_FITS_IN_REGISTER(expr1->rtype)) - expr1 = expr1->data.monadic; - while (expr2->type == ETYPCON && TYPE_FITS_IN_REGISTER(expr2->rtype)) - expr2 = expr2->data.monadic; - - if (expr1->type != EINTCONST || !TYPE_FITS_IN_REGISTER(expr1->rtype) || !CInt64_IsInRange(expr1->data.intval, 4)) - return NULL; - if (expr2->type != EINTCONST || !TYPE_FITS_IN_REGISTER(expr2->rtype) || !CInt64_IsInRange(expr2->data.intval, 4)) - return NULL; - - val1 = expr1->data.intval.lo; - val2 = expr2->data.intval.lo; - condval = 0; - switch (val1) { - case 1: - if (val2 != 0) - return NULL; - break; - case 0: - condval = 1; - if (val2 != 1) - return NULL; - break; - default: - return NULL; - } - - while (cond->type == ELOGNOT) { - condval = (condval + 1) & 1; - cond = cond->data.monadic; - } - - if (condval) { - invop = invert_relop(cond->type); - if (invop == cond->type) - return NULL; - cond->type = invop; - } - - return cond; -} - -static ENode *comparewithzero(ENode *expr) { - ENode *expr1; - ENode *expr2; - ENode *tmp; - - expr1 = lalloc(sizeof(ENode)); - memclrw(expr1, sizeof(ENode)); - expr2 = lalloc(sizeof(ENode)); - memclrw(expr2, sizeof(ENode)); - - while (expr->type == EFORCELOAD || expr->type == ETYPCON || expr->type == ECOMMA) { - if (!TYPE_FITS_IN_REGISTER(expr->rtype)) - break; - if (expr->type == ECOMMA) { - expr->data.diadic.right = comparewithzero(expr->data.diadic.right); - return expr; - } - expr = expr->data.monadic; - } - - if (expr->type == ECOND && TYPE_FITS_IN_REGISTER(expr->rtype)) { - tmp = COND_to_COMPARE(expr->data.cond.cond, expr->data.cond.expr1, expr->data.cond.expr2); - if (tmp) - expr = tmp; - } - - if (expr->type >= ELESS && expr->type <= ENOTEQU) - return expr; - - if (IS_TYPE_FLOAT(expr->rtype)) { - static Float float0 = {0.0}; - - expr2->type = EFLOATCONST; - expr2->cost = 0; - expr2->rtype = (expr->rtype->size == 4) ? (Type *) &stfloat : (Type *) &stdouble; - expr2->data.floatval = float0; - } else { - expr2->type = EINTCONST; - expr2->cost = 0; - if (TYPE_IS_8BYTES(expr->rtype)) - expr2->rtype = (Type *) &stsignedlonglong; - else - expr2->rtype = (Type *) &stsignedint; - expr2->data.intval.lo = 0; - expr2->data.intval.hi = 0; - } - - expr1->type = ENOTEQU; - expr1->cost = expr->cost; - expr1->rtype = (Type *) &stsignedint; - expr1->data.diadic.left = expr; - expr1->data.diadic.right = expr2; - return expr1; -} - -static void rewritefunctioncallreturningstruct(ENode *expr) { - ENode *ret_expr; - ENode *copy; - - ret_expr = expr->data.funccall.args->node; - - copy = lalloc(sizeof(ENode)); - memclrw(copy, sizeof(ENode)); - - *copy = *expr; - expr->type = ECOMMA; - expr->data.diadic.left = copy; - expr->data.diadic.right = ret_expr; -} - -static void rewritestrcpy(ENode *expr) { - ENode *int_expr; - ENodeList *list; - - int_expr = lalloc(sizeof(ENode)); - memclrw(int_expr, sizeof(ENode)); - int_expr->type = EINTCONST; - int_expr->cost = 0; - int_expr->flags = 0; - int_expr->rtype = (Type *) &stunsignedlong; - CInt64_SetLong(&int_expr->data.intval, expr->data.funccall.args->next->node->data.string.size); - - list = lalloc(sizeof(ENodeList)); - memclrw(list, sizeof(ENodeList)); - list->next = NULL; - list->node = int_expr; - expr->data.funccall.args->next->next = list; - expr->data.funccall.funcref->data.objref = __memcpy_object; -} - -static SInt32 magnitude(Type *type) { - if (IS_TYPE_FLOAT(type)) - return type->size * 4; - else if (is_unsigned(type)) - return (type->size * 2) + 1; - else - return type->size * 2; -} - -static Type *promote_type(Type *type) { - if (IS_TYPE_ENUM(type)) - type = TYPE_ENUM(type)->enumtype; - if (TYPE_INTEGRAL(type)->integral > stsignedint.integral) - return type; - else - return (Type *) &stsignedint; -} - -static Type *common_type(Type *type1, Type *type2) { - Type *tmp; - - if (IS_TYPE_FLOAT(type1) || IS_TYPE_FLOAT(type2)) { - if (TYPE_INTEGRAL(type1)->integral > TYPE_INTEGRAL(type2)->integral) - return type1; - else - return type2; - } - - type1 = promote_type(type1); - type2 = promote_type(type2); - if (type1 != type2) { - if (TYPE_INTEGRAL(type1)->integral < TYPE_INTEGRAL(type2)->integral) { - tmp = type1; - type1 = type2; - type2 = tmp; - } - - if (type1->size == type2->size && !is_unsigned(type1) && is_unsigned(type2)) { - if (type1 == (Type *) &stsignedlong) { - type1 = (Type *) &stunsignedlong; - } else { - CError_ASSERT(1789, type1 == (Type *) &stsignedlonglong); - type1 = (Type *) &stunsignedlonglong; - } - } - } - - return type1; -} - -static void rewrite_opassign(ENode *expr, ENodeType exprtype) { - ENode *left_sub; - ENode *right; - Type *left_type; - Type *right_type; - ENode *new_expr; - ENode *tmp; - Type *commontype; - Type *promo_left; - Type *promo_right; - - left_sub = expr->data.diadic.left->data.monadic; - right = expr->data.diadic.right; - left_type = expr->data.diadic.left->rtype; - right_type = expr->data.diadic.right->rtype; - - new_expr = lalloc(sizeof(ENode)); - memclrw(new_expr, sizeof(ENode)); - new_expr->type = exprtype; - new_expr->rtype = left_type; - new_expr->data.diadic.left = expr->data.diadic.left; - new_expr->data.diadic.right = right; - - expr->type = EASS; - expr->data.diadic.left = left_sub; - expr->data.diadic.right = new_expr; - - if (left_sub->type != EOBJREF) { - ENode *define; - ENode *reuse; - - define = lalloc(sizeof(ENode)); - memclrw(define, sizeof(ENode)); - define->type = EDEFINE; - define->rtype = left_type; - - reuse = lalloc(sizeof(ENode)); - memclrw(reuse, sizeof(ENode)); - reuse->type = EREUSE; - reuse->rtype = left_type; - reuse->data.monadic = define; - - if (left_sub->type != EBITFIELD) { - define->data.monadic = expr->data.diadic.left; - expr->data.diadic.left = define; - new_expr->data.diadic.left->data.diadic.left = reuse; - } else { - ENode *copy; - define->data.monadic = left_sub->data.diadic.left; - left_sub->data.diadic.left = define; - - copy = lalloc(sizeof(ENode)); - *copy = *left_sub; - copy->data.diadic.left = reuse; - new_expr->data.diadic.left->data.diadic.left = copy; - } - } - - switch (exprtype) { - case EADD: - case ESUB: - if (IS_TYPE_POINTER(left_type)) - break; - if (right->type == EINTCONST && TYPE_FITS_IN_REGISTER(left_type)) - break; - case EAND: - case EXOR: - case EOR: - if (left_type == right_type) - break; - case EMUL: - case EDIV: - case EMODULO: - commontype = common_type(left_type, right_type); - if (left_type != commontype) { - tmp = lalloc(sizeof(ENode)); - memclrw(tmp, sizeof(ENode)); - tmp->type = ETYPCON; - tmp->rtype = left_type; - tmp->data.monadic = expr->data.diadic.right; - expr->data.diadic.right = tmp; - - tmp = lalloc(sizeof(ENode)); - memclrw(tmp, sizeof(ENode)); - tmp->type = ETYPCON; - tmp->rtype = commontype; - tmp->data.monadic = new_expr->data.diadic.left; - new_expr->data.diadic.left = tmp; - } - if (right_type != commontype) { - tmp = lalloc(sizeof(ENode)); - memclrw(tmp, sizeof(ENode)); - tmp->type = ETYPCON; - tmp->rtype = commontype; - tmp->data.monadic = new_expr->data.diadic.right; - new_expr->data.diadic.right = tmp; - } - new_expr->rtype = commontype; - break; - - case ESHL: - case ESHR: - promo_left = promote_type(left_type); - promo_right = promote_type(right_type); - if (left_type != promo_left) { - tmp = lalloc(sizeof(ENode)); - memclrw(tmp, sizeof(ENode)); - tmp->type = ETYPCON; - tmp->rtype = left_type; - tmp->data.monadic = expr->data.diadic.right; - expr->data.diadic.right = tmp; - - tmp = lalloc(sizeof(ENode)); - memclrw(tmp, sizeof(ENode)); - tmp->type = ETYPCON; - tmp->rtype = promo_left; - tmp->data.monadic = new_expr->data.diadic.left; - new_expr->data.diadic.left = tmp; - } - if (right_type != promo_right) { - if (new_expr->data.diadic.right->type == EINTCONST && promo_right == (Type *) &stsignedint) { - new_expr->data.diadic.right->rtype = (Type *) &stsignedint; - } else { - tmp = lalloc(sizeof(ENode)); - memclrw(tmp, sizeof(ENode)); - tmp->type = ETYPCON; - tmp->rtype = promo_right; - tmp->data.monadic = new_expr->data.diadic.right; - new_expr->data.diadic.right = tmp; - } - } - new_expr->rtype = promo_left; - break; - } -} - -static void rewrite_preincdec(ENode *expr) { - ENode *subexpr; // r31 - Type *type; // r28 - ENode *new_expr; // r29 - - subexpr = expr->data.monadic; - type = expr->rtype; - - new_expr = lalloc(sizeof(ENode)); - memclrw(new_expr, sizeof(ENode)); - - if (IS_TYPE_FLOAT(type)) { - new_expr->type = EFLOATCONST; - new_expr->cost = 0; - new_expr->rtype = type; - new_expr->data.floatval = one_point_zero; - } else if (IS_TYPE_POINTER(type)) { - new_expr->type = EINTCONST; - new_expr->cost = 0; - new_expr->rtype = (Type *) &stunsignedlong; - new_expr->data.intval.hi = 0; - new_expr->data.intval.lo = TYPE_POINTER(type)->target->size; - } else { - new_expr->type = EINTCONST; - new_expr->cost = 0; - new_expr->rtype = type; - new_expr->data.intval.hi = 0; - new_expr->data.intval.lo = 1; - } - - expr->type = (expr->type == EPREDEC) ? ESUBASS : EADDASS; - expr->data.diadic.left = subexpr; - expr->data.diadic.right = new_expr; -} - -// Don't know what this would be called in the original, but weh -typedef union signed_vec { - SInt8 sc[16]; - SInt16 ss[8]; - SInt32 sl[4]; -} signed_vec; - -Boolean canoptimizevectorconst(MWVector128 *vecp, Type *type, COVCResult *result) { - // this function is very broken - signed_vec vec; - union { SInt32 lg; SInt8 ch[4]; } conv32; - union { SInt16 sh; SInt8 ch[2]; } conv16; - char flag; - SInt8 first8; - SInt16 first16; - SInt32 first32; - int i; - char ci; - UInt32 l0, l1, l2, l3; - - if (IS_TYPE_VECTOR(type)) { - vec = *((signed_vec *) vecp); - - first8 = vec.sc[0]; - flag = 1; - i = 1; - while (flag && i < 16) - flag = first8 == vec.sc[i++]; - /*flag = 1; - for (i = 1; flag && i < 16; i++) { - flag = first8 == vec.sc[i]; - }*/ - - if (flag && first8 < 16 && first8 > -17) { - if (result) { - result->op1 = PC_VSPLTISB; - result->op2 = -1; - result->arg = first8; - } - return 1; - } - - first16 = vec.ss[0]; - flag = 1; - for (i = 1; flag && i < 8; i++) { - flag = vec.ss[i] == first16; - } - - conv16.sh = first16; - if (flag && conv16.ch[0] == 0 && conv16.ch[1] < 16 && conv16.ch[1] >= 0) { - if (result) { - result->op1 = PC_VSPLTISH; - result->op2 = -1; - result->arg = conv16.ch[1]; - } - return 1; - } - - if (flag && conv16.ch[0] == -1 && (conv16.ch[1] & 0xF0) == 0xF0) { - if (result) { - result->op1 = PC_VSPLTISH; - result->op2 = -1; - result->arg = conv16.ch[1]; - } - return 1; - } - - first32 = vec.sl[0]; - flag = 1; - for (i = 1; flag && i < 4; i++) { - flag = vec.sl[i] == first32; - } - - conv32.lg = first32; - if (flag && conv32.ch[0] == 0 && conv32.ch[1] == 0 && conv32.ch[2] == 0 && conv32.ch[3] < 16 && conv32.ch[3] >= 0) { - if (result) { - result->op1 = PC_VSPLTISW; - result->op2 = -1; - result->arg = conv32.ch[3]; - } - return 1; - } - - if (flag && conv32.ch[0] == -1 && conv32.ch[1] == -1 && conv32.ch[2] == -1 && (conv32.ch[3] & 0xF0) == 0xF0) { - if (result) { - result->op1 = PC_VSPLTISW; - result->op2 = -1; - result->arg = conv32.ch[3]; - } - return 1; - } - - l0 = vec.sl[0]; - l1 = vec.sl[1]; - l2 = vec.sl[2]; - l3 = vec.sl[3]; - for (ci = 0; ci < 16; ci++) { - UInt32 *l; - UInt32 *r; - - l = (UInt32 *) lvslBytes[(char) ci]; - r = (UInt32 *) lvsrBytes[(char) ci]; - if (l0 == l[0] && l1 == l[1] && l2 == l[2] && l3 == l[3]) { - if (result) { - result->op1 = -1; - result->op2 = PC_LVSL; - result->arg = ci; - } - return 1; - } - if (l0 == r[0] && l1 == r[1] && l2 == r[2] && l3 == r[3]) { - if (result) { - result->op1 = -1; - result->op2 = PC_LVSR; - result->arg = ci; - } - return 1; - } - } - } - - return 0; -} - -static SInt32 countindirects(ENode *expr) { - SInt32 tmp1; - SInt32 tmp2; - - switch (expr->type) { - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case EVECTOR128CONST: - return 0; - case ECOND: - if (expr->data.cond.cond->hascall || expr->data.cond.expr1->hascall || expr->data.cond.expr2->hascall) - return 2; - - if ((tmp1 = countindirects(expr->data.cond.cond)) >= 2) - return 2; - if ((tmp2 = countindirects(expr->data.cond.expr1)) >= 2) - return 2; - if (tmp2 > tmp1) - tmp1 = tmp2; - if ((tmp2 = countindirects(expr->data.cond.expr2)) >= 2) - return 2; - if (tmp2 > tmp1) - tmp1 = tmp2; - return tmp1; - case EFUNCCALL: - case EFUNCCALLP: - return 2; - case EMUL: - case EMULV: - case EDIV: - case EMODULO: - case EADDV: - case ESUBV: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case ELAND: - case ELOR: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case ECOMMA: - case EPMODULO: - case EROTL: - case EROTR: - case EBCLR: - case EBTST: - case EBSET: - if ((tmp1 = countindirects(expr->data.diadic.left)) >= 2) - return 2; - if ((tmp2 = countindirects(expr->data.diadic.right)) >= 2) - return 2; - if (tmp2 > tmp1) - tmp1 = tmp2; - return tmp1; - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EINDIRECT: - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case EFORCELOAD: - case ETYPCON: - case EBITFIELD: - if (expr->type == EINDIRECT) - return countindirects(expr->data.monadic) + 1; - else - return countindirects(expr->data.monadic); - default: - return 2; - } -} - -static Boolean DetectCondSideAffect(ENode *expr) { - switch (expr->type) { - case EMUL: - case EMULV: - case EDIV: - case EMODULO: - case EADDV: - case ESUBV: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case EAND: - case EXOR: - case EOR: - case ECOMMA: - case EPMODULO: - case EROTL: - case EROTR: - case EBCLR: - case EBTST: - case EBSET: - if (DetectCondSideAffect(expr->data.diadic.left)) - return 1; - return DetectCondSideAffect(expr->data.diadic.right); - case EINDIRECT: - if (expr->data.monadic->type == EINDIRECT) - return 1; - if (expr->data.monadic->type == EOBJREF) { - if (expr->data.monadic->data.objref->datatype != DLOCAL && expr->data.monadic->data.objref->datatype != DDATA) - return 1; - if (IS_TYPE_POINTER(expr->data.monadic->data.objref->type)) - return 1; - return Registers_GetVarInfo(expr->data.monadic->data.objref)->noregister != 0; - } - return 1; - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case EFORCELOAD: - case ETYPCON: - case EBITFIELD: - return DetectCondSideAffect(expr->data.monadic); - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case EVECTOR128CONST: - return 0; - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case ELAND: - case ELOR: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case ECOND: - case EFUNCCALL: - case EFUNCCALLP: - case EMFPOINTER: - case ENULLCHECK: - case EPRECOMP: - case EDEFINE: - case EREUSE: - case EASSBLK: - case ECONDASS: - return 1; - default: - CError_FATAL(2523); - return 1; - } -} - -static UInt8 WeightandSumOps(ENode *expr) { - UInt32 score; - - switch (expr->type) { - case ECOND: - case ECONDASS: - score = WeightandSumOps(expr->data.cond.cond); - score += WeightandSumOps(expr->data.cond.expr1); - score += WeightandSumOps(expr->data.cond.expr2); - break; - case EMUL: - case EMULV: - case EMULASS: - score = WeightandSumOps(expr->data.diadic.left) + 10; - score += WeightandSumOps(expr->data.diadic.right); - break; - case EDIV: - case EMODULO: - case EDIVASS: - case EMODASS: - score = WeightandSumOps(expr->data.diadic.left) + 20; - score += WeightandSumOps(expr->data.diadic.right); - break; - case EADDV: - case ESUBV: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case ELAND: - case ELOR: - case EASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case ECOMMA: - case EPMODULO: - case EROTL: - case EROTR: - case EBCLR: - case EBTST: - case EBSET: - score = WeightandSumOps(expr->data.diadic.left) + 1; - score += WeightandSumOps(expr->data.diadic.right); - break; - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EMONMIN: - case EBINNOT: - case ELOGNOT: - score = WeightandSumOps(expr->data.monadic) + 1; - break; - case EINDIRECT: - if (expr->data.monadic->type == EOBJREF && expr->data.monadic->data.objref->datatype == DLOCAL) - if (!Registers_GetVarInfo(expr->data.monadic->data.objref)->noregister) - return 0; - case EFORCELOAD: - case ETYPCON: - case EBITFIELD: - score = WeightandSumOps(expr->data.monadic); - break; - case EOBJREF: - score = 0; - break; - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EVECTOR128CONST: - score = 0; - break; - case EFUNCCALL: - case EFUNCCALLP: - score = 5; - break; - default: - score = 255; - } - - if (score >= 255) - score = 255; - return (UInt8) score; -} - -Boolean TOC_use_fsel(ENode *expr) { - ENode *left; - ENode *right; - Type *rtype; - int score1; - int score2; - - left = expr->data.cond.expr1; - right = expr->data.cond.expr2; - rtype = expr->rtype; - - if (!copts.peephole) return 0; - if (!copts.gen_fsel) return 0; - if (left->hascall) return 0; - if (right->hascall) return 0; - if (!IS_TYPE_FLOAT(rtype)) return 0; - if (!IS_TYPE_FLOAT(left->rtype)) return 0; - if (!IS_TYPE_FLOAT(right->rtype)) return 0; - - if (expr->data.cond.cond->type < ELESS || expr->data.cond.cond->type > ENOTEQU) - return 0; - if (!IS_TYPE_FLOAT(expr->data.cond.cond->data.diadic.right->rtype)) - return 0; - if (expr->data.cond.cond->type == ELOGNOT || expr->data.cond.cond->type == ELAND || expr->data.cond.cond->type == ELOR) - return 0; - - if (expr->type == ECONDASS) { - if (left->type != EINDIRECT) - return 0; - if (left->data.monadic->type != EOBJREF) - return 0; - } - - if (DetectCondSideAffect(left)) - return 0; - if (DetectCondSideAffect(right)) - return 0; - - if (expr->type == ECONDASS) - score1 = 1; - else - score1 = WeightandSumOps(left); - score2 = WeightandSumOps(right); - - if (score1 > copts.gen_fsel) - return 0; - else if (score2 > copts.gen_fsel) - return 0; - else - return 1; -} - -Boolean TOC_use_isel(ENode *expr, Boolean flag) { - int opt; - ENode *left; - ENode *right; - Type *rtype; - Object *obj; - int score1; - int score2; - - left = expr->data.cond.expr1; - right = expr->data.cond.expr2; - rtype = expr->rtype; - if (flag) - opt = 10; - else - opt = copts.gen_isel; - - if (!opt) return 0; - if (!copts.peephole) return 0; - if (left->hascall) return 0; - if (right->hascall) return 0; - if (!TYPE_FITS_IN_REGISTER(rtype)) return 0; - if (!TYPE_FITS_IN_REGISTER(left->rtype)) return 0; - if (!TYPE_FITS_IN_REGISTER(right->rtype)) return 0; - - if (expr->data.cond.cond->type < ELESS || expr->data.cond.cond->type > ENOTEQU) - return 0; - if (TYPE_IS_8BYTES(rtype)) - return 0; - - if (flag) { - if (!TYPE_FITS_IN_REGISTER(expr->data.cond.cond->data.diadic.right->rtype)) - return 0; - if (TYPE_IS_8BYTES(expr->data.cond.cond->data.diadic.right->rtype)) - return 0; - } - - if (expr->type == ECONDASS) { - if (left->type != EINDIRECT) - return 0; - if (left->data.monadic->type != EOBJREF) - return 0; - if (flag) { - obj = left->data.monadic->data.objref; - if (obj->datatype != DLOCAL) - return 0; - if ((Registers_GetVarInfo(obj) ? Registers_GetVarInfo(obj)->reg : 0) == 0) - return 0; - if (obj->u.var.info->rclass != RegClass_GPR) - return 0; - } - } - - if (DetectCondSideAffect(left)) - return 0; - if (DetectCondSideAffect(right)) - return 0; - - if (expr->type == ECONDASS) - score1 = 1; - else - score1 = WeightandSumOps(left); - score2 = WeightandSumOps(right); - - if (score1 > opt) - return 0; - else if (score2 > opt) - return 0; - else - return 1; -} - -SInt32 GetSizeSkip(ENode *expr) { - if (expr->type == EASS) - expr = expr->data.diadic.right; - if (expr->type == ETYPCON && expr->data.monadic->rtype->size < expr->rtype->size) - return expr->data.monadic->rtype->size; - else - return expr->rtype->size; -} - -void Optimize64bitMath(ENode *expr) { - ENode *left; // r23 - ENode *right; // r28 - SInt32 leftsize; // r24 - SInt32 rightsize; // r25 - SInt32 totalsize; // r22 - int unsignedflag; // r4 - - CError_ASSERT(2886, TYPE_IS_8BYTES(expr->rtype)); - - left = expr->data.diadic.left; - right = expr->data.diadic.right; - leftsize = GetSizeSkip(left); - totalsize = (leftsize + (rightsize = GetSizeSkip(right))); - unsignedflag = is_unsigned(expr->rtype) != 0; - - switch (totalsize) { - case 2: - case 3: - case 4: - if (unsignedflag) { - left->rtype = (Type *) &stunsignedint; - right->rtype = (Type *) &stunsignedint; - } else { - left->rtype = (Type *) &stsignedint; - right->rtype = (Type *) &stsignedint; - } - break; - case 5: - case 6: - case 8: - case 9: - case 10: - case 12: - if (expr->type != ESUB || leftsize >= rightsize) { - if (leftsize < 4) { - if (unsignedflag) - left->rtype = (Type *) &stunsignedint; - else - left->rtype = (Type *) &stsignedint; - } else { - if (left->type == ETYPCON && left->data.monadic->rtype != (Type *) &stfloat) - expr->data.diadic.left = left->data.monadic; - } - if (rightsize < 4) { - if (unsignedflag) - right->rtype = (Type *) &stunsignedint; - else - right->rtype = (Type *) &stsignedint; - } else { - if (right->type == ETYPCON && right->data.monadic->rtype != (Type *) &stfloat) - expr->data.diadic.right = right->data.monadic; - } - } - break; - case 16: - break; - default: - CError_FATAL(2975); - } -} - -static Boolean OptimizeNestedAssginments(ENode **pexpr, Object *check) { - ENode *expr; - Boolean success1; - Boolean success2; - - expr = *pexpr; - switch (expr->type) { - case EOBJREF: - return check != expr->data.objref; - case EMUL: - case EMULV: - case EDIV: - case EMODULO: - case EADDV: - case ESUBV: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case ELAND: - case ELOR: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case ECOMMA: - case EPMODULO: - case EROTL: - case EROTR: - case EBCLR: - case EBTST: - case EBSET: - switch (expr->type) { - case EASS: - if (ENODE_IS(expr->data.diadic.left, EOBJREF) && expr->data.diadic.left->data.objref == check) { - *pexpr = expr->data.diadic.right; - return OptimizeNestedAssginments(pexpr, check); - } - break; - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - CError_FATAL(3033); - return 0; - } - if (OptimizeNestedAssginments(&expr->data.diadic.right, check)) - return OptimizeNestedAssginments(&expr->data.diadic.left, check); - else - return 0; - break; - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EINDIRECT: - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case EFORCELOAD: - case ETYPCON: - case EBITFIELD: - return OptimizeNestedAssginments(&expr->data.monadic, check); - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EVECTOR128CONST: - return 1; - case ECOND: - success2 = OptimizeNestedAssginments(&expr->data.cond.expr2, check); - success1 = OptimizeNestedAssginments(&expr->data.cond.expr1, check); - if (!success2 || !success1) - return 0; - return OptimizeNestedAssginments(&expr->data.cond.cond, check) == 0; - case ECONDASS: - if (!OptimizeNestedAssginments(&expr->data.cond.expr2, check)) - return 0; - if (OptimizeNestedAssginments(&expr->data.cond.cond, check)) - return OptimizeNestedAssginments(&expr->data.cond.expr1, check) == 0; - else - return 0; - case EFUNCCALL: - case EFUNCCALLP: - case EMFPOINTER: - case ENULLCHECK: - case EPRECOMP: - case EDEFINE: - case EREUSE: - case EASSBLK: - return 0; - default: - CError_FATAL(3083); - return 0; - } -} - -static void expandTOCexpression(ENode *expr, Type *type, int ignored) { - Object *obj; - Object *tmpobj; - ENode *cond; - ENode *tmpexpr; - ENode *newexpr; - ENodeList *list; - - expr->ignored = ignored; - switch (expr->type) { - case EINTCONST: - expr->hascall = 0; - break; - case EFLOATCONST: - uses_globals = 1; - RewriteFloatConst(expr); - expandTOCexpression(expr, NULL, 0); - break; - case EVECTOR128CONST: - if (!canoptimizevectorconst(&expr->data.vector128val, expr->rtype, NULL)) { - uses_globals = 1; - RewriteVectorConst(expr); - expandTOCexpression(expr, NULL, 0); - } - break; - case ESTRINGCONST: - uses_globals = 1; - CInit_RewriteString(expr, 1); - expandTOCexpression(expr, NULL, 0); - break; - case EOBJREF: - obj = expr->data.objref; - CError_ASSERT(3203, obj->datatype != DALIAS); - if (obj->datatype == DFUNC || obj->datatype == DVFUNC) - uses_globals = 1; - if (obj->datatype == DDATA) { - uses_globals = 1; - if (createIndirect(obj, 0, 1)) { - tmpexpr = lalloc(sizeof(ENode)); - memclrw(tmpexpr, sizeof(ENode)); - tmpexpr->type = EOBJREF; - tmpexpr->cost = 0; - tmpexpr->data.objref = obj->toc; - tmpexpr->rtype = CDecl_NewPointerType(expr->rtype); - - expr->type = EINDIRECT; - expr->cost = 1; - expr->data.monadic = tmpexpr; - } - } - expr->hascall = 0; - break; - case ECONDASS: - expr->ignored = 0; - case ECOND: - if (!ENODE_IS_RANGE(expr->data.cond.cond, ELESS, ENOTEQU)) - expr->data.cond.cond = comparewithzero(expr->data.cond.cond); - expandTOCexpression(expr->data.cond.expr1, NULL, ignored); - expandTOCexpression(expr->data.cond.expr2, NULL, ignored); - if (TOC_use_fsel(expr)) { - cond = expr->data.cond.cond; - if (ENODE_IS(cond->data.diadic.right, EFLOATCONST) && CMach_FloatIsZero(cond->data.diadic.right->data.floatval)) { - expandTOCexpression(cond->data.diadic.left, NULL, 0); - } else if (ENODE_IS(cond->data.diadic.left, EFLOATCONST) && CMach_FloatIsZero(cond->data.diadic.left->data.floatval)) { - expandTOCexpression(cond->data.diadic.right, NULL, 0); - } else { - expandTOCexpression(expr->data.cond.cond, NULL, 0); - } - } else { - expandTOCexpression(expr->data.cond.cond, NULL, 0); - } - expr->hascall = expr->data.cond.cond->hascall | expr->data.cond.expr1->hascall | expr->data.cond.expr2->hascall; - break; - case EFUNCCALL: - case EFUNCCALLP: - if (is_intrinsic_function_call(expr)) { - expr->hascall = 0; - if ((expr->data.funccall.funcref->data.objref->u.func.u.intrinsicid & 0xFFFFu) == Intrinsic_008) { - if (copts.altivec_model) - update_frame_align(16); - dynamic_stack = 1; - requires_frame = 1; - } else if ((expr->data.funccall.funcref->data.objref->u.func.u.intrinsicid & 0xFFFFu) == Intrinsic_035) { - if (expr->data.funccall.args->next->node->type == ESTRINGCONST) { - rewritestrcpy(expr); - } else { - requires_frame = 1; - makes_call = 1; - expr->hascall = 1; - } - } else if ((expr->data.funccall.funcref->data.objref->u.func.u.intrinsicid & 0xFFFFu) == Intrinsic_036) { - if (expr->data.funccall.args->next->next->node->type != EINTCONST) { - requires_frame = 1; - makes_call = 1; - expr->hascall = 1; - } - } - } else { - requires_frame = 1; - makes_call = 1; - expr->hascall = 1; - } - - if (disables_optimizer(expr)) { - disable_optimizer |= 1; - if (copts.disable_registers) - disable_optimizer |= 2; - } - - if (ENODE_IS(expr->data.funccall.funcref, EINDIRECT) && IS_TYPE_FUNC(expr->data.funccall.funcref->rtype)) - *expr->data.funccall.funcref = *expr->data.funccall.funcref->data.monadic; - - if (ENODE_IS(expr->data.funccall.funcref, EOBJREF)) { - expr->data.funccall.funcref->hascall = 0; - if (expr->data.funccall.funcref->data.objref->datatype == DVFUNC && (expr->data.funccall.funcref->flags & ENODE_FLAG_80)) { - tmpobj = galloc(sizeof(Object)); - *tmpobj = *expr->data.funccall.funcref->data.objref; - tmpobj->datatype = DFUNC; - expr->data.funccall.funcref->data.objref = tmpobj; - } - } else { - expandTOCexpression(expr->data.funccall.funcref, NULL, 0); - } - - for (list = expr->data.funccall.args; list; list = list->next) - expandTOCexpression(list->node, NULL, 0); - - if (expr->hascall) - estimate_func_param_size(expr); - - if (is_intrinsic_function_call(expr)) { - for (list = expr->data.funccall.args; list; list = list->next) - expr->hascall |= list->node->hascall; - } - - if (CMach_PassResultInHiddenArg(TYPE_FUNC(expr->data.funccall.functype)->functype)) - rewritefunctioncallreturningstruct(expr); - - break; - case ECOMMA: - expandTOCexpression(expr->data.diadic.left, NULL, 1); - expandTOCexpression(expr->data.diadic.right, NULL, ignored); - expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; - break; - case ELAND: - case ELOR: - if (!ENODE_IS(expr->data.diadic.left, ELOGNOT) && !ENODE_IS2(expr->data.diadic.left, ELAND, ELOR) && !ENODE_IS_RANGE(expr->data.diadic.left, ELESS, ENOTEQU)) - expr->data.diadic.left = comparewithzero(expr->data.diadic.left); - if (!ENODE_IS(expr->data.diadic.right, ELOGNOT) && !ENODE_IS2(expr->data.diadic.right, ELAND, ELOR) && !ENODE_IS_RANGE(expr->data.diadic.right, ELESS, ENOTEQU)) - expr->data.diadic.right = comparewithzero(expr->data.diadic.right); - expandTOCexpression(expr->data.diadic.left, NULL, 0); - expandTOCexpression(expr->data.diadic.right, NULL, 0); - expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; - break; - case EDIVASS: - if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype)) - uses_globals = 1; - rewrite_opassign(expr, EDIV); - goto opassign_common; - case EMULASS: - if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype)) - uses_globals = 1; - rewrite_opassign(expr, EMUL); - goto opassign_common; - case EADDASS: - if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype)) - uses_globals = 1; - rewrite_opassign(expr, EADD); - goto opassign_common; - case ESUBASS: - if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype)) - uses_globals = 1; - rewrite_opassign(expr, ESUB); - goto opassign_common; - case EMODASS: - if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype)) - uses_globals = 1; - rewrite_opassign(expr, EMODULO); - goto opassign_common; - case ESHLASS: - rewrite_opassign(expr, ESHL); - goto opassign_common; - case ESHRASS: - rewrite_opassign(expr, ESHR); - goto opassign_common; - case EANDASS: - rewrite_opassign(expr, EAND); - goto opassign_common; - case EXORASS: - rewrite_opassign(expr, EXOR); - goto opassign_common; - case EORASS: - rewrite_opassign(expr, EOR); - goto opassign_common; - case EASS: - if (ENODE_IS(expr->data.diadic.left, EINDIRECT)) - expr->data.diadic.left = expr->data.diadic.left->data.monadic; - opassign_common: - expandTOCexpression(expr->data.diadic.left, NULL, 0); - expandTOCexpression(expr->data.diadic.right, NULL, 0); - expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; - break; - case EEQU: - case ENOTEQU: - if (ENODE_IS(expr->data.diadic.right, EINTCONST) && expr->data.diadic.right->data.intval.lo == 0 && expr->data.diadic.right->data.intval.hi == 0) { - for (tmpexpr = expr->data.diadic.left; ENODE_IS2(tmpexpr, EFORCELOAD, ETYPCON); tmpexpr = tmpexpr->data.monadic) { - if (!TYPE_FITS_IN_REGISTER(tmpexpr->rtype)) - break; - } - if (ENODE_IS(tmpexpr, ELOGNOT) && TYPE_FITS_IN_REGISTER(tmpexpr->data.monadic->rtype)) { - if (ENODE_IS(expr, EEQU)) - expr->type = ENOTEQU; - else - expr->type = EEQU; - expr->data.diadic.left = tmpexpr->data.monadic; - expandTOCexpression(expr, NULL, 0); - break; - } - if (ENODE_IS(tmpexpr, EEQU)) { - if (ENODE_IS(expr, EEQU)) - tmpexpr->type = ENOTEQU; - *expr = *tmpexpr; - expandTOCexpression(expr, NULL, 0); - break; - } - if (ENODE_IS(tmpexpr, ENOTEQU)) { - if (ENODE_IS(expr, EEQU)) - tmpexpr->type = EEQU; - *expr = *tmpexpr; - expandTOCexpression(expr, NULL, 0); - break; - } - if (ENODE_IS(tmpexpr, ECOND)) { - newexpr = COND_to_COMPARE(tmpexpr->data.cond.cond, tmpexpr->data.cond.expr1, tmpexpr->data.cond.expr2); - if (newexpr) { - *tmpexpr = *newexpr; - expandTOCexpression(expr, NULL, 0); - break; - } - } - } - case EDIV: - if (ENODE_IS(expr, EDIV) && ENODE_IS(expr->data.diadic.right, EFLOATCONST) && CMach_FloatIsPowerOf2(expr->data.diadic.right->data.floatval)) { - expr->type = EMUL; - expr->data.diadic.right->data.floatval = CMach_FloatReciprocal(expr->data.diadic.right->data.floatval); - } - case EMODULO: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - expandTOCexpression(expr->data.diadic.left, NULL, 0); - expandTOCexpression(expr->data.diadic.right, NULL, 0); - expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; - if (TYPE_IS_8BYTES(expr->rtype)) { - if (ENODE_IS2(expr, ESHL, ESHR) && !ENODE_IS(expr->data.diadic.right, EINTCONST)) { - expr->hascall = 1; - requires_frame = 1; - makes_call = 1; - } - if (ENODE_IS2(expr, EDIV, EMODULO)) { - if (ENODE_IS(expr->data.diadic.right, EINTCONST)) { - if (I8_log2n(((SInt64) expr->data.diadic.right->data.intval.hi << 32) + expr->data.diadic.right->data.intval.lo) <= 0) { - expr->hascall = 1; - requires_frame = 1; - makes_call = 1; - } - } else { - expr->hascall = 1; - requires_frame = 1; - makes_call = 1; - } - } - } - break; - case ESUB: - if (ENODE_IS(expr->data.diadic.right, EINTCONST)) { - expr->type = EADD; - expr->data.diadic.right->data.intval = CInt64_Neg(expr->data.diadic.right->data.intval); - } - case EMUL: - case EADD: - case EAND: - case EXOR: - case EOR: - expandTOCexpression(expr->data.diadic.left, type, 0); - expandTOCexpression(expr->data.diadic.right, type, 0); - expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; - if (ENODE_IS3(expr, EMUL, EADD, ESUB) && TYPE_IS_8BYTES(expr->rtype)) - Optimize64bitMath(expr); - if (type) { - if ( - ENODE_IS(expr->data.diadic.left, ETYPCON) && - IS_TYPE_INT_OR_ENUM(expr->data.diadic.left->rtype) && - IS_TYPE_INT_OR_ENUM(expr->data.diadic.left->data.monadic->rtype) && - expr->data.diadic.left->data.monadic->rtype->size >= type->size && - !TYPE_IS_8BYTES(expr->data.diadic.left->data.monadic->rtype) - ) - expr->data.diadic.left = expr->data.diadic.left->data.monadic; - - if ( - ENODE_IS(expr->data.diadic.right, ETYPCON) && - IS_TYPE_INT_OR_ENUM(expr->data.diadic.right->rtype) && - IS_TYPE_INT_OR_ENUM(expr->data.diadic.right->data.monadic->rtype) && - expr->data.diadic.right->data.monadic->rtype->size >= type->size && - !TYPE_IS_8BYTES(expr->data.diadic.right->data.monadic->rtype) - ) - expr->data.diadic.right = expr->data.diadic.right->data.monadic; - - expr->rtype = type; - } - break; - - case ETYPCON: - tmpexpr = expr->data.monadic; - if ((IS_TYPE_INT_OR_ENUM(expr->rtype) && expr->rtype->size < 4) && IS_TYPE_INT_OR_ENUM(tmpexpr->rtype) && !TYPE_IS_8BYTES(tmpexpr->rtype)) { - expandTOCexpression(tmpexpr, expr->rtype, 0); - } else { - expandTOCexpression(tmpexpr, NULL, expr->rtype->type == TYPEVOID); - } - - expr->hascall = tmpexpr->hascall; - if (IS_TYPE_INT_OR_ENUM(tmpexpr->rtype) && IS_TYPE_FLOAT(expr->rtype)) - uses_globals = 1; - - if ((TYPE_IS_8BYTES(tmpexpr->rtype) && IS_TYPE_FLOAT(expr->rtype)) || (TYPE_IS_8BYTES(expr->rtype) && IS_TYPE_FLOAT(tmpexpr->rtype))) { - uses_globals = 1; - expr->hascall = 1; - requires_frame = 1; - makes_call = 1; - } - - if (IS_TYPE_FLOAT(tmpexpr->rtype)) { - if (is_unsigned(expr->rtype) && expr->rtype->size == 4) { - expr->hascall = 1; - requires_frame = 1; - makes_call = 1; - } else { - uses_globals = 1; - } - } - - if (IS_TYPE_VECTOR(expr->rtype) && !IS_TYPE_VECTOR(tmpexpr->rtype)) - PPCError_Error(PPCErrorStr114); - break; - - case EPOSTINC: - if (!expr->ignored) { - if (IS_TYPE_FLOAT(expr->data.monadic->rtype) && is_unsigned(expr->rtype)) - uses_globals = 1; - expandTOCexpression(expr->data.monadic, NULL, 0); - expr->hascall = expr->data.monadic->hascall; - break; - } - expr->type = EPREINC; - case EPREINC: - rewrite_preincdec(expr); - rewrite_opassign(expr, EADD); - goto opassign_common; - - case EPOSTDEC: - if (!expr->ignored) { - if (IS_TYPE_FLOAT(expr->data.monadic->rtype) && is_unsigned(expr->rtype)) - uses_globals = 1; - expandTOCexpression(expr->data.monadic, NULL, 0); - expr->hascall = expr->data.monadic->hascall; - break; - } - expr->type = EPREDEC; - case EPREDEC: - rewrite_preincdec(expr); - rewrite_opassign(expr, ESUB); - goto opassign_common; - - case ELOGNOT: - if (!ENODE_IS(expr->data.monadic, ELOGNOT) && !ENODE_IS2(expr->data.monadic, ELAND, ELOR) && !ENODE_IS_RANGE(expr->data.monadic, ELESS, ENOTEQU)) - expr->data.monadic = comparewithzero(expr->data.monadic); - case EMONMIN: - case EBINNOT: - tmpexpr = expr->data.monadic; - expandTOCexpression(tmpexpr, type, 0); - expr->hascall = tmpexpr->hascall; - if (type && ENODE_IS(expr->data.monadic, ETYPCON)) { - if (IS_TYPE_INT_OR_ENUM(expr->data.monadic->rtype) && IS_TYPE_INT_OR_ENUM(expr->data.monadic->data.monadic->rtype)) { - if (expr->data.monadic->data.monadic->rtype->size >= type->size) { - expr->data.monadic = expr->data.monadic->data.monadic; - expr->rtype = type; - } - } - } - break; - - case EINDIRECT: - case EFORCELOAD: - case EBITFIELD: - tmpexpr = expr->data.monadic; - expandTOCexpression(tmpexpr, NULL, 0); - expr->hascall = tmpexpr->hascall; - break; - - case EDEFINE: - tmpexpr = expr->data.monadic; - expandTOCexpression(tmpexpr, NULL, 0); - expr->hascall = tmpexpr->hascall; - break; - - case EREUSE: - expr->hascall = expr->data.monadic->hascall; - break; - - case ENULLCHECK: - expandTOCexpression(expr->data.diadic.left, NULL, 0); - expandTOCexpression(expr->data.diadic.right, NULL, 0); - expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall; - break; - - case EPRECOMP: - expr->hascall = 0; - break; - - case ELABEL: - obj = createcodelabel(expr->data.label); - newexpr = lalloc(sizeof(ENode)); - memclrw(newexpr, sizeof(ENode)); - newexpr->type = EOBJREF; - newexpr->cost = 0; - newexpr->data.objref = obj; - newexpr->rtype = CDecl_NewPointerType(obj->type); - - expr->type = EINDIRECT; - expr->cost = 1; - expr->data.monadic = newexpr; - expr->hascall = 0; - break; - } -} - -static void checkexceptionreferences(ExceptionAction *action) { - for (; action; action = action->prev) { - switch (action->type) { - case EAT_DESTROYLOCAL: - referenceexception(action->data.destroy_local.local); - break; - case EAT_DESTROYLOCALCOND: - referenceexception(action->data.destroy_local_cond.local); - referenceexception(action->data.destroy_local_cond.cond); - break; - case EAT_DESTROYLOCALOFFSET: - referenceexception(action->data.destroy_local_offset.local); - break; - case EAT_DESTROYLOCALPOINTER: - referenceexception(action->data.destroy_local_pointer.pointer); - break; - case EAT_DESTROYLOCALARRAY: - referenceexception(action->data.destroy_local_array.localarray); - break; - case EAT_DESTROYBASE: - referenceexception(action->data.destroy_member.objectptr); // wrong union? - break; - case EAT_DESTROYPARTIALARRAY: - referenceexception(action->data.destroy_partial_array.arraypointer); - referenceexception(action->data.destroy_partial_array.arraycounter); - referenceexception(action->data.destroy_partial_array.element_size); - break; - case EAT_DESTROYMEMBER: - referenceexception(action->data.destroy_member.objectptr); - break; - case EAT_DESTROYMEMBERCOND: - referenceexception(action->data.destroy_member_cond.objectptr); - referenceexception(action->data.destroy_member_cond.cond); - break; - case EAT_DESTROYMEMBERARRAY: - referenceexception(action->data.destroy_member_array.objectptr); - break; - case EAT_DELETEPOINTER: - case EAT_DELETELOCALPOINTER: - referenceexception(action->data.delete_pointer.pointerobject); - break; - case EAT_DELETEPOINTERCOND: - referenceexception(action->data.delete_pointer_cond.pointerobject); - referenceexception(action->data.delete_pointer_cond.cond); - break; - case EAT_CATCHBLOCK: - referenceexception(action->data.catch_block.catch_object); - referenceexception(action->data.catch_block.catch_info_object); - break; - case EAT_ACTIVECATCHBLOCK: - referenceexception(action->data.active_catch_block.catch_info_object); - break; - } - } -} - -void expandTOCreferences(Statement **stmts) { - Statement *stmt; - IAOperand *op; - int i; - InlineAsm *ia; - VarInfo *vi; - - codelabellist = NULL; - exceptionlist = NULL; - - for (stmt = *stmts; stmt; stmt = stmt->next) { - curstmtvalue = stmt->value; - if (stmt->flags & StmtFlag_1) { - has_catch_blocks = 1; - dynamic_stack = 1; - requires_frame = 1; - } - - switch (stmt->type) { - case ST_EXPRESSION: - expandTOCexpression(stmt->expr, NULL, 1); - if (stmt->expr->type == ETYPCON && IS_TYPE_VOID(stmt->expr->rtype)) - stmt->expr = stmt->expr->data.monadic; - break; - case ST_GOTOEXPR: - expandTOCexpression(stmt->expr, NULL, 0); - break; - case ST_IFGOTO: - case ST_IFNGOTO: - if (stmt->expr->type < ELESS || stmt->expr->type > ENOTEQU) - stmt->expr = comparewithzero(stmt->expr); - expandTOCexpression(stmt->expr, NULL, 0); - break; - case ST_RETURN: - if (!stmt->expr) - continue; - expandTOCexpression( - stmt->expr, NULL, - IS_TYPE_ARRAY(stmt->expr->rtype) || IS_TYPE_NONVECTOR_STRUCT(stmt->expr->rtype) || IS_TYPE_CLASS(stmt->expr->rtype) || - IS_TYPE_12BYTES_MEMBERPOINTER(stmt->expr->rtype)); - break; - case ST_SWITCH: - uses_globals = 1; - expandTOCexpression(stmt->expr, NULL, 0); - break; - case ST_ENDCATCHDTOR: - requires_frame = 1; - makes_call = 1; - break; - case ST_ASM: - if ((ia = (InlineAsm *) stmt->expr)) { - if (ia->flags & IAFlag1) { - if (ia->opcode == IADirective_FrFree) - requires_frame = 1; - } else { - for (i = 0, op = ia->args; i < ia->argcount; i++, op++) { - if (op->type == IAOpnd_Reg) { - if (!op->u.reg.object) { - if (op->u.reg.num == INVALID_PIC_REG) - uses_globals = 1; - else if (op->u.reg.effect & EffectWrite) - asm_used_register(op->u.reg.rclass, op->u.reg.num); - } else if ((vi = Registers_GetVarInfo(op->u.reg.object))) { - vi->flags |= VarInfoFlag40; - } - } else if (op->type == IAOpnd_3) { - uses_globals = 1; - } - } - - if (ia->flags & IAFlag2) - makes_call = 1; - } - } - break; - } - - checkexceptionreferences(stmt->dobjstack); - } -} - -void resetTOCvarinfo(void) { - ObjectList *list; - - for (list = toclist; list; list = list->next) - list->object->u.toc.info = CodeGen_GetNewVarInfo(); -} - -Boolean needdescriptor(void) { - // completely unused, dunno what args this might take - return 0; -} - -Object *createstaticinitobject(void) { - char buf[100]; - char *p; - Str255 fname; - TypeFunc *tfunc; - Object *obj; - - COS_FileGetFSSpecInfo(&cparamblkptr->sourcefile, NULL, NULL, fname); - sprintf(buf, "__sinit_%*.*s", -fname[0], fname[0], &fname[1]); - for (p = &buf[1]; *p; p++) { - if (*p == '.') - *p = '_'; - } - - tfunc = galloc(sizeof(TypeFunc)); - memclrw(tfunc, sizeof(TypeFunc)); - tfunc->type = TYPEFUNC; - tfunc->functype = &stvoid; - tfunc->args = NULL; - tfunc->flags = FUNC_DEFINED; - - obj = galloc(sizeof(Object)); - memclrw(obj, sizeof(Object)); - obj->otype = OT_OBJECT; - obj->type = (Type *) tfunc; - obj->name = GetHashNameNodeExport(buf); - obj->sclass = TK_STATIC; - obj->datatype = DFUNC; - - return obj; -} - -static void estimate_func_param_size(ENode *node) { - SInt32 work; - ENodeList *list; - SInt32 align; - - work = 0; - for (list = node->data.funccall.args; list; list = list->next) { - align = ~7 & (CMach_ArgumentAlignment(list->node->rtype) + 7); - work += ~(align - 1) & (list->node->rtype->size + align - 1); - } - - estimate_out_param_size(work); -} diff --git a/compiler_and_linker/unsorted/ValueNumbering.c b/compiler_and_linker/unsorted/ValueNumbering.c deleted file mode 100644 index 0907fa1..0000000 --- a/compiler_and_linker/unsorted/ValueNumbering.c +++ /dev/null @@ -1,661 +0,0 @@ -#include "compiler/ValueNumbering.h" -#include "compiler/Alias.h" -#include "compiler/PCode.h" -#include "compiler/Registers.h" -#include "compiler/RegisterInfo.h" -#include "compiler/CompilerTools.h" -#include "compiler/CError.h" - -typedef struct ValueLabel { - struct ValueLabel *next; - PCodeArg op; -} ValueLabel; - -typedef struct AvailableValue { - struct AvailableValue *next; - ValueLabel *labelled; - PCode *pcode; - int killedregister; - int aliasnumber; - int opnumbers[0]; -} AvailableValue; - -typedef struct RegValue { - int number; - int x4; - AvailableValue *available; -} RegValue; - -typedef struct State { - void *stackedvalues; - int valueceiling; -} State; - -typedef struct StackedValue { - struct StackedValue *next; - PCodeArg op; - RegValue value; - Alias *alias; - PCode *valuepcode; -} StackedValue; - -int removedcommonsubexpressions; -int nextvaluenumber; -static AvailableValue *opvalue[428]; -static RegValue *regvalue[RegClassMax]; -static StackedValue *stackedvalues; -static int valueceiling; -static int moreaggressiveoptimization; - -static void allocatecsedatastructures(void) { - char rclass; - - for (rclass = 0; rclass < RegClassMax; rclass++) - regvalue[(char) rclass] = oalloc(sizeof(RegValue) * used_virtual_registers[(char) rclass]); -} - -static void initializecsedatastructures(void) { - RegValue *rv; - char rclass; - int i; - - nextvaluenumber = 0; - - for (i = 0; i < 428; i++) - opvalue[i] = NULL; - - for (rclass = 0; rclass < RegClassMax; rclass++) { - rv = regvalue[(char) rclass]; - for (i = 0; i < used_virtual_registers[(char) rclass]; i++, rv++) { - rv->number = nextvaluenumber++; - rv->x4 = 0; - rv->available = NULL; - } - } - - initialize_alias_values(); - stackedvalues = NULL; - valueceiling = 0x7FFFFFFF; -} - -static void labelvalue(AvailableValue *av, PCodeArg *op) { - ValueLabel *label = oalloc(sizeof(ValueLabel)); - label->op = *op; - label->next = av->labelled; - av->labelled = label; -} - -static void unlabelvalue(AvailableValue *av, PCodeArg *op) { - ValueLabel *labelled; - ValueLabel **ptr; - - ptr = &av->labelled; - while ((labelled = *ptr)) { - if (labelled->op.data.reg.reg == op->data.reg.reg) - *ptr = labelled->next; - else - ptr = &labelled->next; - } -} - -static void stackregistervalue(PCodeArg *op, RegValue *value) { - StackedValue *stacked = oalloc(sizeof(StackedValue)); - stacked->next = stackedvalues; - stackedvalues = stacked; - - stacked->op = *op; - stacked->value = *value; -} - -static void stackmemoryvalue(Alias *alias) { - StackedValue *stacked = oalloc(sizeof(StackedValue)); - stacked->next = stackedvalues; - stackedvalues = stacked; - - stacked->op.kind = PCOp_MEMORY; - stacked->alias = alias; - stacked->value.number = alias->valuenumber; - stacked->valuepcode = alias->valuepcode; -} - -static void unstackvalue(StackedValue *stacked) { - PCodeArg *op = &stacked->op; - RegValue *value; - - if (stacked->op.kind == PCOp_MEMORY) { - stacked->alias->valuenumber = stacked->value.number; - stacked->alias->valuepcode = stacked->valuepcode; - } else { - value = ®value[op->arg][op->data.reg.reg]; - if (value->available) - unlabelvalue(value->available, op); - value->number = stacked->value.number; - value->x4 = stacked->value.x4; - value->available = stacked->value.available; - if (value->available) - labelvalue(value->available, op); - } -} - -static int samevalue(PCodeArg *op1, PCodeArg *op2) { - return regvalue[op1->arg][op1->data.reg.reg].number == regvalue[op2->arg][op2->data.reg.reg].number; -} - -static int killregister(PCodeArg *op) { - RegValue *value; - - value = ®value[op->arg][op->data.reg.reg]; - if (value->number < valueceiling && nextvaluenumber >= valueceiling) - stackregistervalue(op, value); - - if (value->available) - unlabelvalue(value->available, op); - value->available = NULL; - value->x4 = 0; - return value->number = nextvaluenumber++; -} - -void killmemory(Alias *alias, PCode *newValue) { - if (alias->valuenumber < valueceiling && nextvaluenumber >= valueceiling) - stackmemoryvalue(alias); - - if (newValue) { - alias->valuenumber = regvalue[newValue->args[0].arg][newValue->args[0].data.reg.reg].number; - alias->valuepcode = newValue; - } else { - alias->valuenumber = nextvaluenumber++; - alias->valuepcode = NULL; - } -} - -static void killspecificCSEs(short op) { - AvailableValue *av; - ValueLabel *labelled; - - for (av = opvalue[op]; av; av = av->next) { - for (labelled = av->labelled; labelled; labelled = labelled->next) - killregister(&labelled->op); - } -} - -static void killallCSEs(void) { - AvailableValue *av; - ValueLabel *labelled; - int i; - - for (i = 0; i < 428; i++) { - for (av = opvalue[i]; av; av = av->next) { - for (labelled = av->labelled; labelled; labelled = labelled->next) - killregister(&labelled->op); - } - } -} - -static void killregisters(PCode *pcode) { - PCodeArg *op; - int i; - - for (i = 0, op = pcode->args; i < pcode->argCount; i++, op++) { - if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite)) - killregister(op); - } -} - -static void copyregister(PCodeArg *src, PCodeArg *dest) { - RegValue *srcvalue; - RegValue *destvalue; - - srcvalue = ®value[src->arg][src->data.reg.reg]; - destvalue = ®value[dest->arg][dest->data.reg.reg]; - - if (destvalue->number < valueceiling && nextvaluenumber >= valueceiling) - stackregistervalue(dest, destvalue); - - if (destvalue->available) - unlabelvalue(destvalue->available, dest); - destvalue->available = srcvalue->available; - if (destvalue->available) - labelvalue(destvalue->available, dest); - - destvalue->number = srcvalue->number; - - if (srcvalue->x4 && srcvalue->number == regvalue[src->arg][srcvalue->x4].number) - destvalue->x4 = srcvalue->x4; - else - destvalue->x4 = src->data.reg.reg; -} - -static int matchvalues(AvailableValue *av, PCode *match) { - PCodeArg *avOp; - PCodeArg *matchOp; - int i; - - for (avOp = &av->pcode->args[0], matchOp = &match->args[0], i = 0; i < match->argCount; i++, avOp++, matchOp++) { - if (i != 0) { - switch (avOp->kind) { - case PCOp_REGISTER: - if (av->opnumbers[i] != regvalue[matchOp->arg][matchOp->data.reg.reg].number) - return 0; - break; - case PCOp_MEMORY: - if (matchOp->kind != PCOp_MEMORY) - return 0; - if (matchOp->data.mem.obj != avOp->data.mem.obj) - return 0; - if (matchOp->data.mem.offset != avOp->data.mem.offset) - return 0; - if ((unsigned char) matchOp->arg != (unsigned char) avOp->arg) - return 0; - break; - case PCOp_IMMEDIATE: - if (matchOp->kind != PCOp_IMMEDIATE) - return 0; - if (matchOp->data.imm.value != avOp->data.imm.value) - return 0; - break; - case PCOp_LABEL: - if (matchOp->kind != PCOp_LABEL) - return 0; - if (matchOp->data.label.label != avOp->data.label.label) - return 0; - break; - case PCOp_SYSREG: - CError_FATAL(572); - } - } - } - - if ((match->flags & (fIsRead | fPCodeFlag20000)) && match->alias->valuenumber != av->aliasnumber) - return 0; - - return 1; -} - -static void chooselocation(AvailableValue *av, PCodeArg *op) { - ValueLabel *labelled; - PCodeArg *baseop; - - baseop = &av->pcode->args[0]; - labelled = av->labelled; - while (labelled) { - if (labelled->op.data.reg.reg == baseop->data.reg.reg) { - *op = labelled->op; - return; - } - labelled = labelled->next; - } - - *op = av->labelled[0].op; -} - -static int findavailablevalue(PCode *pcode, PCodeArg *op) { - AvailableValue *av; - PCodeArg tmp1; - PCodeArg tmp2; - - for (av = opvalue[pcode->op]; av; av = av->next) { - if (av->labelled && av->pcode->flags == pcode->flags && av->pcode->argCount == pcode->argCount) { - if (!matchvalues(av, pcode)) { - if (!(pcode->flags & fCommutative)) - continue; - - tmp1 = pcode->args[1]; - pcode->args[1] = pcode->args[2]; - pcode->args[2] = tmp1; - - if (!matchvalues(av, pcode)) { - tmp2 = pcode->args[1]; - pcode->args[1] = pcode->args[2]; - pcode->args[2] = tmp2; - continue; - } - } - chooselocation(av, op); - return 1; - } - } - - return 0; -} - -static void addavailablevalue(PCode *pcode) { - AvailableValue *av; - PCodeArg *op; - int i; - - av = oalloc(sizeof(AvailableValue) + sizeof(int) * pcode->argCount); - av->labelled = NULL; - av->pcode = pcode; - for (i = 0, op = &pcode->args[0]; i < pcode->argCount; i++, op++) { - if (op->kind == PCOp_REGISTER) - av->opnumbers[i] = regvalue[op->arg][op->data.reg.reg].number; - } - - if (pcode->flags & (fIsRead | fPCodeFlag20000)) - av->aliasnumber = pcode->alias->valuenumber; - - op = &pcode->args[0]; - av->killedregister = killregister(op); - labelvalue(av, op); - regvalue[op->arg][op->data.reg.reg].available = av; - av->next = opvalue[pcode->op]; - opvalue[pcode->op] = av; -} - -static int isCSEop(PCode *pcode) { - PCodeArg *baseOp; - PCodeArg *op; - int i; - - baseOp = &pcode->args[0]; - - switch (pcode->op) { - case PC_CMPI: - case PC_CMP: - case PC_CMPLI: - case PC_CMPL: - case PC_FCMPU: - case PC_FCMPO: - if (!moreaggressiveoptimization) - return 0; - break; - case PC_LI: - case PC_LIS: - if (!moreaggressiveoptimization) - return 0; - if (pcode->args[0].data.reg.reg < first_fe_temporary_register[RegClass_GPR] || pcode->args[0].data.reg.reg > last_temporary_register[RegClass_GPR]) - return 0; - break; - } - - if (PCODE_FLAG_SET_F(pcode) & (fIsVolatile | fSideEffects | fOverflow | fSetsCarry | fRecordBit)) - return 0; - - for (i = 0, op = &pcode->args[0]; i < pcode->argCount; i++, op++) { - if (op != baseOp && - op->kind == baseOp->kind && - op->arg == baseOp->arg && - op->data.reg.reg == baseOp->data.reg.reg) - return 0; - } - - return 1; -} - -static int isCSEload(PCode *pcode) { - PCodeArg *op; - int i; - int count; - - count = 0; - for (i = 0, op = &pcode->args[0]; i < pcode->argCount; i++, op++) { - if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite)) - count++; - } - - return count == 1; -} - -static void registercopy(PCode *pcode) { - PCodeArg *op1; - PCodeArg *op2; - - op1 = &pcode->args[0]; - op2 = &pcode->args[1]; - if (samevalue(op2, op1)) - deletepcode(pcode); - else - copyregister(op2, op1); -} - -static PCode *recentlystored(Alias *alias, PCodeArg *op) { - PCode *pc; - if ((pc = alias->valuepcode) && alias->valuenumber == regvalue[pc->args[0].arg][pc->args[0].data.reg.reg].number) { - *op = pc->args[0]; - return pc; - } else { - return NULL; - } -} - -static void simpleload(PCode *pcode) { - PCodeArg *origOp; - PCodeArg op; - PCode *rs; - - origOp = &pcode->args[0]; - if ((pcode->flags & fIsVolatile) || !isCSEload(pcode)) { - killregisters(pcode); - return; - } - - if (findavailablevalue(pcode, &op)) { - if (!samevalue(origOp, &op)) { - insertpcodebefore(pcode, makecopyinstruction(&op, origOp)); - copyregister(&op, origOp); - } - deletepcode(pcode); - removedcommonsubexpressions = 1; - } else if ((rs = recentlystored(pcode->alias, &op)) && can_reuse_stored_value(rs, pcode)) { - if (!samevalue(origOp, &op)) { - insertpcodebefore(pcode, makecopyinstruction(&op, origOp)); - copyregister(&op, origOp); - } - deletepcode(pcode); - removedcommonsubexpressions = 1; - } else { - addavailablevalue(pcode); - } -} - -static void simplestore(PCode *pcode) { - update_alias_value(pcode->alias, pcode); - killregisters(pcode); -} - -static void pointerload(PCode *pcode) { - PCodeArg *op; - PCodeArg buf; - - op = &pcode->args[0]; - - if ((pcode->flags & fIsVolatile) || !isCSEload(pcode)) { - killregisters(pcode); - return; - } - - if (findavailablevalue(pcode, &buf)) { - if (!samevalue(op, &buf)) { - insertpcodebefore(pcode, makecopyinstruction(&buf, op)); - copyregister(&buf, op); - } - deletepcode(pcode); - removedcommonsubexpressions = 1; - } else { - addavailablevalue(pcode); - } -} - -static void pointerstore(PCode *pcode) { - update_alias_value(pcode->alias, NULL); - killregisters(pcode); -} - -static void arithmeticop(PCode *pcode) { - PCodeArg *op; - PCodeArg buf; - - op = &pcode->args[0]; - - if (findavailablevalue(pcode, &buf)) { - if (!samevalue(op, &buf)) { - insertpcodebefore(pcode, makecopyinstruction(&buf, op)); - copyregister(&buf, op); - } - deletepcode(pcode); - removedcommonsubexpressions = 1; - } else { - addavailablevalue(pcode); - } -} - -static void functioncall(PCode *pcode) { - killregisters(pcode); - if (coloring) { - update_all_alias_values(); - killallCSEs(); - } else { - update_alias_value(pcode->alias, NULL); - } -} - -static void operatefrommemory(PCode *pcode) { - CError_FATAL(980); -} - -static void operatetomemory(PCode *pcode) { - CError_FATAL(1011); -} - -static void propagatecopiesto(PCode *pcode) { - PCodeArg *op; - int i; - - for (i = 0, op = &pcode->args[0]; i < pcode->argCount; i++, op++) { - if ( - op->kind == PCOp_REGISTER && - (op->data.reg.effect & (EffectRead | EffectWrite | Effect8)) == EffectRead && - op->data.reg.reg >= n_real_registers[op->arg] && - regvalue[op->arg][op->data.reg.reg].x4 && - regvalue[op->arg][op->data.reg.reg].x4 >= n_real_registers[op->arg] && - regvalue[op->arg][op->data.reg.reg].number == regvalue[op->arg][regvalue[op->arg][op->data.reg.reg].x4].number - ) { - op->data.reg.reg = regvalue[op->arg][op->data.reg.reg].x4; - } - } -} - -static void removecsesfrombasicblock(PCodeBlock *block) { - PCode *pcode; - PCode *next; - - for (pcode = block->firstPCode; pcode; pcode = next) { - next = pcode->nextPCode; - propagatecopiesto(pcode); - if (pcode->flags & fIsMove) { - registercopy(pcode); - } else if ((pcode->flags & fIsCall) && (pcode->flags & (fLink | fSideEffects))) { - functioncall(pcode); - } else if (pcode->flags & fIsRead) { - if (pcode->flags & fIsPtrOp) - pointerload(pcode); - else - simpleload(pcode); - } else if (pcode->flags & fIsWrite) { - if (pcode->flags & fIsPtrOp) - pointerstore(pcode); - else - simplestore(pcode); - } else if (pcode->flags & fPCodeFlag20000) { - operatefrommemory(pcode); - } else if (pcode->flags & fPCodeFlag40000) { - operatetomemory(pcode); - } else if ((pcode->flags & fIsCSE) && isCSEop(pcode)) { - arithmeticop(pcode); - } else { - killregisters(pcode); - } - } - - block->flags |= fVisited; -} - -static void getvaluestate(State *state) { - state->stackedvalues = stackedvalues; - state->valueceiling = valueceiling; -} - -static void setvaluestate(State *state) { - stackedvalues = state->stackedvalues; - valueceiling = state->valueceiling; -} - -static void forkvaluestate(int number) { - stackedvalues = NULL; - valueceiling = number; -} - -static void regressvaluestate(void) { - AvailableValue *av; - AvailableValue **ptr; - int i; - StackedValue *stacked; - - for (i = 0; i < 428; i++) { - ptr = &opvalue[i]; - while ((av = *ptr)) { - if (av->killedregister >= valueceiling) - *ptr = av->next; - else - ptr = &av->next; - } - } - - for (stacked = stackedvalues; stacked; stacked = stacked->next) - unstackvalue(stacked); -} - -static void removecsesfromextendedbasicblock(PCodeBlock *block) { - PCLink *succ; - int counter; - State state; - - removecsesfrombasicblock(block); - while (block->successors && - !block->successors->nextLink && - block->successors->block->predecessors && - !block->successors->block->predecessors->nextLink) { - block = block->successors->block; - removecsesfrombasicblock(block); - } - - counter = 0; - for (succ = block->successors; succ; succ = succ->nextLink) { - if (!(succ->block->flags & fVisited) && succ->block->predecessors && !succ->block->predecessors->nextLink) - counter++; - } - - if (counter) { - getvaluestate(&state); - forkvaluestate(nextvaluenumber); - for (succ = block->successors; succ; succ = succ->nextLink) { - if (!(succ->block->flags & fVisited) && succ->block->predecessors && !succ->block->predecessors->nextLink) { - removecsesfromextendedbasicblock(succ->block); - regressvaluestate(); - } - } - setvaluestate(&state); - } -} - -void removecommonsubexpressions(Object *proc, int flag) { - PCodeBlock *block; - - moreaggressiveoptimization = flag; - removedcommonsubexpressions = 0; - gather_alias_info(); - allocatecsedatastructures(); - - for (block = pcbasicblocks; block; block = block->nextBlock) - block->flags &= ~fVisited; - - for (block = pcbasicblocks; block; block = block->nextBlock) { - if (!(block->flags & fVisited)) { - initializecsedatastructures(); - removecsesfromextendedbasicblock(block); - } - } - - freeoheap(); -} - diff --git a/compiler_and_linker/unsorted/VectorArraysToRegs.c b/compiler_and_linker/unsorted/VectorArraysToRegs.c deleted file mode 100644 index fde27f1..0000000 --- a/compiler_and_linker/unsorted/VectorArraysToRegs.c +++ /dev/null @@ -1,548 +0,0 @@ -#include "compiler/VectorArraysToRegs.h" -#include "compiler/CError.h" -#include "compiler/CFunc.h" -#include "compiler/BitVectors.h" -#include "compiler/CompilerTools.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" -#include "compiler/Registers.h" -#include "compiler/UseDefChains.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -typedef struct LocalVectorArray { - struct LocalVectorArray *next; - Object *object; - unsigned int invalid:1; - SInt32 arraySize; - SInt32 elementCount; - int totalUses; - int elements[1]; -} LocalVectorArray; - -typedef struct VectorPropInfo { - UInt32 *use; - UInt32 *def; - UInt32 *in; - UInt32 *out; -} VectorPropInfo; - -typedef struct ADDI { - PCode *instr; - RegUseOrDef *list; -} ADDI; - -static int number_of_ADDIs; -static ADDI *ADDIs; -static VectorPropInfo *vectorpropinfo; -static int *naddsinblock; -static int *firstaddinblock; -static Boolean converted_arrays; - -static LocalVectorArray *scanforlocalvectorarrays(void) { - SInt32 elementCount; - LocalVectorArray *head; - LocalVectorArray *array; - ObjectList *list; - int i; - SInt32 arraySize; - - head = NULL; - - for (list = locals; list; list = list->next) { - if ( - list->object && - !(IS_TYPE_POINTER(list->object->type) ? (TPTR_QUAL(list->object->type) & Q_VOLATILE) : (list->object->qual & Q_VOLATILE)) && - list->object->type && - IS_TYPE_ARRAY(list->object->type) && - IS_TYPE_VECTOR(TPTR_TARGET(list->object->type)) - ) { - arraySize = list->object->type->size; - elementCount = arraySize / 16; - if (elementCount > 0 && elementCount <= 8) { - array = oalloc(sizeof(int) * (elementCount - 1) + sizeof(LocalVectorArray)); - array->next = head; - head = array; - - array->object = list->object; - array->arraySize = arraySize; - array->elementCount = elementCount; - array->totalUses = 0; - array->invalid = 0; - - for (i = 0; i < elementCount; i++) { - array->elements[i] = 0; - } - } - } - } - - return head; -} - -static LocalVectorArray *lookup_vector_array_object(LocalVectorArray *arrays, Object *object) { - while (arrays) { - if (arrays->object == object) - return arrays; - arrays = arrays->next; - } - return NULL; -} - -static void scaninstructions(LocalVectorArray *arrays) { - PCodeBlock *block; - PCode *instr; - int counter; - int i; - PCodeArg *op; - LocalVectorArray *array; - int element; - - naddsinblock = oalloc(sizeof(int) * pcblockcount); - memclrw(naddsinblock, sizeof(int) * pcblockcount); - - firstaddinblock = oalloc(sizeof(int) * pcblockcount); - memclrw(firstaddinblock, sizeof(int) * pcblockcount); - - number_of_ADDIs = 0; - - for (block = pcbasicblocks; block; block = block->nextBlock) { - firstaddinblock[block->blockIndex] = number_of_ADDIs; - counter = 0; - for (instr = block->firstPCode; instr; instr = instr->nextPCode) { - if (!(instr->flags & fIsBranch) && instr->argCount) { - op = instr->args; - i = instr->argCount; - while (i--) { - if ( - op->kind == PCOp_MEMORY && - (PCOpMemoryArg) op->arg == PCOpMemory1 && - (array = lookup_vector_array_object(arrays, op->data.mem.obj)) && - !array->invalid - ) - { - if (instr->op != PC_ADDI) { - array->invalid = 1; - } else if (instr->args[0].data.reg.reg < n_real_registers[RegClass_GPR]) { - array->invalid = 1; - } else { - number_of_ADDIs++; - counter++; - } - - if (!array->invalid) { - element = op->data.mem.offset / 16; - if (element < array->elementCount) - array->elements[element]++; - else - array->invalid = 1; - } - } - op++; - } - } - } - naddsinblock[block->blockIndex] = counter; - } -} - -static void computeaddilist(LocalVectorArray *arrays) { - PCodeBlock *block; - PCode *instr; - RegUseOrDef *list; - ADDI *addi; - UInt32 *vec; - LocalVectorArray *array; - UseOrDef *def; - int defID; - UseOrDef *use; - int useID; - - ADDIs = oalloc(sizeof(ADDI) * number_of_ADDIs); - memclrw(ADDIs, sizeof(ADDI) * number_of_ADDIs); - - vec = oalloc(4 * ((number_of_Uses + 31) >> 5)); - - for (block = pcbasicblocks; block; block = block->nextBlock) { - if (naddsinblock[block->blockIndex]) { - bitvectorcopy(vec, usedefinfo[block->blockIndex].usevec1C, number_of_Uses); - addi = &ADDIs[firstaddinblock[block->blockIndex] + naddsinblock[block->blockIndex] - 1]; - for (instr = block->lastPCode; instr; instr = instr->prevPCode) { - if (!(instr->flags & fIsBranch) && instr->argCount) { - int reg; // r18 - if ( - instr->op == PC_ADDI && - (reg = instr->args[0].data.reg.reg) >= n_real_registers[RegClass_GPR] && - instr->args[2].kind == PCOp_MEMORY && - (PCOpMemoryArg) instr->args[2].arg == PCOpMemory1 && - (array = lookup_vector_array_object(arrays, instr->args[2].data.mem.obj)) && - !array->invalid - ) - { - addi->instr = instr; - addi->list = NULL; - for (list = reg_Uses[RegClass_GPR][reg]; list; list = list->next) { - if (bitvectorgetbit(list->id, vec)) { - RegUseOrDef *node = oalloc(sizeof(RegUseOrDef)); - node->id = list->id; - node->next = addi->list; - addi->list = node; - } - } - addi--; - } - - for (def = &Defs[defID = instr->defID]; defID < number_of_Defs && def->pcode == instr; def++, defID++) { - if (def->v.kind == PCOp_REGISTER) { - RegUseOrDef *l; - for (l = reg_Uses[def->v.arg][def->v.u.reg]; l; l = l->next) - bitvectorclearbit(l->id, vec); - } - } - - for (use = &Uses[useID = instr->useID]; useID < number_of_Uses && use->pcode == instr; use++, useID++) { - if (use->v.kind == PCOp_REGISTER) - bitvectorsetbit(useID, vec); - } - } - } - } - } -} - -static void allocatevectorpropinfo(void) { - VectorPropInfo *info; - int i; - - vectorpropinfo = oalloc(sizeof(VectorPropInfo) * pcblockcount); - for (i = 0, info = vectorpropinfo; i < pcblockcount; i++, info++) { - info->use = oalloc(4 * ((number_of_ADDIs + 31) >> 5)); - info->def = oalloc(4 * ((number_of_ADDIs + 31) >> 5)); - info->in = oalloc(4 * ((number_of_ADDIs + 31) >> 5)); - info->out = oalloc(4 * ((number_of_ADDIs + 31) >> 5)); - } -} - -static void computelocalvectorpropinfo(LocalVectorArray *arrays) { - VectorPropInfo *info; - PCodeBlock *block; - PCode *instr; - UInt32 *vec0; - UInt32 *vec4; - int index; - PCodeArg *op; - int i; - int addi_i; - ADDI *addi; - LocalVectorArray *array; - - for (block = pcbasicblocks; block; block = block->nextBlock) { - info = &vectorpropinfo[block->blockIndex]; - vec0 = info->use; - vec4 = info->def; - bitvectorinitialize(vec0, number_of_ADDIs, 0); - bitvectorinitialize(vec4, number_of_ADDIs, 0); - index = firstaddinblock[block->blockIndex]; - - for (instr = block->firstPCode; instr; instr = instr->nextPCode) { - if (!(instr->flags & fIsBranch) && instr->argCount) { - i = instr->argCount; - op = instr->args; - while (i--) { - if (op->kind == PCOp_REGISTER && op->arg == RegClass_GPR && (op->data.reg.effect & EffectWrite)) { - for (addi_i = 0, addi = ADDIs; addi_i < number_of_ADDIs; addi_i++, addi++) { - if ( - addi->instr && - addi->instr->args[0].arg == op->arg && - addi->instr->args[0].data.reg.reg == op->data.reg.reg - ) - { - if (addi->instr->block == block) - bitvectorclearbit(addi_i, vec0); - else - bitvectorsetbit(addi_i, vec4); - } - } - } - op++; - } - - if ( - instr->op == PC_ADDI && - instr->args[2].kind == PCOp_MEMORY && - (PCOpMemoryArg) instr->args[2].arg == PCOpMemory1 && - (array = lookup_vector_array_object(arrays, instr->args[2].data.mem.obj)) && - !array->invalid - ) - { - bitvectorsetbit(index, vec0); - index++; - } - } - } - } -} - -static void computeglobalvectorpropinfo(void) { - VectorPropInfo *info; - PCodeBlock *block; - UInt32 *vec0; - UInt32 *vec4; - UInt32 *vec8; - UInt32 *vecC; - int bitvecsize; - int blockIndex; - int i; - int j; - int flag; - PCLink *preds; - UInt32 val; - - bitvecsize = (number_of_ADDIs + 31) >> 5; - flag = 1; - info = &vectorpropinfo[pcbasicblocks->blockIndex]; - bitvectorinitialize(info->in, number_of_ADDIs, 0); - bitvectorcopy(info->out, info->use, number_of_ADDIs); - - for (block = pcbasicblocks->nextBlock; block; block = block->nextBlock) { - info = &vectorpropinfo[block->blockIndex]; - vecC = info->out; - vec4 = info->def; - for (i = 0; i < bitvecsize; vecC++, vec4++, i++) - *vecC = ~*vec4; - } - - while (flag) { - flag = 0; - for (blockIndex = 0; blockIndex < pcblockcount; blockIndex++) { - if (depthfirstordering[blockIndex]) { - info = &vectorpropinfo[depthfirstordering[blockIndex]->blockIndex]; - if ((preds = depthfirstordering[blockIndex]->predecessors)) { - vec8 = info->in; - bitvectorcopy(vec8, vectorpropinfo[preds->block->blockIndex].out, number_of_ADDIs); - for (preds = preds->nextLink; preds; preds = preds->nextLink) - bitvectorintersect(vec8, vectorpropinfo[preds->block->blockIndex].out, number_of_ADDIs); - } - - vecC = info->out; - vec8 = info->in; - vec0 = info->use; - vec4 = info->def; - for (j = 0; j < bitvecsize; j++) { - val = *vec0 | (*vec8 & ~*vec4); - if (val != *vecC) { - *vecC = val; - flag = 1; - } - vec8++; - vecC++; - vec4++; - vec0++; - } - } - } - } -} - -static int precedes(PCode *a, PCode *b) { - PCode *scan; - - for (scan = a->nextPCode; scan; scan = scan->nextPCode) { - if (scan == b) - return 1; - } - - return 0; -} - -static int checkvectorstoreorload(int addiID, int useID) { - PCode *addiInstr; - UseOrDef *use; - - addiInstr = ADDIs[addiID].instr; - use = Uses + useID; - if (!addiInstr) - return 0; - - if (addiInstr->args[0].data.reg.reg < n_real_registers[RegClass_GPR]) - return 0; - - if (use->pcode->op != PC_LVX && use->pcode->op != PC_STVX) - return 0; - - if ( - use->pcode->args[1].kind != PCOp_REGISTER || - use->pcode->args[1].arg != RegClass_GPR || - use->pcode->args[1].data.reg.reg != 0 - ) - return 0; - - return use->pcode->args[2].data.reg.reg == addiInstr->args[0].data.reg.reg; -} - -static int checkalluses(LocalVectorArray *arrays, int addiID) { - RegUseOrDef *list; - PCode *instr; - LocalVectorArray *array; - - instr = ADDIs[addiID].instr; - for (list = ADDIs[addiID].list; list; list = list->next) { - if (list && !checkvectorstoreorload(addiID, list->id)) { - array = lookup_vector_array_object(arrays, instr->args[2].data.mem.obj); - array->invalid = 1; - return 0; - } - } - - return 1; -} - -static void convert_array_to_register(LocalVectorArray *arrays, int addiID) { - ADDI *addi; - int newReg; - RegUseOrDef *list; - PCode *instr; - PCode *useInstr; - LocalVectorArray *array; - int element; - - addi = ADDIs + addiID; - - if (!(instr = addi->instr)) - return; - - if ( - !(array = lookup_vector_array_object(arrays, instr->args[2].data.mem.obj)) || - array->invalid - ) - return; - - element = instr->args[2].data.mem.offset / 16; - if (element > array->elementCount) - return; - - newReg = array->elements[element]; - for (list = addi->list; list; list = list->next) { - useInstr = Uses[list->id].pcode; - if (useInstr->op == PC_LVX) { - converted_arrays = 1; - change_opcode(useInstr, PC_VMR); - change_num_operands(useInstr, 2); - useInstr->args[1].kind = PCOp_REGISTER; - useInstr->args[1].arg = RegClass_VR; - useInstr->args[1].data.reg.reg = newReg; - useInstr->args[1].data.reg.effect = EffectRead; - } else if (useInstr->op == PC_STVX) { - converted_arrays = 1; - change_opcode(useInstr, PC_VMR); - change_num_operands(useInstr, 2); - useInstr->args[1] = useInstr->args[0]; - useInstr->args[0].kind = PCOp_REGISTER; - useInstr->args[0].arg = RegClass_VR; - useInstr->args[0].data.reg.reg = newReg; - useInstr->args[0].data.reg.effect = EffectWrite; - } else { - CError_FATAL(661); - } - } - deletepcode(addi->instr); -} - -static void convert_arrays_to_registers(LocalVectorArray *arrays) { - int i; - int counter; - LocalVectorArray **ptr; - LocalVectorArray *array; - - for (i = 0; i < number_of_ADDIs; i++) - checkalluses(arrays, i); - - counter = 0; - ptr = &arrays; - array = *ptr; - while (array) { - if (array->invalid) { - *ptr = array->next; - array = *ptr; - continue; - } - - counter += array->elementCount; - - for (i = 0; i < array->elementCount; i++) - array->totalUses += array->elements[i]; - - array = array->next; - } - - if (arrays) { - while (counter > 32) { - LocalVectorArray *best; - int score; - score = 0; - best = NULL; - for (array = arrays; array; array = array->next) { - if (best) { - if (array->totalUses < score) { - score = array->totalUses; - best = array; - } - } else { - best = array; - score = array->totalUses; - } - } - - if (!best) - break; - - if (best == arrays) { - arrays = best->next; - } else { - for (array = arrays; array; array = array->next) { - if (array->next == best) { - array->next = best->next; - break; - } - } - } - - counter -= best->elementCount; - } - - if (!(array = arrays)) - return; - - while (array) { - for (i = 0; i < array->elementCount; i++) - array->elements[i] = used_virtual_registers[RegClass_VR]++; - array = array->next; - } - - if (arrays) { - for (i = 0; i < number_of_ADDIs; i++) - convert_array_to_register(arrays, i); - } - } -} - -int vectorarraystoregs(void) { - LocalVectorArray *arrays; - - converted_arrays = 0; - if ((arrays = scanforlocalvectorarrays())) { - scaninstructions(arrays); - if (number_of_ADDIs > 0) { - computeusedefchains(0); - computeaddilist(arrays); - allocatevectorpropinfo(); - computelocalvectorpropinfo(arrays); - computedepthfirstordering(); - computeglobalvectorpropinfo(); - convert_arrays_to_registers(arrays); - } - } - - freeoheap(); - return converted_arrays; -} diff --git a/compiler_and_linker/unsorted/uDump.c b/compiler_and_linker/unsorted/uDump.c deleted file mode 100644 index 89574a5..0000000 --- a/compiler_and_linker/unsorted/uDump.c +++ /dev/null @@ -1,729 +0,0 @@ -#include "compiler/uDump.h" -#include "compiler/CFunc.h" -#include "compiler/CInt64.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CParser.h" -#include "compiler/Exceptions.h" -#include "compiler/Switch.h" -#include "compiler/enode.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -static FILE *outfile; - -// forward decls -static void spell(Type *type, char *buf); - -static void WritePString(FILE *file, char *str, int len) { - while (len--) { - switch (*str) { - case 0: - fputs("\\x00", file); - break; - case 7: - fputs("\\a", file); - break; - case 8: - fputs("\\b", file); - break; - case 12: - fputs("\\f", file); - break; - case 10: - fputs("\\n", file); - break; - case 13: - fputs("\\r", file); - break; - case 9: - fputs("\\t", file); - break; - case 11: - fputs("\\v", file); - break; - case '"': - case '\'': - case '?': - case '\\': - fputc('\\', file); - default: - fputc(*str, file); - break; - } - str++; - } -} - -static void WriteCString(FILE *file, char *str) { - WritePString(file, str, strlen(str)); -} - -static void StaticSetupDumpIR(void) { -} - -void SetupDumpIR(void) { - // unknown args - StaticSetupDumpIR(); -} - -void CleanupDumpIR(void) { -#ifdef CW_ENABLE_PCODE_DEBUG - // this code is not based on the original as we don't have it - if (outfile) { - fclose(outfile); - outfile = NULL; - } -#endif -} - -void DumpIR(Statement *statements, Object *func) { -#ifdef CW_ENABLE_PCODE_DEBUG - // this code is not based on the original as we don't have it - if (copts.debuglisting) { - if (!outfile) - outfile = fopen("irdump.txt", "a"); - - fputs("--- BEGIN IR DUMP ---\r", outfile); - while (statements) { - switch (statements->type) { - case ST_NOP: - fputs("ST_NOP\r", outfile); - break; - case ST_LABEL: - fputs("ST_LABEL\r", outfile); - break; - case ST_GOTO: - fputs("ST_GOTO\r", outfile); - break; - case ST_EXPRESSION: - fputs("ST_EXPRESSION\r", outfile); - DumpExpression(statements->expr, 1); - break; - case ST_SWITCH: - fputs("ST_SWITCH\r", outfile); - DumpExpression(statements->expr, 1); - break; - case ST_IFGOTO: - fputs("ST_IFGOTO\r", outfile); - DumpExpression(statements->expr, 1); - break; - case ST_IFNGOTO: - fputs("ST_IFNGOTO\r", outfile); - DumpExpression(statements->expr, 1); - break; - case ST_RETURN: - fputs("ST_RETURN\r", outfile); - if (statements->expr) - DumpExpression(statements->expr, 1); - break; - case ST_OVF: - fputs("ST_OVF\r", outfile); - break; - case ST_EXIT: - fputs("ST_EXIT\r", outfile); - break; - case ST_ENTRY: - fputs("ST_ENTRY\r", outfile); - break; - case ST_BEGINCATCH: - fputs("ST_BEGINCATCH\r", outfile); - break; - case ST_ENDCATCH: - fputs("ST_ENDCATCH\r", outfile); - break; - case ST_ENDCATCHDTOR: - fputs("ST_ENDCATCHDTOR\r", outfile); - break; - case ST_GOTOEXPR: - fputs("ST_GOTOEXPR\r", outfile); - break; - case ST_ASM: - fputs("ST_ASM\r", outfile); - break; - case ST_BEGINLOOP: - fputs("ST_BEGINLOOP\r", outfile); - break; - case ST_ENDLOOP: - fputs("ST_ENDLOOP\r", outfile); - break; - } - statements = statements->next; - } - fputs("--- END IR DUMP ---\r", outfile); - fflush(outfile); - } -#endif -} - -void DumpExpression(ENode *expr, int indent) { - static int bt; - static int i; - static char *nodenames[] = { - "EPOSTINC", - "EPOSTDEC", - "EPREINC", - "EPREDEC", - "EINDIRECT", - "EMONMIN", - "EBINNOT", - "ELOGNOT", - "EFORCELOAD", - "EMUL", - "EMULV", - "EDIV", - "EMODULO", - "EADDV", - "ESUBV", - "EADD", - "ESUB", - "ESHL", - "ESHR", - "ELESS", - "EGREATER", - "ELESSEQU", - "EGREATEREQU", - "EEQU", - "ENOTEQU", - "EAND", - "EXOR", - "EOR", - "ELAND", - "ELOR", - "EASS", - "EMULASS", - "EDIVASS", - "EMODASS", - "EADDASS", - "ESUBASS", - "ESHLASS", - "ESHRASS", - "EANDASS", - "EXORASS", - "EORASS", - "ECOMMA", - "EPMODULO", - "EROTL", - "EROTR", - "EBCLR", - "EBTST", - "EBSET", - "ETYPCON", - "EBITFIELD", - "EINTCONST", - "EFLOATCONST", - "ESTRINGCONST", - "ECOND", - "EFUNCCALL", - "EFUNCCALLP", - "EOBJREF", - "EMFPOINTER", - "ENULLCHECK", - "EPRECOMP", - "ETEMP", - "EARGOBJ", - "ELOCOBJ", - "ELABEL", - "ESETCONST", - "ENEWEXCEPTION", - "ENEWEXCEPTIONARRAY", - "EINITTRYCATCH", - "EOBJLIST", - "EMEMBER", - "ETEMPLDEP", - "EINSTRUCTION", - "EDEFINE", - "EREUSE", - "EASSBLK", - "EVECTOR128CONST", - "ECONDASS", - NULL - }; - char buf[64]; - ENodeList *list; - - while (1) { - for (i = 0; i < indent; i++) - fputc('\t', outfile); - - if (expr->flags) - fprintf(outfile, "%s {%02X}", nodenames[expr->type], expr->flags); - else - fprintf(outfile, "%s", nodenames[expr->type]); - - switch (expr->type) { - case EINTCONST: - if (expr->rtype->size > 4) { - fprintf(outfile, - "[0x%.8" PRIX32 "%.8" PRIX32 "]", - expr->data.intval.hi, expr->data.intval.lo); - } else { - fprintf(outfile, - "[%" PRId32 "]", - expr->data.intval.lo); - } - DumpType(expr->rtype); - fprintf(outfile, "\r"); - return; - - case EFLOATCONST: - CMach_PrintFloat(buf, expr->data.floatval); - fprintf(outfile, "[%s]", buf); - DumpType(expr->rtype); - fprintf(outfile, "\r"); - return; - - case ESTRINGCONST: - if (expr->data.string.ispascal) { - fputs("[\"", outfile); - WritePString(outfile, expr->data.string.data, expr->data.string.size); - fputs("\"]", outfile); - } else { - fputs("[\"", outfile); - WriteCString(outfile, expr->data.string.data); - fputs("\"]", outfile); - } - DumpType(expr->rtype); - fprintf(outfile, "\r"); - return; - - case EVECTOR128CONST: - fprintf(outfile, - "[0x%.8" PRIX32 "%.8" PRIX32 "%.8" PRIX32 "%.8" PRIX32 "]", - expr->data.vector128val.ul[0], - expr->data.vector128val.ul[1], - expr->data.vector128val.ul[2], - expr->data.vector128val.ul[3]); - DumpType(expr->rtype); - fprintf(outfile, "\r"); - return; - - case ECOND: - case ECONDASS: - DumpType(expr->rtype); - fprintf(outfile, "\r"); - DumpExpression(expr->data.cond.cond, indent + 1); - DumpExpression(expr->data.cond.expr1, indent + 1); - expr = expr->data.cond.expr2; - indent++; - break; - - case EFUNCCALL: - case EFUNCCALLP: - DumpType(expr->rtype); - fprintf(outfile, "\r"); - DumpExpression(expr->data.funccall.funcref, indent + 1); - for (list = expr->data.funccall.args; list; list = list->next) - DumpExpression(list->node, indent + 1); - return; - - case EOBJREF: - switch (expr->data.objref->datatype) { - case DFUNC: - fprintf(outfile, "[%s{PR}]", CMangler_GetLinkName(expr->data.objref)->name); - break; - case DDATA: - fprintf(outfile, "[%s{RW}]", CMangler_GetLinkName(expr->data.objref)->name); - break; - case DNONLAZYPTR: - fprintf(outfile, "[%s{NL}]", CMangler_GetLinkName(expr->data.objref)->name); - break; - default: - fprintf(outfile, "[%s]", expr->data.objref->name->name); - break; - } - DumpType(expr->rtype); - fprintf(outfile, "\r"); - return; - - ENODE_CASE_DIADIC_1: - case ELAND: - case ELOR: - ENODE_CASE_ASSIGN: - case ECOMMA: - case EPMODULO: - case EROTL: - case EROTR: - case EBTST: - DumpType(expr->rtype); - fprintf(outfile, "\r"); - DumpExpression(expr->data.diadic.left, indent + 1); - expr = expr->data.diadic.right; - indent++; - break; - - ENODE_CASE_MONADIC: - DumpType(expr->rtype); - fprintf(outfile, "\r"); - expr = expr->data.monadic; - indent++; - break; - - case EMFPOINTER: - DumpType(expr->rtype); - fprintf(outfile, "\r"); - DumpExpression(expr->data.mfpointer.accessnode, indent + 1); - expr = expr->data.mfpointer.mfpointer; - indent++; - break; - - case ENULLCHECK: - fprintf(outfile, " unique [%" PRId32 "]", expr->data.nullcheck.precompid); - DumpType(expr->rtype); - fprintf(outfile, "\r"); - DumpExpression(expr->data.nullcheck.nullcheckexpr, indent + 1); - expr = expr->data.nullcheck.condexpr; - indent++; - break; - - case EPRECOMP: - fprintf(outfile, " unique [%" PRId32 "]", expr->data.precompid); - DumpType(expr->rtype); - fprintf(outfile, "\r"); - return; - - case ELABEL: - fprintf(outfile, "[%s]", expr->data.label->uniquename->name); - DumpType(expr->rtype); - fprintf(outfile, "\r"); - return; - - case ETEMP: - DumpType(expr->data.temp.type); - fprintf(outfile, "\r"); - return; - - case EINITTRYCATCH: - DumpType(expr->rtype); - fprintf(outfile, "\r"); - if (expr->data.itc.initexpr) - DumpExpression(expr->data.itc.initexpr, indent + 1); - if (expr->data.itc.tryexpr) - DumpExpression(expr->data.itc.tryexpr, indent + 1); - if (expr->data.itc.catchexpr) - DumpExpression(expr->data.itc.catchexpr, indent + 1); - if (expr->data.itc.result) - DumpExpression(expr->data.itc.result, indent + 1); - return; - - case EDEFINE: - fprintf(outfile, "[%.8" PRIX32 "]", expr); - DumpType(expr->rtype); - fputs("\r", outfile); - expr = expr->data.monadic; - indent++; - break; - - case EREUSE: - fprintf(outfile, "[%.8" PRIX32 "]", expr->data.monadic); - DumpType(expr->rtype); - fputs("\r", outfile); - return; - - default: - return; - } - } -} - -void DumpSwitch(SwitchInfo *info) { - char buf[32]; - SwitchCase *cs; - - for (cs = info->cases; cs; cs = cs->next) { - CInt64_PrintDec(buf, cs->min); - CInt64_PrintDec(buf, cs->min); - fprintf(outfile, "\t\t%11s: %s\r", buf, cs->label->uniquename->name); - } - - fprintf(outfile, "\t\t default: %s\r", info->defaultlabel->uniquename->name); -} - -void DumpType(Type *type) { - char buf[256]; - - spell(type, buf); - fprintf(outfile, " (%s)", buf); -} - -static void spell(Type *type, char *buf) { - char mybuf[256]; - char mybuf2[256]; - - switch (type->type) { - case TYPEVOID: - strcpy(buf, "void"); - break; - case TYPEINT: - switch (TYPE_INTEGRAL(type)->integral) { - case IT_BOOL: - strcpy(buf, "bool"); - break; - case IT_CHAR: - strcpy(buf, "char"); - break; - case IT_WCHAR_T: - strcpy(buf, "wchar_t"); - break; - case IT_SCHAR: - strcpy(buf, "signed char"); - break; - case IT_UCHAR: - strcpy(buf, "unsigned char"); - break; - case IT_SHORT: - strcpy(buf, "short"); - break; - case IT_USHORT: - strcpy(buf, "unsigned short"); - break; - case IT_INT: - strcpy(buf, "int"); - break; - case IT_UINT: - strcpy(buf, "unsigned int"); - break; - case IT_LONG: - strcpy(buf, "long"); - break; - case IT_ULONG: - strcpy(buf, "unsigned long"); - break; - case IT_LONGLONG: - strcpy(buf, "long long"); - break; - case IT_ULONGLONG: - strcpy(buf, "unsigned long long"); - break; - } - break; - case TYPEFLOAT: - switch (TYPE_INTEGRAL(type)->integral) { - case IT_FLOAT: - strcpy(buf, "float"); - break; - case IT_SHORTDOUBLE: - strcpy(buf, "short double"); - break; - case IT_DOUBLE: - strcpy(buf, "double"); - break; - case IT_LONGDOUBLE: - strcpy(buf, "long double"); - break; - } - break; - case TYPEENUM: - strcpy(buf, "enum "); - if (TYPE_ENUM(type)->enumname) - strcat(buf, TYPE_ENUM(type)->enumname->name); - break; - case TYPESTRUCT: - if (IS_TYPESTRUCT_VECTOR(TYPE_STRUCT(type))) { - switch (TYPE_STRUCT(type)->stype) { - case STRUCT_VECTOR_UCHAR: - strcpy(buf, "vector unsigned char "); - break; - case STRUCT_VECTOR_SCHAR: - strcpy(buf, "vector signed char "); - break; - case STRUCT_VECTOR_BCHAR: - strcpy(buf, "vector bool char "); - break; - case STRUCT_VECTOR_USHORT: - strcpy(buf, "vector unsigned short "); - break; - case STRUCT_VECTOR_SSHORT: - strcpy(buf, "vector signed short "); - break; - case STRUCT_VECTOR_BSHORT: - strcpy(buf, "vector bool short "); - break; - case STRUCT_VECTOR_UINT: - strcpy(buf, "vector unsigned int "); - break; - case STRUCT_VECTOR_SINT: - strcpy(buf, "vector signed int "); - break; - case STRUCT_VECTOR_BINT: - strcpy(buf, "vector bool int "); - break; - case STRUCT_VECTOR_FLOAT: - strcpy(buf, "vector float "); - break; - case STRUCT_VECTOR_PIXEL: - strcpy(buf, "vector pixel "); - break; - } - } else { - strcpy(buf, "struct "); - if (TYPE_STRUCT(type)->name) - strcat(buf, TYPE_STRUCT(type)->name->name); - } - break; - case TYPECLASS: - strcpy(buf, "class "); - if (TYPE_CLASS(type)->classname) - strcat(buf, TYPE_CLASS(type)->classname->name); - break; - case TYPEFUNC: - spell(TYPE_FUNC(type)->functype, mybuf); - strcpy(buf, "freturns("); - strcat(buf, mybuf); - strcat(buf, ")"); - break; - case TYPEBITFIELD: - spell(TYPE_BITFIELD(type)->bitfieldtype, mybuf); - sprintf(buf, - "bitfield(%s){%d:%d}", - mybuf, - TYPE_BITFIELD(type)->offset, - TYPE_BITFIELD(type)->bitlength); - break; - case TYPELABEL: - strcpy(buf, "label"); - break; - case TYPEPOINTER: - spell(TPTR_TARGET(type), mybuf); - strcpy(buf, "pointer("); - strcat(buf, mybuf); - strcat(buf, ")"); - break; - case TYPEARRAY: - spell(TPTR_TARGET(type), mybuf); - strcpy(buf, "array("); - strcat(buf, mybuf); - strcat(buf, ")"); - break; - case TYPEMEMBERPOINTER: - spell(TYPE_MEMBER_POINTER(type)->ty2, mybuf); - spell(TYPE_MEMBER_POINTER(type)->ty1, mybuf2); - strcpy(buf, "memberpointer("); - strcat(buf, mybuf); - strcat(buf, ","); - strcat(buf, mybuf2); - strcat(buf, ")"); - break; - } -} - -void DumpStack(ExceptionAction *act) { - while (act) { - fprintf(outfile, "\t\t:"); - switch (act->type) { - case EAT_DESTROYLOCAL: - fprintf(outfile, - "EAT_DESTROYLOCAL %s(&%s)%s", - CMangler_GetLinkName(act->data.destroy_local.dtor)->name, - act->data.destroy_local.local->name->name, - "\r"); - break; - case EAT_DESTROYLOCALCOND: - fprintf(outfile, - "EAT_DESTROYLOCALCOND%s", - "\r"); - break; - case EAT_DESTROYLOCALOFFSET: - fprintf(outfile, - "EAT_DESTROYLOCALOFFSET %s(&%s+%" PRId32 ")%s", - CMangler_GetLinkName(act->data.destroy_local_offset.dtor)->name, - act->data.destroy_local_offset.local->name->name, - act->data.destroy_local_offset.offset, - "\r"); - break; - case EAT_DESTROYLOCALPOINTER: - fprintf(outfile, - "EAT_DESTROYLOCALPOINTER%s", - "\r"); - break; - case EAT_DESTROYLOCALARRAY: - fprintf(outfile, - "EAT_DESTROYLOCALARRAY%s", - "\r"); - break; - case EAT_DESTROYBASE: - fprintf(outfile, - "EAT_DESTROYBASE %s(this+%" PRId32 ")%s", - CMangler_GetLinkName(act->data.destroy_base.dtor)->name, - act->data.destroy_base.offset, - "\r"); - break; - case EAT_DESTROYMEMBER: - fprintf(outfile, - "EAT_DESTROYMEMBER %s(%s+%" PRId32 ")%s", - CMangler_GetLinkName(act->data.destroy_member.dtor)->name, - act->data.destroy_member.objectptr->name->name, - act->data.destroy_member.offset, - "\r"); - break; - case EAT_DESTROYMEMBERCOND: - fprintf(outfile, - "EAT_DESTROYMEMBERCOND if(%s) %s(this+%" PRId32 ")%s", - act->data.destroy_member_cond.cond->name->name, - CMangler_GetLinkName(act->data.destroy_member_cond.dtor)->name, - act->data.destroy_member_cond.offset, - "\r"); - break; - case EAT_DESTROYMEMBERARRAY: - fprintf(outfile, - "EAT_DESTROYMEMBERARRAY %s(this+%" PRId32 ")[%" PRId32 "] size: %" PRId32 "%s", - CMangler_GetLinkName(act->data.destroy_member_array.dtor)->name, - act->data.destroy_member_array.offset, - act->data.destroy_member_array.elements, - act->data.destroy_member_array.element_size, - "\r"); - break; - case EAT_DELETEPOINTER: - fprintf(outfile, - "EAT_DELETEPOINTER(%s)%s", - act->data.delete_pointer.pointerobject->name->name, - "\r"); - break; - case EAT_DELETELOCALPOINTER: - fprintf(outfile, - "EAT_DELETELOCALPOINTER(%s)%s", - act->data.delete_pointer.pointerobject->name->name, - "\r"); - break; - case EAT_DELETEPOINTERCOND: - fprintf(outfile, - "EAT_DELETEPOINTERCOND if (%s)(%s)%s", - act->data.delete_pointer_cond.cond->name->name, - act->data.delete_pointer_cond.pointerobject->name->name, - "\r"); - break; - case EAT_CATCHBLOCK: - fprintf(outfile, "EAT_CATCHBLOCK "); - if (act->data.catch_block.catch_type) { - if (act->data.catch_block.catch_object) - fprintf(outfile, "[%s]", act->data.catch_block.catch_object->name->name); - else - fprintf(outfile, "[]"); - DumpType(act->data.catch_block.catch_type); - } else { - fprintf(outfile, "[...] "); - } - fprintf(outfile, - " Label: %s%s", - act->data.catch_block.catch_label->uniquename->name, - "\r"); - break; - case EAT_SPECIFICATION: - fprintf(outfile, - "EAT_SPECIFICATION%s", - "\r"); - break; - case EAT_ACTIVECATCHBLOCK: - fprintf(outfile, - "EAT_ACTIVECATCHBLOCK%s", - "\r"); - break; - case EAT_TERMINATE: - fprintf(outfile, - "EAT_TERMINATE%s", - "\r"); - break; - } - act = act->prev; - } -} -- cgit v1.2.3