authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-11-24 13:00:38-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-11-24 13:00:38-07:00
logc2e5d50027779468c66608f445f3ab0f77d34c15
tree0d4bce1559548e7b6762a8a93fb551ccf642e126
parente112818e25b710199f5c757c17717499356d516e

write object file and fix void return type


11 files changed, 169 insertions(+), 14 deletions(-)

CMakeLists.txt+1-4
...@@ -30,6 +30,7 @@ set(ZIG_SOURCES...@@ -30,6 +30,7 @@ set(ZIG_SOURCES
30 "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"30 "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
31 "${CMAKE_SOURCE_DIR}/src/util.cpp"31 "${CMAKE_SOURCE_DIR}/src/util.cpp"
32 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"32 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"
33 "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"
33)34)
3435
35set(CONFIGURE_OUT_FILE "${CMAKE_BINARY_DIR}/config.h")36set(CONFIGURE_OUT_FILE "${CMAKE_BINARY_DIR}/config.h")
...@@ -38,10 +39,6 @@ configure_file (...@@ -38,10 +39,6 @@ configure_file (
38 ${CONFIGURE_OUT_FILE}39 ${CONFIGURE_OUT_FILE}
39)40)
4041
41# GTFO, -lstdc++ !!
42set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
43set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
44
45set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wno-unused-variable -Wno-unused-but-set-variable")42set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wno-unused-variable -Wno-unused-but-set-variable")
4643
47set(EXE_CFLAGS "-std=c++11 -Werror -Wall -Werror=strict-prototypes -Werror=old-style-definition -Werror=missing-prototypes")44set(EXE_CFLAGS "-std=c++11 -Werror -Wall -Werror=strict-prototypes -Werror=old-style-definition -Werror=missing-prototypes")
src/codegen.cpp+51-3
...@@ -1,11 +1,16 @@...@@ -1,11 +1,16 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
1#include "codegen.hpp"8#include "codegen.hpp"
2#include "hash_map.hpp"9#include "hash_map.hpp"
10#include "zig_llvm.hpp"
311
4#include <stdio.h>12#include <stdio.h>
513
6#include <llvm-c/Core.h>
7#include <llvm-c/Analysis.h>
8
9struct FnTableEntry {14struct FnTableEntry {
10 LLVMValueRef fn_value;15 LLVMValueRef fn_value;
11 AstNode *proto_node;16 AstNode *proto_node;
...@@ -49,6 +54,7 @@ static void add_node_error(CodeGen *g, AstNode *node, Buf *msg) {...@@ -49,6 +54,7 @@ static void add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
49static LLVMTypeRef to_llvm_type(AstNode *type_node) {54static LLVMTypeRef to_llvm_type(AstNode *type_node) {
50 assert(type_node->type == NodeTypeType);55 assert(type_node->type == NodeTypeType);
51 assert(type_node->codegen_node);56 assert(type_node->codegen_node);
57 assert(type_node->codegen_node->data.type_ref);
5258
53 return type_node->codegen_node->data.type_ref;59 return type_node->codegen_node->data.type_ref;
54}60}
...@@ -134,9 +140,12 @@ static void analyze_node(CodeGen *g, AstNode *node) {...@@ -134,9 +140,12 @@ static void analyze_node(CodeGen *g, AstNode *node) {
134 node->codegen_node->data.type_ref = LLVMInt8Type();140 node->codegen_node->data.type_ref = LLVMInt8Type();
135 } else if (buf_eql_str(name, "i32")) {141 } else if (buf_eql_str(name, "i32")) {
136 node->codegen_node->data.type_ref = LLVMInt32Type();142 node->codegen_node->data.type_ref = LLVMInt32Type();
143 } else if (buf_eql_str(name, "void")) {
144 node->codegen_node->data.type_ref = LLVMVoidType();
137 } else {145 } else {
138 add_node_error(g, node,146 add_node_error(g, node,
139 buf_sprintf("invalid type name: '%s'", buf_ptr(name)));147 buf_sprintf("invalid type name: '%s'", buf_ptr(name)));
148 node->codegen_node->data.type_ref = LLVMInt8Type();
140 }149 }
141 break;150 break;
142 }151 }
...@@ -339,3 +348,42 @@ void code_gen(CodeGen *g) {...@@ -339,3 +348,42 @@ void code_gen(CodeGen *g) {
339ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) {348ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) {
340 return &g->errors;349 return &g->errors;
341}350}
351
352
353void code_gen_link(CodeGen *g, bool is_static, const char *out_file) {
354 LLVMInitializeAllTargets();
355 LLVMInitializeAllTargetMCs();
356 LLVMInitializeAllAsmPrinters();
357 LLVMInitializeAllAsmParsers();
358 LLVMInitializeNativeTarget();
359
360
361 LLVMPassRegistryRef registry = LLVMGetGlobalPassRegistry();
362 LLVMInitializeCore(registry);
363 LLVMInitializeCodeGen(registry);
364 LLVMZigInitializeLoopStrengthReducePass(registry);
365 LLVMZigInitializeLowerIntrinsicsPass(registry);
366 LLVMZigInitializeUnreachableBlockElimPass(registry);
367
368 char *native_triple = LLVMGetDefaultTargetTriple();
369
370 LLVMTargetRef target_ref;
371 char *err_msg = nullptr;
372 if (LLVMGetTargetFromTriple(native_triple, &target_ref, &err_msg)) {
373 zig_panic("unable to get target from triple: %s", err_msg);
374 }
375
376 char *native_cpu = LLVMZigGetHostCPUName();
377 char *native_features = LLVMZigGetNativeFeatures();
378
379 LLVMCodeGenOptLevel opt_level = LLVMCodeGenLevelNone;
380
381 LLVMRelocMode reloc_mode = is_static ? LLVMRelocStatic : LLVMRelocPIC;
382
383 LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine(target_ref, native_triple,
384 native_cpu, native_features, opt_level, reloc_mode, LLVMCodeModelDefault);
385
386 if (LLVMTargetMachineEmitToFile(target_machine, g->mod, strdup(out_file), LLVMObjectFile, &err_msg)) {
387 zig_panic("unable to write object file: %s", err_msg);
388 }
389}
src/codegen.hpp+9
...@@ -1,3 +1,10 @@...@@ -1,3 +1,10 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
1#ifndef ZIG_CODEGEN_HPP8#ifndef ZIG_CODEGEN_HPP
2#define ZIG_CODEGEN_HPP9#define ZIG_CODEGEN_HPP
310
...@@ -20,6 +27,8 @@ void semantic_analyze(CodeGen *g);...@@ -20,6 +27,8 @@ void semantic_analyze(CodeGen *g);
2027
21void code_gen(CodeGen *g);28void code_gen(CodeGen *g);
2229
30void code_gen_link(CodeGen *g, bool is_static, const char *out_file);
31
23ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g);32ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g);
2433
25#endif34#endif
src/hash_map.hpp+7
...@@ -1,3 +1,10 @@...@@ -1,3 +1,10 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
1#ifndef ZIG_HASH_MAP_HPP8#ifndef ZIG_HASH_MAP_HPP
2#define ZIG_HASH_MAP_HPP9#define ZIG_HASH_MAP_HPP
310
src/main.cpp+4
...@@ -112,6 +112,10 @@ static int build(const char *arg0, const char *in_file, const char *out_file, Zi...@@ -112,6 +112,10 @@ static int build(const char *arg0, const char *in_file, const char *out_file, Zi
112 fprintf(stderr, "------------------\n");112 fprintf(stderr, "------------------\n");
113 code_gen(codegen);113 code_gen(codegen);
114114
115 fprintf(stderr, "\nLink:\n");
116 fprintf(stderr, "------------------\n");
117 code_gen_link(codegen, false, out_file);
118
115 return 0;119 return 0;
116}120}
117121
src/parser.cpp+16-4
...@@ -1,3 +1,10 @@...@@ -1,3 +1,10 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
1#include "parser.hpp"8#include "parser.hpp"
29
3#include <stdarg.h>10#include <stdarg.h>
...@@ -168,6 +175,13 @@ static AstNode *ast_create_node_with_node(NodeType type, AstNode *other_node) {...@@ -168,6 +175,13 @@ static AstNode *ast_create_node_with_node(NodeType type, AstNode *other_node) {
168 return node;175 return node;
169}176}
170177
178static AstNode *ast_create_void_type_node(ParseContext *pc, Token *token) {
179 AstNode *node = ast_create_node(NodeTypeType, token);
180 node->data.type.type = AstNodeTypeTypePrimitive;
181 buf_init_from_str(&node->data.type.primitive_name, "void");
182 return node;
183}
184
171static void ast_buf_from_token(ParseContext *pc, Token *token, Buf *buf) {185static void ast_buf_from_token(ParseContext *pc, Token *token, Buf *buf) {
172 buf_init_from_mem(buf, buf_ptr(pc->buf) + token->start_pos, token->end_pos - token->start_pos);186 buf_init_from_mem(buf, buf_ptr(pc->buf) + token->start_pos, token->end_pos - token->start_pos);
173}187}
...@@ -468,13 +482,11 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int token_index, int *new_t...@@ -468,13 +482,11 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int token_index, int *new_t
468 ast_parse_param_decl_list(pc, token_index, &token_index, &node->data.fn_proto.params);482 ast_parse_param_decl_list(pc, token_index, &token_index, &node->data.fn_proto.params);
469483
470 Token *arrow = &pc->tokens->at(token_index);484 Token *arrow = &pc->tokens->at(token_index);
471 token_index += 1;
472 if (arrow->id == TokenIdArrow) {485 if (arrow->id == TokenIdArrow) {
486 token_index += 1;
473 node->data.fn_proto.return_type = ast_parse_type(pc, token_index, &token_index);487 node->data.fn_proto.return_type = ast_parse_type(pc, token_index, &token_index);
474 } else if (arrow->id == TokenIdLBrace) {
475 node->data.fn_proto.return_type = nullptr;
476 } else {488 } else {
477 ast_invalid_token_error(pc, arrow);489 node->data.fn_proto.return_type = ast_create_void_type_node(pc, arrow);
478 }490 }
479491
480 *new_token_index = token_index;492 *new_token_index = token_index;
src/parser.hpp+7
...@@ -1,3 +1,10 @@...@@ -1,3 +1,10 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
1#ifndef ZIG_PARSER_HPP8#ifndef ZIG_PARSER_HPP
2#define ZIG_PARSER_HPP9#define ZIG_PARSER_HPP
310
src/tokenizer.cpp+1
...@@ -170,6 +170,7 @@ ZigList<Token> *tokenize(Buf *buf, Buf *cur_dir_path) {...@@ -170,6 +170,7 @@ ZigList<Token> *tokenize(Buf *buf, Buf *cur_dir_path) {
170 case WHITESPACE:170 case WHITESPACE:
171 break;171 break;
172 case ALPHA:172 case ALPHA:
173 case '_':
173 t.state = TokenizeStateSymbol;174 t.state = TokenizeStateSymbol;
174 begin_token(&t, TokenIdSymbol);175 begin_token(&t, TokenIdSymbol);
175 break;176 break;
src/zig_llvm.cpp created+45
...@@ -0,0 +1,45 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "zig_llvm.hpp"
9
10#include <llvm/InitializePasses.h>
11#include <llvm/PassRegistry.h>
12#include <llvm/MC/SubtargetFeature.h>
13
14
15using namespace llvm;
16
17void LLVMZigInitializeLoopStrengthReducePass(LLVMPassRegistryRef R) {
18 initializeLoopStrengthReducePass(*unwrap(R));
19}
20
21void LLVMZigInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R) {
22 initializeLowerIntrinsicsPass(*unwrap(R));
23}
24
25void LLVMZigInitializeUnreachableBlockElimPass(LLVMPassRegistryRef R) {
26 initializeUnreachableBlockElimPass(*unwrap(R));
27}
28
29char *LLVMZigGetHostCPUName(void) {
30 std::string str = sys::getHostCPUName();
31 return strdup(str.c_str());
32}
33
34char *LLVMZigGetNativeFeatures(void) {
35 return strdup("");
36 //SubtargetFeatures features;
37
38 //StringMap<bool> host_features;
39 //if (sys::getHostCPUFeatures(host_features)) {
40 // for (auto &F : host_features)
41 // features.AddFeature(F.first(), F.second);
42 //}
43
44 //return strdup(features.getString().c_str());
45}
src/zig_llvm.hpp created+24
...@@ -0,0 +1,24 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_ZIG_LLVM_HPP
9#define ZIG_ZIG_LLVM_HPP
10
11#include <llvm-c/Core.h>
12#include <llvm-c/Analysis.h>
13#include <llvm-c/Target.h>
14#include <llvm-c/Initialization.h>
15#include <llvm-c/TargetMachine.h>
16
17void LLVMZigInitializeLoopStrengthReducePass(LLVMPassRegistryRef R);
18void LLVMZigInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
19void LLVMZigInitializeUnreachableBlockElimPass(LLVMPassRegistryRef R);
20
21char *LLVMZigGetHostCPUName(void);
22char *LLVMZigGetNativeFeatures(void);
23
24#endif
test/hello.zig+4-3
...@@ -1,8 +1,9 @@...@@ -1,8 +1,9 @@
1extern {1extern {
2 fn puts(s: *mut u8) -> i32;2 fn puts(s: *mut u8) -> i32;
3 fn exit(code: i32);
3}4}
45
5fn main(argc: i32, argv: *mut *mut u8) -> i32 {6fn _start() {
6 puts("Hello, world!\n");7 puts("Hello, world!");
7 return 0;8 exit(0);
8}9}