#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 */
typedef int /*<<< orphan*/ digest;
typedef int /*<<< orphan*/ MD5_CTX;

/* Variables and functions */
int /*<<< orphan*/ MD5_Final(unsigned char *, int /*<<< orphan*/ *);
int /*<<< orphan*/ MD5_Init(int /*<<< orphan*/ *);
int /*<<< orphan*/ MD5_Update(int /*<<< orphan*/ *, char const *,
                              int /*<<< orphan*/);
int /*<<< orphan*/ _error(char *, int);
char *malloc(int const);
int /*<<< orphan*/ strlen(char const *);
char *_hash_md5(char const *password) {
  char *ret;
  unsigned char digest[16];
  const int len = sizeof(digest);
  unsigned short i;
  unsigned char j;
  MD5_CTX c;
  if ((ret = malloc((len * 2) + 1)) == NULL) {
    _error("malloc", 1);
    return NULL;
  }
  MD5_Init(&c);
  MD5_Update(&c, password, strlen(password));
  MD5_Final(digest, &c);
  for (i = 0; i < len; i++) {
    j = (digest[i] >> 4) & 0xf;
    if (j <= 9)
      ret[i * 2] = (j + '0');
    else
      ret[i * 2] = (j + 'a' - 10);
    j = digest[i] & 0xf;
    if (j <= 9)
      ret[i * 2 + 1] = (j + '0');
    else
      ret[i * 2 + 1] = (j + 'a' - 10);
  }
  ret[len * 2] = '\0';
  return ret;
}


x86 assembly (clang, -O0):
<_hash_md5>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
mov    %rdi,-0x10(%rbp)
movl   $0x10,-0x34(%rbp)
mov    $0x21,%edi
call   1050 <malloc@plt>
mov    %rax,-0x18(%rbp)
cmp    $0x0,%rax
jne    11a9 <_hash_md5+0x49>
lea    0xe6e(%rip),%rdi
mov    $0x1,%esi
call   1060 <_error@plt>
movq   $0x0,-0x8(%rbp)
jmp    12d1 <_hash_md5+0x171>
lea    -0x3c(%rbp),%rdi
call   1070 <MD5_Init@plt>
mov    -0x10(%rbp),%rax
mov    %rax,-0x48(%rbp)
mov    -0x10(%rbp),%rdi
call   1040 <strlen@plt>
mov    -0x48(%rbp),%rsi
mov    %eax,%edx
lea    -0x3c(%rbp),%rdi
call   1080 <MD5_Update@plt>
lea    -0x30(%rbp),%rdi
lea    -0x3c(%rbp),%rsi
call   1030 <MD5_Final@plt>
movw   $0x0,-0x36(%rbp)
movzwl -0x36(%rbp),%eax
cmp    $0x10,%eax
jge    12c1 <_hash_md5+0x161>
movzwl -0x36(%rbp),%eax
movzbl -0x30(%rbp,%rax,1),%eax
sar    $0x4,%eax
and    $0xf,%eax
mov    %al,-0x37(%rbp)
movzbl -0x37(%rbp),%eax
cmp    $0x9,%eax
jg     1230 <_hash_md5+0xd0>
movzbl -0x37(%rbp),%eax
add    $0x30,%eax
mov    %al,%dl
mov    -0x18(%rbp),%rax
movzwl -0x36(%rbp),%ecx
shl    $0x1,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
jmp    124d <_hash_md5+0xed>
movzbl -0x37(%rbp),%eax
add    $0x61,%eax
sub    $0xa,%eax
mov    %al,%dl
mov    -0x18(%rbp),%rax
movzwl -0x36(%rbp),%ecx
shl    $0x1,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
movzwl -0x36(%rbp),%eax
movzbl -0x30(%rbp,%rax,1),%eax
and    $0xf,%eax
mov    %al,-0x37(%rbp)
movzbl -0x37(%rbp),%eax
cmp    $0x9,%eax
jg     128b <_hash_md5+0x12b>
movzbl -0x37(%rbp),%eax
add    $0x30,%eax
mov    %al,%dl
mov    -0x18(%rbp),%rax
movzwl -0x36(%rbp),%ecx
shl    $0x1,%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
jmp    12ab <_hash_md5+0x14b>
movzbl -0x37(%rbp),%eax
add    $0x61,%eax
sub    $0xa,%eax
mov    %al,%dl
mov    -0x18(%rbp),%rax
movzwl -0x36(%rbp),%ecx
shl    $0x1,%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
jmp    12b0 <_hash_md5+0x150>
mov    -0x36(%rbp),%ax
add    $0x1,%ax
mov    %ax,-0x36(%rbp)
jmp    11e5 <_hash_md5+0x85>
mov    -0x18(%rbp),%rax
movb   $0x0,0x20(%rax)
mov    -0x18(%rbp),%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<_hash_md5>:
push   %r15
push   %r14
push   %rbx
sub    $0x20,%rsp
mov    %rdi,%rbx
mov    $0x21,%edi
call   1050 <malloc@plt>
mov    %rax,%r14
test   %rax,%rax
je     12b3 <_hash_md5+0x153>
lea    0xc(%rsp),%r15
mov    %r15,%rdi
call   1070 <MD5_Init@plt>
mov    %rbx,%rdi
call   1040 <strlen@plt>
mov    %r15,%rdi
mov    %rbx,%rsi
mov    %eax,%edx
call   1080 <MD5_Update@plt>
lea    0x10(%rsp),%rdi
mov    %r15,%rsi
call   1030 <MD5_Final@plt>
movq   0x10(%rsp),%xmm3
movdqa %xmm3,%xmm6
psrlw  $0x4,%xmm6
movdqa 0xe37(%rip),%xmm8
pand   %xmm8,%xmm6
movdqa 0xe3a(%rip),%xmm0
movdqa %xmm3,%xmm7
pmaxub %xmm0,%xmm7
pcmpeqb %xmm3,%xmm7
movdqa 0xe36(%rip),%xmm2
movdqa %xmm6,%xmm5
paddb  %xmm2,%xmm5
movdqa 0xe36(%rip),%xmm1
por    %xmm1,%xmm6
pand   %xmm7,%xmm5
pandn  %xmm6,%xmm7
por    %xmm5,%xmm7
movdqa 0xe2d(%rip),%xmm9
pand   %xmm9,%xmm3
movdqa 0xe30(%rip),%xmm4
movdqa %xmm3,%xmm6
pmaxub %xmm4,%xmm6
pcmpeqb %xmm3,%xmm6
movdqa %xmm3,%xmm5
por    %xmm1,%xmm5
paddb  %xmm2,%xmm3
pand   %xmm6,%xmm3
pandn  %xmm5,%xmm6
por    %xmm3,%xmm6
punpcklbw %xmm6,%xmm7
movdqu %xmm7,(%r14)
movq   0x18(%rsp),%xmm6
movdqa %xmm6,%xmm3
psrlw  $0x4,%xmm3
pand   %xmm8,%xmm3
pmaxub %xmm6,%xmm0
pcmpeqb %xmm6,%xmm0
movdqa %xmm3,%xmm5
paddb  %xmm2,%xmm5
por    %xmm1,%xmm3
pand   %xmm0,%xmm5
pandn  %xmm3,%xmm0
por    %xmm5,%xmm0
pand   %xmm9,%xmm6
pmaxub %xmm6,%xmm4
pcmpeqb %xmm6,%xmm4
por    %xmm6,%xmm1
paddb  %xmm2,%xmm6
pand   %xmm4,%xmm6
pandn  %xmm1,%xmm4
por    %xmm6,%xmm4
punpcklbw %xmm4,%xmm0
movdqu %xmm0,0x10(%r14)
movb   $0x0,0x20(%r14)
jmp    12c4 <_hash_md5+0x164>
lea    0xda6(%rip),%rdi
mov    $0x1,%esi
call   1060 <_error@plt>
mov    %r14,%rax
add    $0x20,%rsp
pop    %rbx
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
@.str = [7 x i8] c"malloc\00"
define i8* @_hash_md5(i8* %0) {
%2 = alloca i8*
%3 = alloca i8*
%4 = alloca i8*
%5 = alloca [16 x i8]
%6 = alloca i32
%7 = alloca i16
%8 = alloca i8
%9 = alloca i32
store i8* %0, i8** %3
store i32 16, i32* %6
%10 = call i8* @malloc(i32 33)
store i8* %10, i8** %4
%11 = icmp eq i8* %10, null
br i1 %11, label %12, label %14
12: ; preds = %1
%13 = call i32 @_error(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), i32 1)
store i8* null, i8** %2
br label %105
14: ; preds = %1
%15 = call i32 @MD5_Init(i32* %9)
%16 = load i8*, i8** %3
%17 = load i8*, i8** %3
%18 = call i32 @strlen(i8* %17)
%19 = call i32 @MD5_Update(i32* %9, i8* %16, i32 %18)
%20 = getelementptr inbounds [16 x i8], [16 x i8]* %5, i64 0, i64 0
%21 = call i32 @MD5_Final(i8* %20, i32* %9)
store i16 0, i16* %7
br label %22
22: ; preds = %98, %14
%23 = load i16, i16* %7
%24 = zext i16 %23 to i32
%25 = icmp slt i32 %24, 16
br i1 %25, label %26, label %101
26: ; preds = %22
%27 = load i16, i16* %7
%28 = zext i16 %27 to i64
%29 = getelementptr inbounds [16 x i8], [16 x i8]* %5, i64 0, i64 %28
%30 = load i8, i8* %29
%31 = zext i8 %30 to i32
%32 = ashr i32 %31, 4
%33 = and i32 %32, 15
%34 = trunc i32 %33 to i8
store i8 %34, i8* %8
%35 = load i8, i8* %8
%36 = zext i8 %35 to i32
%37 = icmp sle i32 %36, 9
br i1 %37, label %38, label %49
38: ; preds = %26
%39 = load i8, i8* %8
%40 = zext i8 %39 to i32
%41 = add nsw i32 %40, 48
%42 = trunc i32 %41 to i8
%43 = load i8*, i8** %4
%44 = load i16, i16* %7
%45 = zext i16 %44 to i32
%46 = mul nsw i32 %45, 2
%47 = sext i32 %46 to i64
%48 = getelementptr inbounds i8, i8* %43, i64 %47
store i8 %42, i8* %48
br label %61
49: ; preds = %26
%50 = load i8, i8* %8
%51 = zext i8 %50 to i32
%52 = add nsw i32 %51, 97
%53 = sub nsw i32 %52, 10
%54 = trunc i32 %53 to i8
%55 = load i8*, i8** %4
%56 = load i16, i16* %7
%57 = zext i16 %56 to i32
%58 = mul nsw i32 %57, 2
%59 = sext i32 %58 to i64
%60 = getelementptr inbounds i8, i8* %55, i64 %59
store i8 %54, i8* %60
br label %61
61: ; preds = %49, %38
%62 = load i16, i16* %7
%63 = zext i16 %62 to i64
%64 = getelementptr inbounds [16 x i8], [16 x i8]* %5, i64 0, i64 %63
%65 = load i8, i8* %64
%66 = zext i8 %65 to i32
%67 = and i32 %66, 15
%68 = trunc i32 %67 to i8
store i8 %68, i8* %8
%69 = load i8, i8* %8
%70 = zext i8 %69 to i32
%71 = icmp sle i32 %70, 9
br i1 %71, label %72, label %84
72: ; preds = %61
%73 = load i8, i8* %8
%74 = zext i8 %73 to i32
%75 = add nsw i32 %74, 48
%76 = trunc i32 %75 to i8
%77 = load i8*, i8** %4
%78 = load i16, i16* %7
%79 = zext i16 %78 to i32
%80 = mul nsw i32 %79, 2
%81 = add nsw i32 %80, 1
%82 = sext i32 %81 to i64
%83 = getelementptr inbounds i8, i8* %77, i64 %82
store i8 %76, i8* %83
br label %97
84: ; preds = %61
%85 = load i8, i8* %8
%86 = zext i8 %85 to i32
%87 = add nsw i32 %86, 97
%88 = sub nsw i32 %87, 10
%89 = trunc i32 %88 to i8
%90 = load i8*, i8** %4
%91 = load i16, i16* %7
%92 = zext i16 %91 to i32
%93 = mul nsw i32 %92, 2
%94 = add nsw i32 %93, 1
%95 = sext i32 %94 to i64
%96 = getelementptr inbounds i8, i8* %90, i64 %95
store i8 %89, i8* %96
br label %97
97: ; preds = %84, %72
br label %98
98: ; preds = %97
%99 = load i16, i16* %7
%100 = add i16 %99, 1
store i16 %100, i16* %7
br label %22
101: ; preds = %22
%102 = load i8*, i8** %4
%103 = getelementptr inbounds i8, i8* %102, i64 32
store i8 0, i8* %103
%104 = load i8*, i8** %4
store i8* %104, i8** %2
br label %105
105: ; preds = %101, %12
%106 = load i8*, i8** %2
ret i8* %106
}

LLVM IR (-O2):
@.str = [7 x i8] c"malloc\00"
define noalias i8* @_hash_md5(i8* %0) {
%2 = alloca [16 x i8]
%3 = alloca i32
%4 = getelementptr inbounds [16 x i8], [16 x i8]* %2, i64 0, i64 0
%5 = bitcast i32* %3 to i8*
%6 = tail call dereferenceable_or_null(33) i8* @malloc(i32 33)
%7 = icmp eq i8* %6, null
br i1 %7, label %8, label %10
8: ; preds = %1
%9 = tail call i32 @_error(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0), i32 1)
br label %46
10: ; preds = %1
%11 = call i32 @MD5_Init(i32* %3)
%12 = call i32 @strlen(i8* %0)
%13 = call i32 @MD5_Update(i32* %3, i8* %0, i32 %12)
%14 = call i32 @MD5_Final(i8* %4, i32* %3)
%15 = bitcast [16 x i8]* %2 to <8 x i8>*
%16 = load <8 x i8>, <8 x i8>* %15
%17 = lshr <8 x i8> %16, <i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4>
%18 = icmp ult <8 x i8> %16, <i8 -96, i8 -96, i8 -96, i8 -96, i8 -96, i8 -96, i8 -96, i8 -96>
%19 = add nuw nsw <8 x i8> %17, <i8 87, i8 87, i8 87, i8 87, i8 87, i8 87, i8 87, i8 87>
%20 = or <8 x i8> %17, <i8 48, i8 48, i8 48, i8 48, i8 48, i8 48, i8 48, i8 48>
%21 = select <8 x i1> %18, <8 x i8> %20, <8 x i8> %19
%22 = and <8 x i8> %16, <i8 15, i8 15, i8 15, i8 15, i8 15, i8 15, i8 15, i8 15>
%23 = icmp ult <8 x i8> %22, <i8 10, i8 10, i8 10, i8 10, i8 10, i8 10, i8 10, i8 10>
%24 = or <8 x i8> %22, <i8 48, i8 48, i8 48, i8 48, i8 48, i8 48, i8 48, i8 48>
%25 = add nuw nsw <8 x i8> %22, <i8 87, i8 87, i8 87, i8 87, i8 87, i8 87, i8 87, i8 87>
%26 = select <8 x i1> %23, <8 x i8> %24, <8 x i8> %25
%27 = bitcast i8* %6 to <16 x i8>*
%28 = shufflevector <8 x i8> %21, <8 x i8> %26, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %28, <16 x i8>* %27
%29 = getelementptr inbounds [16 x i8], [16 x i8]* %2, i64 0, i64 8
%30 = bitcast i8* %29 to <8 x i8>*
%31 = load <8 x i8>, <8 x i8>* %30
%32 = lshr <8 x i8> %31, <i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4>
%33 = icmp ult <8 x i8> %31, <i8 -96, i8 -96, i8 -96, i8 -96, i8 -96, i8 -96, i8 -96, i8 -96>
%34 = add nuw nsw <8 x i8> %32, <i8 87, i8 87, i8 87, i8 87, i8 87, i8 87, i8 87, i8 87>
%35 = or <8 x i8> %32, <i8 48, i8 48, i8 48, i8 48, i8 48, i8 48, i8 48, i8 48>
%36 = select <8 x i1> %33, <8 x i8> %35, <8 x i8> %34
%37 = and <8 x i8> %31, <i8 15, i8 15, i8 15, i8 15, i8 15, i8 15, i8 15, i8 15>
%38 = icmp ult <8 x i8> %37, <i8 10, i8 10, i8 10, i8 10, i8 10, i8 10, i8 10, i8 10>
%39 = or <8 x i8> %37, <i8 48, i8 48, i8 48, i8 48, i8 48, i8 48, i8 48, i8 48>
%40 = add nuw nsw <8 x i8> %37, <i8 87, i8 87, i8 87, i8 87, i8 87, i8 87, i8 87, i8 87>
%41 = select <8 x i1> %38, <8 x i8> %39, <8 x i8> %40
%42 = getelementptr inbounds i8, i8* %6, i64 16
%43 = bitcast i8* %42 to <16 x i8>*
%44 = shufflevector <8 x i8> %36, <8 x i8> %41, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %44, <16 x i8>* %43
%45 = getelementptr inbounds i8, i8* %6, i64 32
store i8 0, i8* %45
br label %46
46: ; preds = %10, %8
ret i8* %6
}