Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e30e163

Browse files
C#: Implement IRType
This commit implements the language-neutral IR type system for C#. It mostly follows the same pattern as C++, modified to fit the C# type system. All object references, pointers, and lvalues are represented as `IRAddress` types. All structs and generic parameters are implemented as `IRBlobType`. Function addresses get a single `IRFunctionAddressType`. I had to fix a couple places in the original IR type system where I didn't realize I was still depending on language-specific types. As part of this, `CSharpType` and `CppType` now have a `hasUnspecifiedType()` predicate, which is equivalent to `hasType()`, except that it holds only for the unspecified version of the type. This predicate can go away once we remove the IR's references to the underlying `Type` objects. All C# IR tests pass without modification, but only because this commit continues to print the name of `IRUnknownType` as `null`, and `IRFunctionAddressType` as `glval<null>`. These will be fixed separately in a subsequent commit in this PR.
1 parent 300e580 commit e30e163

34 files changed

Lines changed: 1018 additions & 385 deletions

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ private import internal.IRTypeInternal
77
newtype TIRType =
88
TIRVoidType() or
99
TIRUnknownType() or
10-
TIRErrorType() or
10+
TIRErrorType() {
11+
Language::hasErrorType()
12+
} or
1113
TIRBooleanType(int byteSize) {
1214
Language::hasBooleanType(byteSize)
1315
} or

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import IRVariable
55
import Operand
66
private import internal.InstructionImports as Imports
77
import Imports::EdgeKind
8+
import Imports::IRType
89
import Imports::MemoryAccessKind
910
import Imports::Opcode
1011
private import Imports::OperandTag
@@ -315,7 +316,7 @@ class Instruction extends Construction::TInstruction {
315316
}
316317

317318
private string getResultPrefix() {
318-
if getResultType() instanceof Language::VoidType
319+
if getResultIRType() instanceof IRVoidType
319320
then result = "v"
320321
else
321322
if hasMemoryResult()
@@ -440,6 +441,12 @@ class Instruction extends Construction::TInstruction {
440441
result = Construction::getInstructionResultType(this)
441442
}
442443

444+
/**
445+
* Gets the type of the result produced by this instruction. If the instruction does not produce
446+
* a result, its result type will be `IRVoidType`.
447+
*/
448+
final IRType getResultIRType() { result = getResultLanguageType().getIRType() }
449+
443450
/**
444451
* Gets the type of the result produced by this instruction. If the
445452
* instruction does not produce a result, its result type will be `VoidType`.
@@ -448,13 +455,12 @@ class Instruction extends Construction::TInstruction {
448455
* thought of as "pointer to `getResultType()`".
449456
*/
450457
final Language::Type getResultType() {
451-
exists(Language::LanguageType resultType, Language::Type langType |
458+
exists(Language::LanguageType resultType |
452459
resultType = getResultLanguageType() and
453460
(
454-
resultType.hasType(langType, _) or
455-
not resultType.hasType(_, _) and result instanceof Language::UnknownType
456-
) and
457-
result = langType.getUnspecifiedType()
461+
resultType.hasUnspecifiedType(result, _) or
462+
not resultType.hasUnspecifiedType(_, _) and result instanceof Language::UnknownType
463+
)
458464
)
459465
}
460466

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import semmle.code.cpp.ir.implementation.EdgeKind as EdgeKind
2+
import semmle.code.cpp.ir.implementation.IRType as IRType
23
import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
34
import semmle.code.cpp.ir.implementation.Opcode as Opcode
45
import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import IRVariable
55
import Operand
66
private import internal.InstructionImports as Imports
77
import Imports::EdgeKind
8+
import Imports::IRType
89
import Imports::MemoryAccessKind
910
import Imports::Opcode
1011
private import Imports::OperandTag
@@ -315,7 +316,7 @@ class Instruction extends Construction::TInstruction {
315316
}
316317

317318
private string getResultPrefix() {
318-
if getResultType() instanceof Language::VoidType
319+
if getResultIRType() instanceof IRVoidType
319320
then result = "v"
320321
else
321322
if hasMemoryResult()
@@ -440,6 +441,12 @@ class Instruction extends Construction::TInstruction {
440441
result = Construction::getInstructionResultType(this)
441442
}
442443

444+
/**
445+
* Gets the type of the result produced by this instruction. If the instruction does not produce
446+
* a result, its result type will be `IRVoidType`.
447+
*/
448+
final IRType getResultIRType() { result = getResultLanguageType().getIRType() }
449+
443450
/**
444451
* Gets the type of the result produced by this instruction. If the
445452
* instruction does not produce a result, its result type will be `VoidType`.
@@ -448,13 +455,12 @@ class Instruction extends Construction::TInstruction {
448455
* thought of as "pointer to `getResultType()`".
449456
*/
450457
final Language::Type getResultType() {
451-
exists(Language::LanguageType resultType, Language::Type langType |
458+
exists(Language::LanguageType resultType |
452459
resultType = getResultLanguageType() and
453460
(
454-
resultType.hasType(langType, _) or
455-
not resultType.hasType(_, _) and result instanceof Language::UnknownType
456-
) and
457-
result = langType.getUnspecifiedType()
461+
resultType.hasUnspecifiedType(result, _) or
462+
not resultType.hasUnspecifiedType(_, _) and result instanceof Language::UnknownType
463+
)
458464
)
459465
}
460466

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import semmle.code.cpp.ir.implementation.EdgeKind as EdgeKind
2+
import semmle.code.cpp.ir.implementation.IRType as IRType
23
import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
34
import semmle.code.cpp.ir.implementation.Opcode as Opcode
45
import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import IRVariable
55
import Operand
66
private import internal.InstructionImports as Imports
77
import Imports::EdgeKind
8+
import Imports::IRType
89
import Imports::MemoryAccessKind
910
import Imports::Opcode
1011
private import Imports::OperandTag
@@ -315,7 +316,7 @@ class Instruction extends Construction::TInstruction {
315316
}
316317

317318
private string getResultPrefix() {
318-
if getResultType() instanceof Language::VoidType
319+
if getResultIRType() instanceof IRVoidType
319320
then result = "v"
320321
else
321322
if hasMemoryResult()
@@ -440,6 +441,12 @@ class Instruction extends Construction::TInstruction {
440441
result = Construction::getInstructionResultType(this)
441442
}
442443

444+
/**
445+
* Gets the type of the result produced by this instruction. If the instruction does not produce
446+
* a result, its result type will be `IRVoidType`.
447+
*/
448+
final IRType getResultIRType() { result = getResultLanguageType().getIRType() }
449+
443450
/**
444451
* Gets the type of the result produced by this instruction. If the
445452
* instruction does not produce a result, its result type will be `VoidType`.
@@ -448,13 +455,12 @@ class Instruction extends Construction::TInstruction {
448455
* thought of as "pointer to `getResultType()`".
449456
*/
450457
final Language::Type getResultType() {
451-
exists(Language::LanguageType resultType, Language::Type langType |
458+
exists(Language::LanguageType resultType |
452459
resultType = getResultLanguageType() and
453460
(
454-
resultType.hasType(langType, _) or
455-
not resultType.hasType(_, _) and result instanceof Language::UnknownType
456-
) and
457-
result = langType.getUnspecifiedType()
461+
resultType.hasUnspecifiedType(result, _) or
462+
not resultType.hasUnspecifiedType(_, _) and result instanceof Language::UnknownType
463+
)
458464
)
459465
}
460466

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import semmle.code.cpp.ir.implementation.EdgeKind as EdgeKind
2+
import semmle.code.cpp.ir.implementation.IRType as IRType
23
import semmle.code.cpp.ir.implementation.MemoryAccessKind as MemoryAccessKind
34
import semmle.code.cpp.ir.implementation.Opcode as Opcode
45
import semmle.code.cpp.ir.implementation.internal.OperandTag as OperandTag

cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ private int getTypeSize(Type type) {
3131
else result = type.getSize()
3232
}
3333

34+
/**
35+
* Holds if an `IRErrorType` should exist.
36+
*/
37+
predicate hasErrorType() {
38+
exists(ErroneousType t)
39+
}
40+
3441
/**
3542
* Holds if an `IRBooleanType` with the specified `byteSize` should exist.
3643
*/
@@ -170,9 +177,7 @@ private newtype TCppType =
170177
* of a `VariableAddress` where the variable is of reference type)
171178
*/
172179
class CppType extends TCppType {
173-
string toString() {
174-
result = ""
175-
}
180+
abstract string toString();
176181

177182
/** Gets a string used in IR dumps */
178183
string getDumpString() { result = toString() }
@@ -191,6 +196,13 @@ class CppType extends TCppType {
191196
* it represents a glvalue of type `Type` (if `isGLValue` is `true`).
192197
*/
193198
abstract predicate hasType(Type type, boolean isGLValue);
199+
200+
final predicate hasUnspecifiedType(Type type, boolean isGLValue) {
201+
exists(Type specifiedType |
202+
hasType(specifiedType, isGLValue) and
203+
type = specifiedType.getUnspecifiedType()
204+
)
205+
}
194206
}
195207

196208
/**
@@ -204,6 +216,7 @@ private class CppWrappedType extends CppType {
204216
this = TGLValueAddressType(ctype)
205217
}
206218

219+
abstract string toString();
207220
abstract override IRType getIRType();
208221
abstract override predicate hasType(Type type, boolean isGLValue);
209222
}

csharp/ql/src/semmle/code/csharp/ir/PrintIR.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @name Print IR
33
* @description Outputs a representation of the IR graph
4-
* @id charp/print-ir
4+
* @id csharp/print-ir
55
* @kind graph
66
*/
77

0 commit comments

Comments
 (0)