[PATCH] D17103: [CUDA] Don't crash when trying to printf a non-scalar object.

Hal Finkel via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 10 16:22:50 PST 2016


hfinkel added a comment.

In http://reviews.llvm.org/D17103#349280, @jlebar wrote:

> > > I guess this is the part I'm unsure of.  If it's legal to pass a struct to printf in regular C++ (seems to be?), I'd guess it should be legal in CUDA, too?  I'm just not sure what it's supposed to do (in either case).
>
> > 
>
> > 
>
> > Is this because PTX does not have a way to represent va_arg structs?
>
>
> We do build up something that looks an awful lot like a va_arg struct in this function.  (It's a struct with N members, one for each of the varargs.)  Exactly what printf expects is not particularly carefully specified in the nvvm documentation.
>
> If an arg to printf is non-scalar, we could pass the whole thing into the struct we build here, but that doesn't seem to be what regular C++ does (it seems to take the first 64 bits of the struct -- I have no idea if this is specified somewhere or just UB).


It takes the first 64 bits of the struct in your example because the struct is only 64 bits in size (two 32-bit ints). If you're example was:

  $ cat /tmp/p.cpp 
  #include <stdio.h>
  
  struct Struct {
    int x;
    int y;
    int z;
    int w;
  };
  
  void PrintfNonScalar() {
    Struct S = { 1, 2, 3, 4 };
    printf("%d", S);
  }

then you'd get:

  target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
  target triple = "x86_64-unknown-linux-gnu"
  
  @.str = private unnamed_addr constant [3 x i8] c"%d\00", align 1
  
  ; Function Attrs: nounwind uwtable
  define void @_Z15PrintfNonScalarv() #0 {
    %1 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0), i64 8589934593, i64 17179869187)
    ret void
  }

and so on. The target ABI code decides how to handle this (by coercing the types to a series of ints in this case).

If you were to do this on ppc64, for example, the target ABI code there does a slightly different thing:

  target datalayout = "E-m:e-i64:64-n32:64"
  target triple = "powerpc64-unknown-linux-gnu"
  
  @.str = private unnamed_addr constant [3 x i8] c"%d\00", align 1
  
  ; Function Attrs: nounwind
  define void @_Z15PrintfNonScalarv() #0 {
    %1 = tail call signext i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0), [2 x i64] [i64 4294967298, i64 12884901892])
    ret void
  }

it looks like maybe you just need some more sophisticated code in NVPTXABIInfo in lib/CodeGen/TargetInfo.cpp to produce something the backend will accept?


http://reviews.llvm.org/D17103





More information about the cfe-commits mailing list