mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
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:
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,7 +40,7 @@ private predicate isVariableModeled(IRVariable var) {
|
||||
|
|
||||
bitOffset = 0 and
|
||||
type.getIRType() = var.getIRType() and
|
||||
not operand.hasMayMemoryAccess()
|
||||
not operand.hasMayReadMemoryAccess()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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] :
|
||||
|
||||
Reference in New Issue
Block a user