On Sat, Jul 21, 2012 at 12:59:07PM +0100, David Chisnall wrote: > On 21 Jul 2012, at 00:16, Konstantin Belousov wrote: > > > Ok, I stand corrected. But the standard does not say what you claim > > either. It only specifies that NULL pointer is unequal to any pointer > > to object or function (implicitely saying that you can create a C object > > or function pointer to which is equal to NULL). > > See 6.5.3.2, paragraph 4. In particular: > > > If an invalid value has been assigned to the pointer, the behavior of the > > unary * operator is undefined. > > and then (footnote 87 from the same page): > > > Among the invalid values for dereferencing a pointer by the unary * > > operator are a null pointer > > > This clearly states that any dereference of the null pointer is explicitly > invalid. You can look up the correct paragraph for the other reason yourself > (that any valid pointer must be the result of pointer arithmetic on a valid > pointer). > As I said in the followup, the C part of the code does not dereferences NULL at all.
> > So, lets reformulate it other way: freestanding implementation in clang > > has no use, at least for general purpose kernel. > > The term 'freestanding' has a well-defined meaning in the C specification. > It does not mean 'the C memory model doesn't apply', it means that there is > no underlying operating system providing facilities such as I/O. Compiling > for a freestanding target does not let you opt out of the C memory model. > > > Especially ridiculous > > is the fact that clang throws it hands for asm inline wanting to get > > null address, on the machine with linearly addressable memory. > > C is not a macro assembler, it is a well-defined (mostly) language with a > complex memory model. The relevant bit of code is: Yes, implementation that interprets the freestanding this way is not useful as a tool for implementing kernel. > > > (*(char *)OFFSETOF_CURTHREAD) > > This is dereferencing the NULL pointer if OFFSETOF_CURTHREAD is 0. If you > want to pass the 0 into the assembly then passing it as something other than > a memory operand would make sense. Or, as the warning suggests, add a > volatile qualification to indicate that the asm is not actually dereferencing > this pointer. I want the code to generate exact "movq %gs:0,%<any reg>" instruction, without using volatile, and using C-level constant with the value of offsetof(struct pcpu, pc_curthread), to be able to assert that assumptions of the assembler fragment did not changed. Your words about specifying immediate operand instead of memory reference almost inevitably results in asm-level expression like $0, not 0. At least I cannot write such asm constraint. You are welcome to provide the snippet. > > However... > > > The point of existence of the inline __pure2 __curthread() is to allow > > a compiler to cache the result of the call. Basically, the curthread > > dereference uses %gs basing, which typically adds a measurable penalty > > on the frontend and sometimes on the execution as well. > > Clang designates address space 256 for GS-relative addressing (and 257 for > FS-relative addressing), so you don't need to use any assembly if all that > you want to do is load something relative to one of these segments. From the > clang manual: > > > Annotating a pointer with address space #256 causes it to be code generated > > relative to the X86 GS segment register, and address space #257 causes it > > to be relative to the X86 FS segment. Note that this is a very very > > low-level feature that should only be used if you know what you're doing > > (for example in an OS kernel). > > > > Here is an example: > > > > > #define GS_RELATIVE __attribute__((address_space(256))) > > int foo(int GS_RELATIVE *P) { > > return *P; > > } > > > > Which compiles to (on X86-32): > > > > _foo: > > movl 4(%esp), %eax > > movl %gs:(%eax), %eax > > ret > > Using this instead of the inline asm allows the front end to perform > numerous optimisations because it no longer has a bit of magic embedded > in the middle of the code that the optimisers don't understand. Great, how to express a fetch of the struct thread * from gs-based offset 0 using this machinery and both avoiding NULL pointer dereference warning and avoiding an addition of volatile ?
pgpZKizwSJxkT.pgp
Description: PGP signature