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

Skip to content

Commit c733bc0

Browse files
Andrei DiaconuAndreiDiaconu1
authored andcommitted
Functional basic porting
Ported basic functionalities from the C++ IR Added a simple test that passes the IR sanity check and produces sensible IR (together with the .expected files) to the C# test folder
1 parent fc69c12 commit c733bc0

25 files changed

Lines changed: 2020 additions & 1867 deletions
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
// Most queries should operate on the aliased SSA IR, so that's what we expose
22
// publically as the "IR".
3-
import implementation.aliased_ssa.IR
3+
//import implementation.aliased_ssa.IR
4+
import implementation.raw.IR

csharp/ql/src/semmle/code/csharp/ir/IRConfiguration.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class IRConfiguration extends TIRConfiguration {
1313
/**
1414
* Holds if IR should be created for method `method`. By default, holds for all method.
1515
*/
16-
predicate shouldCreateIRForFunction(Method method) {
16+
predicate shouldCreateIRForFunction(Callable callable) {
1717
any()
1818
}
1919
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
* @id cpp/ir-sanity-check
66
*/
77

8-
import implementation.aliased_ssa.IRSanity
8+
import implementation.raw.IRSanity

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
* @kind graph
66
*/
77

8-
import implementation.aliased_ssa.PrintIR
8+
import implementation.raw.PrintIR
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
import implementation.aliased_ssa.PrintIR
1+
import implementation.raw.PrintIR

csharp/ql/src/semmle/code/csharp/ir/Util.qll

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,38 @@ class ArrayInitWithMod extends ArrayInitializer {
99
entry in [0..this.getNumberOfElements() - 1]
1010
}
1111

12-
predicate isValueInitialized(int entry) {
13-
isInitialized(entry) and
14-
not exists()
12+
pragma[inline]
13+
predicate isValueInitialized(int elementIndex) {
14+
isInitialized(elementIndex) and
15+
not exists(this.getElement(elementIndex))
16+
}
17+
}
18+
19+
class ObjectInitializerMod extends ObjectInitializer {
20+
private predicate isInitialized(Field field) {
21+
not (field.isReadOnly()) and // TODO: Think this is the only instance where a field is not initializable
22+
this.getAMemberInitializer().getTargetVariable() = field
1523
}
16-
}
24+
25+
pragma[inline]
26+
predicate isValueInitialized(Field field) {
27+
this.isInitialized(field) and
28+
not field = this.getAMemberInitializer().getInitializedMember()
29+
}
30+
}
31+
32+
abstract class SideEffectCallable extends Callable {
33+
/**
34+
* Holds if the function never reads from memory that was defined before entry to the function.
35+
* This memory could be from global variables, or from other memory that was reachable from a
36+
* pointer that was passed into the function.
37+
*/
38+
abstract predicate neverReadsMemory();
39+
40+
/**
41+
* Holds if the function never writes to memory that remains allocated after the function
42+
* returns. This memory could be from global variables, or from other memory that was reachable
43+
* from a pointer that was passed into the function.
44+
*/
45+
abstract predicate neverWritesMemory();
46+
}

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ module InstructionSanity {
5151
* Holds if instruction `instr` is missing an expected operand with tag `tag`.
5252
*/
5353
query predicate missingOperand(Instruction instr, string message, IRFunction func, string funcText) {
54+
instr.getAST().fromSource() and
5455
exists(OperandTag tag |
5556
expectsOperand(instr, tag) and
5657
not exists(NonPhiOperand operand |
@@ -68,6 +69,7 @@ module InstructionSanity {
6869
* Holds if instruction `instr` has an unexpected operand with tag `tag`.
6970
*/
7071
query predicate unexpectedOperand(Instruction instr, OperandTag tag) {
72+
instr.getAST().fromSource() and
7173
exists(NonPhiOperand operand |
7274
operand = instr.getAnOperand() and
7375
operand.getOperandTag() = tag) and
@@ -80,6 +82,7 @@ module InstructionSanity {
8082
* Holds if instruction `instr` has multiple operands with tag `tag`.
8183
*/
8284
query predicate duplicateOperand(Instruction instr, OperandTag tag) {
85+
instr.getAST().fromSource() and
8386
strictcount(NonPhiOperand operand |
8487
operand = instr.getAnOperand() and
8588
operand.getOperandTag() = tag
@@ -92,6 +95,7 @@ module InstructionSanity {
9295
* the predecessor block `pred`.
9396
*/
9497
query predicate missingPhiOperand(PhiInstruction instr, IRBlock pred) {
98+
instr.getAST().fromSource() and pred.getEnclosingFunction().fromSource() and
9599
pred = instr.getBlock().getAPredecessor() and
96100
not exists(PhiInputOperand operand |
97101
operand = instr.getAnOperand() and
@@ -111,6 +115,7 @@ module InstructionSanity {
111115
* Holds if an instruction, other than `ExitFunction`, has no successors.
112116
*/
113117
query predicate instructionWithoutSuccessor(Instruction instr) {
118+
instr.getAST().fromSource() and
114119
not exists(instr.getASuccessor()) and
115120
not instr instanceof ExitFunctionInstruction and
116121
// Phi instructions aren't linked into the instruction-level flow graph.
@@ -125,6 +130,7 @@ module InstructionSanity {
125130
query predicate ambiguousSuccessors(
126131
Instruction source, EdgeKind kind, int n, Instruction target
127132
) {
133+
source.getAST().fromSource() and target.getAST().fromSource() and
128134
n = strictcount(Instruction t | source.getSuccessor(kind) = t) and
129135
n > 1 and
130136
source.getSuccessor(kind) = target
@@ -135,6 +141,7 @@ module InstructionSanity {
135141
* contains no element that can cause loops.
136142
*/
137143
query predicate unexplainedLoop(Callable f, Instruction instr) {
144+
instr.getAST().fromSource() and f.fromSource() and
138145
exists(IRBlock block |
139146
instr.getBlock() = block and
140147
block.getEnclosingFunction() = f and
@@ -149,6 +156,7 @@ module InstructionSanity {
149156
* predecessors.
150157
*/
151158
query predicate unnecessaryPhiInstruction(PhiInstruction instr) {
159+
instr.getAST().fromSource() and
152160
count(instr.getBlock().getAPredecessor()) < 2
153161
}
154162

@@ -157,6 +165,7 @@ module InstructionSanity {
157165
* a different function.
158166
*/
159167
query predicate operandAcrossFunctions(Operand operand, Instruction instr, Instruction defInstr) {
168+
instr.getAST().fromSource() and defInstr.getAST().fromSource() and
160169
operand.getUseInstruction() = instr and
161170
operand.getDefinitionInstruction() = defInstr and
162171
instr.getEnclosingIRFunction() != defInstr.getEnclosingIRFunction()
@@ -166,11 +175,13 @@ module InstructionSanity {
166175
* Holds if instruction `instr` is not in exactly one block.
167176
*/
168177
query predicate instructionWithoutUniqueBlock(Instruction instr, int blockCount) {
178+
instr.getAST().fromSource() and
169179
blockCount = count(instr.getBlock()) and
170180
blockCount != 1
171181
}
172182

173183
private predicate forwardEdge(IRBlock b1, IRBlock b2) {
184+
b1.getEnclosingFunction().fromSource() and b2.getEnclosingFunction().fromSource() and
174185
b1.getASuccessor() = b2 and
175186
not b1.getBackEdgeSuccessor(_) = b2
176187
}
@@ -181,6 +192,7 @@ module InstructionSanity {
181192
* This check ensures we don't have too _few_ back edges.
182193
*/
183194
query predicate containsLoopOfForwardEdges(IRFunction f) {
195+
f.getFunction().fromSource() and
184196
exists(IRBlock block |
185197
forwardEdge+(block, block) and
186198
block.getEnclosingIRFunction() = f
@@ -196,6 +208,7 @@ module InstructionSanity {
196208
* This check ensures we don't have too _many_ back edges.
197209
*/
198210
query predicate lostReachability(IRBlock block) {
211+
block.getEnclosingFunction().fromSource() and
199212
exists(IRFunction f, IRBlock entry |
200213
entry = f.getEntryBlock() and
201214
entry.getASuccessor+() = block and
@@ -209,6 +222,7 @@ module InstructionSanity {
209222
* and the `IRBlock` graph.
210223
*/
211224
query predicate backEdgeCountMismatch(Callable f, int fromInstr, int fromBlock) {
225+
f.fromSource() and
212226
fromInstr = count(Instruction i1, Instruction i2 |
213227
i1.getEnclosingCallable() = f and i1.getBackEdgeSuccessor(_) = i2
214228
) and
@@ -625,7 +639,7 @@ class FunctionInstruction extends Instruction {
625639
Callable callableSymbol;
626640

627641
FunctionInstruction() {
628-
callableSymbol = Construction::getInstructionFunction(this)
642+
callableSymbol = Construction::getInstructionCallable(this)
629643
}
630644

631645
override final string getImmediateString() {

csharp/ql/src/semmle/code/csharp/ir/implementation/raw/PrintIR.qll

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
private import IR
2-
import cpp
3-
import semmle.code.cpp.ir.IRConfiguration
4-
private import semmle.code.cpp.Print
2+
import csharp
3+
import semmle.code.csharp.ir.IRConfiguration
4+
//private import semmle.code.csharp.Print
55

66
private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
77

@@ -17,12 +17,12 @@ class PrintIRConfiguration extends TPrintIRConfiguration {
1717
* Holds if the IR for `func` should be printed. By default, holds for all
1818
* functions.
1919
*/
20-
predicate shouldPrintFunction(Function func) {
20+
predicate shouldPrintFunction(Callable func) {
2121
any()
2222
}
2323
}
2424

25-
private predicate shouldPrintFunction(Function func) {
25+
private predicate shouldPrintFunction(Callable func) {
2626
exists(PrintIRConfiguration config |
2727
config.shouldPrintFunction(func)
2828
)
@@ -32,7 +32,7 @@ private predicate shouldPrintFunction(Function func) {
3232
* Override of `IRConfiguration` to only create IR for the functions that are to be dumped.
3333
*/
3434
private class FilteredIRConfiguration extends IRConfiguration {
35-
override predicate shouldCreateIRForFunction(Function func) {
35+
override predicate shouldCreateIRForFunction(Callable func) {
3636
shouldPrintFunction(func)
3737
}
3838
}
@@ -57,7 +57,7 @@ private newtype TPrintableIRNode =
5757
shouldPrintFunction(block.getEnclosingFunction())
5858
} or
5959
TPrintableInstruction(Instruction instr) {
60-
shouldPrintFunction(instr.getEnclosingFunction())
60+
shouldPrintFunction(instr.getEnclosingCallable())
6161
}
6262

6363
/**
@@ -131,7 +131,8 @@ class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
131131
}
132132

133133
override string getLabel() {
134-
result = getIdentityString(irFunc.getFunction())
134+
// TODO: C++ USED THE PRINT MODULE, NOT SURE TOsTRING DOES THE JOB
135+
result = irFunc.getFunction().toString()
135136
}
136137

137138
override int getOrder() {

csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ InstructionTag getInstructionTag(Instruction instruction) {
2121
import Cached
2222
cached private module Cached {
2323
cached predicate functionHasIR(Callable callable) {
24-
exists(getTranslatedFunction(callable))
24+
exists(getTranslatedFunction(callable)) and
25+
callable.fromSource()
2526
}
2627

2728
cached newtype TInstruction =
@@ -48,14 +49,15 @@ cached private module Cached {
4849
instruction = translatedExpr.getResult()
4950
)
5051
}
51-
52+
53+
// TODO: Conversion? Cast?
5254
cached Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
5355
exists(Expr converted, TranslatedExpr translatedExpr |
54-
result = converted.(Conversion).getExpr+()
56+
result = converted.(Cast).getExpr+()
5557
or
5658
result = converted
5759
|
58-
not result instanceof Conversion and
60+
not result instanceof Cast and
5961
translatedExpr = getTranslatedExpr(converted) and
6062
instruction = translatedExpr.getResult()
6163
)
@@ -160,23 +162,24 @@ cached private module Cached {
160162
instruction = inLoop.getInstruction(tag)
161163
)
162164
)
163-
or
165+
//or
166+
// TODO: TRANSLATE TO FOREACH
164167
// Range-based for loop:
165168
// Any edge from within the update of the loop to the condition of
166169
// the loop is a back edge.
167-
exists(TranslatedRangeBasedForStmt s, TranslatedCondition condition |
168-
s instanceof TranslatedRangeBasedForStmt and
169-
condition = s.getCondition() and
170-
result = condition.getFirstInstruction() and
171-
exists(TranslatedElement inUpdate, InstructionTag tag |
172-
result = inUpdate.getInstructionSuccessor(tag, kind) and
173-
exists(TranslatedElement update |
174-
update = s.getUpdate() |
175-
inUpdate = update.getAChild*()
176-
) and
177-
instruction = inUpdate.getInstruction(tag)
178-
)
179-
)
170+
// exists(TranslatedRangeBasedForStmt s, TranslatedCondition condition |
171+
// s instanceof TranslatedRangeBasedForStmt and
172+
// condition = s.getCondition() and
173+
// result = condition.getFirstInstruction() and
174+
// exists(TranslatedElement inUpdate, InstructionTag tag |
175+
// result = inUpdate.getInstructionSuccessor(tag, kind) and
176+
// exists(TranslatedElement update |
177+
// update = s.getUpdate() |
178+
// inUpdate = update.getAChild*()
179+
// ) and
180+
// instruction = inUpdate.getInstruction(tag)
181+
// )
182+
// )
180183
or
181184
// Goto statement:
182185
// As a conservative approximation, any edge out of `goto` is a back edge

csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/InstructionTag.qll

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
import csharp
2+
import semmle.code.csharp.ir.Util
23

34

4-
// TODO: ARE THOSE INITS VALID?
5-
//private predicate fieldIsInitialized(Field field) {
6-
// exists(ClassAggregateLiteral initList |
7-
// initList.isInitialized(field)
8-
// ) or
9-
// exists(ConstructorFieldInit init |
10-
// field = init.getTarget()
11-
// )
12-
//}
13-
//
14-
//private predicate elementIsInitialized(int elementIndex) {
15-
// exists(ArrayAggregateLiteral initList |
16-
// initList.isInitialized(elementIndex)
17-
// )
18-
//}
5+
// TODO:IN C# DOES IT MAKE SENSE TO HAVE BOTH?
6+
private predicate fieldIsInitialized(Field field) {
7+
exists(ObjectInitializer initList |
8+
exists(int i |field = initList.getMemberInitializer(i).getInitializedMember())
9+
) or
10+
exists(MemberInitializer init |
11+
field = init.getInitializedMember()
12+
)
13+
}
14+
15+
private predicate elementIsInitialized(int elementIndex) {
16+
exists(ArrayInitWithMod initList |
17+
initList.isInitialized(elementIndex)
18+
)
19+
}
1920

2021
newtype TInstructionTag =
2122
OnlyInstructionTag() or // Single instruction (not including implicit Load)
@@ -87,7 +88,7 @@ newtype TInstructionTag =
8788
InitializerElementDefaultValueStoreTag(int elementIndex) {
8889
elementIsInitialized(elementIndex)
8990
} // or
90-
// TODO: ASM SHOULD NOT BE HERE?
91+
// TODO: ASM NOT PRESENT IN C#
9192
// AsmTag() or
9293
// AsmInputTag(int elementIndex) {
9394
// exists(AsmStmt asm |

0 commit comments

Comments
 (0)