mirror of
https://github.com/github/codeql.git
synced 2026-05-03 20:58:03 +02:00
Packaging: Refactor the cpp libraries
This PR separates the core cpp packs into `codeql/cpp-queries` and `codeql/cpp-all`. There are very few lines of code changed. Almost all changes are moving files around.
This commit is contained in:
@@ -0,0 +1 @@
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Provides a base class, `IRFunctionBase`, for the stage-independent portions of `IRFunction`.
|
||||
*/
|
||||
|
||||
private import IRFunctionBaseInternal
|
||||
|
||||
private newtype TIRFunction =
|
||||
MkIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) }
|
||||
|
||||
/**
|
||||
* The IR for a function. This base class contains only the predicates that are the same between all
|
||||
* phases of the IR. Each instantiation of `IRFunction` extends this class.
|
||||
*/
|
||||
class IRFunctionBase extends TIRFunction {
|
||||
Language::Function func;
|
||||
|
||||
IRFunctionBase() { this = MkIRFunction(func) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
final string toString() { result = "IR: " + func.toString() }
|
||||
|
||||
/** Gets the function whose IR is represented. */
|
||||
final Language::Function getFunction() { result = func }
|
||||
|
||||
/** Gets the location of the function. */
|
||||
final Language::Location getLocation() { result = func.getLocation() }
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
|
||||
@@ -0,0 +1,298 @@
|
||||
/**
|
||||
* Defines the set of possible `OperandTag`s, which are used to identify the role each `Operand`
|
||||
* plays in the evaluation of its `Instruction`.
|
||||
*/
|
||||
|
||||
private import OperandTagInternal
|
||||
|
||||
private newtype TOperandTag =
|
||||
TAddressOperand() or
|
||||
TBufferSizeOperand() or
|
||||
TSideEffectOperand() or
|
||||
TLoadOperand() or
|
||||
TStoreValueOperand() or
|
||||
TUnaryOperand() or
|
||||
TLeftOperand() or
|
||||
TRightOperand() or
|
||||
TConditionOperand() or
|
||||
TCallTargetOperand() or
|
||||
TThisArgumentOperand() or
|
||||
TPositionalArgumentOperand(int argIndex) { Language::hasPositionalArgIndex(argIndex) } or
|
||||
TChiTotalOperand() or
|
||||
TChiPartialOperand() or
|
||||
TAsmOperand(int index) { Language::hasAsmOperandIndex(index) }
|
||||
|
||||
/**
|
||||
* Identifies the kind of operand on an instruction. Each `Instruction` has at
|
||||
* most one operand of any single `OperandTag`. The set of `OperandTag`s used by
|
||||
* an `Instruction` is determined by the instruction's opcode.
|
||||
*/
|
||||
abstract class OperandTag extends TOperandTag {
|
||||
/** Gets a textual representation of this operand tag */
|
||||
abstract string toString();
|
||||
|
||||
/**
|
||||
* Gets an integer that represents where this this operand will appear in the operand list of an
|
||||
* instruction when the IR is printed.
|
||||
*/
|
||||
abstract int getSortOrder();
|
||||
|
||||
/**
|
||||
* Gets a label that will appear before the operand when the IR is printed.
|
||||
*/
|
||||
final string getLabel() { if alwaysPrintLabel() then result = getId() + ":" else result = "" }
|
||||
|
||||
/**
|
||||
* Gets an identifier that uniquely identifies this operand within its instruction.
|
||||
*/
|
||||
abstract string getId();
|
||||
|
||||
/**
|
||||
* Holds if the operand should always be prefixed with its label in the dump of its instruction.
|
||||
*/
|
||||
predicate alwaysPrintLabel() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An operand that consumes a memory result (e.g. the `LoadOperand` on a `Load` instruction).
|
||||
*/
|
||||
abstract class MemoryOperandTag extends OperandTag { }
|
||||
|
||||
/**
|
||||
* An operand that consumes a register (non-memory) result.
|
||||
*/
|
||||
abstract class RegisterOperandTag extends OperandTag { }
|
||||
|
||||
/**
|
||||
* A memory operand whose type may be different from the result type of its definition instruction.
|
||||
*/
|
||||
abstract class TypedOperandTag extends MemoryOperandTag { }
|
||||
|
||||
// Note: individual subtypes are listed in the order that the operands should
|
||||
// appear in the operand list of the instruction when the IR is printed.
|
||||
/**
|
||||
* The address operand of an instruction that loads or stores a value from
|
||||
* memory (e.g. `Load`, `Store`, `InitializeParameter`, `IndirectReadSideEffect`).
|
||||
*/
|
||||
class AddressOperandTag extends RegisterOperandTag, TAddressOperand {
|
||||
final override string toString() { result = "Address" }
|
||||
|
||||
final override int getSortOrder() { result = 0 }
|
||||
|
||||
final override predicate alwaysPrintLabel() { any() }
|
||||
|
||||
final override string getId() { result = "&" }
|
||||
}
|
||||
|
||||
AddressOperandTag addressOperand() { result = TAddressOperand() }
|
||||
|
||||
/**
|
||||
* The buffer size operand of an instruction that represents a read or write of
|
||||
* a buffer.
|
||||
*/
|
||||
class BufferSizeOperandTag extends RegisterOperandTag, TBufferSizeOperand {
|
||||
final override string toString() { result = "BufferSize" }
|
||||
|
||||
final override int getSortOrder() { result = 1 }
|
||||
|
||||
final override string getId() { result = "size" }
|
||||
}
|
||||
|
||||
BufferSizeOperandTag bufferSizeOperand() { result = TBufferSizeOperand() }
|
||||
|
||||
/**
|
||||
* The operand representing the read side effect of a `SideEffectInstruction`.
|
||||
*/
|
||||
class SideEffectOperandTag extends TypedOperandTag, TSideEffectOperand {
|
||||
final override string toString() { result = "SideEffect" }
|
||||
|
||||
final override int getSortOrder() { result = 2 }
|
||||
|
||||
final override string getId() { result = "side_effect" }
|
||||
}
|
||||
|
||||
SideEffectOperandTag sideEffectOperand() { result = TSideEffectOperand() }
|
||||
|
||||
/**
|
||||
* The source value operand of an instruction that loads a value from memory (e.g. `Load`,
|
||||
* `ReturnValue`, `ThrowValue`).
|
||||
*/
|
||||
class LoadOperandTag extends TypedOperandTag, TLoadOperand {
|
||||
final override string toString() { result = "Load" }
|
||||
|
||||
final override int getSortOrder() { result = 3 }
|
||||
|
||||
final override string getId() { result = "load" }
|
||||
}
|
||||
|
||||
LoadOperandTag loadOperand() { result = TLoadOperand() }
|
||||
|
||||
/**
|
||||
* The source value operand of a `Store` instruction.
|
||||
*/
|
||||
class StoreValueOperandTag extends RegisterOperandTag, TStoreValueOperand {
|
||||
final override string toString() { result = "StoreValue" }
|
||||
|
||||
final override int getSortOrder() { result = 4 }
|
||||
|
||||
final override string getId() { result = "store" }
|
||||
}
|
||||
|
||||
StoreValueOperandTag storeValueOperand() { result = TStoreValueOperand() }
|
||||
|
||||
/**
|
||||
* The sole operand of a unary instruction (e.g. `Convert`, `Negate`, `Copy`).
|
||||
*/
|
||||
class UnaryOperandTag extends RegisterOperandTag, TUnaryOperand {
|
||||
final override string toString() { result = "Unary" }
|
||||
|
||||
final override int getSortOrder() { result = 5 }
|
||||
|
||||
final override string getId() { result = "unary" }
|
||||
}
|
||||
|
||||
UnaryOperandTag unaryOperand() { result = TUnaryOperand() }
|
||||
|
||||
/**
|
||||
* The left operand of a binary instruction (e.g. `Add`, `CompareEQ`).
|
||||
*/
|
||||
class LeftOperandTag extends RegisterOperandTag, TLeftOperand {
|
||||
final override string toString() { result = "Left" }
|
||||
|
||||
final override int getSortOrder() { result = 6 }
|
||||
|
||||
final override string getId() { result = "left" }
|
||||
}
|
||||
|
||||
LeftOperandTag leftOperand() { result = TLeftOperand() }
|
||||
|
||||
/**
|
||||
* The right operand of a binary instruction (e.g. `Add`, `CompareEQ`).
|
||||
*/
|
||||
class RightOperandTag extends RegisterOperandTag, TRightOperand {
|
||||
final override string toString() { result = "Right" }
|
||||
|
||||
final override int getSortOrder() { result = 7 }
|
||||
|
||||
final override string getId() { result = "right" }
|
||||
}
|
||||
|
||||
RightOperandTag rightOperand() { result = TRightOperand() }
|
||||
|
||||
/**
|
||||
* The condition operand of a `ConditionalBranch` or `Switch` instruction.
|
||||
*/
|
||||
class ConditionOperandTag extends RegisterOperandTag, TConditionOperand {
|
||||
final override string toString() { result = "Condition" }
|
||||
|
||||
final override int getSortOrder() { result = 8 }
|
||||
|
||||
final override string getId() { result = "cond" }
|
||||
}
|
||||
|
||||
ConditionOperandTag conditionOperand() { result = TConditionOperand() }
|
||||
|
||||
/**
|
||||
* The operand representing the target function of an `Call` instruction.
|
||||
*/
|
||||
class CallTargetOperandTag extends RegisterOperandTag, TCallTargetOperand {
|
||||
final override string toString() { result = "CallTarget" }
|
||||
|
||||
final override int getSortOrder() { result = 10 }
|
||||
|
||||
final override predicate alwaysPrintLabel() { any() }
|
||||
|
||||
final override string getId() { result = "func" }
|
||||
}
|
||||
|
||||
CallTargetOperandTag callTargetOperand() { result = TCallTargetOperand() }
|
||||
|
||||
/**
|
||||
* An operand representing an argument to a function call. This includes both
|
||||
* positional arguments (represented by `PositionalArgumentOperand`) and the
|
||||
* implicit `this` argument, if any (represented by `ThisArgumentOperand`).
|
||||
*/
|
||||
abstract class ArgumentOperandTag extends RegisterOperandTag { }
|
||||
|
||||
/**
|
||||
* An operand representing the implicit 'this' argument to a member function
|
||||
* call.
|
||||
*/
|
||||
class ThisArgumentOperandTag extends ArgumentOperandTag, TThisArgumentOperand {
|
||||
ThisArgumentOperandTag() { this = TThisArgumentOperand() }
|
||||
|
||||
final override string toString() { result = "Arg(this)" }
|
||||
|
||||
final override int getSortOrder() { result = 11 }
|
||||
|
||||
final override predicate alwaysPrintLabel() { any() }
|
||||
|
||||
final override string getId() { result = "this" }
|
||||
}
|
||||
|
||||
ThisArgumentOperandTag thisArgumentOperand() { result = TThisArgumentOperand() }
|
||||
|
||||
/**
|
||||
* An operand representing an argument to a function call.
|
||||
*/
|
||||
class PositionalArgumentOperandTag extends ArgumentOperandTag, TPositionalArgumentOperand {
|
||||
int argIndex;
|
||||
|
||||
PositionalArgumentOperandTag() { this = TPositionalArgumentOperand(argIndex) }
|
||||
|
||||
final override string toString() { result = "Arg(" + argIndex + ")" }
|
||||
|
||||
final override int getSortOrder() { result = 12 + argIndex }
|
||||
|
||||
final override predicate alwaysPrintLabel() { any() }
|
||||
|
||||
final int getArgIndex() { result = argIndex }
|
||||
|
||||
final override string getId() { result = argIndex.toString() }
|
||||
}
|
||||
|
||||
PositionalArgumentOperandTag positionalArgumentOperand(int argIndex) {
|
||||
result = TPositionalArgumentOperand(argIndex)
|
||||
}
|
||||
|
||||
abstract class ChiOperandTag extends MemoryOperandTag { }
|
||||
|
||||
class ChiTotalOperandTag extends ChiOperandTag, TChiTotalOperand {
|
||||
final override string toString() { result = "ChiTotal" }
|
||||
|
||||
final override int getSortOrder() { result = 13 }
|
||||
|
||||
final override predicate alwaysPrintLabel() { any() }
|
||||
|
||||
final override string getId() { result = "total" }
|
||||
}
|
||||
|
||||
ChiTotalOperandTag chiTotalOperand() { result = TChiTotalOperand() }
|
||||
|
||||
class ChiPartialOperandTag extends ChiOperandTag, TChiPartialOperand {
|
||||
final override string toString() { result = "ChiPartial" }
|
||||
|
||||
final override int getSortOrder() { result = 14 }
|
||||
|
||||
final override predicate alwaysPrintLabel() { any() }
|
||||
|
||||
final override string getId() { result = "partial" }
|
||||
}
|
||||
|
||||
ChiPartialOperandTag chiPartialOperand() { result = TChiPartialOperand() }
|
||||
|
||||
class AsmOperandTag extends RegisterOperandTag, TAsmOperand {
|
||||
int index;
|
||||
|
||||
AsmOperandTag() { this = TAsmOperand(index) }
|
||||
|
||||
final override string toString() { result = "AsmOperand(" + index + ")" }
|
||||
|
||||
final override int getSortOrder() { result = 15 + index }
|
||||
|
||||
final override predicate alwaysPrintLabel() { any() }
|
||||
|
||||
final override string getId() { result = index.toString() }
|
||||
}
|
||||
|
||||
AsmOperandTag asmOperand(int index) { result = TAsmOperand(index) }
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
@@ -0,0 +1,23 @@
|
||||
private import TIRVariableInternal
|
||||
private import Imports::TempVariableTag
|
||||
|
||||
newtype TIRVariable =
|
||||
TIRUserVariable(Language::Variable var, Language::LanguageType type, Language::Function func) {
|
||||
Construction::hasUserVariable(func, var, type)
|
||||
} or
|
||||
TIRTempVariable(
|
||||
Language::Function func, Language::AST ast, TempVariableTag tag, Language::LanguageType type
|
||||
) {
|
||||
Construction::hasTempVariable(func, ast, tag, type)
|
||||
} or
|
||||
TIRDynamicInitializationFlag(
|
||||
Language::Function func, Language::Variable var, Language::LanguageType type
|
||||
) {
|
||||
Construction::hasDynamicInitializationFlag(func, var, type)
|
||||
} or
|
||||
TIRStringLiteral(
|
||||
Language::Function func, Language::AST ast, Language::LanguageType type,
|
||||
Language::StringLiteral literal
|
||||
) {
|
||||
Construction::hasStringLiteral(func, ast, type, literal)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction::Raw as Construction
|
||||
private import semmle.code.cpp.ir.implementation.TempVariableTag as TempVariableTag_
|
||||
|
||||
module Imports {
|
||||
module TempVariableTag = TempVariableTag_;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
private import TInstructionInternal
|
||||
private import IRFunctionBase
|
||||
private import TInstructionImports as Imports
|
||||
private import Imports::IRType
|
||||
private import Imports::Opcode
|
||||
|
||||
/**
|
||||
* An IR instruction. `TInstruction` is shared across all phases of the IR. There are individual
|
||||
* branches of this type for instructions created directly from the AST (`TRawInstruction`) and for
|
||||
* instructions added by each stage of SSA construction (`T*PhiInstruction`, `T*ChiInstruction`,
|
||||
* `T*UnreachedInstruction`). Each stage then defines a `TStageInstruction` type that is a union of
|
||||
* all of the branches that can appear in that particular stage. The public `Instruction` class for
|
||||
* each phase extends the `TStageInstruction` type for that stage.
|
||||
*/
|
||||
cached
|
||||
newtype TInstruction =
|
||||
TRawInstruction(
|
||||
IRConstruction::Raw::InstructionTag1 tag1, IRConstruction::Raw::InstructionTag2 tag2
|
||||
) {
|
||||
IRConstruction::Raw::hasInstruction(tag1, tag2)
|
||||
} or
|
||||
TUnaliasedSSAPhiInstruction(
|
||||
TRawInstruction blockStartInstr, UnaliasedSSA::SSA::MemoryLocation memoryLocation
|
||||
) {
|
||||
UnaliasedSSA::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
|
||||
} or
|
||||
TUnaliasedSSAChiInstruction(TRawInstruction primaryInstruction) { none() } or
|
||||
TUnaliasedSSAUnreachedInstruction(IRFunctionBase irFunc) {
|
||||
UnaliasedSSA::SSA::hasUnreachedInstruction(irFunc)
|
||||
} or
|
||||
TAliasedSSAPhiInstruction(
|
||||
TRawInstruction blockStartInstr, AliasedSSA::SSA::MemoryLocation memoryLocation
|
||||
) {
|
||||
AliasedSSA::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
|
||||
} or
|
||||
TAliasedSSAChiInstruction(TRawInstruction primaryInstruction) {
|
||||
AliasedSSA::SSA::hasChiInstruction(primaryInstruction)
|
||||
} or
|
||||
TAliasedSSAUnreachedInstruction(IRFunctionBase irFunc) {
|
||||
AliasedSSA::SSA::hasUnreachedInstruction(irFunc)
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides wrappers for the constructors of each branch of `TInstruction` 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 UnaliasedSSAInstructions {
|
||||
class TPhiInstruction = TUnaliasedSSAPhiInstruction;
|
||||
|
||||
TPhiInstruction phiInstruction(
|
||||
TRawInstruction blockStartInstr, UnaliasedSSA::SSA::MemoryLocation memoryLocation
|
||||
) {
|
||||
result = TUnaliasedSSAPhiInstruction(blockStartInstr, memoryLocation)
|
||||
}
|
||||
|
||||
TRawInstruction reusedPhiInstruction(TRawInstruction blockStartInstr) { none() }
|
||||
|
||||
class TChiInstruction = TUnaliasedSSAChiInstruction;
|
||||
|
||||
TChiInstruction chiInstruction(TRawInstruction primaryInstruction) {
|
||||
result = TUnaliasedSSAChiInstruction(primaryInstruction)
|
||||
}
|
||||
|
||||
class TUnreachedInstruction = TUnaliasedSSAUnreachedInstruction;
|
||||
|
||||
TUnreachedInstruction unreachedInstruction(IRFunctionBase irFunc) {
|
||||
result = TUnaliasedSSAUnreachedInstruction(irFunc)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides wrappers for the constructors of each branch of `TInstruction` that is used by the
|
||||
* aliased SSA stage.
|
||||
* These wrappers are not parameterized because it is not possible to invoke an IPA constructor via
|
||||
* a class alias.
|
||||
*/
|
||||
module AliasedSSAInstructions {
|
||||
class TPhiInstruction = TAliasedSSAPhiInstruction or TUnaliasedSSAPhiInstruction;
|
||||
|
||||
TPhiInstruction phiInstruction(
|
||||
TRawInstruction blockStartInstr, AliasedSSA::SSA::MemoryLocation memoryLocation
|
||||
) {
|
||||
result = TAliasedSSAPhiInstruction(blockStartInstr, memoryLocation)
|
||||
}
|
||||
|
||||
TPhiInstruction reusedPhiInstruction(TRawInstruction blockStartInstr) {
|
||||
result = TUnaliasedSSAPhiInstruction(blockStartInstr, _)
|
||||
}
|
||||
|
||||
class TChiInstruction = TAliasedSSAChiInstruction;
|
||||
|
||||
TChiInstruction chiInstruction(TRawInstruction primaryInstruction) {
|
||||
result = TAliasedSSAChiInstruction(primaryInstruction)
|
||||
}
|
||||
|
||||
class TUnreachedInstruction = TAliasedSSAUnreachedInstruction;
|
||||
|
||||
TUnreachedInstruction unreachedInstruction(IRFunctionBase irFunc) {
|
||||
result = TAliasedSSAUnreachedInstruction(irFunc)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import semmle.code.cpp.ir.implementation.IRType as IRType
|
||||
import semmle.code.cpp.ir.implementation.Opcode as Opcode
|
||||
@@ -0,0 +1,4 @@
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as UnaliasedSSA
|
||||
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSAConstruction as AliasedSSA
|
||||
@@ -0,0 +1,208 @@
|
||||
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::IRBlock predecessorBlock, Overlap overlap
|
||||
) {
|
||||
exists(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::IRBlock predecessorBlock, Overlap overlap
|
||||
) {
|
||||
exists(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()
|
||||
}
|
||||
|
||||
TPhiOperand reusedPhiOperand(
|
||||
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
|
||||
) {
|
||||
defInstr = UnaliasedConstruction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap) and
|
||||
result = Internal::TUnaliasedPhiOperand(useInstr, predecessorBlock, overlap)
|
||||
}
|
||||
|
||||
TPhiOperand reusedPhiOperand(
|
||||
Unaliased::PhiInstruction useInstr, Unaliased::Instruction defInstr,
|
||||
Unaliased::IRBlock predecessorBlock, Overlap overlap
|
||||
) {
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 or Internal::TUnaliasedPhiOperand;
|
||||
|
||||
class TChiOperand = Internal::TAliasedChiOperand;
|
||||
|
||||
class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand;
|
||||
|
||||
/**
|
||||
* Returns the Phi operand with the specified parameters.
|
||||
*/
|
||||
TPhiOperand phiOperand(
|
||||
Aliased::PhiInstruction useInstr, Aliased::Instruction defInstr,
|
||||
Aliased::IRBlock predecessorBlock, Overlap overlap
|
||||
) {
|
||||
defInstr = AliasedConstruction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap) and
|
||||
result = Internal::TAliasedPhiOperand(useInstr, predecessorBlock, overlap)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Phi operand with the specified parameters.
|
||||
*/
|
||||
TPhiOperand reusedPhiOperand(
|
||||
Aliased::PhiInstruction useInstr, Aliased::Instruction defInstr,
|
||||
Aliased::IRBlock predecessorBlock, Overlap overlap
|
||||
) {
|
||||
exists(Unaliased::IRBlock oldBlock |
|
||||
predecessorBlock = AliasedConstruction::getNewBlock(oldBlock) and
|
||||
result = Internal::TUnaliasedPhiOperand(useInstr, oldBlock, _) and
|
||||
defInstr = AliasedConstruction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Chi operand with the specified parameters.
|
||||
*/
|
||||
TChiOperand chiOperand(TAliasedSSAChiInstruction useInstr, ChiOperandTag tag) {
|
||||
result = Internal::TAliasedChiOperand(useInstr, tag)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
private import semmle.code.cpp.ir.internal.TempVariableTag as TempVariableTag_
|
||||
|
||||
module Imports {
|
||||
module TempVariableTag = TempVariableTag_;
|
||||
}
|
||||
Reference in New Issue
Block a user