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
|