| author | |
| committer | |
| log | b04e64d300b8531c0e84c376d484a62aa9f92614 |
| tree | f44c70585a172d6e4a6ed2ec4368d1e7fe012c1b |
| parent | a50474e7cfc97e404fbb9f3b2f33507afac0ae2b |
4 files changed, 55 insertions(+), 1 deletions(-)
src/all_types.hpp+2| ... | ... | @@ -998,6 +998,7 @@ enum BuiltinFnId { |
| 998 | 998 | BuiltinFnIdCInclude, |
| 999 | 999 | BuiltinFnIdCDefine, |
| 1000 | 1000 | BuiltinFnIdCUndef, |
| 1001 | BuiltinFnIdCompileVar, | |
| 1001 | 1002 | }; |
| 1002 | 1003 | |
| 1003 | 1004 | struct BuiltinFnEntry { |
| ... | ... | @@ -1058,6 +1059,7 @@ struct CodeGen { |
| 1058 | 1059 | |
| 1059 | 1060 | LLVMTargetDataRef target_data_ref; |
| 1060 | 1061 | unsigned pointer_size_bytes; |
| 1062 | bool is_big_endian; | |
| 1061 | 1063 | bool is_static; |
| 1062 | 1064 | bool strip_debug_symbols; |
| 1063 | 1065 | bool have_exported_main; |
src/analyze.cpp+45-1| ... | ... | @@ -3896,7 +3896,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry |
| 3896 | 3896 | uint64_t big_c = char_val->data.x_bignum.data.x_uint; |
| 3897 | 3897 | assert(big_c <= UINT8_MAX); |
| 3898 | 3898 | uint8_t c = big_c; |
| 3899 | buf_appendf(context->c_import_buf, "%c", c); | |
| 3899 | buf_append_char(context->c_import_buf, c); | |
| 3900 | 3900 | } |
| 3901 | 3901 | buf_appendf(context->c_import_buf, ">\n"); |
| 3902 | 3902 | |
| ... | ... | @@ -3907,6 +3907,50 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry |
| 3907 | 3907 | case BuiltinFnIdCUndef: |
| 3908 | 3908 | zig_panic("TODO"); |
| 3909 | 3909 | |
| 3910 | case BuiltinFnIdCompileVar: | |
| 3911 | { | |
| 3912 | AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field; | |
| 3913 | ||
| 3914 | TypeTableEntry *str_type = get_unknown_size_array_type(g, g->builtin_types.entry_u8, true); | |
| 3915 | TypeTableEntry *resolved_type = analyze_expression(g, import, context, str_type, *str_node); | |
| 3916 | ||
| 3917 | if (resolved_type->id == TypeTableEntryIdInvalid) { | |
| 3918 | return resolved_type; | |
| 3919 | } | |
| 3920 | ||
| 3921 | ConstExprValue *const_str_val = &get_resolved_expr(*str_node)->const_val; | |
| 3922 | ||
| 3923 | if (!const_str_val->ok) { | |
| 3924 | add_node_error(g, *str_node, buf_sprintf("@compile_var requires constant expression")); | |
| 3925 | return g->builtin_types.entry_void; | |
| 3926 | } | |
| 3927 | ||
| 3928 | ConstExprValue *ptr_field = const_str_val->data.x_struct.fields[0]; | |
| 3929 | uint64_t len = ptr_field->data.x_ptr.len; | |
| 3930 | Buf var_name = BUF_INIT; | |
| 3931 | buf_resize(&var_name, 0); | |
| 3932 | for (uint64_t i = 0; i < len; i += 1) { | |
| 3933 | ConstExprValue *char_val = ptr_field->data.x_ptr.ptr[i]; | |
| 3934 | uint64_t big_c = char_val->data.x_bignum.data.x_uint; | |
| 3935 | assert(big_c <= UINT8_MAX); | |
| 3936 | uint8_t c = big_c; | |
| 3937 | buf_append_char(&var_name, c); | |
| 3938 | } | |
| 3939 | ||
| 3940 | ConstExprValue *const_val = &get_resolved_expr(node)->const_val; | |
| 3941 | const_val->depends_on_compile_var = true; | |
| 3942 | ||
| 3943 | if (buf_eql_str(&var_name, "is_big_endian")) { | |
| 3944 | return resolve_expr_const_val_as_bool(g, node, g->is_big_endian); | |
| 3945 | } else { | |
| 3946 | add_node_error(g, *str_node, | |
| 3947 | buf_sprintf("unrecognized compile variable: '%s'", buf_ptr(&var_name))); | |
| 3948 | return g->builtin_types.entry_invalid; | |
| 3949 | } | |
| 3950 | ||
| 3951 | break; | |
| 3952 | } | |
| 3953 | ||
| 3910 | 3954 | } |
| 3911 | 3955 | zig_unreachable(); |
| 3912 | 3956 | } |
src/codegen.cpp+3| ... | ... | @@ -304,6 +304,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| 304 | 304 | case BuiltinFnIdMinValue: |
| 305 | 305 | case BuiltinFnIdMaxValue: |
| 306 | 306 | case BuiltinFnIdMemberCount: |
| 307 | case BuiltinFnIdCompileVar: | |
| 307 | 308 | // caught by constant expression eval codegen |
| 308 | 309 | zig_unreachable(); |
| 309 | 310 | } |
| ... | ... | @@ -3221,6 +3222,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 3221 | 3222 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCInclude, "c_include", 1); |
| 3222 | 3223 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCDefine, "c_define", 2); |
| 3223 | 3224 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCUndef, "c_undef", 1); |
| 3225 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCompileVar, "compile_var", 1); | |
| 3224 | 3226 | } |
| 3225 | 3227 | |
| 3226 | 3228 | |
| ... | ... | @@ -3267,6 +3269,7 @@ static void init(CodeGen *g, Buf *source_path) { |
| 3267 | 3269 | |
| 3268 | 3270 | |
| 3269 | 3271 | g->pointer_size_bytes = LLVMPointerSize(g->target_data_ref); |
| 3272 | g->is_big_endian = (LLVMByteOrder(g->target_data_ref) == LLVMBigEndian); | |
| 3270 | 3273 | |
| 3271 | 3274 | g->builder = LLVMCreateBuilder(); |
| 3272 | 3275 | g->dbuilder = LLVMZigCreateDIBuilder(g->module, true); |
test/run_tests.cpp+5| ... | ... | @@ -2033,6 +2033,11 @@ fn func() -> bogus {} |
| 2033 | 2033 | )SOURCE", 2, |
| 2034 | 2034 | ".tmp_source.zig:3:1: error: redefinition of 'func'", |
| 2035 | 2035 | ".tmp_source.zig:2:14: error: use of undeclared identifier 'bogus'"); |
| 2036 | ||
| 2037 | ||
| 2038 | add_compile_fail_case("bogus compile var", R"SOURCE( | |
| 2039 | const x = @compile_var("bogus"); | |
| 2040 | )SOURCE", 1, ".tmp_source.zig:2:24: error: unrecognized compile variable: 'bogus'"); | |
| 2036 | 2041 | } |
| 2037 | 2042 | |
| 2038 | 2043 | ////////////////////////////////////////////////////////////////////////////// |