aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2018-02-28 11:20:11 +0000
committergingerBill <bill@gingerbill.org>2018-02-28 11:20:11 +0000
commitd3ea334e7ab2897bbc948acc57aa9ba073304215 (patch)
tree8f6016ab7bd62c0320c893e0cb7fa6337054420f /src
parent223c473cf64845f0c0824375fa98ca51bad66fc1 (diff)
`cstring`
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp16
-rw-r--r--src/ir.cpp29
-rw-r--r--src/ir_print.cpp15
-rw-r--r--src/types.cpp35
4 files changed, 85 insertions, 10 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index ec6f95b14..7ad75ac48 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -1786,7 +1786,19 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
return true;
// }
}
+ // cstring -> string
+ if (src == t_cstring && dst == t_string) {
+ return true;
+ }
+ // cstring -> ^u8
+ if (src == t_cstring && is_type_u8_ptr(dst)) {
+ return true;
+ }
+ // ^u8 -> cstring
+ if (is_type_u8_ptr(src) && dst == t_cstring) {
+ return true;
+ }
// proc <-> proc
if (is_type_proc(src) && is_type_proc(dst)) {
return true;
@@ -5005,7 +5017,7 @@ bool check_set_index_data(Operand *o, Type *type, bool indirection, i64 *max_cou
switch (t->kind) {
case Type_Basic:
- if (is_type_string(t)) {
+ if (t->Basic.kind == Basic_string) {
if (o->mode == Addressing_Constant) {
*max_count = o->value.value_string.len;
}
@@ -5904,7 +5916,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
Type *t = base_type(type_deref(o->type));
switch (t->kind) {
case Type_Basic:
- if (is_type_string(t)) {
+ if (t->Basic.kind == Basic_string) {
valid = true;
if (o->mode == Addressing_Constant) {
max_count = o->value.value_string.len;
diff --git a/src/ir.cpp b/src/ir.cpp
index a1b3ca8ee..6ab3c9ef7 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -2890,6 +2890,14 @@ irValue *ir_string_len(irProcedure *proc, irValue *string) {
return ir_emit_struct_ev(proc, string, 1);
}
+irValue *ir_cstring_len(irProcedure *proc, irValue *value) {
+ GB_ASSERT(is_type_cstring(ir_type(value)));
+ auto args = array_make<irValue *>(proc->module->allocator, 1);
+ args[0] = ir_emit_conv(proc, value, t_cstring);
+ return ir_emit_global_call(proc, "__cstring_len", args);
+}
+
+
void ir_fill_slice(irProcedure *proc, irValue *slice_ptr, irValue *data, irValue *len) {
Type *t = ir_type(slice_ptr);
@@ -3122,6 +3130,18 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
return ir_emit(proc, ir_instr_conv(proc, irConv_zext, b, t_llvm_bool, t));
}
+ if (src == t_cstring && is_type_u8_ptr(dst)) {
+ return ir_emit_bitcast(proc, value, dst);
+ }
+
+ if (src == t_cstring && dst == t_string) {
+ irValue *c = ir_emit_conv(proc, value, t_cstring);
+ auto args = array_make<irValue *>(proc->module->allocator, 1);
+ args[0] = c;
+ irValue *s = ir_emit_global_call(proc, "__cstring_to_string", args);
+ return ir_emit_conv(proc, s, dst);
+ }
+
// integer -> boolean
if (is_type_integer(src) && is_type_boolean(dst)) {
@@ -4171,7 +4191,9 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
v = ir_emit_load(proc, v);
t = type_deref(t);
}
- if (is_type_string(t)) {
+ if (is_type_cstring(t)) {
+ return ir_cstring_len(proc, v);
+ } else if (is_type_string(t)) {
return ir_string_len(proc, v);
} else if (is_type_array(t)) {
GB_PANIC("Array lengths are constant");
@@ -7902,6 +7924,11 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
tag = ir_emit_conv(proc, variant_ptr, t_type_info_string_ptr);
break;
+ case Basic_cstring:
+ tag = ir_emit_conv(proc, variant_ptr, t_type_info_string_ptr);
+ ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), v_true); // is_cstring
+ break;
+
case Basic_any:
tag = ir_emit_conv(proc, variant_ptr, t_type_info_any_ptr);
break;
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index eaf7e0477..632d9c0e1 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -340,6 +340,7 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t, bool in_struct) {
case Basic_any: ir_write_str_lit(f, "%..any"); return;
case Basic_rawptr: ir_write_str_lit(f, "%..rawptr"); return;
case Basic_string: ir_write_str_lit(f, "%..string"); return;
+ case Basic_cstring: ir_write_str_lit(f, "i8*"); return;
}
break;
@@ -551,11 +552,25 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
ir_write_str_lit(f, "zeroinitializer");
break;
}
+ Type *t = core_type(type);
if (!is_type_string(type)) {
GB_ASSERT(is_type_array(type));
ir_write_str_lit(f, "c\"");
ir_print_escape_string(f, str, false, false);
ir_write_str_lit(f, "\\00\"");
+ } else if (t == t_cstring) {
+ // HACK NOTE(bill): This is a hack but it works because strings are created at the very end
+ // of the .ll file
+ irValue *str_array = ir_add_global_string_array(m, str);
+ ir_write_str_lit(f, "getelementptr inbounds (");
+ ir_print_type(f, m, str_array->Global.entity->type);
+ ir_write_str_lit(f, ", ");
+ ir_print_type(f, m, str_array->Global.entity->type);
+ ir_write_str_lit(f, "* ");
+ ir_print_encoded_global(f, str_array->Global.entity->token.string, false);
+ ir_write_str_lit(f, ", ");
+ ir_print_type(f, m, t_int);
+ ir_write_str_lit(f, " 0, i32 0)");
} else {
// HACK NOTE(bill): This is a hack but it works because strings are created at the very end
// of the .ll file
diff --git a/src/types.cpp b/src/types.cpp
index 239a530d1..c0254729f 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -34,8 +34,9 @@ enum BasicKind {
Basic_uint,
Basic_uintptr,
Basic_rawptr,
- Basic_string, // ^u8 + int
- Basic_any, // rawptr + ^Type_Info
+ Basic_string, // ^u8 + int
+ Basic_cstring, // ^u8
+ Basic_any, // rawptr + ^Type_Info
Basic_UntypedBool,
Basic_UntypedInteger,
@@ -277,6 +278,7 @@ gb_global Type basic_types[] = {
{Type_Basic, {Basic_rawptr, BasicFlag_Pointer, -1, STR_LIT("rawptr")}},
{Type_Basic, {Basic_string, BasicFlag_String, -1, STR_LIT("string")}},
+ {Type_Basic, {Basic_cstring, BasicFlag_String, -1, STR_LIT("cstring")}},
{Type_Basic, {Basic_any, 0, -1, STR_LIT("any")}},
{Type_Basic, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, 0, STR_LIT("untyped bool")}},
@@ -322,6 +324,7 @@ gb_global Type *t_uintptr = &basic_types[Basic_uintptr];
gb_global Type *t_rawptr = &basic_types[Basic_rawptr];
gb_global Type *t_string = &basic_types[Basic_string];
+gb_global Type *t_cstring = &basic_types[Basic_cstring];
gb_global Type *t_any = &basic_types[Basic_any];
gb_global Type *t_untyped_bool = &basic_types[Basic_UntypedBool];
@@ -690,6 +693,13 @@ bool is_type_string(Type *t) {
}
return false;
}
+bool is_type_cstring(Type *t) {
+ t = base_type(t);
+ if (t->kind == Type_Basic) {
+ return t->Basic.kind == Basic_cstring;
+ }
+ return false;
+}
bool is_type_typed(Type *t) {
t = base_type(t);
if (t == nullptr) {
@@ -802,6 +812,13 @@ bool is_type_u8_slice(Type *t) {
}
return false;
}
+bool is_type_u8_ptr(Type *t) {
+ t = base_type(t);
+ if (t->kind == Type_Pointer) {
+ return is_type_u8(t->Slice.elem);
+ }
+ return false;
+}
bool is_type_proc(Type *t) {
t = base_type(t);
return t->kind == Type_Proc;
@@ -933,7 +950,7 @@ bool is_type_indexable(Type *t) {
Type *bt = base_type(t);
switch (bt->kind) {
case Type_Basic:
- return is_type_string(bt);
+ return bt->Basic.kind == Basic_string;
case Type_Array:
case Type_Slice:
case Type_DynamicArray:
@@ -1101,6 +1118,8 @@ bool is_type_comparable(Type *t) {
return false;
case Basic_rune:
return true;
+ case Basic_cstring:
+ return false;
}
return true;
case Type_Pointer:
@@ -1849,8 +1868,9 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
case Type_Basic: {
GB_ASSERT(is_type_typed(t));
switch (t->Basic.kind) {
- case Basic_string: return build_context.word_size;
- case Basic_any: return build_context.word_size;
+ case Basic_string: return build_context.word_size;
+ case Basic_cstring: return build_context.word_size;
+ case Basic_any: return build_context.word_size;
case Basic_int: case Basic_uint: case Basic_uintptr: case Basic_rawptr:
return build_context.word_size;
@@ -2048,8 +2068,9 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
return size;
}
switch (kind) {
- case Basic_string: return 2*build_context.word_size;
- case Basic_any: return 2*build_context.word_size;
+ case Basic_string: return 2*build_context.word_size;
+ case Basic_cstring: return build_context.word_size;
+ case Basic_any: return 2*build_context.word_size;
case Basic_int: case Basic_uint: case Basic_uintptr: case Basic_rawptr:
return build_context.word_size;