This question is a follow-up question on Can the C compiler optimizer violate short-circuiting and reorder memory accesses for operands in a logical-AND expression?.
Consider the following code.
if (*p && *q) {
/* do something */
}
Now as per the discussion at Can the C compiler optimizer violate short-circuiting and reorder memory accesses for operands in a logical-AND expression? (especially David Schwartz comment and answer) it is possible for the optimizer of a standard-conformant C compiler to emit CPU instructions that accesses *q
before *p
while still maintaining the observable behaviour of the sequence point established with the &&
-operator.
Therefore although the optimizer may emit code that accesses *q
before *p
, it still needs to ensure that any side-effects of *q
(such as segmentation fault) is observable only if *p
is non-zero. If *p
is zero, then a fault due to *q
should not be observable, i.e. a speculative fault would occur first due to *q
being executed first on the CPU but the speculative fault would be ignored away once *p
is executed and found to be 0.
My question: How is this speculative fault implemented under the hood?
I would appreciate if you could throw more light on the following points while answering this question.
- As far as I know, when the CPU detects a fault, it generates a trap, that the kernel must handle (either take recovery action such as page swap, or signal the fault such as SIGSEGV to the process). Am I correct?
- So if the compiler must emit code to perform speculative fault, it appears to me that the kernel and the compiler (and possibly the CPU too) must all cooperate with each other to implement speculative fault. How does the compiler emit instructions that would tell the kernel or the CPU that a fault generated due to the code should be considered speculative?