Skip to content

Commit f319381

Browse files
committed
C++: Support the spaceship operator in the IR
1 parent 9b8302f commit f319381

File tree

12 files changed

+110
-62
lines changed

12 files changed

+110
-62
lines changed

cpp/ql/lib/semmle/code/cpp/ir/implementation/Opcode.qll

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ private newtype TOpcode =
4242
TCompareGT() or
4343
TCompareLE() or
4444
TCompareGE() or
45+
TSpaceship() or
4546
TPointerAdd() or
4647
TPointerSub() or
4748
TPointerDiff() or
@@ -765,6 +766,15 @@ module Opcode {
765766
final override string toString() { result = "CompareGE" }
766767
}
767768

769+
/**
770+
* The `Opcode` for a `SpaceshipInstruction`.
771+
*
772+
* See the `SpaceshipInstruction` documentation for more details.
773+
*/
774+
class Spaceship extends BinaryOpcode, TSpaceship {
775+
final override string toString() { result = "Spaceship" }
776+
}
777+
768778
/**
769779
* The `Opcode` for a `PointerAddInstruction`.
770780
*

cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,6 +1604,13 @@ class CompareGEInstruction extends RelationalInstruction {
16041604
override predicate isStrict() { none() }
16051605
}
16061606

1607+
/**
1608+
* An instruction that represents a three-way comparison operator.
1609+
*/
1610+
class CompareThreeWayInstruction extends BinaryInstruction {
1611+
CompareThreeWayInstruction() { this.getOpcode() instanceof Opcode::Spaceship }
1612+
}
1613+
16071614
/**
16081615
* An instruction that branches to one of multiple successor instructions based on the value of an
16091616
* integer operand.

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,6 +1604,13 @@ class CompareGEInstruction extends RelationalInstruction {
16041604
override predicate isStrict() { none() }
16051605
}
16061606

1607+
/**
1608+
* An instruction that represents a three-way comparison operator.
1609+
*/
1610+
class CompareThreeWayInstruction extends BinaryInstruction {
1611+
CompareThreeWayInstruction() { this.getOpcode() instanceof Opcode::Spaceship }
1612+
}
1613+
16071614
/**
16081615
* An instruction that branches to one of multiple successor instructions based on the value of an
16091616
* integer operand.

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1808,6 +1808,11 @@ private Opcode comparisonOpcode(ComparisonOperation expr) {
18081808
expr instanceof GEExpr and result instanceof Opcode::CompareGE
18091809
}
18101810

1811+
private Opcode spaceShipOpcode(SpaceshipExpr expr) {
1812+
exists(expr) and
1813+
result instanceof Opcode::Spaceship
1814+
}
1815+
18111816
/**
18121817
* IR translation of a simple binary operation.
18131818
*/
@@ -1867,7 +1872,8 @@ class TranslatedBinaryOperation extends TranslatedSingleInstructionExpr {
18671872
override Opcode getOpcode() {
18681873
result = binaryArithmeticOpcode(expr) or
18691874
result = binaryBitwiseOpcode(expr) or
1870-
result = comparisonOpcode(expr)
1875+
result = comparisonOpcode(expr) or
1876+
result = spaceShipOpcode(expr)
18711877
}
18721878

18731879
override Type getExprType() {

cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,6 +1604,13 @@ class CompareGEInstruction extends RelationalInstruction {
16041604
override predicate isStrict() { none() }
16051605
}
16061606

1607+
/**
1608+
* An instruction that represents a three-way comparison operator.
1609+
*/
1610+
class CompareThreeWayInstruction extends BinaryInstruction {
1611+
CompareThreeWayInstruction() { this.getOpcode() instanceof Opcode::Spaceship }
1612+
}
1613+
16071614
/**
16081615
* An instruction that branches to one of multiple successor instructions based on the value of an
16091616
* integer operand.

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

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20336,26 +20336,55 @@ ir.cpp:
2033620336
# 2766| r2766_20(glval<ThreeWay>) = CopyValue : r2766_19
2033720337
# 2766| r2766_21(glval<int>) = FieldAddress[x] : r2766_20
2033820338
# 2766| r2766_22(int) = Load[?] : &:r2766_21, ~m2766_12
20339+
# 2766| r2766_23(strong_ordering) = Spaceship : r2766_17, r2766_22
20340+
# 2766| m2766_24(strong_ordering) = Store[#return] : &:r2766_13, r2766_23
20341+
# 2766| v2766_25(void) = ReturnIndirection[#this] : &:r2766_7, m2766_8
20342+
# 2766| v2766_26(void) = ReturnIndirection[y] : &:r2766_11, m2766_12
20343+
# 2766| r2766_27(glval<strong_ordering>) = VariableAddress[#return] :
20344+
# 2766| v2766_28(void) = ReturnValue : &:r2766_27, m2766_24
20345+
# 2766| v2766_29(void) = AliasedUse : m2766_3
20346+
# 2766| v2766_30(void) = ExitFunction :
2033920347

2034020348
# 2769| void test_three_way(int, int, ThreeWay, ThreeWay)
2034120349
# 2769| Block 0
20342-
# 2769| v2769_1(void) = EnterFunction :
20343-
# 2769| m2769_2(unknown) = AliasedDefinition :
20344-
# 2769| m2769_3(unknown) = InitializeNonLocal :
20345-
# 2769| m2769_4(unknown) = Chi : total:m2769_2, partial:m2769_3
20346-
# 2769| r2769_5(glval<int>) = VariableAddress[a] :
20347-
# 2769| m2769_6(int) = InitializeParameter[a] : &:r2769_5
20348-
# 2769| r2769_7(glval<int>) = VariableAddress[b] :
20349-
# 2769| m2769_8(int) = InitializeParameter[b] : &:r2769_7
20350-
# 2769| r2769_9(glval<ThreeWay>) = VariableAddress[c] :
20351-
# 2769| m2769_10(ThreeWay) = InitializeParameter[c] : &:r2769_9
20352-
# 2769| r2769_11(glval<ThreeWay>) = VariableAddress[d] :
20353-
# 2769| m2769_12(ThreeWay) = InitializeParameter[d] : &:r2769_11
20354-
# 2770| r2770_1(glval<strong_ordering>) = VariableAddress[x] :
20355-
# 2770| r2770_2(glval<int>) = VariableAddress[a] :
20356-
# 2770| r2770_3(int) = Load[a] : &:r2770_2, m2769_6
20357-
# 2770| r2770_4(glval<int>) = VariableAddress[b] :
20358-
# 2770| r2770_5(int) = Load[b] : &:r2770_4, m2769_8
20350+
# 2769| v2769_1(void) = EnterFunction :
20351+
# 2769| m2769_2(unknown) = AliasedDefinition :
20352+
# 2769| m2769_3(unknown) = InitializeNonLocal :
20353+
# 2769| m2769_4(unknown) = Chi : total:m2769_2, partial:m2769_3
20354+
# 2769| r2769_5(glval<int>) = VariableAddress[a] :
20355+
# 2769| m2769_6(int) = InitializeParameter[a] : &:r2769_5
20356+
# 2769| r2769_7(glval<int>) = VariableAddress[b] :
20357+
# 2769| m2769_8(int) = InitializeParameter[b] : &:r2769_7
20358+
# 2769| r2769_9(glval<ThreeWay>) = VariableAddress[c] :
20359+
# 2769| m2769_10(ThreeWay) = InitializeParameter[c] : &:r2769_9
20360+
# 2769| r2769_11(glval<ThreeWay>) = VariableAddress[d] :
20361+
# 2769| m2769_12(ThreeWay) = InitializeParameter[d] : &:r2769_11
20362+
# 2770| r2770_1(glval<strong_ordering>) = VariableAddress[x] :
20363+
# 2770| r2770_2(glval<int>) = VariableAddress[a] :
20364+
# 2770| r2770_3(int) = Load[a] : &:r2770_2, m2769_6
20365+
# 2770| r2770_4(glval<int>) = VariableAddress[b] :
20366+
# 2770| r2770_5(int) = Load[b] : &:r2770_4, m2769_8
20367+
# 2770| r2770_6(strong_ordering) = Spaceship : r2770_3, r2770_5
20368+
# 2770| m2770_7(strong_ordering) = Store[x] : &:r2770_1, r2770_6
20369+
# 2771| r2771_1(glval<strong_ordering>) = VariableAddress[y] :
20370+
# 2771| r2771_2(glval<ThreeWay>) = VariableAddress[c] :
20371+
# 2771| r2771_3(glval<unknown>) = FunctionAddress[operator<=>] :
20372+
# 2771| r2771_4(glval<ThreeWay>) = VariableAddress[d] :
20373+
# 2771| r2771_5(ThreeWay &) = CopyValue : r2771_4
20374+
# 2771| r2771_6(strong_ordering) = Call[operator<=>] : func:r2771_3, this:r2771_2, 0:r2771_5
20375+
# 2771| m2771_7(unknown) = ^CallSideEffect : ~m2769_4
20376+
# 2771| m2771_8(unknown) = Chi : total:m2769_4, partial:m2771_7
20377+
# 2771| v2771_9(void) = ^IndirectReadSideEffect[-1] : &:r2771_2, m2769_10
20378+
# 2771| v2771_10(void) = ^BufferReadSideEffect[0] : &:r2771_5, ~m2769_12
20379+
# 2771| m2771_11(ThreeWay) = ^IndirectMayWriteSideEffect[-1] : &:r2771_2
20380+
# 2771| m2771_12(ThreeWay) = Chi : total:m2769_10, partial:m2771_11
20381+
# 2771| m2771_13(unknown) = ^BufferMayWriteSideEffect[0] : &:r2771_5
20382+
# 2771| m2771_14(ThreeWay) = Chi : total:m2769_12, partial:m2771_13
20383+
# 2771| m2771_15(strong_ordering) = Store[y] : &:r2771_1, r2771_6
20384+
# 2772| v2772_1(void) = NoOp :
20385+
# 2769| v2769_13(void) = ReturnVoid :
20386+
# 2769| v2769_14(void) = AliasedUse : ~m2771_8
20387+
# 2769| v2769_15(void) = ExitFunction :
2035920388

2036020389
ir23.cpp:
2036120390
# 1| bool consteval_1()

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ missingOperandType
66
duplicateChiOperand
77
sideEffectWithoutPrimary
88
instructionWithoutSuccessor
9-
| ir.cpp:2766:72:2766:72 | Load: x | Instruction 'Load: x' has no successors in function '$@'. | ir.cpp:2766:24:2766:34 | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) |
10-
| ir.cpp:2770:18:2770:18 | Load: b | Instruction 'Load: b' has no successors in function '$@'. | ir.cpp:2769:6:2769:19 | void test_three_way(int, int, ThreeWay, ThreeWay) | void test_three_way(int, int, ThreeWay, ThreeWay) |
119
ambiguousSuccessors
1210
unexplainedLoop
1311
unnecessaryPhiInstruction

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ missingOperandType
66
duplicateChiOperand
77
sideEffectWithoutPrimary
88
instructionWithoutSuccessor
9-
| ir.cpp:2766:72:2766:72 | Load: x | Instruction 'Load: x' has no successors in function '$@'. | ir.cpp:2766:24:2766:34 | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) |
10-
| ir.cpp:2770:18:2770:18 | Load: b | Instruction 'Load: b' has no successors in function '$@'. | ir.cpp:2769:6:2769:19 | void test_three_way(int, int, ThreeWay, ThreeWay) | void test_three_way(int, int, ThreeWay, ThreeWay) |
119
ambiguousSuccessors
1210
unexplainedLoop
1311
unnecessaryPhiInstruction

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

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
missingOperand
2-
| ir.cpp:2766:58:2766:72 | Store: ... <=> ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | ir.cpp:2766:24:2766:34 | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) |
3-
| ir.cpp:2770:12:2770:18 | Store: ... <=> ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | ir.cpp:2769:6:2769:19 | void test_three_way(int, int, ThreeWay, ThreeWay) | void test_three_way(int, int, ThreeWay, ThreeWay) |
42
unexpectedOperand
53
duplicateOperand
64
missingPhiOperand
75
missingOperandType
86
duplicateChiOperand
97
sideEffectWithoutPrimary
108
instructionWithoutSuccessor
11-
| ir.cpp:2766:72:2766:72 | Load: x | Instruction 'Load: x' has no successors in function '$@'. | ir.cpp:2766:24:2766:34 | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) |
12-
| ir.cpp:2770:18:2770:18 | Load: b | Instruction 'Load: b' has no successors in function '$@'. | ir.cpp:2769:6:2769:19 | void test_three_way(int, int, ThreeWay, ThreeWay) | void test_three_way(int, int, ThreeWay, ThreeWay) |
139
ambiguousSuccessors
1410
unexplainedLoop
1511
unnecessaryPhiInstruction
@@ -25,10 +21,6 @@ lostReachability
2521
backEdgeCountMismatch
2622
useNotDominatedByDefinition
2723
| ir.cpp:1535:8:1535:8 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:1535:8:1535:8 | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() |
28-
| ir.cpp:2766:24:2766:34 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | ir.cpp:2766:24:2766:34 | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) |
29-
| ir.cpp:2766:46:2766:46 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | ir.cpp:2766:24:2766:34 | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) |
30-
| ir.cpp:2766:51:2766:73 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | ir.cpp:2766:24:2766:34 | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) | std::strong_ordering ThreeWay::operator<=>(ThreeWay&) |
31-
| ir.cpp:2770:8:2770:8 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | ir.cpp:2769:6:2769:19 | void test_three_way(int, int, ThreeWay, ThreeWay) | void test_three_way(int, int, ThreeWay, ThreeWay) |
3224
switchInstructionWithoutDefaultEdge
3325
notMarkedAsConflated
3426
wronglyMarkedAsConflated

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

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18492,37 +18492,35 @@ ir.cpp:
1849218492
# 2766| r2766_19(glval<ThreeWay>) = CopyValue : r2766_18
1849318493
# 2766| r2766_20(glval<int>) = FieldAddress[x] : r2766_19
1849418494
# 2766| r2766_21(int) = Load[?] : &:r2766_20, ~m?
18495-
18496-
# 2766| Block 1
18497-
# 2766| mu2766_22(strong_ordering) = Store[#return] : &:r2766_12
18498-
# 2766| v2766_23(void) = ReturnIndirection[#this] : &:r2766_6, ~m?
18499-
# 2766| v2766_24(void) = ReturnIndirection[y] : &:r2766_10, ~m?
18500-
# 2766| r2766_25(glval<strong_ordering>) = VariableAddress[#return] :
18501-
# 2766| v2766_26(void) = ReturnValue : &:r2766_25, ~m?
18502-
# 2766| v2766_27(void) = AliasedUse : ~m?
18503-
# 2766| v2766_28(void) = ExitFunction :
18495+
# 2766| r2766_22(strong_ordering) = Spaceship : r2766_16, r2766_21
18496+
# 2766| mu2766_23(strong_ordering) = Store[#return] : &:r2766_12, r2766_22
18497+
# 2766| v2766_24(void) = ReturnIndirection[#this] : &:r2766_6, ~m?
18498+
# 2766| v2766_25(void) = ReturnIndirection[y] : &:r2766_10, ~m?
18499+
# 2766| r2766_26(glval<strong_ordering>) = VariableAddress[#return] :
18500+
# 2766| v2766_27(void) = ReturnValue : &:r2766_26, ~m?
18501+
# 2766| v2766_28(void) = AliasedUse : ~m?
18502+
# 2766| v2766_29(void) = ExitFunction :
1850418503

1850518504
# 2769| void test_three_way(int, int, ThreeWay, ThreeWay)
1850618505
# 2769| Block 0
18507-
# 2769| v2769_1(void) = EnterFunction :
18508-
# 2769| mu2769_2(unknown) = AliasedDefinition :
18509-
# 2769| mu2769_3(unknown) = InitializeNonLocal :
18510-
# 2769| r2769_4(glval<int>) = VariableAddress[a] :
18511-
# 2769| mu2769_5(int) = InitializeParameter[a] : &:r2769_4
18512-
# 2769| r2769_6(glval<int>) = VariableAddress[b] :
18513-
# 2769| mu2769_7(int) = InitializeParameter[b] : &:r2769_6
18514-
# 2769| r2769_8(glval<ThreeWay>) = VariableAddress[c] :
18515-
# 2769| mu2769_9(ThreeWay) = InitializeParameter[c] : &:r2769_8
18516-
# 2769| r2769_10(glval<ThreeWay>) = VariableAddress[d] :
18517-
# 2769| mu2769_11(ThreeWay) = InitializeParameter[d] : &:r2769_10
18518-
# 2770| r2770_1(glval<strong_ordering>) = VariableAddress[x] :
18519-
# 2770| r2770_2(glval<int>) = VariableAddress[a] :
18520-
# 2770| r2770_3(int) = Load[a] : &:r2770_2, ~m?
18521-
# 2770| r2770_4(glval<int>) = VariableAddress[b] :
18522-
# 2770| r2770_5(int) = Load[b] : &:r2770_4, ~m?
18523-
18524-
# 2770| Block 1
18525-
# 2770| mu2770_6(strong_ordering) = Store[x] : &:r2770_1
18506+
# 2769| v2769_1(void) = EnterFunction :
18507+
# 2769| mu2769_2(unknown) = AliasedDefinition :
18508+
# 2769| mu2769_3(unknown) = InitializeNonLocal :
18509+
# 2769| r2769_4(glval<int>) = VariableAddress[a] :
18510+
# 2769| mu2769_5(int) = InitializeParameter[a] : &:r2769_4
18511+
# 2769| r2769_6(glval<int>) = VariableAddress[b] :
18512+
# 2769| mu2769_7(int) = InitializeParameter[b] : &:r2769_6
18513+
# 2769| r2769_8(glval<ThreeWay>) = VariableAddress[c] :
18514+
# 2769| mu2769_9(ThreeWay) = InitializeParameter[c] : &:r2769_8
18515+
# 2769| r2769_10(glval<ThreeWay>) = VariableAddress[d] :
18516+
# 2769| mu2769_11(ThreeWay) = InitializeParameter[d] : &:r2769_10
18517+
# 2770| r2770_1(glval<strong_ordering>) = VariableAddress[x] :
18518+
# 2770| r2770_2(glval<int>) = VariableAddress[a] :
18519+
# 2770| r2770_3(int) = Load[a] : &:r2770_2, ~m?
18520+
# 2770| r2770_4(glval<int>) = VariableAddress[b] :
18521+
# 2770| r2770_5(int) = Load[b] : &:r2770_4, ~m?
18522+
# 2770| r2770_6(strong_ordering) = Spaceship : r2770_3, r2770_5
18523+
# 2770| mu2770_7(strong_ordering) = Store[x] : &:r2770_1, r2770_6
1852618524
# 2771| r2771_1(glval<strong_ordering>) = VariableAddress[y] :
1852718525
# 2771| r2771_2(glval<ThreeWay>) = VariableAddress[c] :
1852818526
# 2771| r2771_3(glval<unknown>) = FunctionAddress[operator<=>] :

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy