C++: Add Operand.getType()

This commit is contained in:
Dave Bartolomeo
2019-02-08 12:05:47 -08:00
parent fa2ef620ac
commit a54d86423a
11 changed files with 334 additions and 167 deletions

View File

@@ -63,6 +63,36 @@ class Operand extends TOperand {
int getDumpSortOrder() {
result = -1
}
/**
* Gets the type of the value consumed by this operand. This is usually the same as the
* result type of the definition instruction consumed by this operand. For register operands,
* this is always the case. For some memory operands, the operand type may be different from
* the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type.
*/
Type getType() {
result = getDefinitionInstruction().getResultType()
}
/**
* Holds if the value consumed by this operand is a glvalue. If this
* holds, the value of the operand represents the address of a location,
* and the type of the location is given by `getType()`. If this does
* not hold, the value of the operand represents a value whose type is
* given by `getResultType()`.
*/
predicate isGLValue() {
getDefinitionInstruction().isGLValue()
}
/**
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have
* a known constant size, this predicate does not hold.
*/
int getSize() {
result = getDefinitionInstruction().getResultSize()
}
}
/**
@@ -76,6 +106,11 @@ class MemoryOperand extends Operand {
this = TPhiOperand(_, _, _)
}
override predicate isGLValue() {
// A `MemoryOperand` can never be a glvalue
none()
}
/**
* Gets the kind of memory access performed by the operand.
*/
@@ -109,16 +144,16 @@ class RegisterOperand extends Operand {
* An operand that is not an operand of a `PhiInstruction`.
*/
class NonPhiOperand extends Operand, TNonPhiOperand {
Instruction instr;
Instruction useInstr;
Instruction defInstr;
OperandTag tag;
NonPhiOperand() {
this = TNonPhiOperand(instr, tag, defInstr)
this = TNonPhiOperand(useInstr, tag, defInstr)
}
override final Instruction getUseInstruction() {
result = instr
result = useInstr
}
override final Instruction getDefinitionInstruction() {
@@ -138,14 +173,20 @@ class NonPhiOperand extends Operand, TNonPhiOperand {
}
}
class TypedOperand extends NonPhiOperand, MemoryOperand {
override TypedOperandTag tag;
override final Type getType() {
result = Construction::getInstructionOperandType(useInstr, tag)
}
}
/**
* The address operand of an instruction that loads or stores a value from
* memory (e.g. `Load`, `Store`).
*/
class AddressOperand extends NonPhiOperand, RegisterOperand {
AddressOperand() {
this = TNonPhiOperand(_, addressOperand(), _)
}
override AddressOperandTag tag;
override string toString() {
result = "Address"
@@ -156,10 +197,8 @@ class AddressOperand extends NonPhiOperand, RegisterOperand {
* The source value operand of an instruction that loads a value from memory (e.g. `Load`,
* `ReturnValue`, `ThrowValue`).
*/
class LoadOperand extends NonPhiOperand, MemoryOperand {
LoadOperand() {
this = TNonPhiOperand(_, loadOperand(), _)
}
class LoadOperand extends TypedOperand {
override LoadOperandTag tag;
override string toString() {
result = "Load"
@@ -174,9 +213,7 @@ class LoadOperand extends NonPhiOperand, MemoryOperand {
* The source value operand of a `Store` instruction.
*/
class StoreValueOperand extends NonPhiOperand, RegisterOperand {
StoreValueOperand() {
this = TNonPhiOperand(_, storeValueOperand(), _)
}
override StoreValueOperandTag tag;
override string toString() {
result = "StoreValue"
@@ -187,9 +224,7 @@ class StoreValueOperand extends NonPhiOperand, RegisterOperand {
* The sole operand of a unary instruction (e.g. `Convert`, `Negate`, `Copy`).
*/
class UnaryOperand extends NonPhiOperand, RegisterOperand {
UnaryOperand() {
this = TNonPhiOperand(_, unaryOperand(), _)
}
override UnaryOperandTag tag;
override string toString() {
result = "Unary"
@@ -200,9 +235,7 @@ class UnaryOperand extends NonPhiOperand, RegisterOperand {
* The left operand of a binary instruction (e.g. `Add`, `CompareEQ`).
*/
class LeftOperand extends NonPhiOperand, RegisterOperand {
LeftOperand() {
this = TNonPhiOperand(_, leftOperand(), _)
}
override LeftOperandTag tag;
override string toString() {
result = "Left"
@@ -213,9 +246,7 @@ class LeftOperand extends NonPhiOperand, RegisterOperand {
* The right operand of a binary instruction (e.g. `Add`, `CompareEQ`).
*/
class RightOperand extends NonPhiOperand, RegisterOperand {
RightOperand() {
this = TNonPhiOperand(_, rightOperand(), _)
}
override RightOperandTag tag;
override string toString() {
result = "Right"
@@ -226,9 +257,7 @@ class RightOperand extends NonPhiOperand, RegisterOperand {
* The condition operand of a `ConditionalBranch` or `Switch` instruction.
*/
class ConditionOperand extends NonPhiOperand, RegisterOperand {
ConditionOperand() {
this = TNonPhiOperand(_, conditionOperand(), _)
}
override ConditionOperandTag tag;
override string toString() {
result = "Condition"
@@ -240,9 +269,7 @@ class ConditionOperand extends NonPhiOperand, RegisterOperand {
* whose set of uses is unknown.
*/
class UnmodeledUseOperand extends NonPhiOperand, MemoryOperand {
UnmodeledUseOperand() {
this = TNonPhiOperand(_, unmodeledUseOperand(), _)
}
override UnmodeledUseOperandTag tag;
override string toString() {
result = "UnmodeledUse"
@@ -257,9 +284,7 @@ class UnmodeledUseOperand extends NonPhiOperand, MemoryOperand {
* The operand representing the target function of an `Call` instruction.
*/
class CallTargetOperand extends NonPhiOperand, RegisterOperand {
CallTargetOperand() {
this = TNonPhiOperand(_, callTargetOperand(), _)
}
override CallTargetOperandTag tag;
override string toString() {
result = "CallTarget"
@@ -272,11 +297,7 @@ class CallTargetOperand extends NonPhiOperand, RegisterOperand {
* implicit `this` argument, if any (represented by `ThisArgumentOperand`).
*/
class ArgumentOperand extends NonPhiOperand, RegisterOperand {
ArgumentOperand() {
exists(ArgumentOperandTag argTag |
this = TNonPhiOperand(_, argTag, _)
)
}
override ArgumentOperandTag tag;
}
/**
@@ -284,9 +305,7 @@ class ArgumentOperand extends NonPhiOperand, RegisterOperand {
* call.
*/
class ThisArgumentOperand extends ArgumentOperand {
ThisArgumentOperand() {
this = TNonPhiOperand(_, thisArgumentOperand(), _)
}
override ThisArgumentOperandTag tag;
override string toString() {
result = "ThisArgument"
@@ -297,13 +316,11 @@ class ThisArgumentOperand extends ArgumentOperand {
* An operand representing an argument to a function call.
*/
class PositionalArgumentOperand extends ArgumentOperand {
override PositionalArgumentOperandTag tag;
int argIndex;
PositionalArgumentOperand() {
exists(PositionalArgumentOperandTag argTag |
this = TNonPhiOperand(_, argTag, _) and
argIndex = argTag.getArgIndex()
)
argIndex = tag.getArgIndex()
}
override string toString() {
@@ -318,34 +335,39 @@ class PositionalArgumentOperand extends ArgumentOperand {
}
}
class SideEffectOperand extends NonPhiOperand, MemoryOperand {
SideEffectOperand() {
this = TNonPhiOperand(_, sideEffectOperand(), _)
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override final int getSize() {
if getType() instanceof UnknownType then
result = Construction::getInstructionOperandSize(useInstr, tag)
else
result = getType().getSize()
}
override MemoryAccessKind getMemoryAccess() {
instr instanceof CallSideEffectInstruction and
useInstr instanceof CallSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
instr instanceof CallReadSideEffectInstruction and
useInstr instanceof CallReadSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
instr instanceof IndirectReadSideEffectInstruction and
useInstr instanceof IndirectReadSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
instr instanceof BufferReadSideEffectInstruction and
useInstr instanceof BufferReadSideEffectInstruction and
result instanceof BufferMemoryAccess
or
instr instanceof IndirectWriteSideEffectInstruction and
useInstr instanceof IndirectWriteSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
instr instanceof BufferWriteSideEffectInstruction and
useInstr instanceof BufferWriteSideEffectInstruction and
result instanceof BufferMemoryAccess
or
instr instanceof IndirectMayWriteSideEffectInstruction and
useInstr instanceof IndirectMayWriteSideEffectInstruction and
result instanceof IndirectMayMemoryAccess
or
instr instanceof BufferMayWriteSideEffectInstruction and
useInstr instanceof BufferMayWriteSideEffectInstruction and
result instanceof BufferMayMemoryAccess
}
}

View File

@@ -128,6 +128,26 @@ cached private module Cached {
result = getChiInstructionTotalOperand(instruction)
}
cached Type getInstructionOperandType(Instruction instr, TypedOperandTag tag) {
exists(OldInstruction oldInstruction, OldIR::TypedOperand oldOperand |
oldInstruction = getOldInstruction(instr) and
oldOperand = oldInstruction.getAnOperand() and
tag = oldOperand.getOperandTag() and
result = oldOperand.getType()
)
}
cached int getInstructionOperandSize(Instruction instr, SideEffectOperandTag tag) {
exists(OldInstruction oldInstruction, OldIR::SideEffectOperand oldOperand |
oldInstruction = getOldInstruction(instr) and
oldOperand = oldInstruction.getAnOperand() and
tag = oldOperand.getOperandTag() and
// Only return a result for operands that need an explicit result size.
oldOperand.getType() instanceof UnknownType and
result = oldOperand.getSize()
)
}
cached Instruction getPhiInstructionOperandDefinition(PhiInstruction instr,
IRBlock newPredecessorBlock) {
exists(Alias::VirtualVariable vvar, OldBlock phiBlock,

View File

@@ -63,6 +63,36 @@ class Operand extends TOperand {
int getDumpSortOrder() {
result = -1
}
/**
* Gets the type of the value consumed by this operand. This is usually the same as the
* result type of the definition instruction consumed by this operand. For register operands,
* this is always the case. For some memory operands, the operand type may be different from
* the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type.
*/
Type getType() {
result = getDefinitionInstruction().getResultType()
}
/**
* Holds if the value consumed by this operand is a glvalue. If this
* holds, the value of the operand represents the address of a location,
* and the type of the location is given by `getType()`. If this does
* not hold, the value of the operand represents a value whose type is
* given by `getResultType()`.
*/
predicate isGLValue() {
getDefinitionInstruction().isGLValue()
}
/**
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have
* a known constant size, this predicate does not hold.
*/
int getSize() {
result = getDefinitionInstruction().getResultSize()
}
}
/**
@@ -76,6 +106,11 @@ class MemoryOperand extends Operand {
this = TPhiOperand(_, _, _)
}
override predicate isGLValue() {
// A `MemoryOperand` can never be a glvalue
none()
}
/**
* Gets the kind of memory access performed by the operand.
*/
@@ -109,16 +144,16 @@ class RegisterOperand extends Operand {
* An operand that is not an operand of a `PhiInstruction`.
*/
class NonPhiOperand extends Operand, TNonPhiOperand {
Instruction instr;
Instruction useInstr;
Instruction defInstr;
OperandTag tag;
NonPhiOperand() {
this = TNonPhiOperand(instr, tag, defInstr)
this = TNonPhiOperand(useInstr, tag, defInstr)
}
override final Instruction getUseInstruction() {
result = instr
result = useInstr
}
override final Instruction getDefinitionInstruction() {
@@ -138,14 +173,20 @@ class NonPhiOperand extends Operand, TNonPhiOperand {
}
}
class TypedOperand extends NonPhiOperand, MemoryOperand {
override TypedOperandTag tag;
override final Type getType() {
result = Construction::getInstructionOperandType(useInstr, tag)
}
}
/**
* The address operand of an instruction that loads or stores a value from
* memory (e.g. `Load`, `Store`).
*/
class AddressOperand extends NonPhiOperand, RegisterOperand {
AddressOperand() {
this = TNonPhiOperand(_, addressOperand(), _)
}
override AddressOperandTag tag;
override string toString() {
result = "Address"
@@ -156,10 +197,8 @@ class AddressOperand extends NonPhiOperand, RegisterOperand {
* The source value operand of an instruction that loads a value from memory (e.g. `Load`,
* `ReturnValue`, `ThrowValue`).
*/
class LoadOperand extends NonPhiOperand, MemoryOperand {
LoadOperand() {
this = TNonPhiOperand(_, loadOperand(), _)
}
class LoadOperand extends TypedOperand {
override LoadOperandTag tag;
override string toString() {
result = "Load"
@@ -174,9 +213,7 @@ class LoadOperand extends NonPhiOperand, MemoryOperand {
* The source value operand of a `Store` instruction.
*/
class StoreValueOperand extends NonPhiOperand, RegisterOperand {
StoreValueOperand() {
this = TNonPhiOperand(_, storeValueOperand(), _)
}
override StoreValueOperandTag tag;
override string toString() {
result = "StoreValue"
@@ -187,9 +224,7 @@ class StoreValueOperand extends NonPhiOperand, RegisterOperand {
* The sole operand of a unary instruction (e.g. `Convert`, `Negate`, `Copy`).
*/
class UnaryOperand extends NonPhiOperand, RegisterOperand {
UnaryOperand() {
this = TNonPhiOperand(_, unaryOperand(), _)
}
override UnaryOperandTag tag;
override string toString() {
result = "Unary"
@@ -200,9 +235,7 @@ class UnaryOperand extends NonPhiOperand, RegisterOperand {
* The left operand of a binary instruction (e.g. `Add`, `CompareEQ`).
*/
class LeftOperand extends NonPhiOperand, RegisterOperand {
LeftOperand() {
this = TNonPhiOperand(_, leftOperand(), _)
}
override LeftOperandTag tag;
override string toString() {
result = "Left"
@@ -213,9 +246,7 @@ class LeftOperand extends NonPhiOperand, RegisterOperand {
* The right operand of a binary instruction (e.g. `Add`, `CompareEQ`).
*/
class RightOperand extends NonPhiOperand, RegisterOperand {
RightOperand() {
this = TNonPhiOperand(_, rightOperand(), _)
}
override RightOperandTag tag;
override string toString() {
result = "Right"
@@ -226,9 +257,7 @@ class RightOperand extends NonPhiOperand, RegisterOperand {
* The condition operand of a `ConditionalBranch` or `Switch` instruction.
*/
class ConditionOperand extends NonPhiOperand, RegisterOperand {
ConditionOperand() {
this = TNonPhiOperand(_, conditionOperand(), _)
}
override ConditionOperandTag tag;
override string toString() {
result = "Condition"
@@ -240,9 +269,7 @@ class ConditionOperand extends NonPhiOperand, RegisterOperand {
* whose set of uses is unknown.
*/
class UnmodeledUseOperand extends NonPhiOperand, MemoryOperand {
UnmodeledUseOperand() {
this = TNonPhiOperand(_, unmodeledUseOperand(), _)
}
override UnmodeledUseOperandTag tag;
override string toString() {
result = "UnmodeledUse"
@@ -257,9 +284,7 @@ class UnmodeledUseOperand extends NonPhiOperand, MemoryOperand {
* The operand representing the target function of an `Call` instruction.
*/
class CallTargetOperand extends NonPhiOperand, RegisterOperand {
CallTargetOperand() {
this = TNonPhiOperand(_, callTargetOperand(), _)
}
override CallTargetOperandTag tag;
override string toString() {
result = "CallTarget"
@@ -272,11 +297,7 @@ class CallTargetOperand extends NonPhiOperand, RegisterOperand {
* implicit `this` argument, if any (represented by `ThisArgumentOperand`).
*/
class ArgumentOperand extends NonPhiOperand, RegisterOperand {
ArgumentOperand() {
exists(ArgumentOperandTag argTag |
this = TNonPhiOperand(_, argTag, _)
)
}
override ArgumentOperandTag tag;
}
/**
@@ -284,9 +305,7 @@ class ArgumentOperand extends NonPhiOperand, RegisterOperand {
* call.
*/
class ThisArgumentOperand extends ArgumentOperand {
ThisArgumentOperand() {
this = TNonPhiOperand(_, thisArgumentOperand(), _)
}
override ThisArgumentOperandTag tag;
override string toString() {
result = "ThisArgument"
@@ -297,13 +316,11 @@ class ThisArgumentOperand extends ArgumentOperand {
* An operand representing an argument to a function call.
*/
class PositionalArgumentOperand extends ArgumentOperand {
override PositionalArgumentOperandTag tag;
int argIndex;
PositionalArgumentOperand() {
exists(PositionalArgumentOperandTag argTag |
this = TNonPhiOperand(_, argTag, _) and
argIndex = argTag.getArgIndex()
)
argIndex = tag.getArgIndex()
}
override string toString() {
@@ -318,34 +335,39 @@ class PositionalArgumentOperand extends ArgumentOperand {
}
}
class SideEffectOperand extends NonPhiOperand, MemoryOperand {
SideEffectOperand() {
this = TNonPhiOperand(_, sideEffectOperand(), _)
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override final int getSize() {
if getType() instanceof UnknownType then
result = Construction::getInstructionOperandSize(useInstr, tag)
else
result = getType().getSize()
}
override MemoryAccessKind getMemoryAccess() {
instr instanceof CallSideEffectInstruction and
useInstr instanceof CallSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
instr instanceof CallReadSideEffectInstruction and
useInstr instanceof CallReadSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
instr instanceof IndirectReadSideEffectInstruction and
useInstr instanceof IndirectReadSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
instr instanceof BufferReadSideEffectInstruction and
useInstr instanceof BufferReadSideEffectInstruction and
result instanceof BufferMemoryAccess
or
instr instanceof IndirectWriteSideEffectInstruction and
useInstr instanceof IndirectWriteSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
instr instanceof BufferWriteSideEffectInstruction and
useInstr instanceof BufferWriteSideEffectInstruction and
result instanceof BufferMemoryAccess
or
instr instanceof IndirectMayWriteSideEffectInstruction and
useInstr instanceof IndirectMayWriteSideEffectInstruction and
result instanceof IndirectMayMemoryAccess
or
instr instanceof BufferMayWriteSideEffectInstruction and
useInstr instanceof BufferMayWriteSideEffectInstruction and
result instanceof BufferMayMemoryAccess
}
}

View File

@@ -64,6 +64,22 @@ cached private module Cached {
getInstructionTag(instruction), tag)
}
cached Type getInstructionOperandType(Instruction instruction, TypedOperandTag tag) {
// For all `LoadInstruction`s, the operand type of the `LoadOperand` is the same as
// the result type of the load.
result = instruction.(LoadInstruction).getResultType() or
(
not instruction instanceof LoadInstruction and
result = getInstructionTranslatedElement(instruction).getInstructionOperandType(
getInstructionTag(instruction), tag)
)
}
cached int getInstructionOperandSize(Instruction instruction, SideEffectOperandTag tag) {
result = getInstructionTranslatedElement(instruction).getInstructionOperandSize(
getInstructionTag(instruction), tag)
}
cached Instruction getPhiInstructionOperandDefinition(Instruction instruction,
IRBlock predecessorBlock) {
none()

View File

@@ -112,11 +112,20 @@ abstract class TranslatedCall extends TranslatedExpr {
) or
(
tag = CallSideEffectTag() and
hasSideEffect() and
operandTag instanceof SideEffectOperandTag and
result = getEnclosingFunction().getUnmodeledDefinitionInstruction()
)
}
override final Type getInstructionOperandType(InstructionTag tag,
TypedOperandTag operandTag) {
tag = CallSideEffectTag() and
hasSideEffect() and
operandTag instanceof SideEffectOperandTag and
result instanceof UnknownType
}
override final Instruction getResult() {
result = getInstruction(CallTag())
}

View File

@@ -624,6 +624,21 @@ abstract class TranslatedElement extends TTranslatedElement {
none()
}
/**
* Gets the type of the memory operand specified by `operandTag` on the the instruction specified by `tag`.
*/
Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
none()
}
/**
* Gets the size of the memory operand specified by `operandTag` on the the instruction specified by `tag`.
* Only holds for operands whose type is `UnknownType`.
*/
int getInstructionOperandSize(InstructionTag tag, SideEffectOperandTag operandTag) {
none()
}
/**
* Gets the instruction generated by this element with tag `tag`.
*/

View File

@@ -2314,6 +2314,13 @@ class TranslatedThrowValueExpr extends TranslatedThrowExpr,
)
}
override final Type getInstructionOperandType(InstructionTag tag,
TypedOperandTag operandTag) {
tag = ThrowTag() and
operandTag instanceof LoadOperandTag and
result = getExceptionType()
}
override Instruction getTargetAddress() {
result = getInstruction(InitializerVariableAddressTag())
}

View File

@@ -248,6 +248,14 @@ class TranslatedFunction extends TranslatedElement,
)
}
override final Type getInstructionOperandType(InstructionTag tag,
TypedOperandTag operandTag) {
tag = ReturnTag() and
not getReturnType() instanceof VoidType and
operandTag instanceof LoadOperandTag and
result = getReturnType()
}
override final IRVariable getInstructionVariable(InstructionTag tag) {
tag = ReturnValueAddressTag() and
result = getReturnVariable()

View File

@@ -63,6 +63,36 @@ class Operand extends TOperand {
int getDumpSortOrder() {
result = -1
}
/**
* Gets the type of the value consumed by this operand. This is usually the same as the
* result type of the definition instruction consumed by this operand. For register operands,
* this is always the case. For some memory operands, the operand type may be different from
* the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type.
*/
Type getType() {
result = getDefinitionInstruction().getResultType()
}
/**
* Holds if the value consumed by this operand is a glvalue. If this
* holds, the value of the operand represents the address of a location,
* and the type of the location is given by `getType()`. If this does
* not hold, the value of the operand represents a value whose type is
* given by `getResultType()`.
*/
predicate isGLValue() {
getDefinitionInstruction().isGLValue()
}
/**
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have
* a known constant size, this predicate does not hold.
*/
int getSize() {
result = getDefinitionInstruction().getResultSize()
}
}
/**
@@ -76,6 +106,11 @@ class MemoryOperand extends Operand {
this = TPhiOperand(_, _, _)
}
override predicate isGLValue() {
// A `MemoryOperand` can never be a glvalue
none()
}
/**
* Gets the kind of memory access performed by the operand.
*/
@@ -109,16 +144,16 @@ class RegisterOperand extends Operand {
* An operand that is not an operand of a `PhiInstruction`.
*/
class NonPhiOperand extends Operand, TNonPhiOperand {
Instruction instr;
Instruction useInstr;
Instruction defInstr;
OperandTag tag;
NonPhiOperand() {
this = TNonPhiOperand(instr, tag, defInstr)
this = TNonPhiOperand(useInstr, tag, defInstr)
}
override final Instruction getUseInstruction() {
result = instr
result = useInstr
}
override final Instruction getDefinitionInstruction() {
@@ -138,14 +173,20 @@ class NonPhiOperand extends Operand, TNonPhiOperand {
}
}
class TypedOperand extends NonPhiOperand, MemoryOperand {
override TypedOperandTag tag;
override final Type getType() {
result = Construction::getInstructionOperandType(useInstr, tag)
}
}
/**
* The address operand of an instruction that loads or stores a value from
* memory (e.g. `Load`, `Store`).
*/
class AddressOperand extends NonPhiOperand, RegisterOperand {
AddressOperand() {
this = TNonPhiOperand(_, addressOperand(), _)
}
override AddressOperandTag tag;
override string toString() {
result = "Address"
@@ -156,10 +197,8 @@ class AddressOperand extends NonPhiOperand, RegisterOperand {
* The source value operand of an instruction that loads a value from memory (e.g. `Load`,
* `ReturnValue`, `ThrowValue`).
*/
class LoadOperand extends NonPhiOperand, MemoryOperand {
LoadOperand() {
this = TNonPhiOperand(_, loadOperand(), _)
}
class LoadOperand extends TypedOperand {
override LoadOperandTag tag;
override string toString() {
result = "Load"
@@ -174,9 +213,7 @@ class LoadOperand extends NonPhiOperand, MemoryOperand {
* The source value operand of a `Store` instruction.
*/
class StoreValueOperand extends NonPhiOperand, RegisterOperand {
StoreValueOperand() {
this = TNonPhiOperand(_, storeValueOperand(), _)
}
override StoreValueOperandTag tag;
override string toString() {
result = "StoreValue"
@@ -187,9 +224,7 @@ class StoreValueOperand extends NonPhiOperand, RegisterOperand {
* The sole operand of a unary instruction (e.g. `Convert`, `Negate`, `Copy`).
*/
class UnaryOperand extends NonPhiOperand, RegisterOperand {
UnaryOperand() {
this = TNonPhiOperand(_, unaryOperand(), _)
}
override UnaryOperandTag tag;
override string toString() {
result = "Unary"
@@ -200,9 +235,7 @@ class UnaryOperand extends NonPhiOperand, RegisterOperand {
* The left operand of a binary instruction (e.g. `Add`, `CompareEQ`).
*/
class LeftOperand extends NonPhiOperand, RegisterOperand {
LeftOperand() {
this = TNonPhiOperand(_, leftOperand(), _)
}
override LeftOperandTag tag;
override string toString() {
result = "Left"
@@ -213,9 +246,7 @@ class LeftOperand extends NonPhiOperand, RegisterOperand {
* The right operand of a binary instruction (e.g. `Add`, `CompareEQ`).
*/
class RightOperand extends NonPhiOperand, RegisterOperand {
RightOperand() {
this = TNonPhiOperand(_, rightOperand(), _)
}
override RightOperandTag tag;
override string toString() {
result = "Right"
@@ -226,9 +257,7 @@ class RightOperand extends NonPhiOperand, RegisterOperand {
* The condition operand of a `ConditionalBranch` or `Switch` instruction.
*/
class ConditionOperand extends NonPhiOperand, RegisterOperand {
ConditionOperand() {
this = TNonPhiOperand(_, conditionOperand(), _)
}
override ConditionOperandTag tag;
override string toString() {
result = "Condition"
@@ -240,9 +269,7 @@ class ConditionOperand extends NonPhiOperand, RegisterOperand {
* whose set of uses is unknown.
*/
class UnmodeledUseOperand extends NonPhiOperand, MemoryOperand {
UnmodeledUseOperand() {
this = TNonPhiOperand(_, unmodeledUseOperand(), _)
}
override UnmodeledUseOperandTag tag;
override string toString() {
result = "UnmodeledUse"
@@ -257,9 +284,7 @@ class UnmodeledUseOperand extends NonPhiOperand, MemoryOperand {
* The operand representing the target function of an `Call` instruction.
*/
class CallTargetOperand extends NonPhiOperand, RegisterOperand {
CallTargetOperand() {
this = TNonPhiOperand(_, callTargetOperand(), _)
}
override CallTargetOperandTag tag;
override string toString() {
result = "CallTarget"
@@ -272,11 +297,7 @@ class CallTargetOperand extends NonPhiOperand, RegisterOperand {
* implicit `this` argument, if any (represented by `ThisArgumentOperand`).
*/
class ArgumentOperand extends NonPhiOperand, RegisterOperand {
ArgumentOperand() {
exists(ArgumentOperandTag argTag |
this = TNonPhiOperand(_, argTag, _)
)
}
override ArgumentOperandTag tag;
}
/**
@@ -284,9 +305,7 @@ class ArgumentOperand extends NonPhiOperand, RegisterOperand {
* call.
*/
class ThisArgumentOperand extends ArgumentOperand {
ThisArgumentOperand() {
this = TNonPhiOperand(_, thisArgumentOperand(), _)
}
override ThisArgumentOperandTag tag;
override string toString() {
result = "ThisArgument"
@@ -297,13 +316,11 @@ class ThisArgumentOperand extends ArgumentOperand {
* An operand representing an argument to a function call.
*/
class PositionalArgumentOperand extends ArgumentOperand {
override PositionalArgumentOperandTag tag;
int argIndex;
PositionalArgumentOperand() {
exists(PositionalArgumentOperandTag argTag |
this = TNonPhiOperand(_, argTag, _) and
argIndex = argTag.getArgIndex()
)
argIndex = tag.getArgIndex()
}
override string toString() {
@@ -318,34 +335,39 @@ class PositionalArgumentOperand extends ArgumentOperand {
}
}
class SideEffectOperand extends NonPhiOperand, MemoryOperand {
SideEffectOperand() {
this = TNonPhiOperand(_, sideEffectOperand(), _)
class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override final int getSize() {
if getType() instanceof UnknownType then
result = Construction::getInstructionOperandSize(useInstr, tag)
else
result = getType().getSize()
}
override MemoryAccessKind getMemoryAccess() {
instr instanceof CallSideEffectInstruction and
useInstr instanceof CallSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
instr instanceof CallReadSideEffectInstruction and
useInstr instanceof CallReadSideEffectInstruction and
result instanceof EscapedMemoryAccess
or
instr instanceof IndirectReadSideEffectInstruction and
useInstr instanceof IndirectReadSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
instr instanceof BufferReadSideEffectInstruction and
useInstr instanceof BufferReadSideEffectInstruction and
result instanceof BufferMemoryAccess
or
instr instanceof IndirectWriteSideEffectInstruction and
useInstr instanceof IndirectWriteSideEffectInstruction and
result instanceof IndirectMemoryAccess
or
instr instanceof BufferWriteSideEffectInstruction and
useInstr instanceof BufferWriteSideEffectInstruction and
result instanceof BufferMemoryAccess
or
instr instanceof IndirectMayWriteSideEffectInstruction and
useInstr instanceof IndirectMayWriteSideEffectInstruction and
result instanceof IndirectMayMemoryAccess
or
instr instanceof BufferMayWriteSideEffectInstruction and
useInstr instanceof BufferMayWriteSideEffectInstruction and
result instanceof BufferMayMemoryAccess
}
}

View File

@@ -128,6 +128,26 @@ cached private module Cached {
result = getChiInstructionTotalOperand(instruction)
}
cached Type getInstructionOperandType(Instruction instr, TypedOperandTag tag) {
exists(OldInstruction oldInstruction, OldIR::TypedOperand oldOperand |
oldInstruction = getOldInstruction(instr) and
oldOperand = oldInstruction.getAnOperand() and
tag = oldOperand.getOperandTag() and
result = oldOperand.getType()
)
}
cached int getInstructionOperandSize(Instruction instr, SideEffectOperandTag tag) {
exists(OldInstruction oldInstruction, OldIR::SideEffectOperand oldOperand |
oldInstruction = getOldInstruction(instr) and
oldOperand = oldInstruction.getAnOperand() and
tag = oldOperand.getOperandTag() and
// Only return a result for operands that need an explicit result size.
oldOperand.getType() instanceof UnknownType and
result = oldOperand.getSize()
)
}
cached Instruction getPhiInstructionOperandDefinition(PhiInstruction instr,
IRBlock newPredecessorBlock) {
exists(Alias::VirtualVariable vvar, OldBlock phiBlock,

View File

@@ -57,6 +57,12 @@ abstract class MemoryOperandTag extends OperandTag {
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 printing.
@@ -95,7 +101,7 @@ class BufferSizeOperand extends RegisterOperandTag, TBufferSizeOperand {
/**
* The operand representing the read side effect of a `SideEffectInstruction`.
*/
class SideEffectOperandTag extends MemoryOperandTag, TSideEffectOperand {
class SideEffectOperandTag extends TypedOperandTag, TSideEffectOperand {
override final string toString() {
result = "SideEffect"
}
@@ -113,7 +119,7 @@ SideEffectOperandTag sideEffectOperand() {
* The source value operand of an instruction that loads a value from memory (e.g. `Load`,
* `ReturnValue`, `ThrowValue`).
*/
class LoadOperandTag extends MemoryOperandTag, TLoadOperand {
class LoadOperandTag extends TypedOperandTag, TLoadOperand {
override final string toString() {
result = "Load"
}