#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 */
int /*<<< orphan*/ addnchar(char *, long);
char *luaI_addchar(int /*<<< orphan*/);
scalar_t__ lua_check_number(int, char *);
char *lua_check_string(int, char *);
long lua_opt_number(int, long, char *);
int /*<<< orphan*/ lua_pushstring(char *);
long strlen(char *);
void str_sub(void) {
  char *s = lua_check_string(1, "strsub");
  long start = (long)lua_check_number(2, "strsub");
  long end = lua_opt_number(3, strlen(s), "strsub");
  if (1 <= start && start <= end && end <= strlen(s)) {
    luaI_addchar(0);
    addnchar(s + start - 1, end - start + 1);
    lua_pushstring(luaI_addchar(0));
  } else
    lua_pushstring("");
}


x86 assembly (clang, -O0):
<str_sub>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    $0x1,%edi
lea    0xe7c(%rip),%rsi
call   1040 <lua_check_string@plt>
mov    %rax,-0x8(%rbp)
mov    $0x2,%edi
lea    0xe67(%rip),%rsi
call   1030 <lua_check_number@plt>
mov    %rax,-0x10(%rbp)
mov    -0x8(%rbp),%rdi
call   1060 <strlen@plt>
mov    %rax,%rsi
mov    $0x3,%edi
lea    0xe46(%rip),%rdx
call   1080 <lua_opt_number@plt>
mov    %rax,-0x18(%rbp)
mov    $0x1,%eax
cmp    -0x10(%rbp),%rax
jg     1239 <str_sub+0xc9>
mov    -0x10(%rbp),%rax
cmp    -0x18(%rbp),%rax
jg     1239 <str_sub+0xc9>
mov    -0x18(%rbp),%rax
mov    %rax,-0x20(%rbp)
mov    -0x8(%rbp),%rdi
call   1060 <strlen@plt>
mov    %rax,%rcx
mov    -0x20(%rbp),%rax
cmp    %rcx,%rax
jg     1239 <str_sub+0xc9>
xor    %edi,%edi
call   1070 <luaI_addchar@plt>
mov    -0x8(%rbp),%rdi
add    -0x10(%rbp),%rdi
add    $0xffffffffffffffff,%rdi
mov    -0x18(%rbp),%rsi
sub    -0x10(%rbp),%rsi
add    $0x1,%rsi
call   1050 <addnchar@plt>
xor    %edi,%edi
call   1070 <luaI_addchar@plt>
mov    %rax,%rdi
call   1090 <lua_pushstring@plt>
jmp    1245 <str_sub+0xd5>
lea    0xdc6(%rip),%rdi
call   1090 <lua_pushstring@plt>
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<str_sub>:
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
lea    0xe80(%rip),%rbx
mov    $0x1,%edi
mov    %rbx,%rsi
call   1040 <lua_check_string@plt>
mov    %rax,%r14
mov    $0x2,%edi
mov    %rbx,%rsi
call   1030 <lua_check_number@plt>
mov    %rax,%r12
mov    %r14,%rdi
call   1060 <strlen@plt>
mov    $0x3,%edi
mov    %rax,%rsi
mov    %rbx,%rdx
call   1080 <lua_opt_number@plt>
lea    0xe47(%rip),%r15
test   %r12,%r12
jle    1201 <str_sub+0x91>
mov    %rax,%r13
mov    %rax,%rbx
sub    %r12,%rbx
jl     1201 <str_sub+0x91>
mov    %r14,%rdi
call   1060 <strlen@plt>
cmp    %rax,%r13
jg     1201 <str_sub+0x91>
xor    %edi,%edi
call   1070 <luaI_addchar@plt>
lea    (%r14,%r12,1),%rdi
add    $0xffffffffffffffff,%rdi
add    $0x1,%rbx
mov    %rbx,%rsi
call   1050 <addnchar@plt>
xor    %edi,%edi
call   1070 <luaI_addchar@plt>
mov    %rax,%r15
mov    %r15,%rdi
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
jmp    1090 <lua_pushstring@plt>

LLVM IR (-O0):
@.str = [7 x i8] c"strsub\00"
@.str.1 = [1 x i8] zeroinitializer
define void @str_sub() {
%1 = alloca i8*
%2 = alloca i64
%3 = alloca i64
%4 = call i8* @lua_check_string(i32 1, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0))
store i8* %4, i8** %1
%5 = call i64 @lua_check_number(i32 2, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0))
store i64 %5, i64* %2
%6 = load i8*, i8** %1
%7 = call i64 @strlen(i8* %6)
%8 = call i64 @lua_opt_number(i32 3, i64 %7, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0))
store i64 %8, i64* %3
%9 = load i64, i64* %2
%10 = icmp sle i64 1, %9
br i1 %10, label %11, label %33
11: ; preds = %0
%12 = load i64, i64* %2
%13 = load i64, i64* %3
%14 = icmp sle i64 %12, %13
br i1 %14, label %15, label %33
15: ; preds = %11
%16 = load i64, i64* %3
%17 = load i8*, i8** %1
%18 = call i64 @strlen(i8* %17)
%19 = icmp sle i64 %16, %18
br i1 %19, label %20, label %33
20: ; preds = %15
%21 = call i8* @luaI_addchar(i32 0)
%22 = load i8*, i8** %1
%23 = load i64, i64* %2
%24 = getelementptr inbounds i8, i8* %22, i64 %23
%25 = getelementptr inbounds i8, i8* %24, i64 -1
%26 = load i64, i64* %3
%27 = load i64, i64* %2
%28 = sub nsw i64 %26, %27
%29 = add nsw i64 %28, 1
%30 = call i32 @addnchar(i8* %25, i64 %29)
%31 = call i8* @luaI_addchar(i32 0)
%32 = call i32 @lua_pushstring(i8* %31)
br label %35
33: ; preds = %15, %11, %0
%34 = call i32 @lua_pushstring(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.1, i64 0, i64 0))
br label %35
35: ; preds = %33, %20
ret void
}

LLVM IR (-O2):
@.str = [7 x i8] c"strsub\00"
@.str.1 = [1 x i8] zeroinitializer
define void @str_sub() {
%1 = tail call i8* @lua_check_string(i32 1, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0))
%2 = tail call i64 @lua_check_number(i32 2, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0))
%3 = tail call i64 @strlen(i8* dereferenceable(1) %1)
%4 = tail call i64 @lua_opt_number(i32 3, i64 %3, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i64 0, i64 0))
%5 = icmp slt i64 %2, 1
%6 = icmp slt i64 %4, %2
%7 = select i1 %5, i1 true, i1 %6
br i1 %7, label %19, label %8
8: ; preds = %0
%9 = tail call i64 @strlen(i8* dereferenceable(1) %1)
%10 = icmp sgt i64 %4, %9
br i1 %10, label %19, label %11
11: ; preds = %8
%12 = tail call i8* @luaI_addchar(i32 0)
%13 = getelementptr inbounds i8, i8* %1, i64 %2
%14 = getelementptr inbounds i8, i8* %13, i64 -1
%15 = sub nsw i64 1, %2
%16 = add i64 %15, %4
%17 = tail call i32 @addnchar(i8* %14, i64 %16)
%18 = tail call i8* @luaI_addchar(i32 0)
br label %19
19: ; preds = %0, %8, %11
%20 = phi i8* [ %18, %11 ], [ getelementptr inbounds ([1 x i8], [1 x i8]* @.str.1, i64 0, i64 0), %8 ], [ getelementptr inbounds ([1 x i8], [1 x i8]* @.str.1, i64 0, i64 0), %0 ]
%21 = tail call i32 @lua_pushstring(i8* %20)
ret void
}