• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SamboyCoding / Cpp2IL / 30751767570

02 Aug 2026 02:17PM UTC coverage: 35.984% (-0.4%) from 36.382%
30751767570

push

github

SamboyCoding
Decompiler: Remove implicit null checks, resolve fields on generics, resolve generic methods which aren't in the metadata by address if we can

2857 of 9122 branches covered (31.32%)

Branch coverage included in aggregate %.

0 of 108 new or added lines in 4 files covered. (0.0%)

2 existing lines in 2 files now uncovered.

5293 of 13527 relevant lines covered (39.13%)

163430.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/Cpp2IL.Core/Analysis/NullCheckRemover.cs
1
using System.Collections.Generic;
2
using System.Linq;
3
using Cpp2IL.Core.Graphs;
4
using Cpp2IL.Core.ISIL;
5
using Cpp2IL.Core.Model.Contexts;
6

7
namespace Cpp2IL.Core.Analysis;
8

9
// Remove null checks which are explict in il2cpp but implicit in IL
10
public static class NullCheckRemover
11
{
NEW
12
    public static void Run(MethodAnalysisContext method) => Run(method.ControlFlowGraph!);
×
13

14
    public static void Run(ISILControlFlowGraph cfg)
15
    {
NEW
16
        var defOf = BuildDefMap(cfg);
×
NEW
17
        var removedAny = false;
×
18

NEW
19
        foreach (var block in cfg.Blocks)
×
20
        {
NEW
21
            if (block.BlockType != BlockType.TwoWay || block.Instructions.Count == 0)
×
22
                continue;
23

NEW
24
            var terminator = block.Instructions[^1];
×
25

NEW
26
            if (terminator.OpCode != OpCode.ConditionalJump)
×
27
                continue;
28

NEW
29
            if (terminator.Operands[0] is not Block target || !IsNullCheckThrowBlock(target))
×
30
                continue;
31

NEW
32
            if (terminator.Operands[1] is not LocalVariable condition
×
NEW
33
                || !defOf.TryGetValue(condition, out var definition)
×
NEW
34
                || definition.OpCode != OpCode.CheckEqual
×
NEW
35
                || definition.Operands[2] is not Immediate { Value: 0 })
×
36
                continue;
37

NEW
38
            terminator.OpCode = OpCode.Nop;
×
NEW
39
            terminator.SetOperands();
×
40

NEW
41
            block.Successors.Remove(target);
×
NEW
42
            target.Predecessors.Remove(block);
×
NEW
43
            block.CalculateBlockType();
×
NEW
44
            removedAny = true;
×
45
        }
46

NEW
47
        if (!removedAny)
×
NEW
48
            return;
×
49

NEW
50
        foreach (var block in cfg.Blocks.ToList())
×
51
        {
NEW
52
            if (block == cfg.EntryBlock || block.Predecessors.Count > 0 || !IsNullCheckThrowBlock(block))
×
53
                continue;
54

NEW
55
            foreach (var successor in block.Successors)
×
NEW
56
                successor.Predecessors.Remove(block);
×
57

NEW
58
            block.Successors.Clear();
×
NEW
59
            cfg.Blocks.Remove(block);
×
60
        }
61

NEW
62
        DeadCodeEliminator.Run(cfg);
×
NEW
63
    }
×
64

65
    private static bool IsNullCheckThrowBlock(Block block)
66
    {
NEW
67
        var sawThrow = false;
×
68

NEW
69
        foreach (var instruction in block.Instructions)
×
70
        {
NEW
71
            switch (instruction.OpCode)
×
72
            {
73
                case OpCode.Nop:
NEW
74
                case OpCode.Return when sawThrow:
×
75
                    continue;
76

NEW
77
                case OpCode.Throw when instruction.Operands is [TypeAnalysisContext { FullName: "System.NullReferenceException" }]:
×
NEW
78
                    sawThrow = true;
×
NEW
79
                    continue;
×
80

81
                default:
NEW
82
                    return false;
×
83
            }
84
        }
85

NEW
86
        return sawThrow;
×
NEW
87
    }
×
88

89
    private static Dictionary<LocalVariable, Instruction> BuildDefMap(ISILControlFlowGraph cfg)
90
    {
NEW
91
        var defs = new Dictionary<LocalVariable, Instruction>();
×
92

NEW
93
        foreach (var instruction in cfg.Instructions)
×
NEW
94
            if (instruction.Destination is LocalVariable local)
×
NEW
95
                defs[local] = instruction;
×
96

NEW
97
        return defs;
×
98
    }
99
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc