Merge pull request #4825 from rdmarsh2/rdmarsh2/cpp/operand-reuse

C++: share `TOperand` across IR stages
This commit is contained in:
Mathias Vorreiter Pedersen
2021-03-03 08:55:44 +01:00
committed by GitHub
25 changed files with 508 additions and 360 deletions

View File

@@ -10,79 +10,32 @@ private import Imports::MemoryAccessKind
private import Imports::IRType
private import Imports::Overlap
private import Imports::OperandTag
cached
private newtype TOperand =
TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) {
defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and
not Construction::isInCycle(useInstr) and
strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1
} or
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
useInstr.getOpcode().hasOperand(tag)
} or
TPhiOperand(
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
) {
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
}
private import Imports::TOperand
private import internal.OperandInternal
/**
* Base class for all register operands. This is a placeholder for the IPA union type that we will
* eventually use for this purpose.
* An operand of an `Instruction` in this stage of the IR. Implemented as a union of the branches
* of `TOperand` that are used in this stage.
*/
private class RegisterOperandBase extends TRegisterOperand {
/** Gets a textual representation of this element. */
abstract string toString();
}
/**
* Returns the register operand with the specified parameters.
*/
private RegisterOperandBase registerOperand(
Instruction useInstr, RegisterOperandTag tag, Instruction defInstr
) {
result = TRegisterOperand(useInstr, tag, defInstr)
}
/**
* Base class for all non-Phi memory operands. This is a placeholder for the IPA union type that we
* will eventually use for this purpose.
*/
private class NonPhiMemoryOperandBase extends TNonPhiMemoryOperand {
/** Gets a textual representation of this element. */
abstract string toString();
}
/**
* Returns the non-Phi memory operand with the specified parameters.
*/
private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
result = TNonPhiMemoryOperand(useInstr, tag)
}
/**
* Base class for all Phi operands. This is a placeholder for the IPA union type that we will
* eventually use for this purpose.
*/
private class PhiOperandBase extends TPhiOperand {
abstract string toString();
}
/**
* Returns the Phi operand with the specified parameters.
*/
private PhiOperandBase phiOperand(
Instruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
) {
result = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap)
}
private class TStageOperand =
TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand;
/**
* An operand of an `Instruction`. The operand represents a use of the result of one instruction
* (the defining instruction) in another instruction (the use instruction)
*/
class Operand extends TOperand {
class Operand extends TStageOperand {
cached
Operand() {
// Ensure that the operand does not refer to instructions from earlier stages that are unreachable here
exists(Instruction use, Instruction def | this = registerOperand(use, _, def)) or
exists(Instruction use | this = nonSSAMemoryOperand(use, _)) or
exists(Instruction use, Instruction def, IRBlock predecessorBlock |
this = phiOperand(use, def, predecessorBlock, _)
) or
exists(Instruction use | this = chiOperand(use, _))
}
/** Gets a textual representation of this element. */
string toString() { result = "Operand" }
@@ -238,9 +191,11 @@ class Operand extends TOperand {
* An operand that consumes a memory result (e.g. the `LoadOperand` on a `Load` instruction).
*/
class MemoryOperand extends Operand {
cached
MemoryOperand() {
this instanceof NonPhiMemoryOperandBase or
this instanceof PhiOperandBase
this instanceof TNonSSAMemoryOperand or
this instanceof TPhiOperand or
this instanceof TChiOperand
}
/**
@@ -278,7 +233,8 @@ class NonPhiOperand extends Operand {
NonPhiOperand() {
this = registerOperand(useInstr, tag, _) or
this = nonPhiMemoryOperand(useInstr, tag)
this = nonSSAMemoryOperand(useInstr, tag) or
this = chiOperand(useInstr, tag)
}
final override Instruction getUse() { result = useInstr }
@@ -298,10 +254,11 @@ class NonPhiOperand extends Operand {
/**
* An operand that consumes a register (non-memory) result.
*/
class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
class RegisterOperand extends NonPhiOperand, TRegisterOperand {
override RegisterOperandTag tag;
Instruction defInstr;
cached
RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) }
final override string toString() { result = tag.toString() }
@@ -317,10 +274,15 @@ class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
/**
* A memory operand other than the operand of a `Phi` instruction.
*/
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase {
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand {
override MemoryOperandTag tag;
NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) }
cached
NonPhiMemoryOperand() {
this = nonSSAMemoryOperand(useInstr, tag)
or
this = chiOperand(useInstr, tag)
}
final override string toString() { result = tag.toString() }
@@ -462,12 +424,13 @@ class SideEffectOperand extends TypedOperand {
/**
* An operand of a `PhiInstruction`.
*/
class PhiInputOperand extends MemoryOperand, PhiOperandBase {
class PhiInputOperand extends MemoryOperand, TPhiOperand {
PhiInstruction useInstr;
Instruction defInstr;
IRBlock predecessorBlock;
Overlap overlap;
cached
PhiInputOperand() { this = phiOperand(useInstr, defInstr, predecessorBlock, overlap) }
override string toString() { result = "Phi" }

View File

@@ -2,3 +2,4 @@ import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
import semmle.code.cpp.ir.implementation.IRType as IRType
import semmle.code.cpp.ir.internal.Overlap as Overlap
import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag
import semmle.code.cpp.ir.implementation.internal.TOperand as TOperand

View File

@@ -0,0 +1,2 @@
private import semmle.code.cpp.ir.implementation.internal.TOperand
import AliasedSSAOperands

View File

@@ -6,6 +6,7 @@ private import Imports::Overlap
private import Imports::TInstruction
private import Imports::RawIR as RawIR
private import SSAInstructions
private import SSAOperands
private import NewIR
private class OldBlock = Reachability::ReachableBlock;

View File

@@ -3,3 +3,4 @@ import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag
import semmle.code.cpp.ir.internal.Overlap as Overlap
import semmle.code.cpp.ir.implementation.internal.TInstruction as TInstruction
import semmle.code.cpp.ir.implementation.raw.IR as RawIR
import semmle.code.cpp.ir.implementation.internal.TOperand as TOperand

View File

@@ -5,3 +5,4 @@ import semmle.code.cpp.ir.implementation.aliased_ssa.IR as NewIR
import semmle.code.cpp.ir.implementation.internal.TInstruction::AliasedSSAInstructions as SSAInstructions
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import AliasedSSA as Alias
import semmle.code.cpp.ir.implementation.internal.TOperand::AliasedSSAOperands as SSAOperands

View File

@@ -0,0 +1,180 @@
private import TInstruction
private import OperandTag
private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as RawConstruction
private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as UnaliasedConstruction
private import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSAConstruction as AliasedConstruction
private import semmle.code.cpp.ir.implementation.raw.IR as Raw
private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as Unaliased
private import semmle.code.cpp.ir.implementation.aliased_ssa.IR as Aliased
private import semmle.code.cpp.ir.internal.Overlap
/**
* Provides the newtype used to represent operands across all phases of the IR.
*/
private module Internal {
/**
* An IR operand. `TOperand` is shared across all phases of the IR. There are branches of this
* type for operands created directly from the AST (`TRegisterOperand` and `TNonSSAMemoryOperand`),
* for operands computed by each stage of SSA construction (`T*PhiOperand` and
* `TAliasedChiOperand`), and a placehold branch for operands that do not exist in a given
* stage of IR construction (`TNoOperand`).
*/
cached
newtype TOperand =
// RAW
TRegisterOperand(TRawInstruction useInstr, RegisterOperandTag tag, TRawInstruction defInstr) {
defInstr = RawConstruction::getRegisterOperandDefinition(useInstr, tag) and
not RawConstruction::isInCycle(useInstr) and
strictcount(RawConstruction::getRegisterOperandDefinition(useInstr, tag)) = 1
} or
// Placeholder for Phi and Chi operands in stages that don't have the corresponding instructions
TNoOperand() { none() } or
// Can be "removed" later when there's unreachable code
// These operands can be reused across all three stages. They just get different defs.
TNonSSAMemoryOperand(Raw::Instruction useInstr, MemoryOperandTag tag) {
// Has no definition in raw but will get definitions later
useInstr.getOpcode().hasOperand(tag)
} or
TUnaliasedPhiOperand(
Unaliased::PhiInstruction useInstr, Unaliased::Instruction defInstr,
Unaliased::IRBlock predecessorBlock, Overlap overlap
) {
defInstr = UnaliasedConstruction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
} or
//// ALIASED
////
// Until we share SSA, these will be all the phis there are. With SSA
// sharing, these will add to the ones that are already there.
// If we share SSA, be careful with the case where we remove all possible
// indirect writes to a variable because they're dead code. In that case it's
// important that we use the same definition of "is variable aliased" across
// the phases.
TAliasedPhiOperand(
TAliasedSSAPhiInstruction useInstr, Aliased::Instruction defInstr,
Aliased::IRBlock predecessorBlock, Overlap overlap
) {
defInstr = AliasedConstruction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
} or
TAliasedChiOperand(TAliasedSSAChiInstruction useInstr, ChiOperandTag tag) { any() }
}
/**
* Reexports some branches from `TOperand` so they can be used in stage modules without importing
* `TOperand` itself.
*/
private module Shared {
class TRegisterOperand = Internal::TRegisterOperand;
/**
* Returns the register operand with the specified parameters.
*/
TRegisterOperand registerOperand(
TRawInstruction useInstr, RegisterOperandTag tag, TRawInstruction defInstr
) {
result = Internal::TRegisterOperand(useInstr, tag, defInstr)
}
class TNonSSAMemoryOperand = Internal::TNonSSAMemoryOperand;
/**
* Returns the non-Phi memory operand with the specified parameters.
*/
TNonSSAMemoryOperand nonSSAMemoryOperand(TRawInstruction useInstr, MemoryOperandTag tag) {
result = Internal::TNonSSAMemoryOperand(useInstr, tag)
}
}
/**
* Provides wrappers for the constructors of each branch of `TOperand` that is used by the
* raw IR stage.
* These wrappers are not parameterized because it is not possible to invoke an IPA constructor via
* a class alias.
*/
module RawOperands {
import Shared
class TPhiOperand = Internal::TNoOperand;
class TChiOperand = Internal::TNoOperand;
class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand;
/**
* Returns the Phi operand with the specified parameters.
*/
TPhiOperand phiOperand(
Raw::PhiInstruction useInstr, Raw::Instruction defInstr, Raw::IRBlock predecessorBlock,
Overlap overlap
) {
none()
}
/**
* Returns the Chi operand with the specified parameters.
*/
TChiOperand chiOperand(Raw::Instruction useInstr, ChiOperandTag tag) { none() }
}
/**
* Provides wrappers for the constructors of each branch of `TOperand` that is used by the
* unaliased SSA stage.
* These wrappers are not parameterized because it is not possible to invoke an IPA constructor via
* a class alias.
*/
module UnaliasedSSAOperands {
import Shared
class TPhiOperand = Internal::TUnaliasedPhiOperand;
class TChiOperand = Internal::TNoOperand;
class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand;
/**
* Returns the Phi operand with the specified parameters.
*/
TPhiOperand phiOperand(
Unaliased::PhiInstruction useInstr, Unaliased::Instruction defInstr,
Unaliased::IRBlock predecessorBlock, Overlap overlap
) {
result = Internal::TUnaliasedPhiOperand(useInstr, defInstr, predecessorBlock, overlap)
}
/**
* Returns the Chi operand with the specified parameters.
*/
TChiOperand chiOperand(Unaliased::Instruction useInstr, ChiOperandTag tag) { none() }
}
/**
* Provides wrappers for the constructors of each branch of `TOperand` that is used by the
* asliased SSA stage.
* These wrappers are not parameterized because it is not possible to invoke an IPA constructor via
* a class alias.
*/
module AliasedSSAOperands {
import Shared
class TPhiOperand = Internal::TAliasedPhiOperand;
class TChiOperand = Internal::TAliasedChiOperand;
class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand;
/**
* Returns the Phi operand with the specified parameters.
*/
TPhiOperand phiOperand(
TAliasedSSAPhiInstruction useInstr, Aliased::Instruction defInstr,
Aliased::IRBlock predecessorBlock, Overlap overlap
) {
result = Internal::TAliasedPhiOperand(useInstr, defInstr, predecessorBlock, overlap)
}
/**
* Returns the Chi operand with the specified parameters.
*/
TChiOperand chiOperand(TAliasedSSAChiInstruction useInstr, ChiOperandTag tag) {
result = Internal::TAliasedChiOperand(useInstr, tag)
}
}

View File

@@ -10,79 +10,32 @@ private import Imports::MemoryAccessKind
private import Imports::IRType
private import Imports::Overlap
private import Imports::OperandTag
cached
private newtype TOperand =
TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) {
defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and
not Construction::isInCycle(useInstr) and
strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1
} or
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
useInstr.getOpcode().hasOperand(tag)
} or
TPhiOperand(
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
) {
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
}
private import Imports::TOperand
private import internal.OperandInternal
/**
* Base class for all register operands. This is a placeholder for the IPA union type that we will
* eventually use for this purpose.
* An operand of an `Instruction` in this stage of the IR. Implemented as a union of the branches
* of `TOperand` that are used in this stage.
*/
private class RegisterOperandBase extends TRegisterOperand {
/** Gets a textual representation of this element. */
abstract string toString();
}
/**
* Returns the register operand with the specified parameters.
*/
private RegisterOperandBase registerOperand(
Instruction useInstr, RegisterOperandTag tag, Instruction defInstr
) {
result = TRegisterOperand(useInstr, tag, defInstr)
}
/**
* Base class for all non-Phi memory operands. This is a placeholder for the IPA union type that we
* will eventually use for this purpose.
*/
private class NonPhiMemoryOperandBase extends TNonPhiMemoryOperand {
/** Gets a textual representation of this element. */
abstract string toString();
}
/**
* Returns the non-Phi memory operand with the specified parameters.
*/
private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
result = TNonPhiMemoryOperand(useInstr, tag)
}
/**
* Base class for all Phi operands. This is a placeholder for the IPA union type that we will
* eventually use for this purpose.
*/
private class PhiOperandBase extends TPhiOperand {
abstract string toString();
}
/**
* Returns the Phi operand with the specified parameters.
*/
private PhiOperandBase phiOperand(
Instruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
) {
result = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap)
}
private class TStageOperand =
TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand;
/**
* An operand of an `Instruction`. The operand represents a use of the result of one instruction
* (the defining instruction) in another instruction (the use instruction)
*/
class Operand extends TOperand {
class Operand extends TStageOperand {
cached
Operand() {
// Ensure that the operand does not refer to instructions from earlier stages that are unreachable here
exists(Instruction use, Instruction def | this = registerOperand(use, _, def)) or
exists(Instruction use | this = nonSSAMemoryOperand(use, _)) or
exists(Instruction use, Instruction def, IRBlock predecessorBlock |
this = phiOperand(use, def, predecessorBlock, _)
) or
exists(Instruction use | this = chiOperand(use, _))
}
/** Gets a textual representation of this element. */
string toString() { result = "Operand" }
@@ -238,9 +191,11 @@ class Operand extends TOperand {
* An operand that consumes a memory result (e.g. the `LoadOperand` on a `Load` instruction).
*/
class MemoryOperand extends Operand {
cached
MemoryOperand() {
this instanceof NonPhiMemoryOperandBase or
this instanceof PhiOperandBase
this instanceof TNonSSAMemoryOperand or
this instanceof TPhiOperand or
this instanceof TChiOperand
}
/**
@@ -278,7 +233,8 @@ class NonPhiOperand extends Operand {
NonPhiOperand() {
this = registerOperand(useInstr, tag, _) or
this = nonPhiMemoryOperand(useInstr, tag)
this = nonSSAMemoryOperand(useInstr, tag) or
this = chiOperand(useInstr, tag)
}
final override Instruction getUse() { result = useInstr }
@@ -298,10 +254,11 @@ class NonPhiOperand extends Operand {
/**
* An operand that consumes a register (non-memory) result.
*/
class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
class RegisterOperand extends NonPhiOperand, TRegisterOperand {
override RegisterOperandTag tag;
Instruction defInstr;
cached
RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) }
final override string toString() { result = tag.toString() }
@@ -317,10 +274,15 @@ class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
/**
* A memory operand other than the operand of a `Phi` instruction.
*/
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase {
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand {
override MemoryOperandTag tag;
NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) }
cached
NonPhiMemoryOperand() {
this = nonSSAMemoryOperand(useInstr, tag)
or
this = chiOperand(useInstr, tag)
}
final override string toString() { result = tag.toString() }
@@ -462,12 +424,13 @@ class SideEffectOperand extends TypedOperand {
/**
* An operand of a `PhiInstruction`.
*/
class PhiInputOperand extends MemoryOperand, PhiOperandBase {
class PhiInputOperand extends MemoryOperand, TPhiOperand {
PhiInstruction useInstr;
Instruction defInstr;
IRBlock predecessorBlock;
Overlap overlap;
cached
PhiInputOperand() { this = phiOperand(useInstr, defInstr, predecessorBlock, overlap) }
override string toString() { result = "Phi" }

View File

@@ -2,3 +2,4 @@ import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
import semmle.code.cpp.ir.implementation.IRType as IRType
import semmle.code.cpp.ir.internal.Overlap as Overlap
import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag
import semmle.code.cpp.ir.implementation.internal.TOperand as TOperand

View File

@@ -0,0 +1,2 @@
private import semmle.code.cpp.ir.implementation.internal.TOperand
import RawOperands

View File

@@ -10,79 +10,32 @@ private import Imports::MemoryAccessKind
private import Imports::IRType
private import Imports::Overlap
private import Imports::OperandTag
cached
private newtype TOperand =
TRegisterOperand(Instruction useInstr, RegisterOperandTag tag, Instruction defInstr) {
defInstr = Construction::getRegisterOperandDefinition(useInstr, tag) and
not Construction::isInCycle(useInstr) and
strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1
} or
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
useInstr.getOpcode().hasOperand(tag)
} or
TPhiOperand(
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
) {
defInstr = Construction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
}
private import Imports::TOperand
private import internal.OperandInternal
/**
* Base class for all register operands. This is a placeholder for the IPA union type that we will
* eventually use for this purpose.
* An operand of an `Instruction` in this stage of the IR. Implemented as a union of the branches
* of `TOperand` that are used in this stage.
*/
private class RegisterOperandBase extends TRegisterOperand {
/** Gets a textual representation of this element. */
abstract string toString();
}
/**
* Returns the register operand with the specified parameters.
*/
private RegisterOperandBase registerOperand(
Instruction useInstr, RegisterOperandTag tag, Instruction defInstr
) {
result = TRegisterOperand(useInstr, tag, defInstr)
}
/**
* Base class for all non-Phi memory operands. This is a placeholder for the IPA union type that we
* will eventually use for this purpose.
*/
private class NonPhiMemoryOperandBase extends TNonPhiMemoryOperand {
/** Gets a textual representation of this element. */
abstract string toString();
}
/**
* Returns the non-Phi memory operand with the specified parameters.
*/
private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
result = TNonPhiMemoryOperand(useInstr, tag)
}
/**
* Base class for all Phi operands. This is a placeholder for the IPA union type that we will
* eventually use for this purpose.
*/
private class PhiOperandBase extends TPhiOperand {
abstract string toString();
}
/**
* Returns the Phi operand with the specified parameters.
*/
private PhiOperandBase phiOperand(
Instruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
) {
result = TPhiOperand(useInstr, defInstr, predecessorBlock, overlap)
}
private class TStageOperand =
TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand;
/**
* An operand of an `Instruction`. The operand represents a use of the result of one instruction
* (the defining instruction) in another instruction (the use instruction)
*/
class Operand extends TOperand {
class Operand extends TStageOperand {
cached
Operand() {
// Ensure that the operand does not refer to instructions from earlier stages that are unreachable here
exists(Instruction use, Instruction def | this = registerOperand(use, _, def)) or
exists(Instruction use | this = nonSSAMemoryOperand(use, _)) or
exists(Instruction use, Instruction def, IRBlock predecessorBlock |
this = phiOperand(use, def, predecessorBlock, _)
) or
exists(Instruction use | this = chiOperand(use, _))
}
/** Gets a textual representation of this element. */
string toString() { result = "Operand" }
@@ -238,9 +191,11 @@ class Operand extends TOperand {
* An operand that consumes a memory result (e.g. the `LoadOperand` on a `Load` instruction).
*/
class MemoryOperand extends Operand {
cached
MemoryOperand() {
this instanceof NonPhiMemoryOperandBase or
this instanceof PhiOperandBase
this instanceof TNonSSAMemoryOperand or
this instanceof TPhiOperand or
this instanceof TChiOperand
}
/**
@@ -278,7 +233,8 @@ class NonPhiOperand extends Operand {
NonPhiOperand() {
this = registerOperand(useInstr, tag, _) or
this = nonPhiMemoryOperand(useInstr, tag)
this = nonSSAMemoryOperand(useInstr, tag) or
this = chiOperand(useInstr, tag)
}
final override Instruction getUse() { result = useInstr }
@@ -298,10 +254,11 @@ class NonPhiOperand extends Operand {
/**
* An operand that consumes a register (non-memory) result.
*/
class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
class RegisterOperand extends NonPhiOperand, TRegisterOperand {
override RegisterOperandTag tag;
Instruction defInstr;
cached
RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) }
final override string toString() { result = tag.toString() }
@@ -317,10 +274,15 @@ class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
/**
* A memory operand other than the operand of a `Phi` instruction.
*/
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase {
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOperand {
override MemoryOperandTag tag;
NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) }
cached
NonPhiMemoryOperand() {
this = nonSSAMemoryOperand(useInstr, tag)
or
this = chiOperand(useInstr, tag)
}
final override string toString() { result = tag.toString() }
@@ -462,12 +424,13 @@ class SideEffectOperand extends TypedOperand {
/**
* An operand of a `PhiInstruction`.
*/
class PhiInputOperand extends MemoryOperand, PhiOperandBase {
class PhiInputOperand extends MemoryOperand, TPhiOperand {
PhiInstruction useInstr;
Instruction defInstr;
IRBlock predecessorBlock;
Overlap overlap;
cached
PhiInputOperand() { this = phiOperand(useInstr, defInstr, predecessorBlock, overlap) }
override string toString() { result = "Phi" }

View File

@@ -2,3 +2,4 @@ import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
import semmle.code.cpp.ir.implementation.IRType as IRType
import semmle.code.cpp.ir.internal.Overlap as Overlap
import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag
import semmle.code.cpp.ir.implementation.internal.TOperand as TOperand

View File

@@ -0,0 +1,2 @@
private import semmle.code.cpp.ir.implementation.internal.TOperand
import UnaliasedSSAOperands

View File

@@ -6,6 +6,7 @@ private import Imports::Overlap
private import Imports::TInstruction
private import Imports::RawIR as RawIR
private import SSAInstructions
private import SSAOperands
private import NewIR
private class OldBlock = Reachability::ReachableBlock;

View File

@@ -3,3 +3,4 @@ import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag
import semmle.code.cpp.ir.internal.Overlap as Overlap
import semmle.code.cpp.ir.implementation.internal.TInstruction as TInstruction
import semmle.code.cpp.ir.implementation.raw.IR as RawIR
import semmle.code.cpp.ir.implementation.internal.TOperand as TOperand

View File

@@ -6,3 +6,4 @@ import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as RawStage
import semmle.code.cpp.ir.implementation.internal.TInstruction::UnaliasedSSAInstructions as SSAInstructions
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import SimpleSSA as Alias
import semmle.code.cpp.ir.implementation.internal.TOperand::UnaliasedSSAOperands as SSAOperands