Skip to content

Commit 023e1dc

Browse files
author
Dave Bartolomeo
committed
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."
1 parent f48948c commit 023e1dc

File tree

8 files changed

+642
-57
lines changed

8 files changed

+642
-57
lines changed

cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ private newtype TOpcode =
4545
TConvertToDerived() or
4646
TCheckedConvertOrNull() or
4747
TCheckedConvertOrThrow() or
48-
TDynamicCastToVoid() or
48+
TCompleteObjectAddress() or
4949
TVariableAddress() or
5050
TFieldAddress() or
5151
TFunctionAddress() or
@@ -514,8 +514,8 @@ module Opcode {
514514
final override string toString() { result = "CheckedConvertOrThrow" }
515515
}
516516

517-
class DynamicCastToVoid extends UnaryOpcode, TDynamicCastToVoid {
518-
final override string toString() { result = "DynamicCastToVoid" }
517+
class CompleteObjectAddress extends UnaryOpcode, TCompleteObjectAddress {
518+
final override string toString() { result = "CompleteObjectAddress" }
519519
}
520520

521521
class VariableAddress extends Opcode, TVariableAddress {

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 127 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,18 @@ class VariableAddressInstruction extends VariableInstruction {
537537
VariableAddressInstruction() { getOpcode() instanceof Opcode::VariableAddress }
538538
}
539539

540+
/**
541+
* An instruction that returns the address of a function.
542+
*
543+
* This instruction returns the address of a function, including non-member functions, static member
544+
* functions, and non-static member functions.
545+
*
546+
* The result has an `IRFunctionAddress` type.
547+
*/
548+
class FunctionAddressInstruction extends FunctionInstruction {
549+
FunctionAddressInstruction() { getOpcode() instanceof Opcode::FunctionAddress }
550+
}
551+
540552
/**
541553
* An instruction that initializes a parameter of the enclosing function with the value of the
542554
* corresponding argument passed by the caller.
@@ -553,6 +565,16 @@ class InitializeParameterInstruction extends VariableInstruction {
553565
final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() }
554566
}
555567

568+
/**
569+
* An instruction that initializes all memory that existed before this function was called.
570+
*
571+
* This instruction provides a definition for memory that, because it was actually allocated and
572+
* initialized elsewhere, would not otherwise have a definition in this function.
573+
*/
574+
class InitializeNonLocalInstruction extends Instruction {
575+
InitializeNonLocalInstruction() { getOpcode() instanceof Opcode::InitializeNonLocal }
576+
}
577+
556578
/**
557579
* An instruction that initializes the memory pointed to by a parameter of the enclosing function
558580
* with the value of that memory on entry to the function.
@@ -590,6 +612,25 @@ class FieldAddressInstruction extends FieldInstruction {
590612
final Instruction getObjectAddress() { result = getObjectAddressOperand().getDef() }
591613
}
592614

615+
/**
616+
* An instruction that computes the address of the first element of a managed array.
617+
*
618+
* This instruction is used for element access to C# arrays.
619+
*/
620+
class ElementsAddressInstruction extends UnaryInstruction {
621+
ElementsAddressInstruction() { getOpcode() instanceof Opcode::ElementsAddress }
622+
623+
/**
624+
* Gets the operand that provides the address of the array object.
625+
*/
626+
final UnaryOperand getArrayObjectAddressOperand() { result = getAnOperand() }
627+
628+
/**
629+
* Gets the instruction whose result provides the address of the array object.
630+
*/
631+
final Instruction getArrayObjectAddress() { result = getArrayObjectAddressOperand().getDef() }
632+
}
633+
593634
/**
594635
* An instruction that produces a well-defined but unknown result and has
595636
* unknown side effects, including side effects that are not conservatively
@@ -1177,6 +1218,19 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction {
11771218
CheckedConvertOrThrowInstruction() { getOpcode() instanceof Opcode::CheckedConvertOrThrow }
11781219
}
11791220

1221+
/**
1222+
* An instruction that returns the address of the complete object that contains the subobject
1223+
* pointed to by its operand.
1224+
*
1225+
* If the operand holds a null address, the result is a null address.
1226+
*
1227+
* This instruction is used to represent `dyanmic_cast<void*>` in C++, which returns the pointer to
1228+
* the most-derived object.
1229+
*/
1230+
class CompleteObjectAddressInstruction extends UnaryInstruction {
1231+
CompleteObjectAddressInstruction() { getOpcode() instanceof Opcode::CompleteObjectAddress }
1232+
}
1233+
11801234
/**
11811235
* An instruction that converts the address of an object to the address of a different subobject of
11821236
* the same object, without any type checking at runtime.
@@ -1453,7 +1507,7 @@ class CallInstruction extends Instruction {
14531507
* Gets the `Function` that the call targets, if this is statically known.
14541508
*/
14551509
final Language::Function getStaticCallTarget() {
1456-
result = getCallTarget().(FunctionInstruction).getFunctionSymbol()
1510+
result = getCallTarget().(FunctionAddressInstruction).getFunctionSymbol()
14571511
}
14581512

14591513
/**
@@ -1516,9 +1570,10 @@ class CallSideEffectInstruction extends SideEffectInstruction {
15161570

15171571
/**
15181572
* An instruction representing the side effect of a function call on any memory
1519-
* that might be read by that call. This instruction is emitted instead of
1520-
* `CallSideEffectInstruction` when it's certain that the call target cannot
1521-
* write to escaped memory.
1573+
* that might be read by that call.
1574+
*
1575+
* This instruction is emitted instead of `CallSideEffectInstruction` when it is certain that the
1576+
* call target cannot write to escaped memory.
15221577
*/
15231578
class CallReadSideEffectInstruction extends SideEffectInstruction {
15241579
CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect }
@@ -1612,6 +1667,7 @@ class SizedBufferMustWriteSideEffectInstruction extends WriteSideEffectInstructi
16121667

16131668
/**
16141669
* An instruction representing the potential write of an indirect parameter within a function call.
1670+
*
16151671
* Unlike `IndirectWriteSideEffectInstruction`, the location might not be completely overwritten.
16161672
* written.
16171673
*/
@@ -1623,6 +1679,7 @@ class IndirectMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
16231679

16241680
/**
16251681
* An instruction representing the write of an indirect buffer parameter within a function call.
1682+
*
16261683
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
16271684
*/
16281685
class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
@@ -1631,6 +1688,7 @@ class BufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
16311688

16321689
/**
16331690
* An instruction representing the write of an indirect buffer parameter within a function call.
1691+
*
16341692
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
16351693
*/
16361694
class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstruction {
@@ -1642,7 +1700,7 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
16421700
}
16431701

16441702
/**
1645-
* An instruction representing the initial value of newly allocated memory, e.g. the result of a
1703+
* An instruction representing the initial value of newly allocated memory, such as the result of a
16461704
* call to `malloc`.
16471705
*/
16481706
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
@@ -1860,17 +1918,20 @@ class ChiInstruction extends Instruction {
18601918
}
18611919

18621920
/**
1863-
* An instruction representing unreachable code. Inserted in place of the original target
1864-
* instruction of a `ConditionalBranch` or `Switch` instruction where that particular edge is
1865-
* infeasible.
1921+
* An instruction representing unreachable code.
1922+
*
1923+
* This instruction is inserted in place of the original target instruction of a `ConditionalBranch`
1924+
* or `Switch` instruction where that particular edge is infeasible.
18661925
*/
18671926
class UnreachedInstruction extends Instruction {
18681927
UnreachedInstruction() { getOpcode() instanceof Opcode::Unreached }
18691928
}
18701929

18711930
/**
1872-
* An instruction representing a built-in operation. This is used to represent
1873-
* operations such as access to variable argument lists.
1931+
* An instruction representing a built-in operation.
1932+
*
1933+
* This is used to represent a variety of intrinsic operations provided by the compiler
1934+
* implementation, such as vector arithmetic.
18741935
*/
18751936
class BuiltInOperationInstruction extends Instruction {
18761937
Language::BuiltInOperation operation;
@@ -1892,3 +1953,59 @@ class BuiltInInstruction extends BuiltInOperationInstruction {
18921953

18931954
final override string getImmediateString() { result = getBuiltInOperation().toString() }
18941955
}
1956+
1957+
/**
1958+
* An instruction that returns a `va_list` to access the arguments passed to the `...` parameter.
1959+
*
1960+
* The operand specifies the address of the `IREllipsisVariable` used to represent the `...`
1961+
* parameter. The result is a `va_list` that initially refers to the first argument that was passed
1962+
* to the `...` parameter.
1963+
*/
1964+
class VarArgsStartInstruction extends UnaryInstruction {
1965+
VarArgsStartInstruction() { getOpcode() instanceof Opcode::VarArgsStart }
1966+
}
1967+
1968+
/**
1969+
* An instruction that cleans up a `va_list` after it is no longer in use.
1970+
*
1971+
* The operand specifies the address of the `va_list` to clean up. This instruction does not return
1972+
* a result.
1973+
*/
1974+
class VarArgsEndInstruction extends UnaryInstruction {
1975+
VarArgsEndInstruction() { getOpcode() instanceof Opcode::VarArgsEnd }
1976+
}
1977+
1978+
/**
1979+
* An instruction that returns the address of the argument currently pointed to by a `va_list`.
1980+
*
1981+
* The operand is the `va_list` that points to the argument. The result is the address of the
1982+
* argument.
1983+
*/
1984+
class VarArgInstruction extends UnaryInstruction {
1985+
VarArgInstruction() { getOpcode() instanceof Opcode::VarArg }
1986+
}
1987+
1988+
/**
1989+
* An instruction that modifies a `va_list` to point to the next argument that was passed to the
1990+
* `...` parameter.
1991+
*
1992+
* The operand is the current `va_list`. The result is an updated `va_list` that points to the next
1993+
* argument of the `...` parameter.
1994+
*/
1995+
class NextVarArgInstruction extends UnaryInstruction {
1996+
NextVarArgInstruction() { getOpcode() instanceof Opcode::NextVarArg }
1997+
}
1998+
1999+
/**
2000+
* An instruction that allocates a new object on the managed heap.
2001+
*
2002+
* This instruction is used to represent the allocation of a new object in C# using the `new`
2003+
* expression. This instruction does not invoke a constructor for the object. Instead, there will be
2004+
* a subsequent `Call` instruction to invoke the appropriate constructor directory, passing the
2005+
* result of the `NewObj` as the `this` argument.
2006+
*
2007+
* The result is the address of the newly allocated object.
2008+
*/
2009+
class NewObjInstruction extends Instruction {
2010+
NewObjInstruction() { getOpcode() instanceof Opcode::NewObj }
2011+
}

0 commit comments

Comments
 (0)