While trying to create a simple testcase demonstrating a bug in the xlc
compiler, I did a little experiment. Here is a code snip from core.c:
<snip>
/* Code from core.c */
if (mode == AP_MODE_INIT) {
return APR_SUCCESS;
}
if (!ctx)
{
ctx = apr_pcalloc(f->c->pool, sizeof(*ctx));
ctx->b = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
e = apr_bucket_socket_create(net->client_socket, f->c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(ctx->b, e);
net->in_ctx = ctx;
}
else if (APR_BRIGADE_EMPTY(ctx->b)) {
return APR_EOF;
}
avoid_xlc_bug(f->c->base_server);
BRIGADE_NORMALIZE(ctx->b);
</snip>
And here is that same code with the macros unrolled. The xlc optimizer
chokes on this. avoid_xlc_bug() just returns 1 and does nothing else (and
makes the optimzer happy again). This is just nasty.
/* Code from core.c with macros unrolled. */
if (mode == AP_MODE_INIT) {
#line 3330
return 0;
}
if (!ctx)
{
ctx = apr_pcalloc(f->c->pool, sizeof(*ctx));
ctx->b = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
#line 3339
e = apr_bucket_socket_create(net->client_socket, f->c->bucket_alloc);
do { apr_bucket *ap__b = (e); do { ((((ap__b))))->link.next = ((struct
apr_bucket
*)((char *)(((&(ctx->b)->list))) - ((l
ong) (((char *) (&(((struct apr_bucket*)0)->link))) - ((char *) 0)))));
((((ap__b))))->link.prev = (((struct apr_bucket *)((char
*)(((&(ctx->b)->list))) - ((long) (((char *) (&(((struct
apr_bucket*)0)->link))) - ((char
*) 0))))))->link.prev; ((((struct apr
_bucket *)((char *)(((&(ctx->b)->list))) - ((long) (((char *) (&(((struct
apr_bucket*)0)->link))) - ((char *) 0))))))->link.prev
)->link.next = (((ap__b))); (((struct apr_bucket *)((char
*)(((&(ctx->b)->list))) -
((long) (((char *) (&(((struct apr_bucket*)0
)->link))) - ((char *) 0))))))->link.prev = (((ap__b))); } while (0); }
while (0);
net->in_ctx = ctx;
}
else if ((((&(ctx->b)->list))->next == (struct apr_bucket *)((char
*)((&(ctx->b)->list)) - ((long) (((char *) (&(((struct ap
r_bucket*)0)->link))) - ((char *) 0)))))) {
return ((20000 + 500) + 14);
}
avoid_xlc_bug(f->c->base_server);
#line 3350
do { apr_bucket *e = (&(ctx->b)->list)->next; do { if (e->length == 0)
{ apr_bucket
*d; d = ((e))->link.next; do { do { ((((
(e))))->link.prev)->link.next = ((((e))))->link.next;
(((((e))))->link.next)->link.prev =
((((e))))->link.prev; } while (0); do
{ (e)->type->destroy((e)->data); (e)->free(e); } while (0); } while (0); e =
d; } e =
((e))->link.next; } while (!(((&(ctx->b)->
list))->next == (struct apr_bucket *)((char *)((&(ctx->b)->list)) - ((long)
(((char *)
(&(((struct apr_bucket*)0)->link))) - ((c
har *) 0))))) && (e != (struct apr_bucket *)((char *)(&(ctx->b)->list) -
((long) (((char
*) (&(((struct apr_bucket*)0)->link)))
- ((char *) 0)))))); } while (0);
#line 3358
if ((((&(ctx->b)->list))->next == (struct apr_bucket *)((char
*)((&(ctx->b)->list)) -
((long) (((char *) (&(((struct apr_buc
ket*)0)->link))) - ((char *) 0)))))) {
return ((20000 + 500) + 14);
}
#line 3365