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...@@ -42,9 +42,12 @@ make
4242
43## Roadmap43## Roadmap
4444
45 * variable declarations and assignment expressions45 * unreachable <--> noreturn attribute
46 * Type checking46 * unused label error
47 * loops47 * loops
48 * structs
49 * tagged enums
50 * calling external variadic functions and exporting variadic functions
48 * inline assembly and syscalls51 * inline assembly and syscalls
49 * conditional compilation and ability to check target platform and architecture52 * conditional compilation and ability to check target platform and architecture
50 * main function with command line arguments53 * main function with command line arguments
example/shared_library/mathtest.zig+4
...@@ -4,3 +4,7 @@ export library "mathtest";...@@ -4,3 +4,7 @@ export library "mathtest";
4export fn add(a: i32, b: i32) -> i32 {4export fn add(a: i32, b: i32) -> i32 {
5 a + b5 a + b
6}6}
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) {...@@ -951,6 +951,9 @@ static Buf *to_c_type(CodeGen *g, AstNode *type_node) {
951 } else if (type_entry == g->builtin_types.entry_i32) {951 } else if (type_entry == g->builtin_types.entry_i32) {
952 g->c_stdint_used = true;952 g->c_stdint_used = true;
953 return buf_create_from_str("int32_t");953 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;
954 } else {957 } else {
955 zig_panic("TODO to_c_type");958 zig_panic("TODO to_c_type");
956 }959 }
...@@ -968,6 +971,9 @@ static void generate_h_file(CodeGen *g) {...@@ -968,6 +971,9 @@ static void generate_h_file(CodeGen *g) {
968 Buf *extern_c_macro = buf_sprintf("%s_EXTERN_C", buf_ptr(g->root_out_name));971 Buf *extern_c_macro = buf_sprintf("%s_EXTERN_C", buf_ptr(g->root_out_name));
969 buf_upcase(extern_c_macro);972 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
971 Buf h_buf = BUF_INIT;977 Buf h_buf = BUF_INIT;
972 buf_resize(&h_buf, 0);978 buf_resize(&h_buf, 0);
973 for (int fn_def_i = 0; fn_def_i < g->fn_defs.length; fn_def_i += 1) {979 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) {...@@ -979,9 +985,11 @@ static void generate_h_file(CodeGen *g) {
979 if (fn_proto->visib_mod != FnProtoVisibModExport)985 if (fn_proto->visib_mod != FnProtoVisibModExport)
980 continue;986 continue;
981987
988 Buf *return_type_c = to_c_type(g, fn_proto->return_type);
989
982 buf_appendf(&h_buf, "%s %s %s(",990 buf_appendf(&h_buf, "%s %s %s(",
983 buf_ptr(export_macro),991 buf_ptr(export_macro),
984 buf_ptr(to_c_type(g, fn_proto->return_type)),992 buf_ptr(return_type_c),
985 buf_ptr(&fn_proto->name));993 buf_ptr(&fn_proto->name));
986994
987 if (fn_proto->params.length) {995 if (fn_proto->params.length) {
...@@ -994,10 +1002,13 @@ static void generate_h_file(CodeGen *g) {...@@ -994,10 +1002,13 @@ static void generate_h_file(CodeGen *g) {
994 if (param_i < fn_proto->params.length - 1)1002 if (param_i < fn_proto->params.length - 1)
995 buf_appendf(&h_buf, ", ");1003 buf_appendf(&h_buf, ", ");
996 }1004 }
997 buf_appendf(&h_buf, ");\n");1005 buf_appendf(&h_buf, ")");
998 } else {1006 } else {
999 buf_appendf(&h_buf, "void);\n");1007 buf_appendf(&h_buf, "void)");
1000 }1008 }
1009
1010 buf_appendf(&h_buf, ";\n");
1011
1001 }1012 }
10021013
1003 Buf *ifdef_dance_name = buf_sprintf("%s_%s_H",1014 Buf *ifdef_dance_name = buf_sprintf("%s_%s_H",
...@@ -1009,6 +1020,8 @@ static void generate_h_file(CodeGen *g) {...@@ -1009,6 +1020,8 @@ static void generate_h_file(CodeGen *g) {
10091020
1010 if (g->c_stdint_used)1021 if (g->c_stdint_used)
1011 fprintf(out_h, "#include <stdint.h>\n");1022 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
1013 fprintf(out_h, "\n");1026 fprintf(out_h, "\n");
10141027
src/parseh.cpp+86-50
...@@ -22,6 +22,8 @@ struct ParseH {...@@ -22,6 +22,8 @@ struct ParseH {
22 Fn *cur_fn;22 Fn *cur_fn;
23 int arg_index;23 int arg_index;
24 int cur_indent;24 int cur_indent;
25 CXSourceRange range;
26 CXSourceLocation location;
25};27};
2628
27static const int indent_size = 4;29static const int indent_size = 4;
...@@ -60,11 +62,20 @@ start_over:...@@ -60,11 +62,20 @@ start_over:
60 return c_name;62 return c_name;
61}63}
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) {
64 if (raw_type.kind == CXType_Unexposed) {75 if (raw_type.kind == CXType_Unexposed) {
65 CXType canonical = clang_getCanonicalType(raw_type);76 CXType canonical = clang_getCanonicalType(raw_type);
66 if (canonical.kind != CXType_Unexposed)77 if (canonical.kind != CXType_Unexposed)
67 return to_zig_type(canonical);78 return to_zig_type(p, canonical);
68 else79 else
69 zig_panic("clang C api insufficient");80 zig_panic("clang C api insufficient");
70 }81 }
...@@ -83,11 +94,14 @@ static Buf *to_zig_type(CXType raw_type) {...@@ -83,11 +94,14 @@ static Buf *to_zig_type(CXType raw_type) {
83 case CXType_UChar:94 case CXType_UChar:
84 return buf_create_from_str("u8");95 return buf_create_from_str("u8");
85 case CXType_WChar:96 case CXType_WChar:
86 zig_panic("TODO");97 print_location(p);
98 zig_panic("TODO wchar");
87 case CXType_Char16:99 case CXType_Char16:
88 zig_panic("TODO");100 print_location(p);
101 zig_panic("TODO char16");
89 case CXType_Char32:102 case CXType_Char32:
90 zig_panic("TODO");103 print_location(p);
104 zig_panic("TODO char32");
91 case CXType_UShort:105 case CXType_UShort:
92 return buf_create_from_str("c_ushort");106 return buf_create_from_str("c_ushort");
93 case CXType_UInt:107 case CXType_UInt:
...@@ -97,7 +111,8 @@ static Buf *to_zig_type(CXType raw_type) {...@@ -97,7 +111,8 @@ static Buf *to_zig_type(CXType raw_type) {
97 case CXType_ULongLong:111 case CXType_ULongLong:
98 return buf_create_from_str("c_ulonglong");112 return buf_create_from_str("c_ulonglong");
99 case CXType_UInt128:113 case CXType_UInt128:
100 zig_panic("TODO");114 print_location(p);
115 zig_panic("TODO uint128");
101 case CXType_Short:116 case CXType_Short:
102 return buf_create_from_str("c_short");117 return buf_create_from_str("c_short");
103 case CXType_Int:118 case CXType_Int:
...@@ -107,43 +122,34 @@ static Buf *to_zig_type(CXType raw_type) {...@@ -107,43 +122,34 @@ static Buf *to_zig_type(CXType raw_type) {
107 case CXType_LongLong:122 case CXType_LongLong:
108 return buf_create_from_str("c_longlong");123 return buf_create_from_str("c_longlong");
109 case CXType_Int128:124 case CXType_Int128:
110 zig_panic("TODO");125 print_location(p);
126 zig_panic("TODO int128");
111 case CXType_Float:127 case CXType_Float:
112 return buf_create_from_str("f32");128 return buf_create_from_str("f32");
113 case CXType_Double:129 case CXType_Double:
114 return buf_create_from_str("f64");130 return buf_create_from_str("f64");
115 case CXType_LongDouble:131 case CXType_LongDouble:
116 return buf_create_from_str("f128");132 return buf_create_from_str("f128");
117 case CXType_NullPtr:133 case CXType_IncompleteArray:
118 zig_panic("TODO");134 {
119 case CXType_Overload:135 CXType pointee_type = clang_getArrayElementType(raw_type);
120 zig_panic("TODO");136 Buf *pointee_buf = to_zig_type(p, pointee_type);
121 case CXType_Dependent:137 if (clang_isConstQualifiedType(pointee_type)) {
122 zig_panic("TODO");138 return buf_sprintf("*const %s", buf_ptr(pointee_buf));
123 case CXType_ObjCId:139 } else {
124 zig_panic("TODO");140 return buf_sprintf("*mut %s", buf_ptr(pointee_buf));
125 case CXType_ObjCClass:141 }
126 zig_panic("TODO");142 }
127 case CXType_ObjCSel:
128 zig_panic("TODO");
129 case CXType_Complex:
130 zig_panic("TODO");
131 case CXType_Pointer:143 case CXType_Pointer:
132 {144 {
133 CXType pointee_type = clang_getPointeeType(raw_type);145 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);
135 if (clang_isConstQualifiedType(pointee_type)) {147 if (clang_isConstQualifiedType(pointee_type)) {
136 return buf_sprintf("*const %s", buf_ptr(pointee_buf));148 return buf_sprintf("*const %s", buf_ptr(pointee_buf));
137 } else {149 } else {
138 return buf_sprintf("*mut %s", buf_ptr(pointee_buf));150 return buf_sprintf("*mut %s", buf_ptr(pointee_buf));
139 }151 }
140 }152 }
141 case CXType_BlockPointer:
142 zig_panic("TODO");
143 case CXType_LValueReference:
144 zig_panic("TODO");
145 case CXType_RValueReference:
146 zig_panic("TODO");
147 case CXType_Record:153 case CXType_Record:
148 {154 {
149 const char *name = prefixes_stripped(raw_type);155 const char *name = prefixes_stripped(raw_type);
...@@ -176,28 +182,44 @@ static Buf *to_zig_type(CXType raw_type) {...@@ -176,28 +182,44 @@ static Buf *to_zig_type(CXType raw_type) {
176 } else {182 } else {
177 CXCursor typedef_cursor = clang_getTypeDeclaration(raw_type);183 CXCursor typedef_cursor = clang_getTypeDeclaration(raw_type);
178 CXType underlying_type = clang_getTypedefDeclUnderlyingType(typedef_cursor);184 CXType underlying_type = clang_getTypedefDeclUnderlyingType(typedef_cursor);
179 return to_zig_type(underlying_type);185 return to_zig_type(p, underlying_type);
180 }186 }
181 }187 }
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");
190 case CXType_ConstantArray:188 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");
192 case CXType_Vector:205 case CXType_Vector:
193 zig_panic("TODO");206 print_location(p);
194 case CXType_IncompleteArray:207 zig_panic("TODO vector");
195 zig_panic("TODO");208 case CXType_LValueReference:
209 case CXType_RValueReference:
196 case CXType_VariableArray:210 case CXType_VariableArray:
197 zig_panic("TODO");
198 case CXType_DependentSizedArray:211 case CXType_DependentSizedArray:
199 zig_panic("TODO");
200 case CXType_MemberPointer:212 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);
201 zig_panic("TODO");223 zig_panic("TODO");
202 }224 }
203225
...@@ -238,6 +260,9 @@ static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXCl...@@ -238,6 +260,9 @@ static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXCl
238 enum CXCursorKind kind = clang_getCursorKind(cursor);260 enum CXCursorKind kind = clang_getCursorKind(cursor);
239 CXString name = clang_getCursorSpelling(cursor);261 CXString name = clang_getCursorSpelling(cursor);
240262
263 p->range = clang_getCursorExtent(cursor);
264 p->location = clang_getRangeStart(p->range);
265
241 switch (kind) {266 switch (kind) {
242 case CXCursor_FunctionDecl:267 case CXCursor_FunctionDecl:
243 {268 {
...@@ -245,27 +270,37 @@ static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXCl...@@ -245,27 +270,37 @@ static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXCl
245 if (!is_storage_class_export(storage_class))270 if (!is_storage_class_export(storage_class))
246 return CXChildVisit_Continue;271 return CXChildVisit_Continue;
247272
248 end_fn(p);
249 begin_fn(p);
250
251 CXType fn_type = clang_getCursorType(cursor);273 CXType fn_type = clang_getCursorType(cursor);
252 if (clang_isFunctionTypeVariadic(fn_type)) {274 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;
254 }278 }
255 if (clang_getFunctionTypeCallingConv(fn_type) != CXCallingConv_C) {279 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;
257 }283 }
284
285 end_fn(p);
286 begin_fn(p);
287
258 CXType return_type = clang_getResultType(fn_type);288 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
261 buf_init_from_str(&p->cur_fn->name, clang_getCString(name));291 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
263 p->cur_fn->arg_count = clang_getNumArgTypes(fn_type);298 p->cur_fn->arg_count = clang_getNumArgTypes(fn_type);
264 p->cur_fn->args = allocate<Arg>(p->cur_fn->arg_count);299 p->cur_fn->args = allocate<Arg>(p->cur_fn->arg_count);
265300
266 for (int i = 0; i < p->cur_fn->arg_count; i += 1) {301 for (int i = 0; i < p->cur_fn->arg_count; i += 1) {
267 CXType param_type = clang_getArgType(fn_type, i);302 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);
269 }304 }
270305
271 p->arg_index = 0;306 p->arg_index = 0;
...@@ -283,6 +318,7 @@ static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXCl...@@ -283,6 +318,7 @@ static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXCl
283 case CXCursor_UnexposedAttr:318 case CXCursor_UnexposedAttr:
284 case CXCursor_CompoundStmt:319 case CXCursor_CompoundStmt:
285 case CXCursor_FieldDecl:320 case CXCursor_FieldDecl:
321 case CXCursor_TypedefDecl:
286 return CXChildVisit_Continue;322 return CXChildVisit_Continue;
287 default:323 default:
288 return CXChildVisit_Recurse;324 return CXChildVisit_Recurse;
src/semantic_info.hpp+2
...@@ -102,6 +102,8 @@ struct CodeGen {...@@ -102,6 +102,8 @@ struct CodeGen {
102 FnTableEntry *cur_fn;102 FnTableEntry *cur_fn;
103 LLVMBasicBlockRef cur_basic_block;103 LLVMBasicBlockRef cur_basic_block;
104 bool c_stdint_used;104 bool c_stdint_used;
105 bool c_unreachable_used;
106 Buf *c_unreachable_macro;
105 AstNode *root_export_decl;107 AstNode *root_export_decl;
106 int version_major;108 int version_major;
107 int version_minor;109 int version_minor;