Skip to content

Commit 5d997c7

Browse files
C++: Big QLDoc comment for ChiInstruction
1 parent 53cd5e9 commit 5d997c7

File tree

3 files changed

+195
-6
lines changed

3 files changed

+195
-6
lines changed

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

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,6 +1345,16 @@ class UnmodeledUseInstruction extends Instruction {
13451345
}
13461346
}
13471347

1348+
/**
1349+
* An instruction representing the choice of one of multiple input values based on control flow.
1350+
*
1351+
* A `PhiInstruction` is inserted at the beginning of a block whenever two different definitions of
1352+
* the same variable reach that block. The `PhiInstruction` will have one operand corresponding to
1353+
* each control flow predecessor of the block, with that operand representing the version of the
1354+
* variable that flows from that predecessor. The result value of the `PhiInstruction` will be
1355+
* a copy of whichever operand corresponds to the actual predecessor that entered the block at
1356+
* runtime.
1357+
*/
13481358
class PhiInstruction extends Instruction {
13491359
PhiInstruction() {
13501360
opcode instanceof Opcode::Phi
@@ -1356,8 +1366,46 @@ class PhiInstruction extends Instruction {
13561366
}
13571367

13581368
/**
1359-
* An instruction representing the write to a piece of memory resulting from a write to a subset
1360-
* of that memory.
1369+
* An instruction representing the effect that a write to a memory may have on potential aliases of
1370+
* that memory.
1371+
*
1372+
* A `ChiInstruction` is inserted immediately after an instruction that writes to memory. The
1373+
* `ChiInstruction` has two operands. The first operand, given by `getTotalOperand()`, represents
1374+
* the previous state of all of the memory that might be alised by the memory write. The second
1375+
* operand, given by `getPartialOperand()`, represents the memory that was actually modified by the
1376+
* memory write. The result of the `ChiInstruction` represents the same memory as
1377+
* `getTotalOperand()`, updated to include the changes due to the value that was actually stored by
1378+
* the memory write.
1379+
*
1380+
* As an example, suppose that variable `p` and `q` are pointers that may or may not point to the
1381+
* same memory:
1382+
* ```
1383+
* *p = 5;
1384+
* x = *q;
1385+
* ```
1386+
*
1387+
* The IR would look like:
1388+
* ```
1389+
* r1_1 = VariableAddress[p]
1390+
* r1_2 = Load r1_1, m0_0 // Load the value of `p`
1391+
* r1_3 = Constant[5]
1392+
* m1_4 = Store r1_2, r1_3 // Store to `*p`
1393+
* m1_5 = ^Chi m0_1, m1_4 // Side effect of the previous Store on aliased memory
1394+
* r1_6 = VariableAddress[x]
1395+
* r1_7 = VariableAddress[q]
1396+
* r1_8 = Load r1_7, m0_2 // Load the value of `q`
1397+
* r1_9 = Load r1_8, m1_5 // Load the value of `*q`
1398+
* m1_10 = Store r1_6, r1_9 // Store to x
1399+
* ```
1400+
*
1401+
* Note the `Chi` instruction after the store to `*p`. The indicates that the previous contents of
1402+
* aliased memory (`m0_1`) are merged with the new value written by the store (`m1_4`), producing a
1403+
* new version of aliased memory (`m1_5`). On the subsequent load from `*q`, the source operand of
1404+
* `*q` is `m1_5`, indicating that the store to `*p` may (or may not) have updated the memory
1405+
* pointed to by `q`.
1406+
*
1407+
* For more information about how `Chi` instructions are used to model memory side effects, see
1408+
* https://link.springer.com/content/pdf/10.1007%2F3-540-61053-7_66.pdf.
13611409
*/
13621410
class ChiInstruction extends Instruction {
13631411
ChiInstruction() {
@@ -1367,6 +1415,21 @@ class ChiInstruction extends Instruction {
13671415
override final MemoryAccessKind getResultMemoryAccess() {
13681416
result instanceof ChiTotalMemoryAccess
13691417
}
1418+
1419+
/**
1420+
* Gets the operand that represents the previous state of all memory that might be aliased by the
1421+
* memory write.
1422+
*/
1423+
final Instruction getTotalOperand() {
1424+
result = getAnOperand().(ChiTotalOperand).getDefinitionInstruction()
1425+
}
1426+
1427+
/**
1428+
* Gets the operand that represents the new value written by the memory write.
1429+
*/
1430+
final Instruction getPartialOperand() {
1431+
result = getAnOperand().(ChiPartialOperand).getDefinitionInstruction()
1432+
}
13701433
}
13711434

13721435
/**

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

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,6 +1345,16 @@ class UnmodeledUseInstruction extends Instruction {
13451345
}
13461346
}
13471347

1348+
/**
1349+
* An instruction representing the choice of one of multiple input values based on control flow.
1350+
*
1351+
* A `PhiInstruction` is inserted at the beginning of a block whenever two different definitions of
1352+
* the same variable reach that block. The `PhiInstruction` will have one operand corresponding to
1353+
* each control flow predecessor of the block, with that operand representing the version of the
1354+
* variable that flows from that predecessor. The result value of the `PhiInstruction` will be
1355+
* a copy of whichever operand corresponds to the actual predecessor that entered the block at
1356+
* runtime.
1357+
*/
13481358
class PhiInstruction extends Instruction {
13491359
PhiInstruction() {
13501360
opcode instanceof Opcode::Phi
@@ -1356,8 +1366,46 @@ class PhiInstruction extends Instruction {
13561366
}
13571367

13581368
/**
1359-
* An instruction representing the write to a piece of memory resulting from a write to a subset
1360-
* of that memory.
1369+
* An instruction representing the effect that a write to a memory may have on potential aliases of
1370+
* that memory.
1371+
*
1372+
* A `ChiInstruction` is inserted immediately after an instruction that writes to memory. The
1373+
* `ChiInstruction` has two operands. The first operand, given by `getTotalOperand()`, represents
1374+
* the previous state of all of the memory that might be alised by the memory write. The second
1375+
* operand, given by `getPartialOperand()`, represents the memory that was actually modified by the
1376+
* memory write. The result of the `ChiInstruction` represents the same memory as
1377+
* `getTotalOperand()`, updated to include the changes due to the value that was actually stored by
1378+
* the memory write.
1379+
*
1380+
* As an example, suppose that variable `p` and `q` are pointers that may or may not point to the
1381+
* same memory:
1382+
* ```
1383+
* *p = 5;
1384+
* x = *q;
1385+
* ```
1386+
*
1387+
* The IR would look like:
1388+
* ```
1389+
* r1_1 = VariableAddress[p]
1390+
* r1_2 = Load r1_1, m0_0 // Load the value of `p`
1391+
* r1_3 = Constant[5]
1392+
* m1_4 = Store r1_2, r1_3 // Store to `*p`
1393+
* m1_5 = ^Chi m0_1, m1_4 // Side effect of the previous Store on aliased memory
1394+
* r1_6 = VariableAddress[x]
1395+
* r1_7 = VariableAddress[q]
1396+
* r1_8 = Load r1_7, m0_2 // Load the value of `q`
1397+
* r1_9 = Load r1_8, m1_5 // Load the value of `*q`
1398+
* m1_10 = Store r1_6, r1_9 // Store to x
1399+
* ```
1400+
*
1401+
* Note the `Chi` instruction after the store to `*p`. The indicates that the previous contents of
1402+
* aliased memory (`m0_1`) are merged with the new value written by the store (`m1_4`), producing a
1403+
* new version of aliased memory (`m1_5`). On the subsequent load from `*q`, the source operand of
1404+
* `*q` is `m1_5`, indicating that the store to `*p` may (or may not) have updated the memory
1405+
* pointed to by `q`.
1406+
*
1407+
* For more information about how `Chi` instructions are used to model memory side effects, see
1408+
* https://link.springer.com/content/pdf/10.1007%2F3-540-61053-7_66.pdf.
13611409
*/
13621410
class ChiInstruction extends Instruction {
13631411
ChiInstruction() {
@@ -1367,6 +1415,21 @@ class ChiInstruction extends Instruction {
13671415
override final MemoryAccessKind getResultMemoryAccess() {
13681416
result instanceof ChiTotalMemoryAccess
13691417
}
1418+
1419+
/**
1420+
* Gets the operand that represents the previous state of all memory that might be aliased by the
1421+
* memory write.
1422+
*/
1423+
final Instruction getTotalOperand() {
1424+
result = getAnOperand().(ChiTotalOperand).getDefinitionInstruction()
1425+
}
1426+
1427+
/**
1428+
* Gets the operand that represents the new value written by the memory write.
1429+
*/
1430+
final Instruction getPartialOperand() {
1431+
result = getAnOperand().(ChiPartialOperand).getDefinitionInstruction()
1432+
}
13701433
}
13711434

13721435
/**

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

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,6 +1345,16 @@ class UnmodeledUseInstruction extends Instruction {
13451345
}
13461346
}
13471347

1348+
/**
1349+
* An instruction representing the choice of one of multiple input values based on control flow.
1350+
*
1351+
* A `PhiInstruction` is inserted at the beginning of a block whenever two different definitions of
1352+
* the same variable reach that block. The `PhiInstruction` will have one operand corresponding to
1353+
* each control flow predecessor of the block, with that operand representing the version of the
1354+
* variable that flows from that predecessor. The result value of the `PhiInstruction` will be
1355+
* a copy of whichever operand corresponds to the actual predecessor that entered the block at
1356+
* runtime.
1357+
*/
13481358
class PhiInstruction extends Instruction {
13491359
PhiInstruction() {
13501360
opcode instanceof Opcode::Phi
@@ -1356,8 +1366,46 @@ class PhiInstruction extends Instruction {
13561366
}
13571367

13581368
/**
1359-
* An instruction representing the write to a piece of memory resulting from a write to a subset
1360-
* of that memory.
1369+
* An instruction representing the effect that a write to a memory may have on potential aliases of
1370+
* that memory.
1371+
*
1372+
* A `ChiInstruction` is inserted immediately after an instruction that writes to memory. The
1373+
* `ChiInstruction` has two operands. The first operand, given by `getTotalOperand()`, represents
1374+
* the previous state of all of the memory that might be alised by the memory write. The second
1375+
* operand, given by `getPartialOperand()`, represents the memory that was actually modified by the
1376+
* memory write. The result of the `ChiInstruction` represents the same memory as
1377+
* `getTotalOperand()`, updated to include the changes due to the value that was actually stored by
1378+
* the memory write.
1379+
*
1380+
* As an example, suppose that variable `p` and `q` are pointers that may or may not point to the
1381+
* same memory:
1382+
* ```
1383+
* *p = 5;
1384+
* x = *q;
1385+
* ```
1386+
*
1387+
* The IR would look like:
1388+
* ```
1389+
* r1_1 = VariableAddress[p]
1390+
* r1_2 = Load r1_1, m0_0 // Load the value of `p`
1391+
* r1_3 = Constant[5]
1392+
* m1_4 = Store r1_2, r1_3 // Store to `*p`
1393+
* m1_5 = ^Chi m0_1, m1_4 // Side effect of the previous Store on aliased memory
1394+
* r1_6 = VariableAddress[x]
1395+
* r1_7 = VariableAddress[q]
1396+
* r1_8 = Load r1_7, m0_2 // Load the value of `q`
1397+
* r1_9 = Load r1_8, m1_5 // Load the value of `*q`
1398+
* m1_10 = Store r1_6, r1_9 // Store to x
1399+
* ```
1400+
*
1401+
* Note the `Chi` instruction after the store to `*p`. The indicates that the previous contents of
1402+
* aliased memory (`m0_1`) are merged with the new value written by the store (`m1_4`), producing a
1403+
* new version of aliased memory (`m1_5`). On the subsequent load from `*q`, the source operand of
1404+
* `*q` is `m1_5`, indicating that the store to `*p` may (or may not) have updated the memory
1405+
* pointed to by `q`.
1406+
*
1407+
* For more information about how `Chi` instructions are used to model memory side effects, see
1408+
* https://link.springer.com/content/pdf/10.1007%2F3-540-61053-7_66.pdf.
13611409
*/
13621410
class ChiInstruction extends Instruction {
13631411
ChiInstruction() {
@@ -1367,6 +1415,21 @@ class ChiInstruction extends Instruction {
13671415
override final MemoryAccessKind getResultMemoryAccess() {
13681416
result instanceof ChiTotalMemoryAccess
13691417
}
1418+
1419+
/**
1420+
* Gets the operand that represents the previous state of all memory that might be aliased by the
1421+
* memory write.
1422+
*/
1423+
final Instruction getTotalOperand() {
1424+
result = getAnOperand().(ChiTotalOperand).getDefinitionInstruction()
1425+
}
1426+
1427+
/**
1428+
* Gets the operand that represents the new value written by the memory write.
1429+
*/
1430+
final Instruction getPartialOperand() {
1431+
result = getAnOperand().(ChiPartialOperand).getDefinitionInstruction()
1432+
}
13701433
}
13711434

13721435
/**

0 commit comments

Comments
 (0)