C++: Add conservative side effects for function calls

This commit is contained in:
Dave Bartolomeo
2018-09-07 11:17:03 -07:00
parent f9ed39915f
commit 1fb36ff7e7
17 changed files with 2689 additions and 1785 deletions

View File

@@ -1,7 +1,10 @@
import cpp
newtype TMemoryAccessKind =
private newtype TMemoryAccessKind =
TIndirectMemoryAccess() or
TIndirectMayMemoryAccess() or
TBufferMemoryAccess() or
TBufferMayMemoryAccess() or
TEscapedMemoryAccess() or
TPhiMemoryAccess() or
TUnmodeledMemoryAccess()
@@ -15,8 +18,8 @@ class MemoryAccessKind extends TMemoryAccessKind {
}
/**
* The operand or result accesses memory at the address specified by the
* `AddressOperand` on the same instruction.
* The operand or result accesses memory at the address specified by the `AddressOperand` on the
* same instruction.
*/
class IndirectMemoryAccess extends MemoryAccessKind, TIndirectMemoryAccess {
override string toString() {
@@ -24,6 +27,38 @@ class IndirectMemoryAccess extends MemoryAccessKind, TIndirectMemoryAccess {
}
}
/**
* The operand or result may access some, all, or none of the memory at the address specified by the
* `AddressOperand` on the same instruction.
*/
class IndirectMayMemoryAccess extends MemoryAccessKind, TIndirectMayMemoryAccess {
override string toString() {
result = "indirect(may)"
}
}
/**
* The operand or result accesses memory starting at the address specified by the `AddressOperand`
* on the same instruction, accessing a number of consecutive elements given by the
* `BufferSizeOperand`.
*/
class BufferMemoryAccess extends MemoryAccessKind, TBufferMemoryAccess {
override string toString() {
result = "buffer"
}
}
/**
* The operand or result may access some, all, or none of the memory starting at the address
* specified by the `AddressOperand` on the same instruction, accessing a number of consecutive
* elements given by the `BufferSizeOperand`.
*/
class BufferMayMemoryAccess extends MemoryAccessKind, TBufferMayMemoryAccess {
override string toString() {
result = "buffer(may)"
}
}
/**
* The operand or result accesses all memory whose address has escaped.
*/

View File

@@ -58,7 +58,15 @@ private newtype TOpcode =
TVarArgsStart() or
TVarArgsEnd() or
TVarArg() or
TVarArgCopy()
TVarArgCopy() or
TCallSideEffect() or
TCallReadSideEffect() or
TIndirectReadSideEffect() or
TIndirectWriteSideEffect() or
TIndirectMayWriteSideEffect() or
TBufferReadSideEffect() or
TBufferWriteSideEffect() or
TBufferMayWriteSideEffect()
class Opcode extends TOpcode {
string toString() {
@@ -92,6 +100,29 @@ abstract class OpcodeWithCondition extends Opcode {}
abstract class BuiltInOpcode extends Opcode {}
abstract class SideEffectOpcode extends Opcode {}
/**
* An opcode that reads from a set of memory locations as a side effect.
*/
abstract class ReadSideEffectOpcode extends SideEffectOpcode {}
/**
* An opcode that writes to a set of memory locations as a side effect.
*/
abstract class WriteSideEffectOpcode extends SideEffectOpcode {}
/**
* 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 SideEffectOpcode {}
/**
* An opcode that accesses a buffer via an `AddressOperand` and a `BufferSizeOperand`.
*/
abstract class BufferAccessOpcode extends MemoryAccessOpcode {}
module Opcode {
class NoOp extends Opcode, TNoOp { override final string toString() { result = "NoOp" } }
class Uninitialized extends MemoryAccessOpcode, TUninitialized { override final string toString() { result = "Uninitialized" } }
@@ -153,4 +184,12 @@ module Opcode {
class VarArgsEnd extends BuiltInOpcode, TVarArgsEnd { override final string toString() { result = "VarArgsEnd" } }
class VarArg extends BuiltInOpcode, TVarArg { override final string toString() { result = "VarArg" } }
class VarArgCopy extends BuiltInOpcode, TVarArgCopy { override final string toString() { result = "VarArgCopy" } }
class CallSideEffect extends MayWriteSideEffectOpcode, TCallSideEffect { override final string toString() { result = "CallSideEffect" } }
class CallReadSideEffect extends ReadSideEffectOpcode, TCallReadSideEffect { override final string toString() { result = "CallReadSideEffect" } }
class IndirectReadSideEffect extends ReadSideEffectOpcode, MemoryAccessOpcode, TIndirectReadSideEffect { override final string toString() { result = "IndirectReadSideEffect" } }
class IndirectWriteSideEffect extends WriteSideEffectOpcode, MemoryAccessOpcode, TIndirectWriteSideEffect { override final string toString() { result = "IndirectWriteSideEffect" } }
class IndirectMayWriteSideEffect extends MayWriteSideEffectOpcode, MemoryAccessOpcode, TIndirectMayWriteSideEffect { override final string toString() { result = "IndirectMayWriteSideEffect" } }
class BufferReadSideEffect extends ReadSideEffectOpcode, BufferAccessOpcode, TBufferReadSideEffect { override final string toString() { result = "BufferReadSideEffect" } }
class BufferWriteSideEffect extends WriteSideEffectOpcode, BufferAccessOpcode, TBufferWriteSideEffect { override final string toString() { result = "BufferWriteSideEffect" } }
class BufferMayWriteSideEffect extends MayWriteSideEffectOpcode, BufferAccessOpcode, TBufferMayWriteSideEffect { override final string toString() { result = "BufferMayWriteSideEffect" } }
}

View File

@@ -33,11 +33,16 @@ module InstructionSanity {
) or
opcode instanceof CopyOpcode and tag instanceof CopySourceOperandTag or
opcode instanceof MemoryAccessOpcode and tag instanceof AddressOperandTag or
opcode instanceof BufferAccessOpcode and tag instanceof BufferSizeOperand or
opcode instanceof OpcodeWithCondition and tag instanceof ConditionOperandTag or
opcode instanceof Opcode::ReturnValue and tag instanceof ReturnValueOperandTag or
opcode instanceof Opcode::ThrowValue and tag instanceof ExceptionOperandTag or
opcode instanceof Opcode::UnmodeledUse and tag instanceof UnmodeledUseOperandTag or
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag or
(
(opcode instanceof ReadSideEffectOpcode or opcode instanceof MayWriteSideEffectOpcode) and
tag instanceof SideEffectOperandTag
)
)
)
}
@@ -162,9 +167,9 @@ class Instruction extends Construction::TInstruction {
*/
final string getOperationString() {
if exists(getImmediateString()) then
result = opcode.toString() + "[" + getImmediateString() + "]"
result = getOperationPrefix() + opcode.toString() + "[" + getImmediateString() + "]"
else
result = opcode.toString()
result = getOperationPrefix() + opcode.toString()
}
/**
@@ -174,6 +179,13 @@ class Instruction extends Construction::TInstruction {
none()
}
private string getOperationPrefix() {
if this instanceof SideEffectInstruction then
result = "^"
else
result = ""
}
private string getResultPrefix() {
if resultType instanceof VoidType then
result = "v"
@@ -1084,6 +1096,9 @@ class SwitchInstruction extends Instruction {
}
}
/**
* An instruction that calls a function.
*/
class CallInstruction extends Instruction {
CallInstruction() {
opcode instanceof Opcode::Call
@@ -1094,6 +1109,116 @@ class CallInstruction extends Instruction {
}
}
/**
* An instruction representing a side effect of a function call.
*/
class SideEffectInstruction extends Instruction {
SideEffectInstruction() {
opcode instanceof SideEffectOpcode
}
final Instruction getPrimaryInstruction() {
result = Construction::getPrimaryInstructionForSideEffect(this)
}
}
/**
* An instruction representing the side effect of a function call on any memory that might be
* accessed by that call.
*/
class CallSideEffectInstruction extends SideEffectInstruction {
CallSideEffectInstruction() {
opcode instanceof Opcode::CallSideEffect
}
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof EscapedMemoryAccess
}
}
/**
* An instruction representing the side effect of a function call on any memory that might be read
* by that call.
*/
class CallReadSideEffectInstruction extends SideEffectInstruction {
CallReadSideEffectInstruction() {
opcode instanceof Opcode::CallReadSideEffect
}
}
/**
* An instruction representing the read of an indirect parameter within a function call.
*/
class IndirectReadSideEffectInstruction extends SideEffectInstruction {
IndirectReadSideEffectInstruction() {
opcode instanceof Opcode::IndirectReadSideEffect
}
}
/**
* An instruction representing the read of an indirect buffer parameter within a function call.
*/
class BufferReadSideEffectInstruction extends SideEffectInstruction {
BufferReadSideEffectInstruction() {
opcode instanceof Opcode::BufferReadSideEffect
}
}
/**
* An instruction representing the write of an indirect parameter within a function call.
*/
class IndirectWriteSideEffectInstruction extends SideEffectInstruction {
IndirectWriteSideEffectInstruction() {
opcode instanceof Opcode::IndirectWriteSideEffect
}
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof IndirectMemoryAccess
}
}
/**
* An instruction representing the write of an indirect buffer parameter within a function call. The
* entire buffer is overwritten.
*/
class BufferWriteSideEffectInstruction extends SideEffectInstruction {
BufferWriteSideEffectInstruction() {
opcode instanceof Opcode::BufferWriteSideEffect
}
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof BufferMemoryAccess
}
}
/**
* An instruction representing the potential write of an indirect parameter within a function call.
* Unlike `IndirectWriteSideEffectInstruction`, the location might not be completely overwritten.
* written.
*/
class IndirectMayWriteSideEffectInstruction extends SideEffectInstruction {
IndirectMayWriteSideEffectInstruction() {
opcode instanceof Opcode::IndirectMayWriteSideEffect
}
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof IndirectMayMemoryAccess
}
}
/**
* An instruction representing the write of an indirect buffer parameter within a function call.
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
*/
class BufferMayWriteSideEffectInstruction extends SideEffectInstruction {
BufferMayWriteSideEffectInstruction() {
opcode instanceof Opcode::BufferMayWriteSideEffect
}
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof BufferMayMemoryAccess
}
}
/**
* An instruction that throws an exception.
*/

View File

@@ -306,6 +306,38 @@ class PositionalArgumentOperand extends ArgumentOperand {
}
}
class SideEffectOperand extends NonPhiOperand {
SideEffectOperand() {
this = TNonPhiOperand(_, sideEffectOperand(), _)
}
override MemoryAccessKind getMemoryAccess() {
instr instanceof CallSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
instr instanceof CallReadSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
instr instanceof IndirectReadSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
instr instanceof BufferReadSideEffectInstruction and
result instanceof BufferMemoryAccess
or
instr instanceof IndirectWriteSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
instr instanceof BufferWriteSideEffectInstruction and
result instanceof BufferMemoryAccess
or
instr instanceof IndirectMayWriteSideEffectInstruction and
result instanceof IndirectMayMemoryAccess
or
instr instanceof BufferMayWriteSideEffectInstruction and
result instanceof BufferMayMemoryAccess
}
}
/**
* An operand of a `PhiInstruction`.
*/
@@ -350,6 +382,7 @@ class PhiOperand extends Operand, TPhiOperand {
}
}
/**
* An operand that reads a value from memory.
*/

View File

@@ -227,6 +227,13 @@ cached private module Cached {
)
}
cached Instruction getPrimaryInstructionForSideEffect(Instruction instruction) {
exists(OldIR::SideEffectInstruction oldInstruction |
oldInstruction = getOldInstruction(instruction) and
result = getNewInstruction(oldInstruction.getPrimaryInstruction())
)
}
private predicate ssa_variableUpdate(Alias::VirtualVariable vvar,
OldIR::Instruction instr, OldIR::IRBlock block, int index) {
block.getInstruction(index) = instr and

View File

@@ -33,11 +33,16 @@ module InstructionSanity {
) or
opcode instanceof CopyOpcode and tag instanceof CopySourceOperandTag or
opcode instanceof MemoryAccessOpcode and tag instanceof AddressOperandTag or
opcode instanceof BufferAccessOpcode and tag instanceof BufferSizeOperand or
opcode instanceof OpcodeWithCondition and tag instanceof ConditionOperandTag or
opcode instanceof Opcode::ReturnValue and tag instanceof ReturnValueOperandTag or
opcode instanceof Opcode::ThrowValue and tag instanceof ExceptionOperandTag or
opcode instanceof Opcode::UnmodeledUse and tag instanceof UnmodeledUseOperandTag or
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag or
(
(opcode instanceof ReadSideEffectOpcode or opcode instanceof MayWriteSideEffectOpcode) and
tag instanceof SideEffectOperandTag
)
)
)
}
@@ -162,9 +167,9 @@ class Instruction extends Construction::TInstruction {
*/
final string getOperationString() {
if exists(getImmediateString()) then
result = opcode.toString() + "[" + getImmediateString() + "]"
result = getOperationPrefix() + opcode.toString() + "[" + getImmediateString() + "]"
else
result = opcode.toString()
result = getOperationPrefix() + opcode.toString()
}
/**
@@ -174,6 +179,13 @@ class Instruction extends Construction::TInstruction {
none()
}
private string getOperationPrefix() {
if this instanceof SideEffectInstruction then
result = "^"
else
result = ""
}
private string getResultPrefix() {
if resultType instanceof VoidType then
result = "v"
@@ -1084,6 +1096,9 @@ class SwitchInstruction extends Instruction {
}
}
/**
* An instruction that calls a function.
*/
class CallInstruction extends Instruction {
CallInstruction() {
opcode instanceof Opcode::Call
@@ -1094,6 +1109,116 @@ class CallInstruction extends Instruction {
}
}
/**
* An instruction representing a side effect of a function call.
*/
class SideEffectInstruction extends Instruction {
SideEffectInstruction() {
opcode instanceof SideEffectOpcode
}
final Instruction getPrimaryInstruction() {
result = Construction::getPrimaryInstructionForSideEffect(this)
}
}
/**
* An instruction representing the side effect of a function call on any memory that might be
* accessed by that call.
*/
class CallSideEffectInstruction extends SideEffectInstruction {
CallSideEffectInstruction() {
opcode instanceof Opcode::CallSideEffect
}
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof EscapedMemoryAccess
}
}
/**
* An instruction representing the side effect of a function call on any memory that might be read
* by that call.
*/
class CallReadSideEffectInstruction extends SideEffectInstruction {
CallReadSideEffectInstruction() {
opcode instanceof Opcode::CallReadSideEffect
}
}
/**
* An instruction representing the read of an indirect parameter within a function call.
*/
class IndirectReadSideEffectInstruction extends SideEffectInstruction {
IndirectReadSideEffectInstruction() {
opcode instanceof Opcode::IndirectReadSideEffect
}
}
/**
* An instruction representing the read of an indirect buffer parameter within a function call.
*/
class BufferReadSideEffectInstruction extends SideEffectInstruction {
BufferReadSideEffectInstruction() {
opcode instanceof Opcode::BufferReadSideEffect
}
}
/**
* An instruction representing the write of an indirect parameter within a function call.
*/
class IndirectWriteSideEffectInstruction extends SideEffectInstruction {
IndirectWriteSideEffectInstruction() {
opcode instanceof Opcode::IndirectWriteSideEffect
}
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof IndirectMemoryAccess
}
}
/**
* An instruction representing the write of an indirect buffer parameter within a function call. The
* entire buffer is overwritten.
*/
class BufferWriteSideEffectInstruction extends SideEffectInstruction {
BufferWriteSideEffectInstruction() {
opcode instanceof Opcode::BufferWriteSideEffect
}
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof BufferMemoryAccess
}
}
/**
* An instruction representing the potential write of an indirect parameter within a function call.
* Unlike `IndirectWriteSideEffectInstruction`, the location might not be completely overwritten.
* written.
*/
class IndirectMayWriteSideEffectInstruction extends SideEffectInstruction {
IndirectMayWriteSideEffectInstruction() {
opcode instanceof Opcode::IndirectMayWriteSideEffect
}
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof IndirectMayMemoryAccess
}
}
/**
* An instruction representing the write of an indirect buffer parameter within a function call.
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
*/
class BufferMayWriteSideEffectInstruction extends SideEffectInstruction {
BufferMayWriteSideEffectInstruction() {
opcode instanceof Opcode::BufferMayWriteSideEffect
}
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof BufferMayMemoryAccess
}
}
/**
* An instruction that throws an exception.
*/

View File

@@ -306,6 +306,38 @@ class PositionalArgumentOperand extends ArgumentOperand {
}
}
class SideEffectOperand extends NonPhiOperand {
SideEffectOperand() {
this = TNonPhiOperand(_, sideEffectOperand(), _)
}
override MemoryAccessKind getMemoryAccess() {
instr instanceof CallSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
instr instanceof CallReadSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
instr instanceof IndirectReadSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
instr instanceof BufferReadSideEffectInstruction and
result instanceof BufferMemoryAccess
or
instr instanceof IndirectWriteSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
instr instanceof BufferWriteSideEffectInstruction and
result instanceof BufferMemoryAccess
or
instr instanceof IndirectMayWriteSideEffectInstruction and
result instanceof IndirectMayMemoryAccess
or
instr instanceof BufferMayWriteSideEffectInstruction and
result instanceof BufferMayMemoryAccess
}
}
/**
* An operand of a `PhiInstruction`.
*/
@@ -350,6 +382,7 @@ class PhiOperand extends Operand, TPhiOperand {
}
}
/**
* An operand that reads a value from memory.
*/

View File

@@ -167,6 +167,13 @@ cached private module Cached {
result = element.getInstructionResultSize(tag)
)
}
cached Instruction getPrimaryInstructionForSideEffect(Instruction instruction) {
exists(TranslatedElement element, InstructionTag tag |
instructionOrigin(instruction, element, tag) and
result = element.getPrimaryInstructionForSideEffect(tag)
)
}
}
import CachedForDebugging

View File

@@ -43,6 +43,7 @@ newtype TInstructionTag =
SwitchBranchTag() or
CallTargetTag() or
CallTag() or
CallSideEffectTag() or
AllocationSizeTag() or
AllocationElementSizeTag() or
AllocationExtentConvertTag() or
@@ -113,6 +114,7 @@ string getInstructionTagId(TInstructionTag tag) {
tag = SwitchBranchTag() and result = "SwitchBranch" or
tag = CallTargetTag() and result = "CallTarget" or
tag = CallTag() and result = "Call" or
tag = CallSideEffectTag() and result = "CallSideEffect" or
tag = AllocationSizeTag() and result = "AllocSize" or
tag = AllocationElementSizeTag() and result = "AllocElemSize" or
tag = AllocationExtentConvertTag() and result = "AllocExtConv" or

View File

@@ -534,6 +534,14 @@ abstract class TranslatedElement extends TTranslatedElement {
result = getParent().getExceptionSuccessorInstruction()
}
/**
* Gets the primary instruction for the side effect instruction that was
* generated by this element for tag `tag`.
*/
Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
none()
}
/**
* Holds if this element generates a temporary variable with type `type`.
* `tag` must be unique for each variable generated from the same AST node

View File

@@ -33,11 +33,16 @@ module InstructionSanity {
) or
opcode instanceof CopyOpcode and tag instanceof CopySourceOperandTag or
opcode instanceof MemoryAccessOpcode and tag instanceof AddressOperandTag or
opcode instanceof BufferAccessOpcode and tag instanceof BufferSizeOperand or
opcode instanceof OpcodeWithCondition and tag instanceof ConditionOperandTag or
opcode instanceof Opcode::ReturnValue and tag instanceof ReturnValueOperandTag or
opcode instanceof Opcode::ThrowValue and tag instanceof ExceptionOperandTag or
opcode instanceof Opcode::UnmodeledUse and tag instanceof UnmodeledUseOperandTag or
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag or
(
(opcode instanceof ReadSideEffectOpcode or opcode instanceof MayWriteSideEffectOpcode) and
tag instanceof SideEffectOperandTag
)
)
)
}
@@ -162,9 +167,9 @@ class Instruction extends Construction::TInstruction {
*/
final string getOperationString() {
if exists(getImmediateString()) then
result = opcode.toString() + "[" + getImmediateString() + "]"
result = getOperationPrefix() + opcode.toString() + "[" + getImmediateString() + "]"
else
result = opcode.toString()
result = getOperationPrefix() + opcode.toString()
}
/**
@@ -174,6 +179,13 @@ class Instruction extends Construction::TInstruction {
none()
}
private string getOperationPrefix() {
if this instanceof SideEffectInstruction then
result = "^"
else
result = ""
}
private string getResultPrefix() {
if resultType instanceof VoidType then
result = "v"
@@ -1084,6 +1096,9 @@ class SwitchInstruction extends Instruction {
}
}
/**
* An instruction that calls a function.
*/
class CallInstruction extends Instruction {
CallInstruction() {
opcode instanceof Opcode::Call
@@ -1094,6 +1109,116 @@ class CallInstruction extends Instruction {
}
}
/**
* An instruction representing a side effect of a function call.
*/
class SideEffectInstruction extends Instruction {
SideEffectInstruction() {
opcode instanceof SideEffectOpcode
}
final Instruction getPrimaryInstruction() {
result = Construction::getPrimaryInstructionForSideEffect(this)
}
}
/**
* An instruction representing the side effect of a function call on any memory that might be
* accessed by that call.
*/
class CallSideEffectInstruction extends SideEffectInstruction {
CallSideEffectInstruction() {
opcode instanceof Opcode::CallSideEffect
}
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof EscapedMemoryAccess
}
}
/**
* An instruction representing the side effect of a function call on any memory that might be read
* by that call.
*/
class CallReadSideEffectInstruction extends SideEffectInstruction {
CallReadSideEffectInstruction() {
opcode instanceof Opcode::CallReadSideEffect
}
}
/**
* An instruction representing the read of an indirect parameter within a function call.
*/
class IndirectReadSideEffectInstruction extends SideEffectInstruction {
IndirectReadSideEffectInstruction() {
opcode instanceof Opcode::IndirectReadSideEffect
}
}
/**
* An instruction representing the read of an indirect buffer parameter within a function call.
*/
class BufferReadSideEffectInstruction extends SideEffectInstruction {
BufferReadSideEffectInstruction() {
opcode instanceof Opcode::BufferReadSideEffect
}
}
/**
* An instruction representing the write of an indirect parameter within a function call.
*/
class IndirectWriteSideEffectInstruction extends SideEffectInstruction {
IndirectWriteSideEffectInstruction() {
opcode instanceof Opcode::IndirectWriteSideEffect
}
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof IndirectMemoryAccess
}
}
/**
* An instruction representing the write of an indirect buffer parameter within a function call. The
* entire buffer is overwritten.
*/
class BufferWriteSideEffectInstruction extends SideEffectInstruction {
BufferWriteSideEffectInstruction() {
opcode instanceof Opcode::BufferWriteSideEffect
}
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof BufferMemoryAccess
}
}
/**
* An instruction representing the potential write of an indirect parameter within a function call.
* Unlike `IndirectWriteSideEffectInstruction`, the location might not be completely overwritten.
* written.
*/
class IndirectMayWriteSideEffectInstruction extends SideEffectInstruction {
IndirectMayWriteSideEffectInstruction() {
opcode instanceof Opcode::IndirectMayWriteSideEffect
}
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof IndirectMayMemoryAccess
}
}
/**
* An instruction representing the write of an indirect buffer parameter within a function call.
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
*/
class BufferMayWriteSideEffectInstruction extends SideEffectInstruction {
BufferMayWriteSideEffectInstruction() {
opcode instanceof Opcode::BufferMayWriteSideEffect
}
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof BufferMayMemoryAccess
}
}
/**
* An instruction that throws an exception.
*/

View File

@@ -306,6 +306,38 @@ class PositionalArgumentOperand extends ArgumentOperand {
}
}
class SideEffectOperand extends NonPhiOperand {
SideEffectOperand() {
this = TNonPhiOperand(_, sideEffectOperand(), _)
}
override MemoryAccessKind getMemoryAccess() {
instr instanceof CallSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
instr instanceof CallReadSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
instr instanceof IndirectReadSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
instr instanceof BufferReadSideEffectInstruction and
result instanceof BufferMemoryAccess
or
instr instanceof IndirectWriteSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
instr instanceof BufferWriteSideEffectInstruction and
result instanceof BufferMemoryAccess
or
instr instanceof IndirectMayWriteSideEffectInstruction and
result instanceof IndirectMayMemoryAccess
or
instr instanceof BufferMayWriteSideEffectInstruction and
result instanceof BufferMayMemoryAccess
}
}
/**
* An operand of a `PhiInstruction`.
*/
@@ -350,6 +382,7 @@ class PhiOperand extends Operand, TPhiOperand {
}
}
/**
* An operand that reads a value from memory.
*/

View File

@@ -1,6 +1,7 @@
import SSAConstructionInternal
import cpp
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.internal.OperandTag
private import NewIR
import Cached
@@ -226,6 +227,13 @@ cached private module Cached {
)
}
cached Instruction getPrimaryInstructionForSideEffect(Instruction instruction) {
exists(OldIR::SideEffectInstruction oldInstruction |
oldInstruction = getOldInstruction(instruction) and
result = getNewInstruction(oldInstruction.getPrimaryInstruction())
)
}
private predicate ssa_variableUpdate(Alias::VirtualVariable vvar,
OldIR::Instruction instr, OldIR::IRBlock block, int index) {
block.getInstruction(index) = instr and

View File

@@ -10,6 +10,8 @@ private int getMaxCallArgIndex() {
private newtype TOperandTag =
TAddressOperand() or
TBufferSizeOperand() or
TSideEffectOperand() or
TCopySourceOperand() or
TUnaryOperand() or
TLeftOperand() or
@@ -25,7 +27,7 @@ private newtype TOperandTag =
exists(BuiltInOperation op |
exists(op.getChild(argIndex))
)
}
}
/**
* Identifies the kind of operand on an instruction. Each `Instruction` has at
@@ -47,7 +49,7 @@ abstract class OperandTag extends TOperandTag {
/**
* The address operand of an instruction that loads or stores a value from
* memory (e.g. `Load`, `Store`).
* memory (e.g. `Load`, `Store`, `InitializeParameter`, `IndirectReadSideEffect`).
*/
class AddressOperandTag extends OperandTag, TAddressOperand {
override final string toString() {
@@ -63,6 +65,37 @@ AddressOperandTag addressOperand() {
result = TAddressOperand()
}
/**
* The buffer size operand of an instruction that represents a read or write of
* a buffer.
*/
class BufferSizeOperand extends OperandTag, TBufferSizeOperand {
override final string toString() {
result = "BufferSize"
}
override final int getSortOrder() {
result = 1
}
}
/**
* The operand representing the read side effect of a `SideEffectInstruction`.
*/
class SideEffectOperandTag extends OperandTag, TSideEffectOperand {
override final string toString() {
result = "SideEffect"
}
override final int getSortOrder() {
result = 2
}
}
SideEffectOperandTag sideEffectOperand() {
result = TSideEffectOperand()
}
/**
* The source value operand of an instruction that copies this value to its
* result (e.g. `Copy`, `Load`, `Store`).
@@ -73,7 +106,7 @@ class CopySourceOperandTag extends OperandTag, TCopySourceOperand {
}
override final int getSortOrder() {
result = 1
result = 3
}
}
@@ -90,7 +123,7 @@ class UnaryOperandTag extends OperandTag, TUnaryOperand {
}
override final int getSortOrder() {
result = 2
result = 4
}
}
@@ -107,7 +140,7 @@ class LeftOperandTag extends OperandTag, TLeftOperand {
}
override final int getSortOrder() {
result = 3
result = 5
}
}
@@ -124,7 +157,7 @@ class RightOperandTag extends OperandTag, TRightOperand {
}
override final int getSortOrder() {
result = 4
result = 6
}
}
@@ -141,7 +174,7 @@ class ReturnValueOperandTag extends OperandTag, TReturnValueOperand {
}
override final int getSortOrder() {
result = 5
result = 7
}
}
@@ -158,7 +191,7 @@ class ExceptionOperandTag extends OperandTag, TExceptionOperand {
}
override final int getSortOrder() {
result = 6
result = 8
}
}
@@ -175,7 +208,7 @@ class ConditionOperandTag extends OperandTag, TConditionOperand {
}
override final int getSortOrder() {
result = 7
result = 9
}
}
@@ -193,7 +226,7 @@ class UnmodeledUseOperandTag extends OperandTag, TUnmodeledUseOperand {
}
override final int getSortOrder() {
result = 8
result = 10
}
}
@@ -210,7 +243,7 @@ class CallTargetOperandTag extends OperandTag, TCallTargetOperand {
}
override final int getSortOrder() {
result = 9
result = 11
}
}
@@ -240,7 +273,7 @@ class ThisArgumentOperandTag extends ArgumentOperandTag, TThisArgumentOperand {
}
override final int getSortOrder() {
result = 10
result = 12
}
override final string getLabel() {
@@ -268,7 +301,7 @@ class PositionalArgumentOperandTag extends ArgumentOperandTag,
}
override final int getSortOrder() {
result = 11 + argIndex
result = 14 + argIndex
}
final int getArgIndex() {
@@ -278,4 +311,4 @@ class PositionalArgumentOperandTag extends ArgumentOperandTag,
PositionalArgumentOperandTag positionalArgumentOperand(int argIndex) {
result = TPositionalArgumentOperand(argIndex)
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff