Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wip: Add c_char type #861

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion doc/langref.html.in
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,11 @@ pub fn main() void {
<td>unsigned pointer sized integer</td>
</tr>

<tr>
<td><code>c_char</code></td>
<td><code>char</code></td>
<td>for ABI compatibility with C</td>
</tr>
<tr>
<td><code>c_short</code></td>
<td><code>short</code></td>
Expand Down Expand Up @@ -5334,6 +5339,7 @@ pub const have_error_return_tracing = true;
These have guaranteed C ABI compatibility and can be used like any other type.
</p>
<ul>
<li><code>c_char</code> - This differs from C in that an 8-bit size is assumed.</li>
<li><code>c_short</code></li>
<li><code>c_ushort</code></li>
<li><code>c_int</code></li>
Expand Down Expand Up @@ -5954,7 +5960,7 @@ hljs.registerLanguage("zig", function(t) {
},
a = t.IR + "\\s*\\(",
c = {
keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong",
keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_char c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong",
built_in: "breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic canImplicitCast ptrCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchg fence divExact truncate atomicRmw",
literal: "true false null undefined"
},
Expand Down
8 changes: 4 additions & 4 deletions src/analyze.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4833,22 +4833,22 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
size_t len_with_null = buf_len(str) + 1;
ConstExprValue *array_val = create_const_vals(1);
array_val->special = ConstValSpecialStatic;
array_val->type = get_array_type(g, g->builtin_types.entry_u8, len_with_null);
array_val->type = get_array_type(g, g->builtin_types.entry_c_int[CIntTypeChar], len_with_null);
array_val->data.x_array.s_none.elements = create_const_vals(len_with_null);
for (size_t i = 0; i < buf_len(str); i += 1) {
ConstExprValue *this_char = &array_val->data.x_array.s_none.elements[i];
this_char->special = ConstValSpecialStatic;
this_char->type = g->builtin_types.entry_u8;
this_char->type = g->builtin_types.entry_c_int[CIntTypeChar];
bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(str)[i]);
}
ConstExprValue *null_char = &array_val->data.x_array.s_none.elements[len_with_null - 1];
null_char->special = ConstValSpecialStatic;
null_char->type = g->builtin_types.entry_u8;
null_char->type = g->builtin_types.entry_c_int[CIntTypeChar];
bigint_init_unsigned(&null_char->data.x_bigint, 0);

// then make the pointer point to it
const_val->special = ConstValSpecialStatic;
const_val->type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
const_val->type = get_pointer_to_type(g, g->builtin_types.entry_c_int[CIntTypeChar], true);
const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
const_val->data.x_ptr.data.base_array.array_val = array_val;
const_val->data.x_ptr.data.base_array.elem_index = 0;
Expand Down
6 changes: 5 additions & 1 deletion src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5578,6 +5578,9 @@ struct CIntTypeInfo {
};

static const CIntTypeInfo c_int_type_infos[] = {
// Signedness of a c char is implementation-defined.
// Assume true (x86 default), but would be better as a target detail.
{CIntTypeChar, "c_char", true},
{CIntTypeShort, "c_short", true},
{CIntTypeUShort, "c_ushort", false},
{CIntTypeInt, "c_int", true},
Expand Down Expand Up @@ -5666,7 +5669,7 @@ static void define_builtin_types(CodeGen *g) {
for (size_t i = 0; i < array_length(c_int_type_infos); i += 1) {
const CIntTypeInfo *info = &c_int_type_infos[i];
uint32_t size_in_bits = target_c_type_size_in_bits(&g->zig_target, info->id);
bool is_signed = info->is_signed;
bool is_signed = info->id == CIntTypeChar ? target_is_char_signed(&g->zig_target) : info->is_signed;

TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
entry->type_ref = LLVMIntType(size_in_bits);
Expand Down Expand Up @@ -6455,6 +6458,7 @@ void codegen_add_object(CodeGen *g, Buf *object_path) {

// Must be coordinated with with CIntType enum
static const char *c_int_type_names[] = {
"char",
"short",
"unsigned short",
"int",
Expand Down
67 changes: 67 additions & 0 deletions src/target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,67 @@ static bool is_os_darwin(ZigTarget *target) {
}
}

// see https://wiki.debian.org/ArchitectureSpecificsMemo
bool target_is_char_signed(ZigTarget *target) {
switch (target->arch.arch) {
case ZigLLVM_mips:
case ZigLLVM_mipsel:
case ZigLLVM_mips64:
case ZigLLVM_mips64el:
case ZigLLVM_x86:
case ZigLLVM_x86_64:
return true;

case ZigLLVM_arm:
case ZigLLVM_ppc:
case ZigLLVM_ppc64:
case ZigLLVM_ppc64le:
return false;

case ZigLLVM_armeb:
case ZigLLVM_aarch64:
case ZigLLVM_aarch64_be:
case ZigLLVM_arc:
case ZigLLVM_avr:
case ZigLLVM_bpfel:
case ZigLLVM_bpfeb:
case ZigLLVM_hexagon:
case ZigLLVM_msp430:
case ZigLLVM_nios2:
case ZigLLVM_r600:
case ZigLLVM_amdgcn:
case ZigLLVM_riscv32:
case ZigLLVM_riscv64:
case ZigLLVM_sparc:
case ZigLLVM_sparcv9:
case ZigLLVM_sparcel:
case ZigLLVM_systemz:
case ZigLLVM_tce:
case ZigLLVM_tcele:
case ZigLLVM_thumb:
case ZigLLVM_thumbeb:
case ZigLLVM_xcore:
case ZigLLVM_nvptx:
case ZigLLVM_nvptx64:
case ZigLLVM_le32:
case ZigLLVM_le64:
case ZigLLVM_amdil:
case ZigLLVM_amdil64:
case ZigLLVM_hsail:
case ZigLLVM_hsail64:
case ZigLLVM_spir:
case ZigLLVM_spir64:
case ZigLLVM_kalimba:
case ZigLLVM_shave:
case ZigLLVM_lanai:
case ZigLLVM_wasm32:
case ZigLLVM_wasm64:
case ZigLLVM_renderscript32:
case ZigLLVM_renderscript64:
zig_panic("TODO c char sign for this target");
}
}

void resolve_target_object_format(ZigTarget *target) {
if (target->oformat != ZigLLVM_UnknownObjectFormat) {
return;
Expand Down Expand Up @@ -684,6 +745,8 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
switch (target->os) {
case OsFreestanding:
switch (id) {
case CIntTypeChar:
return 8;
case CIntTypeShort:
case CIntTypeUShort:
return 16;
Expand All @@ -703,6 +766,8 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
case OsMacOSX:
case OsZen:
switch (id) {
case CIntTypeChar:
return 8;
case CIntTypeShort:
case CIntTypeUShort:
return 16;
Expand All @@ -720,6 +785,8 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
}
case OsWindows:
switch (id) {
case CIntTypeChar:
return 8;
case CIntTypeShort:
case CIntTypeUShort:
return 16;
Expand Down
3 changes: 3 additions & 0 deletions src/target.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ struct ZigTarget {
};

enum CIntType {
CIntTypeChar,
CIntTypeShort,
CIntTypeUShort,
CIntTypeInt,
Expand Down Expand Up @@ -103,6 +104,8 @@ void init_all_targets(void);

void get_target_triple(Buf *triple, const ZigTarget *target);

bool target_is_char_signed(ZigTarget *target);

void resolve_target_object_format(ZigTarget *target);

uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id);
Expand Down
3 changes: 2 additions & 1 deletion src/translate_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -729,8 +729,9 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
case BuiltinType::Bool:
return trans_create_node_symbol_str(c, "bool");
case BuiltinType::Char_U:
case BuiltinType::UChar:
case BuiltinType::Char_S:
return trans_create_node_symbol_str(c, "c_char");
case BuiltinType::UChar:
return trans_create_node_symbol_str(c, "u8");
case BuiltinType::SChar:
return trans_create_node_symbol_str(c, "i8");
Expand Down
16 changes: 8 additions & 8 deletions test/translate_c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
\\void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d);
\\void baz(int8_t a, int16_t b, int32_t c, int64_t d);
,
\\pub extern fn foo(a: u8, b: u8, c: i8) c_int;
\\pub extern fn foo(a: c_char, b: u8, c: i8) c_int;
,
\\pub extern fn bar(a: u8, b: u16, c: u32, d: u64) void;
\\pub extern fn bar(a: c_char, b: u16, c: u32, d: u64) void;
,
\\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void;
);
Expand Down Expand Up @@ -67,7 +67,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
,
\\const struct_Foo = extern struct {
\\ x: c_int,
\\ y: ?&u8,
\\ y: ?&c_char,
\\};
,
\\pub const Foo = struct_Foo;
Expand Down Expand Up @@ -206,9 +206,9 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
\\ return (??fn_ptr)();
\\}
,
\\pub extern var fn_ptr2: ?extern fn(c_int, f32) u8;
\\pub extern var fn_ptr2: ?extern fn(c_int, f32) c_char;
,
\\pub inline fn bar(arg0: c_int, arg1: f32) u8 {
\\pub inline fn bar(arg0: c_int, arg1: f32) c_char {
\\ return (??fn_ptr2)(arg0, arg1);
\\}
);
Expand Down Expand Up @@ -979,7 +979,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
\\ return "bar";
\\}
,
\\pub fn foo() ?&const u8 {
\\pub fn foo() ?&const c_char {
\\ return c"bar";
\\}
);
Expand Down Expand Up @@ -1152,7 +1152,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
cases.add("const ptr initializer",
\\static const char *v0 = "0.0.0";
,
\\pub var v0: ?&const u8 = c"0.0.0";
\\pub var v0: ?&const c_char = c"0.0.0";
);

cases.add("static incomplete array inside function",
Expand All @@ -1161,7 +1161,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
\\}
,
\\pub fn foo() void {
\\ const v2: &const u8 = c"2.2.2";
\\ const v2: &const c_char = c"2.2.2";
\\}
);

Expand Down