[cfe-commits] [PATCH] CodeGen support for transparent_union

Stefan Kristiansson stefan.kristiansson at saunalahti.fi
Fri Aug 10 20:48:08 PDT 2012


On Sat, Aug 11, 2012 at 1:03 AM, Jan Voung <jvoung at google.com> wrote:
>
> What if the union variants were pointers or ints, etc.?
> Wouldn't the calling convention be different in that case?
>
> E.g.,
>
> glibc's __SOCKADDR_ARG is either a transparent union,
> or struct sockaddr *__restrict, depending on some pre-processor defines.
>

Those cases are still handled correctly, that is exactly the problem
this patch tries to solve.
It was actually the __SOCKADDR_ARG, but in uclibc, combined with an ABI
for the backend I'm working on that says that unions always are passed
by reference
that made me take a look at this.

Assuming long and pointers have the same machine representation:

$ cat transparent-union.c
struct s {
  int a;
  int b;
  long c;
};

typedef union {
  struct s *a;
  int *b;
  long c;
} ARG __attribute__ ((__transparent_union__));

void f0(ARG u);

void f1(struct s *a)
{
  f0(a);
}

void f2(int *a)
{
  f0(a);
}

void f3(long a)
{
  f0(a);
}

$ clang -O2 -c -S transparent-union.c -emit-llvm -o -
; ModuleID = 'transparent-union.c'
target datalayout =
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%struct.s = type { i32, i32, i64 }

define void @f1(%struct.s* %a) nounwind uwtable {
entry:
  tail call void @f0(%struct.s* %a) nounwind
  ret void
}

declare void @f0(%struct.s*)

define void @f2(i32* %a) nounwind uwtable {
entry:
  %0 = bitcast i32* %a to %struct.s*
  tail call void @f0(%struct.s* %0) nounwind
  ret void
}

define void @f3(i64 %a) nounwind uwtable {
entry:
  %0 = inttoptr i64 %a to %struct.s*
  tail call void @f0(%struct.s* %0) nounwind
  ret void
}

Stefan



More information about the cfe-commits mailing list