summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-ir-operator-shift-overflow.cpp
blob: 5f829f05acbb4abdaa500ccb14d3028b41a4c160 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// slang-ir-operator-shift-overflow.cpp
#include "slang-ir-operator-shift-overflow.h"

#include "slang.h"
#include "slang-ir.h"
#include "slang-ir-insts.h"
#include "slang-ir-layout.h"

namespace Slang {

    class DiagnosticSink;
    struct IRModule;

    void checkForOperatorShiftOverflowRecursive(
        IRInst* inst,
        CompilerOptionSet& optionSet,
        DiagnosticSink* sink)
    {
        if (auto code = as<IRGlobalValueWithCode>(inst))
        {
            for (auto block : code->getBlocks())
            {
                for (auto opInst : block->getChildren())
                {
                    switch (opInst->getOp())
                    {
                    case kIROp_Lsh:
                    {
                        SLANG_ASSERT(opInst->getOperandCount() == 2);

                        IRInst* rhs = opInst->getOperand(1);
                        auto rhsLit = as<IRIntLit>(rhs);
                        if (!rhsLit)
                            continue;

                        IRInst* lhs = opInst->getOperand(0);
                        IRType* lhsType = lhs->getDataType();

                        IRSizeAndAlignment sizeAlignment;
                        if (SLANG_FAILED(getNaturalSizeAndAlignment(optionSet, lhsType, &sizeAlignment)))
                            continue;

                        IRIntegerValue shiftAmount = rhsLit->getValue();
                        if (sizeAlignment.size * 8 <= shiftAmount)
                        {
                            sink->diagnose(opInst, Diagnostics::operatorShiftLeftOverflow, lhsType, shiftAmount);
                        }
                        break;
                    }
                    }
                }
            }
        }

        for (auto childInst : inst->getChildren())
        {
            checkForOperatorShiftOverflowRecursive(childInst, optionSet, sink);
        }
    }

    void checkForOperatorShiftOverflow(
        IRModule* module,
        CompilerOptionSet& optionSet,
        DiagnosticSink* sink)
    {
        // Look for `operator<<` instructions
        checkForOperatorShiftOverflowRecursive(module->getModuleInst(), optionSet, sink);
    }

}