Merge pull request #16688 from MathiasVP/flow-through-builtin-bit-cast

C++: Fix IR generation for builtins and add flow through `__builtin_bit_cast`
This commit is contained in:
Mathias Vorreiter Pedersen
2024-06-06 13:28:41 +01:00
committed by GitHub
8 changed files with 89 additions and 6 deletions

View File

@@ -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

View File

@@ -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())
)
@@ -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())
)
}
@@ -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()
)
}

View File

@@ -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
}

View File

@@ -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 |

View File

@@ -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>:

View File

@@ -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

View File

@@ -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

View File

@@ -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