Skip to content

Commit 79406f8

Browse files
authored
Merge pull request #987 from rdmarsh2/rdmarsh/cpp/ir-asm-stmt
Approved by dave-bartolomeo
2 parents c9a0eed + 4371d02 commit 79406f8

File tree

15 files changed

+377
-8
lines changed

15 files changed

+377
-8
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ private newtype TOpcode =
6969
TBufferWriteSideEffect() or
7070
TBufferMayWriteSideEffect() or
7171
TChi() or
72+
TInlineAsm() or
7273
TUnreached()
7374

7475
class Opcode extends TOpcode {
@@ -214,5 +215,6 @@ module Opcode {
214215
class BufferWriteSideEffect extends WriteSideEffectOpcode, BufferAccessOpcode, TBufferWriteSideEffect { override final string toString() { result = "BufferWriteSideEffect" } }
215216
class BufferMayWriteSideEffect extends MayWriteSideEffectOpcode, BufferAccessOpcode, TBufferMayWriteSideEffect { override final string toString() { result = "BufferMayWriteSideEffect" } }
216217
class Chi extends Opcode, TChi { override final string toString() { result = "Chi" } }
218+
class InlineAsm extends Opcode, TInlineAsm { override final string toString() { result = "InlineAsm" } }
217219
class Unreached extends Opcode, TUnreached { override final string toString() { result = "Unreached" } }
218220
}

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ module InstructionSanity {
4040
opcode instanceof Opcode::Chi and tag instanceof ChiTotalOperandTag or
4141
opcode instanceof Opcode::Chi and tag instanceof ChiPartialOperandTag or
4242
(
43-
(opcode instanceof ReadSideEffectOpcode or opcode instanceof MayWriteSideEffectOpcode) and
43+
(opcode instanceof ReadSideEffectOpcode or opcode instanceof MayWriteSideEffectOpcode or opcode instanceof Opcode::InlineAsm) and
4444
tag instanceof SideEffectOperandTag
4545
)
4646
)
@@ -73,7 +73,8 @@ module InstructionSanity {
7373
operand.getOperandTag() = tag) and
7474
not expectsOperand(instr, tag) and
7575
not (instr instanceof CallInstruction and tag instanceof ArgumentOperandTag) and
76-
not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperandTag)
76+
not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperandTag) and
77+
not (instr instanceof InlineAsmInstruction and tag instanceof AsmOperandTag)
7778
}
7879

7980
/**
@@ -1474,6 +1475,19 @@ class BufferMayWriteSideEffectInstruction extends SideEffectInstruction {
14741475
}
14751476
}
14761477

1478+
/**
1479+
* An instruction representing a GNU or MSVC inline assembly statement.
1480+
*/
1481+
class InlineAsmInstruction extends Instruction {
1482+
InlineAsmInstruction() {
1483+
getOpcode() instanceof Opcode::InlineAsm
1484+
}
1485+
1486+
override final MemoryAccessKind getResultMemoryAccess() {
1487+
result instanceof EscapedMayMemoryAccess
1488+
}
1489+
}
1490+
14771491
/**
14781492
* An instruction that throws an exception.
14791493
*/

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ module InstructionSanity {
4040
opcode instanceof Opcode::Chi and tag instanceof ChiTotalOperandTag or
4141
opcode instanceof Opcode::Chi and tag instanceof ChiPartialOperandTag or
4242
(
43-
(opcode instanceof ReadSideEffectOpcode or opcode instanceof MayWriteSideEffectOpcode) and
43+
(opcode instanceof ReadSideEffectOpcode or opcode instanceof MayWriteSideEffectOpcode or opcode instanceof Opcode::InlineAsm) and
4444
tag instanceof SideEffectOperandTag
4545
)
4646
)
@@ -73,7 +73,8 @@ module InstructionSanity {
7373
operand.getOperandTag() = tag) and
7474
not expectsOperand(instr, tag) and
7575
not (instr instanceof CallInstruction and tag instanceof ArgumentOperandTag) and
76-
not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperandTag)
76+
not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperandTag) and
77+
not (instr instanceof InlineAsmInstruction and tag instanceof AsmOperandTag)
7778
}
7879

7980
/**
@@ -1474,6 +1475,19 @@ class BufferMayWriteSideEffectInstruction extends SideEffectInstruction {
14741475
}
14751476
}
14761477

1478+
/**
1479+
* An instruction representing a GNU or MSVC inline assembly statement.
1480+
*/
1481+
class InlineAsmInstruction extends Instruction {
1482+
InlineAsmInstruction() {
1483+
getOpcode() instanceof Opcode::InlineAsm
1484+
}
1485+
1486+
override final MemoryAccessKind getResultMemoryAccess() {
1487+
result instanceof EscapedMayMemoryAccess
1488+
}
1489+
}
1490+
14771491
/**
14781492
* An instruction that throws an exception.
14791493
*/

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,13 @@ newtype TInstructionTag =
8484
} or
8585
InitializerElementDefaultValueStoreTag(int elementIndex) {
8686
elementIsInitialized(elementIndex)
87-
}
87+
} or
88+
AsmTag() or
89+
AsmInputTag(int elementIndex) {
90+
exists(AsmStmt asm |
91+
exists(asm.getChild(elementIndex))
92+
)
93+
}
8894

8995
class InstructionTag extends TInstructionTag {
9096
final string toString() {
@@ -161,5 +167,9 @@ string getInstructionTagId(TInstructionTag tag) {
161167
tag = InitializerElementDefaultValueStoreTag(index) and tagName = "InitElemDefValStore"
162168
) and
163169
result = tagName + "(" + index + ")"
170+
) or
171+
tag = AsmTag() and result = "Asm" or
172+
exists(int index |
173+
tag = AsmInputTag(index) and result = "AsmInputTag(" + index + ")"
164174
)
165175
}

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ private predicate ignoreExprAndDescendants(Expr expr) {
6464
// represent them.
6565
newExpr.getInitializer().getFullyConverted() = expr
6666
) or
67+
// Do not translate input/output variables in GNU asm statements
68+
getRealParent(expr) instanceof AsmStmt or
6769
ignoreExprAndDescendants(getRealParent(expr)) // recursive case
6870
}
6971

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,3 +810,81 @@ class TranslatedSwitchStmt extends TranslatedStmt {
810810
child = getBody() and result = getParent().getChildSuccessor(this)
811811
}
812812
}
813+
814+
class TranslatedAsmStmt extends TranslatedStmt {
815+
override AsmStmt stmt;
816+
817+
override TranslatedElement getChild(int id) {
818+
none()
819+
}
820+
821+
override Instruction getFirstInstruction() {
822+
if exists(stmt.getChild(0))
823+
then result = getInstruction(AsmInputTag(0))
824+
else result = getInstruction(AsmTag())
825+
}
826+
827+
override predicate hasInstruction(Opcode opcode, InstructionTag tag,
828+
Type resultType, boolean isGLValue) {
829+
tag = AsmTag() and
830+
opcode instanceof Opcode::InlineAsm and
831+
resultType instanceof UnknownType and
832+
isGLValue = false
833+
or
834+
exists(int index, VariableAccess va |
835+
tag = AsmInputTag(index) and
836+
stmt.getChild(index) = va and
837+
opcode instanceof Opcode::VariableAddress and
838+
resultType = va.getType().getUnspecifiedType() and
839+
isGLValue = true
840+
)
841+
}
842+
843+
override IRVariable getInstructionVariable(InstructionTag tag) {
844+
exists(int index |
845+
tag = AsmInputTag(index) and
846+
result = getIRUserVariable(stmt.getEnclosingFunction(), stmt.getChild(index).(VariableAccess).getTarget())
847+
)
848+
}
849+
850+
override Instruction getInstructionOperand(InstructionTag tag,
851+
OperandTag operandTag) {
852+
tag = AsmTag() and
853+
operandTag instanceof SideEffectOperandTag and
854+
result = getTranslatedFunction(stmt.getEnclosingFunction()).getUnmodeledDefinitionInstruction()
855+
or
856+
exists(int index |
857+
tag = AsmTag() and
858+
operandTag = asmOperand(index) and
859+
result = getInstruction(AsmInputTag(index))
860+
)
861+
}
862+
863+
override final Type getInstructionOperandType(InstructionTag tag,
864+
TypedOperandTag operandTag) {
865+
tag = AsmTag() and
866+
operandTag instanceof SideEffectOperandTag and
867+
result instanceof UnknownType
868+
}
869+
870+
override Instruction getInstructionSuccessor(InstructionTag tag,
871+
EdgeKind kind) {
872+
tag = AsmTag() and
873+
result = getParent().getChildSuccessor(this) and
874+
kind instanceof GotoEdge
875+
or
876+
exists(int index |
877+
tag = AsmInputTag(index) and
878+
kind instanceof GotoEdge and
879+
if exists(stmt.getChild(index + 1))
880+
then
881+
result = getInstruction(AsmInputTag(index + 1))
882+
else
883+
result = getInstruction(AsmTag())
884+
)
885+
}
886+
887+
override Instruction getChildSuccessor(TranslatedElement child) {
888+
none()
889+
}
890+
}

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ module InstructionSanity {
4040
opcode instanceof Opcode::Chi and tag instanceof ChiTotalOperandTag or
4141
opcode instanceof Opcode::Chi and tag instanceof ChiPartialOperandTag or
4242
(
43-
(opcode instanceof ReadSideEffectOpcode or opcode instanceof MayWriteSideEffectOpcode) and
43+
(opcode instanceof ReadSideEffectOpcode or opcode instanceof MayWriteSideEffectOpcode or opcode instanceof Opcode::InlineAsm) and
4444
tag instanceof SideEffectOperandTag
4545
)
4646
)
@@ -73,7 +73,8 @@ module InstructionSanity {
7373
operand.getOperandTag() = tag) and
7474
not expectsOperand(instr, tag) and
7575
not (instr instanceof CallInstruction and tag instanceof ArgumentOperandTag) and
76-
not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperandTag)
76+
not (instr instanceof BuiltInInstruction and tag instanceof PositionalArgumentOperandTag) and
77+
not (instr instanceof InlineAsmInstruction and tag instanceof AsmOperandTag)
7778
}
7879

7980
/**
@@ -1474,6 +1475,19 @@ class BufferMayWriteSideEffectInstruction extends SideEffectInstruction {
14741475
}
14751476
}
14761477

1478+
/**
1479+
* An instruction representing a GNU or MSVC inline assembly statement.
1480+
*/
1481+
class InlineAsmInstruction extends Instruction {
1482+
InlineAsmInstruction() {
1483+
getOpcode() instanceof Opcode::InlineAsm
1484+
}
1485+
1486+
override final MemoryAccessKind getResultMemoryAccess() {
1487+
result instanceof EscapedMayMemoryAccess
1488+
}
1489+
}
1490+
14771491
/**
14781492
* An instruction that throws an exception.
14791493
*/

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

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@ private newtype TOperandTag =
2828
)
2929
} or
3030
TChiTotalOperand() or
31-
TChiPartialOperand()
31+
TChiPartialOperand() or
32+
TAsmOperand(int index) {
33+
exists(AsmStmt asm |
34+
exists(asm.getChild(index))
35+
)
36+
}
3237

3338
/**
3439
* Identifies the kind of operand on an instruction. Each `Instruction` has at
@@ -362,3 +367,27 @@ class ChiPartialOperandTag extends MemoryOperandTag, TChiPartialOperand {
362367
ChiPartialOperandTag chiPartialOperand() {
363368
result = TChiPartialOperand()
364369
}
370+
371+
class AsmOperandTag extends RegisterOperandTag, TAsmOperand {
372+
int index;
373+
374+
AsmOperandTag() {
375+
this = TAsmOperand(index)
376+
}
377+
378+
override final string toString() {
379+
result = "AsmOperand(" + index + ")"
380+
}
381+
382+
override final int getSortOrder() {
383+
result = 15 + index
384+
}
385+
386+
override final string getLabel() {
387+
result = index.toString() + ":"
388+
}
389+
}
390+
391+
AsmOperandTag asmOperand(int index) {
392+
result = TAsmOperand(index)
393+
}

cpp/ql/test/library-tests/ir/ir/PrintAST.expected

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7570,3 +7570,50 @@ ir.cpp:
75707570
# 1077| 0: break;
75717571
# 1079| 2: label ...:
75727572
# 1080| 3: return ...
7573+
# 1099| int AsmStmt(int)
7574+
# 1099| params:
7575+
# 1099| 0: x
7576+
# 1099| Type = int
7577+
# 1099| body: { ... }
7578+
# 1100| 0: asm statement
7579+
# 1101| 1: return ...
7580+
# 1101| 0: x
7581+
# 1101| Type = int
7582+
# 1101| ValueCategory = prvalue(load)
7583+
# 1104| void AsmStmtWithOutputs(unsigned int&, unsigned int&, unsigned int&, unsigned int&)
7584+
# 1104| params:
7585+
# 1104| 0: a
7586+
# 1104| Type = unsigned int &
7587+
# 1104| 1: b
7588+
# 1104| Type = unsigned int &
7589+
# 1104| 2: c
7590+
# 1104| Type = unsigned int &
7591+
# 1104| 3: d
7592+
# 1104| Type = unsigned int &
7593+
# 1105| body: { ... }
7594+
# 1106| 0: asm statement
7595+
# 1109| 0: (reference dereference)
7596+
# 1109| Type = unsigned int
7597+
# 1109| ValueCategory = lvalue
7598+
# 1109| expr: a
7599+
# 1109| Type = unsigned int &
7600+
# 1109| ValueCategory = prvalue(load)
7601+
# 1109| 1: (reference dereference)
7602+
# 1109| Type = unsigned int
7603+
# 1109| ValueCategory = lvalue
7604+
# 1109| expr: b
7605+
# 1109| Type = unsigned int &
7606+
# 1109| ValueCategory = prvalue(load)
7607+
# 1109| 2: (reference dereference)
7608+
# 1109| Type = unsigned int
7609+
# 1109| ValueCategory = lvalue
7610+
# 1109| expr: c
7611+
# 1109| Type = unsigned int &
7612+
# 1109| ValueCategory = prvalue(load)
7613+
# 1109| 3: (reference dereference)
7614+
# 1109| Type = unsigned int
7615+
# 1109| ValueCategory = lvalue
7616+
# 1109| expr: d
7617+
# 1109| Type = unsigned int &
7618+
# 1109| ValueCategory = prvalue(load)
7619+
# 1111| 1: return ...

cpp/ql/test/library-tests/ir/ir/ir.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,4 +1096,18 @@ struct LambdaContainer {
10961096

10971097
#endif
10981098

1099+
int AsmStmt(int x) {
1100+
__asm__("");
1101+
return x;
1102+
}
1103+
1104+
static void AsmStmtWithOutputs(unsigned int& a, unsigned int& b, unsigned int& c, unsigned int& d)
1105+
{
1106+
__asm__ __volatile__
1107+
(
1108+
"cpuid\n\t"
1109+
: "+a" (a), "+b" (b), "+c" (c), "+d" (d)
1110+
);
1111+
}
1112+
10991113
// semmle-extractor-options: -std=c++17

0 commit comments

Comments
 (0)