Instruction and opcode cleanup

- Renamed `DynamicCastToVoid` to the more descriptive `CompleteObjectAddress`
- Split verbose description from summary in a few Instruction QLDoc comments.
- Added `Instruction` classes for the few remaining `Opcode`s that didn't have one.
- Removed a use of "e.g."
This commit is contained in:
Dave Bartolomeo
2020-06-26 11:39:10 -04:00
parent f48948c604
commit 023e1dc0a2
8 changed files with 642 additions and 57 deletions

View File

@@ -45,7 +45,7 @@ private newtype TOpcode =
TConvertToDerived() or
TCheckedConvertOrNull() or
TCheckedConvertOrThrow() or
TDynamicCastToVoid() or
TCompleteObjectAddress() or
TVariableAddress() or
TFieldAddress() or
TFunctionAddress() or
@@ -514,8 +514,8 @@ module Opcode {
final override string toString() { result = "CheckedConvertOrThrow" }
}
class DynamicCastToVoid extends UnaryOpcode, TDynamicCastToVoid {
final override string toString() { result = "DynamicCastToVoid" }
class CompleteObjectAddress extends UnaryOpcode, TCompleteObjectAddress {
final override string toString() { result = "CompleteObjectAddress" }
}
class VariableAddress extends Opcode, TVariableAddress {

View File

@@ -537,6 +537,18 @@ class VariableAddressInstruction extends VariableInstruction {
VariableAddressInstruction() { getOpcode() instanceof Opcode::VariableAddress }
}
/**
* An instruction that returns the address of a function.
*
* This instruction returns the address of a function, including non-member functions, static member
* functions, and non-static member functions.
*
* The result has an `IRFunctionAddress` type.
*/
class FunctionAddressInstruction extends FunctionInstruction {
FunctionAddressInstruction() { getOpcode() instanceof Opcode::FunctionAddress }
}
/**
* An instruction that initializes a parameter of the enclosing function with the value of the
* corresponding argument passed by the caller.
@@ -553,6 +565,16 @@ class InitializeParameterInstruction extends VariableInstruction {
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
}
/**
* An instruction that initializes all memory that existed before this function was called.
*
* This instruction provides a definition for memory that, because it was actually allocated and
* initialized elsewhere, would not otherwise have a definition in this function.
*/
class InitializeNonLocalInstruction extends Instruction {
InitializeNonLocalInstruction() { getOpcode() instanceof Opcode::InitializeNonLocal }
}
/**
* An instruction that initializes the memory pointed to by a parameter of the enclosing function
* with the value of that memory on entry to the function.
@@ -590,6 +612,25 @@ class FieldAddressInstruction extends FieldInstruction {
final Instruction getObjectAddress() { result = getObjectAddressOperand().getDef() }
}
/**
* An instruction that computes the address of the first element of a managed array.
*
* This instruction is used for element access to C# arrays.
*/
class ElementsAddressInstruction extends UnaryInstruction {
ElementsAddressInstruction() { getOpcode() instanceof Opcode::ElementsAddress }
/**
* Gets the operand that provides the address of the array object.
*/
final UnaryOperand getArrayObjectAddressOperand() { result = getAnOperand() }
/**
* Gets the instruction whose result provides the address of the array object.
*/
final Instruction getArrayObjectAddress() { result = getArrayObjectAddressOperand().getDef() }
}
/**
* An instruction that produces a well-defined but unknown result and has
* unknown side effects, including side effects that are not conservatively
@@ -1177,6 +1218,19 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction {
CheckedConvertOrThrowInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrThrow }
}
/**
* An instruction that returns the address of the complete object that contains the subobject
* pointed to by its operand.
*
* If the operand holds a null address, the result is a null address.
*
* This instruction is used to represent `dyanmic_cast<void*>` in C++, which returns the pointer to
* the most-derived object.
*/
class CompleteObjectAddressInstruction extends UnaryInstruction {
CompleteObjectAddressInstruction() { getOpcode() instanceof Opcode::CompleteObjectAddress }
}
/**
* An instruction that converts the address of an object to the address of a different subobject of
* the same object, without any type checking at runtime.
@@ -1453,7 +1507,7 @@ class CallInstruction extends Instruction {
* Gets the `Function` that the call targets, if this is statically known.
*/
final Language::Function getStaticCallTarget() {
result = getCallTarget().(FunctionInstruction).getFunctionSymbol()
result = getCallTarget().(FunctionAddressInstruction).getFunctionSymbol()
}
/**
@@ -1516,9 +1570,10 @@ class CallSideEffectInstruction extends SideEffectInstruction {
/**
* An instruction representing the side effect of a function call on any memory
* that might be read by that call. This instruction is emitted instead of
* `CallSideEffectInstruction` when it's certain that the call target cannot
* write to escaped memory.
* that might be read by that call.
*
* This instruction is emitted instead of `CallSideEffectInstruction` when it is certain that the
* call target cannot write to escaped memory.
*/
class CallReadSideEffectInstruction extends SideEffectInstruction {
CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect }
@@ -1612,6 +1667,7 @@ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstructi
/**
* An instruction representing the potential write of an indirect parameter within a function call.
*
* Unlike `IndirectWriteSideEffectInstruction`, the location might not be completely overwritten.
* written.
*/
@@ -1623,6 +1679,7 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
/**
* An instruction representing the write of an indirect buffer parameter within a function call.
*
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
*/
class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
@@ -1631,6 +1688,7 @@ class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
/**
* An instruction representing the write of an indirect buffer parameter within a function call.
*
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
*/
class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
@@ -1642,7 +1700,7 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
}
/**
* An instruction representing the initial value of newly allocated memory, e.g. the result of a
* An instruction representing the initial value of newly allocated memory, such as the result of a
* call to `malloc`.
*/
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
@@ -1860,17 +1918,20 @@ class ChiInstruction extends Instruction {
}
/**
* An instruction representing unreachable code. Inserted in place of the original target
* instruction of a `ConditionalBranch` or `Switch` instruction where that particular edge is
* infeasible.
* An instruction representing unreachable code.
*
* This instruction is inserted in place of the original target instruction of a `ConditionalBranch`
* or `Switch` instruction where that particular edge is infeasible.
*/
class UnreachedInstruction extends Instruction {
UnreachedInstruction() { getOpcode() instanceof Opcode::Unreached }
}
/**
* An instruction representing a built-in operation. This is used to represent
* operations such as access to variable argument lists.
* An instruction representing a built-in operation.
*
* This is used to represent a variety of intrinsic operations provided by the compiler
* implementation, such as vector arithmetic.
*/
class BuiltInOperationInstruction extends Instruction {
Language::BuiltInOperation operation;
@@ -1892,3 +1953,59 @@ class BuiltInInstruction extends BuiltInOperationInstruction {
final override string getImmediateString() { result = getBuiltInOperation().toString() }
}
/**
* An instruction that returns a `va_list` to access the arguments passed to the `...` parameter.
*
* The operand specifies the address of the `IREllipsisVariable` used to represent the `...`
* parameter. The result is a `va_list` that initially refers to the first argument that was passed
* to the `...` parameter.
*/
class VarArgsStartInstruction extends UnaryInstruction {
VarArgsStartInstruction() { getOpcode() instanceof Opcode::VarArgsStart }
}
/**
* An instruction that cleans up a `va_list` after it is no longer in use.
*
* The operand specifies the address of the `va_list` to clean up. This instruction does not return
* a result.
*/
class VarArgsEndInstruction extends UnaryInstruction {
VarArgsEndInstruction() { getOpcode() instanceof Opcode::VarArgsEnd }
}
/**
* An instruction that returns the address of the argument currently pointed to by a `va_list`.
*
* The operand is the `va_list` that points to the argument. The result is the address of the
* argument.
*/
class VarArgInstruction extends UnaryInstruction {
VarArgInstruction() { getOpcode() instanceof Opcode::VarArg }
}
/**
* An instruction that modifies a `va_list` to point to the next argument that was passed to the
* `...` parameter.
*
* The operand is the current `va_list`. The result is an updated `va_list` that points to the next
* argument of the `...` parameter.
*/
class NextVarArgInstruction extends UnaryInstruction {
NextVarArgInstruction() { getOpcode() instanceof Opcode::NextVarArg }
}
/**
* An instruction that allocates a new object on the managed heap.
*
* This instruction is used to represent the allocation of a new object in C# using the `new`
* expression. This instruction does not invoke a constructor for the object. Instead, there will be
* a subsequent `Call` instruction to invoke the appropriate constructor directory, passing the
* result of the `NewObj` as the `this` argument.
*
* The result is the address of the newly allocated object.
*/
class NewObjInstruction extends Instruction {
NewObjInstruction() { getOpcode() instanceof Opcode::NewObj }
}

View File

@@ -537,6 +537,18 @@ class VariableAddressInstruction extends VariableInstruction {
VariableAddressInstruction() { getOpcode() instanceof Opcode::VariableAddress }
}
/**
* An instruction that returns the address of a function.
*
* This instruction returns the address of a function, including non-member functions, static member
* functions, and non-static member functions.
*
* The result has an `IRFunctionAddress` type.
*/
class FunctionAddressInstruction extends FunctionInstruction {
FunctionAddressInstruction() { getOpcode() instanceof Opcode::FunctionAddress }
}
/**
* An instruction that initializes a parameter of the enclosing function with the value of the
* corresponding argument passed by the caller.
@@ -553,6 +565,16 @@ class InitializeParameterInstruction extends VariableInstruction {
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
}
/**
* An instruction that initializes all memory that existed before this function was called.
*
* This instruction provides a definition for memory that, because it was actually allocated and
* initialized elsewhere, would not otherwise have a definition in this function.
*/
class InitializeNonLocalInstruction extends Instruction {
InitializeNonLocalInstruction() { getOpcode() instanceof Opcode::InitializeNonLocal }
}
/**
* An instruction that initializes the memory pointed to by a parameter of the enclosing function
* with the value of that memory on entry to the function.
@@ -590,6 +612,25 @@ class FieldAddressInstruction extends FieldInstruction {
final Instruction getObjectAddress() { result = getObjectAddressOperand().getDef() }
}
/**
* An instruction that computes the address of the first element of a managed array.
*
* This instruction is used for element access to C# arrays.
*/
class ElementsAddressInstruction extends UnaryInstruction {
ElementsAddressInstruction() { getOpcode() instanceof Opcode::ElementsAddress }
/**
* Gets the operand that provides the address of the array object.
*/
final UnaryOperand getArrayObjectAddressOperand() { result = getAnOperand() }
/**
* Gets the instruction whose result provides the address of the array object.
*/
final Instruction getArrayObjectAddress() { result = getArrayObjectAddressOperand().getDef() }
}
/**
* An instruction that produces a well-defined but unknown result and has
* unknown side effects, including side effects that are not conservatively
@@ -1177,6 +1218,19 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction {
CheckedConvertOrThrowInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrThrow }
}
/**
* An instruction that returns the address of the complete object that contains the subobject
* pointed to by its operand.
*
* If the operand holds a null address, the result is a null address.
*
* This instruction is used to represent `dyanmic_cast<void*>` in C++, which returns the pointer to
* the most-derived object.
*/
class CompleteObjectAddressInstruction extends UnaryInstruction {
CompleteObjectAddressInstruction() { getOpcode() instanceof Opcode::CompleteObjectAddress }
}
/**
* An instruction that converts the address of an object to the address of a different subobject of
* the same object, without any type checking at runtime.
@@ -1453,7 +1507,7 @@ class CallInstruction extends Instruction {
* Gets the `Function` that the call targets, if this is statically known.
*/
final Language::Function getStaticCallTarget() {
result = getCallTarget().(FunctionInstruction).getFunctionSymbol()
result = getCallTarget().(FunctionAddressInstruction).getFunctionSymbol()
}
/**
@@ -1516,9 +1570,10 @@ class CallSideEffectInstruction extends SideEffectInstruction {
/**
* An instruction representing the side effect of a function call on any memory
* that might be read by that call. This instruction is emitted instead of
* `CallSideEffectInstruction` when it's certain that the call target cannot
* write to escaped memory.
* that might be read by that call.
*
* This instruction is emitted instead of `CallSideEffectInstruction` when it is certain that the
* call target cannot write to escaped memory.
*/
class CallReadSideEffectInstruction extends SideEffectInstruction {
CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect }
@@ -1612,6 +1667,7 @@ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstructi
/**
* An instruction representing the potential write of an indirect parameter within a function call.
*
* Unlike `IndirectWriteSideEffectInstruction`, the location might not be completely overwritten.
* written.
*/
@@ -1623,6 +1679,7 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
/**
* An instruction representing the write of an indirect buffer parameter within a function call.
*
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
*/
class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
@@ -1631,6 +1688,7 @@ class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
/**
* An instruction representing the write of an indirect buffer parameter within a function call.
*
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
*/
class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
@@ -1642,7 +1700,7 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
}
/**
* An instruction representing the initial value of newly allocated memory, e.g. the result of a
* An instruction representing the initial value of newly allocated memory, such as the result of a
* call to `malloc`.
*/
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
@@ -1860,17 +1918,20 @@ class ChiInstruction extends Instruction {
}
/**
* An instruction representing unreachable code. Inserted in place of the original target
* instruction of a `ConditionalBranch` or `Switch` instruction where that particular edge is
* infeasible.
* An instruction representing unreachable code.
*
* This instruction is inserted in place of the original target instruction of a `ConditionalBranch`
* or `Switch` instruction where that particular edge is infeasible.
*/
class UnreachedInstruction extends Instruction {
UnreachedInstruction() { getOpcode() instanceof Opcode::Unreached }
}
/**
* An instruction representing a built-in operation. This is used to represent
* operations such as access to variable argument lists.
* An instruction representing a built-in operation.
*
* This is used to represent a variety of intrinsic operations provided by the compiler
* implementation, such as vector arithmetic.
*/
class BuiltInOperationInstruction extends Instruction {
Language::BuiltInOperation operation;
@@ -1892,3 +1953,59 @@ class BuiltInInstruction extends BuiltInOperationInstruction {
final override string getImmediateString() { result = getBuiltInOperation().toString() }
}
/**
* An instruction that returns a `va_list` to access the arguments passed to the `...` parameter.
*
* The operand specifies the address of the `IREllipsisVariable` used to represent the `...`
* parameter. The result is a `va_list` that initially refers to the first argument that was passed
* to the `...` parameter.
*/
class VarArgsStartInstruction extends UnaryInstruction {
VarArgsStartInstruction() { getOpcode() instanceof Opcode::VarArgsStart }
}
/**
* An instruction that cleans up a `va_list` after it is no longer in use.
*
* The operand specifies the address of the `va_list` to clean up. This instruction does not return
* a result.
*/
class VarArgsEndInstruction extends UnaryInstruction {
VarArgsEndInstruction() { getOpcode() instanceof Opcode::VarArgsEnd }
}
/**
* An instruction that returns the address of the argument currently pointed to by a `va_list`.
*
* The operand is the `va_list` that points to the argument. The result is the address of the
* argument.
*/
class VarArgInstruction extends UnaryInstruction {
VarArgInstruction() { getOpcode() instanceof Opcode::VarArg }
}
/**
* An instruction that modifies a `va_list` to point to the next argument that was passed to the
* `...` parameter.
*
* The operand is the current `va_list`. The result is an updated `va_list` that points to the next
* argument of the `...` parameter.
*/
class NextVarArgInstruction extends UnaryInstruction {
NextVarArgInstruction() { getOpcode() instanceof Opcode::NextVarArg }
}
/**
* An instruction that allocates a new object on the managed heap.
*
* This instruction is used to represent the allocation of a new object in C# using the `new`
* expression. This instruction does not invoke a constructor for the object. Instead, there will be
* a subsequent `Call` instruction to invoke the appropriate constructor directory, passing the
* result of the `NewObj` as the `this` argument.
*
* The result is the address of the newly allocated object.
*/
class NewObjInstruction extends Instruction {
NewObjInstruction() { getOpcode() instanceof Opcode::NewObj }
}

View File

@@ -1011,7 +1011,7 @@ class TranslatedDynamicCast extends TranslatedSingleInstructionConversion {
if resultType instanceof PointerType
then
if resultType.(PointerType).getBaseType() instanceof VoidType
then result instanceof Opcode::DynamicCastToVoid
then result instanceof Opcode::CompleteObjectAddress
else result instanceof Opcode::CheckedConvertOrNull
else result instanceof Opcode::CheckedConvertOrThrow
)

View File

@@ -537,6 +537,18 @@ class VariableAddressInstruction extends VariableInstruction {
VariableAddressInstruction() { getOpcode() instanceof Opcode::VariableAddress }
}
/**
* An instruction that returns the address of a function.
*
* This instruction returns the address of a function, including non-member functions, static member
* functions, and non-static member functions.
*
* The result has an `IRFunctionAddress` type.
*/
class FunctionAddressInstruction extends FunctionInstruction {
FunctionAddressInstruction() { getOpcode() instanceof Opcode::FunctionAddress }
}
/**
* An instruction that initializes a parameter of the enclosing function with the value of the
* corresponding argument passed by the caller.
@@ -553,6 +565,16 @@ class InitializeParameterInstruction extends VariableInstruction {
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
}
/**
* An instruction that initializes all memory that existed before this function was called.
*
* This instruction provides a definition for memory that, because it was actually allocated and
* initialized elsewhere, would not otherwise have a definition in this function.
*/
class InitializeNonLocalInstruction extends Instruction {
InitializeNonLocalInstruction() { getOpcode() instanceof Opcode::InitializeNonLocal }
}
/**
* An instruction that initializes the memory pointed to by a parameter of the enclosing function
* with the value of that memory on entry to the function.
@@ -590,6 +612,25 @@ class FieldAddressInstruction extends FieldInstruction {
final Instruction getObjectAddress() { result = getObjectAddressOperand().getDef() }
}
/**
* An instruction that computes the address of the first element of a managed array.
*
* This instruction is used for element access to C# arrays.
*/
class ElementsAddressInstruction extends UnaryInstruction {
ElementsAddressInstruction() { getOpcode() instanceof Opcode::ElementsAddress }
/**
* Gets the operand that provides the address of the array object.
*/
final UnaryOperand getArrayObjectAddressOperand() { result = getAnOperand() }
/**
* Gets the instruction whose result provides the address of the array object.
*/
final Instruction getArrayObjectAddress() { result = getArrayObjectAddressOperand().getDef() }
}
/**
* An instruction that produces a well-defined but unknown result and has
* unknown side effects, including side effects that are not conservatively
@@ -1177,6 +1218,19 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction {
CheckedConvertOrThrowInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrThrow }
}
/**
* An instruction that returns the address of the complete object that contains the subobject
* pointed to by its operand.
*
* If the operand holds a null address, the result is a null address.
*
* This instruction is used to represent `dyanmic_cast<void*>` in C++, which returns the pointer to
* the most-derived object.
*/
class CompleteObjectAddressInstruction extends UnaryInstruction {
CompleteObjectAddressInstruction() { getOpcode() instanceof Opcode::CompleteObjectAddress }
}
/**
* An instruction that converts the address of an object to the address of a different subobject of
* the same object, without any type checking at runtime.
@@ -1453,7 +1507,7 @@ class CallInstruction extends Instruction {
* Gets the `Function` that the call targets, if this is statically known.
*/
final Language::Function getStaticCallTarget() {
result = getCallTarget().(FunctionInstruction).getFunctionSymbol()
result = getCallTarget().(FunctionAddressInstruction).getFunctionSymbol()
}
/**
@@ -1516,9 +1570,10 @@ class CallSideEffectInstruction extends SideEffectInstruction {
/**
* An instruction representing the side effect of a function call on any memory
* that might be read by that call. This instruction is emitted instead of
* `CallSideEffectInstruction` when it's certain that the call target cannot
* write to escaped memory.
* that might be read by that call.
*
* This instruction is emitted instead of `CallSideEffectInstruction` when it is certain that the
* call target cannot write to escaped memory.
*/
class CallReadSideEffectInstruction extends SideEffectInstruction {
CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect }
@@ -1612,6 +1667,7 @@ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstructi
/**
* An instruction representing the potential write of an indirect parameter within a function call.
*
* Unlike `IndirectWriteSideEffectInstruction`, the location might not be completely overwritten.
* written.
*/
@@ -1623,6 +1679,7 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
/**
* An instruction representing the write of an indirect buffer parameter within a function call.
*
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
*/
class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
@@ -1631,6 +1688,7 @@ class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
/**
* An instruction representing the write of an indirect buffer parameter within a function call.
*
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
*/
class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
@@ -1642,7 +1700,7 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
}
/**
* An instruction representing the initial value of newly allocated memory, e.g. the result of a
* An instruction representing the initial value of newly allocated memory, such as the result of a
* call to `malloc`.
*/
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
@@ -1860,17 +1918,20 @@ class ChiInstruction extends Instruction {
}
/**
* An instruction representing unreachable code. Inserted in place of the original target
* instruction of a `ConditionalBranch` or `Switch` instruction where that particular edge is
* infeasible.
* An instruction representing unreachable code.
*
* This instruction is inserted in place of the original target instruction of a `ConditionalBranch`
* or `Switch` instruction where that particular edge is infeasible.
*/
class UnreachedInstruction extends Instruction {
UnreachedInstruction() { getOpcode() instanceof Opcode::Unreached }
}
/**
* An instruction representing a built-in operation. This is used to represent
* operations such as access to variable argument lists.
* An instruction representing a built-in operation.
*
* This is used to represent a variety of intrinsic operations provided by the compiler
* implementation, such as vector arithmetic.
*/
class BuiltInOperationInstruction extends Instruction {
Language::BuiltInOperation operation;
@@ -1892,3 +1953,59 @@ class BuiltInInstruction extends BuiltInOperationInstruction {
final override string getImmediateString() { result = getBuiltInOperation().toString() }
}
/**
* An instruction that returns a `va_list` to access the arguments passed to the `...` parameter.
*
* The operand specifies the address of the `IREllipsisVariable` used to represent the `...`
* parameter. The result is a `va_list` that initially refers to the first argument that was passed
* to the `...` parameter.
*/
class VarArgsStartInstruction extends UnaryInstruction {
VarArgsStartInstruction() { getOpcode() instanceof Opcode::VarArgsStart }
}
/**
* An instruction that cleans up a `va_list` after it is no longer in use.
*
* The operand specifies the address of the `va_list` to clean up. This instruction does not return
* a result.
*/
class VarArgsEndInstruction extends UnaryInstruction {
VarArgsEndInstruction() { getOpcode() instanceof Opcode::VarArgsEnd }
}
/**
* An instruction that returns the address of the argument currently pointed to by a `va_list`.
*
* The operand is the `va_list` that points to the argument. The result is the address of the
* argument.
*/
class VarArgInstruction extends UnaryInstruction {
VarArgInstruction() { getOpcode() instanceof Opcode::VarArg }
}
/**
* An instruction that modifies a `va_list` to point to the next argument that was passed to the
* `...` parameter.
*
* The operand is the current `va_list`. The result is an updated `va_list` that points to the next
* argument of the `...` parameter.
*/
class NextVarArgInstruction extends UnaryInstruction {
NextVarArgInstruction() { getOpcode() instanceof Opcode::NextVarArg }
}
/**
* An instruction that allocates a new object on the managed heap.
*
* This instruction is used to represent the allocation of a new object in C# using the `new`
* expression. This instruction does not invoke a constructor for the object. Instead, there will be
* a subsequent `Call` instruction to invoke the appropriate constructor directory, passing the
* result of the `NewObj` as the `this` argument.
*
* The result is the address of the newly allocated object.
*/
class NewObjInstruction extends Instruction {
NewObjInstruction() { getOpcode() instanceof Opcode::NewObj }
}

View File

@@ -45,7 +45,7 @@ private newtype TOpcode =
TConvertToDerived() or
TCheckedConvertOrNull() or
TCheckedConvertOrThrow() or
TDynamicCastToVoid() or
TCompleteObjectAddress() or
TVariableAddress() or
TFieldAddress() or
TFunctionAddress() or
@@ -514,8 +514,8 @@ module Opcode {
final override string toString() { result = "CheckedConvertOrThrow" }
}
class DynamicCastToVoid extends UnaryOpcode, TDynamicCastToVoid {
final override string toString() { result = "DynamicCastToVoid" }
class CompleteObjectAddress extends UnaryOpcode, TCompleteObjectAddress {
final override string toString() { result = "CompleteObjectAddress" }
}
class VariableAddress extends Opcode, TVariableAddress {

View File

@@ -537,6 +537,18 @@ class VariableAddressInstruction extends VariableInstruction {
VariableAddressInstruction() { getOpcode() instanceof Opcode::VariableAddress }
}
/**
* An instruction that returns the address of a function.
*
* This instruction returns the address of a function, including non-member functions, static member
* functions, and non-static member functions.
*
* The result has an `IRFunctionAddress` type.
*/
class FunctionAddressInstruction extends FunctionInstruction {
FunctionAddressInstruction() { getOpcode() instanceof Opcode::FunctionAddress }
}
/**
* An instruction that initializes a parameter of the enclosing function with the value of the
* corresponding argument passed by the caller.
@@ -553,6 +565,16 @@ class InitializeParameterInstruction extends VariableInstruction {
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
}
/**
* An instruction that initializes all memory that existed before this function was called.
*
* This instruction provides a definition for memory that, because it was actually allocated and
* initialized elsewhere, would not otherwise have a definition in this function.
*/
class InitializeNonLocalInstruction extends Instruction {
InitializeNonLocalInstruction() { getOpcode() instanceof Opcode::InitializeNonLocal }
}
/**
* An instruction that initializes the memory pointed to by a parameter of the enclosing function
* with the value of that memory on entry to the function.
@@ -590,6 +612,25 @@ class FieldAddressInstruction extends FieldInstruction {
final Instruction getObjectAddress() { result = getObjectAddressOperand().getDef() }
}
/**
* An instruction that computes the address of the first element of a managed array.
*
* This instruction is used for element access to C# arrays.
*/
class ElementsAddressInstruction extends UnaryInstruction {
ElementsAddressInstruction() { getOpcode() instanceof Opcode::ElementsAddress }
/**
* Gets the operand that provides the address of the array object.
*/
final UnaryOperand getArrayObjectAddressOperand() { result = getAnOperand() }
/**
* Gets the instruction whose result provides the address of the array object.
*/
final Instruction getArrayObjectAddress() { result = getArrayObjectAddressOperand().getDef() }
}
/**
* An instruction that produces a well-defined but unknown result and has
* unknown side effects, including side effects that are not conservatively
@@ -1177,6 +1218,19 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction {
CheckedConvertOrThrowInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrThrow }
}
/**
* An instruction that returns the address of the complete object that contains the subobject
* pointed to by its operand.
*
* If the operand holds a null address, the result is a null address.
*
* This instruction is used to represent `dyanmic_cast<void*>` in C++, which returns the pointer to
* the most-derived object.
*/
class CompleteObjectAddressInstruction extends UnaryInstruction {
CompleteObjectAddressInstruction() { getOpcode() instanceof Opcode::CompleteObjectAddress }
}
/**
* An instruction that converts the address of an object to the address of a different subobject of
* the same object, without any type checking at runtime.
@@ -1453,7 +1507,7 @@ class CallInstruction extends Instruction {
* Gets the `Function` that the call targets, if this is statically known.
*/
final Language::Function getStaticCallTarget() {
result = getCallTarget().(FunctionInstruction).getFunctionSymbol()
result = getCallTarget().(FunctionAddressInstruction).getFunctionSymbol()
}
/**
@@ -1516,9 +1570,10 @@ class CallSideEffectInstruction extends SideEffectInstruction {
/**
* An instruction representing the side effect of a function call on any memory
* that might be read by that call. This instruction is emitted instead of
* `CallSideEffectInstruction` when it's certain that the call target cannot
* write to escaped memory.
* that might be read by that call.
*
* This instruction is emitted instead of `CallSideEffectInstruction` when it is certain that the
* call target cannot write to escaped memory.
*/
class CallReadSideEffectInstruction extends SideEffectInstruction {
CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect }
@@ -1612,6 +1667,7 @@ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstructi
/**
* An instruction representing the potential write of an indirect parameter within a function call.
*
* Unlike `IndirectWriteSideEffectInstruction`, the location might not be completely overwritten.
* written.
*/
@@ -1623,6 +1679,7 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
/**
* An instruction representing the write of an indirect buffer parameter within a function call.
*
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
*/
class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
@@ -1631,6 +1688,7 @@ class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
/**
* An instruction representing the write of an indirect buffer parameter within a function call.
*
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
*/
class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
@@ -1642,7 +1700,7 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
}
/**
* An instruction representing the initial value of newly allocated memory, e.g. the result of a
* An instruction representing the initial value of newly allocated memory, such as the result of a
* call to `malloc`.
*/
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
@@ -1860,17 +1918,20 @@ class ChiInstruction extends Instruction {
}
/**
* An instruction representing unreachable code. Inserted in place of the original target
* instruction of a `ConditionalBranch` or `Switch` instruction where that particular edge is
* infeasible.
* An instruction representing unreachable code.
*
* This instruction is inserted in place of the original target instruction of a `ConditionalBranch`
* or `Switch` instruction where that particular edge is infeasible.
*/
class UnreachedInstruction extends Instruction {
UnreachedInstruction() { getOpcode() instanceof Opcode::Unreached }
}
/**
* An instruction representing a built-in operation. This is used to represent
* operations such as access to variable argument lists.
* An instruction representing a built-in operation.
*
* This is used to represent a variety of intrinsic operations provided by the compiler
* implementation, such as vector arithmetic.
*/
class BuiltInOperationInstruction extends Instruction {
Language::BuiltInOperation operation;
@@ -1892,3 +1953,59 @@ class BuiltInInstruction extends BuiltInOperationInstruction {
final override string getImmediateString() { result = getBuiltInOperation().toString() }
}
/**
* An instruction that returns a `va_list` to access the arguments passed to the `...` parameter.
*
* The operand specifies the address of the `IREllipsisVariable` used to represent the `...`
* parameter. The result is a `va_list` that initially refers to the first argument that was passed
* to the `...` parameter.
*/
class VarArgsStartInstruction extends UnaryInstruction {
VarArgsStartInstruction() { getOpcode() instanceof Opcode::VarArgsStart }
}
/**
* An instruction that cleans up a `va_list` after it is no longer in use.
*
* The operand specifies the address of the `va_list` to clean up. This instruction does not return
* a result.
*/
class VarArgsEndInstruction extends UnaryInstruction {
VarArgsEndInstruction() { getOpcode() instanceof Opcode::VarArgsEnd }
}
/**
* An instruction that returns the address of the argument currently pointed to by a `va_list`.
*
* The operand is the `va_list` that points to the argument. The result is the address of the
* argument.
*/
class VarArgInstruction extends UnaryInstruction {
VarArgInstruction() { getOpcode() instanceof Opcode::VarArg }
}
/**
* An instruction that modifies a `va_list` to point to the next argument that was passed to the
* `...` parameter.
*
* The operand is the current `va_list`. The result is an updated `va_list` that points to the next
* argument of the `...` parameter.
*/
class NextVarArgInstruction extends UnaryInstruction {
NextVarArgInstruction() { getOpcode() instanceof Opcode::NextVarArg }
}
/**
* An instruction that allocates a new object on the managed heap.
*
* This instruction is used to represent the allocation of a new object in C# using the `new`
* expression. This instruction does not invoke a constructor for the object. Instead, there will be
* a subsequent `Call` instruction to invoke the appropriate constructor directory, passing the
* result of the `NewObj` as the `this` argument.
*
* The result is the address of the newly allocated object.
*/
class NewObjInstruction extends Instruction {
NewObjInstruction() { getOpcode() instanceof Opcode::NewObj }
}

View File

@@ -537,6 +537,18 @@ class VariableAddressInstruction extends VariableInstruction {
VariableAddressInstruction() { getOpcode() instanceof Opcode::VariableAddress }
}
/**
* An instruction that returns the address of a function.
*
* This instruction returns the address of a function, including non-member functions, static member
* functions, and non-static member functions.
*
* The result has an `IRFunctionAddress` type.
*/
class FunctionAddressInstruction extends FunctionInstruction {
FunctionAddressInstruction() { getOpcode() instanceof Opcode::FunctionAddress }
}
/**
* An instruction that initializes a parameter of the enclosing function with the value of the
* corresponding argument passed by the caller.
@@ -553,6 +565,16 @@ class InitializeParameterInstruction extends VariableInstruction {
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
}
/**
* An instruction that initializes all memory that existed before this function was called.
*
* This instruction provides a definition for memory that, because it was actually allocated and
* initialized elsewhere, would not otherwise have a definition in this function.
*/
class InitializeNonLocalInstruction extends Instruction {
InitializeNonLocalInstruction() { getOpcode() instanceof Opcode::InitializeNonLocal }
}
/**
* An instruction that initializes the memory pointed to by a parameter of the enclosing function
* with the value of that memory on entry to the function.
@@ -590,6 +612,25 @@ class FieldAddressInstruction extends FieldInstruction {
final Instruction getObjectAddress() { result = getObjectAddressOperand().getDef() }
}
/**
* An instruction that computes the address of the first element of a managed array.
*
* This instruction is used for element access to C# arrays.
*/
class ElementsAddressInstruction extends UnaryInstruction {
ElementsAddressInstruction() { getOpcode() instanceof Opcode::ElementsAddress }
/**
* Gets the operand that provides the address of the array object.
*/
final UnaryOperand getArrayObjectAddressOperand() { result = getAnOperand() }
/**
* Gets the instruction whose result provides the address of the array object.
*/
final Instruction getArrayObjectAddress() { result = getArrayObjectAddressOperand().getDef() }
}
/**
* An instruction that produces a well-defined but unknown result and has
* unknown side effects, including side effects that are not conservatively
@@ -1177,6 +1218,19 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction {
CheckedConvertOrThrowInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrThrow }
}
/**
* An instruction that returns the address of the complete object that contains the subobject
* pointed to by its operand.
*
* If the operand holds a null address, the result is a null address.
*
* This instruction is used to represent `dyanmic_cast<void*>` in C++, which returns the pointer to
* the most-derived object.
*/
class CompleteObjectAddressInstruction extends UnaryInstruction {
CompleteObjectAddressInstruction() { getOpcode() instanceof Opcode::CompleteObjectAddress }
}
/**
* An instruction that converts the address of an object to the address of a different subobject of
* the same object, without any type checking at runtime.
@@ -1453,7 +1507,7 @@ class CallInstruction extends Instruction {
* Gets the `Function` that the call targets, if this is statically known.
*/
final Language::Function getStaticCallTarget() {
result = getCallTarget().(FunctionInstruction).getFunctionSymbol()
result = getCallTarget().(FunctionAddressInstruction).getFunctionSymbol()
}
/**
@@ -1516,9 +1570,10 @@ class CallSideEffectInstruction extends SideEffectInstruction {
/**
* An instruction representing the side effect of a function call on any memory
* that might be read by that call. This instruction is emitted instead of
* `CallSideEffectInstruction` when it's certain that the call target cannot
* write to escaped memory.
* that might be read by that call.
*
* This instruction is emitted instead of `CallSideEffectInstruction` when it is certain that the
* call target cannot write to escaped memory.
*/
class CallReadSideEffectInstruction extends SideEffectInstruction {
CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect }
@@ -1612,6 +1667,7 @@ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstructi
/**
* An instruction representing the potential write of an indirect parameter within a function call.
*
* Unlike `IndirectWriteSideEffectInstruction`, the location might not be completely overwritten.
* written.
*/
@@ -1623,6 +1679,7 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
/**
* An instruction representing the write of an indirect buffer parameter within a function call.
*
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
*/
class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
@@ -1631,6 +1688,7 @@ class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
/**
* An instruction representing the write of an indirect buffer parameter within a function call.
*
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
*/
class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
@@ -1642,7 +1700,7 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
}
/**
* An instruction representing the initial value of newly allocated memory, e.g. the result of a
* An instruction representing the initial value of newly allocated memory, such as the result of a
* call to `malloc`.
*/
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
@@ -1860,17 +1918,20 @@ class ChiInstruction extends Instruction {
}
/**
* An instruction representing unreachable code. Inserted in place of the original target
* instruction of a `ConditionalBranch` or `Switch` instruction where that particular edge is
* infeasible.
* An instruction representing unreachable code.
*
* This instruction is inserted in place of the original target instruction of a `ConditionalBranch`
* or `Switch` instruction where that particular edge is infeasible.
*/
class UnreachedInstruction extends Instruction {
UnreachedInstruction() { getOpcode() instanceof Opcode::Unreached }
}
/**
* An instruction representing a built-in operation. This is used to represent
* operations such as access to variable argument lists.
* An instruction representing a built-in operation.
*
* This is used to represent a variety of intrinsic operations provided by the compiler
* implementation, such as vector arithmetic.
*/
class BuiltInOperationInstruction extends Instruction {
Language::BuiltInOperation operation;
@@ -1892,3 +1953,59 @@ class BuiltInInstruction extends BuiltInOperationInstruction {
final override string getImmediateString() { result = getBuiltInOperation().toString() }
}
/**
* An instruction that returns a `va_list` to access the arguments passed to the `...` parameter.
*
* The operand specifies the address of the `IREllipsisVariable` used to represent the `...`
* parameter. The result is a `va_list` that initially refers to the first argument that was passed
* to the `...` parameter.
*/
class VarArgsStartInstruction extends UnaryInstruction {
VarArgsStartInstruction() { getOpcode() instanceof Opcode::VarArgsStart }
}
/**
* An instruction that cleans up a `va_list` after it is no longer in use.
*
* The operand specifies the address of the `va_list` to clean up. This instruction does not return
* a result.
*/
class VarArgsEndInstruction extends UnaryInstruction {
VarArgsEndInstruction() { getOpcode() instanceof Opcode::VarArgsEnd }
}
/**
* An instruction that returns the address of the argument currently pointed to by a `va_list`.
*
* The operand is the `va_list` that points to the argument. The result is the address of the
* argument.
*/
class VarArgInstruction extends UnaryInstruction {
VarArgInstruction() { getOpcode() instanceof Opcode::VarArg }
}
/**
* An instruction that modifies a `va_list` to point to the next argument that was passed to the
* `...` parameter.
*
* The operand is the current `va_list`. The result is an updated `va_list` that points to the next
* argument of the `...` parameter.
*/
class NextVarArgInstruction extends UnaryInstruction {
NextVarArgInstruction() { getOpcode() instanceof Opcode::NextVarArg }
}
/**
* An instruction that allocates a new object on the managed heap.
*
* This instruction is used to represent the allocation of a new object in C# using the `new`
* expression. This instruction does not invoke a constructor for the object. Instead, there will be
* a subsequent `Call` instruction to invoke the appropriate constructor directory, passing the
* result of the `NewObj` as the `this` argument.
*
* The result is the address of the newly allocated object.
*/
class NewObjInstruction extends Instruction {
NewObjInstruction() { getOpcode() instanceof Opcode::NewObj }
}