예제 #1
0
        public override void Visit(While @while)
        {
            var expr = new ExpressionSimplifierVisitor().Visit(@while.Expr);

            if (expr is Bool b && b.Value == false)
            {
                return;
            }
            _state.ConsolidateVariables();

            _state.GoToNextLabel(out var startWhileLabel);
            _llvmGenerator.Emit($"br label %{startWhileLabel}");

            _state.DetachVarEnv();
            _state.DetachVarEnv();
            var reservedRegisters = _state.ReserveRegisterForCurrentVars(startWhileLabel);

            _state.GoToNextLabel(out var whileLabel);
            _llvmGenerator.Emit($"{whileLabel}:");
            var startLength = _llvmGenerator.GetCurrentLength();

            VisitBlock(@while.Block);

            _state.ConsolidateVariables();
            _state.RestorePreviousVarEnvWithMerge();
            _llvmGenerator.Emit($"br label %{startWhileLabel}");

            _state.CurrentLabel = startWhileLabel;
            _llvmGenerator.Emit($"{startWhileLabel}:");
            _state.RestorePreviousVarEnvWithMerge();

            _state.RemoveReservedRegisters(reservedRegisters, out var removedRegisters);
            _state.ConsolidateVariables(reservedRegisters);

            var removedRegs       = removedRegisters.ToHashSet();
            var reservedToReplace = reservedRegisters.ToList().Where(reg => removedRegs.Contains(reg.Value.Register)).ToList();

            _llvmGenerator.ReplaceRegisters(startLength, reservedToReplace.Select(res =>
                                                                                  (res.Value.Register, _state.VarToLabelToRegister[res.Key][_state.CurrentLabel].Register)).ToList());

            var exprResult    = new ExpressionGeneratorVisitor(_state).Visit(expr);
            var endWhileLabel = _state.NewLabel;

            _llvmGenerator.Emit($"br i1 {exprResult.Register}, label %{whileLabel}, label %{endWhileLabel}");

            _state.CurrentLabel = endWhileLabel;
            _llvmGenerator.Emit($"{endWhileLabel}:");
        }
 private void VisitBlockWithoutRestore(Block block)
 {
     _state.DetachVarEnv();
     block.Stmts.ToList().ForEach(Visit);
 }