summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-ir-operator-shift-overflow.cpp
blob: 8a19da3d0fe1707b8dccb8fc786ae8845c573df8 (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
71
72
73
74
75
76
// slang-ir-operator-shift-overflow.cpp
#include "slang-ir-operator-shift-overflow.h"

#include "slang-ir-insts.h"
#include "slang-ir-layout.h"
#include "slang-ir.h"
#include "slang.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);
}

} // namespace Slang