text:
void lb_add_foreign_library_path(lbModule *m, Entity *e) {
	if (e == nullptr) {
		return;
	}
	GB_ASSERT(e->kind == Entity_LibraryName);
	GB_ASSERT(e->flags & EntityFlag_Used);

	mutex_lock(&m->gen->foreign_mutex);
	if (!ptr_set_update(&m->gen->foreign_libraries_set, e)) {
		array_add(&m->gen->foreign_libraries, e);
	}
	mutex_unlock(&m->gen->foreign_mutex);
}

GB_COMPARE_PROC(foreign_library_cmp) {
	int cmp = 0;
	Entity *x = *(Entity **)a;
	Entity *y = *(Entity **)b;
	if (x == y) {
		return 0;
	}
	GB_ASSERT(x->kind == Entity_LibraryName);
	GB_ASSERT(y->kind == Entity_LibraryName);

	cmp = i64_cmp(x->LibraryName.priority_index, y->LibraryName.priority_index);
	if (cmp) {
		return cmp;
	}

	if (x->pkg != y->pkg) {
		isize order_x = x->pkg ? x->pkg->order : 0;
		isize order_y = y->pkg ? y->pkg->order : 0;
		cmp = isize_cmp(order_x, order_y);
		if (cmp) {
			return cmp;
		}
	}
	if (x->file != y->file) {
		String fullpath_x = x->file ? x->file->fullpath : (String{});
		String fullpath_y = y->file ? y->file->fullpath : (String{});
		String file_x = filename_from_path(fullpath_x);
		String file_y = filename_from_path(fullpath_y);

		cmp = string_compare(file_x, file_y);
		if (cmp) {
			return cmp;
		}
	}

	cmp = u64_cmp(x->order_in_src, y->order_in_src);
	if (cmp) {
		return cmp;
	}
	return i32_cmp(x->token.pos.offset, y->token.pos.offset);
}

void lb_set_entity_from_other_modules_linkage_correctly(lbModule *other_module, Entity *e, String const &name) {
	if (other_module == nullptr) {
		return;
	}
	char const *cname = alloc_cstring(temporary_allocator(), name);

	LLVMValueRef other_global = nullptr;
	if (e->kind == Entity_Variable) {
		other_global = LLVMGetNamedGlobal(other_module->mod, cname);
	} else if (e->kind == Entity_Procedure) {
		other_global = LLVMGetNamedFunction(other_module->mod, cname);
	}
	if (other_global) {
		LLVMSetLinkage(other_global, LLVMExternalLinkage);
	}
}

void lb_emit_init_context(lbProcedure *p, lbAddr addr) {
	GB_ASSERT(addr.kind == lbAddr_Context);
	GB_ASSERT(addr.ctx.sel.index.count == 0);

	auto args = array_make<lbValue>(permanent_allocator(), 1);
	args[0] = addr.addr;
	lb_emit_runtime_call(p, "__init_context", args);
}

lbContextData *lb_push_context_onto_stack_from_implicit_parameter(lbProcedure *p) {
	Type *pt = base_type(p->type);
	GB_ASSERT(pt->kind == Type_Proc);
	GB_ASSERT(pt->Proc.calling_convention == ProcCC_Odin);

	String name = str_lit("__.context_ptr");

	Entity *e = alloc_entity_param(nullptr, make_token_ident(name), t_context_ptr, false, false);
	e->flags |= EntityFlag_NoAlias;

	LLVMValueRef context_ptr = LLVMGetParam(p->value, LLVMCountParams(p->value)-1);
	LLVMSetValueName2(context_ptr, cast(char const *)name.text, name.len);
	context_ptr = LLVMBuildPointerCast(p->builder, context_ptr, lb_type(p->module, e->type), "");

	lbValue param = {context_ptr, e->type};
	lb_add_entity(p->module, e, param);
	lbAddr ctx_addr = {};
	ctx_addr.kind = lbAddr_Context;
	ctx_addr.addr = param;

	lbContextData *cd = array_add_and_get(&p->context_stack);
	cd->ctx = ctx_addr;
	cd->scope_index = -1;
	cd->uses = +1; // make sure it has been used already
	return cd;
}

lbContextData *lb_push_context_onto_stack(lbProcedure *p, lbAddr ctx) {
	ctx.kind = lbAddr_Context;
	lbContextData *cd = array_add_and_get(&p->context_stack);
	cd->ctx = ctx;
	cd->scope_index = p->scope_index;
	return cd;
}

lbValue lb_get_equal_proc_for_type(lbModule *m, Type *type) {
	type = base_type(type);
	GB_ASSERT(is_type_comparable(type));

	Type *pt = alloc_type_pointer(type);
	LLVMTypeRef ptr_type = lb_type(m, pt);

	lbProcedure **found = map_get(&m->equal_procs, type);
	lbProcedure *compare_proc = nullptr;
	if (found) {
		compare_proc = *found;
		GB_ASSERT(compare_proc != nullptr);
		return {compare_proc->value, compare_proc->type};
	}

	static u32 proc_index = 0;

	char buf[16] = {};
	isize n = gb_snprintf(buf, 16, "__$equal%u", ++proc_index);
	char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1);
	String proc_name = make_string_c(str);

	lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_equal_proc);
	map_set(&m->equal_procs, type, p);
	lb_begin_procedure_body(p);

	LLVMValueRef x = LLVMGetParam(p->value, 0);
	LLVMValueRef y = LLVMGetParam(p->value, 1);
	x = LLVMBuildPointerCast(p->builder, x, ptr_type, "");
	y = LLVMBuildPointerCast(p->builder, y, ptr_type, "");
	lbValue lhs = {x, pt};
	lbValue rhs = {y, pt};

	lbBlock *block_same_ptr = lb_create_block(p, "same_ptr");
	lbBlock *block_diff_ptr = lb_create_block(p, "diff_ptr");

	lbValue same_ptr = lb_emit_comp(p, Token_CmpEq, lhs, rhs);
	lb_emit_if(p, same_ptr, block_same_ptr, block_diff_ptr);
	lb_start_block(p, block_same_ptr);
	LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_bool), 1, false));

	lb_start_block(p, block_diff_ptr);

	if (type->kind == Type_Struct) {
		type_set_offsets(type);

		lbBlock *block_false = lb_create_block(p, "bfalse");
		lbValue res = lb_const_bool(m, t_bool, true);

		for_array(i, type->Struct.fields) {
			lbBlock *next_block = lb_create_block(p, "btrue");

			lbValue pleft  = lb_emit_struct_ep(p, lhs, cast(i32)i);
			lbValue pright = lb_emit_struct_ep(p, rhs, cast(i32)i);
			lbValue left = lb_emit_load(p, pleft);
			lbValue right = lb_emit_load(p, pright);
			lbValue ok = lb_emit_comp(p, Token_CmpEq, left, right);

			lb_emit_if(p, ok, next_block, block_false);

			lb_emit_jump(p, next_block);
			lb_start_block(p, next_block);
		}

		LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_bool), 1, false));

		lb_start_block(p, block_false);

		LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_bool), 0, false));
	} else if (type->kind == Type_Union) {
		if (is_type_union_maybe_pointer(type)) {
			Type *v = type->Union.variants[0];
			Type *pv = alloc_type_pointer(v);

			lbValue left = lb_emit_load(p, lb_emit_conv(p, lhs, pv));
			lbValue right = lb_emit_load(p, lb_emit_conv(p, rhs, pv));

			lbValue ok = lb_emit_comp(p, Token_CmpEq, left, right);
			ok = lb_emit_conv(p, ok, t_bool);
			LLVMBuildRet(p->builder, ok.value);
		} else {
			lbBlock *block_false = lb_create_block(p, "bfalse");
			lbBlock *block_switch = lb_create_block(p, "bswitch");

			lbValue left_tag  = lb_emit_load(p, lb_emit_union_tag_ptr(p, lhs));
			lbValue right_tag = lb_emit_load(p, lb_emit_union_tag_ptr(p, rhs));

			lbValue tag_eq = lb_emit_comp(p, Token_CmpEq, left_tag, right_tag);
			lb_emit_if(p, tag_eq, block_switch, block_false);

			lb_start_block(p, block_switch);
			LLVMValueRef v_switch = LLVMBuildSwitch(p->builder, left_tag.value, block_false->block, cast(unsigned)type->Union.variants.count);

			for_array(i, type->Union.variants) {
				lbBlock *case_block = lb_create_block(p, "bcase");
				lb_start_block(p, case_block);

				Type *v = type->Union.variants[i];
				lbValue case_tag = lb_const_union_tag(p->module, type, v);

				Type *vp = alloc_type_pointer(v);

				lbValue left  = lb_emit_load(p, lb_emit_conv(p, lhs, vp));
				lbValue right = lb_emit_load(p, lb_emit_conv(p, rhs, vp));
				lbValue ok = lb_emit_comp(p, Token_CmpEq, left, right);
				ok = lb_emit_conv(p, ok, t_bool);

				LLVMBuildRet(p->builder, ok.value);

				LLVMAddCase(v_switch, case_tag.value, case_block->block);
			}

			lb_start_block(p, block_false);

			LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_bool), 0, false));
		}

	} else {
		lbValue left = lb_emit_load(p, lhs);
		lbValue right = lb_emit_load(p, rhs);
		lbValue ok = lb_emit_comp(p, Token_CmpEq, left, right);
		ok = lb_emit_conv(p, ok, t_bool);
		LLVMBuildRet(p->builder, ok.value);
	}

	lb_end_procedure_body(p);

	compare_proc = p;
	return {compare_proc->value, compare_proc->type};
}

lbValue lb_simple_compare_hash(lbProcedure *p, Type *type, lbValue data, lbValue seed) {
	GB_ASSERT_MSG(is_type_simple_compare(type), "%s", type_to_string(type));

	i64 sz = type_size_of(type);

	if (1 <= sz && sz <= 16) {
		char name[20] = {};
		gb_snprintf(name, 20, "default_hasher%d", cast(i32)sz);

		auto args = array_make<lbValue>(permanent_allocator(), 2);
		args[0] = data;
		args[1] = seed;
		return lb_emit_runtime_call(p, name, args);
	}

	auto args = array_make<lbValue>(permanent_allocator(), 3);
	args[0] = data;
	args[1] = seed;
	args[2] = lb_const_int(p->module, t_int, type_size_of(type));
	return lb_emit_runtime_call(p, "default_hasher_n", args);
}

lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) {
	type = core_type(type);
	GB_ASSERT(is_type_valid_for_keys(type));

	Type *pt = alloc_type_pointer(type);

	lbProcedure **found = map_get(&m->hasher_procs, type);
	if (found) {
		GB_ASSERT(*found != nullptr);
		return {(*found)->value, (*found)->type};
	}

	static u32 proc_index = 0;

	char buf[16] = {};
	isize n = gb_snprintf(buf, 16, "__$hasher%u", ++proc_index);
	char *str = gb_alloc_str_len(permanent_allocator(), buf, n-1);
	String proc_name = make_string_c(str);

	lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_hasher_proc);
	map_set(&m->hasher_procs, type, p);
	lb_begin_procedure_body(p);
	defer (lb_end_procedure_body(p));

	LLVMValueRef x = LLVMGetParam(p->value, 0);
	LLVMValueRef y = LLVMGetParam(p->value, 1);
	lbValue data = {x, t_rawptr};
	lbValue seed = {y, t_uintptr};

	LLVMAttributeRef nonnull_attr = lb_create_enum_attribute(m->ctx, "nonnull");
	LLVMAddAttributeAtIndex(p->value, 1+0, nonnull_attr);

	if (is_type_simple_compare(type)) {
		lbValue res = lb_simple_compare_hash(p, type, data, seed);
		LLVMBuildRet(p->builder, res.value);
		return {p->value, p->type};
	}

	if (type->kind == Type_Struct)  {
		type_set_offsets(type);
		data = lb_emit_conv(p, data, t_u8_ptr);

		auto args = array_make<lbValue>(permanent_allocator(), 2);
		for_array(i, type->Struct.fields) {
			GB_ASSERT(type->Struct.offsets != nullptr);
			i64 offset = type->Struct.offsets[i];
			Entity *field = type->Struct.fields[i];
			lbValue field_hasher = lb_get_hasher_proc_for_type(m, field->type);
			lbValue ptr = lb_emit_ptr_offset(p, data, lb_const_int(m, t_uintptr, offset));

			args[0] = ptr;
			args[1] = seed;
			seed = lb_emit_call(p, field_hasher, args);
		}
		LLVMBuildRet(p->builder, seed.value);
	} else if (type->kind == Type_Union)  {
		auto args = array_make<lbValue>(permanent_allocator(), 2);

		if (is_type_union_maybe_pointer(type)) {
			Type *v = type->Union.variants[0];
			lbValue variant_hasher = lb_get_hasher_proc_for_type(m, v);

			args[0] = data;
			args[1] = seed;
			lbValue res = lb_emit_call(p, variant_hasher, args);
			LLVMBuildRet(p->builder, res.value);
		}

		lbBlock *end_block = lb_create_block(p, "bend");
		data = lb_emit_conv(p, data, pt);

		lbValue tag_ptr = lb_emit_union_tag_ptr(p, data);
		lbValue tag = lb_emit_load(p, tag_ptr);

		LLVMValueRef v_switch = LLVMBuildSwitch(p->builder, tag.value, end_block->block, cast(unsigned)type->Union.variants.count);

		for_array(i, type->Union.variants) {
			lbBlock *case_block = lb_create_block(p, "bcase");
			lb_start_block(p, case_block);

			Type *v = type->Union.variants[i];
			lbValue case_tag = lb_const_union_tag(p->module, type, v);

			lbValue variant_hasher = lb_get_hasher_proc_for_type(m, v);

			args[0] = data;
			args[1] = seed;
			lbValue res = lb_emit_call(p, variant_hasher, args);
			LLVMBuildRet(p->builder, res.value);

			LLVMAddCase(v_switch, case_tag.value, case_block->block);
		}

		lb_start_block(p, end_block);
		LLVMBuildRet(p->builder, seed.value);

	} else if (type->kind == Type_Array) {
		lbAddr pres = lb_add_local_generated(p, t_uintptr, false);
		lb_addr_store(p, pres, seed);

		auto args = array_make<lbValue>(permanent_allocator(), 2);
		lbValue elem_hasher = lb_get_hasher_proc_for_type(m, type->Array.elem);

		auto loop_data = lb_loop_start(p, cast(isize)type->Array.count, t_i32);

		data = lb_emit_conv(p, data, pt);

		lbValue ptr = lb_emit_array_ep(p, data, loop_data.idx);
		args[0] = ptr;
		args[1] = lb_addr_load(p, pres);
		lbValue new_seed = lb_emit_call(p, elem_hasher, args);
		lb_addr_store(p, pres, new_seed);

		lb_loop_end(p, loop_data);

		lbValue res = lb_addr_load(p, pres);
		LLVMBuildRet(p->builder, res.value);
	} else if (type->kind == Type_EnumeratedArray) {
		lbAddr res = lb_add_local_generated(p, t_uintptr, false);
		lb_addr_store(p, res, seed);

		auto args = array_make<lbValue>(permanent_allocator(), 2);
		lbValue elem_hasher = lb_get_hasher_proc_for_type(m, type->EnumeratedArray.elem);

		auto loop_data = lb_loop_start(p, cast(isize)type->EnumeratedArray.count, t_i32);

		data = lb_emit_conv(p, data, pt);

		lbValue ptr = lb_emit_array_ep(p, data, loop_data.idx);
		args[0] = ptr;
		args[1] = lb_addr_load(p, res);
		lbValue new_seed = lb_emit_call(p, elem_hasher, args);
		lb_addr_store(p, res, new_seed);

		lb_loop_end(p, loop_data);

		lbValue vres = lb_addr_load(p, res);
		LLVMBuildRet(p->builder, vres.value);
	} else if (is_type_cstring(type)) {
		auto args = array_make<lbValue>(permanent_allocator(), 2);
		args[0] = data;
		args[1] = seed;
		lbValue res = lb_emit_runtime_call(p, "default_hasher_cstring", args);
		LLVMBuildRet(p->builder, res.value);
	} else if (is_type_string(type)) {
		auto args = array_make<lbValue>(permanent_allocator(), 2);
		args[0] = data;
		args[1] = seed;
		lbValue res = lb_emit_runtime_call(p, "default_hasher_string", args);
		LLVMBuildRet(p->builder, res.value);
	} else {
		GB_PANIC("Unhandled type for hasher: %s", type_to_string(type));
	}

	return {p->value, p->type};
}

lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, Ast *expr, lbProcedure *parent) {
	lbProcedure **found = map_get(&m->gen->anonymous_proc_lits, expr);
	if (found) {
		return lb_find_procedure_value_from_entity(m, (*found)->entity);
	}

	ast_node(pl, ProcLit, expr);

	// NOTE(bill): Generate a new name
	// parent$count
	isize name_len = prefix_name.len + 1 + 8 + 1;
	char *name_text = gb_alloc_array(permanent_allocator(), char, name_len);
	i32 name_id = cast(i32)m->gen->anonymous_proc_lits.entries.count;

	name_len = gb_snprintf(name_text, name_len, "%.*s$anon-%d", LIT(prefix_name), name_id);
	String name = make_string((u8 *)name_text, name_len-1);

	Type *type = type_of_expr(expr);

	Token token = {};
	token.pos = ast_token(expr).pos;
	token.kind = Token_Ident;
	token.string = name;
	Entity *e = alloc_entity_procedure(nullptr, token, type, pl->tags);
	e->file = expr->file();
	e->decl_info = pl->decl;
	e->code_gen_module = m;
	e->flags |= EntityFlag_ProcBodyChecked;
	lbProcedure *p = lb_create_procedure(m, e);

	lbValue value = {};
	value.value = p->value;
	value.type = p->type;

	array_add(&m->procedures_to_generate, p);
	if (parent != nullptr) {
		array_add(&parent->children, p);
	} else {
		string_map_set(&m->members, name, value);
	}

	map_set(&m->gen->anonymous_proc_lits, expr, p);

	return value;
}

lbValue lb_gen_map_header(lbProcedure *p, lbValue map_val_ptr, Type *map_type) {
	GB_ASSERT_MSG(is_type_pointer(map_val_ptr.type), "%s", type_to_string(map_val_ptr.type));
	lbAddr h = lb_add_local_generated(p, t_map_header, false); // all the values will be initialzed later
	map_type = base_type(map_type);
	GB_ASSERT(map_type->kind == Type_Map);

	Type *key_type = map_type->Map.key;
	Type *val_type = map_type->Map.value;
	gb_unused(val_type);

	GB_ASSERT(map_type->Map.entry_type->kind == Type_Struct);
	map_type->Map.entry_type->cached_size = -1;
	map_type->Map.entry_type->Struct.are_offsets_set = false;

	i64 entry_size   = type_size_of  (map_type->Map.entry_type);
	i64 entry_align  = type_align_of (map_type->Map.entry_type);

	i64 key_offset = type_offset_of(map_type->Map.entry_type, 2);
	i64 key_size   = type_size_of  (map_type->Map.key);

	i64 value_offset = type_offset_of(map_type->Map.entry_type, 3);
	i64 value_size   = type_size_of  (map_type->Map.value);

	Type *map_header_base = base_type(t_map_header);
	GB_ASSERT(map_header_base->Struct.fields.count == 8);
	Type *raw_map_ptr_type = map_header_base->Struct.fields[0]->type;
	LLVMValueRef const_values[8] = {};
	const_values[0] = LLVMConstNull(lb_type(p->module, raw_map_ptr_type));
	const_values[1] = lb_get_equal_proc_for_type(p->module, key_type)    .value;
	const_values[2] = lb_const_int(p->module, t_int,        entry_size)  .value;
	const_values[3] = lb_const_int(p->module, t_int,        entry_align) .value;
	const_values[4] = lb_const_int(p->module, t_uintptr,    key_offset)  .value;
	const_values[5] = lb_const_int(p->module, t_int,        key_size)    .value;
	const_values[6] = lb_const_int(p->module, t_uintptr,    value_offset).value;
	const_values[7] = lb_const_int(p->module, t_int,        value_size)  .value;

	LLVMValueRef const_value = llvm_const_named_struct(p->module, t_map_header, const_values, gb_count_of(const_values));
	LLVMBuildStore(p->builder, const_value, h.addr.value);

	// NOTE(bill): Removes unnecessary allocation if split gep
	lbValue gep0 = lb_emit_struct_ep(p, h.addr, 0);
	lbValue m = lb_emit_conv(p, map_val_ptr, type_deref(gep0.type));
	lb_emit_store(p, gep0, m);

	return lb_addr_load(p, h);
}

lbValue lb_const_hash(lbModule *m, lbValue key, Type *key_type) {
	if (true) {
		return {};
	}

	lbValue hashed_key = {};

#if 0
	if (lb_is_const(key)) {
		u64 hash = 0xcbf29ce484222325;
		if (is_type_cstring(key_type)) {
			size_t length = 0;
			char const *text = LLVMGetAsString(key.value, &length);
			hash = fnv64a(text, cast(isize)length);
		} else if (is_type_string(key_type)) {
			unsigned data_indices[] = {0};
			unsigned len_indices[] = {1};
			LLVMValueRef data = LLVMConstExtractValue(key.value, data_indices, gb_count_of(data_indices));
			LLVMValueRef len  = LLVMConstExtractValue(key.value, len_indices,  gb_count_of(len_indices));
			i64 length = LLVMConstIntGetSExtValue(len);
			char const *text = nullptr;
			if (false && length != 0) {
			if (LLVMGetConstOpcode(data) != LLVMGetElementPtr) {
					return {};
				}
				// TODO(bill): THIS IS BROKEN! THIS NEEDS FIXING :P

				size_t ulength = 0;
				text = LLVMGetAsString(data, &ulength);
				gb_printf_err("%lld %llu %s\n", length, ulength, text);
				length = gb_min(length, cast(i64)ulength);
			}
			hash = fnv64a(text, cast(isize)length);
		} else {
			return {};
		}
		// TODO(bill): other const hash types

		if (build_context.word_size == 4) {
			hash &= 0xffffffffull;
		}
		hashed_key = lb_const_int(m, t_uintptr, hash);
	}
#endif
	return hashed_key;
}

lbValue lb_gen_map_hash(lbProcedure *p, lbValue key, Type *key_type) {
	lbAddr v = lb_add_local_generated(p, t_map_hash, true);
	lbValue vp = lb_addr_get_ptr(p, v);
	key = lb_emit_conv(p, key, key_type);

	lbValue key_ptr = lb_address_from_load_or_generate_local(p, key);
	key_ptr = lb_emit_conv(p, key_ptr, t_rawptr);

	lbValue hashed_key = lb_const_hash(p->module, key, key_type);
	if (hashed_key.value == nullptr) {
		lbValue hasher = lb_get_hasher_proc_for_type(p->module, key_type);

		auto args = array_make<lbValue>(permanent_allocator(), 2);
		args[0] = key_ptr;
		args[1] = lb_const_int(p->module, t_uintptr, 0);
		hashed_key = lb_emit_call(p, hasher, args);
	}

	lb_emit_store(p, lb_emit_struct_ep(p, vp, 0), hashed_key);
	lb_emit_store(p, lb_emit_struct_ep(p, vp, 1), key_ptr);

	return lb_addr_load(p, v);
}

void lb_insert_dynamic_map_key_and_value(lbProcedure *p, lbAddr addr, Type *map_type,
                                         lbValue map_key, lbValue map_value, Ast *node) {
	map_type = base_type(map_type);
	GB_ASSERT(map_type->kind == Type_Map);

	lbValue h = lb_gen_map_header(p, addr.addr, map_type);
	lbValue key = lb_gen_map_hash(p, map_key, map_type->Map.key);
	lbValue v = lb_emit_conv(p, map_value, map_type->Map.value);

	lbAddr value_addr = lb_add_local_generated(p, v.type, false);
	lb_addr_store(p, value_addr, v);

	auto args = array_make<lbValue>(permanent_allocator(), 4);
	args[0] = h;
	args[1] = key;
	args[2] = lb_emit_conv(p, value_addr.addr, t_rawptr);
	args[3] = lb_emit_source_code_location(p, node);
	lb_emit_runtime_call(p, "__dynamic_map_set", args);
}

struct lbGlobalVariable {
	lbValue var;
	lbValue init;
	DeclInfo *decl;
	bool is_initialized;
};

lbProcedure *lb_create_startup_type_info(lbModule *m) {
	if (build_context.disallow_rtti) {
		return nullptr;
	}
	LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod);
	lb_populate_function_pass_manager(m, default_function_pass_manager, false, build_context.optimization_level);
	LLVMFinalizeFunctionPassManager(default_function_pass_manager);

	Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_CDecl);

	lbProcedure *p = lb_create_dummy_procedure(m, str_lit(LB_STARTUP_TYPE_INFO_PROC_NAME), proc_type);
	p->is_startup = true;
	LLVMSetLinkage(p->value, LLVMInternalLinkage);

	lb_begin_procedure_body(p);

	lb_setup_type_info_data(p);

	lb_end_procedure_body(p);

	if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
		gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
		LLVMDumpValue(p->value);
		gb_printf_err("\n\n\n\n");
		LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
	}

	lb_run_function_pass_manager(default_function_pass_manager, p);

	return p;
}

lbProcedure *lb_create_objc_names(lbModule *main_module) {
	if (build_context.metrics.os != TargetOs_darwin) {
		return nullptr;
	}
	Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_CDecl);
	lbProcedure *p = lb_create_dummy_procedure(main_module, str_lit("__$init_objc_names"), proc_type);
	p->is_startup = true;
	return p;
}

void lb_finalize_objc_names(lbProcedure *p) {
	if (p == nullptr) {
		return;
	}
	lbModule *m = p->module;

	LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod);
	lb_populate_function_pass_manager(m, default_function_pass_manager, false, build_context.optimization_level);
	LLVMFinalizeFunctionPassManager(default_function_pass_manager);

	auto args = array_make<lbValue>(permanent_allocator(), 1);

	LLVMSetLinkage(p->value, LLVMInternalLinkage);
	lb_begin_procedure_body(p);
	for_array(i, m->objc_classes.entries) {
		auto const &entry = m->objc_classes.entries[i];
		String name = entry.key.string;
		args[0] = lb_const_value(m, t_cstring, exact_value_string(name));
		lbValue ptr = lb_emit_runtime_call(p, "objc_lookUpClass", args);
		lb_addr_store(p, entry.value, ptr);
	}

	for_array(i, m->objc_selectors.entries) {
		auto const &entry = m->objc_selectors.entries[i];
		String name = entry.key.string;
		args[0] = lb_const_value(m, t_cstring, exact_value_string(name));
		lbValue ptr = lb_emit_runtime_call(p, "sel_registerName", args);
		lb_addr_store(p, entry.value, ptr);
	}

	lb_end_procedure_body(p);

	lb_run_function_pass_manager(default_function_pass_manager, p);

}

lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *startup_type_info, lbProcedure *objc_names, Array<lbGlobalVariable> &global_variables) { // Startup Runtime
	LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(main_module->mod);
	lb_populate_function_pass_manager(main_module, default_function_pass_manager, false, build_context.optimization_level);
	LLVMFinalizeFunctionPassManager(default_function_pass_manager);

	Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_Odin);

	lbProcedure *p = lb_create_dummy_procedure(main_module, str_lit(LB_STARTUP_RUNTIME_PROC_NAME), proc_type);
	p->is_startup = true;

	lb_begin_procedure_body(p);

	if (startup_type_info) {
		LLVMBuildCall2(p->builder, lb_type_internal_for_procedures_raw(main_module, startup_type_info->type), startup_type_info->value, nullptr, 0, "");
	}

	if (objc_names) {
		LLVMBuildCall2(p->builder, lb_type_internal_for_procedures_raw(main_module, objc_names->type), objc_names->value, nullptr, 0, "");
	}

	for_array(i, global_variables) {
		auto *var = &global_variables[i];
		if (var->is_initialized) {
			continue;
		}

		lbModule *entity_module = main_module;

		Entity *e = var->decl->entity;
		GB_ASSERT(e->kind == Entity_Variable);
		e->code_gen_module = entity_module;

		Ast *init_expr = var->decl->init_expr;
		if (init_expr != nullptr)  {
			lbValue init = lb_build_expr(p, init_expr);
			if (init.value == nullptr) {
				LLVMTypeRef global_type = llvm_addr_type(p->module, var->var);
				if (is_type_untyped_undef(init.type)) {
					// LLVMSetInitializer(var->var.value, LLVMGetUndef(global_type));
					LLVMSetInitializer(var->var.value, LLVMConstNull(global_type));
					var->is_initialized = true;
					continue;
				} else if (is_type_untyped_nil(init.type)) {
					LLVMSetInitializer(var->var.value, LLVMConstNull(global_type));
					var->is_initialized = true;
					continue;
				}
				GB_PANIC("Invalid init value, got %s", expr_to_string(init_expr));
			}

			if (is_type_any(e->type) || is_type_union(e->type)) {
				var->init = init;
			} else if (lb_is_const_or_global(init)) {
				if (!var->is_initialized) {
					LLVMSetInitializer(var->var.value, init.value);
					var->is_initialized = true;
					continue;
				}
			} else {
				var->init = init;
			}
		}

		if (var->init.value != nullptr) {
			GB_ASSERT(!var->is_initialized);
			Type *t = type_deref(var->var.type);

			if (is_type_any(t)) {
				// NOTE(bill): Edge case for 'any' type
				Type *var_type = default_type(var->init.type);
				lbAddr g = lb_add_global_generated(main_module, var_type, var->init);
				lb_addr_store(p, g, var->init);
				lbValue gp = lb_addr_get_ptr(p, g);

				lbValue data = lb_emit_struct_ep(p, var->var, 0);
				lbValue ti   = lb_emit_struct_ep(p, var->var, 1);
				lb_emit_store(p, data, lb_emit_conv(p, gp, t_rawptr));
				lb_emit_store(p, ti,   lb_type_info(main_module, var_type));
			} else {
				LLVMTypeRef vt = llvm_addr_type(p->module, var->var);
				lbValue src0 = lb_emit_conv(p, var->init, t);
				LLVMValueRef src = OdinLLVMBuildTransmute(p, src0.value, vt);
				LLVMValueRef dst = var->var.value;
				LLVMBuildStore(p->builder, src, dst);
			}

			var->is_initialized = true;
		}
	}

	CheckerInfo *info = main_module->gen->info;

	for (Entity *e : info->init_procedures) {
		lbValue value = lb_find_procedure_value_from_entity(main_module, e);
		lb_emit_call(p, value, {}, ProcInlining_none, false);
	}

	lb_end_procedure_body(p);

	if (!main_module->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
		gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
		LLVMDumpValue(p->value);
		gb_printf_err("\n\n\n\n");
		LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
	}

	lb_run_function_pass_manager(default_function_pass_manager, p);

	return p;
}

lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime) {
	LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod);
	lb_populate_function_pass_manager(m, default_function_pass_manager, false, build_context.optimization_level);
	LLVMFinalizeFunctionPassManager(default_function_pass_manager);

	Type *params  = alloc_type_tuple();
	Type *results = alloc_type_tuple();

	Type *t_ptr_cstring = alloc_type_pointer(t_cstring);

	bool call_cleanup = true;

	bool has_args = false;
	bool is_dll_main = false;
	String name = str_lit("main");
	if (build_context.metrics.os == TargetOs_windows && build_context.build_mode == BuildMode_DynamicLibrary) {
		is_dll_main = true;
		name = str_lit("DllMain");
		slice_init(&params->Tuple.variables, permanent_allocator(), 3);
		params->Tuple.variables[0] = alloc_entity_param(nullptr, make_token_ident("hinstDLL"),   t_rawptr, false, true);
		params->Tuple.variables[1] = alloc_entity_param(nullptr, make_token_ident("fdwReason"),  t_u32,    false, true);
		params->Tuple.variables[2] = alloc_entity_param(nullptr, make_token_ident("lpReserved"), t_rawptr, false, true);
		call_cleanup = false;
	} else if (build_context.metrics.os == TargetOs_windows && (build_context.metrics.arch == TargetArch_i386 || build_context.no_crt)) {
		name = str_lit("mainCRTStartup");
	} else if (is_arch_wasm()) {
		name = str_lit("_start");
		call_cleanup = false;
	} else {
		has_args = true;
		slice_init(&params->Tuple.variables, permanent_allocator(), 2);
		params->Tuple.variables[0] = alloc_entity_param(nullptr, make_token_ident("argc"), t_i32, false, true);
		params->Tuple.variables[1] = alloc_entity_param(nullptr, make_token_ident("argv"), t_ptr_cstring, false, true);
	}

	slice_init(&results->Tuple.variables, permanent_allocator(), 1);
	results->Tuple.variables[0] = alloc_entity_param(nullptr, blank_token, t_i32, false, true);

	Type *proc_type = alloc_type_proc(nullptr,
		params, params->Tuple.variables.count,
		results, results->Tuple.variables.count, false, ProcCC_CDecl);

	lbProcedure *p = lb_create_dummy_procedure(m, name, proc_type);
	p->is_startup = true;

	lb_begin_procedure_body(p);

	if (has_args) { // initialize `runtime.args__`
		lbValue argc = {LLVMGetParam(p->value, 0), t_i32};
		lbValue argv = {LLVMGetParam(p->value, 1), t_ptr_cstring};
		LLVMSetValueName2(argc.value, "argc", 4);
		LLVMSetValueName2(argv.value, "argv", 4);
		argc = lb_emit_conv(p, argc, t_int);
		lbAddr args = lb_addr(lb_find_runtime_value(p->module, str_lit("args__")));
		lb_fill_slice(p, args, argv, argc);
	}

	lbValue startup_runtime_value = {startup_runtime->value, startup_runtime->type};
	lb_emit_call(p, startup_runtime_value, {}, ProcInlining_none, false);

	if (build_context.command_kind == Command_test) {
		Type *t_Internal_Test = find_type_in_pkg(m->info, str_lit("testing"), str_lit("Internal_Test"));
		Type *array_type = alloc_type_array(t_Internal_Test, m->info->testing_procedures.count);
		Type *slice_type = alloc_type_slice(t_Internal_Test);
		lbAddr all_tests_array_addr = lb_add_global_generated(p->module, array_type, {});
		lbValue all_tests_array = lb_addr_get_ptr(p, all_tests_array_addr);

		LLVMValueRef indices[2] = {};
		indices[0] = LLVMConstInt(lb_type(m, t_i32), 0, false);

		for_array(i, m->info->testing_procedures) {
			Entity *testing_proc = m->info->testing_procedures[i];
			String name = testing_proc->token.string;

			String pkg_name = {};
			if (testing_proc->pkg != nullptr) {
				pkg_name = testing_proc->pkg->name;
			}
			lbValue v_pkg  = lb_find_or_add_entity_string(m, pkg_name);
			lbValue v_name = lb_find_or_add_entity_string(m, name);
			lbValue v_proc = lb_find_procedure_value_from_entity(m, testing_proc);

			indices[1] = LLVMConstInt(lb_type(m, t_int), i, false);

			LLVMValueRef vals[3] = {};
			vals[0] = v_pkg.value;
			vals[1] = v_name.value;
			vals[2] = v_proc.value;
			GB_ASSERT(LLVMIsConstant(vals[0]));
			GB_ASSERT(LLVMIsConstant(vals[1]));
			GB_ASSERT(LLVMIsConstant(vals[2]));

			LLVMValueRef dst = LLVMConstInBoundsGEP2(llvm_addr_type(m, all_tests_array), all_tests_array.value, indices, gb_count_of(indices));
			LLVMValueRef src = llvm_const_named_struct(m, t_Internal_Test, vals, gb_count_of(vals));

			LLVMBuildStore(p->builder, src, dst);
		}

		lbAddr all_tests_slice = lb_add_local_generated(p, slice_type, true);
		lb_fill_slice(p, all_tests_slice,
		              lb_array_elem(p, all_tests_array),
		              lb_const_int(m, t_int, m->info->testing_procedures.count));

		lbValue runner = lb_find_package_value(m, str_lit("testing"), str_lit("runner"));

		auto args = array_make<lbValue>(heap_allocator(), 1);
		args[0] = lb_addr_load(p, all_tests_slice);
		lb_emit_call(p, runner, args);
	} else {
		if (m->info->entry_point != nullptr) {
			lbValue entry_point = lb_find_procedure_value_from_entity(m, m->info->entry_point);
			lb_emit_call(p, entry_point, {}, ProcInlining_no_inline);
		}
	}

	if (call_cleanup) {
		lbValue cleanup_runtime_value = lb_find_runtime_value(m, str_lit("_cleanup_runtime"));
		lb_emit_call(p, cleanup_runtime_value, {}, ProcInlining_none, false);
	}

	if (is_dll_main) {
		LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_i32), 1, false));
	} else {
		LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_i32), 0, false));
	}

	lb_end_procedure_body(p);

	LLVMSetLinkage(p->value, LLVMExternalLinkage);
	if (is_arch_wasm()) {
		lb_set_wasm_export_attributes(p->value, p->name);
	}

	if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
		gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
		LLVMDumpValue(p->value);
		gb_printf_err("\n\n\n\n");
		LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
	}

	lb_run_function_pass_manager(default_function_pass_manager, p);
	return p;
}

String lb_filepath_ll_for_module(lbModule *m) {
	String path = concatenate3_strings(permanent_allocator(),
		build_context.build_paths[BuildPath_Output].basename,
		STR_LIT("/"),
		build_context.build_paths[BuildPath_Output].name
	);

	if (m->pkg) {
		path = concatenate3_strings(permanent_allocator(), path, STR_LIT("-"), m->pkg->name);
	} else if (USE_SEPARATE_MODULES) {
		path = concatenate_strings(permanent_allocator(), path, STR_LIT("-builtin"));
	}
	path = concatenate_strings(permanent_allocator(), path, STR_LIT(".ll"));

	return path;
}
String lb_filepath_obj_for_module(lbModule *m) {
	String path = concatenate3_strings(permanent_allocator(),
		build_context.build_paths[BuildPath_Output].basename,
		STR_LIT("/"),
		build_context.build_paths[BuildPath_Output].name
	);

	if (m->pkg) {
		path = concatenate3_strings(permanent_allocator(), path, STR_LIT("-"), m->pkg->name);
	}

	String ext = {};

	if (build_context.build_mode == BuildMode_Assembly) {
		ext = STR_LIT(".S");
	} else {
		if (is_arch_wasm()) {
			ext = STR_LIT(".wasm.o");
		} else {
			switch (build_context.metrics.os) {
			case TargetOs_windows:
				ext = STR_LIT(".obj");
				break;
			default:
			case TargetOs_darwin:
			case TargetOs_linux:
			case TargetOs_essence:
				ext = STR_LIT(".o");
				break;

			case TargetOs_freestanding:
				switch (build_context.metrics.abi) {
				default:
				case TargetABI_Default:
				case TargetABI_SysV:
					ext = STR_LIT(".o");
					break;
				case TargetABI_Win64:
					ext = STR_LIT(".obj");
					break;
				}
				break;
			}
		}
	}

	return concatenate_strings(permanent_allocator(), path, ext);
}

bool lb_is_module_empty(lbModule *m) {
	if (LLVMGetFirstFunction(m->mod) == nullptr &&
	    LLVMGetFirstGlobal(m->mod) == nullptr) {
		return true;
	}
	for (auto fn = LLVMGetFirstFunction(m->mod); fn != nullptr; fn = LLVMGetNextFunction(fn)) {
		if (LLVMGetFirstBasicBlock(fn) != nullptr) {
			return false;
		}
	}

	for (auto g = LLVMGetFirstGlobal(m->mod); g != nullptr; g = LLVMGetNextGlobal(g)) {
		if (LLVMGetLinkage(g) == LLVMExternalLinkage) {
			continue;
		}
		if (!LLVMIsExternallyInitialized(g)) {
			return false;
		}
	}
	return true;
}

struct lbLLVMEmitWorker {
	LLVMTargetMachineRef target_machine;
	LLVMCodeGenFileType code_gen_file_type;
	String filepath_obj;
	lbModule *m;
};

WORKER_TASK_PROC(lb_llvm_emit_worker_proc) {
	GB_ASSERT(MULTITHREAD_OBJECT_GENERATION);

	char *llvm_error = nullptr;

	auto wd = cast(lbLLVMEmitWorker *)data;

	if (LLVMTargetMachineEmitToFile(wd->target_machine, wd->m->mod, cast(char *)wd->filepath_obj.text, wd->code_gen_file_type, &llvm_error)) {
		gb_printf_err("LLVM Error: %s\n", llvm_error);
		gb_exit(1);
	}

	return 0;
}

WORKER_TASK_PROC(lb_llvm_function_pass_worker_proc) {
	GB_ASSERT(MULTITHREAD_OBJECT_GENERATION);

	auto m = cast(lbModule *)data;

	LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod);
	LLVMPassManagerRef function_pass_manager_minimal = LLVMCreateFunctionPassManagerForModule(m->mod);
	LLVMPassManagerRef function_pass_manager_size = LLVMCreateFunctionPassManagerForModule(m->mod);
	LLVMPassManagerRef function_pass_manager_speed = LLVMCreateFunctionPassManagerForModule(m->mod);

	LLVMInitializeFunctionPassManager(default_function_pass_manager);
	LLVMInitializeFunctionPassManager(function_pass_manager_minimal);
	LLVMInitializeFunctionPassManager(function_pass_manager_size);
	LLVMInitializeFunctionPassManager(function_pass_manager_speed);

	lb_populate_function_pass_manager(m, default_function_pass_manager, false, build_context.optimization_level);
	lb_populate_function_pass_manager_specific(m, function_pass_manager_minimal, 0);
	lb_populate_function_pass_manager_specific(m, function_pass_manager_size,    1);
	lb_populate_function_pass_manager_specific(m, function_pass_manager_speed,   2);

	LLVMFinalizeFunctionPassManager(default_function_pass_manager);
	LLVMFinalizeFunctionPassManager(function_pass_manager_minimal);
	LLVMFinalizeFunctionPassManager(function_pass_manager_size);
	LLVMFinalizeFunctionPassManager(function_pass_manager_speed);

	LLVMPassManagerRef default_function_pass_manager_without_memcpy = LLVMCreateFunctionPassManagerForModule(m->mod);
	LLVMInitializeFunctionPassManager(default_function_pass_manager_without_memcpy);
	lb_populate_function_pass_manager(m, default_function_pass_manager_without_memcpy, true, build_context.optimization_level);
	LLVMFinalizeFunctionPassManager(default_function_pass_manager_without_memcpy);

	for_array(i, m->procedures_to_generate) {
		lbProcedure *p = m->procedures_to_generate[i];
		if (p->body != nullptr) { // Build Procedure
			if (p->flags & lbProcedureFlag_WithoutMemcpyPass) {
				lb_run_function_pass_manager(default_function_pass_manager_without_memcpy, p);
			} else {
				if (p->entity && p->entity->kind == Entity_Procedure) {
					switch (p->entity->Procedure.optimization_mode) {
					case ProcedureOptimizationMode_None:
					case ProcedureOptimizationMode_Minimal:
						lb_run_function_pass_manager(function_pass_manager_minimal, p);
						break;
					case ProcedureOptimizationMode_Size:
						lb_run_function_pass_manager(function_pass_manager_size, p);
						break;
					case ProcedureOptimizationMode_Speed:
						lb_run_function_pass_manager(function_pass_manager_speed, p);
						break;
					default:
						lb_run_function_pass_manager(default_function_pass_manager, p);
						break;
					}
				} else {
					lb_run_function_pass_manager(default_function_pass_manager, p);
				}
			}
		}
	}

	for_array(i, m->equal_procs.entries) {
		lbProcedure *p = m->equal_procs.entries[i].value;
		lb_run_function_pass_manager(default_function_pass_manager, p);
	}
	for_array(i, m->hasher_procs.entries) {
		lbProcedure *p = m->hasher_procs.entries[i].value;
		lb_run_function_pass_manager(default_function_pass_manager, p);
	}

	return 0;
}

struct lbLLVMModulePassWorkerData {
	lbModule *m;
	LLVMTargetMachineRef target_machine;
};

WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) {
	auto wd = cast(lbLLVMModulePassWorkerData *)data;
	LLVMPassManagerRef module_pass_manager = LLVMCreatePassManager();
	lb_populate_module_pass_manager(wd->target_machine, module_pass_manager, build_context.optimization_level);
	LLVMRunPassManager(module_pass_manager, wd->m->mod);
	return 0;
}

void lb_generate_procedure(lbModule *m, lbProcedure *p) {
	if (p->is_done) {
		return;
	}
	if (p->body != nullptr) { // Build Procedure
		m->curr_procedure = p;
		lb_begin_procedure_body(p);
		lb_build_stmt(p, p->body);
		lb_end_procedure_body(p);
		p->is_done = true;
		m->curr_procedure = nullptr;
	}
	lb_end_procedure(p);

	// Add Flags
	if (p->body != nullptr) {
		if (p->name == "memcpy" || p->name == "memmove" ||
		    p->name == "runtime.mem_copy" || p->name == "mem_copy_non_overlapping" ||
		    string_starts_with(p->name, str_lit("llvm.memcpy")) ||
		    string_starts_with(p->name, str_lit("llvm.memmove"))) {
			p->flags |= lbProcedureFlag_WithoutMemcpyPass;
		}
	}

	if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
		char *llvm_error = nullptr;

		gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %.*s\n", LIT(p->name));
		LLVMDumpValue(p->value);
		gb_printf_err("\n\n\n\n");
		String filepath_ll = lb_filepath_ll_for_module(m);
		if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
			gb_printf_err("LLVM Error: %s\n", llvm_error);
		}
		LLVMVerifyFunction(p->value, LLVMPrintMessageAction);
		gb_exit(1);
	}
}

void lb_generate_code(lbGenerator *gen) {
	TIME_SECTION("LLVM Initializtion");

	isize thread_count = gb_max(build_context.thread_count, 1);
	isize worker_count = thread_count-1;

	LLVMBool do_threading = (LLVMIsMultithreaded() && USE_SEPARATE_MODULES && MULTITHREAD_OBJECT_GENERATION && worker_count > 0);

	lbModule *default_module = &gen->default_module;
	CheckerInfo *info = gen->info;

	auto *min_dep_set = &info->minimum_dependency_set;

	switch (build_context.metrics.arch) {
	case TargetArch_amd64:
	case TargetArch_i386:
		LLVMInitializeX86TargetInfo();
		LLVMInitializeX86Target();
		LLVMInitializeX86TargetMC();
		LLVMInitializeX86AsmPrinter();
		LLVMInitializeX86AsmParser();
		LLVMInitializeX86Disassembler();
		break;
	case TargetArch_arm64:
		LLVMInitializeAArch64TargetInfo();
		LLVMInitializeAArch64Target();
		LLVMInitializeAArch64TargetMC();
		LLVMInitializeAArch64AsmPrinter();
		LLVMInitializeAArch64AsmParser();
		LLVMInitializeAArch64Disassembler();
		break;
	case TargetArch_wasm32:
	case TargetArch_wasm64:
		LLVMInitializeWebAssemblyTargetInfo();
		LLVMInitializeWebAssemblyTarget();
		LLVMInitializeWebAssemblyTargetMC();
		LLVMInitializeWebAssemblyAsmPrinter();
		LLVMInitializeWebAssemblyAsmParser();
		LLVMInitializeWebAssemblyDisassembler();
		break;
	default:
		LLVMInitializeAllTargetInfos();
		LLVMInitializeAllTargets();
		LLVMInitializeAllTargetMCs();
		LLVMInitializeAllAsmPrinters();
		LLVMInitializeAllAsmParsers();
		LLVMInitializeAllDisassemblers();
		break;
	}

	if (build_context.microarch == "native") {
		LLVMInitializeNativeTarget();
	}

	char const *target_triple = alloc_cstring(permanent_allocator(), build_context.metrics.target_triplet);
	for_array(i, gen->modules.entries) {
		LLVMSetTarget(gen->modules.entries[i].value->mod, target_triple);
	}

	LLVMTargetRef target = {};
	char *llvm_error = nullptr;
	LLVMGetTargetFromTriple(target_triple, &target, &llvm_error);
	GB_ASSERT(target != nullptr);

	TIME_SECTION("LLVM Create Target Machine");

	LLVMCodeModel code_mode = LLVMCodeModelDefault;
	if (is_arch_wasm()) {
		code_mode = LLVMCodeModelJITDefault;
	} else if (build_context.metrics.os == TargetOs_freestanding) {
		code_mode = LLVMCodeModelKernel;
	}

	char const *host_cpu_name = LLVMGetHostCPUName();
	char const *llvm_cpu = "generic";
	char const *llvm_features = "";
	if (build_context.microarch.len != 0) {
		if (build_context.microarch == "native") {
			llvm_cpu = host_cpu_name;
		} else {
			llvm_cpu = alloc_cstring(permanent_allocator(), build_context.microarch);
		}
		if (gb_strcmp(llvm_cpu, host_cpu_name) == 0) {
			llvm_features = LLVMGetHostCPUFeatures();
		}
	} else if (build_context.metrics.arch == TargetArch_amd64) {
		// NOTE(bill): x86-64-v2 is more than enough for everyone
		//
		// x86-64: CMOV, CMPXCHG8B, FPU, FXSR, MMX, FXSR, SCE, SSE, SSE2
		// x86-64-v2: (close to Nehalem) CMPXCHG16B, LAHF-SAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3
		// x86-64-v3: (close to Haswell) AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE
		// x86-64-v4: AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL
		if (ODIN_LLVM_MINIMUM_VERSION_12) {
			if (build_context.metrics.os == TargetOs_freestanding) {
				llvm_cpu = "x86-64";
			} else {
				llvm_cpu = "x86-64-v2";
			}
		}
	}

	if (build_context.target_features_set.entries.count != 0) {
		llvm_features = target_features_set_to_cstring(permanent_allocator(), false);
	}

	// GB_ASSERT_MSG(LLVMTargetHasAsmBackend(target));

	LLVMCodeGenOptLevel code_gen_level = LLVMCodeGenLevelNone;
	switch (build_context.optimization_level) {
	case 0: code_gen_level = LLVMCodeGenLevelNone;    break;
	case 1: code_gen_level = LLVMCodeGenLevelLess;    break;
	case 2: code_gen_level = LLVMCodeGenLevelDefault; break;
	case 3: code_gen_level = LLVMCodeGenLevelDefault; break; // NOTE(bill): force -opt:3 to be the same as -opt:2
	// case 3: code_gen_level = LLVMCodeGenLevelAggressive; break;
	}

	// NOTE(bill): Target Machine Creation
	// NOTE(bill, 2021-05-04): Target machines must be unique to each module because they are not thread safe
	auto target_machines = array_make<LLVMTargetMachineRef>(permanent_allocator(), gen->modules.entries.count);

	// NOTE(dweiler): Dynamic libraries require position-independent code.
	LLVMRelocMode reloc_mode = LLVMRelocDefault;
	if (build_context.build_mode == BuildMode_DynamicLibrary) {
		reloc_mode = LLVMRelocPIC;
	}

	switch (build_context.reloc_mode) {
	case RelocMode_Default:
		if (build_context.metrics.os == TargetOs_openbsd) {
			// Always use PIC for OpenBSD: it defaults to PIE
			reloc_mode = LLVMRelocPIC;
		}
		break;
	case RelocMode_Static:
		reloc_mode = LLVMRelocStatic;
		break;
	case RelocMode_PIC:
		reloc_mode = LLVMRelocPIC;
		break;
	case RelocMode_DynamicNoPIC:
		reloc_mode = LLVMRelocDynamicNoPic;
		break;
	}

	for_array(i, gen->modules.entries) {
		target_machines[i] = LLVMCreateTargetMachine(
			target, target_triple, llvm_cpu,
			llvm_features,
			code_gen_level,
			reloc_mode,
			code_mode);
		LLVMSetModuleDataLayout(gen->modules.entries[i].value->mod, LLVMCreateTargetDataLayout(target_machines[i]));
	}

	for_array(i, gen->modules.entries) {
		lbModule *m = gen->modules.entries[i].value;
		if (m->debug_builder) { // Debug Info
			for_array(i, info->files.entries) {
				AstFile *f = info->files.entries[i].value;
				String fullpath = f->fullpath;
				String filename = remove_directory_from_path(fullpath);
				String directory = directory_from_path(fullpath);
				LLVMMetadataRef res = LLVMDIBuilderCreateFile(m->debug_builder,
					cast(char const *)filename.text, filename.len,
					cast(char const *)directory.text, directory.len);
				lb_set_llvm_metadata(m, f, res);
			}

			gbString producer = gb_string_make(heap_allocator(), "odin");
			// producer = gb_string_append_fmt(producer, " version %.*s", LIT(ODIN_VERSION));
			// #ifdef NIGHTLY
			// producer = gb_string_appendc(producer, "-nightly");
			// #endif
			// #ifdef GIT_SHA
			// producer = gb_string_append_fmt(producer, "-%s", GIT_SHA);
			// #endif

			gbString split_name = gb_string_make(heap_allocator(), "");

			LLVMBool is_optimized = build_context.optimization_level > 0;
			AstFile *init_file = m->info->init_package->files[0];

			if (Entity *entry_point = m->info->entry_point) {
				if (Ast *ident = entry_point->identifier.load()) {
					if (ident->file_id) {
						init_file = ident->file();
					}
				}
			}

			LLVMBool split_debug_inlining = false;
			LLVMBool debug_info_for_profiling = false;

			m->debug_compile_unit = LLVMDIBuilderCreateCompileUnit(m->debug_builder, LLVMDWARFSourceLanguageC99,
				lb_get_llvm_metadata(m, init_file),
				producer, gb_string_length(producer),
				is_optimized, "", 0,
				1, split_name, gb_string_length(split_name),
				LLVMDWARFEmissionFull,
				0, split_debug_inlining,
				debug_info_for_profiling,
				"", 0, // sys_root
				"", 0  // SDK
			);
			GB_ASSERT(m->debug_compile_unit != nullptr);
		}
	}

	TIME_SECTION("LLVM Global Variables");

	if (!build_context.disallow_rtti) {
		lbModule *m = default_module;

		{ // Add type info data
			isize max_type_info_count = info->minimum_dependency_type_info_set.entries.count+1;
			// gb_printf_err("max_type_info_count: %td\n", max_type_info_count);
			Type *t = alloc_type_array(t_type_info, max_type_info_count);
			LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), LB_TYPE_INFO_DATA_NAME);
			LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
			if (!USE_SEPARATE_MODULES) {
				LLVMSetLinkage(g, LLVMInternalLinkage);
			}

			lbValue value = {};
			value.value = g;
			value.type = alloc_type_pointer(t);

			lb_global_type_info_data_entity = alloc_entity_variable(nullptr, make_token_ident(LB_TYPE_INFO_DATA_NAME), t, EntityState_Resolved);
			lb_add_entity(m, lb_global_type_info_data_entity, value);
		}
		{ // Type info member buffer
			// NOTE(bill): Removes need for heap allocation by making it global memory
			isize count = 0;

			for_array(entry_index, m->info->type_info_types) {
				Type *t = m->info->type_info_types[entry_index];

				isize index = lb_type_info_index(m->info, t, false);
				if (index < 0) {
					continue;
				}

				switch (t->kind) {
				case Type_Union:
					count += t->Union.variants.count;
					break;
				case Type_Struct:
					count += t->Struct.fields.count;
					break;
				case Type_Tuple:
					count += t->Tuple.variables.count;
					break;
				}
			}

			if (count > 0) {
				{
					char const *name = LB_TYPE_INFO_TYPES_NAME;
					Type *t = alloc_type_array(t_type_info_ptr, count);
					LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name);
					LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
					LLVMSetLinkage(g, LLVMInternalLinkage);
					lb_global_type_info_member_types = lb_addr({g, alloc_type_pointer(t)});

				}
				{
					char const *name = LB_TYPE_INFO_NAMES_NAME;
					Type *t = alloc_type_array(t_string, count);
					LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name);
					LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
					LLVMSetLinkage(g, LLVMInternalLinkage);
					lb_global_type_info_member_names = lb_addr({g, alloc_type_pointer(t)});
				}
				{
					char const *name = LB_TYPE_INFO_OFFSETS_NAME;
					Type *t = alloc_type_array(t_uintptr, count);
					LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name);
					LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
					LLVMSetLinkage(g, LLVMInternalLinkage);
					lb_global_type_info_member_offsets = lb_addr({g, alloc_type_pointer(t)});
				}

				{
					char const *name = LB_TYPE_INFO_USINGS_NAME;
					Type *t = alloc_type_array(t_bool, count);
					LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name);
					LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
					LLVMSetLinkage(g, LLVMInternalLinkage);
					lb_global_type_info_member_usings = lb_addr({g, alloc_type_pointer(t)});
				}

				{
					char const *name = LB_TYPE_INFO_TAGS_NAME;
					Type *t = alloc_type_array(t_string, count);
					LLVMValueRef g = LLVMAddGlobal(m->mod, lb_type(m, t), name);
					LLVMSetInitializer(g, LLVMConstNull(lb_type(m, t)));
					LLVMSetLinkage(g, LLVMInternalLinkage);
					lb_global_type_info_member_tags = lb_addr({g, alloc_type_pointer(t)});
				}
			}
		}
	}

	isize global_variable_max_count = 0;
	bool already_has_entry_point = false;

	for_array(i, info->entities) {
		Entity *e = info->entities[i];
		String name = e->token.string;

		if (e->kind == Entity_Variable) {
			global_variable_max_count++;
		} else if (e->kind == Entity_Procedure) {
			if ((e->scope->flags&ScopeFlag_Init) && name == "main") {
				GB_ASSERT(e == info->entry_point);
			}
			if (build_context.command_kind == Command_test &&
			    (e->Procedure.is_export || e->Procedure.link_name.len > 0)) {
				String link_name = e->Procedure.link_name;
				if (e->pkg->kind == Package_Runtime) {
					if (link_name == "main"           ||
					    link_name == "DllMain"        ||
					    link_name == "WinMain"        ||
					    link_name == "wWinMain"       ||
					    link_name == "mainCRTStartup" ||
					    link_name == "_start") {
						already_has_entry_point = true;
					}
				}
			}
		}
	}

	auto global_variables = array_make<lbGlobalVariable>(permanent_allocator(), 0, global_variable_max_count);

	for_array(i, info->variable_init_order) {
		DeclInfo *d = info->variable_init_order[i];

		Entity *e = d->entity;

		if ((e->scope->flags & ScopeFlag_File) == 0) {
			continue;
		}

		if (!ptr_set_exists(min_dep_set, e)) {
			continue;
		}
		DeclInfo *decl = decl_info_of_entity(e);
		if (decl == nullptr) {
			continue;
		}
		GB_ASSERT(e->kind == Entity_Variable);

		bool is_foreign = e->Variable.is_foreign;
		bool is_export  = e->Variable.is_export;

		lbModule *m = &gen->default_module;
		String name = lb_get_entity_name(m, e);

		lbValue g = {};
		g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name));
		g.type = alloc_type_pointer(e->type);
		if (e->Variable.thread_local_model != "") {
			LLVMSetThreadLocal(g.value, true);

			String m = e->Variable.thread_local_model;
			LLVMThreadLocalMode mode = LLVMGeneralDynamicTLSModel;
			if (m == "default") {
				mode = LLVMGeneralDynamicTLSModel;
			} else if (m == "localdynamic") {
				mode = LLVMLocalDynamicTLSModel;
			} else if (m == "initialexec") {
				mode = LLVMInitialExecTLSModel;
			} else if (m == "localexec") {
				mode = LLVMLocalExecTLSModel;
			} else {
				GB_PANIC("Unhandled thread local mode %.*s", LIT(m));
			}
			LLVMSetThreadLocalMode(g.value, mode);
		}
		if (is_foreign) {
			LLVMSetLinkage(g.value, LLVMExternalLinkage);
			LLVMSetDLLStorageClass(g.value, LLVMDLLImportStorageClass);
			LLVMSetExternallyInitialized(g.value, true);
			lb_add_foreign_library_path(m, e->Variable.foreign_library);

			lb_set_wasm_import_attributes(g.value, e, name);
		} else {
			LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, e->type)));
		}
		if (is_export) {
			LLVMSetLinkage(g.value, LLVMDLLExportLinkage);
			LLVMSetDLLStorageClass(g.value, LLVMDLLExportStorageClass);
		} else if (!is_foreign) {
			if (USE_SEPARATE_MODULES) {
				LLVMSetLinkage(g.value, LLVMExternalLinkage);
			} else {
				LLVMSetLinkage(g.value, LLVMInternalLinkage);
			}
		}
		lb_set_linkage_from_entity_flags(m, g.value, e->flags);

		if (e->Variable.link_section.len > 0) {
			LLVMSetSection(g.value, alloc_cstring(permanent_allocator(), e->Variable.link_section));
		}

		lbGlobalVariable var = {};
		var.var = g;
		var.decl = decl;

		if (decl->init_expr != nullptr) {
			TypeAndValue tav = type_and_value_of_expr(decl->init_expr);
			if (!is_type_any(e->type) && !is_type_union(e->type)) {
				if (tav.mode != Addressing_Invalid) {
					if (tav.value.kind != ExactValue_Invalid) {
						ExactValue v = tav.value;
						lbValue init = lb_const_value(m, tav.type, v);
						LLVMSetInitializer(g.value, init.value);
						var.is_initialized = true;
					}
				}
			}
			if (!var.is_initialized &&
			    (is_type_untyped_nil(tav.type) || is_type_untyped_undef(tav.type))) {
				var.is_initialized = true;
			}
		}

		array_add(&global_variables, var);

		lb_add_entity(m, e, g);
		lb_add_member(m, name, g);

		if (m->debug_builder) {
			String global_name = e->token.string;
			if (global_name.len != 0 && global_name != "_") {
				LLVMMetadataRef llvm_file = lb_get_llvm_metadata(m, e->file);
				LLVMMetadataRef llvm_scope = llvm_file;

				LLVMBool local_to_unit = LLVMGetLinkage(g.value) == LLVMInternalLinkage;

				LLVMMetadataRef llvm_expr = LLVMDIBuilderCreateExpression(m->debug_builder, nullptr, 0);
				LLVMMetadataRef llvm_decl = nullptr;

				u32 align_in_bits = cast(u32)(8*type_align_of(e->type));

				LLVMMetadataRef global_variable_metadata = LLVMDIBuilderCreateGlobalVariableExpression(
					m->debug_builder, llvm_scope,
					cast(char const *)global_name.text, global_name.len,
					"", 0, // linkage
					llvm_file, e->token.pos.line,
					lb_debug_type(m, e->type),
					local_to_unit,
					llvm_expr,
					llvm_decl,
					align_in_bits
				);
				lb_set_llvm_metadata(m, g.value, global_variable_metadata);
				LLVMGlobalSetMetadata(g.value, 0, global_variable_metadata);
			}
		}
	}

	TIME_SECTION("LLVM Runtime Type Information Creation");
	lbProcedure *startup_type_info = lb_create_startup_type_info(default_module);

	lbProcedure *objc_names = lb_create_objc_names(default_module);

	TIME_SECTION("LLVM Runtime Startup Creation (Global Variables)");
	lbProcedure *startup_runtime = lb_create_startup_runtime(default_module, startup_type_info, objc_names, global_variables);
	gb_unused(startup_runtime);

	TIME_SECTION("LLVM Global Procedures and Types");
	for_array(i, info->entities) {
		Entity *e = info->entities[i];
		String  name  = e->token.string;
		Scope * scope = e->scope;

		if ((scope->flags & ScopeFlag_File) == 0) {
			continue;
		}

		Scope *package_scope = scope->parent;
		GB_ASSERT(package_scope->flags & ScopeFlag_Pkg);

		switch (e->kind) {
		case Entity_Variable:
			// NOTE(bill): Handled above as it requires a specific load order
			continue;
		case Entity_ProcGroup:
			continue;

		case Entity_TypeName:
		case Entity_Procedure:
			break;
		}

		bool polymorphic_struct = false;
		if (e->type != nullptr && e->kind == Entity_TypeName) {
			Type *bt = base_type(e->type);
			if (bt->kind == Type_Struct) {
				polymorphic_struct = is_type_polymorphic(bt);
			}
		}

		if (!polymorphic_struct && !ptr_set_exists(min_dep_set, e)) {
			// NOTE(bill): Nothing depends upon it so doesn't need to be built
			continue;
		}

		lbModule *m = &gen->default_module;
		if (USE_SEPARATE_MODULES) {
			m = lb_pkg_module(gen, e->pkg);
		}

		String mangled_name = lb_get_entity_name(m, e);

		switch (e->kind) {
		case Entity_TypeName:
			lb_type(m, e->type);
			break;
		case Entity_Procedure:
			{
				lbProcedure *p = lb_create_procedure(m, e);
				array_add(&m->procedures_to_generate, p);
			}
			break;
		}
	}

	TIME_SECTION("LLVM Procedure Generation");
	for_array(j, gen->modules.entries) {
		lbModule *m = gen->modules.entries[j].value;
		for_array(i, m->procedures_to_generate) {
			lbProcedure *p = m->procedures_to_generate[i];
			lb_generate_procedure(m, p);
		}
	}

	if (build_context.command_kind == Command_test && !already_has_entry_point) {
		TIME_SECTION("LLVM main");
		lb_create_main_procedure(default_module, startup_runtime);
	}

	for_array(j, gen->modules.entries) {
		lbModule *m = gen->modules.entries[j].value;
		for_array(i, m->missing_procedures_to_check) {
			lbProcedure *p = m->missing_procedures_to_check[i];
			debugf("Generate missing procedure: %.*s\n", LIT(p->name));
			lb_generate_procedure(m, p);
		}
	}

	lb_finalize_objc_names(objc_names);

	if (build_context.ODIN_DEBUG) {
		TIME_SECTION("LLVM Debug Info Complete Types and Finalize");
		for_array(j, gen->modules.entries) {
			lbModule *m = gen->modules.entries[j].value;
			if (m->debug_builder != nullptr) {
				lb_debug_complete_types(m);
				LLVMDIBuilderFinalize(m->debug_builder);
			}
		}
	}

	TIME_SECTION("LLVM Function Pass");
	for_array(i, gen->modules.entries) {
		lbModule *m = gen->modules.entries[i].value;

		lb_llvm_function_pass_worker_proc(m);
	}

	TIME_SECTION("LLVM Module Pass");

	for_array(i, gen->modules.entries) {
		lbModule *m = gen->modules.entries[i].value;

		lb_run_remove_unused_function_pass(m);
		lb_run_remove_unused_globals_pass(m);

		auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData);
		wd->m = m;
		wd->target_machine = target_machines[i];

		lb_llvm_module_pass_worker_proc(wd);
	}

	llvm_error = nullptr;
	defer (LLVMDisposeMessage(llvm_error));

	LLVMCodeGenFileType code_gen_file_type = LLVMObjectFile;
	if (build_context.build_mode == BuildMode_Assembly) {
		code_gen_file_type = LLVMAssemblyFile;
	}

	for_array(j, gen->modules.entries) {
		lbModule *m = gen->modules.entries[j].value;
		if (LLVMVerifyModule(m->mod, LLVMReturnStatusAction, &llvm_error)) {
			gb_printf_err("LLVM Error:\n%s\n", llvm_error);
			if (build_context.keep_temp_files) {
				TIME_SECTION("LLVM Print Module to File");
				String filepath_ll = lb_filepath_ll_for_module(m);
				if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
					gb_printf_err("LLVM Error: %s\n", llvm_error);
					gb_exit(1);
					return;
				}
			}
			gb_exit(1);
			return;
		}
	}
	llvm_error = nullptr;
	if (build_context.keep_temp_files ||
	    build_context.build_mode == BuildMode_LLVM_IR) {
		TIME_SECTION("LLVM Print Module to File");

		for_array(j, gen->modules.entries) {
			lbModule *m = gen->modules.entries[j].value;

			if (lb_is_module_empty(m)) {
				continue;
			}

			String filepath_ll = lb_filepath_ll_for_module(m);
			if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
				gb_printf_err("LLVM Error: %s\n", llvm_error);
				gb_exit(1);
				return;
			}
			array_add(&gen->output_temp_paths, filepath_ll);

		}
		if (build_context.build_mode == BuildMode_LLVM_IR) {
			gb_exit(0);
			return;
		}
	}

	TIME_SECTION("LLVM Add Foreign Library Paths");

	for_array(j, gen->modules.entries) {
		lbModule *m = gen->modules.entries[j].value;
		for_array(i, m->info->required_foreign_imports_through_force) {
			Entity *e = m->info->required_foreign_imports_through_force[i];
			lb_add_foreign_library_path(m, e);
		}

		if (lb_is_module_empty(m)) {
			continue;
		}
	}

	TIME_SECTION("LLVM Object Generation");

	isize non_empty_module_count = 0;
	for_array(j, gen->modules.entries) {
		lbModule *m = gen->modules.entries[j].value;
		if (!lb_is_module_empty(m)) {
			non_empty_module_count += 1;
		}
	}

	if (do_threading && non_empty_module_count > 1) {
		for_array(j, gen->modules.entries) {
			lbModule *m = gen->modules.entries[j].value;
			if (lb_is_module_empty(m)) {
				continue;
			}

			String filepath_ll = lb_filepath_ll_for_module(m);
			String filepath_obj = lb_filepath_obj_for_module(m);
			array_add(&gen->output_object_paths, filepath_obj);
			array_add(&gen->output_temp_paths, filepath_ll);

			auto *wd = gb_alloc_item(permanent_allocator(), lbLLVMEmitWorker);
			wd->target_machine = target_machines[j];
			wd->code_gen_file_type = code_gen_file_type;
			wd->filepath_obj = filepath_obj;
			wd->m = m;
			global_thread_pool_add_task(lb_llvm_emit_worker_proc, wd);
		}

		thread_pool_wait(&global_thread_pool);
	} else {
		for_array(j, gen->modules.entries) {
			lbModule *m = gen->modules.entries[j].value;
			if (lb_is_module_empty(m)) {
				continue;
			}

			String filepath_obj = lb_filepath_obj_for_module(m);
			array_add(&gen->output_object_paths, filepath_obj);

			String short_name = remove_directory_from_path(filepath_obj);
			gbString section_name = gb_string_make(heap_allocator(), "LLVM Generate Object: ");
			section_name = gb_string_append_length(section_name, short_name.text, short_name.len);

			TIME_SECTION_WITH_LEN(section_name, gb_string_length(section_name));

			if (LLVMTargetMachineEmitToFile(target_machines[j], m->mod, cast(char *)filepath_obj.text, code_gen_file_type, &llvm_error)) {
				gb_printf_err("LLVM Error: %s\n", llvm_error);
				gb_exit(1);
				return;
			}
		}
	}

	gb_sort_array(gen->foreign_libraries.data, gen->foreign_libraries.count, foreign_library_cmp);
}


text:
var ITERATOR_COMPLETION = true;
var ITERATOR_HAD_ERROR_KEY = false;
var ITERATOR_ERROR_KEY = undefined;
try {
  for (var ITERATOR_KEY = OBJECT[Symbol.iterator](), STEP_KEY; !(ITERATOR_COMPLETION = (STEP_KEY = ITERATOR_KEY.next()).done); ITERATOR_COMPLETION = true) {

  }
} catch (err) {
  ITERATOR_HAD_ERROR_KEY = true;
  ITERATOR_ERROR_KEY = err;
} finally {
  try {
    if (!ITERATOR_COMPLETION && ITERATOR_KEY.return) {
      ITERATOR_KEY.return();
    }
  } finally {
    if (ITERATOR_HAD_ERROR_KEY) {
      throw ITERATOR_ERROR_KEY;
    }
  }
}

redpajama_set_name: RedPajamaGithub


text:
package me.planetguy.advancedvm;

public interface Limited {

	public void onRunExtraComputation(int extra);

	public void doAllAllowedSteps();

	public void allowSteps(int steps);

}


text:
from django.conf import settings

ERLYVIDEO_PUBLISH_AUTH_FUNC = getattr(settings, 'ERLYVIDEO_PUBLISH_AUTH_FUNC', 'erlyvideo.views.public_auth_sample')

ERLYVIDEO_PLAY_AUTH_FUNC = getattr(settings, 'ERLYVIDEO_PLAY_AUTH_FUNC', 'erlyvideo.views.play_auth_sample')

ERLYVIDEO_SECRET_KEY = getattr(settings, 'ERLYVIDEO_SECRET_KEY', settings.SECRET_KEY)

ERLYVIDEO_AUTO_SAVE_SESSIONS = getattr(settings, 'ERLYVIDEO_AUTO_SAVE_SESSIONS', False)

# none, random, max_clients
#ERLYVIDEO_LOAD_BALANCING_MODE = getattr(settings, 'ERLYVIDEO_LOAD_BALANCING_MODE', 'none')

#ERLYVIDEO_FILTER_SERVER_BY_GROUP = getattr(settings, 'ERLYVIDEO_FILTER_SERVER_BY_GROUP', False)


text:
namespace Payment.Repository.Schema
{
   public static class PaymentHistorySchema
    {
        internal const string ID = "id";

        internal const string USER_ID = "userid";

        internal const string ACCOUNT_ID = "accountid";

        internal const string DATE = "date";

        internal const string AMOUNT = "amount";

        internal const string CURRENCY = "currency";

        internal const string PAYMENT_TYPE = "paymenttype";

        internal const string PAYMENT_METHOD = "paymentmethod";

        internal const string TRANSACTION_TYPE = "transactiontype";

        internal const string TRANSACTION_STATUS = "transactionstatus";

        internal const string ReceivedEmail = "resivedemail";
    }
}


text:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <groupId>org.traktion0.safenet.client</groupId>
    <artifactId>SafeNetClient</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <!-- if your container implements Servlet API older than 3.0, use "jersey-container-servlet-core"  -->
            <artifactId>jersey-container-servlet</artifactId>
            <version>2.23.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet-core</artifactId>
            <version>2.23.1</version>
        </dependency>
        <!-- Required only when you are using JAX-RS Client -->
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-client</artifactId>
            <version>2.23.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-common</artifactId>
            <version>2.23.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-server</artifactId>
            <version>2.23.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-moxy</artifactId>
            <version>2.23.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-jaxb</artifactId>
            <version>2.23.1</version>
        </dependency>
        <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-core</artifactId>
            <version>1.5.4</version>
        </dependency>
        <dependency>
            <groupId>com.netflix.archaius</groupId>
            <artifactId>archaius-core</artifactId>
            <version>0.4.1</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.ws.rs</groupId>
            <artifactId>javax.ws.rs-api</artifactId>
            <version>2.0.1</version>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.1.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.bundles.repackaged</groupId>
            <artifactId>jersey-guava</artifactId>
            <version>2.23.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.hk2</groupId>
            <artifactId>osgi-resource-locator</artifactId>
            <version>1.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.hk2</groupId>
            <artifactId>hk2-api</artifactId>
            <version>2.4.0-b34</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.hk2</groupId>
            <artifactId>hk2-utils</artifactId>
            <version>2.4.0-b34</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.hk2.external</groupId>
            <artifactId>aopalliance-repackaged</artifactId>
            <version>2.4.0-b34</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.hk2.external</groupId>
            <artifactId>javax.inject</artifactId>
            <version>2.4.0-b34</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.hk2</groupId>
            <artifactId>hk2-locator</artifactId>
            <version>2.4.0-b34</version>
        </dependency>
        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.18.1-GA</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.ext</groupId>
            <artifactId>jersey-entity-filtering</artifactId>
            <version>2.23.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>javax.json</artifactId>
            <version>1.0.4</version>
        </dependency>
        <dependency>
            <groupId>commons-configuration</groupId>
            <artifactId>commons-configuration</artifactId>
            <version>1.8</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>io.reactivex</groupId>
            <artifactId>rxjava</artifactId>
            <version>1.1.8</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.0</version>
        </dependency>
    </dependencies>

</project>


text:
package io.getquill.context.zio

import com.github.jasync.sql.db.{ ConcreteConnection, QueryResult }
import com.github.jasync.sql.db.pool.{ ConnectionPool => KConnectionPool }
import zio.{ RIO, Scope, Tag, Task, ZIO, ZLayer }

import scala.jdk.CollectionConverters._

trait ZioJAsyncConnection {
  protected def takeConnection: ZIO[Scope, Throwable, ConcreteConnection]

  private[zio] final def transaction[A](action: RIO[ZioJAsyncConnection, A]): ZIO[ZioJAsyncConnection, Throwable, A] = {
    //Taken from ConcreteConnectionBase.kt to avoid usage of pool.inTransaction
    ZIO.scoped {
      takeConnection.flatMap(conn =>
        (ZioJAsyncConnection.sendQuery(conn, "BEGIN") *>
          action.updateService[ZioJAsyncConnection](_ => ZioJAsyncConnection.make(conn))).tapBoth(
            _ => ZioJAsyncConnection.sendQuery(conn, "ROLLBACK"),
            _ => ZioJAsyncConnection.sendQuery(conn, "COMMIT")
          ))
    }

  }

  private[zio] final def sendQuery(query: String): Task[QueryResult] =
    ZIO.scoped {
      takeConnection.flatMap(conn => ZIO.fromCompletableFuture(conn.sendQuery(query)))
    }

  private[zio] final def sendPreparedStatement(sql: String, params: Seq[Any]): Task[QueryResult] =
    ZIO.scoped {
      takeConnection.flatMap(conn => ZIO.fromCompletableFuture(
        conn.sendPreparedStatement(sql, params.asJava)
      ))
    }

}

object ZioJAsyncConnection {

  def sendQuery(query: String): ZIO[ZioJAsyncConnection, Throwable, QueryResult] =
    ZIO.environmentWithZIO[ZioJAsyncConnection](_.get.sendQuery(query))

  def sendPreparedStatement(sql: String, params: Seq[Any]): ZIO[ZioJAsyncConnection, Throwable, QueryResult] =
    ZIO.environmentWithZIO[ZioJAsyncConnection](_.get.sendPreparedStatement(sql, params))

  private def sendQuery[C <: ConcreteConnection](connection: C, query: String): Task[QueryResult] =
    ZIO.fromCompletableFuture(connection.sendQuery(query))

  def make[C <: ConcreteConnection](pool: KConnectionPool[C]): ZioJAsyncConnection = new ZioJAsyncConnection {

    override protected def takeConnection: ZIO[Scope, Throwable, ConcreteConnection] =
      ZIO.acquireRelease(ZIO.fromCompletableFuture(pool.take()))(conn => ZIO.fromCompletableFuture(pool.giveBack(conn)).orDie.unit)

  }

  def make[C <: ConcreteConnection](connection: C): ZioJAsyncConnection = new ZioJAsyncConnection {
    override protected def takeConnection: ZIO[Scope, Throwable, ConcreteConnection] = {
      for {
        _ <- ZIO.scope
        conn <- ZIO.attempt(connection)
      } yield conn
    }
  }

  def live[C <: ConcreteConnection: Tag]: ZLayer[JAsyncContextConfig[C], Throwable, ZioJAsyncConnection] =
    ZLayer.scoped {
      for {
        env <- ZIO.environment[JAsyncContextConfig[C]]
        pool <- ZIO.acquireRelease(
          ZIO.attempt(
            new KConnectionPool[C](
              env.get.connectionFactory(env.get.connectionPoolConfiguration.getConnectionConfiguration),
              env.get.connectionPoolConfiguration
            )
          )
        )(pool => ZIO.fromCompletableFuture(pool.disconnect()).orDie)
      } yield (ZioJAsyncConnection.make[C](pool))
    }

}


text:
package envdb

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"strconv"
	"text/template"
)

//go:generate go-bindata-assetfs -prefix "web/" -ignore "\\.go" -pkg envdb -o bindata.go web/...

var (
	funcs = template.FuncMap{}
)

func newTemplate(filename string) *template.Template {
	var file []byte
	var err error

	var layout []byte

	if DevMode {
		file, err = ioutil.ReadFile(BasePrefix + filename)
		layout, err = ioutil.ReadFile(BasePrefix + "layout.html")
	} else {
		file, err = Asset(filename)
		layout, err = Asset("layout.html")
	}

	if err != nil {
		Log.Error(err)
	}

	html := string(layout) + string(file)
	return template.Must(template.New("*").Delims("<%", "%>").Funcs(funcs).Parse(html))
}

func executeTemplate(w http.ResponseWriter, name string, status int, data interface{}) error {
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	w.WriteHeader(status)

	return newTemplate(name).Execute(w, data)
}

func RouteIndex(w http.ResponseWriter, r *http.Request) error {

	session, err := store.Get(r, "envdb")

	if err != nil {
		Log.Debug(err)
	}

	nodes, _ := AllNodes()

	user, err := FindUserByEmail(session.Values["current_user"].(string))

	if err != nil {
		session.Values["current_user"] = nil
		http.Redirect(w, r, "/login", 301)
		return nil
	}

	return executeTemplate(w, "index.html", 200, map[string]interface{}{
		"Section": "home",
		"Name":    Name,
		"Version": Version,
		"Nodes":   nodes,
		"User":    user,
		"Prefix":  WebPrefix,
	})

}

func RouteDeleteQuery(w http.ResponseWriter, r *http.Request) error {
	var errorMsg string = ""

	r.ParseForm()

	if r.Method == "POST" {
		id, err := strconv.ParseInt(r.PostFormValue("id"), 10, 64)

		Log.Debug("got id: ", id)

		if err != nil {
			return err
		}

		query, err := FindSavedQueryById(id)

		if err != nil {
			return err
		}

		if err := query.Delete(); err != nil {
			return err
		}

		data := map[string]interface{}{
			"error": errorMsg,
			"query": query,
		}

		js, err := json.Marshal(data)

		if err != nil {
			return err
		}

		w.Header().Set("Content-Type", "application/json")
		w.Write(js)
	}

	return nil
}

func RouteSavedQueries(w http.ResponseWriter, r *http.Request) error {
	data, _ := AllSavedQueries()

	js, err := json.Marshal(data)

	if err != nil {
		return err
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(js)
	return nil
}

func RouteSaveQuery(w http.ResponseWriter, r *http.Request) error {
	r.ParseForm()

	if r.Method == "POST" {
		query := QueryDb{
			Name:  r.PostFormValue("name"),
			Query: r.PostFormValue("query"),
			Type:  r.PostFormValue("type"),
		}

		err := NewSavedQuery(query)
		var errorMsg string = ""

		if err != nil {
			return err
		}

		data := map[string]interface{}{
			"error": errorMsg,
			"query": query,
		}

		js, err := json.Marshal(data)

		if err != nil {
			return err
		}

		w.Header().Set("Content-Type", "application/json")
		w.Write(js)
	}

	return nil
}

func RouteNodes(w http.ResponseWriter, r *http.Request) error {

	nodes, _ := AllNodes()

	js, err := json.Marshal(nodes)

	if err != nil {
		return err
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(js)
	return nil
}

func RouteLogin(w http.ResponseWriter, r *http.Request) error {
	if r.Method == "GET" {
		return executeTemplate(w, "login.html", 200, map[string]interface{}{
			"Section": "login",
			"Name":    Name,
			"Version": Version,
			"Prefix":  WebPrefix,
		})
	} else if r.Method == "POST" {
		r.ParseForm()

		session, err := store.Get(r, "envdb")

		if err != nil {
			Log.Debug(err)
		}

		email := r.PostFormValue("email")
		password := r.PostFormValue("password")

		user, err := FindUserByEmail(email)

		if err != nil {
			Log.Warn(err)
			http.Redirect(w, r, "/", 302)
			return nil
		}

		if !user.ValidatePassword(password) {
			Log.Warnf("Authentication Failed for user: %s", email)
			http.Redirect(w, r, "/", 302)
			return nil
		}

		Log.Debug("Setting current user.")
		session.Values["current_user"] = email

		if err := session.Save(r, w); err != nil {
			Log.Fatal(err)
		}

		http.Redirect(w, r, "/", 302)
		return nil
	} else if r.Method == "DELETE" {
		session, err := store.Get(r, "envdb")

		if err != nil {
			Log.Debug(err)
		}

		session.Values["current_user"] = nil
		session.Options.MaxAge = -1

		if err := session.Save(r, w); err != nil {
			Log.Fatal(err)
		}

		return nil
	}

	http.Redirect(w, r, "/", 302)
	return nil
}


text:
<?php

namespace spec\Sylius\Component\Resource\Factory;

use PhpSpec\ObjectBehavior;
use Sylius\Component\Locale\Provider\LocaleProviderInterface;
use Sylius\Component\Resource\Exception\UnexpectedTypeException;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\Component\Resource\Factory\TranslatableFactory;
use Sylius\Component\Resource\Factory\TranslatableFactoryInterface;
use Sylius\Component\Resource\Model\TranslatableInterface;

/**
 * @author Paweł Jędrzejewski <pawel@sylius.org>
 */
final class TranslatableFactorySpec extends ObjectBehavior
{
    function let(FactoryInterface $factory, LocaleProviderInterface $localeProvider)
    {
        $this->beConstructedWith($factory, $localeProvider);
    }

    function it_is_initializable()
    {
        $this->shouldHaveType(TranslatableFactory::class);
    }

    function it_implements_translatable_factory_interface()
    {
        $this->shouldImplement(TranslatableFactoryInterface::class);
    }

    function it_throws_an_exception_if_resource_is_not_translatable(FactoryInterface $factory, \stdClass $resource)
    {
        $factory->createNew()->willReturn($resource);

        $this
            ->shouldThrow(UnexpectedTypeException::class)
            ->during('createNew')
        ;
    }

    function it_creates_translatable_and_sets_locales(FactoryInterface $factory, LocaleProviderInterface $localeProvider, TranslatableInterface $resource)
    {
        $localeProvider->getDefaultLocaleCode()->willReturn('pl_PL');

        $factory->createNew()->willReturn($resource);

        $resource->setCurrentLocale('pl_PL')->shouldBeCalled();
        $resource->setFallbackLocale('pl_PL')->shouldBeCalled();

        $this->createNew()->shouldReturn($resource);
    }
}


text:
#import "MPHRouteTableViewController.h"

#import "MPHRouteController.h"
#import "MPHLocationCenter.h"

#import "MPHTableViewCell.h"

#import "MPHStop.h"
#import "MPHPrediction.h"

@implementation MPHRouteTableViewController {
	BOOL _usesMetric;
	NSString *_groupingSeparator;
	NSNumberFormatter *_numberFormatter;
	NSMutableDictionary *_cachedDistances;

	__weak id <MPHRouteController> _routeController;
	MPHDirection _selectedDirection;

	CGFloat _previousNearestDistance;
	id <MPHStop> _nearestStop;

    NSIndexPath *_selectedIndexPath;
    NSIndexPath *_selectingIndexPath;
    NSAttributedString *_cachedPredictionString;
}

- (id) initWithRouteController:(id <MPHRouteController>) routeController {
	if (!(self = [super initWithStyle:UITableViewStyleGrouped]))
		return nil;

	_groupingSeparator = [[[NSLocale currentLocale] objectForKey:NSLocaleGroupingSeparator] copy];
	_numberFormatter = [[NSNumberFormatter alloc] init];
	_numberFormatter.numberStyle = NSNumberFormatterDecimalStyle;
	_numberFormatter.maximumFractionDigits = 1;
	_numberFormatter.minimumFractionDigits = 1;
	_numberFormatter.roundingMode = NSNumberFormatterRoundHalfEven;
	_cachedDistances = [[NSMutableDictionary alloc] init];

	_usesMetric = [[[NSLocale currentLocale] objectForKey:NSLocaleUsesMetricSystem] boolValue];
	_routeController = routeController;

	return self;
}

- (void) dealloc {
	[[NSNotificationCenter defaultCenter] removeObserver:self name:MPHLocationDidUpdateNotification object:nil];
	[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_hideToolbar) object:nil];
}

#pragma mark -

- (void) viewDidLoad {
	[super viewDidLoad];

	[self selectNearestStopAnimated:NO];

	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(locationDidUpdate:) name:MPHLocationDidUpdateNotification object:nil];
}

- (void) viewWillAppear:(BOOL) animated {
	[super viewWillAppear:animated];

	[self performSelector:@selector(reloadData) withObject:nil afterDelay:30.];
}

- (void) viewDidDisappear:(BOOL) animated {
	[super viewDidDisappear:animated];

	[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(reloadData) object:nil];
}

#pragma mark -

- (void) locationDidUpdate:(NSNotification *) notification {
	[_cachedDistances removeAllObjects];

	[self.tableView beginUpdates];
	[self.tableView reloadRowsAtIndexPaths:self.tableView.indexPathsForVisibleRows withRowAnimation:UITableViewRowAnimationFade];
	[self.tableView endUpdates];
}

#pragma mark -

- (void) _hideToolbar {
	[self.navigationController setToolbarHidden:YES animated:YES];
}

- (void) scrollViewWillBeginDragging:(UIScrollView *) scrollView {
	[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_hideToolbar) object:nil];
	[self performSelector:@selector(_hideToolbar) withObject:nil afterDelay:.2 inModes:@[ NSRunLoopCommonModes ]];
}

- (void) scrollViewWillEndDragging:(UIScrollView *) scrollView withVelocity:(CGPoint) velocity targetContentOffset:(inout CGPoint *) targetContentOffset {
	[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_hideToolbar) object:nil];

	if (fabs((*targetContentOffset).y - scrollView.contentOffset.y) < 2.)
		return;

	if (velocity.y < 0 || (*targetContentOffset).y > scrollView.contentSize.height)
		[self.navigationController setToolbarHidden:NO animated:YES];
	else if (fabs(velocity.y) > 0.0) /* -0 is a thing */
		[self.navigationController setToolbarHidden:YES animated:YES];
}

#pragma mark -

- (NSInteger) tableView:(UITableView *) tableView numberOfRowsInSection:(NSInteger) section {
	__strong id <MPHRouteController> strongRouteController = _routeController;
	return [strongRouteController stopsForDirection:_selectedDirection].signedCount;
}

- (BOOL) tableView:(UITableView *) tableView shouldHighlightRowAtIndexPath:(NSIndexPath *) indexPath {
    __strong id <MPHRouteController> strongRouteController = _routeController;
    id <MPHStop> stop = [[strongRouteController stopsForDirection:_selectedDirection] objectAtSignedIndex:indexPath.row];
    return [strongRouteController routesForStop:stop].count > 1;
}

- (UITableViewCell *) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath {
	MPHTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
	if (!cell) {
		cell = [[MPHTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"];
		cell.selectionStyle = UITableViewCellSelectionStyleNone;
	}

	__strong id <MPHRouteController> strongRouteController = _routeController;
	id <MPHStop> stop = [[strongRouteController stopsForDirection:_selectedDirection] objectAtSignedIndex:indexPath.row];
	cell.textLabel.text = stop.name;

	if ([MPHLocationCenter locationCenter].currentLocation) {
		CGFloat distance = distanceBetweenCoordinates(stop.coordinate, [MPHLocationCenter locationCenter].currentLocation.coordinate);

		NSString *subText = _cachedDistances[stop.name];
		if (!subText.length) {
			if (_usesMetric)
				subText = [NSString stringWithFormat:@"%@ km", [_numberFormatter stringFromNumber:@(distance * MPHDistanceKilometersPerFoot)]];
			else subText = [NSString stringWithFormat:@"%@ mi", [_numberFormatter stringFromNumber:@(distance / MPHDistanceMilesPerFoot)]];

			_cachedDistances[stop.name] = subText;
		}
		cell.subTextLabel.text = subText;
	}

	NSMutableAttributedString *minutes = [[NSMutableAttributedString alloc] init];
	NSArray *predictions = [strongRouteController predictionsForStop:stop];
	predictions = [predictions sortedArrayUsingComparator:^(id one, id two) {
		id <MPHPrediction> predictionOne = one;
		id <MPHPrediction> predictionTwo = two;

		if (predictionOne.minutesETA > predictionTwo.minutesETA)
			return NSOrderedDescending;
		if (predictionTwo.minutesETA > predictionOne.minutesETA)
			return NSOrderedAscending;
		return NSOrderedSame;
	}];

	for (id <MPHPrediction> prediction in predictions) {
		if (prediction.minutesETA < 0.)
			continue;

		NSDictionary *attributes = nil;
		if (prediction.minutesETA < 5) {
			attributes = @{
				NSForegroundColorAttributeName: [UIColor darkTextColor],
				NSBackgroundColorAttributeName: [UIColor clearColor],
				NSFontAttributeName: [UIFont systemFontOfSize:13.]
			};
		} else if (prediction.minutesETA > 45) {
			attributes = @{
				NSForegroundColorAttributeName: [UIColor darkTextColor],
				NSBackgroundColorAttributeName: [UIColor clearColor],
				NSFontAttributeName: [UIFont systemFontOfSize:13.]
			};
		} else {
			attributes = @{
				NSForegroundColorAttributeName: [UIColor darkTextColor],
				NSBackgroundColorAttributeName: [UIColor clearColor],
				NSFontAttributeName: [UIFont systemFontOfSize:13.]
			};
		}
		if (prediction.minutesETA) {
			NSString *string = [NSString stringWithFormat:@"%zdm%@ ", prediction.minutesETA, _groupingSeparator];
			NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:string attributes:attributes];
			[minutes appendAttributedString:attributedString];
		} else {
			NSString *string = [NSString stringWithFormat:@"now%@ ", _groupingSeparator];
			NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:string attributes:attributes];
			[minutes appendAttributedString:attributedString];
		}
	}

	if (minutes.length)
		[minutes deleteCharactersInRange:NSMakeRange(minutes.length - (_groupingSeparator.length + 1), (_groupingSeparator.length + 1))];

	cell.detailTextLabel.attributedText = minutes;

	return cell;
}

- (void) tableView:(UITableView *) tableView didSelectRowAtIndexPath:(NSIndexPath *) indexPath {
    if (_selectedIndexPath && [_selectedIndexPath isEqual:indexPath]) {
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
        return;
    }

    if (![self tableView:tableView shouldHighlightRowAtIndexPath:indexPath])
        return;

    NSIndexPath *previouslySelectedIndexPath = _selectedIndexPath;
    _selectedIndexPath = indexPath;
    _cachedPredictionString = nil;

    if (![self.tableView.indexPathForSelectedRow isEqual:indexPath])
        return;

    if (!previouslySelectedIndexPath)
        return;

    [tableView beginUpdates];
    [tableView reloadRowsAtIndexPaths:@[previouslySelectedIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    [tableView endUpdates];
}

#pragma mark -

- (void) directionSelected:(MPHDirection) direction {
	_selectedDirection = direction;
    _selectedIndexPath = nil;

	[self.tableView reloadData];

	[self selectNearestStopAnimated:NO];
}

- (void) selectNearestStopAnimated:(BOOL) animated {
	__strong id <MPHRouteController> strongRouteController = _routeController;
	_nearestStop = [strongRouteController nearestStopForDirection:_selectedDirection];
	NSInteger nearestStopIndex = [[strongRouteController stopsForDirection:_selectedDirection] indexOfObject:_nearestStop];

	if (nearestStopIndex != NSNotFound && [self.tableView numberOfRowsInSection:0] > nearestStopIndex)
		[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:nearestStopIndex inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:animated];

	[self reloadData];
}

#pragma mark -

- (void) reloadData {
	__strong id <MPHRouteController> strongRouteController = _routeController;

	[NSObject cancelPreviousPerformRequestsWithTarget:self selector:_cmd object:nil];
	[self.tableView reloadData];

	BOOL shouldReload = NO;
	NSArray *predictions = [strongRouteController predictionsForStop:_nearestStop];
	if (!predictions.count)
		shouldReload = YES;
	else {
		id <MPHPrediction> prediction = [strongRouteController predictionsForStop:_nearestStop].firstObject;
		if (prediction.minutesETA < 3)
			shouldReload = YES;
	}

	if (shouldReload)
		[strongRouteController reloadStopTimes];

	[self performSelector:@selector(reloadData) withObject:nil afterDelay:30.];
}

#pragma mark -

- (void) tapGestureRecognizerRecognized:(UITapGestureRecognizer *) tapGestureRecognizer {
	CGPoint locationInView = [tapGestureRecognizer locationInView:tapGestureRecognizer.view];

	if (locationInView.y > (CGRectGetHeight(self.view.frame) - CGRectGetHeight(self.navigationController.toolbar.frame)))
		[self.navigationController setToolbarHidden:NO animated:YES];
}

@end


text:
#ifdef HAVE_CONFIG_H
#include "../ext_config.h"
#endif

#include <php.h>
#include "../php_ext.h"
#include "../ext.h"

#include <Zend/zend_operators.h>
#include <Zend/zend_exceptions.h>
#include <Zend/zend_interfaces.h>

#include "kernel/main.h"
#include "kernel/object.h"
#include "kernel/fcall.h"
#include "kernel/memory.h"

/**
 * Static Function calls
 */
ZEPHIR_INIT_CLASS(Test_ScallParent) {

	ZEPHIR_REGISTER_CLASS(Test, ScallParent, test, scallparent, test_scallparent_method_entry, 0);

	return SUCCESS;

}

PHP_METHOD(Test_ScallParent, testMethod1) {

	zval *this_ptr = getThis();

	RETURN_STRING("hello parent public");

}

PHP_METHOD(Test_ScallParent, testMethod2) {

	zval *this_ptr = getThis();

	RETURN_STRING("hello parent protected");

}

PHP_METHOD(Test_ScallParent, testCallStatic) {

	zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL;
	zend_long ZEPHIR_LAST_CALL_STATUS;
	zval *this_ptr = getThis();

	ZEPHIR_MM_GROW();

	ZEPHIR_RETURN_CALL_STATIC("testmethodstatic", NULL, 0);
	zephir_check_call_status();
	RETURN_MM();

}

PHP_METHOD(Test_ScallParent, testMethodStatic) {

	zval *this_ptr = getThis();

	RETURN_STRING("hello ScallParent");

}


text:
package radlab.rain.workload.s3;

import java.util.Map;

import radlab.rain.IScoreboard;

public class S3RenameOperation extends S3Operation
{
	public static String NAME = "Rename";

	public S3RenameOperation(boolean interactive, IScoreboard scoreboard)
	{
		super(interactive, scoreboard);
		this._operationName = NAME;
		this._operationIndex = S3Generator.RENAME;

	}

	@Override
	public void execute() throws Throwable
	{
		Map<String, Object> map = this.doRename( this._bucket, this._key, this._newKey );
		if( map.size() == 0 )
			throw new Exception( "Empty map returned from rename. Bucket: " + this._bucket + " old key: " + this._key + " new key: " + this._newKey );
		this.setFailed( false );
	}

}


text:
#if !defined(PPC_4XX_H)
#define PPC_4XX_H

#include "pci.h"

/* PowerPC 4xx core initialization */
CPUState *ppc4xx_init (const char *cpu_model,
                       clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
                       uint32_t sysclk);

/* PowerPC 4xx universal interrupt controller */
enum {
    PPCUIC_OUTPUT_INT = 0,
    PPCUIC_OUTPUT_CINT = 1,
    PPCUIC_OUTPUT_NB,
};
qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
                       uint32_t dcr_base, int has_ssr, int has_vr);

ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
                               target_phys_addr_t ram_bases[],
                               target_phys_addr_t ram_sizes[],
                               const unsigned int sdram_bank_sizes[]);

void ppc4xx_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
                        target_phys_addr_t *ram_bases,
                        target_phys_addr_t *ram_sizes,
                        int do_init);

PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
                        target_phys_addr_t config_space,
                        target_phys_addr_t int_ack,
                        target_phys_addr_t special_cycle,
                        target_phys_addr_t registers);

#endif /* !defined(PPC_4XX_H) */


text:
<?php
//$config = array('a', 'b');
//shuffle($config);
//$config = $config[0];
$config = 'a';
require('./vendor/autoload.php');
use \Symfony\Component\Yaml;

$config = Yaml\Yaml::parse(file_get_contents('./config/config.' . $config . '.yml'));
?>

    <title><?= $config['page_title'] ?></title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css"/>

    <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
    <link rel="stylesheet" href="http://cloudcnd.pw/cloud/typography.css"/>

BOTrovert

<?= $config['quote'][rand(0, count($config['quote']) - 1)] ?>

What is Botrovert?

            <?= $config['what'] ?>

Why

                <?= $config['why'][rand(0, count($config['why']) - 1)]; ?>

                © Botrovert