#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
char *getenv(char *);
scalar_t__ malloc(int);
int /*<<< orphan*/ sprintf(char *, char *, char *);
int strlen(char *);
const char *observe_handler() {
  static char *handler = NULL;
  if (handler == NULL) {
    char *root = getenv("OBSERVE_ROOT");
    handler = (char *)malloc((strlen(root) +
                              sizeof("/"
                                     "handle") +
                              1) *
                             sizeof(char));
    sprintf(handler,
            "%s"
            "/"
            "handle",
            root);
  }
  return handler;
}


x86 assembly (clang, -O0):
<observe_handler>:
push   %rbp
mov    %rsp,%rbp
sub    $0x10,%rsp
cmpq   $0x0,0x2ef8(%rip)
jne    11a2 <observe_handler+0x62>
lea    0xea3(%rip),%rdi
call   1030 <getenv@plt>
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rdi
call   1040 <strlen@plt>
cltq
add    $0x8,%rax
add    $0x1,%rax
shl    $0x0,%rax
mov    %eax,%edi
call   1050 <malloc@plt>
mov    %rax,0x2ebd(%rip)
mov    0x2eb6(%rip),%rdi
mov    -0x8(%rbp),%rdx
lea    0xe70(%rip),%rsi
call   1060 <sprintf@plt>
mov    0x2e9f(%rip),%rax
add    $0x10,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<observe_handler>:
push   %rbx
mov    0x2f00(%rip),%rax
test   %rax,%rax
je     114f <observe_handler+0xf>
pop    %rbx
ret
lea    0xeaa(%rip),%rdi
call   1030 <getenv@plt>
mov    %rax,%rbx
mov    %rax,%rdi
call   1040 <strlen@plt>
lea    0x9(%rax),%edi
call   1050 <malloc@plt>
mov    %rax,0x2ed3(%rip)
lea    0xe91(%rip),%rsi
mov    %rax,%rdi
mov    %rbx,%rdx
call   1060 <sprintf@plt>
mov    0x2eba(%rip),%rax
pop    %rbx
ret

LLVM IR (-O0):
@observe_handler.handler = internal global i8* null
@.str = [13 x i8] c"OBSERVE_ROOT\00"
@.str.1 = [10 x i8] c"%s/handle\00"
define i8* @observe_handler() {
%1 = alloca i8*
%2 = load i8*, i8** @observe_handler.handler
%3 = icmp eq i8* %2, null
br i1 %3, label %4, label %18
4: ; preds = %0
%5 = call i8* @getenv(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i64 0, i64 0))
store i8* %5, i8** %1
%6 = load i8*, i8** %1
%7 = call i32 @strlen(i8* %6)
%8 = sext i32 %7 to i64
%9 = add i64 %8, 8
%10 = add i64 %9, 1
%11 = mul i64 %10, 1
%12 = trunc i64 %11 to i32
%13 = call i64 @malloc(i32 %12)
%14 = inttoptr i64 %13 to i8*
store i8* %14, i8** @observe_handler.handler
%15 = load i8*, i8** @observe_handler.handler
%16 = load i8*, i8** %1
%17 = call i32 @sprintf(i8* %15, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.1, i64 0, i64 0), i8* %16)
br label %18
18: ; preds = %4, %0
%19 = load i8*, i8** @observe_handler.handler
ret i8* %19
}

LLVM IR (-O2):
@observe_handler.handler = internal unnamed_addr global i8* null
@.str = [13 x i8] c"OBSERVE_ROOT\00"
@.str.1 = [10 x i8] c"%s/handle\00"
define i8* @observe_handler() {
%1 = load i8*, i8** @observe_handler.handler
%2 = icmp eq i8* %1, null
br i1 %2, label %3, label %11
3: ; preds = %0
%4 = tail call i8* @getenv(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i64 0, i64 0))
%5 = tail call i32 @strlen(i8* %4)
%6 = add i32 %5, 9
%7 = tail call i64 @malloc(i32 %6)
%8 = inttoptr i64 %7 to i8*
store i8* %8, i8** @observe_handler.handler
%9 = tail call i32 @sprintf(i8* dereferenceable(1) %8, i8* dereferenceable(1) getelementptr inbounds ([10 x i8], [10 x i8]* @.str.1, i64 0, i64 0), i8* %4)
%10 = load i8*, i8** @observe_handler.handler
br label %11
11: ; preds = %3, %0
%12 = phi i8* [ %10, %3 ], [ %1, %0 ]
ret i8* %12
}