C++: Consolidate opcode properties onto Opcode class

Previously, we had several predicates on `Instruction` and `Operand` whose values were determined solely by the opcode of the instruction. For large snapshots, this meant that we would populate large tables mapping each of the millions of `Instruction`s to the appropriate value, times three (once for each IR flavor).

This change moves all of these opcode properties onto `Opcode` itself, with inline wrapper predicates on `Instruction` and `Operand` where necessary. On smaller snapshots, like ChakraCore, performance is a wash, but this did speed up Wireshark by about 4%.

Even ignoring the modest performance benefit, having these properties defined on `Opcode` seems like a better organization than having them on `Instruction` and `Operand`.
This commit is contained in:
Dave Bartolomeo
2020-01-07 13:17:27 -07:00
parent f921cf7d01
commit 9df37399f8
18 changed files with 563 additions and 829 deletions

View File

@@ -1,3 +1,7 @@
private import internal.OpcodeImports as Imports
private import internal.OperandTag
import Imports::MemoryAccessKind
private newtype TOpcode =
TNoOp() or
TUninitialized() or
@@ -84,11 +88,69 @@ private newtype TOpcode =
class Opcode extends TOpcode {
string toString() { result = "UnknownOpcode" }
/**
* Gets the kind of memory access performed by this instruction's result.
* Holds only for opcodes with a memory result.
*/
MemoryAccessKind getWriteMemoryAccess() { none() }
/**
* Gets the kind of memory access performed by this instruction's `MemoryOperand`. Holds only for
* opcodes that read from memory.
*/
MemoryAccessKind getReadMemoryAccess() { none() }
/**
* Holds if the instruction has an `AddressOperand`.
*/
predicate hasAddressOperand() { none() }
/**
* Holds if the instruction has a `BufferSizeOperand`.
*/
predicate hasBufferSizeOperand() { none() }
/**
* Holds if the instruction's write memory access is a `may` write, as opposed to a `must` write.
*/
predicate hasMayWriteMemoryAccess() { none() }
/**
* Holds if the instruction's read memory access is a `may` read, as opposed to a `must` read.
*/
predicate hasMayReadMemoryAccess() { none() }
/**
* Holds if the instruction must have an operand with the specified `OperandTag`.
*/
final predicate hasOperand(OperandTag tag) {
hasOperandInternal(tag)
or
hasAddressOperand() and tag instanceof AddressOperandTag
or
hasBufferSizeOperand() and tag instanceof BufferSizeOperandTag
}
/**
* Holds if the instruction must have an operand with the specified `OperandTag`, ignoring
* `AddressOperandTag` and `BufferSizeOperandTag`.
*/
predicate hasOperandInternal(OperandTag tag) { none() }
}
abstract class UnaryOpcode extends Opcode { }
abstract class UnaryOpcode extends Opcode {
final override predicate hasOperandInternal(OperandTag tag) {
tag instanceof UnaryOperandTag
}
}
abstract class BinaryOpcode extends Opcode { }
abstract class BinaryOpcode extends Opcode {
final override predicate hasOperandInternal(OperandTag tag) {
tag instanceof LeftOperandTag or
tag instanceof RightOperandTag
}
}
abstract class PointerArithmeticOpcode extends BinaryOpcode { }
@@ -122,55 +184,141 @@ abstract class ThrowOpcode extends Opcode { }
abstract class CatchOpcode extends Opcode { }
abstract class OpcodeWithCondition extends Opcode { }
abstract class OpcodeWithCondition extends Opcode {
final override predicate hasOperandInternal(OperandTag tag) {
tag instanceof ConditionOperandTag
}
}
abstract class BuiltInOperationOpcode extends Opcode { }
abstract class SideEffectOpcode extends Opcode { }
/**
* An opcode that accesses a single memory location via an `AddressOperand`.
*/
abstract class IndirectMemoryAccessOpcode extends Opcode {
final override predicate hasAddressOperand() { any() }
}
/**
* An opcode that writes to a single memory location via an `AddressOperand`.
*/
abstract class IndirectWriteOpcode extends IndirectMemoryAccessOpcode {
final override MemoryAccessKind getWriteMemoryAccess() { result instanceof IndirectMemoryAccess }
}
/**
* An opcode that reads from a single memory location via an `AddressOperand`.
*/
abstract class IndirectReadOpcode extends IndirectMemoryAccessOpcode {
final override MemoryAccessKind getReadMemoryAccess() { result instanceof IndirectMemoryAccess }
}
/**
* An opcode that accesses a memory buffer of unknown size.
*/
abstract class BufferAccessOpcode extends Opcode {
final override predicate hasAddressOperand() { any() }
}
/**
* An opcode that writes to a memory buffer of unknown size.
*/
abstract class BufferWriteOpcode extends BufferAccessOpcode {
final override MemoryAccessKind getWriteMemoryAccess() { result instanceof BufferMemoryAccess }
}
/**
* An opcode that reads from a memory buffer of unknown size.
*/
abstract class BufferReadOpcode extends BufferAccessOpcode {
final override MemoryAccessKind getReadMemoryAccess() { result instanceof BufferMemoryAccess }
}
/**
* An opcode that accesses a memory buffer whose size is determined by a `BufferSizeOperand`.
*/
abstract class SizedBufferAccessOpcode extends Opcode {
final override predicate hasAddressOperand() { any() }
final override predicate hasBufferSizeOperand() { any() }
}
/**
* An opcode that writes to a memory buffer whose size is determined by a `BufferSizeOperand`.
*/
abstract class SizedBufferWriteOpcode extends SizedBufferAccessOpcode {
final override MemoryAccessKind getWriteMemoryAccess() {
result instanceof BufferMemoryAccess //TODO: SizedBufferMemoryAccess
}
}
/**
* An opcode that reads from a memory buffer whose size is determined by a `BufferSizeOperand`.
*/
abstract class SizedBufferReadOpcode extends SizedBufferAccessOpcode {
final override MemoryAccessKind getReadMemoryAccess() {
result instanceof BufferMemoryAccess //TODO: SizedBufferMemoryAccess
}
}
/**
* An opcode that might write to any escaped memory location.
*/
abstract class EscapedWriteOpcode extends Opcode {
final override MemoryAccessKind getWriteMemoryAccess() { result instanceof EscapedMemoryAccess }
}
/**
* An opcode that might read from any escaped memory location.
*/
abstract class EscapedReadOpcode extends Opcode {
final override MemoryAccessKind getReadMemoryAccess() { result instanceof EscapedMemoryAccess }
}
/**
* An opcode whose write memory access is a `may` write, as opposed to a `must` write.
*/
abstract class MayWriteOpcode extends Opcode {
final override predicate hasMayWriteMemoryAccess() { any() }
}
/**
* An opcode whose read memory access is a `may` read, as opposed to a `must` read.
*/
abstract class MayReadOpcode extends Opcode {
final override predicate hasMayReadMemoryAccess() { any() }
}
/**
* An opcode that reads a value from memory.
*/
abstract class OpcodeWithLoad extends MemoryAccessOpcode { }
abstract class OpcodeWithLoad extends IndirectReadOpcode {
final override predicate hasOperandInternal(OperandTag tag) {
tag instanceof LoadOperandTag
}
}
/**
* An opcode that reads from a set of memory locations as a side effect.
*/
abstract class ReadSideEffectOpcode extends SideEffectOpcode { }
abstract class ReadSideEffectOpcode extends SideEffectOpcode {
final override predicate hasOperandInternal(OperandTag tag) {
tag instanceof SideEffectOperandTag
}
}
/**
* An opcode that writes to a set of memory locations as a side effect.
*/
abstract class WriteSideEffectOpcode extends SideEffectOpcode { }
/**
* An opcode that definitely writes to a set of memory locations as a side effect.
*/
abstract class MustWriteSideEffectOpcode extends WriteSideEffectOpcode { }
/**
* An opcode that may overwrite some, all, or none of an existing set of memory locations. Modeled
* as a read of the original contents, plus a "may" write of the new contents.
*/
abstract class MayWriteSideEffectOpcode extends WriteSideEffectOpcode { }
/**
* An opcode that accesses a buffer via an `AddressOperand`.
*/
abstract class BufferAccessOpcode extends MemoryAccessOpcode { }
/**
* An opcode that accesses a buffer via an `AddressOperand` with a `BufferSizeOperand` specifying
* the number of elements accessed.
*/
abstract class SizedBufferAccessOpcode extends BufferAccessOpcode { }
module Opcode {
class NoOp extends Opcode, TNoOp {
final override string toString() { result = "NoOp" }
}
class Uninitialized extends MemoryAccessOpcode, TUninitialized {
class Uninitialized extends IndirectWriteOpcode, TUninitialized {
final override string toString() { result = "Uninitialized" }
}
@@ -178,11 +326,11 @@ module Opcode {
final override string toString() { result = "Error" }
}
class InitializeParameter extends MemoryAccessOpcode, TInitializeParameter {
class InitializeParameter extends IndirectWriteOpcode, TInitializeParameter {
final override string toString() { result = "InitializeParameter" }
}
class InitializeIndirection extends MemoryAccessOpcode, TInitializeIndirection {
class InitializeIndirection extends IndirectWriteOpcode, TInitializeIndirection {
final override string toString() { result = "InitializeIndirection" }
}
@@ -206,8 +354,12 @@ module Opcode {
final override string toString() { result = "ReturnVoid" }
}
class ReturnIndirection extends MemoryAccessOpcode, TReturnIndirection {
class ReturnIndirection extends IndirectReadOpcode, TReturnIndirection {
final override string toString() { result = "ReturnIndirection" }
final override predicate hasOperandInternal(OperandTag tag) {
tag instanceof SideEffectOperandTag
}
}
class CopyValue extends UnaryOpcode, CopyOpcode, TCopyValue {
@@ -218,8 +370,12 @@ module Opcode {
final override string toString() { result = "Load" }
}
class Store extends CopyOpcode, MemoryAccessOpcode, TStore {
class Store extends CopyOpcode, IndirectWriteOpcode, TStore {
final override string toString() { result = "Store" }
final override predicate hasOperandInternal(OperandTag tag) {
tag instanceof StoreValueOperandTag
}
}
class Add extends BinaryArithmeticOpcode, TAdd {
@@ -372,6 +528,10 @@ module Opcode {
class Call extends Opcode, TCall {
final override string toString() { result = "Call" }
final override predicate hasOperandInternal(OperandTag tag) {
tag instanceof CallTargetOperandTag
}
}
class CatchByType extends CatchOpcode, TCatchByType {
@@ -396,22 +556,46 @@ module Opcode {
class UnmodeledDefinition extends Opcode, TUnmodeledDefinition {
final override string toString() { result = "UnmodeledDefinition" }
final override MemoryAccessKind getWriteMemoryAccess() {
result instanceof UnmodeledMemoryAccess
}
}
class UnmodeledUse extends Opcode, TUnmodeledUse {
final override string toString() { result = "UnmodeledUse" }
final override predicate hasOperandInternal(OperandTag tag) {
tag instanceof UnmodeledUseOperandTag
}
}
class AliasedDefinition extends Opcode, TAliasedDefinition {
final override string toString() { result = "AliasedDefinition" }
final override MemoryAccessKind getWriteMemoryAccess() {
result instanceof EscapedMemoryAccess
}
}
class AliasedUse extends Opcode, TAliasedUse {
final override string toString() { result = "AliasedUse" }
final override MemoryAccessKind getReadMemoryAccess() {
result instanceof NonLocalMemoryAccess
}
final override predicate hasOperandInternal(OperandTag tag) {
tag instanceof SideEffectOperandTag
}
}
class Phi extends Opcode, TPhi {
final override string toString() { result = "Phi" }
final override MemoryAccessKind getWriteMemoryAccess() {
result instanceof PhiMemoryAccess
}
}
class BuiltIn extends BuiltInOperationOpcode, TBuiltIn {
@@ -434,64 +618,81 @@ module Opcode {
final override string toString() { result = "VarArgCopy" }
}
class CallSideEffect extends MayWriteSideEffectOpcode, TCallSideEffect {
class CallSideEffect extends WriteSideEffectOpcode, EscapedWriteOpcode, MayWriteOpcode,
ReadSideEffectOpcode, EscapedReadOpcode, MayReadOpcode, TCallSideEffect {
final override string toString() { result = "CallSideEffect" }
}
class CallReadSideEffect extends ReadSideEffectOpcode, TCallReadSideEffect {
class CallReadSideEffect extends ReadSideEffectOpcode, EscapedReadOpcode, MayReadOpcode,
TCallReadSideEffect {
final override string toString() { result = "CallReadSideEffect" }
}
class IndirectReadSideEffect extends ReadSideEffectOpcode, MemoryAccessOpcode,
class IndirectReadSideEffect extends ReadSideEffectOpcode, IndirectReadOpcode,
TIndirectReadSideEffect {
final override string toString() { result = "IndirectReadSideEffect" }
}
class IndirectMustWriteSideEffect extends MustWriteSideEffectOpcode, MemoryAccessOpcode,
class IndirectMustWriteSideEffect extends WriteSideEffectOpcode, IndirectWriteOpcode,
TIndirectMustWriteSideEffect {
final override string toString() { result = "IndirectMustWriteSideEffect" }
}
class IndirectMayWriteSideEffect extends MayWriteSideEffectOpcode, MemoryAccessOpcode,
TIndirectMayWriteSideEffect {
class IndirectMayWriteSideEffect extends WriteSideEffectOpcode, IndirectWriteOpcode,
MayWriteOpcode, TIndirectMayWriteSideEffect {
final override string toString() { result = "IndirectMayWriteSideEffect" }
}
class BufferReadSideEffect extends ReadSideEffectOpcode, BufferAccessOpcode, TBufferReadSideEffect {
class BufferReadSideEffect extends ReadSideEffectOpcode, BufferReadOpcode, TBufferReadSideEffect {
final override string toString() { result = "BufferReadSideEffect" }
}
class BufferMustWriteSideEffect extends MustWriteSideEffectOpcode, BufferAccessOpcode,
class BufferMustWriteSideEffect extends WriteSideEffectOpcode, BufferWriteOpcode,
TBufferMustWriteSideEffect {
final override string toString() { result = "BufferMustWriteSideEffect" }
}
class BufferMayWriteSideEffect extends MayWriteSideEffectOpcode, BufferAccessOpcode,
class BufferMayWriteSideEffect extends WriteSideEffectOpcode, BufferWriteOpcode, MayWriteOpcode,
TBufferMayWriteSideEffect {
final override string toString() { result = "BufferMayWriteSideEffect" }
}
class SizedBufferReadSideEffect extends ReadSideEffectOpcode, SizedBufferAccessOpcode,
class SizedBufferReadSideEffect extends ReadSideEffectOpcode, SizedBufferReadOpcode,
TSizedBufferReadSideEffect {
final override string toString() { result = "SizedBufferReadSideEffect" }
}
class SizedBufferMustWriteSideEffect extends MustWriteSideEffectOpcode, SizedBufferAccessOpcode,
class SizedBufferMustWriteSideEffect extends WriteSideEffectOpcode, SizedBufferWriteOpcode,
TSizedBufferMustWriteSideEffect {
final override string toString() { result = "SizedBufferMustWriteSideEffect" }
}
class SizedBufferMayWriteSideEffect extends MayWriteSideEffectOpcode, SizedBufferAccessOpcode,
TSizedBufferMayWriteSideEffect {
class SizedBufferMayWriteSideEffect extends WriteSideEffectOpcode, SizedBufferWriteOpcode,
MayWriteOpcode, TSizedBufferMayWriteSideEffect {
final override string toString() { result = "SizedBufferMayWriteSideEffect" }
}
class Chi extends Opcode, TChi {
final override string toString() { result = "Chi" }
final override predicate hasOperandInternal(OperandTag tag) {
tag instanceof ChiTotalOperandTag
or
tag instanceof ChiPartialOperandTag
}
final override MemoryAccessKind getWriteMemoryAccess() {
result instanceof ChiTotalMemoryAccess
}
}
class InlineAsm extends Opcode, TInlineAsm {
class InlineAsm extends Opcode, EscapedWriteOpcode, MayWriteOpcode, EscapedReadOpcode,
MayReadOpcode, TInlineAsm {
final override string toString() { result = "InlineAsm" }
final override predicate hasOperandInternal(OperandTag tag) {
tag instanceof SideEffectOperandTag
}
}
class Unreached extends Opcode, TUnreached {

View File

@@ -11,60 +11,12 @@ import Imports::Opcode
private import Imports::OperandTag
module InstructionSanity {
/**
* Holds if the instruction `instr` should be expected to have an operand
* with operand tag `tag`. Only holds for singleton operand tags. Tags with
* parameters, such as `PhiInputOperand` and `PositionalArgumentOperand` are handled
* separately in `unexpectedOperand`.
*/
private predicate expectsOperand(Instruction instr, OperandTag tag) {
exists(Opcode opcode |
opcode = instr.getOpcode() and
(
opcode instanceof UnaryOpcode and tag instanceof UnaryOperandTag
or
opcode instanceof BinaryOpcode and
(
tag instanceof LeftOperandTag or
tag instanceof RightOperandTag
)
or
opcode instanceof MemoryAccessOpcode and tag instanceof AddressOperandTag
or
opcode instanceof SizedBufferAccessOpcode and tag instanceof BufferSizeOperandTag
or
opcode instanceof OpcodeWithCondition and tag instanceof ConditionOperandTag
or
opcode instanceof OpcodeWithLoad and tag instanceof LoadOperandTag
or
opcode instanceof Opcode::Store and tag instanceof StoreValueOperandTag
or
opcode instanceof Opcode::UnmodeledUse and tag instanceof UnmodeledUseOperandTag
or
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag
or
opcode instanceof Opcode::Chi and tag instanceof ChiTotalOperandTag
or
opcode instanceof Opcode::Chi and tag instanceof ChiPartialOperandTag
or
(
opcode instanceof ReadSideEffectOpcode or
opcode instanceof Opcode::InlineAsm or
opcode instanceof Opcode::CallSideEffect or
opcode instanceof Opcode::ReturnIndirection or
opcode instanceof Opcode::AliasedUse
) and
tag instanceof SideEffectOperandTag
)
)
}
/**
* Holds if instruction `instr` is missing an expected operand with tag `tag`.
*/
query predicate missingOperand(Instruction instr, string message, IRFunction func, string funcText) {
exists(OperandTag tag |
expectsOperand(instr, tag) and
instr.getOpcode().hasOperand(tag) and
not exists(NonPhiOperand operand |
operand = instr.getAnOperand() and
operand.getOperandTag() = tag
@@ -84,7 +36,7 @@ module InstructionSanity {
operand = instr.getAnOperand() and
operand.getOperandTag() = tag
) and
not expectsOperand(instr, tag) and
not instr.getOpcode().hasOperand(tag) and
not (instr instanceof CallInstruction and tag instanceof ArgumentOperandTag) and
not (
instr instanceof BuiltInOperationInstruction and tag instanceof PositionalArgumentOperandTag
@@ -549,7 +501,8 @@ class Instruction extends Construction::TInstruction {
* Gets the kind of memory access performed by this instruction's result.
* Holds only for instructions with a memory result.
*/
MemoryAccessKind getResultMemoryAccess() { none() }
pragma[inline]
final MemoryAccessKind getResultMemoryAccess() { result = getOpcode().getWriteMemoryAccess() }
/**
* Holds if the memory access performed by this instruction's result will not always write to
@@ -559,7 +512,8 @@ class Instruction extends Construction::TInstruction {
* location is a conservative estimate of the memory that might actually be accessed at runtime
* (for example, the global side effects of a function call).
*/
predicate hasResultMayMemoryAccess() { none() }
pragma[inline]
final predicate hasResultMayMemoryAccess() { getOpcode().hasMayWriteMemoryAccess() }
/**
* Gets the operand that holds the memory address to which this instruction stores its
@@ -710,16 +664,12 @@ class InitializeParameterInstruction extends VariableInstruction {
InitializeParameterInstruction() { getOpcode() instanceof Opcode::InitializeParameter }
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
}
class InitializeIndirectionInstruction extends VariableInstruction {
InitializeIndirectionInstruction() { getOpcode() instanceof Opcode::InitializeIndirection }
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
}
/**
@@ -754,8 +704,6 @@ class ErrorInstruction extends Instruction {
class UninitializedInstruction extends VariableInstruction {
UninitializedInstruction() { getOpcode() instanceof Opcode::Uninitialized }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
/**
* Gets the variable that is uninitialized.
*/
@@ -821,8 +769,6 @@ class LoadInstruction extends CopyInstruction {
class StoreInstruction extends CopyInstruction {
StoreInstruction() { getOpcode() instanceof Opcode::Store }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
final AddressOperand getDestinationAddressOperand() { result = getAnOperand() }
final Instruction getDestinationAddress() { result = getDestinationAddressOperand().getDef() }
@@ -1236,10 +1182,6 @@ class SideEffectInstruction extends Instruction {
*/
class CallSideEffectInstruction extends SideEffectInstruction {
CallSideEffectInstruction() { getOpcode() instanceof Opcode::CallSideEffect }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof EscapedMemoryAccess }
final override predicate hasResultMayMemoryAccess() { any() }
}
/**
@@ -1303,8 +1245,6 @@ class IndirectMustWriteSideEffectInstruction extends WriteSideEffectInstruction
IndirectMustWriteSideEffectInstruction() {
getOpcode() instanceof Opcode::IndirectMustWriteSideEffect
}
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
}
/**
@@ -1315,8 +1255,6 @@ class BufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction {
BufferMustWriteSideEffectInstruction() {
getOpcode() instanceof Opcode::BufferMustWriteSideEffect
}
final override MemoryAccessKind getResultMemoryAccess() { result instanceof BufferMemoryAccess }
}
/**
@@ -1328,8 +1266,6 @@ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstructi
getOpcode() instanceof Opcode::SizedBufferMustWriteSideEffect
}
final override MemoryAccessKind getResultMemoryAccess() { result instanceof BufferMemoryAccess }
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
}
@@ -1342,10 +1278,6 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
IndirectMayWriteSideEffectInstruction() {
getOpcode() instanceof Opcode::IndirectMayWriteSideEffect
}
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
final override predicate hasResultMayMemoryAccess() { any() }
}
/**
@@ -1354,10 +1286,6 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
*/
class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
BufferMayWriteSideEffectInstruction() { getOpcode() instanceof Opcode::BufferMayWriteSideEffect }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof BufferMemoryAccess }
final override predicate hasResultMayMemoryAccess() { any() }
}
/**
@@ -1369,10 +1297,6 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
getOpcode() instanceof Opcode::SizedBufferMayWriteSideEffect
}
final override MemoryAccessKind getResultMemoryAccess() { result instanceof BufferMemoryAccess }
final override predicate hasResultMayMemoryAccess() { any() }
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
}
@@ -1381,10 +1305,6 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
*/
class InlineAsmInstruction extends Instruction {
InlineAsmInstruction() { getOpcode() instanceof Opcode::InlineAsm }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof EscapedMemoryAccess }
final override predicate hasResultMayMemoryAccess() { any() }
}
/**
@@ -1470,10 +1390,6 @@ class CatchAnyInstruction extends CatchInstruction {
class UnmodeledDefinitionInstruction extends Instruction {
UnmodeledDefinitionInstruction() { getOpcode() instanceof Opcode::UnmodeledDefinition }
final override MemoryAccessKind getResultMemoryAccess() {
result instanceof UnmodeledMemoryAccess
}
}
/**
@@ -1481,8 +1397,6 @@ class UnmodeledDefinitionInstruction extends Instruction {
*/
class AliasedDefinitionInstruction extends Instruction {
AliasedDefinitionInstruction() { getOpcode() instanceof Opcode::AliasedDefinition }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof EscapedMemoryAccess }
}
/**
@@ -1511,8 +1425,6 @@ class UnmodeledUseInstruction extends Instruction {
class PhiInstruction extends Instruction {
PhiInstruction() { getOpcode() instanceof Opcode::Phi }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof PhiMemoryAccess }
/**
* Gets all of the instruction's `PhiInputOperand`s, representing the values that flow from each predecessor block.
*/
@@ -1573,8 +1485,6 @@ class PhiInstruction extends Instruction {
class ChiInstruction extends Instruction {
ChiInstruction() { getOpcode() instanceof Opcode::Chi }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof ChiTotalMemoryAccess }
/**
* Gets the operand that represents the previous state of all memory that might be aliased by the
* memory write.

View File

@@ -170,7 +170,9 @@ class MemoryOperand extends Operand {
/**
* Gets the kind of memory access performed by the operand.
*/
MemoryAccessKind getMemoryAccess() { none() }
MemoryAccessKind getMemoryAccess() {
result = getUse().getOpcode().getReadMemoryAccess()
}
/**
* Holds if the memory access performed by this operand will not always read from every bit in the
@@ -180,7 +182,9 @@ class MemoryOperand extends Operand {
* conservative estimate of the memory that might actually be accessed at runtime (for example,
* the global side effects of a function call).
*/
predicate hasMayMemoryAccess() { none() }
predicate hasMayReadMemoryAccess() {
getUse().getOpcode().hasMayReadMemoryAccess()
}
/**
* Returns the operand that holds the memory address from which the current operand loads its
@@ -274,8 +278,6 @@ class LoadOperand extends TypedOperand {
override LoadOperandTag tag;
override string toString() { result = "Load" }
final override MemoryAccessKind getMemoryAccess() { result instanceof IndirectMemoryAccess }
}
/**
@@ -331,8 +333,6 @@ class UnmodeledUseOperand extends NonPhiMemoryOperand {
override UnmodeledUseOperandTag tag;
override string toString() { result = "UnmodeledUse" }
final override MemoryAccessKind getMemoryAccess() { result instanceof UnmodeledMemoryAccess }
}
/**
@@ -382,50 +382,6 @@ class PositionalArgumentOperand extends ArgumentOperand {
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override MemoryAccessKind getMemoryAccess() {
useInstr instanceof AliasedUseInstruction and
result instanceof NonLocalMemoryAccess
or
useInstr instanceof CallSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
useInstr instanceof CallReadSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
useInstr instanceof IndirectReadSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
useInstr instanceof BufferReadSideEffectInstruction and
result instanceof BufferMemoryAccess
or
useInstr instanceof IndirectMustWriteSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
useInstr instanceof BufferMustWriteSideEffectInstruction and
result instanceof BufferMemoryAccess
or
useInstr instanceof IndirectMayWriteSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
useInstr instanceof BufferMayWriteSideEffectInstruction and
result instanceof BufferMemoryAccess
or
useInstr instanceof ReturnIndirectionInstruction and
result instanceof BufferMemoryAccess
}
final override predicate hasMayMemoryAccess() {
useInstr instanceof AliasedUseInstruction
or
useInstr instanceof CallSideEffectInstruction
or
useInstr instanceof CallReadSideEffectInstruction
or
useInstr instanceof IndirectMayWriteSideEffectInstruction
or
useInstr instanceof BufferMayWriteSideEffectInstruction
}
}
/**

View File

@@ -29,7 +29,7 @@ private predicate hasOperandMemoryAccess(
resultPointsTo(operand.getAddressOperand().getAnyDef(), var, startBitOffset) and
languageType = operand.getLanguageType() and
type = languageType.getIRType() and
(if operand.hasMayMemoryAccess() then isMayAccess = true else isMayAccess = false) and
(if operand.hasMayReadMemoryAccess() then isMayAccess = true else isMayAccess = false) and
if exists(type.getByteSize())
then endBitOffset = Ints::add(startBitOffset, Ints::mul(type.getByteSize(), 8))
else endBitOffset = Ints::unknown()
@@ -476,7 +476,7 @@ MemoryLocation getResultMemoryLocation(Instruction instr) {
MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
exists(MemoryAccessKind kind, boolean isMayAccess |
kind = operand.getMemoryAccess() and
(if operand.hasMayMemoryAccess() then isMayAccess = true else isMayAccess = false) and
(if operand.hasMayReadMemoryAccess() then isMayAccess = true else isMayAccess = false) and
(
(
kind.usesAddressOperand() and

View File

@@ -0,0 +1 @@
import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind

View File

@@ -11,60 +11,12 @@ import Imports::Opcode
private import Imports::OperandTag
module InstructionSanity {
/**
* Holds if the instruction `instr` should be expected to have an operand
* with operand tag `tag`. Only holds for singleton operand tags. Tags with
* parameters, such as `PhiInputOperand` and `PositionalArgumentOperand` are handled
* separately in `unexpectedOperand`.
*/
private predicate expectsOperand(Instruction instr, OperandTag tag) {
exists(Opcode opcode |
opcode = instr.getOpcode() and
(
opcode instanceof UnaryOpcode and tag instanceof UnaryOperandTag
or
opcode instanceof BinaryOpcode and
(
tag instanceof LeftOperandTag or
tag instanceof RightOperandTag
)
or
opcode instanceof MemoryAccessOpcode and tag instanceof AddressOperandTag
or
opcode instanceof SizedBufferAccessOpcode and tag instanceof BufferSizeOperandTag
or
opcode instanceof OpcodeWithCondition and tag instanceof ConditionOperandTag
or
opcode instanceof OpcodeWithLoad and tag instanceof LoadOperandTag
or
opcode instanceof Opcode::Store and tag instanceof StoreValueOperandTag
or
opcode instanceof Opcode::UnmodeledUse and tag instanceof UnmodeledUseOperandTag
or
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag
or
opcode instanceof Opcode::Chi and tag instanceof ChiTotalOperandTag
or
opcode instanceof Opcode::Chi and tag instanceof ChiPartialOperandTag
or
(
opcode instanceof ReadSideEffectOpcode or
opcode instanceof Opcode::InlineAsm or
opcode instanceof Opcode::CallSideEffect or
opcode instanceof Opcode::ReturnIndirection or
opcode instanceof Opcode::AliasedUse
) and
tag instanceof SideEffectOperandTag
)
)
}
/**
* Holds if instruction `instr` is missing an expected operand with tag `tag`.
*/
query predicate missingOperand(Instruction instr, string message, IRFunction func, string funcText) {
exists(OperandTag tag |
expectsOperand(instr, tag) and
instr.getOpcode().hasOperand(tag) and
not exists(NonPhiOperand operand |
operand = instr.getAnOperand() and
operand.getOperandTag() = tag
@@ -84,7 +36,7 @@ module InstructionSanity {
operand = instr.getAnOperand() and
operand.getOperandTag() = tag
) and
not expectsOperand(instr, tag) and
not instr.getOpcode().hasOperand(tag) and
not (instr instanceof CallInstruction and tag instanceof ArgumentOperandTag) and
not (
instr instanceof BuiltInOperationInstruction and tag instanceof PositionalArgumentOperandTag
@@ -549,7 +501,8 @@ class Instruction extends Construction::TInstruction {
* Gets the kind of memory access performed by this instruction's result.
* Holds only for instructions with a memory result.
*/
MemoryAccessKind getResultMemoryAccess() { none() }
pragma[inline]
final MemoryAccessKind getResultMemoryAccess() { result = getOpcode().getWriteMemoryAccess() }
/**
* Holds if the memory access performed by this instruction's result will not always write to
@@ -559,7 +512,8 @@ class Instruction extends Construction::TInstruction {
* location is a conservative estimate of the memory that might actually be accessed at runtime
* (for example, the global side effects of a function call).
*/
predicate hasResultMayMemoryAccess() { none() }
pragma[inline]
final predicate hasResultMayMemoryAccess() { getOpcode().hasMayWriteMemoryAccess() }
/**
* Gets the operand that holds the memory address to which this instruction stores its
@@ -710,16 +664,12 @@ class InitializeParameterInstruction extends VariableInstruction {
InitializeParameterInstruction() { getOpcode() instanceof Opcode::InitializeParameter }
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
}
class InitializeIndirectionInstruction extends VariableInstruction {
InitializeIndirectionInstruction() { getOpcode() instanceof Opcode::InitializeIndirection }
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
}
/**
@@ -754,8 +704,6 @@ class ErrorInstruction extends Instruction {
class UninitializedInstruction extends VariableInstruction {
UninitializedInstruction() { getOpcode() instanceof Opcode::Uninitialized }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
/**
* Gets the variable that is uninitialized.
*/
@@ -821,8 +769,6 @@ class LoadInstruction extends CopyInstruction {
class StoreInstruction extends CopyInstruction {
StoreInstruction() { getOpcode() instanceof Opcode::Store }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
final AddressOperand getDestinationAddressOperand() { result = getAnOperand() }
final Instruction getDestinationAddress() { result = getDestinationAddressOperand().getDef() }
@@ -1236,10 +1182,6 @@ class SideEffectInstruction extends Instruction {
*/
class CallSideEffectInstruction extends SideEffectInstruction {
CallSideEffectInstruction() { getOpcode() instanceof Opcode::CallSideEffect }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof EscapedMemoryAccess }
final override predicate hasResultMayMemoryAccess() { any() }
}
/**
@@ -1303,8 +1245,6 @@ class IndirectMustWriteSideEffectInstruction extends WriteSideEffectInstruction
IndirectMustWriteSideEffectInstruction() {
getOpcode() instanceof Opcode::IndirectMustWriteSideEffect
}
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
}
/**
@@ -1315,8 +1255,6 @@ class BufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction {
BufferMustWriteSideEffectInstruction() {
getOpcode() instanceof Opcode::BufferMustWriteSideEffect
}
final override MemoryAccessKind getResultMemoryAccess() { result instanceof BufferMemoryAccess }
}
/**
@@ -1328,8 +1266,6 @@ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstructi
getOpcode() instanceof Opcode::SizedBufferMustWriteSideEffect
}
final override MemoryAccessKind getResultMemoryAccess() { result instanceof BufferMemoryAccess }
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
}
@@ -1342,10 +1278,6 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
IndirectMayWriteSideEffectInstruction() {
getOpcode() instanceof Opcode::IndirectMayWriteSideEffect
}
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
final override predicate hasResultMayMemoryAccess() { any() }
}
/**
@@ -1354,10 +1286,6 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
*/
class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
BufferMayWriteSideEffectInstruction() { getOpcode() instanceof Opcode::BufferMayWriteSideEffect }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof BufferMemoryAccess }
final override predicate hasResultMayMemoryAccess() { any() }
}
/**
@@ -1369,10 +1297,6 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
getOpcode() instanceof Opcode::SizedBufferMayWriteSideEffect
}
final override MemoryAccessKind getResultMemoryAccess() { result instanceof BufferMemoryAccess }
final override predicate hasResultMayMemoryAccess() { any() }
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
}
@@ -1381,10 +1305,6 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
*/
class InlineAsmInstruction extends Instruction {
InlineAsmInstruction() { getOpcode() instanceof Opcode::InlineAsm }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof EscapedMemoryAccess }
final override predicate hasResultMayMemoryAccess() { any() }
}
/**
@@ -1470,10 +1390,6 @@ class CatchAnyInstruction extends CatchInstruction {
class UnmodeledDefinitionInstruction extends Instruction {
UnmodeledDefinitionInstruction() { getOpcode() instanceof Opcode::UnmodeledDefinition }
final override MemoryAccessKind getResultMemoryAccess() {
result instanceof UnmodeledMemoryAccess
}
}
/**
@@ -1481,8 +1397,6 @@ class UnmodeledDefinitionInstruction extends Instruction {
*/
class AliasedDefinitionInstruction extends Instruction {
AliasedDefinitionInstruction() { getOpcode() instanceof Opcode::AliasedDefinition }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof EscapedMemoryAccess }
}
/**
@@ -1511,8 +1425,6 @@ class UnmodeledUseInstruction extends Instruction {
class PhiInstruction extends Instruction {
PhiInstruction() { getOpcode() instanceof Opcode::Phi }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof PhiMemoryAccess }
/**
* Gets all of the instruction's `PhiInputOperand`s, representing the values that flow from each predecessor block.
*/
@@ -1573,8 +1485,6 @@ class PhiInstruction extends Instruction {
class ChiInstruction extends Instruction {
ChiInstruction() { getOpcode() instanceof Opcode::Chi }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof ChiTotalMemoryAccess }
/**
* Gets the operand that represents the previous state of all memory that might be aliased by the
* memory write.

View File

@@ -170,7 +170,9 @@ class MemoryOperand extends Operand {
/**
* Gets the kind of memory access performed by the operand.
*/
MemoryAccessKind getMemoryAccess() { none() }
MemoryAccessKind getMemoryAccess() {
result = getUse().getOpcode().getReadMemoryAccess()
}
/**
* Holds if the memory access performed by this operand will not always read from every bit in the
@@ -180,7 +182,9 @@ class MemoryOperand extends Operand {
* conservative estimate of the memory that might actually be accessed at runtime (for example,
* the global side effects of a function call).
*/
predicate hasMayMemoryAccess() { none() }
predicate hasMayReadMemoryAccess() {
getUse().getOpcode().hasMayReadMemoryAccess()
}
/**
* Returns the operand that holds the memory address from which the current operand loads its
@@ -274,8 +278,6 @@ class LoadOperand extends TypedOperand {
override LoadOperandTag tag;
override string toString() { result = "Load" }
final override MemoryAccessKind getMemoryAccess() { result instanceof IndirectMemoryAccess }
}
/**
@@ -331,8 +333,6 @@ class UnmodeledUseOperand extends NonPhiMemoryOperand {
override UnmodeledUseOperandTag tag;
override string toString() { result = "UnmodeledUse" }
final override MemoryAccessKind getMemoryAccess() { result instanceof UnmodeledMemoryAccess }
}
/**
@@ -382,50 +382,6 @@ class PositionalArgumentOperand extends ArgumentOperand {
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override MemoryAccessKind getMemoryAccess() {
useInstr instanceof AliasedUseInstruction and
result instanceof NonLocalMemoryAccess
or
useInstr instanceof CallSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
useInstr instanceof CallReadSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
useInstr instanceof IndirectReadSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
useInstr instanceof BufferReadSideEffectInstruction and
result instanceof BufferMemoryAccess
or
useInstr instanceof IndirectMustWriteSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
useInstr instanceof BufferMustWriteSideEffectInstruction and
result instanceof BufferMemoryAccess
or
useInstr instanceof IndirectMayWriteSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
useInstr instanceof BufferMayWriteSideEffectInstruction and
result instanceof BufferMemoryAccess
or
useInstr instanceof ReturnIndirectionInstruction and
result instanceof BufferMemoryAccess
}
final override predicate hasMayMemoryAccess() {
useInstr instanceof AliasedUseInstruction
or
useInstr instanceof CallSideEffectInstruction
or
useInstr instanceof CallReadSideEffectInstruction
or
useInstr instanceof IndirectMayWriteSideEffectInstruction
or
useInstr instanceof BufferMayWriteSideEffectInstruction
}
}
/**

View File

@@ -11,60 +11,12 @@ import Imports::Opcode
private import Imports::OperandTag
module InstructionSanity {
/**
* Holds if the instruction `instr` should be expected to have an operand
* with operand tag `tag`. Only holds for singleton operand tags. Tags with
* parameters, such as `PhiInputOperand` and `PositionalArgumentOperand` are handled
* separately in `unexpectedOperand`.
*/
private predicate expectsOperand(Instruction instr, OperandTag tag) {
exists(Opcode opcode |
opcode = instr.getOpcode() and
(
opcode instanceof UnaryOpcode and tag instanceof UnaryOperandTag
or
opcode instanceof BinaryOpcode and
(
tag instanceof LeftOperandTag or
tag instanceof RightOperandTag
)
or
opcode instanceof MemoryAccessOpcode and tag instanceof AddressOperandTag
or
opcode instanceof SizedBufferAccessOpcode and tag instanceof BufferSizeOperandTag
or
opcode instanceof OpcodeWithCondition and tag instanceof ConditionOperandTag
or
opcode instanceof OpcodeWithLoad and tag instanceof LoadOperandTag
or
opcode instanceof Opcode::Store and tag instanceof StoreValueOperandTag
or
opcode instanceof Opcode::UnmodeledUse and tag instanceof UnmodeledUseOperandTag
or
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag
or
opcode instanceof Opcode::Chi and tag instanceof ChiTotalOperandTag
or
opcode instanceof Opcode::Chi and tag instanceof ChiPartialOperandTag
or
(
opcode instanceof ReadSideEffectOpcode or
opcode instanceof Opcode::InlineAsm or
opcode instanceof Opcode::CallSideEffect or
opcode instanceof Opcode::ReturnIndirection or
opcode instanceof Opcode::AliasedUse
) and
tag instanceof SideEffectOperandTag
)
)
}
/**
* Holds if instruction `instr` is missing an expected operand with tag `tag`.
*/
query predicate missingOperand(Instruction instr, string message, IRFunction func, string funcText) {
exists(OperandTag tag |
expectsOperand(instr, tag) and
instr.getOpcode().hasOperand(tag) and
not exists(NonPhiOperand operand |
operand = instr.getAnOperand() and
operand.getOperandTag() = tag
@@ -84,7 +36,7 @@ module InstructionSanity {
operand = instr.getAnOperand() and
operand.getOperandTag() = tag
) and
not expectsOperand(instr, tag) and
not instr.getOpcode().hasOperand(tag) and
not (instr instanceof CallInstruction and tag instanceof ArgumentOperandTag) and
not (
instr instanceof BuiltInOperationInstruction and tag instanceof PositionalArgumentOperandTag
@@ -549,7 +501,8 @@ class Instruction extends Construction::TInstruction {
* Gets the kind of memory access performed by this instruction's result.
* Holds only for instructions with a memory result.
*/
MemoryAccessKind getResultMemoryAccess() { none() }
pragma[inline]
final MemoryAccessKind getResultMemoryAccess() { result = getOpcode().getWriteMemoryAccess() }
/**
* Holds if the memory access performed by this instruction's result will not always write to
@@ -559,7 +512,8 @@ class Instruction extends Construction::TInstruction {
* location is a conservative estimate of the memory that might actually be accessed at runtime
* (for example, the global side effects of a function call).
*/
predicate hasResultMayMemoryAccess() { none() }
pragma[inline]
final predicate hasResultMayMemoryAccess() { getOpcode().hasMayWriteMemoryAccess() }
/**
* Gets the operand that holds the memory address to which this instruction stores its
@@ -710,16 +664,12 @@ class InitializeParameterInstruction extends VariableInstruction {
InitializeParameterInstruction() { getOpcode() instanceof Opcode::InitializeParameter }
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
}
class InitializeIndirectionInstruction extends VariableInstruction {
InitializeIndirectionInstruction() { getOpcode() instanceof Opcode::InitializeIndirection }
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
}
/**
@@ -754,8 +704,6 @@ class ErrorInstruction extends Instruction {
class UninitializedInstruction extends VariableInstruction {
UninitializedInstruction() { getOpcode() instanceof Opcode::Uninitialized }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
/**
* Gets the variable that is uninitialized.
*/
@@ -821,8 +769,6 @@ class LoadInstruction extends CopyInstruction {
class StoreInstruction extends CopyInstruction {
StoreInstruction() { getOpcode() instanceof Opcode::Store }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
final AddressOperand getDestinationAddressOperand() { result = getAnOperand() }
final Instruction getDestinationAddress() { result = getDestinationAddressOperand().getDef() }
@@ -1236,10 +1182,6 @@ class SideEffectInstruction extends Instruction {
*/
class CallSideEffectInstruction extends SideEffectInstruction {
CallSideEffectInstruction() { getOpcode() instanceof Opcode::CallSideEffect }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof EscapedMemoryAccess }
final override predicate hasResultMayMemoryAccess() { any() }
}
/**
@@ -1303,8 +1245,6 @@ class IndirectMustWriteSideEffectInstruction extends WriteSideEffectInstruction
IndirectMustWriteSideEffectInstruction() {
getOpcode() instanceof Opcode::IndirectMustWriteSideEffect
}
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
}
/**
@@ -1315,8 +1255,6 @@ class BufferMustWriteSideEffectInstruction extends WriteSideEffectInstruction {
BufferMustWriteSideEffectInstruction() {
getOpcode() instanceof Opcode::BufferMustWriteSideEffect
}
final override MemoryAccessKind getResultMemoryAccess() { result instanceof BufferMemoryAccess }
}
/**
@@ -1328,8 +1266,6 @@ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstructi
getOpcode() instanceof Opcode::SizedBufferMustWriteSideEffect
}
final override MemoryAccessKind getResultMemoryAccess() { result instanceof BufferMemoryAccess }
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
}
@@ -1342,10 +1278,6 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
IndirectMayWriteSideEffectInstruction() {
getOpcode() instanceof Opcode::IndirectMayWriteSideEffect
}
final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess }
final override predicate hasResultMayMemoryAccess() { any() }
}
/**
@@ -1354,10 +1286,6 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
*/
class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
BufferMayWriteSideEffectInstruction() { getOpcode() instanceof Opcode::BufferMayWriteSideEffect }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof BufferMemoryAccess }
final override predicate hasResultMayMemoryAccess() { any() }
}
/**
@@ -1369,10 +1297,6 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
getOpcode() instanceof Opcode::SizedBufferMayWriteSideEffect
}
final override MemoryAccessKind getResultMemoryAccess() { result instanceof BufferMemoryAccess }
final override predicate hasResultMayMemoryAccess() { any() }
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
}
@@ -1381,10 +1305,6 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
*/
class InlineAsmInstruction extends Instruction {
InlineAsmInstruction() { getOpcode() instanceof Opcode::InlineAsm }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof EscapedMemoryAccess }
final override predicate hasResultMayMemoryAccess() { any() }
}
/**
@@ -1470,10 +1390,6 @@ class CatchAnyInstruction extends CatchInstruction {
class UnmodeledDefinitionInstruction extends Instruction {
UnmodeledDefinitionInstruction() { getOpcode() instanceof Opcode::UnmodeledDefinition }
final override MemoryAccessKind getResultMemoryAccess() {
result instanceof UnmodeledMemoryAccess
}
}
/**
@@ -1481,8 +1397,6 @@ class UnmodeledDefinitionInstruction extends Instruction {
*/
class AliasedDefinitionInstruction extends Instruction {
AliasedDefinitionInstruction() { getOpcode() instanceof Opcode::AliasedDefinition }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof EscapedMemoryAccess }
}
/**
@@ -1511,8 +1425,6 @@ class UnmodeledUseInstruction extends Instruction {
class PhiInstruction extends Instruction {
PhiInstruction() { getOpcode() instanceof Opcode::Phi }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof PhiMemoryAccess }
/**
* Gets all of the instruction's `PhiInputOperand`s, representing the values that flow from each predecessor block.
*/
@@ -1573,8 +1485,6 @@ class PhiInstruction extends Instruction {
class ChiInstruction extends Instruction {
ChiInstruction() { getOpcode() instanceof Opcode::Chi }
final override MemoryAccessKind getResultMemoryAccess() { result instanceof ChiTotalMemoryAccess }
/**
* Gets the operand that represents the previous state of all memory that might be aliased by the
* memory write.

View File

@@ -170,7 +170,9 @@ class MemoryOperand extends Operand {
/**
* Gets the kind of memory access performed by the operand.
*/
MemoryAccessKind getMemoryAccess() { none() }
MemoryAccessKind getMemoryAccess() {
result = getUse().getOpcode().getReadMemoryAccess()
}
/**
* Holds if the memory access performed by this operand will not always read from every bit in the
@@ -180,7 +182,9 @@ class MemoryOperand extends Operand {
* conservative estimate of the memory that might actually be accessed at runtime (for example,
* the global side effects of a function call).
*/
predicate hasMayMemoryAccess() { none() }
predicate hasMayReadMemoryAccess() {
getUse().getOpcode().hasMayReadMemoryAccess()
}
/**
* Returns the operand that holds the memory address from which the current operand loads its
@@ -274,8 +278,6 @@ class LoadOperand extends TypedOperand {
override LoadOperandTag tag;
override string toString() { result = "Load" }
final override MemoryAccessKind getMemoryAccess() { result instanceof IndirectMemoryAccess }
}
/**
@@ -331,8 +333,6 @@ class UnmodeledUseOperand extends NonPhiMemoryOperand {
override UnmodeledUseOperandTag tag;
override string toString() { result = "UnmodeledUse" }
final override MemoryAccessKind getMemoryAccess() { result instanceof UnmodeledMemoryAccess }
}
/**
@@ -382,50 +382,6 @@ class PositionalArgumentOperand extends ArgumentOperand {
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override MemoryAccessKind getMemoryAccess() {
useInstr instanceof AliasedUseInstruction and
result instanceof NonLocalMemoryAccess
or
useInstr instanceof CallSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
useInstr instanceof CallReadSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
useInstr instanceof IndirectReadSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
useInstr instanceof BufferReadSideEffectInstruction and
result instanceof BufferMemoryAccess
or
useInstr instanceof IndirectMustWriteSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
useInstr instanceof BufferMustWriteSideEffectInstruction and
result instanceof BufferMemoryAccess
or
useInstr instanceof IndirectMayWriteSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
useInstr instanceof BufferMayWriteSideEffectInstruction and
result instanceof BufferMemoryAccess
or
useInstr instanceof ReturnIndirectionInstruction and
result instanceof BufferMemoryAccess
}
final override predicate hasMayMemoryAccess() {
useInstr instanceof AliasedUseInstruction
or
useInstr instanceof CallSideEffectInstruction
or
useInstr instanceof CallReadSideEffectInstruction
or
useInstr instanceof IndirectMayWriteSideEffectInstruction
or
useInstr instanceof BufferMayWriteSideEffectInstruction
}
}
/**

View File

@@ -40,7 +40,7 @@ private predicate isVariableModeled(IRVariable var) {
|
bitOffset = 0 and
type.getIRType() = var.getIRType() and
not operand.hasMayMemoryAccess()
not operand.hasMayReadMemoryAccess()
)
}

View File

@@ -760,7 +760,7 @@ ssa.cpp:
# 179| r179_6(int *) = Load : &:r179_4, m179_5
# 179| m179_7(unknown) = InitializeIndirection[p] : &:r179_6
# 179| m179_8(unknown) = Chi : total:m179_2, partial:m179_7
# 180| m180_1(unknown) = InlineAsm : ~mu179_3
# 180| m180_1(unknown) = InlineAsm : ~m179_8
# 180| m180_2(unknown) = Chi : total:m179_8, partial:m180_1
# 181| r181_1(glval<int>) = VariableAddress[#return] :
# 181| r181_2(glval<int *>) = VariableAddress[p] :
@@ -811,7 +811,7 @@ ssa.cpp:
# 190| r190_4(glval<unsigned int &>) = VariableAddress[d] :
# 190| r190_5(unsigned int &) = Load : &:r190_4, m184_20
# 190| r190_6(unsigned int) = Load : &:r190_5, ~m184_23
# 186| m186_1(unknown) = InlineAsm : ~mu184_3, 0:r189_3, 1:r189_6, 2:r190_3, 3:r190_6
# 186| m186_1(unknown) = InlineAsm : ~m184_23, 0:r189_3, 1:r189_6, 2:r190_3, 3:r190_6
# 186| m186_2(unknown) = Chi : total:m184_23, partial:m186_1
# 192| v192_1(void) = NoOp :
# 184| v184_24(void) = ReturnIndirection : &:r184_6, ~m186_2
@@ -901,7 +901,7 @@ ssa.cpp:
# 209| r209_7(void *) = Convert : r209_6
# 209| r209_8(int) = Constant[4] :
# 209| r209_9(void *) = Call : func:r209_1, 0:r209_4, 1:r209_7, 2:r209_8
# 209| v209_10(void) = ^SizedBufferReadSideEffect[1] : &:r209_7, r209_8, ~mu207_3
# 209| v209_10(void) = ^SizedBufferReadSideEffect[1] : &:r209_7, r209_8, ~m207_5
# 209| m209_11(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r209_4, r209_8
# 209| m209_12(unknown) = Chi : total:m208_3, partial:m209_11
# 210| r210_1(glval<int>) = VariableAddress[#return] :