Skip to content

C++: Fix IR generation for builtins and add flow through __builtin_bit_cast #16688

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ predicate conversionFlow(
instrTo.(CheckedConvertOrNullInstruction).getUnaryOperand() = opFrom
or
instrTo.(InheritanceConversionInstruction).getUnaryOperand() = opFrom
or
exists(BuiltInInstruction builtIn |
builtIn = instrTo and
// __builtin_bit_cast
builtIn.getBuiltInOperation() instanceof BuiltInBitCast and
opFrom = builtIn.getAnOperand()
)
)
or
additional = true and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3208,9 +3208,20 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {

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

/**
* Gets the rnk'th (0-indexed) child for which a `TranslatedElement` exists.
*
* We use this predicate to filter out `TypeName` expressions that sometimes
* occur in builtin operations since the IR doesn't have an instruction to
* represent a reference to a type.
*/
private TranslatedElement getRankedChild(int rnk) {
result = rank[rnk + 1](int id, TranslatedElement te | te = this.getChild(id) | te order by id)
}

final override Instruction getFirstInstruction(EdgeKind kind) {
if exists(this.getChild(0))
then result = this.getChild(0).getFirstInstruction(kind)
if exists(this.getRankedChild(0))
then result = this.getRankedChild(0).getFirstInstruction(kind)
else (
kind instanceof GotoEdge and result = this.getInstruction(OnlyInstructionTag())
)
Expand All @@ -3230,11 +3241,11 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
}

final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
exists(int id | child = this.getChild(id) |
result = this.getChild(id + 1).getFirstInstruction(kind)
exists(int id | child = this.getRankedChild(id) |
result = this.getRankedChild(id + 1).getFirstInstruction(kind)
or
kind instanceof GotoEdge and
not exists(this.getChild(id + 1)) and
not exists(this.getRankedChild(id + 1)) and
result = this.getInstruction(OnlyInstructionTag())
)
}
Expand All @@ -3249,7 +3260,7 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr {
tag = OnlyInstructionTag() and
exists(int index |
operandTag = positionalArgumentOperand(index) and
result = this.getChild(index).(TranslatedExpr).getResult()
result = this.getRankedChild(index).(TranslatedExpr).getResult()
)
}

Expand Down
6 changes: 6 additions & 0 deletions cpp/ql/test/library-tests/dataflow/dataflow-tests/clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,9 @@ void following_pointers( // $ ast-def=sourceStruct1_ptr ir-def=*cleanArray1 ir-d
sink(stackArray); // $ ast,ir
indirect_sink(stackArray); // $ ast ir=50:25 ir=50:35 ir=51:19
}

void test_bitcast() {
unsigned long x = source();
double d = __builtin_bit_cast(double, x);
sink(d); // $ ir MISSING: ast
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ irFlow
| clang.cpp:50:25:50:30 | call to source | clang.cpp:53:17:53:26 | *stackArray |
| clang.cpp:50:35:50:40 | call to source | clang.cpp:53:17:53:26 | *stackArray |
| clang.cpp:51:19:51:24 | call to source | clang.cpp:53:17:53:26 | *stackArray |
| clang.cpp:57:21:57:28 | call to source | clang.cpp:59:8:59:8 | d |
| dispatch.cpp:9:37:9:42 | call to source | dispatch.cpp:35:16:35:25 | call to notSource1 |
| dispatch.cpp:9:37:9:42 | call to source | dispatch.cpp:43:15:43:24 | call to notSource1 |
| dispatch.cpp:10:37:10:42 | call to source | dispatch.cpp:36:16:36:25 | call to notSource2 |
Expand Down
19 changes: 19 additions & 0 deletions cpp/ql/test/library-tests/ir/ir/PrintAST.expected
Original file line number Diff line number Diff line change
Expand Up @@ -22734,6 +22734,25 @@ ir.cpp:
# 2552| Type = [Class] ClassWithDestructor
# 2552| ValueCategory = xvalue
# 2553| getStmt(1): [ReturnStmt] return ...
# 2555| [TopLevelFunction] void builtin_bitcast(unsigned long)
# 2555| <params>:
# 2555| getParameter(0): [Parameter] ul
# 2555| Type = [LongType] unsigned long
# 2555| getEntryPoint(): [BlockStmt] { ... }
# 2556| getStmt(0): [DeclStmt] declaration
# 2556| getDeclarationEntry(0): [VariableDeclarationEntry] definition of d
# 2556| Type = [DoubleType] double
# 2556| getVariable().getInitializer(): [Initializer] initializer for d
# 2556| getExpr(): [BuiltInBitCast] __builtin_bit_cast
# 2556| Type = [DoubleType] double
# 2556| ValueCategory = prvalue
# 2556| getChild(0): [TypeName] double
# 2556| Type = [DoubleType] double
# 2556| ValueCategory = prvalue
# 2556| getChild(1): [VariableAccess] ul
# 2556| Type = [LongType] unsigned long
# 2556| ValueCategory = prvalue(load)
# 2557| getStmt(1): [ReturnStmt] return ...
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| <params>:
Expand Down
18 changes: 18 additions & 0 deletions cpp/ql/test/library-tests/ir/ir/aliased_ir.expected
Original file line number Diff line number Diff line change
Expand Up @@ -18351,6 +18351,24 @@ ir.cpp:
# 2550| Block 2
# 2550| v2550_10(void) = Unreached :

# 2555| void builtin_bitcast(unsigned long)
# 2555| Block 0
# 2555| v2555_1(void) = EnterFunction :
# 2555| m2555_2(unknown) = AliasedDefinition :
# 2555| m2555_3(unknown) = InitializeNonLocal :
# 2555| m2555_4(unknown) = Chi : total:m2555_2, partial:m2555_3
# 2555| r2555_5(glval<unsigned long>) = VariableAddress[ul] :
# 2555| m2555_6(unsigned long) = InitializeParameter[ul] : &:r2555_5
# 2556| r2556_1(glval<double>) = VariableAddress[d] :
# 2556| r2556_2(glval<unsigned long>) = VariableAddress[ul] :
# 2556| r2556_3(unsigned long) = Load[ul] : &:r2556_2, m2555_6
# 2556| r2556_4(double) = BuiltIn[__builtin_bit_cast] : 0:r2556_3
# 2556| m2556_5(double) = Store[d] : &:r2556_1, r2556_4
# 2557| v2557_1(void) = NoOp :
# 2555| v2555_7(void) = ReturnVoid :
# 2555| v2555_8(void) = AliasedUse : m2555_3
# 2555| v2555_9(void) = ExitFunction :

perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0
Expand Down
4 changes: 4 additions & 0 deletions cpp/ql/test/library-tests/ir/ir/ir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2552,4 +2552,8 @@ void constexpr_inconsistency(bool b) {
;
}

void builtin_bitcast(unsigned long ul) {
double d = __builtin_bit_cast(double, ul);
}

// semmle-extractor-options: -std=c++20 --clang
17 changes: 17 additions & 0 deletions cpp/ql/test/library-tests/ir/ir/raw_ir.expected
Original file line number Diff line number Diff line change
Expand Up @@ -16693,6 +16693,23 @@ ir.cpp:
# 2550| v2550_7(void) = AliasedUse : ~m?
# 2550| v2550_8(void) = ExitFunction :

# 2555| void builtin_bitcast(unsigned long)
# 2555| Block 0
# 2555| v2555_1(void) = EnterFunction :
# 2555| mu2555_2(unknown) = AliasedDefinition :
# 2555| mu2555_3(unknown) = InitializeNonLocal :
# 2555| r2555_4(glval<unsigned long>) = VariableAddress[ul] :
# 2555| mu2555_5(unsigned long) = InitializeParameter[ul] : &:r2555_4
# 2556| r2556_1(glval<double>) = VariableAddress[d] :
# 2556| r2556_2(glval<unsigned long>) = VariableAddress[ul] :
# 2556| r2556_3(unsigned long) = Load[ul] : &:r2556_2, ~m?
# 2556| r2556_4(double) = BuiltIn[__builtin_bit_cast] : 0:r2556_3
# 2556| mu2556_5(double) = Store[d] : &:r2556_1, r2556_4
# 2557| v2557_1(void) = NoOp :
# 2555| v2555_6(void) = ReturnVoid :
# 2555| v2555_7(void) = AliasedUse : ~m?
# 2555| v2555_8(void) = ExitFunction :

perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0
Expand Down
Loading