| 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 | 30 | "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp" |
| 31 | 31 | "${CMAKE_SOURCE_DIR}/src/util.cpp" |
| 32 | 32 | "${CMAKE_SOURCE_DIR}/src/codegen.cpp" |
| 33 | "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp" | |
| 33 | 34 | ) |
| 34 | 35 | |
| 35 | 36 | set(CONFIGURE_OUT_FILE "${CMAKE_BINARY_DIR}/config.h") |
| ... | ... | @@ -38,10 +39,6 @@ configure_file ( |
| 38 | 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 | 42 | set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wno-unused-variable -Wno-unused-but-set-variable") |
| 46 | 43 | |
| 47 | 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 | /* | |
| 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 | 8 | #include "codegen.hpp" |
| 2 | 9 | #include "hash_map.hpp" |
| 10 | #include "zig_llvm.hpp" | |
| 3 | 11 | |
| 4 | 12 | #include <stdio.h> |
| 5 | 13 | |
| 6 | #include <llvm-c/Core.h> | |
| 7 | #include <llvm-c/Analysis.h> | |
| 8 | ||
| 9 | 14 | struct FnTableEntry { |
| 10 | 15 | LLVMValueRef fn_value; |
| 11 | 16 | AstNode *proto_node; |
| ... | ... | @@ -49,6 +54,7 @@ static void add_node_error(CodeGen *g, AstNode *node, Buf *msg) { |
| 49 | 54 | static LLVMTypeRef to_llvm_type(AstNode *type_node) { |
| 50 | 55 | assert(type_node->type == NodeTypeType); |
| 51 | 56 | assert(type_node->codegen_node); |
| 57 | assert(type_node->codegen_node->data.type_ref); | |
| 52 | 58 | |
| 53 | 59 | return type_node->codegen_node->data.type_ref; |
| 54 | 60 | } |
| ... | ... | @@ -134,9 +140,12 @@ static void analyze_node(CodeGen *g, AstNode *node) { |
| 134 | 140 | node->codegen_node->data.type_ref = LLVMInt8Type(); |
| 135 | 141 | } else if (buf_eql_str(name, "i32")) { |
| 136 | 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 | 145 | } else { |
| 138 | 146 | add_node_error(g, node, |
| 139 | 147 | buf_sprintf("invalid type name: '%s'", buf_ptr(name))); |
| 148 | node->codegen_node->data.type_ref = LLVMInt8Type(); | |
| 140 | 149 | } |
| 141 | 150 | break; |
| 142 | 151 | } |
| ... | ... | @@ -339,3 +348,42 @@ void code_gen(CodeGen *g) { |
| 339 | 348 | ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) { |
| 340 | 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 | /* | |
| 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 | 8 | #ifndef ZIG_CODEGEN_HPP |
| 2 | 9 | #define ZIG_CODEGEN_HPP |
| 3 | 10 | |
| ... | ... | @@ -20,6 +27,8 @@ void semantic_analyze(CodeGen *g); |
| 20 | 27 | |
| 21 | 28 | void code_gen(CodeGen *g); |
| 22 | 29 | |
| 30 | void code_gen_link(CodeGen *g, bool is_static, const char *out_file); | |
| 31 | ||
| 23 | 32 | ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g); |
| 24 | 33 | |
| 25 | 34 | #endif |
src/hash_map.hpp+7| ... | ... | @@ -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 | 8 | #ifndef ZIG_HASH_MAP_HPP |
| 2 | 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 | 112 | fprintf(stderr, "------------------\n"); |
| 113 | 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 | 119 | return 0; |
| 116 | 120 | } |
| 117 | 121 |
src/parser.cpp+16-4| ... | ... | @@ -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 | 8 | #include "parser.hpp" |
| 2 | 9 | |
| 3 | 10 | #include <stdarg.h> |
| ... | ... | @@ -168,6 +175,13 @@ static AstNode *ast_create_node_with_node(NodeType type, AstNode *other_node) { |
| 168 | 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 | 185 | static void ast_buf_from_token(ParseContext *pc, Token *token, Buf *buf) { |
| 172 | 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 | 482 | ast_parse_param_decl_list(pc, token_index, &token_index, &node->data.fn_proto.params); |
| 469 | 483 | |
| 470 | 484 | Token *arrow = &pc->tokens->at(token_index); |
| 471 | token_index += 1; | |
| 472 | 485 | if (arrow->id == TokenIdArrow) { |
| 486 | token_index += 1; | |
| 473 | 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 | 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 | 492 | *new_token_index = token_index; |
src/parser.hpp+7| ... | ... | @@ -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 | 8 | #ifndef ZIG_PARSER_HPP |
| 2 | 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 | 170 | case WHITESPACE: |
| 171 | 171 | break; |
| 172 | 172 | case ALPHA: |
| 173 | case '_': | |
| 173 | 174 | t.state = TokenizeStateSymbol; |
| 174 | 175 | begin_token(&t, TokenIdSymbol); |
| 175 | 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 | 1 | extern { |
| 2 | 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 | puts("Hello, world!\n"); | |
| 7 | return 0; | |
| 6 | fn _start() { | |
| 7 | puts("Hello, world!"); | |
| 8 | exit(0); | |
| 8 | 9 | } |