[PATCH] D28166: Properly merge K&R functions that have attributes

Aaron Ballman via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 3 08:09:09 PST 2017


aaron.ballman added a comment.

In https://reviews.llvm.org/D28166#633643, @rsmith wrote:

> In https://reviews.llvm.org/D28166#633621, @aaron.ballman wrote:
>
> > Do you think this patch should be gated on (or perhaps combined with) a fix for the lowering bug, or do you think this patch is reasonable on its own? Given that it turns working code into UB, I think my preference is to gate it on a fix for the lowering bug, but I'm also not certain I am the right person to implement that fix (though I could give it a shot).
>
>
> The test in question has a comment pointing to PR7117, which in turn indicates that we might miscompile parts of FreeBSD if we land this as-is. So I think we need to gate this on a fix for the lowering bug.


I agree with that logic, but would also point out that this bug appears to have nothing to do with attributed functions, but K&R calls in general. Removing the `__stdcall` entirely shows an identical issue:

  void g(int n) {}
  void (*p)() = g;
  void f() { p(0);}

generates

  ; ModuleID = '-'
  source_filename = "-"
  target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
  target triple = "x86_64-pc-windows-msvc"
  
  @p = global void (...)* bitcast (void (i32)* @g to void (...)*), align 8
  
  ; Function Attrs: noinline nounwind
  define void @g(i32 %n) #0 {
  entry:
    %n.addr = alloca i32, align 4
    store i32 %n, i32* %n.addr, align 4
    ret void
  }
  
  ; Function Attrs: noinline nounwind
  define void @f() #0 {
  entry:
    %0 = load void (...)*, void (...)** @p, align 8
    %callee.knr.cast = bitcast void (...)* %0 to void (i64)*
    call void %callee.knr.cast(i64 0)
    ret void
  }
  
  attributes #0 = { noinline nounwind "correctly-rounded-divide-sqrt-fp-math"="fal
  se" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-
  elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-mat
  h"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-p
  rotector-buffer-size"="8" "target-features"="+mmx,+sse,+sse2,+x87" "unsafe-fp-ma
  th"="false" "use-soft-float"="false" }
  
  !llvm.ident = !{!0}
  
  !0 = !{!"clang version 4.0.0 (trunk 290670)"}

I'm happy to try to work on fixing this, but am unfamiliar with this part of the codegen. I *think* the problem is that we gin up the function type for a non-prototyped function based on the function call expression argument types, and the literal `0` is getting the type `signed long long`. This forces us to bitcast the function to one taking an i64 rather than an i32. If you switch the argument from the literal `0` to a variable of type `int`, the bitcast becomes `%3 = bitcast void (...)* %1 to void (i32)*`, which is correct (at least, as I interpret the comments left in `EmitCall()` around line 4245).

Suggestions and hints welcome. :-)


https://reviews.llvm.org/D28166





More information about the cfe-commits mailing list