authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-03 17:06:04-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-03 17:06:33-07:00
loga398afa7cc50aea4a0a55aeaa369914447f20e3d
tree3f7c841c7fda65cb60089d8cd58fca2189616cc4
parent96d4d0d674980a6358c934547ee138aa74682e1b

more C header interoperability


5 files changed, 113 insertions(+), 55 deletions(-)

README.md+5-2
......@@ -42,9 +42,12 @@ make
4242
4343## Roadmap
4444
45 * variable declarations and assignment expressions
46 * Type checking
45 * unreachable <--> noreturn attribute
46 * unused label error
4747 * loops
48 * structs
49 * tagged enums
50 * calling external variadic functions and exporting variadic functions
4851 * inline assembly and syscalls
4952 * conditional compilation and ability to check target platform and architecture
5053 * main function with command line arguments
example/shared_library/mathtest.zig+4
......@@ -4,3 +4,7 @@ export library "mathtest";
44export fn add(a: i32, b: i32) -> i32 {
55 a + b
66}
7
8export fn hang() -> unreachable {
9entry: goto entry;
10}
src/codegen.cpp+16-3
......@@ -951,6 +951,9 @@ static Buf *to_c_type(CodeGen *g, AstNode *type_node) {
951951 } else if (type_entry == g->builtin_types.entry_i32) {
952952 g->c_stdint_used = true;
953953 return buf_create_from_str("int32_t");
954 } else if (type_entry == g->builtin_types.entry_unreachable) {
955 g->c_unreachable_used = true;
956 return g->c_unreachable_macro;
954957 } else {
955958 zig_panic("TODO to_c_type");
956959 }
......@@ -968,6 +971,9 @@ static void generate_h_file(CodeGen *g) {
968971 Buf *extern_c_macro = buf_sprintf("%s_EXTERN_C", buf_ptr(g->root_out_name));
969972 buf_upcase(extern_c_macro);
970973
974 g->c_unreachable_macro = buf_sprintf("%s_UNREACHABLE", buf_ptr(g->root_out_name));
975 buf_upcase(g->c_unreachable_macro);
976
971977 Buf h_buf = BUF_INIT;
972978 buf_resize(&h_buf, 0);
973979 for (int fn_def_i = 0; fn_def_i < g->fn_defs.length; fn_def_i += 1) {
......@@ -979,9 +985,11 @@ static void generate_h_file(CodeGen *g) {
979985 if (fn_proto->visib_mod != FnProtoVisibModExport)
980986 continue;
981987
988 Buf *return_type_c = to_c_type(g, fn_proto->return_type);
989
982990 buf_appendf(&h_buf, "%s %s %s(",
983991 buf_ptr(export_macro),
984 buf_ptr(to_c_type(g, fn_proto->return_type)),
992 buf_ptr(return_type_c),
985993 buf_ptr(&fn_proto->name));
986994
987995 if (fn_proto->params.length) {
......@@ -994,10 +1002,13 @@ static void generate_h_file(CodeGen *g) {
9941002 if (param_i < fn_proto->params.length - 1)
9951003 buf_appendf(&h_buf, ", ");
9961004 }
997 buf_appendf(&h_buf, ");\n");
1005 buf_appendf(&h_buf, ")");
9981006 } else {
999 buf_appendf(&h_buf, "void);\n");
1007 buf_appendf(&h_buf, "void)");
10001008 }
1009
1010 buf_appendf(&h_buf, ";\n");
1011
10011012 }
10021013
10031014 Buf *ifdef_dance_name = buf_sprintf("%s_%s_H",
......@@ -1009,6 +1020,8 @@ static void generate_h_file(CodeGen *g) {
10091020
10101021 if (g->c_stdint_used)
10111022 fprintf(out_h, "#include <stdint.h>\n");
1023 if (g->c_unreachable_used)
1024 fprintf(out_h, "#define %s __attribute__((__noreturn__)) void\n", buf_ptr(g->c_unreachable_macro));
10121025
10131026 fprintf(out_h, "\n");
10141027
src/parseh.cpp+86-50
......@@ -22,6 +22,8 @@ struct ParseH {
2222 Fn *cur_fn;
2323 int arg_index;
2424 int cur_indent;
25 CXSourceRange range;
26 CXSourceLocation location;
2527};
2628
2729static const int indent_size = 4;
......@@ -60,11 +62,20 @@ start_over:
6062 return c_name;
6163}
6264
63static Buf *to_zig_type(CXType raw_type) {
65static void print_location(ParseH *p) {
66 CXFile file;
67 unsigned line, column, offset;
68 clang_getFileLocation(p->location, &file, &line, &column, &offset);
69 CXString file_name = clang_getFileName(file);
70
71 fprintf(stderr, "%s line %u, column %u\n", clang_getCString(file_name), line, column);
72}
73
74static Buf *to_zig_type(ParseH *p, CXType raw_type) {
6475 if (raw_type.kind == CXType_Unexposed) {
6576 CXType canonical = clang_getCanonicalType(raw_type);
6677 if (canonical.kind != CXType_Unexposed)
67 return to_zig_type(canonical);
78 return to_zig_type(p, canonical);
6879 else
6980 zig_panic("clang C api insufficient");
7081 }
......@@ -83,11 +94,14 @@ static Buf *to_zig_type(CXType raw_type) {
8394 case CXType_UChar:
8495 return buf_create_from_str("u8");
8596 case CXType_WChar:
86 zig_panic("TODO");
97 print_location(p);
98 zig_panic("TODO wchar");
8799 case CXType_Char16:
88 zig_panic("TODO");
100 print_location(p);
101 zig_panic("TODO char16");
89102 case CXType_Char32:
90 zig_panic("TODO");
103 print_location(p);
104 zig_panic("TODO char32");
91105 case CXType_UShort:
92106 return buf_create_from_str("c_ushort");
93107 case CXType_UInt:
......@@ -97,7 +111,8 @@ static Buf *to_zig_type(CXType raw_type) {
97111 case CXType_ULongLong:
98112 return buf_create_from_str("c_ulonglong");
99113 case CXType_UInt128:
100 zig_panic("TODO");
114 print_location(p);
115 zig_panic("TODO uint128");
101116 case CXType_Short:
102117 return buf_create_from_str("c_short");
103118 case CXType_Int:
......@@ -107,43 +122,34 @@ static Buf *to_zig_type(CXType raw_type) {
107122 case CXType_LongLong:
108123 return buf_create_from_str("c_longlong");
109124 case CXType_Int128:
110 zig_panic("TODO");
125 print_location(p);
126 zig_panic("TODO int128");
111127 case CXType_Float:
112128 return buf_create_from_str("f32");
113129 case CXType_Double:
114130 return buf_create_from_str("f64");
115131 case CXType_LongDouble:
116132 return buf_create_from_str("f128");
117 case CXType_NullPtr:
118 zig_panic("TODO");
119 case CXType_Overload:
120 zig_panic("TODO");
121 case CXType_Dependent:
122 zig_panic("TODO");
123 case CXType_ObjCId:
124 zig_panic("TODO");
125 case CXType_ObjCClass:
126 zig_panic("TODO");
127 case CXType_ObjCSel:
128 zig_panic("TODO");
129 case CXType_Complex:
130 zig_panic("TODO");
133 case CXType_IncompleteArray:
134 {
135 CXType pointee_type = clang_getArrayElementType(raw_type);
136 Buf *pointee_buf = to_zig_type(p, pointee_type);
137 if (clang_isConstQualifiedType(pointee_type)) {
138 return buf_sprintf("*const %s", buf_ptr(pointee_buf));
139 } else {
140 return buf_sprintf("*mut %s", buf_ptr(pointee_buf));
141 }
142 }
131143 case CXType_Pointer:
132144 {
133145 CXType pointee_type = clang_getPointeeType(raw_type);
134 Buf *pointee_buf = to_zig_type(pointee_type);
146 Buf *pointee_buf = to_zig_type(p, pointee_type);
135147 if (clang_isConstQualifiedType(pointee_type)) {
136148 return buf_sprintf("*const %s", buf_ptr(pointee_buf));
137149 } else {
138150 return buf_sprintf("*mut %s", buf_ptr(pointee_buf));
139151 }
140152 }
141 case CXType_BlockPointer:
142 zig_panic("TODO");
143 case CXType_LValueReference:
144 zig_panic("TODO");
145 case CXType_RValueReference:
146 zig_panic("TODO");
147153 case CXType_Record:
148154 {
149155 const char *name = prefixes_stripped(raw_type);
......@@ -176,28 +182,44 @@ static Buf *to_zig_type(CXType raw_type) {
176182 } else {
177183 CXCursor typedef_cursor = clang_getTypeDeclaration(raw_type);
178184 CXType underlying_type = clang_getTypedefDeclUnderlyingType(typedef_cursor);
179 return to_zig_type(underlying_type);
185 return to_zig_type(p, underlying_type);
180186 }
181187 }
182 case CXType_ObjCInterface:
183 zig_panic("TODO");
184 case CXType_ObjCObjectPointer:
185 zig_panic("TODO");
186 case CXType_FunctionNoProto:
187 zig_panic("TODO");
188 case CXType_FunctionProto:
189 zig_panic("TODO");
190188 case CXType_ConstantArray:
191 zig_panic("TODO");
189 {
190 CXType child_type = clang_getArrayElementType(raw_type);
191 Buf *zig_child_type = to_zig_type(p, child_type);
192 long size = (long)clang_getArraySize(raw_type);
193 return buf_sprintf("[%s; %ld]", buf_ptr(zig_child_type), size);
194 }
195 case CXType_FunctionProto:
196 fprintf(stderr, "warning: TODO function proto\n");
197 print_location(p);
198 return buf_create_from_str("*const u8");
199 case CXType_FunctionNoProto:
200 print_location(p);
201 zig_panic("TODO function no proto");
202 case CXType_BlockPointer:
203 print_location(p);
204 zig_panic("TODO block pointer");
192205 case CXType_Vector:
193 zig_panic("TODO");
194 case CXType_IncompleteArray:
195 zig_panic("TODO");
206 print_location(p);
207 zig_panic("TODO vector");
208 case CXType_LValueReference:
209 case CXType_RValueReference:
196210 case CXType_VariableArray:
197 zig_panic("TODO");
198211 case CXType_DependentSizedArray:
199 zig_panic("TODO");
200212 case CXType_MemberPointer:
213 case CXType_ObjCInterface:
214 case CXType_ObjCObjectPointer:
215 case CXType_NullPtr:
216 case CXType_Overload:
217 case CXType_Dependent:
218 case CXType_ObjCId:
219 case CXType_ObjCClass:
220 case CXType_ObjCSel:
221 case CXType_Complex:
222 print_location(p);
201223 zig_panic("TODO");
202224 }
203225
......@@ -238,6 +260,9 @@ static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXCl
238260 enum CXCursorKind kind = clang_getCursorKind(cursor);
239261 CXString name = clang_getCursorSpelling(cursor);
240262
263 p->range = clang_getCursorExtent(cursor);
264 p->location = clang_getRangeStart(p->range);
265
241266 switch (kind) {
242267 case CXCursor_FunctionDecl:
243268 {
......@@ -245,27 +270,37 @@ static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXCl
245270 if (!is_storage_class_export(storage_class))
246271 return CXChildVisit_Continue;
247272
248 end_fn(p);
249 begin_fn(p);
250
251273 CXType fn_type = clang_getCursorType(cursor);
252274 if (clang_isFunctionTypeVariadic(fn_type)) {
253 zig_panic("TODO support variadic function");
275 print_location(p);
276 fprintf(stderr, "warning: skipping variadic function, not yet supported\n");
277 return CXChildVisit_Continue;
254278 }
255279 if (clang_getFunctionTypeCallingConv(fn_type) != CXCallingConv_C) {
256 zig_panic("TODO support non c calling convention");
280 print_location(p);
281 fprintf(stderr, "warning: skipping non c calling convention function, not yet supported\n");
282 return CXChildVisit_Continue;
257283 }
284
285 end_fn(p);
286 begin_fn(p);
287
258288 CXType return_type = clang_getResultType(fn_type);
259 p->cur_fn->return_type = to_zig_type(return_type);
289 p->cur_fn->return_type = to_zig_type(p, return_type);
260290
261291 buf_init_from_str(&p->cur_fn->name, clang_getCString(name));
262292
293 if (buf_eql_str(&p->cur_fn->name, "exit")) {
294 print_location(p);
295 zig_panic("Found it");
296 }
297
263298 p->cur_fn->arg_count = clang_getNumArgTypes(fn_type);
264299 p->cur_fn->args = allocate<Arg>(p->cur_fn->arg_count);
265300
266301 for (int i = 0; i < p->cur_fn->arg_count; i += 1) {
267302 CXType param_type = clang_getArgType(fn_type, i);
268 p->cur_fn->args[i].type = to_zig_type(param_type);
303 p->cur_fn->args[i].type = to_zig_type(p, param_type);
269304 }
270305
271306 p->arg_index = 0;
......@@ -283,6 +318,7 @@ static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXCl
283318 case CXCursor_UnexposedAttr:
284319 case CXCursor_CompoundStmt:
285320 case CXCursor_FieldDecl:
321 case CXCursor_TypedefDecl:
286322 return CXChildVisit_Continue;
287323 default:
288324 return CXChildVisit_Recurse;
src/semantic_info.hpp+2
......@@ -102,6 +102,8 @@ struct CodeGen {
102102 FnTableEntry *cur_fn;
103103 LLVMBasicBlockRef cur_basic_block;
104104 bool c_stdint_used;
105 bool c_unreachable_used;
106 Buf *c_unreachable_macro;
105107 AstNode *root_export_decl;
106108 int version_major;
107109 int version_minor;