| author | |
| committer | |
| log | c2e5d50027779468c66608f445f3ab0f77d34c15 |
| tree | 0d4bce1559548e7b6762a8a93fb551ccf642e126 |
| parent | e112818e25b710199f5c757c17717499356d516e |
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 | ) |
| 34 | 35 | ||
| 35 | set(CONFIGURE_OUT_FILE "${CMAKE_BINARY_DIR}/config.h") | 36 | set(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 | ) |
| 40 | 41 | ||
| 41 | # GTFO, -lstdc++ !! | ||
| 42 | set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "") | ||
| 43 | set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "") | ||
| 44 | |||
| 45 | set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wno-unused-variable -Wno-unused-but-set-variable") | 42 | set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wno-unused-variable -Wno-unused-but-set-variable") |
| 46 | 43 | ||
| 47 | set(EXE_CFLAGS "-std=c++11 -Werror -Wall -Werror=strict-prototypes -Werror=old-style-definition -Werror=missing-prototypes") | 44 | set(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" | ||
| 3 | 11 | ||
| 4 | #include <stdio.h> | 12 | #include <stdio.h> |
| 5 | 13 | ||
| 6 | #include <llvm-c/Core.h> | ||
| 7 | #include <llvm-c/Analysis.h> | ||
| 8 | |||
| 9 | struct FnTableEntry { | 14 | struct 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) { |
| 49 | static LLVMTypeRef to_llvm_type(AstNode *type_node) { | 54 | static 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); | ||
| 52 | 58 | ||
| 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) { |
| 339 | ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) { | 348 | ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) { |
| 340 | return &g->errors; | 349 | return &g->errors; |
| 341 | } | 350 | } |
| 351 | |||
| 352 | |||
| 353 | void 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_HPP | 8 | #ifndef ZIG_CODEGEN_HPP |
| 2 | #define ZIG_CODEGEN_HPP | 9 | #define ZIG_CODEGEN_HPP |
| 3 | 10 | ||
| ... | @@ -20,6 +27,8 @@ void semantic_analyze(CodeGen *g); | ... | @@ -20,6 +27,8 @@ void semantic_analyze(CodeGen *g); |
| 20 | 27 | ||
| 21 | void code_gen(CodeGen *g); | 28 | void code_gen(CodeGen *g); |
| 22 | 29 | ||
| 30 | void code_gen_link(CodeGen *g, bool is_static, const char *out_file); | ||
| 31 | |||
| 23 | ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g); | 32 | ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g); |
| 24 | 33 | ||
| 25 | #endif | 34 | #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_HPP | 8 | #ifndef ZIG_HASH_MAP_HPP |
| 2 | #define ZIG_HASH_MAP_HPP | 9 | #define ZIG_HASH_MAP_HPP |
| 3 | 10 |
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); |
| 114 | 114 | ||
| 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 | } |
| 117 | 121 |
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" |
| 2 | 9 | ||
| 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 | } |
| 170 | 177 | ||
| 178 | static 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 | |||
| 171 | static void ast_buf_from_token(ParseContext *pc, Token *token, Buf *buf) { | 185 | static 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); |
| 469 | 483 | ||
| 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 | } |
| 479 | 491 | ||
| 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_HPP | 8 | #ifndef ZIG_PARSER_HPP |
| 2 | #define ZIG_PARSER_HPP | 9 | #define ZIG_PARSER_HPP |
| 3 | 10 |
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 | |||
| 15 | using namespace llvm; | ||
| 16 | |||
| 17 | void LLVMZigInitializeLoopStrengthReducePass(LLVMPassRegistryRef R) { | ||
| 18 | initializeLoopStrengthReducePass(*unwrap(R)); | ||
| 19 | } | ||
| 20 | |||
| 21 | void LLVMZigInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R) { | ||
| 22 | initializeLowerIntrinsicsPass(*unwrap(R)); | ||
| 23 | } | ||
| 24 | |||
| 25 | void LLVMZigInitializeUnreachableBlockElimPass(LLVMPassRegistryRef R) { | ||
| 26 | initializeUnreachableBlockElimPass(*unwrap(R)); | ||
| 27 | } | ||
| 28 | |||
| 29 | char *LLVMZigGetHostCPUName(void) { | ||
| 30 | std::string str = sys::getHostCPUName(); | ||
| 31 | return strdup(str.c_str()); | ||
| 32 | } | ||
| 33 | |||
| 34 | char *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 | |||
| 17 | void LLVMZigInitializeLoopStrengthReducePass(LLVMPassRegistryRef R); | ||
| 18 | void LLVMZigInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R); | ||
| 19 | void LLVMZigInitializeUnreachableBlockElimPass(LLVMPassRegistryRef R); | ||
| 20 | |||
| 21 | char *LLVMZigGetHostCPUName(void); | ||
| 22 | char *LLVMZigGetNativeFeatures(void); | ||
| 23 | |||
| 24 | #endif | ||
test/hello.zig+4-3| ... | @@ -1,8 +1,9 @@ | ... | @@ -1,8 +1,9 @@ |
| 1 | extern { | 1 | extern { |
| 2 | fn puts(s: *mut u8) -> i32; | 2 | fn puts(s: *mut u8) -> i32; |
| 3 | fn exit(code: i32); | ||
| 3 | } | 4 | } |
| 4 | 5 | ||
| 5 | fn main(argc: i32, argv: *mut *mut u8) -> i32 { | 6 | fn _start() { |
| 6 | puts("Hello, world!\n"); | 7 | puts("Hello, world!"); |
| 7 | return 0; | 8 | exit(0); |
| 8 | } | 9 | } |