Skip to content

Commit 314eb5d

Browse files
authored
Merge pull request github#16688 from MathiasVP/flow-through-builtin-bit-cast
C++: Fix IR generation for builtins and add flow through `__builtin_bit_cast`
2 parents 331f676 + bd9ece0 commit 314eb5d

File tree

8 files changed

+89
-6
lines changed

8 files changed

+89
-6
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ predicate conversionFlow(
114114
instrTo.(CheckedConvertOrNullInstruction).getUnaryOperand() = opFrom
115115
or
116116
instrTo.(InheritanceConversionInstruction).getUnaryOperand() = opFrom
117+
or
118+
exists(BuiltInInstruction builtIn |
119+
builtIn = instrTo and
120+
// __builtin_bit_cast
121+
builtIn.getBuiltInOperation() instanceof BuiltInBitCast and
122+
opFrom = builtIn.getAnOperand()
123+
)
117124
)
118125
or
119126
additional = true and

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3208,9 +3208,20 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
32083208

32093209
final override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) }
32103210

3211+
/**
3212+
* Gets the rnk'th (0-indexed) child for which a `TranslatedElement` exists.
3213+
*
3214+
* We use this predicate to filter out `TypeName` expressions that sometimes
3215+
* occur in builtin operations since the IR doesn't have an instruction to
3216+
* represent a reference to a type.
3217+
*/
3218+
private TranslatedElement getRankedChild(int rnk) {
3219+
result = rank[rnk + 1](int id, TranslatedElement te | te = this.getChild(id) | te order by id)
3220+
}
3221+
32113222
final override Instruction getFirstInstruction(EdgeKind kind) {
3212-
if exists(this.getChild(0))
3213-
then result = this.getChild(0).getFirstInstruction(kind)
3223+
if exists(this.getRankedChild(0))
3224+
then result = this.getRankedChild(0).getFirstInstruction(kind)
32143225
else (
32153226
kind instanceof GotoEdge and result = this.getInstruction(OnlyInstructionTag())
32163227
)
@@ -3230,11 +3241,11 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
32303241
}
32313242

32323243
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
3233-
exists(int id | child = this.getChild(id) |
3234-
result = this.getChild(id + 1).getFirstInstruction(kind)
3244+
exists(int id | child = this.getRankedChild(id) |
3245+
result = this.getRankedChild(id + 1).getFirstInstruction(kind)
32353246
or
32363247
kind instanceof GotoEdge and
3237-
not exists(this.getChild(id + 1)) and
3248+
not exists(this.getRankedChild(id + 1)) and
32383249
result = this.getInstruction(OnlyInstructionTag())
32393250
)
32403251
}
@@ -3249,7 +3260,7 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
32493260
tag = OnlyInstructionTag() and
32503261
exists(int index |
32513262
operandTag = positionalArgumentOperand(index) and
3252-
result = this.getChild(index).(TranslatedExpr).getResult()
3263+
result = this.getRankedChild(index).(TranslatedExpr).getResult()
32533264
)
32543265
}
32553266

cpp/ql/test/library-tests/dataflow/dataflow-tests/clang.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,9 @@ void following_pointers( // $ ast-def=sourceStruct1_ptr ir-def=*cleanArray1 ir-d
5252
sink(stackArray); // $ ast,ir
5353
indirect_sink(stackArray); // $ ast ir=50:25 ir=50:35 ir=51:19
5454
}
55+
56+
void test_bitcast() {
57+
unsigned long x = source();
58+
double d = __builtin_bit_cast(double, x);
59+
sink(d); // $ ir MISSING: ast
60+
}

cpp/ql/test/library-tests/dataflow/dataflow-tests/test-source-sink.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ irFlow
153153
| clang.cpp:50:25:50:30 | call to source | clang.cpp:53:17:53:26 | *stackArray |
154154
| clang.cpp:50:35:50:40 | call to source | clang.cpp:53:17:53:26 | *stackArray |
155155
| clang.cpp:51:19:51:24 | call to source | clang.cpp:53:17:53:26 | *stackArray |
156+
| clang.cpp:57:21:57:28 | call to source | clang.cpp:59:8:59:8 | d |
156157
| dispatch.cpp:9:37:9:42 | call to source | dispatch.cpp:35:16:35:25 | call to notSource1 |
157158
| dispatch.cpp:9:37:9:42 | call to source | dispatch.cpp:43:15:43:24 | call to notSource1 |
158159
| dispatch.cpp:10:37:10:42 | call to source | dispatch.cpp:36:16:36:25 | call to notSource2 |

cpp/ql/test/library-tests/ir/ir/PrintAST.expected

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22734,6 +22734,25 @@ ir.cpp:
2273422734
# 2552| Type = [Class] ClassWithDestructor
2273522735
# 2552| ValueCategory = xvalue
2273622736
# 2553| getStmt(1): [ReturnStmt] return ...
22737+
# 2555| [TopLevelFunction] void builtin_bitcast(unsigned long)
22738+
# 2555| <params>:
22739+
# 2555| getParameter(0): [Parameter] ul
22740+
# 2555| Type = [LongType] unsigned long
22741+
# 2555| getEntryPoint(): [BlockStmt] { ... }
22742+
# 2556| getStmt(0): [DeclStmt] declaration
22743+
# 2556| getDeclarationEntry(0): [VariableDeclarationEntry] definition of d
22744+
# 2556| Type = [DoubleType] double
22745+
# 2556| getVariable().getInitializer(): [Initializer] initializer for d
22746+
# 2556| getExpr(): [BuiltInBitCast] __builtin_bit_cast
22747+
# 2556| Type = [DoubleType] double
22748+
# 2556| ValueCategory = prvalue
22749+
# 2556| getChild(0): [TypeName] double
22750+
# 2556| Type = [DoubleType] double
22751+
# 2556| ValueCategory = prvalue
22752+
# 2556| getChild(1): [VariableAccess] ul
22753+
# 2556| Type = [LongType] unsigned long
22754+
# 2556| ValueCategory = prvalue(load)
22755+
# 2557| getStmt(1): [ReturnStmt] return ...
2273722756
perf-regression.cpp:
2273822757
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
2273922758
# 4| <params>:

cpp/ql/test/library-tests/ir/ir/aliased_ir.expected

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18351,6 +18351,24 @@ ir.cpp:
1835118351
# 2550| Block 2
1835218352
# 2550| v2550_10(void) = Unreached :
1835318353

18354+
# 2555| void builtin_bitcast(unsigned long)
18355+
# 2555| Block 0
18356+
# 2555| v2555_1(void) = EnterFunction :
18357+
# 2555| m2555_2(unknown) = AliasedDefinition :
18358+
# 2555| m2555_3(unknown) = InitializeNonLocal :
18359+
# 2555| m2555_4(unknown) = Chi : total:m2555_2, partial:m2555_3
18360+
# 2555| r2555_5(glval<unsigned long>) = VariableAddress[ul] :
18361+
# 2555| m2555_6(unsigned long) = InitializeParameter[ul] : &:r2555_5
18362+
# 2556| r2556_1(glval<double>) = VariableAddress[d] :
18363+
# 2556| r2556_2(glval<unsigned long>) = VariableAddress[ul] :
18364+
# 2556| r2556_3(unsigned long) = Load[ul] : &:r2556_2, m2555_6
18365+
# 2556| r2556_4(double) = BuiltIn[__builtin_bit_cast] : 0:r2556_3
18366+
# 2556| m2556_5(double) = Store[d] : &:r2556_1, r2556_4
18367+
# 2557| v2557_1(void) = NoOp :
18368+
# 2555| v2555_7(void) = ReturnVoid :
18369+
# 2555| v2555_8(void) = AliasedUse : m2555_3
18370+
# 2555| v2555_9(void) = ExitFunction :
18371+
1835418372
perf-regression.cpp:
1835518373
# 6| void Big::Big()
1835618374
# 6| Block 0

cpp/ql/test/library-tests/ir/ir/ir.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2552,4 +2552,8 @@ void constexpr_inconsistency(bool b) {
25522552
;
25532553
}
25542554

2555+
void builtin_bitcast(unsigned long ul) {
2556+
double d = __builtin_bit_cast(double, ul);
2557+
}
2558+
25552559
// semmle-extractor-options: -std=c++20 --clang

cpp/ql/test/library-tests/ir/ir/raw_ir.expected

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16693,6 +16693,23 @@ ir.cpp:
1669316693
# 2550| v2550_7(void) = AliasedUse : ~m?
1669416694
# 2550| v2550_8(void) = ExitFunction :
1669516695

16696+
# 2555| void builtin_bitcast(unsigned long)
16697+
# 2555| Block 0
16698+
# 2555| v2555_1(void) = EnterFunction :
16699+
# 2555| mu2555_2(unknown) = AliasedDefinition :
16700+
# 2555| mu2555_3(unknown) = InitializeNonLocal :
16701+
# 2555| r2555_4(glval<unsigned long>) = VariableAddress[ul] :
16702+
# 2555| mu2555_5(unsigned long) = InitializeParameter[ul] : &:r2555_4
16703+
# 2556| r2556_1(glval<double>) = VariableAddress[d] :
16704+
# 2556| r2556_2(glval<unsigned long>) = VariableAddress[ul] :
16705+
# 2556| r2556_3(unsigned long) = Load[ul] : &:r2556_2, ~m?
16706+
# 2556| r2556_4(double) = BuiltIn[__builtin_bit_cast] : 0:r2556_3
16707+
# 2556| mu2556_5(double) = Store[d] : &:r2556_1, r2556_4
16708+
# 2557| v2557_1(void) = NoOp :
16709+
# 2555| v2555_6(void) = ReturnVoid :
16710+
# 2555| v2555_7(void) = AliasedUse : ~m?
16711+
# 2555| v2555_8(void) = ExitFunction :
16712+
1669616713
perf-regression.cpp:
1669716714
# 6| void Big::Big()
1669816715
# 6| Block 0

0 commit comments

Comments
 (0)