mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-06 21:17:40 +00:00
Add intrinsics.constant_utf16_cstring
This commit is contained in:
@@ -2122,6 +2122,77 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
|
||||
case BuiltinProc_objc_find_class: return lb_handle_objc_find_class(p, expr);
|
||||
case BuiltinProc_objc_register_selector: return lb_handle_objc_register_selector(p, expr);
|
||||
case BuiltinProc_objc_register_class: return lb_handle_objc_register_class(p, expr);
|
||||
|
||||
|
||||
case BuiltinProc_constant_utf16_cstring:
|
||||
{
|
||||
auto const encode_surrogate_pair = [](Rune r, u16 *r1, u16 *r2) {
|
||||
if (r < 0x10000 || r > 0x10ffff) {
|
||||
*r1 = 0xfffd;
|
||||
*r2 = 0xfffd;
|
||||
} else {
|
||||
r -= 0x10000;
|
||||
*r1 = 0xd800 + ((r>>10)&0x3ff);
|
||||
*r2 = 0xdc00 + (r&0x3ff);
|
||||
}
|
||||
};
|
||||
|
||||
lbModule *m = p->module;
|
||||
|
||||
auto tav = type_and_value_of_expr(ce->args[0]);
|
||||
GB_ASSERT(tav.value.kind == ExactValue_String);
|
||||
String value = tav.value.value_string;
|
||||
|
||||
LLVMTypeRef llvm_u16 = lb_type(m, t_u16);
|
||||
|
||||
isize max_len = value.len*2 + 1;
|
||||
LLVMValueRef *buffer = gb_alloc_array(temporary_allocator(), LLVMValueRef, max_len);
|
||||
isize n = 0;
|
||||
while (value.len > 0) {
|
||||
Rune r = 0;
|
||||
isize w = gb_utf8_decode(value.text, value.len, &r);
|
||||
value.text += w;
|
||||
value.len -= w;
|
||||
if ((0 <= r && r < 0xd800) || (0xe000 <= r && r < 0x10000)) {
|
||||
buffer[n++] = LLVMConstInt(llvm_u16, cast(u16)r, false);
|
||||
} else if (0x10000 <= r && r <= 0x10ffff) {
|
||||
u16 r1, r2;
|
||||
encode_surrogate_pair(r, &r1, &r2);
|
||||
buffer[n++] = LLVMConstInt(llvm_u16, r1, false);
|
||||
buffer[n++] = LLVMConstInt(llvm_u16, r2, false);
|
||||
} else {
|
||||
buffer[n++] = LLVMConstInt(llvm_u16, 0xfffd, false);
|
||||
}
|
||||
}
|
||||
|
||||
buffer[n++] = LLVMConstInt(llvm_u16, 0, false);
|
||||
|
||||
LLVMValueRef array = LLVMConstArray(llvm_u16, buffer, cast(unsigned int)n);
|
||||
|
||||
char *name = nullptr;
|
||||
{
|
||||
isize max_len = 7+8+1;
|
||||
name = gb_alloc_array(permanent_allocator(), char, max_len);
|
||||
u32 id = m->gen->global_array_index.fetch_add(1);
|
||||
isize len = gb_snprintf(name, max_len, "csbs$%x", id);
|
||||
len -= 1;
|
||||
}
|
||||
LLVMValueRef global_data = LLVMAddGlobal(m->mod, LLVMTypeOf(array), name);
|
||||
LLVMSetInitializer(global_data, array);
|
||||
LLVMSetLinkage(global_data, LLVMInternalLinkage);
|
||||
|
||||
|
||||
|
||||
LLVMValueRef indices[] = {
|
||||
LLVMConstInt(lb_type(m, t_u32), 0, false),
|
||||
LLVMConstInt(lb_type(m, t_u32), 0, false),
|
||||
};
|
||||
lbValue res = {};
|
||||
res.type = tv.type;
|
||||
res.value = LLVMBuildInBoundsGEP(p->builder, global_data, indices, gb_count_of(indices), "");
|
||||
return res;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
GB_PANIC("Unhandled built-in procedure %.*s", LIT(builtin_procs[id].name));
|
||||
|
||||
Reference in New Issue
Block a user