#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 *malloc(int);
char valueToHexDigit(unsigned char);
char *highCharToUnicode(const char *str, size_t inlen, size_t *outlen) {
  char *out = NULL;
  unsigned char higherDigit = 0;
  unsigned char lowerDigit = 0;
  unsigned char plane[2] = {0, 0};
  if (inlen == 3) {
    plane[0] = str[0] << 4;
    plane[0] |= ((str[1] >> 2) & 15);
    plane[1] = str[1] << 6;
    plane[1] |= (str[2] & 63);
  } else if (inlen == 2) {
    plane[0] |= ((str[0] >> 2) & 15);
    plane[1] = str[0] << 6;
    plane[1] |= (str[1] & 63);
  } else {
    return NULL;
  }
  *outlen = 6;
  out = malloc(sizeof(char) * 6);
  if (out == NULL) {
    return NULL;
  }
  out[0] = '\\';
  out[1] = 'u';
  higherDigit = (unsigned char)plane[0] / 16;
  lowerDigit = plane[0] - (higherDigit * 16);
  out[2] = valueToHexDigit(higherDigit);
  out[3] = valueToHexDigit(lowerDigit);
  higherDigit = (unsigned char)plane[1] / 16;
  lowerDigit = plane[1] - (higherDigit * 16);
  out[4] = valueToHexDigit(higherDigit);
  out[5] = valueToHexDigit(lowerDigit);
  return out;
}


x86 assembly (clang, -O0):
<highCharToUnicode>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
mov    %rdx,-0x20(%rbp)
movq   $0x0,-0x28(%rbp)
movb   $0x0,-0x29(%rbp)
movb   $0x0,-0x2a(%rbp)
lea    -0x2c(%rbp),%rdi
xor    %esi,%esi
mov    $0x2,%edx
call   1030 <memset@plt>
cmpq   $0x3,-0x18(%rbp)
jne    11ba <highCharToUnicode+0x8a>
mov    -0x10(%rbp),%rax
movsbl (%rax),%eax
shl    $0x4,%eax
mov    %al,-0x2c(%rbp)
mov    -0x10(%rbp),%rax
movsbl 0x1(%rax),%ecx
sar    $0x2,%ecx
and    $0xf,%ecx
movzbl -0x2c(%rbp),%eax
or     %ecx,%eax
mov    %al,-0x2c(%rbp)
mov    -0x10(%rbp),%rax
movsbl 0x1(%rax),%eax
shl    $0x6,%eax
mov    %al,-0x2b(%rbp)
mov    -0x10(%rbp),%rax
movsbl 0x2(%rax),%ecx
and    $0x3f,%ecx
movzbl -0x2b(%rbp),%eax
or     %ecx,%eax
mov    %al,-0x2b(%rbp)
jmp    1213 <highCharToUnicode+0xe3>
cmpq   $0x2,-0x18(%rbp)
jne    1201 <highCharToUnicode+0xd1>
mov    -0x10(%rbp),%rax
movsbl (%rax),%ecx
sar    $0x2,%ecx
and    $0xf,%ecx
movzbl -0x2c(%rbp),%eax
or     %ecx,%eax
mov    %al,-0x2c(%rbp)
mov    -0x10(%rbp),%rax
movsbl (%rax),%eax
shl    $0x6,%eax
mov    %al,-0x2b(%rbp)
mov    -0x10(%rbp),%rax
movsbl 0x1(%rax),%ecx
and    $0x3f,%ecx
movzbl -0x2b(%rbp),%eax
or     %ecx,%eax
mov    %al,-0x2b(%rbp)
jmp    120e <highCharToUnicode+0xde>
movq   $0x0,-0x8(%rbp)
jmp    12e1 <highCharToUnicode+0x1b1>
jmp    1213 <highCharToUnicode+0xe3>
mov    -0x20(%rbp),%rax
movq   $0x6,(%rax)
mov    $0x6,%edi
call   1040 <malloc@plt>
mov    %rax,-0x28(%rbp)
cmpq   $0x0,-0x28(%rbp)
jne    1244 <highCharToUnicode+0x114>
movq   $0x0,-0x8(%rbp)
jmp    12e1 <highCharToUnicode+0x1b1>
mov    -0x28(%rbp),%rax
movb   $0x5c,(%rax)
mov    -0x28(%rbp),%rax
movb   $0x75,0x1(%rax)
movzbl -0x2c(%rbp),%eax
mov    $0x10,%ecx
cltd
idiv   %ecx
mov    %al,-0x29(%rbp)
movzbl -0x2c(%rbp),%eax
movzbl -0x29(%rbp),%ecx
shl    $0x4,%ecx
sub    %ecx,%eax
mov    %al,-0x2a(%rbp)
movzbl -0x29(%rbp),%edi
call   1050 <valueToHexDigit@plt>
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %cl,0x2(%rax)
movzbl -0x2a(%rbp),%edi
call   1050 <valueToHexDigit@plt>
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %cl,0x3(%rax)
movzbl -0x2b(%rbp),%eax
mov    $0x10,%ecx
cltd
idiv   %ecx
mov    %al,-0x29(%rbp)
movzbl -0x2b(%rbp),%eax
movzbl -0x29(%rbp),%ecx
shl    $0x4,%ecx
sub    %ecx,%eax
mov    %al,-0x2a(%rbp)
movzbl -0x29(%rbp),%edi
call   1050 <valueToHexDigit@plt>
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %cl,0x4(%rax)
movzbl -0x2a(%rbp),%edi
call   1050 <valueToHexDigit@plt>
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %cl,0x5(%rax)
mov    -0x28(%rbp),%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<highCharToUnicode>:
push   %rbp
push   %r15
push   %r14
push   %rbx
push   %rax
cmp    $0x2,%rsi
je     1152 <highCharToUnicode+0x32>
cmp    $0x3,%rsi
jne    11d2 <highCharToUnicode+0xb2>
mov    (%rdi),%al
mov    0x1(%rdi),%r14b
shl    $0x4,%al
mov    %r14d,%ebx
shr    $0x2,%bl
and    $0xf,%bl
or     %al,%bl
mov    $0x2,%eax
jmp    1163 <highCharToUnicode+0x43>
mov    (%rdi),%r14b
mov    %r14d,%ebx
shr    $0x2,%bl
and    $0xf,%bl
mov    $0x1,%eax
mov    (%rdi,%rax,1),%r15b
movq   $0x6,(%rdx)
mov    $0x6,%edi
call   1030 <malloc@plt>
test   %rax,%rax
je     11d2 <highCharToUnicode+0xb2>
mov    %rax,%rbp
mov    %r15d,%eax
and    $0x30,%al
shl    $0x6,%r14b
or     %al,%r14b
movw   $0x755c,0x0(%rbp)
mov    %ebx,%eax
shr    $0x4,%al
and    $0xf,%bl
movzbl %al,%edi
call   1040 <valueToHexDigit@plt>
mov    %al,0x2(%rbp)
movzbl %bl,%edi
call   1040 <valueToHexDigit@plt>
mov    %al,0x3(%rbp)
shr    $0x4,%r14b
and    $0xf,%r15b
movzbl %r14b,%edi
call   1040 <valueToHexDigit@plt>
mov    %al,0x4(%rbp)
movzbl %r15b,%edi
call   1040 <valueToHexDigit@plt>
mov    %al,0x5(%rbp)
jmp    11d4 <highCharToUnicode+0xb4>
xor    %ebp,%ebp
mov    %rbp,%rax
add    $0x8,%rsp
pop    %rbx
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define i8* @highCharToUnicode(i8* %0, i64 %1, i64* %2) {
%4 = alloca i8*
%5 = alloca i8*
%6 = alloca i64
%7 = alloca i64*
%8 = alloca i8*
%9 = alloca i8
%10 = alloca i8
%11 = alloca [2 x i8]
store i8* %0, i8** %5
store i64 %1, i64* %6
store i64* %2, i64** %7
store i8* null, i8** %8
store i8 0, i8* %9
store i8 0, i8* %10
%12 = bitcast [2 x i8]* %11 to i8*
%13 = load i64, i64* %6
%14 = icmp eq i64 %13, 3
br i1 %14, label %15, label %51
15: ; preds = %3
%16 = load i8*, i8** %5
%17 = getelementptr inbounds i8, i8* %16, i64 0
%18 = load i8, i8* %17
%19 = sext i8 %18 to i32
%20 = shl i32 %19, 4
%21 = trunc i32 %20 to i8
%22 = getelementptr inbounds [2 x i8], [2 x i8]* %11, i64 0, i64 0
store i8 %21, i8* %22
%23 = load i8*, i8** %5
%24 = getelementptr inbounds i8, i8* %23, i64 1
%25 = load i8, i8* %24
%26 = sext i8 %25 to i32
%27 = ashr i32 %26, 2
%28 = and i32 %27, 15
%29 = getelementptr inbounds [2 x i8], [2 x i8]* %11, i64 0, i64 0
%30 = load i8, i8* %29
%31 = zext i8 %30 to i32
%32 = or i32 %31, %28
%33 = trunc i32 %32 to i8
store i8 %33, i8* %29
%34 = load i8*, i8** %5
%35 = getelementptr inbounds i8, i8* %34, i64 1
%36 = load i8, i8* %35
%37 = sext i8 %36 to i32
%38 = shl i32 %37, 6
%39 = trunc i32 %38 to i8
%40 = getelementptr inbounds [2 x i8], [2 x i8]* %11, i64 0, i64 1
store i8 %39, i8* %40
%41 = load i8*, i8** %5
%42 = getelementptr inbounds i8, i8* %41, i64 2
%43 = load i8, i8* %42
%44 = sext i8 %43 to i32
%45 = and i32 %44, 63
%46 = getelementptr inbounds [2 x i8], [2 x i8]* %11, i64 0, i64 1
%47 = load i8, i8* %46
%48 = zext i8 %47 to i32
%49 = or i32 %48, %45
%50 = trunc i32 %49 to i8
store i8 %50, i8* %46
br label %85
51: ; preds = %3
%52 = load i64, i64* %6
%53 = icmp eq i64 %52, 2
br i1 %53, label %54, label %83
54: ; preds = %51
%55 = load i8*, i8** %5
%56 = getelementptr inbounds i8, i8* %55, i64 0
%57 = load i8, i8* %56
%58 = sext i8 %57 to i32
%59 = ashr i32 %58, 2
%60 = and i32 %59, 15
%61 = getelementptr inbounds [2 x i8], [2 x i8]* %11, i64 0, i64 0
%62 = load i8, i8* %61
%63 = zext i8 %62 to i32
%64 = or i32 %63, %60
%65 = trunc i32 %64 to i8
store i8 %65, i8* %61
%66 = load i8*, i8** %5
%67 = getelementptr inbounds i8, i8* %66, i64 0
%68 = load i8, i8* %67
%69 = sext i8 %68 to i32
%70 = shl i32 %69, 6
%71 = trunc i32 %70 to i8
%72 = getelementptr inbounds [2 x i8], [2 x i8]* %11, i64 0, i64 1
store i8 %71, i8* %72
%73 = load i8*, i8** %5
%74 = getelementptr inbounds i8, i8* %73, i64 1
%75 = load i8, i8* %74
%76 = sext i8 %75 to i32
%77 = and i32 %76, 63
%78 = getelementptr inbounds [2 x i8], [2 x i8]* %11, i64 0, i64 1
%79 = load i8, i8* %78
%80 = zext i8 %79 to i32
%81 = or i32 %80, %77
%82 = trunc i32 %81 to i8
store i8 %82, i8* %78
br label %84
83: ; preds = %51
store i8* null, i8** %4
br label %139
84: ; preds = %54
br label %85
85: ; preds = %84, %15
%86 = load i64*, i64** %7
store i64 6, i64* %86
%87 = call i8* @malloc(i32 6)
store i8* %87, i8** %8
%88 = load i8*, i8** %8
%89 = icmp eq i8* %88, null
br i1 %89, label %90, label %91
90: ; preds = %85
store i8* null, i8** %4
br label %139
91: ; preds = %85
%92 = load i8*, i8** %8
%93 = getelementptr inbounds i8, i8* %92, i64 0
store i8 92, i8* %93
%94 = load i8*, i8** %8
%95 = getelementptr inbounds i8, i8* %94, i64 1
store i8 117, i8* %95
%96 = getelementptr inbounds [2 x i8], [2 x i8]* %11, i64 0, i64 0
%97 = load i8, i8* %96
%98 = zext i8 %97 to i32
%99 = sdiv i32 %98, 16
%100 = trunc i32 %99 to i8
store i8 %100, i8* %9
%101 = getelementptr inbounds [2 x i8], [2 x i8]* %11, i64 0, i64 0
%102 = load i8, i8* %101
%103 = zext i8 %102 to i32
%104 = load i8, i8* %9
%105 = zext i8 %104 to i32
%106 = mul nsw i32 %105, 16
%107 = sub nsw i32 %103, %106
%108 = trunc i32 %107 to i8
store i8 %108, i8* %10
%109 = load i8, i8* %9
%110 = call signext i8 @valueToHexDigit(i8 zeroext %109)
%111 = load i8*, i8** %8
%112 = getelementptr inbounds i8, i8* %111, i64 2
store i8 %110, i8* %112
%113 = load i8, i8* %10
%114 = call signext i8 @valueToHexDigit(i8 zeroext %113)
%115 = load i8*, i8** %8
%116 = getelementptr inbounds i8, i8* %115, i64 3
store i8 %114, i8* %116
%117 = getelementptr inbounds [2 x i8], [2 x i8]* %11, i64 0, i64 1
%118 = load i8, i8* %117
%119 = zext i8 %118 to i32
%120 = sdiv i32 %119, 16
%121 = trunc i32 %120 to i8
store i8 %121, i8* %9
%122 = getelementptr inbounds [2 x i8], [2 x i8]* %11, i64 0, i64 1
%123 = load i8, i8* %122
%124 = zext i8 %123 to i32
%125 = load i8, i8* %9
%126 = zext i8 %125 to i32
%127 = mul nsw i32 %126, 16
%128 = sub nsw i32 %124, %127
%129 = trunc i32 %128 to i8
store i8 %129, i8* %10
%130 = load i8, i8* %9
%131 = call signext i8 @valueToHexDigit(i8 zeroext %130)
%132 = load i8*, i8** %8
%133 = getelementptr inbounds i8, i8* %132, i64 4
store i8 %131, i8* %133
%134 = load i8, i8* %10
%135 = call signext i8 @valueToHexDigit(i8 zeroext %134)
%136 = load i8*, i8** %8
%137 = getelementptr inbounds i8, i8* %136, i64 5
store i8 %135, i8* %137
%138 = load i8*, i8** %8
store i8* %138, i8** %4
br label %139
139: ; preds = %91, %90, %83
%140 = load i8*, i8** %4
ret i8* %140
}

LLVM IR (-O2):
define noalias i8* @highCharToUnicode(i8* nocapture %0, i64 %1, i64* nocapture writeonly %2) {
switch i64 %1, label %41 [
i64 3, label %4
i64 2, label %12
]
4: ; preds = %3
%5 = load i8, i8* %0
%6 = shl i8 %5, 4
%7 = getelementptr inbounds i8, i8* %0, i64 1
%8 = load i8, i8* %7
%9 = lshr i8 %8, 2
%10 = and i8 %9, 15
%11 = or i8 %10, %6
br label %16
12: ; preds = %3
%13 = load i8, i8* %0
%14 = lshr i8 %13, 2
%15 = and i8 %14, 15
br label %16
16: ; preds = %12, %4
%17 = phi i8 [ %13, %12 ], [ %8, %4 ]
%18 = phi i64 [ 1, %12 ], [ 2, %4 ]
%19 = phi i8 [ %15, %12 ], [ %11, %4 ]
%20 = getelementptr inbounds i8, i8* %0, i64 %18
%21 = load i8, i8* %20
store i64 6, i64* %2
%22 = tail call dereferenceable_or_null(6) i8* @malloc(i32 6)
%23 = icmp eq i8* %22, null
br i1 %23, label %41, label %24
24: ; preds = %16
%25 = and i8 %21, 48
%26 = shl i8 %17, 6
%27 = or i8 %25, %26
store i8 92, i8* %22
%28 = getelementptr inbounds i8, i8* %22, i64 1
store i8 117, i8* %28
%29 = lshr i8 %19, 4
%30 = and i8 %19, 15
%31 = tail call signext i8 @valueToHexDigit(i8 zeroext %29)
%32 = getelementptr inbounds i8, i8* %22, i64 2
store i8 %31, i8* %32
%33 = tail call signext i8 @valueToHexDigit(i8 zeroext %30)
%34 = getelementptr inbounds i8, i8* %22, i64 3
store i8 %33, i8* %34
%35 = lshr exact i8 %27, 4
%36 = and i8 %21, 15
%37 = tail call signext i8 @valueToHexDigit(i8 zeroext %35)
%38 = getelementptr inbounds i8, i8* %22, i64 4
store i8 %37, i8* %38
%39 = tail call signext i8 @valueToHexDigit(i8 zeroext %36)
%40 = getelementptr inbounds i8, i8* %22, i64 5
store i8 %39, i8* %40
br label %41
41: ; preds = %16, %3, %24
%42 = phi i8* [ %22, %24 ], [ null, %3 ], [ null, %16 ]
ret i8* %42
}