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:
Andrew Eisenberg
2021-08-16 17:23:27 -07:00
parent e566fb9c5a
commit 2c5dd2dfa3
421 changed files with 175 additions and 159 deletions

View File

@@ -0,0 +1 @@
import semmle.code.cpp.ir.internal.IRCppLanguage as Language

View File

@@ -0,0 +1 @@
import semmle.code.cpp.ir.internal.IRCppLanguage as Language

View File

@@ -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() }
}

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction

View File

@@ -0,0 +1 @@
import semmle.code.cpp.ir.internal.IRCppLanguage as Language

View File

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

View File

@@ -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) }

View File

@@ -0,0 +1 @@
import semmle.code.cpp.ir.internal.IRCppLanguage as Language

View File

@@ -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)
}

View File

@@ -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_;
}

View File

@@ -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)
}
}

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.IRType as IRType
import semmle.code.cpp.ir.implementation.Opcode as Opcode

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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_;
}